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 942 - (hide annotations) (download) (as text)
Sun Dec 11 11:09:13 2011 UTC (13 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 31355 byte(s)
Remove the "position" parameter from the PutBack*X() functions (only used in
slim mode).

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