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 1426 - (hide annotations) (download) (as text)
Wed Jun 26 18:26:27 2013 UTC (11 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 41536 byte(s)
Sort the nodes geographically at the beginning rather than at the end.

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