首页 > 解决方案 > 与vividsolutions jts'within'方法有关的问题

问题描述

我正在使用 com.vividsolutions.jts 库进行一些空间分析。以下是多边形的顶点。

[ -91.23046875, 51.069016659603896 ], [ -84.375, 47.989921667414194 ], [ -80.595703125, 49.89463439573421 ], [ -87.01171875, 53.64463782485651 ], [ -91.23046875, 51.069016659603896 ]

我在该多边形附近创建随机点,并使用以下代码检查点是否位于多边形内:

point.within(polygon)

我看到的是,对于某些点,结果是正确的,而对于某些点,结果是错误的。

例如,以下是点列表和它们的“内部”方法的结果:

-82.5438973303955, 48.92064284689714 - 结果在里面,即使点在外面

-82.5397253036499, 48.91818466351969 - 结果在里面,即使点在外面

-82.54247188568115, 48.91942550176894 - 结果在里面,即使点在外面

-84.375,47.9892323448971 - 外部(正确)

为什么我会看到这种随机行为?

标签: geospatialjts

解决方案


我刚刚使用 QGis 绘制了您的多边形,而您抱怨的点和三个点显然在多边形中。

在此处输入图像描述

我对此进行了更多调查,我怀疑您可能在允许/不允许地球曲线方面存在问题。

首先,我切换到平面投影 (EPSG:3347) Stats Canada Lambert - 这会切换结果以匹配您所看到的。但是,如果我使多边形的边缘变密(以便它沿线重新投影,而不仅仅是在拐角处),结果再次与我的匹配。

在此处输入图像描述

粉红色是幼稚的投影,黄色是致密的边缘。

如果您想自己玩,这里是代码:

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

推荐阅读