Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Annotation of /trunk/src/superx.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1605 - (hide annotations) (download) (as text)
Sat Oct 18 10:30:57 2014 UTC (10 years, 5 months ago) by amb
File MIME type: text/x-csrc
File size: 16071 byte(s)
Free memory that it allocated by IndexSegments() when no longer needed rather
than holding on to it.

1 amb 110 /***************************************
2     Super-Segment data type functions.
3 amb 151
4     Part of the Routino routing software.
5 amb 110 ******************/ /******************
6 amb 1598 This file Copyright 2008-2014 Andrew M. Bishop
7 amb 110
8 amb 151 This program is free software: you can redistribute it and/or modify
9     it under the terms of the GNU Affero General Public License as published by
10     the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12    
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     GNU Affero General Public License for more details.
17    
18     You should have received a copy of the GNU Affero General Public License
19     along with this program. If not, see <http://www.gnu.org/licenses/>.
20 amb 110 ***************************************/
21    
22    
23     #include <stdlib.h>
24    
25 amb 955 #include "types.h"
26     #include "segments.h"
27 amb 449 #include "ways.h"
28    
29 amb 955 #include "typesx.h"
30 amb 110 #include "nodesx.h"
31     #include "segmentsx.h"
32     #include "waysx.h"
33     #include "superx.h"
34    
35 amb 449 #include "files.h"
36 amb 519 #include "logging.h"
37 amb 449 #include "results.h"
38 amb 110
39 amb 449
40 amb 680 /* Local functions */
41 amb 228
42 amb 1161 static Results *FindSuperRoutes(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx,node_t start,Way *match);
43 amb 228
44    
45 amb 110 /*++++++++++++++++++++++++++++++++++++++
46 amb 680 Select the super-nodes from the list of nodes.
47 amb 110
48 amb 680 NodesX *nodesx The set of nodes to use.
49 amb 110
50 amb 680 SegmentsX *segmentsx The set of segments to use.
51 amb 110
52 amb 680 WaysX *waysx The set of ways to use.
53 amb 110 ++++++++++++++++++++++++++++++++++++++*/
54    
55 amb 653 void ChooseSuperNodes(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx)
56 amb 110 {
57 amb 214 index_t i;
58 amb 780 index_t nnodes=0;
59 amb 110
60 amb 510 if(nodesx->number==0 || segmentsx->number==0 || waysx->number==0)
61 amb 508 return;
62    
63 amb 275 /* Print the start message */
64    
65 amb 519 printf_first("Finding Super-Nodes: Nodes=0 Super-Nodes=0");
66 amb 227
67 amb 947 /* Allocate and set the super-node markers */
68    
69     if(!nodesx->super)
70     {
71 amb 950 nodesx->super=AllocBitMask(nodesx->number);
72 amb 1598 log_malloc(nodesx->super,LengthBitMask(nodesx->number)*sizeof(BitMask));
73 amb 947
74 amb 1166 logassert(nodesx->super,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */
75 amb 947
76 amb 1089 SetAllBits(nodesx->super,nodesx->number);
77 amb 947 }
78    
79 amb 555 /* Map into memory / open the files */
80 amb 275
81 amb 1423 nodesx->fd=ReOpenFileBuffered(nodesx->filename_tmp);
82    
83 amb 452 #if !SLIM
84 amb 1120 segmentsx->data=MapFile(segmentsx->filename_tmp);
85     waysx->data=MapFile(waysx->filename_tmp);
86 amb 555 #else
87 amb 1414 segmentsx->fd=SlimMapFile(segmentsx->filename_tmp);
88     waysx->fd=SlimMapFile(waysx->filename_tmp);
89 amb 1297
90     InvalidateSegmentXCache(segmentsx->cache);
91     InvalidateWayXCache(waysx->cache);
92 amb 452 #endif
93 amb 257
94 amb 110 /* Find super-nodes */
95    
96 amb 229 for(i=0;i<nodesx->number;i++)
97 amb 110 {
98 amb 1423 NodeX nodex;
99    
100     ReadFileBuffered(nodesx->fd,&nodex,sizeof(NodeX));
101    
102 amb 654 if(IsBitSet(nodesx->super,i))
103 amb 652 {
104     int issuper=0;
105 amb 110
106 amb 1423 if(nodex.flags&(NODE_TURNRSTRCT|NODE_TURNRSTRCT2))
107 amb 652 issuper=1;
108     else
109     {
110     int count=0,j;
111 amb 759 Way segmentway[MAX_SEG_PER_NODE];
112     int segmentweight[MAX_SEG_PER_NODE];
113 amb 652 SegmentX *segmentx=FirstSegmentX(segmentsx,i,1);
114 amb 229
115 amb 652 while(segmentx)
116     {
117     WayX *wayx=LookupWayX(waysx,segmentx->way,1);
118     int nsegments;
119 amb 110
120 amb 652 /* Segments that are loops count twice */
121 amb 641
122 amb 1166 logassert(count<MAX_SEG_PER_NODE,"Too many segments for one node (increase MAX_SEG_PER_NODE?)"); /* Only a limited amount of information stored. */
123 amb 469
124 amb 652 if(segmentx->node1==segmentx->node2)
125     segmentweight[count]=2;
126     else
127     segmentweight[count]=1;
128 amb 469
129 amb 652 segmentway[count]=wayx->way;
130 amb 643
131 amb 1069 /* If the node allows less traffic types than any connecting way then it is super if it allows anything */
132 amb 110
133 amb 1423 if((wayx->way.allow&nodex.allow)!=wayx->way.allow && nodex.allow!=Transports_None)
134 amb 652 {
135     issuper=1;
136     break;
137     }
138    
139     nsegments=segmentweight[count];
140    
141     for(j=0;j<count;j++)
142     if(wayx->way.allow & segmentway[j].allow)
143 amb 643 {
144 amb 652 /* If two ways are different in any attribute and there is a type of traffic that can use both then it is super */
145 amb 110
146 amb 652 if(WaysCompare(&segmentway[j],&wayx->way))
147     {
148     issuper=1;
149     break;
150     }
151 amb 434
152 amb 652 /* If there are two other segments that can be used by the same types of traffic as this one then it is super */
153 amb 110
154 amb 652 nsegments+=segmentweight[j];
155     if(nsegments>2)
156     {
157     issuper=1;
158     break;
159     }
160     }
161 amb 643
162 amb 652 if(issuper)
163     break;
164 amb 110
165 amb 943 segmentx=NextSegmentX(segmentsx,segmentx,i);
166 amb 110
167 amb 652 count++;
168     }
169     }
170 amb 434
171 amb 652 /* Mark the node as super if it is. */
172    
173     if(issuper)
174     nnodes++;
175 amb 653 else
176 amb 654 ClearBit(nodesx->super,i);
177 amb 110 }
178    
179     if(!((i+1)%10000))
180 amb 790 printf_middle("Finding Super-Nodes: Nodes=%"Pindex_t" Super-Nodes=%"Pindex_t,i+1,nnodes);
181 amb 110 }
182    
183 amb 555 /* Unmap from memory / close the files */
184 amb 275
185 amb 452 #if !SLIM
186 amb 1122 segmentsx->data=UnmapFile(segmentsx->data);
187     waysx->data=UnmapFile(waysx->data);
188 amb 555 #else
189 amb 1414 segmentsx->fd=SlimUnmapFile(segmentsx->fd);
190     waysx->fd=SlimUnmapFile(waysx->fd);
191 amb 452 #endif
192 amb 275
193 amb 1423 nodesx->fd=CloseFileBuffered(nodesx->fd);
194    
195 amb 275 /* Print the final message */
196    
197 amb 790 printf_last("Found Super-Nodes: Nodes=%"Pindex_t" Super-Nodes=%"Pindex_t,nodesx->number,nnodes);
198 amb 110 }
199    
200    
201     /*++++++++++++++++++++++++++++++++++++++
202 amb 680 Create the super-segments from the existing segments.
203 amb 110
204 amb 680 SegmentsX *CreateSuperSegments Returns the new super segments.
205 amb 110
206 amb 680 NodesX *nodesx The set of nodes to use.
207 amb 110
208 amb 680 SegmentsX *segmentsx The set of segments to use.
209 amb 110
210 amb 680 WaysX *waysx The set of ways to use.
211 amb 110 ++++++++++++++++++++++++++++++++++++++*/
212    
213 amb 653 SegmentsX *CreateSuperSegments(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx)
214 amb 110 {
215 amb 214 index_t i;
216 amb 110 SegmentsX *supersegmentsx;
217 amb 780 index_t sn=0,ss=0;
218 amb 110
219 amb 1339 supersegmentsx=NewSegmentList();
220 amb 508
221 amb 510 if(segmentsx->number==0 || waysx->number==0)
222 amb 1120 {
223 amb 1151 FinishSegmentList(supersegmentsx);
224 amb 1120
225 amb 508 return(supersegmentsx);
226 amb 1120 }
227 amb 508
228 amb 275 /* Print the start message */
229    
230 amb 519 printf_first("Creating Super-Segments: Super-Nodes=0 Super-Segments=0");
231 amb 227
232 amb 555 /* Map into memory / open the files */
233 amb 275
234 amb 452 #if !SLIM
235 amb 1120 nodesx->data=MapFile(nodesx->filename_tmp);
236     segmentsx->data=MapFile(segmentsx->filename_tmp);
237     waysx->data=MapFile(waysx->filename_tmp);
238 amb 555 #else
239 amb 1414 nodesx->fd=SlimMapFile(nodesx->filename_tmp);
240     segmentsx->fd=SlimMapFile(segmentsx->filename_tmp);
241     waysx->fd=SlimMapFile(waysx->filename_tmp);
242 amb 1297
243     InvalidateNodeXCache(nodesx->cache);
244     InvalidateSegmentXCache(segmentsx->cache);
245     InvalidateWayXCache(waysx->cache);
246 amb 452 #endif
247 amb 257
248 amb 275 /* Create super-segments for each super-node. */
249    
250 amb 110 for(i=0;i<nodesx->number;i++)
251     {
252 amb 654 if(IsBitSet(nodesx->super,i))
253 amb 110 {
254 amb 643 SegmentX *segmentx;
255 amb 652 int count=0,match;
256 amb 759 Way prevway[MAX_SEG_PER_NODE];
257 amb 110
258 amb 646 segmentx=FirstSegmentX(segmentsx,i,1);
259 amb 110
260 amb 643 while(segmentx)
261 amb 110 {
262 amb 279 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
263 amb 110
264     /* Check that this type of way hasn't already been routed */
265    
266 amb 643 match=0;
267    
268 amb 652 if(count>0)
269 amb 110 {
270 amb 643 int j;
271 amb 110
272 amb 652 for(j=0;j<count;j++)
273 amb 643 if(!WaysCompare(&prevway[j],&wayx->way))
274 amb 110 {
275 amb 643 match=1;
276 amb 110 break;
277     }
278     }
279    
280 amb 1166 logassert(count<MAX_SEG_PER_NODE,"Too many segments for one node (increase MAX_SEG_PER_NODE?)"); /* Only a limited amount of history stored. */
281 amb 643
282 amb 652 prevway[count++]=wayx->way;
283 amb 643
284 amb 110 /* Route the way and store the super-segments. */
285    
286 amb 643 if(!match)
287 amb 110 {
288 amb 1161 Results *results=FindSuperRoutes(nodesx,segmentsx,waysx,i,&wayx->way);
289 amb 110 Result *result=FirstResult(results);
290    
291     while(result)
292     {
293 amb 654 if(IsBitSet(nodesx->super,result->node) && result->segment!=NO_SEGMENT)
294 amb 110 {
295 amb 1174 if(wayx->way.type&Highway_OneWay && result->node!=i)
296 amb 1168 AppendSegmentList(supersegmentsx,segmentx->way,i,result->node,DISTANCE((distance_t)result->score)|ONEWAY_1TO2);
297 amb 172 else
298 amb 1168 AppendSegmentList(supersegmentsx,segmentx->way,i,result->node,DISTANCE((distance_t)result->score));
299 amb 216
300 amb 229 ss++;
301 amb 110 }
302    
303     result=NextResult(results,result);
304     }
305     }
306    
307 amb 943 segmentx=NextSegmentX(segmentsx,segmentx,i);
308 amb 110 }
309 amb 227
310     sn++;
311 amb 110
312 amb 229 if(!(sn%10000))
313 amb 790 printf_middle("Creating Super-Segments: Super-Nodes=%"Pindex_t" Super-Segments=%"Pindex_t,sn,ss);
314 amb 110 }
315     }
316    
317 amb 1420 FinishSegmentList(supersegmentsx);
318    
319 amb 555 /* Unmap from memory / close the files */
320 amb 275
321 amb 452 #if !SLIM
322 amb 1122 nodesx->data=UnmapFile(nodesx->data);
323     segmentsx->data=UnmapFile(segmentsx->data);
324     waysx->data=UnmapFile(waysx->data);
325 amb 555 #else
326 amb 1414 nodesx->fd=SlimUnmapFile(nodesx->fd);
327     segmentsx->fd=SlimUnmapFile(segmentsx->fd);
328     waysx->fd=SlimUnmapFile(waysx->fd);
329 amb 452 #endif
330 amb 275
331 amb 1605 /* Free the no-longer required memory */
332    
333     if(segmentsx->firstnode)
334     {
335     log_free(segmentsx->firstnode);
336     free(segmentsx->firstnode);
337     segmentsx->firstnode=NULL;
338     }
339    
340 amb 275 /* Print the final message */
341    
342 amb 790 printf_last("Created Super-Segments: Super-Nodes=%"Pindex_t" Super-Segments=%"Pindex_t,sn,ss);
343 amb 110
344     return(supersegmentsx);
345     }
346    
347    
348     /*++++++++++++++++++++++++++++++++++++++
349 amb 256 Merge the segments and super-segments into a new segment list.
350 amb 110
351 amb 681 SegmentsX *MergeSuperSegments Returns a new set of merged segments.
352 amb 256
353 amb 681 SegmentsX *segmentsx The set of segments to use.
354 amb 110
355 amb 681 SegmentsX *supersegmentsx The set of super-segments to use.
356 amb 110 ++++++++++++++++++++++++++++++++++++++*/
357    
358 amb 681 SegmentsX *MergeSuperSegments(SegmentsX *segmentsx,SegmentsX *supersegmentsx)
359 amb 110 {
360 amb 1423 index_t i,j,lastj;
361 amb 780 index_t merged=0,added=0;
362 amb 681 SegmentsX *mergedsegmentsx;
363 amb 1540 SegmentX supersegmentx;
364 amb 110
365 amb 1339 mergedsegmentsx=NewSegmentList();
366 amb 508
367 amb 550 if(segmentsx->number==0)
368 amb 1120 {
369 amb 1151 FinishSegmentList(mergedsegmentsx);
370 amb 1120
371 amb 508 return(mergedsegmentsx);
372 amb 1120 }
373 amb 508
374 amb 275 /* Print the start message */
375    
376 amb 761 printf_first("Merging Segments: Segments=0 Super=0 Merged=0 Added=0");
377 amb 227
378 amb 1423 /* Open the files */
379 amb 275
380 amb 1423 segmentsx->fd=ReOpenFileBuffered(segmentsx->filename_tmp);
381 amb 550 if(supersegmentsx->number>0)
382 amb 1423 supersegmentsx->fd=ReOpenFileBuffered(supersegmentsx->filename_tmp);
383 amb 1297
384 amb 275 /* Loop through and create a new list of combined segments */
385    
386 amb 1423 lastj=-1;
387     j=0;
388    
389     for(i=0;i<segmentsx->number;i++)
390 amb 110 {
391 amb 256 int super=0;
392 amb 1423 SegmentX segmentx;
393 amb 256
394 amb 1423 ReadFileBuffered(segmentsx->fd,&segmentx,sizeof(SegmentX));
395    
396 amb 110 while(j<supersegmentsx->number)
397     {
398 amb 1423 if(j!=lastj)
399 amb 110 {
400 amb 1423 ReadFileBuffered(supersegmentsx->fd,&supersegmentx,sizeof(SegmentX));
401     lastj=j;
402     }
403    
404     if(segmentx.node1 ==supersegmentx.node1 &&
405     segmentx.node2 ==supersegmentx.node2 &&
406     segmentx.distance==supersegmentx.distance)
407     {
408 amb 780 merged++;
409 amb 257 j++;
410 amb 256 /* mark as super-segment and normal segment */
411     super=1;
412 amb 110 break;
413     }
414 amb 1423 else if((segmentx.node1==supersegmentx.node1 &&
415     segmentx.node2==supersegmentx.node2) ||
416     (segmentx.node1==supersegmentx.node1 &&
417     segmentx.node2>supersegmentx.node2) ||
418     (segmentx.node1>supersegmentx.node1))
419 amb 110 {
420 amb 256 /* mark as super-segment */
421 amb 1423 AppendSegmentList(mergedsegmentsx,supersegmentx.way,supersegmentx.node1,supersegmentx.node2,supersegmentx.distance|SEGMENT_SUPER);
422 amb 780 added++;
423 amb 216 j++;
424 amb 110 }
425     else
426 amb 257 {
427     /* mark as normal segment */
428 amb 110 break;
429 amb 257 }
430 amb 110 }
431    
432 amb 256 if(super)
433 amb 1423 AppendSegmentList(mergedsegmentsx,segmentx.way,segmentx.node1,segmentx.node2,segmentx.distance|SEGMENT_SUPER|SEGMENT_NORMAL);
434 amb 256 else
435 amb 1423 AppendSegmentList(mergedsegmentsx,segmentx.way,segmentx.node1,segmentx.node2,segmentx.distance|SEGMENT_NORMAL);
436 amb 208
437 amb 110 if(!((i+1)%10000))
438 amb 790 printf_middle("Merging Segments: Segments=%"Pindex_t" Super=%"Pindex_t" Merged=%"Pindex_t" Added=%"Pindex_t,i+1,j,merged,added);
439 amb 110 }
440    
441 amb 1540 if(j<supersegmentsx->number)
442 amb 1490 {
443 amb 1540 if(j==lastj)
444     {
445     AppendSegmentList(mergedsegmentsx,supersegmentx.way,supersegmentx.node1,supersegmentx.node2,supersegmentx.distance|SEGMENT_SUPER);
446 amb 1490
447 amb 1540 j++;
448     }
449 amb 1490
450 amb 1540 while(j<supersegmentsx->number)
451     {
452     ReadFileBuffered(supersegmentsx->fd,&supersegmentx,sizeof(SegmentX));
453    
454     AppendSegmentList(mergedsegmentsx,supersegmentx.way,supersegmentx.node1,supersegmentx.node2,supersegmentx.distance|SEGMENT_SUPER);
455    
456     added++;
457     j++;
458     }
459 amb 1490 }
460    
461 amb 1420 FinishSegmentList(mergedsegmentsx);
462    
463 amb 1423 /* Close the files */
464 amb 275
465 amb 1423 segmentsx->fd=CloseFileBuffered(segmentsx->fd);
466 amb 550 if(supersegmentsx->number>0)
467 amb 1423 supersegmentsx->fd=CloseFileBuffered(supersegmentsx->fd);
468 amb 275
469     /* Print the final message */
470    
471 amb 790 printf_last("Merged Segments: Segments=%"Pindex_t" Super=%"Pindex_t" Merged=%"Pindex_t" Added=%"Pindex_t,segmentsx->number,supersegmentsx->number,merged,added);
472 amb 256
473     return(mergedsegmentsx);
474 amb 110 }
475    
476    
477     /*++++++++++++++++++++++++++++++++++++++
478 amb 680 Find all routes from a specified super-node to any other super-node that follows a certain type of way.
479 amb 110
480 amb 1161 Results *FindSuperRoutes Returns a set of results.
481 amb 110
482     NodesX *nodesx The set of nodes to use.
483    
484     SegmentsX *segmentsx The set of segments to use.
485    
486     WaysX *waysx The set of ways to use.
487    
488     node_t start The start node.
489    
490 amb 680 Way *match A template for the type of way that the route must follow.
491 amb 110 ++++++++++++++++++++++++++++++++++++++*/
492    
493 amb 1161 static Results *FindSuperRoutes(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx,node_t start,Way *match)
494 amb 110 {
495 amb 1444 static Results *results=NULL;
496     static Queue *queue=NULL;
497 amb 110 Result *result1,*result2;
498 amb 204 WayX *wayx;
499 amb 110
500     /* Insert the first node into the queue */
501    
502 amb 1444 if(!results)
503     results=NewResultsList(8);
504     else
505     ResetResultsList(results);
506 amb 110
507 amb 1444 if(!queue)
508     queue=NewQueueList(8);
509     else
510     ResetQueueList(queue);
511    
512 amb 605 result1=InsertResult(results,start,NO_SEGMENT);
513 amb 110
514 amb 1289 InsertInQueue(queue,result1,0);
515 amb 110
516     /* Loop across all nodes in the queue */
517    
518 amb 236 while((result1=PopFromQueue(queue)))
519 amb 110 {
520 amb 785 index_t node1;
521 amb 643 SegmentX *segmentx;
522    
523 amb 110 node1=result1->node;
524    
525 amb 646 segmentx=FirstSegmentX(segmentsx,node1,2); /* position 1 is already used */
526 amb 110
527 amb 643 while(segmentx)
528 amb 110 {
529 amb 1071 NodeX *node2x;
530 amb 643 index_t node2,seg2;
531 amb 113 distance_t cumulative_distance;
532    
533 amb 680 /* must not be one-way against the direction of travel */
534 amb 647 if(IsOnewayTo(segmentx,node1))
535     goto endloop;
536 amb 110
537 amb 643 seg2=IndexSegmentX(segmentsx,segmentx);
538    
539 amb 680 /* must not be a u-turn */
540 amb 656 if(result1->segment==seg2)
541 amb 110 goto endloop;
542    
543 amb 890 wayx=LookupWayX(waysx,segmentx->way,2); /* position 1 is already used */
544 amb 110
545 amb 680 /* must be the right type of way */
546 amb 262 if(WaysCompare(&wayx->way,match))
547 amb 110 goto endloop;
548    
549 amb 1071 node2=OtherNode(segmentx,node1);
550    
551     node2x=LookupNodeX(nodesx,node2,2); /* position 1 is already used */
552    
553     /* Don't route beyond a node with no access */
554     if(node2x->allow==Transports_None)
555     goto endloop;
556    
557 amb 1168 cumulative_distance=(distance_t)result1->score+DISTANCE(segmentx->distance);
558 amb 110
559 amb 642 result2=FindResult(results,node2,seg2);
560 amb 110
561     if(!result2) /* New end node */
562     {
563 amb 642 result2=InsertResult(results,node2,seg2);
564 amb 605 result2->prev=result1;
565 amb 172 result2->score=cumulative_distance;
566 amb 110
567 amb 680 /* don't route beyond a super-node. */
568 amb 654 if(!IsBitSet(nodesx->super,node2))
569 amb 1289 InsertInQueue(queue,result2,cumulative_distance);
570 amb 110 }
571 amb 172 else if(cumulative_distance<result2->score)
572 amb 110 {
573 amb 605 result2->prev=result1;
574 amb 172 result2->score=cumulative_distance;
575 amb 110
576 amb 680 /* don't route beyond a super-node. */
577 amb 654 if(!IsBitSet(nodesx->super,node2))
578 amb 1289 InsertInQueue(queue,result2,cumulative_distance);
579 amb 110 }
580    
581     endloop:
582    
583 amb 943 segmentx=NextSegmentX(segmentsx,segmentx,node1);
584 amb 110 }
585     }
586    
587     return(results);
588     }

Properties

Name Value
cvs:description Super-nodes and super-segments functions.