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 1408 - (hide annotations) (download) (as text)
Fri Jun 21 14:43:37 2013 UTC (11 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 41509 byte(s)
Use the new functions for buffering while reading when looping through files
other than the ones already done that use the FILESORT_VARINT method of storing
data.

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