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 944 - (show annotations) (download) (as text)
Sun Dec 11 11:56:05 2011 UTC (13 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 31351 byte(s)
Fill the structures with zero before inserting data and writing to file (removes
junk from unused spaces in database files).

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 /* Local 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,(void*)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 SeekReadFile(relationsx->rfd,&relationsize,FILESORT_VARSIZE,position);
97
98 relationsx->rnumber++;
99 position+=relationsize+FILESORT_VARSIZE;
100 }
101
102 SeekFile(relationsx->rfd,size);
103 }
104 else
105 relationsx->rfd=OpenFileNew(relationsx->rfilename);
106
107
108 /* Turn Restriction Relations */
109
110 relationsx->trfilename=(char*)malloc(strlen(option_tmpdirname)+32);
111
112 if(append)
113 sprintf(relationsx->trfilename,"%s/relationsx.turn.input.tmp",option_tmpdirname);
114 else
115 sprintf(relationsx->trfilename,"%s/relationsx.turn.%p.tmp",option_tmpdirname,(void*)relationsx);
116
117 if(append)
118 {
119 off_t size;
120
121 relationsx->trfd=OpenFileAppend(relationsx->trfilename);
122
123 size=SizeFile(relationsx->trfilename);
124
125 relationsx->trnumber=size/sizeof(TurnRestrictRelX);
126 }
127 else
128 relationsx->trfd=OpenFileNew(relationsx->trfilename);
129
130 return(relationsx);
131 }
132
133
134 /*++++++++++++++++++++++++++++++++++++++
135 Free a relation list.
136
137 RelationsX *relationsx The set of relations to be freed.
138
139 int keep Set to 1 if the file is to be kept (for appending later).
140 ++++++++++++++++++++++++++++++++++++++*/
141
142 void FreeRelationList(RelationsX *relationsx,int keep)
143 {
144 /* Route relations */
145
146 if(!keep)
147 DeleteFile(relationsx->rfilename);
148
149 free(relationsx->rfilename);
150
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 noway=NO_WAY;
189 relation_t norelation=NO_RELATION;
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,&noway, sizeof(way_t));
201
202 WriteFile(relationsx->rfd,relations ,nrelations*sizeof(relation_t));
203 WriteFile(relationsx->rfd,&norelation, sizeof(relation_t));
204
205 relationsx->rnumber++;
206
207 assert(!(relationsx->rnumber==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.restriction=restriction;
240 relationx.except=except;
241
242 WriteFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
243
244 relationsx->trnumber++;
245
246 assert(!(relationsx->trnumber==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 /* Close the files (finished appending) */
259
260 relationsx->rfd=CloseFile(relationsx->rfd);
261
262 relationsx->trfd=CloseFile(relationsx->trfd);
263
264
265 /* Route Relations */
266
267
268 /* Turn Restriction Relations. */
269
270 if(relationsx->trnumber)
271 {
272 index_t trxnumber;
273 int trfd;
274
275 /* Print the start message */
276
277 printf_first("Sorting Turn Relations");
278
279 /* Re-open the file read-only and a new file writeable */
280
281 relationsx->trfd=ReOpenFile(relationsx->trfilename);
282
283 DeleteFile(relationsx->trfilename);
284
285 trfd=OpenFileNew(relationsx->trfilename);
286
287 /* Sort the relations */
288
289 trxnumber=relationsx->trnumber;
290 relationsx->trnumber=0;
291
292 sortrelationsx=relationsx;
293
294 filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRestrictRelX),(int (*)(const void*,const void*))sort_by_id,(int (*)(void*,index_t))deduplicate_by_id);
295
296 /* Close the files */
297
298 relationsx->trfd=CloseFile(relationsx->trfd);
299 CloseFile(trfd);
300
301 /* Print the final message */
302
303 printf_last("Sorted Turn Relations: Relations=%"Pindex_t" Duplicates=%"Pindex_t,trxnumber,trxnumber-relationsx->trnumber);
304 }
305 }
306
307
308 /*++++++++++++++++++++++++++++++++++++++
309 Sort the turn restriction relations into id order.
310
311 int sort_by_id Returns the comparison of the id fields.
312
313 TurnRestrictRelX *a The first extended relation.
314
315 TurnRestrictRelX *b The second extended relation.
316 ++++++++++++++++++++++++++++++++++++++*/
317
318 static int sort_by_id(TurnRestrictRelX *a,TurnRestrictRelX *b)
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 Deduplicate the extended relations using the id after sorting.
334
335 int deduplicate_by_id Return 1 if the value is to be kept, otherwise 0.
336
337 TurnRestrictRelX *relationx The extended relation.
338
339 index_t index The index of this relation in the total.
340 ++++++++++++++++++++++++++++++++++++++*/
341
342 static int deduplicate_by_id(TurnRestrictRelX *relationx,index_t index)
343 {
344 static relation_t previd;
345
346 if(index==0 || relationx->id!=previd)
347 {
348 previd=relationx->id;
349
350 sortrelationsx->trnumber++;
351
352 return(1);
353 }
354 else
355 {
356 logerror("Relation %"Prelation_t" is duplicated.\n",relationx->id);
357
358 return(0);
359 }
360 }
361
362
363 /*++++++++++++++++++++++++++++++++++++++
364 Sort the list of turn relations.
365
366 RelationsX* relationsx The set of relations to process.
367 ++++++++++++++++++++++++++++++++++++++*/
368
369 void SortTurnRelationList(RelationsX* relationsx)
370 {
371 int trfd;
372
373 if(relationsx->trnumber==0)
374 return;
375
376 /* Print the start message */
377
378 printf_first("Sorting Turn Relations");
379
380 /* Re-open the file read-only and a new file writeable */
381
382 relationsx->trfd=ReOpenFile(relationsx->trfilename);
383
384 DeleteFile(relationsx->trfilename);
385
386 trfd=OpenFileNew(relationsx->trfilename);
387
388 /* Sort the relations */
389
390 filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRestrictRelX),(int (*)(const void*,const void*))sort_by_via,NULL);
391
392 /* Close the files */
393
394 relationsx->trfd=CloseFile(relationsx->trfd);
395 CloseFile(trfd);
396
397 /* Print the final message */
398
399 printf_last("Sorted Turn Relations: Relations=%"Pindex_t,relationsx->trnumber);
400 }
401
402
403 /*++++++++++++++++++++++++++++++++++++++
404 Sort the turn restriction relations into via index order (then by from and to segments).
405
406 int sort_by_via Returns the comparison of the via, from and to fields.
407
408 TurnRestrictRelX *a The first extended relation.
409
410 TurnRestrictRelX *b The second extended relation.
411 ++++++++++++++++++++++++++++++++++++++*/
412
413 static int sort_by_via(TurnRestrictRelX *a,TurnRestrictRelX *b)
414 {
415 index_t a_id=a->via;
416 index_t b_id=b->via;
417
418 if(a_id<b_id)
419 return(-1);
420 else if(a_id>b_id)
421 return(1);
422 else
423 {
424 index_t a_id=a->from;
425 index_t b_id=b->from;
426
427 if(a_id<b_id)
428 return(-1);
429 else if(a_id>b_id)
430 return(1);
431 else
432 {
433 index_t a_id=a->to;
434 index_t b_id=b->to;
435
436 if(a_id<b_id)
437 return(-1);
438 else if(a_id>b_id)
439 return(1);
440 else
441 return(0);
442 }
443 }
444 }
445
446
447 /*++++++++++++++++++++++++++++++++++++++
448 Process the route relations and apply the information to the ways.
449
450 RelationsX *relationsx The set of relations to use.
451
452 WaysX *waysx The set of ways to modify.
453 ++++++++++++++++++++++++++++++++++++++*/
454
455 void ProcessRouteRelations(RelationsX *relationsx,WaysX *waysx)
456 {
457 RouteRelX *unmatched=NULL,*lastunmatched=NULL;
458 int nunmatched=0,lastnunmatched=0,iteration=1;
459
460 if(waysx->number==0)
461 return;
462
463 /* Map into memory / open the files */
464
465 #if !SLIM
466 waysx->data=MapFileWriteable(waysx->filename);
467 #else
468 waysx->fd=ReOpenFileWriteable(waysx->filename);
469 #endif
470
471 /* Re-open the file read-only */
472
473 relationsx->rfd=ReOpenFile(relationsx->rfilename);
474
475 /* Read through the file. */
476
477 do
478 {
479 int ways=0,relations=0;
480 index_t i;
481
482 SeekFile(relationsx->rfd,0);
483
484 /* Print the start message */
485
486 printf_first("Processing Route Relations (%d): Relations=0 Modified Ways=0",iteration);
487
488 for(i=0;i<relationsx->rnumber;i++)
489 {
490 FILESORT_VARINT size;
491 RouteRelX relationx;
492 way_t wayid;
493 relation_t relationid;
494 transports_t routes=Transports_None;
495
496 /* Read each route relation */
497
498 ReadFile(relationsx->rfd,&size,FILESORT_VARSIZE);
499 ReadFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
500
501 /* Decide what type of route it is */
502
503 if(iteration==1)
504 {
505 relations++;
506 routes=relationx.routes;
507 }
508 else
509 {
510 int j;
511
512 for(j=0;j<lastnunmatched;j++)
513 if(lastunmatched[j].id==relationx.id)
514 {
515 relations++;
516
517 if((lastunmatched[j].routes|relationx.routes)==relationx.routes)
518 routes=0; /* Nothing new to add */
519 else
520 routes=lastunmatched[j].routes;
521
522 break;
523 }
524 }
525
526 /* Loop through the ways */
527
528 do
529 {
530 ReadFile(relationsx->rfd,&wayid,sizeof(way_t));
531
532 /* Update the ways that are listed for the relation */
533
534 if(wayid==NO_WAY)
535 continue;
536
537 if(routes)
538 {
539 index_t way=IndexWayX(waysx,wayid);
540
541 if(way!=NO_WAY)
542 {
543 WayX *wayx=LookupWayX(waysx,way,1);
544
545 if(routes&Transports_Foot)
546 wayx->way.props|=Properties_FootRoute;
547
548 if(routes&Transports_Bicycle)
549 wayx->way.props|=Properties_BicycleRoute;
550
551 PutBackWayX(waysx,wayx);
552
553 ways++;
554 }
555 else
556 logerror("Route Relation %"Prelation_t" contains Way %"Pway_t" but it does not exist in the Routino database.\n",relationx.id,wayid);
557 }
558 }
559 while(wayid!=NO_WAY);
560
561 /* Loop through the relations */
562
563 do
564 {
565 ReadFile(relationsx->rfd,&relationid,sizeof(relation_t));
566
567 /* Add the relations that are listed for this relation to the list for next time */
568
569 if(relationid==NO_RELATION)
570 continue;
571
572 if(relationid==relationx.id)
573 logerror("Relation %"Prelation_t" contains itself.\n",relationx.id);
574 else if(routes)
575 {
576 if(nunmatched%256==0)
577 unmatched=(RouteRelX*)realloc((void*)unmatched,(nunmatched+256)*sizeof(RouteRelX));
578
579 unmatched[nunmatched].id=relationid;
580 unmatched[nunmatched].routes=routes;
581
582 nunmatched++;
583 }
584 }
585 while(relationid!=NO_RELATION);
586
587 if(!((i+1)%1000))
588 printf_middle("Processing Route Relations (%d): Relations=%"Pindex_t" Modified Ways=%"Pindex_t,iteration,relations,ways);
589 }
590
591 if(lastunmatched)
592 free(lastunmatched);
593
594 lastunmatched=unmatched;
595 lastnunmatched=nunmatched;
596
597 unmatched=NULL;
598 nunmatched=0;
599
600 /* Print the final message */
601
602 printf_last("Processed Route Relations (%d): Relations=%"Pindex_t" Modified Ways=%"Pindex_t,iteration,relations,ways);
603 }
604 while(lastnunmatched && iteration++<8);
605
606 if(lastunmatched)
607 free(lastunmatched);
608
609 /* Close the file */
610
611 relationsx->rfd=CloseFile(relationsx->rfd);
612
613 /* Unmap from memory / close the files */
614
615 #if !SLIM
616 waysx->data=UnmapFile(waysx->filename);
617 #else
618 waysx->fd=CloseFile(waysx->fd);
619 #endif
620 }
621
622
623 /*++++++++++++++++++++++++++++++++++++++
624 Process the turn relations (first part) to update them with the node/way information.
625
626 RelationsX *relationsx The set of relations to modify.
627
628 NodesX *nodesx The set of nodes to use.
629
630 WaysX *waysx The set of ways to use.
631 ++++++++++++++++++++++++++++++++++++++*/
632
633 void ProcessTurnRelations1(RelationsX *relationsx,NodesX *nodesx,WaysX *waysx)
634 {
635 int trfd;
636 index_t i,deleted=0;
637
638 /* Print the start message */
639
640 printf_first("Processing Turn Relations (1): Relations=0");
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 for(i=0;i<relationsx->trnumber;i++)
653 {
654 TurnRestrictRelX relationx;
655 node_t via;
656 way_t from,to;
657
658 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
659
660 via =IndexNodeX(nodesx,relationx.via);
661 from=IndexWayX(waysx,relationx.from);
662 to =IndexWayX(waysx,relationx.to);
663
664 if(via==NO_NODE)
665 logerror("Turn Relation %"Prelation_t" contains Node %"Pnode_t" but it does not exist in the Routino database.\n",relationx.id,relationx.via);
666
667 if(from==NO_WAY)
668 logerror("Turn Relation %"Prelation_t" contains Way %"Pway_t" but it does not exist in the Routino database.\n",relationx.id,relationx.from);
669
670 if(to==NO_WAY)
671 logerror("Turn Relation %"Prelation_t" contains Way %"Pway_t" but it does not exist in the Routino database.\n",relationx.id,relationx.to);
672
673 relationx.via =via;
674 relationx.from=from;
675 relationx.to =to;
676
677 if(relationx.via==NO_NODE || relationx.from==NO_WAY || relationx.to==NO_WAY)
678 deleted++;
679 else
680 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
681
682 if(!((i+1)%1000))
683 printf_middle("Processing Turn Relations (1): Relations=%"Pindex_t" Deleted=%"Pindex_t,i+1-deleted,deleted);
684 }
685
686 /* Close the files */
687
688 relationsx->trfd=CloseFile(relationsx->trfd);
689 CloseFile(trfd);
690
691 /* Print the final message */
692
693 printf_last("Processed Turn Relations (1): Relations=%"Pindex_t" Deleted=%"Pindex_t,relationsx->trnumber-deleted,deleted);
694
695 relationsx->trnumber-=deleted;
696 }
697
698
699 /*++++++++++++++++++++++++++++++++++++++
700 Process the turn relations (second part) to convert them to nodes.
701
702 RelationsX *relationsx The set of relations to modify.
703
704 NodesX *nodesx The set of nodes to use.
705
706 SegmentsX *segmentsx The set of segments to use.
707
708 WaysX *waysx The set of ways to use.
709 ++++++++++++++++++++++++++++++++++++++*/
710
711 void ProcessTurnRelations2(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx)
712 {
713 TurnRestrictRelX relationx;
714 int trfd;
715 index_t total=0,deleted=0;
716
717 if(nodesx->number==0 || segmentsx->number==0)
718 return;
719
720 /* Print the start message */
721
722 printf_first("Processing Turn Relations (2): Relations=0");
723
724 /* Map into memory / open the files */
725
726 #if !SLIM
727 nodesx->data=MapFileWriteable(nodesx->filename);
728 segmentsx->data=MapFile(segmentsx->filename);
729 waysx->data=MapFile(waysx->filename);
730 #else
731 nodesx->fd=ReOpenFileWriteable(nodesx->filename);
732 segmentsx->fd=ReOpenFile(segmentsx->filename);
733 waysx->fd=ReOpenFile(waysx->filename);
734 #endif
735
736 /* Re-open the file read-only and a new file writeable */
737
738 relationsx->trfd=ReOpenFile(relationsx->trfilename);
739
740 DeleteFile(relationsx->trfilename);
741
742 trfd=OpenFileNew(relationsx->trfilename);
743
744 /* Process all of the relations */
745
746 while(!ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX)))
747 {
748 NodeX *nodex;
749 SegmentX *segmentx;
750
751 if(relationx.restriction==TurnRestrict_no_right_turn ||
752 relationx.restriction==TurnRestrict_no_left_turn ||
753 relationx.restriction==TurnRestrict_no_u_turn ||
754 relationx.restriction==TurnRestrict_no_straight_on)
755 {
756 index_t node_from=NO_NODE,node_to=NO_NODE;
757 int oneway_from=0,oneway_to=0,vehicles_from=1,vehicles_to=1;
758
759 /* Find the segments that join the node 'via' */
760
761 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
762
763 while(segmentx)
764 {
765 if(segmentx->way==relationx.from)
766 {
767 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
768
769 if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
770 {
771 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'from' way.\n",relationx.id);
772 deleted++;
773 goto endloop;
774 }
775
776 node_from=OtherNode(segmentx,relationx.via);
777
778 if(IsOnewayFrom(segmentx,relationx.via))
779 oneway_from=1; /* not allowed */
780
781 if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
782 vehicles_from=0; /* not allowed */
783 }
784
785 if(segmentx->way==relationx.to)
786 {
787 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
788
789 if(node_to!=NO_NODE) /* Only one segment can be on the 'to' way */
790 {
791 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'to' way.\n",relationx.id);
792 deleted++;
793 goto endloop;
794 }
795
796 node_to=OtherNode(segmentx,relationx.via);
797
798 if(IsOnewayTo(segmentx,relationx.via))
799 oneway_to=1; /* not allowed */
800
801 if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
802 vehicles_to=0; /* not allowed */
803 }
804
805 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via);
806 }
807
808 if(node_from==NO_NODE)
809 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'from' way.\n",relationx.id);
810
811 if(node_to==NO_NODE)
812 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'to' way.\n",relationx.id);
813
814 if(oneway_from)
815 logerror("Turn Relation %"Prelation_t" is not stored because the 'from' way is oneway away from the 'via' node.\n",relationx.id);
816
817 if(oneway_to)
818 logerror("Turn Relation %"Prelation_t" is not needed because the 'to' way is oneway towards the 'via' node.\n",relationx.id);
819
820 if(!vehicles_from)
821 logerror("Turn Relation %"Prelation_t" is not stored because the 'from' way does not allow vehicles.\n",relationx.id);
822
823 if(!vehicles_to)
824 logerror("Turn Relation %"Prelation_t" is not needed because the 'to' way does not allow vehicles.\n",relationx.id);
825
826 if(oneway_from || oneway_to || !vehicles_from || !vehicles_to || node_from==NO_NODE || node_to==NO_NODE)
827 {
828 deleted++;
829 goto endloop;
830 }
831
832 /* Write the results */
833
834 relationx.from=node_from;
835 relationx.to =node_to;
836
837 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
838
839 total++;
840
841 if(!(total%1000))
842 printf_middle("Processing Turn Relations (2): Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,total,deleted,total-relationsx->trnumber+deleted);
843 }
844 else
845 {
846 index_t node_from=NO_NODE,node_to=NO_NODE,node_other[MAX_SEG_PER_NODE];
847 int nnodes_other=0,i;
848 int oneway_from=0,vehicles_from=1;
849
850 /* Find the segments that join the node 'via' */
851
852 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
853
854 while(segmentx)
855 {
856 if(segmentx->way==relationx.from)
857 {
858 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
859
860 if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
861 {
862 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'from' way.\n",relationx.id);
863 deleted++;
864 goto endloop;
865 }
866
867 node_from=OtherNode(segmentx,relationx.via);
868
869 if(IsOnewayFrom(segmentx,relationx.via))
870 oneway_from=1; /* not allowed */
871
872 if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
873 vehicles_from=0; /* not allowed */
874 }
875
876 if(segmentx->way==relationx.to)
877 {
878 if(node_to!=NO_NODE) /* Only one segment can be on the 'to' way */
879 {
880 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'to' way.\n",relationx.id);
881 deleted++;
882 goto endloop;
883 }
884
885 node_to=OtherNode(segmentx,relationx.via);
886 }
887
888 if(segmentx->way!=relationx.from && segmentx->way!=relationx.to)
889 {
890 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
891
892 if(IsOnewayTo(segmentx,relationx.via))
893 ; /* not allowed */
894 else if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
895 ; /* not allowed */
896 else
897 {
898 assert(nnodes_other<MAX_SEG_PER_NODE); /* Only a limited amount of information stored. */
899
900 node_other[nnodes_other++]=OtherNode(segmentx,relationx.via);
901 }
902 }
903
904 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via);
905 }
906
907 if(node_from==NO_NODE)
908 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'from' way.\n",relationx.id);
909
910 if(node_to==NO_NODE)
911 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'to' way.\n",relationx.id);
912
913 if(nnodes_other==0)
914 logerror("Turn Relation %"Prelation_t" is not needed because the only allowed exit from the 'via' node is the 'to' way.\n",relationx.id);
915
916 if(oneway_from)
917 logerror("Turn Relation %"Prelation_t" is not needed because the 'from' way is oneway away from the 'via' node.\n",relationx.id);
918
919 if(!vehicles_from)
920 logerror("Turn Relation %"Prelation_t" is not stored because the 'from' way does not allow vehicles.\n",relationx.id);
921
922 if(oneway_from || !vehicles_from || node_from==NO_NODE || node_to==NO_NODE || nnodes_other==0)
923 {
924 deleted++;
925 goto endloop;
926 }
927
928 /* Write the results */
929
930 for(i=0;i<nnodes_other;i++)
931 {
932 relationx.from=node_from;
933 relationx.to =node_other[i];
934
935 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
936
937 total++;
938
939 if(!(total%1000))
940 printf_middle("Processing Turn Relations (2): Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,total,deleted,total-relationsx->trnumber+deleted);
941 }
942 }
943
944 /* Force super nodes on via node and adjacent nodes */
945
946 nodex=LookupNodeX(nodesx,relationx.via,1);
947 nodex->flags|=NODE_TURNRSTRCT;
948 PutBackNodeX(nodesx,nodex);
949
950 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
951
952 while(segmentx)
953 {
954 index_t othernode=OtherNode(segmentx,relationx.via);
955
956 nodex=LookupNodeX(nodesx,othernode,1);
957 nodex->flags|=NODE_TURNRSTRCT2;
958 PutBackNodeX(nodesx,nodex);
959
960 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via);
961 }
962
963 endloop: ;
964 }
965
966 /* Close the files */
967
968 relationsx->trfd=CloseFile(relationsx->trfd);
969 CloseFile(trfd);
970
971 /* Unmap from memory / close the files */
972
973 #if !SLIM
974 nodesx->data=UnmapFile(nodesx->filename);
975 segmentsx->data=UnmapFile(segmentsx->filename);
976 waysx->data=UnmapFile(waysx->filename);
977 #else
978 nodesx->fd=CloseFile(nodesx->fd);
979 segmentsx->fd=CloseFile(segmentsx->fd);
980 waysx->fd=CloseFile(waysx->fd);
981 #endif
982
983 /* Print the final message */
984
985 printf_last("Processed Turn Relations (2): Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,total,deleted,total-relationsx->trnumber+deleted);
986
987 relationsx->trnumber=total;
988 }
989
990
991 /*++++++++++++++++++++++++++++++++++++++
992 Update the node indexes after geographical sorting.
993
994 RelationsX *relationsx The set of relations to modify.
995
996 NodesX *nodesx The set of nodes to use.
997
998 SegmentsX *segmentsx The set of segments to use.
999 ++++++++++++++++++++++++++++++++++++++*/
1000
1001 void UpdateTurnRelations(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx)
1002 {
1003 int trfd;
1004 index_t i;
1005
1006 /* Print the start message */
1007
1008 printf_first("Updating Turn Relations: Relations=0");
1009
1010 /* Map into memory / open the files */
1011
1012 #if !SLIM
1013 segmentsx->data=MapFile(segmentsx->filename);
1014 #else
1015 segmentsx->fd=ReOpenFile(segmentsx->filename);
1016 #endif
1017
1018 /* Re-open the file read-only and a new file writeable */
1019
1020 relationsx->trfd=ReOpenFile(relationsx->trfilename);
1021
1022 DeleteFile(relationsx->trfilename);
1023
1024 trfd=OpenFileNew(relationsx->trfilename);
1025
1026 /* Process all of the relations */
1027
1028 for(i=0;i<relationsx->trnumber;i++)
1029 {
1030 TurnRestrictRelX relationx;
1031 SegmentX *segmentx;
1032 index_t from_node,via_node,to_node;
1033
1034 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
1035
1036 from_node=nodesx->gdata[relationx.from];
1037 via_node =nodesx->gdata[relationx.via];
1038 to_node =nodesx->gdata[relationx.to];
1039
1040 segmentx=FirstSegmentX(segmentsx,via_node,1);
1041
1042 do
1043 {
1044 if(OtherNode(segmentx,via_node)==from_node)
1045 relationx.from=IndexSegmentX(segmentsx,segmentx);
1046
1047 if(OtherNode(segmentx,via_node)==to_node)
1048 relationx.to=IndexSegmentX(segmentsx,segmentx);
1049
1050 segmentx=NextSegmentX(segmentsx,segmentx,via_node);
1051 }
1052 while(segmentx);
1053
1054 relationx.via=via_node;
1055
1056 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
1057
1058 if(!(relationsx->trnumber%1000))
1059 printf_middle("Updating Turn Relations: Relations=%"Pindex_t,relationsx->trnumber);
1060 }
1061
1062 /* Close the files */
1063
1064 relationsx->trfd=CloseFile(relationsx->trfd);
1065 CloseFile(trfd);
1066
1067 /* Unmap from memory / close the files */
1068
1069 #if !SLIM
1070 segmentsx->data=UnmapFile(segmentsx->filename);
1071 #else
1072 segmentsx->fd=CloseFile(segmentsx->fd);
1073 #endif
1074
1075 /* Print the final message */
1076
1077 printf_last("Updated Turn Relations: Relations=%"Pindex_t,relationsx->trnumber);
1078 }
1079
1080
1081 /*++++++++++++++++++++++++++++++++++++++
1082 Save the relation list to a file.
1083
1084 RelationsX* relationsx The set of relations to save.
1085
1086 const char *filename The name of the file to save.
1087 ++++++++++++++++++++++++++++++++++++++*/
1088
1089 void SaveRelationList(RelationsX* relationsx,const char *filename)
1090 {
1091 index_t i;
1092 int fd;
1093 RelationsFile relationsfile={0};
1094
1095 /* Print the start message */
1096
1097 printf_first("Writing Relations: Turn Relations=0");
1098
1099 /* Re-open the file read-only */
1100
1101 relationsx->trfd=ReOpenFile(relationsx->trfilename);
1102
1103 /* Write out the relations data */
1104
1105 fd=OpenFileNew(filename);
1106
1107 SeekFile(fd,sizeof(RelationsFile));
1108
1109 for(i=0;i<relationsx->trnumber;i++)
1110 {
1111 TurnRestrictRelX relationx;
1112 TurnRelation relation={0};
1113
1114 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
1115
1116 relation.from=relationx.from;
1117 relation.via=relationx.via;
1118 relation.to=relationx.to;
1119 relation.except=relationx.except;
1120
1121 WriteFile(fd,&relation,sizeof(TurnRelation));
1122
1123 if(!((i+1)%1000))
1124 printf_middle("Writing Relations: Turn Relations=%"Pindex_t,i+1);
1125 }
1126
1127 /* Write out the header structure */
1128
1129 relationsfile.trnumber=relationsx->trnumber;
1130
1131 SeekFile(fd,0);
1132 WriteFile(fd,&relationsfile,sizeof(RelationsFile));
1133
1134 CloseFile(fd);
1135
1136 /* Close the file */
1137
1138 relationsx->trfd=CloseFile(relationsx->trfd);
1139
1140 /* Print the final message */
1141
1142 printf_last("Wrote Relations: Turn Relations=%"Pindex_t,relationsx->trnumber);
1143 }