Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/optimiser.c
Parent Directory
|
Revision Log
Revision 47 -
(hide annotations)
(download)
(as text)
Sun Jan 18 09:06:29 2009 UTC (16 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 34915 byte(s)
Sun Jan 18 09:06:29 2009 UTC (16 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 34915 byte(s)
Fix bugs when start and/or finish nodes are supernodes.
1 | amb | 2 | /*************************************** |
2 | amb | 47 | $Header: /home/amb/CVS/routino/src/optimiser.c,v 1.17 2009-01-18 09:06:29 amb Exp $ |
3 | amb | 2 | |
4 | Routing optimiser. | ||
5 | ******************/ /****************** | ||
6 | Written by Andrew M. Bishop | ||
7 | |||
8 | amb | 3 | This file Copyright 2008,2009 Andrew M. Bishop |
9 | amb | 2 | It may be distributed under the GNU Public License, version 2, or |
10 | any higher version. See section COPYING of the GNU Public license | ||
11 | for conditions under which this file may be redistributed. | ||
12 | ***************************************/ | ||
13 | |||
14 | |||
15 | amb | 11 | #include <assert.h> |
16 | amb | 2 | #include <string.h> |
17 | #include <stdlib.h> | ||
18 | |||
19 | amb | 26 | #include "nodes.h" |
20 | #include "ways.h" | ||
21 | #include "segments.h" | ||
22 | amb | 28 | #include "results.h" |
23 | amb | 2 | #include "functions.h" |
24 | |||
25 | amb | 26 | |
26 | amb | 11 | #define INCREMENT 1024 |
27 | amb | 2 | |
28 | amb | 10 | |
29 | amb | 2 | /*+ A queue results. +*/ |
30 | typedef struct _Queue | ||
31 | { | ||
32 | amb | 45 | uint32_t alloced; /*+ The amount of space allocated for results in the array. +*/ |
33 | uint32_t number; /*+ The number of occupied results in the array. +*/ | ||
34 | uint32_t *queue; /*+ An array of offsets into the results array. +*/ | ||
35 | amb | 2 | } |
36 | Queue; | ||
37 | |||
38 | |||
39 | /*+ The queue of nodes. +*/ | ||
40 | amb | 45 | Queue OSMQueue={0,0,NULL}; |
41 | amb | 2 | |
42 | amb | 31 | /*+ Print the progress? +*/ |
43 | int print_progress=1; | ||
44 | amb | 2 | |
45 | amb | 31 | |
46 | amb | 2 | /* Functions */ |
47 | |||
48 | amb | 45 | static void insert_in_queue(Results *results,Result *result); |
49 | amb | 2 | |
50 | |||
51 | /*++++++++++++++++++++++++++++++++++++++ | ||
52 | Find the optimum route between two nodes. | ||
53 | |||
54 | amb | 26 | Results *FindRoute Returns a set of results. |
55 | |||
56 | Nodes *nodes The set of nodes to use. | ||
57 | |||
58 | Segments *segments The set of segments to use. | ||
59 | |||
60 | amb | 2 | node_t start The start node. |
61 | |||
62 | node_t finish The finish node. | ||
63 | ++++++++++++++++++++++++++++++++++++++*/ | ||
64 | |||
65 | amb | 31 | Results *FindRoute(Nodes *nodes,Segments *segments,node_t start,node_t finish) |
66 | amb | 2 | { |
67 | amb | 31 | Results *results; |
68 | amb | 43 | node_t node1,node2; |
69 | amb | 10 | HalfResult shortest1,quickest1; |
70 | HalfResult shortest2,quickest2; | ||
71 | HalfResult shortestfinish,quickestfinish; | ||
72 | amb | 2 | Result *result1,*result2; |
73 | Segment *segment; | ||
74 | int nresults=0; | ||
75 | |||
76 | amb | 10 | /* Set up the finish conditions */ |
77 | |||
78 | amb | 36 | shortestfinish.distance=INVALID_DISTANCE; |
79 | shortestfinish.duration=INVALID_DURATION; | ||
80 | quickestfinish.distance=INVALID_DISTANCE; | ||
81 | quickestfinish.duration=INVALID_DURATION; | ||
82 | amb | 10 | |
83 | amb | 2 | /* Insert the first node into the queue */ |
84 | |||
85 | amb | 31 | results=NewResultsList(); |
86 | amb | 2 | |
87 | amb | 31 | result1=InsertResult(results,start); |
88 | amb | 28 | |
89 | amb | 2 | result1->node=start; |
90 | amb | 43 | result1->shortest.prev=0; |
91 | result1->shortest.next=0; | ||
92 | amb | 10 | result1->shortest.distance=0; |
93 | result1->shortest.duration=0; | ||
94 | amb | 43 | result1->quickest.prev=0; |
95 | result1->quickest.next=0; | ||
96 | amb | 10 | result1->quickest.distance=0; |
97 | result1->quickest.duration=0; | ||
98 | amb | 2 | |
99 | amb | 45 | insert_in_queue(results,result1); |
100 | amb | 2 | |
101 | /* Loop across all nodes in the queue */ | ||
102 | |||
103 | amb | 45 | while(OSMQueue.number>0) |
104 | amb | 2 | { |
105 | amb | 45 | result1=LookupResult(results,OSMQueue.queue[--OSMQueue.number]); |
106 | amb | 43 | node1=result1->node; |
107 | amb | 10 | shortest1.distance=result1->shortest.distance; |
108 | shortest1.duration=result1->shortest.duration; | ||
109 | quickest1.distance=result1->quickest.distance; | ||
110 | quickest1.duration=result1->quickest.duration; | ||
111 | amb | 2 | |
112 | amb | 43 | segment=FindFirstSegment(segments,node1); |
113 | amb | 2 | |
114 | while(segment) | ||
115 | { | ||
116 | node2=segment->node2; | ||
117 | |||
118 | amb | 36 | if(segment->distance==INVALID_SHORT_DISTANCE || |
119 | segment->duration==INVALID_SHORT_DURATION) | ||
120 | amb | 31 | goto endloop; |
121 | |||
122 | amb | 10 | shortest2.distance=shortest1.distance+segment->distance; |
123 | shortest2.duration=shortest1.duration+segment->duration; | ||
124 | quickest2.distance=quickest1.distance+segment->distance; | ||
125 | quickest2.duration=quickest1.duration+segment->duration; | ||
126 | amb | 2 | |
127 | amb | 10 | if(shortest2.distance>shortestfinish.distance && quickest2.duration>quickestfinish.duration) |
128 | amb | 2 | goto endloop; |
129 | |||
130 | amb | 42 | result2=FindResult(results,node2); |
131 | |||
132 | amb | 2 | if(!result2) /* New end node */ |
133 | { | ||
134 | amb | 31 | result2=InsertResult(results,node2); |
135 | amb | 2 | result2->node=node2; |
136 | amb | 43 | result2->shortest.prev=node1; |
137 | result2->shortest.next=0; | ||
138 | amb | 10 | result2->shortest.distance=shortest2.distance; |
139 | result2->shortest.duration=shortest2.duration; | ||
140 | amb | 43 | result2->quickest.prev=node1; |
141 | result2->quickest.next=0; | ||
142 | amb | 10 | result2->quickest.distance=quickest2.distance; |
143 | result2->quickest.duration=quickest2.duration; | ||
144 | amb | 2 | |
145 | nresults++; | ||
146 | |||
147 | if(node2==finish) | ||
148 | { | ||
149 | amb | 10 | shortestfinish.distance=shortest2.distance; |
150 | shortestfinish.duration=shortest2.duration; | ||
151 | quickestfinish.distance=quickest2.distance; | ||
152 | quickestfinish.duration=quickest2.duration; | ||
153 | amb | 2 | } |
154 | else | ||
155 | amb | 45 | insert_in_queue(results,result2); |
156 | amb | 2 | } |
157 | else | ||
158 | { | ||
159 | amb | 10 | if(shortest2.distance<result2->shortest.distance || |
160 | (shortest2.distance==result2->shortest.distance && | ||
161 | shortest2.duration<result2->shortest.duration)) /* New end node is shorter */ | ||
162 | amb | 2 | { |
163 | amb | 43 | result2->shortest.prev=node1; |
164 | amb | 10 | result2->shortest.distance=shortest2.distance; |
165 | result2->shortest.duration=shortest2.duration; | ||
166 | amb | 2 | |
167 | if(node2==finish) | ||
168 | { | ||
169 | amb | 10 | shortestfinish.distance=shortest2.distance; |
170 | shortestfinish.duration=shortest2.duration; | ||
171 | amb | 2 | } |
172 | else | ||
173 | amb | 45 | insert_in_queue(results,result2); |
174 | amb | 2 | } |
175 | |||
176 | amb | 10 | if(quickest2.duration<result2->quickest.duration || |
177 | (quickest2.duration==result2->quickest.duration && | ||
178 | quickest2.distance<result2->quickest.distance)) /* New end node is quicker */ | ||
179 | amb | 2 | { |
180 | amb | 43 | result2->quickest.prev=node1; |
181 | amb | 10 | result2->quickest.distance=quickest2.distance; |
182 | result2->quickest.duration=quickest2.duration; | ||
183 | amb | 2 | |
184 | if(node2==finish) | ||
185 | { | ||
186 | amb | 10 | quickestfinish.distance=quickest2.distance; |
187 | quickestfinish.duration=quickest2.duration; | ||
188 | amb | 2 | } |
189 | else | ||
190 | amb | 45 | insert_in_queue(results,result2); |
191 | amb | 2 | } |
192 | } | ||
193 | |||
194 | endloop: | ||
195 | |||
196 | amb | 26 | segment=FindNextSegment(segments,segment); |
197 | amb | 2 | } |
198 | |||
199 | amb | 31 | if(print_progress && !(nresults%1000)) |
200 | amb | 2 | { |
201 | amb | 45 | printf("\rRouting: End Nodes=%d Queue=%d Journey=%.1fkm,%.0fmin ",nresults,OSMQueue.number, |
202 | amb | 10 | distance_to_km(shortest2.distance),duration_to_minutes(quickest2.duration)); |
203 | amb | 2 | fflush(stdout); |
204 | } | ||
205 | } | ||
206 | |||
207 | amb | 31 | if(print_progress) |
208 | { | ||
209 | printf("\rRouted: End Nodes=%d Shortest=%.1fkm,%.0fmin Quickest=%.1fkm,%.0fmin\n",nresults, | ||
210 | distance_to_km(shortestfinish.distance),duration_to_minutes(shortestfinish.duration), | ||
211 | distance_to_km(quickestfinish.distance),duration_to_minutes(quickestfinish.duration)); | ||
212 | fflush(stdout); | ||
213 | } | ||
214 | |||
215 | /* Reverse the results */ | ||
216 | |||
217 | result2=FindResult(results,finish); | ||
218 | |||
219 | do | ||
220 | { | ||
221 | amb | 43 | if(result2->shortest.prev) |
222 | amb | 31 | { |
223 | amb | 43 | node_t node1=result2->shortest.prev; |
224 | amb | 31 | |
225 | result1=FindResult(results,node1); | ||
226 | |||
227 | amb | 43 | result1->shortest.next=result2->node; |
228 | amb | 31 | |
229 | result2=result1; | ||
230 | } | ||
231 | else | ||
232 | result2=NULL; | ||
233 | } | ||
234 | while(result2); | ||
235 | |||
236 | result2=FindResult(results,finish); | ||
237 | |||
238 | do | ||
239 | { | ||
240 | amb | 43 | if(result2->quickest.prev) |
241 | amb | 31 | { |
242 | amb | 43 | node_t node1=result2->quickest.prev; |
243 | amb | 31 | |
244 | result1=FindResult(results,node1); | ||
245 | |||
246 | amb | 43 | result1->quickest.next=result2->node; |
247 | amb | 31 | |
248 | result2=result1; | ||
249 | } | ||
250 | else | ||
251 | result2=NULL; | ||
252 | } | ||
253 | while(result2); | ||
254 | |||
255 | return(results); | ||
256 | amb | 2 | } |
257 | |||
258 | |||
259 | /*++++++++++++++++++++++++++++++++++++++ | ||
260 | amb | 34 | Find the optimum route between two nodes. |
261 | |||
262 | Results *FindRoute3 Returns a set of results. | ||
263 | |||
264 | Nodes *nodes The set of nodes to use. | ||
265 | |||
266 | Segments *segments The set of segments to use. | ||
267 | |||
268 | node_t start The start node. | ||
269 | |||
270 | node_t finish The finish node. | ||
271 | |||
272 | Results *begin The initial portion of the route. | ||
273 | |||
274 | Results *end The final portion of the route. | ||
275 | ++++++++++++++++++++++++++++++++++++++*/ | ||
276 | |||
277 | Results *FindRoute3(Nodes *nodes,Segments *segments,node_t start,node_t finish,Results *begin,Results *end) | ||
278 | { | ||
279 | Results *results; | ||
280 | amb | 43 | node_t node1,node2; |
281 | amb | 34 | HalfResult shortest1,quickest1; |
282 | HalfResult shortest2,quickest2; | ||
283 | HalfResult shortestfinish,quickestfinish; | ||
284 | Result *result1,*result2,*result3; | ||
285 | Segment *segment; | ||
286 | int nresults=0; | ||
287 | amb | 45 | int j; |
288 | amb | 34 | |
289 | /* Set up the finish conditions */ | ||
290 | |||
291 | amb | 36 | shortestfinish.distance=INVALID_DISTANCE; |
292 | shortestfinish.duration=INVALID_DURATION; | ||
293 | quickestfinish.distance=INVALID_DISTANCE; | ||
294 | quickestfinish.duration=INVALID_DURATION; | ||
295 | amb | 34 | |
296 | amb | 47 | /* Insert the start nodes */ |
297 | amb | 34 | |
298 | results=NewResultsList(); | ||
299 | |||
300 | result1=InsertResult(results,start); | ||
301 | result2=FindResult(begin,start); | ||
302 | |||
303 | *result1=*result2; | ||
304 | |||
305 | /* Insert the finish points of the beginning part of the path into the queue */ | ||
306 | |||
307 | amb | 45 | for(j=0;j<begin->number;j++) |
308 | if(FindNode(nodes,begin->results[j].node)) | ||
309 | { | ||
310 | if(!(result1=FindResult(results,begin->results[j].node))) | ||
311 | amb | 34 | { |
312 | amb | 45 | result1=InsertResult(results,begin->results[j].node); |
313 | amb | 34 | |
314 | amb | 45 | *result1=begin->results[j]; |
315 | amb | 34 | |
316 | amb | 45 | result1->shortest.prev=start; |
317 | result1->quickest.prev=start; | ||
318 | amb | 47 | } |
319 | amb | 34 | |
320 | amb | 47 | insert_in_queue(results,result1); |
321 | amb | 45 | } |
322 | amb | 34 | |
323 | /* Loop across all nodes in the queue */ | ||
324 | |||
325 | amb | 45 | while(OSMQueue.number>0) |
326 | amb | 34 | { |
327 | amb | 45 | result1=LookupResult(results,OSMQueue.queue[--OSMQueue.number]); |
328 | amb | 43 | node1=result1->node; |
329 | amb | 34 | shortest1.distance=result1->shortest.distance; |
330 | shortest1.duration=result1->shortest.duration; | ||
331 | quickest1.distance=result1->quickest.distance; | ||
332 | quickest1.duration=result1->quickest.duration; | ||
333 | |||
334 | amb | 43 | segment=FindFirstSegment(segments,node1); |
335 | amb | 34 | |
336 | while(segment) | ||
337 | { | ||
338 | node2=segment->node2; | ||
339 | |||
340 | amb | 36 | if(segment->distance==INVALID_SHORT_DISTANCE || |
341 | segment->duration==INVALID_SHORT_DURATION) | ||
342 | amb | 34 | goto endloop; |
343 | |||
344 | shortest2.distance=shortest1.distance+segment->distance; | ||
345 | shortest2.duration=shortest1.duration+segment->duration; | ||
346 | quickest2.distance=quickest1.distance+segment->distance; | ||
347 | quickest2.duration=quickest1.duration+segment->duration; | ||
348 | |||
349 | if(shortest2.distance>shortestfinish.distance && quickest2.duration>quickestfinish.duration) | ||
350 | goto endloop; | ||
351 | |||
352 | amb | 42 | result2=FindResult(results,node2); |
353 | |||
354 | amb | 34 | if(!result2) /* New end node */ |
355 | { | ||
356 | result2=InsertResult(results,node2); | ||
357 | result2->node=node2; | ||
358 | amb | 43 | result2->shortest.prev=node1; |
359 | result2->shortest.next=0; | ||
360 | amb | 34 | result2->shortest.distance=shortest2.distance; |
361 | result2->shortest.duration=shortest2.duration; | ||
362 | amb | 43 | result2->quickest.prev=node1; |
363 | result2->quickest.next=0; | ||
364 | amb | 34 | result2->quickest.distance=quickest2.distance; |
365 | result2->quickest.duration=quickest2.duration; | ||
366 | |||
367 | nresults++; | ||
368 | |||
369 | if((result3=FindResult(end,node2))) | ||
370 | { | ||
371 | if((shortest2.distance+result3->shortest.distance)<shortestfinish.distance || | ||
372 | ((shortest2.distance+result3->shortest.distance)==shortestfinish.distance && | ||
373 | (shortest2.duration+result3->shortest.duration)<shortestfinish.duration)) | ||
374 | { | ||
375 | shortestfinish.distance=shortest2.distance+result3->shortest.distance; | ||
376 | shortestfinish.duration=shortest2.duration+result3->shortest.duration; | ||
377 | } | ||
378 | if((quickest2.duration+result3->quickest.duration)<quickestfinish.duration || | ||
379 | ((quickest2.duration+result3->quickest.duration)==quickestfinish.duration && | ||
380 | (quickest2.distance+result3->quickest.distance)<quickestfinish.distance)) | ||
381 | { | ||
382 | quickestfinish.distance=quickest2.distance+result3->quickest.distance; | ||
383 | quickestfinish.duration=quickest2.duration+result3->quickest.duration; | ||
384 | } | ||
385 | } | ||
386 | else | ||
387 | amb | 45 | insert_in_queue(results,result2); |
388 | amb | 34 | } |
389 | else | ||
390 | { | ||
391 | if(shortest2.distance<result2->shortest.distance || | ||
392 | (shortest2.distance==result2->shortest.distance && | ||
393 | shortest2.duration<result2->shortest.duration)) /* New end node is shorter */ | ||
394 | { | ||
395 | amb | 43 | result2->shortest.prev=node1; |
396 | amb | 34 | result2->shortest.distance=shortest2.distance; |
397 | result2->shortest.duration=shortest2.duration; | ||
398 | |||
399 | if((result3=FindResult(end,node2))) | ||
400 | { | ||
401 | if((shortest2.distance+result3->shortest.distance)<shortestfinish.distance || | ||
402 | ((shortest2.distance+result3->shortest.distance)==shortestfinish.distance && | ||
403 | (shortest2.duration+result3->shortest.duration)<shortestfinish.duration)) | ||
404 | { | ||
405 | shortestfinish.distance=shortest2.distance+result3->shortest.distance; | ||
406 | shortestfinish.duration=shortest2.duration+result3->shortest.duration; | ||
407 | } | ||
408 | if((quickest2.duration+result3->quickest.duration)<quickestfinish.duration || | ||
409 | ((quickest2.duration+result3->quickest.duration)==quickestfinish.duration && | ||
410 | (quickest2.distance+result3->quickest.distance)<quickestfinish.distance)) | ||
411 | { | ||
412 | quickestfinish.distance=quickest2.distance+result3->quickest.distance; | ||
413 | quickestfinish.duration=quickest2.duration+result3->quickest.duration; | ||
414 | } | ||
415 | } | ||
416 | else | ||
417 | amb | 45 | insert_in_queue(results,result2); |
418 | amb | 34 | } |
419 | |||
420 | if(quickest2.duration<result2->quickest.duration || | ||
421 | (quickest2.duration==result2->quickest.duration && | ||
422 | quickest2.distance<result2->quickest.distance)) /* New end node is quicker */ | ||
423 | { | ||
424 | amb | 43 | result2->quickest.prev=node1; |
425 | amb | 34 | result2->quickest.distance=quickest2.distance; |
426 | result2->quickest.duration=quickest2.duration; | ||
427 | |||
428 | if((result3=FindResult(end,node2))) | ||
429 | { | ||
430 | if((shortest2.distance+result3->shortest.distance)<shortestfinish.distance || | ||
431 | ((shortest2.distance+result3->shortest.distance)==shortestfinish.distance && | ||
432 | (shortest2.duration+result3->shortest.duration)<shortestfinish.duration)) | ||
433 | { | ||
434 | shortestfinish.distance=shortest2.distance+result3->shortest.distance; | ||
435 | shortestfinish.duration=shortest2.duration+result3->shortest.duration; | ||
436 | } | ||
437 | if((quickest2.duration+result3->quickest.duration)<quickestfinish.duration || | ||
438 | ((quickest2.duration+result3->quickest.duration)==quickestfinish.duration && | ||
439 | (quickest2.distance+result3->quickest.distance)<quickestfinish.distance)) | ||
440 | { | ||
441 | quickestfinish.distance=quickest2.distance+result3->quickest.distance; | ||
442 | quickestfinish.duration=quickest2.duration+result3->quickest.duration; | ||
443 | } | ||
444 | } | ||
445 | else | ||
446 | amb | 45 | insert_in_queue(results,result2); |
447 | amb | 34 | } |
448 | } | ||
449 | |||
450 | endloop: | ||
451 | |||
452 | segment=FindNextSegment(segments,segment); | ||
453 | } | ||
454 | |||
455 | if(print_progress && !(nresults%1000)) | ||
456 | { | ||
457 | amb | 45 | printf("\rRouting: End Nodes=%d Queue=%d Journey=%.1fkm,%.0fmin ",nresults,OSMQueue.number, |
458 | amb | 34 | distance_to_km(shortest2.distance),duration_to_minutes(quickest2.duration)); |
459 | fflush(stdout); | ||
460 | } | ||
461 | } | ||
462 | |||
463 | if(print_progress) | ||
464 | { | ||
465 | printf("\rRouted: End Nodes=%d Shortest=%.1fkm,%.0fmin Quickest=%.1fkm,%.0fmin\n",nresults, | ||
466 | distance_to_km(shortestfinish.distance),duration_to_minutes(shortestfinish.duration), | ||
467 | distance_to_km(quickestfinish.distance),duration_to_minutes(quickestfinish.duration)); | ||
468 | fflush(stdout); | ||
469 | } | ||
470 | |||
471 | /* Finish off the end part of the route. */ | ||
472 | |||
473 | amb | 47 | if(!(result2=FindResult(results,finish))) |
474 | { | ||
475 | result1=InsertResult(results,finish); | ||
476 | result2=FindResult(end,finish); | ||
477 | amb | 34 | |
478 | amb | 47 | *result1=*result2; |
479 | |||
480 | for(j=0;j<end->number;j++) | ||
481 | if(FindNode(nodes,end->results[j].node)) | ||
482 | if((result1=FindResult(results,end->results[j].node))) | ||
483 | amb | 34 | { |
484 | amb | 47 | if((result1->shortest.distance+end->results[j].shortest.distance)<result2->shortest.distance || |
485 | ((result1->shortest.distance+end->results[j].shortest.distance)==result2->shortest.distance && | ||
486 | (result1->shortest.duration+end->results[j].shortest.duration)<result2->shortest.duration)) | ||
487 | { | ||
488 | result2->shortest.distance=result1->shortest.distance+end->results[j].shortest.distance; | ||
489 | result2->shortest.duration=result1->shortest.duration+end->results[j].shortest.duration; | ||
490 | result2->shortest.prev=result1->node; | ||
491 | } | ||
492 | if((result1->quickest.duration+end->results[j].quickest.duration)<result2->quickest.duration || | ||
493 | ((result1->quickest.duration+end->results[j].quickest.duration)==result2->quickest.duration && | ||
494 | (result1->quickest.distance+end->results[j].quickest.distance)<result2->quickest.distance)) | ||
495 | { | ||
496 | result2->quickest.distance=result1->quickest.distance+end->results[j].quickest.distance; | ||
497 | result2->quickest.duration=result1->quickest.duration+end->results[j].quickest.duration; | ||
498 | result2->quickest.prev=result1->node; | ||
499 | } | ||
500 | amb | 34 | } |
501 | amb | 47 | } |
502 | amb | 34 | |
503 | /* Reverse the results */ | ||
504 | |||
505 | result2=FindResult(results,finish); | ||
506 | |||
507 | do | ||
508 | { | ||
509 | amb | 43 | if(result2->shortest.prev) |
510 | amb | 34 | { |
511 | amb | 43 | node_t node1=result2->shortest.prev; |
512 | amb | 34 | |
513 | result1=FindResult(results,node1); | ||
514 | |||
515 | amb | 43 | result1->shortest.next=result2->node; |
516 | amb | 34 | |
517 | result2=result1; | ||
518 | } | ||
519 | else | ||
520 | result2=NULL; | ||
521 | } | ||
522 | while(result2); | ||
523 | |||
524 | result2=FindResult(results,finish); | ||
525 | |||
526 | do | ||
527 | { | ||
528 | amb | 43 | if(result2->quickest.prev) |
529 | amb | 34 | { |
530 | amb | 43 | node_t node1=result2->quickest.prev; |
531 | amb | 34 | |
532 | result1=FindResult(results,node1); | ||
533 | |||
534 | amb | 43 | result1->quickest.next=result2->node; |
535 | amb | 34 | |
536 | result2=result1; | ||
537 | } | ||
538 | else | ||
539 | result2=NULL; | ||
540 | } | ||
541 | while(result2); | ||
542 | |||
543 | return(results); | ||
544 | } | ||
545 | |||
546 | |||
547 | /*++++++++++++++++++++++++++++++++++++++ | ||
548 | amb | 2 | Print the optimum route between two nodes. |
549 | |||
550 | amb | 31 | Results *Results The set of results to print. |
551 | |||
552 | Nodes *nodes The list of nodes. | ||
553 | |||
554 | amb | 26 | Segments *segments The set of segments to use. |
555 | |||
556 | Ways *ways The list of ways. | ||
557 | |||
558 | amb | 2 | node_t start The start node. |
559 | |||
560 | node_t finish The finish node. | ||
561 | ++++++++++++++++++++++++++++++++++++++*/ | ||
562 | |||
563 | amb | 31 | void PrintRoute(Results *results,Nodes *nodes,Segments *segments,Ways *ways,node_t start,node_t finish) |
564 | amb | 2 | { |
565 | FILE *file; | ||
566 | Result *result; | ||
567 | |||
568 | /* Print the result for the shortest route */ | ||
569 | |||
570 | file=fopen("shortest.txt","w"); | ||
571 | |||
572 | amb | 31 | result=FindResult(results,start); |
573 | amb | 2 | |
574 | do | ||
575 | { | ||
576 | amb | 43 | Node *node=FindNode(nodes,result->node); |
577 | |||
578 | if(result->shortest.prev) | ||
579 | amb | 2 | { |
580 | amb | 6 | Segment *segment; |
581 | Way *way; | ||
582 | amb | 2 | |
583 | amb | 43 | segment=FindFirstSegment(segments,result->shortest.prev); |
584 | amb | 34 | while(segment->node2!=result->node) |
585 | amb | 26 | segment=FindNextSegment(segments,segment); |
586 | amb | 2 | |
587 | amb | 26 | way=FindWay(ways,segment->way); |
588 | amb | 6 | |
589 | amb | 43 | fprintf(file,"%9.5f %9.5f %5.3f %5.2f %6.1f %5.1f %3d %s\n",node->latitude,node->longitude, |
590 | amb | 5 | distance_to_km(segment->distance),duration_to_minutes(segment->duration), |
591 | amb | 34 | distance_to_km(result->shortest.distance),duration_to_minutes(result->shortest.duration), |
592 | amb | 31 | (way->limit?way->limit:way->speed),WayName(ways,way)); |
593 | amb | 34 | } |
594 | else | ||
595 | amb | 43 | fprintf(file,"%9.5f %9.5f %5.3f %5.2f %6.1f %5.1f\n",node->latitude,node->longitude, |
596 | amb | 34 | 0.0,0.0,0.0,0.0); |
597 | amb | 2 | |
598 | amb | 43 | if(result->shortest.next) |
599 | result=FindResult(results,result->shortest.next); | ||
600 | amb | 2 | else |
601 | result=NULL; | ||
602 | } | ||
603 | while(result); | ||
604 | |||
605 | fclose(file); | ||
606 | |||
607 | /* Print the result for the quickest route */ | ||
608 | |||
609 | file=fopen("quickest.txt","w"); | ||
610 | |||
611 | amb | 31 | result=FindResult(results,start); |
612 | amb | 2 | |
613 | do | ||
614 | { | ||
615 | amb | 43 | Node *node=FindNode(nodes,result->node); |
616 | |||
617 | if(result->quickest.prev) | ||
618 | amb | 2 | { |
619 | amb | 6 | Segment *segment; |
620 | Way *way; | ||
621 | amb | 2 | |
622 | amb | 43 | segment=FindFirstSegment(segments,result->quickest.prev); |
623 | amb | 34 | while(segment->node2!=result->node) |
624 | amb | 26 | segment=FindNextSegment(segments,segment); |
625 | amb | 2 | |
626 | amb | 26 | way=FindWay(ways,segment->way); |
627 | amb | 6 | |
628 | amb | 43 | fprintf(file,"%9.5f %9.5f %5.3f %5.2f %6.1f %5.1f %3d %s\n",node->latitude,node->longitude, |
629 | amb | 5 | distance_to_km(segment->distance),duration_to_minutes(segment->duration), |
630 | amb | 34 | distance_to_km(result->quickest.distance),duration_to_minutes(result->quickest.duration), |
631 | amb | 31 | (way->limit?way->limit:way->speed),WayName(ways,way)); |
632 | amb | 34 | } |
633 | else | ||
634 | amb | 43 | fprintf(file,"%9.5f %9.5f %5.3f %5.2f %6.1f %5.1f\n",node->latitude,node->longitude, |
635 | amb | 34 | 0.0,0.0,0.0,0.0); |
636 | amb | 2 | |
637 | amb | 43 | if(result->quickest.next) |
638 | result=FindResult(results,result->quickest.next); | ||
639 | amb | 2 | else |
640 | result=NULL; | ||
641 | } | ||
642 | while(result); | ||
643 | |||
644 | amb | 31 | fclose(file); |
645 | } | ||
646 | amb | 3 | |
647 | |||
648 | amb | 31 | /*++++++++++++++++++++++++++++++++++++++ |
649 | Find all routes from a specified node to any node in the specified list. | ||
650 | amb | 3 | |
651 | amb | 31 | Results *FindRoute2 Returns a set of results. |
652 | |||
653 | Nodes *nodes The set of nodes to use. | ||
654 | |||
655 | Segments *segments The set of segments to use. | ||
656 | |||
657 | node_t start The start node. | ||
658 | |||
659 | Nodes *finish The finishing nodes. | ||
660 | ++++++++++++++++++++++++++++++++++++++*/ | ||
661 | |||
662 | Results *FindRoutes(Nodes *nodes,Segments *segments,node_t start,Nodes *finish) | ||
663 | { | ||
664 | Results *results; | ||
665 | amb | 43 | node_t node1,node2; |
666 | amb | 31 | HalfResult shortest1,quickest1; |
667 | HalfResult shortest2,quickest2; | ||
668 | Result *result1,*result2; | ||
669 | Segment *segment; | ||
670 | int nresults=0; | ||
671 | |||
672 | /* Insert the first node into the queue */ | ||
673 | |||
674 | results=NewResultsList(); | ||
675 | |||
676 | result1=InsertResult(results,start); | ||
677 | |||
678 | result1->node=start; | ||
679 | amb | 43 | result1->shortest.prev=0; |
680 | result1->shortest.next=0; | ||
681 | amb | 31 | result1->shortest.distance=0; |
682 | result1->shortest.duration=0; | ||
683 | amb | 43 | result1->quickest.prev=0; |
684 | result1->quickest.next=0; | ||
685 | amb | 31 | result1->quickest.distance=0; |
686 | result1->quickest.duration=0; | ||
687 | |||
688 | amb | 45 | insert_in_queue(results,result1); |
689 | amb | 31 | |
690 | /* Loop across all nodes in the queue */ | ||
691 | |||
692 | amb | 45 | while(OSMQueue.number>0) |
693 | amb | 31 | { |
694 | amb | 45 | result1=LookupResult(results,OSMQueue.queue[--OSMQueue.number]); |
695 | amb | 43 | node1=result1->node; |
696 | amb | 31 | shortest1.distance=result1->shortest.distance; |
697 | shortest1.duration=result1->shortest.duration; | ||
698 | quickest1.distance=result1->quickest.distance; | ||
699 | quickest1.duration=result1->quickest.duration; | ||
700 | |||
701 | amb | 43 | segment=FindFirstSegment(segments,node1); |
702 | amb | 31 | |
703 | while(segment) | ||
704 | { | ||
705 | node2=segment->node2; | ||
706 | |||
707 | amb | 36 | if(segment->distance==INVALID_SHORT_DISTANCE || |
708 | segment->duration==INVALID_SHORT_DURATION) | ||
709 | amb | 31 | goto endloop; |
710 | |||
711 | shortest2.distance=shortest1.distance+segment->distance; | ||
712 | shortest2.duration=shortest1.duration+segment->duration; | ||
713 | quickest2.distance=quickest1.distance+segment->distance; | ||
714 | quickest2.duration=quickest1.duration+segment->duration; | ||
715 | |||
716 | result2=FindResult(results,node2); | ||
717 | |||
718 | if(!result2) /* New end node */ | ||
719 | { | ||
720 | result2=InsertResult(results,node2); | ||
721 | result2->node=node2; | ||
722 | amb | 43 | result2->shortest.prev=node1; |
723 | result2->shortest.next=0; | ||
724 | amb | 31 | result2->shortest.distance=shortest2.distance; |
725 | result2->shortest.duration=shortest2.duration; | ||
726 | amb | 43 | result2->quickest.prev=node1; |
727 | result2->quickest.next=0; | ||
728 | amb | 31 | result2->quickest.distance=quickest2.distance; |
729 | result2->quickest.duration=quickest2.duration; | ||
730 | |||
731 | nresults++; | ||
732 | |||
733 | if(!FindNode(finish,node2)) | ||
734 | amb | 45 | insert_in_queue(results,result2); |
735 | amb | 31 | } |
736 | else | ||
737 | { | ||
738 | if(shortest2.distance<result2->shortest.distance || | ||
739 | (shortest2.distance==result2->shortest.distance && | ||
740 | shortest2.duration<result2->shortest.duration)) /* New end node is shorter */ | ||
741 | { | ||
742 | amb | 43 | result2->shortest.prev=node1; |
743 | amb | 31 | result2->shortest.distance=shortest2.distance; |
744 | result2->shortest.duration=shortest2.duration; | ||
745 | |||
746 | if(!FindNode(finish,node2)) | ||
747 | amb | 45 | insert_in_queue(results,result2); |
748 | amb | 31 | } |
749 | |||
750 | if(quickest2.duration<result2->quickest.duration || | ||
751 | (quickest2.duration==result2->quickest.duration && | ||
752 | quickest2.distance<result2->quickest.distance)) /* New end node is quicker */ | ||
753 | { | ||
754 | amb | 43 | result2->quickest.prev=node1; |
755 | amb | 31 | result2->quickest.distance=quickest2.distance; |
756 | result2->quickest.duration=quickest2.duration; | ||
757 | |||
758 | if(!FindNode(finish,node2)) | ||
759 | amb | 45 | insert_in_queue(results,result2); |
760 | amb | 31 | } |
761 | } | ||
762 | |||
763 | endloop: | ||
764 | |||
765 | segment=FindNextSegment(segments,segment); | ||
766 | } | ||
767 | } | ||
768 | |||
769 | return(results); | ||
770 | amb | 2 | } |
771 | |||
772 | |||
773 | /*++++++++++++++++++++++++++++++++++++++ | ||
774 | amb | 47 | Find all routes from any node in the specified list to a specific node. |
775 | amb | 34 | |
776 | amb | 47 | Results *FindReverseRoute Returns a set of results. |
777 | amb | 34 | |
778 | Nodes *nodes The set of nodes to use. | ||
779 | |||
780 | Segments *segments The set of segments to use. | ||
781 | |||
782 | Nodes *start The starting nodes. | ||
783 | |||
784 | node_t finish The finishing node. | ||
785 | ++++++++++++++++++++++++++++++++++++++*/ | ||
786 | |||
787 | Results *FindReverseRoutes(Nodes *nodes,Segments *segments,Nodes *start,node_t finish) | ||
788 | { | ||
789 | Results *results; | ||
790 | amb | 43 | node_t node1,node2; |
791 | amb | 34 | HalfResult shortest1,quickest1; |
792 | HalfResult shortest2,quickest2; | ||
793 | Result *result1,*result2; | ||
794 | Segment *segment; | ||
795 | int nresults=0; | ||
796 | |||
797 | /* Insert the first node into the queue */ | ||
798 | |||
799 | results=NewResultsList(); | ||
800 | |||
801 | result1=InsertResult(results,finish); | ||
802 | |||
803 | result1->node=finish; | ||
804 | amb | 43 | result1->shortest.prev=0; |
805 | result1->shortest.next=0; | ||
806 | amb | 34 | result1->shortest.distance=0; |
807 | result1->shortest.duration=0; | ||
808 | amb | 43 | result1->quickest.prev=0; |
809 | result1->quickest.next=0; | ||
810 | amb | 34 | result1->quickest.distance=0; |
811 | result1->quickest.duration=0; | ||
812 | |||
813 | amb | 45 | insert_in_queue(results,result1); |
814 | amb | 34 | |
815 | /* Loop across all nodes in the queue */ | ||
816 | |||
817 | amb | 45 | while(OSMQueue.number>0) |
818 | amb | 34 | { |
819 | amb | 45 | result1=LookupResult(results,OSMQueue.queue[--OSMQueue.number]); |
820 | amb | 43 | node1=result1->node; |
821 | amb | 34 | shortest1.distance=result1->shortest.distance; |
822 | shortest1.duration=result1->shortest.duration; | ||
823 | quickest1.distance=result1->quickest.distance; | ||
824 | quickest1.duration=result1->quickest.duration; | ||
825 | |||
826 | amb | 43 | segment=FindFirstSegment(segments,node1); |
827 | amb | 34 | |
828 | while(segment) | ||
829 | { | ||
830 | /* Reverse the segment and check it exists */ | ||
831 | |||
832 | node_t reversenode; | ||
833 | Segment *reversesegment; | ||
834 | |||
835 | reversenode=segment->node2; | ||
836 | reversesegment=FindFirstSegment(segments,reversenode); | ||
837 | |||
838 | amb | 43 | while(reversesegment && reversesegment->node2!=node1) |
839 | amb | 34 | reversesegment=FindNextSegment(segments,reversesegment); |
840 | |||
841 | if(!reversesegment) | ||
842 | goto endloop; | ||
843 | |||
844 | node2=reversesegment->node1; | ||
845 | |||
846 | amb | 36 | if(reversesegment->distance==INVALID_SHORT_DISTANCE || |
847 | reversesegment->duration==INVALID_SHORT_DURATION) | ||
848 | amb | 34 | goto endloop; |
849 | |||
850 | shortest2.distance=shortest1.distance+reversesegment->distance; | ||
851 | shortest2.duration=shortest1.duration+reversesegment->duration; | ||
852 | quickest2.distance=quickest1.distance+reversesegment->distance; | ||
853 | quickest2.duration=quickest1.duration+reversesegment->duration; | ||
854 | |||
855 | result2=FindResult(results,node2); | ||
856 | |||
857 | if(!result2) /* New end node */ | ||
858 | { | ||
859 | result2=InsertResult(results,node2); | ||
860 | result2->node=node2; | ||
861 | amb | 43 | result2->shortest.prev=0; |
862 | result2->shortest.next=node1; | ||
863 | amb | 34 | result2->shortest.distance=shortest2.distance; |
864 | result2->shortest.duration=shortest2.duration; | ||
865 | amb | 43 | result2->quickest.prev=0; |
866 | result2->quickest.next=node1; | ||
867 | amb | 34 | result2->quickest.distance=quickest2.distance; |
868 | result2->quickest.duration=quickest2.duration; | ||
869 | |||
870 | nresults++; | ||
871 | |||
872 | if(!FindNode(start,node2)) | ||
873 | amb | 45 | insert_in_queue(results,result2); |
874 | amb | 34 | } |
875 | else | ||
876 | { | ||
877 | if(shortest2.distance<result2->shortest.distance || | ||
878 | (shortest2.distance==result2->shortest.distance && | ||
879 | shortest2.duration<result2->shortest.duration)) /* New end node is shorter */ | ||
880 | { | ||
881 | amb | 43 | result2->shortest.next=node1; |
882 | amb | 34 | result2->shortest.distance=shortest2.distance; |
883 | result2->shortest.duration=shortest2.duration; | ||
884 | |||
885 | if(!FindNode(start,node2)) | ||
886 | amb | 45 | insert_in_queue(results,result2); |
887 | amb | 34 | } |
888 | |||
889 | if(quickest2.duration<result2->quickest.duration || | ||
890 | (quickest2.duration==result2->quickest.duration && | ||
891 | quickest2.distance<result2->quickest.distance)) /* New end node is quicker */ | ||
892 | { | ||
893 | amb | 43 | result2->quickest.next=node1; |
894 | amb | 34 | result2->quickest.distance=quickest2.distance; |
895 | result2->quickest.duration=quickest2.duration; | ||
896 | |||
897 | if(!FindNode(start,node2)) | ||
898 | amb | 45 | insert_in_queue(results,result2); |
899 | amb | 34 | } |
900 | } | ||
901 | |||
902 | endloop: | ||
903 | |||
904 | segment=FindNextSegment(segments,segment); | ||
905 | } | ||
906 | } | ||
907 | |||
908 | return(results); | ||
909 | } | ||
910 | |||
911 | |||
912 | /*++++++++++++++++++++++++++++++++++++++ | ||
913 | amb | 31 | Print the optimum route between two nodes. |
914 | |||
915 | amb | 34 | Results *results The set of results. |
916 | amb | 31 | |
917 | Nodes *nodes The list of nodes. | ||
918 | |||
919 | Segments *segments The set of segments to use. | ||
920 | |||
921 | Ways *ways The list of ways. | ||
922 | |||
923 | amb | 33 | Nodes *supernodes The list of supernodes. |
924 | amb | 31 | |
925 | Segments *supersegments The list of supersegments. | ||
926 | |||
927 | node_t start The start node. | ||
928 | |||
929 | node_t finish The finish node. | ||
930 | ++++++++++++++++++++++++++++++++++++++*/ | ||
931 | |||
932 | amb | 33 | void PrintRoutes(Results *results,Nodes *nodes,Segments *segments,Ways *ways,Nodes *supernodes,Segments *supersegments,node_t start,node_t finish) |
933 | amb | 31 | { |
934 | Result *result1,*result2,*result3,*result4; | ||
935 | Results *combined; | ||
936 | |||
937 | combined=NewResultsList(); | ||
938 | |||
939 | print_progress=0; | ||
940 | |||
941 | /* Sort out the shortest */ | ||
942 | |||
943 | result1=FindResult(results,start); | ||
944 | amb | 34 | result4=NULL; |
945 | amb | 31 | |
946 | do | ||
947 | { | ||
948 | result3=InsertResult(combined,result1->node); | ||
949 | |||
950 | result3->node=result1->node; | ||
951 | amb | 36 | |
952 | amb | 31 | result3->shortest=result1->shortest; |
953 | amb | 43 | result3->shortest.next=0; |
954 | amb | 34 | if(result4) |
955 | amb | 43 | result3->shortest.prev=result4->node; |
956 | amb | 36 | else |
957 | amb | 43 | result3->shortest.prev=0; |
958 | amb | 31 | |
959 | amb | 34 | result4=result3; |
960 | |||
961 | amb | 43 | if(result1->shortest.next) |
962 | amb | 31 | { |
963 | amb | 43 | Results *results2=FindRoute(nodes,segments,result1->node,result1->shortest.next); |
964 | amb | 31 | |
965 | result2=FindResult(results2,result1->node); | ||
966 | |||
967 | amb | 43 | result3->shortest.next=result2->shortest.next; |
968 | amb | 36 | |
969 | amb | 43 | result2=FindResult(results2,result2->shortest.next); |
970 | amb | 36 | |
971 | amb | 31 | do |
972 | { | ||
973 | amb | 43 | if(result2->shortest.prev && result2->shortest.next) |
974 | amb | 31 | { |
975 | result4=InsertResult(combined,result2->node); | ||
976 | |||
977 | result4->node=result2->node; | ||
978 | amb | 36 | |
979 | result4->shortest=result2->shortest; | ||
980 | result4->shortest.distance+=result3->shortest.distance; | ||
981 | result4->shortest.duration+=result3->shortest.duration; | ||
982 | amb | 31 | } |
983 | |||
984 | amb | 43 | if(result2->shortest.next) |
985 | result2=FindResult(results2,result2->shortest.next); | ||
986 | amb | 31 | else |
987 | result2=NULL; | ||
988 | } | ||
989 | while(result2); | ||
990 | |||
991 | FreeResultsList(results2); | ||
992 | |||
993 | amb | 43 | result1=FindResult(results,result1->shortest.next); |
994 | amb | 31 | } |
995 | else | ||
996 | result1=NULL; | ||
997 | } | ||
998 | while(result1); | ||
999 | |||
1000 | /* Sort out the quickest */ | ||
1001 | |||
1002 | result1=FindResult(results,start); | ||
1003 | amb | 34 | result4=NULL; |
1004 | amb | 31 | |
1005 | do | ||
1006 | { | ||
1007 | result3=FindResult(combined,result1->node); | ||
1008 | |||
1009 | if(!result3) | ||
1010 | amb | 34 | { |
1011 | amb | 31 | result3=InsertResult(combined,result1->node); |
1012 | |||
1013 | amb | 34 | result3->node=result1->node; |
1014 | } | ||
1015 | |||
1016 | amb | 31 | result3->quickest=result1->quickest; |
1017 | amb | 43 | result3->quickest.next=0; |
1018 | amb | 34 | if(result4) |
1019 | amb | 43 | result3->quickest.prev=result4->node; |
1020 | amb | 36 | else |
1021 | amb | 43 | result3->quickest.prev=0; |
1022 | amb | 31 | |
1023 | amb | 34 | result4=result3; |
1024 | |||
1025 | amb | 43 | if(result1->quickest.next) |
1026 | amb | 31 | { |
1027 | amb | 43 | Results *results2=FindRoute(nodes,segments,result1->node,result1->quickest.next); |
1028 | amb | 31 | |
1029 | result2=FindResult(results2,result1->node); | ||
1030 | |||
1031 | amb | 43 | result3->quickest.next=result2->quickest.next; |
1032 | amb | 36 | |
1033 | amb | 43 | result2=FindResult(results2,result2->quickest.next); |
1034 | amb | 36 | |
1035 | amb | 31 | do |
1036 | { | ||
1037 | amb | 43 | if(result2->quickest.prev && result2->quickest.next) |
1038 | amb | 31 | { |
1039 | result4=FindResult(combined,result2->node); | ||
1040 | |||
1041 | if(!result4) | ||
1042 | amb | 36 | { |
1043 | amb | 31 | result4=InsertResult(combined,result2->node); |
1044 | |||
1045 | amb | 36 | result4->node=result2->node; |
1046 | } | ||
1047 | |||
1048 | result4->quickest=result2->quickest; | ||
1049 | result4->quickest.distance+=result3->quickest.distance; | ||
1050 | result4->quickest.duration+=result3->quickest.duration; | ||
1051 | amb | 31 | } |
1052 | |||
1053 | amb | 43 | if(result2->quickest.next) |
1054 | result2=FindResult(results2,result2->quickest.next); | ||
1055 | amb | 31 | else |
1056 | result2=NULL; | ||
1057 | } | ||
1058 | while(result2); | ||
1059 | |||
1060 | FreeResultsList(results2); | ||
1061 | |||
1062 | amb | 43 | result1=FindResult(results,result1->quickest.next); |
1063 | amb | 31 | } |
1064 | else | ||
1065 | result1=NULL; | ||
1066 | } | ||
1067 | while(result1); | ||
1068 | |||
1069 | /* Now print out the result normally */ | ||
1070 | |||
1071 | print_progress=1; | ||
1072 | |||
1073 | PrintRoute(combined,nodes,segments,ways,start,finish); | ||
1074 | } | ||
1075 | |||
1076 | |||
1077 | /*++++++++++++++++++++++++++++++++++++++ | ||
1078 | amb | 2 | Insert an item into the queue in the right order. |
1079 | |||
1080 | amb | 45 | Results *results The set of results. |
1081 | |||
1082 | amb | 2 | Result *result The result to insert into the queue. |
1083 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1084 | |||
1085 | amb | 45 | static void insert_in_queue(Results *results,Result *result) |
1086 | amb | 2 | { |
1087 | amb | 45 | int start=0; |
1088 | int end=OSMQueue.number-1; | ||
1089 | amb | 2 | int mid; |
1090 | int insert=-1; | ||
1091 | |||
1092 | /* Check that the whole thing is allocated. */ | ||
1093 | |||
1094 | amb | 45 | if(!OSMQueue.queue) |
1095 | amb | 2 | { |
1096 | amb | 45 | OSMQueue.alloced=INCREMENT; |
1097 | OSMQueue.number=0; | ||
1098 | OSMQueue.queue=(uint32_t*)malloc(OSMQueue.alloced*sizeof(uint32_t)); | ||
1099 | amb | 2 | } |
1100 | |||
1101 | /* Check that the arrays have enough space. */ | ||
1102 | |||
1103 | amb | 45 | if(OSMQueue.number==OSMQueue.alloced) |
1104 | amb | 2 | { |
1105 | amb | 45 | OSMQueue.alloced+=INCREMENT; |
1106 | OSMQueue.queue=(uint32_t*)realloc((void*)OSMQueue.queue,OSMQueue.alloced*sizeof(uint32_t)); | ||
1107 | amb | 2 | } |
1108 | |||
1109 | /* Binary search - search key may not match, new insertion point required | ||
1110 | * | ||
1111 | * # <- start | Check mid and move start or end if it doesn't match | ||
1112 | * # | | ||
1113 | * # | Since there may not be an exact match we must set end=mid | ||
1114 | * # <- mid | or start=mid because we know that mid doesn't match. | ||
1115 | * # | | ||
1116 | * # | Eventually end=start+1 and the insertion point is before | ||
1117 | * # <- end | end (since it cannot be before the initial start or end). | ||
1118 | */ | ||
1119 | |||
1120 | amb | 45 | if(OSMQueue.number==0) /* There is nothing in the queue */ |
1121 | insert=0; | ||
1122 | else if(result->shortest.distance>results->results[OSMQueue.queue[start]].shortest.distance) /* Check key is not before start */ | ||
1123 | amb | 2 | insert=start; |
1124 | amb | 45 | else if(result->shortest.distance<results->results[OSMQueue.queue[end]].shortest.distance) /* Check key is not after end */ |
1125 | amb | 2 | insert=end+1; |
1126 | else | ||
1127 | { | ||
1128 | do | ||
1129 | { | ||
1130 | amb | 45 | mid=(start+end)/2; /* Choose mid point */ |
1131 | amb | 2 | |
1132 | amb | 45 | if(results->results[OSMQueue.queue[mid]].shortest.distance>result->shortest.distance) /* Mid point is too low */ |
1133 | amb | 2 | start=mid; |
1134 | amb | 45 | else if(results->results[OSMQueue.queue[mid]].shortest.distance<result->shortest.distance) /* Mid point is too high */ |
1135 | amb | 2 | end=mid; |
1136 | amb | 45 | else /* Mid point is correct */ |
1137 | amb | 2 | { |
1138 | amb | 45 | if(&results->results[OSMQueue.queue[mid]]==result) |
1139 | amb | 2 | return; |
1140 | |||
1141 | insert=mid; | ||
1142 | break; | ||
1143 | } | ||
1144 | } | ||
1145 | while((end-start)>1); | ||
1146 | |||
1147 | if(insert==-1) | ||
1148 | insert=end; | ||
1149 | } | ||
1150 | |||
1151 | /* Shuffle the array up */ | ||
1152 | |||
1153 | amb | 45 | if(insert!=OSMQueue.number) |
1154 | memmove(&OSMQueue.queue[insert+1],&OSMQueue.queue[insert],(OSMQueue.number-insert)*sizeof(uint32_t)); | ||
1155 | amb | 2 | |
1156 | /* Insert the new entry */ | ||
1157 | |||
1158 | amb | 45 | OSMQueue.queue[insert]=result-results->results; |
1159 | amb | 2 | |
1160 | amb | 45 | OSMQueue.number++; |
1161 | amb | 2 | } |
Properties
Name | Value |
---|---|
cvs:description | Route optimiser. |