Teekonnaarvutuse juhend

Praktiline juhend näidetega: teekonna arvutamine, vahepunktid, geomeetria ja väljundvormingud.

Päris näited. Päringud on tehtud teenuse vastu https://pump.elemroot.com/LogismeRouting.
Sisukord

Endpoint ja meetod

MeetodAadress
GEThttps://pump.elemroot.com/LogismeRouting/SURRouting

Teedevõrk katab Eesti, Läti ja Leedu (üks Balti graaf): nt Riia → Vilnius töötab. Ainult GET; POST annab 400.

Parameetrite koondtabel

ParamTähendusVõimalikud väärtused / näideVaikimisi
pref *Marsruudi-eelistus (tõstutundetu; tundmatu → 400)Fastest, Shortest, Pedestrian (= sama mis Shortest: autoteede võrk vahemaa järgi)—
start *Stardipunkt E,N (ida,põhi = pikkus,laius); alias Start22.513265,58.265563—
end *Sihtpunkt E,N; alias End23.233129,58.605584—
viaVahepunktid E,N, tühikuga eraldatud; alias Via22.8,58.45 22.9,58.5—
srsKoordinaatsüsteem (EPSG); ka bBox samas süsteemisainult EPSG:4326 või EPSG:3301 (L-EST97; prefiks EPSG: kohustuslik, tõstutundetu); muu väärtus annab 500EPSG:4326
outputVäljundvorming (tõstutundetu; tundmatu → 400)xml, jsonxml
noRouteGeomJäta geomeetria väljatäpselt false (väiketähtedega) = lisa geomeetria; FALSE/0 = vaikimisi (geom puudub)—
separateViaResultsIga via-lõik eralditrue / täpselt false (liidab lõigud üheks: kogupikkus ja -aeg on summa, LineString pidev joon); vaikimisi tõene—
maxDevÜldistamise max kõrvalekalle (m)nt 1, 10; 0 = üldistamata täisgeomeetria; mittenumbriline → 500—
maxPointsGeomeetria punktide ülempiir (võidab maxDev-i)täisarv, nt 100; mittenumbriline → 500—
bBoxKärpimisaken (kaks E,N punkti tühikuga; väljaspool akent taandub joon sirgeks)22.5,58.2 23.3,58.7; vale kuju → 400—
callbackJSONP callback (ainult koos output=json)funktsiooni nimi, nt cb → vastus cb && cb([…]) (/ESRIRouting-il cb({…}))—
key *API-võti (puudub/vale → 403 JSON {"error":"invalid_api_key"}); POST-il alati URL-isdocs_382d376eaaa6d004b7b93b7d (demo, kiiruspiiranguga)—
L-EST koordinaadid (EPSG:3301). Marsruutimine toetab ka Eesti tasapinnalisi koordinaate: lisa srs=EPSG:3301 ja anna start/end L-EST kujul E,N (ida,põhi meetrites). Väljundi koordinaadid (BoundingBox, LineString, gml:pos) tulevad samuti samas süsteemis. Näide:
curl "https://pump.elemroot.com/LogismeRouting/SURRouting?pref=Fastest&start=660545.95,6476102.22&end=553474.28,6583771.55&srs=EPSG:3301&output=json&noRouteGeom=false&key=docs_382d376eaaa6d004b7b93b7d"

Esimene päring

Päring
curl "https://pump.elemroot.com/LogismeRouting/SURRouting?pref=Fastest&start=22.513265,58.265563&end=23.233129,58.605584&output=json&key=docs_382d376eaaa6d004b7b93b7d"
Vastus (json: ainult kokkuvõte)
[
  {
    "RouteSummary": {
      "BoundingBox": [
        { "e": 22.512399678574166, "n": 58.26509890506477 },
        { "e": 23.233128562435795, "n": 58.60563260378001 }
      ],
      "TotalTime": "P0Y0M0DT0H48M35.080S",
      "TotalDistance": "62973.600000000006"
    }
  }
]
VäliTähendus
TotalTimeSõiduaeg ISO 8601 kestusena (P0Y0M0DT0H48M35.080S = 48 min 35,08 s)
TotalDistanceKogupikkus meetrites (string)
BoundingBoxTeekonna ümbritsev ristkülik (kaks nurgapunkti {e,n})

