Вчера я написал сообщение в блоге, показывающее, как найти среднюю точку между двумя широтами / долготами, используя Cypher, что сработало как первая попытка заполнить пропущенные места, но я понял, что могу добиться большего.
Как я упоминал в предыдущем посте, когда я нахожу остановку, в которой отсутствуют координаты широты / долготы, я обычно могу найти две близлежащие остановки, которые позволяют мне триангулировать местоположение этой остановки.
У меня также есть маршруты поездов, которые указывают количество секунд, необходимое для перехода от одной остановки к другой, что позволяет мне указать, ближе ли остановка без местоположения к одной остановке, чем к другой.
Например, рассмотрим остановки a, b и c, где b не имеет местоположения. Если у нас есть эти расстояния между остановками:
|
1
|
(a)-[:NEXT {time: 60}]->(b)-[:NEXT {time: 240}]->(c) |
это говорит нам о том, что точка «b» на самом деле равна 0.2 расстояния от «a» до «c», а не является средней точкой.
Есть формула, которую мы можем использовать, чтобы решить эту проблему:
|
01
02
03
04
05
06
07
08
09
10
11
|
a = sin((1−f)⋅δ) / sin δb = sin(f⋅δ) / sin δx = a ⋅ cos φ1 ⋅ cos λ1 + b ⋅ cos φ2 ⋅ cos λ2y = a ⋅ cos φ1 ⋅ sin λ1 + b ⋅ cos φ2 ⋅ sin λ2z = a ⋅ sin φ1 + b ⋅ sin φ2φi = atan2(z, √x² + y²)λi = atan2(y, x) δ is the angular distance d/R between the two points.φ = latitudeλ = longitude |
В переводе на Cypher (с обязательными греческими символами) это выглядит так, чтобы найти точку 0.2 пути от одной точки к другой
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
with {latitude: 51.4931963543, longitude: -0.0475185810} AS p1, {latitude: 51.47908, longitude: -0.05393950 } AS p2 WITH p1, p2, distance(point(p1), point(p2)) / 6371000 AS δ, 0.2 AS fWITH p1, p2, δ, sin((1-f) * δ) / sin(δ) AS a, sin(f * δ) / sin(δ) AS bWITH radians(p1.latitude) AS φ1, radians(p1.longitude) AS λ1, radians(p2.latitude) AS φ2, radians(p2.longitude) AS λ2, a, bWITH a * cos(φ1) * cos(λ1) + b * cos(φ2) * cos(λ2) AS x, a * cos(φ1) * sin(λ1) + b * cos(φ2) * sin(λ2) AS y, a * sin(φ1) + b * sin(φ2) AS zRETURN degrees(atan2(z, sqrt(x^2 + y^2))) AS φi, degrees(atan2(y,x)) AS λi |
|
1
2
3
4
5
|
╒═════════════════╤════════════════════╕│φi │λi │╞═════════════════╪════════════════════╡│51.49037311149128│-0.04880308288561931│└─────────────────┴────────────────────┘ |
Быстрая проверка работоспособности с подключением 0,5 вместо 0,2 находит середину, которую я смог проверить на соответствие вчерашнему посту:
|
1
2
3
4
5
|
╒═════════════════╤═════════════════════╕│φi │λi │╞═════════════════╪═════════════════════╡│51.48613822097523│-0.050729537454086385│└─────────────────┴─────────────────────┘ |
На этом пока все!
| Ссылка: | Neo4j: Найдите промежуточную точку между двумя широтами / долготами от нашего партнера по JCG Марка Нидхэма в блоге Марка Нидхэма . |