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 1146 - (hide annotations) (download) (as text)
Sat Nov 17 14:06:57 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 38054 byte(s)
Suppress some error log messages when applying changes (false positive duplicate
detection due to modification of existing items).

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