Teejoone geomeetria

Vaikimisi geomeetriat EI tagastata: saad ainult kokkuvõtte. Teejoone punktide saamiseks lisa noRouteGeom=false.
Päring
curl "https://pump.elemroot.com/LogismeRouting/SURRouting?pref=Fastest&start=22.513265,58.265563&end=23.233129,58.605584&output=json&noRouteGeom=false&key=docs_382d376eaaa6d004b7b93b7d"
Vastus (lisandub RouteGeometry)
[
  {
    "RouteSummary": { "TotalTime": "P0Y0M0DT0H48M35.080S", "TotalDistance": "62973.600000000006", "BoundingBox": [ ... ] },
    "RouteGeometry": {
      "LineString": [
        { "n": 58.265563, "e": 22.513265 },
        { "n": 58.265921552298856, "e": 22.512801561977046 },
        { "n": 58.2658073706609, "e": 22.51254892386472 }
      ]
    }
  }
]

LineString on teejoone punktid järjekorras stardist sihtpunktini ({n, e} = põhi, ida).

Vahepunktid (via)

Lisa via-punkte (tühikuga eraldatud E,N punktid):

curl "https://pump.elemroot.com/LogismeRouting/SURRouting?pref=Shortest&start=22.513265,58.265563&via=22.8,58.45&end=23.233129,58.605584&output=json&key=docs_382d376eaaa6d004b7b93b7d"
Vaikimisi eraldi lõigud. Via-punktidega tagastatakse iga lõik eraldi RouteSummary objektina (start→via1, via1→end, …). Üheks teekonnaks liitmiseks lisa separateViaResults=false (täpselt väiketähtedega); siis on TotalDistance/TotalTime lõikude summa ja LineString üks pidev joon.
Vastus (kaks lõiku)
[
  { "RouteSummary": { "TotalDistance": "28189.0", "TotalTime": "P0Y0M0DT0H22M17.770S", "BoundingBox": [ ... ] } },
  { "RouteSummary": { "TotalDistance": "34742.1", "TotalTime": "P0Y0M0DT0H31M47.620S", "BoundingBox": [ ... ] } }
]

Koordinaatide järjekord

NB: sisendi E,N on vastupidine geokodeerimise/pöördgeo q-le (lat,lon).

XML (OpenLS XLS)

Vaikimisi (output=xml) tagastatakse OpenLS XLS XML:

<?xml version='1.0' encoding='UTF-8'?>
<XLS version="1.1" xmlns="http://www.opengis.net/xls" xmlns:gml="http://www.opengis.net/gml">
  <ResponseHeader/>
  <Response version="" requestID="">
    <DetermineRouteResponse>
      <RouteSummary>
        <TotalTime>P0Y0M0DT0H48M35.080S</TotalTime>
        <TotalDistance value="62973.600000000006"/>
        <BoundingBox>
          <gml:pos>58.26509890506477 22.512399678574166</gml:pos>
          <gml:pos>58.60563260378001 23.233128562435795</gml:pos>
        </BoundingBox>
      </RouteSummary>
      <RouteGeometry>
        <gml:LineString>
          <gml:pos>58.265563 22.513265</gml:pos>
          <gml:pos>58.265921552298856 22.512801561977046</gml:pos>
        </gml:LineString>
      </RouteGeometry>
    </DetermineRouteResponse>
  </Response>
</XLS>

Geomeetria üldistamine

Teejoone geomeetriat saab üldistada (lihtsustada):

