Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/relationsx.c
Parent Directory
|
Revision Log
Revision 1118 -
(hide annotations)
(download)
(as text)
Wed Oct 31 19:01:40 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 33677 byte(s)
Wed Oct 31 19:01:40 2012 UTC (12 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 33677 byte(s)
Add the option for the sorting function to preserve the input order of equivalent items on the output. Use this feature in sorting so that slim mode and normal mode give the same results.
1 | amb | 496 | /*************************************** |
2 | Extended Relation data type functions. | ||
3 | |||
4 | Part of the Routino routing software. | ||
5 | ******************/ /****************** | ||
6 | amb | 948 | This file Copyright 2010-2012 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 <assert.h> | ||
24 | #include <stdlib.h> | ||
25 | #include <string.h> | ||
26 | |||
27 | amb | 542 | #include "types.h" |
28 | amb | 955 | #include "segments.h" |
29 | amb | 542 | #include "relations.h" |
30 | |||
31 | #include "nodesx.h" | ||
32 | #include "segmentsx.h" | ||
33 | amb | 496 | #include "waysx.h" |
34 | #include "relationsx.h" | ||
35 | |||
36 | #include "files.h" | ||
37 | amb | 519 | #include "logging.h" |
38 | amb | 532 | #include "sorting.h" |
39 | amb | 496 | |
40 | |||
41 | amb | 1108 | /* Global variables */ |
42 | |||
43 | /*+ The command line '--tmpdir' option or its default value. +*/ | ||
44 | extern char *option_tmpdirname; | ||
45 | |||
46 | amb | 680 | /* Local functions */ |
47 | amb | 540 | |
48 | amb | 559 | static int sort_by_id(TurnRestrictRelX *a,TurnRestrictRelX *b); |
49 | amb | 540 | static int deduplicate_by_id(TurnRestrictRelX *relationx,index_t index); |
50 | |||
51 | amb | 1108 | static int geographically_index(TurnRestrictRelX *relationx,index_t index); |
52 | amb | 559 | static int sort_by_via(TurnRestrictRelX *a,TurnRestrictRelX *b); |
53 | amb | 540 | |
54 | amb | 1108 | /* Local variables */ |
55 | amb | 559 | |
56 | amb | 1108 | /*+ Temporary file-local variables for use by the sort functions. +*/ |
57 | static SegmentsX *sortsegmentsx; | ||
58 | static NodesX *sortnodesx; | ||
59 | amb | 496 | |
60 | |||
61 | /*++++++++++++++++++++++++++++++++++++++ | ||
62 | Allocate a new relation list (create a new file or open an existing one). | ||
63 | |||
64 | RelationsX *NewRelationList Returns the relation list. | ||
65 | |||
66 | int append Set to 1 if the file is to be opened for appending (now or later). | ||
67 | ++++++++++++++++++++++++++++++++++++++*/ | ||
68 | |||
69 | RelationsX *NewRelationList(int append) | ||
70 | { | ||
71 | RelationsX *relationsx; | ||
72 | |||
73 | relationsx=(RelationsX*)calloc(1,sizeof(RelationsX)); | ||
74 | |||
75 | assert(relationsx); /* Check calloc() worked */ | ||
76 | |||
77 | amb | 540 | |
78 | amb | 559 | /* Route Relations */ |
79 | |||
80 | amb | 496 | relationsx->rfilename=(char*)malloc(strlen(option_tmpdirname)+32); |
81 | |||
82 | if(append) | ||
83 | sprintf(relationsx->rfilename,"%s/relationsx.route.input.tmp",option_tmpdirname); | ||
84 | else | ||
85 | amb | 788 | sprintf(relationsx->rfilename,"%s/relationsx.route.%p.tmp",option_tmpdirname,(void*)relationsx); |
86 | amb | 496 | |
87 | if(append) | ||
88 | { | ||
89 | off_t size,position=0; | ||
90 | |||
91 | amb | 505 | relationsx->rfd=OpenFileAppend(relationsx->rfilename); |
92 | amb | 496 | |
93 | size=SizeFile(relationsx->rfilename); | ||
94 | |||
95 | while(position<size) | ||
96 | { | ||
97 | FILESORT_VARINT relationsize; | ||
98 | |||
99 | amb | 887 | SeekReadFile(relationsx->rfd,&relationsize,FILESORT_VARSIZE,position); |
100 | amb | 496 | |
101 | amb | 650 | relationsx->rnumber++; |
102 | amb | 496 | position+=relationsize+FILESORT_VARSIZE; |
103 | } | ||
104 | |||
105 | SeekFile(relationsx->rfd,size); | ||
106 | } | ||
107 | else | ||
108 | amb | 505 | relationsx->rfd=OpenFileNew(relationsx->rfilename); |
109 | amb | 496 | |
110 | amb | 540 | |
111 | amb | 559 | /* Turn Restriction Relations */ |
112 | |||
113 | amb | 540 | relationsx->trfilename=(char*)malloc(strlen(option_tmpdirname)+32); |
114 | |||
115 | if(append) | ||
116 | sprintf(relationsx->trfilename,"%s/relationsx.turn.input.tmp",option_tmpdirname); | ||
117 | else | ||
118 | amb | 788 | sprintf(relationsx->trfilename,"%s/relationsx.turn.%p.tmp",option_tmpdirname,(void*)relationsx); |
119 | amb | 540 | |
120 | if(append) | ||
121 | { | ||
122 | off_t size; | ||
123 | |||
124 | relationsx->trfd=OpenFileAppend(relationsx->trfilename); | ||
125 | |||
126 | size=SizeFile(relationsx->trfilename); | ||
127 | |||
128 | amb | 650 | relationsx->trnumber=size/sizeof(TurnRestrictRelX); |
129 | amb | 540 | } |
130 | else | ||
131 | relationsx->trfd=OpenFileNew(relationsx->trfilename); | ||
132 | |||
133 | amb | 496 | return(relationsx); |
134 | } | ||
135 | |||
136 | |||
137 | /*++++++++++++++++++++++++++++++++++++++ | ||
138 | Free a relation list. | ||
139 | |||
140 | amb | 681 | RelationsX *relationsx The set of relations to be freed. |
141 | amb | 496 | |
142 | amb | 680 | int keep Set to 1 if the file is to be kept (for appending later). |
143 | amb | 496 | ++++++++++++++++++++++++++++++++++++++*/ |
144 | |||
145 | void FreeRelationList(RelationsX *relationsx,int keep) | ||
146 | { | ||
147 | amb | 540 | /* Route relations */ |
148 | |||
149 | amb | 496 | if(!keep) |
150 | DeleteFile(relationsx->rfilename); | ||
151 | |||
152 | free(relationsx->rfilename); | ||
153 | |||
154 | amb | 559 | |
155 | amb | 540 | /* Turn Restriction relations */ |
156 | |||
157 | if(!keep) | ||
158 | DeleteFile(relationsx->trfilename); | ||
159 | |||
160 | free(relationsx->trfilename); | ||
161 | |||
162 | amb | 496 | free(relationsx); |
163 | } | ||
164 | |||
165 | |||
166 | /*++++++++++++++++++++++++++++++++++++++ | ||
167 | Append a single relation to an unsorted route relation list. | ||
168 | |||
169 | RelationsX* relationsx The set of relations to process. | ||
170 | |||
171 | relation_t id The ID of the relation. | ||
172 | |||
173 | amb | 529 | transports_t routes The types of routes that this relation is for. |
174 | amb | 496 | |
175 | way_t *ways The array of ways that are members of the relation. | ||
176 | |||
177 | int nways The number of ways that are members of the relation. | ||
178 | |||
179 | relation_t *relations The array of relations that are members of the relation. | ||
180 | |||
181 | int nrelations The number of relations that are members of the relation. | ||
182 | ++++++++++++++++++++++++++++++++++++++*/ | ||
183 | |||
184 | amb | 540 | void AppendRouteRelation(RelationsX* relationsx,relation_t id, |
185 | transports_t routes, | ||
186 | amb | 496 | way_t *ways,int nways, |
187 | relation_t *relations,int nrelations) | ||
188 | { | ||
189 | RouteRelX relationx; | ||
190 | amb | 505 | FILESORT_VARINT size; |
191 | amb | 805 | way_t noway=NO_WAY; |
192 | relation_t norelation=NO_RELATION; | ||
193 | amb | 496 | |
194 | relationx.id=id; | ||
195 | relationx.routes=routes; | ||
196 | |||
197 | size=sizeof(RouteRelX)+(nways+1)*sizeof(way_t)+(nrelations+1)*sizeof(relation_t); | ||
198 | |||
199 | amb | 505 | WriteFile(relationsx->rfd,&size,FILESORT_VARSIZE); |
200 | amb | 496 | WriteFile(relationsx->rfd,&relationx,sizeof(RouteRelX)); |
201 | |||
202 | amb | 805 | WriteFile(relationsx->rfd,ways ,nways*sizeof(way_t)); |
203 | WriteFile(relationsx->rfd,&noway, sizeof(way_t)); | ||
204 | amb | 496 | |
205 | amb | 805 | WriteFile(relationsx->rfd,relations ,nrelations*sizeof(relation_t)); |
206 | WriteFile(relationsx->rfd,&norelation, sizeof(relation_t)); | ||
207 | amb | 496 | |
208 | amb | 650 | relationsx->rnumber++; |
209 | amb | 496 | |
210 | amb | 1065 | assert(relationsx->rnumber!=0); /* Zero marks the high-water mark for relations. */ |
211 | amb | 496 | } |
212 | |||
213 | |||
214 | /*++++++++++++++++++++++++++++++++++++++ | ||
215 | amb | 540 | Append a single relation to an unsorted turn restriction relation list. |
216 | |||
217 | RelationsX* relationsx The set of relations to process. | ||
218 | |||
219 | relation_t id The ID of the relation. | ||
220 | |||
221 | way_t from The way that the turn restriction starts from. | ||
222 | |||
223 | way_t to The way that the restriction finished on. | ||
224 | |||
225 | node_t via The node that the turn restriction passes through. | ||
226 | |||
227 | TurnRestriction restriction The type of restriction. | ||
228 | |||
229 | transports_t except The set of transports allowed to bypass the restriction. | ||
230 | ++++++++++++++++++++++++++++++++++++++*/ | ||
231 | |||
232 | void AppendTurnRestrictRelation(RelationsX* relationsx,relation_t id, | ||
233 | way_t from,way_t to,node_t via, | ||
234 | TurnRestriction restriction,transports_t except) | ||
235 | { | ||
236 | amb | 951 | TurnRestrictRelX relationx={0}; |
237 | amb | 540 | |
238 | relationx.id=id; | ||
239 | relationx.from=from; | ||
240 | relationx.to=to; | ||
241 | relationx.via=via; | ||
242 | amb | 786 | relationx.restriction=restriction; |
243 | amb | 540 | relationx.except=except; |
244 | |||
245 | WriteFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX)); | ||
246 | |||
247 | amb | 650 | relationsx->trnumber++; |
248 | amb | 540 | |
249 | amb | 1065 | assert(relationsx->trnumber!=0); /* Zero marks the high-water mark for relations. */ |
250 | amb | 540 | } |
251 | |||
252 | |||
253 | /*++++++++++++++++++++++++++++++++++++++ | ||
254 | amb | 496 | Sort the list of relations. |
255 | |||
256 | RelationsX* relationsx The set of relations to process. | ||
257 | ++++++++++++++++++++++++++++++++++++++*/ | ||
258 | |||
259 | void SortRelationList(RelationsX* relationsx) | ||
260 | { | ||
261 | amb | 559 | /* Close the files (finished appending) */ |
262 | amb | 540 | |
263 | amb | 612 | relationsx->rfd=CloseFile(relationsx->rfd); |
264 | amb | 542 | |
265 | amb | 612 | relationsx->trfd=CloseFile(relationsx->trfd); |
266 | amb | 540 | |
267 | amb | 559 | |
268 | /* Route Relations */ | ||
269 | |||
270 | |||
271 | /* Turn Restriction Relations. */ | ||
272 | |||
273 | amb | 650 | if(relationsx->trnumber) |
274 | amb | 551 | { |
275 | amb | 650 | index_t trxnumber; |
276 | amb | 551 | int trfd; |
277 | amb | 540 | |
278 | amb | 551 | /* Print the start message */ |
279 | amb | 540 | |
280 | amb | 895 | printf_first("Sorting Turn Relations"); |
281 | amb | 540 | |
282 | amb | 555 | /* Re-open the file read-only and a new file writeable */ |
283 | |||
284 | relationsx->trfd=ReOpenFile(relationsx->trfilename); | ||
285 | |||
286 | amb | 551 | DeleteFile(relationsx->trfilename); |
287 | amb | 540 | |
288 | amb | 551 | trfd=OpenFileNew(relationsx->trfilename); |
289 | amb | 540 | |
290 | amb | 551 | /* Sort the relations */ |
291 | amb | 540 | |
292 | amb | 650 | trxnumber=relationsx->trnumber; |
293 | |||
294 | amb | 1106 | relationsx->trnumber=filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRestrictRelX),NULL, |
295 | (int (*)(const void*,const void*))sort_by_id, | ||
296 | (int (*)(void*,index_t))deduplicate_by_id); | ||
297 | amb | 540 | |
298 | amb | 555 | /* Close the files */ |
299 | amb | 540 | |
300 | amb | 612 | relationsx->trfd=CloseFile(relationsx->trfd); |
301 | amb | 551 | CloseFile(trfd); |
302 | amb | 540 | |
303 | amb | 551 | /* Print the final message */ |
304 | amb | 540 | |
305 | amb | 895 | printf_last("Sorted Turn Relations: Relations=%"Pindex_t" Duplicates=%"Pindex_t,trxnumber,trxnumber-relationsx->trnumber); |
306 | amb | 551 | } |
307 | amb | 496 | } |
308 | |||
309 | |||
310 | /*++++++++++++++++++++++++++++++++++++++ | ||
311 | amb | 559 | Sort the turn restriction relations into id order. |
312 | amb | 540 | |
313 | amb | 559 | int sort_by_id Returns the comparison of the id fields. |
314 | amb | 540 | |
315 | TurnRestrictRelX *a The first extended relation. | ||
316 | |||
317 | TurnRestrictRelX *b The second extended relation. | ||
318 | ++++++++++++++++++++++++++++++++++++++*/ | ||
319 | |||
320 | amb | 559 | static int sort_by_id(TurnRestrictRelX *a,TurnRestrictRelX *b) |
321 | amb | 540 | { |
322 | amb | 559 | relation_t a_id=a->id; |
323 | relation_t b_id=b->id; | ||
324 | amb | 540 | |
325 | if(a_id<b_id) | ||
326 | return(-1); | ||
327 | else if(a_id>b_id) | ||
328 | return(1); | ||
329 | else | ||
330 | amb | 1118 | return(FILESORT_PRESERVE_ORDER(a,b)); |
331 | amb | 540 | } |
332 | |||
333 | |||
334 | /*++++++++++++++++++++++++++++++++++++++ | ||
335 | Deduplicate the extended relations using the id after sorting. | ||
336 | |||
337 | amb | 680 | int deduplicate_by_id Return 1 if the value is to be kept, otherwise 0. |
338 | amb | 540 | |
339 | TurnRestrictRelX *relationx The extended relation. | ||
340 | |||
341 | amb | 1106 | index_t index The number of sorted relations that have already been written to the output file. |
342 | amb | 540 | ++++++++++++++++++++++++++++++++++++++*/ |
343 | |||
344 | static int deduplicate_by_id(TurnRestrictRelX *relationx,index_t index) | ||
345 | { | ||
346 | static relation_t previd; | ||
347 | |||
348 | if(index==0 || relationx->id!=previd) | ||
349 | { | ||
350 | previd=relationx->id; | ||
351 | |||
352 | return(1); | ||
353 | } | ||
354 | amb | 812 | else |
355 | { | ||
356 | logerror("Relation %"Prelation_t" is duplicated.\n",relationx->id); | ||
357 | amb | 540 | |
358 | amb | 812 | return(0); |
359 | } | ||
360 | amb | 540 | } |
361 | |||
362 | |||
363 | /*++++++++++++++++++++++++++++++++++++++ | ||
364 | amb | 496 | Process the route relations and apply the information to the ways. |
365 | |||
366 | amb | 681 | RelationsX *relationsx The set of relations to use. |
367 | amb | 496 | |
368 | amb | 681 | WaysX *waysx The set of ways to modify. |
369 | amb | 496 | ++++++++++++++++++++++++++++++++++++++*/ |
370 | |||
371 | void ProcessRouteRelations(RelationsX *relationsx,WaysX *waysx) | ||
372 | { | ||
373 | amb | 505 | RouteRelX *unmatched=NULL,*lastunmatched=NULL; |
374 | amb | 761 | int nunmatched=0,lastnunmatched=0,iteration=1; |
375 | amb | 496 | |
376 | amb | 510 | if(waysx->number==0) |
377 | amb | 508 | return; |
378 | |||
379 | amb | 555 | /* Map into memory / open the files */ |
380 | amb | 496 | |
381 | amb | 505 | #if !SLIM |
382 | amb | 651 | waysx->data=MapFileWriteable(waysx->filename); |
383 | amb | 555 | #else |
384 | waysx->fd=ReOpenFileWriteable(waysx->filename); | ||
385 | amb | 505 | #endif |
386 | amb | 496 | |
387 | amb | 555 | /* Re-open the file read-only */ |
388 | amb | 548 | |
389 | relationsx->rfd=ReOpenFile(relationsx->rfilename); | ||
390 | |||
391 | amb | 542 | /* Read through the file. */ |
392 | amb | 496 | |
393 | amb | 505 | do |
394 | amb | 496 | { |
395 | amb | 522 | int ways=0,relations=0; |
396 | amb | 780 | index_t i; |
397 | amb | 522 | |
398 | amb | 505 | SeekFile(relationsx->rfd,0); |
399 | amb | 496 | |
400 | amb | 505 | /* Print the start message */ |
401 | amb | 496 | |
402 | amb | 761 | printf_first("Processing Route Relations (%d): Relations=0 Modified Ways=0",iteration); |
403 | amb | 496 | |
404 | amb | 650 | for(i=0;i<relationsx->rnumber;i++) |
405 | amb | 496 | { |
406 | amb | 505 | FILESORT_VARINT size; |
407 | RouteRelX relationx; | ||
408 | way_t wayid; | ||
409 | relation_t relationid; | ||
410 | amb | 529 | transports_t routes=Transports_None; |
411 | amb | 496 | |
412 | amb | 505 | /* Read each route relation */ |
413 | amb | 496 | |
414 | amb | 505 | ReadFile(relationsx->rfd,&size,FILESORT_VARSIZE); |
415 | ReadFile(relationsx->rfd,&relationx,sizeof(RouteRelX)); | ||
416 | amb | 496 | |
417 | amb | 505 | /* Decide what type of route it is */ |
418 | amb | 496 | |
419 | amb | 761 | if(iteration==1) |
420 | amb | 522 | { |
421 | relations++; | ||
422 | amb | 505 | routes=relationx.routes; |
423 | amb | 522 | } |
424 | amb | 505 | else |
425 | amb | 506 | { |
426 | amb | 522 | int j; |
427 | |||
428 | for(j=0;j<lastnunmatched;j++) | ||
429 | if(lastunmatched[j].id==relationx.id) | ||
430 | { | ||
431 | relations++; | ||
432 | |||
433 | if((lastunmatched[j].routes|relationx.routes)==relationx.routes) | ||
434 | routes=0; /* Nothing new to add */ | ||
435 | else | ||
436 | amb | 506 | routes=lastunmatched[j].routes; |
437 | amb | 806 | |
438 | amb | 522 | break; |
439 | } | ||
440 | amb | 506 | } |
441 | amb | 496 | |
442 | amb | 505 | /* Loop through the ways */ |
443 | |||
444 | do | ||
445 | { | ||
446 | ReadFile(relationsx->rfd,&wayid,sizeof(way_t)); | ||
447 | |||
448 | /* Update the ways that are listed for the relation */ | ||
449 | |||
450 | amb | 805 | if(wayid==NO_WAY) |
451 | amb | 806 | continue; |
452 | |||
453 | if(routes) | ||
454 | amb | 505 | { |
455 | amb | 506 | index_t way=IndexWayX(waysx,wayid); |
456 | amb | 505 | |
457 | if(way!=NO_WAY) | ||
458 | { | ||
459 | WayX *wayx=LookupWayX(waysx,way,1); | ||
460 | |||
461 | amb | 529 | if(routes&Transports_Foot) |
462 | amb | 995 | { |
463 | amb | 1064 | if(!(wayx->way.allow&Transports_Foot)) |
464 | { | ||
465 | logerror("Route Relation %"Prelation_t" for Foot contains Way %"Pway_t" that does not allow Foot transport; overriding.\n",relationx.id,wayid); | ||
466 | wayx->way.allow|=Transports_Foot; | ||
467 | } | ||
468 | amb | 505 | wayx->way.props|=Properties_FootRoute; |
469 | amb | 995 | } |
470 | amb | 505 | |
471 | amb | 529 | if(routes&Transports_Bicycle) |
472 | amb | 995 | { |
473 | amb | 1064 | if(!(wayx->way.allow&Transports_Bicycle)) |
474 | { | ||
475 | logerror("Route Relation %"Prelation_t" for Bicycle contains Way %"Pway_t" that does not allow Bicycle transport; overriding.\n",relationx.id,wayid); | ||
476 | wayx->way.allow|=Transports_Bicycle; | ||
477 | } | ||
478 | amb | 505 | wayx->way.props|=Properties_BicycleRoute; |
479 | amb | 995 | } |
480 | amb | 505 | |
481 | amb | 942 | PutBackWayX(waysx,wayx); |
482 | amb | 522 | |
483 | ways++; | ||
484 | amb | 505 | } |
485 | amb | 812 | else |
486 | amb | 832 | logerror("Route Relation %"Prelation_t" contains Way %"Pway_t" but it does not exist in the Routino database.\n",relationx.id,wayid); |
487 | amb | 505 | } |
488 | } | ||
489 | amb | 805 | while(wayid!=NO_WAY); |
490 | amb | 505 | |
491 | /* Loop through the relations */ | ||
492 | |||
493 | do | ||
494 | { | ||
495 | ReadFile(relationsx->rfd,&relationid,sizeof(relation_t)); | ||
496 | |||
497 | /* Add the relations that are listed for this relation to the list for next time */ | ||
498 | |||
499 | amb | 805 | if(relationid==NO_RELATION) |
500 | amb | 806 | continue; |
501 | |||
502 | amb | 812 | if(relationid==relationx.id) |
503 | logerror("Relation %"Prelation_t" contains itself.\n",relationx.id); | ||
504 | else if(routes) | ||
505 | amb | 505 | { |
506 | if(nunmatched%256==0) | ||
507 | unmatched=(RouteRelX*)realloc((void*)unmatched,(nunmatched+256)*sizeof(RouteRelX)); | ||
508 | |||
509 | unmatched[nunmatched].id=relationid; | ||
510 | unmatched[nunmatched].routes=routes; | ||
511 | |||
512 | nunmatched++; | ||
513 | } | ||
514 | } | ||
515 | amb | 805 | while(relationid!=NO_RELATION); |
516 | amb | 505 | |
517 | amb | 757 | if(!((i+1)%1000)) |
518 | amb | 790 | printf_middle("Processing Route Relations (%d): Relations=%"Pindex_t" Modified Ways=%"Pindex_t,iteration,relations,ways); |
519 | amb | 496 | } |
520 | |||
521 | amb | 505 | if(lastunmatched) |
522 | free(lastunmatched); | ||
523 | |||
524 | lastunmatched=unmatched; | ||
525 | lastnunmatched=nunmatched; | ||
526 | |||
527 | unmatched=NULL; | ||
528 | nunmatched=0; | ||
529 | |||
530 | /* Print the final message */ | ||
531 | |||
532 | amb | 790 | printf_last("Processed Route Relations (%d): Relations=%"Pindex_t" Modified Ways=%"Pindex_t,iteration,relations,ways); |
533 | amb | 496 | } |
534 | amb | 812 | while(lastnunmatched && iteration++<8); |
535 | amb | 496 | |
536 | amb | 505 | if(lastunmatched) |
537 | free(lastunmatched); | ||
538 | |||
539 | amb | 555 | /* Close the file */ |
540 | |||
541 | amb | 612 | relationsx->rfd=CloseFile(relationsx->rfd); |
542 | amb | 496 | |
543 | amb | 555 | /* Unmap from memory / close the files */ |
544 | amb | 496 | |
545 | amb | 505 | #if !SLIM |
546 | amb | 651 | waysx->data=UnmapFile(waysx->filename); |
547 | amb | 555 | #else |
548 | amb | 612 | waysx->fd=CloseFile(waysx->fd); |
549 | amb | 511 | #endif |
550 | amb | 496 | } |
551 | amb | 542 | |
552 | |||
553 | /*++++++++++++++++++++++++++++++++++++++ | ||
554 | amb | 645 | Process the turn relations (first part) to update them with the node/way information. |
555 | amb | 542 | |
556 | amb | 681 | RelationsX *relationsx The set of relations to modify. |
557 | amb | 542 | |
558 | amb | 680 | NodesX *nodesx The set of nodes to use. |
559 | amb | 542 | |
560 | amb | 680 | WaysX *waysx The set of ways to use. |
561 | amb | 645 | ++++++++++++++++++++++++++++++++++++++*/ |
562 | |||
563 | void ProcessTurnRelations1(RelationsX *relationsx,NodesX *nodesx,WaysX *waysx) | ||
564 | { | ||
565 | amb | 780 | int trfd; |
566 | index_t i,deleted=0; | ||
567 | amb | 645 | |
568 | /* Print the start message */ | ||
569 | |||
570 | amb | 761 | printf_first("Processing Turn Relations (1): Relations=0"); |
571 | amb | 645 | |
572 | /* Re-open the file read-only and a new file writeable */ | ||
573 | |||
574 | relationsx->trfd=ReOpenFile(relationsx->trfilename); | ||
575 | |||
576 | DeleteFile(relationsx->trfilename); | ||
577 | |||
578 | trfd=OpenFileNew(relationsx->trfilename); | ||
579 | |||
580 | /* Process all of the relations */ | ||
581 | |||
582 | for(i=0;i<relationsx->trnumber;i++) | ||
583 | { | ||
584 | TurnRestrictRelX relationx; | ||
585 | amb | 812 | node_t via; |
586 | way_t from,to; | ||
587 | amb | 645 | |
588 | ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX)); | ||
589 | |||
590 | amb | 812 | via =IndexNodeX(nodesx,relationx.via); |
591 | from=IndexWayX(waysx,relationx.from); | ||
592 | to =IndexWayX(waysx,relationx.to); | ||
593 | amb | 645 | |
594 | amb | 812 | if(via==NO_NODE) |
595 | amb | 832 | logerror("Turn Relation %"Prelation_t" contains Node %"Pnode_t" but it does not exist in the Routino database.\n",relationx.id,relationx.via); |
596 | amb | 812 | |
597 | if(from==NO_WAY) | ||
598 | amb | 832 | logerror("Turn Relation %"Prelation_t" contains Way %"Pway_t" but it does not exist in the Routino database.\n",relationx.id,relationx.from); |
599 | amb | 812 | |
600 | if(to==NO_WAY) | ||
601 | amb | 832 | logerror("Turn Relation %"Prelation_t" contains Way %"Pway_t" but it does not exist in the Routino database.\n",relationx.id,relationx.to); |
602 | amb | 812 | |
603 | relationx.via =via; | ||
604 | relationx.from=from; | ||
605 | relationx.to =to; | ||
606 | |||
607 | amb | 756 | if(relationx.via==NO_NODE || relationx.from==NO_WAY || relationx.to==NO_WAY) |
608 | deleted++; | ||
609 | else | ||
610 | WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX)); | ||
611 | amb | 645 | |
612 | amb | 757 | if(!((i+1)%1000)) |
613 | amb | 1100 | printf_middle("Processing Turn Relations (1): Relations=%"Pindex_t" Deleted=%"Pindex_t,i+1,deleted); |
614 | amb | 645 | } |
615 | |||
616 | /* Close the files */ | ||
617 | |||
618 | relationsx->trfd=CloseFile(relationsx->trfd); | ||
619 | CloseFile(trfd); | ||
620 | |||
621 | /* Print the final message */ | ||
622 | |||
623 | amb | 1100 | printf_last("Processed Turn Relations (1): Relations=%"Pindex_t" Deleted=%"Pindex_t,relationsx->trnumber,deleted); |
624 | amb | 756 | |
625 | relationsx->trnumber-=deleted; | ||
626 | amb | 645 | } |
627 | |||
628 | |||
629 | /*++++++++++++++++++++++++++++++++++++++ | ||
630 | Process the turn relations (second part) to convert them to nodes. | ||
631 | |||
632 | amb | 681 | RelationsX *relationsx The set of relations to modify. |
633 | amb | 645 | |
634 | amb | 680 | NodesX *nodesx The set of nodes to use. |
635 | amb | 645 | |
636 | amb | 680 | SegmentsX *segmentsx The set of segments to use. |
637 | amb | 542 | |
638 | amb | 680 | WaysX *waysx The set of ways to use. |
639 | amb | 542 | ++++++++++++++++++++++++++++++++++++++*/ |
640 | |||
641 | amb | 645 | void ProcessTurnRelations2(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx) |
642 | amb | 542 | { |
643 | amb | 548 | TurnRestrictRelX relationx; |
644 | amb | 542 | int trfd; |
645 | amb | 780 | index_t total=0,deleted=0; |
646 | amb | 542 | |
647 | amb | 548 | if(nodesx->number==0 || segmentsx->number==0) |
648 | return; | ||
649 | |||
650 | amb | 542 | /* Print the start message */ |
651 | |||
652 | amb | 761 | printf_first("Processing Turn Relations (2): Relations=0"); |
653 | amb | 542 | |
654 | amb | 555 | /* Map into memory / open the files */ |
655 | amb | 548 | |
656 | #if !SLIM | ||
657 | amb | 651 | nodesx->data=MapFileWriteable(nodesx->filename); |
658 | segmentsx->data=MapFile(segmentsx->filename); | ||
659 | amb | 806 | waysx->data=MapFile(waysx->filename); |
660 | amb | 555 | #else |
661 | amb | 560 | nodesx->fd=ReOpenFileWriteable(nodesx->filename); |
662 | amb | 555 | segmentsx->fd=ReOpenFile(segmentsx->filename); |
663 | amb | 806 | waysx->fd=ReOpenFile(waysx->filename); |
664 | amb | 548 | #endif |
665 | |||
666 | amb | 555 | /* Re-open the file read-only and a new file writeable */ |
667 | |||
668 | amb | 548 | relationsx->trfd=ReOpenFile(relationsx->trfilename); |
669 | |||
670 | amb | 542 | DeleteFile(relationsx->trfilename); |
671 | |||
672 | trfd=OpenFileNew(relationsx->trfilename); | ||
673 | |||
674 | /* Process all of the relations */ | ||
675 | |||
676 | amb | 548 | while(!ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX))) |
677 | amb | 542 | { |
678 | amb | 615 | NodeX *nodex; |
679 | amb | 645 | SegmentX *segmentx; |
680 | amb | 615 | |
681 | amb | 786 | if(relationx.restriction==TurnRestrict_no_right_turn || |
682 | relationx.restriction==TurnRestrict_no_left_turn || | ||
683 | relationx.restriction==TurnRestrict_no_u_turn || | ||
684 | relationx.restriction==TurnRestrict_no_straight_on) | ||
685 | amb | 548 | { |
686 | amb | 770 | index_t node_from=NO_NODE,node_to=NO_NODE; |
687 | amb | 806 | int oneway_from=0,oneway_to=0,vehicles_from=1,vehicles_to=1; |
688 | amb | 542 | |
689 | amb | 548 | /* Find the segments that join the node 'via' */ |
690 | amb | 542 | |
691 | amb | 646 | segmentx=FirstSegmentX(segmentsx,relationx.via,1); |
692 | amb | 542 | |
693 | amb | 742 | while(segmentx) |
694 | amb | 548 | { |
695 | amb | 645 | if(segmentx->way==relationx.from) |
696 | amb | 548 | { |
697 | amb | 806 | WayX *wayx=LookupWayX(waysx,segmentx->way,1); |
698 | |||
699 | amb | 551 | if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */ |
700 | amb | 742 | { |
701 | amb | 832 | logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'from' way.\n",relationx.id); |
702 | amb | 742 | deleted++; |
703 | amb | 551 | goto endloop; |
704 | amb | 742 | } |
705 | amb | 548 | |
706 | amb | 645 | node_from=OtherNode(segmentx,relationx.via); |
707 | amb | 806 | |
708 | if(IsOnewayFrom(segmentx,relationx.via)) | ||
709 | oneway_from=1; /* not allowed */ | ||
710 | |||
711 | amb | 837 | if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV))) |
712 | amb | 806 | vehicles_from=0; /* not allowed */ |
713 | amb | 548 | } |
714 | |||
715 | amb | 645 | if(segmentx->way==relationx.to) |
716 | amb | 548 | { |
717 | amb | 806 | WayX *wayx=LookupWayX(waysx,segmentx->way,1); |
718 | |||
719 | amb | 551 | if(node_to!=NO_NODE) /* Only one segment can be on the 'to' way */ |
720 | amb | 742 | { |
721 | amb | 832 | logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'to' way.\n",relationx.id); |
722 | amb | 742 | deleted++; |
723 | amb | 551 | goto endloop; |
724 | amb | 742 | } |
725 | amb | 548 | |
726 | amb | 806 | node_to=OtherNode(segmentx,relationx.via); |
727 | amb | 670 | |
728 | amb | 806 | if(IsOnewayTo(segmentx,relationx.via)) |
729 | oneway_to=1; /* not allowed */ | ||
730 | |||
731 | amb | 837 | if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV))) |
732 | amb | 806 | vehicles_to=0; /* not allowed */ |
733 | amb | 548 | } |
734 | |||
735 | amb | 943 | segmentx=NextSegmentX(segmentsx,segmentx,relationx.via); |
736 | amb | 548 | } |
737 | |||
738 | amb | 812 | if(node_from==NO_NODE) |
739 | amb | 832 | logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'from' way.\n",relationx.id); |
740 | amb | 812 | |
741 | if(node_to==NO_NODE) | ||
742 | amb | 832 | logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'to' way.\n",relationx.id); |
743 | amb | 812 | |
744 | if(oneway_from) | ||
745 | logerror("Turn Relation %"Prelation_t" is not stored because the 'from' way is oneway away from the 'via' node.\n",relationx.id); | ||
746 | |||
747 | if(oneway_to) | ||
748 | logerror("Turn Relation %"Prelation_t" is not needed because the 'to' way is oneway towards the 'via' node.\n",relationx.id); | ||
749 | |||
750 | if(!vehicles_from) | ||
751 | amb | 837 | logerror("Turn Relation %"Prelation_t" is not stored because the 'from' way does not allow vehicles.\n",relationx.id); |
752 | amb | 812 | |
753 | if(!vehicles_to) | ||
754 | amb | 837 | logerror("Turn Relation %"Prelation_t" is not needed because the 'to' way does not allow vehicles.\n",relationx.id); |
755 | amb | 812 | |
756 | amb | 806 | if(oneway_from || oneway_to || !vehicles_from || !vehicles_to || node_from==NO_NODE || node_to==NO_NODE) |
757 | amb | 742 | { |
758 | deleted++; | ||
759 | amb | 548 | goto endloop; |
760 | amb | 742 | } |
761 | amb | 548 | |
762 | amb | 551 | /* Write the results */ |
763 | amb | 548 | |
764 | amb | 645 | relationx.from=node_from; |
765 | relationx.to =node_to; | ||
766 | amb | 548 | |
767 | amb | 551 | WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX)); |
768 | amb | 548 | |
769 | amb | 559 | total++; |
770 | amb | 548 | |
771 | amb | 757 | if(!(total%1000)) |
772 | amb | 790 | printf_middle("Processing Turn Relations (2): Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,total,deleted,total-relationsx->trnumber+deleted); |
773 | amb | 551 | } |
774 | else | ||
775 | { | ||
776 | amb | 806 | index_t node_from=NO_NODE,node_to=NO_NODE,node_other[MAX_SEG_PER_NODE]; |
777 | int nnodes_other=0,i; | ||
778 | int oneway_from=0,vehicles_from=1; | ||
779 | amb | 548 | |
780 | amb | 551 | /* Find the segments that join the node 'via' */ |
781 | amb | 548 | |
782 | amb | 646 | segmentx=FirstSegmentX(segmentsx,relationx.via,1); |
783 | amb | 548 | |
784 | amb | 742 | while(segmentx) |
785 | amb | 551 | { |
786 | amb | 645 | if(segmentx->way==relationx.from) |
787 | amb | 551 | { |
788 | amb | 806 | WayX *wayx=LookupWayX(waysx,segmentx->way,1); |
789 | |||
790 | amb | 551 | if(node_from!=NO_NODE) /* Only one segment can be on the 'from' way */ |
791 | amb | 742 | { |
792 | amb | 832 | logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'from' way.\n",relationx.id); |
793 | amb | 742 | deleted++; |
794 | amb | 548 | goto endloop; |
795 | amb | 742 | } |
796 | amb | 548 | |
797 | amb | 645 | node_from=OtherNode(segmentx,relationx.via); |
798 | amb | 806 | |
799 | if(IsOnewayFrom(segmentx,relationx.via)) | ||
800 | oneway_from=1; /* not allowed */ | ||
801 | |||
802 | amb | 837 | if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV))) |
803 | amb | 806 | vehicles_from=0; /* not allowed */ |
804 | amb | 548 | } |
805 | amb | 551 | |
806 | amb | 806 | if(segmentx->way==relationx.to) |
807 | amb | 551 | { |
808 | amb | 806 | if(node_to!=NO_NODE) /* Only one segment can be on the 'to' way */ |
809 | { | ||
810 | amb | 832 | logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not at the end of the 'to' way.\n",relationx.id); |
811 | amb | 806 | deleted++; |
812 | goto endloop; | ||
813 | } | ||
814 | amb | 551 | |
815 | amb | 806 | node_to=OtherNode(segmentx,relationx.via); |
816 | } | ||
817 | amb | 670 | |
818 | amb | 806 | if(segmentx->way!=relationx.from && segmentx->way!=relationx.to) |
819 | { | ||
820 | WayX *wayx=LookupWayX(waysx,segmentx->way,1); | ||
821 | |||
822 | if(IsOnewayTo(segmentx,relationx.via)) | ||
823 | ; /* not allowed */ | ||
824 | amb | 837 | else if(!(wayx->way.allow&(Transports_Bicycle|Transports_Moped|Transports_Motorbike|Transports_Motorcar|Transports_Goods|Transports_HGV|Transports_PSV))) |
825 | amb | 806 | ; /* not allowed */ |
826 | else | ||
827 | amb | 812 | { |
828 | assert(nnodes_other<MAX_SEG_PER_NODE); /* Only a limited amount of information stored. */ | ||
829 | |||
830 | amb | 806 | node_other[nnodes_other++]=OtherNode(segmentx,relationx.via); |
831 | amb | 812 | } |
832 | amb | 551 | } |
833 | |||
834 | amb | 943 | segmentx=NextSegmentX(segmentsx,segmentx,relationx.via); |
835 | amb | 548 | } |
836 | |||
837 | amb | 812 | if(node_from==NO_NODE) |
838 | amb | 832 | logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'from' way.\n",relationx.id); |
839 | amb | 812 | |
840 | if(node_to==NO_NODE) | ||
841 | amb | 832 | logerror("Turn Relation %"Prelation_t" is not stored because the 'via' node is not part of the 'to' way.\n",relationx.id); |
842 | amb | 812 | |
843 | if(nnodes_other==0) | ||
844 | logerror("Turn Relation %"Prelation_t" is not needed because the only allowed exit from the 'via' node is the 'to' way.\n",relationx.id); | ||
845 | |||
846 | if(oneway_from) | ||
847 | amb | 832 | logerror("Turn Relation %"Prelation_t" is not needed because the 'from' way is oneway away from the 'via' node.\n",relationx.id); |
848 | amb | 812 | |
849 | if(!vehicles_from) | ||
850 | amb | 837 | logerror("Turn Relation %"Prelation_t" is not stored because the 'from' way does not allow vehicles.\n",relationx.id); |
851 | amb | 812 | |
852 | amb | 806 | if(oneway_from || !vehicles_from || node_from==NO_NODE || node_to==NO_NODE || nnodes_other==0) |
853 | amb | 742 | { |
854 | deleted++; | ||
855 | amb | 548 | goto endloop; |
856 | amb | 742 | } |
857 | amb | 548 | |
858 | /* Write the results */ | ||
859 | |||
860 | amb | 806 | for(i=0;i<nnodes_other;i++) |
861 | amb | 551 | { |
862 | amb | 645 | relationx.from=node_from; |
863 | amb | 806 | relationx.to =node_other[i]; |
864 | amb | 548 | |
865 | amb | 551 | WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX)); |
866 | amb | 548 | |
867 | amb | 559 | total++; |
868 | amb | 548 | |
869 | amb | 757 | if(!(total%1000)) |
870 | amb | 790 | printf_middle("Processing Turn Relations (2): Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,total,deleted,total-relationsx->trnumber+deleted); |
871 | amb | 551 | } |
872 | amb | 615 | } |
873 | amb | 560 | |
874 | amb | 615 | /* Force super nodes on via node and adjacent nodes */ |
875 | |||
876 | nodex=LookupNodeX(nodesx,relationx.via,1); | ||
877 | nodex->flags|=NODE_TURNRSTRCT; | ||
878 | amb | 942 | PutBackNodeX(nodesx,nodex); |
879 | amb | 615 | |
880 | amb | 646 | segmentx=FirstSegmentX(segmentsx,relationx.via,1); |
881 | amb | 615 | |
882 | amb | 742 | while(segmentx) |
883 | amb | 615 | { |
884 | amb | 645 | index_t othernode=OtherNode(segmentx,relationx.via); |
885 | amb | 615 | |
886 | nodex=LookupNodeX(nodesx,othernode,1); | ||
887 | amb | 597 | nodex->flags|=NODE_TURNRSTRCT2; |
888 | amb | 942 | PutBackNodeX(nodesx,nodex); |
889 | amb | 597 | |
890 | amb | 943 | segmentx=NextSegmentX(segmentsx,segmentx,relationx.via); |
891 | amb | 548 | } |
892 | |||
893 | endloop: ; | ||
894 | amb | 542 | } |
895 | |||
896 | amb | 555 | /* Close the files */ |
897 | amb | 542 | |
898 | amb | 612 | relationsx->trfd=CloseFile(relationsx->trfd); |
899 | amb | 542 | CloseFile(trfd); |
900 | |||
901 | amb | 555 | /* Unmap from memory / close the files */ |
902 | amb | 542 | |
903 | amb | 548 | #if !SLIM |
904 | amb | 651 | nodesx->data=UnmapFile(nodesx->filename); |
905 | segmentsx->data=UnmapFile(segmentsx->filename); | ||
906 | amb | 806 | waysx->data=UnmapFile(waysx->filename); |
907 | amb | 555 | #else |
908 | amb | 612 | nodesx->fd=CloseFile(nodesx->fd); |
909 | segmentsx->fd=CloseFile(segmentsx->fd); | ||
910 | amb | 806 | waysx->fd=CloseFile(waysx->fd); |
911 | amb | 548 | #endif |
912 | |||
913 | amb | 542 | /* Print the final message */ |
914 | |||
915 | amb | 790 | printf_last("Processed Turn Relations (2): Relations=%"Pindex_t" Deleted=%"Pindex_t" Added=%"Pindex_t,total,deleted,total-relationsx->trnumber+deleted); |
916 | amb | 559 | |
917 | relationsx->trnumber=total; | ||
918 | amb | 542 | } |
919 | |||
920 | |||
921 | /*++++++++++++++++++++++++++++++++++++++ | ||
922 | amb | 1098 | Remove pruned turn relations and update the node indexes after pruning nodes. |
923 | amb | 542 | |
924 | amb | 681 | RelationsX *relationsx The set of relations to modify. |
925 | amb | 542 | |
926 | amb | 665 | NodesX *nodesx The set of nodes to use. |
927 | amb | 1098 | ++++++++++++++++++++++++++++++++++++++*/ |
928 | amb | 665 | |
929 | amb | 1098 | void RemovePrunedTurnRelations(RelationsX *relationsx,NodesX *nodesx) |
930 | { | ||
931 | TurnRestrictRelX relationx; | ||
932 | index_t total=0,pruned=0,notpruned=0; | ||
933 | int trfd; | ||
934 | |||
935 | /* Print the start message */ | ||
936 | |||
937 | printf_first("Deleting Pruned Turn Relations: Relations=0 Pruned=0"); | ||
938 | |||
939 | /* Re-open the file read-only and a new file writeable */ | ||
940 | |||
941 | relationsx->trfd=ReOpenFile(relationsx->trfilename); | ||
942 | |||
943 | DeleteFile(relationsx->trfilename); | ||
944 | |||
945 | trfd=OpenFileNew(relationsx->trfilename); | ||
946 | |||
947 | /* Process all of the relations */ | ||
948 | |||
949 | while(!ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX))) | ||
950 | { | ||
951 | relationx.from=nodesx->pdata[relationx.from]; | ||
952 | relationx.via =nodesx->pdata[relationx.via]; | ||
953 | relationx.to =nodesx->pdata[relationx.to]; | ||
954 | |||
955 | if(relationx.from==NO_NODE || relationx.via==NO_NODE || relationx.to==NO_NODE) | ||
956 | pruned++; | ||
957 | else | ||
958 | { | ||
959 | WriteFile(trfd,&relationx,sizeof(TurnRestrictRelX)); | ||
960 | |||
961 | notpruned++; | ||
962 | } | ||
963 | |||
964 | total++; | ||
965 | |||
966 | if(!(total%1000)) | ||
967 | printf_middle("Deleting Pruned Turn Relations: Relations=%"Pindex_t" Pruned=%"Pindex_t,total,pruned); | ||
968 | } | ||
969 | |||
970 | relationsx->trnumber=notpruned; | ||
971 | |||
972 | /* Close the files */ | ||
973 | |||
974 | relationsx->trfd=CloseFile(relationsx->trfd); | ||
975 | CloseFile(trfd); | ||
976 | |||
977 | /* Print the final message */ | ||
978 | |||
979 | printf_last("Deleted Pruned Turn Relations: Relations=%"Pindex_t" Pruned=%"Pindex_t,total,pruned); | ||
980 | } | ||
981 | |||
982 | |||
983 | /*++++++++++++++++++++++++++++++++++++++ | ||
984 | amb | 1108 | Sort the turn relations geographically after updating the node indexes. |
985 | amb | 1098 | |
986 | RelationsX *relationsx The set of relations to modify. | ||
987 | |||
988 | NodesX *nodesx The set of nodes to use. | ||
989 | |||
990 | amb | 680 | SegmentsX *segmentsx The set of segments to use. |
991 | amb | 542 | ++++++++++++++++++++++++++++++++++++++*/ |
992 | |||
993 | amb | 1108 | void SortTurnRelationListGeographically(RelationsX *relationsx,NodesX *nodesx,SegmentsX *segmentsx) |
994 | amb | 542 | { |
995 | int trfd; | ||
996 | |||
997 | /* Print the start message */ | ||
998 | |||
999 | amb | 1108 | printf_first("Sorting Turn Relations Geographically"); |
1000 | amb | 542 | |
1001 | amb | 599 | /* Map into memory / open the files */ |
1002 | |||
1003 | #if !SLIM | ||
1004 | amb | 651 | segmentsx->data=MapFile(segmentsx->filename); |
1005 | amb | 599 | #else |
1006 | segmentsx->fd=ReOpenFile(segmentsx->filename); | ||
1007 | #endif | ||
1008 | |||
1009 | amb | 555 | /* Re-open the file read-only and a new file writeable */ |
1010 | amb | 542 | |
1011 | amb | 555 | relationsx->trfd=ReOpenFile(relationsx->trfilename); |
1012 | |||
1013 | amb | 542 | DeleteFile(relationsx->trfilename); |
1014 | |||
1015 | trfd=OpenFileNew(relationsx->trfilename); | ||
1016 | |||
1017 | amb | 1108 | /* Update the segments with geographically sorted node indexes and sort them */ |
1018 | amb | 542 | |
1019 | amb | 1108 | sortnodesx=nodesx; |
1020 | sortsegmentsx=segmentsx; | ||
1021 | amb | 542 | |
1022 | amb | 1108 | filesort_fixed(relationsx->trfd,trfd,sizeof(TurnRestrictRelX),(int (*)(void*,index_t))geographically_index, |
1023 | (int (*)(const void*,const void*))sort_by_via, | ||
1024 | NULL); | ||
1025 | amb | 542 | |
1026 | amb | 555 | /* Close the files */ |
1027 | amb | 542 | |
1028 | amb | 612 | relationsx->trfd=CloseFile(relationsx->trfd); |
1029 | amb | 542 | CloseFile(trfd); |
1030 | |||
1031 | amb | 599 | /* Unmap from memory / close the files */ |
1032 | |||
1033 | #if !SLIM | ||
1034 | amb | 651 | segmentsx->data=UnmapFile(segmentsx->filename); |
1035 | amb | 599 | #else |
1036 | amb | 612 | segmentsx->fd=CloseFile(segmentsx->fd); |
1037 | amb | 599 | #endif |
1038 | |||
1039 | amb | 542 | /* Print the final message */ |
1040 | |||
1041 | amb | 1110 | printf_last("Sorted Turn Relations Geographically: Turn Relations=%"Pindex_t,relationsx->trnumber); |
1042 | amb | 645 | } |
1043 | |||
1044 | |||
1045 | /*++++++++++++++++++++++++++++++++++++++ | ||
1046 | amb | 1108 | Update the turn relation indexes. |
1047 | |||
1048 | int geographically_index Return 1 if the value is to be kept, otherwise 0. | ||
1049 | |||
1050 | TurnRestrictRelX *relationx The extended turn relation. | ||
1051 | |||
1052 | amb | 1112 | index_t index The number of unsorted turn relations that have been read from the input file. |
1053 | amb | 1108 | ++++++++++++++++++++++++++++++++++++++*/ |
1054 | |||
1055 | static int geographically_index(TurnRestrictRelX *relationx,index_t index) | ||
1056 | { | ||
1057 | SegmentX *segmentx; | ||
1058 | index_t from_node,via_node,to_node; | ||
1059 | |||
1060 | from_node=sortnodesx->gdata[relationx->from]; | ||
1061 | via_node =sortnodesx->gdata[relationx->via]; | ||
1062 | to_node =sortnodesx->gdata[relationx->to]; | ||
1063 | |||
1064 | segmentx=FirstSegmentX(sortsegmentsx,via_node,1); | ||
1065 | |||
1066 | do | ||
1067 | { | ||
1068 | if(OtherNode(segmentx,via_node)==from_node) | ||
1069 | relationx->from=IndexSegmentX(sortsegmentsx,segmentx); | ||
1070 | |||
1071 | if(OtherNode(segmentx,via_node)==to_node) | ||
1072 | relationx->to=IndexSegmentX(sortsegmentsx,segmentx); | ||
1073 | |||
1074 | segmentx=NextSegmentX(sortsegmentsx,segmentx,via_node); | ||
1075 | } | ||
1076 | while(segmentx); | ||
1077 | |||
1078 | relationx->via=via_node; | ||
1079 | |||
1080 | return(1); | ||
1081 | } | ||
1082 | |||
1083 | |||
1084 | /*++++++++++++++++++++++++++++++++++++++ | ||
1085 | Sort the turn restriction relations into via index order (then by from and to segments). | ||
1086 | |||
1087 | int sort_by_via Returns the comparison of the via, from and to fields. | ||
1088 | |||
1089 | TurnRestrictRelX *a The first extended relation. | ||
1090 | |||
1091 | TurnRestrictRelX *b The second extended relation. | ||
1092 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1093 | |||
1094 | static int sort_by_via(TurnRestrictRelX *a,TurnRestrictRelX *b) | ||
1095 | { | ||
1096 | index_t a_id=a->via; | ||
1097 | index_t b_id=b->via; | ||
1098 | |||
1099 | if(a_id<b_id) | ||
1100 | return(-1); | ||
1101 | else if(a_id>b_id) | ||
1102 | return(1); | ||
1103 | else | ||
1104 | { | ||
1105 | index_t a_id=a->from; | ||
1106 | index_t b_id=b->from; | ||
1107 | |||
1108 | if(a_id<b_id) | ||
1109 | return(-1); | ||
1110 | else if(a_id>b_id) | ||
1111 | return(1); | ||
1112 | else | ||
1113 | { | ||
1114 | index_t a_id=a->to; | ||
1115 | index_t b_id=b->to; | ||
1116 | |||
1117 | if(a_id<b_id) | ||
1118 | return(-1); | ||
1119 | else if(a_id>b_id) | ||
1120 | return(1); | ||
1121 | else | ||
1122 | amb | 1118 | return(FILESORT_PRESERVE_ORDER(a,b)); |
1123 | amb | 1108 | } |
1124 | } | ||
1125 | } | ||
1126 | |||
1127 | |||
1128 | /*++++++++++++++++++++++++++++++++++++++ | ||
1129 | amb | 542 | Save the relation list to a file. |
1130 | |||
1131 | RelationsX* relationsx The set of relations to save. | ||
1132 | |||
1133 | const char *filename The name of the file to save. | ||
1134 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1135 | |||
1136 | void SaveRelationList(RelationsX* relationsx,const char *filename) | ||
1137 | { | ||
1138 | index_t i; | ||
1139 | int fd; | ||
1140 | RelationsFile relationsfile={0}; | ||
1141 | |||
1142 | /* Print the start message */ | ||
1143 | |||
1144 | printf_first("Writing Relations: Turn Relations=0"); | ||
1145 | |||
1146 | amb | 559 | /* Re-open the file read-only */ |
1147 | amb | 555 | |
1148 | relationsx->trfd=ReOpenFile(relationsx->trfilename); | ||
1149 | |||
1150 | amb | 542 | /* Write out the relations data */ |
1151 | |||
1152 | fd=OpenFileNew(filename); | ||
1153 | |||
1154 | SeekFile(fd,sizeof(RelationsFile)); | ||
1155 | |||
1156 | for(i=0;i<relationsx->trnumber;i++) | ||
1157 | { | ||
1158 | TurnRestrictRelX relationx; | ||
1159 | amb | 944 | TurnRelation relation={0}; |
1160 | amb | 542 | |
1161 | ReadFile(relationsx->trfd,&relationx,sizeof(TurnRestrictRelX)); | ||
1162 | |||
1163 | amb | 551 | relation.from=relationx.from; |
1164 | relation.via=relationx.via; | ||
1165 | relation.to=relationx.to; | ||
1166 | relation.except=relationx.except; | ||
1167 | amb | 542 | |
1168 | amb | 551 | WriteFile(fd,&relation,sizeof(TurnRelation)); |
1169 | |||
1170 | amb | 757 | if(!((i+1)%1000)) |
1171 | amb | 790 | printf_middle("Writing Relations: Turn Relations=%"Pindex_t,i+1); |
1172 | amb | 542 | } |
1173 | |||
1174 | /* Write out the header structure */ | ||
1175 | |||
1176 | relationsfile.trnumber=relationsx->trnumber; | ||
1177 | |||
1178 | SeekFile(fd,0); | ||
1179 | WriteFile(fd,&relationsfile,sizeof(RelationsFile)); | ||
1180 | |||
1181 | CloseFile(fd); | ||
1182 | |||
1183 | /* Close the file */ | ||
1184 | |||
1185 | amb | 612 | relationsx->trfd=CloseFile(relationsx->trfd); |
1186 | amb | 542 | |
1187 | /* Print the final message */ | ||
1188 | |||
1189 | amb | 790 | printf_last("Wrote Relations: Turn Relations=%"Pindex_t,relationsx->trnumber); |
1190 | amb | 542 | } |