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