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 310 -
(hide annotations)
(download)
(as text)
Fri Dec 11 19:27:39 2009 UTC (15 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 24402 byte(s)
Fri Dec 11 19:27:39 2009 UTC (15 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 24402 byte(s)
Added a new function to sort variable length data - simplifies the compacting of ways, reduces memory usage potentially required for it and simplifies the code.
1 | amb | 110 | /*************************************** |
2 | amb | 310 | $Header: /home/amb/CVS/routino/src/segmentsx.c,v 1.47 2009-12-11 19:27:39 amb Exp $ |
3 | amb | 110 | |
4 | Extended Segment data type functions. | ||
5 | amb | 151 | |
6 | Part of the Routino routing software. | ||
7 | amb | 110 | ******************/ /****************** |
8 | amb | 151 | This file Copyright 2008,2009 Andrew M. Bishop |
9 | amb | 110 | |
10 | amb | 151 | This program is free software: you can redistribute it and/or modify |
11 | it under the terms of the GNU Affero General Public License as published by | ||
12 | the Free Software Foundation, either version 3 of the License, or | ||
13 | (at your option) any later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU Affero General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU Affero General Public License | ||
21 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
22 | amb | 110 | ***************************************/ |
23 | |||
24 | |||
25 | #include <assert.h> | ||
26 | #include <math.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <stdio.h> | ||
29 | amb | 256 | #include <string.h> |
30 | amb | 110 | |
31 | #include "types.h" | ||
32 | #include "functions.h" | ||
33 | #include "nodesx.h" | ||
34 | #include "segmentsx.h" | ||
35 | #include "waysx.h" | ||
36 | amb | 228 | #include "nodes.h" |
37 | #include "segments.h" | ||
38 | #include "ways.h" | ||
39 | amb | 110 | |
40 | |||
41 | amb | 275 | /* Constants */ |
42 | |||
43 | amb | 289 | /*+ The amount of memory to use for sorting. +*/ |
44 | amb | 275 | #define SORT_RAMSIZE (64*1024*1024) |
45 | |||
46 | amb | 256 | /* Variables */ |
47 | amb | 110 | |
48 | amb | 289 | /*+ The command line '--slim' option. +*/ |
49 | amb | 256 | extern int option_slim; |
50 | amb | 289 | |
51 | /*+ The command line '--tmpdir' option or its default value. +*/ | ||
52 | amb | 284 | extern char *option_tmpdirname; |
53 | amb | 110 | |
54 | amb | 228 | /* Local Functions */ |
55 | amb | 110 | |
56 | amb | 275 | static int sort_by_id(SegmentX *a,SegmentX *b); |
57 | |||
58 | amb | 228 | static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2); |
59 | amb | 110 | |
60 | |||
61 | /*++++++++++++++++++++++++++++++++++++++ | ||
62 | Allocate a new segment list. | ||
63 | |||
64 | SegmentsX *NewSegmentList Returns the segment list. | ||
65 | ++++++++++++++++++++++++++++++++++++++*/ | ||
66 | |||
67 | SegmentsX *NewSegmentList(void) | ||
68 | { | ||
69 | SegmentsX *segmentsx; | ||
70 | |||
71 | amb | 213 | segmentsx=(SegmentsX*)calloc(1,sizeof(SegmentsX)); |
72 | amb | 110 | |
73 | amb | 243 | assert(segmentsx); /* Check calloc() worked */ |
74 | |||
75 | amb | 284 | segmentsx->filename=(char*)malloc(strlen(option_tmpdirname)+32); |
76 | sprintf(segmentsx->filename,"%s/segments.%p.tmp",option_tmpdirname,segmentsx); | ||
77 | amb | 216 | |
78 | amb | 256 | segmentsx->fd=OpenFile(segmentsx->filename); |
79 | |||
80 | amb | 110 | return(segmentsx); |
81 | } | ||
82 | |||
83 | |||
84 | /*++++++++++++++++++++++++++++++++++++++ | ||
85 | amb | 226 | Free a segment list. |
86 | amb | 110 | |
87 | SegmentsX *segmentsx The list to be freed. | ||
88 | ++++++++++++++++++++++++++++++++++++++*/ | ||
89 | |||
90 | void FreeSegmentList(SegmentsX *segmentsx) | ||
91 | { | ||
92 | amb | 256 | DeleteFile(segmentsx->filename); |
93 | amb | 283 | free(segmentsx->filename); |
94 | amb | 256 | |
95 | amb | 275 | if(segmentsx->idata) |
96 | free(segmentsx->idata); | ||
97 | amb | 226 | |
98 | amb | 279 | if(segmentsx->firstnode) |
99 | free(segmentsx->firstnode); | ||
100 | |||
101 | amb | 226 | if(segmentsx->sdata) |
102 | free(segmentsx->sdata); | ||
103 | |||
104 | amb | 110 | free(segmentsx); |
105 | } | ||
106 | |||
107 | |||
108 | /*++++++++++++++++++++++++++++++++++++++ | ||
109 | amb | 285 | Append a single segment to a segment list. |
110 | amb | 110 | |
111 | amb | 285 | SegmentsX* segmentsx The set of segments to process. |
112 | amb | 110 | |
113 | amb | 285 | way_t way The way that the segment belongs to. |
114 | |||
115 | node_t node1 The first node in the segment. | ||
116 | |||
117 | node_t node2 The second node in the segment. | ||
118 | |||
119 | distance_t distance The distance between the nodes (or just the flags). | ||
120 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
121 | |||
122 | amb | 285 | void AppendSegment(SegmentsX* segmentsx,way_t way,node_t node1,node_t node2,distance_t distance) |
123 | amb | 110 | { |
124 | amb | 285 | SegmentX segmentx; |
125 | amb | 110 | |
126 | amb | 285 | assert(!segmentsx->idata); /* Must not have idata filled in => unsorted */ |
127 | amb | 281 | |
128 | amb | 285 | segmentx.node1=node1; |
129 | segmentx.node2=node2; | ||
130 | segmentx.way=way; | ||
131 | segmentx.distance=distance; | ||
132 | amb | 110 | |
133 | amb | 285 | WriteFile(segmentsx->fd,&segmentx,sizeof(SegmentX)); |
134 | amb | 281 | |
135 | amb | 285 | segmentsx->xnumber++; |
136 | } | ||
137 | amb | 227 | |
138 | amb | 281 | |
139 | amb | 285 | /*++++++++++++++++++++++++++++++++++++++ |
140 | Sort the segment list. | ||
141 | amb | 232 | |
142 | amb | 285 | SegmentsX* segmentsx The set of segments to process. |
143 | ++++++++++++++++++++++++++++++++++++++*/ | ||
144 | amb | 110 | |
145 | amb | 285 | void SortSegmentList(SegmentsX* segmentsx) |
146 | { | ||
147 | int fd; | ||
148 | amb | 243 | |
149 | amb | 285 | /* Check the start conditions */ |
150 | amb | 243 | |
151 | amb | 285 | assert(!segmentsx->idata); /* Must not have idata filled in => unsorted */ |
152 | amb | 232 | |
153 | amb | 285 | /* Print the start message */ |
154 | amb | 232 | |
155 | amb | 285 | printf("Sorting Segments"); |
156 | fflush(stdout); | ||
157 | amb | 110 | |
158 | amb | 285 | /* Close the files and re-open them (finished appending) */ |
159 | amb | 110 | |
160 | amb | 285 | CloseFile(segmentsx->fd); |
161 | segmentsx->fd=ReOpenFile(segmentsx->filename); | ||
162 | amb | 110 | |
163 | amb | 285 | DeleteFile(segmentsx->filename); |
164 | amb | 110 | |
165 | amb | 285 | fd=OpenFile(segmentsx->filename); |
166 | amb | 110 | |
167 | amb | 285 | /* Sort by node indexes */ |
168 | amb | 132 | |
169 | amb | 310 | filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),SORT_RAMSIZE,(int (*)(const void*,const void*))sort_by_id,NULL); |
170 | amb | 285 | |
171 | segmentsx->number=segmentsx->xnumber; | ||
172 | |||
173 | /* Close the files and re-open them */ | ||
174 | |||
175 | CloseFile(segmentsx->fd); | ||
176 | amb | 281 | CloseFile(fd); |
177 | |||
178 | amb | 285 | segmentsx->fd=ReOpenFile(segmentsx->filename); |
179 | |||
180 | amb | 281 | /* Print the final message */ |
181 | |||
182 | amb | 285 | printf("\rSorted Segments: Segments=%d\n",segmentsx->xnumber); |
183 | amb | 132 | fflush(stdout); |
184 | amb | 110 | } |
185 | |||
186 | |||
187 | /*++++++++++++++++++++++++++++++++++++++ | ||
188 | amb | 285 | Sort the segments into id order (node1 then node2). |
189 | amb | 110 | |
190 | amb | 285 | int sort_by_id Returns the comparison of the node fields. |
191 | amb | 110 | |
192 | amb | 285 | SegmentX *a The first segment. |
193 | amb | 110 | |
194 | amb | 285 | SegmentX *b The second segment. |
195 | amb | 256 | ++++++++++++++++++++++++++++++++++++++*/ |
196 | |||
197 | amb | 285 | static int sort_by_id(SegmentX *a,SegmentX *b) |
198 | amb | 256 | { |
199 | amb | 285 | node_t a_id1=a->node1; |
200 | node_t b_id1=b->node1; | ||
201 | amb | 256 | |
202 | amb | 285 | if(a_id1<b_id1) |
203 | return(-1); | ||
204 | else if(a_id1>b_id1) | ||
205 | return(1); | ||
206 | else /* if(a_id1==b_id1) */ | ||
207 | amb | 256 | { |
208 | amb | 285 | node_t a_id2=a->node2; |
209 | node_t b_id2=b->node2; | ||
210 | amb | 256 | |
211 | amb | 285 | if(a_id2<b_id2) |
212 | return(-1); | ||
213 | else if(a_id2>b_id2) | ||
214 | return(1); | ||
215 | else | ||
216 | { | ||
217 | distance_t a_distance=a->distance; | ||
218 | distance_t b_distance=b->distance; | ||
219 | amb | 256 | |
220 | amb | 285 | if(a_distance<b_distance) |
221 | return(-1); | ||
222 | else if(a_distance>b_distance) | ||
223 | return(1); | ||
224 | else | ||
225 | return(0); | ||
226 | } | ||
227 | amb | 256 | } |
228 | } | ||
229 | |||
230 | |||
231 | /*++++++++++++++++++++++++++++++++++++++ | ||
232 | amb | 275 | Find the first segment index with a particular starting node. |
233 | amb | 257 | |
234 | amb | 275 | index_t IndexFirstSegmentX Returns a pointer to the index of the first extended segment with the specified id. |
235 | amb | 256 | |
236 | SegmentsX* segmentsx The set of segments to process. | ||
237 | |||
238 | amb | 110 | node_t node The node to look for. |
239 | ++++++++++++++++++++++++++++++++++++++*/ | ||
240 | |||
241 | amb | 275 | index_t IndexFirstSegmentX(SegmentsX* segmentsx,node_t node) |
242 | amb | 110 | { |
243 | int start=0; | ||
244 | int end=segmentsx->number-1; | ||
245 | int mid; | ||
246 | int found; | ||
247 | |||
248 | amb | 280 | /* Check if the first node index exists */ |
249 | |||
250 | amb | 279 | if(segmentsx->firstnode) |
251 | { | ||
252 | index_t index=segmentsx->firstnode[node]; | ||
253 | |||
254 | if(segmentsx->firstnode[node+1]==index) | ||
255 | return(NO_SEGMENT); | ||
256 | |||
257 | return(index); | ||
258 | } | ||
259 | |||
260 | amb | 275 | assert(segmentsx->idata); /* Must have idata filled in => sorted by node 1 */ |
261 | amb | 110 | |
262 | /* Binary search - search key exact match only is required. | ||
263 | * | ||
264 | * # <- start | Check mid and move start or end if it doesn't match | ||
265 | * # | | ||
266 | * # | Since an exact match is wanted we can set end=mid-1 | ||
267 | * # <- mid | or start=mid+1 because we know that mid doesn't match. | ||
268 | * # | | ||
269 | * # | Eventually either end=start or end=start+1 and one of | ||
270 | * # <- end | start or end is the wanted one. | ||
271 | */ | ||
272 | |||
273 | amb | 275 | if(end<start) /* There are no nodes */ |
274 | return(NO_SEGMENT); | ||
275 | else if(node<segmentsx->idata[start]) /* Check key is not before start */ | ||
276 | return(NO_SEGMENT); | ||
277 | else if(node>segmentsx->idata[end]) /* Check key is not after end */ | ||
278 | return(NO_SEGMENT); | ||
279 | amb | 257 | else |
280 | amb | 110 | { |
281 | amb | 257 | do |
282 | { | ||
283 | amb | 275 | mid=(start+end)/2; /* Choose mid point */ |
284 | amb | 110 | |
285 | amb | 275 | if(segmentsx->idata[mid]<node) /* Mid point is too low */ |
286 | amb | 257 | start=mid; |
287 | amb | 275 | else if(segmentsx->idata[mid]>node) /* Mid point is too high */ |
288 | amb | 257 | end=mid; |
289 | amb | 275 | else /* Mid point is correct */ |
290 | amb | 257 | {found=mid; goto found;} |
291 | } | ||
292 | while((end-start)>1); | ||
293 | amb | 110 | |
294 | amb | 275 | if(segmentsx->idata[start]==node) /* Start is correct */ |
295 | amb | 257 | {found=start; goto found;} |
296 | |||
297 | amb | 275 | if(segmentsx->idata[end]==node) /* End is correct */ |
298 | amb | 257 | {found=end; goto found;} |
299 | amb | 110 | } |
300 | |||
301 | amb | 275 | return(NO_SEGMENT); |
302 | amb | 110 | |
303 | found: | ||
304 | |||
305 | amb | 275 | while(found>0 && segmentsx->idata[found-1]==node) |
306 | amb | 110 | found--; |
307 | |||
308 | amb | 275 | return(found); |
309 | amb | 110 | } |
310 | |||
311 | |||
312 | /*++++++++++++++++++++++++++++++++++++++ | ||
313 | amb | 257 | Find the next segment index with a particular starting node. |
314 | amb | 110 | |
315 | amb | 275 | index_t IndexNextSegmentX Returns the index of the next segment with the same id. |
316 | amb | 110 | |
317 | SegmentsX* segmentsx The set of segments to process. | ||
318 | |||
319 | amb | 279 | index_t segindex The current segment index. |
320 | |||
321 | index_t nodeindex The node index. | ||
322 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
323 | |||
324 | amb | 279 | index_t IndexNextSegmentX(SegmentsX* segmentsx,index_t segindex,index_t nodeindex) |
325 | amb | 110 | { |
326 | amb | 279 | assert(segmentsx->firstnode); /* Must have firstnode filled in => segments updated */ |
327 | |||
328 | if(++segindex==segmentsx->firstnode[nodeindex+1]) | ||
329 | amb | 275 | return(NO_SEGMENT); |
330 | amb | 229 | else |
331 | amb | 279 | return(segindex); |
332 | amb | 110 | } |
333 | |||
334 | |||
335 | /*++++++++++++++++++++++++++++++++++++++ | ||
336 | amb | 285 | Lookup a particular segment. |
337 | amb | 110 | |
338 | amb | 285 | SegmentX *LookupSegmentX Returns a pointer to the extended segment with the specified id. |
339 | amb | 110 | |
340 | amb | 256 | SegmentsX* segmentsx The set of segments to process. |
341 | |||
342 | amb | 285 | index_t index The segment index to look for. |
343 | amb | 256 | |
344 | amb | 285 | int position The position in the cache to use. |
345 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
346 | |||
347 | amb | 285 | SegmentX *LookupSegmentX(SegmentsX* segmentsx,index_t index,int position) |
348 | amb | 110 | { |
349 | amb | 285 | assert(index!=NO_SEGMENT); /* Must be a valid segment */ |
350 | amb | 275 | |
351 | amb | 285 | if(option_slim) |
352 | amb | 110 | { |
353 | amb | 285 | SeekFile(segmentsx->fd,index*sizeof(SegmentX)); |
354 | amb | 110 | |
355 | amb | 285 | ReadFile(segmentsx->fd,&segmentsx->cached[position-1],sizeof(SegmentX)); |
356 | amb | 110 | |
357 | amb | 285 | return(&segmentsx->cached[position-1]); |
358 | amb | 110 | } |
359 | amb | 285 | else |
360 | { | ||
361 | return(&segmentsx->xdata[index]); | ||
362 | } | ||
363 | amb | 110 | } |
364 | |||
365 | |||
366 | /*++++++++++++++++++++++++++++++++++++++ | ||
367 | amb | 275 | Remove bad segments (duplicated, zero length or missing nodes). |
368 | amb | 110 | |
369 | amb | 195 | NodesX *nodesx The nodes to check. |
370 | |||
371 | amb | 110 | SegmentsX *segmentsx The segments to modify. |
372 | ++++++++++++++++++++++++++++++++++++++*/ | ||
373 | |||
374 | amb | 204 | void RemoveBadSegments(NodesX *nodesx,SegmentsX *segmentsx) |
375 | amb | 110 | { |
376 | amb | 275 | int duplicate=0,loop=0,missing=0,good=0,total=0; |
377 | SegmentX segmentx; | ||
378 | int fd; | ||
379 | node_t prevnode1=NO_NODE,prevnode2=NO_NODE; | ||
380 | amb | 110 | |
381 | amb | 275 | /* Print the start message */ |
382 | |||
383 | amb | 227 | printf("Checking: Segments=0 Duplicate=0 Loop=0 Missing-Node=0"); |
384 | fflush(stdout); | ||
385 | |||
386 | amb | 279 | /* Allocate the array of indexes */ |
387 | |||
388 | segmentsx->idata=(node_t*)malloc(segmentsx->xnumber*sizeof(node_t)); | ||
389 | |||
390 | assert(segmentsx->idata); /* Check malloc() worked */ | ||
391 | |||
392 | amb | 275 | /* Modify the on-disk image */ |
393 | |||
394 | DeleteFile(segmentsx->filename); | ||
395 | |||
396 | fd=OpenFile(segmentsx->filename); | ||
397 | SeekFile(segmentsx->fd,0); | ||
398 | |||
399 | while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX))) | ||
400 | amb | 110 | { |
401 | amb | 275 | if(prevnode1==segmentx.node1 && prevnode2==segmentx.node2) |
402 | duplicate++; | ||
403 | else if(segmentx.node1==segmentx.node2) | ||
404 | amb | 257 | loop++; |
405 | amb | 275 | else if(IndexNodeX(nodesx,segmentx.node1)==NO_NODE || |
406 | IndexNodeX(nodesx,segmentx.node2)==NO_NODE) | ||
407 | missing++; | ||
408 | else | ||
409 | amb | 257 | { |
410 | amb | 275 | WriteFile(fd,&segmentx,sizeof(SegmentX)); |
411 | |||
412 | amb | 279 | segmentsx->idata[good]=segmentx.node1; |
413 | amb | 275 | good++; |
414 | |||
415 | prevnode1=segmentx.node1; | ||
416 | prevnode2=segmentx.node2; | ||
417 | amb | 110 | } |
418 | |||
419 | amb | 275 | total++; |
420 | amb | 256 | |
421 | amb | 275 | if(!(total%10000)) |
422 | amb | 110 | { |
423 | amb | 275 | printf("\rChecking: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d",total,duplicate,loop,missing); |
424 | amb | 110 | fflush(stdout); |
425 | } | ||
426 | } | ||
427 | |||
428 | amb | 275 | /* Close the files and re-open them */ |
429 | |||
430 | CloseFile(segmentsx->fd); | ||
431 | CloseFile(fd); | ||
432 | |||
433 | segmentsx->fd=ReOpenFile(segmentsx->filename); | ||
434 | |||
435 | segmentsx->number=good; | ||
436 | |||
437 | /* Print the final message */ | ||
438 | |||
439 | printf("\rChecked: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d \n",total,duplicate,loop,missing); | ||
440 | amb | 110 | fflush(stdout); |
441 | } | ||
442 | |||
443 | |||
444 | /*++++++++++++++++++++++++++++++++++++++ | ||
445 | amb | 285 | Measure the segments and replace node/way ids with indexes. |
446 | amb | 110 | |
447 | SegmentsX* segmentsx The set of segments to process. | ||
448 | |||
449 | NodesX *nodesx The list of nodes to use. | ||
450 | amb | 279 | |
451 | WaysX *waysx The list of ways to use. | ||
452 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
453 | |||
454 | amb | 279 | void UpdateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx) |
455 | amb | 110 | { |
456 | amb | 279 | index_t index=0; |
457 | int i,fd; | ||
458 | amb | 256 | SegmentX segmentx; |
459 | amb | 110 | |
460 | amb | 275 | /* Print the start message */ |
461 | |||
462 | amb | 227 | printf("Measuring Segments: Segments=0"); |
463 | fflush(stdout); | ||
464 | |||
465 | amb | 275 | /* Map into memory */ |
466 | amb | 257 | |
467 | amb | 258 | if(!option_slim) |
468 | amb | 275 | nodesx->xdata=MapFile(nodesx->filename); |
469 | amb | 258 | |
470 | amb | 280 | /* Free the now-unneeded index */ |
471 | |||
472 | free(segmentsx->idata); | ||
473 | segmentsx->idata=NULL; | ||
474 | |||
475 | amb | 279 | /* Allocate the array of indexes */ |
476 | |||
477 | segmentsx->firstnode=(index_t*)malloc((nodesx->number+1)*sizeof(index_t)); | ||
478 | |||
479 | assert(segmentsx->firstnode); /* Check malloc() worked */ | ||
480 | |||
481 | for(i=0;i<nodesx->number;i++) | ||
482 | segmentsx->firstnode[i]=NO_SEGMENT; | ||
483 | |||
484 | segmentsx->firstnode[nodesx->number]=segmentsx->number; | ||
485 | |||
486 | amb | 275 | /* Modify the on-disk image */ |
487 | |||
488 | amb | 256 | DeleteFile(segmentsx->filename); |
489 | |||
490 | fd=OpenFile(segmentsx->filename); | ||
491 | SeekFile(segmentsx->fd,0); | ||
492 | |||
493 | while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX))) | ||
494 | amb | 110 | { |
495 | amb | 279 | index_t node1=IndexNodeX(nodesx,segmentx.node1); |
496 | index_t node2=IndexNodeX(nodesx,segmentx.node2); | ||
497 | index_t way =IndexWayX (waysx ,segmentx.way); | ||
498 | amb | 110 | |
499 | amb | 279 | NodeX *nodex1=LookupNodeX(nodesx,node1,1); |
500 | NodeX *nodex2=LookupNodeX(nodesx,node2,2); | ||
501 | |||
502 | /* Replace the node and way ids with their indexes */ | ||
503 | |||
504 | segmentx.node1=node1; | ||
505 | segmentx.node2=node2; | ||
506 | segmentx.way =way; | ||
507 | |||
508 | amb | 275 | /* Set the distance but preserve the ONEWAY_* flags */ |
509 | |||
510 | segmentx.distance|=DISTANCE(DistanceX(nodex1,nodex2)); | ||
511 | |||
512 | amb | 279 | /* Set the first segment index in the nodes */ |
513 | |||
514 | if(index<segmentsx->firstnode[node1]) | ||
515 | segmentsx->firstnode[node1]=index; | ||
516 | |||
517 | /* Write the modified segment */ | ||
518 | |||
519 | amb | 275 | WriteFile(fd,&segmentx,sizeof(SegmentX)); |
520 | |||
521 | amb | 279 | index++; |
522 | amb | 275 | |
523 | amb | 279 | if(!(index%10000)) |
524 | amb | 257 | { |
525 | amb | 279 | printf("\rMeasuring Segments: Segments=%d",index); |
526 | amb | 275 | fflush(stdout); |
527 | } | ||
528 | } | ||
529 | amb | 110 | |
530 | amb | 275 | /* Close the files and re-open them */ |
531 | amb | 257 | |
532 | amb | 275 | CloseFile(segmentsx->fd); |
533 | CloseFile(fd); | ||
534 | |||
535 | segmentsx->fd=ReOpenFile(segmentsx->filename); | ||
536 | |||
537 | amb | 280 | /* Free the other now-unneeded indexes */ |
538 | amb | 279 | |
539 | free(nodesx->idata); | ||
540 | nodesx->idata=NULL; | ||
541 | |||
542 | free(waysx->idata); | ||
543 | waysx->idata=NULL; | ||
544 | |||
545 | amb | 275 | /* Unmap from memory */ |
546 | |||
547 | if(!option_slim) | ||
548 | nodesx->xdata=UnmapFile(nodesx->filename); | ||
549 | |||
550 | /* Print the final message */ | ||
551 | |||
552 | printf("\rMeasured Segments: Segments=%d \n",segmentsx->number); | ||
553 | fflush(stdout); | ||
554 | } | ||
555 | |||
556 | |||
557 | /*++++++++++++++++++++++++++++++++++++++ | ||
558 | Make the segments all point the same way (node1<node2). | ||
559 | |||
560 | SegmentsX* segmentsx The set of segments to process. | ||
561 | ++++++++++++++++++++++++++++++++++++++*/ | ||
562 | |||
563 | void RotateSegments(SegmentsX* segmentsx) | ||
564 | { | ||
565 | int index=0,rotated=0; | ||
566 | int fd; | ||
567 | SegmentX segmentx; | ||
568 | |||
569 | /* Check the start conditions */ | ||
570 | |||
571 | assert(!segmentsx->idata); /* Must not have idata filled in => not sorted by node 1 */ | ||
572 | |||
573 | /* Print the start message */ | ||
574 | |||
575 | printf("Rotating Segments: Segments=0 Rotated=0"); | ||
576 | fflush(stdout); | ||
577 | |||
578 | /* Close the files and re-open them (finished appending) */ | ||
579 | |||
580 | CloseFile(segmentsx->fd); | ||
581 | segmentsx->fd=ReOpenFile(segmentsx->filename); | ||
582 | |||
583 | DeleteFile(segmentsx->filename); | ||
584 | |||
585 | fd=OpenFile(segmentsx->filename); | ||
586 | |||
587 | /* Modify the file contents */ | ||
588 | |||
589 | while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX))) | ||
590 | { | ||
591 | if(segmentx.node1>segmentx.node2) | ||
592 | { | ||
593 | node_t temp; | ||
594 | |||
595 | temp=segmentx.node1; | ||
596 | segmentx.node1=segmentx.node2; | ||
597 | segmentx.node2=temp; | ||
598 | |||
599 | if(segmentx.distance&(ONEWAY_2TO1|ONEWAY_1TO2)) | ||
600 | segmentx.distance^=ONEWAY_2TO1|ONEWAY_1TO2; | ||
601 | |||
602 | rotated++; | ||
603 | amb | 257 | } |
604 | amb | 110 | |
605 | amb | 256 | WriteFile(fd,&segmentx,sizeof(SegmentX)); |
606 | |||
607 | amb | 275 | index++; |
608 | amb | 256 | |
609 | amb | 275 | if(!(index%10000)) |
610 | amb | 110 | { |
611 | amb | 275 | printf("\rRotating Segments: Segments=%d Rotated=%d",index,rotated); |
612 | amb | 110 | fflush(stdout); |
613 | } | ||
614 | } | ||
615 | |||
616 | amb | 275 | /* Close the files and re-open them */ |
617 | |||
618 | amb | 256 | CloseFile(segmentsx->fd); |
619 | CloseFile(fd); | ||
620 | |||
621 | segmentsx->fd=ReOpenFile(segmentsx->filename); | ||
622 | |||
623 | amb | 275 | /* Print the final message */ |
624 | amb | 256 | |
625 | amb | 275 | printf("\rRotated Segments: Segments=%d Rotated=%d \n",index,rotated); |
626 | amb | 110 | fflush(stdout); |
627 | } | ||
628 | |||
629 | |||
630 | /*++++++++++++++++++++++++++++++++++++++ | ||
631 | amb | 275 | Remove the duplicate segments. |
632 | amb | 110 | |
633 | SegmentsX* segmentsx The set of segments to process. | ||
634 | |||
635 | amb | 279 | NodesX *nodesx The list of nodes to use. |
636 | |||
637 | amb | 110 | WaysX *waysx The list of ways to use. |
638 | ++++++++++++++++++++++++++++++++++++++*/ | ||
639 | |||
640 | amb | 279 | void DeduplicateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx) |
641 | amb | 110 | { |
642 | amb | 275 | int duplicate=0,good=0; |
643 | index_t firstindex=0,index=0; | ||
644 | amb | 279 | int i,fd; |
645 | amb | 275 | SegmentX prevsegmentx[16],segmentx; |
646 | amb | 110 | |
647 | amb | 275 | /* Print the start message */ |
648 | |||
649 | amb | 227 | printf("Deduplicating Segments: Segments=0 Duplicate=0"); |
650 | fflush(stdout); | ||
651 | |||
652 | amb | 275 | /* Map into memory */ |
653 | amb | 256 | |
654 | amb | 275 | if(!option_slim) |
655 | waysx->xdata=MapFile(waysx->filename); | ||
656 | |||
657 | amb | 279 | /* Allocate the array of indexes */ |
658 | |||
659 | segmentsx->firstnode=(index_t*)malloc((nodesx->number+1)*sizeof(index_t)); | ||
660 | |||
661 | assert(segmentsx->firstnode); /* Check malloc() worked */ | ||
662 | |||
663 | for(i=0;i<nodesx->number;i++) | ||
664 | segmentsx->firstnode[i]=NO_SEGMENT; | ||
665 | |||
666 | segmentsx->firstnode[nodesx->number]=segmentsx->number; | ||
667 | |||
668 | amb | 275 | /* Modify the on-disk image */ |
669 | |||
670 | DeleteFile(segmentsx->filename); | ||
671 | |||
672 | fd=OpenFile(segmentsx->filename); | ||
673 | SeekFile(segmentsx->fd,0); | ||
674 | |||
675 | while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX))) | ||
676 | amb | 110 | { |
677 | amb | 275 | int isduplicate=0; |
678 | amb | 256 | |
679 | amb | 275 | if(index && segmentx.node1==prevsegmentx[0].node1 && |
680 | segmentx.node2==prevsegmentx[0].node2) | ||
681 | amb | 110 | { |
682 | amb | 264 | index_t previndex=firstindex; |
683 | amb | 110 | |
684 | amb | 275 | while(previndex<index) |
685 | amb | 110 | { |
686 | amb | 275 | int offset=previndex-firstindex; |
687 | |||
688 | if(DISTFLAG(segmentx.distance)==DISTFLAG(prevsegmentx[offset].distance)) | ||
689 | amb | 264 | { |
690 | amb | 279 | WayX *wayx1=LookupWayX(waysx,prevsegmentx[offset].way,1); |
691 | WayX *wayx2=LookupWayX(waysx, segmentx .way,2); | ||
692 | amb | 110 | |
693 | amb | 275 | if(!WaysCompare(&wayx1->way,&wayx2->way)) |
694 | amb | 264 | { |
695 | amb | 275 | isduplicate=1; |
696 | duplicate++; | ||
697 | break; | ||
698 | amb | 264 | } |
699 | } | ||
700 | |||
701 | previndex++; | ||
702 | amb | 110 | } |
703 | amb | 275 | |
704 | assert((index-firstindex)<(sizeof(prevsegmentx)/sizeof(prevsegmentx[0]))); | ||
705 | |||
706 | prevsegmentx[index-firstindex]=segmentx; | ||
707 | amb | 110 | } |
708 | amb | 264 | else |
709 | { | ||
710 | amb | 275 | firstindex=index; |
711 | prevsegmentx[0]=segmentx; | ||
712 | amb | 264 | } |
713 | amb | 110 | |
714 | amb | 275 | if(!isduplicate) |
715 | amb | 110 | { |
716 | amb | 275 | WriteFile(fd,&segmentx,sizeof(SegmentX)); |
717 | |||
718 | amb | 279 | if(good<segmentsx->firstnode[segmentx.node1]) |
719 | segmentsx->firstnode[segmentx.node1]=good; | ||
720 | |||
721 | amb | 275 | good++; |
722 | } | ||
723 | |||
724 | index++; | ||
725 | |||
726 | if(!(index%10000)) | ||
727 | { | ||
728 | printf("\rDeduplicating Segments: Segments=%d Duplicate=%d",index,duplicate); | ||
729 | amb | 110 | fflush(stdout); |
730 | } | ||
731 | } | ||
732 | |||
733 | amb | 275 | /* Close the files and re-open them */ |
734 | |||
735 | CloseFile(segmentsx->fd); | ||
736 | CloseFile(fd); | ||
737 | |||
738 | segmentsx->fd=ReOpenFile(segmentsx->filename); | ||
739 | |||
740 | amb | 279 | segmentsx->number=good; |
741 | amb | 275 | |
742 | amb | 279 | /* Fix-up the firstnode index for the missing nodes */ |
743 | amb | 275 | |
744 | amb | 279 | for(i=nodesx->number-1;i>=0;i--) |
745 | if(segmentsx->firstnode[i]==NO_SEGMENT) | ||
746 | segmentsx->firstnode[i]=segmentsx->firstnode[i+1]; | ||
747 | amb | 275 | |
748 | /* Unmap from memory */ | ||
749 | |||
750 | if(!option_slim) | ||
751 | waysx->xdata=UnmapFile(waysx->filename); | ||
752 | |||
753 | /* Print the final message */ | ||
754 | |||
755 | printf("\rDeduplicated Segments: Segments=%d Duplicate=%d Unique=%d\n",index,duplicate,index-duplicate); | ||
756 | amb | 110 | fflush(stdout); |
757 | } | ||
758 | |||
759 | |||
760 | /*++++++++++++++++++++++++++++++++++++++ | ||
761 | amb | 209 | Create the real segments data. |
762 | |||
763 | SegmentsX* segmentsx The set of segments to use. | ||
764 | |||
765 | WaysX* waysx The set of ways to use. | ||
766 | ++++++++++++++++++++++++++++++++++++++*/ | ||
767 | |||
768 | void CreateRealSegments(SegmentsX *segmentsx,WaysX *waysx) | ||
769 | { | ||
770 | amb | 214 | index_t i; |
771 | amb | 209 | |
772 | amb | 275 | /* Check the start conditions */ |
773 | |||
774 | amb | 243 | assert(!segmentsx->sdata); /* Must not have sdata filled in => no real segments */ |
775 | amb | 213 | |
776 | amb | 275 | /* Print the start message */ |
777 | |||
778 | amb | 227 | printf("Creating Real Segments: Segments=0"); |
779 | fflush(stdout); | ||
780 | |||
781 | amb | 275 | /* Map into memory */ |
782 | amb | 209 | |
783 | amb | 275 | if(!option_slim) |
784 | { | ||
785 | segmentsx->xdata=MapFile(segmentsx->filename); | ||
786 | waysx->xdata=MapFile(waysx->filename); | ||
787 | } | ||
788 | |||
789 | amb | 280 | /* Free the unneeded memory */ |
790 | |||
791 | free(segmentsx->firstnode); | ||
792 | segmentsx->firstnode=NULL; | ||
793 | |||
794 | amb | 279 | /* Allocate the memory */ |
795 | amb | 275 | |
796 | amb | 209 | segmentsx->sdata=(Segment*)malloc(segmentsx->number*sizeof(Segment)); |
797 | |||
798 | amb | 243 | assert(segmentsx->sdata); /* Check malloc() worked */ |
799 | |||
800 | amb | 275 | /* Loop through and fill */ |
801 | amb | 209 | |
802 | for(i=0;i<segmentsx->number;i++) | ||
803 | { | ||
804 | amb | 275 | SegmentX *segmentx=LookupSegmentX(segmentsx,i,1); |
805 | amb | 279 | WayX *wayx=LookupWayX(waysx,segmentx->way,1); |
806 | amb | 209 | |
807 | segmentsx->sdata[i].node1=0; | ||
808 | segmentsx->sdata[i].node2=0; | ||
809 | segmentsx->sdata[i].next2=NO_NODE; | ||
810 | amb | 310 | segmentsx->sdata[i].way=wayx->prop; |
811 | amb | 256 | segmentsx->sdata[i].distance=segmentx->distance; |
812 | amb | 209 | |
813 | if(!((i+1)%10000)) | ||
814 | { | ||
815 | printf("\rCreating Real Segments: Segments=%d",i+1); | ||
816 | fflush(stdout); | ||
817 | } | ||
818 | } | ||
819 | |||
820 | amb | 275 | /* Unmap from memory */ |
821 | |||
822 | if(!option_slim) | ||
823 | { | ||
824 | segmentsx->xdata=UnmapFile(segmentsx->filename); | ||
825 | waysx->xdata=UnmapFile(waysx->filename); | ||
826 | } | ||
827 | |||
828 | /* Print the final message */ | ||
829 | |||
830 | amb | 209 | printf("\rCreating Real Segments: Segments=%d \n",segmentsx->number); |
831 | fflush(stdout); | ||
832 | } | ||
833 | |||
834 | |||
835 | /*++++++++++++++++++++++++++++++++++++++ | ||
836 | amb | 110 | Assign the nodes indexes to the segments. |
837 | |||
838 | SegmentsX* segmentsx The set of segments to process. | ||
839 | |||
840 | NodesX *nodesx The list of nodes to use. | ||
841 | ++++++++++++++++++++++++++++++++++++++*/ | ||
842 | |||
843 | void IndexSegments(SegmentsX* segmentsx,NodesX *nodesx) | ||
844 | { | ||
845 | amb | 214 | index_t i; |
846 | amb | 110 | |
847 | amb | 275 | /* Check the start conditions */ |
848 | |||
849 | amb | 281 | assert(nodesx->ndata); /* Must have ndata filled in => real nodes exist */ |
850 | assert(segmentsx->sdata); /* Must have sdata filled in => real segments exist */ | ||
851 | amb | 110 | |
852 | amb | 275 | /* Print the start message */ |
853 | |||
854 | amb | 227 | printf("Indexing Nodes: Nodes=0"); |
855 | fflush(stdout); | ||
856 | |||
857 | amb | 275 | /* Map into memory */ |
858 | |||
859 | if(!option_slim) | ||
860 | amb | 281 | { |
861 | nodesx->xdata=MapFile(nodesx->filename); | ||
862 | amb | 275 | segmentsx->xdata=MapFile(segmentsx->filename); |
863 | amb | 281 | } |
864 | amb | 275 | |
865 | amb | 110 | /* Index the segments */ |
866 | |||
867 | for(i=0;i<nodesx->number;i++) | ||
868 | { | ||
869 | amb | 281 | NodeX *nodex=LookupNodeX(nodesx,i,1); |
870 | Node *node =&nodesx->ndata[nodex->id]; | ||
871 | amb | 212 | index_t index=SEGMENT(node->firstseg); |
872 | amb | 110 | |
873 | do | ||
874 | { | ||
875 | amb | 275 | SegmentX *segmentx=LookupSegmentX(segmentsx,index,1); |
876 | amb | 256 | |
877 | amb | 281 | if(segmentx->node1==nodex->id) |
878 | amb | 110 | { |
879 | amb | 209 | segmentsx->sdata[index].node1=i; |
880 | amb | 110 | |
881 | amb | 209 | index++; |
882 | amb | 128 | |
883 | amb | 256 | if(index>=segmentsx->number) |
884 | amb | 209 | break; |
885 | amb | 256 | |
886 | amb | 275 | segmentx=LookupSegmentX(segmentsx,index,1); |
887 | amb | 256 | |
888 | amb | 281 | if(segmentx->node1!=nodex->id) |
889 | amb | 256 | break; |
890 | amb | 110 | } |
891 | else | ||
892 | { | ||
893 | amb | 209 | segmentsx->sdata[index].node2=i; |
894 | amb | 110 | |
895 | amb | 209 | if(segmentsx->sdata[index].next2==NO_NODE) |
896 | break; | ||
897 | amb | 110 | else |
898 | amb | 209 | index=segmentsx->sdata[index].next2; |
899 | amb | 110 | } |
900 | } | ||
901 | amb | 209 | while(1); |
902 | amb | 110 | |
903 | if(!((i+1)%10000)) | ||
904 | { | ||
905 | printf("\rIndexing Nodes: Nodes=%d",i+1); | ||
906 | fflush(stdout); | ||
907 | } | ||
908 | } | ||
909 | |||
910 | amb | 275 | /* Unmap from memory */ |
911 | |||
912 | if(!option_slim) | ||
913 | amb | 281 | { |
914 | nodesx->xdata=UnmapFile(nodesx->filename); | ||
915 | amb | 275 | segmentsx->xdata=UnmapFile(segmentsx->filename); |
916 | amb | 281 | } |
917 | amb | 275 | |
918 | /* Print the final message */ | ||
919 | |||
920 | amb | 110 | printf("\rIndexed Nodes: Nodes=%d \n",nodesx->number); |
921 | fflush(stdout); | ||
922 | } | ||
923 | |||
924 | |||
925 | /*++++++++++++++++++++++++++++++++++++++ | ||
926 | amb | 285 | Save the segment list to a file. |
927 | |||
928 | SegmentsX* segmentsx The set of segments to save. | ||
929 | |||
930 | const char *filename The name of the file to save. | ||
931 | ++++++++++++++++++++++++++++++++++++++*/ | ||
932 | |||
933 | void SaveSegmentList(SegmentsX* segmentsx,const char *filename) | ||
934 | { | ||
935 | index_t i; | ||
936 | int fd; | ||
937 | Segments *segments; | ||
938 | int super_number=0,normal_number=0; | ||
939 | |||
940 | /* Check the start conditions */ | ||
941 | |||
942 | assert(segmentsx->sdata); /* Must have sdata filled in => real segments */ | ||
943 | |||
944 | /* Print the start message */ | ||
945 | |||
946 | printf("Writing Segments: Segments=0"); | ||
947 | fflush(stdout); | ||
948 | |||
949 | /* Count the number of super-segments and normal segments */ | ||
950 | |||
951 | for(i=0;i<segmentsx->number;i++) | ||
952 | { | ||
953 | if(IsSuperSegment(&segmentsx->sdata[i])) | ||
954 | super_number++; | ||
955 | if(IsNormalSegment(&segmentsx->sdata[i])) | ||
956 | normal_number++; | ||
957 | } | ||
958 | |||
959 | /* Fill in a Segments structure with the offset of the real data in the file after | ||
960 | the Segment structure itself. */ | ||
961 | |||
962 | segments=calloc(1,sizeof(Segments)); | ||
963 | |||
964 | assert(segments); /* Check calloc() worked */ | ||
965 | |||
966 | segments->number=segmentsx->number; | ||
967 | segments->snumber=super_number; | ||
968 | segments->nnumber=normal_number; | ||
969 | |||
970 | segments->data=NULL; | ||
971 | |||
972 | segments->segments=(void*)sizeof(Segments); | ||
973 | |||
974 | /* Write out the Segments structure and then the real data. */ | ||
975 | |||
976 | fd=OpenFile(filename); | ||
977 | |||
978 | WriteFile(fd,segments,sizeof(Segments)); | ||
979 | |||
980 | for(i=0;i<segments->number;i++) | ||
981 | { | ||
982 | WriteFile(fd,&segmentsx->sdata[i],sizeof(Segment)); | ||
983 | |||
984 | if(!((i+1)%10000)) | ||
985 | { | ||
986 | printf("\rWriting Segments: Segments=%d",i+1); | ||
987 | fflush(stdout); | ||
988 | } | ||
989 | } | ||
990 | |||
991 | CloseFile(fd); | ||
992 | |||
993 | /* Print the final message */ | ||
994 | |||
995 | printf("\rWrote Segments: Segments=%d \n",segments->number); | ||
996 | fflush(stdout); | ||
997 | |||
998 | /* Free the fake Segments */ | ||
999 | |||
1000 | free(segments); | ||
1001 | } | ||
1002 | |||
1003 | |||
1004 | /*++++++++++++++++++++++++++++++++++++++ | ||
1005 | amb | 110 | Calculate the distance between two nodes. |
1006 | |||
1007 | distance_t DistanceX Returns the distance between the extended nodes. | ||
1008 | |||
1009 | NodeX *nodex1 The starting node. | ||
1010 | |||
1011 | NodeX *nodex2 The end node. | ||
1012 | ++++++++++++++++++++++++++++++++++++++*/ | ||
1013 | |||
1014 | amb | 228 | static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2) |
1015 | amb | 110 | { |
1016 | amb | 223 | double dlon = latlong_to_radians(nodex1->longitude) - latlong_to_radians(nodex2->longitude); |
1017 | double dlat = latlong_to_radians(nodex1->latitude) - latlong_to_radians(nodex2->latitude); | ||
1018 | double lat1 = latlong_to_radians(nodex1->latitude); | ||
1019 | double lat2 = latlong_to_radians(nodex2->latitude); | ||
1020 | amb | 110 | |
1021 | amb | 219 | double a1,a2,a,sa,c,d; |
1022 | amb | 110 | |
1023 | if(dlon==0 && dlat==0) | ||
1024 | return 0; | ||
1025 | |||
1026 | amb | 219 | a1 = sin (dlat / 2); |
1027 | a2 = sin (dlon / 2); | ||
1028 | a = (a1 * a1) + cos (lat1) * cos (lat2) * a2 * a2; | ||
1029 | sa = sqrt (a); | ||
1030 | amb | 110 | if (sa <= 1.0) |
1031 | amb | 219 | {c = 2 * asin (sa);} |
1032 | amb | 110 | else |
1033 | amb | 219 | {c = 2 * asin (1.0);} |
1034 | amb | 110 | d = 6378.137 * c; |
1035 | |||
1036 | return km_to_distance(d); | ||
1037 | } |
Properties
Name | Value |
---|---|
cvs:description | Extended segments functions. |