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/router.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 336 - (hide annotations) (download) (as text)
Sun Mar 28 17:50:43 2010 UTC (14 years, 11 months ago) by amb
File MIME type: text/x-csrc
File size: 18764 byte(s)
Add an option to print out the profiles as XML format.

1 amb 2 /***************************************
2 amb 336 $Header: /home/amb/CVS/routino/src/router.c,v 1.72 2010-03-28 17:50:17 amb Exp $
3 amb 2
4     OSM router.
5 amb 151
6     Part of the Routino routing software.
7 amb 2 ******************/ /******************
8 amb 324 This file Copyright 2008-2010 Andrew M. Bishop
9 amb 2
10 amb 151 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.
14    
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.
19    
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 amb 2 ***************************************/
23    
24    
25     #include <stdio.h>
26 amb 31 #include <string.h>
27 amb 2 #include <stdlib.h>
28 amb 130 #include <ctype.h>
29 amb 2
30 amb 96 #include "types.h"
31 amb 2 #include "functions.h"
32 amb 82 #include "profiles.h"
33 amb 115 #include "nodes.h"
34     #include "segments.h"
35 amb 109 #include "ways.h"
36 amb 2
37    
38 amb 242 /*+ The number of waypoints allowed to be specified. +*/
39     #define NWAYPOINTS 99
40    
41 amb 303 /*+ The maximum distance from the specified point to search for a node or segment (in km). +*/
42 amb 321 #define MAXSEARCH 1
43 amb 242
44 amb 303 /*+ The minimum distance along a segment from a node to insert a fake node. (in km). +*/
45     #define MINSEGMENT 0.005
46    
47    
48     /*+ A set of fake segments to allow start/finish in the middle of a segment. +*/
49     static Segment fake_segments[2*NWAYPOINTS];
50    
51     /*+ A set of fake node latitudes and longitudes. +*/
52     static double point_lon[NWAYPOINTS+1],point_lat[NWAYPOINTS+1];
53    
54 amb 113 /*+ The option not to print any progress information. +*/
55 amb 107 int option_quiet=0;
56    
57 amb 324 /*+ The options to select the format of the output. +*/
58     int option_html=0,option_gpx_track=0,option_gpx_route=0,option_text=0,option_text_all=0;
59    
60 amb 113 /*+ The option to calculate the quickest route insted of the shortest. +*/
61     int option_quickest=0;
62 amb 107
63 amb 113
64 amb 2 int main(int argc,char** argv)
65     {
66 amb 95 Nodes *OSMNodes;
67     Segments *OSMSegments;
68     Ways *OSMWays;
69 amb 242 Results *results[NWAYPOINTS+1]={NULL};
70     int point_used[NWAYPOINTS+1]={0};
71 amb 336 int help_profile=0,help_profile_xml=0,help_profile_js=0,help_profile_pl=0;
72 amb 329 char *dirname=NULL,*prefix=NULL;
73 amb 315 int exactnodes=0;
74 amb 82 Transport transport=Transport_None;
75     Profile profile;
76 amb 176 index_t start=NO_NODE,finish=NO_NODE;
77 amb 303 int arg,point;
78 amb 2
79 amb 44 /* Parse the command line arguments */
80 amb 2
81 amb 145 if(argc<2)
82 amb 2 {
83 amb 44 usage:
84 amb 75
85 amb 336 fprintf(stderr,"Usage: router [--help | --help-profile | --help-profile-xml |\n"
86     " --help-profile-js | --help-profile-pl ]\n"
87 amb 101 " [--dir=<name>] [--prefix=<name>]\n"
88 amb 315 " [--exact-nodes-only]\n"
89 amb 239 " [--quiet]\n"
90 amb 324 " [--output-html]\n"
91 amb 325 " [--output-gpx-track] [--output-gpx-route]\n"
92     " [--output-text] [--output-text-all]\n"
93     " [--shortest | --quickest]\n"
94 amb 324 " --lon1=<longitude> --lat1=<latitude>\n"
95     " --lon2=<longitude> --lon2=<latitude>\n"
96     " [ ... --lon99=<longitude> --lon99=<latitude>]\n"
97 amb 101 " [--transport=<transport>]\n"
98 amb 166 " [--highway-<highway>=<preference> ...]\n"
99 amb 101 " [--speed-<highway>=<speed> ...]\n"
100 amb 298 " [--property-<property>=<preference> ...]\n"
101 amb 130 " [--oneway=[0|1]]\n"
102 amb 135 " [--weight=<weight>]\n"
103     " [--height=<height>] [--width=<width>] [--length=<length>]\n"
104 amb 75 "\n"
105 amb 82 "<transport> defaults to motorcar but can be set to:\n"
106 amb 75 "%s"
107     "\n"
108 amb 82 "<highway> can be selected from:\n"
109     "%s"
110 amb 103 "\n"
111 amb 298 "<property> can be selected from:\n"
112     "%s"
113     "\n"
114 amb 166 "<preference> is a preference expressed as a percentage\n"
115 amb 82 "<speed> is a speed in km/hour\n"
116 amb 135 "<weight> is a weight in tonnes\n"
117     "<height>, <width>, <length> are dimensions in metres\n"
118 amb 82 "\n",
119 amb 298 TransportList(),HighwayList(),PropertyList());
120 amb 75
121 amb 2 return(1);
122     }
123    
124 amb 130 /* Get the transport type if specified and fill in the default profile */
125 amb 75
126 amb 165 for(arg=1;arg<argc;arg++)
127     if(!strncmp(argv[arg],"--transport=",12))
128 amb 82 {
129 amb 165 transport=TransportType(&argv[arg][12]);
130 amb 75
131 amb 82 if(transport==Transport_None)
132     goto usage;
133     }
134    
135     if(transport==Transport_None)
136     transport=Transport_Motorcar;
137    
138     profile=*GetProfile(transport);
139    
140     /* Parse the other command line arguments */
141    
142 amb 165 for(arg=1;arg<argc;arg++)
143 amb 44 {
144 amb 324 if(!strcmp(argv[arg],"--help"))
145     goto usage;
146     else if(!strcmp(argv[arg],"--help-profile"))
147     help_profile=1;
148 amb 336 else if(!strcmp(argv[arg],"--help-profile-xml"))
149     help_profile_xml=1;
150 amb 324 else if(!strcmp(argv[arg],"--help-profile-js"))
151     help_profile_js=1;
152     else if(!strcmp(argv[arg],"--help-profile-pl"))
153     help_profile_pl=1;
154     else if(!strncmp(argv[arg],"--dir=",6))
155     dirname=&argv[arg][6];
156     else if(!strncmp(argv[arg],"--prefix=",9))
157     prefix=&argv[arg][9];
158     else if(!strcmp(argv[arg],"--exact-nodes-only"))
159     exactnodes=1;
160     else if(!strcmp(argv[arg],"--quiet"))
161     option_quiet=1;
162     else if(!strcmp(argv[arg],"--output-html"))
163     option_html=1;
164     else if(!strcmp(argv[arg],"--output-gpx-track"))
165     option_gpx_track=1;
166     else if(!strcmp(argv[arg],"--output-gpx-route"))
167     option_gpx_route=1;
168     else if(!strcmp(argv[arg],"--output-text"))
169     option_text=1;
170     else if(!strcmp(argv[arg],"--output-text-all"))
171     option_text_all=1;
172 amb 325 else if(!strcmp(argv[arg],"--shortest"))
173     option_quickest=0;
174     else if(!strcmp(argv[arg],"--quickest"))
175     option_quickest=1;
176 amb 324 else if(isdigit(argv[arg][0]) ||
177 amb 165 ((argv[arg][0]=='-' || argv[arg][0]=='+') && isdigit(argv[arg][1])))
178 amb 130 {
179 amb 303 for(point=1;point<=NWAYPOINTS;point++)
180     if(point_used[point]!=3)
181 amb 165 {
182 amb 303 if(point_used[point]==0)
183 amb 165 {
184 amb 303 point_lon[point]=degrees_to_radians(atof(argv[arg]));
185     point_used[point]=1;
186 amb 165 }
187 amb 303 else /* if(point_used[point]==1) */
188 amb 165 {
189 amb 303 point_lat[point]=degrees_to_radians(atof(argv[arg]));
190     point_used[point]=3;
191 amb 165 }
192     break;
193     }
194     }
195 amb 242 else if(!strncmp(argv[arg],"--lon",5) && isdigit(argv[arg][5]))
196     {
197     char *p=&argv[arg][6];
198     while(isdigit(*p)) p++;
199     if(*p++!='=')
200     goto usage;
201    
202 amb 303 point=atoi(&argv[arg][5]);
203     if(point>NWAYPOINTS || point_used[point]&1)
204 amb 242 goto usage;
205    
206 amb 303 point_lon[point]=degrees_to_radians(atof(p));
207     point_used[point]+=1;
208 amb 130 }
209 amb 242 else if(!strncmp(argv[arg],"--lat",5) && isdigit(argv[arg][5]))
210     {
211     char *p=&argv[arg][6];
212     while(isdigit(*p)) p++;
213     if(*p++!='=')
214     goto usage;
215    
216 amb 303 point=atoi(&argv[arg][5]);
217     if(point>NWAYPOINTS || point_used[point]&2)
218 amb 242 goto usage;
219    
220 amb 303 point_lat[point]=degrees_to_radians(atof(p));
221     point_used[point]+=2;
222 amb 165 }
223     else if(!strncmp(argv[arg],"--transport=",12))
224 amb 324 ; /* Done this already */
225 amb 165 else if(!strncmp(argv[arg],"--highway-",10))
226 amb 75 {
227 amb 130 Highway highway;
228 amb 165 char *equal=strchr(argv[arg],'=');
229 amb 130 char *string;
230 amb 82
231 amb 130 if(!equal)
232     goto usage;
233    
234 amb 165 string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+10);
235     string[equal-argv[arg]-10]=0;
236 amb 130
237     highway=HighwayType(string);
238    
239 amb 300 if(highway==Way_Count)
240 amb 82 goto usage;
241    
242 amb 166 profile.highway[highway]=atof(equal+1);
243 amb 298
244     free(string);
245 amb 75 }
246 amb 165 else if(!strncmp(argv[arg],"--speed-",8))
247 amb 82 {
248     Highway highway;
249 amb 165 char *equal=strchr(argv[arg],'=');
250 amb 82 char *string;
251    
252     if(!equal)
253     goto usage;
254    
255 amb 165 string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+8);
256     string[equal-argv[arg]-8]=0;
257 amb 82
258     highway=HighwayType(string);
259    
260 amb 300 if(highway==Way_Count)
261 amb 82 goto usage;
262    
263 amb 166 profile.speed[highway]=kph_to_speed(atof(equal+1));
264 amb 298
265     free(string);
266 amb 82 }
267 amb 298 else if(!strncmp(argv[arg],"--property-",11))
268     {
269     Property property;
270     char *equal=strchr(argv[arg],'=');
271     char *string;
272    
273     if(!equal)
274     goto usage;
275    
276     string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+11);
277     string[equal-argv[arg]-11]=0;
278    
279     property=PropertyType(string);
280    
281 amb 300 if(property==Way_Count)
282 amb 298 goto usage;
283    
284     profile.props_yes[property]=atof(equal+1);
285    
286     free(string);
287     }
288 amb 165 else if(!strncmp(argv[arg],"--oneway=",9))
289 amb 166 profile.oneway=!!atoi(&argv[arg][9]);
290 amb 165 else if(!strncmp(argv[arg],"--weight=",9))
291     profile.weight=tonnes_to_weight(atof(&argv[arg][9]));
292     else if(!strncmp(argv[arg],"--height=",9))
293     profile.height=metres_to_height(atof(&argv[arg][9]));
294     else if(!strncmp(argv[arg],"--width=",8))
295     profile.width=metres_to_width(atof(&argv[arg][8]));
296     else if(!strncmp(argv[arg],"--length=",9))
297     profile.length=metres_to_length(atof(&argv[arg][9]));
298 amb 44 else
299     goto usage;
300     }
301    
302 amb 303 for(point=1;point<=NWAYPOINTS;point++)
303     if(point_used[point]==1 || point_used[point]==2)
304 amb 165 goto usage;
305    
306 amb 82 if(help_profile)
307     {
308     PrintProfile(&profile);
309    
310     return(0);
311     }
312 amb 336 else if(help_profile_xml)
313     {
314     PrintProfilesXML();
315    
316     return(0);
317     }
318 amb 129 else if(help_profile_js)
319     {
320     PrintProfilesJS();
321 amb 82
322 amb 129 return(0);
323     }
324 amb 145 else if(help_profile_pl)
325     {
326     PrintProfilesPerl();
327 amb 129
328 amb 145 return(0);
329     }
330    
331 amb 166 UpdateProfile(&profile);
332    
333 amb 329 /* Load in the data - Note: No error checking because Load*List() will call exit() in case of an error. */
334 amb 2
335 amb 329 OSMNodes=LoadNodeList(FileName(dirname,prefix,"nodes.mem"));
336 amb 95
337 amb 329 OSMSegments=LoadSegmentList(FileName(dirname,prefix,"segments.mem"));
338 amb 100
339 amb 329 OSMWays=LoadWayList(FileName(dirname,prefix,"ways.mem"));
340 amb 66
341 amb 307 if(!(profile.allow & OSMWays->allow))
342     {
343     fprintf(stderr,"Error: Database was not generated for selected transport.\n");
344     return(1);
345     }
346    
347 amb 324 if(option_html==0 && option_gpx_track==0 && option_gpx_route==0 && option_text==0 && option_text_all==0)
348     option_html=option_gpx_track=option_gpx_route=option_text=option_text_all=1;
349    
350 amb 303 /* Loop through all pairs of points */
351 amb 99
352 amb 303 for(point=1;point<=NWAYPOINTS;point++)
353 amb 107 {
354 amb 239 Results *begin,*end;
355 amb 315 distance_t distmax=km_to_distance(MAXSEARCH);
356     distance_t distmin;
357     Segment *segment=NULL;
358 amb 303 index_t node1,node2;
359 amb 99
360 amb 303 if(point_used[point]!=3)
361 amb 165 continue;
362 amb 107
363 amb 303 /* Find the closest point */
364 amb 107
365 amb 174 start=finish;
366 amb 165
367 amb 315 if(exactnodes)
368     {
369     finish=FindClosestNode(OSMNodes,OSMSegments,OSMWays,point_lat[point],point_lon[point],distmax,&profile,&distmin);
370     }
371     else
372     {
373     distance_t dist1,dist2;
374 amb 165
375 amb 315 segment=FindClosestSegment(OSMNodes,OSMSegments,OSMWays,point_lat[point],point_lon[point],distmax,&profile,&distmin,&node1,&node2,&dist1,&dist2);
376 amb 303
377 amb 315 finish=CreateFakes(OSMNodes,point,segment,node1,node2,dist1,dist2);
378     }
379 amb 303
380 amb 176 if(finish==NO_NODE)
381 amb 107 {
382 amb 303 fprintf(stderr,"Error: Cannot find node close to specified point %d.\n",point);
383 amb 107 return(1);
384     }
385    
386     if(!option_quiet)
387     {
388 amb 219 double lat,lon;
389 amb 107
390 amb 303 if(IsFakeNode(finish))
391     GetFakeLatLong(finish,&lat,&lon);
392     else
393     GetLatLong(OSMNodes,finish,&lat,&lon);
394 amb 107
395 amb 303 if(IsFakeNode(finish))
396     printf("Point %d is segment %d (node %d -> %d): %3.6f %4.6f = %2.3f km\n",point,IndexSegment(OSMSegments,segment),node1,node2,
397 amb 315 radians_to_degrees(lon),radians_to_degrees(lat),distance_to_km(distmin));
398 amb 303 else
399     printf("Point %d is node %d: %3.6f %4.6f = %2.3f km\n",point,finish,
400 amb 315 radians_to_degrees(lon),radians_to_degrees(lat),distance_to_km(distmin));
401 amb 107 }
402    
403 amb 176 if(start==NO_NODE)
404 amb 165 continue;
405    
406 amb 239 /* Calculate the beginning of the route */
407 amb 165
408 amb 303 if(!IsFakeNode(start) && IsSuperNode(OSMNodes,start))
409 amb 126 {
410 amb 239 Result *result;
411 amb 107
412 amb 239 begin=NewResultsList(1);
413 amb 97
414 amb 239 begin->start=start;
415    
416     result=InsertResult(begin,start);
417    
418     ZeroResult(result);
419     }
420     else
421 amb 77 {
422 amb 239 begin=FindStartRoutes(OSMNodes,OSMSegments,OSMWays,start,&profile);
423 amb 2
424 amb 239 if(!begin)
425 amb 112 {
426 amb 239 fprintf(stderr,"Error: Cannot find initial section of route compatible with profile.\n");
427 amb 112 return(1);
428     }
429     }
430 amb 239
431     if(FindResult(begin,finish))
432     {
433 amb 290 FixForwardRoute(begin,finish);
434    
435 amb 303 results[point]=begin;
436 amb 305
437     if(!option_quiet)
438     {
439     printf("\rRouted: Super-Nodes Checked = %d\n",begin->number);
440     fflush(stdout);
441     }
442 amb 239 }
443 amb 34 else
444     {
445 amb 239 Results *superresults;
446 amb 48
447 amb 239 /* Calculate the end of the route */
448 amb 34
449 amb 303 if(!IsFakeNode(finish) && IsSuperNode(OSMNodes,finish))
450 amb 34 {
451     Result *result;
452    
453 amb 239 end=NewResultsList(1);
454 amb 34
455 amb 239 end->finish=finish;
456 amb 34
457 amb 239 result=InsertResult(end,finish);
458 amb 165
459 amb 166 ZeroResult(result);
460 amb 34 }
461     else
462 amb 112 {
463 amb 239 end=FindFinishRoutes(OSMNodes,OSMSegments,OSMWays,finish,&profile);
464 amb 34
465 amb 239 if(!end)
466 amb 112 {
467 amb 239 fprintf(stderr,"Error: Cannot find final section of route compatible with profile.\n");
468 amb 112 return(1);
469     }
470     }
471    
472 amb 239 /* Calculate the middle of the route */
473    
474     superresults=FindMiddleRoute(OSMNodes,OSMSegments,OSMWays,begin,end,&profile);
475    
476 amb 317 FreeResultsList(begin);
477     FreeResultsList(end);
478    
479 amb 239 if(!superresults)
480 amb 165 {
481 amb 239 fprintf(stderr,"Error: Cannot find route compatible with profile.\n");
482     return(1);
483 amb 165 }
484 amb 34
485 amb 303 results[point]=CombineRoutes(superresults,OSMNodes,OSMSegments,OSMWays,&profile);
486 amb 317
487     FreeResultsList(superresults);
488 amb 34 }
489 amb 31 }
490    
491 amb 239 /* Print out the combined route */
492 amb 164
493 amb 239 PrintRouteHead(FileName(dirname,prefix,"copyright.txt"));
494 amb 164
495 amb 317 PrintRoute(results,NWAYPOINTS,OSMNodes,OSMSegments,OSMWays,&profile);
496 amb 164
497 amb 239 PrintRouteTail();
498    
499 amb 2 return(0);
500     }
501 amb 303
502    
503     /*++++++++++++++++++++++++++++++++++++++
504     Create a pair of fake segments corresponding to the given segment split in two.
505    
506     index_t CreateFakes Returns the fake node index (or a real one in special cases).
507    
508     Nodes *nodes The set of nodes to use.
509    
510     int point Which of the waypoints is this.
511    
512     Segment *segment The segment to split.
513    
514     index_t node1 The first node at the end of this segment.
515    
516     index_t node2 The second node at the end of this segment.
517    
518     distance_t dist1 The distance to the first node.
519    
520     distance_t dist2 The distance to the second node.
521     ++++++++++++++++++++++++++++++++++++++*/
522    
523     index_t CreateFakes(Nodes *nodes,int point,Segment *segment,index_t node1,index_t node2,distance_t dist1,distance_t dist2)
524     {
525     index_t fakenode;
526     double lat1,lon1,lat2,lon2;
527    
528     /* Check if we are actually close enough to an existing node */
529    
530     if(dist1<km_to_distance(MINSEGMENT) && dist2>km_to_distance(MINSEGMENT))
531     return(node1);
532    
533     if(dist2<km_to_distance(MINSEGMENT) && dist1>km_to_distance(MINSEGMENT))
534     return(node2);
535    
536     if(dist1<km_to_distance(MINSEGMENT) && dist2<km_to_distance(MINSEGMENT))
537     {
538     if(dist1<dist2)
539     return(node1);
540     else
541     return(node2);
542     }
543    
544     /* Create the fake node */
545    
546     fakenode=point|NODE_SUPER;
547    
548     GetLatLong(nodes,node1,&lat1,&lon1);
549     GetLatLong(nodes,node2,&lat2,&lon2);
550    
551     if(lat1>3 && lat2<-3)
552     lat2+=2*M_PI;
553     else if(lat1<-3 && lat2>3)
554     lat1+=2*M_PI;
555    
556     point_lat[point]=lat1+(lat2-lat1)*(double)dist1/(double)(dist1+dist2);
557     point_lon[point]=lon1+(lon2-lon1)*(double)dist1/(double)(dist1+dist2);
558    
559     if(point_lat[point]>M_PI) point_lat[point]-=2*M_PI;
560    
561     /* Create the first fake segment */
562    
563     fake_segments[2*point-2]=*segment;
564    
565     if(segment->node1==node1)
566     fake_segments[2*point-2].node1=fakenode;
567     else
568     fake_segments[2*point-2].node2=fakenode;
569    
570     fake_segments[2*point-2].distance=DISTANCE(dist1)|DISTFLAG(segment->distance);
571    
572     /* Create the second fake segment */
573    
574     fake_segments[2*point-1]=*segment;
575    
576     if(segment->node1==node2)
577     fake_segments[2*point-1].node1=fakenode;
578     else
579     fake_segments[2*point-1].node2=fakenode;
580    
581     fake_segments[2*point-1].distance=DISTANCE(dist2)|DISTFLAG(segment->distance);
582    
583     return(fakenode);
584     }
585    
586    
587     /*++++++++++++++++++++++++++++++++++++++
588     Lookup the latitude and longitude of a fake node.
589    
590     index_t fakenode The node to lookup.
591    
592     double *latitude Returns the latitude
593    
594     double *longitude Returns the longitude.
595     ++++++++++++++++++++++++++++++++++++++*/
596    
597     void GetFakeLatLong(index_t fakenode, double *latitude,double *longitude)
598     {
599     index_t realnode=fakenode&(~NODE_SUPER);
600    
601     *latitude =point_lat[realnode];
602     *longitude=point_lon[realnode];
603     }
604    
605    
606     /*++++++++++++++++++++++++++++++++++++++
607     Finds the first fake segment associated to a fake node.
608    
609     Segment *FirstFakeSegment Returns the first fake segment.
610    
611     index_t fakenode The node to lookup.
612     ++++++++++++++++++++++++++++++++++++++*/
613    
614     Segment *FirstFakeSegment(index_t fakenode)
615     {
616     index_t realnode=fakenode&(~NODE_SUPER);
617    
618     return(&fake_segments[2*realnode-2]);
619     }
620    
621    
622     /*++++++++++++++++++++++++++++++++++++++
623     Finds the next (there can only be two) fake segment associated to a fake node.
624    
625     Segment *NextFakeSegment Returns the second fake segment.
626    
627     Segment *segment The first fake segment.
628    
629     index_t fakenode The node to lookup.
630     ++++++++++++++++++++++++++++++++++++++*/
631    
632     Segment *NextFakeSegment(Segment *segment,index_t fakenode)
633     {
634     index_t realnode=fakenode&(~NODE_SUPER);
635    
636     if(segment==&fake_segments[2*realnode-2])
637     return(&fake_segments[2*realnode-1]);
638     else
639     return(NULL);
640     }
641    
642    
643     /*++++++++++++++++++++++++++++++++++++++
644     Finds the next (there can only be two) fake segment associated to a fake node.
645    
646     Segment *ExtraFakeSegment Returns a segment between the two specified nodes if it exists.
647    
648     index_t node The real node.
649    
650     index_t fakenode The fake node to lookup.
651     ++++++++++++++++++++++++++++++++++++++*/
652    
653     Segment *ExtraFakeSegment(index_t node,index_t fakenode)
654     {
655     index_t realnode=fakenode&(~NODE_SUPER);
656    
657     if(fake_segments[2*realnode-2].node1==node || fake_segments[2*realnode-2].node2==node)
658 amb 304 return(&fake_segments[2*realnode-2]);
659 amb 303
660     if(fake_segments[2*realnode-1].node1==node || fake_segments[2*realnode-1].node2==node)
661     return(&fake_segments[2*realnode-1]);
662    
663     return(NULL);
664     }

Properties

Name Value
cvs:description Router.