Format route points as waypoints
This commit is contained in:
parent
449a24e5ce
commit
7fc2f6bee5
8 changed files with 380 additions and 19 deletions
|
|
@ -69,6 +69,9 @@ BR.Export = L.Class.extend({
|
||||||
|
|
||||||
_formatTrack: function (format, name, includeWaypoints) {
|
_formatTrack: function (format, name, includeWaypoints) {
|
||||||
const track = BR.Export._concatTotalTrack(this.segments);
|
const track = BR.Export._concatTotalTrack(this.segments);
|
||||||
|
if (includeWaypoints) {
|
||||||
|
this._addRouteWaypoints(track);
|
||||||
|
}
|
||||||
//console.log('GeoJson: ', trackGeoJson);
|
//console.log('GeoJson: ', trackGeoJson);
|
||||||
//console.log('GeoJson: ', JSON.stringify(trackGeoJson, null, 4));
|
//console.log('GeoJson: ', JSON.stringify(trackGeoJson, null, 4));
|
||||||
switch (format) {
|
switch (format) {
|
||||||
|
|
@ -85,6 +88,24 @@ BR.Export = L.Class.extend({
|
||||||
console.error('Export format not implemented: ' + format);
|
console.error('Export format not implemented: ' + format);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_addRouteWaypoints: function (track) {
|
||||||
|
const routePoints = [];
|
||||||
|
for (const [i, latLng] of this.latLngs.entries()) {
|
||||||
|
let name = 'via' + i;
|
||||||
|
let type = 'via';
|
||||||
|
if (i === 0) {
|
||||||
|
name = 'from';
|
||||||
|
type = 'from';
|
||||||
|
} else if (i === this.latLngs.length - 1) {
|
||||||
|
name = 'to';
|
||||||
|
type = 'to';
|
||||||
|
}
|
||||||
|
const properties = { name, type };
|
||||||
|
routePoints.push(turf.point([latLng.lng, latLng.lat], properties));
|
||||||
|
}
|
||||||
|
track.features.push(...routePoints);
|
||||||
|
},
|
||||||
|
|
||||||
_validationMessage: function () {
|
_validationMessage: function () {
|
||||||
var trackname = this.trackname;
|
var trackname = this.trackname;
|
||||||
var replaceRegex = new RegExp('[^' + this.tracknameAllowedChars + ']', 'g');
|
var replaceRegex = new RegExp('[^' + this.tracknameAllowedChars + ']', 'g');
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,34 @@ BR.Gpx = {
|
||||||
format: function (geoJson, turnInstructionMode = 0, transportMode = 'bike') {
|
format: function (geoJson, turnInstructionMode = 0, transportMode = 'bike') {
|
||||||
if (!geoJson?.features) return '';
|
if (!geoJson?.features) return '';
|
||||||
|
|
||||||
const trkNameTransform = {
|
class GpxTransform {
|
||||||
comment: '',
|
constructor(voiceHintsTransform) {
|
||||||
trk: function (trk, feature, coordsList) {
|
this.voiceHintsTransform = voiceHintsTransform;
|
||||||
|
this.comment = voiceHintsTransform?.comment || '';
|
||||||
|
|
||||||
|
if (this.voiceHintsTransform) {
|
||||||
|
Object.keys(this.voiceHintsTransform).forEach((member) => {
|
||||||
|
if (!GpxTransform.prototype.hasOwnProperty(member)) {
|
||||||
|
this[member] = this.voiceHintsTransform[member];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wpt(wpt, feature, coord, index) {
|
||||||
|
// not in use right now, just to be safe in case of future overrides
|
||||||
|
wpt = (voiceHintsTransform?.wpt && voiceHintsTransform.wpt(wpt, feature, coord, index)) || wpt;
|
||||||
|
if (feature.properties.name) {
|
||||||
|
wpt.name = feature.properties.name;
|
||||||
|
}
|
||||||
|
if (feature.properties.type) {
|
||||||
|
wpt.type = feature.properties.type;
|
||||||
|
}
|
||||||
|
return wpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
trk(trk, feature, coordsList) {
|
||||||
|
trk = (voiceHintsTransform?.trk && voiceHintsTransform.trk(trk, feature, coordsList)) || trk;
|
||||||
// name as first tag, by using assign and in this order
|
// name as first tag, by using assign and in this order
|
||||||
return Object.assign(
|
return Object.assign(
|
||||||
{
|
{
|
||||||
|
|
@ -12,14 +37,15 @@ BR.Gpx = {
|
||||||
},
|
},
|
||||||
trk
|
trk
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
let gpxTransform = trkNameTransform;
|
|
||||||
|
|
||||||
|
let voiceHintsTransform;
|
||||||
if (turnInstructionMode > 1) {
|
if (turnInstructionMode > 1) {
|
||||||
const voiceHints = BR.voiceHints(geoJson, turnInstructionMode, transportMode);
|
const voiceHints = BR.voiceHints(geoJson, turnInstructionMode, transportMode);
|
||||||
gpxTransform = voiceHints.getGpxTransform();
|
voiceHintsTransform = voiceHints.getGpxTransform();
|
||||||
}
|
}
|
||||||
|
const gpxTransform = new GpxTransform(voiceHintsTransform);
|
||||||
|
|
||||||
let gpx = togpx(geoJson, {
|
let gpx = togpx(geoJson, {
|
||||||
featureTitle: function () {},
|
featureTitle: function () {},
|
||||||
|
|
|
||||||
|
|
@ -48,14 +48,7 @@
|
||||||
comment: '',
|
comment: '',
|
||||||
trk: function (trk, feature, coordsList) {
|
trk: function (trk, feature, coordsList) {
|
||||||
const properties = this._getTrk();
|
const properties = this._getTrk();
|
||||||
|
return Object.assign(properties, trk);
|
||||||
return Object.assign(
|
|
||||||
{
|
|
||||||
name: feature.properties.name,
|
|
||||||
},
|
|
||||||
properties,
|
|
||||||
trk
|
|
||||||
);
|
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -146,12 +139,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
_addWaypoints(gpx) {
|
_addWaypoints(gpx) {
|
||||||
|
const waypoints = [];
|
||||||
this._loopHints((hint, cmd, coord) => {
|
this._loopHints((hint, cmd, coord) => {
|
||||||
const properties = this._getWpt(hint, cmd, coord);
|
const properties = this._getWpt(hint, cmd, coord);
|
||||||
|
|
||||||
const wpt = this._createWpt(coord, properties);
|
const wpt = this._createWpt(coord, properties);
|
||||||
gpx.wpt.push(wpt);
|
waypoints.push(wpt);
|
||||||
});
|
});
|
||||||
|
gpx.wpt.unshift(...waypoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
_createWpt(coord, properties) {
|
_createWpt(coord, properties) {
|
||||||
|
|
|
||||||
|
|
@ -112,10 +112,10 @@ BR.Diff.adoptGpx = function (gpx, replaceCreator = true) {
|
||||||
gpx = gpx.replace(/(lon|lat)="([-0-9]+.[0-9]+?)0+"/g, '$1="$2"'); // remove trailing zeros
|
gpx = gpx.replace(/(lon|lat)="([-0-9]+.[0-9]+?)0+"/g, '$1="$2"'); // remove trailing zeros
|
||||||
// remove trailing zeros comment-style voicehints
|
// remove trailing zeros comment-style voicehints
|
||||||
gpx = gpx.replace(/;\s*([-0-9]+.[0-9]+?)0+;/g, (match, p1) => `;${p1.padStart(10)};`);
|
gpx = gpx.replace(/;\s*([-0-9]+.[0-9]+?)0+;/g, (match, p1) => `;${p1.padStart(10)};`);
|
||||||
|
gpx = gpx.replace(/>([-0-9]+?\.\d*0+)<\//g, (match, p1) => `>${+p1}</`); // remove trailing zeros
|
||||||
gpx = gpx.replace('</gpx>\n', '</gpx>');
|
gpx = gpx.replace('</gpx>\n', '</gpx>');
|
||||||
|
|
||||||
// added
|
// added
|
||||||
gpx = gpx.replace(/>([-.0-9]+?0+)<\//g, (match, p1) => `>${+p1}</`); // remove trailing zeros
|
|
||||||
// trunc bc. float precision diffs
|
// trunc bc. float precision diffs
|
||||||
gpx = gpx.replace(/(rteTime|rteSpeed)>([^<]*)<\//g, (match, p1, p2) => `${p1}>${(+p2).toFixed(3)}</`);
|
gpx = gpx.replace(/(rteTime|rteSpeed)>([^<]*)<\//g, (match, p1, p2) => `${p1}>${(+p2).toFixed(3)}</`);
|
||||||
gpx = gpx.replace(/\n?\s*<\/extensions>\n?\s*<extensions>/, ''); // ignore (invalid) double tag
|
gpx = gpx.replace(/\n?\s*<\/extensions>\n?\s*<extensions>/, ''); // ignore (invalid) double tag
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
BR = {};
|
BR = {};
|
||||||
|
BR.conf = {};
|
||||||
|
$ = require('jquery');
|
||||||
require('leaflet');
|
require('leaflet');
|
||||||
turf = require('@turf/turf');
|
turf = require('@turf/turf');
|
||||||
require('../../js/control/Export.js');
|
require('../../js/control/Export.js');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
const indexHtmlString = fs.readFileSync('index.html', 'utf8');
|
||||||
|
const indexHtml = new DOMParser().parseFromString(indexHtmlString, 'text/html');
|
||||||
|
|
||||||
// &lonlats=8.467712,49.488117;8.469354,49.488394;8.470556,49.488946;8.469982,49.489176 + turnInstructionMode=2
|
// &lonlats=8.467712,49.488117;8.469354,49.488394;8.470556,49.488946;8.469982,49.489176 + turnInstructionMode=2
|
||||||
const segments = require('./data/segments.json');
|
const segments = require('./data/segments.json');
|
||||||
|
|
@ -24,6 +30,10 @@ function adopt(total, brouterTotal) {
|
||||||
total.features[0].properties.name = brouterTotal.features[0].properties.name;
|
total.features[0].properties.name = brouterTotal.features[0].properties.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
document.body = indexHtml.body.cloneNode(true);
|
||||||
|
});
|
||||||
|
|
||||||
test('total track', () => {
|
test('total track', () => {
|
||||||
const segmentsString = JSON.stringify(segments, null, 2);
|
const segmentsString = JSON.stringify(segments, null, 2);
|
||||||
let total = BR.Export._concatTotalTrack(segments);
|
let total = BR.Export._concatTotalTrack(segments);
|
||||||
|
|
@ -38,3 +48,30 @@ test('total track', () => {
|
||||||
adopt(total, brouterTotal);
|
adopt(total, brouterTotal);
|
||||||
expect(total).toEqual(brouterTotal);
|
expect(total).toEqual(brouterTotal);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('include route points', () => {
|
||||||
|
const getLngCoord = (i) => track.features[i].geometry.coordinates[0];
|
||||||
|
const getProperty = (i, p) => track.features[i].properties[p];
|
||||||
|
const latLngs = [L.latLng(0, 0), L.latLng(1, 1), L.latLng(2, 2)];
|
||||||
|
const trackFeature = turf.lineString([
|
||||||
|
[0, 0],
|
||||||
|
[1, 1],
|
||||||
|
[2, 2],
|
||||||
|
]);
|
||||||
|
const track = turf.featureCollection([trackFeature]);
|
||||||
|
const exportRoute = new BR.Export();
|
||||||
|
|
||||||
|
exportRoute.update(latLngs, null);
|
||||||
|
exportRoute._addRouteWaypoints(track);
|
||||||
|
|
||||||
|
expect(track.features[0].geometry.type).toEqual('LineString');
|
||||||
|
expect(getLngCoord(1)).toEqual(0);
|
||||||
|
expect(getLngCoord(2)).toEqual(1);
|
||||||
|
expect(getLngCoord(3)).toEqual(2);
|
||||||
|
expect(getProperty(1, 'name')).toEqual('from');
|
||||||
|
expect(getProperty(2, 'name')).toEqual('via1');
|
||||||
|
expect(getProperty(3, 'name')).toEqual('to');
|
||||||
|
expect(getProperty(1, 'type')).toEqual('from');
|
||||||
|
expect(getProperty(2, 'type')).toEqual('via');
|
||||||
|
expect(getProperty(3, 'type')).toEqual('to');
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ require('../../js/format/Gpx.js');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
const geoJson = require('./data/track.json');
|
const geoJson = require('./data/track.json');
|
||||||
|
// lonlats=8.467712,49.488117;8.469354,49.488394;8.470556,49.488946;8.469982,49.489176 + turnInstructionMode = 5
|
||||||
|
// console log in Export._formatTrack
|
||||||
|
const waypointsGeoJson = require('./data/waypoints.json');
|
||||||
const path = 'tests/format/data/';
|
const path = 'tests/format/data/';
|
||||||
|
|
||||||
// resolve intended/accepted differences before comparing
|
// resolve intended/accepted differences before comparing
|
||||||
|
|
@ -26,7 +29,8 @@ function adoptGpx(gpx, replaceCreator = true) {
|
||||||
.split(newline)
|
.split(newline)
|
||||||
.map((line) => line.replace(/lon="([^"]*)" lat="([^"]*)"/, 'lat="$2" lon="$1"'))
|
.map((line) => line.replace(/lon="([^"]*)" lat="([^"]*)"/, 'lat="$2" lon="$1"'))
|
||||||
.join(newline);
|
.join(newline);
|
||||||
gpx = gpx.replace(/(lon|lat)="([-0-9]+.[0-9]+?)0+"/g, '$1="$2"'); // remove trailing zeros
|
gpx = gpx.replace(/(lon|lat)="([-0-9]+\.[0-9]+?)0+"/g, '$1="$2"'); // remove trailing zeros
|
||||||
|
gpx = gpx.replace(/>([-0-9]+\.\d*0+)<\//g, (match, p1) => `>${+p1}</`); // remove trailing zeros
|
||||||
gpx = gpx.replace('</gpx>\n', '</gpx>');
|
gpx = gpx.replace('</gpx>\n', '</gpx>');
|
||||||
|
|
||||||
return gpx;
|
return gpx;
|
||||||
|
|
@ -42,10 +46,15 @@ test('simple track', () => {
|
||||||
expect(gpx).toEqual(brouterGpx);
|
expect(gpx).toEqual(brouterGpx);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('waypoints', () => {
|
||||||
|
const brouterGpx = read('waypoints.gpx');
|
||||||
|
const gpx = BR.Gpx.format(waypointsGeoJson, 5);
|
||||||
|
expect(gpx).toEqual(brouterGpx);
|
||||||
|
});
|
||||||
|
|
||||||
describe('voice hints', () => {
|
describe('voice hints', () => {
|
||||||
test('2-locus', () => {
|
test('2-locus', () => {
|
||||||
let brouterGpx = read('2-locus.gpx');
|
let brouterGpx = read('2-locus.gpx');
|
||||||
brouterGpx = brouterGpx.replace(/.0<\/locus:rteDistance/g, '</locus:rteDistance'); // ignore .0 decimal
|
|
||||||
brouterGpx = brouterGpx.replace(/\n\s*<\/extensions>\n\s*<extensions>/, ''); // ignore (invalid) double tag
|
brouterGpx = brouterGpx.replace(/\n\s*<\/extensions>\n\s*<extensions>/, ''); // ignore (invalid) double tag
|
||||||
// ignore float rounding differences
|
// ignore float rounding differences
|
||||||
brouterGpx = brouterGpx.replace(
|
brouterGpx = brouterGpx.replace(
|
||||||
|
|
|
||||||
42
tests/format/data/waypoints.gpx
Normal file
42
tests/format/data/waypoints.gpx
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- track-length = 388 filtered ascend = 1 plain-ascend = 0 cost=703 energy=.0kwh time=44s -->
|
||||||
|
<gpx
|
||||||
|
xmlns="http://www.topografix.com/GPX/1/1"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
|
||||||
|
creator="BRouter-1.6.1" version="1.1">
|
||||||
|
<wpt lon="8.468340" lat="49.488794"><name>right</name><sym>right</sym><type>Right</type></wpt>
|
||||||
|
<wpt lon="8.469971" lat="49.488151"><name>left</name><sym>left</sym><type>Left</type></wpt>
|
||||||
|
<wpt lon="8.470671" lat="49.488909"><name>left</name><sym>left</sym><type>Left</type></wpt>
|
||||||
|
<wpt lon="8.467712" lat="49.488117">
|
||||||
|
<name>from</name>
|
||||||
|
<type>from</type>
|
||||||
|
</wpt>
|
||||||
|
<wpt lon="8.469354" lat="49.488394">
|
||||||
|
<name>via1</name>
|
||||||
|
<type>via</type>
|
||||||
|
</wpt>
|
||||||
|
<wpt lon="8.470556" lat="49.488946">
|
||||||
|
<name>via2</name>
|
||||||
|
<type>via</type>
|
||||||
|
</wpt>
|
||||||
|
<wpt lon="8.469982" lat="49.489176">
|
||||||
|
<name>to</name>
|
||||||
|
<type>to</type>
|
||||||
|
</wpt>
|
||||||
|
<trk>
|
||||||
|
<name>waypoints + 5-gpsies</name>
|
||||||
|
<trkseg>
|
||||||
|
<trkpt lon="8.467714" lat="49.488115"><ele>101.5</ele></trkpt>
|
||||||
|
<trkpt lon="8.468340" lat="49.488794"><ele>101.5</ele></trkpt>
|
||||||
|
<trkpt lon="8.468586" lat="49.488698"><ele>101.5</ele></trkpt>
|
||||||
|
<trkpt lon="8.468743" lat="49.488636"><ele>101.5</ele></trkpt>
|
||||||
|
<trkpt lon="8.469161" lat="49.488473"><ele>101.75</ele></trkpt>
|
||||||
|
<trkpt lon="8.469355" lat="49.488395"><ele>102.0</ele></trkpt>
|
||||||
|
<trkpt lon="8.469971" lat="49.488151"><ele>103.5</ele></trkpt>
|
||||||
|
<trkpt lon="8.470671" lat="49.488909"><ele>99.5</ele></trkpt>
|
||||||
|
<trkpt lon="8.470561" lat="49.488951"><ele>99.5</ele></trkpt>
|
||||||
|
<trkpt lon="8.469984" lat="49.489178"><ele>100.0</ele></trkpt>
|
||||||
|
</trkseg>
|
||||||
|
</trk>
|
||||||
|
</gpx>
|
||||||
231
tests/format/data/waypoints.json
Normal file
231
tests/format/data/waypoints.json
Normal file
|
|
@ -0,0 +1,231 @@
|
||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"creator": "BRouter-1.1",
|
||||||
|
"name": "Track",
|
||||||
|
"track-length": "388",
|
||||||
|
"filtered ascend": "1",
|
||||||
|
"plain-ascend": "0",
|
||||||
|
"total-time": "44",
|
||||||
|
"total-energy": "4420",
|
||||||
|
"cost": "703",
|
||||||
|
"voicehints": [
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
5,
|
||||||
|
0,
|
||||||
|
88,
|
||||||
|
89
|
||||||
|
],
|
||||||
|
[
|
||||||
|
6,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
99,
|
||||||
|
-90
|
||||||
|
],
|
||||||
|
[
|
||||||
|
7,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
10,
|
||||||
|
-90
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"messages": [
|
||||||
|
[
|
||||||
|
"Longitude",
|
||||||
|
"Latitude",
|
||||||
|
"Elevation",
|
||||||
|
"Distance",
|
||||||
|
"CostPerKm",
|
||||||
|
"ElevCost",
|
||||||
|
"TurnCost",
|
||||||
|
"NodeCost",
|
||||||
|
"InitialCost",
|
||||||
|
"WayTags",
|
||||||
|
"NodeTags"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"8468340",
|
||||||
|
"49488794",
|
||||||
|
"101",
|
||||||
|
"89",
|
||||||
|
"1000",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"highway=residential surface=asphalt cycleway=lane oneway=yes lcn=yes smoothness=good route_bicycle_icn=yes route_bicycle_ncn=yes route_bicycle_rcn=yes",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"8469971",
|
||||||
|
"49488151",
|
||||||
|
"102",
|
||||||
|
"88",
|
||||||
|
"1150",
|
||||||
|
"0",
|
||||||
|
"90",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"highway=residential surface=asphalt oneway=yes smoothness=good",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"8469852",
|
||||||
|
"49489230",
|
||||||
|
"99",
|
||||||
|
"162",
|
||||||
|
"1150",
|
||||||
|
"0",
|
||||||
|
"180",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"highway=residential surface=asphalt oneway=yes smoothness=good",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"8469852",
|
||||||
|
"49489230",
|
||||||
|
"100",
|
||||||
|
"49",
|
||||||
|
"1150",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"0",
|
||||||
|
"highway=residential surface=asphalt oneway=yes smoothness=good",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"times": [
|
||||||
|
0,
|
||||||
|
9.592,
|
||||||
|
12.271,
|
||||||
|
14.13,
|
||||||
|
19.406,
|
||||||
|
22.134,
|
||||||
|
28.832,
|
||||||
|
37.817,
|
||||||
|
38.938,
|
||||||
|
44.217
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "LineString",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
8.467714,
|
||||||
|
49.488115,
|
||||||
|
101.5
|
||||||
|
],
|
||||||
|
[
|
||||||
|
8.46834,
|
||||||
|
49.488794,
|
||||||
|
101.5
|
||||||
|
],
|
||||||
|
[
|
||||||
|
8.468586,
|
||||||
|
49.488698,
|
||||||
|
101.5
|
||||||
|
],
|
||||||
|
[
|
||||||
|
8.468743,
|
||||||
|
49.488636,
|
||||||
|
101.5
|
||||||
|
],
|
||||||
|
[
|
||||||
|
8.469161,
|
||||||
|
49.488473,
|
||||||
|
101.75
|
||||||
|
],
|
||||||
|
[
|
||||||
|
8.469355,
|
||||||
|
49.488395,
|
||||||
|
102
|
||||||
|
],
|
||||||
|
[
|
||||||
|
8.469971,
|
||||||
|
49.488151,
|
||||||
|
103.5
|
||||||
|
],
|
||||||
|
[
|
||||||
|
8.470671,
|
||||||
|
49.488909,
|
||||||
|
99.5
|
||||||
|
],
|
||||||
|
[
|
||||||
|
8.470561,
|
||||||
|
49.488951,
|
||||||
|
99.5
|
||||||
|
],
|
||||||
|
[
|
||||||
|
8.469984,
|
||||||
|
49.489178,
|
||||||
|
100
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"name": "from",
|
||||||
|
"type": "from"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
8.467712,
|
||||||
|
49.488117
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"name": "via1",
|
||||||
|
"type": "via"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
8.469354,
|
||||||
|
49.488394
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"name": "via2",
|
||||||
|
"type": "via"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
8.470556,
|
||||||
|
49.488946
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"name": "to",
|
||||||
|
"type": "to"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
8.469982,
|
||||||
|
49.489176
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue