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 548 - (show annotations) (download) (as text)
Sun Dec 19 11:34:02 2010 UTC (14 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 22240 byte(s)
A temporary check-in that handles turn restrictions more complicated than
actually allowed (ways must start/end at the via node).

1 /***************************************
2 $Header: /home/amb/CVS/routino/src/relationsx.c,v 1.15 2010-12-19 11:34:02 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_via(TurnRestrictRelX *a,TurnRestrictRelX *b);
47 static int deduplicate_by_id(TurnRestrictRelX *relationx,index_t index);
48
49 static int bearing_angle(NodesX *nodesx,index_t via,node_t node);
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 /* Route relations */
77
78 relationsx->rfilename=(char*)malloc(strlen(option_tmpdirname)+32);
79
80 if(append)
81 sprintf(relationsx->rfilename,"%s/relationsx.route.input.tmp",option_tmpdirname);
82 else
83 sprintf(relationsx->rfilename,"%s/relationsx.route.%p.tmp",option_tmpdirname,relationsx);
84
85 if(append)
86 {
87 off_t size,position=0;
88
89 relationsx->rfd=OpenFileAppend(relationsx->rfilename);
90
91 size=SizeFile(relationsx->rfilename);
92
93 while(position<size)
94 {
95 FILESORT_VARINT relationsize;
96
97 SeekFile(relationsx->rfd,position);
98 ReadFile(relationsx->rfd,&relationsize,FILESORT_VARSIZE);
99
100 relationsx->rxnumber++;
101 position+=relationsize+FILESORT_VARSIZE;
102 }
103
104 SeekFile(relationsx->rfd,size);
105 }
106 else
107 relationsx->rfd=OpenFileNew(relationsx->rfilename);
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->trxnumber=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 /* Turn Restriction relations */
153
154 if(!keep)
155 DeleteFile(relationsx->trfilename);
156
157 free(relationsx->trfilename);
158
159 free(relationsx);
160 }
161
162
163 /*++++++++++++++++++++++++++++++++++++++
164 Append a single relation to an unsorted route relation list.
165
166 RelationsX* relationsx The set of relations to process.
167
168 relation_t id The ID of the relation.
169
170 transports_t routes The types of routes that this relation is for.
171
172 way_t *ways The array of ways that are members of the relation.
173
174 int nways The number of ways that are members of the relation.
175
176 relation_t *relations The array of relations that are members of the relation.
177
178 int nrelations The number of relations that are members of the relation.
179 ++++++++++++++++++++++++++++++++++++++*/
180
181 void AppendRouteRelation(RelationsX* relationsx,relation_t id,
182 transports_t routes,
183 way_t *ways,int nways,
184 relation_t *relations,int nrelations)
185 {
186 RouteRelX relationx;
187 FILESORT_VARINT size;
188 way_t zeroway=0;
189 relation_t zerorelation=0;
190
191 relationx.id=id;
192 relationx.routes=routes;
193
194 size=sizeof(RouteRelX)+(nways+1)*sizeof(way_t)+(nrelations+1)*sizeof(relation_t);
195
196 WriteFile(relationsx->rfd,&size,FILESORT_VARSIZE);
197 WriteFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
198
199 WriteFile(relationsx->rfd,ways ,nways*sizeof(way_t));
200 WriteFile(relationsx->rfd,&zeroway, sizeof(way_t));
201
202 WriteFile(relationsx->rfd,relations ,nrelations*sizeof(relation_t));
203 WriteFile(relationsx->rfd,&zerorelation, sizeof(relation_t));
204
205 relationsx->rxnumber++;
206
207 assert(!(relationsx->rxnumber==0)); /* Zero marks the high-water mark for relations. */
208 }
209
210
211 /*++++++++++++++++++++++++++++++++++++++
212 Append a single relation to an unsorted turn restriction relation list.
213
214 RelationsX* relationsx The set of relations to process.
215
216 relation_t id The ID of the relation.
217
218 way_t from The way that the turn restriction starts from.
219
220 way_t to The way that the restriction finished on.
221
222 node_t via The node that the turn restriction passes through.
223
224 TurnRestriction restriction The type of restriction.
225
226 transports_t except The set of transports allowed to bypass the restriction.
227 ++++++++++++++++++++++++++++++++++++++*/
228
229 void AppendTurnRestrictRelation(RelationsX* relationsx,relation_t id,
230 way_t from,way_t to,node_t via,
231 TurnRestriction restriction,transports_t except)
232 {
233 TurnRestrictRelX relationx;
234
235 relationx.id=id;
236 relationx.from=from;
237 relationx.to=to;
238 relationx.via=via;
239 relationx.restrict=restriction;
240 relationx.except=except;
241
242 WriteFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
243
244 relationsx->trxnumber++;
245
246 assert(!(relationsx->trxnumber==0)); /* Zero marks the high-water mark for relations. */
247 }
248
249
250 /*++++++++++++++++++++++++++++++++++++++
251 Sort the list of relations.
252
253 RelationsX* relationsx The set of relations to process.
254 ++++++++++++++++++++++++++++++++++++++*/
255
256 void SortRelationList(RelationsX* relationsx)
257 {
258 /* Don't need to sort route relations */
259
260
261 /* Sort the turn restriction relations by node. */
262
263 int trfd;
264
265 /* Print the start message */
266
267 printf_first("Sorting Turn Restriction Relations");
268
269 /* Open the new file */
270
271 DeleteFile(relationsx->trfilename);
272
273 trfd=OpenFileNew(relationsx->trfilename);
274
275 /* Sort the relations */
276
277 sortrelationsx=relationsx;
278
279 filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRestrictRelX),(int (*)(const void*,const void*))sort_by_via,(int (*)(void*,index_t))deduplicate_by_id);
280
281 /* Close the files and re-open read-only */
282
283 CloseFile(relationsx->trfd);
284 CloseFile(trfd);
285
286 relationsx->trfd=ReOpenFile(relationsx->trfilename);
287
288 /* Print the final message */
289
290 printf_last("Sorted Relations: Relations=%d Duplicates=%d",relationsx->trxnumber,relationsx->trxnumber-relationsx->trnumber);
291 }
292
293
294 /*++++++++++++++++++++++++++++++++++++++
295 Sort the turn restriction relations into via node order.
296
297 int sort_by_via Returns the comparison of the via fields.
298
299 TurnRestrictRelX *a The first extended relation.
300
301 TurnRestrictRelX *b The second extended relation.
302 ++++++++++++++++++++++++++++++++++++++*/
303
304 static int sort_by_via(TurnRestrictRelX *a,TurnRestrictRelX *b)
305 {
306 node_t a_id=a->via;
307 node_t b_id=b->via;
308
309 if(a_id<b_id)
310 return(-1);
311 else if(a_id>b_id)
312 return(1);
313 else
314 {
315 relation_t a_id=a->id;
316 relation_t b_id=b->id;
317
318 if(a_id<b_id)
319 return(-1);
320 else if(a_id>b_id)
321 return(1);
322 else
323 return(0);
324 }
325 }
326
327
328 /*++++++++++++++++++++++++++++++++++++++
329 Deduplicate the extended relations using the id after sorting.
330
331 int deduplicate_by_id Return 1 if the value is to be kept, otherwise zero.
332
333 TurnRestrictRelX *relationx The extended relation.
334
335 index_t index The index of this relation in the total.
336 ++++++++++++++++++++++++++++++++++++++*/
337
338 static int deduplicate_by_id(TurnRestrictRelX *relationx,index_t index)
339 {
340 static relation_t previd;
341
342 if(index==0 || relationx->id!=previd)
343 {
344 previd=relationx->id;
345
346 sortrelationsx->trnumber++;
347
348 return(1);
349 }
350
351 return(0);
352 }
353
354
355 /*++++++++++++++++++++++++++++++++++++++
356 Process the route relations and apply the information to the ways.
357
358 RelationsX *relationsx The set of relations to process.
359
360 WaysX *waysx The set of ways to update.
361 ++++++++++++++++++++++++++++++++++++++*/
362
363 void ProcessRouteRelations(RelationsX *relationsx,WaysX *waysx)
364 {
365 RouteRelX *unmatched=NULL,*lastunmatched=NULL;
366 int nunmatched=0,lastnunmatched=0,iteration=0;
367
368 if(waysx->number==0)
369 return;
370
371 /* Map into memory */
372
373 #if !SLIM
374 waysx->xdata=MapFileWriteable(waysx->filename);
375 #endif
376
377 /* Re-open the ways file read/write */
378
379 #if SLIM
380 CloseFile(waysx->fd);
381 waysx->fd=ReOpenFileWriteable(waysx->filename);
382 #endif
383
384 /* Close the file and re-open it (finished appending) */
385
386 CloseFile(relationsx->rfd);
387 relationsx->rfd=ReOpenFile(relationsx->rfilename);
388
389 /* Read through the file. */
390
391 do
392 {
393 int ways=0,relations=0;
394 int i;
395
396 SeekFile(relationsx->rfd,0);
397
398 /* Print the start message */
399
400 printf_first("Processing Route Relations: Iteration=%d Relations=0 Modified Ways=0",iteration);
401
402 for(i=0;i<relationsx->rxnumber;i++)
403 {
404 FILESORT_VARINT size;
405 RouteRelX relationx;
406 way_t wayid;
407 relation_t relationid;
408 transports_t routes=Transports_None;
409
410 /* Read each route relation */
411
412 ReadFile(relationsx->rfd,&size,FILESORT_VARSIZE);
413 ReadFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
414
415 /* Decide what type of route it is */
416
417 if(iteration==0)
418 {
419 relations++;
420 routes=relationx.routes;
421 }
422 else
423 {
424 int j;
425
426 for(j=0;j<lastnunmatched;j++)
427 if(lastunmatched[j].id==relationx.id)
428 {
429 relations++;
430
431 if((lastunmatched[j].routes|relationx.routes)==relationx.routes)
432 routes=0; /* Nothing new to add */
433 else
434 routes=lastunmatched[j].routes;
435 break;
436 }
437 }
438
439 /* Loop through the ways */
440
441 do
442 {
443 ReadFile(relationsx->rfd,&wayid,sizeof(way_t));
444
445 /* Update the ways that are listed for the relation */
446
447 if(wayid && routes)
448 {
449 index_t way=IndexWayX(waysx,wayid);
450
451 if(way!=NO_WAY)
452 {
453 WayX *wayx=LookupWayX(waysx,way,1);
454
455 if(routes&Transports_Foot)
456 wayx->way.props|=Properties_FootRoute;
457
458 if(routes&Transports_Bicycle)
459 wayx->way.props|=Properties_BicycleRoute;
460
461 #if SLIM
462 PutBackWayX(waysx,way,1);
463 #endif
464
465 ways++;
466 }
467 }
468 }
469 while(wayid);
470
471 /* Loop through the relations */
472
473 do
474 {
475 ReadFile(relationsx->rfd,&relationid,sizeof(relation_t));
476
477 /* Add the relations that are listed for this relation to the list for next time */
478
479 if(relationid && routes && relationid!=relationx.id)
480 {
481 if(nunmatched%256==0)
482 unmatched=(RouteRelX*)realloc((void*)unmatched,(nunmatched+256)*sizeof(RouteRelX));
483
484 unmatched[nunmatched].id=relationid;
485 unmatched[nunmatched].routes=routes;
486
487 nunmatched++;
488 }
489 }
490 while(relationid);
491
492 if(!((i+1)%10000))
493 printf_middle("Processing Route Relations: Iteration=%d Relations=%d Modified Ways=%d",iteration,relations,ways);
494 }
495
496 if(lastunmatched)
497 free(lastunmatched);
498
499 lastunmatched=unmatched;
500 lastnunmatched=nunmatched;
501
502 unmatched=NULL;
503 nunmatched=0;
504
505 /* Print the final message */
506
507 printf_last("Processed Route Relations: Iteration=%d Relations=%d Modified Ways=%d",iteration,relations,ways);
508 }
509 while(lastnunmatched && ++iteration<5);
510
511 if(lastunmatched)
512 free(lastunmatched);
513
514 CloseFile(relationsx->rfd);
515
516 /* Unmap from memory */
517
518 #if !SLIM
519 waysx->xdata=UnmapFile(waysx->filename);
520 #endif
521
522 /* Re-open the ways file read only */
523
524 #if SLIM
525 CloseFile(waysx->fd);
526 waysx->fd=ReOpenFile(waysx->filename);
527 #endif
528 }
529
530
531 /*++++++++++++++++++++++++++++++++++++++
532 Process the turn relations (first part) to update them with the node information.
533
534 RelationsX *relationsx The set of relations to process.
535
536 NodesX *nodesx The set of nodes to process.
537
538 SegmentsX *segmentsx The set of segments to process.
539
540 WaysX *waysx The set of ways to process.
541 ++++++++++++++++++++++++++++++++++++++*/
542
543 void ProcessTurnRelations1(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx)
544 {
545 TurnRestrictRelX relationx;
546 int trfd;
547
548 if(nodesx->number==0 || segmentsx->number==0)
549 return;
550
551 /* Print the start message */
552
553 printf_first("Processing Turn Restriction Relations (1): Turn Relations=0");
554
555 /* Map into memory */
556
557 #if !SLIM
558 nodesx->xdata =MapFile(nodesx->filename);
559 segmentsx->xdata=MapFile(segmentsx->filename);
560 #endif
561
562 /* Close the file and re-open it (finished appending) */
563
564 CloseFile(relationsx->trfd);
565 relationsx->trfd=ReOpenFile(relationsx->trfilename);
566
567 /* Open the new file */
568
569 DeleteFile(relationsx->trfilename);
570
571 trfd=OpenFileNew(relationsx->trfilename);
572
573 /* Process all of the relations */
574
575 relationsx->trnumber=0;
576
577 while(!ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX)))
578 {
579 if(relationx.restrict==TurnRestrict_no_right_turn ||
580 relationx.restrict==TurnRestrict_no_left_turn ||
581 relationx.restrict==TurnRestrict_no_u_turn ||
582 relationx.restrict==TurnRestrict_no_straight_on)
583 {
584 index_t seg,via;
585 node_t node_from[4],node_to[4];
586 int nodes_from=0,nodes_to=0;
587 node_t best_from=NO_NODE,best_to=NO_NODE;
588 int best_angle=180;
589 int i,j;
590
591 /* Find the segments that join the node 'via' */
592
593 seg=IndexFirstSegmentX1(segmentsx,relationx.via);
594
595 do
596 {
597 SegmentX *segx=LookupSegmentX(segmentsx,seg,1);
598
599 if(segx->way==relationx.from && segx->distance!=ONEWAY_1TO2)
600 {
601 node_from[nodes_from]=segx->node2;
602
603 if(++nodes_from==4)
604 break;
605 }
606
607 if(segx->way==relationx.to && segx->distance!=ONEWAY_2TO1)
608 {
609 node_to[nodes_to]=segx->node2;
610
611 if(++nodes_to==4)
612 break;
613 }
614
615 seg=IndexNextSegmentX1(segmentsx,seg,relationx.via);
616 }
617 while(seg!=NO_SEGMENT);
618
619 if(nodes_to==4 || nodes_from==4) /* Too many segments for the same way */
620 goto endloop;
621
622 if(nodes_to==0 || nodes_from==0) /* Not enough segments for the selected ways */
623 goto endloop;
624
625 /* Work out which combination of nodes match the restriction */
626
627 via=IndexNodeX(nodesx,relationx.via);
628
629 for(i=0;i<nodes_from;i++)
630 {
631 int angle_from=bearing_angle(nodesx,via,node_from[i]);
632
633 for(j=0;j<nodes_to;j++)
634 {
635 int angle_to=bearing_angle(nodesx,via,node_to[j]);
636 int turn_angle=angle_from-angle_to;
637
638 if(relationx.restrict==TurnRestrict_no_right_turn)
639 turn_angle-=90;
640 else if(relationx.restrict==TurnRestrict_no_left_turn)
641 turn_angle+=90;
642 else if(relationx.restrict==TurnRestrict_no_u_turn)
643 turn_angle-=0;
644 else /* if(relationx.restrict==TurnRestrict_no_straight_on) */
645 turn_angle-=180;
646
647 while(turn_angle> 180) turn_angle-=360;
648 while(turn_angle<-180) turn_angle+=360;
649
650 if(turn_angle<0) turn_angle=-turn_angle;
651
652 if(turn_angle<90 && best_angle<90) /* Too many ways at "good" angles */
653 goto endloop;
654
655 if(turn_angle<best_angle)
656 {
657 best_from=node_from[i];
658 best_to=node_to[j];
659 best_angle=turn_angle;
660 }
661 }
662 }
663
664 if(best_angle>90) /* Not a good enough match */
665 goto endloop;
666
667 /* Write the results */
668
669 relationx.from=IndexNodeX(nodesx,best_from);
670 relationx.to =IndexNodeX(nodesx,best_to);
671 relationx.via =via;
672
673 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
674
675 relationsx->trnumber++;
676
677 if(!(relationsx->trnumber%10000))
678 printf_middle("Processing Turn Restriction Relations (1): Turn Relations=%d",relationsx->trnumber);
679 }
680 else
681 {
682 /* Write the results */
683
684 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
685
686 relationsx->trnumber++;
687
688 if(!(relationsx->trnumber%10000))
689 printf_middle("Processing Turn Restriction Relations (1): Turn Relations=%d",relationsx->trnumber);
690 }
691
692 endloop: ;
693 }
694
695 /* Close the files and re-open read-only */
696
697 CloseFile(relationsx->trfd);
698 CloseFile(trfd);
699
700 relationsx->trfd=ReOpenFile(relationsx->trfilename);
701
702 /* Unmap from memory */
703
704 #if !SLIM
705 nodesx->xdata =UnmapFile(nodesx->filename);
706 segmentsx->xdata=UnmapFile(segmentsx->filename);
707 #endif
708
709 /* Print the final message */
710
711 printf_last("Processing Turn Restriction Relations (1): Turn Relations=%d",relationsx->trnumber);
712 }
713
714
715 /*++++++++++++++++++++++++++++++++++++++
716 Calculate the bearing of the segment between a pair of nodes.
717
718 int bearing_angle Returns a value in the range 0 to 359 indicating the bearing.
719
720 NodesX *nodesx The set of nodes to process.
721
722 index_t via The via node (the reference point around which the bearing is calculated).
723
724 node_t node The second node (the bearing of which is calculated from the via node).
725
726 Angles are calculated using flat Cartesian lat/long grid approximation (after scaling longitude due to latitude).
727 ++++++++++++++++++++++++++++++++++++++*/
728
729 static int bearing_angle(NodesX *nodesx,index_t via,node_t node)
730 {
731 double lat1,lat2;
732 double lon1,lon2;
733 double angle;
734 index_t index;
735 NodeX *nodex1,*nodex2;
736
737 index=IndexNodeX(nodesx,node);
738
739 nodex1=LookupNodeX(nodesx,via,1);
740 nodex2=LookupNodeX(nodesx,index,2);
741
742 lat1=nodex1->latitude;
743 lon1=nodex1->longitude;
744
745 lat2=nodex2->latitude;
746 lon2=nodex2->longitude;
747
748 angle=atan2((lat2-lat1),(lon2-lon1)*cos(lat1));
749
750 angle=radians_to_degrees(angle);
751
752 angle=round(270-angle);
753
754 if(angle< 0) angle+=360;
755 if(angle>360) angle-=360;
756
757 return((int)angle);
758 }
759
760
761 /*++++++++++++++++++++++++++++++++++++++
762 Process the turn relations (second part) to update them with the re-ordered node information.
763
764 RelationsX *relationsx The set of relations to process.
765
766 NodesX *nodesx The set of nodes to process.
767 ++++++++++++++++++++++++++++++++++++++*/
768
769 void ProcessTurnRelations2(RelationsX *relationsx,NodesX *nodesx)
770 {
771 int trfd;
772 index_t i;
773
774 /* Print the start message */
775
776 printf_first("Processing Turn Restriction Relations (2): Turn Relations=0");
777
778 /* Map into memory */
779
780 #if !SLIM
781 nodesx->xdata=MapFile(nodesx->filename);
782 #endif
783
784 /* Open the new file */
785
786 DeleteFile(relationsx->trfilename);
787
788 trfd=OpenFileNew(relationsx->trfilename);
789
790 /* Process all of the relations */
791
792 for(i=0;i<relationsx->trnumber;i++)
793 {
794 TurnRestrictRelX relationx;
795 NodeX *nodex;
796
797 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
798
799 nodex=LookupNodeX(nodesx,relationx.from,1);
800 relationx.from=nodex->id;
801
802 nodex=LookupNodeX(nodesx,relationx.via,1);
803 relationx.via=nodex->id;
804
805 nodex=LookupNodeX(nodesx,relationx.to,1);
806 relationx.to=nodex->id;
807
808 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
809
810 if(!((i+1)%10000))
811 printf_middle("Processing Turn Restriction Relations (2): Turn Relations=%d",i+1);
812 }
813
814 /* Close the files and re-open read-only */
815
816 CloseFile(relationsx->trfd);
817 CloseFile(trfd);
818
819 relationsx->trfd=ReOpenFile(relationsx->trfilename);
820
821 /* Unmap from memory */
822
823 #if !SLIM
824 nodesx->xdata=UnmapFile(nodesx->filename);
825 #endif
826
827 /* Print the final message */
828
829 printf_last("Processing Turn Restriction Relations (2): Turn Relations=%d",relationsx->trnumber);
830 }
831
832
833 /*++++++++++++++++++++++++++++++++++++++
834 Save the relation list to a file.
835
836 RelationsX* relationsx The set of relations to save.
837
838 const char *filename The name of the file to save.
839 ++++++++++++++++++++++++++++++++++++++*/
840
841 void SaveRelationList(RelationsX* relationsx,const char *filename)
842 {
843 index_t i;
844 int fd;
845 RelationsFile relationsfile={0};
846
847 /* Print the start message */
848
849 printf_first("Writing Relations: Turn Relations=0");
850
851 /* Write out the relations data */
852
853 fd=OpenFileNew(filename);
854
855 SeekFile(fd,sizeof(RelationsFile));
856
857 for(i=0;i<relationsx->trnumber;i++)
858 {
859 TurnRestrictRelX relationx;
860
861 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
862
863 WriteFile(fd,&relationx,sizeof(TurnRelation));
864
865 if(!((i+1)%10000))
866 printf_middle("Writing Relations: Turn Relations=%d",i+1);
867 }
868
869 /* Write out the header structure */
870
871 relationsfile.trnumber=relationsx->trnumber;
872
873 SeekFile(fd,0);
874 WriteFile(fd,&relationsfile,sizeof(RelationsFile));
875
876 CloseFile(fd);
877
878 /* Close the file */
879
880 CloseFile(relationsx->trfd);
881
882 /* Print the final message */
883
884 printf_last("Wrote Relations: Turn Relations=%d",relationsx->trnumber);
885 }