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 615 - (hide annotations) (download) (as text)
Sat Jan 29 19:58:24 2011 UTC (14 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 24765 byte(s)
All nodes adjacent to a turn restriction must also be turn restrictions.

1 amb 496 /***************************************
2     Extended Relation data type functions.
3    
4     Part of the Routino routing software.
5     ******************/ /******************
6 amb 597 This file Copyright 2010-2011 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 <stdio.h>
26     #include <string.h>
27     #include <sys/stat.h>
28    
29 amb 542 #include "types.h"
30     #include "relations.h"
31    
32     #include "nodesx.h"
33     #include "segmentsx.h"
34 amb 496 #include "waysx.h"
35     #include "relationsx.h"
36    
37     #include "files.h"
38 amb 519 #include "logging.h"
39 amb 532 #include "sorting.h"
40 amb 496
41    
42 amb 540 /* Functions */
43    
44 amb 559 static int sort_by_id(TurnRestrictRelX *a,TurnRestrictRelX *b);
45 amb 540 static int deduplicate_by_id(TurnRestrictRelX *relationx,index_t index);
46    
47 amb 559 static int sort_by_via(TurnRestrictRelX *a,TurnRestrictRelX *b);
48 amb 540
49 amb 559
50 amb 496 /* Variables */
51    
52     /*+ The command line '--tmpdir' option or its default value. +*/
53     extern char *option_tmpdirname;
54    
55 amb 540 static RelationsX* sortrelationsx;
56 amb 496
57 amb 540
58 amb 496 /*++++++++++++++++++++++++++++++++++++++
59     Allocate a new relation list (create a new file or open an existing one).
60    
61     RelationsX *NewRelationList Returns the relation list.
62    
63     int append Set to 1 if the file is to be opened for appending (now or later).
64     ++++++++++++++++++++++++++++++++++++++*/
65    
66     RelationsX *NewRelationList(int append)
67     {
68     RelationsX *relationsx;
69    
70     relationsx=(RelationsX*)calloc(1,sizeof(RelationsX));
71    
72     assert(relationsx); /* Check calloc() worked */
73    
74 amb 540
75 amb 559 /* Route Relations */
76    
77 amb 496 relationsx->rfilename=(char*)malloc(strlen(option_tmpdirname)+32);
78    
79     if(append)
80     sprintf(relationsx->rfilename,"%s/relationsx.route.input.tmp",option_tmpdirname);
81     else
82     sprintf(relationsx->rfilename,"%s/relationsx.route.%p.tmp",option_tmpdirname,relationsx);
83    
84     if(append)
85     {
86     off_t size,position=0;
87    
88 amb 505 relationsx->rfd=OpenFileAppend(relationsx->rfilename);
89 amb 496
90     size=SizeFile(relationsx->rfilename);
91    
92     while(position<size)
93     {
94     FILESORT_VARINT relationsize;
95    
96     SeekFile(relationsx->rfd,position);
97     ReadFile(relationsx->rfd,&relationsize,FILESORT_VARSIZE);
98    
99     relationsx->rxnumber++;
100     position+=relationsize+FILESORT_VARSIZE;
101     }
102    
103     SeekFile(relationsx->rfd,size);
104     }
105     else
106 amb 505 relationsx->rfd=OpenFileNew(relationsx->rfilename);
107 amb 496
108 amb 540
109 amb 559 /* Turn Restriction Relations */
110    
111 amb 540 relationsx->trfilename=(char*)malloc(strlen(option_tmpdirname)+32);
112    
113     if(append)
114     sprintf(relationsx->trfilename,"%s/relationsx.turn.input.tmp",option_tmpdirname);
115     else
116     sprintf(relationsx->trfilename,"%s/relationsx.turn.%p.tmp",option_tmpdirname,relationsx);
117    
118     if(append)
119     {
120     off_t size;
121    
122     relationsx->trfd=OpenFileAppend(relationsx->trfilename);
123    
124     size=SizeFile(relationsx->trfilename);
125    
126     relationsx->trxnumber=size/sizeof(TurnRestrictRelX);
127     }
128     else
129     relationsx->trfd=OpenFileNew(relationsx->trfilename);
130    
131 amb 496 return(relationsx);
132     }
133    
134    
135     /*++++++++++++++++++++++++++++++++++++++
136     Free a relation list.
137    
138     RelationsX *relationsx The list to be freed.
139    
140     int keep Set to 1 if the file is to be kept.
141     ++++++++++++++++++++++++++++++++++++++*/
142    
143     void FreeRelationList(RelationsX *relationsx,int keep)
144     {
145 amb 540 /* Route relations */
146    
147 amb 496 if(!keep)
148     DeleteFile(relationsx->rfilename);
149    
150     free(relationsx->rfilename);
151    
152 amb 559
153 amb 540 /* Turn Restriction relations */
154    
155     if(!keep)
156     DeleteFile(relationsx->trfilename);
157    
158     free(relationsx->trfilename);
159    
160 amb 496 free(relationsx);
161     }
162    
163    
164     /*++++++++++++++++++++++++++++++++++++++
165     Append a single relation to an unsorted route relation list.
166    
167     RelationsX* relationsx The set of relations to process.
168    
169     relation_t id The ID of the relation.
170    
171 amb 529 transports_t routes The types of routes that this relation is for.
172 amb 496
173     way_t *ways The array of ways that are members of the relation.
174    
175     int nways The number of ways that are members of the relation.
176    
177     relation_t *relations The array of relations that are members of the relation.
178    
179     int nrelations The number of relations that are members of the relation.
180     ++++++++++++++++++++++++++++++++++++++*/
181    
182 amb 540 void AppendRouteRelation(RelationsX* relationsx,relation_t id,
183     transports_t routes,
184 amb 496 way_t *ways,int nways,
185     relation_t *relations,int nrelations)
186     {
187     RouteRelX relationx;
188 amb 505 FILESORT_VARINT size;
189 amb 496 way_t zeroway=0;
190     relation_t zerorelation=0;
191    
192     relationx.id=id;
193     relationx.routes=routes;
194    
195     size=sizeof(RouteRelX)+(nways+1)*sizeof(way_t)+(nrelations+1)*sizeof(relation_t);
196    
197 amb 505 WriteFile(relationsx->rfd,&size,FILESORT_VARSIZE);
198 amb 496 WriteFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
199    
200     WriteFile(relationsx->rfd,ways ,nways*sizeof(way_t));
201     WriteFile(relationsx->rfd,&zeroway, sizeof(way_t));
202    
203     WriteFile(relationsx->rfd,relations ,nrelations*sizeof(relation_t));
204     WriteFile(relationsx->rfd,&zerorelation, sizeof(relation_t));
205    
206     relationsx->rxnumber++;
207    
208     assert(!(relationsx->rxnumber==0)); /* Zero marks the high-water mark for relations. */
209     }
210    
211    
212     /*++++++++++++++++++++++++++++++++++++++
213 amb 540 Append a single relation to an unsorted turn restriction relation list.
214    
215     RelationsX* relationsx The set of relations to process.
216    
217     relation_t id The ID of the relation.
218    
219     way_t from The way that the turn restriction starts from.
220    
221     way_t to The way that the restriction finished on.
222    
223     node_t via The node that the turn restriction passes through.
224    
225     TurnRestriction restriction The type of restriction.
226    
227     transports_t except The set of transports allowed to bypass the restriction.
228     ++++++++++++++++++++++++++++++++++++++*/
229    
230     void AppendTurnRestrictRelation(RelationsX* relationsx,relation_t id,
231     way_t from,way_t to,node_t via,
232     TurnRestriction restriction,transports_t except)
233     {
234     TurnRestrictRelX relationx;
235    
236     relationx.id=id;
237     relationx.from=from;
238     relationx.to=to;
239     relationx.via=via;
240     relationx.restrict=restriction;
241     relationx.except=except;
242    
243     WriteFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
244    
245     relationsx->trxnumber++;
246    
247     assert(!(relationsx->trxnumber==0)); /* Zero marks the high-water mark for relations. */
248     }
249    
250    
251     /*++++++++++++++++++++++++++++++++++++++
252 amb 496 Sort the list of relations.
253    
254     RelationsX* relationsx The set of relations to process.
255     ++++++++++++++++++++++++++++++++++++++*/
256    
257     void SortRelationList(RelationsX* relationsx)
258     {
259 amb 559 /* Close the files (finished appending) */
260 amb 540
261 amb 612 relationsx->rfd=CloseFile(relationsx->rfd);
262 amb 542
263 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
264 amb 540
265 amb 559
266     /* Route Relations */
267    
268    
269     /* Turn Restriction Relations. */
270    
271 amb 551 if(relationsx->trxnumber)
272     {
273     int trfd;
274 amb 540
275 amb 551 /* Print the start message */
276 amb 540
277 amb 551 printf_first("Sorting Turn Restriction Relations");
278 amb 540
279 amb 555 /* Re-open the file read-only and a new file writeable */
280    
281     relationsx->trfd=ReOpenFile(relationsx->trfilename);
282    
283 amb 551 DeleteFile(relationsx->trfilename);
284 amb 540
285 amb 551 trfd=OpenFileNew(relationsx->trfilename);
286 amb 540
287 amb 551 /* Sort the relations */
288 amb 540
289 amb 551 sortrelationsx=relationsx;
290 amb 540
291 amb 559 filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRestrictRelX),(int (*)(const void*,const void*))sort_by_id,(int (*)(void*,index_t))deduplicate_by_id);
292 amb 540
293 amb 555 /* Close the files */
294 amb 540
295 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
296 amb 551 CloseFile(trfd);
297 amb 540
298 amb 551 /* Print the final message */
299 amb 540
300 amb 551 printf_last("Sorted Relations: Relations=%d Duplicates=%d",relationsx->trxnumber,relationsx->trxnumber-relationsx->trnumber);
301     }
302 amb 496 }
303    
304    
305     /*++++++++++++++++++++++++++++++++++++++
306 amb 559 Sort the turn restriction relations into id order.
307 amb 540
308 amb 559 int sort_by_id Returns the comparison of the id fields.
309 amb 540
310     TurnRestrictRelX *a The first extended relation.
311    
312     TurnRestrictRelX *b The second extended relation.
313     ++++++++++++++++++++++++++++++++++++++*/
314    
315 amb 559 static int sort_by_id(TurnRestrictRelX *a,TurnRestrictRelX *b)
316 amb 540 {
317 amb 559 relation_t a_id=a->id;
318     relation_t b_id=b->id;
319 amb 540
320     if(a_id<b_id)
321     return(-1);
322     else if(a_id>b_id)
323     return(1);
324     else
325 amb 559 return(0);
326 amb 540 }
327    
328    
329     /*++++++++++++++++++++++++++++++++++++++
330     Deduplicate the extended relations using the id after sorting.
331    
332     int deduplicate_by_id Return 1 if the value is to be kept, otherwise zero.
333    
334     TurnRestrictRelX *relationx The extended relation.
335    
336     index_t index The index of this relation in the total.
337     ++++++++++++++++++++++++++++++++++++++*/
338    
339     static int deduplicate_by_id(TurnRestrictRelX *relationx,index_t index)
340     {
341     static relation_t previd;
342    
343     if(index==0 || relationx->id!=previd)
344     {
345     previd=relationx->id;
346    
347     sortrelationsx->trnumber++;
348    
349     return(1);
350     }
351    
352     return(0);
353     }
354    
355    
356     /*++++++++++++++++++++++++++++++++++++++
357 amb 559 Sort the list of turn relations.
358    
359     RelationsX* relationsx The set of relations to process.
360     ++++++++++++++++++++++++++++++++++++++*/
361    
362     void SortTurnRelationList(RelationsX* relationsx)
363     {
364     int trfd;
365    
366     if(relationsx->trnumber==0)
367     return;
368    
369     /* Print the start message */
370    
371     printf_first("Sorting Turn Restriction Relations");
372    
373     /* Re-open the file read-only and a new file writeable */
374    
375     relationsx->trfd=ReOpenFile(relationsx->trfilename);
376    
377     DeleteFile(relationsx->trfilename);
378    
379     trfd=OpenFileNew(relationsx->trfilename);
380    
381     /* Sort the relations */
382    
383     filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRestrictRelX),(int (*)(const void*,const void*))sort_by_via,NULL);
384    
385     /* Close the files */
386    
387 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
388 amb 559 CloseFile(trfd);
389    
390     /* Print the final message */
391    
392     printf_last("Sorted Relations: Relations=%d",relationsx->trnumber);
393     }
394    
395    
396     /*++++++++++++++++++++++++++++++++++++++
397     Sort the turn restriction relations into via node order.
398    
399     int sort_by_via Returns the comparison of the via fields.
400    
401     TurnRestrictRelX *a The first extended relation.
402    
403     TurnRestrictRelX *b The second extended relation.
404     ++++++++++++++++++++++++++++++++++++++*/
405    
406     static int sort_by_via(TurnRestrictRelX *a,TurnRestrictRelX *b)
407     {
408     node_t a_id=a->via;
409     node_t b_id=b->via;
410    
411     if(a_id<b_id)
412     return(-1);
413     else if(a_id>b_id)
414     return(1);
415     else
416     {
417     node_t a_id=a->from;
418     node_t b_id=b->from;
419    
420     if(a_id<b_id)
421     return(-1);
422     else if(a_id>b_id)
423     return(1);
424     else
425     {
426     node_t a_id=a->to;
427     node_t b_id=b->to;
428    
429     if(a_id<b_id)
430     return(-1);
431     else if(a_id>b_id)
432     return(1);
433     else
434     return(0);
435     }
436     }
437     }
438    
439    
440     /*++++++++++++++++++++++++++++++++++++++
441 amb 496 Process the route relations and apply the information to the ways.
442    
443     RelationsX *relationsx The set of relations to process.
444    
445     WaysX *waysx The set of ways to update.
446     ++++++++++++++++++++++++++++++++++++++*/
447    
448     void ProcessRouteRelations(RelationsX *relationsx,WaysX *waysx)
449     {
450 amb 505 RouteRelX *unmatched=NULL,*lastunmatched=NULL;
451     int nunmatched=0,lastnunmatched=0,iteration=0;
452 amb 496
453 amb 510 if(waysx->number==0)
454 amb 508 return;
455    
456 amb 555 /* Map into memory / open the files */
457 amb 496
458 amb 505 #if !SLIM
459 amb 507 waysx->xdata=MapFileWriteable(waysx->filename);
460 amb 555 #else
461     waysx->fd=ReOpenFileWriteable(waysx->filename);
462 amb 505 #endif
463 amb 496
464 amb 555 /* Re-open the file read-only */
465 amb 548
466     relationsx->rfd=ReOpenFile(relationsx->rfilename);
467    
468 amb 542 /* Read through the file. */
469 amb 496
470 amb 505 do
471 amb 496 {
472 amb 522 int ways=0,relations=0;
473     int i;
474    
475 amb 505 SeekFile(relationsx->rfd,0);
476 amb 496
477 amb 505 /* Print the start message */
478 amb 496
479 amb 522 printf_first("Processing Route Relations: Iteration=%d Relations=0 Modified Ways=0",iteration);
480 amb 496
481 amb 505 for(i=0;i<relationsx->rxnumber;i++)
482 amb 496 {
483 amb 505 FILESORT_VARINT size;
484     RouteRelX relationx;
485     way_t wayid;
486     relation_t relationid;
487 amb 529 transports_t routes=Transports_None;
488 amb 496
489 amb 505 /* Read each route relation */
490 amb 496
491 amb 505 ReadFile(relationsx->rfd,&size,FILESORT_VARSIZE);
492     ReadFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
493 amb 496
494 amb 505 /* Decide what type of route it is */
495 amb 496
496 amb 505 if(iteration==0)
497 amb 522 {
498     relations++;
499 amb 505 routes=relationx.routes;
500 amb 522 }
501 amb 505 else
502 amb 506 {
503 amb 522 int j;
504    
505     for(j=0;j<lastnunmatched;j++)
506     if(lastunmatched[j].id==relationx.id)
507     {
508     relations++;
509    
510     if((lastunmatched[j].routes|relationx.routes)==relationx.routes)
511     routes=0; /* Nothing new to add */
512     else
513 amb 506 routes=lastunmatched[j].routes;
514 amb 522 break;
515     }
516 amb 506 }
517 amb 496
518 amb 505 /* Loop through the ways */
519    
520     do
521     {
522     ReadFile(relationsx->rfd,&wayid,sizeof(way_t));
523    
524     /* Update the ways that are listed for the relation */
525    
526     if(wayid && routes)
527     {
528 amb 506 index_t way=IndexWayX(waysx,wayid);
529 amb 505
530     if(way!=NO_WAY)
531     {
532     WayX *wayx=LookupWayX(waysx,way,1);
533    
534 amb 529 if(routes&Transports_Foot)
535 amb 505 wayx->way.props|=Properties_FootRoute;
536    
537 amb 529 if(routes&Transports_Bicycle)
538 amb 505 wayx->way.props|=Properties_BicycleRoute;
539    
540     PutBackWayX(waysx,way,1);
541 amb 522
542     ways++;
543 amb 505 }
544     }
545     }
546     while(wayid);
547    
548     /* Loop through the relations */
549    
550     do
551     {
552     ReadFile(relationsx->rfd,&relationid,sizeof(relation_t));
553    
554     /* Add the relations that are listed for this relation to the list for next time */
555    
556 amb 506 if(relationid && routes && relationid!=relationx.id)
557 amb 505 {
558     if(nunmatched%256==0)
559     unmatched=(RouteRelX*)realloc((void*)unmatched,(nunmatched+256)*sizeof(RouteRelX));
560    
561     unmatched[nunmatched].id=relationid;
562     unmatched[nunmatched].routes=routes;
563    
564     nunmatched++;
565     }
566     }
567     while(relationid);
568    
569     if(!((i+1)%10000))
570 amb 522 printf_middle("Processing Route Relations: Iteration=%d Relations=%d Modified Ways=%d",iteration,relations,ways);
571 amb 496 }
572    
573 amb 505 if(lastunmatched)
574     free(lastunmatched);
575    
576     lastunmatched=unmatched;
577     lastnunmatched=nunmatched;
578    
579     unmatched=NULL;
580     nunmatched=0;
581    
582     /* Print the final message */
583    
584 amb 522 printf_last("Processed Route Relations: Iteration=%d Relations=%d Modified Ways=%d",iteration,relations,ways);
585 amb 496 }
586 amb 505 while(lastnunmatched && ++iteration<5);
587 amb 496
588 amb 505 if(lastunmatched)
589     free(lastunmatched);
590    
591 amb 555 /* Close the file */
592    
593 amb 612 relationsx->rfd=CloseFile(relationsx->rfd);
594 amb 496
595 amb 555 /* Unmap from memory / close the files */
596 amb 496
597 amb 505 #if !SLIM
598     waysx->xdata=UnmapFile(waysx->filename);
599 amb 555 #else
600 amb 612 waysx->fd=CloseFile(waysx->fd);
601 amb 511 #endif
602 amb 496 }
603 amb 542
604    
605     /*++++++++++++++++++++++++++++++++++++++
606     Process the turn relations (first part) to update them with the node information.
607    
608     RelationsX *relationsx The set of relations to process.
609    
610     NodesX *nodesx The set of nodes to process.
611    
612     SegmentsX *segmentsx The set of segments to process.
613    
614     WaysX *waysx The set of ways to process.
615     ++++++++++++++++++++++++++++++++++++++*/
616    
617     void ProcessTurnRelations1(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx)
618     {
619 amb 548 TurnRestrictRelX relationx;
620 amb 542 int trfd;
621 amb 559 int total=0;
622 amb 542
623 amb 548 if(nodesx->number==0 || segmentsx->number==0)
624     return;
625    
626 amb 542 /* Print the start message */
627    
628     printf_first("Processing Turn Restriction Relations (1): Turn Relations=0");
629    
630 amb 555 /* Map into memory / open the files */
631 amb 548
632     #if !SLIM
633 amb 560 nodesx->xdata=MapFileWriteable(nodesx->filename);
634 amb 548 segmentsx->xdata=MapFile(segmentsx->filename);
635 amb 555 #else
636 amb 560 nodesx->fd=ReOpenFileWriteable(nodesx->filename);
637 amb 555 segmentsx->fd=ReOpenFile(segmentsx->filename);
638 amb 548 #endif
639    
640 amb 555 /* Re-open the file read-only and a new file writeable */
641    
642 amb 548 relationsx->trfd=ReOpenFile(relationsx->trfilename);
643    
644 amb 542 DeleteFile(relationsx->trfilename);
645    
646     trfd=OpenFileNew(relationsx->trfilename);
647    
648     /* Process all of the relations */
649    
650 amb 548 while(!ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX)))
651 amb 542 {
652 amb 615 NodeX *nodex;
653     node_t node_via=relationx.via;
654     index_t seg;
655    
656 amb 548 if(relationx.restrict==TurnRestrict_no_right_turn ||
657     relationx.restrict==TurnRestrict_no_left_turn ||
658     relationx.restrict==TurnRestrict_no_u_turn ||
659     relationx.restrict==TurnRestrict_no_straight_on)
660     {
661 amb 551 node_t node_from=NO_NODE,node_to=NO_NODE;
662 amb 542
663 amb 548 /* Find the segments that join the node 'via' */
664 amb 542
665 amb 548 seg=IndexFirstSegmentX1(segmentsx,relationx.via);
666 amb 542
667 amb 548 do
668     {
669     SegmentX *segx=LookupSegmentX(segmentsx,seg,1);
670 amb 542
671 amb 551 if(segx->way==relationx.from)
672 amb 548 {
673 amb 551 if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
674     goto endloop;
675 amb 548
676 amb 551 node_from=segx->node2;
677 amb 548 }
678    
679 amb 551 if(segx->way==relationx.to)
680 amb 548 {
681 amb 551 if(node_to!=NO_NODE) /* Only one segment can be on the 'to' way */
682     goto endloop;
683 amb 548
684 amb 551 node_to=segx->node2;
685 amb 548 }
686    
687     seg=IndexNextSegmentX1(segmentsx,seg,relationx.via);
688     }
689     while(seg!=NO_SEGMENT);
690    
691 amb 551 if(node_to==NO_NODE || node_from==NO_NODE) /* Not enough segments for the selected ways */
692 amb 548 goto endloop;
693    
694 amb 551 /* Write the results */
695 amb 548
696 amb 551 relationx.from=IndexNodeX(nodesx,node_from);
697     relationx.to =IndexNodeX(nodesx,node_to);
698     relationx.via =IndexNodeX(nodesx,relationx.via);
699 amb 548
700 amb 551 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
701 amb 548
702 amb 559 total++;
703 amb 548
704 amb 559 if(!(total%10000))
705     printf_middle("Processing Turn Restriction Relations (1): Turn Relations=%d New=%d",total,total-relationsx->trnumber);
706 amb 551 }
707     else
708     {
709     node_t node_from=NO_NODE,node_to[8];
710     int nnodes_to=0,i;
711 amb 548
712 amb 551 /* Find the segments that join the node 'via' */
713 amb 548
714 amb 551 seg=IndexFirstSegmentX1(segmentsx,relationx.via);
715 amb 548
716 amb 551 do
717     {
718     SegmentX *segx=LookupSegmentX(segmentsx,seg,1);
719 amb 548
720 amb 551 if(segx->way==relationx.from)
721     {
722     if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
723 amb 548 goto endloop;
724    
725 amb 551 node_from=segx->node2;
726 amb 548 }
727 amb 551
728     if(segx->way!=relationx.to)
729     {
730     if(nnodes_to==8) /* Too many segments (arbitrary choice) */
731     goto endloop;
732    
733     node_to[nnodes_to++]=segx->node2;
734     }
735    
736     seg=IndexNextSegmentX1(segmentsx,seg,relationx.via);
737 amb 548 }
738 amb 551 while(seg!=NO_SEGMENT);
739 amb 548
740 amb 551 if(nnodes_to==0 || node_from==NO_NODE) /* Not enough segments for the selected ways */
741 amb 548 goto endloop;
742    
743     /* Write the results */
744    
745 amb 551 relationx.via=IndexNodeX(nodesx,relationx.via);
746 amb 548
747 amb 551 for(i=0;i<nnodes_to;i++)
748     {
749     if(node_to[i]==node_from)
750     continue;
751 amb 548
752 amb 551 relationx.from=IndexNodeX(nodesx,node_from);
753     relationx.to =IndexNodeX(nodesx,node_to[i]);
754 amb 548
755 amb 551 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
756 amb 548
757 amb 559 total++;
758 amb 548
759 amb 559 if(!(total%10000))
760     printf_middle("Processing Turn Restriction Relations (1): Turn Relations=%d New=%d",total,total-relationsx->trnumber);
761 amb 551 }
762 amb 615 }
763 amb 560
764 amb 615 /* Force super nodes on via node and adjacent nodes */
765    
766     nodex=LookupNodeX(nodesx,relationx.via,1);
767     nodex->flags|=NODE_TURNRSTRCT;
768     PutBackNodeX(nodesx,relationx.via,1);
769    
770     seg=IndexFirstSegmentX1(segmentsx,node_via);
771    
772     do
773     {
774     SegmentX *segx=LookupSegmentX(segmentsx,seg,1);
775     index_t othernode=IndexNodeX(nodesx,segx->node2);
776    
777     nodex=LookupNodeX(nodesx,othernode,1);
778 amb 597 nodex->flags|=NODE_TURNRSTRCT2;
779 amb 615 PutBackNodeX(nodesx,othernode,1);
780 amb 597
781 amb 615 seg=IndexNextSegmentX1(segmentsx,seg,node_via);
782 amb 548 }
783 amb 615 while(seg!=NO_SEGMENT);
784 amb 548
785     endloop: ;
786 amb 542 }
787    
788 amb 555 /* Close the files */
789 amb 542
790 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
791 amb 542 CloseFile(trfd);
792    
793 amb 555 /* Unmap from memory / close the files */
794 amb 542
795 amb 548 #if !SLIM
796 amb 555 nodesx->xdata=UnmapFile(nodesx->filename);
797 amb 548 segmentsx->xdata=UnmapFile(segmentsx->filename);
798 amb 555 #else
799 amb 612 nodesx->fd=CloseFile(nodesx->fd);
800     segmentsx->fd=CloseFile(segmentsx->fd);
801 amb 548 #endif
802    
803 amb 542 /* Print the final message */
804    
805 amb 559 printf_last("Processing Turn Restriction Relations (1): Turn Relations=%d New=%d",total,total-relationsx->trnumber);
806    
807     relationsx->trnumber=total;
808 amb 542 }
809    
810    
811     /*++++++++++++++++++++++++++++++++++++++
812     Process the turn relations (second part) to update them with the re-ordered node information.
813    
814     RelationsX *relationsx The set of relations to process.
815    
816     NodesX *nodesx The set of nodes to process.
817 amb 599
818     SegmentsX *segmentsx The set of segments to process.
819 amb 542 ++++++++++++++++++++++++++++++++++++++*/
820    
821 amb 599 void ProcessTurnRelations2(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx)
822 amb 542 {
823     int trfd;
824 amb 559 int i;
825 amb 542
826     /* Print the start message */
827    
828     printf_first("Processing Turn Restriction Relations (2): Turn Relations=0");
829    
830 amb 599 /* Map into memory / open the files */
831    
832     #if !SLIM
833     nodesx->xdata=MapFile(nodesx->filename);
834     segmentsx->xdata=MapFile(segmentsx->filename);
835     segmentsx->sdata=MapFile(segmentsx->sfilename);
836     #else
837     nodesx->fd=ReOpenFile(nodesx->filename);
838     segmentsx->fd=ReOpenFile(segmentsx->filename);
839     segmentsx->sfd=ReOpenFile(segmentsx->sfilename);
840     #endif
841    
842 amb 555 /* Re-open the file read-only and a new file writeable */
843 amb 542
844 amb 555 relationsx->trfd=ReOpenFile(relationsx->trfilename);
845    
846 amb 542 DeleteFile(relationsx->trfilename);
847    
848     trfd=OpenFileNew(relationsx->trfilename);
849    
850     /* Process all of the relations */
851    
852 amb 559 for(i=0;i<relationsx->trnumber;i++)
853 amb 542 {
854 amb 599 NodeX *nodex;
855 amb 559 TurnRestrictRelX relationx;
856 amb 599 index_t from_node,via_node,to_node;
857     index_t seg;
858 amb 542
859 amb 559 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
860 amb 542
861 amb 599 from_node=relationx.from;
862     via_node=relationx.via;
863     to_node=relationx.to;
864 amb 542
865 amb 599 relationx.via=nodesx->gdata[via_node];
866 amb 542
867 amb 599 nodex=LookupNodeX(nodesx,relationx.via,1);
868     seg=nodex->id;
869 amb 559
870 amb 599 do
871     {
872     SegmentX *segmentx=LookupSegmentX(segmentsx,seg,1);
873    
874     if((segmentx->node1==from_node && segmentx->node2==via_node) ||
875     (segmentx->node2==from_node && segmentx->node1==via_node))
876     relationx.from=seg;
877    
878     if((segmentx->node1==to_node && segmentx->node2==via_node) ||
879     (segmentx->node2==to_node && segmentx->node1==via_node))
880     relationx.to=seg;
881    
882     if(segmentx->node1==via_node)
883     seg++;
884     else if(segmentx->node2==via_node)
885     {
886     Segment *segment=LookupSegmentXSegment(segmentsx,seg,1);
887    
888     seg=segment->next2;
889     }
890     else
891     seg=NO_SEGMENT;
892     }
893     while(seg!=NO_SEGMENT);
894    
895 amb 542 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
896    
897 amb 559 if(!(relationsx->trnumber%10000))
898     printf_middle("Processing Turn Restriction Relations (2): Turn Relations=%d",relationsx->trnumber);
899 amb 542 }
900    
901 amb 555 /* Close the files */
902 amb 542
903 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
904 amb 542 CloseFile(trfd);
905    
906 amb 599 /* Unmap from memory / close the files */
907    
908     #if !SLIM
909     nodesx->xdata=UnmapFile(nodesx->filename);
910     segmentsx->xdata=UnmapFile(segmentsx->filename);
911     segmentsx->sdata=UnmapFile(segmentsx->sfilename);
912     #else
913 amb 612 nodesx->fd=CloseFile(nodesx->fd);
914     segmentsx->fd=CloseFile(segmentsx->fd);
915     segmentsx->sfd=CloseFile(segmentsx->sfd);
916 amb 599 #endif
917    
918 amb 542 /* Print the final message */
919    
920 amb 559 printf_last("Processing Turn Restriction Relations (2): Turn Relations=%d",relationsx->trnumber);
921 amb 542 }
922    
923    
924     /*++++++++++++++++++++++++++++++++++++++
925     Save the relation list to a file.
926    
927     RelationsX* relationsx The set of relations to save.
928    
929     const char *filename The name of the file to save.
930     ++++++++++++++++++++++++++++++++++++++*/
931    
932     void SaveRelationList(RelationsX* relationsx,const char *filename)
933     {
934     index_t i;
935     int fd;
936     RelationsFile relationsfile={0};
937    
938     /* Print the start message */
939    
940     printf_first("Writing Relations: Turn Relations=0");
941    
942 amb 559 /* Re-open the file read-only */
943 amb 555
944     relationsx->trfd=ReOpenFile(relationsx->trfilename);
945    
946 amb 542 /* Write out the relations data */
947    
948     fd=OpenFileNew(filename);
949    
950     SeekFile(fd,sizeof(RelationsFile));
951    
952     for(i=0;i<relationsx->trnumber;i++)
953     {
954     TurnRestrictRelX relationx;
955 amb 551 TurnRelation relation;
956 amb 542
957     ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
958    
959 amb 551 relation.from=relationx.from;
960     relation.via=relationx.via;
961     relation.to=relationx.to;
962     relation.except=relationx.except;
963 amb 542
964 amb 551 WriteFile(fd,&relation,sizeof(TurnRelation));
965    
966 amb 542 if(!((i+1)%10000))
967     printf_middle("Writing Relations: Turn Relations=%d",i+1);
968     }
969    
970     /* Write out the header structure */
971    
972     relationsfile.trnumber=relationsx->trnumber;
973    
974     SeekFile(fd,0);
975     WriteFile(fd,&relationsfile,sizeof(RelationsFile));
976    
977     CloseFile(fd);
978    
979     /* Close the file */
980    
981 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
982 amb 542
983     /* Print the final message */
984    
985     printf_last("Wrote Relations: Turn Relations=%d",relationsx->trnumber);
986     }