Mongodb 寻找重叠的轨迹

Mongodb 寻找重叠的轨迹,mongodb,gis,geospatial,Mongodb,Gis,Geospatial,考虑以下情况: 我在mongodb中将行程/轨迹存储为LineString,索引为2dsphere 根据提供的图像,Trip 1是用户想要搜索的轨迹,Trip2-6是已经存储在mongodb上的行程 给定$near上的maxDistance,Trip1应与Trip3和Trip4“匹配”,如图所示 但是,似乎接受多边形或多边形作为$geometry类型,并且似乎只接受点 是否有任何省时的方法来使用mongo查询实现以下场景 谢谢 编辑:正如Alex Blex所说,我将几何体更改为多边形 数据可视

考虑以下情况:

我在mongodb中将行程/轨迹存储为
LineString
,索引为
2dsphere

根据提供的图像,
Trip 1
是用户想要搜索的轨迹,
Trip2-6
是已经存储在mongodb上的行程

给定$near上的maxDistance,Trip1应与Trip3和Trip4“匹配”,如图所示

但是,似乎接受多边形或多边形作为$geometry类型,并且似乎只接受点

是否有任何省时的方法来使用mongo查询实现以下场景

谢谢


编辑:正如Alex Blex所说,我将几何体更改为多边形

数据可视化(行程1为搜索行程,行程2-3存储在数据库中)

因此,我们在mongo上存储了以下文档:

Trip2

Trip3

旅程1是我们寻找的旅程

我运行的查询如下所示:

 db.trips.find({ tripData: { $geoIntersects : { $geometry : trip1 } } } )

此查询不会像预期的那样返回任何内容,因为旅行不会像您在可视化中看到的那样相交。如何使用$near运算符修改查询以匹配Trip1和Trip3?

地理相交
需要查询中的多边形或多边形,即问题中的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]
    ];
}

生成石灰多边形,如下图所示:

返回值可用于
geoIntersects
查询具有
LineString
位置的文档

问题区域以红色突出显示。在边缘情况下,第一个多边形覆盖的距离大于
d
,在相同边缘情况下,第二个多边形覆盖的距离小于
d

如果这是唯一的问题,我会采用假阴性方法,在点
[x1,y1]
[x2,y2]
附近再运行两次
查询,以检查突出显示区域中是否有遗漏的文档

如果Trip1是一个复杂的
线字符串
,则需要进行更多的计算才能将其转换为多边形。如图所示:

除了第一个和最后一个点的边缘情况外,每个线段的起点和终点都存在类似的问题。基本上,您需要计算每个线段之间的角度,以计算多边形对应的顶点。你仍然可行。在多边形的假负片版本中,应切割用红色圈起的顶点,再次考虑线段之间的角度

如果查询中的Trip1线有许多线段,可能会非常昂贵,因为您需要为每个顶点运行
near
query+2个端点


作为一种实用的方法,如果是可以接受的,那么假阳性版本可能工作得相当快,因为它是一个单一的查询

你是如何储存旅行的?如果它只是一条直线,您可以做一个简单的数学来计算交点。我将行程存储为LineString(这意味着坐标数组),但我希望利用2dsphere索引,并具有mongo提供的处理地理空间数据的效率。此外,我认为做数学计算会很耗时,因为我必须在最坏的情况下将行程1的每个点与其他行程的每个点进行比较。所谓“数学”,我的意思是通过将
附近的
值添加到坐标,将目标
行程1
转换为多边形。基本上与您绘制的石灰形状相交。如果你提供一些数据,用代码回答会更简单。@AlexBlex谢谢你的时间,我已经编辑了这个问题。你不喜欢测试驱动的方法,是吗=)我希望看到2个文档和1个查询,坐标是你知道只应返回1个文档,例如
trip4
,和
trip6
文档,和
Trip 1
查询
near
值。感谢您的回答。不管这种方法看起来多么好,我还是实现了RouteBox。
  tripData: Object
 {
   type: Polygon
   coordinates: [ 
      [ [2,2] , [1,4] , [3,5] , [4,2] , [2,2] ] 
   ]
 }
 db.trips.find({ tripData: { $geoIntersects : { $geometry : trip1 } } } )
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]
    ];
}