forked from perliedman/geojson-path-finder
-
Notifications
You must be signed in to change notification settings - Fork 0
/
compactor.js
126 lines (105 loc) · 4.1 KB
/
compactor.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
'use strict';
module.exports = {
compactNode: compactNode,
compactGraph: compactGraph
};
function findNextEnd(prev, v, vertices, ends, vertexCoords, edgeData, trackIncoming, options) {
var weight = vertices[prev][v],
reverseWeight = vertices[v][prev],
coordinates = [],
path = [],
reducedEdge = [];//options.edgeDataSeed;
if (options.edgeDataReduceFn) {
reducedEdge.push(options.edgeDataReduceFn(reducedEdge, edgeData[v][prev]));
}
while (!ends[v]) {
var edges = vertices[v];
if (!edges) { break; }
var next = Object.keys(edges).filter(function notPrevious(k) { return k !== prev; })[0];
weight += edges[next];
if (trackIncoming) {
reverseWeight += vertices[next][v];
if (path.indexOf(v) >= 0) {
ends[v] = vertices[v];
break;
}
path.push(v);
}
if (options.edgeDataReduceFn) {
reducedEdge.push(options.edgeDataReduceFn(reducedEdge, edgeData[v][next]));
}
coordinates.push(vertexCoords[v]);
prev = v;
v = next;
}
return {
vertex: v,
weight: weight,
reverseWeight: reverseWeight,
coordinates: coordinates,
reducedEdge: reducedEdge
};
}
function compactNode(k, vertices, ends, vertexCoords, edgeData, trackIncoming, options) {
options = options || {};
var neighbors = vertices[k];
return Object.keys(neighbors).reduce(function compactEdge(result, j) {
var neighbor = findNextEnd(k, j, vertices, ends, vertexCoords, edgeData, trackIncoming, options);
var weight = neighbor.weight;
var reverseWeight = neighbor.reverseWeight;
if (neighbor.vertex !== k) {
if (!result.edges[neighbor.vertex] || result.edges[neighbor.vertex] > weight) {
result.edges[neighbor.vertex] = weight;
result.coordinates[neighbor.vertex] = [vertexCoords[k]].concat(neighbor.coordinates);
result.reducedEdges[neighbor.vertex] = neighbor.reducedEdge;
}
if (trackIncoming &&
!isNaN(reverseWeight) && (!result.incomingEdges[neighbor.vertex] || result.incomingEdges[neighbor.vertex] > reverseWeight)) {
result.incomingEdges[neighbor.vertex] = reverseWeight;
var coordinates = [vertexCoords[k]].concat(neighbor.coordinates);
coordinates.reverse();
result.incomingCoordinates[neighbor.vertex] = coordinates;
}
}
return result;
}, {edges: {}, incomingEdges: {}, coordinates: {}, incomingCoordinates: {}, reducedEdges: {}});
}
function compactGraph(vertices, vertexCoords, edgeData, options) {
options = options || {};
var progress = options.progress;
var ends = Object.keys(vertices).reduce(function findEnds(es, k, i, vs) {
var vertex = vertices[k];
var edges = Object.keys(vertex);
var numberEdges = edges.length;
var remove;
if (numberEdges === 1) {
var other = vertices[edges[0]];
remove = !other[k];
} else if (numberEdges === 2) {
remove = edges.filter(function(n) {
return vertices[n][k];
}).length === numberEdges;
} else {
remove = false;
}
if (!remove) {
es[k] = vertex;
}
if (i % 1000 === 0 && progress) {
progress('compact:ends', i, vs.length);
}
return es;
}, {});
return Object.keys(ends).reduce(function compactEnd(result, k, i, es) {
var compacted = compactNode(k, vertices, ends, vertexCoords, edgeData, false, options);
result.graph[k] = compacted.edges;
result.coordinates[k] = compacted.coordinates;
if (options.edgeDataReduceFn) {
result.reducedEdges[k] = compacted.reducedEdges;
}
if (i % 1000 === 0 && progress) {
progress('compact:nodes', i, es.length);
}
return result;
}, {graph: {}, coordinates: {}, reducedEdges: {}});
};