我已将mongodb中的行程/轨迹存储为LineString
,索引为2dsphere
。
根据提供的图像,Trip 1
是用户想要搜索的轨迹,Trip2-6
是已存储在mongodb上的行程。
鉴于$ near附近的maxDistance,Trip1应该是"匹配"如图所示,使用Trip 3和4。
然而,$geointersects似乎接受Polygon or Multipolygon
作为$ geometry类型而$near似乎只接受Point
。
使用mongo查询实现以下方案是否有时间效率方式?
谢谢!
编辑:我将几何体更改为Polygon
,正如Alex Blex所说。
数据的可视化(Trip 1是搜索Trip,Trip2-3存储在db中)
所以我们在mongo上存储了以下文件:
TRIP2
tripData: Object
{
type: Polygon
coordinates: [
[ [8,2] , [7,3] , [7,4], [8,2] ]
]
}
TRIP3
tripData: Object
{
type: Polygon
coordinates: [
[ [3,1], [4,1], [4,1.9999], [3,1] ]
]
}
旅程1是我们搜索的行程
tripData: Object
{
type: Polygon
coordinates: [
[ [2,2] , [1,4] , [3,5] , [4,2] , [2,2] ]
]
}
我运行的查询如下:
db.trips.find({ tripData: { $geoIntersects : { $geometry : trip1 } } } )
此查询没有按预期返回任何内容,因为您可以在Visualization中看到行程不相交。如何修改查询以使用$ near运算符将Trip1与Trip3匹配?
答案 0 :(得分:1)
geoIntersects
要求查询中的多边形或多边形 ,即问题中的Trip1。 Trip2-6是LineString
存储在文档中,非常好。所以唯一要做的就是使用偏移将Trip1转换为多边形,在问题中显示为lime near
。
让我们先考虑直线。将行[[x1,y1][x2,y2]]
转换为偏移d
的多边形的功能可以简单如下:
function LineToPolyWithFalsePositive(line, d) {
var teta = Math.atan2(line[1][0] - line[0][0], line[1][1] - line[0][1]);
var s = Math.sin(teta);
var c = Math.cos(teta);
return [
[line[0][0] - d*s - d*c, line[0][1] - d*c + d*s],
[line[1][0] + d*s - d*c, line[1][1] + d*c + d*s],
[line[1][0] + d*s + d*c, line[1][1] + d*c - d*s],
[line[0][0] - d*s + d*c, line[0][1] - d*c - d*s]
];
}
或
function LineToPolyWithFalseNegative(line, d) {
var teta = Math.atan2(line[1][0] - line[0][0], line[1][1] - line[0][1]);
var s = Math.sin(teta);
var c = Math.cos(teta);
return [
[line[0][0] - d*s, line[0][1] - d*c],
[line[0][0] - d*c, line[0][1] + d*s],
[line[1][0] - d*c, line[1][1] + d*s],
[line[1][0] + d*s, line[1][1] + d*c],
[line[1][0] + d*c, line[1][1] - d*s],
[line[0][0] + d*c, line[0][1] - d*s]
];
}
生成石灰多边形如下图所示:
返回的值可用于geoIntersects
查询LineString
位置的文档。
有问题的区域以红色突出显示。第一个多边形在边缘情况下覆盖的距离大于d
,而在相同的边缘情况下,第二个多边形覆盖的距离小于d
。
如果这是唯一的问题,我会采用假阴性方法,对点near
和[x1,y1]
再进行2次[x2,y2]
次查询,以检查是否有任何错过的文件突出显示的区域。
如果Trip1是复杂的LineString
,则需要进行更多的计算才能将其转换为多边形。见图:
除了第一点和最后一点的边缘情况之外,每个段的开始和结束都存在类似的问题。基本上,您需要计算每个段与多边形的锻炼对应顶点之间的角度。你仍然可以。在多边形的假阴性版本中,应该切割用红色圈出的顶点,再次考虑段之间的角度。
如果查询中的Trip1行有很多段,则可能非常昂贵,因为您需要为每个顶点运行near
查询+ 2作为终点。
作为一种实用的方法,如果 可接受,则误报版本可能会非常快,因为它是单个查询。