locationtech/spatial4j

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)));