polylines

This commit is contained in:
Milan Pässler 2020-02-14 16:34:52 +01:00
parent 72d26191fa
commit a998e4b244
5 changed files with 96 additions and 15 deletions

View file

@ -4,6 +4,7 @@ import ./point
import ./operator
import ./journey
import ./line
import ./polyline
import json
import sequtils
import strutils
@ -13,8 +14,9 @@ proc parseJourneysResponse*(data: JsonNode, isRefresh: bool = false): JourneysRe
let operators = map(data["res"]["common"]["opL"].getElems(), parseOperator)
let remarks = map(data["res"]["common"]["remL"].getElems(), parseRemark)
let lines = data["res"]["common"]["prodL"]
let polylines = map(data["res"]["common"]["polyL"].getElems(), mkParsePolyline(points))
let timestamp = parseInt(data["res"]["planrtTS"].getStr())
let common = CommonData(points: points, operators: operators, remarks: remarks, lines: lines, timestamp: timestamp)
let common = CommonData(points: points, operators: operators, remarks: remarks, lines: lines, polylines: polylines, timestamp: timestamp)
result.journeys = data["res"]["outConL"].getElems().map(mkParseJourney(common))
if not isRefresh:

View file

@ -27,6 +27,14 @@ proc parseLegPart(common: CommonData, lp: JsonNode): LegPart =
proc mkParseLeg*(common: CommonData): proc =
proc parseLeg(l: JsonNode): Leg =
if l{"polyG"}{"polyX"}.getElems().len() > 0:
result.polyline = Polyline(
type: "FeatureCollection"
)
for n in l{"polyG"}{"polyX"}.getElems():
result.polyline.features &= common.polylines[n.getInt()].features
echo pretty(%result.polyline)
let typeStr = l{"type"}.getStr()
if typeStr == "JNY":
result.direction = some(l{"jny"}{"dirTxt"}.getStr())

View file

@ -0,0 +1,74 @@
import ../types
import ../util
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

View file

@ -9,6 +9,7 @@ type
remarks*: seq[Remark]
operators*: seq[Operator]
points*: seq[Point]
polylines*: seq[Polyline]
dateStr*: string
timestamp*: int64
@ -42,3 +43,11 @@ type
addName*: Option[string]
opX*: Option[int]
prodCtx*: HafasProdCtx
HafasLocRef* = object
ppIdx*: int
locX*: int
HafasPolyline* = object
crdEncYX*: string
ppLocRefL*: Option[seq[HafasLocRef]]

View file

@ -69,6 +69,7 @@ type
cancelled*: bool
departure*: LegPart
arrival*: LegPart
polyline*: Polyline
distance*: Option[int] # required for isWalking or isTransfer
tripId*: Option[string] # required for not isWalking and not isTranfer
line*: Option[Line] # required for not isWalking and not isTranfer
@ -169,26 +170,13 @@ type
Feature* = object
`type`*: string
properties*: FeatureProperties
properties*: Option[Stop]
geometry*: FeatureGeometry
FeatureProperties* = object
`type`*: string
id*: int
name*: string
location*: FeatureLocation
products*: Products
station*: Station
FeatureGeometry* = object
`type`*: string
coordinates*: seq[float]
FeatureLocation* = object
`type`*: string
latitiude*: float
longitude*: float
notFoundException* = object of Exception
errorException* = object of Exception