PHP / Mongo geoJSON循环无效

时间:2016-08-10 18:26:14

标签: php mongodb geojson

我将一些坐标传递给mongo进行地理搜索。如果坐标不相交(例如图8),它可以正常工作。但是当两条线相交时,它会给出loop is not valid。有没有办法找到交叉点并将所有这些循环分开?

请注意可能有很多。

编辑:我添加了示例查询和错误。请注意,我理解为什么会发生这种情况,我只是想知道是否有一些已知的方法将这些循环分成单独的多边形(某些算法或Mongo内)。

查询:

db.items.find({
    "address.location": {
        "$geoWithin": {
            "$geometry": {
                "type": "Polygon",
                "coordinates": [[
                    [-97.209091, 49.905691],
                    [-97.206345, 49.918072],
                    [-97.178879, 49.919399],
                    [-97.165146, 49.907903],
                    [-97.164459, 49.892865],
                    [-97.180939, 49.889326],
                    [-97.197418, 49.895077],
                    [-97.200165, 49.902596],
                    [-97.203598, 49.919399],
                    [-97.216644, 49.928682],
                    [-97.244797, 49.927356],
                    [-97.255096, 49.913209],
                    [-97.209091, 49.905691]
                ]]
            }
        }
    }
});

错误:

Error: error: {
    "waitedMS" : NumberLong(0),
    "ok" : 0,
    "errmsg" : "Loop is not valid: [
            [ -97.209091, 49.905691 ]
            [ -97.206345, 49.918072 ],
            [ -97.17887899999999, 49.919399 ],
            [ -97.16514599999999, 49.907903 ],
            [ -97.16445899999999, 49.892865 ],
            [ -97.180939, 49.889326 ],
            [ -97.197418, 49.895077 ],
            [ -97.200165, 49.902596 ],
            [ -97.203598, 49.919399 ],
            [ -97.216644, 49.928682 ],
            [ -97.24479700000001, 49.927356 ],
            [ -97.25509599999999, 49.913209 ],
            [ -97.209091, 49.905691 ]
        ]
        Edges 1 and 7 cross.
        Edge locations in degrees: [-97.2063450, 49.9180720]-[-97.1788790, 49.9193990]
        and [-97.2001650, 49.9025960]-[-97.2035980, 49.9193990]
    ",
    "code" : 2
}

更新

我添加了一个蛮力方法的图像。

Polygon Slicing

  • 基本上它是在交叉点上展望未来。
  • 如果找到一个,它会交换点,使其保持在循环内。
  • 它会将切断作为某个队列中的“起点”添加。
  • 当一个向前看并找到它自己的起点时,我们有一个循环。
  • 然后继续通过“起点”队列,直到它为空。
  • 新的多边形集应包含所有单独的循环(理论上)。

但是这有一些问题,通过所有这些循环可能会非常昂贵。假设最多50个点将是大约1275次操作。

同样处理0/180度坐标的环绕可能是一个挑战。

无论如何,我不想花一整天的时间,我甚至可以处理一个不涉及环绕条件的解决方案。

希望这个地方有一个很好的算法,我可以直播(可能有一些奇特的技术术语)。

如果有更有效的方法,那么蛮力前瞻也会很棒。

2 个答案:

答案 0 :(得分:4)

这是因为您的坐标相同会在多边形形状中产生异常:[ - 97.1788790, 49.9193990 ]和[-97.2035980, 49.9193990 ]。在您的代码中删除或更改任何重复的坐标

"coordinates": [[
    [-97.209091, 49.905691],
    [-97.206345, 49.918072],
    [-97.178879, 49.919399], // this line
    [-97.165146, 49.907903],
    [-97.164459, 49.892865],
    [-97.180939, 49.889326],
    [-97.197418, 49.895077],
    [-97.200165, 49.902596],
    [-97.203598, 49.919399], // and this one
    [-97.216644, 49.928682],
    [-97.244797, 49.927356],
    [-97.255096, 49.913209],
    [-97.209091, 49.905691]
]]

答案 1 :(得分:2)

正如我在评论中提到的,查询空间数据的更好工具是使用PostGIS。

例如,PostGIS有ST_validReason()来查找polygon的问题和要修复的st_makevalid,但如果这不是一个选项,那么我将使用shapely python库{{shapely创建一个可用于PHP脚本的服务3}}

https://github.com/Toblerity/Shapely

  

Shapely的第一个前提是Python程序员应该能够   在RDBMS之外执行PostGIS类型几何操作

当然{{1}}是一种流行的工具,您应该从更有经验的用户那里获得有关StackOverflow或gis.stackexchange.com的未来帮助

我认为你试图解决的问题并不像听起来那么简单。

所以我会执行以下步骤:

1找到如何使用匀称

类似的问题:   http://toblerity.org/shapely/manual.html

2创建一个简单的php服务,将查询详细信息传递给python脚本

3 Shapely不会阻止创建无效多边形,但在操作时会引发异常。所以基本上在这样的例外情况下,我会从第1步调用脚本。

如果这只是一个查询,我只会使用QGIS软件(导入点为CSV,创建一个新的shapefile图层(类型为多边形),并使用数字顶点编辑插件)

<强>更新

我认为多边形应该由创建它的工具修复,因此在这种情况下,应该是用户。也许您可以通过从不同角度查看来解决该问题,如果形状来自用户并且在应用程序中的GoogleMap中绘制,则可能在绘图期间不强制执行交叉。

还找到了这个Splitting self-intersecting polygon only returned one polygon in shapely in Python(排序点和创建没有交叉点的多边形)