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 812 - (hide annotations) (download) (as text)
Thu Jul 21 18:44:52 2011 UTC (13 years, 7 months ago) by amb
File MIME type: text/x-csrc
File size: 31014 byte(s)
Add logging of parsing and processing errors.

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