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 560 - (hide annotations) (download) (as text)
Tue Dec 21 14:54:27 2010 UTC (14 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 22800 byte(s)
Update the nodes to force a super-node where there is a turn restriction.

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