Проблема с Vividsolutions JTS внутри метода - PullRequest
0 голосов
/ 25 марта 2020

Я использую библиотеку com.vividsolutions.jts для некоторого пространственного анализа. Ниже приведены вершины многоугольника.

[-91.23046875, 51.069016659603896], [-84.375, 47.989921667414194], [-80.595703125, 49.89463439573421], [-87.01171875, 5385.268688373). ]

Я создаю случайные точки в непосредственной близости от этого многоугольника и использую следующий код, чтобы проверить, находится ли точка внутри многоугольника или нет:

point.within(polygon)

Я вижу, что для результат некоторых точек является правильным, в то время как результаты некоторых точек являются неправильными.

Например, ниже приведен список точек и результат метода «в пределах» для них:

-82.5438973303955 , 48.92064284689714 - результат внутри, даже если точки снаружи

-82.5397253036499, 48.91818466351969 - результат внутри, хотя точки снаружи

-82.54247188568115, 48.91942550176894 - результат внутри, даже если точки снаружи

-84,375,47.9892323448971 - снаружи (правильно)

Почему я вижу это случайное поведение?

1 Ответ

0 голосов
/ 27 марта 2020

Я только что использовал QGis для построения вашего многоугольника, а точки и три точки, на которые вы жалуетесь, явно находятся в многоугольнике.

enter image description here

I Я провел немного больше исследований по этому вопросу, и я подозреваю, что у вас может быть проблема с разрешением / запретом на изгиб Земли.

Сначала я переключился на плоскую проекцию (EPSG: 3347) Stats Canada Lambert - это переключает результаты в соответствии с тем, что вы видите. Но если я уплотню края вашего многоугольника (так, чтобы он перепроектировался по всей линии, а не только по углам), результаты снова совпадают с моими.

enter image description here

Розовый цвет - наивная проекция, а желтый - уплотненный край.

Вот код, если вы хотите поиграть с ним самостоятельно:

import java.util.ArrayList;

import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.locationtech.jts.densify.Densifier;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;

public class JTSWithin {
  static GeometryFactory gf = new GeometryFactory();

  public static void main(String[] args)
      throws NoSuchAuthorityCodeException, FactoryException, MismatchedDimensionException, TransformException {
    double c[][] = { { -91.23046875, 51.069016659603896 }, { -84.375, 47.989921667414194 },
        { -80.595703125, 49.89463439573421 }, { -87.01171875, 53.64463782485651 },
        { -91.23046875, 51.069016659603896 } };
    ArrayList<Coordinate> coords = new ArrayList<>();
    for (double pair[] : c) {
      Coordinate coord = new Coordinate(pair[0], pair[1]);
      coords.add(coord);
    }
    Polygon poly = gf.createPolygon(coords.toArray(new Coordinate[] {}));
    System.out.println(poly);

    Coordinate[] tests = { new Coordinate(-82.5438973303955, 48.92064284689714),
        new Coordinate(-82.5397253036499, 48.91818466351969), new Coordinate(-82.54247188568115, 48.91942550176894),
        new Coordinate(-84.375, 47.9892323448971) };

    for (Coordinate t : tests) {
      Point p = gf.createPoint(t);
      System.out.println(p);
      System.out.println(p.within(poly));
      System.out.println(poly.contains(p));
    }
    System.out.println("\nProjection\n");
    CoordinateReferenceSystem crs = CRS.decode("EPSG:3347");
    MathTransform wgsToCanada = CRS.findMathTransform(DefaultGeographicCRS.WGS84, crs);
    Geometry dp = Densifier.densify(poly, 0.0001);
    Polygon pPoly = (Polygon) JTS.transform(dp, wgsToCanada);

    for (Coordinate t : tests) {
      Point p = gf.createPoint(t);
      Point tp = (Point) JTS.transform(p, wgsToCanada);
      System.out.println(tp);
      System.out.println(tp.within(pPoly));
      System.out.println(pPoly.contains(tp));
    }
  }
}
...