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 229 -
(hide annotations)
(download)
(as text)
Sun Jul 19 12:54:07 2009 UTC (15 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 21886 byte(s)
Sun Jul 19 12:54:07 2009 UTC (15 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 21886 byte(s)
Store only one copy of each segment but index once for each direction.
1 | amb | 110 | /*************************************** |
2 | amb | 229 | $Header: /home/amb/CVS/routino/src/segmentsx.c,v 1.28 2009-07-19 12:54:07 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 | |||
30 | #include "types.h" | ||
31 | #include "functions.h" | ||
32 | #include "nodesx.h" | ||
33 | #include "segmentsx.h" | ||
34 | #include "waysx.h" | ||
35 | amb | 228 | #include "nodes.h" |
36 | #include "segments.h" | ||
37 | #include "ways.h" | ||
38 | amb | 110 | |
39 | |||
40 | /* Constants */ | ||
41 | |||
42 | amb | 229 | /*+ The array size increment for SegmentsX (UK is ~7.1M raw segments, this is ~53 increments). +*/ |
43 | #define INCREMENT_SEGMENTSX (128*1024) | ||
44 | amb | 110 | |
45 | |||
46 | amb | 228 | /* Local Functions */ |
47 | amb | 110 | |
48 | amb | 229 | static int sort_by_id1_and_distance(SegmentX **a,SegmentX **b); |
49 | static int sort_by_id2_and_distance(SegmentX **a,SegmentX **b); | ||
50 | static SegmentX **find_first1_segmentx(SegmentsX* segmentsx,node_t node); | ||
51 | static SegmentX **find_first2_segmentx(SegmentsX* segmentsx,node_t node); | ||
52 | amb | 228 | static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2); |
53 | amb | 110 | |
54 | |||
55 | /*++++++++++++++++++++++++++++++++++++++ | ||
56 | Allocate a new segment list. | ||
57 | |||
58 | SegmentsX *NewSegmentList Returns the segment list. | ||
59 | ++++++++++++++++++++++++++++++++++++++*/ | ||
60 | |||
61 | SegmentsX *NewSegmentList(void) | ||
62 | { | ||
63 | SegmentsX *segmentsx; | ||
64 | |||
65 | amb | 213 | segmentsx=(SegmentsX*)calloc(1,sizeof(SegmentsX)); |
66 | amb | 110 | |
67 | amb | 216 | segmentsx->row=-1; |
68 | |||
69 | amb | 110 | return(segmentsx); |
70 | } | ||
71 | |||
72 | |||
73 | /*++++++++++++++++++++++++++++++++++++++ | ||
74 | amb | 226 | Free a segment list. |
75 | amb | 110 | |
76 | SegmentsX *segmentsx The list to be freed. | ||
77 | ++++++++++++++++++++++++++++++++++++++*/ | ||
78 | |||
79 | void FreeSegmentList(SegmentsX *segmentsx) | ||
80 | { | ||
81 | amb | 213 | if(segmentsx->xdata) |
82 | amb | 222 | { |
83 | int i; | ||
84 | amb | 225 | for(i=0;i<=segmentsx->row;i++) |
85 | amb | 222 | free(segmentsx->xdata[i]); |
86 | amb | 213 | free(segmentsx->xdata); |
87 | amb | 222 | } |
88 | amb | 226 | |
89 | amb | 229 | if(segmentsx->n1data) |
90 | free(segmentsx->n1data); | ||
91 | amb | 226 | |
92 | amb | 229 | if(segmentsx->n2data) |
93 | free(segmentsx->n2data); | ||
94 | |||
95 | amb | 226 | if(segmentsx->sdata) |
96 | free(segmentsx->sdata); | ||
97 | |||
98 | amb | 110 | free(segmentsx); |
99 | } | ||
100 | |||
101 | |||
102 | /*++++++++++++++++++++++++++++++++++++++ | ||
103 | Save the segment list to a file. | ||
104 | |||
105 | SegmentsX* segmentsx The set of segments to save. | ||
106 | |||
107 | const char *filename The name of the file to save. | ||
108 | ++++++++++++++++++++++++++++++++++++++*/ | ||
109 | |||
110 | void SaveSegmentList(SegmentsX* segmentsx,const char *filename) | ||
111 | { | ||
112 | amb | 214 | index_t i; |
113 | amb | 110 | int fd; |
114 | Segments *segments=calloc(1,sizeof(Segments)); | ||
115 | |||
116 | assert(segmentsx->sorted); /* Must be sorted */ | ||
117 | amb | 213 | assert(segmentsx->sdata); /* Must have sdata filled in */ |
118 | amb | 110 | |
119 | amb | 227 | printf("Writing Segments: Segments=0"); |
120 | fflush(stdout); | ||
121 | |||
122 | amb | 110 | /* Fill in a Segments structure with the offset of the real data in the file after |
123 | the Segment structure itself. */ | ||
124 | |||
125 | segments->number=segmentsx->number; | ||
126 | segments->data=NULL; | ||
127 | segments->segments=(void*)sizeof(Segments); | ||
128 | |||
129 | /* Write out the Segments structure and then the real data. */ | ||
130 | |||
131 | fd=OpenFile(filename); | ||
132 | |||
133 | WriteFile(fd,segments,sizeof(Segments)); | ||
134 | |||
135 | amb | 203 | for(i=0;i<segments->number;i++) |
136 | amb | 132 | { |
137 | amb | 209 | WriteFile(fd,&segmentsx->sdata[i],sizeof(Segment)); |
138 | amb | 110 | |
139 | amb | 132 | if(!((i+1)%10000)) |
140 | { | ||
141 | printf("\rWriting Segments: Segments=%d",i+1); | ||
142 | fflush(stdout); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | amb | 203 | printf("\rWrote Segments: Segments=%d \n",segments->number); |
147 | amb | 132 | fflush(stdout); |
148 | |||
149 | amb | 110 | CloseFile(fd); |
150 | |||
151 | /* Free the fake Segments */ | ||
152 | |||
153 | free(segments); | ||
154 | } | ||
155 | |||
156 | |||
157 | /*++++++++++++++++++++++++++++++++++++++ | ||
158 | Find the first segment with a particular starting node. | ||
159 | |||
160 | SegmentX **FindFirstSegmentX Returns a pointer to the first extended segment with the specified id. | ||
161 | |||
162 | SegmentsX* segmentsx The set of segments to process. | ||
163 | |||
164 | node_t node The node to look for. | ||
165 | ++++++++++++++++++++++++++++++++++++++*/ | ||
166 | |||
167 | SegmentX **FindFirstSegmentX(SegmentsX* segmentsx,node_t node) | ||
168 | { | ||
169 | amb | 229 | SegmentX **first=find_first1_segmentx(segmentsx,node); |
170 | |||
171 | if(first) | ||
172 | return(first); | ||
173 | |||
174 | return(find_first2_segmentx(segmentsx,node)); | ||
175 | } | ||
176 | |||
177 | |||
178 | /*++++++++++++++++++++++++++++++++++++++ | ||
179 | Find the first segment with a particular starting node in either n1data or n2data. | ||
180 | |||
181 | SegmentX **find_first1_segmentx Returns a pointer to the first extended segment with the specified id. | ||
182 | |||
183 | SegmentsX* segmentsx The set of segments to process. | ||
184 | |||
185 | node_t node The node to look for. | ||
186 | ++++++++++++++++++++++++++++++++++++++*/ | ||
187 | |||
188 | static SegmentX **find_first1_segmentx(SegmentsX* segmentsx,node_t node) | ||
189 | { | ||
190 | amb | 110 | int start=0; |
191 | int end=segmentsx->number-1; | ||
192 | int mid; | ||
193 | int found; | ||
194 | |||
195 | assert(segmentsx->sorted); /* Must be sorted */ | ||
196 | amb | 229 | assert(segmentsx->n1data); /* Must have n1data filled in */ |
197 | amb | 110 | |
198 | /* Binary search - search key exact match only is required. | ||
199 | * | ||
200 | * # <- start | Check mid and move start or end if it doesn't match | ||
201 | * # | | ||
202 | * # | Since an exact match is wanted we can set end=mid-1 | ||
203 | * # <- mid | or start=mid+1 because we know that mid doesn't match. | ||
204 | * # | | ||
205 | * # | Eventually either end=start or end=start+1 and one of | ||
206 | * # <- end | start or end is the wanted one. | ||
207 | */ | ||
208 | |||
209 | amb | 229 | if(end<start) /* There are no nodes */ |
210 | amb | 110 | return(NULL); |
211 | amb | 229 | else if(node<segmentsx->n1data[start]->node1) /* Check key is not before start */ |
212 | amb | 110 | return(NULL); |
213 | amb | 229 | else if(node>segmentsx->n1data[end]->node1) /* Check key is not after end */ |
214 | amb | 110 | return(NULL); |
215 | else | ||
216 | { | ||
217 | do | ||
218 | { | ||
219 | amb | 229 | mid=(start+end)/2; /* Choose mid point */ |
220 | amb | 110 | |
221 | amb | 229 | if(segmentsx->n1data[mid]->node1<node) /* Mid point is too low */ |
222 | amb | 110 | start=mid; |
223 | amb | 229 | else if(segmentsx->n1data[mid]->node1>node) /* Mid point is too high */ |
224 | amb | 110 | end=mid; |
225 | amb | 229 | else /* Mid point is correct */ |
226 | amb | 110 | {found=mid; goto found;} |
227 | } | ||
228 | while((end-start)>1); | ||
229 | |||
230 | amb | 229 | if(segmentsx->n1data[start]->node1==node) /* Start is correct */ |
231 | amb | 110 | {found=start; goto found;} |
232 | |||
233 | amb | 229 | if(segmentsx->n1data[end]->node1==node) /* End is correct */ |
234 | amb | 110 | {found=end; goto found;} |
235 | } | ||
236 | |||
237 | return(NULL); | ||
238 | |||
239 | found: | ||
240 | |||
241 | amb | 229 | while(found>0 && segmentsx->n1data[found-1]->node1==node) |
242 | amb | 110 | found--; |
243 | |||
244 | amb | 229 | return(&segmentsx->n1data[found]); |
245 | amb | 110 | } |
246 | |||
247 | |||
248 | /*++++++++++++++++++++++++++++++++++++++ | ||
249 | amb | 229 | Find the first segment with a particular starting node in node2. |
250 | |||
251 | SegmentX **find_first2_segmentx Returns a pointer to the first extended segment with the specified id. | ||
252 | |||
253 | SegmentsX* segmentsx The set of segments to process. | ||
254 | |||
255 | node_t node The node to look for. | ||
256 | ++++++++++++++++++++++++++++++++++++++*/ | ||
257 | |||
258 | static SegmentX **find_first2_segmentx(SegmentsX* segmentsx,node_t node) | ||
259 | { | ||
260 | int start=0; | ||
261 | int end=segmentsx->number-1; | ||
262 | int mid; | ||
263 | int found; | ||
264 | |||
265 | assert(segmentsx->sorted); /* Must be sorted */ | ||
266 | assert(segmentsx->n2data); /* Must have n2data filled in */ | ||
267 | |||
268 | /* Binary search - search key exact match only is required. | ||
269 | * | ||
270 | * # <- start | Check mid and move start or end if it doesn't match | ||
271 | * # | | ||
272 | * # | Since an exact match is wanted we can set end=mid-1 | ||
273 | * # <- mid | or start=mid+1 because we know that mid doesn't match. | ||
274 | * # | | ||
275 | * # | Eventually either end=start or end=start+1 and one of | ||
276 | * # <- end | start or end is the wanted one. | ||
277 | */ | ||
278 | |||
279 | if(end<start) /* There are no nodes */ | ||
280 | return(NULL); | ||
281 | else if(node<segmentsx->n2data[start]->node2) /* Check key is not before start */ | ||
282 | return(NULL); | ||
283 | else if(node>segmentsx->n2data[end]->node2) /* Check key is not after end */ | ||
284 | return(NULL); | ||
285 | else | ||
286 | { | ||
287 | do | ||
288 | { | ||
289 | mid=(start+end)/2; /* Choose mid point */ | ||
290 | |||
291 | if(segmentsx->n2data[mid]->node2<node) /* Mid point is too low */ | ||
292 | start=mid; | ||
293 | else if(segmentsx->n2data[mid]->node2>node) /* Mid point is too high */ | ||
294 | end=mid; | ||
295 | else /* Mid point is correct */ | ||
296 | {found=mid; goto found;} | ||
297 | } | ||
298 | while((end-start)>1); | ||
299 | |||
300 | if(segmentsx->n2data[start]->node2==node) /* Start is correct */ | ||
301 | {found=start; goto found;} | ||
302 | |||
303 | if(segmentsx->n2data[end]->node2==node) /* End is correct */ | ||
304 | {found=end; goto found;} | ||
305 | } | ||
306 | |||
307 | return(NULL); | ||
308 | |||
309 | found: | ||
310 | |||
311 | while(found>0 && segmentsx->n2data[found-1]->node2==node) | ||
312 | found--; | ||
313 | |||
314 | return(&segmentsx->n2data[found]); | ||
315 | } | ||
316 | |||
317 | |||
318 | /*++++++++++++++++++++++++++++++++++++++ | ||
319 | amb | 110 | Find the next segment with a particular starting node. |
320 | |||
321 | SegmentX **FindNextSegmentX Returns a pointer to the next segment with the same id. | ||
322 | |||
323 | SegmentsX* segmentsx The set of segments to process. | ||
324 | |||
325 | SegmentX **segmentx The current segment. | ||
326 | ++++++++++++++++++++++++++++++++++++++*/ | ||
327 | |||
328 | SegmentX **FindNextSegmentX(SegmentsX* segmentsx,SegmentX **segmentx) | ||
329 | { | ||
330 | amb | 229 | if((segmentsx->n1data<segmentsx->n2data && segmentx<segmentsx->n2data) || |
331 | (segmentsx->n1data>segmentsx->n2data && segmentx>segmentsx->n1data)) | ||
332 | { | ||
333 | SegmentX **next=segmentx+1; | ||
334 | amb | 110 | |
335 | amb | 229 | if((next-segmentsx->n1data)==segmentsx->number) |
336 | return(find_first2_segmentx(segmentsx,(*segmentx)->node1)); | ||
337 | amb | 110 | |
338 | amb | 229 | if((*next)->node1==(*segmentx)->node1) |
339 | return(next); | ||
340 | amb | 110 | |
341 | amb | 229 | return(find_first2_segmentx(segmentsx,(*segmentx)->node1)); |
342 | } | ||
343 | else | ||
344 | { | ||
345 | SegmentX **next=segmentx+1; | ||
346 | |||
347 | if((next-segmentsx->n2data)==segmentsx->number) | ||
348 | return(NULL); | ||
349 | |||
350 | if((*next)->node2==(*segmentx)->node2) | ||
351 | return(next); | ||
352 | |||
353 | return(NULL); | ||
354 | } | ||
355 | amb | 110 | } |
356 | |||
357 | |||
358 | /*++++++++++++++++++++++++++++++++++++++ | ||
359 | Append a segment to a segment list. | ||
360 | |||
361 | SegmentsX* segmentsx The set of segments to process. | ||
362 | |||
363 | amb | 203 | way_t way The way that the segment belongs to. |
364 | |||
365 | amb | 110 | node_t node1 The first node in the segment. |
366 | |||
367 | node_t node2 The second node in the segment. | ||
368 | amb | 228 | |
369 | distance_t distance The distance between the nodes (or just the flags). | ||
370 | amb | 110 | ++++++++++++++++++++++++++++++++++++++*/ |
371 | |||
372 | amb | 209 | void AppendSegment(SegmentsX* segmentsx,way_t way,node_t node1,node_t node2,distance_t distance) |
373 | amb | 110 | { |
374 | /* Check that the array has enough space. */ | ||
375 | |||
376 | amb | 216 | if(segmentsx->row==-1 || segmentsx->col==INCREMENT_SEGMENTSX) |
377 | amb | 110 | { |
378 | amb | 216 | segmentsx->row++; |
379 | segmentsx->col=0; | ||
380 | amb | 110 | |
381 | amb | 216 | if((segmentsx->row%16)==0) |
382 | segmentsx->xdata=(SegmentX**)realloc((void*)segmentsx->xdata,(segmentsx->row+16)*sizeof(SegmentX*)); | ||
383 | |||
384 | segmentsx->xdata[segmentsx->row]=(SegmentX*)malloc(INCREMENT_SEGMENTSX*sizeof(SegmentX)); | ||
385 | amb | 110 | } |
386 | |||
387 | /* Insert the segment */ | ||
388 | |||
389 | amb | 216 | segmentsx->xdata[segmentsx->row][segmentsx->col].way=way; |
390 | segmentsx->xdata[segmentsx->row][segmentsx->col].distance=distance; | ||
391 | amb | 110 | |
392 | amb | 229 | if(node1>node2) |
393 | { | ||
394 | segmentsx->xdata[segmentsx->row][segmentsx->col].node1=node2; | ||
395 | segmentsx->xdata[segmentsx->row][segmentsx->col].node2=node1; | ||
396 | if(distance&(ONEWAY_2TO1|ONEWAY_1TO2)) | ||
397 | segmentsx->xdata[segmentsx->row][segmentsx->col].distance^=(ONEWAY_2TO1|ONEWAY_1TO2); | ||
398 | } | ||
399 | else | ||
400 | { | ||
401 | segmentsx->xdata[segmentsx->row][segmentsx->col].node1=node1; | ||
402 | segmentsx->xdata[segmentsx->row][segmentsx->col].node2=node2; | ||
403 | } | ||
404 | |||
405 | amb | 216 | segmentsx->col++; |
406 | amb | 110 | |
407 | segmentsx->sorted=0; | ||
408 | } | ||
409 | |||
410 | |||
411 | /*++++++++++++++++++++++++++++++++++++++ | ||
412 | Sort the segment list. | ||
413 | |||
414 | SegmentsX* segmentsx The set of segments to process. | ||
415 | ++++++++++++++++++++++++++++++++++++++*/ | ||
416 | |||
417 | void SortSegmentList(SegmentsX* segmentsx) | ||
418 | { | ||
419 | amb | 214 | index_t i; |
420 | amb | 110 | |
421 | amb | 213 | assert(segmentsx->xdata); /* Must have xdata filled in */ |
422 | |||
423 | amb | 227 | printf("Sorting Segments"); |
424 | fflush(stdout); | ||
425 | amb | 132 | |
426 | amb | 213 | /* Allocate the array of pointers and sort them */ |
427 | amb | 110 | |
428 | amb | 229 | segmentsx->n1data=(SegmentX**)realloc(segmentsx->n1data,(segmentsx->row*INCREMENT_SEGMENTSX+segmentsx->col)*sizeof(SegmentX*)); |
429 | segmentsx->n2data=(SegmentX**)realloc(segmentsx->n2data,(segmentsx->row*INCREMENT_SEGMENTSX+segmentsx->col)*sizeof(SegmentX*)); | ||
430 | amb | 110 | |
431 | segmentsx->number=0; | ||
432 | |||
433 | amb | 216 | for(i=0;i<(segmentsx->row*INCREMENT_SEGMENTSX+segmentsx->col);i++) |
434 | if(segmentsx->xdata[i/INCREMENT_SEGMENTSX][i%INCREMENT_SEGMENTSX].node1!=NO_NODE) | ||
435 | amb | 110 | { |
436 | amb | 229 | segmentsx->n1data[segmentsx->number]=&segmentsx->xdata[i/INCREMENT_SEGMENTSX][i%INCREMENT_SEGMENTSX]; |
437 | segmentsx->n2data[segmentsx->number]=&segmentsx->xdata[i/INCREMENT_SEGMENTSX][i%INCREMENT_SEGMENTSX]; | ||
438 | amb | 110 | segmentsx->number++; |
439 | } | ||
440 | |||
441 | amb | 229 | qsort(segmentsx->n1data,segmentsx->number,sizeof(SegmentX*),(int (*)(const void*,const void*))sort_by_id1_and_distance); |
442 | qsort(segmentsx->n2data,segmentsx->number,sizeof(SegmentX*),(int (*)(const void*,const void*))sort_by_id2_and_distance); | ||
443 | amb | 110 | |
444 | amb | 227 | printf("\rSorted Segments \n"); |
445 | fflush(stdout); | ||
446 | amb | 213 | |
447 | amb | 110 | segmentsx->sorted=1; |
448 | } | ||
449 | |||
450 | |||
451 | /*++++++++++++++++++++++++++++++++++++++ | ||
452 | amb | 229 | Sort the segments into id order (node1 then node2) and then distance order. |
453 | amb | 110 | |
454 | amb | 229 | int sort_by_id1_and_distance Returns the comparison of the node fields. |
455 | amb | 110 | |
456 | SegmentX **a The first Segment. | ||
457 | |||
458 | SegmentX **b The second Segment. | ||
459 | ++++++++++++++++++++++++++++++++++++++*/ | ||
460 | |||
461 | amb | 229 | static int sort_by_id1_and_distance(SegmentX **a,SegmentX **b) |
462 | amb | 110 | { |
463 | node_t a_id1=(*a)->node1; | ||
464 | node_t b_id1=(*b)->node1; | ||
465 | |||
466 | if(a_id1<b_id1) | ||
467 | return(-1); | ||
468 | else if(a_id1>b_id1) | ||
469 | return(1); | ||
470 | else /* if(a_id1==b_id1) */ | ||
471 | { | ||
472 | node_t a_id2=(*a)->node2; | ||
473 | node_t b_id2=(*b)->node2; | ||
474 | |||
475 | if(a_id2<b_id2) | ||
476 | return(-1); | ||
477 | else if(a_id2>b_id2) | ||
478 | return(1); | ||
479 | else | ||
480 | { | ||
481 | amb | 229 | distance_t a_distance=(*a)->distance; |
482 | distance_t b_distance=(*b)->distance; | ||
483 | amb | 110 | |
484 | if(a_distance<b_distance) | ||
485 | return(-1); | ||
486 | else if(a_distance>b_distance) | ||
487 | return(1); | ||
488 | else | ||
489 | return(0); | ||
490 | } | ||
491 | } | ||
492 | } | ||
493 | |||
494 | |||
495 | /*++++++++++++++++++++++++++++++++++++++ | ||
496 | amb | 229 | Sort the segments into id order (node2 then node1) and then distance order. |
497 | |||
498 | int sort_by_id2_and_distance Returns the comparison of the node fields. | ||
499 | |||
500 | SegmentX **a The first Segment. | ||
501 | |||
502 | SegmentX **b The second Segment. | ||
503 | ++++++++++++++++++++++++++++++++++++++*/ | ||
504 | |||
505 | static int sort_by_id2_and_distance(SegmentX **a,SegmentX **b) | ||
506 | { | ||
507 | node_t a_id2=(*a)->node2; | ||
508 | node_t b_id2=(*b)->node2; | ||
509 | |||
510 | if(a_id2<b_id2) | ||
511 | return(-1); | ||
512 | else if(a_id2>b_id2) | ||
513 | return(1); | ||
514 | else /* if(a_id2==b_id2) */ | ||
515 | { | ||
516 | node_t a_id1=(*a)->node1; | ||
517 | node_t b_id1=(*b)->node1; | ||
518 | |||
519 | if(a_id1<b_id1) | ||
520 | return(-1); | ||
521 | else if(a_id1>b_id1) | ||
522 | return(1); | ||
523 | else | ||
524 | { | ||
525 | distance_t a_distance=(*a)->distance; | ||
526 | distance_t b_distance=(*b)->distance; | ||
527 | |||
528 | if(a_distance<b_distance) | ||
529 | return(-1); | ||
530 | else if(a_distance>b_distance) | ||
531 | return(1); | ||
532 | else | ||
533 | return(0); | ||
534 | } | ||
535 | } | ||
536 | } | ||
537 | |||
538 | |||
539 | /*++++++++++++++++++++++++++++++++++++++ | ||
540 | amb | 110 | Remove bad segments (zero length or duplicated). |
541 | |||
542 | amb | 195 | NodesX *nodesx The nodes to check. |
543 | |||
544 | amb | 110 | SegmentsX *segmentsx The segments to modify. |
545 | ++++++++++++++++++++++++++++++++++++++*/ | ||
546 | |||
547 | amb | 204 | void RemoveBadSegments(NodesX *nodesx,SegmentsX *segmentsx) |
548 | amb | 110 | { |
549 | amb | 214 | index_t i; |
550 | amb | 195 | int duplicate=0,loop=0,missing=0; |
551 | amb | 110 | |
552 | amb | 229 | assert(segmentsx->n1data); /* Must have n1data filled in */ |
553 | amb | 110 | |
554 | amb | 227 | printf("Checking: Segments=0 Duplicate=0 Loop=0 Missing-Node=0"); |
555 | fflush(stdout); | ||
556 | |||
557 | amb | 110 | for(i=0;i<segmentsx->number;i++) |
558 | { | ||
559 | amb | 229 | if(i && segmentsx->n1data[i]->node1==segmentsx->n1data[i-1]->node1 && |
560 | segmentsx->n1data[i]->node2==segmentsx->n1data[i-1]->node2) | ||
561 | amb | 110 | { |
562 | duplicate++; | ||
563 | amb | 229 | segmentsx->n1data[i-1]->node1=NO_NODE; |
564 | amb | 110 | } |
565 | amb | 229 | else if(segmentsx->n1data[i]->node1==segmentsx->n1data[i]->node2) |
566 | amb | 110 | { |
567 | loop++; | ||
568 | amb | 229 | segmentsx->n1data[i]->node1=NO_NODE; |
569 | amb | 110 | } |
570 | amb | 229 | else if(!FindNodeX(nodesx,segmentsx->n1data[i]->node1) || |
571 | !FindNodeX(nodesx,segmentsx->n1data[i]->node2)) | ||
572 | amb | 195 | { |
573 | missing++; | ||
574 | amb | 229 | segmentsx->n1data[i]->node1=NO_NODE; |
575 | amb | 195 | } |
576 | amb | 110 | |
577 | if(!((i+1)%10000)) | ||
578 | { | ||
579 | amb | 195 | printf("\rChecking: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d",i+1,duplicate,loop,missing); |
580 | amb | 110 | fflush(stdout); |
581 | } | ||
582 | } | ||
583 | |||
584 | amb | 195 | printf("\rChecked: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d \n",segmentsx->number,duplicate,loop,missing); |
585 | amb | 110 | fflush(stdout); |
586 | } | ||
587 | |||
588 | |||
589 | /*++++++++++++++++++++++++++++++++++++++ | ||
590 | Measure the segments. | ||
591 | |||
592 | SegmentsX* segmentsx The set of segments to process. | ||
593 | |||
594 | NodesX *nodesx The list of nodes to use. | ||
595 | ++++++++++++++++++++++++++++++++++++++*/ | ||
596 | |||
597 | void MeasureSegments(SegmentsX* segmentsx,NodesX *nodesx) | ||
598 | { | ||
599 | amb | 214 | index_t i; |
600 | amb | 110 | |
601 | amb | 229 | assert(segmentsx->n1data); /* Must have n1data filled in */ |
602 | amb | 110 | |
603 | amb | 227 | printf("Measuring Segments: Segments=0"); |
604 | fflush(stdout); | ||
605 | |||
606 | amb | 110 | for(i=0;i<segmentsx->number;i++) |
607 | { | ||
608 | amb | 229 | NodeX **nodex1=FindNodeX(nodesx,segmentsx->n1data[i]->node1); |
609 | NodeX **nodex2=FindNodeX(nodesx,segmentsx->n1data[i]->node2); | ||
610 | amb | 110 | |
611 | /* Set the distance but preserve the ONEWAY_* flags */ | ||
612 | |||
613 | amb | 229 | segmentsx->n1data[i]->distance|=DISTANCE(DistanceX(*nodex1,*nodex2)); |
614 | amb | 110 | |
615 | if(!((i+1)%10000)) | ||
616 | { | ||
617 | printf("\rMeasuring Segments: Segments=%d",i+1); | ||
618 | fflush(stdout); | ||
619 | } | ||
620 | } | ||
621 | |||
622 | printf("\rMeasured Segments: Segments=%d \n",segmentsx->number); | ||
623 | fflush(stdout); | ||
624 | } | ||
625 | |||
626 | |||
627 | /*++++++++++++++++++++++++++++++++++++++ | ||
628 | Mark the duplicate segments. | ||
629 | |||
630 | SegmentsX* segmentsx The set of segments to process. | ||
631 | |||
632 | WaysX *waysx The list of ways to use. | ||
633 | ++++++++++++++++++++++++++++++++++++++*/ | ||
634 | |||
635 | amb | 212 | void DeduplicateSegments(SegmentsX* segmentsx,WaysX *waysx) |
636 | amb | 110 | { |
637 | amb | 214 | index_t i; |
638 | int duplicate=0; | ||
639 | amb | 110 | |
640 | amb | 229 | assert(segmentsx->n1data); /* Must have n1data filled in */ |
641 | amb | 110 | |
642 | amb | 227 | printf("Deduplicating Segments: Segments=0 Duplicate=0"); |
643 | fflush(stdout); | ||
644 | |||
645 | amb | 110 | for(i=1;i<segmentsx->number;i++) |
646 | { | ||
647 | amb | 229 | if(segmentsx->n1data[i]->node1==segmentsx->n1data[i-1]->node1 && |
648 | segmentsx->n1data[i]->node2==segmentsx->n1data[i-1]->node2 && | ||
649 | DISTFLAG(segmentsx->n1data[i]->distance)==DISTFLAG(segmentsx->n1data[i-1]->distance)) | ||
650 | amb | 110 | { |
651 | amb | 229 | WayX *wayx1=FindWayX(waysx,segmentsx->n1data[i-1]->way); |
652 | WayX *wayx2=FindWayX(waysx,segmentsx->n1data[i ]->way); | ||
653 | amb | 110 | |
654 | amb | 204 | if(!WaysCompare(wayx1->way,wayx2->way)) |
655 | amb | 110 | { |
656 | amb | 229 | segmentsx->n1data[i-1]->node1=NO_NODE; |
657 | amb | 110 | |
658 | duplicate++; | ||
659 | } | ||
660 | } | ||
661 | |||
662 | if(!((i+1)%10000)) | ||
663 | { | ||
664 | printf("\rDeduplicating Segments: Segments=%d Duplicate=%d",i+1,duplicate); | ||
665 | fflush(stdout); | ||
666 | } | ||
667 | } | ||
668 | |||
669 | amb | 229 | printf("\rDeduplicated Segments: Segments=%d Duplicate=%d Unique=%d\n",segmentsx->number,duplicate,segmentsx->number-duplicate); |
670 | amb | 110 | fflush(stdout); |
671 | } | ||
672 | |||
673 | |||
674 | /*++++++++++++++++++++++++++++++++++++++ | ||
675 | amb | 209 | Create the real segments data. |
676 | |||
677 | SegmentsX* segmentsx The set of segments to use. | ||
678 | |||
679 | WaysX* waysx The set of ways to use. | ||
680 | ++++++++++++++++++++++++++++++++++++++*/ | ||
681 | |||
682 | void CreateRealSegments(SegmentsX *segmentsx,WaysX *waysx) | ||
683 | { | ||
684 | amb | 214 | index_t i; |
685 | amb | 209 | |
686 | amb | 229 | assert(segmentsx->n1data); /* Must have n1data filled in */ |
687 | amb | 213 | |
688 | amb | 227 | printf("Creating Real Segments: Segments=0"); |
689 | fflush(stdout); | ||
690 | |||
691 | amb | 209 | /* Allocate the memory */ |
692 | |||
693 | segmentsx->sdata=(Segment*)malloc(segmentsx->number*sizeof(Segment)); | ||
694 | |||
695 | /* Loop through and allocate. */ | ||
696 | |||
697 | for(i=0;i<segmentsx->number;i++) | ||
698 | { | ||
699 | amb | 229 | WayX *wayx=FindWayX(waysx,segmentsx->n1data[i]->way); |
700 | amb | 209 | |
701 | segmentsx->sdata[i].node1=0; | ||
702 | segmentsx->sdata[i].node2=0; | ||
703 | segmentsx->sdata[i].next2=NO_NODE; | ||
704 | amb | 216 | segmentsx->sdata[i].way=IndexWayInWaysX(waysx,wayx); |
705 | amb | 229 | segmentsx->sdata[i].distance=segmentsx->n1data[i]->distance; |
706 | amb | 209 | |
707 | if(!((i+1)%10000)) | ||
708 | { | ||
709 | printf("\rCreating Real Segments: Segments=%d",i+1); | ||
710 | fflush(stdout); | ||
711 | } | ||
712 | } | ||
713 | |||
714 | printf("\rCreating Real Segments: Segments=%d \n",segmentsx->number); | ||
715 | fflush(stdout); | ||
716 | } | ||
717 | |||
718 | |||
719 | /*++++++++++++++++++++++++++++++++++++++ | ||
720 | amb | 110 | Assign the nodes indexes to the segments. |
721 | |||
722 | SegmentsX* segmentsx The set of segments to process. | ||
723 | |||
724 | NodesX *nodesx The list of nodes to use. | ||
725 | ++++++++++++++++++++++++++++++++++++++*/ | ||
726 | |||
727 | void IndexSegments(SegmentsX* segmentsx,NodesX *nodesx) | ||
728 | { | ||
729 | amb | 214 | index_t i; |
730 | amb | 110 | |
731 | assert(segmentsx->sorted); /* Must be sorted */ | ||
732 | amb | 229 | assert(segmentsx->n1data); /* Must have n1data filled in */ |
733 | amb | 213 | assert(segmentsx->sdata); /* Must have sdata filled in */ |
734 | amb | 110 | assert(nodesx->sorted); /* Must be sorted */ |
735 | amb | 213 | assert(nodesx->gdata); /* Must have gdata filled in */ |
736 | amb | 110 | |
737 | amb | 227 | printf("Indexing Nodes: Nodes=0"); |
738 | fflush(stdout); | ||
739 | |||
740 | amb | 110 | /* Index the segments */ |
741 | |||
742 | for(i=0;i<nodesx->number;i++) | ||
743 | { | ||
744 | amb | 212 | NodeX **nodex=FindNodeX(nodesx,nodesx->gdata[i]->id); |
745 | Node *node =&nodesx->ndata[nodex-nodesx->idata]; | ||
746 | index_t index=SEGMENT(node->firstseg); | ||
747 | amb | 110 | |
748 | do | ||
749 | { | ||
750 | amb | 229 | if(segmentsx->n1data[index]->node1==nodesx->gdata[i]->id) |
751 | amb | 110 | { |
752 | amb | 209 | segmentsx->sdata[index].node1=i; |
753 | amb | 110 | |
754 | amb | 209 | index++; |
755 | amb | 128 | |
756 | amb | 229 | if(index>=segmentsx->number || segmentsx->n1data[index]->node1!=nodesx->gdata[i]->id) |
757 | amb | 209 | break; |
758 | amb | 110 | } |
759 | else | ||
760 | { | ||
761 | amb | 209 | segmentsx->sdata[index].node2=i; |
762 | amb | 110 | |
763 | amb | 209 | if(segmentsx->sdata[index].next2==NO_NODE) |
764 | break; | ||
765 | amb | 110 | else |
766 | amb | 209 | index=segmentsx->sdata[index].next2; |
767 | amb | 110 | } |
768 | } | ||
769 | amb | 209 | while(1); |
770 | amb | 110 | |
771 | if(!((i+1)%10000)) | ||
772 | { | ||
773 | printf("\rIndexing Nodes: Nodes=%d",i+1); | ||
774 | fflush(stdout); | ||
775 | } | ||
776 | } | ||
777 | |||
778 | printf("\rIndexed Nodes: Nodes=%d \n",nodesx->number); | ||
779 | fflush(stdout); | ||
780 | } | ||
781 | |||
782 | |||
783 | /*++++++++++++++++++++++++++++++++++++++ | ||
784 | Calculate the distance between two nodes. | ||
785 | |||
786 | distance_t DistanceX Returns the distance between the extended nodes. | ||
787 | |||
788 | NodeX *nodex1 The starting node. | ||
789 | |||
790 | NodeX *nodex2 The end node. | ||
791 | ++++++++++++++++++++++++++++++++++++++*/ | ||
792 | |||
793 | amb | 228 | static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2) |
794 | amb | 110 | { |
795 | amb | 223 | double dlon = latlong_to_radians(nodex1->longitude) - latlong_to_radians(nodex2->longitude); |
796 | double dlat = latlong_to_radians(nodex1->latitude) - latlong_to_radians(nodex2->latitude); | ||
797 | double lat1 = latlong_to_radians(nodex1->latitude); | ||
798 | double lat2 = latlong_to_radians(nodex2->latitude); | ||
799 | amb | 110 | |
800 | amb | 219 | double a1,a2,a,sa,c,d; |
801 | amb | 110 | |
802 | if(dlon==0 && dlat==0) | ||
803 | return 0; | ||
804 | |||
805 | amb | 219 | a1 = sin (dlat / 2); |
806 | a2 = sin (dlon / 2); | ||
807 | a = (a1 * a1) + cos (lat1) * cos (lat2) * a2 * a2; | ||
808 | sa = sqrt (a); | ||
809 | amb | 110 | if (sa <= 1.0) |
810 | amb | 219 | {c = 2 * asin (sa);} |
811 | amb | 110 | else |
812 | amb | 219 | {c = 2 * asin (1.0);} |
813 | amb | 110 | d = 6378.137 * c; |
814 | |||
815 | return km_to_distance(d); | ||
816 | } |
Properties
Name | Value |
---|---|
cvs:description | Extended segments functions. |