74 lines
1.9 KiB
Nim
74 lines
1.9 KiB
Nim
import ../types
|
|
import json
|
|
import options
|
|
import math
|
|
|
|
proc gpsDistance(fromLat: float, fromLon: float, toLat: float, toLon: float): float =
|
|
proc toRad(x: float): float = x * PI / 180
|
|
let dLat = toRad(toLat - fromLat)
|
|
let dLon = toRad(toLon - fromLon)
|
|
let fromLat = toRad(fromLat)
|
|
let toLat = toRad(toLat)
|
|
let a = pow(sin(dLat / 2), 2) + (pow(sin(dLon / 2), 2) * cos(fromLat) * cos(toLat))
|
|
let c = 2 * arctan2(sqrt(a), sqrt(1 - a))
|
|
return 6371 * c
|
|
|
|
proc parseIntegers(str: string): seq[int] =
|
|
var byte = 0
|
|
var current = 0
|
|
var bits = 0
|
|
for c in str:
|
|
byte = int(c) - 63
|
|
current = current or (( byte and 31 ) shl bits)
|
|
bits += 5
|
|
|
|
if byte < 32:
|
|
if (current and 1) == 1:
|
|
current = -current
|
|
current = current shr 1
|
|
|
|
result.add(current)
|
|
|
|
current = 0
|
|
bits = 0
|
|
|
|
proc mkParsePolyline*(points: seq[Point]): proc =
|
|
proc parsePolyline(l: JsonNode): Polyline =
|
|
let line = l.to(HafasPolyLine)
|
|
|
|
result.type = "FeatureCollection"
|
|
|
|
var lat = 0
|
|
var lon = 0
|
|
|
|
let ints = parseIntegers(line.crdEncYX)
|
|
var i = 0
|
|
while i < len(ints):
|
|
lat += ints[i]
|
|
lon += ints[i+1]
|
|
result.features.add(Feature(
|
|
type: "Feature",
|
|
geometry: FeatureGeometry(
|
|
type: "Point",
|
|
coordinates: @[lon / 100000, lat / 100000],
|
|
),
|
|
))
|
|
i += 2
|
|
|
|
if line.ppLocRefL.isSome:
|
|
for p in line.ppLocRefL.get:
|
|
result.features[p.ppIdx].properties = points[p.locX].stop
|
|
|
|
# sort out coordinates closer than 5m to their neighbours
|
|
var j = 1
|
|
while true:
|
|
if j >= len(result.features): break
|
|
let last = result.features[j-1].geometry.coordinates
|
|
let current = result.features[j].geometry.coordinates
|
|
if gpsDistance(last[1], last[0], current[1], current[0]) <= 0.005:
|
|
result.features.delete(j)
|
|
continue
|
|
j += 1
|
|
|
|
return parsePolyline
|