ParamTähendus
maxDevMaksimaalne lubatud kõrvalekalle meetrites (vaikimisi 1). Suurem = jämedam joon; 0 = üldistamata täisgeomeetria.
maxPointsGeomeetria punktide ülempiir (kui antud, võidab maxDev-i).
bBoxKärpimisaken (kaks E,N punkti tühikuga, samas srs-is): akna sees täpne, väljaspool taandub joon praktiliselt sirgeks (jäävad ainult akna otsapunktid ja sihtpunkt).
Mittenumbriline maxDev/maxPoints annab 500; vale bBox kuju 400.
curl "https://pump.elemroot.com/LogismeRouting/SURRouting?pref=Fastest&start=22.513265,58.265563&end=23.233129,58.605584&output=json&noRouteGeom=false&maxDev=10&maxPoints=100&key=docs_382d376eaaa6d004b7b93b7d"

ESRI-liides (ArcGIS)

Endpoint /ESRIRouting on ArcGIS Network Analyst stiilis liides. Peatuspunktid antakse parameetriga stops (ArcGIS FeatureSet JSON või lihtsüntaks x1,y1;x2,y2), vastus on ArcGIS Directions JSON. f=json on kohustuslik.

ESRI-liides. Endpoint /LogismeRouting/ESRIRouting toetab nt impedanceAttributeName=Distance (lühim teepikkus). Allolev näide on päris töötav päring.
Päring (stops EPSG:3301, sihifunktsioon Distance)
curl -G "https://pump.elemroot.com/LogismeRouting/ESRIRouting" \
  --data-urlencode 'stops={"features":[{"geometry":{"x":635541.4,"y":6583331.7,"spatialReference":{"wkid":3301}},"attributes":{}},{"geometry":{"x":638218.2,"y":6589326.7,"spatialReference":{"wkid":3301}},"attributes":{}}]}' \
  --data-urlencode "outSR=3301" \
  --data-urlencode "impedanceAttributeName=Distance" \
  --data-urlencode "directionsLanguage=et_EE" \
  --data-urlencode "directionsLengthUnits=esriNAUKilometers" \
  --data-urlencode "outputGeometryPrecisionUnits=esriMeters" \
  --data-urlencode "outputGeometryPrecision=0.7" \
  --data-urlencode "ignoreInvalidLocations=true" \
  --data-urlencode "returnDirections=true" \
  --data-urlencode "returnRoutes=false" \
  --data-urlencode "findBestSequence=false" \
  --data-urlencode "startTime=1307001600000" \
  --data-urlencode "key=docs_382d376eaaa6d004b7b93b7d" \
  --data-urlencode "f=json"
Vastus (ArcGIS Directions, lühendatud)
{
  "directions": [
    {
      "summary": {
        "envelope": { "xmin": 635541.4, "ymin": 6583322.45, "xmax": 638218.2, "ymax": 6589326.7,
                      "spatialReference": { "wkid": 3301 } },
        "totalDriveTime": 14.0415,
        "totalTime": 14.0415,
        "totalLength": 11.4213
      },
      "features": [
        { "compressedGeometry": "+3+1q5u0+iqn3b+u-s",
          "attributes": { "ETA": 1307001600000, "length": 0.0136, "maneuverType": "esriDMTDepart",
                          "time": 0.0817, "text": "1. sihtpunkt" } },
        { "compressedGeometry": "+3+1q5uu+iqn2f-p7-r1+o-d…",
          "attributes": { "ETA": 1307001604900, "length": 11.3988, "maneuverType": "esriDMTTurnRight",
                          "time": 13.9063, "text": "Sõida 11,4 km." } }
      ]
    }
  ],
  "messages": []
}
VäliTähendus
summary.totalLengthKogupikkus alati kilomeetrites (ei sõltu directionsLengthUnits-ist)
routeId / routeNameMarsruudi ID (1) ja nimi ("Location 1 - Location N", või peatuste attributes.Name järgi)
summary.totalDriveTime / totalTimeAeg minutites
summary.envelopeMarsruudi ümbritsev ristkülik (xmin/ymin/xmax/ymax + wkid)
features[].compressedGeometryESRI pakitud geomeetria (lõigu joon)
features[].attributes.textSõidujuhise tekst
features[].attributes.maneuverTypeManöövri tüüp (esriDMTDepart, esriDMTTurnRight, …)
features[].attributes.length / timeLõigu pikkus (ühik = directionsLengthUnits: km või m) / aeg minutites
features[].attributes.ETASaabumisaeg (Unix-ms; arvutatud startTime-ist)

