incyclist-services 1.3.19 → 1.3.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,619 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.destinationPoint = exports.alongTrackDistanceTo = exports.initialBearingTo = exports.isWithinBoundary = exports.getBounds = exports.getVector = exports.getCrossingInfo = exports.getPointCrossingPath = exports.getCrossing = exports.isWithinRange = exports.getNearestPath = exports.distanceToPath = exports.isBetween = exports._getPointOnLine = exports.findAdditional = exports.getFirstBranch = exports.isOneWay = exports.isAllowed = exports.isNode = exports.isWay = exports.pointEquals = exports.boundaryToString = exports.generateQuery = exports.buildQuery = exports.generateID = exports.splitAtPoint = exports.removeDuplicates = exports.splitAtIndex = exports.isRoundabout = exports.getUntilFirstBranch = exports.splitAtPointInfo = exports.parseMapData = exports.updateTypeStats = exports.addWay = exports.addNode = void 0;
4
+ const utils_1 = require("../../utils");
5
+ const geo_1 = require("../../utils/geo");
6
+ const math_1 = require("../../utils/math");
7
+ const consts_1 = require("./consts");
8
+ function addNode(node, nodesLookup, id, path) {
9
+ let point = nodesLookup[node];
10
+ if (point !== undefined)
11
+ path.push(point);
12
+ if (point.ways === undefined)
13
+ point.ways = [];
14
+ let found = point.ways.find(e => (e.toString() === id.toString()));
15
+ if (found === undefined)
16
+ nodesLookup[node].ways.push(id.toString());
17
+ }
18
+ exports.addNode = addNode;
19
+ function addWay(w, ways, waysLookup) {
20
+ if (waysLookup[w.id] !== undefined)
21
+ ways = ways.filter(e => e.id !== w.id);
22
+ ways.push(w);
23
+ waysLookup[w.id.toString()] = w;
24
+ }
25
+ exports.addWay = addWay;
26
+ function updateTypeStats(types, type) {
27
+ let t = (type === undefined ? '-' : type);
28
+ if (types[t] !== undefined)
29
+ types[t]++;
30
+ else
31
+ types[t] = 1;
32
+ }
33
+ exports.updateTypeStats = updateTypeStats;
34
+ function parseMapData(str, filter) {
35
+ if (str === undefined)
36
+ return;
37
+ let data;
38
+ if (typeof (str) === 'string') {
39
+ try {
40
+ data = JSON.parse(str);
41
+ }
42
+ catch (error) {
43
+ return;
44
+ }
45
+ }
46
+ else {
47
+ data = str;
48
+ }
49
+ if (data.elements === undefined)
50
+ return;
51
+ let nodesLookup = {};
52
+ let waysLookup = {};
53
+ let ways = [];
54
+ let types = {};
55
+ let idx = 0;
56
+ let id;
57
+ data.elements.forEach(element => {
58
+ if (element.type === 'node') {
59
+ id = (element.id !== undefined && typeof element.id === 'number') ? id = element.id.toString() : '_INT_' + idx;
60
+ nodesLookup[element.id.toString()] = { id, lat: element.lat, lng: element.lon, tags: element.tags };
61
+ idx++;
62
+ }
63
+ });
64
+ idx = 0;
65
+ data.elements.forEach(element => {
66
+ var _a, _b, _c;
67
+ let path = [];
68
+ if (element.type === 'way') {
69
+ const way = element;
70
+ id = (element.id !== undefined && typeof element.id === 'number') ? id = element.id.toString() : '_INT_' + idx;
71
+ const name = (_a = element.tags) === null || _a === void 0 ? void 0 : _a.name;
72
+ const type = (_b = element.tags) === null || _b === void 0 ? void 0 : _b.highway;
73
+ if (type !== undefined && (filter === undefined || filter.find(e => e === type) === undefined)) {
74
+ (_c = way.nodes) === null || _c === void 0 ? void 0 : _c.forEach(node => {
75
+ addNode(node, nodesLookup, id, path);
76
+ });
77
+ updateTypeStats(types, type);
78
+ addWay({ id: id.toString(), path, type, name, tags: element.tags, bounds: way.bounds }, ways, waysLookup);
79
+ idx++;
80
+ }
81
+ }
82
+ });
83
+ return { ways, nodesLookup, waysLookup, typeStats: types };
84
+ }
85
+ exports.parseMapData = parseMapData;
86
+ function splitAtPointInfo(way, pointInfo) {
87
+ if (!way)
88
+ return;
89
+ let path = way.path;
90
+ let result = [[], []];
91
+ let foundBranch2 = false;
92
+ path.forEach((node, idx) => {
93
+ if (idx <= pointInfo.idx)
94
+ result[0].push(node);
95
+ if (idx === pointInfo.idx) {
96
+ result[1].push(node);
97
+ }
98
+ if (!foundBranch2 && idx > pointInfo.idx && node.ways.length === 1)
99
+ result[1].push(node);
100
+ if (!foundBranch2 && idx > pointInfo.idx && node.ways.length > 1) {
101
+ if (findAdditional(pointInfo.branches, node.ways, way.id, (id1, id2) => (id1 === id2)) !== undefined)
102
+ foundBranch2 = true;
103
+ result[1].push(node);
104
+ }
105
+ });
106
+ return result;
107
+ }
108
+ exports.splitAtPointInfo = splitAtPointInfo;
109
+ function getUntilFirstBranch(w, props) {
110
+ if (!w)
111
+ return;
112
+ const reverse = (props !== undefined) ? props.reverse : false;
113
+ const ignore = (props !== undefined) ? props.ignore : undefined;
114
+ let branch;
115
+ let path = w.path;
116
+ if (reverse) {
117
+ w.path = [...path];
118
+ w.path.reverse();
119
+ path = w.path;
120
+ }
121
+ let piBranch = getFirstBranch(w, ignore);
122
+ if (piBranch !== undefined) {
123
+ branch = { id: w.id, path: [] };
124
+ path.forEach((p, idx) => {
125
+ if (idx <= piBranch.idx)
126
+ branch.path.push(p);
127
+ });
128
+ }
129
+ else {
130
+ branch = { id: w.id, path: w.path };
131
+ }
132
+ return branch;
133
+ }
134
+ exports.getUntilFirstBranch = getUntilFirstBranch;
135
+ function isRoundabout(w, strictCheck = false) {
136
+ if (!w)
137
+ return;
138
+ let roundabout = (w.tags !== undefined && (w.tags.roundabout === true || w.tags.junction === 'roundabout'));
139
+ if (roundabout)
140
+ return true;
141
+ if (strictCheck)
142
+ return false;
143
+ if (w.path === undefined || w.path.length < 2)
144
+ return false;
145
+ roundabout = (w.path[0].id === w.path[w.path.length - 1].id);
146
+ return roundabout;
147
+ }
148
+ exports.isRoundabout = isRoundabout;
149
+ function splitAtIndex(way, idxSplit) {
150
+ let path = way.path;
151
+ let result = [[], []];
152
+ path.forEach((p, idx) => {
153
+ if (idx <= idxSplit)
154
+ result[0].push(p);
155
+ if (idx >= idxSplit)
156
+ result[1].push(p);
157
+ });
158
+ return result;
159
+ }
160
+ exports.splitAtIndex = splitAtIndex;
161
+ function removeDuplicates(options) {
162
+ const endPoints = [];
163
+ const unique = [];
164
+ const uniqueUsed = [];
165
+ options.forEach((o) => { endPoints.push(o.path[o.path.length - 1].id); });
166
+ endPoints.forEach((id) => {
167
+ if (unique.indexOf(id) < 0) {
168
+ unique.push(id);
169
+ uniqueUsed.push(false);
170
+ }
171
+ });
172
+ return options.filter((o) => {
173
+ const id = o.path[o.path.length - 1].id;
174
+ const idx = unique.indexOf(id);
175
+ if (idx >= 0 && !uniqueUsed[idx]) {
176
+ uniqueUsed[idx] = true;
177
+ return true;
178
+ }
179
+ return false;
180
+ });
181
+ }
182
+ exports.removeDuplicates = removeDuplicates;
183
+ function splitAtPoint(way, point) {
184
+ let path = way.path;
185
+ let result = [{ id: way.id, path: [], onewayReverse: false }, { id: way.id, path: [], onewayReverse: false }];
186
+ let found = false;
187
+ let roundabout = isRoundabout(way);
188
+ if (!roundabout) {
189
+ path.forEach((p, idx) => {
190
+ if (!found)
191
+ result[0].path.push(p);
192
+ if (!found)
193
+ found = pointEquals(p, point);
194
+ if (found)
195
+ result[1].path.push(p);
196
+ });
197
+ result[0].path.reverse();
198
+ if (isOneWay(way))
199
+ result[0].onewayReverse = true;
200
+ }
201
+ else {
202
+ let idx = undefined;
203
+ path.forEach((p, i) => {
204
+ if (!found) {
205
+ found = pointEquals(p, point);
206
+ if (found)
207
+ idx = i;
208
+ }
209
+ });
210
+ if (idx !== undefined) {
211
+ let i;
212
+ for (i = 0; i < path.length; i++) {
213
+ let len = path.length;
214
+ let p = path[(idx + i) % len];
215
+ let q = path[(idx - i + len) % len];
216
+ if (result[0].path.length === 0 ||
217
+ (p.id !== result[0].path[result[0].path.length - 1].id && p.id !== result[0].path[0].id))
218
+ result[0].path.push(p);
219
+ if (result[1].path.length === 0 ||
220
+ (q.id !== result[1].path[result[1].path.length - 1].id && q.id !== result[1].path[0].id))
221
+ result[1].path.push(q);
222
+ }
223
+ if (isOneWay(way)) {
224
+ result[1].onewayReverse = true;
225
+ }
226
+ }
227
+ else {
228
+ return ([]);
229
+ }
230
+ }
231
+ return result;
232
+ }
233
+ exports.splitAtPoint = splitAtPoint;
234
+ function generateID(ways) {
235
+ if (ways === undefined || ways.length === 0)
236
+ return;
237
+ if (ways.length < 2)
238
+ return ways[0];
239
+ let w = [...ways];
240
+ let widStr = 'R:' + w.sort().join(',');
241
+ return widStr;
242
+ }
243
+ exports.generateID = generateID;
244
+ ;
245
+ function buildQuery(template, boundary) {
246
+ if (template === undefined)
247
+ return;
248
+ return template.replace('__boundary__', boundaryToString(boundary));
249
+ }
250
+ exports.buildQuery = buildQuery;
251
+ function generateQuery(location, radius) {
252
+ const boundary = getBounds(location.lat, location.lng, radius);
253
+ const template = consts_1.GET_WAYS_IN_AREA;
254
+ return buildQuery(template, boundary);
255
+ }
256
+ exports.generateQuery = generateQuery;
257
+ function boundaryToString(boundary) {
258
+ if (boundary === undefined)
259
+ return 'undefined';
260
+ let ne = boundary.northeast;
261
+ let sw = boundary.southwest;
262
+ if (ne !== undefined && (ne.lat === undefined || ne.lng === undefined))
263
+ return 'error: northeast incorrect';
264
+ if (sw !== undefined && (sw.lat === undefined || sw.lng === undefined))
265
+ return 'error: southwest incorrect';
266
+ if (ne === undefined)
267
+ ne = sw;
268
+ if (sw === undefined)
269
+ sw = ne;
270
+ if (sw === undefined)
271
+ return 'undefined';
272
+ let str = sw.lat + ',' + sw.lng + ',' + ne.lat + ',' + ne.lng;
273
+ return str;
274
+ }
275
+ exports.boundaryToString = boundaryToString;
276
+ function pointEquals(p1, p2) {
277
+ if (p1 === undefined || p2 === undefined)
278
+ return false;
279
+ return (p1.id === p2.id || (p1.lat !== undefined && p1.lng !== undefined && p1.lat === p2.lat && p1.lng === p2.lng));
280
+ }
281
+ exports.pointEquals = pointEquals;
282
+ function isWay(p) {
283
+ if (p === undefined || p === null || p.id === undefined || p.path === undefined || p.tags === undefined)
284
+ return false;
285
+ return true;
286
+ }
287
+ exports.isWay = isWay;
288
+ function isNode(p) {
289
+ if (p === undefined || p === null || p.id === undefined || p.lat === undefined || p.lng === undefined || p.ways === undefined)
290
+ return false;
291
+ return true;
292
+ }
293
+ exports.isNode = isNode;
294
+ function isAllowed(way, from, to) {
295
+ if (isNode(from) && isWay(way)) {
296
+ const fromIdx = way.path.findIndex(p => p.id === from.id);
297
+ if (fromIdx !== -1 && !isOneWay(way))
298
+ return true;
299
+ let p0 = way.path[0];
300
+ let pN = way.path[way.path.length - 1];
301
+ if (from.id === p0.id)
302
+ return true;
303
+ if (from.id !== p0.id && from.id === pN.id)
304
+ return !isOneWay(way);
305
+ if (isNode(to) && to.id === pN.id)
306
+ return true;
307
+ if (isNode(from) && isNode(to)) {
308
+ const toId = way.path.findIndex(p => p.id === to.id);
309
+ if (fromIdx === -1 || toId === -1)
310
+ return;
311
+ return !isOneWay(way) || fromIdx < toId;
312
+ }
313
+ }
314
+ return undefined;
315
+ }
316
+ exports.isAllowed = isAllowed;
317
+ function isOneWay(way) {
318
+ if (!way || !way.tags || !way.tags.oneway)
319
+ return false;
320
+ let ow = way.tags.oneway;
321
+ return (ow.toString() === 'true' || ow === 'yes');
322
+ }
323
+ exports.isOneWay = isOneWay;
324
+ function getFirstBranch(way, ignore) {
325
+ if (way === undefined || way.path === undefined)
326
+ return;
327
+ let pFound = undefined;
328
+ way.path.forEach((node, idx) => {
329
+ if (idx === 0)
330
+ return;
331
+ let ways = [];
332
+ node.ways.forEach((w) => {
333
+ if (ignore === undefined || w !== ignore)
334
+ ways.push(w);
335
+ });
336
+ if (!pFound && node.ways !== undefined && ways.length > 1) {
337
+ let branches = [];
338
+ ways.forEach(pw => {
339
+ if (pw !== way.id)
340
+ branches.push(pw);
341
+ });
342
+ pFound = { point: node, idx, branches };
343
+ }
344
+ });
345
+ return pFound;
346
+ }
347
+ exports.getFirstBranch = getFirstBranch;
348
+ function findAdditional(a1, a2, id3, fn) {
349
+ let res = [];
350
+ a1.forEach(e1 => {
351
+ a2.forEach(e2 => {
352
+ if (!fn(e1, e2) && !fn(e1, id3) && !fn(e2, id3))
353
+ res.push(e2);
354
+ });
355
+ });
356
+ if (res.length === 0)
357
+ return undefined;
358
+ return res;
359
+ }
360
+ exports.findAdditional = findAdditional;
361
+ function _getPointOnLine(point, p1, p2) {
362
+ let bL = initialBearingTo(p1, p2);
363
+ let bP = bL + 90;
364
+ let p3 = destinationPoint(point, 100, bP);
365
+ return getCrossing(p1, p2, point, p3, false);
366
+ }
367
+ exports._getPointOnLine = _getPointOnLine;
368
+ function isBetween(point, p1, p2) {
369
+ if (point === undefined || p1 === undefined || p2 === undefined ||
370
+ point.lat === undefined || point.lng === undefined ||
371
+ p1.lat === undefined || p1.lng === undefined ||
372
+ p2.lat === undefined || p2.lng === undefined)
373
+ return undefined;
374
+ let d = utils_1.geo.distanceBetween(p1, point);
375
+ let bDest = initialBearingTo(p1, p2);
376
+ let bPoint = initialBearingTo(p1, point);
377
+ let angle = bPoint - bDest;
378
+ if ((0, math_1.abs)(angle) > 30)
379
+ return { between: false, offset: d };
380
+ let dP2 = utils_1.geo.distanceBetween(p1, p2);
381
+ let offset = (0, math_1.abs)(d * (0, math_1.sin)(angle));
382
+ if (offset < consts_1.MAX_DISTANCE_FROM_PATH && dP2 > d) {
383
+ return { between: true, offset };
384
+ }
385
+ return { between: false, offset: (dP2 - d) };
386
+ }
387
+ exports.isBetween = isBetween;
388
+ function distanceToPath(point, way) {
389
+ if (point === undefined || point.lat === undefined || point.lng === undefined
390
+ || way === undefined || way.path === undefined || way.path.length === 0)
391
+ return undefined;
392
+ let minDistance;
393
+ let minIdx = -1;
394
+ let prev;
395
+ let foundExact = false;
396
+ way.path.forEach((element, idx) => {
397
+ if (element.lat === point.lat && element.lng === point.lng) {
398
+ minDistance = 0;
399
+ foundExact = true;
400
+ return;
401
+ }
402
+ if (foundExact)
403
+ return;
404
+ if (prev !== undefined) {
405
+ let res = isBetween(point, prev, element);
406
+ if (res && res.between) {
407
+ minDistance = res.offset;
408
+ foundExact = true;
409
+ return;
410
+ }
411
+ }
412
+ let distance = utils_1.geo.distanceBetween(element, point);
413
+ if (minDistance === undefined || distance < minDistance) {
414
+ minDistance = distance;
415
+ minIdx = idx;
416
+ }
417
+ prev = element;
418
+ });
419
+ if (foundExact)
420
+ return minDistance;
421
+ if (minIdx > 0) {
422
+ const alpha = initialBearingTo(way.path[minIdx - 1], way.path[minIdx]);
423
+ const alpha2 = initialBearingTo(way.path[minIdx - 1], point);
424
+ let beta = alpha2 - alpha;
425
+ if (beta > 270)
426
+ beta -= 360;
427
+ if ((beta > -90 && beta < 90)) {
428
+ const dist = (0, math_1.sin)((0, math_1.abs)(beta)) * utils_1.geo.distanceBetween(way.path[minIdx - 1], point);
429
+ const distPath = (0, math_1.cos)((0, math_1.abs)(beta)) * utils_1.geo.distanceBetween(way.path[minIdx - 1], point);
430
+ if (dist < minDistance && distPath > 0 && distPath < utils_1.geo.distanceBetween(way.path[minIdx - 1], way.path[minIdx]))
431
+ minDistance = dist;
432
+ }
433
+ }
434
+ if (minIdx < way.path.length - 2) {
435
+ const alpha = initialBearingTo(way.path[minIdx], way.path[minIdx + 1]);
436
+ let beta = initialBearingTo(way.path[minIdx], point) - alpha;
437
+ if (beta > 270)
438
+ beta -= 360;
439
+ if ((beta > -90 && beta < 90)) {
440
+ const dist = (0, math_1.sin)((0, math_1.abs)(beta)) * utils_1.geo.distanceBetween(way.path[minIdx], point);
441
+ const distPath = (0, math_1.cos)((0, math_1.abs)(beta)) * utils_1.geo.distanceBetween(way.path[minIdx], point);
442
+ if (dist < minDistance && distPath > 0 && distPath < utils_1.geo.distanceBetween(way.path[minIdx], way.path[minIdx + 1]))
443
+ minDistance = dist;
444
+ }
445
+ }
446
+ return minDistance;
447
+ }
448
+ exports.distanceToPath = distanceToPath;
449
+ function getNearestPath(point, ways) {
450
+ if (ways === undefined || point === undefined)
451
+ return;
452
+ let w;
453
+ let min = { path: undefined, distance: undefined, way: undefined };
454
+ for (w of ways) {
455
+ let distance = distanceToPath(point, w);
456
+ if (distance !== undefined && (min.distance === undefined || distance < min.distance)) {
457
+ min.distance = distance;
458
+ min.path = w.path;
459
+ min.way = w;
460
+ }
461
+ }
462
+ return min;
463
+ }
464
+ exports.getNearestPath = getNearestPath;
465
+ function isWithinRange(distance) {
466
+ return (0, math_1.abs)(distance) < consts_1.MAX_DISTANCE_FROM_PATH;
467
+ }
468
+ exports.isWithinRange = isWithinRange;
469
+ function getCrossing(A, B, C, D, exact = true) {
470
+ let AB = getVector(A, B);
471
+ let CD = getVector(C, D);
472
+ let AC = getVector(A, C);
473
+ const ciA = Object.assign(Object.assign({}, A), { distance: 0 });
474
+ const ciB = Object.assign(Object.assign({}, B), { distance: utils_1.geo.distanceBetween(A, B) });
475
+ if (isWithinRange(utils_1.geo.distanceBetween(A, C)))
476
+ return ciA;
477
+ if (isWithinRange(utils_1.geo.distanceBetween(A, D)))
478
+ return ciA;
479
+ if (isWithinRange(utils_1.geo.distanceBetween(B, C)))
480
+ return ciB;
481
+ if (isWithinRange(utils_1.geo.distanceBetween(B, D)))
482
+ return ciB;
483
+ const V = (0, geo_1.crossing)(AB, CD, AC);
484
+ if (V === undefined)
485
+ return undefined;
486
+ const p1Len = AB.len();
487
+ const distance = V.len();
488
+ if (AB.isSameDirection(V) && (distance < p1Len || isWithinRange(p1Len - distance))) {
489
+ let X = utils_1.geo.getPointBetween(A, B, distance);
490
+ let CX = getVector(C, X);
491
+ if (!exact || (CX.len() < CD.len() || isWithinRange(CD.len() - CX.len()))) {
492
+ return Object.assign(Object.assign({}, X), { distance });
493
+ }
494
+ }
495
+ return undefined;
496
+ }
497
+ exports.getCrossing = getCrossing;
498
+ function getPointCrossingPath(point, path, closest = false) {
499
+ let pPrev = undefined;
500
+ let X = undefined;
501
+ let pClosest = undefined;
502
+ if (path === undefined)
503
+ return undefined;
504
+ path.forEach((p, i) => {
505
+ let pDist = (0, math_1.abs)(utils_1.geo.distanceBetween(p, point));
506
+ if (pClosest === undefined || pClosest.distance > pDist) {
507
+ pClosest = { distance: pDist, point: p, idx: i };
508
+ }
509
+ if (pPrev !== undefined) {
510
+ let pX = _getPointOnLine(point, pPrev, p);
511
+ if (pX !== undefined) {
512
+ let dist = (0, math_1.abs)(utils_1.geo.distanceBetween(pX, point));
513
+ if (X === undefined || (X.distance > dist)) {
514
+ X = { point: pX, distance: dist, idx: i };
515
+ }
516
+ }
517
+ }
518
+ pPrev = p;
519
+ });
520
+ if (X !== undefined) {
521
+ return X;
522
+ }
523
+ else {
524
+ if (closest)
525
+ return pClosest;
526
+ }
527
+ }
528
+ exports.getPointCrossingPath = getPointCrossingPath;
529
+ function getCrossingInfo(way1, way2) {
530
+ if (way1 === undefined || way1.path === undefined || way2 === undefined || way2.path === undefined)
531
+ return;
532
+ let crossing = undefined;
533
+ way1.path.forEach((p1, i) => {
534
+ way2.path.forEach((p2, j) => {
535
+ if (crossing === undefined && p1.id === p2.id) {
536
+ crossing = { point: p1, idx1: i, idx2: j };
537
+ }
538
+ });
539
+ });
540
+ return crossing;
541
+ }
542
+ exports.getCrossingInfo = getCrossingInfo;
543
+ function getVector(p1, p2) {
544
+ if (p1 === undefined)
545
+ throw new Error("missing mandatory argument: p1");
546
+ if (p2 === undefined)
547
+ throw new Error("missing mandatory argument: p2");
548
+ let distance = utils_1.geo.distanceBetween(p1, p2);
549
+ if (distance === 0) {
550
+ return new utils_1.Vector([0, 0]);
551
+ }
552
+ let bearing = initialBearingTo(p1, p2);
553
+ return new utils_1.Vector({ path: { bearing, distance } });
554
+ }
555
+ exports.getVector = getVector;
556
+ function getBounds(lat, lng, offset) {
557
+ const pi = Math.PI;
558
+ const m = (1 / ((2 * pi / 360) * consts_1.RADIUS_EARTH)) / 1000;
559
+ let boundary = {
560
+ northeast: { lat: undefined, lng: undefined },
561
+ southwest: { lat: undefined, lng: undefined }
562
+ };
563
+ boundary.northeast.lat = lat + offset * m;
564
+ boundary.northeast.lng = lng + (offset * m) / Math.cos(lat * pi / 180);
565
+ boundary.southwest.lat = lat - offset * m;
566
+ boundary.southwest.lng = lng - (offset * m) / Math.cos(lat * pi / 180);
567
+ return boundary;
568
+ }
569
+ exports.getBounds = getBounds;
570
+ function isWithinBoundary(location, boundary) {
571
+ if (location === undefined || location.lat === undefined || location.lng === undefined)
572
+ return false;
573
+ const lat = location.lat;
574
+ const lng = location.lng;
575
+ const sw = boundary.southwest;
576
+ const ne = boundary.northeast;
577
+ return (lat >= sw.lat && lat <= ne.lat && lng >= sw.lng && lng <= ne.lng);
578
+ }
579
+ exports.isWithinBoundary = isWithinBoundary;
580
+ function initialBearingTo(p1, p2) {
581
+ if (p1 === undefined || p2 === undefined || (p1.lat === p2.lat && p1.lng === p2.lng))
582
+ return;
583
+ const φ1 = (0, math_1.rad)(p1.lat);
584
+ const φ2 = (0, math_1.rad)(p2.lat);
585
+ const Δλ = (0, math_1.rad)(p2.lng - p1.lng);
586
+ const x = Math.cos(φ1) * Math.sin(φ2) - Math.sin(φ1) * Math.cos(φ2) * Math.cos(Δλ);
587
+ const y = Math.sin(Δλ) * Math.cos(φ2);
588
+ const θ = Math.atan2(y, x);
589
+ const bearing = (0, math_1.degrees)(θ);
590
+ return bearing;
591
+ }
592
+ exports.initialBearingTo = initialBearingTo;
593
+ function alongTrackDistanceTo(point, pathStart, pathEnd, radius = consts_1.RADIUS_EARTH * 1000) {
594
+ if (point === undefined || pathStart === undefined || pathEnd === undefined)
595
+ return;
596
+ const R = radius;
597
+ const δ13 = utils_1.geo.calculateDistance(pathStart.lat, pathStart.lng, point.lat, point.lng, R) / R;
598
+ const θ13 = (0, math_1.rad)(initialBearingTo(pathStart, point));
599
+ const θ12 = (0, math_1.rad)(initialBearingTo(pathStart, pathEnd));
600
+ const δxt = Math.asin(Math.sin(δ13) * Math.sin(θ13 - θ12));
601
+ const δat = Math.acos(Math.cos(δ13) / Math.abs(Math.cos(δxt)));
602
+ let d = δat * Math.sign(Math.cos(θ12 - θ13)) * R;
603
+ return d;
604
+ }
605
+ exports.alongTrackDistanceTo = alongTrackDistanceTo;
606
+ function destinationPoint(start, distance, bearing, radius = consts_1.RADIUS_EARTH * 1000) {
607
+ const δ = distance / radius;
608
+ const θ = (0, math_1.rad)(bearing);
609
+ const φ1 = (0, math_1.rad)(start.lat), λ1 = (0, math_1.rad)(start.lng);
610
+ const sinφ2 = Math.sin(φ1) * Math.cos(δ) + Math.cos(φ1) * Math.sin(δ) * Math.cos(θ);
611
+ const φ2 = Math.asin(sinφ2);
612
+ const y = Math.sin(θ) * Math.sin(δ) * Math.cos(φ1);
613
+ const x = Math.cos(δ) - Math.sin(φ1) * sinφ2;
614
+ const λ2 = λ1 + Math.atan2(y, x);
615
+ const lat = (0, math_1.degrees)(φ2);
616
+ const lng = (0, math_1.degrees)(λ2);
617
+ return { lat, lng };
618
+ }
619
+ exports.destinationPoint = destinationPoint;
@@ -1,7 +1,10 @@
1
+ import { JSONObject } from '../../../utils';
2
+ import { RouteApiDetail } from '../api/types';
1
3
  import { XMLParser, XmlParserContext } from './xml';
2
4
  export declare class IncyclistXMLParser extends XMLParser {
3
5
  static SCHEME: string;
4
6
  protected loadDescription(context: XmlParserContext): Promise<void>;
5
7
  protected loadPoints(context: XmlParserContext): Promise<void>;
8
+ protected processCuts(data: JSONObject, route: RouteApiDetail): void;
6
9
  protected parseVideo(context: XmlParserContext): Promise<void>;
7
10
  }