Вчера я написал сообщение в блоге, показывающее, как найти среднюю точку между двумя широтами / долготами, используя 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 λ 2 y = a ⋅ cos φ 1 ⋅ sin λ 1 + b ⋅ cos φ 2 ⋅ sin λ 2 z = 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 f WITH p1, p2, δ, sin(( 1 -f) * δ) / sin(δ) AS a, sin(f * δ) / sin(δ) AS b WITH radians(p1.latitude) AS φ 1 , radians(p1.longitude) AS λ 1 , radians(p2.latitude) AS φ 2 , radians(p2.longitude) AS λ 2 , a, b WITH 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 z RETURN 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 Марка Нидхэма в блоге Марка Нидхэма . |