检测 GPS 坐标是否落在地图上的多边形内
正如标题中所述,我们的目标是找到一种方法来检测给定的 GPS 坐标是否落在多边形内。
多边形本身可以是凸多边形,也可以是凹多边形。它被定义为一组边向量和该多边形内的一个已知点。每个边缘向量进一步由四个坐标定义,这四个坐标是各个尖端点的纬度和经度以及相对于起始点的方位。
StackOverflow 上有几个与此类似的问题,但它们仅以一般术语和 2D 平面描述了解决方案,而我正在寻找一种现有的实现,支持由 WGS 84。
有哪些 API 或服务可用于进行此类碰撞测试?
As stated in the title, the goal is to have a way for detecting whether a given GPS coordinate falls inside a polygon or not.
The polygon itself can be either convex or concave. It's defined as a set of edge vectors and a known point within that polygon. Each edge vector is further defined by four coordinates which are the latitudes and longitudes of respective tip points and a bearing relative to the starting point.
There are a couple of questions similar to this one here on StackOverflow but they describe the solution only in general terms and for a 2D plane, whereas I am looking for an existing implementation that supports polygons defined by latitude/longitude pairs in WGS 84.
What API-s or services are out there for doing such collision tests?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
这是一个 java 程序,它使用一个函数,如果在由纬度/经度列表定义的多边形内部找到纬度/经度,则返回 true,并演示了佛罗里达州。
I'我不确定它是否涉及纬度/经度 GPS 系统不是 x/y 坐标平面这一事实。对于我的使用,我已经证明它是有效的(我认为如果您在边界框中指定足够的点,它就会消除地球是球体的效果,并且地球上两点之间的直线不是箭头直线 方法
首先指定构成多边形角点的点,它可以有凹角和凸角。下面我使用的坐标描绘了佛罗里达州的周长,
coordinate_is_inside_polygon
使用了算法I。不太明白。这是我得到的来源的官方解释:“...Philippe Reverdy 转发的解决方案是计算测试点与构成多边形的每对点之间的角度之和。如果该总和为 2pi,则该点是内部点,如果为 0,则该点是外部点,这也适用于带有孔的多边形,因为该多边形是由进出孔的重合边组成的路径定义的。这是许多 CAD 软件包中的常见做法。 “
我的单元测试表明它确实工作可靠,即使边界框是“C”形状,甚至形状像 Torus。(我的单元测试测试了佛罗里达州内的许多点,并确保函数返回 true。我选择了世界其他地方的一些坐标,并确保它返回 false。我选择了世界各地的地方。 。
我不确定如果多边形边界框穿过赤道、本初子午线或坐标从 -180 -> 180、-90 -> 90 变化的任何区域,这是否会起作用 对我来说,我只需要它来处理佛罗里达州的周边,如果您必须定义一个跨越地球或穿过这些线的多边形,您可以通过制作两条线来解决它。多边形,一个代表子午线一侧的区域,一个代表另一侧的区域,并测试您的点是否位于这些点中的任何一个。
这是我找到这个算法的地方:确定点是否位于多边形内部 - 解决方案 2
亲自运行它来仔细检查它。
将其放入名为 Runner.java 的文件中
恶魔魔法需要进行单元测试。将其放入名为 MainTest.java 的文件中以验证它是否适合您
我使用 eclipse IDE 让它使用 java 1.6.0 运行 java。对我来说,所有单元测试都通过了。您需要将 junit 4 jar 文件包含在类路径中或将其导入到 Eclipse 中。
Here is a java program which uses a function that will return true if a latitude/longitude is found inside of a polygon defined by a list of lat/longs, with demonstration for the state of florida.
I'm not sure if it deals with the fact that the lat/long GPS system is not an x/y coordinate plane. For my uses I have demonstrated that it works (I think if you specify enough points in the bounding box, it washes away the effect that the earth is a sphere, and that straight lines between two points on the earth is not an arrow straight line.
First specify the points that make up the corner points of the polygon, it can have concave and convex corners. The coordinates I use below traces the perimeter of the state of Florida.
method
coordinate_is_inside_polygon
utilizes an algorithm I don't quite understand. Here is an official explanation from the source where I got it:"... solution forwarded by Philippe Reverdy is to compute the sum of the angles made between the test point and each pair of points making up the polygon. If this sum is 2pi then the point is an interior point, if 0 then the point is an exterior point. This also works for polygons with holes given the polygon is defined with a path made up of coincident edges into and out of the hole as is common practice in many CAD packages. "
My unit tests show it does work reliably, even when the bounding box is a 'C' shape or even shaped like a Torus. (My unit tests test many points inside Florida and make sure the function returns true. And I pick a number of coordinates everywhere else in the world and make sure it returns false. I pick places all over the world which might confuse it.
I'm not sure this will work if the polygon bounding box crosses the equator, prime meridian, or any area where the coordinates change from -180 -> 180, -90 -> 90. Or your polygon wraps around the earth around the north/south poles. For me, I only need it to work for the perimeter of Florida. If you have to define a polygon that spans the earth or crosses these lines, you could work around it by making two polygons, one representing the area on one side of the meridian and one representing the area on the other side and testing if your point is in either of those points.
Here is where I found this algorithm: Determining if a point lies on the interior of a polygon - Solution 2
Run it for yourself to double check it.
Put this in a file called Runner.java
Demon magic needs to be unit-tested. Put this in a file called MainTest.java to verify it works for you
I used eclipse IDE to get this to run java using java 1.6.0. For me all the unit tests pass. You need to include the junit 4 jar file in your classpath or import it into Eclipse.
我的想法与 shab First 类似(他的提议称为 光线投射算法),但是像 Spacedman 一样有第二个想法:
我实现并测试了数学上正确的方法,即与大圆相交并确定两个相交点之一是否在两个圆弧上。 (注意:我按照此处描述的步骤进行操作,但我发现了几个错误:第 6 步末尾缺少
sign
函数(就在arcsin
之前),并且最终测试是数字垃圾(因为减法的条件很差) ); 而是使用L_1T >= max(L_1a, L_1b)
来测试 S1 是否在第一条弧上等。)这也是极其缓慢且数字噩梦(评估约 100 个三角函数等);事实证明它不适用于我们的嵌入式系统。
不过有一个技巧:如果您考虑的区域足够小,只需进行标准制图投影,例如 球形墨卡托投影,每个点:
然后,您可以应用光线投射,其中通过此函数检查弧的相交:
I thought similarly as shab first (his proposal is called Ray-Casting Algorithm), but had second thoughts like Spacedman:
I implemented and tested the mathematically correct way of doing that, e.i. intersecting great circles and determining whether one of the two intersecting points is on both arcs. (Note: I followed the steps described here, but I found several errors: The
sign
function is missing at the end of step 6 (just beforearcsin
), and the final test is numerical garbage (as subtraction is badly conditioned); use ratherL_1T >= max(L_1a, L_1b)
to test whether S1 is on the first arc etc.)That also is extremely slow and a numerical nightmare (evaluates ~100 trigonometric functions, among other things); it proved not to be usable in our embedded systems.
There's a trick, though: If the area you are considering is small enough, just do a standard cartographic projection, e.g. spherical Mercator projection, of each point:
Then, you can apply ray-casting, where the intersection of arcs is checked by this function:
如果球体上有 WGS84 坐标,那么您的多边形将球体分为两个区域 - 我们如何知道哪个区域在多边形“内部”,哪个区域在多边形“外部”?这个问题本质上是没有意义的!
例如,假设多边形形成了赤道线 - 北半球是“内”还是“外”?
If you have WGS84 coordinates on the sphere, then your polygon divides the sphere into two areas - how do we know which area is 'inside' and which is 'outside' the polygon? The question is essentially meaningless!
For example, suppose the polygon formed the line of the equator - is the Northern hemisphere 'in' or 'out'?
根据记忆,确定一个点是否位于多边形内的方法是想象从该位置到某个远处的点画一条线。然后计算该线与多边形线段之间的交点数量。如果计数为偶数,则它不在多边形内。如果为 false,则它确实位于多边形内。
From memory, the way to determine whether a point lies within a polygon is to imagine drawing a line from the position to some far away point. You then count the number of intersections between the line and the line segments of the polygon. If it count is even, then it does not lie within the polygon. If it is false, then it does lie within the polygon.
JavaScript 版本 -
JavaScript Version -
假设您处理环绕子午线并穿过赤道的情况(通过添加偏移量) - 难道您不能将其视为多边形中的简单二维点吗?
Assuming you handle the case of wrapping around the meridian and crossing the equator (by adding offsets) - can't you just treat this as a simple 2d point in polygon ?
这是用 Go 编写的算法:
它采用 [lat,long] 格式的点坐标和 [[lat,long],[lat,long]...] 格式的多边形。算法将连接多边形切片中的第一个点和最后一个点
Here is the algorithm written in Go:
It takes point coordinates in [lat,long] format and polygon in format [[lat,long],[lat,long]...]. Algorithm will join the first and last point in the polygon slice
VB.NET 中的 Runner.Java 代码
为了使 .NET 用户受益,相同的代码被放入 VB.NET 中。已经尝试过了,速度还蛮快的。尝试了 350000 条记录,几分钟内就完成了。
但正如作者所说,我还没有测试与赤道相交、多区域等的场景。
“使用
”功能
Runner.Java code in VB.NET
For the benefit of .NET folks the same code is put in VB.NET. Have tried it and is quite fast. Tried with 350000 records, it finishes in just few minutes.
But as said by author, i'm yet to test scenarios intersecting equator, multizones etc.
'Usage
'Functions