Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /trunk/src/relationsx.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 650 - (show annotations) (download) (as text)
Sun Feb 27 15:49:21 2011 UTC (14 years ago) by amb
File MIME type: text/x-csrc
File size: 26472 byte(s)
Don't have both xnumber and number in the nodesx, segmentsx, waysx and
relationsx structures.

1 /***************************************
2 Extended Relation data type functions.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2010-2011 Andrew M. Bishop
7
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 #include "types.h"
30 #include "relations.h"
31
32 #include "nodesx.h"
33 #include "segmentsx.h"
34 #include "waysx.h"
35 #include "relationsx.h"
36
37 #include "files.h"
38 #include "logging.h"
39 #include "sorting.h"
40
41
42 /* Functions */
43
44 static int sort_by_id(TurnRestrictRelX *a,TurnRestrictRelX *b);
45 static int deduplicate_by_id(TurnRestrictRelX *relationx,index_t index);
46
47 static int sort_by_via(TurnRestrictRelX *a,TurnRestrictRelX *b);
48
49
50 /* Variables */
51
52 /*+ The command line '--tmpdir' option or its default value. +*/
53 extern char *option_tmpdirname;
54
55 static RelationsX* sortrelationsx;
56
57
58 /*++++++++++++++++++++++++++++++++++++++
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
75 /* Route Relations */
76
77 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 relationsx->rfd=OpenFileAppend(relationsx->rfilename);
89
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->rnumber++;
100 position+=relationsize+FILESORT_VARSIZE;
101 }
102
103 SeekFile(relationsx->rfd,size);
104 }
105 else
106 relationsx->rfd=OpenFileNew(relationsx->rfilename);
107
108
109 /* Turn Restriction Relations */
110
111 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->trnumber=size/sizeof(TurnRestrictRelX);
127 }
128 else
129 relationsx->trfd=OpenFileNew(relationsx->trfilename);
130
131 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 /* Route relations */
146
147 if(!keep)
148 DeleteFile(relationsx->rfilename);
149
150 free(relationsx->rfilename);
151
152
153 /* Turn Restriction relations */
154
155 if(!keep)
156 DeleteFile(relationsx->trfilename);
157
158 free(relationsx->trfilename);
159
160 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 transports_t routes The types of routes that this relation is for.
172
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 void AppendRouteRelation(RelationsX* relationsx,relation_t id,
183 transports_t routes,
184 way_t *ways,int nways,
185 relation_t *relations,int nrelations)
186 {
187 RouteRelX relationx;
188 FILESORT_VARINT size;
189 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 WriteFile(relationsx->rfd,&size,FILESORT_VARSIZE);
198 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->rnumber++;
207
208 assert(!(relationsx->rnumber==0)); /* Zero marks the high-water mark for relations. */
209 }
210
211
212 /*++++++++++++++++++++++++++++++++++++++
213 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->trnumber++;
246
247 assert(!(relationsx->trnumber==0)); /* Zero marks the high-water mark for relations. */
248 }
249
250
251 /*++++++++++++++++++++++++++++++++++++++
252 Sort the list of relations.
253
254 RelationsX* relationsx The set of relations to process.
255 ++++++++++++++++++++++++++++++++++++++*/
256
257 void SortRelationList(RelationsX* relationsx)
258 {
259 /* Close the files (finished appending) */
260
261 relationsx->rfd=CloseFile(relationsx->rfd);
262
263 relationsx->trfd=CloseFile(relationsx->trfd);
264
265
266 /* Route Relations */
267
268
269 /* Turn Restriction Relations. */
270
271 if(relationsx->trnumber)
272 {
273 index_t trxnumber;
274 int trfd;
275
276 /* Print the start message */
277
278 printf_first("Sorting Turn Restriction Relations");
279
280 /* Re-open the file read-only and a new file writeable */
281
282 relationsx->trfd=ReOpenFile(relationsx->trfilename);
283
284 DeleteFile(relationsx->trfilename);
285
286 trfd=OpenFileNew(relationsx->trfilename);
287
288 /* Sort the relations */
289
290 trxnumber=relationsx->trnumber;
291 relationsx->trnumber=0;
292
293 sortrelationsx=relationsx;
294
295 filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRestrictRelX),(int (*)(const void*,const void*))sort_by_id,(int (*)(void*,index_t))deduplicate_by_id);
296
297 /* Close the files */
298
299 relationsx->trfd=CloseFile(relationsx->trfd);
300 CloseFile(trfd);
301
302 /* Print the final message */
303
304 printf_last("Sorted Relations: Relations=%d Duplicates=%d",trxnumber,trxnumber-relationsx->trnumber);
305 }
306 }
307
308
309 /*++++++++++++++++++++++++++++++++++++++
310 Sort the turn restriction relations into id order.
311
312 int sort_by_id Returns the comparison of the id fields.
313
314 TurnRestrictRelX *a The first extended relation.
315
316 TurnRestrictRelX *b The second extended relation.
317 ++++++++++++++++++++++++++++++++++++++*/
318
319 static int sort_by_id(TurnRestrictRelX *a,TurnRestrictRelX *b)
320 {
321 relation_t a_id=a->id;
322 relation_t b_id=b->id;
323
324 if(a_id<b_id)
325 return(-1);
326 else if(a_id>b_id)
327 return(1);
328 else
329 return(0);
330 }
331
332
333 /*++++++++++++++++++++++++++++++++++++++
334 Deduplicate the extended relations using the id after sorting.
335
336 int deduplicate_by_id Return 1 if the value is to be kept, otherwise zero.
337
338 TurnRestrictRelX *relationx The extended relation.
339
340 index_t index The index of this relation in the total.
341 ++++++++++++++++++++++++++++++++++++++*/
342
343 static int deduplicate_by_id(TurnRestrictRelX *relationx,index_t index)
344 {
345 static relation_t previd;
346
347 if(index==0 || relationx->id!=previd)
348 {
349 previd=relationx->id;
350
351 sortrelationsx->trnumber++;
352
353 return(1);
354 }
355
356 return(0);
357 }
358
359
360 /*++++++++++++++++++++++++++++++++++++++
361 Sort the list of turn relations.
362
363 RelationsX* relationsx The set of relations to process.
364 ++++++++++++++++++++++++++++++++++++++*/
365
366 void SortTurnRelationList(RelationsX* relationsx)
367 {
368 int trfd;
369
370 if(relationsx->trnumber==0)
371 return;
372
373 /* Print the start message */
374
375 printf_first("Sorting Turn Restriction Relations");
376
377 /* Re-open the file read-only and a new file writeable */
378
379 relationsx->trfd=ReOpenFile(relationsx->trfilename);
380
381 DeleteFile(relationsx->trfilename);
382
383 trfd=OpenFileNew(relationsx->trfilename);
384
385 /* Sort the relations */
386
387 filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRestrictRelX),(int (*)(const void*,const void*))sort_by_via,NULL);
388
389 /* Close the files */
390
391 relationsx->trfd=CloseFile(relationsx->trfd);
392 CloseFile(trfd);
393
394 /* Print the final message */
395
396 printf_last("Sorted Relations: Relations=%d",relationsx->trnumber);
397 }
398
399
400 /*++++++++++++++++++++++++++++++++++++++
401 Sort the turn restriction relations into via node order.
402
403 int sort_by_via Returns the comparison of the via fields.
404
405 TurnRestrictRelX *a The first extended relation.
406
407 TurnRestrictRelX *b The second extended relation.
408 ++++++++++++++++++++++++++++++++++++++*/
409
410 static int sort_by_via(TurnRestrictRelX *a,TurnRestrictRelX *b)
411 {
412 node_t a_id=a->via;
413 node_t b_id=b->via;
414
415 if(a_id<b_id)
416 return(-1);
417 else if(a_id>b_id)
418 return(1);
419 else
420 {
421 node_t a_id=a->from;
422 node_t b_id=b->from;
423
424 if(a_id<b_id)
425 return(-1);
426 else if(a_id>b_id)
427 return(1);
428 else
429 {
430 node_t a_id=a->to;
431 node_t b_id=b->to;
432
433 if(a_id<b_id)
434 return(-1);
435 else if(a_id>b_id)
436 return(1);
437 else
438 return(0);
439 }
440 }
441 }
442
443
444 /*++++++++++++++++++++++++++++++++++++++
445 Process the route relations and apply the information to the ways.
446
447 RelationsX *relationsx The set of relations to process.
448
449 WaysX *waysx The set of ways to update.
450 ++++++++++++++++++++++++++++++++++++++*/
451
452 void ProcessRouteRelations(RelationsX *relationsx,WaysX *waysx)
453 {
454 RouteRelX *unmatched=NULL,*lastunmatched=NULL;
455 int nunmatched=0,lastnunmatched=0,iteration=0;
456
457 if(waysx->number==0)
458 return;
459
460 /* Map into memory / open the files */
461
462 #if !SLIM
463 waysx->xdata=MapFileWriteable(waysx->filename);
464 #else
465 waysx->fd=ReOpenFileWriteable(waysx->filename);
466 #endif
467
468 /* Re-open the file read-only */
469
470 relationsx->rfd=ReOpenFile(relationsx->rfilename);
471
472 /* Read through the file. */
473
474 do
475 {
476 int ways=0,relations=0;
477 int i;
478
479 SeekFile(relationsx->rfd,0);
480
481 /* Print the start message */
482
483 printf_first("Processing Route Relations: Iteration=%d Relations=0 Modified Ways=0",iteration);
484
485 for(i=0;i<relationsx->rnumber;i++)
486 {
487 FILESORT_VARINT size;
488 RouteRelX relationx;
489 way_t wayid;
490 relation_t relationid;
491 transports_t routes=Transports_None;
492
493 /* Read each route relation */
494
495 ReadFile(relationsx->rfd,&size,FILESORT_VARSIZE);
496 ReadFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
497
498 /* Decide what type of route it is */
499
500 if(iteration==0)
501 {
502 relations++;
503 routes=relationx.routes;
504 }
505 else
506 {
507 int j;
508
509 for(j=0;j<lastnunmatched;j++)
510 if(lastunmatched[j].id==relationx.id)
511 {
512 relations++;
513
514 if((lastunmatched[j].routes|relationx.routes)==relationx.routes)
515 routes=0; /* Nothing new to add */
516 else
517 routes=lastunmatched[j].routes;
518 break;
519 }
520 }
521
522 /* Loop through the ways */
523
524 do
525 {
526 ReadFile(relationsx->rfd,&wayid,sizeof(way_t));
527
528 /* Update the ways that are listed for the relation */
529
530 if(wayid && routes)
531 {
532 index_t way=IndexWayX(waysx,wayid);
533
534 if(way!=NO_WAY)
535 {
536 WayX *wayx=LookupWayX(waysx,way,1);
537
538 if(routes&Transports_Foot)
539 wayx->way.props|=Properties_FootRoute;
540
541 if(routes&Transports_Bicycle)
542 wayx->way.props|=Properties_BicycleRoute;
543
544 PutBackWayX(waysx,way,1);
545
546 ways++;
547 }
548 }
549 }
550 while(wayid);
551
552 /* Loop through the relations */
553
554 do
555 {
556 ReadFile(relationsx->rfd,&relationid,sizeof(relation_t));
557
558 /* Add the relations that are listed for this relation to the list for next time */
559
560 if(relationid && routes && relationid!=relationx.id)
561 {
562 if(nunmatched%256==0)
563 unmatched=(RouteRelX*)realloc((void*)unmatched,(nunmatched+256)*sizeof(RouteRelX));
564
565 unmatched[nunmatched].id=relationid;
566 unmatched[nunmatched].routes=routes;
567
568 nunmatched++;
569 }
570 }
571 while(relationid);
572
573 if(!((i+1)%10000))
574 printf_middle("Processing Route Relations: Iteration=%d Relations=%d Modified Ways=%d",iteration,relations,ways);
575 }
576
577 if(lastunmatched)
578 free(lastunmatched);
579
580 lastunmatched=unmatched;
581 lastnunmatched=nunmatched;
582
583 unmatched=NULL;
584 nunmatched=0;
585
586 /* Print the final message */
587
588 printf_last("Processed Route Relations: Iteration=%d Relations=%d Modified Ways=%d",iteration,relations,ways);
589 }
590 while(lastnunmatched && ++iteration<5);
591
592 if(lastunmatched)
593 free(lastunmatched);
594
595 /* Close the file */
596
597 relationsx->rfd=CloseFile(relationsx->rfd);
598
599 /* Unmap from memory / close the files */
600
601 #if !SLIM
602 waysx->xdata=UnmapFile(waysx->filename);
603 #else
604 waysx->fd=CloseFile(waysx->fd);
605 #endif
606 }
607
608
609 /*++++++++++++++++++++++++++++++++++++++
610 Process the turn relations (first part) to update them with the node/way information.
611
612 RelationsX *relationsx The set of relations to process.
613
614 NodesX *nodesx The set of nodes to process.
615
616 WaysX *waysx The set of ways to process.
617 ++++++++++++++++++++++++++++++++++++++*/
618
619 void ProcessTurnRelations1(RelationsX *relationsx,NodesX *nodesx,WaysX *waysx)
620 {
621 int i,trfd;
622
623 /* Print the start message */
624
625 printf_first("Processing Turn Restriction Relations (1): Turn Relations=0");
626
627 /* Re-open the file read-only and a new file writeable */
628
629 relationsx->trfd=ReOpenFile(relationsx->trfilename);
630
631 DeleteFile(relationsx->trfilename);
632
633 trfd=OpenFileNew(relationsx->trfilename);
634
635 /* Process all of the relations */
636
637 for(i=0;i<relationsx->trnumber;i++)
638 {
639 TurnRestrictRelX relationx;
640
641 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
642
643 relationx.via =IndexNodeX(nodesx,relationx.via);
644 relationx.from=IndexWayX(waysx,relationx.from);
645 relationx.to =IndexWayX(waysx,relationx.to);
646
647 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
648
649 if(!((i+1)%10000))
650 printf_middle("Processing Turn Restriction Relations (1): Turn Relations=%d",i+1);
651 }
652
653 /* Close the files */
654
655 relationsx->trfd=CloseFile(relationsx->trfd);
656 CloseFile(trfd);
657
658 /* Print the final message */
659
660 printf_last("Processed Turn Restriction Relations (1): Turn Relations=%d",relationsx->trnumber);
661 }
662
663
664 /*++++++++++++++++++++++++++++++++++++++
665 Process the turn relations (second part) to convert them to nodes.
666
667 RelationsX *relationsx The set of relations to process.
668
669 NodesX *nodesx The set of nodes to process.
670
671 SegmentsX *segmentsx The set of segments to process.
672
673 WaysX *waysx The set of ways to process.
674 ++++++++++++++++++++++++++++++++++++++*/
675
676 void ProcessTurnRelations2(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx)
677 {
678 TurnRestrictRelX relationx;
679 int trfd;
680 int total=0;
681
682 if(nodesx->number==0 || segmentsx->number==0)
683 return;
684
685 /* Print the start message */
686
687 printf_first("Processing Turn Restriction Relations (2): Turn Relations=0");
688
689 /* Map into memory / open the files */
690
691 #if !SLIM
692 nodesx->xdata=MapFileWriteable(nodesx->filename);
693 segmentsx->xdata=MapFile(segmentsx->filename);
694 #else
695 nodesx->fd=ReOpenFileWriteable(nodesx->filename);
696 segmentsx->fd=ReOpenFile(segmentsx->filename);
697 #endif
698
699 /* Re-open the file read-only and a new file writeable */
700
701 relationsx->trfd=ReOpenFile(relationsx->trfilename);
702
703 DeleteFile(relationsx->trfilename);
704
705 trfd=OpenFileNew(relationsx->trfilename);
706
707 /* Process all of the relations */
708
709 while(!ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX)))
710 {
711 NodeX *nodex;
712 SegmentX *segmentx;
713
714 if(relationx.restrict==TurnRestrict_no_right_turn ||
715 relationx.restrict==TurnRestrict_no_left_turn ||
716 relationx.restrict==TurnRestrict_no_u_turn ||
717 relationx.restrict==TurnRestrict_no_straight_on)
718 {
719 node_t node_from=NO_NODE,node_to=NO_NODE;
720
721 /* Find the segments that join the node 'via' */
722
723 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
724
725 do
726 {
727 if(segmentx->way==relationx.from)
728 {
729 if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
730 goto endloop;
731
732 node_from=OtherNode(segmentx,relationx.via);
733 }
734
735 if(segmentx->way==relationx.to)
736 {
737 if(node_to!=NO_NODE) /* Only one segment can be on the 'to' way */
738 goto endloop;
739
740 node_to=OtherNode(segmentx,relationx.via);
741 }
742
743 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via,1);
744 }
745 while(segmentx);
746
747 if(node_to==NO_NODE || node_from==NO_NODE) /* Not enough segments for the selected ways */
748 goto endloop;
749
750 /* Write the results */
751
752 relationx.from=node_from;
753 relationx.to =node_to;
754
755 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
756
757 total++;
758
759 if(!(total%10000))
760 printf_middle("Processing Turn Restriction Relations (2): Turn Relations=%d New=%d",total,total-relationsx->trnumber);
761 }
762 else
763 {
764 node_t node_from=NO_NODE,node_to[8];
765 int nnodes_to=0,i;
766
767 /* Find the segments that join the node 'via' */
768
769 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
770
771 do
772 {
773 if(segmentx->way==relationx.from)
774 {
775 if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
776 goto endloop;
777
778 node_from=OtherNode(segmentx,relationx.via);
779 }
780
781 if(segmentx->way!=relationx.to)
782 {
783 if(nnodes_to==8) /* Too many segments (arbitrary choice) */
784 goto endloop;
785
786 node_to[nnodes_to++]=OtherNode(segmentx,relationx.via);
787 }
788
789 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via,1);
790 }
791 while(segmentx);
792
793 if(nnodes_to==0 || node_from==NO_NODE) /* Not enough segments for the selected ways */
794 goto endloop;
795
796 /* Write the results */
797
798 for(i=0;i<nnodes_to;i++)
799 {
800 if(node_to[i]==node_from)
801 continue;
802
803 relationx.from=node_from;
804 relationx.to =node_to[i];
805
806 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
807
808 total++;
809
810 if(!(total%10000))
811 printf_middle("Processing Turn Restriction Relations (2): Turn Relations=%d New=%d",total,total-relationsx->trnumber);
812 }
813 }
814
815 /* Force super nodes on via node and adjacent nodes */
816
817 nodex=LookupNodeX(nodesx,relationx.via,1);
818 nodex->flags|=NODE_TURNRSTRCT;
819 PutBackNodeX(nodesx,relationx.via,1);
820
821 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
822
823 do
824 {
825 index_t othernode=OtherNode(segmentx,relationx.via);
826
827 nodex=LookupNodeX(nodesx,othernode,1);
828 nodex->flags|=NODE_TURNRSTRCT2;
829 PutBackNodeX(nodesx,othernode,1);
830
831 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via,1);
832 }
833 while(segmentx);
834
835 endloop: ;
836 }
837
838 /* Close the files */
839
840 relationsx->trfd=CloseFile(relationsx->trfd);
841 CloseFile(trfd);
842
843 /* Unmap from memory / close the files */
844
845 #if !SLIM
846 nodesx->xdata=UnmapFile(nodesx->filename);
847 segmentsx->xdata=UnmapFile(segmentsx->filename);
848 #else
849 nodesx->fd=CloseFile(nodesx->fd);
850 segmentsx->fd=CloseFile(segmentsx->fd);
851 #endif
852
853 /* Print the final message */
854
855 printf_last("Processed Turn Restriction Relations (2): Turn Relations=%d New=%d",total,total-relationsx->trnumber);
856
857 relationsx->trnumber=total;
858 }
859
860
861 /*++++++++++++++++++++++++++++++++++++++
862 Process the turn relations (third part) to update them with the re-ordered node information.
863
864 RelationsX *relationsx The set of relations to process.
865
866 SegmentsX *segmentsx The set of segments to process.
867 ++++++++++++++++++++++++++++++++++++++*/
868
869 void ProcessTurnRelations3(RelationsX *relationsx,SegmentsX *segmentsx)
870 {
871 int trfd;
872 int i;
873
874 if(segmentsx->number==0)
875 return;
876
877 /* Print the start message */
878
879 printf_first("Processing Turn Restriction Relations (3): Turn Relations=0");
880
881 /* Map into memory / open the files */
882
883 #if !SLIM
884 segmentsx->xdata=MapFile(segmentsx->filename);
885 #else
886 segmentsx->fd=ReOpenFile(segmentsx->filename);
887 #endif
888
889 /* Re-open the file read-only and a new file writeable */
890
891 relationsx->trfd=ReOpenFile(relationsx->trfilename);
892
893 DeleteFile(relationsx->trfilename);
894
895 trfd=OpenFileNew(relationsx->trfilename);
896
897 /* Process all of the relations */
898
899 for(i=0;i<relationsx->trnumber;i++)
900 {
901 TurnRestrictRelX relationx;
902 SegmentX *segmentx;
903 index_t from_node,via_node,to_node;
904
905 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
906
907 from_node=relationx.from;
908 via_node =relationx.via;
909 to_node =relationx.to;
910
911 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
912
913 do
914 {
915 if(OtherNode(segmentx,relationx.via)==from_node)
916 relationx.from=IndexSegmentX(segmentsx,segmentx);
917
918 if(OtherNode(segmentx,relationx.via)==to_node)
919 relationx.to=IndexSegmentX(segmentsx,segmentx);
920
921 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via,1);
922 }
923 while(segmentx);
924
925 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
926
927 if(!(relationsx->trnumber%10000))
928 printf_middle("Processing Turn Restriction Relations (3): Turn Relations=%d",relationsx->trnumber);
929 }
930
931 /* Close the files */
932
933 relationsx->trfd=CloseFile(relationsx->trfd);
934 CloseFile(trfd);
935
936 /* Unmap from memory / close the files */
937
938 #if !SLIM
939 segmentsx->xdata=UnmapFile(segmentsx->filename);
940 #else
941 segmentsx->fd=CloseFile(segmentsx->fd);
942 #endif
943
944 /* Print the final message */
945
946 printf_last("Processed Turn Restriction Relations (3): Turn Relations=%d",relationsx->trnumber);
947 }
948
949
950 /*++++++++++++++++++++++++++++++++++++++
951 Update the node indexes after geographical sorting.
952
953 RelationsX *relationsx The set of relations to process.
954
955 NodesX *nodesx The set of nodes to use.
956 ++++++++++++++++++++++++++++++++++++++*/
957
958 void UpdateTurnRelations(RelationsX *relationsx,NodesX *nodesx)
959 {
960 int trfd;
961 int i;
962
963 /* Print the start message */
964
965 printf_first("Updating Turn Restriction Relations: Turn Relations=0");
966
967 /* Re-open the file read-only and a new file writeable */
968
969 relationsx->trfd=ReOpenFile(relationsx->trfilename);
970
971 DeleteFile(relationsx->trfilename);
972
973 trfd=OpenFileNew(relationsx->trfilename);
974
975 /* Process all of the relations */
976
977 for(i=0;i<relationsx->trnumber;i++)
978 {
979 TurnRestrictRelX relationx;
980
981 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
982
983 relationx.via=nodesx->gdata[relationx.via];
984
985 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
986
987 if(!(relationsx->trnumber%10000))
988 printf_middle("Updating Turn Restriction Relations: Turn Relations=%d",relationsx->trnumber);
989 }
990
991 /* Close the files */
992
993 relationsx->trfd=CloseFile(relationsx->trfd);
994 CloseFile(trfd);
995
996 /* Print the final message */
997
998 printf_last("Updated Turn Restriction Relations: Turn Relations=%d",relationsx->trnumber);
999 }
1000
1001
1002 /*++++++++++++++++++++++++++++++++++++++
1003 Save the relation list to a file.
1004
1005 RelationsX* relationsx The set of relations to save.
1006
1007 const char *filename The name of the file to save.
1008 ++++++++++++++++++++++++++++++++++++++*/
1009
1010 void SaveRelationList(RelationsX* relationsx,const char *filename)
1011 {
1012 index_t i;
1013 int fd;
1014 RelationsFile relationsfile={0};
1015
1016 /* Print the start message */
1017
1018 printf_first("Writing Relations: Turn Relations=0");
1019
1020 /* Re-open the file read-only */
1021
1022 relationsx->trfd=ReOpenFile(relationsx->trfilename);
1023
1024 /* Write out the relations data */
1025
1026 fd=OpenFileNew(filename);
1027
1028 SeekFile(fd,sizeof(RelationsFile));
1029
1030 for(i=0;i<relationsx->trnumber;i++)
1031 {
1032 TurnRestrictRelX relationx;
1033 TurnRelation relation;
1034
1035 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
1036
1037 relation.from=relationx.from;
1038 relation.via=relationx.via;
1039 relation.to=relationx.to;
1040 relation.except=relationx.except;
1041
1042 WriteFile(fd,&relation,sizeof(TurnRelation));
1043
1044 if(!((i+1)%10000))
1045 printf_middle("Writing Relations: Turn Relations=%d",i+1);
1046 }
1047
1048 /* Write out the header structure */
1049
1050 relationsfile.trnumber=relationsx->trnumber;
1051
1052 SeekFile(fd,0);
1053 WriteFile(fd,&relationsfile,sizeof(RelationsFile));
1054
1055 CloseFile(fd);
1056
1057 /* Close the file */
1058
1059 relationsx->trfd=CloseFile(relationsx->trfd);
1060
1061 /* Print the final message */
1062
1063 printf_last("Wrote Relations: Turn Relations=%d",relationsx->trnumber);
1064 }