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 1098 - (show annotations) (download) (as text)
Sat Oct 20 12:52:01 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 33696 byte(s)
Delete the pruned nodes before searching for super-nodes etc.

1 /***************************************
2 Extended Relation data type functions.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2010-2012 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 <string.h>
26
27 #include "types.h"
28 #include "segments.h"
29 #include "relations.h"
30
31 #include "nodesx.h"
32 #include "segmentsx.h"
33 #include "waysx.h"
34 #include "relationsx.h"
35
36 #include "files.h"
37 #include "logging.h"
38 #include "sorting.h"
39
40
41 /* Local functions */
42
43 static int sort_by_id(TurnRestrictRelX *a,TurnRestrictRelX *b);
44 static int deduplicate_by_id(TurnRestrictRelX *relationx,index_t index);
45
46 static int sort_by_via(TurnRestrictRelX *a,TurnRestrictRelX *b);
47
48
49 /* Variables */
50
51 /*+ The command line '--tmpdir' option or its default value. +*/
52 extern char *option_tmpdirname;
53
54
55 /*++++++++++++++++++++++++++++++++++++++
56 Allocate a new relation list (create a new file or open an existing one).
57
58 RelationsX *NewRelationList Returns the relation list.
59
60 int append Set to 1 if the file is to be opened for appending (now or later).
61 ++++++++++++++++++++++++++++++++++++++*/
62
63 RelationsX *NewRelationList(int append)
64 {
65 RelationsX *relationsx;
66
67 relationsx=(RelationsX*)calloc(1,sizeof(RelationsX));
68
69 assert(relationsx); /* Check calloc() worked */
70
71
72 /* Route Relations */
73
74 relationsx->rfilename=(char*)malloc(strlen(option_tmpdirname)+32);
75
76 if(append)
77 sprintf(relationsx->rfilename,"%s/relationsx.route.input.tmp",option_tmpdirname);
78 else
79 sprintf(relationsx->rfilename,"%s/relationsx.route.%p.tmp",option_tmpdirname,(void*)relationsx);
80
81 if(append)
82 {
83 off_t size,position=0;
84
85 relationsx->rfd=OpenFileAppend(relationsx->rfilename);
86
87 size=SizeFile(relationsx->rfilename);
88
89 while(position<size)
90 {
91 FILESORT_VARINT relationsize;
92
93 SeekReadFile(relationsx->rfd,&relationsize,FILESORT_VARSIZE,position);
94
95 relationsx->rnumber++;
96 position+=relationsize+FILESORT_VARSIZE;
97 }
98
99 SeekFile(relationsx->rfd,size);
100 }
101 else
102 relationsx->rfd=OpenFileNew(relationsx->rfilename);
103
104
105 /* Turn Restriction Relations */
106
107 relationsx->trfilename=(char*)malloc(strlen(option_tmpdirname)+32);
108
109 if(append)
110 sprintf(relationsx->trfilename,"%s/relationsx.turn.input.tmp",option_tmpdirname);
111 else
112 sprintf(relationsx->trfilename,"%s/relationsx.turn.%p.tmp",option_tmpdirname,(void*)relationsx);
113
114 if(append)
115 {
116 off_t size;
117
118 relationsx->trfd=OpenFileAppend(relationsx->trfilename);
119
120 size=SizeFile(relationsx->trfilename);
121
122 relationsx->trnumber=size/sizeof(TurnRestrictRelX);
123 }
124 else
125 relationsx->trfd=OpenFileNew(relationsx->trfilename);
126
127 return(relationsx);
128 }
129
130
131 /*++++++++++++++++++++++++++++++++++++++
132 Free a relation list.
133
134 RelationsX *relationsx The set of relations to be freed.
135
136 int keep Set to 1 if the file is to be kept (for appending later).
137 ++++++++++++++++++++++++++++++++++++++*/
138
139 void FreeRelationList(RelationsX *relationsx,int keep)
140 {
141 /* Route relations */
142
143 if(!keep)
144 DeleteFile(relationsx->rfilename);
145
146 free(relationsx->rfilename);
147
148
149 /* Turn Restriction relations */
150
151 if(!keep)
152 DeleteFile(relationsx->trfilename);
153
154 free(relationsx->trfilename);
155
156 free(relationsx);
157 }
158
159
160 /*++++++++++++++++++++++++++++++++++++++
161 Append a single relation to an unsorted route relation list.
162
163 RelationsX* relationsx The set of relations to process.
164
165 relation_t id The ID of the relation.
166
167 transports_t routes The types of routes that this relation is for.
168
169 way_t *ways The array of ways that are members of the relation.
170
171 int nways The number of ways that are members of the relation.
172
173 relation_t *relations The array of relations that are members of the relation.
174
175 int nrelations The number of relations that are members of the relation.
176 ++++++++++++++++++++++++++++++++++++++*/
177
178 void AppendRouteRelation(RelationsX* relationsx,relation_t id,
179 transports_t routes,
180 way_t *ways,int nways,
181 relation_t *relations,int nrelations)
182 {
183 RouteRelX relationx;
184 FILESORT_VARINT size;
185 way_t noway=NO_WAY;
186 relation_t norelation=NO_RELATION;
187
188 relationx.id=id;
189 relationx.routes=routes;
190
191 size=sizeof(RouteRelX)+(nways+1)*sizeof(way_t)+(nrelations+1)*sizeof(relation_t);
192
193 WriteFile(relationsx->rfd,&size,FILESORT_VARSIZE);
194 WriteFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
195
196 WriteFile(relationsx->rfd,ways ,nways*sizeof(way_t));
197 WriteFile(relationsx->rfd,&noway, sizeof(way_t));
198
199 WriteFile(relationsx->rfd,relations ,nrelations*sizeof(relation_t));
200 WriteFile(relationsx->rfd,&norelation, sizeof(relation_t));
201
202 relationsx->rnumber++;
203
204 assert(relationsx->rnumber!=0); /* Zero marks the high-water mark for relations. */
205 }
206
207
208 /*++++++++++++++++++++++++++++++++++++++
209 Append a single relation to an unsorted turn restriction relation list.
210
211 RelationsX* relationsx The set of relations to process.
212
213 relation_t id The ID of the relation.
214
215 way_t from The way that the turn restriction starts from.
216
217 way_t to The way that the restriction finished on.
218
219 node_t via The node that the turn restriction passes through.
220
221 TurnRestriction restriction The type of restriction.
222
223 transports_t except The set of transports allowed to bypass the restriction.
224 ++++++++++++++++++++++++++++++++++++++*/
225
226 void AppendTurnRestrictRelation(RelationsX* relationsx,relation_t id,
227 way_t from,way_t to,node_t via,
228 TurnRestriction restriction,transports_t except)
229 {
230 TurnRestrictRelX relationx={0};
231
232 relationx.id=id;
233 relationx.from=from;
234 relationx.to=to;
235 relationx.via=via;
236 relationx.restriction=restriction;
237 relationx.except=except;
238
239 WriteFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
240
241 relationsx->trnumber++;
242
243 assert(relationsx->trnumber!=0); /* Zero marks the high-water mark for relations. */
244 }
245
246
247 /*++++++++++++++++++++++++++++++++++++++
248 Sort the list of relations.
249
250 RelationsX* relationsx The set of relations to process.
251 ++++++++++++++++++++++++++++++++++++++*/
252
253 void SortRelationList(RelationsX* relationsx)
254 {
255 /* Close the files (finished appending) */
256
257 relationsx->rfd=CloseFile(relationsx->rfd);
258
259 relationsx->trfd=CloseFile(relationsx->trfd);
260
261
262 /* Route Relations */
263
264
265 /* Turn Restriction Relations. */
266
267 if(relationsx->trnumber)
268 {
269 index_t trxnumber;
270 int trfd;
271
272 /* Print the start message */
273
274 printf_first("Sorting Turn Relations");
275
276 /* Re-open the file read-only and a new file writeable */
277
278 relationsx->trfd=ReOpenFile(relationsx->trfilename);
279
280 DeleteFile(relationsx->trfilename);
281
282 trfd=OpenFileNew(relationsx->trfilename);
283
284 /* Sort the relations */
285
286 trxnumber=relationsx->trnumber;
287 relationsx->trnumber=0;
288
289 relationsx->trnumber=filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRestrictRelX),(int (*)(const void*,const void*))sort_by_id,(int (*)(void*,index_t))deduplicate_by_id);
290
291 /* Close the files */
292
293 relationsx->trfd=CloseFile(relationsx->trfd);
294 CloseFile(trfd);
295
296 /* Print the final message */
297
298 printf_last("Sorted Turn Relations: Relations=%"Pindex_t" Duplicates=%"Pindex_t,trxnumber,trxnumber-relationsx->trnumber);
299 }
300 }
301
302
303 /*++++++++++++++++++++++++++++++++++++++
304 Sort the turn restriction relations into id order.
305
306 int sort_by_id Returns the comparison of the id fields.
307
308 TurnRestrictRelX *a The first extended relation.
309
310 TurnRestrictRelX *b The second extended relation.
311 ++++++++++++++++++++++++++++++++++++++*/
312
313 static int sort_by_id(TurnRestrictRelX *a,TurnRestrictRelX *b)
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 Deduplicate the extended relations using the id after sorting.
329
330 int deduplicate_by_id Return 1 if the value is to be kept, otherwise 0.
331
332 TurnRestrictRelX *relationx The extended relation.
333
334 index_t index The index of this relation in the total.
335 ++++++++++++++++++++++++++++++++++++++*/
336
337 static int deduplicate_by_id(TurnRestrictRelX *relationx,index_t index)
338 {
339 static relation_t previd;
340
341 if(index==0 || relationx->id!=previd)
342 {
343 previd=relationx->id;
344
345 return(1);
346 }
347 else
348 {
349 logerror("Relation %"Prelation_t" is duplicated.\n",relationx->id);
350
351 return(0);
352 }
353 }
354
355
356 /*++++++++++++++++++++++++++++++++++++++
357 Sort the list of turn relations.
358
359 RelationsX* relationsx The set of relations to process.
360 ++++++++++++++++++++++++++++++++++++++*/
361
362 void SortTurnRelationList(RelationsX* relationsx)
363 {
364 int trfd;
365
366 if(relationsx->trnumber==0)
367 return;
368
369 /* Print the start message */
370
371 printf_first("Sorting Turn Relations");
372
373 /* Re-open the file read-only and a new file writeable */
374
375 relationsx->trfd=ReOpenFile(relationsx->trfilename);
376
377 DeleteFile(relationsx->trfilename);
378
379 trfd=OpenFileNew(relationsx->trfilename);
380
381 /* Sort the relations */
382
383 filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRestrictRelX),(int (*)(const void*,const void*))sort_by_via,NULL);
384
385 /* Close the files */
386
387 relationsx->trfd=CloseFile(relationsx->trfd);
388 CloseFile(trfd);
389
390 /* Print the final message */
391
392 printf_last("Sorted Turn Relations: Relations=%"Pindex_t,relationsx->trnumber);
393 }
394
395
396 /*++++++++++++++++++++++++++++++++++++++
397 Sort the turn restriction relations into via index order (then by from and to segments).
398
399 int sort_by_via Returns the comparison of the via, from and to fields.
400
401 TurnRestrictRelX *a The first extended relation.
402
403 TurnRestrictRelX *b The second extended relation.
404 ++++++++++++++++++++++++++++++++++++++*/
405
406 static int sort_by_via(TurnRestrictRelX *a,TurnRestrictRelX *b)
407 {
408 index_t a_id=a->via;
409 index_t b_id=b->via;
410
411 if(a_id<b_id)
412 return(-1);
413 else if(a_id>b_id)
414 return(1);
415 else
416 {
417 index_t a_id=a->from;
418 index_t b_id=b->from;
419
420 if(a_id<b_id)
421 return(-1);
422 else if(a_id>b_id)
423 return(1);
424 else
425 {
426 index_t a_id=a->to;
427 index_t b_id=b->to;
428
429 if(a_id<b_id)
430 return(-1);
431 else if(a_id>b_id)
432 return(1);
433 else
434 return(0);
435 }
436 }
437 }
438
439
440 /*++++++++++++++++++++++++++++++++++++++
441 Process the route relations and apply the information to the ways.
442
443 RelationsX *relationsx The set of relations to use.
444
445 WaysX *waysx The set of ways to modify.
446 ++++++++++++++++++++++++++++++++++++++*/
447
448 void ProcessRouteRelations(RelationsX *relationsx,WaysX *waysx)
449 {
450 RouteRelX *unmatched=NULL,*lastunmatched=NULL;
451 int nunmatched=0,lastnunmatched=0,iteration=1;
452
453 if(waysx->number==0)
454 return;
455
456 /* Map into memory / open the files */
457
458 #if !SLIM
459 waysx->data=MapFileWriteable(waysx->filename);
460 #else
461 waysx->fd=ReOpenFileWriteable(waysx->filename);
462 #endif
463
464 /* Re-open the file read-only */
465
466 relationsx->rfd=ReOpenFile(relationsx->rfilename);
467
468 /* Read through the file. */
469
470 do
471 {
472 int ways=0,relations=0;
473 index_t i;
474
475 SeekFile(relationsx->rfd,0);
476
477 /* Print the start message */
478
479 printf_first("Processing Route Relations (%d): Relations=0 Modified Ways=0",iteration);
480
481 for(i=0;i<relationsx->rnumber;i++)
482 {
483 FILESORT_VARINT size;
484 RouteRelX relationx;
485 way_t wayid;
486 relation_t relationid;
487 transports_t routes=Transports_None;
488
489 /* Read each route relation */
490
491 ReadFile(relationsx->rfd,&size,FILESORT_VARSIZE);
492 ReadFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
493
494 /* Decide what type of route it is */
495
496 if(iteration==1)
497 {
498 relations++;
499 routes=relationx.routes;
500 }
501 else
502 {
503 int j;
504
505 for(j=0;j<lastnunmatched;j++)
506 if(lastunmatched[j].id==relationx.id)
507 {
508 relations++;
509
510 if((lastunmatched[j].routes|relationx.routes)==relationx.routes)
511 routes=0; /* Nothing new to add */
512 else
513 routes=lastunmatched[j].routes;
514
515 break;
516 }
517 }
518
519 /* Loop through the ways */
520
521 do
522 {
523 ReadFile(relationsx->rfd,&wayid,sizeof(way_t));
524
525 /* Update the ways that are listed for the relation */
526
527 if(wayid==NO_WAY)
528 continue;
529
530 if(routes)
531 {
532 index_t way=IndexWayX(waysx,wayid);
533
534 if(way!=NO_WAY)
535 {
536 WayX *wayx=LookupWayX(waysx,way,1);
537
538 if(routes&Transports_Foot)
539 {
540 if(!(wayx->way.allow&Transports_Foot))
541 {
542 logerror("Route Relation %"Prelation_t" for Foot contains Way %"Pway_t" that does not allow Foot transport; overriding.\n",relationx.id,wayid);
543 wayx->way.allow|=Transports_Foot;
544 }
545 wayx->way.props|=Properties_FootRoute;
546 }
547
548 if(routes&Transports_Bicycle)
549 {
550 if(!(wayx->way.allow&Transports_Bicycle))
551 {
552 logerror("Route Relation %"Prelation_t" for Bicycle contains Way %"Pway_t" that does not allow Bicycle transport; overriding.\n",relationx.id,wayid);
553 wayx->way.allow|=Transports_Bicycle;
554 }
555 wayx->way.props|=Properties_BicycleRoute;
556 }
557
558 PutBackWayX(waysx,wayx);
559
560 ways++;
561 }
562 else
563 logerror("Route Relation %"Prelation_t" contains Way %"Pway_t" but it does not exist in the Routino database.\n",relationx.id,wayid);
564 }
565 }
566 while(wayid!=NO_WAY);
567
568 /* Loop through the relations */
569
570 do
571 {
572 ReadFile(relationsx->rfd,&relationid,sizeof(relation_t));
573
574 /* Add the relations that are listed for this relation to the list for next time */
575
576 if(relationid==NO_RELATION)
577 continue;
578
579 if(relationid==relationx.id)
580 logerror("Relation %"Prelation_t" contains itself.\n",relationx.id);
581 else if(routes)
582 {
583 if(nunmatched%256==0)
584 unmatched=(RouteRelX*)realloc((void*)unmatched,(nunmatched+256)*sizeof(RouteRelX));
585
586 unmatched[nunmatched].id=relationid;
587 unmatched[nunmatched].routes=routes;
588
589 nunmatched++;
590 }
591 }
592 while(relationid!=NO_RELATION);
593
594 if(!((i+1)%1000))
595 printf_middle("Processing Route Relations (%d): Relations=%"Pindex_t" Modified Ways=%"Pindex_t,iteration,relations,ways);
596 }
597
598 if(lastunmatched)
599 free(lastunmatched);
600
601 lastunmatched=unmatched;
602 lastnunmatched=nunmatched;
603
604 unmatched=NULL;
605 nunmatched=0;
606
607 /* Print the final message */
608
609 printf_last("Processed Route Relations (%d): Relations=%"Pindex_t" Modified Ways=%"Pindex_t,iteration,relations,ways);
610 }
611 while(lastnunmatched && iteration++<8);
612
613 if(lastunmatched)
614 free(lastunmatched);
615
616 /* Close the file */
617
618 relationsx->rfd=CloseFile(relationsx->rfd);
619
620 /* Unmap from memory / close the files */
621
622 #if !SLIM
623 waysx->data=UnmapFile(waysx->filename);
624 #else
625 waysx->fd=CloseFile(waysx->fd);
626 #endif
627 }
628
629
630 /*++++++++++++++++++++++++++++++++++++++
631 Process the turn relations (first part) to update them with the node/way information.
632
633 RelationsX *relationsx The set of relations to modify.
634
635 NodesX *nodesx The set of nodes to use.
636
637 WaysX *waysx The set of ways to use.
638 ++++++++++++++++++++++++++++++++++++++*/
639
640 void ProcessTurnRelations1(RelationsX *relationsx,NodesX *nodesx,WaysX *waysx)
641 {
642 int trfd;
643 index_t i,deleted=0;
644
645 /* Print the start message */
646
647 printf_first("Processing Turn Relations (1): Relations=0");
648
649 /* Re-open the file read-only and a new file writeable */
650
651 relationsx->trfd=ReOpenFile(relationsx->trfilename);
652
653 DeleteFile(relationsx->trfilename);
654
655 trfd=OpenFileNew(relationsx->trfilename);
656
657 /* Process all of the relations */
658
659 for(i=0;i<relationsx->trnumber;i++)
660 {
661 TurnRestrictRelX relationx;
662 node_t via;
663 way_t from,to;
664
665 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
666
667 via =IndexNodeX(nodesx,relationx.via);
668 from=IndexWayX(waysx,relationx.from);
669 to =IndexWayX(waysx,relationx.to);
670
671 if(via==NO_NODE)
672 logerror("Turn Relation %"Prelation_t" contains Node %"Pnode_t" but it does not exist in the Routino database.\n",relationx.id,relationx.via);
673
674 if(from==NO_WAY)
675 logerror("Turn Relation %"Prelation_t" contains Way %"Pway_t" but it does not exist in the Routino database.\n",relationx.id,relationx.from);
676
677 if(to==NO_WAY)
678 logerror("Turn Relation %"Prelation_t" contains Way %"Pway_t" but it does not exist in the Routino database.\n",relationx.id,relationx.to);
679
680 relationx.via =via;
681 relationx.from=from;
682 relationx.to =to;
683
684 if(relationx.via==NO_NODE || relationx.from==NO_WAY || relationx.to==NO_WAY)
685 deleted++;
686 else
687 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
688
689 if(!((i+1)%1000))
690 printf_middle("Processing Turn Relations (1): Relations=%"Pindex_t" Deleted=%"Pindex_t,i+1-deleted,deleted);
691 }
692
693 /* Close the files */
694
695 relationsx->trfd=CloseFile(relationsx->trfd);
696 CloseFile(trfd);
697
698 /* Print the final message */
699
700 printf_last("Processed Turn Relations (1): Relations=%"Pindex_t" Deleted=%"Pindex_t,relationsx->trnumber-deleted,deleted);
701
702 relationsx->trnumber-=deleted;
703 }
704
705
706 /*++++++++++++++++++++++++++++++++++++++
707 Process the turn relations (second part) to convert them to nodes.
708
709 RelationsX *relationsx The set of relations to modify.
710
711 NodesX *nodesx The set of nodes to use.
712
713 SegmentsX *segmentsx The set of segments to use.
714
715 WaysX *waysx The set of ways to use.
716 ++++++++++++++++++++++++++++++++++++++*/
717
718 void ProcessTurnRelations2(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx)
719 {
720 TurnRestrictRelX relationx;
721 int trfd;
722 index_t total=0,deleted=0;
723
724 if(nodesx->number==0 || segmentsx->number==0)
725 return;
726
727 /* Print the start message */
728
729 printf_first("Processing Turn Relations (2): Relations=0");
730
731 /* Map into memory / open the files */
732
733 #if !SLIM
734 nodesx->data=MapFileWriteable(nodesx->filename);
735 segmentsx->data=MapFile(segmentsx->filename);
736 waysx->data=MapFile(waysx->filename);
737 #else
738 nodesx->fd=ReOpenFileWriteable(nodesx->filename);
739 segmentsx->fd=ReOpenFile(segmentsx->filename);
740 waysx->fd=ReOpenFile(waysx->filename);
741 #endif
742
743 /* Re-open the file read-only and a new file writeable */
744
745 relationsx->trfd=ReOpenFile(relationsx->trfilename);
746
747 DeleteFile(relationsx->trfilename);
748
749 trfd=OpenFileNew(relationsx->trfilename);
750
751 /* Process all of the relations */
752
753 while(!ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX)))
754 {
755 NodeX *nodex;
756 SegmentX *segmentx;
757
758 if(relationx.restriction==TurnRestrict_no_right_turn ||
759 relationx.restriction==TurnRestrict_no_left_turn ||
760 relationx.restriction==TurnRestrict_no_u_turn ||
761 relationx.restriction==TurnRestrict_no_straight_on)
762 {
763 index_t node_from=NO_NODE,node_to=NO_NODE;
764 int oneway_from=0,oneway_to=0,vehicles_from=1,vehicles_to=1;
765
766 /* Find the segments that join the node 'via' */
767
768 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
769
770 while(segmentx)
771 {
772 if(segmentx->way==relationx.from)
773 {
774 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
775
776 if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
777 {
778 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'from' way.\n",relationx.id);
779 deleted++;
780 goto endloop;
781 }
782
783 node_from=OtherNode(segmentx,relationx.via);
784
785 if(IsOnewayFrom(segmentx,relationx.via))
786 oneway_from=1; /* not allowed */
787
788 if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
789 vehicles_from=0; /* not allowed */
790 }
791
792 if(segmentx->way==relationx.to)
793 {
794 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
795
796 if(node_to!=NO_NODE) /* Only one segment can be on the 'to' way */
797 {
798 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'to' way.\n",relationx.id);
799 deleted++;
800 goto endloop;
801 }
802
803 node_to=OtherNode(segmentx,relationx.via);
804
805 if(IsOnewayTo(segmentx,relationx.via))
806 oneway_to=1; /* not allowed */
807
808 if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
809 vehicles_to=0; /* not allowed */
810 }
811
812 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via);
813 }
814
815 if(node_from==NO_NODE)
816 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'from' way.\n",relationx.id);
817
818 if(node_to==NO_NODE)
819 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'to' way.\n",relationx.id);
820
821 if(oneway_from)
822 logerror("Turn Relation %"Prelation_t" is not stored because the 'from' way is oneway away from the 'via' node.\n",relationx.id);
823
824 if(oneway_to)
825 logerror("Turn Relation %"Prelation_t" is not needed because the 'to' way is oneway towards the 'via' node.\n",relationx.id);
826
827 if(!vehicles_from)
828 logerror("Turn Relation %"Prelation_t" is not stored because the 'from' way does not allow vehicles.\n",relationx.id);
829
830 if(!vehicles_to)
831 logerror("Turn Relation %"Prelation_t" is not needed because the 'to' way does not allow vehicles.\n",relationx.id);
832
833 if(oneway_from || oneway_to || !vehicles_from || !vehicles_to || node_from==NO_NODE || node_to==NO_NODE)
834 {
835 deleted++;
836 goto endloop;
837 }
838
839 /* Write the results */
840
841 relationx.from=node_from;
842 relationx.to =node_to;
843
844 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
845
846 total++;
847
848 if(!(total%1000))
849 printf_middle("Processing Turn Relations (2): Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,total,deleted,total-relationsx->trnumber+deleted);
850 }
851 else
852 {
853 index_t node_from=NO_NODE,node_to=NO_NODE,node_other[MAX_SEG_PER_NODE];
854 int nnodes_other=0,i;
855 int oneway_from=0,vehicles_from=1;
856
857 /* Find the segments that join the node 'via' */
858
859 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
860
861 while(segmentx)
862 {
863 if(segmentx->way==relationx.from)
864 {
865 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
866
867 if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
868 {
869 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'from' way.\n",relationx.id);
870 deleted++;
871 goto endloop;
872 }
873
874 node_from=OtherNode(segmentx,relationx.via);
875
876 if(IsOnewayFrom(segmentx,relationx.via))
877 oneway_from=1; /* not allowed */
878
879 if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
880 vehicles_from=0; /* not allowed */
881 }
882
883 if(segmentx->way==relationx.to)
884 {
885 if(node_to!=NO_NODE) /* Only one segment can be on the 'to' way */
886 {
887 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'to' way.\n",relationx.id);
888 deleted++;
889 goto endloop;
890 }
891
892 node_to=OtherNode(segmentx,relationx.via);
893 }
894
895 if(segmentx->way!=relationx.from && segmentx->way!=relationx.to)
896 {
897 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
898
899 if(IsOnewayTo(segmentx,relationx.via))
900 ; /* not allowed */
901 else if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
902 ; /* not allowed */
903 else
904 {
905 assert(nnodes_other<MAX_SEG_PER_NODE); /* Only a limited amount of information stored. */
906
907 node_other[nnodes_other++]=OtherNode(segmentx,relationx.via);
908 }
909 }
910
911 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via);
912 }
913
914 if(node_from==NO_NODE)
915 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'from' way.\n",relationx.id);
916
917 if(node_to==NO_NODE)
918 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'to' way.\n",relationx.id);
919
920 if(nnodes_other==0)
921 logerror("Turn Relation %"Prelation_t" is not needed because the only allowed exit from the 'via' node is the 'to' way.\n",relationx.id);
922
923 if(oneway_from)
924 logerror("Turn Relation %"Prelation_t" is not needed because the 'from' way is oneway away from the 'via' node.\n",relationx.id);
925
926 if(!vehicles_from)
927 logerror("Turn Relation %"Prelation_t" is not stored because the 'from' way does not allow vehicles.\n",relationx.id);
928
929 if(oneway_from || !vehicles_from || node_from==NO_NODE || node_to==NO_NODE || nnodes_other==0)
930 {
931 deleted++;
932 goto endloop;
933 }
934
935 /* Write the results */
936
937 for(i=0;i<nnodes_other;i++)
938 {
939 relationx.from=node_from;
940 relationx.to =node_other[i];
941
942 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
943
944 total++;
945
946 if(!(total%1000))
947 printf_middle("Processing Turn Relations (2): Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,total,deleted,total-relationsx->trnumber+deleted);
948 }
949 }
950
951 /* Force super nodes on via node and adjacent nodes */
952
953 nodex=LookupNodeX(nodesx,relationx.via,1);
954 nodex->flags|=NODE_TURNRSTRCT;
955 PutBackNodeX(nodesx,nodex);
956
957 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
958
959 while(segmentx)
960 {
961 index_t othernode=OtherNode(segmentx,relationx.via);
962
963 nodex=LookupNodeX(nodesx,othernode,1);
964 nodex->flags|=NODE_TURNRSTRCT2;
965 PutBackNodeX(nodesx,nodex);
966
967 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via);
968 }
969
970 endloop: ;
971 }
972
973 /* Close the files */
974
975 relationsx->trfd=CloseFile(relationsx->trfd);
976 CloseFile(trfd);
977
978 /* Unmap from memory / close the files */
979
980 #if !SLIM
981 nodesx->data=UnmapFile(nodesx->filename);
982 segmentsx->data=UnmapFile(segmentsx->filename);
983 waysx->data=UnmapFile(waysx->filename);
984 #else
985 nodesx->fd=CloseFile(nodesx->fd);
986 segmentsx->fd=CloseFile(segmentsx->fd);
987 waysx->fd=CloseFile(waysx->fd);
988 #endif
989
990 /* Print the final message */
991
992 printf_last("Processed Turn Relations (2): Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,total,deleted,total-relationsx->trnumber+deleted);
993
994 relationsx->trnumber=total;
995 }
996
997
998 /*++++++++++++++++++++++++++++++++++++++
999 Remove pruned turn relations and update the node indexes after pruning nodes.
1000
1001 RelationsX *relationsx The set of relations to modify.
1002
1003 NodesX *nodesx The set of nodes to use.
1004 ++++++++++++++++++++++++++++++++++++++*/
1005
1006 void RemovePrunedTurnRelations(RelationsX *relationsx,NodesX *nodesx)
1007 {
1008 TurnRestrictRelX relationx;
1009 index_t total=0,pruned=0,notpruned=0;
1010 int trfd;
1011
1012 /* Print the start message */
1013
1014 printf_first("Deleting Pruned Turn Relations: Relations=0 Pruned=0");
1015
1016 /* Re-open the file read-only and a new file writeable */
1017
1018 relationsx->trfd=ReOpenFile(relationsx->trfilename);
1019
1020 DeleteFile(relationsx->trfilename);
1021
1022 trfd=OpenFileNew(relationsx->trfilename);
1023
1024 /* Process all of the relations */
1025
1026 while(!ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX)))
1027 {
1028 relationx.from=nodesx->pdata[relationx.from];
1029 relationx.via =nodesx->pdata[relationx.via];
1030 relationx.to =nodesx->pdata[relationx.to];
1031
1032 if(relationx.from==NO_NODE || relationx.via==NO_NODE || relationx.to==NO_NODE)
1033 pruned++;
1034 else
1035 {
1036 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
1037
1038 notpruned++;
1039 }
1040
1041 total++;
1042
1043 if(!(total%1000))
1044 printf_middle("Deleting Pruned Turn Relations: Relations=%"Pindex_t" Pruned=%"Pindex_t,total,pruned);
1045 }
1046
1047 relationsx->trnumber=notpruned;
1048
1049 /* Close the files */
1050
1051 relationsx->trfd=CloseFile(relationsx->trfd);
1052 CloseFile(trfd);
1053
1054 /* Free the memory */
1055
1056 if(nodesx->pdata)
1057 {
1058 free(nodesx->pdata);
1059 nodesx->pdata=NULL;
1060 }
1061
1062 /* Print the final message */
1063
1064 printf_last("Deleted Pruned Turn Relations: Relations=%"Pindex_t" Pruned=%"Pindex_t,total,pruned);
1065 }
1066
1067
1068 /*++++++++++++++++++++++++++++++++++++++
1069 Update the node indexes and replace nodes with segments after geographical sorting.
1070
1071 RelationsX *relationsx The set of relations to modify.
1072
1073 NodesX *nodesx The set of nodes to use.
1074
1075 SegmentsX *segmentsx The set of segments to use.
1076 ++++++++++++++++++++++++++++++++++++++*/
1077
1078 void UpdateTurnRelations(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx)
1079 {
1080 int trfd;
1081 index_t i;
1082
1083 /* Print the start message */
1084
1085 printf_first("Updating Turn Relations: Relations=0");
1086
1087 /* Map into memory / open the files */
1088
1089 #if !SLIM
1090 segmentsx->data=MapFile(segmentsx->filename);
1091 #else
1092 segmentsx->fd=ReOpenFile(segmentsx->filename);
1093 #endif
1094
1095 /* Re-open the file read-only and a new file writeable */
1096
1097 relationsx->trfd=ReOpenFile(relationsx->trfilename);
1098
1099 DeleteFile(relationsx->trfilename);
1100
1101 trfd=OpenFileNew(relationsx->trfilename);
1102
1103 /* Process all of the relations */
1104
1105 for(i=0;i<relationsx->trnumber;i++)
1106 {
1107 TurnRestrictRelX relationx;
1108 SegmentX *segmentx;
1109 index_t from_node,via_node,to_node;
1110
1111 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
1112
1113 from_node=nodesx->gdata[relationx.from];
1114 via_node =nodesx->gdata[relationx.via];
1115 to_node =nodesx->gdata[relationx.to];
1116
1117 segmentx=FirstSegmentX(segmentsx,via_node,1);
1118
1119 do
1120 {
1121 if(OtherNode(segmentx,via_node)==from_node)
1122 relationx.from=IndexSegmentX(segmentsx,segmentx);
1123
1124 if(OtherNode(segmentx,via_node)==to_node)
1125 relationx.to=IndexSegmentX(segmentsx,segmentx);
1126
1127 segmentx=NextSegmentX(segmentsx,segmentx,via_node);
1128 }
1129 while(segmentx);
1130
1131 relationx.via=via_node;
1132
1133 WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX));
1134
1135 if(!((i+1)%1000))
1136 printf_middle("Updating Turn Relations: Relations=%"Pindex_t,i+1);
1137 }
1138
1139 /* Close the files */
1140
1141 relationsx->trfd=CloseFile(relationsx->trfd);
1142 CloseFile(trfd);
1143
1144 /* Unmap from memory / close the files */
1145
1146 #if !SLIM
1147 segmentsx->data=UnmapFile(segmentsx->filename);
1148 #else
1149 segmentsx->fd=CloseFile(segmentsx->fd);
1150 #endif
1151
1152 /* Print the final message */
1153
1154 printf_last("Updated Turn Relations: Relations=%"Pindex_t,relationsx->trnumber);
1155 }
1156
1157
1158 /*++++++++++++++++++++++++++++++++++++++
1159 Save the relation list to a file.
1160
1161 RelationsX* relationsx The set of relations to save.
1162
1163 const char *filename The name of the file to save.
1164 ++++++++++++++++++++++++++++++++++++++*/
1165
1166 void SaveRelationList(RelationsX* relationsx,const char *filename)
1167 {
1168 index_t i;
1169 int fd;
1170 RelationsFile relationsfile={0};
1171
1172 /* Print the start message */
1173
1174 printf_first("Writing Relations: Turn Relations=0");
1175
1176 /* Re-open the file read-only */
1177
1178 relationsx->trfd=ReOpenFile(relationsx->trfilename);
1179
1180 /* Write out the relations data */
1181
1182 fd=OpenFileNew(filename);
1183
1184 SeekFile(fd,sizeof(RelationsFile));
1185
1186 for(i=0;i<relationsx->trnumber;i++)
1187 {
1188 TurnRestrictRelX relationx;
1189 TurnRelation relation={0};
1190
1191 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX));
1192
1193 relation.from=relationx.from;
1194 relation.via=relationx.via;
1195 relation.to=relationx.to;
1196 relation.except=relationx.except;
1197
1198 WriteFile(fd,&relation,sizeof(TurnRelation));
1199
1200 if(!((i+1)%1000))
1201 printf_middle("Writing Relations: Turn Relations=%"Pindex_t,i+1);
1202 }
1203
1204 /* Write out the header structure */
1205
1206 relationsfile.trnumber=relationsx->trnumber;
1207
1208 SeekFile(fd,0);
1209 WriteFile(fd,&relationsfile,sizeof(RelationsFile));
1210
1211 CloseFile(fd);
1212
1213 /* Close the file */
1214
1215 relationsx->trfd=CloseFile(relationsx->trfd);
1216
1217 /* Print the final message */
1218
1219 printf_last("Wrote Relations: Turn Relations=%"Pindex_t,relationsx->trnumber);
1220 }