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 324 - (hide annotations) (download) (as text)
Thu Mar 18 18:59:20 2010 UTC (15 years ago) by amb
File MIME type: text/x-csrc
File size: 18809 byte(s)
Allow selection of which outputs are to be created.

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

Properties

Name Value
cvs:description Router.