Parameetrid (* = kohustuslik; tabel genereeritakse OpenAPI-YAML-ist):

ParamTähendusVõimalikud väärtused / näideVaikimisi
stops *Peatuspunktid, vähemalt 2; FeatureSet'i attributes.Name = peatuse nimi (routeName, juhiste tekst); RouteName → 400FeatureSet JSON {"features":[{"geometry":{"x":…,"y":…,"spatialReference":{"wkid":3301}},"attributes":{}},…]} või lihtsüntaks x1,y1;x2,y2—
f *Väljundvormingpeab olema json (puudumisel sõnumita 400)—
outSRVäljundi ja sisendi WKID; antuna peab iga punkti spatialReference.wkid olema sama; puudumisel EI tohi punktidel spatialReference'i üldse olla (kraadid, EPSG:4326)3301 või 4326; muu → 400—
directionsLanguage *Juhiste keel (Java Locale); tundmatu → 400et_EE, en_US, de_DE, fi_FI, ru_RU, sv_SE, ja_JP (ka lühikuju et)—
directionsLengthUnits *Pikkusühik features[].attributes.length väljas; summary.totalLength ja juhiste tekst on alati kmesriNAUKilometers / esriNAUMeters—
outputGeometryPrecisionUnits *Geomeetria täpsuse ühikpeab olema esriMeters—
outputGeometryPrecisionGeomeetria üldistustäpsus meetrites (vaikimisi ≈0,05: näite 0.7 on jämedam)arv, nt 0.7; mittenumbriline → 400—
impedanceAttributeNameSihifunktsioonDistance = lühim; DrivingMinutes või puudub = kiireim; muu → 400—
ignoreInvalidLocations *Kohustuslik ühilduvusparameeter (väärtust ei kasutata)nt true—
returnDirectionsSõidujuhiste tagastaminevaikimisi true; false annab sisutu vastuse {"messages":[]}—
returnRoutes *Marsruudi-objektide tagastaminekohustuslik, peab olema false (true/puudub → 400)—
findBestSequence *Peatuste järjekordkohustuslik; false = antud järjekord, true = peatuste järjekorra optimeerimine (TSP; algus ja lõpp jäävad paigale)—
returnStopsPeatuste FeatureSet vastusesse (ObjectID, Sequence, Cumul_Time s, Status, geomeetria)true / false (vaikimisi)—
startTimeLäht-aeg Unix-ms (ETA jaoks); puudumisel on ETA möödunud ms alates 01307001600000; mittenumbriline → 400—
key *API-võti (puudub/vale → 403 JSON {"error":"invalid_api_key"}); POST-il alati URL-isdocs_382d376eaaa6d004b7b93b7d (demo, kiiruspiiranguga)—

