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 1261 - (hide annotations) (download) (as text)
Thu Feb 28 19:10:13 2013 UTC (12 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 37674 byte(s)
Rationalise some of the turn relation error messages.

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