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