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 1118 - (hide annotations) (download) (as text)
Wed Oct 31 19:01:40 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 33677 byte(s)
Add the option for the sorting function to preserve the input order of
equivalent items on the output.  Use this feature in sorting so that slim mode
and normal mode give the same results.

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 1118 return(FILESORT_PRESERVE_ORDER(a,b));
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 amb 1112 index_t index The number of unsorted turn relations that have been read from the input file.
1053 amb 1108 ++++++++++++++++++++++++++++++++++++++*/
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 amb 1118 return(FILESORT_PRESERVE_ORDER(a,b));
1123 amb 1108 }
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 }