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 1405 - (hide annotations) (download) (as text)
Thu Jun 20 18:36:47 2013 UTC (11 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 41302 byte(s)
Use the new functions for buffering while reading when looping through files
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 1405 SeekFileBuffered(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 542 /* Read through the file. */
645 amb 496
646 amb 505 do
647 amb 496 {
648 amb 522 int ways=0,relations=0;
649 amb 780 index_t i;
650 amb 522
651 amb 1405 /* Re-open the file read-only */
652 amb 496
653 amb 1405 relationsx->rrfd=ReOpenFileBuffered(relationsx->rrfilename_tmp);
654    
655 amb 505 /* Print the start message */
656 amb 496
657 amb 761 printf_first("Processing Route Relations (%d): Relations=0 Modified Ways=0",iteration);
658 amb 496
659 amb 1342 for(i=0;i<relationsx->rrnumber;i++)
660 amb 496 {
661 amb 505 FILESORT_VARINT size;
662     RouteRelX relationx;
663     way_t wayid;
664 amb 1370 node_t nodeid;
665 amb 505 relation_t relationid;
666 amb 529 transports_t routes=Transports_None;
667 amb 496
668 amb 505 /* Read each route relation */
669 amb 496
670 amb 1405 ReadFileBuffered(relationsx->rrfd,&size,FILESORT_VARSIZE);
671     ReadFileBuffered(relationsx->rrfd,&relationx,sizeof(RouteRelX));
672 amb 496
673 amb 505 /* Decide what type of route it is */
674 amb 496
675 amb 761 if(iteration==1)
676 amb 522 {
677     relations++;
678 amb 505 routes=relationx.routes;
679 amb 522 }
680 amb 505 else
681 amb 506 {
682 amb 522 int j;
683    
684     for(j=0;j<lastnunmatched;j++)
685     if(lastunmatched[j].id==relationx.id)
686     {
687     relations++;
688    
689     if((lastunmatched[j].routes|relationx.routes)==relationx.routes)
690     routes=0; /* Nothing new to add */
691     else
692 amb 506 routes=lastunmatched[j].routes;
693 amb 806
694 amb 522 break;
695     }
696 amb 506 }
697 amb 496
698 amb 1370 /* Skip the nodes */
699    
700 amb 1405 while(!ReadFileBuffered(relationsx->rrfd,&nodeid,sizeof(node_t)) && nodeid!=NO_NODE_ID)
701     ;
702 amb 1370
703 amb 505 /* Loop through the ways */
704    
705 amb 1405 while(!ReadFileBuffered(relationsx->rrfd,&wayid,sizeof(way_t)) && wayid!=NO_WAY_ID)
706 amb 505 {
707     /* Update the ways that are listed for the relation */
708    
709 amb 806 if(routes)
710 amb 505 {
711 amb 506 index_t way=IndexWayX(waysx,wayid);
712 amb 505
713     if(way!=NO_WAY)
714     {
715     WayX *wayx=LookupWayX(waysx,way,1);
716    
717 amb 529 if(routes&Transports_Foot)
718 amb 995 {
719 amb 1064 if(!(wayx->way.allow&Transports_Foot))
720     {
721 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));
722 amb 1064 wayx->way.allow|=Transports_Foot;
723     }
724 amb 505 wayx->way.props|=Properties_FootRoute;
725 amb 995 }
726 amb 505
727 amb 529 if(routes&Transports_Bicycle)
728 amb 995 {
729 amb 1064 if(!(wayx->way.allow&Transports_Bicycle))
730     {
731 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));
732 amb 1064 wayx->way.allow|=Transports_Bicycle;
733     }
734 amb 505 wayx->way.props|=Properties_BicycleRoute;
735 amb 995 }
736 amb 505
737 amb 942 PutBackWayX(waysx,wayx);
738 amb 522
739     ways++;
740 amb 505 }
741 amb 812 else
742 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));
743 amb 505 }
744     }
745    
746     /* Loop through the relations */
747    
748 amb 1405 while(!ReadFileBuffered(relationsx->rrfd,&relationid,sizeof(relation_t)) && relationid!=NO_RELATION_ID)
749 amb 505 {
750     /* Add the relations that are listed for this relation to the list for next time */
751    
752 amb 812 if(relationid==relationx.id)
753 amb 1313 logerror("Relation %"Prelation_t" contains itself.\n",logerror_relation(relationx.id));
754 amb 812 else if(routes)
755 amb 505 {
756     if(nunmatched%256==0)
757     unmatched=(RouteRelX*)realloc((void*)unmatched,(nunmatched+256)*sizeof(RouteRelX));
758    
759     unmatched[nunmatched].id=relationid;
760     unmatched[nunmatched].routes=routes;
761    
762     nunmatched++;
763     }
764     }
765    
766 amb 757 if(!((i+1)%1000))
767 amb 790 printf_middle("Processing Route Relations (%d): Relations=%"Pindex_t" Modified Ways=%"Pindex_t,iteration,relations,ways);
768 amb 496 }
769    
770 amb 505 if(lastunmatched)
771     free(lastunmatched);
772    
773     lastunmatched=unmatched;
774     lastnunmatched=nunmatched;
775    
776     unmatched=NULL;
777     nunmatched=0;
778    
779 amb 1405 /* Close the file */
780    
781     relationsx->rrfd=CloseFileBuffered(relationsx->rrfd);
782    
783 amb 505 /* Print the final message */
784    
785 amb 790 printf_last("Processed Route Relations (%d): Relations=%"Pindex_t" Modified Ways=%"Pindex_t,iteration,relations,ways);
786 amb 496 }
787 amb 812 while(lastnunmatched && iteration++<8);
788 amb 496
789 amb 505 if(lastunmatched)
790     free(lastunmatched);
791    
792 amb 1167 if(keep)
793 amb 1342 RenameFile(relationsx->rrfilename_tmp,relationsx->rrfilename);
794 amb 1136
795 amb 555 /* Unmap from memory / close the files */
796 amb 496
797 amb 505 #if !SLIM
798 amb 1122 waysx->data=UnmapFile(waysx->data);
799 amb 555 #else
800 amb 612 waysx->fd=CloseFile(waysx->fd);
801 amb 511 #endif
802 amb 496 }
803 amb 542
804    
805     /*++++++++++++++++++++++++++++++++++++++
806 amb 1353 Process the turn relations to update them with node/segment information.
807 amb 542
808 amb 681 RelationsX *relationsx The set of relations to modify.
809 amb 542
810 amb 680 NodesX *nodesx The set of nodes to use.
811 amb 542
812 amb 1353 SegmentsX *segmentsx The set of segments to use.
813    
814 amb 680 WaysX *waysx The set of ways to use.
815 amb 1136
816 amb 1167 int keep If set to 1 then keep the old data file otherwise delete it.
817 amb 645 ++++++++++++++++++++++++++++++++++++++*/
818    
819 amb 1353 void ProcessTurnRelations(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx,int keep)
820 amb 645 {
821 amb 780 int trfd;
822 amb 1353 index_t i,total=0,deleted=0;
823 amb 645
824 amb 1353 if(nodesx->number==0 || segmentsx->number==0)
825     return;
826    
827 amb 645 /* Print the start message */
828    
829 amb 1353 printf_first("Processing Turn Relations: Relations=0 Deleted=0 Added=0");
830 amb 645
831 amb 1353 /* Map into memory / open the files */
832    
833     #if !SLIM
834     nodesx->data=MapFileWriteable(nodesx->filename_tmp);
835     segmentsx->data=MapFile(segmentsx->filename_tmp);
836     waysx->data=MapFile(waysx->filename_tmp);
837     #else
838     nodesx->fd=ReOpenFileWriteable(nodesx->filename_tmp);
839     segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
840     waysx->fd=ReOpenFile(waysx->filename_tmp);
841    
842     InvalidateNodeXCache(nodesx->cache);
843     InvalidateSegmentXCache(segmentsx->cache);
844     InvalidateWayXCache(waysx->cache);
845     #endif
846    
847 amb 645 /* Re-open the file read-only and a new file writeable */
848    
849 amb 1120 relationsx->trfd=ReOpenFile(relationsx->trfilename_tmp);
850 amb 645
851 amb 1167 if(keep)
852 amb 1136 RenameFile(relationsx->trfilename_tmp,relationsx->trfilename);
853     else
854     DeleteFile(relationsx->trfilename_tmp);
855 amb 645
856 amb 1120 trfd=OpenFileNew(relationsx->trfilename_tmp);
857 amb 645
858     /* Process all of the relations */
859    
860     for(i=0;i<relationsx->trnumber;i++)
861     {
862 amb 1163 TurnRelX relationx;
863 amb 1353 NodeX *nodex;
864     SegmentX *segmentx;
865 amb 1138 index_t via,from,to;
866 amb 645
867 amb 1163 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRelX));
868 amb 645
869 amb 812 via =IndexNodeX(nodesx,relationx.via);
870     from=IndexWayX(waysx,relationx.from);
871     to =IndexWayX(waysx,relationx.to);
872 amb 645
873 amb 812 if(via==NO_NODE)
874 amb 1353 {
875 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));
876 amb 1353 deleted++;
877     goto endloop;
878     }
879 amb 812
880     if(from==NO_WAY)
881 amb 1353 {
882 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));
883 amb 1353 deleted++;
884     goto endloop;
885     }
886 amb 812
887     if(to==NO_WAY)
888 amb 1353 {
889 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));
890 amb 1353 deleted++;
891     goto endloop;
892     }
893 amb 812
894     relationx.via =via;
895     relationx.from=from;
896     relationx.to =to;
897    
898 amb 786 if(relationx.restriction==TurnRestrict_no_right_turn ||
899     relationx.restriction==TurnRestrict_no_left_turn ||
900     relationx.restriction==TurnRestrict_no_u_turn ||
901     relationx.restriction==TurnRestrict_no_straight_on)
902 amb 548 {
903 amb 770 index_t node_from=NO_NODE,node_to=NO_NODE;
904 amb 806 int oneway_from=0,oneway_to=0,vehicles_from=1,vehicles_to=1;
905 amb 542
906 amb 548 /* Find the segments that join the node 'via' */
907 amb 542
908 amb 646 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
909 amb 542
910 amb 742 while(segmentx)
911 amb 548 {
912 amb 645 if(segmentx->way==relationx.from)
913 amb 548 {
914 amb 806 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
915    
916 amb 551 if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
917 amb 742 {
918 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));
919 amb 742 deleted++;
920 amb 551 goto endloop;
921 amb 742 }
922 amb 548
923 amb 645 node_from=OtherNode(segmentx,relationx.via);
924 amb 806
925     if(IsOnewayFrom(segmentx,relationx.via))
926     oneway_from=1; /* not allowed */
927    
928 amb 1243 if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorcycle|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
929 amb 806 vehicles_from=0; /* not allowed */
930 amb 548 }
931    
932 amb 645 if(segmentx->way==relationx.to)
933 amb 548 {
934 amb 806 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
935    
936 amb 551 if(node_to!=NO_NODE) /* Only one segment can be on the 'to' way */
937 amb 742 {
938 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));
939 amb 742 deleted++;
940 amb 551 goto endloop;
941 amb 742 }
942 amb 548
943 amb 806 node_to=OtherNode(segmentx,relationx.via);
944 amb 670
945 amb 806 if(IsOnewayTo(segmentx,relationx.via))
946     oneway_to=1; /* not allowed */
947    
948 amb 1243 if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorcycle|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
949 amb 806 vehicles_to=0; /* not allowed */
950 amb 548 }
951    
952 amb 943 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via);
953 amb 548 }
954    
955 amb 812 if(node_from==NO_NODE)
956 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));
957 amb 812
958     if(node_to==NO_NODE)
959 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));
960 amb 812
961     if(oneway_from)
962 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));
963 amb 812
964     if(oneway_to)
965 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));
966 amb 812
967     if(!vehicles_from)
968 amb 1313 logerror("Turn Relation %"Prelation_t" is not needed because the 'from' way does not allow vehicles.\n",logerror_relation(relationx.id));
969 amb 812
970     if(!vehicles_to)
971 amb 1313 logerror("Turn Relation %"Prelation_t" is not needed because the 'to' way does not allow vehicles.\n",logerror_relation(relationx.id));
972 amb 812
973 amb 806 if(oneway_from || oneway_to || !vehicles_from || !vehicles_to || node_from==NO_NODE || node_to==NO_NODE)
974 amb 742 {
975     deleted++;
976 amb 548 goto endloop;
977 amb 742 }
978 amb 548
979 amb 551 /* Write the results */
980 amb 548
981 amb 645 relationx.from=node_from;
982     relationx.to =node_to;
983 amb 548
984 amb 1163 WriteFile(trfd,&relationx,sizeof(TurnRelX));
985 amb 548
986 amb 559 total++;
987 amb 551 }
988     else
989     {
990 amb 806 index_t node_from=NO_NODE,node_to=NO_NODE,node_other[MAX_SEG_PER_NODE];
991     int nnodes_other=0,i;
992     int oneway_from=0,vehicles_from=1;
993 amb 548
994 amb 551 /* Find the segments that join the node 'via' */
995 amb 548
996 amb 646 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
997 amb 548
998 amb 742 while(segmentx)
999 amb 551 {
1000 amb 645 if(segmentx->way==relationx.from)
1001 amb 551 {
1002 amb 806 WayX *wayx=LookupWayX(waysx,segmentx->way,1);
1003    
1004 amb 551 if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */
1005 amb 742 {
1006 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));
1007 amb 742 deleted++;
1008 amb 548 goto endloop;
1009 amb 742 }
1010 amb 548
1011 amb 645 node_from=OtherNode(segmentx,relationx.via);
1012 amb 806
1013     if(IsOnewayFrom(segmentx,relationx.via))
1014     oneway_from=1; /* not allowed */
1015    
1016 amb 1243 if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorcycle|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
1017 amb 806 vehicles_from=0; /* not allowed */
1018 amb 548 }
1019 amb 551
1020 amb 806 if(segmentx->way==relationx.to)
1021 amb 551 {
1022 amb 806 if(node_to!=NO_NODE) /* Only one segment can be on the 'to' way */
1023     {
1024 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));
1025 amb 806 deleted++;
1026     goto endloop;
1027     }
1028 amb 551
1029 amb 806 node_to=OtherNode(segmentx,relationx.via);
1030     }
1031 amb 670
1032 amb 806 if(segmentx->way!=relationx.from && segmentx->way!=relationx.to)
1033     {
1034     WayX *wayx=LookupWayX(waysx,segmentx->way,1);
1035    
1036     if(IsOnewayTo(segmentx,relationx.via))
1037     ; /* not allowed */
1038 amb 1243 else if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorcycle|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV)))
1039 amb 806 ; /* not allowed */
1040     else
1041 amb 812 {
1042 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. */
1043 amb 812
1044 amb 806 node_other[nnodes_other++]=OtherNode(segmentx,relationx.via);
1045 amb 812 }
1046 amb 551 }
1047    
1048 amb 943 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via);
1049 amb 548 }
1050    
1051 amb 812 if(node_from==NO_NODE)
1052 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));
1053 amb 812
1054     if(node_to==NO_NODE)
1055 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));
1056 amb 812
1057     if(nnodes_other==0)
1058 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));
1059 amb 812
1060     if(oneway_from)
1061 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));
1062 amb 812
1063     if(!vehicles_from)
1064 amb 1313 logerror("Turn Relation %"Prelation_t" is not needed because the 'from' way does not allow vehicles.\n",logerror_relation(relationx.id));
1065 amb 812
1066 amb 806 if(oneway_from || !vehicles_from || node_from==NO_NODE || node_to==NO_NODE || nnodes_other==0)
1067 amb 742 {
1068     deleted++;
1069 amb 548 goto endloop;
1070 amb 742 }
1071 amb 548
1072     /* Write the results */
1073    
1074 amb 806 for(i=0;i<nnodes_other;i++)
1075 amb 551 {
1076 amb 645 relationx.from=node_from;
1077 amb 806 relationx.to =node_other[i];
1078 amb 548
1079 amb 1163 WriteFile(trfd,&relationx,sizeof(TurnRelX));
1080 amb 548
1081 amb 559 total++;
1082 amb 551 }
1083 amb 615 }
1084 amb 560
1085 amb 615 /* Force super nodes on via node and adjacent nodes */
1086    
1087     nodex=LookupNodeX(nodesx,relationx.via,1);
1088     nodex->flags|=NODE_TURNRSTRCT;
1089 amb 942 PutBackNodeX(nodesx,nodex);
1090 amb 615
1091 amb 646 segmentx=FirstSegmentX(segmentsx,relationx.via,1);
1092 amb 615
1093 amb 742 while(segmentx)
1094 amb 615 {
1095 amb 645 index_t othernode=OtherNode(segmentx,relationx.via);
1096 amb 615
1097     nodex=LookupNodeX(nodesx,othernode,1);
1098 amb 597 nodex->flags|=NODE_TURNRSTRCT2;
1099 amb 942 PutBackNodeX(nodesx,nodex);
1100 amb 597
1101 amb 943 segmentx=NextSegmentX(segmentsx,segmentx,relationx.via);
1102 amb 548 }
1103    
1104 amb 1353 endloop:
1105    
1106     if(!((i+1)%1000))
1107     printf_middle("Processing Turn Relations: Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,i+1,deleted,total-relationsx->trnumber+deleted);
1108 amb 542 }
1109    
1110 amb 555 /* Close the files */
1111 amb 542
1112 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
1113 amb 542 CloseFile(trfd);
1114    
1115 amb 1353 /* Free the now-unneeded indexes */
1116    
1117     free(nodesx->idata);
1118     nodesx->idata=NULL;
1119    
1120     free(waysx->idata);
1121     waysx->idata=NULL;
1122    
1123 amb 555 /* Unmap from memory / close the files */
1124 amb 542
1125 amb 548 #if !SLIM
1126 amb 1122 nodesx->data=UnmapFile(nodesx->data);
1127     segmentsx->data=UnmapFile(segmentsx->data);
1128     waysx->data=UnmapFile(waysx->data);
1129 amb 555 #else
1130 amb 612 nodesx->fd=CloseFile(nodesx->fd);
1131     segmentsx->fd=CloseFile(segmentsx->fd);
1132 amb 806 waysx->fd=CloseFile(waysx->fd);
1133 amb 548 #endif
1134    
1135 amb 542 /* Print the final message */
1136    
1137 amb 1353 printf_last("Processed Turn Relations: Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,total,deleted,total-relationsx->trnumber+deleted);
1138 amb 559
1139     relationsx->trnumber=total;
1140 amb 542 }
1141    
1142    
1143     /*++++++++++++++++++++++++++++++++++++++
1144 amb 1098 Remove pruned turn relations and update the node indexes after pruning nodes.
1145 amb 542
1146 amb 681 RelationsX *relationsx The set of relations to modify.
1147 amb 542
1148 amb 665 NodesX *nodesx The set of nodes to use.
1149 amb 1098 ++++++++++++++++++++++++++++++++++++++*/
1150 amb 665
1151 amb 1098 void RemovePrunedTurnRelations(RelationsX *relationsx,NodesX *nodesx)
1152     {
1153 amb 1163 TurnRelX relationx;
1154 amb 1098 index_t total=0,pruned=0,notpruned=0;
1155     int trfd;
1156    
1157 amb 1208 if(relationsx->trnumber==0)
1158     return;
1159    
1160 amb 1098 /* Print the start message */
1161    
1162     printf_first("Deleting Pruned Turn Relations: Relations=0 Pruned=0");
1163    
1164     /* Re-open the file read-only and a new file writeable */
1165    
1166 amb 1120 relationsx->trfd=ReOpenFile(relationsx->trfilename_tmp);
1167 amb 1098
1168 amb 1120 DeleteFile(relationsx->trfilename_tmp);
1169 amb 1098
1170 amb 1120 trfd=OpenFileNew(relationsx->trfilename_tmp);
1171 amb 1098
1172     /* Process all of the relations */
1173    
1174 amb 1163 while(!ReadFile(relationsx->trfd,&relationx,sizeof(TurnRelX)))
1175 amb 1098 {
1176     relationx.from=nodesx->pdata[relationx.from];
1177     relationx.via =nodesx->pdata[relationx.via];
1178     relationx.to =nodesx->pdata[relationx.to];
1179    
1180     if(relationx.from==NO_NODE || relationx.via==NO_NODE || relationx.to==NO_NODE)
1181     pruned++;
1182     else
1183     {
1184 amb 1163 WriteFile(trfd,&relationx,sizeof(TurnRelX));
1185 amb 1098
1186     notpruned++;
1187     }
1188    
1189     total++;
1190    
1191     if(!(total%1000))
1192     printf_middle("Deleting Pruned Turn Relations: Relations=%"Pindex_t" Pruned=%"Pindex_t,total,pruned);
1193     }
1194    
1195     relationsx->trnumber=notpruned;
1196    
1197     /* Close the files */
1198    
1199     relationsx->trfd=CloseFile(relationsx->trfd);
1200     CloseFile(trfd);
1201    
1202     /* Print the final message */
1203    
1204     printf_last("Deleted Pruned Turn Relations: Relations=%"Pindex_t" Pruned=%"Pindex_t,total,pruned);
1205     }
1206    
1207    
1208     /*++++++++++++++++++++++++++++++++++++++
1209 amb 1108 Sort the turn relations geographically after updating the node indexes.
1210 amb 1098
1211     RelationsX *relationsx The set of relations to modify.
1212    
1213     NodesX *nodesx The set of nodes to use.
1214    
1215 amb 680 SegmentsX *segmentsx The set of segments to use.
1216 amb 542 ++++++++++++++++++++++++++++++++++++++*/
1217    
1218 amb 1108 void SortTurnRelationListGeographically(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx)
1219 amb 542 {
1220     int trfd;
1221    
1222 amb 1208 if(segmentsx->number==0)
1223     return;
1224    
1225 amb 542 /* Print the start message */
1226    
1227 amb 1108 printf_first("Sorting Turn Relations Geographically");
1228 amb 542
1229 amb 599 /* Map into memory / open the files */
1230    
1231     #if !SLIM
1232 amb 1120 segmentsx->data=MapFile(segmentsx->filename_tmp);
1233 amb 599 #else
1234 amb 1120 segmentsx->fd=ReOpenFile(segmentsx->filename_tmp);
1235 amb 1297
1236     InvalidateSegmentXCache(segmentsx->cache);
1237 amb 599 #endif
1238    
1239 amb 555 /* Re-open the file read-only and a new file writeable */
1240 amb 542
1241 amb 1120 relationsx->trfd=ReOpenFile(relationsx->trfilename_tmp);
1242 amb 555
1243 amb 1120 DeleteFile(relationsx->trfilename_tmp);
1244 amb 542
1245 amb 1120 trfd=OpenFileNew(relationsx->trfilename_tmp);
1246 amb 542
1247 amb 1108 /* Update the segments with geographically sorted node indexes and sort them */
1248 amb 542
1249 amb 1108 sortnodesx=nodesx;
1250     sortsegmentsx=segmentsx;
1251 amb 542
1252 amb 1163 filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRelX),(int (*)(void*,index_t))geographically_index,
1253     (int (*)(const void*,const void*))sort_by_via,
1254     NULL);
1255 amb 542
1256 amb 555 /* Close the files */
1257 amb 542
1258 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
1259 amb 542 CloseFile(trfd);
1260    
1261 amb 599 /* Unmap from memory / close the files */
1262    
1263     #if !SLIM
1264 amb 1122 segmentsx->data=UnmapFile(segmentsx->data);
1265 amb 599 #else
1266 amb 612 segmentsx->fd=CloseFile(segmentsx->fd);
1267 amb 599 #endif
1268    
1269 amb 542 /* Print the final message */
1270    
1271 amb 1110 printf_last("Sorted Turn Relations Geographically: Turn Relations=%"Pindex_t,relationsx->trnumber);
1272 amb 645 }
1273    
1274    
1275     /*++++++++++++++++++++++++++++++++++++++
1276 amb 1108 Update the turn relation indexes.
1277    
1278     int geographically_index Return 1 if the value is to be kept, otherwise 0.
1279    
1280 amb 1163 TurnRelX *relationx The extended turn relation.
1281 amb 1108
1282 amb 1112 index_t index The number of unsorted turn relations that have been read from the input file.
1283 amb 1108 ++++++++++++++++++++++++++++++++++++++*/
1284    
1285 amb 1163 static int geographically_index(TurnRelX *relationx,index_t index)
1286 amb 1108 {
1287     SegmentX *segmentx;
1288     index_t from_node,via_node,to_node;
1289    
1290     from_node=sortnodesx->gdata[relationx->from];
1291     via_node =sortnodesx->gdata[relationx->via];
1292     to_node =sortnodesx->gdata[relationx->to];
1293    
1294     segmentx=FirstSegmentX(sortsegmentsx,via_node,1);
1295    
1296     do
1297     {
1298     if(OtherNode(segmentx,via_node)==from_node)
1299     relationx->from=IndexSegmentX(sortsegmentsx,segmentx);
1300    
1301     if(OtherNode(segmentx,via_node)==to_node)
1302     relationx->to=IndexSegmentX(sortsegmentsx,segmentx);
1303    
1304     segmentx=NextSegmentX(sortsegmentsx,segmentx,via_node);
1305     }
1306     while(segmentx);
1307    
1308     relationx->via=via_node;
1309    
1310     return(1);
1311     }
1312    
1313    
1314     /*++++++++++++++++++++++++++++++++++++++
1315     Sort the turn restriction relations into via index order (then by from and to segments).
1316    
1317     int sort_by_via Returns the comparison of the via, from and to fields.
1318    
1319 amb 1163 TurnRelX *a The first extended relation.
1320 amb 1108
1321 amb 1163 TurnRelX *b The second extended relation.
1322 amb 1108 ++++++++++++++++++++++++++++++++++++++*/
1323    
1324 amb 1163 static int sort_by_via(TurnRelX *a,TurnRelX *b)
1325 amb 1108 {
1326     index_t a_id=a->via;
1327     index_t b_id=b->via;
1328    
1329     if(a_id<b_id)
1330     return(-1);
1331     else if(a_id>b_id)
1332     return(1);
1333     else
1334     {
1335     index_t a_id=a->from;
1336     index_t b_id=b->from;
1337    
1338     if(a_id<b_id)
1339     return(-1);
1340     else if(a_id>b_id)
1341     return(1);
1342     else
1343     {
1344     index_t a_id=a->to;
1345     index_t b_id=b->to;
1346    
1347     if(a_id<b_id)
1348     return(-1);
1349     else if(a_id>b_id)
1350     return(1);
1351     else
1352 amb 1118 return(FILESORT_PRESERVE_ORDER(a,b));
1353 amb 1108 }
1354     }
1355     }
1356    
1357    
1358     /*++++++++++++++++++++++++++++++++++++++
1359 amb 542 Save the relation list to a file.
1360    
1361     RelationsX* relationsx The set of relations to save.
1362    
1363     const char *filename The name of the file to save.
1364     ++++++++++++++++++++++++++++++++++++++*/
1365    
1366     void SaveRelationList(RelationsX* relationsx,const char *filename)
1367     {
1368     index_t i;
1369     int fd;
1370     RelationsFile relationsfile={0};
1371    
1372     /* Print the start message */
1373    
1374     printf_first("Writing Relations: Turn Relations=0");
1375    
1376 amb 559 /* Re-open the file read-only */
1377 amb 555
1378 amb 1120 relationsx->trfd=ReOpenFile(relationsx->trfilename_tmp);
1379 amb 555
1380 amb 542 /* Write out the relations data */
1381    
1382     fd=OpenFileNew(filename);
1383    
1384     SeekFile(fd,sizeof(RelationsFile));
1385    
1386     for(i=0;i<relationsx->trnumber;i++)
1387     {
1388 amb 1163 TurnRelX relationx;
1389 amb 944 TurnRelation relation={0};
1390 amb 542
1391 amb 1163 ReadFile(relationsx->trfd,&relationx,sizeof(TurnRelX));
1392 amb 542
1393 amb 551 relation.from=relationx.from;
1394     relation.via=relationx.via;
1395     relation.to=relationx.to;
1396     relation.except=relationx.except;
1397 amb 542
1398 amb 551 WriteFile(fd,&relation,sizeof(TurnRelation));
1399    
1400 amb 757 if(!((i+1)%1000))
1401 amb 790 printf_middle("Writing Relations: Turn Relations=%"Pindex_t,i+1);
1402 amb 542 }
1403    
1404     /* Write out the header structure */
1405    
1406     relationsfile.trnumber=relationsx->trnumber;
1407    
1408     SeekFile(fd,0);
1409     WriteFile(fd,&relationsfile,sizeof(RelationsFile));
1410    
1411     CloseFile(fd);
1412    
1413     /* Close the file */
1414    
1415 amb 612 relationsx->trfd=CloseFile(relationsx->trfd);
1416 amb 542
1417     /* Print the final message */
1418    
1419 amb 790 printf_last("Wrote Relations: Turn Relations=%"Pindex_t,relationsx->trnumber);
1420 amb 542 }