Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/segmentsx.c
Parent Directory
|
Revision Log
Revision 1169 -
(hide annotations)
(download)
(as text)
Wed Nov 21 11:12:04 2012 UTC (12 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 31499 byte(s)
Wed Nov 21 11:12:04 2012 UTC (12 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 31499 byte(s)
Finally fix the segment area handling - segments that are areas are discarded in preference to those that are not (as it was between r914 and r1136) and segments that are areas don't have the wrong distance (as they did between r914 and r1136). Revision r1137 correctly changed to use a flag and fixed the distance bug but then didn't sort using the new flag. Revision r1153 started sorting using the segment flags but the area was not the most significant bit so they were not sorted last. Revision r1164 correctly cleared the area flag when no longer needed but didn't fix the rest. Revision r1168 reverted r1164 so needed to be re-applied.
1 | amb | 110 | /*************************************** |
2 | Extended Segment data type functions. | ||
3 | amb | 151 | |
4 | Part of the Routino routing software. | ||
5 | amb | 110 | ******************/ /****************** |
6 | amb | 949 | This file Copyright 2008-2012 Andrew M. Bishop |
7 | amb | 110 | |
8 | amb | 151 | 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 | amb | 110 | ***************************************/ |
21 | |||
22 | |||
23 | #include <math.h> | ||
24 | #include <stdlib.h> | ||
25 | amb | 955 | #include <string.h> |
26 | amb | 110 | |
27 | #include "types.h" | ||
28 | amb | 228 | #include "segments.h" |
29 | #include "ways.h" | ||
30 | amb | 110 | |
31 | amb | 955 | #include "typesx.h" |
32 | amb | 449 | #include "nodesx.h" |
33 | #include "segmentsx.h" | ||
34 | #include "waysx.h" | ||
35 | amb | 110 | |
36 | amb | 449 | #include "files.h" |
37 | amb | 519 | #include "logging.h" |
38 | amb | 532 | #include "sorting.h" |
39 | amb | 449 | |
40 | |||
41 | amb | 680 | /* Global variables */ |
42 | amb | 110 | |
43 | amb | 289 | /*+ The command line '--tmpdir' option or its default value. +*/ |
44 | amb | 284 | extern char *option_tmpdirname; |
45 | amb | 110 | |
46 | amb | 1146 | /*+ The option to apply changes (needed to suppress some error log messages) +*/ |
47 | extern int option_changes; | ||
48 | |||
49 | amb | 1100 | /* Local variables */ |
50 | |||
51 | amb | 1107 | /*+ Temporary file-local variables for use by the sort functions. +*/ |
52 | amb | 1132 | static NodesX *sortnodesx; |
53 | amb | 1100 | static SegmentsX *sortsegmentsx; |
54 | amb | 1132 | static WaysX *sortwaysx; |
55 | amb | 1100 | |
56 | amb | 680 | /* Local functions */ |
57 | amb | 110 | |
58 | amb | 1140 | static int sort_by_way_id(SegmentX *a,SegmentX *b); |
59 | static int apply_changes(SegmentX *segmentx,index_t index); | ||
60 | amb | 1160 | |
61 | amb | 275 | static int sort_by_id(SegmentX *a,SegmentX *b); |
62 | amb | 1155 | static int deduplicate(SegmentX *segmentx,index_t index); |
63 | amb | 1160 | |
64 | amb | 949 | static int delete_pruned(SegmentX *segmentx,index_t index); |
65 | amb | 1160 | |
66 | amb | 1132 | static int deduplicate_super(SegmentX *segmentx,index_t index); |
67 | amb | 275 | |
68 | amb | 1160 | static int geographically_index(SegmentX *segmentx,index_t index); |
69 | |||
70 | amb | 1168 | static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2); |
71 | amb | 110 | |
72 | |||
73 | /*++++++++++++++++++++++++++++++++++++++ | ||
74 | amb | 326 | Allocate a new segment list (create a new file or open an existing one). |
75 | amb | 110 | |
76 | SegmentsX *NewSegmentList Returns the segment list. | ||
77 | amb | 326 | |
78 | amb | 1123 | int append Set to 1 if the file is to be opened for appending. |
79 | |||
80 | amb | 1139 | int readonly Set to 1 if the file is to be opened for reading. |
81 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
82 | |||
83 | amb | 1123 | SegmentsX *NewSegmentList(int append,int readonly) |
84 | amb | 110 | { |
85 | SegmentsX *segmentsx; | ||
86 | |||
87 | amb | 213 | segmentsx=(SegmentsX*)calloc(1,sizeof(SegmentsX)); |
88 | amb | 110 | |
89 | amb | 1166 | logassert(segmentsx,"Failed to allocate memory (try using slim mode?)"); /* Check calloc() worked */ |
90 | amb | 243 | |
91 | amb | 1120 | segmentsx->filename =(char*)malloc(strlen(option_tmpdirname)+32); |
92 | segmentsx->filename_tmp=(char*)malloc(strlen(option_tmpdirname)+32); | ||
93 | amb | 216 | |
94 | amb | 1120 | sprintf(segmentsx->filename ,"%s/segmentsx.parsed.mem",option_tmpdirname); |
95 | sprintf(segmentsx->filename_tmp,"%s/segmentsx.%p.tmp" ,option_tmpdirname,(void*)segmentsx); | ||
96 | amb | 256 | |
97 | amb | 1123 | if(append || readonly) |
98 | if(ExistsFile(segmentsx->filename)) | ||
99 | { | ||
100 | off_t size; | ||
101 | amb | 326 | |
102 | amb | 1123 | size=SizeFile(segmentsx->filename); |
103 | amb | 326 | |
104 | amb | 1123 | segmentsx->number=size/sizeof(SegmentX); |
105 | amb | 1139 | |
106 | RenameFile(segmentsx->filename,segmentsx->filename_tmp); | ||
107 | amb | 1123 | } |
108 | amb | 326 | |
109 | amb | 1123 | if(append) |
110 | amb | 1139 | segmentsx->fd=OpenFileAppend(segmentsx->filename_tmp); |
111 | amb | 1123 | else if(!readonly) |
112 | amb | 1139 | segmentsx->fd=OpenFileNew(segmentsx->filename_tmp); |
113 | amb | 326 | else |
114 | amb | 1123 | segmentsx->fd=-1; |
115 | amb | 326 | |
116 | amb | 110 | return(segmentsx); |
117 | } | ||
118 | |||
119 | |||
120 | /*++++++++++++++++++++++++++++++++++++++ | ||
121 | amb | 226 | Free a segment list. |
122 | amb | 110 | |
123 | amb | 681 | SegmentsX *segmentsx The set of segments to be freed. |
124 | amb | 1151 | |
125 | amb | 1167 | int keep If set then the results file is to be kept. |
126 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
127 | |||
128 | amb | 1167 | void FreeSegmentList(SegmentsX *segmentsx,int keep) |
129 | amb | 110 | { |
130 | amb | 1167 | if(keep) |
131 | amb | 1151 | RenameFile(segmentsx->filename_tmp,segmentsx->filename); |
132 | else | ||
133 | DeleteFile(segmentsx->filename_tmp); | ||
134 | amb | 1120 | |
135 | amb | 283 | free(segmentsx->filename); |
136 | amb | 1120 | free(segmentsx->filename_tmp); |
137 | amb | 256 | |
138 | amb | 949 | if(segmentsx->firstnode) |
139 | free(segmentsx->firstnode); | ||
140 | |||
141 | if(segmentsx->next1) | ||
142 | free(segmentsx->next1); | ||
143 | |||
144 | amb | 643 | if(segmentsx->usednode) |
145 | free(segmentsx->usednode); | ||
146 | |||
147 | amb | 110 | free(segmentsx); |
148 | } | ||
149 | |||
150 | |||
151 | /*++++++++++++++++++++++++++++++++++++++ | ||
152 | amb | 493 | Append a single segment to an unsorted segment list. |
153 | amb | 110 | |
154 | amb | 681 | SegmentsX *segmentsx The set of segments to modify. |
155 | amb | 110 | |
156 | amb | 285 | way_t way The way that the segment belongs to. |
157 | |||
158 | node_t node1 The first node in the segment. | ||
159 | |||
160 | node_t node2 The second node in the segment. | ||
161 | |||
162 | amb | 1168 | distance_t distance The distance between the nodes (or just the flags). |
163 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
164 | |||
165 | amb | 1168 | void AppendSegmentList(SegmentsX *segmentsx,way_t way,node_t node1,node_t node2,distance_t distance) |
166 | amb | 110 | { |
167 | amb | 285 | SegmentX segmentx; |
168 | amb | 110 | |
169 | amb | 643 | if(node1>node2) |
170 | { | ||
171 | node_t temp; | ||
172 | |||
173 | temp=node1; | ||
174 | node1=node2; | ||
175 | node2=temp; | ||
176 | |||
177 | amb | 1168 | if(distance&(ONEWAY_2TO1|ONEWAY_1TO2)) |
178 | distance^=ONEWAY_2TO1|ONEWAY_1TO2; | ||
179 | amb | 643 | } |
180 | |||
181 | amb | 285 | segmentx.node1=node1; |
182 | segmentx.node2=node2; | ||
183 | amb | 643 | segmentx.next2=NO_SEGMENT; |
184 | amb | 285 | segmentx.way=way; |
185 | amb | 1168 | segmentx.distance=distance; |
186 | amb | 110 | |
187 | amb | 285 | WriteFile(segmentsx->fd,&segmentx,sizeof(SegmentX)); |
188 | amb | 281 | |
189 | amb | 650 | segmentsx->number++; |
190 | amb | 466 | |
191 | amb | 1166 | logassert(segmentsx->number<SEGMENT_FAKE,"Too many segments (change index_t to 64-bits?)"); /* SEGMENT_FAKE marks the high-water mark for real segments. */ |
192 | amb | 285 | } |
193 | amb | 227 | |
194 | amb | 281 | |
195 | amb | 285 | /*++++++++++++++++++++++++++++++++++++++ |
196 | amb | 1120 | Finish appending segments and change the filename over. |
197 | |||
198 | SegmentsX *segmentsx The segments that have been appended. | ||
199 | ++++++++++++++++++++++++++++++++++++++*/ | ||
200 | |||
201 | amb | 1151 | void FinishSegmentList(SegmentsX *segmentsx) |
202 | amb | 1120 | { |
203 | amb | 1136 | if(segmentsx->fd!=-1) |
204 | segmentsx->fd=CloseFile(segmentsx->fd); | ||
205 | amb | 1120 | } |
206 | |||
207 | |||
208 | /*++++++++++++++++++++++++++++++++++++++ | ||
209 | amb | 1160 | Find the first extended segment with a particular starting node index. |
210 | |||
211 | SegmentX *FirstSegmentX Returns a pointer to the first extended segment with the specified id. | ||
212 | |||
213 | SegmentsX *segmentsx The set of segments to use. | ||
214 | |||
215 | index_t nodeindex The node index to look for. | ||
216 | |||
217 | int position A flag to pass through. | ||
218 | ++++++++++++++++++++++++++++++++++++++*/ | ||
219 | |||
220 | SegmentX *FirstSegmentX(SegmentsX *segmentsx,index_t nodeindex,int position) | ||
221 | { | ||
222 | index_t index=segmentsx->firstnode[nodeindex]; | ||
223 | SegmentX *segmentx; | ||
224 | |||
225 | if(index==NO_SEGMENT) | ||
226 | return(NULL); | ||
227 | |||
228 | segmentx=LookupSegmentX(segmentsx,index,position); | ||
229 | |||
230 | return(segmentx); | ||
231 | } | ||
232 | |||
233 | |||
234 | /*++++++++++++++++++++++++++++++++++++++ | ||
235 | Find the next segment with a particular starting node index. | ||
236 | |||
237 | SegmentX *NextSegmentX Returns a pointer to the next segment with the same id. | ||
238 | |||
239 | SegmentsX *segmentsx The set of segments to use. | ||
240 | |||
241 | SegmentX *segmentx The current segment. | ||
242 | |||
243 | index_t nodeindex The node index. | ||
244 | ++++++++++++++++++++++++++++++++++++++*/ | ||
245 | |||
246 | SegmentX *NextSegmentX(SegmentsX *segmentsx,SegmentX *segmentx,index_t nodeindex) | ||
247 | { | ||
248 | #if SLIM | ||
249 | int position=1+(segmentx-&segmentsx->cached[0]); | ||
250 | #endif | ||
251 | |||
252 | if(segmentx->node1==nodeindex) | ||
253 | { | ||
254 | if(segmentsx->next1) | ||
255 | { | ||
256 | index_t index=IndexSegmentX(segmentsx,segmentx); | ||
257 | |||
258 | if(segmentsx->next1[index]==NO_SEGMENT) | ||
259 | return(NULL); | ||
260 | |||
261 | segmentx=LookupSegmentX(segmentsx,segmentsx->next1[index],position); | ||
262 | |||
263 | return(segmentx); | ||
264 | } | ||
265 | else | ||
266 | { | ||
267 | #if SLIM | ||
268 | index_t index=IndexSegmentX(segmentsx,segmentx); | ||
269 | index++; | ||
270 | |||
271 | if(index>=segmentsx->number) | ||
272 | return(NULL); | ||
273 | |||
274 | segmentx=LookupSegmentX(segmentsx,index,position); | ||
275 | #else | ||
276 | segmentx++; | ||
277 | |||
278 | if(IndexSegmentX(segmentsx,segmentx)>=segmentsx->number) | ||
279 | return(NULL); | ||
280 | #endif | ||
281 | |||
282 | if(segmentx->node1!=nodeindex) | ||
283 | return(NULL); | ||
284 | |||
285 | return(segmentx); | ||
286 | } | ||
287 | } | ||
288 | else | ||
289 | { | ||
290 | if(segmentx->next2==NO_SEGMENT) | ||
291 | return(NULL); | ||
292 | |||
293 | return(LookupSegmentX(segmentsx,segmentx->next2,position)); | ||
294 | } | ||
295 | } | ||
296 | |||
297 | |||
298 | /*++++++++++++++++++++++++++++++++++++++ | ||
299 | amb | 1140 | Apply the changes to the segments (no unique id to use). |
300 | |||
301 | SegmentsX *segmentsx The set of segments to sort and modify. | ||
302 | ++++++++++++++++++++++++++++++++++++++*/ | ||
303 | |||
304 | void ApplySegmentChanges(SegmentsX *segmentsx) | ||
305 | { | ||
306 | int fd; | ||
307 | index_t xnumber; | ||
308 | |||
309 | /* Print the start message */ | ||
310 | |||
311 | printf_first("Applying Segment Changes"); | ||
312 | |||
313 | /* Re-open the file read-only and a new file writeable */ | ||
314 | |||
315 | segmentsx->fd=ReOpenFile(segmentsx->filename_tmp); | ||
316 | |||
317 | DeleteFile(segmentsx->filename_tmp); | ||
318 | |||
319 | fd=OpenFileNew(segmentsx->filename_tmp); | ||
320 | |||
321 | /* Sort by node indexes */ | ||
322 | |||
323 | xnumber=segmentsx->number; | ||
324 | |||
325 | segmentsx->number=filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),NULL, | ||
326 | (int (*)(const void*,const void*))sort_by_way_id, | ||
327 | (int (*)(void*,index_t))apply_changes); | ||
328 | |||
329 | /* Close the files */ | ||
330 | |||
331 | segmentsx->fd=CloseFile(segmentsx->fd); | ||
332 | CloseFile(fd); | ||
333 | |||
334 | /* Print the final message */ | ||
335 | |||
336 | printf_last("Applying Segment Changes: Segments=%"Pindex_t" Changed=%"Pindex_t,xnumber,xnumber-segmentsx->number); | ||
337 | } | ||
338 | |||
339 | |||
340 | /*++++++++++++++++++++++++++++++++++++++ | ||
341 | amb | 1160 | Sort the segments into way id order. |
342 | amb | 232 | |
343 | amb | 1160 | int sort_by_way_id Returns the comparison of the way fields. |
344 | |||
345 | SegmentX *a The first segment. | ||
346 | |||
347 | SegmentX *b The second segment. | ||
348 | amb | 1100 | ++++++++++++++++++++++++++++++++++++++*/ |
349 | amb | 949 | |
350 | amb | 1160 | static int sort_by_way_id(SegmentX *a,SegmentX *b) |
351 | amb | 1100 | { |
352 | amb | 1160 | way_t a_id=a->way; |
353 | way_t b_id=b->way; | ||
354 | amb | 1100 | |
355 | amb | 1160 | if(a_id<b_id) |
356 | return(-1); | ||
357 | else if(a_id>b_id) | ||
358 | return(1); | ||
359 | else /* if(a_id==b_id) */ | ||
360 | return(-FILESORT_PRESERVE_ORDER(a,b)); /* latest version first */ | ||
361 | } | ||
362 | amb | 1100 | |
363 | |||
364 | amb | 1160 | /*++++++++++++++++++++++++++++++++++++++ |
365 | Apply the changes to the segments. | ||
366 | amb | 1100 | |
367 | amb | 1160 | int apply_changes Return 1 if the value is to be kept, otherwise 0. |
368 | amb | 1100 | |
369 | amb | 1160 | SegmentX *segmentx The extended segment. |
370 | amb | 1100 | |
371 | amb | 1160 | index_t index The number of sorted segments that have already been written to the output file. |
372 | ++++++++++++++++++++++++++++++++++++++*/ | ||
373 | amb | 1100 | |
374 | amb | 1160 | static int apply_changes(SegmentX *segmentx,index_t index) |
375 | { | ||
376 | static way_t prevway=NO_WAY_ID; | ||
377 | static int deleted=0; | ||
378 | amb | 1100 | |
379 | amb | 1160 | if(prevway!=segmentx->way) |
380 | { | ||
381 | prevway=segmentx->way; | ||
382 | deleted=0; | ||
383 | } | ||
384 | amb | 1131 | |
385 | amb | 1160 | if(!deleted) |
386 | if(segmentx->node1==NO_NODE_ID) | ||
387 | deleted=1; | ||
388 | amb | 1131 | |
389 | amb | 1160 | if(deleted) |
390 | return(0); | ||
391 | else | ||
392 | return(1); | ||
393 | amb | 1131 | } |
394 | |||
395 | |||
396 | /*++++++++++++++++++++++++++++++++++++++ | ||
397 | amb | 1160 | Sort the segment list and deduplicate it. |
398 | amb | 1100 | |
399 | SegmentsX *segmentsx The set of segments to sort and modify. | ||
400 | amb | 285 | ++++++++++++++++++++++++++++++++++++++*/ |
401 | amb | 110 | |
402 | amb | 1160 | void SortSegmentList(SegmentsX *segmentsx) |
403 | amb | 285 | { |
404 | int fd; | ||
405 | amb | 1132 | index_t xnumber; |
406 | amb | 243 | |
407 | amb | 285 | /* Print the start message */ |
408 | amb | 232 | |
409 | amb | 1160 | printf_first("Sorting Segments"); |
410 | amb | 110 | |
411 | amb | 555 | /* Re-open the file read-only and a new file writeable */ |
412 | |||
413 | amb | 1120 | segmentsx->fd=ReOpenFile(segmentsx->filename_tmp); |
414 | amb | 110 | |
415 | amb | 1120 | DeleteFile(segmentsx->filename_tmp); |
416 | amb | 110 | |
417 | amb | 1120 | fd=OpenFileNew(segmentsx->filename_tmp); |
418 | amb | 110 | |
419 | amb | 285 | /* Sort by node indexes */ |
420 | amb | 132 | |
421 | amb | 1132 | xnumber=segmentsx->number; |
422 | |||
423 | amb | 1160 | segmentsx->number=filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),NULL, |
424 | amb | 1132 | (int (*)(const void*,const void*))sort_by_id, |
425 | amb | 1160 | (int (*)(void*,index_t))deduplicate); |
426 | amb | 1100 | |
427 | amb | 555 | /* Close the files */ |
428 | amb | 285 | |
429 | amb | 612 | segmentsx->fd=CloseFile(segmentsx->fd); |
430 | amb | 281 | CloseFile(fd); |
431 | |||
432 | /* Print the final message */ | ||
433 | |||
434 | amb | 1160 | printf_last("Sorted Segments: Segments=%"Pindex_t" Duplicates=%"Pindex_t,xnumber,xnumber-segmentsx->number); |
435 | amb | 110 | } |
436 | |||
437 | |||
438 | /*++++++++++++++++++++++++++++++++++++++ | ||
439 | amb | 680 | Sort the segments into id order, first by node1 then by node2, finally by distance. |
440 | amb | 110 | |
441 | amb | 285 | int sort_by_id Returns the comparison of the node fields. |
442 | amb | 110 | |
443 | amb | 285 | SegmentX *a The first segment. |
444 | amb | 110 | |
445 | amb | 285 | SegmentX *b The second segment. |
446 | amb | 256 | ++++++++++++++++++++++++++++++++++++++*/ |
447 | |||
448 | amb | 285 | static int sort_by_id(SegmentX *a,SegmentX *b) |
449 | amb | 256 | { |
450 | amb | 285 | node_t a_id1=a->node1; |
451 | node_t b_id1=b->node1; | ||
452 | amb | 256 | |
453 | amb | 285 | if(a_id1<b_id1) |
454 | return(-1); | ||
455 | else if(a_id1>b_id1) | ||
456 | return(1); | ||
457 | else /* if(a_id1==b_id1) */ | ||
458 | amb | 256 | { |
459 | amb | 285 | node_t a_id2=a->node2; |
460 | node_t b_id2=b->node2; | ||
461 | amb | 256 | |
462 | amb | 285 | if(a_id2<b_id2) |
463 | return(-1); | ||
464 | else if(a_id2>b_id2) | ||
465 | return(1); | ||
466 | else | ||
467 | { | ||
468 | amb | 1168 | distance_t a_distance=DISTANCE(a->distance); |
469 | distance_t b_distance=DISTANCE(b->distance); | ||
470 | amb | 256 | |
471 | amb | 1168 | if(a_distance<b_distance) |
472 | amb | 285 | return(-1); |
473 | amb | 1168 | else if(a_distance>b_distance) |
474 | amb | 285 | return(1); |
475 | else | ||
476 | amb | 1153 | { |
477 | amb | 1168 | distance_t a_distflag=DISTFLAG(a->distance); |
478 | distance_t b_distflag=DISTFLAG(b->distance); | ||
479 | amb | 1153 | |
480 | amb | 1168 | if(a_distflag<b_distflag) |
481 | amb | 1153 | return(-1); |
482 | amb | 1168 | else if(a_distflag>b_distflag) |
483 | amb | 1153 | return(1); |
484 | else | ||
485 | return(FILESORT_PRESERVE_ORDER(a,b)); /* preserve order */ | ||
486 | } | ||
487 | amb | 285 | } |
488 | amb | 256 | } |
489 | } | ||
490 | |||
491 | |||
492 | /*++++++++++++++++++++++++++++++++++++++ | ||
493 | amb | 1155 | Discard duplicate segments. |
494 | amb | 1131 | |
495 | amb | 1155 | int deduplicate Return 1 if the value is to be kept, otherwise 0. |
496 | amb | 1131 | |
497 | SegmentX *segmentx The extended segment. | ||
498 | |||
499 | index_t index The number of sorted segments that have already been written to the output file. | ||
500 | ++++++++++++++++++++++++++++++++++++++*/ | ||
501 | |||
502 | amb | 1155 | static int deduplicate(SegmentX *segmentx,index_t index) |
503 | amb | 1131 | { |
504 | static node_t prevnode1=NO_NODE_ID,prevnode2=NO_NODE_ID; | ||
505 | amb | 1155 | static way_t prevway=NO_WAY_ID; |
506 | amb | 1168 | static distance_t prevdist=0; |
507 | amb | 1131 | |
508 | amb | 1168 | if(prevnode1!=segmentx->node1 || prevnode2!=segmentx->node2 || prevway!=segmentx->way || prevdist!=segmentx->distance) |
509 | amb | 1131 | { |
510 | prevnode1=segmentx->node1; | ||
511 | prevnode2=segmentx->node2; | ||
512 | amb | 1155 | prevway=segmentx->way; |
513 | amb | 1168 | prevdist=segmentx->distance; |
514 | amb | 1131 | |
515 | return(1); | ||
516 | } | ||
517 | else | ||
518 | return(0); | ||
519 | } | ||
520 | |||
521 | |||
522 | /*++++++++++++++++++++++++++++++++++++++ | ||
523 | amb | 680 | Remove bad segments (duplicated, zero length or with missing nodes). |
524 | amb | 110 | |
525 | amb | 1136 | SegmentsX *segmentsx The set of segments to modify. |
526 | |||
527 | amb | 681 | NodesX *nodesx The set of nodes to use. |
528 | amb | 195 | |
529 | amb | 1140 | WaysX *waysx The set of ways to use. |
530 | |||
531 | amb | 1167 | int keep If set to 1 then keep the old data file otherwise delete it. |
532 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
533 | |||
534 | amb | 1167 | void RemoveBadSegments(SegmentsX *segmentsx,NodesX *nodesx,WaysX *waysx,int keep) |
535 | amb | 110 | { |
536 | amb | 1155 | index_t noway=0,loop=0,nonode=0,duplicate=0,good=0,total=0; |
537 | node_t prevnode1=NO_NODE_ID,prevnode2=NO_NODE_ID; | ||
538 | amb | 1168 | distance_t prevdist=0; |
539 | amb | 275 | SegmentX segmentx; |
540 | int fd; | ||
541 | amb | 110 | |
542 | amb | 275 | /* Print the start message */ |
543 | |||
544 | amb | 1155 | printf_first("Checking Segments: Segments=0 Loop=0 No-Way=0 No-Node=0 Duplicate=0"); |
545 | amb | 227 | |
546 | amb | 1100 | /* Allocate the node usage bitmask */ |
547 | amb | 643 | |
548 | amb | 950 | segmentsx->usednode=AllocBitMask(nodesx->number); |
549 | amb | 643 | |
550 | amb | 1166 | logassert(segmentsx->usednode,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */ |
551 | amb | 643 | |
552 | amb | 555 | /* Re-open the file read-only and a new file writeable */ |
553 | amb | 275 | |
554 | amb | 1120 | segmentsx->fd=ReOpenFile(segmentsx->filename_tmp); |
555 | amb | 555 | |
556 | amb | 1167 | if(keep) |
557 | amb | 1136 | RenameFile(segmentsx->filename_tmp,segmentsx->filename); |
558 | else | ||
559 | DeleteFile(segmentsx->filename_tmp); | ||
560 | amb | 275 | |
561 | amb | 1120 | fd=OpenFileNew(segmentsx->filename_tmp); |
562 | amb | 275 | |
563 | amb | 555 | /* Modify the on-disk image */ |
564 | |||
565 | amb | 275 | while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX))) |
566 | amb | 110 | { |
567 | amb | 643 | index_t index1=IndexNodeX(nodesx,segmentx.node1); |
568 | index_t index2=IndexNodeX(nodesx,segmentx.node2); | ||
569 | amb | 1140 | index_t indexw=IndexWayX(waysx,segmentx.way); |
570 | amb | 643 | |
571 | amb | 1140 | if(indexw==NO_WAY) |
572 | amb | 812 | { |
573 | amb | 1140 | logerror("Segment belongs to way %"Pway_t" but it doesn't exist.\n",segmentx.way); |
574 | |||
575 | noway++; | ||
576 | } | ||
577 | else if(segmentx.node1==segmentx.node2) | ||
578 | { | ||
579 | amb | 812 | logerror("Segment connects node %"Pnode_t" to itself.\n",segmentx.node1); |
580 | |||
581 | amb | 257 | loop++; |
582 | amb | 812 | } |
583 | amb | 643 | else if(index1==NO_NODE || index2==NO_NODE) |
584 | amb | 812 | { |
585 | if(index1==NO_NODE && index2==NO_NODE) | ||
586 | logerror("Segment connects nodes %"Pnode_t" and %"Pnode_t" but neither exist.\n",segmentx.node1,segmentx.node2); | ||
587 | |||
588 | if(index1==NO_NODE && index2!=NO_NODE) | ||
589 | logerror("Segment connects nodes %"Pnode_t" and %"Pnode_t" but the first one does not exist.\n",segmentx.node1,segmentx.node2); | ||
590 | |||
591 | if(index1!=NO_NODE && index2==NO_NODE) | ||
592 | logerror("Segment connects nodes %"Pnode_t" and %"Pnode_t" but the second one does not exist.\n",segmentx.node1,segmentx.node2); | ||
593 | |||
594 | amb | 761 | nonode++; |
595 | amb | 812 | } |
596 | amb | 1155 | else if(prevnode1==segmentx.node1 && prevnode2==segmentx.node2) |
597 | { | ||
598 | amb | 1168 | if(!(prevdist&SEGMENT_AREA) && !(segmentx.distance&SEGMENT_AREA)) |
599 | amb | 1155 | logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated.\n",segmentx.node1,segmentx.node2); |
600 | |||
601 | amb | 1168 | if(!(prevdist&SEGMENT_AREA) && (segmentx.distance&SEGMENT_AREA)) |
602 | amb | 1155 | logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated (discarded the area).\n",segmentx.node1,segmentx.node2); |
603 | |||
604 | amb | 1168 | if((prevdist&SEGMENT_AREA) && !(segmentx.distance&SEGMENT_AREA)) |
605 | amb | 1155 | logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated (discarded the non-area).\n",segmentx.node1,segmentx.node2); |
606 | |||
607 | amb | 1168 | if((prevdist&SEGMENT_AREA) && (segmentx.distance&SEGMENT_AREA)) |
608 | amb | 1155 | logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" is duplicated (both are areas).\n",segmentx.node1,segmentx.node2); |
609 | |||
610 | duplicate++; | ||
611 | } | ||
612 | amb | 275 | else |
613 | amb | 257 | { |
614 | amb | 275 | WriteFile(fd,&segmentx,sizeof(SegmentX)); |
615 | |||
616 | amb | 655 | SetBit(segmentsx->usednode,index1); |
617 | SetBit(segmentsx->usednode,index2); | ||
618 | amb | 643 | |
619 | amb | 1155 | prevnode1=segmentx.node1; |
620 | prevnode2=segmentx.node2; | ||
621 | amb | 1168 | prevdist=DISTANCE(segmentx.distance); |
622 | amb | 1155 | |
623 | amb | 275 | good++; |
624 | amb | 110 | } |
625 | |||
626 | amb | 275 | total++; |
627 | amb | 256 | |
628 | amb | 275 | if(!(total%10000)) |
629 | amb | 1155 | printf_middle("Checking Segments: Segments=%"Pindex_t" Loop=%"Pindex_t" No-Way=%"Pindex_t" No-Node=%"Pindex_t" Duplicate=%"Pindex_t,total,loop,noway,nonode,duplicate); |
630 | amb | 110 | } |
631 | |||
632 | amb | 555 | segmentsx->number=good; |
633 | amb | 275 | |
634 | amb | 555 | /* Close the files */ |
635 | |||
636 | amb | 612 | segmentsx->fd=CloseFile(segmentsx->fd); |
637 | amb | 275 | CloseFile(fd); |
638 | |||
639 | /* Print the final message */ | ||
640 | |||
641 | amb | 1155 | printf_last("Checked Segments: Segments=%"Pindex_t" Loop=%"Pindex_t" No-Way=%"Pindex_t" No-Node=%"Pindex_t" Duplicate=%"Pindex_t,total,loop,noway,nonode,duplicate); |
642 | amb | 110 | } |
643 | |||
644 | |||
645 | /*++++++++++++++++++++++++++++++++++++++ | ||
646 | amb | 285 | Measure the segments and replace node/way ids with indexes. |
647 | amb | 110 | |
648 | amb | 681 | SegmentsX *segmentsx The set of segments to process. |
649 | amb | 110 | |
650 | amb | 680 | NodesX *nodesx The set of nodes to use. |
651 | amb | 279 | |
652 | amb | 680 | WaysX *waysx The set of ways to use. |
653 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
654 | |||
655 | amb | 681 | void MeasureSegments(SegmentsX *segmentsx,NodesX *nodesx,WaysX *waysx) |
656 | amb | 110 | { |
657 | amb | 279 | index_t index=0; |
658 | amb | 643 | int fd; |
659 | amb | 256 | SegmentX segmentx; |
660 | amb | 110 | |
661 | amb | 275 | /* Print the start message */ |
662 | |||
663 | amb | 519 | printf_first("Measuring Segments: Segments=0"); |
664 | amb | 227 | |
665 | amb | 555 | /* Map into memory / open the file */ |
666 | amb | 257 | |
667 | amb | 452 | #if !SLIM |
668 | amb | 1120 | nodesx->data=MapFile(nodesx->filename_tmp); |
669 | amb | 555 | #else |
670 | amb | 1120 | nodesx->fd=ReOpenFile(nodesx->filename_tmp); |
671 | amb | 452 | #endif |
672 | amb | 258 | |
673 | amb | 1100 | /* Allocate the way usage bitmask */ |
674 | |||
675 | segmentsx->usedway=AllocBitMask(waysx->number); | ||
676 | |||
677 | amb | 1166 | logassert(segmentsx->usedway,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */ |
678 | amb | 1100 | |
679 | amb | 555 | /* Re-open the file read-only and a new file writeable */ |
680 | amb | 275 | |
681 | amb | 1120 | segmentsx->fd=ReOpenFile(segmentsx->filename_tmp); |
682 | amb | 555 | |
683 | amb | 1120 | DeleteFile(segmentsx->filename_tmp); |
684 | amb | 256 | |
685 | amb | 1120 | fd=OpenFileNew(segmentsx->filename_tmp); |
686 | amb | 256 | |
687 | amb | 555 | /* Modify the on-disk image */ |
688 | |||
689 | amb | 256 | while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX))) |
690 | amb | 110 | { |
691 | amb | 279 | index_t node1=IndexNodeX(nodesx,segmentx.node1); |
692 | index_t node2=IndexNodeX(nodesx,segmentx.node2); | ||
693 | index_t way =IndexWayX (waysx ,segmentx.way); | ||
694 | amb | 110 | |
695 | amb | 279 | NodeX *nodex1=LookupNodeX(nodesx,node1,1); |
696 | NodeX *nodex2=LookupNodeX(nodesx,node2,2); | ||
697 | |||
698 | /* Replace the node and way ids with their indexes */ | ||
699 | |||
700 | segmentx.node1=node1; | ||
701 | segmentx.node2=node2; | ||
702 | segmentx.way =way; | ||
703 | |||
704 | amb | 1100 | SetBit(segmentsx->usedway,segmentx.way); |
705 | |||
706 | amb | 1167 | /* Set the distance but keep the other flags except for area */ |
707 | amb | 275 | |
708 | amb | 1168 | segmentx.distance=DISTANCE(DistanceX(nodex1,nodex2))|DISTFLAG(segmentx.distance); |
709 | amb | 1169 | segmentx.distance&=~SEGMENT_AREA; |
710 | amb | 275 | |
711 | amb | 279 | /* Write the modified segment */ |
712 | |||
713 | amb | 275 | WriteFile(fd,&segmentx,sizeof(SegmentX)); |
714 | |||
715 | amb | 279 | index++; |
716 | amb | 275 | |
717 | amb | 279 | if(!(index%10000)) |
718 | amb | 790 | printf_middle("Measuring Segments: Segments=%"Pindex_t,index); |
719 | amb | 275 | } |
720 | amb | 110 | |
721 | amb | 555 | /* Close the files */ |
722 | amb | 257 | |
723 | amb | 612 | segmentsx->fd=CloseFile(segmentsx->fd); |
724 | amb | 275 | CloseFile(fd); |
725 | |||
726 | amb | 280 | /* Free the other now-unneeded indexes */ |
727 | amb | 279 | |
728 | free(nodesx->idata); | ||
729 | nodesx->idata=NULL; | ||
730 | |||
731 | free(waysx->idata); | ||
732 | waysx->idata=NULL; | ||
733 | |||
734 | amb | 555 | /* Unmap from memory / close the file */ |
735 | amb | 275 | |
736 | amb | 452 | #if !SLIM |
737 | amb | 1122 | nodesx->data=UnmapFile(nodesx->data); |
738 | amb | 555 | #else |
739 | amb | 612 | nodesx->fd=CloseFile(nodesx->fd); |
740 | amb | 452 | #endif |
741 | amb | 275 | |
742 | /* Print the final message */ | ||
743 | |||
744 | amb | 790 | printf_last("Measured Segments: Segments=%"Pindex_t,segmentsx->number); |
745 | amb | 275 | } |
746 | |||
747 | |||
748 | /*++++++++++++++++++++++++++++++++++++++ | ||
749 | amb | 1160 | Index the segments by creating the firstnode index and filling in the segment next2 parameter. |
750 | |||
751 | SegmentsX *segmentsx The set of segments to modify. | ||
752 | |||
753 | NodesX *nodesx The set of nodes to use. | ||
754 | |||
755 | WaysX *waysx The set of ways to use. | ||
756 | ++++++++++++++++++++++++++++++++++++++*/ | ||
757 | |||
758 | void IndexSegments(SegmentsX *segmentsx,NodesX *nodesx,WaysX *waysx) | ||
759 | { | ||
760 | index_t index,i; | ||
761 | |||
762 | if(segmentsx->number==0) | ||
763 | return; | ||
764 | |||
765 | /* Print the start message */ | ||
766 | |||
767 | printf_first("Indexing Segments: Segments=0"); | ||
768 | |||
769 | /* Allocate the array of indexes */ | ||
770 | |||
771 | if(segmentsx->firstnode) | ||
772 | free(segmentsx->firstnode); | ||
773 | |||
774 | segmentsx->firstnode=(index_t*)malloc(nodesx->number*sizeof(index_t)); | ||
775 | |||
776 | amb | 1166 | logassert(segmentsx->firstnode,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */ |
777 | amb | 1160 | |
778 | for(i=0;i<nodesx->number;i++) | ||
779 | segmentsx->firstnode[i]=NO_SEGMENT; | ||
780 | |||
781 | /* Map into memory / open the files */ | ||
782 | |||
783 | #if !SLIM | ||
784 | segmentsx->data=MapFileWriteable(segmentsx->filename_tmp); | ||
785 | #else | ||
786 | segmentsx->fd=ReOpenFileWriteable(segmentsx->filename_tmp); | ||
787 | #endif | ||
788 | |||
789 | /* Read through the segments in reverse order */ | ||
790 | |||
791 | for(index=segmentsx->number-1;index!=NO_SEGMENT;index--) | ||
792 | { | ||
793 | SegmentX *segmentx=LookupSegmentX(segmentsx,index,1); | ||
794 | |||
795 | if(nodesx->pdata) | ||
796 | { | ||
797 | segmentx->node1=nodesx->pdata[segmentx->node1]; | ||
798 | segmentx->node2=nodesx->pdata[segmentx->node2]; | ||
799 | } | ||
800 | |||
801 | if(waysx->cdata) | ||
802 | segmentx->way=waysx->cdata[segmentx->way]; | ||
803 | |||
804 | segmentx->next2=segmentsx->firstnode[segmentx->node2]; | ||
805 | |||
806 | PutBackSegmentX(segmentsx,segmentx); | ||
807 | |||
808 | segmentsx->firstnode[segmentx->node1]=index; | ||
809 | segmentsx->firstnode[segmentx->node2]=index; | ||
810 | |||
811 | if(!(index%10000)) | ||
812 | printf_middle("Indexing Segments: Segments=%"Pindex_t,segmentsx->number-index); | ||
813 | } | ||
814 | |||
815 | /* Unmap from memory / close the files */ | ||
816 | |||
817 | #if !SLIM | ||
818 | segmentsx->data=UnmapFile(segmentsx->data); | ||
819 | #else | ||
820 | segmentsx->fd=CloseFile(segmentsx->fd); | ||
821 | #endif | ||
822 | |||
823 | /* Free the memory */ | ||
824 | |||
825 | if(nodesx->pdata) | ||
826 | { | ||
827 | free(nodesx->pdata); | ||
828 | nodesx->pdata=NULL; | ||
829 | } | ||
830 | |||
831 | if(waysx->cdata) | ||
832 | { | ||
833 | free(waysx->cdata); | ||
834 | waysx->cdata=NULL; | ||
835 | } | ||
836 | |||
837 | /* Print the final message */ | ||
838 | |||
839 | printf_last("Indexed Segments: Segments=%"Pindex_t,segmentsx->number); | ||
840 | } | ||
841 | |||
842 | |||
843 | /*++++++++++++++++++++++++++++++++++++++ | ||
844 | Prune the deleted segments while resorting the list. | ||
845 | |||
846 | SegmentsX *segmentsx The set of segments to sort and modify. | ||
847 | |||
848 | WaysX *waysx The set of ways to check. | ||
849 | ++++++++++++++++++++++++++++++++++++++*/ | ||
850 | |||
851 | void RemovePrunedSegments(SegmentsX *segmentsx,WaysX *waysx) | ||
852 | { | ||
853 | int fd; | ||
854 | index_t xnumber; | ||
855 | |||
856 | /* Print the start message */ | ||
857 | |||
858 | printf_first("Sorting and Pruning Segments"); | ||
859 | |||
860 | /* Allocate the way usage bitmask */ | ||
861 | |||
862 | segmentsx->usedway=AllocBitMask(waysx->number); | ||
863 | |||
864 | amb | 1166 | logassert(segmentsx->usedway,"Failed to allocate memory (try using slim mode?)"); /* Check AllocBitMask() worked */ |
865 | amb | 1160 | |
866 | /* Re-open the file read-only and a new file writeable */ | ||
867 | |||
868 | segmentsx->fd=ReOpenFile(segmentsx->filename_tmp); | ||
869 | |||
870 | DeleteFile(segmentsx->filename_tmp); | ||
871 | |||
872 | fd=OpenFileNew(segmentsx->filename_tmp); | ||
873 | |||
874 | /* Sort by node indexes */ | ||
875 | |||
876 | xnumber=segmentsx->number; | ||
877 | |||
878 | sortsegmentsx=segmentsx; | ||
879 | |||
880 | segmentsx->number=filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),(int (*)(void*,index_t))delete_pruned, | ||
881 | (int (*)(const void*,const void*))sort_by_id, | ||
882 | NULL); | ||
883 | |||
884 | /* Close the files */ | ||
885 | |||
886 | segmentsx->fd=CloseFile(segmentsx->fd); | ||
887 | CloseFile(fd); | ||
888 | |||
889 | /* Print the final message */ | ||
890 | |||
891 | printf_last("Sorted and Pruned Segments: Segments=%"Pindex_t" Deleted=%"Pindex_t,xnumber,xnumber-segmentsx->number); | ||
892 | } | ||
893 | |||
894 | |||
895 | /*++++++++++++++++++++++++++++++++++++++ | ||
896 | Delete the pruned segments. | ||
897 | |||
898 | int delete_pruned Return 1 if the value is to be kept, otherwise 0. | ||
899 | |||
900 | SegmentX *segmentx The extended segment. | ||
901 | |||
902 | index_t index The number of unsorted segments that have been read from the input file. | ||
903 | ++++++++++++++++++++++++++++++++++++++*/ | ||
904 | |||
905 | static int delete_pruned(SegmentX *segmentx,index_t index) | ||
906 | { | ||
907 | if(IsPrunedSegmentX(segmentx)) | ||
908 | return(0); | ||
909 | |||
910 | SetBit(sortsegmentsx->usedway,segmentx->way); | ||
911 | |||
912 | return(1); | ||
913 | } | ||
914 | |||
915 | |||
916 | /*++++++++++++++++++++++++++++++++++++++ | ||
917 | amb | 1132 | Remove the duplicate super-segments. |
918 | amb | 110 | |
919 | amb | 1132 | SegmentsX *segmentsx The set of super-segments to modify. |
920 | amb | 110 | |
921 | amb | 680 | WaysX *waysx The set of ways to use. |
922 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
923 | |||
924 | amb | 1132 | void DeduplicateSuperSegments(SegmentsX *segmentsx,WaysX *waysx) |
925 | amb | 110 | { |
926 | amb | 1132 | int fd; |
927 | index_t xnumber; | ||
928 | amb | 110 | |
929 | amb | 275 | /* Print the start message */ |
930 | |||
931 | amb | 1132 | printf_first("Sorting and Deduplicating Super-Segments"); |
932 | amb | 227 | |
933 | amb | 555 | /* Map into memory / open the file */ |
934 | amb | 256 | |
935 | amb | 452 | #if !SLIM |
936 | amb | 1120 | waysx->data=MapFile(waysx->filename_tmp); |
937 | amb | 555 | #else |
938 | amb | 1120 | waysx->fd=ReOpenFile(waysx->filename_tmp); |
939 | amb | 452 | #endif |
940 | amb | 275 | |
941 | amb | 555 | /* Re-open the file read-only and a new file writeable */ |
942 | amb | 275 | |
943 | amb | 1120 | segmentsx->fd=ReOpenFile(segmentsx->filename_tmp); |
944 | amb | 555 | |
945 | amb | 1120 | DeleteFile(segmentsx->filename_tmp); |
946 | amb | 275 | |
947 | amb | 1120 | fd=OpenFileNew(segmentsx->filename_tmp); |
948 | amb | 275 | |
949 | amb | 1132 | /* Sort by node indexes */ |
950 | amb | 555 | |
951 | amb | 1132 | xnumber=segmentsx->number; |
952 | amb | 256 | |
953 | amb | 1132 | sortsegmentsx=segmentsx; |
954 | sortwaysx=waysx; | ||
955 | amb | 110 | |
956 | amb | 1132 | segmentsx->number=filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),NULL, |
957 | (int (*)(const void*,const void*))sort_by_id, | ||
958 | (int (*)(void*,index_t))deduplicate_super); | ||
959 | amb | 264 | |
960 | amb | 555 | /* Close the files */ |
961 | |||
962 | amb | 612 | segmentsx->fd=CloseFile(segmentsx->fd); |
963 | amb | 275 | CloseFile(fd); |
964 | |||
965 | amb | 555 | /* Unmap from memory / close the file */ |
966 | amb | 275 | |
967 | amb | 452 | #if !SLIM |
968 | amb | 1122 | waysx->data=UnmapFile(waysx->data); |
969 | amb | 555 | #else |
970 | amb | 612 | waysx->fd=CloseFile(waysx->fd); |
971 | amb | 452 | #endif |
972 | amb | 275 | |
973 | /* Print the final message */ | ||
974 | |||
975 | amb | 1132 | printf_last("Sorted and Deduplicated Super-Segments: Super-Segments=%"Pindex_t" Duplicate=%"Pindex_t,xnumber,xnumber-segmentsx->number); |
976 | amb | 110 | } |
977 | |||
978 | |||
979 | /*++++++++++++++++++++++++++++++++++++++ | ||
980 | amb | 1132 | De-duplicate super-segments. |
981 | |||
982 | int deduplicate_super Return 1 if the value is to be kept, otherwise 0. | ||
983 | |||
984 | SegmentX *segmentx The extended super-segment. | ||
985 | |||
986 | index_t index The number of sorted super-segments that have already been written to the output file. | ||
987 | ++++++++++++++++++++++++++++++++++++++*/ | ||
988 | |||
989 | static int deduplicate_super(SegmentX *segmentx,index_t index) | ||
990 | { | ||
991 | static int nprev=0; | ||
992 | static index_t prevnode1=NO_NODE,prevnode2=NO_NODE; | ||
993 | static SegmentX prevsegx[MAX_SEG_PER_NODE]; | ||
994 | static Way prevway[MAX_SEG_PER_NODE]; | ||
995 | |||
996 | WayX *wayx=LookupWayX(sortwaysx,segmentx->way,1); | ||
997 | int isduplicate=0; | ||
998 | |||
999 | if(index==0 || segmentx->node1!=prevnode1 || segmentx->node2!=prevnode2) | ||
1000 | { | ||
1001 | nprev=1; | ||
1002 | prevnode1=segmentx->node1; | ||
1003 | prevnode2=segmentx->node2; | ||
1004 | prevsegx[0]=*segmentx; | ||
1005 | prevway[0] =wayx->way; | ||
1006 | } | ||
1007 | else | ||
1008 | { | ||
1009 | int offset; | ||
1010 | |||
1011 | for(offset=0;offset<nprev;offset++) | ||
1012 | { | ||
1013 | amb | 1168 | if(DISTFLAG(segmentx->distance)==DISTFLAG(prevsegx[offset].distance)) |
1014 | amb | 1132 | if(!WaysCompare(&prevway[offset],&wayx->way)) |
1015 | { | ||
1016 | isduplicate=1; | ||
1017 | break; | ||
1018 | } | ||
1019 | } | ||
1020 | |||
1021 | if(isduplicate) | ||
1022 | { | ||
1023 | nprev--; | ||
1024 | |||
1025 | for(;offset<nprev;offset++) | ||
1026 | { | ||
1027 | prevsegx[offset]=prevsegx[offset+1]; | ||
1028 | prevway[offset] =prevway[offset+1]; | ||
1029 | } | ||
1030 | } | ||
1031 | else | ||
1032 | { | ||
1033 | amb | 1166 | logassert(nprev<MAX_SEG_PER_NODE,"Too many segments for one node (increase MAX_SEG_PER_NODE?)"); /* Only a limited amount of information stored. */ |
1034 | amb | 1132 | |
1035 | prevsegx[nprev]=*segmentx; | ||
1036 | prevway[nprev] =wayx->way; | ||
1037 | |||
1038 | nprev++; | ||
1039 | } | ||
1040 | } | ||
1041 | |||
1042 | return(!isduplicate); | ||
1043 | } | ||
1044 | |||
1045 | |||
1046 | /*++++++++++++++++++++++++++++++++++++++ | ||
1047 | amb | 1160 | Sort the segments geographically after updating the node indexes. |
1048 | amb | 209 | |
1049 | amb | 681 | SegmentsX *segmentsx The set of segments to modify. |
1050 | amb | 209 | |
1051 | amb | 1100 | NodesX *nodesx The set of nodes to use. |
1052 | amb | 209 | ++++++++++++++++++++++++++++++++++++++*/ |
1053 | |||
1054 | amb | 1160 | void SortSegmentListGeographically(SegmentsX *segmentsx,NodesX *nodesx) |
1055 | amb | 209 | { |
1056 | amb | 1160 | int fd; |
1057 | amb | 209 | |
1058 | amb | 275 | /* Print the start message */ |
1059 | |||
1060 | amb | 1160 | printf_first("Sorting Segments Geographically"); |
1061 | amb | 227 | |
1062 | amb | 1160 | /* Re-open the file read-only and a new file writeable */ |
1063 | amb | 643 | |
1064 | amb | 1160 | segmentsx->fd=ReOpenFile(segmentsx->filename_tmp); |
1065 | amb | 643 | |
1066 | amb | 1160 | DeleteFile(segmentsx->filename_tmp); |
1067 | amb | 643 | |
1068 | amb | 1160 | fd=OpenFileNew(segmentsx->filename_tmp); |
1069 | amb | 1102 | |
1070 | amb | 1160 | /* Update the segments with geographically sorted node indexes and sort them */ |
1071 | amb | 643 | |
1072 | amb | 1160 | sortnodesx=nodesx; |
1073 | amb | 209 | |
1074 | amb | 1160 | filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),(int (*)(void*,index_t))geographically_index, |
1075 | (int (*)(const void*,const void*))sort_by_id, | ||
1076 | NULL); | ||
1077 | /* Close the files */ | ||
1078 | amb | 275 | |
1079 | amb | 1160 | segmentsx->fd=CloseFile(segmentsx->fd); |
1080 | CloseFile(fd); | ||
1081 | amb | 280 | |
1082 | amb | 1160 | /* Print the final message */ |
1083 | amb | 209 | |
1084 | amb | 1160 | printf_last("Sorted Segments Geographically: Segments=%"Pindex_t,segmentsx->number); |
1085 | } | ||
1086 | amb | 1098 | |
1087 | amb | 1100 | |
1088 | amb | 1160 | /*++++++++++++++++++++++++++++++++++++++ |
1089 | Update the segment indexes. | ||
1090 | amb | 209 | |
1091 | amb | 1160 | int geographically_index Return 1 if the value is to be kept, otherwise 0. |
1092 | amb | 448 | |
1093 | amb | 1160 | SegmentX *segmentx The extended segment. |
1094 | amb | 558 | |
1095 | amb | 1160 | index_t index The number of unsorted segments that have been read from the input file. |
1096 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1097 | amb | 209 | |
1098 | amb | 1160 | static int geographically_index(SegmentX *segmentx,index_t index) |
1099 | { | ||
1100 | segmentx->node1=sortnodesx->gdata[segmentx->node1]; | ||
1101 | segmentx->node2=sortnodesx->gdata[segmentx->node2]; | ||
1102 | amb | 275 | |
1103 | amb | 1160 | if(segmentx->node1>segmentx->node2) |
1104 | { | ||
1105 | index_t temp; | ||
1106 | amb | 275 | |
1107 | amb | 1160 | temp=segmentx->node1; |
1108 | segmentx->node1=segmentx->node2; | ||
1109 | segmentx->node2=temp; | ||
1110 | amb | 1100 | |
1111 | amb | 1168 | if(segmentx->distance&(ONEWAY_2TO1|ONEWAY_1TO2)) |
1112 | segmentx->distance^=ONEWAY_2TO1|ONEWAY_1TO2; | ||
1113 | amb | 1100 | } |
1114 | |||
1115 | amb | 1160 | return(1); |
1116 | amb | 209 | } |
1117 | |||
1118 | |||
1119 | /*++++++++++++++++++++++++++++++++++++++ | ||
1120 | amb | 285 | Save the segment list to a file. |
1121 | |||
1122 | amb | 681 | SegmentsX *segmentsx The set of segments to save. |
1123 | amb | 285 | |
1124 | const char *filename The name of the file to save. | ||
1125 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1126 | |||
1127 | amb | 681 | void SaveSegmentList(SegmentsX *segmentsx,const char *filename) |
1128 | amb | 285 | { |
1129 | index_t i; | ||
1130 | int fd; | ||
1131 | amb | 500 | SegmentsFile segmentsfile={0}; |
1132 | amb | 780 | index_t super_number=0,normal_number=0; |
1133 | amb | 285 | |
1134 | /* Print the start message */ | ||
1135 | |||
1136 | amb | 519 | printf_first("Writing Segments: Segments=0"); |
1137 | amb | 285 | |
1138 | amb | 558 | /* Re-open the file */ |
1139 | |||
1140 | amb | 1120 | segmentsx->fd=ReOpenFile(segmentsx->filename_tmp); |
1141 | amb | 558 | |
1142 | amb | 461 | /* Write out the segments data */ |
1143 | amb | 285 | |
1144 | amb | 502 | fd=OpenFileNew(filename); |
1145 | amb | 461 | |
1146 | SeekFile(fd,sizeof(SegmentsFile)); | ||
1147 | |||
1148 | amb | 285 | for(i=0;i<segmentsx->number;i++) |
1149 | { | ||
1150 | amb | 643 | SegmentX segmentx; |
1151 | amb | 944 | Segment segment={0}; |
1152 | amb | 448 | |
1153 | amb | 643 | ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)); |
1154 | amb | 558 | |
1155 | amb | 1168 | segment.node1 =segmentx.node1; |
1156 | segment.node2 =segmentx.node2; | ||
1157 | segment.next2 =segmentx.next2; | ||
1158 | segment.way =segmentx.way; | ||
1159 | segment.distance=segmentx.distance; | ||
1160 | amb | 643 | |
1161 | amb | 558 | if(IsSuperSegment(&segment)) |
1162 | amb | 285 | super_number++; |
1163 | amb | 558 | if(IsNormalSegment(&segment)) |
1164 | amb | 285 | normal_number++; |
1165 | |||
1166 | amb | 558 | WriteFile(fd,&segment,sizeof(Segment)); |
1167 | amb | 448 | |
1168 | amb | 285 | if(!((i+1)%10000)) |
1169 | amb | 790 | printf_middle("Writing Segments: Segments=%"Pindex_t,i+1); |
1170 | amb | 285 | } |
1171 | |||
1172 | amb | 461 | /* Write out the header structure */ |
1173 | |||
1174 | segmentsfile.number=segmentsx->number; | ||
1175 | segmentsfile.snumber=super_number; | ||
1176 | segmentsfile.nnumber=normal_number; | ||
1177 | |||
1178 | SeekFile(fd,0); | ||
1179 | WriteFile(fd,&segmentsfile,sizeof(SegmentsFile)); | ||
1180 | |||
1181 | amb | 285 | CloseFile(fd); |
1182 | |||
1183 | amb | 558 | /* Close the file */ |
1184 | |||
1185 | amb | 643 | segmentsx->fd=CloseFile(segmentsx->fd); |
1186 | amb | 558 | |
1187 | amb | 285 | /* Print the final message */ |
1188 | |||
1189 | amb | 790 | printf_last("Wrote Segments: Segments=%"Pindex_t,segmentsx->number); |
1190 | amb | 285 | } |
1191 | |||
1192 | |||
1193 | /*++++++++++++++++++++++++++++++++++++++ | ||
1194 | amb | 110 | Calculate the distance between two nodes. |
1195 | |||
1196 | amb | 1168 | distance_t DistanceX Returns the distance between the extended nodes. |
1197 | amb | 110 | |
1198 | NodeX *nodex1 The starting node. | ||
1199 | |||
1200 | NodeX *nodex2 The end node. | ||
1201 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1202 | |||
1203 | amb | 1168 | static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2) |
1204 | amb | 110 | { |
1205 | amb | 223 | double dlon = latlong_to_radians(nodex1->longitude) - latlong_to_radians(nodex2->longitude); |
1206 | double dlat = latlong_to_radians(nodex1->latitude) - latlong_to_radians(nodex2->latitude); | ||
1207 | double lat1 = latlong_to_radians(nodex1->latitude); | ||
1208 | double lat2 = latlong_to_radians(nodex2->latitude); | ||
1209 | amb | 110 | |
1210 | amb | 219 | double a1,a2,a,sa,c,d; |
1211 | amb | 110 | |
1212 | if(dlon==0 && dlat==0) | ||
1213 | return 0; | ||
1214 | |||
1215 | amb | 219 | a1 = sin (dlat / 2); |
1216 | a2 = sin (dlon / 2); | ||
1217 | a = (a1 * a1) + cos (lat1) * cos (lat2) * a2 * a2; | ||
1218 | sa = sqrt (a); | ||
1219 | amb | 110 | if (sa <= 1.0) |
1220 | amb | 219 | {c = 2 * asin (sa);} |
1221 | amb | 110 | else |
1222 | amb | 219 | {c = 2 * asin (1.0);} |
1223 | amb | 110 | d = 6378.137 * c; |
1224 | |||
1225 | return km_to_distance(d); | ||
1226 | } |
Properties
Name | Value |
---|---|
cvs:description | Extended segments functions. |