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 1106 - (hide annotations) (download) (as text)
Sun Oct 21 15:55:48 2012 UTC (12 years, 5 months ago) by amb
File MIME type: text/x-csrc
File size: 33932 byte(s)
Change the sorting functions to have a pre-sort and post-sort selection function
instead of just a post-selection one (this will allow deletion of some items
before sorting instead of after sorting in some cases).

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