27
27
import com .graphhopper .storage .Graph ;
28
28
import com .graphhopper .util .EdgeIterator ;
29
29
import com .graphhopper .util .GHUtility ;
30
+ import org .jetbrains .annotations .NotNull ;
30
31
31
32
import java .util .ArrayList ;
32
33
import java .util .Collection ;
35
36
36
37
import static com .graphhopper .isochrone .algorithm .ShortestPathTree .ExploreType .*;
37
38
import static java .util .Comparator .comparingDouble ;
39
+ import static java .util .Comparator .comparingLong ;
38
40
39
41
/**
40
42
* Computes a shortest path tree by a given weighting. Terminates when all shortest paths up to
@@ -85,7 +87,8 @@ public String toString() {
85
87
}
86
88
87
89
private final IntObjectHashMap <IsoLabel > fromMap ;
88
- private final PriorityQueue <IsoLabel > queueByWeighting ;
90
+ private final PriorityQueue <IsoLabel > queueByWeighting ; // a.k.a. the Dijkstra queue
91
+ private PriorityQueue <IsoLabel > queueByZ ; // so we know when we are finished
89
92
private int visitedNodes ;
90
93
private double limit = -1 ;
91
94
private ExploreType exploreType = TIME ;
@@ -94,6 +97,7 @@ public String toString() {
94
97
public ShortestPathTree (Graph g , Weighting weighting , boolean reverseFlow , TraversalMode traversalMode ) {
95
98
super (g , weighting , traversalMode );
96
99
queueByWeighting = new PriorityQueue <>(1000 , comparingDouble (l -> l .weight ));
100
+ queueByZ = new PriorityQueue <>(1000 );
97
101
fromMap = new GHIntObjectHashMap <>(1000 );
98
102
this .reverseFlow = reverseFlow ;
99
103
}
@@ -109,6 +113,7 @@ public Path calcPath(int from, int to) {
109
113
public void setTimeLimit (double limit ) {
110
114
exploreType = TIME ;
111
115
this .limit = limit ;
116
+ this .queueByZ = new PriorityQueue <>(1000 , comparingLong (l -> l .time ));
112
117
}
113
118
114
119
/**
@@ -117,25 +122,30 @@ public void setTimeLimit(double limit) {
117
122
public void setDistanceLimit (double limit ) {
118
123
exploreType = DISTANCE ;
119
124
this .limit = limit ;
125
+ this .queueByZ = new PriorityQueue <>(1000 , comparingDouble (l -> l .distance ));
120
126
}
121
127
122
128
public void setWeightLimit (double limit ) {
123
129
exploreType = WEIGHT ;
124
130
this .limit = limit ;
131
+ this .queueByZ = new PriorityQueue <>(1000 , comparingDouble (l -> l .weight ));
125
132
}
126
133
127
134
public void search (int from , final Consumer <IsoLabel > consumer ) {
128
135
checkAlreadyRun ();
129
136
IsoLabel currentLabel = new IsoLabel (from , -1 , 0 , 0 , 0 , null );
130
137
queueByWeighting .add (currentLabel );
138
+ queueByZ .add (currentLabel );
131
139
if (traversalMode == TraversalMode .NODE_BASED ) {
132
140
fromMap .put (from , currentLabel );
133
141
}
134
- while (!queueByWeighting . isEmpty ()) {
142
+ while (!finished ()) {
135
143
currentLabel = queueByWeighting .poll ();
136
144
if (currentLabel .deleted )
137
145
continue ;
138
- consumer .accept (currentLabel );
146
+ if (getExploreValue (currentLabel ) <= limit ) {
147
+ consumer .accept (currentLabel );
148
+ }
139
149
currentLabel .deleted = true ;
140
150
visitedNodes ++;
141
151
@@ -152,31 +162,33 @@ public void search(int from, final Consumer<IsoLabel> consumer) {
152
162
double nextDistance = iter .getDistance () + currentLabel .distance ;
153
163
long nextTime = GHUtility .calcMillisWithTurnMillis (weighting , iter , reverseFlow , currentLabel .edge ) + currentLabel .time ;
154
164
int nextTraversalId = traversalMode .createTraversalId (iter , reverseFlow );
155
- IsoLabel label = fromMap .get (nextTraversalId );
156
- if (label == null ) {
157
- label = new IsoLabel (iter .getAdjNode (), iter .getEdge (), nextWeight , nextTime , nextDistance , currentLabel );
158
- fromMap .put (nextTraversalId , label );
159
- if (getExploreValue (label ) <= limit ) {
160
- queueByWeighting .add (label );
161
- }
162
- } else if (label .weight > nextWeight ) {
163
- label .deleted = true ;
164
- label = new IsoLabel (iter .getAdjNode (), iter .getEdge (), nextWeight , nextTime , nextDistance , currentLabel );
165
- fromMap .put (nextTraversalId , label );
166
- if (getExploreValue (label ) <= limit ) {
167
- queueByWeighting .add (label );
168
- }
165
+ IsoLabel nextLabel = fromMap .get (nextTraversalId );
166
+ if (nextLabel == null ) {
167
+ nextLabel = new IsoLabel (iter .getAdjNode (), iter .getEdge (), nextWeight , nextTime , nextDistance , currentLabel );
168
+ fromMap .put (nextTraversalId , nextLabel );
169
+ queueByWeighting .add (nextLabel );
170
+ queueByZ .add (nextLabel );
171
+ } else if (nextLabel .weight > nextWeight ) {
172
+ nextLabel .deleted = true ;
173
+ nextLabel = new IsoLabel (iter .getAdjNode (), iter .getEdge (), nextWeight , nextTime , nextDistance , currentLabel );
174
+ fromMap .put (nextTraversalId , nextLabel );
175
+ queueByWeighting .add (nextLabel );
176
+ queueByZ .add (nextLabel );
169
177
}
170
178
}
171
179
}
172
180
}
173
181
174
182
public Collection <IsoLabel > getIsochroneEdges () {
175
183
// assert alreadyRun
184
+ return getIsochroneEdges (limit );
185
+ }
186
+
187
+ public ArrayList <IsoLabel > getIsochroneEdges (double z ) {
176
188
ArrayList <IsoLabel > result = new ArrayList <>();
177
189
for (ObjectCursor <IsoLabel > cursor : fromMap .values ()) {
178
- if (getExploreValue ( cursor .value ) > limit ) {
179
- assert cursor .value . parent == null || getExploreValue (cursor .value .parent ) <= limit ;
190
+ if (cursor .value . parent != null &&
191
+ ( getExploreValue ( cursor .value ) > z ^ getExploreValue (cursor .value .parent ) > z )) {
180
192
result .add (cursor .value );
181
193
}
182
194
}
@@ -191,6 +203,14 @@ private double getExploreValue(IsoLabel label) {
191
203
return label .distance ;
192
204
}
193
205
206
+ protected boolean finished () {
207
+ while (queueByZ .peek () != null && queueByZ .peek ().deleted )
208
+ queueByZ .poll ();
209
+ if (queueByZ .peek () == null )
210
+ return true ;
211
+ return getExploreValue (queueByZ .peek ()) >= limit ;
212
+ }
213
+
194
214
@ Override
195
215
public String getName () {
196
216
return "reachability" ;
0 commit comments