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 949 - (hide annotations) (download) (as text)
Fri Jan 13 17:13:39 2012 UTC (13 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 31513 byte(s)
Add an infrastructure to allow adding new functions to prune nodes and segments.

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