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 2199 - (hide annotations) (download) (as text)
Sun Apr 6 14:20:12 2025 UTC (3 days, 4 hours ago) by amb
File MIME type: text/x-csrc
File size: 44214 byte(s)
Revert part of r2189 and add extra checks on the sizes of node_t, way_t and relation_t with respect to index_t.

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