Validation of the polygon with spatial4j library fails
moniuh opened this issue · 1 comments
Hi everyone,
I have a small application that I'm using to verify if geojson files are correct. also checked with https://geojsonlint.com/
{ "type": "FeatureCollection", "features": [{ "type": "Feature", "properties": {}, "geometry": { "type": "Polygon", "coordinates": [ [ [170, -9.9], [172.1, -13.2], [177, -5], [-170.1, -5.7], [170, -9], [170, -9.9] ] ] } }] }
`
package com.company.jts_test;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.util.GeometricShapeFactory;
import org.locationtech.spatial4j.context.jts.JtsSpatialContext;
import org.locationtech.spatial4j.shape.jts.JtsGeometry;
import org.locationtech.spatial4j.shape.jts.JtsShapeFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class Main {
/** WGS 84 SRID. */
private static final int SRID = 4326;
/** JTS Floating Precision Model. */
private static final PrecisionModel PRECISION_MODEL = new PrecisionModel(PrecisionModel.FLOATING);
/** The Constant JTS_SPATIAL_CONTEXT. */
private static final JtsSpatialContext JTS_SPATIAL_CONTEXT = JtsSpatialContext.GEO;
/** The Constant JTS_SHAPE_FACTORY. */
private static final JtsShapeFactory JTS_SHAPE_FACTORY = JTS_SPATIAL_CONTEXT.getShapeFactory();
/** The Constant JTS_GEOMETRY_FACTORY. */
private static final GeometryFactory JTS_GEOMETRY_FACTORY = JTS_SHAPE_FACTORY.getGeometryFactory();
/**
* JTS Geometry Factory with floating {@link #PRECISION_MODEL} and WGS 85 {@link #SRID}.
*/
public static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory(PRECISION_MODEL, SRID);
/** The Constant GEOMETRY_SHAPE_FACTORY. */
public static final GeometricShapeFactory GEOMETRY_SHAPE_FACTORY = new GeometricShapeFactory(GEOMETRY_FACTORY);
public static void main(String[] args) {
try {
var d = convert(null);
} catch (IOException e) {
e.printStackTrace();
}
}
public static Collection<Object> convert(byte[] rawData) throws IOException {
Collection<Object> result = new ArrayList<>();
Collection<Coordinate2D> p = new ArrayList<>();
List<List<Double>> coordinates = (List<List<Double>>) List.of(
List.of(170.0, -9.9),
List.of(172.1, -13.2),
List.of(177.0, -5.0),
List.of(-170.1, -5.7),
List.of(170.0, -9.0),
List.of(170.0, -9.9)
);
for (List<Double> point : coordinates) {
p.add(new Coordinate2D(point.get(1), point.get(0)));
}
isPolygonValid(p);
return result;
}
private static JtsWxError isPolygonValid(Collection<Coordinate2D> p) {
Coordinate[] c = p.stream().map(coordinate -> new Coordinate(coordinate.getLongitude(), coordinate.getLatitude())).toArray(Coordinate[]::new);
return isPolygonValid(c);
}
public static JtsWxError isPolygonValid(Coordinate[] coordinates) {
Polygon geometry = JTS_GEOMETRY_FACTORY.createPolygon(coordinates);
return validateGeometry(geometry);
}
private static JtsWxError validateGeometry(Polygon geometry) {
if(geometry == null) {
return new JtsWxError(1,"");
}
// try {
JtsGeometry jtsGeometry = (JtsGeometry) JTS_SHAPE_FACTORY.makeShapeFromGeometry(geometry);
jtsGeometry.validate();
// }
//catch(Exception exception) {
// return new JtsWxError(1,exception.getMessage());
// }
return new JtsWxError(1,"OK");
}
}
`
Exception in thread "main" org.locationtech.jts.geom.TopologyException: found non-noded intersection between LINESTRING ( 172.1 -13.2, 177 -5 ) and LINESTRING ( 180 -7.341708542713568, 170 -9 ) [ (175.11679477586557, -8.151486293449425, NaN) ] at org.locationtech.jts.noding.FastNodingValidator.checkValid(FastNodingValidator.java:139) at org.locationtech.jts.geomgraph.EdgeNodingValidator.checkValid(EdgeNodingValidator.java:80) at org.locationtech.jts.geomgraph.EdgeNodingValidator.checkValid(EdgeNodingValidator.java:45) at org.locationtech.jts.operation.overlay.OverlayOp.computeOverlay(OverlayOp.java:229) at org.locationtech.jts.operation.overlay.OverlayOp.getResultGeometry(OverlayOp.java:181) at org.locationtech.jts.operation.overlay.OverlayOp.overlayOp(OverlayOp.java:84) at org.locationtech.jts.operation.overlay.snap.SnapIfNeededOverlayOp.getResultGeometry(SnapIfNeededOverlayOp.java:75) at org.locationtech.jts.operation.overlay.snap.SnapIfNeededOverlayOp.overlayOp(SnapIfNeededOverlayOp.java:37) at org.locationtech.jts.geom.GeometryOverlay.overlay(GeometryOverlay.java:76) at org.locationtech.jts.geom.GeometryOverlay.intersection(GeometryOverlay.java:119) at org.locationtech.jts.geom.Geometry.intersection(Geometry.java:1330) at org.locationtech.spatial4j.shape.jts.JtsGeometry.cutUnwrappedGeomInto360(JtsGeometry.java:585) at org.locationtech.spatial4j.shape.jts.JtsGeometry.<init>(JtsGeometry.java:67) at org.locationtech.spatial4j.shape.jts.JtsShapeFactory.makeShape(JtsShapeFactory.java:531) at org.locationtech.spatial4j.shape.jts.JtsShapeFactory.makeShape(JtsShapeFactory.java:548) at org.locationtech.spatial4j.shape.jts.JtsShapeFactory.makeShapeFromGeometry(JtsShapeFactory.java:500) at com.company.jts_test.Main.validateGeometry(Main.java:88) at com.company.jts_test.Main.isPolygonValid(Main.java:80) at com.company.jts_test.Main.isPolygonValid(Main.java:75) at com.company.jts_test.Main.convert(Main.java:68) at com.company.jts_test.Main.main(Main.java:43)
I think maybe you are getting your X & Y crossed?
p.add(new Coordinate2D(point.get(1), point.get(0)));