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 557 - (show annotations) (download) (as text)
Mon Dec 20 19:11:02 2010 UTC (14 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 21389 byte(s)
Make the PutBack*() functions be no-ops in slim mode and remove the
pre-processor guards from around the function calls.

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