Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Annotation of /trunk/src/relationsx.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 995 - (hide annotations) (download) (as text)
Wed May 9 16:49:05 2012 UTC (12 years, 11 months ago) by amb
File MIME type: text/x-csrc
File size: 31687 byte(s)
Force bicycle routes to be bicycle accessible and foot routes to be foot
accessible.

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