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 1353 - (hide annotations) (download) (as text)
Thu May 30 18:03:49 2013 UTC (11 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 40882 byte(s)
Merge the ProcessTurnRelations1() and ProcessTurnRelations2() functions into a
single one now that segment processing is already complete.

1 amb 496 /***************************************
2     Extended Relation data type functions.
3    
4     Part of the Routino routing software.
5     ******************/ /******************
6 amb 1261 This file Copyright 2010-2013 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 <stdlib.h>
24     #include <string.h>
25    
26 amb 542 #include "types.h"
27 amb 955 #include "segments.h"
28 amb 542 #include "relations.h"
29    
30     #include "nodesx.h"
31     #include "segmentsx.h"
32 amb 496 #include "waysx.h"
33     #include "relationsx.h"
34    
35     #include "files.h"
36 amb 519 #include "logging.h"
37 amb 532 #include "sorting.h"
38 amb 496
39    
40 amb 1108 /* Global variables */
41    
42     /*+ The command line '--tmpdir' option or its default value. +*/
43     extern char *option_tmpdirname;
44    
45 amb 1146 /* Local variables */
46    
47     /*+ Temporary file-local variables for use by the sort functions. +*/
48     static SegmentsX *sortsegmentsx;
49     static NodesX *sortnodesx;
50    
51 amb 680 /* Local functions */
52 amb 540
53 amb 1134 static int sort_route_by_id(RouteRelX *a,RouteRelX *b);
54     static int deduplicate_route_by_id(RouteRelX *relationx,index_t index);
55 amb 540
56 amb 1163 static int sort_turn_by_id(TurnRelX *a,TurnRelX *b);
57     static int deduplicate_turn_by_id(TurnRelX *relationx,index_t index);
58 amb 1134
59 amb 1163 static int geographically_index(TurnRelX *relationx,index_t index);
60     static int sort_by_via(TurnRelX *a,TurnRelX *b);
61 amb 540
62 amb 559
63 amb 496 /*++++++++++++++++++++++++++++++++++++++
64     Allocate a new relation list (create a new file or open an existing one).
65    
66     RelationsX *NewRelationList Returns the relation list.
67    
68 amb 1123 int append Set to 1 if the file is to be opened for appending.
69    
70 amb 1139 int readonly Set to 1 if the file is to be opened for reading.
71 amb 496 ++++++++++++++++++++++++++++++++++++++*/
72    
73 amb 1123 RelationsX *NewRelationList(int append,int readonly)
74 amb 496 {
75     RelationsX *relationsx;
76    
77     relationsx=(RelationsX*)calloc(1,sizeof(RelationsX));
78    
79 amb 1166 logassert(relationsx,"Failed to allocate memory (try using slim mode?)"); /* Check calloc() worked */
80 amb 496
81 amb 540
82 amb 559 /* Route Relations */
83    
84 amb 1342 relationsx->rrfilename =(char*)malloc(strlen(option_tmpdirname)+32);
85     relationsx->rrfilename_tmp=(char*)malloc(strlen(option_tmpdirname)+32);
86 amb 496
87 amb 1342 sprintf(relationsx->rrfilename ,"%s/relationsx.route.parsed.mem",option_tmpdirname);
88     sprintf(relationsx->rrfilename_tmp,"%s/relationsx.route.%p.tmp" ,option_tmpdirname,(void*)relationsx);
89 amb 496
90 amb 1123 if(append || readonly)
91 amb 1342 if(ExistsFile(relationsx->rrfilename))
92 amb 1123 {
93     off_t size,position=0;
94 amb 1342 int rrfd;
95 amb 496
96 amb 1342 size=SizeFile(relationsx->rrfilename);
97 amb 496
98 amb 1342 rrfd=ReOpenFile(relationsx->rrfilename);
99 amb 496
100 amb 1123 while(position<size)
101     {
102     FILESORT_VARINT relationsize;
103 amb 496
104 amb 1342 SeekReadFile(rrfd,&relationsize,FILESORT_VARSIZE,position);
105 amb 496
106 amb 1342 relationsx->rrnumber++;
107 amb 1341
108 amb 1123 position+=relationsize+FILESORT_VARSIZE;
109     }
110    
111 amb 1342 CloseFile(rrfd);
112 amb 1139
113 amb 1342 RenameFile(relationsx->rrfilename,relationsx->rrfilename_tmp);
114 amb 496 }
115    
116 amb 1123 if(append)
117 amb 1342 relationsx->rrfd=OpenFileAppend(relationsx->rrfilename_tmp);
118 amb 1123 else if(!readonly)
119 amb 1342 relationsx->rrfd=OpenFileNew(relationsx->rrfilename_tmp);
120 amb 496 else
121 amb 1342 relationsx->rrfd=-1;
122 amb 496
123 amb 540
124 amb 559 /* Turn Restriction Relations */
125    
126 amb 1120 relationsx->trfilename =(char*)malloc(strlen(option_tmpdirname)+32);
127     relationsx->trfilename_tmp=(char*)malloc(strlen(option_tmpdirname)+32);
128 amb 540
129 amb 1120 sprintf(relationsx->trfilename ,"%s/relationsx.turn.parsed.mem",option_tmpdirname);
130     sprintf(relationsx->trfilename_tmp,"%s/relationsx.turn.%p.tmp" ,option_tmpdirname,(void*)relationsx);
131 amb 540
132 amb 1123 if(append || readonly)
133     if(ExistsFile(relationsx->trfilename))
134     {
135     off_t size;
136 amb 540
137 amb 1123 size=SizeFile(relationsx->trfilename);
138 amb 540
139 amb 1163 relationsx->trnumber=size/sizeof(TurnRelX);
140 amb 1139
141     RenameFile(relationsx->trfilename,relationsx->trfilename_tmp);
142 amb 1123 }
143 amb 540
144 amb 1123 if(append)
145 amb 1139 relationsx->trfd=OpenFileAppend(relationsx->trfilename_tmp);
146 amb 1123 else if(!readonly)
147 amb 1139 relationsx->trfd=OpenFileNew(relationsx->trfilename_tmp);
148 amb 540 else
149 amb 1123 relationsx->trfd=-1;
150 amb 540
151 amb 496 return(relationsx);
152     }
153    
154    
155     /*++++++++++++++++++++++++++++++++++++++
156     Free a relation list.
157    
158 amb 681 RelationsX *relationsx The set of relations to be freed.
159 amb 1151
160 amb 1167 int keep If set then the results file is to be kept.
161 amb 496 ++++++++++++++++++++++++++++++++++++++*/
162    
163 amb 1167 void FreeRelationList(RelationsX *relationsx,int keep)
164 amb 496 {
165 amb 540 /* Route relations */
166    
167 amb 1167 if(keep)
168 amb 1342 RenameFile(relationsx->rrfilename_tmp,relationsx->rrfilename);
169 amb 1151 else
170 amb 1342 DeleteFile(relationsx->rrfilename_tmp);
171 amb 1120
172 amb 1342 free(relationsx->rrfilename);
173     free(relationsx->rrfilename_tmp);
174 amb 496
175 amb 1342 if(relationsx->rridata)
176     free(relationsx->rridata);
177 amb 559
178 amb 1342 if(relationsx->rrodata)
179     free(relationsx->rrodata);
180 amb 1341
181    
182 amb 540 /* Turn Restriction relations */
183    
184 amb 1167 if(keep)
185 amb 1151 RenameFile(relationsx->trfilename_tmp,relationsx->trfilename);
186     else
187     DeleteFile(relationsx->trfilename_tmp);
188 amb 1120
189 amb 540 free(relationsx->trfilename);
190 amb 1120 free(relationsx->trfilename_tmp);
191 amb 540
192 amb 1341 if(relationsx->tridata)
193     free(relationsx->tridata);
194    
195    
196 amb 496 free(relationsx);
197     }
198    
199    
200     /*++++++++++++++++++++++++++++++++++++++
201     Append a single relation to an unsorted route relation list.
202    
203     RelationsX* relationsx The set of relations to process.
204    
205     relation_t id The ID of the relation.
206    
207 amb 529 transports_t routes The types of routes that this relation is for.
208 amb 496
209     way_t *ways The array of ways that are members of the relation.
210    
211     int nways The number of ways that are members of the relation.
212    
213     relation_t *relations The array of relations that are members of the relation.
214    
215     int nrelations The number of relations that are members of the relation.
216     ++++++++++++++++++++++++++++++++++++++*/
217    
218 amb 1161 void AppendRouteRelationList(RelationsX* relationsx,relation_t id,
219     transports_t routes,
220     way_t *ways,int nways,
221     relation_t *relations,int nrelations)
222 amb 496 {
223 amb 1147 RouteRelX relationx={0};
224 amb 505 FILESORT_VARINT size;
225 amb 1138 way_t noway=NO_WAY_ID;
226     relation_t norelation=NO_RELATION_ID;
227 amb 496
228     relationx.id=id;
229     relationx.routes=routes;
230    
231     size=sizeof(RouteRelX)+(nways+1)*sizeof(way_t)+(nrelations+1)*sizeof(relation_t);
232    
233 amb 1342 WriteFile(relationsx->rrfd,&size,FILESORT_VARSIZE);
234     WriteFile(relationsx->rrfd,&relationx,sizeof(RouteRelX));
235 amb 496
236 amb 1342 WriteFile(relationsx->rrfd,ways ,nways*sizeof(way_t));
237     WriteFile(relationsx->rrfd,&noway, sizeof(way_t));
238 amb 496
239 amb 1342 WriteFile(relationsx->rrfd,relations ,nrelations*sizeof(relation_t));
240     WriteFile(relationsx->rrfd,&norelation, sizeof(relation_t));
241 amb 496
242 amb 1342 relationsx->rrnumber++;
243 amb 496
244 amb 1342 logassert(relationsx->rrnumber!=0,"Too many route relations (change index_t to 64-bits?)"); /* Zero marks the high-water mark for relations. */
245 amb 496 }
246    
247    
248     /*++++++++++++++++++++++++++++++++++++++
249 amb 540 Append a single relation to an unsorted turn restriction relation list.
250    
251     RelationsX* relationsx The set of relations to process.
252    
253     relation_t id The ID of the relation.
254    
255     way_t from The way that the turn restriction starts from.
256    
257     way_t to The way that the restriction finished on.
258    
259     node_t via The node that the turn restriction passes through.
260    
261     TurnRestriction restriction The type of restriction.
262    
263     transports_t except The set of transports allowed to bypass the restriction.
264     ++++++++++++++++++++++++++++++++++++++*/
265    
266 amb 1161 void AppendTurnRelationList(RelationsX* relationsx,relation_t id,
267     way_t from,way_t to,node_t via,
268     TurnRestriction restriction,transports_t except)
269 amb 540 {
270 amb 1163 TurnRelX relationx={0};
271 amb 540
272     relationx.id=id;
273     relationx.from=from;
274     relationx.to=to;
275     relationx.via=via;
276 amb 786 relationx.restriction=restriction;
277 amb 540 relationx.except=except;
278    
279 amb 1163 WriteFile(relationsx->trfd,&relationx,sizeof(TurnRelX));
280 amb 540
281 amb 650 relationsx->trnumber++;
282 amb 540
283 amb 1166 logassert(relationsx->trnumber!=0,"Too many turn relations (change index_t to 64-bits?)"); /* Zero marks the high-water mark for relations. */
284 amb 540 }
285    
286    
287     /*++++++++++++++++++++++++++++++++++++++
288 amb 1120 Finish appending relations and change the filename over.
289 amb 496
290 amb 1120 RelationsX *relationsx The relations that have been appended.
291 amb 496 ++++++++++++++++++++++++++++++++++++++*/
292    
293 amb 1151 void FinishRelationList(RelationsX *relationsx)
294 amb 496 {
295 amb 1342 if(relationsx->rrfd!=-1)
296     relationsx->rrfd =CloseFile(relationsx->rrfd);
297 amb 540
298 amb 1136 if(relationsx->trfd!=-1)
299     relationsx->trfd=CloseFile(relationsx->trfd);
300 amb 1120 }
301    
302    
303     /*++++++++++++++++++++++++++++++++++++++
304 amb 1341 Find a particular route relation index.
305    
306     index_t IndexRouteRelX Returns the index of the route relation with the specified id.
307    
308     Relationsx *relationsx The set of relations to process.
309    
310     relation_t id The relation id to look for.
311     ++++++++++++++++++++++++++++++++++++++*/
312    
313     index_t IndexRouteRelX(RelationsX *relationsx,relation_t id)
314     {
315     index_t start=0;
316 amb 1342 index_t end=relationsx->rrnumber-1;
317 amb 1341 index_t mid;
318    
319 amb 1342 if(relationsx->rrnumber==0) /* There are no route relations */
320 amb 1341 return(NO_RELATION);
321    
322 amb 1342 if(id<relationsx->rridata[start]) /* Key is before start */
323 amb 1341 return(NO_RELATION);
324    
325 amb 1342 if(id>relationsx->rridata[end]) /* Key is after end */
326 amb 1341 return(NO_RELATION);
327    
328     /* Binary search - search key exact match only is required.
329     *
330     * # <- start | Check mid and move start or end if it doesn't match
331     * # |
332     * # | Since an exact match is wanted we can set end=mid-1
333     * # <- mid | or start=mid+1 because we know that mid doesn't match.
334     * # |
335     * # | Eventually either end=start or end=start+1 and one of
336     * # <- end | start or end is the wanted one.
337     */
338    
339     do
340     {
341     mid=(start+end)/2; /* Choose mid point */
342    
343 amb 1342 if(relationsx->rridata[mid]<id) /* Mid point is too low */
344 amb 1341 start=mid+1;
345 amb 1342 else if(relationsx->rridata[mid]>id) /* Mid point is too high */
346 amb 1341 end=mid?(mid-1):mid;
347     else /* Mid point is correct */
348     return(mid);
349     }
350     while((end-start)>1);
351    
352 amb 1342 if(relationsx->rridata[start]==id) /* Start is correct */
353 amb 1341 return(start);
354    
355 amb 1342 if(relationsx->rridata[end]==id) /* End is correct */
356 amb 1341 return(end);
357    
358     return(NO_RELATION);
359     }
360    
361    
362     /*++++++++++++++++++++++++++++++++++++++
363     Find a particular route relation index.
364    
365     index_t IndexTurnRelX Returns the index of the turn relation with the specified id.
366    
367     Relationsx *relationsx The set of relations to process.
368    
369     relation_t id The relation id to look for.
370     ++++++++++++++++++++++++++++++++++++++*/
371    
372     index_t IndexTurnRelX(RelationsX *relationsx,relation_t id)
373     {
374     index_t start=0;
375     index_t end=relationsx->trnumber-1;
376     index_t mid;
377    
378     if(relationsx->trnumber==0) /* There are no route relations */
379     return(NO_RELATION);
380    
381     if(id<relationsx->tridata[start]) /* Key is before start */
382     return(NO_RELATION);
383    
384     if(id>relationsx->tridata[end]) /* Key is after end */
385     return(NO_RELATION);
386    
387     /* Binary search - search key exact match only is required.
388     *
389     * # <- start | Check mid and move start or end if it doesn't match
390     * # |
391     * # | Since an exact match is wanted we can set end=mid-1
392     * # <- mid | or start=mid+1 because we know that mid doesn't match.
393     * # |
394     * # | Eventually either end=start or end=start+1 and one of
395     * # <- end | start or end is the wanted one.
396     */
397    
398     do
399     {
400     mid=(start+end)/2; /* Choose mid point */
401    
402     if(relationsx->tridata[mid]<id) /* Mid point is too low */
403     start=mid+1;
404     else if(relationsx->tridata[mid]>id) /* Mid point is too high */
405     end=mid?(mid-1):mid;
406     else /* Mid point is correct */
407     return(mid);
408     }
409     while((end-start)>1);
410    
411     if(relationsx->tridata[start]==id) /* Start is correct */
412     return(start);
413    
414     if(relationsx->tridata[end]==id) /* End is correct */
415     return(end);
416    
417     return(NO_RELATION);
418     }
419    
420    
421     /*++++++++++++++++++++++++++++++++++++++
422 amb 1120 Sort the list of relations.
423    
424     RelationsX* relationsx The set of relations to process.
425     ++++++++++++++++++++++++++++++++++++++*/
426    
427     void SortRelationList(RelationsX* relationsx)
428     {
429 amb 559 /* Route Relations */
430    
431 amb 1342 if(relationsx->rrnumber)
432 amb 1134 {
433 amb 1342 index_t rrxnumber;
434     int rrfd;
435 amb 1134
436     /* Print the start message */
437    
438     printf_first("Sorting Route Relations");
439    
440     /* Re-open the file read-only and a new file writeable */
441    
442 amb 1342 relationsx->rrfd=ReOpenFile(relationsx->rrfilename_tmp);
443 amb 1134
444 amb 1342 DeleteFile(relationsx->rrfilename_tmp);
445 amb 1134
446 amb 1342 rrfd=OpenFileNew(relationsx->rrfilename_tmp);
447 amb 1134
448     /* Sort the relations */
449    
450 amb 1342 rrxnumber=relationsx->rrnumber;
451 amb 1134
452 amb 1342 relationsx->rrnumber=filesort_vary(relationsx->rrfd,rrfd,NULL,
453     (int (*)(const void*,const void*))sort_route_by_id,
454     (int (*)(void*,index_t))deduplicate_route_by_id);
455 amb 1134
456     /* Close the files */
457    
458 amb 1342 relationsx->rrfd=CloseFile(relationsx->rrfd);
459     CloseFile(rrfd);
460 amb 1134
461     /* Print the final message */
462    
463 amb 1342 printf_last("Sorted Route Relations: Relations=%"Pindex_t" Duplicates=%"Pindex_t,rrxnumber,rrxnumber-relationsx->rrnumber);
464 amb 1134 }
465    
466 amb 559 /* Turn Restriction Relations. */
467    
468 amb 650 if(relationsx->trnumber)
469 amb 551 {
470 amb 650 index_t trxnumber;
471 amb 551 int trfd;
472 amb 540
473 amb 551 /* Print the start message */
474 amb 540
475 amb 895 printf_first("Sorting Turn Relations");
476 amb 540
477 amb 555 /* Re-open the file read-only and a new file writeable */
478    
479 amb 1120 relationsx->trfd=ReOpenFile(relationsx->trfilename_tmp);
480 amb 555
481 amb 1120 DeleteFile(relationsx->trfilename_tmp);
482 amb 540
483 amb 1120 trfd=OpenFileNew(relationsx->trfilename_tmp);
484 amb 540
485 amb 551 /* Sort the relations */
486 amb 540
487 amb 650 trxnumber=relationsx->trnumber;
488    
489 amb 1163 relationsx->trnumber=filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRelX),NULL,
490     (int (*)(const void*,const void*))sort_turn_by_id,
491     (int (*)(void*,index_t))deduplicate_turn_by_id);
492 amb 540
493 amb 555 /* Close the files */
494 amb 540
495 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
496 amb 551 CloseFile(trfd);
497 amb 540
498 amb 551 /* Print the final message */
499 amb 540
500 amb 895 printf_last("Sorted Turn Relations: Relations=%"Pindex_t" Duplicates=%"Pindex_t,trxnumber,trxnumber-relationsx->trnumber);
501 amb 551 }
502 amb 496 }
503    
504    
505     /*++++++++++++++++++++++++++++++++++++++
506 amb 1134 Sort the route relations into id order.
507    
508     int sort_route_by_id Returns the comparison of the id fields.
509    
510     RouteRelX *a The first extended relation.
511    
512     RouteRelX *b The second extended relation.
513     ++++++++++++++++++++++++++++++++++++++*/
514    
515     static int sort_route_by_id(RouteRelX *a,RouteRelX *b)
516     {
517     relation_t a_id=a->id;
518     relation_t b_id=b->id;
519    
520     if(a_id<b_id)
521     return(-1);
522     else if(a_id>b_id)
523     return(1);
524     else
525 amb 1140 return(-FILESORT_PRESERVE_ORDER(a,b)); /* latest version first */
526 amb 1134 }
527    
528    
529     /*++++++++++++++++++++++++++++++++++++++
530     Deduplicate the route relations using the id after sorting.
531    
532     int deduplicate_route_by_id Return 1 if the value is to be kept, otherwise 0.
533    
534     RouteRelX *relationx The extended relation.
535    
536     index_t index The number of sorted relations that have already been written to the output file.
537     ++++++++++++++++++++++++++++++++++++++*/
538    
539     static int deduplicate_route_by_id(RouteRelX *relationx,index_t index)
540     {
541 amb 1140 static relation_t previd=NO_RELATION_ID;
542 amb 1134
543 amb 1140 if(relationx->id!=previd)
544 amb 1134 {
545     previd=relationx->id;
546    
547 amb 1140 if(relationx->routes==RELATION_DELETED)
548     return(0);
549     else
550     return(1);
551 amb 1134 }
552     else
553     return(0);
554     }
555    
556    
557     /*++++++++++++++++++++++++++++++++++++++
558 amb 559 Sort the turn restriction relations into id order.
559 amb 540
560 amb 1134 int sort_turn_by_id Returns the comparison of the id fields.
561 amb 540
562 amb 1163 TurnRelX *a The first extended relation.
563 amb 540
564 amb 1163 TurnRelX *b The second extended relation.
565 amb 540 ++++++++++++++++++++++++++++++++++++++*/
566    
567 amb 1163 static int sort_turn_by_id(TurnRelX *a,TurnRelX *b)
568 amb 540 {
569 amb 559 relation_t a_id=a->id;
570     relation_t b_id=b->id;
571 amb 540
572     if(a_id<b_id)
573     return(-1);
574     else if(a_id>b_id)
575     return(1);
576     else
577 amb 1140 return(-FILESORT_PRESERVE_ORDER(a,b)); /* latest version first */
578 amb 540 }
579    
580    
581     /*++++++++++++++++++++++++++++++++++++++
582 amb 1134 Deduplicate the turn restriction relations using the id after sorting.
583 amb 540
584 amb 1134 int deduplicate_turn_by_id Return 1 if the value is to be kept, otherwise 0.
585 amb 540
586 amb 1163 TurnRelX *relationx The extended relation.
587 amb 540
588 amb 1106 index_t index The number of sorted relations that have already been written to the output file.
589 amb 540 ++++++++++++++++++++++++++++++++++++++*/
590    
591 amb 1163 static int deduplicate_turn_by_id(TurnRelX *relationx,index_t index)
592 amb 540 {
593 amb 1140 static relation_t previd=NO_RELATION_ID;
594 amb 540
595 amb 1140 if(relationx->id!=previd)
596 amb 540 {
597     previd=relationx->id;
598    
599 amb 1140 if(relationx->except==RELATION_DELETED)
600     return(0);
601     else
602     return(1);
603 amb 540 }
604 amb 812 else
605     return(0);
606 amb 540 }
607    
608    
609     /*++++++++++++++++++++++++++++++++++++++
610 amb 496 Process the route relations and apply the information to the ways.
611    
612 amb 681 RelationsX *relationsx The set of relations to use.
613 amb 496
614 amb 681 WaysX *waysx The set of ways to modify.
615 amb 1136
616 amb 1167 int keep If set to 1 then keep the old data file otherwise delete it.
617 amb 496 ++++++++++++++++++++++++++++++++++++++*/
618    
619 amb 1167 void ProcessRouteRelations(RelationsX *relationsx,WaysX *waysx,int keep)
620 amb 496 {
621 amb 505 RouteRelX *unmatched=NULL,*lastunmatched=NULL;
622 amb 761 int nunmatched=0,lastnunmatched=0,iteration=1;
623 amb 496
624 amb 510 if(waysx->number==0)
625 amb 508 return;
626    
627 amb 555 /* Map into memory / open the files */
628 amb 496
629 amb 505 #if !SLIM
630 amb 1120 waysx->data=MapFileWriteable(waysx->filename_tmp);
631 amb 555 #else
632 amb 1120 waysx->fd=ReOpenFileWriteable(waysx->filename_tmp);
633 amb 1297
634     InvalidateWayXCache(waysx->cache);
635 amb 505 #endif
636 amb 496
637 amb 555 /* Re-open the file read-only */
638 amb 548
639 amb 1342 relationsx->rrfd=ReOpenFile(relationsx->rrfilename_tmp);
640 amb 548
641 amb 542 /* Read through the file. */
642 amb 496
643 amb 505 do
644 amb 496 {
645 amb 522 int ways=0,relations=0;
646 amb 780 index_t i;
647 amb 522
648 amb 1342 SeekFile(relationsx->rrfd,0);
649 amb 496
650 amb 505 /* Print the start message */
651 amb 496
652 amb 761 printf_first("Processing Route Relations (%d): Relations=0 Modified Ways=0",iteration);
653 amb 496
654 amb 1342 for(i=0;i<relationsx->rrnumber;i++)
655 amb 496 {
656 amb 505 FILESORT_VARINT size;
657     RouteRelX relationx;
658     way_t wayid;
659     relation_t relationid;
660 amb 529 transports_t routes=Transports_None;
661 amb 496
662 amb 505 /* Read each route relation */
663 amb 496
664 amb 1342 ReadFile(relationsx->rrfd,&size,FILESORT_VARSIZE);
665     ReadFile(relationsx->rrfd,&relationx,sizeof(RouteRelX));
666 amb 496
667 amb 505 /* Decide what type of route it is */
668 amb 496
669 amb 761 if(iteration==1)
670 amb 522 {
671     relations++;
672 amb 505 routes=relationx.routes;
673 amb 522 }
674 amb 505 else
675 amb 506 {
676 amb 522 int j;
677    
678     for(j=0;j<lastnunmatched;j++)
679     if(lastunmatched[j].id==relationx.id)
680     {
681     relations++;
682    
683     if((lastunmatched[j].routes|relationx.routes)==relationx.routes)
684     routes=0; /* Nothing new to add */
685     else
686 amb 506 routes=lastunmatched[j].routes;
687 amb 806
688 amb 522 break;
689     }
690 amb 506 }
691 amb 496
692 amb 505 /* Loop through the ways */
693    
694     do
695     {
696 amb 1342 ReadFile(relationsx->rrfd,&wayid,sizeof(way_t));
697 amb 505
698     /* Update the ways that are listed for the relation */
699    
700 amb 1138 if(wayid==NO_WAY_ID)
701 amb 806 continue;
702    
703     if(routes)
704 amb 505 {
705 amb 506 index_t way=IndexWayX(waysx,wayid);
706 amb 505
707     if(way!=NO_WAY)
708     {
709     WayX *wayx=LookupWayX(waysx,way,1);
710    
711 amb 529 if(routes&Transports_Foot)
712 amb 995 {
713 amb 1064 if(!(wayx->way.allow&Transports_Foot))
714     {
715 amb 1313 logerror("Route Relation %"Prelation_t" for Foot contains Way %"Pway_t" that does not allow Foot transport; overriding.\n",logerror_relation(relationx.id),logerror_way(wayid));
716 amb 1064 wayx->way.allow|=Transports_Foot;
717     }
718 amb 505 wayx->way.props|=Properties_FootRoute;
719 amb 995 }
720 amb 505
721 amb 529 if(routes&Transports_Bicycle)
722 amb 995 {
723 amb 1064 if(!(wayx->way.allow&Transports_Bicycle))
724     {
725 amb 1313 logerror("Route Relation %"Prelation_t" for Bicycle contains Way %"Pway_t" that does not allow Bicycle transport; overriding.\n",logerror_relation(relationx.id),logerror_way(wayid));
726 amb 1064 wayx->way.allow|=Transports_Bicycle;
727     }
728 amb 505 wayx->way.props|=Properties_BicycleRoute;
729 amb 995 }
730 amb 505
731 amb 942 PutBackWayX(waysx,wayx);
732 amb 522
733     ways++;
734 amb 505 }
735 amb 812 else
736 amb 1313 logerror("Route Relation %"Prelation_t" contains Way %"Pway_t" that does not exist in the Routino database (not a highway?).\n",logerror_relation(relationx.id),logerror_way(wayid));
737 amb 505 }
738     }
739 amb 1138 while(wayid!=NO_WAY_ID);
740 amb 505
741     /* Loop through the relations */
742    
743     do
744     {
745 amb 1342 ReadFile(relationsx->rrfd,&relationid,sizeof(relation_t));
746 amb 505
747     /* Add the relations that are listed for this relation to the list for next time */
748    
749 amb 1138 if(relationid==NO_RELATION_ID)
750 amb 806 continue;
751    
752 amb 812 if(relationid==relationx.id)
753 amb 1313 logerror("Relation %"Prelation_t" contains itself.\n",logerror_relation(relationx.id));
754 amb 812 else if(routes)
755 amb 505 {
756     if(nunmatched%256==0)
757     unmatched=(RouteRelX*)realloc((void*)unmatched,(nunmatched+256)*sizeof(RouteRelX));
758    
759     unmatched[nunmatched].id=relationid;
760     unmatched[nunmatched].routes=routes;
761    
762     nunmatched++;
763     }
764     }
765 amb 1138 while(relationid!=NO_RELATION_ID);
766 amb 505
767 amb 757 if(!((i+1)%1000))
768 amb 790 printf_middle("Processing Route Relations (%d): Relations=%"Pindex_t" Modified Ways=%"Pindex_t,iteration,relations,ways);
769 amb 496 }
770    
771 amb 505 if(lastunmatched)
772     free(lastunmatched);
773    
774     lastunmatched=unmatched;
775     lastnunmatched=nunmatched;
776    
777     unmatched=NULL;
778     nunmatched=0;
779    
780     /* Print the final message */
781    
782 amb 790 printf_last("Processed Route Relations (%d): Relations=%"Pindex_t" Modified Ways=%"Pindex_t,iteration,relations,ways);
783 amb 496 }
784 amb 812 while(lastnunmatched && iteration++<8);
785 amb 496
786 amb 505 if(lastunmatched)
787     free(lastunmatched);
788    
789 amb 555 /* Close the file */
790    
791 amb 1342 relationsx->rrfd=CloseFile(relationsx->rrfd);
792 amb 496
793 amb 1167 if(keep)
794 amb 1342 RenameFile(relationsx->rrfilename_tmp,relationsx->rrfilename);
795 amb 1136
796 amb 1342 relationsx->rrknumber=relationsx->rrnumber;
797 amb 1317
798 amb 555 /* Unmap from memory / close the files */
799 amb 496
800 amb 505 #if !SLIM
801 amb 1122 waysx->data=UnmapFile(waysx->data);
802 amb 555 #else
803 amb 612 waysx->fd=CloseFile(waysx->fd);
804 amb 511 #endif
805 amb 496 }
806 amb 542
807    
808     /*++++++++++++++++++++++++++++++++++++++
809 amb 1353 Process the turn relations to update them with node/segment information.
810 amb 542
811 amb 681 RelationsX *relationsx The set of relations to modify.
812 amb 542
813 amb 680 NodesX *nodesx The set of nodes to use.
814 amb 542
815 amb 1353 SegmentsX *segmentsx The set of segments to use.
816    
817 amb 680 WaysX *waysx The set of ways to use.
818 amb 1136
819 amb 1167 int keep If set to 1 then keep the old data file otherwise delete it.
820 amb 645 ++++++++++++++++++++++++++++++++++++++*/
821    
822 amb 1353 void ProcessTurnRelations(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx,int keep)
823 amb 645 {
824 amb 780 int trfd;
825 amb 1353 index_t i,total=0,deleted=0;
826 amb 645
827 amb 1353 if(nodesx->number==0 || segmentsx->number==0)
828     return;
829    
830 amb 645 /* Print the start message */
831    
832 amb 1353 printf_first("Processing Turn Relations: Relations=0 Deleted=0 Added=0");
833 amb 645
834 amb 1353 /* Map into memory / open the files */
835    
836     #if !SLIM
837     nodesx->data=MapFileWriteable(nodesx->filename_tmp);
838     segmentsx->data=MapFile(segmentsx->filename_tmp);
839     waysx->data=MapFile(waysx->filename_tmp);
840     #else
841     nodesx->fd=ReOpenFileWriteable(nodesx->filename_tmp);
842     segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
843     waysx->fd=ReOpenFile(waysx->filename_tmp);
844    
845     InvalidateNodeXCache(nodesx->cache);
846     InvalidateSegmentXCache(segmentsx->cache);
847     InvalidateWayXCache(waysx->cache);
848     #endif
849    
850 amb 645 /* Re-open the file read-only and a new file writeable */
851    
852 amb 1120 relationsx->trfd=ReOpenFile(relationsx->trfilename_tmp);
853 amb 645
854 amb 1167 if(keep)
855 amb 1136 RenameFile(relationsx->trfilename_tmp,relationsx->trfilename);
856     else
857     DeleteFile(relationsx->trfilename_tmp);
858 amb 645
859 amb 1317 relationsx->trknumber=relationsx->trnumber;
860    
861 amb 1120 trfd=OpenFileNew(relationsx->trfilename_tmp);
862 amb 645
863     /* Process all of the relations */
864    
865     for(i=0;i<relationsx->trnumber;i++)
866     {
867 amb 1163 TurnRelX relationx;
868 amb 1353 NodeX *nodex;
869     SegmentX *segmentx;
870 amb 1138 index_t via,from,to;
871 amb 645
872 amb 1163 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRelX));
873 amb 645
874 amb 812 via =IndexNodeX(nodesx,relationx.via);
875     from=IndexWayX(waysx,relationx.from);
876     to =IndexWayX(waysx,relationx.to);
877 amb 645
878 amb 812 if(via==NO_NODE)
879 amb 1353 {
880 amb 1313 logerror("Turn Relation %"Prelation_t" contains Node %"Pnode_t" that does not exist in the Routino database (not a highway node?).\n",logerror_relation(relationx.id),logerror_node(relationx.via));
881 amb 1353 deleted++;
882     goto endloop;
883     }
884 amb 812
885     if(from==NO_WAY)
886 amb 1353 {
887 amb 1313 logerror("Turn Relation %"Prelation_t" contains Way %"Pway_t" that does not exist in the Routino database (not a highway?).\n",logerror_relation(relationx.id),logerror_way(relationx.from));
888 amb 1353 deleted++;
889     goto endloop;
890     }
891 amb 812
892     if(to==NO_WAY)
893 amb 1353 {
894 amb 1313 logerror("Turn Relation %"Prelation_t" contains Way %"Pway_t" that does not exist in the Routino database (not a highway?).\n",logerror_relation(relationx.id),logerror_way(relationx.to));
895 amb 1353 deleted++;
896     goto endloop;
897     }
898 amb 812
899     relationx.via =via;
900     relationx.from=from;
901     relationx.to =to;
902    
903 amb 786 if(relationx.restriction==TurnRestrict_no_right_turn ||
904     relationx.restriction==TurnRestrict_no_left_turn ||
905     relationx.restriction==TurnRestrict_no_u_turn ||
906     relationx.restriction==TurnRestrict_no_straight_on)
907 amb 548 {
908 amb 770 index_t node_from=NO_NODE,node_to=NO_NODE;
909 amb 806 int oneway_from=0,oneway_to=0,vehicles_from=1,vehicles_to=1;
910 amb 542
911 amb 548 /* Find the segments that join the node 'via' */
912 amb 542
913 amb 646 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
914 amb 542
915 amb 742 while(segmentx)
916 amb 548 {
917 amb 645 if(segmentx->way==relationx.from)
918 amb 548 {
919 amb 806 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
920    
921 amb 551 if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
922 amb 742 {
923 amb 1313 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'from' way.\n",logerror_relation(relationx.id));
924 amb 742 deleted++;
925 amb 551 goto endloop;
926 amb 742 }
927 amb 548
928 amb 645 node_from=OtherNode(segmentx,relationx.via);
929 amb 806
930     if(IsOnewayFrom(segmentx,relationx.via))
931     oneway_from=1; /* not allowed */
932    
933 amb 1243 if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorcycle|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
934 amb 806 vehicles_from=0; /* not allowed */
935 amb 548 }
936    
937 amb 645 if(segmentx->way==relationx.to)
938 amb 548 {
939 amb 806 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
940    
941 amb 551 if(node_to!=NO_NODE) /* Only one segment can be on the 'to' way */
942 amb 742 {
943 amb 1313 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'to' way.\n",logerror_relation(relationx.id));
944 amb 742 deleted++;
945 amb 551 goto endloop;
946 amb 742 }
947 amb 548
948 amb 806 node_to=OtherNode(segmentx,relationx.via);
949 amb 670
950 amb 806 if(IsOnewayTo(segmentx,relationx.via))
951     oneway_to=1; /* not allowed */
952    
953 amb 1243 if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorcycle|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
954 amb 806 vehicles_to=0; /* not allowed */
955 amb 548 }
956    
957 amb 943 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via);
958 amb 548 }
959    
960 amb 812 if(node_from==NO_NODE)
961 amb 1313 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'from' way.\n",logerror_relation(relationx.id));
962 amb 812
963     if(node_to==NO_NODE)
964 amb 1313 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'to' way.\n",logerror_relation(relationx.id));
965 amb 812
966     if(oneway_from)
967 amb 1313 logerror("Turn Relation %"Prelation_t" is not needed because the 'from' way is oneway away from the 'via' node.\n",logerror_relation(relationx.id));
968 amb 812
969     if(oneway_to)
970 amb 1313 logerror("Turn Relation %"Prelation_t" is not needed because the 'to' way is oneway towards the 'via' node.\n",logerror_relation(relationx.id));
971 amb 812
972     if(!vehicles_from)
973 amb 1313 logerror("Turn Relation %"Prelation_t" is not needed because the 'from' way does not allow vehicles.\n",logerror_relation(relationx.id));
974 amb 812
975     if(!vehicles_to)
976 amb 1313 logerror("Turn Relation %"Prelation_t" is not needed because the 'to' way does not allow vehicles.\n",logerror_relation(relationx.id));
977 amb 812
978 amb 806 if(oneway_from || oneway_to || !vehicles_from || !vehicles_to || node_from==NO_NODE || node_to==NO_NODE)
979 amb 742 {
980     deleted++;
981 amb 548 goto endloop;
982 amb 742 }
983 amb 548
984 amb 551 /* Write the results */
985 amb 548
986 amb 645 relationx.from=node_from;
987     relationx.to =node_to;
988 amb 548
989 amb 1163 WriteFile(trfd,&relationx,sizeof(TurnRelX));
990 amb 548
991 amb 559 total++;
992 amb 551 }
993     else
994     {
995 amb 806 index_t node_from=NO_NODE,node_to=NO_NODE,node_other[MAX_SEG_PER_NODE];
996     int nnodes_other=0,i;
997     int oneway_from=0,vehicles_from=1;
998 amb 548
999 amb 551 /* Find the segments that join the node 'via' */
1000 amb 548
1001 amb 646 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
1002 amb 548
1003 amb 742 while(segmentx)
1004 amb 551 {
1005 amb 645 if(segmentx->way==relationx.from)
1006 amb 551 {
1007 amb 806 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
1008    
1009 amb 551 if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
1010 amb 742 {
1011 amb 1313 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'from' way.\n",logerror_relation(relationx.id));
1012 amb 742 deleted++;
1013 amb 548 goto endloop;
1014 amb 742 }
1015 amb 548
1016 amb 645 node_from=OtherNode(segmentx,relationx.via);
1017 amb 806
1018     if(IsOnewayFrom(segmentx,relationx.via))
1019     oneway_from=1; /* not allowed */
1020    
1021 amb 1243 if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorcycle|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
1022 amb 806 vehicles_from=0; /* not allowed */
1023 amb 548 }
1024 amb 551
1025 amb 806 if(segmentx->way==relationx.to)
1026 amb 551 {
1027 amb 806 if(node_to!=NO_NODE) /* Only one segment can be on the 'to' way */
1028     {
1029 amb 1313 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'to' way.\n",logerror_relation(relationx.id));
1030 amb 806 deleted++;
1031     goto endloop;
1032     }
1033 amb 551
1034 amb 806 node_to=OtherNode(segmentx,relationx.via);
1035     }
1036 amb 670
1037 amb 806 if(segmentx->way!=relationx.from && segmentx->way!=relationx.to)
1038     {
1039     WayX *wayx=LookupWayX(waysx,segmentx->way,1);
1040    
1041     if(IsOnewayTo(segmentx,relationx.via))
1042     ; /* not allowed */
1043 amb 1243 else if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorcycle|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
1044 amb 806 ; /* not allowed */
1045     else
1046 amb 812 {
1047 amb 1166 logassert(nnodes_other<MAX_SEG_PER_NODE,"Too many segments for one node (increase MAX_SEG_PER_NODE?)"); /* Only a limited amount of information stored. */
1048 amb 812
1049 amb 806 node_other[nnodes_other++]=OtherNode(segmentx,relationx.via);
1050 amb 812 }
1051 amb 551 }
1052    
1053 amb 943 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via);
1054 amb 548 }
1055    
1056 amb 812 if(node_from==NO_NODE)
1057 amb 1313 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'from' way.\n",logerror_relation(relationx.id));
1058 amb 812
1059     if(node_to==NO_NODE)
1060 amb 1313 logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'to' way.\n",logerror_relation(relationx.id));
1061 amb 812
1062     if(nnodes_other==0)
1063 amb 1313 logerror("Turn Relation %"Prelation_t" is not needed because the only allowed exit from the 'via' node is the 'to' way.\n",logerror_relation(relationx.id));
1064 amb 812
1065     if(oneway_from)
1066 amb 1313 logerror("Turn Relation %"Prelation_t" is not needed because the 'from' way is oneway away from the 'via' node.\n",logerror_relation(relationx.id));
1067 amb 812
1068     if(!vehicles_from)
1069 amb 1313 logerror("Turn Relation %"Prelation_t" is not needed because the 'from' way does not allow vehicles.\n",logerror_relation(relationx.id));
1070 amb 812
1071 amb 806 if(oneway_from || !vehicles_from || node_from==NO_NODE || node_to==NO_NODE || nnodes_other==0)
1072 amb 742 {
1073     deleted++;
1074 amb 548 goto endloop;
1075 amb 742 }
1076 amb 548
1077     /* Write the results */
1078    
1079 amb 806 for(i=0;i<nnodes_other;i++)
1080 amb 551 {
1081 amb 645 relationx.from=node_from;
1082 amb 806 relationx.to =node_other[i];
1083 amb 548
1084 amb 1163 WriteFile(trfd,&relationx,sizeof(TurnRelX));
1085 amb 548
1086 amb 559 total++;
1087 amb 551 }
1088 amb 615 }
1089 amb 560
1090 amb 615 /* Force super nodes on via node and adjacent nodes */
1091    
1092     nodex=LookupNodeX(nodesx,relationx.via,1);
1093     nodex->flags|=NODE_TURNRSTRCT;
1094 amb 942 PutBackNodeX(nodesx,nodex);
1095 amb 615
1096 amb 646 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
1097 amb 615
1098 amb 742 while(segmentx)
1099 amb 615 {
1100 amb 645 index_t othernode=OtherNode(segmentx,relationx.via);
1101 amb 615
1102     nodex=LookupNodeX(nodesx,othernode,1);
1103 amb 597 nodex->flags|=NODE_TURNRSTRCT2;
1104 amb 942 PutBackNodeX(nodesx,nodex);
1105 amb 597
1106 amb 943 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via);
1107 amb 548 }
1108    
1109 amb 1353 endloop:
1110    
1111     if(!((i+1)%1000))
1112     printf_middle("Processing Turn Relations: Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,i+1,deleted,total-relationsx->trnumber+deleted);
1113 amb 542 }
1114    
1115 amb 555 /* Close the files */
1116 amb 542
1117 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
1118 amb 542 CloseFile(trfd);
1119    
1120 amb 1353 /* Free the now-unneeded indexes */
1121    
1122     free(nodesx->idata);
1123     nodesx->idata=NULL;
1124    
1125     free(waysx->idata);
1126     waysx->idata=NULL;
1127    
1128 amb 555 /* Unmap from memory / close the files */
1129 amb 542
1130 amb 548 #if !SLIM
1131 amb 1122 nodesx->data=UnmapFile(nodesx->data);
1132     segmentsx->data=UnmapFile(segmentsx->data);
1133     waysx->data=UnmapFile(waysx->data);
1134 amb 555 #else
1135 amb 612 nodesx->fd=CloseFile(nodesx->fd);
1136     segmentsx->fd=CloseFile(segmentsx->fd);
1137 amb 806 waysx->fd=CloseFile(waysx->fd);
1138 amb 548 #endif
1139    
1140 amb 542 /* Print the final message */
1141    
1142 amb 1353 printf_last("Processed Turn Relations: Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,total,deleted,total-relationsx->trnumber+deleted);
1143 amb 559
1144     relationsx->trnumber=total;
1145 amb 542 }
1146    
1147    
1148     /*++++++++++++++++++++++++++++++++++++++
1149 amb 1098 Remove pruned turn relations and update the node indexes after pruning nodes.
1150 amb 542
1151 amb 681 RelationsX *relationsx The set of relations to modify.
1152 amb 542
1153 amb 665 NodesX *nodesx The set of nodes to use.
1154 amb 1098 ++++++++++++++++++++++++++++++++++++++*/
1155 amb 665
1156 amb 1098 void RemovePrunedTurnRelations(RelationsX *relationsx,NodesX *nodesx)
1157     {
1158 amb 1163 TurnRelX relationx;
1159 amb 1098 index_t total=0,pruned=0,notpruned=0;
1160     int trfd;
1161    
1162 amb 1208 if(relationsx->trnumber==0)
1163     return;
1164    
1165 amb 1098 /* Print the start message */
1166    
1167     printf_first("Deleting Pruned Turn Relations: Relations=0 Pruned=0");
1168    
1169     /* Re-open the file read-only and a new file writeable */
1170    
1171 amb 1120 relationsx->trfd=ReOpenFile(relationsx->trfilename_tmp);
1172 amb 1098
1173 amb 1120 DeleteFile(relationsx->trfilename_tmp);
1174 amb 1098
1175 amb 1120 trfd=OpenFileNew(relationsx->trfilename_tmp);
1176 amb 1098
1177     /* Process all of the relations */
1178    
1179 amb 1163 while(!ReadFile(relationsx->trfd,&relationx,sizeof(TurnRelX)))
1180 amb 1098 {
1181     relationx.from=nodesx->pdata[relationx.from];
1182     relationx.via =nodesx->pdata[relationx.via];
1183     relationx.to =nodesx->pdata[relationx.to];
1184    
1185     if(relationx.from==NO_NODE || relationx.via==NO_NODE || relationx.to==NO_NODE)
1186     pruned++;
1187     else
1188     {
1189 amb 1163 WriteFile(trfd,&relationx,sizeof(TurnRelX));
1190 amb 1098
1191     notpruned++;
1192     }
1193    
1194     total++;
1195    
1196     if(!(total%1000))
1197     printf_middle("Deleting Pruned Turn Relations: Relations=%"Pindex_t" Pruned=%"Pindex_t,total,pruned);
1198     }
1199    
1200     relationsx->trnumber=notpruned;
1201    
1202     /* Close the files */
1203    
1204     relationsx->trfd=CloseFile(relationsx->trfd);
1205     CloseFile(trfd);
1206    
1207     /* Print the final message */
1208    
1209     printf_last("Deleted Pruned Turn Relations: Relations=%"Pindex_t" Pruned=%"Pindex_t,total,pruned);
1210     }
1211    
1212    
1213     /*++++++++++++++++++++++++++++++++++++++
1214 amb 1108 Sort the turn relations geographically after updating the node indexes.
1215 amb 1098
1216     RelationsX *relationsx The set of relations to modify.
1217    
1218     NodesX *nodesx The set of nodes to use.
1219    
1220 amb 680 SegmentsX *segmentsx The set of segments to use.
1221 amb 542 ++++++++++++++++++++++++++++++++++++++*/
1222    
1223 amb 1108 void SortTurnRelationListGeographically(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx)
1224 amb 542 {
1225     int trfd;
1226    
1227 amb 1208 if(segmentsx->number==0)
1228     return;
1229    
1230 amb 542 /* Print the start message */
1231    
1232 amb 1108 printf_first("Sorting Turn Relations Geographically");
1233 amb 542
1234 amb 599 /* Map into memory / open the files */
1235    
1236     #if !SLIM
1237 amb 1120 segmentsx->data=MapFile(segmentsx->filename_tmp);
1238 amb 599 #else
1239 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
1240 amb 1297
1241     InvalidateSegmentXCache(segmentsx->cache);
1242 amb 599 #endif
1243    
1244 amb 555 /* Re-open the file read-only and a new file writeable */
1245 amb 542
1246 amb 1120 relationsx->trfd=ReOpenFile(relationsx->trfilename_tmp);
1247 amb 555
1248 amb 1120 DeleteFile(relationsx->trfilename_tmp);
1249 amb 542
1250 amb 1120 trfd=OpenFileNew(relationsx->trfilename_tmp);
1251 amb 542
1252 amb 1108 /* Update the segments with geographically sorted node indexes and sort them */
1253 amb 542
1254 amb 1108 sortnodesx=nodesx;
1255     sortsegmentsx=segmentsx;
1256 amb 542
1257 amb 1163 filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRelX),(int (*)(void*,index_t))geographically_index,
1258     (int (*)(const void*,const void*))sort_by_via,
1259     NULL);
1260 amb 542
1261 amb 555 /* Close the files */
1262 amb 542
1263 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
1264 amb 542 CloseFile(trfd);
1265    
1266 amb 599 /* Unmap from memory / close the files */
1267    
1268     #if !SLIM
1269 amb 1122 segmentsx->data=UnmapFile(segmentsx->data);
1270 amb 599 #else
1271 amb 612 segmentsx->fd=CloseFile(segmentsx->fd);
1272 amb 599 #endif
1273    
1274 amb 542 /* Print the final message */
1275    
1276 amb 1110 printf_last("Sorted Turn Relations Geographically: Turn Relations=%"Pindex_t,relationsx->trnumber);
1277 amb 645 }
1278    
1279    
1280     /*++++++++++++++++++++++++++++++++++++++
1281 amb 1108 Update the turn relation indexes.
1282    
1283     int geographically_index Return 1 if the value is to be kept, otherwise 0.
1284    
1285 amb 1163 TurnRelX *relationx The extended turn relation.
1286 amb 1108
1287 amb 1112 index_t index The number of unsorted turn relations that have been read from the input file.
1288 amb 1108 ++++++++++++++++++++++++++++++++++++++*/
1289    
1290 amb 1163 static int geographically_index(TurnRelX *relationx,index_t index)
1291 amb 1108 {
1292     SegmentX *segmentx;
1293     index_t from_node,via_node,to_node;
1294    
1295     from_node=sortnodesx->gdata[relationx->from];
1296     via_node =sortnodesx->gdata[relationx->via];
1297     to_node =sortnodesx->gdata[relationx->to];
1298    
1299     segmentx=FirstSegmentX(sortsegmentsx,via_node,1);
1300    
1301     do
1302     {
1303     if(OtherNode(segmentx,via_node)==from_node)
1304     relationx->from=IndexSegmentX(sortsegmentsx,segmentx);
1305    
1306     if(OtherNode(segmentx,via_node)==to_node)
1307     relationx->to=IndexSegmentX(sortsegmentsx,segmentx);
1308    
1309     segmentx=NextSegmentX(sortsegmentsx,segmentx,via_node);
1310     }
1311     while(segmentx);
1312    
1313     relationx->via=via_node;
1314    
1315     return(1);
1316     }
1317    
1318    
1319     /*++++++++++++++++++++++++++++++++++++++
1320     Sort the turn restriction relations into via index order (then by from and to segments).
1321    
1322     int sort_by_via Returns the comparison of the via, from and to fields.
1323    
1324 amb 1163 TurnRelX *a The first extended relation.
1325 amb 1108
1326 amb 1163 TurnRelX *b The second extended relation.
1327 amb 1108 ++++++++++++++++++++++++++++++++++++++*/
1328    
1329 amb 1163 static int sort_by_via(TurnRelX *a,TurnRelX *b)
1330 amb 1108 {
1331     index_t a_id=a->via;
1332     index_t b_id=b->via;
1333    
1334     if(a_id<b_id)
1335     return(-1);
1336     else if(a_id>b_id)
1337     return(1);
1338     else
1339     {
1340     index_t a_id=a->from;
1341     index_t b_id=b->from;
1342    
1343     if(a_id<b_id)
1344     return(-1);
1345     else if(a_id>b_id)
1346     return(1);
1347     else
1348     {
1349     index_t a_id=a->to;
1350     index_t b_id=b->to;
1351    
1352     if(a_id<b_id)
1353     return(-1);
1354     else if(a_id>b_id)
1355     return(1);
1356     else
1357 amb 1118 return(FILESORT_PRESERVE_ORDER(a,b));
1358 amb 1108 }
1359     }
1360     }
1361    
1362    
1363     /*++++++++++++++++++++++++++++++++++++++
1364 amb 542 Save the relation list to a file.
1365    
1366     RelationsX* relationsx The set of relations to save.
1367    
1368     const char *filename The name of the file to save.
1369     ++++++++++++++++++++++++++++++++++++++*/
1370    
1371     void SaveRelationList(RelationsX* relationsx,const char *filename)
1372     {
1373     index_t i;
1374     int fd;
1375     RelationsFile relationsfile={0};
1376    
1377     /* Print the start message */
1378    
1379     printf_first("Writing Relations: Turn Relations=0");
1380    
1381 amb 559 /* Re-open the file read-only */
1382 amb 555
1383 amb 1120 relationsx->trfd=ReOpenFile(relationsx->trfilename_tmp);
1384 amb 555
1385 amb 542 /* Write out the relations data */
1386    
1387     fd=OpenFileNew(filename);
1388    
1389     SeekFile(fd,sizeof(RelationsFile));
1390    
1391     for(i=0;i<relationsx->trnumber;i++)
1392     {
1393 amb 1163 TurnRelX relationx;
1394 amb 944 TurnRelation relation={0};
1395 amb 542
1396 amb 1163 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRelX));
1397 amb 542
1398 amb 551 relation.from=relationx.from;
1399     relation.via=relationx.via;
1400     relation.to=relationx.to;
1401     relation.except=relationx.except;
1402 amb 542
1403 amb 551 WriteFile(fd,&relation,sizeof(TurnRelation));
1404    
1405 amb 757 if(!((i+1)%1000))
1406 amb 790 printf_middle("Writing Relations: Turn Relations=%"Pindex_t,i+1);
1407 amb 542 }
1408    
1409     /* Write out the header structure */
1410    
1411     relationsfile.trnumber=relationsx->trnumber;
1412    
1413     SeekFile(fd,0);
1414     WriteFile(fd,&relationsfile,sizeof(RelationsFile));
1415    
1416     CloseFile(fd);
1417    
1418     /* Close the file */
1419    
1420 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
1421 amb 542
1422     /* Print the final message */
1423    
1424 amb 790 printf_last("Wrote Relations: Turn Relations=%"Pindex_t,relationsx->trnumber);
1425 amb 542 }