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 559 - (show annotations) (download) (as text)
Tue Dec 21 12:23:04 2010 UTC (14 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 22468 byte(s)
Finish the processing of the turn relations now that the extra node lookup table
is in place.

1 /***************************************
2 $Header: /home/amb/CVS/routino/src/relationsx.c,v 1.19 2010-12-21 12:23:04 amb Exp $
3
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 #include "types.h"
32 #include "relations.h"
33
34 #include "nodesx.h"
35 #include "segmentsx.h"
36 #include "waysx.h"
37 #include "relationsx.h"
38
39 #include "files.h"
40 #include "logging.h"
41 #include "sorting.h"
42
43
44 /* Functions */
45
46 static int sort_by_id(TurnRestrictRelX *a,TurnRestrictRelX *b);
47 static int deduplicate_by_id(TurnRestrictRelX *relationx,index_t index);
48
49 static int sort_by_via(TurnRestrictRelX *a,TurnRestrictRelX *b);
50
51
52 /* Variables */
53
54 /*+ The command line '--tmpdir' option or its default value. +*/
55 extern char *option_tmpdirname;
56
57 static RelationsX* sortrelationsx;
58
59
60 /*++++++++++++++++++++++++++++++++++++++
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
77 /* Route Relations */
78
79 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 relationsx->rfd=OpenFileAppend(relationsx->rfilename);
91
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 relationsx->rfd=OpenFileNew(relationsx->rfilename);
109
110
111 /* Turn Restriction Relations */
112
113 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 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 /* Route relations */
148
149 if(!keep)
150 DeleteFile(relationsx->rfilename);
151
152 free(relationsx->rfilename);
153
154
155 /* Turn Restriction relations */
156
157 if(!keep)
158 DeleteFile(relationsx->trfilename);
159
160 free(relationsx->trfilename);
161
162 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 transports_t routes The types of routes that this relation is for.
174
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 void AppendRouteRelation(RelationsX* relationsx,relation_t id,
185 transports_t routes,
186 way_t *ways,int nways,
187 relation_t *relations,int nrelations)
188 {
189 RouteRelX relationx;
190 FILESORT_VARINT size;
191 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 WriteFile(relationsx->rfd,&size,FILESORT_VARSIZE);
200 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 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 Sort the list of relations.
255
256 RelationsX* relationsx The set of relations to process.
257 ++++++++++++++++++++++++++++++++++++++*/
258
259 void SortRelationList(RelationsX* relationsx)
260 {
261 /* Close the files (finished appending) */
262
263 CloseFile(relationsx->rfd);
264
265 CloseFile(relationsx->trfd);
266
267
268 /* Route Relations */
269
270
271 /* Turn Restriction Relations. */
272
273 if(relationsx->trxnumber)
274 {
275 int trfd;
276
277 /* Print the start message */
278
279 printf_first("Sorting Turn Restriction Relations");
280
281 /* Re-open the file read-only and a new file writeable */
282
283 relationsx->trfd=ReOpenFile(relationsx->trfilename);
284
285 DeleteFile(relationsx->trfilename);
286
287 trfd=OpenFileNew(relationsx->trfilename);
288
289 /* Sort the relations */
290
291 sortrelationsx=relationsx;
292
293 filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRestrictRelX),(int (*)(const void*,const void*))sort_by_id,(int (*)(void*,index_t))deduplicate_by_id);
294
295 /* Close the files */
296
297 CloseFile(relationsx->trfd);
298 CloseFile(trfd);
299
300 /* Print the final message */
301
302 printf_last("Sorted Relations: Relations=%d Duplicates=%d",relationsx->trxnumber,relationsx->trxnumber-relationsx->trnumber);
303 }
304 }
305
306
307 /*++++++++++++++++++++++++++++++++++++++
308 Sort the turn restriction relations into id order.
309
310 int sort_by_id Returns the comparison of the id fields.
311
312 TurnRestrictRelX *a The first extended relation.
313
314 TurnRestrictRelX *b The second extended relation.
315 ++++++++++++++++++++++++++++++++++++++*/
316
317 static int sort_by_id(TurnRestrictRelX *a,TurnRestrictRelX *b)
318 {
319 relation_t a_id=a->id;
320 relation_t b_id=b->id;
321
322 if(a_id<b_id)
323 return(-1);
324 else if(a_id>b_id)
325 return(1);
326 else
327 return(0);
328 }
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 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 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 RouteRelX *unmatched=NULL,*lastunmatched=NULL;
453 int nunmatched=0,lastnunmatched=0,iteration=0;
454
455 if(waysx->number==0)
456 return;
457
458 /* Map into memory / open the files */
459
460 #if !SLIM
461 waysx->xdata=MapFileWriteable(waysx->filename);
462 #else
463 waysx->fd=ReOpenFileWriteable(waysx->filename);
464 #endif
465
466 /* Re-open the file read-only */
467
468 relationsx->rfd=ReOpenFile(relationsx->rfilename);
469
470 /* Read through the file. */
471
472 do
473 {
474 int ways=0,relations=0;
475 int i;
476
477 SeekFile(relationsx->rfd,0);
478
479 /* Print the start message */
480
481 printf_first("Processing Route Relations: Iteration=%d Relations=0 Modified Ways=0",iteration);
482
483 for(i=0;i<relationsx->rxnumber;i++)
484 {
485 FILESORT_VARINT size;
486 RouteRelX relationx;
487 way_t wayid;
488 relation_t relationid;
489 transports_t routes=Transports_None;
490
491 /* Read each route relation */
492
493 ReadFile(relationsx->rfd,&size,FILESORT_VARSIZE);
494 ReadFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
495
496 /* Decide what type of route it is */
497
498 if(iteration==0)
499 {
500 relations++;
501 routes=relationx.routes;
502 }
503 else
504 {
505 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 routes=lastunmatched[j].routes;
516 break;
517 }
518 }
519
520 /* 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 index_t way=IndexWayX(waysx,wayid);
531
532 if(way!=NO_WAY)
533 {
534 WayX *wayx=LookupWayX(waysx,way,1);
535
536 if(routes&Transports_Foot)
537 wayx->way.props|=Properties_FootRoute;
538
539 if(routes&Transports_Bicycle)
540 wayx->way.props|=Properties_BicycleRoute;
541
542 PutBackWayX(waysx,way,1);
543
544 ways++;
545 }
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 if(relationid && routes && relationid!=relationx.id)
559 {
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 printf_middle("Processing Route Relations: Iteration=%d Relations=%d Modified Ways=%d",iteration,relations,ways);
573 }
574
575 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 printf_last("Processed Route Relations: Iteration=%d Relations=%d Modified Ways=%d",iteration,relations,ways);
587 }
588 while(lastnunmatched && ++iteration<5);
589
590 if(lastunmatched)
591 free(lastunmatched);
592
593 /* Close the file */
594
595 CloseFile(relationsx->rfd);
596
597 /* Unmap from memory / close the files */
598
599 #if !SLIM
600 waysx->xdata=UnmapFile(waysx->filename);
601 #else
602 CloseFile(waysx->fd);
603 #endif
604 }
605
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 TurnRestrictRelX relationx;
622 int trfd;
623 int total=0;
624
625 if(nodesx->number==0 || segmentsx->number==0)
626 return;
627
628 /* Print the start message */
629
630 printf_first("Processing Turn Restriction Relations (1): Turn Relations=0");
631
632 /* Map into memory / open the files */
633
634 #if !SLIM
635 nodesx->xdata=MapFile(nodesx->filename);
636 segmentsx->xdata=MapFile(segmentsx->filename);
637 #else
638 nodesx->fd=ReOpenFile(nodesx->filename);
639 segmentsx->fd=ReOpenFile(segmentsx->filename);
640 #endif
641
642 /* Re-open the file read-only and a new file writeable */
643
644 relationsx->trfd=ReOpenFile(relationsx->trfilename);
645
646 DeleteFile(relationsx->trfilename);
647
648 trfd=OpenFileNew(relationsx->trfilename);
649
650 /* Process all of the relations */
651
652 while(!ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX)))
653 {
654 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 index_t seg;
660 node_t node_from=NO_NODE,node_to=NO_NODE;
661
662 /* Find the segments that join the node 'via' */
663
664 seg=IndexFirstSegmentX1(segmentsx,relationx.via);
665
666 do
667 {
668 SegmentX *segx=LookupSegmentX(segmentsx,seg,1);
669
670 if(segx->way==relationx.from)
671 {
672 if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
673 goto endloop;
674
675 node_from=segx->node2;
676 }
677
678 if(segx->way==relationx.to)
679 {
680 if(node_to!=NO_NODE) /* Only one segment can be on the 'to' way */
681 goto endloop;
682
683 node_to=segx->node2;
684 }
685
686 seg=IndexNextSegmentX1(segmentsx,seg,relationx.via);
687 }
688 while(seg!=NO_SEGMENT);
689
690 if(node_to==NO_NODE || node_from==NO_NODE) /* Not enough segments for the selected ways */
691 goto endloop;
692
693 /* Write the results */
694
695 relationx.from=IndexNodeX(nodesx,node_from);
696 relationx.to =IndexNodeX(nodesx,node_to);
697 relationx.via =IndexNodeX(nodesx,relationx.via);
698
699 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
700
701 total++;
702
703 if(!(total%10000))
704 printf_middle("Processing Turn Restriction Relations (1): Turn Relations=%d New=%d",total,total-relationsx->trnumber);
705 }
706 else
707 {
708 index_t seg;
709 node_t node_from=NO_NODE,node_to[8];
710 int nnodes_to=0,i;
711
712 /* Find the segments that join the node 'via' */
713
714 seg=IndexFirstSegmentX1(segmentsx,relationx.via);
715
716 do
717 {
718 SegmentX *segx=LookupSegmentX(segmentsx,seg,1);
719
720 if(segx->way==relationx.from)
721 {
722 if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
723 goto endloop;
724
725 node_from=segx->node2;
726 }
727
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 }
738 while(seg!=NO_SEGMENT);
739
740 if(nnodes_to==0 || node_from==NO_NODE) /* Not enough segments for the selected ways */
741 goto endloop;
742
743 /* Write the results */
744
745 relationx.via=IndexNodeX(nodesx,relationx.via);
746
747 for(i=0;i<nnodes_to;i++)
748 {
749 if(node_to[i]==node_from)
750 continue;
751
752 relationx.from=IndexNodeX(nodesx,node_from);
753 relationx.to =IndexNodeX(nodesx,node_to[i]);
754
755 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
756
757 total++;
758
759 if(!(total%10000))
760 printf_middle("Processing Turn Restriction Relations (1): Turn Relations=%d New=%d",total,total-relationsx->trnumber);
761 }
762 }
763
764 endloop: ;
765 }
766
767 /* Close the files */
768
769 CloseFile(relationsx->trfd);
770 CloseFile(trfd);
771
772 /* Unmap from memory / close the files */
773
774 #if !SLIM
775 nodesx->xdata=UnmapFile(nodesx->filename);
776 segmentsx->xdata=UnmapFile(segmentsx->filename);
777 #else
778 CloseFile(nodesx->fd);
779 CloseFile(segmentsx->fd);
780 #endif
781
782 /* Print the final message */
783
784 printf_last("Processing Turn Restriction Relations (1): Turn Relations=%d New=%d",total,total-relationsx->trnumber);
785
786 relationsx->trnumber=total;
787 }
788
789
790 /*++++++++++++++++++++++++++++++++++++++
791 Process the turn relations (second part) to update them with the re-ordered node information.
792
793 RelationsX *relationsx The set of relations to process.
794
795 NodesX *nodesx The set of nodes to process.
796 ++++++++++++++++++++++++++++++++++++++*/
797
798 void ProcessTurnRelations2(RelationsX *relationsx,NodesX *nodesx)
799 {
800 int trfd;
801 int i;
802
803 /* Print the start message */
804
805 printf_first("Processing Turn Restriction Relations (2): Turn Relations=0");
806
807 /* Re-open the file read-only and a new file writeable */
808
809 relationsx->trfd=ReOpenFile(relationsx->trfilename);
810
811 DeleteFile(relationsx->trfilename);
812
813 trfd=OpenFileNew(relationsx->trfilename);
814
815 /* Process all of the relations */
816
817 for(i=0;i<relationsx->trnumber;i++)
818 {
819 TurnRestrictRelX relationx;
820
821 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
822
823 relationx.from=nodesx->gdata[relationx.from];
824
825 relationx.via=nodesx->gdata[relationx.via];
826
827 relationx.to=nodesx->gdata[relationx.to];
828
829 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
830
831 if(!(relationsx->trnumber%10000))
832 printf_middle("Processing Turn Restriction Relations (2): Turn Relations=%d",relationsx->trnumber);
833 }
834
835 /* Close the files */
836
837 CloseFile(relationsx->trfd);
838 CloseFile(trfd);
839
840 /* Print the final message */
841
842 printf_last("Processing Turn Restriction Relations (2): Turn Relations=%d",relationsx->trnumber);
843 }
844
845
846 /*++++++++++++++++++++++++++++++++++++++
847 Save the relation list to a file.
848
849 RelationsX* relationsx The set of relations to save.
850
851 const char *filename The name of the file to save.
852 ++++++++++++++++++++++++++++++++++++++*/
853
854 void SaveRelationList(RelationsX* relationsx,const char *filename)
855 {
856 index_t i;
857 int fd;
858 RelationsFile relationsfile={0};
859
860 /* Print the start message */
861
862 printf_first("Writing Relations: Turn Relations=0");
863
864 /* Re-open the file read-only */
865
866 relationsx->trfd=ReOpenFile(relationsx->trfilename);
867
868 /* Write out the relations data */
869
870 fd=OpenFileNew(filename);
871
872 SeekFile(fd,sizeof(RelationsFile));
873
874 for(i=0;i<relationsx->trnumber;i++)
875 {
876 TurnRestrictRelX relationx;
877 TurnRelation relation;
878
879 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
880
881 relation.from=relationx.from;
882 relation.via=relationx.via;
883 relation.to=relationx.to;
884 relation.except=relationx.except;
885
886 WriteFile(fd,&relation,sizeof(TurnRelation));
887
888 if(!((i+1)%10000))
889 printf_middle("Writing Relations: Turn Relations=%d",i+1);
890 }
891
892 /* Write out the header structure */
893
894 relationsfile.trnumber=relationsx->trnumber;
895
896 SeekFile(fd,0);
897 WriteFile(fd,&relationsfile,sizeof(RelationsFile));
898
899 CloseFile(fd);
900
901 /* Close the file */
902
903 CloseFile(relationsx->trfd);
904
905 /* Print the final message */
906
907 printf_last("Wrote Relations: Turn Relations=%d",relationsx->trnumber);
908 }