【问题标题】:Way finding / navigation with neo4j使用 neo4j 进行寻路/导航
【发布时间】:2015-06-06 16:31:14
【问题描述】:

我知道我可能会因为提出这个问题而受到责骂,但我希望有人能帮助我指出正确的方向。

我正在尝试创建一个像谷歌地图这样的寻路应用程序,但让它在地图上标记到多个点的路线。

我正在尝试制作一种动物运输工具,允许多人在从 A 点到 B 点的路径上相遇。我想我读到您可以使用图形数据库来做到这一点。

谁能提供有关地图数据库、文章等的资源来帮助我?我一直在尝试用谷歌搜索文章,但可以找到任何匹配项,所以我认为我使用了错误的术语,例如“寻路”或“方向”

谢谢!

【问题讨论】:

  • 您能澄清一下“在地图上标记多个点的路线”是什么意思吗?您稍后提到了从 A 到 B 的路径,但这只是 2 点。

标签: php neo4j


【解决方案1】:

图形数据库非常适合用于路径查找,尤其是 FrobberOfBits 提到的 shortestPath

只要您有可以形成路径的节点,这就会很好地工作。根据我对您的 cmets 的了解,实际上您需要首先根据用户驾驶偏好动态构建这些节点。

另外,显然您目前没有 A 点到 B 点的数据模型?

这就是我将如何进行,简单地说:

用例是点 A 是我的家,点 2 是 Neo4j 社区看护者的住所,在地图上应该是:

从A到B的路径中的所有小白点都可以是Neo4j节点。

现在您说,例如,有一个很棒的女孩,她的驾驶偏好为 50 公里,以便加入该路线,因此必须更改当前路线。

在您的应用程序中,您不会强迫用户选择一个中间点,您必须即时创建它。

所以我的快速解决方案是在半径上找到最接近初始路线目标点的点。

要实现它,首先你需要从女孩当前位置到目的地(这里是德累斯顿)的初始方位

其中lat1和lon1是女孩的位置,lat2、lon2是德累斯顿的位置

然后,给定这个初始方位,您可以计算从方位 bearing50 公里距离中的女孩开始的位置,例如

在 PHP 中它看起来像(经过测试):

// Function that calculate new coordinates from point A
// Given a bearing and a distance to point B
function getAwayPosition($lat1, $lon1, $lat2, $lon2, $distance)
{
    // Getting true course from point A to point B
    $la1 = deg2rad($lat1);
    $la2 = deg2rad($lat2);
    $lo1 = deg2rad($lon1);
    $lo2 = deg2rad($lon2);

    $y = sin($la2-$la1)*cos($lo1);
    $x = cos($lo1*sin($lo2))-sin($lo1)*cos($lo2)*cos($la2-$la1);
    $course = fmod(rad2deg(atan2($y, $x)+360), 360);

    // Getting the new lat/lon points from lat1/lon1 given the course and the distance
    $bearing = deg2rad($course); //back to radians for the coordinates calculation
    $laa = asin(sin($la1 * cos($distance/6371 + $la1 * cos($course))));
    $loo = $lo1 + atan2(sin($bearing) * sin($distance/6371) * cos($la1), cos($distance/6371) - sin($la1) * sin($laa));

    return array(
        'lat' => rad2deg($laa),
        'lon' => rad2deg($loo),
        'bearing' => $course
    );
}

注意:Cypher 中还有 haversin 函数用于计算地球距离,不过我没怎么玩过

因此,您可以添加一个节点来代表女孩想要的位置,以便加入旅行。

到目前为止,我们现在有 3 个适合 Neo4j 的节点:

现在我认为剩下的过程取决于您的数据模型,如果从 A 到 B 的路径尚未在您的数据库中形成 Neo4j 节点,您可以通过计算与所有节点的距离来动态构建它使用 Google Maps API 和设置的点作为关系属性。 然后你可以做一个 Cypher shortestPath 并减少关系距离属性。

如果您已经有代表从 A 到 B 的初始路线的多个中间点的节点,您可以使用 Neo4j Spatial 并获取从女孩所需位置到路线中间节点的最近点,并与距离。 再次为最佳映射路线的最短路径。

第二种解决方案会更好,因为您将立即拥有一个图表来玩:

如果您想获得公里数最少的路径,还有一个简单的 Cypher 查询:

MATCH (a:Point {id:'A'}), (b:Point {id:'B'})
MATCH p=allShortestPaths((a)-[:NEXT_POINT]-(b))
RETURN p, reduce(totalKm = 0, x in relationships(p)| totalKm + x.kilometers) as distance
ORDER BY distance ASC

还有带有成本属性的 Djikstra 算法可通过 Neo4j ReST API http://neo4j.com/docs/stable/rest-api-graph-algos.html

一些资源:

所以作为一个结论,如果你想使用 Neo4j 来确定最好的 路线,你需要帮助他处理数据库中的一些数据;-)

【讨论】:

  • 天哪,太棒了!非常感谢您提供的所有信息
【解决方案2】:

您所描述的似乎是从 A 到 B 的路线,通过不同的航路点(人们的位置),但目标是最小化从 A 到 B 的总距离。具有这些特征的图中的路径称为Minimum Spanning Tree。至关重要的是,人们可以前往“主要路线”这一事实只是引入了额外的航路点,它不会改变整体问题或经典解决问题的方式。

Cypher 和 REST API 都没有计算最小生成树的功能,不幸的是,简单地收集各个节点之间的最短路径(例如使用 Dijkstra 算法)然后尝试从这些最短路径段创建路径在一般情况。

但是,通过服务器插件或 Neo4j 中的非托管扩展来实现 Prim's algorithm 并不难,我建议您研究一下。

【讨论】:

  • 您是如何/在哪里找到该国家/地区的地理数据库的?
【解决方案3】:

我会start with this article。要提出更具体的问题,您需要一个数据模型和一个您正在尝试做什么的示例。

但通常使用的语言可能是“最短路径”。通常,如果您试图找到从 A 点到 B 点的路径,您正在寻找“路径成本”最小的“最短路径”。有时成本是距离,有时成本是时间 - 但无论哪种方式,您通常都在寻找最短路径,而不仅仅是任何路径。

【讨论】:

  • 这将是 2 到 x 点之间的最佳映射路线,具体取决于运输链中的人数。也希望能够根据每个人愿意开车到每个点中间的距离来计算每个人的半径
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-15
  • 1970-01-01
  • 2016-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多