atriusmaps-node-sdk 3.3.196 → 3.3.226
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.
- package/dist/cjs/_virtual/_empty_module_placeholder.js +2 -2
- package/dist/cjs/deploy/prepareSDKConfig.js +152 -2
- package/dist/cjs/nodesdk/nodeEntry.js +109 -0
- package/dist/cjs/package.json.js +190 -14
- package/dist/cjs/plugins/clientAPI/src/clientAPI.js +11 -2
- package/dist/cjs/plugins/dynamicPois/src/dynamicPois.js +218 -21
- package/dist/cjs/plugins/poiDataManager/src/poiDataManager.js +292 -21
- package/dist/cjs/plugins/sdkServer/src/sdkHeadless.js +99 -20
- package/dist/cjs/plugins/sdkServer/src/sdkServer.js +219 -2
- package/dist/cjs/plugins/sdkServer/src/util.js +16 -3
- package/dist/cjs/plugins/searchService/src/poiSearch.js +57 -19
- package/dist/cjs/plugins/searchService/src/searchService.js +246 -21
- package/dist/cjs/plugins/searchService/src/searchTypeahead.js +60 -3
- package/dist/cjs/plugins/searchService/src/utils.js +23 -4
- package/dist/cjs/plugins/venueDataLoader/src/venueDataLoader.js +472 -21
- package/dist/cjs/plugins/venueDataLoader/src/venueLoadingUtils.js +191 -23
- package/dist/cjs/plugins/wayfinder/src/findRoute.js +147 -19
- package/dist/cjs/plugins/wayfinder/src/minPriorityQueue.js +88 -2
- package/dist/cjs/plugins/wayfinder/src/navGraph.js +393 -5
- package/dist/cjs/plugins/wayfinder/src/navGraphDebug.js +110 -20
- package/dist/cjs/plugins/wayfinder/src/segmentBadges.js +28 -2
- package/dist/cjs/plugins/wayfinder/src/segmentBuilder.js +257 -19
- package/dist/cjs/plugins/wayfinder/src/segmentCategories.js +29 -2
- package/dist/cjs/plugins/wayfinder/src/stepBuilder.js +238 -3
- package/dist/cjs/plugins/wayfinder/src/wayfinder.js +597 -22
- package/dist/cjs/src/app.js +191 -25
- package/dist/cjs/src/configs/postproc-mol-url-parms.js +58 -2
- package/dist/cjs/src/configs/postproc-stateTracking.js +53 -19
- package/dist/cjs/src/controller.js +43 -4
- package/dist/cjs/src/debugTools.js +128 -23
- package/dist/cjs/src/env.js +17 -2
- package/dist/cjs/src/extModules/bustle.js +128 -4
- package/dist/cjs/src/extModules/flexapi/src/help.js +23 -4
- package/dist/cjs/src/extModules/flexapi/src/index.js +65 -4
- package/dist/cjs/src/extModules/flexapi/src/validate.js +133 -5
- package/dist/cjs/src/extModules/geohasher.js +90 -3
- package/dist/cjs/src/extModules/log.js +69 -2
- package/dist/cjs/src/historyManager.js +29 -2
- package/dist/cjs/src/utils/bounds.js +22 -4
- package/dist/cjs/src/utils/buildStructureLookup.js +31 -19
- package/dist/cjs/src/utils/configUtils.js +71 -3
- package/dist/cjs/src/utils/dom.js +48 -5
- package/dist/cjs/src/utils/funcs.js +30 -3
- package/dist/cjs/src/utils/geodesy.js +35 -3
- package/dist/cjs/src/utils/geom.js +209 -27
- package/dist/cjs/src/utils/i18n.js +69 -5
- package/dist/cjs/src/utils/observable.js +73 -2
- package/dist/cjs/src/utils/rand.js +82 -3
- package/dist/nodesdk/nodeEntry.js +1 -0
- package/dist/package.json.js +1 -0
- package/dist/plugins/searchService/src/searchService.js +1 -0
- package/dist/plugins/venueDataLoader/src/venueDataLoader.js +1 -0
- package/dist/plugins/venueDataLoader/src/venueLoadingUtils.js +1 -0
- package/dist/src/app.js +1 -0
- package/package.json +13 -9
- package/.yarnrc.yml +0 -1
- package/config/rollup.config.cjs.js +0 -31
- package/dist/cjs/deploy/nodeEntry.js +0 -20
- package/dist/cjs/src/auth/Auth.js +0 -23
- package/lib/deploy/nodeEntry.js +0 -1
- package/lib/package.json.js +0 -1
- package/lib/plugins/searchService/src/searchService.js +0 -1
- package/lib/plugins/venueDataLoader/src/venueDataLoader.js +0 -1
- package/lib/plugins/venueDataLoader/src/venueLoadingUtils.js +0 -1
- package/lib/src/app.js +0 -1
- package/lib/src/configs/sdkHeadless.json +0 -28
- /package/{lib → dist}/_virtual/_empty_module_placeholder.js +0 -0
- /package/{lib → dist}/deploy/prepareSDKConfig.js +0 -0
- /package/{lib → dist}/plugins/clientAPI/src/clientAPI.js +0 -0
- /package/{lib → dist}/plugins/dynamicPois/src/dynamicPois.js +0 -0
- /package/{lib → dist}/plugins/poiDataManager/src/poiDataManager.js +0 -0
- /package/{lib → dist}/plugins/sdkServer/src/sdkHeadless.js +0 -0
- /package/{lib → dist}/plugins/sdkServer/src/sdkServer.js +0 -0
- /package/{lib → dist}/plugins/sdkServer/src/util.js +0 -0
- /package/{lib → dist}/plugins/searchService/src/poiSearch.js +0 -0
- /package/{lib → dist}/plugins/searchService/src/searchTypeahead.js +0 -0
- /package/{lib → dist}/plugins/searchService/src/utils.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/findRoute.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/minPriorityQueue.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/navGraph.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/navGraphDebug.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/segmentBadges.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/segmentBuilder.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/segmentCategories.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/stepBuilder.js +0 -0
- /package/{lib → dist}/plugins/wayfinder/src/wayfinder.js +0 -0
- /package/{lib → dist}/src/configs/postproc-mol-url-parms.js +0 -0
- /package/{lib → dist}/src/configs/postproc-stateTracking.js +0 -0
- /package/{lib → dist}/src/configs/sdkHeadless.json.js +0 -0
- /package/{lib → dist}/src/controller.js +0 -0
- /package/{lib → dist}/src/debugTools.js +0 -0
- /package/{lib → dist}/src/env.js +0 -0
- /package/{lib → dist}/src/extModules/bustle.js +0 -0
- /package/{lib → dist}/src/extModules/flexapi/src/help.js +0 -0
- /package/{lib → dist}/src/extModules/flexapi/src/index.js +0 -0
- /package/{lib → dist}/src/extModules/flexapi/src/validate.js +0 -0
- /package/{lib → dist}/src/extModules/geohasher.js +0 -0
- /package/{lib → dist}/src/extModules/log.js +0 -0
- /package/{lib → dist}/src/historyManager.js +0 -0
- /package/{lib → dist}/src/utils/bounds.js +0 -0
- /package/{lib → dist}/src/utils/buildStructureLookup.js +0 -0
- /package/{lib → dist}/src/utils/configUtils.js +0 -0
- /package/{lib → dist}/src/utils/dom.js +0 -0
- /package/{lib → dist}/src/utils/funcs.js +0 -0
- /package/{lib → dist}/src/utils/geodesy.js +0 -0
- /package/{lib → dist}/src/utils/geom.js +0 -0
- /package/{lib → dist}/src/utils/i18n.js +0 -0
- /package/{lib → dist}/src/utils/observable.js +0 -0
- /package/{lib → dist}/src/utils/rand.js +0 -0
|
@@ -2,13 +2,401 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var R = require('ramda');
|
|
6
6
|
var geohasher = require('../../../src/extModules/geohasher.js');
|
|
7
7
|
var geodesy = require('../../../src/utils/geodesy.js');
|
|
8
8
|
var minPriorityQueue = require('./minPriorityQueue.js');
|
|
9
9
|
|
|
10
|
-
const
|
|
10
|
+
const DEFAULT_WALKING_SPEED_M_PER_MIN = 60;
|
|
11
|
+
const CLOSED_CHECKPOINT_EDGE_WEIGHT = 9999;
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
/**
|
|
14
|
+
* @typedef NavNode
|
|
15
|
+
* @property {number} ordinal
|
|
16
|
+
* @property {Array.<NavEdge>} edges
|
|
17
|
+
* @property {string} id
|
|
18
|
+
* @property {number} lat
|
|
19
|
+
* @property {number} lng
|
|
20
|
+
* @property {string} floorId
|
|
21
|
+
* @property {structureId} structureId
|
|
22
|
+
*
|
|
23
|
+
* @typedef NavEdge
|
|
24
|
+
* @property {string} dst - id of node at edge end
|
|
25
|
+
* @property {string} src - id of node at edge start
|
|
26
|
+
* @property {number} distance
|
|
27
|
+
* @property {string|undefined} o - id of security lane POI associated with this edge
|
|
28
|
+
* @property {CurvedPath|null} path - list of Bezier points if edge represents curve
|
|
29
|
+
* @property {boolean} isAccessible
|
|
30
|
+
* @property {boolean} isDriveway - true if edge points to POI, false if edge just connects other edges
|
|
31
|
+
* @property {number} transitTime
|
|
32
|
+
* @property {string} type
|
|
33
|
+
* @property {number} weight - value used by Dijkstra algorithm (usually edge time or distance)
|
|
34
|
+
*
|
|
35
|
+
* @param {RawNavGraph} data
|
|
36
|
+
* @param {function} floorIdToOrdinal
|
|
37
|
+
* @param {function} floorIdToStructureId
|
|
38
|
+
* @param {Array.<SecurityLane>} securityLanesMap - list of security lanes
|
|
39
|
+
* @return {Object}
|
|
40
|
+
*/
|
|
41
|
+
// todo remove dead commented code
|
|
42
|
+
function createNavGraph (data, floorIdToOrdinal, floorIdToStructureId, securityLanesMap) {
|
|
43
|
+
const nodes = { };
|
|
44
|
+
const geoDb = { };
|
|
45
|
+
let securityWaitTimes = {};
|
|
46
|
+
|
|
47
|
+
data.nodes.forEach(nodeData => {
|
|
48
|
+
const ordinal = floorIdToOrdinal(nodeData.floorId);
|
|
49
|
+
const structureId = floorIdToStructureId(nodeData.floorId);
|
|
50
|
+
const node = {
|
|
51
|
+
...R.pick(['id', 'lat', 'lng', 'floorId'], nodeData),
|
|
52
|
+
edges: [],
|
|
53
|
+
ordinal,
|
|
54
|
+
structureId
|
|
55
|
+
};
|
|
56
|
+
addNode(node);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
data.edges.forEach(ed => nodes[ed.s].edges.push(createEdge(ed, nodes)));
|
|
60
|
+
|
|
61
|
+
function addNode (node) {
|
|
62
|
+
const largeGeo = node.floorId + ':' + geohasher.encode(node.lat, node.lng).substr(0, 7);
|
|
63
|
+
const mediumGeo = node.floorId + ':' + geohasher.encode(node.lat, node.lng).substr(0, 8);
|
|
64
|
+
|
|
65
|
+
if (!geoDb[largeGeo])
|
|
66
|
+
geoDb[largeGeo] = [];
|
|
67
|
+
|
|
68
|
+
geoDb[largeGeo].push(node);
|
|
69
|
+
|
|
70
|
+
if (!geoDb[mediumGeo])
|
|
71
|
+
geoDb[mediumGeo] = [];
|
|
72
|
+
|
|
73
|
+
geoDb[mediumGeo].push(node);
|
|
74
|
+
|
|
75
|
+
nodes[node.id] = node;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function createEdge (data, nodes) {
|
|
79
|
+
const type = getEdgeType(data);
|
|
80
|
+
const isAccessible = type.toLowerCase() !== 'escalator' && type.toLowerCase() !== 'stairs';
|
|
81
|
+
// todo consider calculating edge distance with 'path' differently
|
|
82
|
+
const distance = distanceBetweenNodes(data.s, data.d, nodes);
|
|
83
|
+
const transitTime = data.l || distance / DEFAULT_WALKING_SPEED_M_PER_MIN;
|
|
84
|
+
|
|
85
|
+
const buildCurvedPath = points => points.map(point => {
|
|
86
|
+
return {
|
|
87
|
+
start: { lat: point.s[0], lng: point.s[1] },
|
|
88
|
+
out: { lat: point.o[0], lng: point.o[1] },
|
|
89
|
+
in: { lat: point.i[0], lng: point.i[1] },
|
|
90
|
+
end: { lat: point.e[0], lng: point.e[1] }
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const path = data.p ? buildCurvedPath(data.p) : null;
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
distance,
|
|
98
|
+
dst: data.d,
|
|
99
|
+
o: data.o,
|
|
100
|
+
isAccessible,
|
|
101
|
+
isDriveway: !R.isNil(data.h) && !data.h,
|
|
102
|
+
src: data.s,
|
|
103
|
+
transitTime,
|
|
104
|
+
type,
|
|
105
|
+
path,
|
|
106
|
+
weight: transitTime
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function getEdgeType (data) {
|
|
111
|
+
if (data.x) return 'Security Checkpoint'
|
|
112
|
+
if (data.t === '') return 'Ground'
|
|
113
|
+
return data.t
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const findClosestNode = endpoint => {
|
|
117
|
+
if (endpoint.floorId === undefined && endpoint.ordinal === undefined) // one of these must be present
|
|
118
|
+
throw Error('Endpoint specified in findRoute without floorId nor an ordinal')
|
|
119
|
+
const lat = endpoint.lat || endpoint.latitude; // handle bluedot location
|
|
120
|
+
const lng = endpoint.lng || endpoint.longitude; // handle bluedot location
|
|
121
|
+
return endpoint.floorId
|
|
122
|
+
? findClosestNodeByFloor(endpoint.floorId, lat, lng, geoDb, nodes)
|
|
123
|
+
: findClosestNodeByOrdinal(endpoint.ordinal, lat, lng, nodes)
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
function findShortestPathEntry (start, end, nodes, options = {}) {
|
|
127
|
+
const startNode = findClosestNode(start);
|
|
128
|
+
const endNode = findClosestNode(end);
|
|
129
|
+
|
|
130
|
+
// This code section does improve performance by about 10-20%, but comes at a cost
|
|
131
|
+
// of making the caching unusable in some cases
|
|
132
|
+
// if (start.structureId === end.structureId) {
|
|
133
|
+
// options.minOrd = Math.min(start.ordinal, end.ordinal)
|
|
134
|
+
// options.maxOrd = Math.max(start.ordinal, end.ordinal)
|
|
135
|
+
// options.structureId = start.structureId
|
|
136
|
+
// }
|
|
137
|
+
return findShortestPath(startNode, endNode, nodes, securityWaitTimes, securityLanesMap, options)
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* @param {Endpoint} start - start endpoint
|
|
141
|
+
* @param {Array.<Endpoint>} destArray - list of destinations
|
|
142
|
+
* @param {RouteOptions} options extra options (such as requireAccessibility)
|
|
143
|
+
* @returns {Array.<Array.<NavNode>>} array of routes corresponding to destinations specified
|
|
144
|
+
*/
|
|
145
|
+
function findAllShortestPaths (start, destArray, options) {
|
|
146
|
+
const startNode = findClosestNode(start);
|
|
147
|
+
const destNodeArray = destArray.map(dest => findClosestNode(dest));
|
|
148
|
+
if (!startNode || !destNodeArray.length) return []
|
|
149
|
+
return findAllShortestPathsImpl(startNode, destNodeArray, nodes, securityWaitTimes, securityLanesMap, options)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function updateWithSecurityWaitTime (waitTimesData) {
|
|
153
|
+
securityWaitTimes = R.map(R.omit(['lastUpdated']), waitTimesData);
|
|
154
|
+
clearCache();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
_nodes: nodes,
|
|
159
|
+
_geoDb: geoDb,
|
|
160
|
+
findClosestNode: (floorId, lat, lng) => findClosestNodeByFloor(floorId, lat, lng, geoDb, nodes),
|
|
161
|
+
findShortestPath: (start, end, options) => findShortestPathEntry(start, end, nodes, options),
|
|
162
|
+
findAllShortestPaths,
|
|
163
|
+
floorIdToOrdinal, // todo lets get rid of this...
|
|
164
|
+
floorIdToStructureId, // todo lets get rid of this...,
|
|
165
|
+
updateWithSecurityWaitTime,
|
|
166
|
+
clearCache
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function distanceBetweenNodes (n1, n2, nodes) {
|
|
171
|
+
const node1 = nodes[n1];
|
|
172
|
+
const node2 = nodes[n2];
|
|
173
|
+
const distance = geodesy.distance(node1.lat, node1.lng, node2.lat, node2.lng);
|
|
174
|
+
return distance
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* @param {Object.<Node>} start - a node in the navGraph to start on
|
|
179
|
+
* @param {Array.<Node>} destinations - array of nodes to find path to
|
|
180
|
+
* @param {Object.<string, NavNode>} nodes - dictionary of nodes by id
|
|
181
|
+
* @param {Object.<string, SecurityWaitTime>} securityWaitTimes - map of POI id to security wait time
|
|
182
|
+
* @param {Object.<string, SecurityLane>} securityLanesMap - map of POI id to security lane
|
|
183
|
+
* @param {RouteOptions} [options={}] extra options (such as requireAccessibility)
|
|
184
|
+
* @returns {Array.<Array.<Node>>} list of shortest path to each destination
|
|
185
|
+
*/
|
|
186
|
+
function findAllShortestPathsImpl (start, destinations, nodes, securityWaitTimes = {}, securityLanesMap = {}, options = {}) {
|
|
187
|
+
// const previous = findPaths(start, start, nodes, options)
|
|
188
|
+
|
|
189
|
+
// const backtrackPath = node => buildBacktrackPath(nodes, previous, node)
|
|
190
|
+
// const poiNodeTuples = Array.from(destinations.entries())
|
|
191
|
+
|
|
192
|
+
// const poiPathTuples = poiNodeTuples.map(([poi, node]) => [poi, backtrackPath(node)])
|
|
193
|
+
// return new Map(poiPathTuples)
|
|
194
|
+
return destinations.map(d => {
|
|
195
|
+
try {
|
|
196
|
+
return findShortestPath(start, d, nodes, securityWaitTimes, securityLanesMap, options)
|
|
197
|
+
} catch (e) { return null }
|
|
198
|
+
})
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
let cost, prev, visited, visitQueue, lastStartId, lastOptionsStr;
|
|
202
|
+
|
|
203
|
+
const clearCache = () => {
|
|
204
|
+
cost = { };
|
|
205
|
+
prev = { };
|
|
206
|
+
visited = { };
|
|
207
|
+
visitQueue = new minPriorityQueue();
|
|
208
|
+
lastStartId = null;
|
|
209
|
+
lastOptionsStr = {};
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// This is a temporary name during a "probation" period - then I will
|
|
213
|
+
// ditch findShortestPath and rewrite findAllShortestPaths and ditch
|
|
214
|
+
// backtrackPath, etc.
|
|
215
|
+
// NOTE: export just for testing
|
|
216
|
+
/**
|
|
217
|
+
* @param {Object<Node>} start a node in the navGraph to start on
|
|
218
|
+
* @param {Object<Node>} end a node in the navGraph to find path to
|
|
219
|
+
* @param {Object.<string, Node>} nodes dictionary of nodes by id
|
|
220
|
+
* @param {Object.<string, SecurityWaitTime>} securityWaitTimes - map of POI id to security wait time
|
|
221
|
+
* @param {Object.<string, SecurityLane>} securityLanesMap - map of POI id to security lane
|
|
222
|
+
* @param {RouteOptions} options={} extra options (such as requireAccessibility)
|
|
223
|
+
* @returns {Array.<Node>} an array of nodes that represent the shortest route from start to end. null if no route exists.
|
|
224
|
+
*/
|
|
225
|
+
function findShortestPath (start, end, nodes, securityWaitTimes = {}, securityLanesMap = {}, options = { }) {
|
|
226
|
+
if (start.id !== lastStartId || lastOptionsStr !== JSON.stringify(options)) {
|
|
227
|
+
clearCache();
|
|
228
|
+
visitQueue.offerWithPriority(start.id, 0);
|
|
229
|
+
cost[start.id] = 0;
|
|
230
|
+
visited[start.id] = true;
|
|
231
|
+
|
|
232
|
+
lastStartId = start.id;
|
|
233
|
+
lastOptionsStr = JSON.stringify(options);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// continue crawling paths - but stop once we found destination
|
|
237
|
+
while (!visitQueue.isEmpty() && !visited[end.id]) {
|
|
238
|
+
const node = nodes[visitQueue.poll()]; // pop
|
|
239
|
+
const ccost = cost[node.id]; // current cost to this node
|
|
240
|
+
for (let ei = 0; ei < node.edges.length; ei++) {
|
|
241
|
+
const e = node.edges[ei]; // next edge from this node
|
|
242
|
+
|
|
243
|
+
if (visited[e.dst])
|
|
244
|
+
continue
|
|
245
|
+
|
|
246
|
+
if (options.requiresAccessibility && !e.isAccessible) {
|
|
247
|
+
// ignore not accessible edges if we're looking for an accessible route
|
|
248
|
+
continue
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// This code section does improve performance by about 10-20%, but comes at a cost
|
|
252
|
+
// of making the caching unusable in some cases
|
|
253
|
+
// if ((options.minOrd !== undefined && nodes[e.dst].ordinal < options.minOrd) ||
|
|
254
|
+
// (options.maxOrd !== undefined && nodes[e.dst].ordinal > options.maxOrd) ||
|
|
255
|
+
// (options.structureId !== undefined && nodes[e.dst].structureId !== options.structureId))
|
|
256
|
+
// continue
|
|
257
|
+
|
|
258
|
+
let weight = e.weight;
|
|
259
|
+
if (e.o && securityWaitTimes[e.o]) {
|
|
260
|
+
const dynamicData = securityWaitTimes[e.o];
|
|
261
|
+
if (dynamicData.queueTime) weight = dynamicData.queueTime;
|
|
262
|
+
if (dynamicData.isTemporarilyClosed) weight = CLOSED_CHECKPOINT_EDGE_WEIGHT;
|
|
263
|
+
e.securityWaitTimes = dynamicData;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (e.o && securityLanesMap[e.o]) {
|
|
267
|
+
e.securityLane = securityLanesMap[e.o];
|
|
268
|
+
const { type, id } = securityLanesMap[e.o];
|
|
269
|
+
const securityLanesIds = R.path(['selectedSecurityLanes', type], options);
|
|
270
|
+
if (securityLanesIds && !securityLanesIds.includes(id))
|
|
271
|
+
continue
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (cost[e.dst] === undefined) {
|
|
275
|
+
prev[e.dst] = node;
|
|
276
|
+
cost[e.dst] = ccost + weight;
|
|
277
|
+
visitQueue.offerWithPriority(e.dst, ccost + weight); // add node to the toCheck array
|
|
278
|
+
} else
|
|
279
|
+
if (cost[e.dst] > (ccost + weight)) { // is this a shorter path? Relaxation...
|
|
280
|
+
// if so, update the cost and parent
|
|
281
|
+
cost[e.dst] = ccost + weight;
|
|
282
|
+
prev[e.dst] = node;
|
|
283
|
+
visitQueue.raisePriority(e.dst, ccost + weight);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
visited[node.id] = true; // we have now been selected
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (!visited[end.id]) // if we never found our endpoint, it was inaccessible
|
|
290
|
+
return null
|
|
291
|
+
|
|
292
|
+
// build the path and return it
|
|
293
|
+
const path = [];
|
|
294
|
+
let node = end;
|
|
295
|
+
while (node) {
|
|
296
|
+
path.push(node);
|
|
297
|
+
node = prev[node.id];
|
|
298
|
+
}
|
|
299
|
+
return path.reverse()
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function geohashSearch (floorId, geohash, geoDb, size) {
|
|
303
|
+
const geohashPrefix = geohash.substr(0, size);
|
|
304
|
+
|
|
305
|
+
const searchGeos = [];
|
|
306
|
+
searchGeos.push(floorId + ':' + geohasher.calculateAdjacent(geohasher.calculateAdjacent(geohashPrefix, 'top'), 'left'));
|
|
307
|
+
searchGeos.push(floorId + ':' + geohasher.calculateAdjacent(geohashPrefix, 'top'));
|
|
308
|
+
searchGeos.push(floorId + ':' + geohasher.calculateAdjacent(geohasher.calculateAdjacent(geohashPrefix, 'top'), 'right'));
|
|
309
|
+
searchGeos.push(floorId + ':' + geohasher.calculateAdjacent(geohashPrefix, 'left'));
|
|
310
|
+
searchGeos.push(floorId + ':' + geohashPrefix);
|
|
311
|
+
searchGeos.push(floorId + ':' + geohasher.calculateAdjacent(geohashPrefix, 'right'));
|
|
312
|
+
searchGeos.push(floorId + ':' + geohasher.calculateAdjacent(geohasher.calculateAdjacent(geohashPrefix, 'bottom'), 'left'));
|
|
313
|
+
searchGeos.push(floorId + ':' + geohasher.calculateAdjacent(geohashPrefix, 'bottom'));
|
|
314
|
+
searchGeos.push(floorId + ':' + geohasher.calculateAdjacent(geohasher.calculateAdjacent(geohashPrefix, 'bottom'), 'right'));
|
|
315
|
+
|
|
316
|
+
const nodes = [];
|
|
317
|
+
for (let i = 0; i < searchGeos.length; i++) {
|
|
318
|
+
const nodesFound = geoDb[searchGeos[i]];
|
|
319
|
+
if (nodesFound) {
|
|
320
|
+
for (let j = 0; j < nodesFound.length; j++)
|
|
321
|
+
nodes.push(nodesFound[j]);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return nodes
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function findNodesByGeohash (floorId, geohash, geoDb, nodes) {
|
|
329
|
+
let foundNodes = geohashSearch(floorId, geohash, geoDb, 8);
|
|
330
|
+
if (foundNodes.length > 0)
|
|
331
|
+
return foundNodes
|
|
332
|
+
|
|
333
|
+
// broaden our search a bit and try again...
|
|
334
|
+
foundNodes = geohashSearch(floorId, geohash, geoDb, 7);
|
|
335
|
+
if (foundNodes.length > 0)
|
|
336
|
+
return foundNodes
|
|
337
|
+
|
|
338
|
+
// give up and let someone else try...
|
|
339
|
+
return null
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* @param floorId
|
|
344
|
+
* @param lat
|
|
345
|
+
* @param lng
|
|
346
|
+
* @param geoDb
|
|
347
|
+
* @param {Object<string, NavNode>} nodes - dictionary of node id to node object
|
|
348
|
+
* @return {NavNode} - node that is on the same floor and closest to the lat,lng point
|
|
349
|
+
*/
|
|
350
|
+
function findClosestNodeByFloor (floorId, lat, lng, geoDb, nodes) {
|
|
351
|
+
const cnodes = findNodesByGeohash(floorId, geohasher.encode(lat, lng), geoDb) ||
|
|
352
|
+
findClosestNodeByFloor2(floorId, lat, lng, nodes);
|
|
353
|
+
|
|
354
|
+
const nodeWithDistance = [];
|
|
355
|
+
for (let i = 0; i < cnodes.length; i++) {
|
|
356
|
+
// Attached distance to each node from the origin.
|
|
357
|
+
const distance = geodesy.distance(lat, lng, cnodes[i].lat, cnodes[i].lng);
|
|
358
|
+
nodeWithDistance.push([cnodes[i], distance]);
|
|
359
|
+
}
|
|
360
|
+
// todo do not sort, just find min node
|
|
361
|
+
// Sort by distance.
|
|
362
|
+
nodeWithDistance.sort(function (a, b) { return a[1] - b[1] });
|
|
363
|
+
const nodesSortedByDistance = [];
|
|
364
|
+
for (let i = 0; i < nodeWithDistance.length; i++)
|
|
365
|
+
nodesSortedByDistance.push(nodeWithDistance[i][0]);
|
|
366
|
+
|
|
367
|
+
return nodesSortedByDistance[0]
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// A slightly slower alternative to findClosestNode (an experiment - its simpler, but slower)
|
|
371
|
+
function findClosestNodeByFloor2 (floorId, lat, lng, nodes) {
|
|
372
|
+
const floorNodes = Object.values(nodes)
|
|
373
|
+
.filter(n => n.floorId === floorId)
|
|
374
|
+
.map(n => [n, geodesy.distance(n.lat, n.lng, lat, lng)]);
|
|
375
|
+
if (!floorNodes.length)
|
|
376
|
+
throw Error(`findClosestNodeByFloor2 found no nodes on floor ${floorId}`)
|
|
377
|
+
return selectShortest(floorNodes)
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function findClosestNodeByOrdinal (ord, lat, lng, nodes) {
|
|
381
|
+
const ordNodes = Object.values(nodes)
|
|
382
|
+
.filter(n => n.ordinal === ord)
|
|
383
|
+
.map(n => [n, geodesy.distance(n.lat, n.lng, lat, lng)]);
|
|
384
|
+
if (!ordNodes.length)
|
|
385
|
+
throw Error(`findClosestNodeByOrdinal found no nodes on ordinal ${ord}`)
|
|
386
|
+
return selectShortest(ordNodes)
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// companion to above function - it returns closest node
|
|
390
|
+
// ar is 2-dim array - ar[i][0] = node, ar[i][1] = distance
|
|
391
|
+
// TODO: use this approach in findClosestNode - no need to sort first!
|
|
392
|
+
function selectShortest (ar) {
|
|
393
|
+
let shortest = ar[0];
|
|
394
|
+
for (let i = 1; i < ar.length; i++)
|
|
395
|
+
if (ar[i][1] < shortest[1]) shortest = ar[i];
|
|
396
|
+
|
|
397
|
+
return shortest[0]
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
exports.createNavGraph = createNavGraph;
|
|
401
|
+
exports.findClosestNodeByOrdinal = findClosestNodeByOrdinal;
|
|
402
|
+
exports.findShortestPath = findShortestPath;
|
|
@@ -2,29 +2,119 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var R = require('ramda');
|
|
6
6
|
|
|
7
7
|
function _interopNamespace(e) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
8
|
+
if (e && e.__esModule) return e;
|
|
9
|
+
var n = Object.create(null);
|
|
10
|
+
if (e) {
|
|
11
|
+
Object.keys(e).forEach(function (k) {
|
|
12
|
+
if (k !== 'default') {
|
|
13
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function () { return e[k]; }
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
n["default"] = e;
|
|
22
|
+
return Object.freeze(n);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
var
|
|
25
|
+
var R__namespace = /*#__PURE__*/_interopNamespace(R);
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Visits all nodes (breadth-first) from the nodes2visit
|
|
29
|
+
* array, adding them to vnodes and adding their connected
|
|
30
|
+
* nodes to nodes2visit - until nodes2visit is empty.
|
|
31
|
+
* Nothing is returned - but the vnodes array will have been
|
|
32
|
+
* altered.
|
|
33
|
+
* @param {Object.<id:node>} nodes - the node pool you wish to scan
|
|
34
|
+
* @param {Node} startingNode - which node to start the scan
|
|
35
|
+
*/
|
|
36
|
+
function visitAll (nodes, startingNode) {
|
|
37
|
+
// initialize nodes2visit with the specified node to start
|
|
38
|
+
const nodes2visit = [startingNode];
|
|
39
|
+
const vnodes = new Set(); // visited nodes
|
|
28
40
|
|
|
29
|
-
|
|
30
|
-
|
|
41
|
+
while (nodes2visit.length) {
|
|
42
|
+
const node = nodes2visit.splice(0, 1)[0]; // next node to visit
|
|
43
|
+
if (node && !vnodes.has(node)) {
|
|
44
|
+
vnodes.add(node);
|
|
45
|
+
node.edges.forEach(edge => {
|
|
46
|
+
if (!vnodes.has(nodes[edge.dst]))
|
|
47
|
+
nodes2visit.push(nodes[edge.dst]);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return vnodes
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @param {Object.<id:node>} nodes - the node pool you wish to scan
|
|
57
|
+
* @param {Node} [startingNode] - which node to start the scan (default: "first" node)
|
|
58
|
+
* @returns two arrays of nodes in an object, { orphaned, connected }
|
|
59
|
+
*/
|
|
60
|
+
function orphanTest (nodes, startingNode) {
|
|
61
|
+
const nodesArray = Object.values(nodes); // Convert to array
|
|
62
|
+
|
|
63
|
+
const vnodes = visitAll(nodes, startingNode || nodesArray[0]); // If no node is specified, use the first one we find
|
|
64
|
+
const onodes = nodesArray.filter(n => !vnodes.has(n));
|
|
65
|
+
|
|
66
|
+
console.log(`${onodes.length} Orphaned nodes found from ${nodesArray.length} total`);
|
|
67
|
+
|
|
68
|
+
return { orphaned: onodes, orphanedByFloor: R__namespace.groupBy(R__namespace.prop('floorId'), onodes), connected: Array.from(vnodes) }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const enrichDebugNavGraph = (nodes) => ({
|
|
72
|
+
nodes: toOrphanedNodesArray(nodes),
|
|
73
|
+
edges: getNavEdgeFeatures(nodes)
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const transformNodes = isOrphaned =>
|
|
77
|
+
R__namespace.map(R__namespace.pipe(R__namespace.assoc('isOrphaned', isOrphaned), R__namespace.dissoc('edges')));
|
|
78
|
+
|
|
79
|
+
const toOrphanedNodesArray = R__namespace.pipe(
|
|
80
|
+
orphanTest,
|
|
81
|
+
R__namespace.pick(['connected', 'orphaned']),
|
|
82
|
+
R__namespace.evolve({
|
|
83
|
+
connected: transformNodes(false),
|
|
84
|
+
orphaned: transformNodes(true)
|
|
85
|
+
}),
|
|
86
|
+
R__namespace.values,
|
|
87
|
+
R__namespace.flatten
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const getNavEdgeFeatures = nodes =>
|
|
91
|
+
Object.values(nodes).flatMap(node => node.edges)
|
|
92
|
+
.map(edge => mapEdge(edge, nodes));
|
|
93
|
+
|
|
94
|
+
const mapEdge = ({ src, dst, type, isDriveway }, nodeMap) => ({
|
|
95
|
+
startCoordinates: [nodeMap[src].lng, nodeMap[src].lat],
|
|
96
|
+
endCoordinates: [nodeMap[dst].lng, nodeMap[dst].lat],
|
|
97
|
+
isDriveway,
|
|
98
|
+
ordinal: nodeMap[src].ordinal,
|
|
99
|
+
category: getEdgeCategory(type),
|
|
100
|
+
defaultStrokeColor: getStrokeColorForMissingCategory(type)
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const getStrokeColorForMissingCategory = R__namespace.cond([
|
|
104
|
+
[R__namespace.equals('Stairs'), R__namespace.always('#EFBC9B')],
|
|
105
|
+
[R__namespace.equals('Elevator'), R__namespace.always('#A491D3')],
|
|
106
|
+
[R__namespace.equals('Escalator'), R__namespace.always('#563F1B')],
|
|
107
|
+
[R__namespace.equals('Ramp'), R__namespace.always('#DBD053')],
|
|
108
|
+
[R__namespace.T, R__namespace.always('#FF0000')]
|
|
109
|
+
]);
|
|
110
|
+
|
|
111
|
+
const getEdgeCategory = R__namespace.cond([
|
|
112
|
+
[R__namespace.equals('Train'), R__namespace.always('nav.train')],
|
|
113
|
+
[R__namespace.equals('Bus'), R__namespace.always('nav.transit')],
|
|
114
|
+
[R__namespace.equals('Security Checkpoint'), R__namespace.always('nav.secure')],
|
|
115
|
+
[R__namespace.equals('Ground'), R__namespace.always('nav.primary')],
|
|
116
|
+
[R__namespace.T, R__namespace.always('')]
|
|
117
|
+
]);
|
|
118
|
+
|
|
119
|
+
exports.enrichDebugNavGraph = enrichDebugNavGraph;
|
|
120
|
+
exports.orphanTest = orphanTest;
|
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const segmentBadges = {
|
|
4
|
+
START: 'wayfinding.start',
|
|
5
|
+
END: 'wayfinding.end',
|
|
6
|
+
WALKING_TO_SECURITY_CHECKPOINT: 'wayfinding.security',
|
|
7
|
+
ELEVATOR: 'wayfinding.elevator',
|
|
8
|
+
ELEVATOR_UP: 'wayfinding.elevator.up',
|
|
9
|
+
ELEVATOR_DOWN: 'wayfinding.elevator.down',
|
|
10
|
+
STAIRS: 'wayfinding.stairs',
|
|
11
|
+
STAIRS_UP: 'wayfinding.stairs.up',
|
|
12
|
+
STAIRS_DOWN: 'wayfinding.stairs.down',
|
|
13
|
+
ESCALATOR: 'wayfinding.escalator',
|
|
14
|
+
ESCALATOR_UP: 'wayfinding.escalator.up',
|
|
15
|
+
ESCALATOR_DOWN: 'wayfinding.escalator.down',
|
|
16
|
+
WALK: 'wayfinding.movingwalkway',
|
|
17
|
+
WALK_DOWN: 'walk.movingwalkway',
|
|
18
|
+
WALK_UP: 'walk.movingwalkway',
|
|
19
|
+
TRAIN: 'wayfinding.train',
|
|
20
|
+
TRAIN_UP: 'wayfinding.train.up',
|
|
21
|
+
TRAIN_DOWN: 'wayfinding.train.down',
|
|
22
|
+
BUS: 'wayfinding.bus',
|
|
23
|
+
BUS_UP: 'wayfinding.bus.up',
|
|
24
|
+
BUS_DOWN: 'wayfinding.bus.down',
|
|
25
|
+
SECURITY_CHECKPOINT: 'wayfinding.security',
|
|
26
|
+
RAMP: 'wayfinding.ramp',
|
|
27
|
+
RAMP_UP: 'wayfinding.ramp.up',
|
|
28
|
+
RAMP_DOWN: 'wayfinding.ramp.down'
|
|
29
|
+
};
|
|
4
30
|
|
|
5
|
-
module.exports =
|
|
31
|
+
module.exports = segmentBadges;
|