Osa ArcGIS-parameetreid eiratakse (accumulateAttributeNames, useHierarchy, outputLines, preserveFirstStop, preserveLastStop, directionsStyleName, useTimeWindows, returnBarriers-pere väärtusega false); neid võib päringus hoida ühilduvuse huvides. Seevastu barriers, polylineBarriers, restrictUTurns, restrictionAttributeNames, attributeParameterValues, directionsTimeAttributeName annavad 400 („isn't supported").

Peatuste järjekorra optimeerimine (findBestSequence=true)

Mitme peatusega marsruudil võib teenus peatuste järjekorra ise optimeerida (rändkaupmehe ülesanne, TSP): algus- ja lõpp-peatus jäävad paigale, vahepealsed järjestatakse ümber nii, et kogu ring oleks lühim/kiireim (vastavalt impedanceAttributeName-ile). Vastus (juhised, pikkus, aeg) käib optimeeritud järjestuse kohta; uue järjekorra saad kätte returnStops=true-ga: stops[].ObjectID on sisendjärjekord, Sequence uus järjekord, Cumul_Time kumulatiivne sõiduaeg sekundites.

Päring (4 peatust Tartus, EPSG:3301; sama parameetrikomplekt mis ülal, ainult findBestSequence=true&returnStops=true)
curl -G "https://pump.elemroot.com/LogismeRouting/ESRIRouting" \
  --data-urlencode 'stops={"features":[{"geometry":{"x":659000,"y":6473000,"spatialReference":{"wkid":3301}},"attributes":{}},{"geometry":{"x":664500,"y":6470500,"spatialReference":{"wkid":3301}},"attributes":{}},{"geometry":{"x":661500,"y":6472500,"spatialReference":{"wkid":3301}},"attributes":{}},{"geometry":{"x":658000,"y":6469500,"spatialReference":{"wkid":3301}},"attributes":{}}]}' \
  --data-urlencode "outSR=3301" --data-urlencode "impedanceAttributeName=Distance" \
  --data-urlencode "directionsLanguage=et_EE" --data-urlencode "directionsLengthUnits=esriNAUKilometers" \
  --data-urlencode "outputGeometryPrecisionUnits=esriMeters" --data-urlencode "ignoreInvalidLocations=true" \
  --data-urlencode "returnRoutes=false" --data-urlencode "findBestSequence=true" --data-urlencode "returnStops=true" \
  --data-urlencode "key=docs_382d376eaaa6d004b7b93b7d" --data-urlencode "f=json"
Vastus (lühendatud: sama päring findBestSequence=false andis 22,62 km / 38,3 min)
{
  "directions": [ { "routeId": 1, "routeName": "Location 1 - Location 4",
                    "summary": { "totalLength": 21.1842, "totalTime": 33.7405, … }, "features": [ … ] } ],
  "stops": {
    "features": [
      { "attributes": { "ObjectID": 1, "Sequence": 1, "Cumul_Time": 0,       "Status": 0 }, "geometry": { "x": 659000, "y": 6473000 } },
      { "attributes": { "ObjectID": 2, "Sequence": 3, "Cumul_Time": 1067.39, "Status": 0 }, "geometry": { "x": 664500, "y": 6470500 } },
      { "attributes": { "ObjectID": 3, "Sequence": 2, "Cumul_Time": 495.46,  "Status": 0 }, "geometry": { "x": 661500, "y": 6472500 } },
      { "attributes": { "ObjectID": 4, "Sequence": 4, "Cumul_Time": 2024.43, "Status": 0 }, "geometry": { "x": 658000, "y": 6469500 } }
    ],
    "spatialReference": { "wkid": 3301 }
  }
}

Peatuste järjekord muutus 1→2→3→4 pealt 1→3→2→4 peale ja ring lühenes 1,4 km võrra. Ilma returnStops-ita on optimeeritud järjekord vastuses kaudselt (juhiste tekst „N. sihtpunkt").

Muud liidesed

Lisaks lühi-URL REST- ja ESRI-liidesele pakub teenus:

TeeLiides
/SURRoutingLühi-URL REST (query-parameetrid): selle juhendi teema
/routingXML-sisend (POST XML keha)
/ESRIRoutingESRI-ühilduv liides (sh trajektoori kirjeldus)
/services/*SOAP (Apache Axis)

Millal mida kasutada

Sagedasemad ülesanded ja neile vastav liides/parameetrikombinatsioon. Kõik read on elusalt kontrollitud.

ÜlesanneKombinatsioonMiks
Kiireim/lühim teekond A→B: ainult pikkus ja aeg/SURRouting?pref=Fastest&start=…&end=…&output=jsonvaikimisi ainult kokkuvõte, väikseim vastus
Teejoon kaardilenoRouteGeom=false (+ maxDev=10 või maxPoints=100 kergemaks)geomeetria vaikimisi puudub; üldistus vähendab punkte
Mitu peatust antud järjekorrasvia=E,N E,N (+ separateViaResults=false üheks teekonnaks)lõigud eraldi või summeeritult
Peatuste järjekorra optimeerimine (TSP)/ESRIRouting … findBestSequence=true&returnStops=trueainult ESRI-liides; vt eespool
Sõidujuhised (pöörded, tekst, ETA)/ESRIRouting … returnDirections=true&directionsLanguage=et_EE/SURRouting juhiseid ei anna
L-EST97 koordinaadid meetritessrs=EPSG:3301 (SUR) · outSR=3301 + wkid: 3301 (ESRI)sisend ja väljund samas süsteemis
ArcGIS-klient (Network Analyst stiilis)/ESRIRouting täisparameetritega (vt näidet)ühilduv Directions JSON
OpenLS XML (pärandintegratsioon)output=xml (vaikimisi)XLS 1.1
Brauserist ilma CORS-ita (JSONP)output=json&callback=cbvastus cb && cb([…]); CORS-päised on niikuinii olemas
Viis lõksu. (1) Sisend on E,N = lon,lat: vastupidi geokodeerimise q-le. (2) Geomeetria tuleb ainult noRouteGeom=false-ga (täpselt väiketähtedega). (3) Marsruudi puudumine on /SURRouting-il 500 (HTML), /ESRIRouting-il 400 (JSON); kontrolli mõlemat. (4) POST-il peab key olema URL-is, mitte kehas. (5) Sama parameeter kaks korda päringus → loeb esimene väärtus.

Veakäsitlus

OlukordKoodTeade
Puuduv kohustuslik parameeter400Missing parameter "pref"
Vigased koordinaadid400Invalid point coordinates … / Non-numeric coordinates …
Tundmatu output / pref; vale bBox kuju400Unknown output format: … / Unsupported cost function: … / Invalid bBox value: …
POST päring (võti URL-is)400Sorry, HTTP POST not supported (kui võti pole URL-is, tuleb enne 403)
Võti puudub või on vale403JSON {"error":"invalid_api_key"}
Liiga tihedad päringud (demo-võti)429Too Many Requests (HTML)
Marsruuti ei leitud; tundmatu srs; mittenumbriline maxDev/maxPoints500No route exists from location (id=1; e=…; n=…) to location (id=2; …). / Unknown EPSG code: …

/SURRouting vea keha (400/500) on Tomcati HTML-vealeht, sõnum on pealkirjas (<h1>HTTP Status 400 - Missing parameter "pref"</h1>). /ESRIRouting vead on JSON {"error":{"message":"…","status":400}}; ka „marsruuti ei leitud" ja teedevõrgu ristkülikust väljas punkt (Coordinates of destination … are out of range) on ESRI-l 400, mitte 500.

Teedevõrgust välja jääv punkt annab 500 (/ESRIRouting-il 400). Kui punkt on teedevõrgust liiga kaugel (nt meres või lagedal), ei leia teenus marsruuti ja vastab 500-ga. Tõrge võib sõltuda suunast: sama punkt võib start-ina töötada (naelutatakse lähimale teele), aga end-ina anda 500. Mitme peatusega marsruudil tasub 500 korral proovida lõike ükshaaval: nii leiad üles konkreetse probleemse punkti.

API viide (Swagger UI) → Interaktiivne „proovi järele”. OpenAPI spec (YAML-fail) → Masinloetav API kirjeldus tööriistadele. NB: avaneb toore YAML-failina.

Näited galeriis