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,6 @@
1
+ export declare const RADIUS_EARTH = 6378.1;
2
+ export declare const DEFAULT_RADIUS = 1000;
3
+ export declare const DEFAULT_MIN_WAYS = 70;
4
+ export declare const DEFAULT_MAX_WAYS = 300;
5
+ export declare const MAX_DISTANCE_FROM_PATH = 5;
6
+ export declare const GET_WAYS_IN_AREA = "[out:json];way[highway](__boundary__);(._;>;);out geom;";
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET_WAYS_IN_AREA = exports.MAX_DISTANCE_FROM_PATH = exports.DEFAULT_MAX_WAYS = exports.DEFAULT_MIN_WAYS = exports.DEFAULT_RADIUS = exports.RADIUS_EARTH = void 0;
4
+ exports.RADIUS_EARTH = 6378.1;
5
+ exports.DEFAULT_RADIUS = 1000;
6
+ exports.DEFAULT_MIN_WAYS = 70;
7
+ exports.DEFAULT_MAX_WAYS = 300;
8
+ exports.MAX_DISTANCE_FROM_PATH = 5;
9
+ exports.GET_WAYS_IN_AREA = '[out:json];way[highway](__boundary__);(._;>;);out geom;';
@@ -0,0 +1,51 @@
1
+ import { EventLogger } from "gd-eventlog";
2
+ import { OverpassApi } from "../../api";
3
+ import { LatLng } from "../../utils/geo";
4
+ import { Boundary, FreeRideDataSet, IncyclistWaySplit, IncyclistWay, IncyclistNode } from "./types";
5
+ export declare class MapAreaService {
6
+ protected static consts: {
7
+ DEFAULT_RADIUS: number;
8
+ DEFAULT_MIN_WAYS: number;
9
+ DEFAULT_MAX_WAYS: number;
10
+ MAX_DISTANCE_FROM_PATH: number;
11
+ GET_WAYS_IN_AREA: string;
12
+ };
13
+ protected static _instances: {};
14
+ static getInstance(id?: string): any;
15
+ protected overpass: OverpassApi;
16
+ protected logger: EventLogger;
17
+ protected minWays: number;
18
+ protected maxWays: number;
19
+ protected radius: number;
20
+ protected data: FreeRideDataSet;
21
+ protected boundary: Boundary;
22
+ protected location: IncyclistNode;
23
+ protected query: string;
24
+ protected queryLocation: IncyclistNode;
25
+ protected openmapData: JSON | string;
26
+ protected loaded: 'success' | 'failure' | 'unknown';
27
+ protected filter: any;
28
+ constructor(props?: any);
29
+ setLocation(location: any, reload: any, onLoaded: any): void;
30
+ splitAtFirstBranch(way: IncyclistWay): IncyclistWaySplit;
31
+ getNextOptions(way?: IncyclistWay, way1?: IncyclistWay, reload?: boolean, props?: {
32
+ mapReload: boolean;
33
+ }): Promise<unknown>;
34
+ isWithinBoundary(location: LatLng): boolean;
35
+ protected init(props: any): void;
36
+ protected load(callback: any): Promise<void>;
37
+ protected setData(openmapData: any, callback: any): void;
38
+ protected _getNextOptions(loc: any, way: any, way1: any): any[];
39
+ protected collectRoundabout(way: any): any[];
40
+ protected replaceWayID(way: IncyclistWay, newId: string, replaceLookup?: boolean): IncyclistWay;
41
+ protected checkRoundabouts(): void;
42
+ protected getWay(props: string | IncyclistWay): IncyclistWay;
43
+ protected getNode(props?: string | IncyclistNode): IncyclistNode;
44
+ protected copyWay(wayFrom: IncyclistWay, id?: string): {
45
+ w: IncyclistWay;
46
+ roundabout: boolean;
47
+ };
48
+ protected checkOptionsOnCurrentWay(location: IncyclistNode, way: IncyclistWay, options: any): void;
49
+ protected checkOptionsOnDifferentWay(location: any, w: any, options: any): any;
50
+ }
51
+ export declare const useMapArea: (id: any) => any;
@@ -0,0 +1,561 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.useMapArea = exports.MapAreaService = void 0;
16
+ const gd_eventlog_1 = require("gd-eventlog");
17
+ const api_1 = require("../../api");
18
+ const clone_1 = __importDefault(require("../../utils/clone"));
19
+ const utils_1 = require("./utils");
20
+ const consts_1 = require("./consts");
21
+ class MapAreaService {
22
+ static getInstance(id = 'default') {
23
+ if (!MapAreaService._instances[id])
24
+ MapAreaService._instances[id] = new MapAreaService();
25
+ return MapAreaService._instances[id];
26
+ }
27
+ constructor(props) {
28
+ this.loaded = 'unknown';
29
+ this.overpass = new api_1.OverpassApi();
30
+ this.logger = new gd_eventlog_1.EventLogger('MapArea');
31
+ this.init(props);
32
+ }
33
+ setLocation(location, reload, onLoaded) {
34
+ this.location = location;
35
+ if (location === undefined) {
36
+ if (onLoaded)
37
+ onLoaded('failure', this.data.ways, this.openmapData);
38
+ return;
39
+ }
40
+ if (reload) {
41
+ this.boundary = (0, utils_1.getBounds)(this.location.lat, this.location.lng, this.radius);
42
+ this.load(onLoaded);
43
+ }
44
+ else {
45
+ if (onLoaded)
46
+ onLoaded('success', this.data.ways, this.openmapData);
47
+ }
48
+ }
49
+ splitAtFirstBranch(way) {
50
+ if (way === undefined || way.path === undefined)
51
+ return;
52
+ let result = {
53
+ way: { id: way.id, path: [] },
54
+ branches: []
55
+ };
56
+ try {
57
+ let pointInfo = (0, utils_1.getFirstBranch)(way);
58
+ if (pointInfo !== undefined) {
59
+ let paths = (0, utils_1.splitAtPointInfo)(way, pointInfo);
60
+ result.way.path = paths[0];
61
+ let branch = { id: way.id, path: paths[1] };
62
+ if (branch.path.length > 1)
63
+ result.branches.push(branch);
64
+ pointInfo.point.ways.forEach((wid) => {
65
+ let w = (0, clone_1.default)(this.data.waysLookup[wid]);
66
+ if (w !== undefined && w.id !== way.id) {
67
+ if (w.path[0].id === pointInfo.point.id) {
68
+ branch = (0, utils_1.getUntilFirstBranch)(w, { ignore: way.id });
69
+ if (branch.path.length > 1)
70
+ result.branches.push(branch);
71
+ }
72
+ else if (w.path[w.path.length - 1].id === pointInfo.point.id) {
73
+ w.path.reverse();
74
+ branch = (0, utils_1.getUntilFirstBranch)(w, { ignore: way.id });
75
+ if (branch.path.length > 1)
76
+ result.branches.push(branch);
77
+ }
78
+ else {
79
+ let branches = (0, utils_1.splitAtPoint)(w, pointInfo.point);
80
+ branch = (0, utils_1.getUntilFirstBranch)(branches[0], { ignore: way.id });
81
+ if (branch.path.length > 1)
82
+ result.branches.push(branch);
83
+ branch = (0, utils_1.getUntilFirstBranch)(branches[1], { ignore: way.id });
84
+ if (branch.path.length > 1)
85
+ result.branches.push(branch);
86
+ }
87
+ }
88
+ });
89
+ }
90
+ else {
91
+ result.way.path = [...way.path];
92
+ }
93
+ }
94
+ catch (error) {
95
+ this.logger.logEvent({ message: 'error', fn: 'splitAtFirstBranch()', way, error: error.message, stack: error.stack });
96
+ result = undefined;
97
+ }
98
+ return result;
99
+ }
100
+ getNextOptions(way, way1 = undefined, reload = false, props) {
101
+ return new Promise((resolve, reject) => {
102
+ if (way === undefined || way.id === undefined || way.path === undefined || way.path.length < 1)
103
+ return reject({ retry: false, message: 'invalid arguments' });
104
+ let location = way.path[way.path.length - 1];
105
+ if (location.id === undefined) {
106
+ if (way.path.length > 1)
107
+ location = way.path[way.path.length - 2];
108
+ else {
109
+ return resolve([]);
110
+ }
111
+ }
112
+ let currentWay = { w: way, roundabout: false };
113
+ if (way.path[0].id === undefined) {
114
+ currentWay = this.copyWay(way);
115
+ }
116
+ if (props && props.mapReload === false) {
117
+ resolve(this._getNextOptions(location, currentWay, way1));
118
+ }
119
+ else {
120
+ this.setLocation(location, reload, (status, ways, data) => {
121
+ if (status !== 'success') {
122
+ reject({ retry: true, code: 1, message: 'could not load data' });
123
+ }
124
+ resolve(this._getNextOptions(location, currentWay, way1));
125
+ });
126
+ }
127
+ });
128
+ }
129
+ isWithinBoundary(location) {
130
+ return (0, utils_1.isWithinBoundary)(location, this.boundary);
131
+ }
132
+ init(props) {
133
+ this.minWays = consts_1.DEFAULT_MIN_WAYS;
134
+ this.maxWays = consts_1.DEFAULT_MAX_WAYS;
135
+ this.radius = consts_1.DEFAULT_RADIUS;
136
+ this.data = undefined;
137
+ if (props === undefined)
138
+ return;
139
+ if (props.onLoaded)
140
+ this.onLoaded = props.onLoaded;
141
+ if (props.minWays)
142
+ this.minWays = props.minWays;
143
+ if (props.maxWays)
144
+ this.maxWays = props.maxWays;
145
+ if (props.radius)
146
+ this.radius = props.radius;
147
+ if (props.filter)
148
+ this.filter = props.filter;
149
+ if (props.location) {
150
+ this.setLocation(props.location, true, this.onLoaded);
151
+ }
152
+ }
153
+ load(callback) {
154
+ return __awaiter(this, void 0, void 0, function* () {
155
+ var _a;
156
+ const onLoaded = callback ? callback : this.onLoaded;
157
+ let ts, ts1;
158
+ try {
159
+ this.query = (0, utils_1.buildQuery)(consts_1.GET_WAYS_IN_AREA, this.boundary);
160
+ this.queryLocation = this.location;
161
+ const { id, lat, lng } = this.location;
162
+ this.logger.logEvent({ message: 'overpass query', query: this.query, location: { id, lat, lng }, radius: this.radius });
163
+ ts = Date.now();
164
+ let openmapData = yield this.overpass.query(this.query);
165
+ ts1 = Date.now();
166
+ this.logger.logEvent({ message: 'overpass query result', status: 'success', duration: (ts1 - ts) });
167
+ this.setData(openmapData, onLoaded);
168
+ }
169
+ catch (error) {
170
+ ts1 = Date.now();
171
+ this.logger.logEvent({ message: 'overpass query result', status: 'failure', error: { code: error.code, response: error.response }, duration: (ts1 - ts) });
172
+ if (onLoaded !== undefined)
173
+ onLoaded('failure', (_a = this.data) === null || _a === void 0 ? void 0 : _a.ways, this.openmapData);
174
+ }
175
+ });
176
+ }
177
+ setData(openmapData, callback) {
178
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
179
+ const onLoaded = callback ? callback : this.onLoaded;
180
+ let ts = Date.now();
181
+ this.data = (0, utils_1.parseMapData)(openmapData, this.filter);
182
+ let ts1 = Date.now();
183
+ this.logger.logEvent({ message: 'Parse', duration: (ts1 - ts),
184
+ ways: (_b = (_a = this.data) === null || _a === void 0 ? void 0 : _a.ways.length) !== null && _b !== void 0 ? _b : 0,
185
+ nodes: Object.keys((_d = (_c = this.data) === null || _c === void 0 ? void 0 : _c.nodesLookup) !== null && _d !== void 0 ? _d : {}).length,
186
+ typeStats: (_e = this.data) === null || _e === void 0 ? void 0 : _e.typeStats
187
+ });
188
+ if (this.data !== undefined) {
189
+ this.openmapData = openmapData;
190
+ this.checkRoundabouts();
191
+ this.loaded = 'success';
192
+ if (((_f = this.data) === null || _f === void 0 ? void 0 : _f.ways.length) < this.minWays) {
193
+ if (((_g = this.data) === null || _g === void 0 ? void 0 : _g.ways.length) > 0) {
194
+ let gap = this.minWays / ((_h = this.data) === null || _h === void 0 ? void 0 : _h.ways.length);
195
+ this.radius = this.radius * Math.sqrt(gap);
196
+ }
197
+ else {
198
+ this.radius = this.radius * 2;
199
+ }
200
+ }
201
+ else if (((_j = this.data) === null || _j === void 0 ? void 0 : _j.ways.length) > this.maxWays) {
202
+ let gap = ((_k = this.data) === null || _k === void 0 ? void 0 : _k.ways.length) / this.maxWays;
203
+ this.radius = this.radius / Math.sqrt(gap);
204
+ }
205
+ }
206
+ else {
207
+ this.loaded = 'failure';
208
+ }
209
+ if (onLoaded !== undefined) {
210
+ onLoaded(this.loaded, (_l = this.data) === null || _l === void 0 ? void 0 : _l.ways, this.openmapData);
211
+ }
212
+ }
213
+ _getNextOptions(loc, way, way1) {
214
+ let location = this.getNode(loc);
215
+ let options = [];
216
+ if (location !== undefined) {
217
+ location.ways.forEach((wid, idx) => {
218
+ if (wid === way.id) {
219
+ this.checkOptionsOnCurrentWay(location, way, options);
220
+ }
221
+ else if (way1 !== undefined && wid === way1.id) {
222
+ }
223
+ else {
224
+ let w = this.getWay(wid);
225
+ options = this.checkOptionsOnDifferentWay(location, w, options);
226
+ }
227
+ });
228
+ }
229
+ return options;
230
+ }
231
+ collectRoundabout(way) {
232
+ if (!(0, utils_1.isRoundabout)(way, true))
233
+ return undefined;
234
+ const contains = (ways, wid) => {
235
+ let found = ways.find(id => id === wid);
236
+ return found !== undefined;
237
+ };
238
+ const addNodes = (ways, way) => {
239
+ way.path.forEach((n, idx) => {
240
+ if (idx > 0) {
241
+ n.ways.forEach(wid => {
242
+ var _a;
243
+ let w = (_a = this.data) === null || _a === void 0 ? void 0 : _a.waysLookup[wid];
244
+ if ((0, utils_1.isRoundabout)(w, true) && wid !== way.id && !contains(ways, wid)) {
245
+ ways.push(wid);
246
+ addNodes(ways, w);
247
+ }
248
+ });
249
+ }
250
+ });
251
+ };
252
+ let ways = [way.id];
253
+ addNodes(ways, way);
254
+ return ways;
255
+ }
256
+ ;
257
+ replaceWayID(way, newId, replaceLookup = true) {
258
+ var _a;
259
+ if (way === undefined || newId === undefined || way.id === undefined || way.path === undefined || !this.data)
260
+ return;
261
+ let oldId = way.id;
262
+ let w = (_a = this.data) === null || _a === void 0 ? void 0 : _a.waysLookup[oldId];
263
+ w.originalId = w.id;
264
+ w.id = newId;
265
+ w.path.forEach((nx, j) => {
266
+ var _a;
267
+ w.path[j] = (_a = this.data) === null || _a === void 0 ? void 0 : _a.nodesLookup[nx.id];
268
+ let n = w.path[j];
269
+ n.ways.forEach((wid, i) => { if (wid === oldId)
270
+ n.ways[i] = newId; });
271
+ n.ways = [...new Set(n.ways)];
272
+ });
273
+ if (replaceLookup)
274
+ this.data.waysLookup[newId] = w;
275
+ delete this.data.waysLookup[oldId];
276
+ return w;
277
+ }
278
+ ;
279
+ checkRoundabouts() {
280
+ var _a;
281
+ let roundaboutsStrict = [];
282
+ let roundaboutsImplicit = [];
283
+ try {
284
+ (_a = this.data) === null || _a === void 0 ? void 0 : _a.ways.forEach(way => {
285
+ if ((0, utils_1.isRoundabout)(way, true)) {
286
+ let ways = this.collectRoundabout(way);
287
+ let id = (0, utils_1.generateID)(ways);
288
+ let found = roundaboutsStrict.find(e => e.id === id);
289
+ if (!found) {
290
+ found = (way.path[0].id === way.path[way.path.length - 1].id);
291
+ if (found) {
292
+ roundaboutsImplicit.push(way);
293
+ }
294
+ }
295
+ if (!found)
296
+ roundaboutsStrict.push({ id, ways });
297
+ }
298
+ else if ((0, utils_1.isRoundabout)(way, false)) {
299
+ roundaboutsImplicit.push(way);
300
+ }
301
+ });
302
+ this.logger.debug('_checkRoundabouts: found roundabouts:', roundaboutsStrict);
303
+ roundaboutsStrict.forEach(ri => {
304
+ var _a;
305
+ let originalNodes = [];
306
+ ri.ways.forEach((wid, i) => {
307
+ var _a;
308
+ let way = (_a = this.data) === null || _a === void 0 ? void 0 : _a.waysLookup[wid];
309
+ let path = way.path;
310
+ path.forEach(n => {
311
+ if (originalNodes.length === 0 ||
312
+ originalNodes[originalNodes.length - 1] !== n.id)
313
+ originalNodes.push(n.id);
314
+ });
315
+ });
316
+ ri.ways.forEach((wid, i) => {
317
+ var _a;
318
+ let way = (_a = this.data) === null || _a === void 0 ? void 0 : _a.waysLookup[wid];
319
+ this.replaceWayID(way, ri.id, i === 0);
320
+ });
321
+ let roundabout = (_a = this.data) === null || _a === void 0 ? void 0 : _a.waysLookup[ri.id];
322
+ roundabout.path = [];
323
+ originalNodes.forEach(nid => {
324
+ var _a;
325
+ let node = (_a = this.data) === null || _a === void 0 ? void 0 : _a.nodesLookup[nid];
326
+ roundabout.path.push(node);
327
+ });
328
+ roundabout.tags.roundabout = 'yes';
329
+ });
330
+ roundaboutsImplicit.forEach(roundabout => {
331
+ if (roundabout.tags === undefined)
332
+ roundabout.tags = {};
333
+ roundabout.tags.roundabout = 'yes';
334
+ });
335
+ }
336
+ catch (error) {
337
+ this.logger.logEvent({ message: 'Error', error });
338
+ }
339
+ }
340
+ getWay(props) {
341
+ var _a, _b;
342
+ if (!props)
343
+ return;
344
+ if (typeof props === 'string') {
345
+ return (0, clone_1.default)((_a = this.data) === null || _a === void 0 ? void 0 : _a.waysLookup[props]);
346
+ }
347
+ if (props.id !== undefined)
348
+ return (0, clone_1.default)((_b = this.data) === null || _b === void 0 ? void 0 : _b.waysLookup[props.id]);
349
+ }
350
+ getNode(props) {
351
+ var _a, _b;
352
+ if (!props)
353
+ return this.location;
354
+ if (typeof props === 'string') {
355
+ return (0, clone_1.default)((_a = this.data) === null || _a === void 0 ? void 0 : _a.nodesLookup[props]);
356
+ }
357
+ if (typeof props === 'object' && props.id === undefined && props.lat !== undefined && props.lng !== undefined && props.ways !== undefined) {
358
+ return (0, clone_1.default)(props);
359
+ }
360
+ if (props.id !== undefined) {
361
+ return (0, clone_1.default)((_b = this.data) === null || _b === void 0 ? void 0 : _b.nodesLookup[props.id]);
362
+ }
363
+ }
364
+ copyWay(wayFrom, id) {
365
+ let w;
366
+ w = (id === undefined) ? this.getWay(wayFrom) : this.getWay(id);
367
+ let path = w.path;
368
+ let roundabout = (0, utils_1.isRoundabout)(w);
369
+ if (!roundabout && wayFrom !== undefined && wayFrom.id === w.id) {
370
+ let idxPrev = undefined;
371
+ let idx = undefined;
372
+ let point = wayFrom.path[wayFrom.path.length - 1];
373
+ let prev = wayFrom.path[wayFrom.path.length - 2];
374
+ path.forEach((p, i) => {
375
+ if (idx === undefined || idxPrev === undefined) {
376
+ if ((0, utils_1.pointEquals)(p, point))
377
+ idx = i;
378
+ if ((0, utils_1.pointEquals)(p, prev))
379
+ idxPrev = i;
380
+ }
381
+ });
382
+ if (idx !== undefined && idxPrev !== undefined) {
383
+ if (idxPrev < idx)
384
+ w.path = path.filter((n, i) => i >= idx);
385
+ if (idxPrev > idx) {
386
+ w.path = path.filter((n, i) => i <= idx);
387
+ w.path.reverse();
388
+ }
389
+ }
390
+ }
391
+ return { w, roundabout };
392
+ }
393
+ checkOptionsOnCurrentWay(location, way, options) {
394
+ try {
395
+ if (way.path.length > 1) {
396
+ let prev = way.path[way.path.length - 2];
397
+ let { w, roundabout } = this.copyWay(way);
398
+ if (roundabout) {
399
+ let branches = (0, utils_1.splitAtPoint)(w, location);
400
+ branches.forEach(b => {
401
+ if (b.path.length > 1 && b.path[1].id !== prev.id) {
402
+ options.push(b);
403
+ }
404
+ });
405
+ }
406
+ else {
407
+ if (w.path.length > 1) {
408
+ let result = this.splitAtFirstBranch(w);
409
+ options.push(result.way);
410
+ }
411
+ }
412
+ }
413
+ }
414
+ catch (e) {
415
+ console.log(e);
416
+ }
417
+ }
418
+ checkOptionsOnDifferentWay(location, w, options) {
419
+ if (!w || !w.path || !location)
420
+ return;
421
+ let result;
422
+ let roundabout = (0, utils_1.isRoundabout)(w);
423
+ let self = this;
424
+ if (!roundabout) {
425
+ if (w.path[0].id === location.id) {
426
+ result = this.splitAtFirstBranch(w);
427
+ let expand = false;
428
+ if (result.way.path.length === w.path.length) {
429
+ const pLast = w.path[w.path.length - 1];
430
+ if (pLast.ways.length === 2) {
431
+ const wIdNext = pLast.ways.find(wid => wid !== w.id);
432
+ const wNext = this.getWay({ id: wIdNext });
433
+ if (!(0, utils_1.isRoundabout)(wNext)) {
434
+ const pNextStart = wNext.path[0];
435
+ const pNextEnd = wNext.path[wNext.path.length - 1];
436
+ if (pNextStart.id === pLast.id) {
437
+ expand = true;
438
+ const segment = this.splitAtFirstBranch(wNext);
439
+ const combined = {
440
+ id: segment.way.id,
441
+ path: w.path.concat(segment.way.path.slice(1))
442
+ };
443
+ options.push(combined);
444
+ }
445
+ else if (pNextEnd.id === pLast.id) {
446
+ const wReverse = this.copyWay(wNext);
447
+ if (wReverse && wReverse.path) {
448
+ wReverse.path = wReverse.path.reverse();
449
+ const segment = this.splitAtFirstBranch(wNext);
450
+ const combined = {
451
+ id: segment.way.id,
452
+ path: w.path.concat(segment.way.path.slice(1))
453
+ };
454
+ options.push(combined);
455
+ }
456
+ else {
457
+ console.log(' ~~~~ unexpected', wNext, wReverse);
458
+ }
459
+ }
460
+ else {
461
+ const idxSplit = wNext.path.findIndex((p) => p.id === pLast.id);
462
+ if (idxSplit !== 1) {
463
+ const nextPaths = splitAtIndex(wNext, idxSplit);
464
+ nextPaths.forEach((p) => {
465
+ if (p[0].ways.find(wid => wid === w.id)) {
466
+ expand = true;
467
+ const wFull = {
468
+ id: wIdNext,
469
+ path: p.slice(1)
470
+ };
471
+ const segment = this.splitAtFirstBranch(wFull);
472
+ const combined = {
473
+ id: segment.way.id,
474
+ path: w.path.concat(segment.way.path.slice(1))
475
+ };
476
+ options.push(combined);
477
+ }
478
+ else if (p[p.length - 1].ways.find(wid => wid === w.id)) {
479
+ expand = true;
480
+ const wFull = {
481
+ id: wIdNext,
482
+ path: p.reverse()
483
+ };
484
+ const segment = this.splitAtFirstBranch(wFull);
485
+ const combined = {
486
+ id: segment.way.id,
487
+ path: w.path.concat(segment.way.path.slice(1))
488
+ };
489
+ options.push(combined);
490
+ }
491
+ });
492
+ }
493
+ }
494
+ }
495
+ }
496
+ }
497
+ if (!expand)
498
+ options.push(result.way);
499
+ }
500
+ else if (w.path[w.path.length - 1].id === location.id) {
501
+ w.path.reverse();
502
+ result = this.splitAtFirstBranch(w);
503
+ if ((0, utils_1.isOneWay)(w))
504
+ result.way.onewayReverse = true;
505
+ options.push(result.way);
506
+ }
507
+ else {
508
+ let ways = (0, utils_1.splitAtPoint)(w, location);
509
+ if (!ways[0].onewayReverse) {
510
+ result = this.splitAtFirstBranch(ways[0]);
511
+ options.push(result.way);
512
+ }
513
+ if (!ways[1].onewayReverse) {
514
+ result = this.splitAtFirstBranch(ways[1]);
515
+ options.push(result.way);
516
+ }
517
+ }
518
+ }
519
+ else {
520
+ let r = (0, utils_1.splitAtPoint)(w, location);
521
+ if (!r || r.length === 0)
522
+ return;
523
+ let path = [];
524
+ r[0].path.forEach((p, idx) => {
525
+ if (idx === 0) {
526
+ path.push(p);
527
+ return;
528
+ }
529
+ if (p.ways.length > 1) {
530
+ p.ways.forEach(owid => {
531
+ if (owid !== w.id) {
532
+ let ow = (0, clone_1.default)(this.waysLookup[owid]);
533
+ if (ow !== undefined) {
534
+ if (!(0, utils_1.isAllowed)(ow, p))
535
+ return;
536
+ if (ow.path[ow.path.length - 1].id === p.id)
537
+ ow.path.reverse();
538
+ let optPath1 = self.splitAtFirstBranch(ow);
539
+ let optPath = [...path];
540
+ optPath.push(...optPath1.way.path);
541
+ let o = {
542
+ roundabout: w.id,
543
+ id: ow.id,
544
+ path: optPath
545
+ };
546
+ options.push(o);
547
+ }
548
+ }
549
+ });
550
+ }
551
+ path.push(p);
552
+ });
553
+ }
554
+ return (0, utils_1.removeDuplicates)(options);
555
+ }
556
+ }
557
+ exports.MapAreaService = MapAreaService;
558
+ MapAreaService.consts = { DEFAULT_RADIUS: consts_1.DEFAULT_RADIUS, DEFAULT_MIN_WAYS: consts_1.DEFAULT_MIN_WAYS, DEFAULT_MAX_WAYS: consts_1.DEFAULT_MAX_WAYS, MAX_DISTANCE_FROM_PATH: consts_1.MAX_DISTANCE_FROM_PATH, GET_WAYS_IN_AREA: consts_1.GET_WAYS_IN_AREA };
559
+ MapAreaService._instances = {};
560
+ const useMapArea = (id) => MapAreaService.getInstance(id);
561
+ exports.useMapArea = useMapArea;