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 1110 - (hide annotations) (download) (as text)
Mon Oct 22 07:41:55 2012 UTC (12 years, 5 months ago) by amb
File MIME type: text/x-csrc
File size: 33621 byte(s)
Change the message after sorting geographically to be consistent with others.

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