1 /***************************************
2 $Header: /home/amb/routino/src/RCS/superx.c,v 1.44 2010/10/09 14:14:42 amb Exp $
4 Super-Segment data type functions.
6 Part of the Routino routing software.
7 ******************/ /******************
8 This file Copyright 2008-2010 Andrew M. Bishop
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU Affero General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Affero General Public License for more details.
20 You should have received a copy of the GNU Affero General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 ***************************************/
31 #include "segmentsx.h"
41 static Results *FindRoutesWay(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx,node_t start,Way *match,int iteration);
44 /*++++++++++++++++++++++++++++++++++++++
45 Select the super-segments from the list of segments.
47 NodesX *nodesx The nodes.
49 SegmentsX *segmentsx The segments.
51 WaysX *waysx The ways.
52 ++++++++++++++++++++++++++++++++++++++*/
54 void ChooseSuperNodes(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx)
59 if(nodesx->number==0 || segmentsx->number==0 || waysx->number==0)
62 /* Print the start message */
64 printf("Finding Super-Nodes: Nodes=0 Super-Nodes=0");
70 nodesx->xdata=MapFile(nodesx->filename);
71 segmentsx->xdata=MapFile(segmentsx->filename);
72 waysx->xdata=MapFile(waysx->filename);
75 /* Find super-nodes */
77 for(i=0;i<nodesx->number;i++)
79 NodeX *nodex=LookupNodeX(nodesx,i,1);
81 index_t index1,index2;
83 index1=IndexFirstSegmentX(segmentsx,i);
85 while(index1!=NO_SEGMENT)
87 SegmentX *segmentx1=LookupSegmentX(segmentsx,index1,1);
88 WayX *wayx1=LookupWayX(waysx,segmentx1->way,1);
90 index1=IndexNextSegmentX(segmentsx,index1,i);
93 /* If the node allows less traffic types than any connecting way ... */
95 if((wayx1->way.allow&nodex->allow)!=wayx1->way.allow)
101 while(index2!=NO_SEGMENT)
103 SegmentX *segmentx2=LookupSegmentX(segmentsx,index2,2);
104 WayX *wayx2=LookupWayX(waysx,segmentx2->way,2);
106 /* If the ways are different in any attribute and there is a type of traffic that can use both ... */
108 if(WaysCompare(&wayx1->way,&wayx2->way))
109 if(wayx1->way.allow & wayx2->way.allow)
115 index2=IndexNextSegmentX(segmentsx,index2,i);
122 /* Store the node if there is a difference in the connected ways that could affect routing. */
133 printf("\rFinding Super-Nodes: Nodes=%d Super-Nodes=%d",i+1,nnodes);
138 /* Unmap from memory */
141 nodesx->xdata=UnmapFile(nodesx->filename);
142 segmentsx->xdata=UnmapFile(segmentsx->filename);
143 waysx->xdata=UnmapFile(waysx->filename);
146 /* Print the final message */
148 printf("\rFound Super-Nodes: Nodes=%d Super-Nodes=%d \n",nodesx->number,nnodes);
153 /*++++++++++++++++++++++++++++++++++++++
154 Create the super-segments.
156 SegmentsX *CreateSuperSegments Creates the super segments.
158 NodesX *nodesx The nodes.
160 SegmentsX *segmentsx The segments.
162 WaysX *waysx The ways.
164 int iteration The current super-node / super-segment iteration number.
165 ++++++++++++++++++++++++++++++++++++++*/
167 SegmentsX *CreateSuperSegments(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx,int iteration)
170 SegmentsX *supersegmentsx;
173 supersegmentsx=NewSegmentList(0);
175 if(segmentsx->number==0 || waysx->number==0)
176 return(supersegmentsx);
178 /* Print the start message */
180 printf("Creating Super-Segments: Super-Nodes=0 Super-Segments=0");
183 /* Map into memory */
186 segmentsx->xdata=MapFile(segmentsx->filename);
187 waysx->xdata=MapFile(waysx->filename);
190 /* Create super-segments for each super-node. */
192 for(i=0;i<nodesx->number;i++)
194 if(nodesx->super[i]>iteration)
198 index=first=IndexFirstSegmentX(segmentsx,i);
200 while(index!=NO_SEGMENT)
202 SegmentX *segmentx=LookupSegmentX(segmentsx,index,1);
203 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
205 /* Check that this type of way hasn't already been routed */
209 index_t otherindex=first;
211 while(otherindex!=NO_SEGMENT && otherindex!=index)
213 SegmentX *othersegmentx=LookupSegmentX(segmentsx,otherindex,2);
214 WayX *otherwayx=LookupWayX(waysx,othersegmentx->way,2);
216 if(!WaysCompare(&otherwayx->way,&wayx->way))
222 otherindex=IndexNextSegmentX(segmentsx,otherindex,i);
226 /* Route the way and store the super-segments. */
230 Results *results=FindRoutesWay(nodesx,segmentsx,waysx,i,&wayx->way,iteration);
231 Result *result=FirstResult(results);
235 if(result->node!=i && nodesx->super[result->node]>iteration)
237 if(wayx->way.type&Way_OneWay)
239 AppendSegment(supersegmentsx,segmentx->way,i,result->node,DISTANCE((distance_t)result->score)|ONEWAY_1TO2);
240 AppendSegment(supersegmentsx,segmentx->way,result->node,i,DISTANCE((distance_t)result->score)|ONEWAY_2TO1);
243 AppendSegment(supersegmentsx,segmentx->way,i,result->node,DISTANCE((distance_t)result->score));
248 result=NextResult(results,result);
251 FreeResultsList(results);
254 index=IndexNextSegmentX(segmentsx,index,i);
261 printf("\rCreating Super-Segments: Super-Nodes=%d Super-Segments=%d",sn,ss);
267 /* Unmap from memory */
270 segmentsx->xdata=UnmapFile(segmentsx->filename);
271 waysx->xdata=UnmapFile(waysx->filename);
274 /* Print the final message */
276 printf("\rCreated Super-Segments: Super-Nodes=%d Super-Segments=%d \n",sn,ss);
279 return(supersegmentsx);
283 /*++++++++++++++++++++++++++++++++++++++
284 Merge the segments and super-segments into a new segment list.
286 SegmentsX* MergeSuperSegments Returns a new set of merged segments.
288 SegmentsX* segmentsx The set of segments to process.
290 SegmentsX* supersegmentsx The set of super-segments to merge.
291 ++++++++++++++++++++++++++++++++++++++*/
293 SegmentsX *MergeSuperSegments(SegmentsX* segmentsx,SegmentsX* supersegmentsx)
297 SegmentsX* mergedsegmentsx;
299 mergedsegmentsx=NewSegmentList(0);
301 if(segmentsx->number==0 || supersegmentsx->number==0)
302 return(mergedsegmentsx);
304 /* Print the start message */
306 printf("Merging: Segments=0 Super-Segments=0 Merged=0 Added=0");
309 /* Map into memory */
312 segmentsx->xdata=MapFile(segmentsx->filename);
313 supersegmentsx->xdata=MapFile(supersegmentsx->filename);
316 /* Loop through and create a new list of combined segments */
318 for(i=0,j=0;i<segmentsx->number;i++)
321 SegmentX *segmentx=LookupSegmentX(segmentsx,i,1);
323 while(j<supersegmentsx->number)
325 SegmentX *supersegmentx=LookupSegmentX(supersegmentsx,j,1);
327 if(segmentx->node1 ==supersegmentx->node1 &&
328 segmentx->node2 ==supersegmentx->node2 &&
329 segmentx->distance==supersegmentx->distance)
333 /* mark as super-segment and normal segment */
337 else if((segmentx->node1==supersegmentx->node1 &&
338 segmentx->node2==supersegmentx->node2) ||
339 (segmentx->node1==supersegmentx->node1 &&
340 segmentx->node2>supersegmentx->node2) ||
341 (segmentx->node1>supersegmentx->node1))
343 /* mark as super-segment */
344 AppendSegment(mergedsegmentsx,supersegmentx->way,supersegmentx->node1,supersegmentx->node2,supersegmentx->distance|SEGMENT_SUPER);
350 /* mark as normal segment */
356 AppendSegment(mergedsegmentsx,segmentx->way,segmentx->node1,segmentx->node2,segmentx->distance|SEGMENT_SUPER|SEGMENT_NORMAL);
358 AppendSegment(mergedsegmentsx,segmentx->way,segmentx->node1,segmentx->node2,segmentx->distance|SEGMENT_NORMAL);
362 printf("\rMerging: Segments=%d Super-Segments=%d Merged=%d Added=%d",i+1,j,m,a);
367 /* Unmap from memory */
370 segmentsx->xdata=UnmapFile(segmentsx->filename);
371 supersegmentsx->xdata=UnmapFile(supersegmentsx->filename);
374 /* Print the final message */
376 printf("\rMerged: Segments=%d Super-Segments=%d Merged=%d Added=%d \n",segmentsx->number,supersegmentsx->number,m,a);
379 return(mergedsegmentsx);
383 /*++++++++++++++++++++++++++++++++++++++
384 Find all routes from a specified node to any node in the specified list that follows a certain type of way.
386 Results *FindRoutesWay Returns a set of results.
388 NodesX *nodesx The set of nodes to use.
390 SegmentsX *segmentsx The set of segments to use.
392 WaysX *waysx The set of ways to use.
394 node_t start The start node.
396 Way *match The way that the route must match.
398 int iteration The current super-node / super-segment iteration number.
399 ++++++++++++++++++++++++++++++++++++++*/
401 static Results *FindRoutesWay(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx,node_t start,Way *match,int iteration)
406 Result *result1,*result2;
410 /* Insert the first node into the queue */
412 results=NewResultsList(8);
414 queue=NewQueueList();
416 result1=InsertResult(results,start);
420 InsertInQueue(queue,result1);
422 /* Loop across all nodes in the queue */
424 while((result1=PopFromQueue(queue)))
428 index=IndexFirstSegmentX(segmentsx,node1);
430 while(index!=NO_SEGMENT)
432 SegmentX *segmentx=LookupSegmentX(segmentsx,index,2); /* must use 2 here */
433 distance_t cumulative_distance;
435 if(segmentx->distance&ONEWAY_2TO1)
438 node2=segmentx->node2;
440 if(result1->prev==node2)
443 wayx=LookupWayX(waysx,segmentx->way,2);
445 if(WaysCompare(&wayx->way,match))
448 cumulative_distance=(distance_t)result1->score+DISTANCE(segmentx->distance);
450 result2=FindResult(results,node2);
452 if(!result2) /* New end node */
454 result2=InsertResult(results,node2);
456 result2->next=NO_NODE;
457 result2->score=cumulative_distance;
458 result2->sortby=cumulative_distance;
460 if(nodesx->super[node2]<=iteration)
461 InsertInQueue(queue,result2);
463 else if(cumulative_distance<result2->score)
466 result2->score=cumulative_distance;
467 result2->sortby=cumulative_distance;
469 if(nodesx->super[node2]<=iteration)
470 InsertInQueue(queue,result2);
475 index=IndexNextSegmentX(segmentsx,index,node1);
479 FreeQueueList(queue);