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 1163 - (hide annotations) (download) (as text)
Tue Nov 20 14:30:56 2012 UTC (12 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 37682 byte(s)
Tidy up all of the recent code changes - Rename TurnRestrictRelX structure to
TurnRelX.

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