geospatial - 与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 - 外部(正确)
为什么我会看到这种随机行为?
解决方案
我刚刚使用 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));
}
}
}
推荐阅读
- excel-formula - 单元格值显示为 1。公式无法将值识别为 1
- mysql - 从外部访问 docker 容器内的 mysql db
- c - 进程以退出代码结束,而不是返回主函数
- vue.js - 对何时使用 @client 指令以及访问 Apollo 缓存的不同方式感到困惑
- julia - 如何在 Julia 中将可能是“无”的变量插入字符串?
- javascript - 删除字符串的开头直到找到一个字符
- perl - 使用 Perl Module::Build 在项目上指定 shebang
- php - 将文件添加到 zip 并使用 php 下载 zip
- firebase - Firestore:com.google.cloud.firestore.CollectionReference.where() 不工作
- php - 下拉年份显示去年两次