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 1139 - (hide annotations) (download) (as text)
Thu Nov 15 19:16:47 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 37681 byte(s)
Fixed the --preserve option.

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