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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1138 - (hide annotations) (download) (as text)
Mon Nov 12 19:24:09 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 37436 byte(s)
Fix mis-use of NO_WAY/NO_WAY_ID and NO_RELATION/NO_RELATION_ID constants in
route relation handling.

1 amb 496 /***************************************
2     Extended Relation data type functions.
3    
4     Part of the Routino routing software.
5     ******************/ /******************
6 amb 948 This file Copyright 2010-2012 Andrew M. Bishop
7 amb 496
8     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     ***************************************/
21    
22    
23     #include <assert.h>
24     #include <stdlib.h>
25     #include <string.h>
26    
27 amb 542 #include "types.h"
28 amb 955 #include "segments.h"
29 amb 542 #include "relations.h"
30    
31     #include "nodesx.h"
32     #include "segmentsx.h"
33 amb 496 #include "waysx.h"
34     #include "relationsx.h"
35    
36     #include "files.h"
37 amb 519 #include "logging.h"
38 amb 532 #include "sorting.h"
39 amb 496
40    
41 amb 1108 /* Global variables */
42    
43     /*+ The command line '--tmpdir' option or its default value. +*/
44     extern char *option_tmpdirname;
45    
46 amb 680 /* Local functions */
47 amb 540
48 amb 1134 static int sort_route_by_id(RouteRelX *a,RouteRelX *b);
49     static int deduplicate_route_by_id(RouteRelX *relationx,index_t index);
50 amb 540
51 amb 1134 static int sort_turn_by_id(TurnRestrictRelX *a,TurnRestrictRelX *b);
52     static int deduplicate_turn_by_id(TurnRestrictRelX *relationx,index_t index);
53    
54 amb 1108 static int geographically_index(TurnRestrictRelX *relationx,index_t index);
55 amb 559 static int sort_by_via(TurnRestrictRelX *a,TurnRestrictRelX *b);
56 amb 540
57 amb 1108 /* Local variables */
58 amb 559
59 amb 1108 /*+ Temporary file-local variables for use by the sort functions. +*/
60     static SegmentsX *sortsegmentsx;
61     static NodesX *sortnodesx;
62 amb 496
63    
64     /*++++++++++++++++++++++++++++++++++++++
65     Allocate a new relation list (create a new file or open an existing one).
66    
67     RelationsX *NewRelationList Returns the relation list.
68    
69 amb 1123 int append Set to 1 if the file is to be opened for appending.
70    
71     int readonly Set to 1 if the file is not to be opened.
72 amb 496 ++++++++++++++++++++++++++++++++++++++*/
73    
74 amb 1123 RelationsX *NewRelationList(int append,int readonly)
75 amb 496 {
76     RelationsX *relationsx;
77    
78     relationsx=(RelationsX*)calloc(1,sizeof(RelationsX));
79    
80     assert(relationsx); /* Check calloc() worked */
81    
82 amb 540
83 amb 559 /* Route Relations */
84    
85 amb 1120 relationsx->rfilename =(char*)malloc(strlen(option_tmpdirname)+32);
86     relationsx->rfilename_tmp=(char*)malloc(strlen(option_tmpdirname)+32);
87 amb 496
88 amb 1120 sprintf(relationsx->rfilename ,"%s/relationsx.route.parsed.mem",option_tmpdirname);
89     sprintf(relationsx->rfilename_tmp,"%s/relationsx.route.%p.tmp" ,option_tmpdirname,(void*)relationsx);
90 amb 496
91 amb 1123 if(append || readonly)
92     if(ExistsFile(relationsx->rfilename))
93     {
94     off_t size,position=0;
95     int rfd;
96 amb 496
97 amb 1123 size=SizeFile(relationsx->rfilename);
98 amb 496
99 amb 1123 rfd=ReOpenFile(relationsx->rfilename);
100 amb 496
101 amb 1123 while(position<size)
102     {
103     FILESORT_VARINT relationsize;
104 amb 496
105 amb 1123 SeekReadFile(rfd,&relationsize,FILESORT_VARSIZE,position);
106 amb 496
107 amb 1123 relationsx->rnumber++;
108     position+=relationsize+FILESORT_VARSIZE;
109     }
110    
111     CloseFile(rfd);
112 amb 496 }
113    
114 amb 1123 if(append)
115     relationsx->rfd=OpenFileAppend(relationsx->rfilename);
116     else if(!readonly)
117     relationsx->rfd=OpenFileNew(relationsx->rfilename);
118 amb 496 else
119 amb 1123 relationsx->rfd=-1;
120 amb 496
121 amb 540
122 amb 559 /* Turn Restriction Relations */
123    
124 amb 1120 relationsx->trfilename =(char*)malloc(strlen(option_tmpdirname)+32);
125     relationsx->trfilename_tmp=(char*)malloc(strlen(option_tmpdirname)+32);
126 amb 540
127 amb 1120 sprintf(relationsx->trfilename ,"%s/relationsx.turn.parsed.mem",option_tmpdirname);
128     sprintf(relationsx->trfilename_tmp,"%s/relationsx.turn.%p.tmp" ,option_tmpdirname,(void*)relationsx);
129 amb 540
130 amb 1123 if(append || readonly)
131     if(ExistsFile(relationsx->trfilename))
132     {
133     off_t size;
134 amb 540
135 amb 1123 size=SizeFile(relationsx->trfilename);
136 amb 540
137 amb 1123 relationsx->trnumber=size/sizeof(TurnRestrictRelX);
138     }
139 amb 540
140 amb 1123 if(append)
141     relationsx->trfd=OpenFileAppend(relationsx->trfilename);
142     else if(!readonly)
143     relationsx->trfd=OpenFileNew(relationsx->trfilename);
144 amb 540 else
145 amb 1123 relationsx->trfd=-1;
146 amb 540
147 amb 496 return(relationsx);
148     }
149    
150    
151     /*++++++++++++++++++++++++++++++++++++++
152     Free a relation list.
153    
154 amb 681 RelationsX *relationsx The set of relations to be freed.
155 amb 496 ++++++++++++++++++++++++++++++++++++++*/
156    
157 amb 1136 void FreeRelationList(RelationsX *relationsx)
158 amb 496 {
159 amb 540 /* Route relations */
160    
161 amb 1120 DeleteFile(relationsx->rfilename_tmp);
162    
163 amb 496 free(relationsx->rfilename);
164 amb 1120 free(relationsx->rfilename_tmp);
165 amb 496
166 amb 559
167 amb 540 /* Turn Restriction relations */
168    
169 amb 1120 DeleteFile(relationsx->trfilename_tmp);
170    
171 amb 540 free(relationsx->trfilename);
172 amb 1120 free(relationsx->trfilename_tmp);
173 amb 540
174 amb 496 free(relationsx);
175     }
176    
177    
178     /*++++++++++++++++++++++++++++++++++++++
179     Append a single relation to an unsorted route relation list.
180    
181     RelationsX* relationsx The set of relations to process.
182    
183     relation_t id The ID of the relation.
184    
185 amb 529 transports_t routes The types of routes that this relation is for.
186 amb 496
187     way_t *ways The array of ways that are members of the relation.
188    
189     int nways The number of ways that are members of the relation.
190    
191     relation_t *relations The array of relations that are members of the relation.
192    
193     int nrelations The number of relations that are members of the relation.
194     ++++++++++++++++++++++++++++++++++++++*/
195    
196 amb 540 void AppendRouteRelation(RelationsX* relationsx,relation_t id,
197     transports_t routes,
198 amb 496 way_t *ways,int nways,
199     relation_t *relations,int nrelations)
200     {
201     RouteRelX relationx;
202 amb 505 FILESORT_VARINT size;
203 amb 1138 way_t noway=NO_WAY_ID;
204     relation_t norelation=NO_RELATION_ID;
205 amb 496
206     relationx.id=id;
207     relationx.routes=routes;
208    
209     size=sizeof(RouteRelX)+(nways+1)*sizeof(way_t)+(nrelations+1)*sizeof(relation_t);
210    
211 amb 505 WriteFile(relationsx->rfd,&size,FILESORT_VARSIZE);
212 amb 496 WriteFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
213    
214 amb 805 WriteFile(relationsx->rfd,ways ,nways*sizeof(way_t));
215     WriteFile(relationsx->rfd,&noway, sizeof(way_t));
216 amb 496
217 amb 805 WriteFile(relationsx->rfd,relations ,nrelations*sizeof(relation_t));
218     WriteFile(relationsx->rfd,&norelation, sizeof(relation_t));
219 amb 496
220 amb 650 relationsx->rnumber++;
221 amb 496
222 amb 1065 assert(relationsx->rnumber!=0); /* Zero marks the high-water mark for relations. */
223 amb 496 }
224    
225    
226     /*++++++++++++++++++++++++++++++++++++++
227 amb 540 Append a single relation to an unsorted turn restriction relation list.
228    
229     RelationsX* relationsx The set of relations to process.
230    
231     relation_t id The ID of the relation.
232    
233     way_t from The way that the turn restriction starts from.
234    
235     way_t to The way that the restriction finished on.
236    
237     node_t via The node that the turn restriction passes through.
238    
239     TurnRestriction restriction The type of restriction.
240    
241     transports_t except The set of transports allowed to bypass the restriction.
242     ++++++++++++++++++++++++++++++++++++++*/
243    
244     void AppendTurnRestrictRelation(RelationsX* relationsx,relation_t id,
245     way_t from,way_t to,node_t via,
246     TurnRestriction restriction,transports_t except)
247     {
248 amb 951 TurnRestrictRelX relationx={0};
249 amb 540
250     relationx.id=id;
251     relationx.from=from;
252     relationx.to=to;
253     relationx.via=via;
254 amb 786 relationx.restriction=restriction;
255 amb 540 relationx.except=except;
256    
257     WriteFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
258    
259 amb 650 relationsx->trnumber++;
260 amb 540
261 amb 1065 assert(relationsx->trnumber!=0); /* Zero marks the high-water mark for relations. */
262 amb 540 }
263    
264    
265     /*++++++++++++++++++++++++++++++++++++++
266 amb 1120 Finish appending relations and change the filename over.
267 amb 496
268 amb 1120 RelationsX *relationsx The relations that have been appended.
269 amb 496 ++++++++++++++++++++++++++++++++++++++*/
270    
271 amb 1120 void FinishRelationList(RelationsX *relationsx)
272 amb 496 {
273 amb 559 /* Close the files (finished appending) */
274 amb 540
275 amb 1136 if(relationsx->rfd!=-1)
276     relationsx->rfd =CloseFile(relationsx->rfd);
277 amb 540
278 amb 1136 if(relationsx->trfd!=-1)
279     relationsx->trfd=CloseFile(relationsx->trfd);
280    
281 amb 1120 /* Rename the files to the temporary names (used everywhere else) */
282 amb 559
283 amb 1120 RenameFile(relationsx->rfilename ,relationsx->rfilename_tmp);
284     RenameFile(relationsx->trfilename,relationsx->trfilename_tmp);
285     }
286    
287    
288     /*++++++++++++++++++++++++++++++++++++++
289     Sort the list of relations.
290    
291     RelationsX* relationsx The set of relations to process.
292     ++++++++++++++++++++++++++++++++++++++*/
293    
294     void SortRelationList(RelationsX* relationsx)
295     {
296 amb 559 /* Route Relations */
297    
298 amb 1134 if(relationsx->rnumber)
299     {
300     index_t rxnumber;
301     int rfd;
302    
303     /* Print the start message */
304    
305     printf_first("Sorting Route Relations");
306    
307     /* Re-open the file read-only and a new file writeable */
308    
309     relationsx->rfd=ReOpenFile(relationsx->rfilename_tmp);
310    
311     DeleteFile(relationsx->rfilename_tmp);
312    
313     rfd=OpenFileNew(relationsx->rfilename_tmp);
314    
315     /* Sort the relations */
316    
317     rxnumber=relationsx->rnumber;
318    
319     relationsx->rnumber=filesort_vary(relationsx->rfd,rfd,NULL,
320     (int (*)(const void*,const void*))sort_route_by_id,
321     (int (*)(void*,index_t))deduplicate_route_by_id);
322    
323     /* Close the files */
324    
325     relationsx->rfd=CloseFile(relationsx->rfd);
326     CloseFile(rfd);
327    
328     /* Print the final message */
329    
330     printf_last("Sorted Route Relations: Relations=%"Pindex_t" Duplicates=%"Pindex_t,rxnumber,rxnumber-relationsx->rnumber);
331     }
332    
333 amb 559 /* Turn Restriction Relations. */
334    
335 amb 650 if(relationsx->trnumber)
336 amb 551 {
337 amb 650 index_t trxnumber;
338 amb 551 int trfd;
339 amb 540
340 amb 551 /* Print the start message */
341 amb 540
342 amb 895 printf_first("Sorting Turn Relations");
343 amb 540
344 amb 555 /* Re-open the file read-only and a new file writeable */
345    
346 amb 1120 relationsx->trfd=ReOpenFile(relationsx->trfilename_tmp);
347 amb 555
348 amb 1120 DeleteFile(relationsx->trfilename_tmp);
349 amb 540
350 amb 1120 trfd=OpenFileNew(relationsx->trfilename_tmp);
351 amb 540
352 amb 551 /* Sort the relations */
353 amb 540
354 amb 650 trxnumber=relationsx->trnumber;
355    
356 amb 1106 relationsx->trnumber=filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRestrictRelX),NULL,
357 amb 1134 (int (*)(const void*,const void*))sort_turn_by_id,
358     (int (*)(void*,index_t))deduplicate_turn_by_id);
359 amb 540
360 amb 555 /* Close the files */
361 amb 540
362 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
363 amb 551 CloseFile(trfd);
364 amb 540
365 amb 551 /* Print the final message */
366 amb 540
367 amb 895 printf_last("Sorted Turn Relations: Relations=%"Pindex_t" Duplicates=%"Pindex_t,trxnumber,trxnumber-relationsx->trnumber);
368 amb 551 }
369 amb 496 }
370    
371    
372     /*++++++++++++++++++++++++++++++++++++++
373 amb 1134 Sort the route relations into id order.
374    
375     int sort_route_by_id Returns the comparison of the id fields.
376    
377     RouteRelX *a The first extended relation.
378    
379     RouteRelX *b The second extended relation.
380     ++++++++++++++++++++++++++++++++++++++*/
381    
382     static int sort_route_by_id(RouteRelX *a,RouteRelX *b)
383     {
384     relation_t a_id=a->id;
385     relation_t b_id=b->id;
386    
387     if(a_id<b_id)
388     return(-1);
389     else if(a_id>b_id)
390     return(1);
391     else
392     return(FILESORT_PRESERVE_ORDER(a,b));
393     }
394    
395    
396     /*++++++++++++++++++++++++++++++++++++++
397     Deduplicate the route relations using the id after sorting.
398    
399     int deduplicate_route_by_id Return 1 if the value is to be kept, otherwise 0.
400    
401     RouteRelX *relationx The extended relation.
402    
403     index_t index The number of sorted relations that have already been written to the output file.
404     ++++++++++++++++++++++++++++++++++++++*/
405    
406     static int deduplicate_route_by_id(RouteRelX *relationx,index_t index)
407     {
408     static relation_t previd;
409    
410     if(index==0 || relationx->id!=previd)
411     {
412     previd=relationx->id;
413    
414     return(1);
415     }
416     else
417     {
418     logerror("Relation %"Prelation_t" is duplicated.\n",relationx->id);
419    
420     return(0);
421     }
422     }
423    
424    
425     /*++++++++++++++++++++++++++++++++++++++
426 amb 559 Sort the turn restriction relations into id order.
427 amb 540
428 amb 1134 int sort_turn_by_id Returns the comparison of the id fields.
429 amb 540
430     TurnRestrictRelX *a The first extended relation.
431    
432     TurnRestrictRelX *b The second extended relation.
433     ++++++++++++++++++++++++++++++++++++++*/
434    
435 amb 1134 static int sort_turn_by_id(TurnRestrictRelX *a,TurnRestrictRelX *b)
436 amb 540 {
437 amb 559 relation_t a_id=a->id;
438     relation_t b_id=b->id;
439 amb 540
440     if(a_id<b_id)
441     return(-1);
442     else if(a_id>b_id)
443     return(1);
444     else
445 amb 1118 return(FILESORT_PRESERVE_ORDER(a,b));
446 amb 540 }
447    
448    
449     /*++++++++++++++++++++++++++++++++++++++
450 amb 1134 Deduplicate the turn restriction relations using the id after sorting.
451 amb 540
452 amb 1134 int deduplicate_turn_by_id Return 1 if the value is to be kept, otherwise 0.
453 amb 540
454     TurnRestrictRelX *relationx The extended relation.
455    
456 amb 1106 index_t index The number of sorted relations that have already been written to the output file.
457 amb 540 ++++++++++++++++++++++++++++++++++++++*/
458    
459 amb 1134 static int deduplicate_turn_by_id(TurnRestrictRelX *relationx,index_t index)
460 amb 540 {
461     static relation_t previd;
462    
463     if(index==0 || relationx->id!=previd)
464     {
465     previd=relationx->id;
466    
467     return(1);
468     }
469 amb 812 else
470     {
471     logerror("Relation %"Prelation_t" is duplicated.\n",relationx->id);
472 amb 540
473 amb 812 return(0);
474     }
475 amb 540 }
476    
477    
478     /*++++++++++++++++++++++++++++++++++++++
479 amb 496 Process the route relations and apply the information to the ways.
480    
481 amb 681 RelationsX *relationsx The set of relations to use.
482 amb 496
483 amb 681 WaysX *waysx The set of ways to modify.
484 amb 1136
485     int preserve If set to 1 then keep the old data file otherwise delete it.
486 amb 496 ++++++++++++++++++++++++++++++++++++++*/
487    
488 amb 1136 void ProcessRouteRelations(RelationsX *relationsx,WaysX *waysx,int preserve)
489 amb 496 {
490 amb 505 RouteRelX *unmatched=NULL,*lastunmatched=NULL;
491 amb 761 int nunmatched=0,lastnunmatched=0,iteration=1;
492 amb 496
493 amb 510 if(waysx->number==0)
494 amb 508 return;
495    
496 amb 555 /* Map into memory / open the files */
497 amb 496
498 amb 505 #if !SLIM
499 amb 1120 waysx->data=MapFileWriteable(waysx->filename_tmp);
500 amb 555 #else
501 amb 1120 waysx->fd=ReOpenFileWriteable(waysx->filename_tmp);
502 amb 505 #endif
503 amb 496
504 amb 555 /* Re-open the file read-only */
505 amb 548
506 amb 1120 relationsx->rfd=ReOpenFile(relationsx->rfilename_tmp);
507 amb 548
508 amb 542 /* Read through the file. */
509 amb 496
510 amb 505 do
511 amb 496 {
512 amb 522 int ways=0,relations=0;
513 amb 780 index_t i;
514 amb 522
515 amb 505 SeekFile(relationsx->rfd,0);
516 amb 496
517 amb 505 /* Print the start message */
518 amb 496
519 amb 761 printf_first("Processing Route Relations (%d): Relations=0 Modified Ways=0",iteration);
520 amb 496
521 amb 650 for(i=0;i<relationsx->rnumber;i++)
522 amb 496 {
523 amb 505 FILESORT_VARINT size;
524     RouteRelX relationx;
525     way_t wayid;
526     relation_t relationid;
527 amb 529 transports_t routes=Transports_None;
528 amb 496
529 amb 505 /* Read each route relation */
530 amb 496
531 amb 505 ReadFile(relationsx->rfd,&size,FILESORT_VARSIZE);
532     ReadFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
533 amb 496
534 amb 505 /* Decide what type of route it is */
535 amb 496
536 amb 761 if(iteration==1)
537 amb 522 {
538     relations++;
539 amb 505 routes=relationx.routes;
540 amb 522 }
541 amb 505 else
542 amb 506 {
543 amb 522 int j;
544    
545     for(j=0;j<lastnunmatched;j++)
546     if(lastunmatched[j].id==relationx.id)
547     {
548     relations++;
549    
550     if((lastunmatched[j].routes|relationx.routes)==relationx.routes)
551     routes=0; /* Nothing new to add */
552     else
553 amb 506 routes=lastunmatched[j].routes;
554 amb 806
555 amb 522 break;
556     }
557 amb 506 }
558 amb 496
559 amb 505 /* Loop through the ways */
560    
561     do
562     {
563     ReadFile(relationsx->rfd,&wayid,sizeof(way_t));
564    
565     /* Update the ways that are listed for the relation */
566    
567 amb 1138 if(wayid==NO_WAY_ID)
568 amb 806 continue;
569    
570     if(routes)
571 amb 505 {
572 amb 506 index_t way=IndexWayX(waysx,wayid);
573 amb 505
574     if(way!=NO_WAY)
575     {
576     WayX *wayx=LookupWayX(waysx,way,1);
577    
578 amb 529 if(routes&Transports_Foot)
579 amb 995 {
580 amb 1064 if(!(wayx->way.allow&Transports_Foot))
581     {
582     logerror("Route Relation %"Prelation_t" for Foot contains Way %"Pway_t" that does not allow Foot transport; overriding.\n",relationx.id,wayid);
583     wayx->way.allow|=Transports_Foot;
584     }
585 amb 505 wayx->way.props|=Properties_FootRoute;
586 amb 995 }
587 amb 505
588 amb 529 if(routes&Transports_Bicycle)
589 amb 995 {
590 amb 1064 if(!(wayx->way.allow&Transports_Bicycle))
591     {
592     logerror("Route Relation %"Prelation_t" for Bicycle contains Way %"Pway_t" that does not allow Bicycle transport; overriding.\n",relationx.id,wayid);
593     wayx->way.allow|=Transports_Bicycle;
594     }
595 amb 505 wayx->way.props|=Properties_BicycleRoute;
596 amb 995 }
597 amb 505
598 amb 942 PutBackWayX(waysx,wayx);
599 amb 522
600     ways++;
601 amb 505 }
602 amb 812 else
603 amb 832 logerror("Route Relation %"Prelation_t" contains Way %"Pway_t" but it does not exist in the Routino database.\n",relationx.id,wayid);
604 amb 505 }
605     }
606 amb 1138 while(wayid!=NO_WAY_ID);
607 amb 505
608     /* Loop through the relations */
609    
610     do
611     {
612     ReadFile(relationsx->rfd,&relationid,sizeof(relation_t));
613    
614     /* Add the relations that are listed for this relation to the list for next time */
615    
616 amb 1138 if(relationid==NO_RELATION_ID)
617 amb 806 continue;
618    
619 amb 812 if(relationid==relationx.id)
620     logerror("Relation %"Prelation_t" contains itself.\n",relationx.id);
621     else if(routes)
622 amb 505 {
623     if(nunmatched%256==0)
624     unmatched=(RouteRelX*)realloc((void*)unmatched,(nunmatched+256)*sizeof(RouteRelX));
625    
626     unmatched[nunmatched].id=relationid;
627     unmatched[nunmatched].routes=routes;
628    
629     nunmatched++;
630     }
631     }
632 amb 1138 while(relationid!=NO_RELATION_ID);
633 amb 505
634 amb 757 if(!((i+1)%1000))
635 amb 790 printf_middle("Processing Route Relations (%d): Relations=%"Pindex_t" Modified Ways=%"Pindex_t,iteration,relations,ways);
636 amb 496 }
637    
638 amb 505 if(lastunmatched)
639     free(lastunmatched);
640    
641     lastunmatched=unmatched;
642     lastnunmatched=nunmatched;
643    
644     unmatched=NULL;
645     nunmatched=0;
646    
647     /* Print the final message */
648    
649 amb 790 printf_last("Processed Route Relations (%d): Relations=%"Pindex_t" Modified Ways=%"Pindex_t,iteration,relations,ways);
650 amb 496 }
651 amb 812 while(lastnunmatched && iteration++<8);
652 amb 496
653 amb 505 if(lastunmatched)
654     free(lastunmatched);
655    
656 amb 555 /* Close the file */
657    
658 amb 612 relationsx->rfd=CloseFile(relationsx->rfd);
659 amb 496
660 amb 1136 if(preserve)
661     RenameFile(relationsx->rfilename_tmp,relationsx->rfilename);
662    
663 amb 555 /* Unmap from memory / close the files */
664 amb 496
665 amb 505 #if !SLIM
666 amb 1122 waysx->data=UnmapFile(waysx->data);
667 amb 555 #else
668 amb 612 waysx->fd=CloseFile(waysx->fd);
669 amb 511 #endif
670 amb 496 }
671 amb 542
672    
673     /*++++++++++++++++++++++++++++++++++++++
674 amb 645 Process the turn relations (first part) to update them with the node/way information.
675 amb 542
676 amb 681 RelationsX *relationsx The set of relations to modify.
677 amb 542
678 amb 680 NodesX *nodesx The set of nodes to use.
679 amb 542
680 amb 680 WaysX *waysx The set of ways to use.
681 amb 1136
682     int preserve If set to 1 then keep the old data file otherwise delete it.
683 amb 645 ++++++++++++++++++++++++++++++++++++++*/
684    
685 amb 1136 void ProcessTurnRelations1(RelationsX *relationsx,NodesX *nodesx,WaysX *waysx,int preserve)
686 amb 645 {
687 amb 780 int trfd;
688     index_t i,deleted=0;
689 amb 645
690     /* Print the start message */
691    
692 amb 761 printf_first("Processing Turn Relations (1): Relations=0");
693 amb 645
694     /* Re-open the file read-only and a new file writeable */
695    
696 amb 1120 relationsx->trfd=ReOpenFile(relationsx->trfilename_tmp);
697 amb 645
698 amb 1136 if(preserve)
699     RenameFile(relationsx->trfilename_tmp,relationsx->trfilename);
700     else
701     DeleteFile(relationsx->trfilename_tmp);
702 amb 645
703 amb 1120 trfd=OpenFileNew(relationsx->trfilename_tmp);
704 amb 645
705     /* Process all of the relations */
706    
707     for(i=0;i<relationsx->trnumber;i++)
708     {
709     TurnRestrictRelX relationx;
710 amb 1138 index_t via,from,to;
711 amb 645
712     ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
713    
714 amb 812 via =IndexNodeX(nodesx,relationx.via);
715     from=IndexWayX(waysx,relationx.from);
716     to =IndexWayX(waysx,relationx.to);
717 amb 645
718 amb 812 if(via==NO_NODE)
719 amb 832 logerror("Turn Relation %"Prelation_t" contains Node %"Pnode_t" but it does not exist in the Routino database.\n",relationx.id,relationx.via);
720 amb 812
721     if(from==NO_WAY)
722 amb 832 logerror("Turn Relation %"Prelation_t" contains Way %"Pway_t" but it does not exist in the Routino database.\n",relationx.id,relationx.from);
723 amb 812
724     if(to==NO_WAY)
725 amb 832 logerror("Turn Relation %"Prelation_t" contains Way %"Pway_t" but it does not exist in the Routino database.\n",relationx.id,relationx.to);
726 amb 812
727     relationx.via =via;
728     relationx.from=from;
729     relationx.to =to;
730    
731 amb 756 if(relationx.via==NO_NODE || relationx.from==NO_WAY || relationx.to==NO_WAY)
732     deleted++;
733     else
734     WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
735 amb 645
736 amb 757 if(!((i+1)%1000))
737 amb 1100 printf_middle("Processing Turn Relations (1): Relations=%"Pindex_t" Deleted=%"Pindex_t,i+1,deleted);
738 amb 645 }
739    
740     /* Close the files */
741    
742     relationsx->trfd=CloseFile(relationsx->trfd);
743     CloseFile(trfd);
744    
745     /* Print the final message */
746    
747 amb 1100 printf_last("Processed Turn Relations (1): Relations=%"Pindex_t" Deleted=%"Pindex_t,relationsx->trnumber,deleted);
748 amb 756
749     relationsx->trnumber-=deleted;
750 amb 645 }
751    
752    
753     /*++++++++++++++++++++++++++++++++++++++
754     Process the turn relations (second part) to convert them to nodes.
755    
756 amb 681 RelationsX *relationsx The set of relations to modify.
757 amb 645
758 amb 680 NodesX *nodesx The set of nodes to use.
759 amb 645
760 amb 680 SegmentsX *segmentsx The set of segments to use.
761 amb 542
762 amb 680 WaysX *waysx The set of ways to use.
763 amb 542 ++++++++++++++++++++++++++++++++++++++*/
764    
765 amb 645 void ProcessTurnRelations2(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx)
766 amb 542 {
767 amb 548 TurnRestrictRelX relationx;
768 amb 542 int trfd;
769 amb 780 index_t total=0,deleted=0;
770 amb 542
771 amb 548 if(nodesx->number==0 || segmentsx->number==0)
772     return;
773    
774 amb 542 /* Print the start message */
775    
776 amb 761 printf_first("Processing Turn Relations (2): Relations=0");
777 amb 542
778 amb 555 /* Map into memory / open the files */
779 amb 548
780     #if !SLIM
781 amb 1120 nodesx->data=MapFileWriteable(nodesx->filename_tmp);
782     segmentsx->data=MapFile(segmentsx->filename_tmp);
783     waysx->data=MapFile(waysx->filename_tmp);
784 amb 555 #else
785 amb 1120 nodesx->fd=ReOpenFileWriteable(nodesx->filename_tmp);
786     segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
787     waysx->fd=ReOpenFile(waysx->filename_tmp);
788 amb 548 #endif
789    
790 amb 555 /* Re-open the file read-only and a new file writeable */
791    
792 amb 1120 relationsx->trfd=ReOpenFile(relationsx->trfilename_tmp);
793 amb 548
794 amb 1120 DeleteFile(relationsx->trfilename_tmp);
795 amb 542
796 amb 1120 trfd=OpenFileNew(relationsx->trfilename_tmp);
797 amb 542
798     /* Process all of the relations */
799    
800 amb 548 while(!ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX)))
801 amb 542 {
802 amb 615 NodeX *nodex;
803 amb 645 SegmentX *segmentx;
804 amb 615
805 amb 786 if(relationx.restriction==TurnRestrict_no_right_turn ||
806     relationx.restriction==TurnRestrict_no_left_turn ||
807     relationx.restriction==TurnRestrict_no_u_turn ||
808     relationx.restriction==TurnRestrict_no_straight_on)
809 amb 548 {
810 amb 770 index_t node_from=NO_NODE,node_to=NO_NODE;
811 amb 806 int oneway_from=0,oneway_to=0,vehicles_from=1,vehicles_to=1;
812 amb 542
813 amb 548 /* Find the segments that join the node 'via' */
814 amb 542
815 amb 646 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
816 amb 542
817 amb 742 while(segmentx)
818 amb 548 {
819 amb 645 if(segmentx->way==relationx.from)
820 amb 548 {
821 amb 806 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
822    
823 amb 551 if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
824 amb 742 {
825 amb 832 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'from' way.\n",relationx.id);
826 amb 742 deleted++;
827 amb 551 goto endloop;
828 amb 742 }
829 amb 548
830 amb 645 node_from=OtherNode(segmentx,relationx.via);
831 amb 806
832     if(IsOnewayFrom(segmentx,relationx.via))
833     oneway_from=1; /* not allowed */
834    
835 amb 837 if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
836 amb 806 vehicles_from=0; /* not allowed */
837 amb 548 }
838    
839 amb 645 if(segmentx->way==relationx.to)
840 amb 548 {
841 amb 806 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
842    
843 amb 551 if(node_to!=NO_NODE) /* Only one segment can be on the 'to' way */
844 amb 742 {
845 amb 832 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'to' way.\n",relationx.id);
846 amb 742 deleted++;
847 amb 551 goto endloop;
848 amb 742 }
849 amb 548
850 amb 806 node_to=OtherNode(segmentx,relationx.via);
851 amb 670
852 amb 806 if(IsOnewayTo(segmentx,relationx.via))
853     oneway_to=1; /* not allowed */
854    
855 amb 837 if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
856 amb 806 vehicles_to=0; /* not allowed */
857 amb 548 }
858    
859 amb 943 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via);
860 amb 548 }
861    
862 amb 812 if(node_from==NO_NODE)
863 amb 832 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'from' way.\n",relationx.id);
864 amb 812
865     if(node_to==NO_NODE)
866 amb 832 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'to' way.\n",relationx.id);
867 amb 812
868     if(oneway_from)
869     logerror("Turn Relation %"Prelation_t" is not stored because the 'from' way is oneway away from the 'via' node.\n",relationx.id);
870    
871     if(oneway_to)
872     logerror("Turn Relation %"Prelation_t" is not needed because the 'to' way is oneway towards the 'via' node.\n",relationx.id);
873    
874     if(!vehicles_from)
875 amb 837 logerror("Turn Relation %"Prelation_t" is not stored because the 'from' way does not allow vehicles.\n",relationx.id);
876 amb 812
877     if(!vehicles_to)
878 amb 837 logerror("Turn Relation %"Prelation_t" is not needed because the 'to' way does not allow vehicles.\n",relationx.id);
879 amb 812
880 amb 806 if(oneway_from || oneway_to || !vehicles_from || !vehicles_to || node_from==NO_NODE || node_to==NO_NODE)
881 amb 742 {
882     deleted++;
883 amb 548 goto endloop;
884 amb 742 }
885 amb 548
886 amb 551 /* Write the results */
887 amb 548
888 amb 645 relationx.from=node_from;
889     relationx.to =node_to;
890 amb 548
891 amb 551 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
892 amb 548
893 amb 559 total++;
894 amb 548
895 amb 757 if(!(total%1000))
896 amb 790 printf_middle("Processing Turn Relations (2): Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,total,deleted,total-relationsx->trnumber+deleted);
897 amb 551 }
898     else
899     {
900 amb 806 index_t node_from=NO_NODE,node_to=NO_NODE,node_other[MAX_SEG_PER_NODE];
901     int nnodes_other=0,i;
902     int oneway_from=0,vehicles_from=1;
903 amb 548
904 amb 551 /* Find the segments that join the node 'via' */
905 amb 548
906 amb 646 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
907 amb 548
908 amb 742 while(segmentx)
909 amb 551 {
910 amb 645 if(segmentx->way==relationx.from)
911 amb 551 {
912 amb 806 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
913    
914 amb 551 if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
915 amb 742 {
916 amb 832 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'from' way.\n",relationx.id);
917 amb 742 deleted++;
918 amb 548 goto endloop;
919 amb 742 }
920 amb 548
921 amb 645 node_from=OtherNode(segmentx,relationx.via);
922 amb 806
923     if(IsOnewayFrom(segmentx,relationx.via))
924     oneway_from=1; /* not allowed */
925    
926 amb 837 if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
927 amb 806 vehicles_from=0; /* not allowed */
928 amb 548 }
929 amb 551
930 amb 806 if(segmentx->way==relationx.to)
931 amb 551 {
932 amb 806 if(node_to!=NO_NODE) /* Only one segment can be on the 'to' way */
933     {
934 amb 832 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'to' way.\n",relationx.id);
935 amb 806 deleted++;
936     goto endloop;
937     }
938 amb 551
939 amb 806 node_to=OtherNode(segmentx,relationx.via);
940     }
941 amb 670
942 amb 806 if(segmentx->way!=relationx.from && segmentx->way!=relationx.to)
943     {
944     WayX *wayx=LookupWayX(waysx,segmentx->way,1);
945    
946     if(IsOnewayTo(segmentx,relationx.via))
947     ; /* not allowed */
948 amb 837 else if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
949 amb 806 ; /* not allowed */
950     else
951 amb 812 {
952     assert(nnodes_other<MAX_SEG_PER_NODE); /* Only a limited amount of information stored. */
953    
954 amb 806 node_other[nnodes_other++]=OtherNode(segmentx,relationx.via);
955 amb 812 }
956 amb 551 }
957    
958 amb 943 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via);
959 amb 548 }
960    
961 amb 812 if(node_from==NO_NODE)
962 amb 832 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'from' way.\n",relationx.id);
963 amb 812
964     if(node_to==NO_NODE)
965 amb 832 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'to' way.\n",relationx.id);
966 amb 812
967     if(nnodes_other==0)
968     logerror("Turn Relation %"Prelation_t" is not needed because the only allowed exit from the 'via' node is the 'to' way.\n",relationx.id);
969    
970     if(oneway_from)
971 amb 832 logerror("Turn Relation %"Prelation_t" is not needed because the 'from' way is oneway away from the 'via' node.\n",relationx.id);
972 amb 812
973     if(!vehicles_from)
974 amb 837 logerror("Turn Relation %"Prelation_t" is not stored because the 'from' way does not allow vehicles.\n",relationx.id);
975 amb 812
976 amb 806 if(oneway_from || !vehicles_from || node_from==NO_NODE || node_to==NO_NODE || nnodes_other==0)
977 amb 742 {
978     deleted++;
979 amb 548 goto endloop;
980 amb 742 }
981 amb 548
982     /* Write the results */
983    
984 amb 806 for(i=0;i<nnodes_other;i++)
985 amb 551 {
986 amb 645 relationx.from=node_from;
987 amb 806 relationx.to =node_other[i];
988 amb 548
989 amb 551 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
990 amb 548
991 amb 559 total++;
992 amb 548
993 amb 757 if(!(total%1000))
994 amb 790 printf_middle("Processing Turn Relations (2): Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,total,deleted,total-relationsx->trnumber+deleted);
995 amb 551 }
996 amb 615 }
997 amb 560
998 amb 615 /* Force super nodes on via node and adjacent nodes */
999    
1000     nodex=LookupNodeX(nodesx,relationx.via,1);
1001     nodex->flags|=NODE_TURNRSTRCT;
1002 amb 942 PutBackNodeX(nodesx,nodex);
1003 amb 615
1004 amb 646 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
1005 amb 615
1006 amb 742 while(segmentx)
1007 amb 615 {
1008 amb 645 index_t othernode=OtherNode(segmentx,relationx.via);
1009 amb 615
1010     nodex=LookupNodeX(nodesx,othernode,1);
1011 amb 597 nodex->flags|=NODE_TURNRSTRCT2;
1012 amb 942 PutBackNodeX(nodesx,nodex);
1013 amb 597
1014 amb 943 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via);
1015 amb 548 }
1016    
1017     endloop: ;
1018 amb 542 }
1019    
1020 amb 555 /* Close the files */
1021 amb 542
1022 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
1023 amb 542 CloseFile(trfd);
1024    
1025 amb 555 /* Unmap from memory / close the files */
1026 amb 542
1027 amb 548 #if !SLIM
1028 amb 1122 nodesx->data=UnmapFile(nodesx->data);
1029     segmentsx->data=UnmapFile(segmentsx->data);
1030     waysx->data=UnmapFile(waysx->data);
1031 amb 555 #else
1032 amb 612 nodesx->fd=CloseFile(nodesx->fd);
1033     segmentsx->fd=CloseFile(segmentsx->fd);
1034 amb 806 waysx->fd=CloseFile(waysx->fd);
1035 amb 548 #endif
1036    
1037 amb 542 /* Print the final message */
1038    
1039 amb 790 printf_last("Processed Turn Relations (2): Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,total,deleted,total-relationsx->trnumber+deleted);
1040 amb 559
1041     relationsx->trnumber=total;
1042 amb 542 }
1043    
1044    
1045     /*++++++++++++++++++++++++++++++++++++++
1046 amb 1098 Remove pruned turn relations and update the node indexes after pruning nodes.
1047 amb 542
1048 amb 681 RelationsX *relationsx The set of relations to modify.
1049 amb 542
1050 amb 665 NodesX *nodesx The set of nodes to use.
1051 amb 1098 ++++++++++++++++++++++++++++++++++++++*/
1052 amb 665
1053 amb 1098 void RemovePrunedTurnRelations(RelationsX *relationsx,NodesX *nodesx)
1054     {
1055     TurnRestrictRelX relationx;
1056     index_t total=0,pruned=0,notpruned=0;
1057     int trfd;
1058    
1059     /* Print the start message */
1060    
1061     printf_first("Deleting Pruned Turn Relations: Relations=0 Pruned=0");
1062    
1063     /* Re-open the file read-only and a new file writeable */
1064    
1065 amb 1120 relationsx->trfd=ReOpenFile(relationsx->trfilename_tmp);
1066 amb 1098
1067 amb 1120 DeleteFile(relationsx->trfilename_tmp);
1068 amb 1098
1069 amb 1120 trfd=OpenFileNew(relationsx->trfilename_tmp);
1070 amb 1098
1071     /* Process all of the relations */
1072    
1073     while(!ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX)))
1074     {
1075     relationx.from=nodesx->pdata[relationx.from];
1076     relationx.via =nodesx->pdata[relationx.via];
1077     relationx.to =nodesx->pdata[relationx.to];
1078    
1079     if(relationx.from==NO_NODE || relationx.via==NO_NODE || relationx.to==NO_NODE)
1080     pruned++;
1081     else
1082     {
1083     WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
1084    
1085     notpruned++;
1086     }
1087    
1088     total++;
1089    
1090     if(!(total%1000))
1091     printf_middle("Deleting Pruned Turn Relations: Relations=%"Pindex_t" Pruned=%"Pindex_t,total,pruned);
1092     }
1093    
1094     relationsx->trnumber=notpruned;
1095    
1096     /* Close the files */
1097    
1098     relationsx->trfd=CloseFile(relationsx->trfd);
1099     CloseFile(trfd);
1100    
1101     /* Print the final message */
1102    
1103     printf_last("Deleted Pruned Turn Relations: Relations=%"Pindex_t" Pruned=%"Pindex_t,total,pruned);
1104     }
1105    
1106    
1107     /*++++++++++++++++++++++++++++++++++++++
1108 amb 1108 Sort the turn relations geographically after updating the node indexes.
1109 amb 1098
1110     RelationsX *relationsx The set of relations to modify.
1111    
1112     NodesX *nodesx The set of nodes to use.
1113    
1114 amb 680 SegmentsX *segmentsx The set of segments to use.
1115 amb 542 ++++++++++++++++++++++++++++++++++++++*/
1116    
1117 amb 1108 void SortTurnRelationListGeographically(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx)
1118 amb 542 {
1119     int trfd;
1120    
1121     /* Print the start message */
1122    
1123 amb 1108 printf_first("Sorting Turn Relations Geographically");
1124 amb 542
1125 amb 599 /* Map into memory / open the files */
1126    
1127     #if !SLIM
1128 amb 1120 segmentsx->data=MapFile(segmentsx->filename_tmp);
1129 amb 599 #else
1130 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
1131 amb 599 #endif
1132    
1133 amb 555 /* Re-open the file read-only and a new file writeable */
1134 amb 542
1135 amb 1120 relationsx->trfd=ReOpenFile(relationsx->trfilename_tmp);
1136 amb 555
1137 amb 1120 DeleteFile(relationsx->trfilename_tmp);
1138 amb 542
1139 amb 1120 trfd=OpenFileNew(relationsx->trfilename_tmp);
1140 amb 542
1141 amb 1108 /* Update the segments with geographically sorted node indexes and sort them */
1142 amb 542
1143 amb 1108 sortnodesx=nodesx;
1144     sortsegmentsx=segmentsx;
1145 amb 542
1146 amb 1108 filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRestrictRelX),(int (*)(void*,index_t))geographically_index,
1147     (int (*)(const void*,const void*))sort_by_via,
1148     NULL);
1149 amb 542
1150 amb 555 /* Close the files */
1151 amb 542
1152 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
1153 amb 542 CloseFile(trfd);
1154    
1155 amb 599 /* Unmap from memory / close the files */
1156    
1157     #if !SLIM
1158 amb 1122 segmentsx->data=UnmapFile(segmentsx->data);
1159 amb 599 #else
1160 amb 612 segmentsx->fd=CloseFile(segmentsx->fd);
1161 amb 599 #endif
1162    
1163 amb 542 /* Print the final message */
1164    
1165 amb 1110 printf_last("Sorted Turn Relations Geographically: Turn Relations=%"Pindex_t,relationsx->trnumber);
1166 amb 645 }
1167    
1168    
1169     /*++++++++++++++++++++++++++++++++++++++
1170 amb 1108 Update the turn relation indexes.
1171    
1172     int geographically_index Return 1 if the value is to be kept, otherwise 0.
1173    
1174     TurnRestrictRelX *relationx The extended turn relation.
1175    
1176 amb 1112 index_t index The number of unsorted turn relations that have been read from the input file.
1177 amb 1108 ++++++++++++++++++++++++++++++++++++++*/
1178    
1179     static int geographically_index(TurnRestrictRelX *relationx,index_t index)
1180     {
1181     SegmentX *segmentx;
1182     index_t from_node,via_node,to_node;
1183    
1184     from_node=sortnodesx->gdata[relationx->from];
1185     via_node =sortnodesx->gdata[relationx->via];
1186     to_node =sortnodesx->gdata[relationx->to];
1187    
1188     segmentx=FirstSegmentX(sortsegmentsx,via_node,1);
1189    
1190     do
1191     {
1192     if(OtherNode(segmentx,via_node)==from_node)
1193     relationx->from=IndexSegmentX(sortsegmentsx,segmentx);
1194    
1195     if(OtherNode(segmentx,via_node)==to_node)
1196     relationx->to=IndexSegmentX(sortsegmentsx,segmentx);
1197    
1198     segmentx=NextSegmentX(sortsegmentsx,segmentx,via_node);
1199     }
1200     while(segmentx);
1201    
1202     relationx->via=via_node;
1203    
1204     return(1);
1205     }
1206    
1207    
1208     /*++++++++++++++++++++++++++++++++++++++
1209     Sort the turn restriction relations into via index order (then by from and to segments).
1210    
1211     int sort_by_via Returns the comparison of the via, from and to fields.
1212    
1213     TurnRestrictRelX *a The first extended relation.
1214    
1215     TurnRestrictRelX *b The second extended relation.
1216     ++++++++++++++++++++++++++++++++++++++*/
1217    
1218     static int sort_by_via(TurnRestrictRelX *a,TurnRestrictRelX *b)
1219     {
1220     index_t a_id=a->via;
1221     index_t b_id=b->via;
1222    
1223     if(a_id<b_id)
1224     return(-1);
1225     else if(a_id>b_id)
1226     return(1);
1227     else
1228     {
1229     index_t a_id=a->from;
1230     index_t b_id=b->from;
1231    
1232     if(a_id<b_id)
1233     return(-1);
1234     else if(a_id>b_id)
1235     return(1);
1236     else
1237     {
1238     index_t a_id=a->to;
1239     index_t b_id=b->to;
1240    
1241     if(a_id<b_id)
1242     return(-1);
1243     else if(a_id>b_id)
1244     return(1);
1245     else
1246 amb 1118 return(FILESORT_PRESERVE_ORDER(a,b));
1247 amb 1108 }
1248     }
1249     }
1250    
1251    
1252     /*++++++++++++++++++++++++++++++++++++++
1253 amb 542 Save the relation list to a file.
1254    
1255     RelationsX* relationsx The set of relations to save.
1256    
1257     const char *filename The name of the file to save.
1258     ++++++++++++++++++++++++++++++++++++++*/
1259    
1260     void SaveRelationList(RelationsX* relationsx,const char *filename)
1261     {
1262     index_t i;
1263     int fd;
1264     RelationsFile relationsfile={0};
1265    
1266     /* Print the start message */
1267    
1268     printf_first("Writing Relations: Turn Relations=0");
1269    
1270 amb 559 /* Re-open the file read-only */
1271 amb 555
1272 amb 1120 relationsx->trfd=ReOpenFile(relationsx->trfilename_tmp);
1273 amb 555
1274 amb 542 /* Write out the relations data */
1275    
1276     fd=OpenFileNew(filename);
1277    
1278     SeekFile(fd,sizeof(RelationsFile));
1279    
1280     for(i=0;i<relationsx->trnumber;i++)
1281     {
1282     TurnRestrictRelX relationx;
1283 amb 944 TurnRelation relation={0};
1284 amb 542
1285     ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
1286    
1287 amb 551 relation.from=relationx.from;
1288     relation.via=relationx.via;
1289     relation.to=relationx.to;
1290     relation.except=relationx.except;
1291 amb 542
1292 amb 551 WriteFile(fd,&relation,sizeof(TurnRelation));
1293    
1294 amb 757 if(!((i+1)%1000))
1295 amb 790 printf_middle("Writing Relations: Turn Relations=%"Pindex_t,i+1);
1296 amb 542 }
1297    
1298     /* Write out the header structure */
1299    
1300     relationsfile.trnumber=relationsx->trnumber;
1301    
1302     SeekFile(fd,0);
1303     WriteFile(fd,&relationsfile,sizeof(RelationsFile));
1304    
1305     CloseFile(fd);
1306    
1307     /* Close the file */
1308    
1309 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
1310 amb 542
1311     /* Print the final message */
1312    
1313 amb 790 printf_last("Wrote Relations: Turn Relations=%"Pindex_t,relationsx->trnumber);
1314 amb 542 }