Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/segments.c
Parent Directory
|
Revision Log
Revision 104 -
(hide annotations)
(download)
(as text)
Fri Feb 6 20:23:35 2009 UTC (16 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 17151 byte(s)
Fri Feb 6 20:23:35 2009 UTC (16 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 17151 byte(s)
Segments now not duplicated in database. Routing with all nodes works, not with super-nodes.
1 | amb | 2 | /*************************************** |
2 | amb | 104 | $Header: /home/amb/CVS/routino/src/segments.c,v 1.30 2009-02-06 20:23:33 amb Exp $ |
3 | amb | 2 | |
4 | Segment data type functions. | ||
5 | ******************/ /****************** | ||
6 | Written by Andrew M. Bishop | ||
7 | |||
8 | amb | 4 | This file Copyright 2008,2009 Andrew M. Bishop |
9 | amb | 2 | It may be distributed under the GNU Public License, version 2, or |
10 | any higher version. See section COPYING of the GNU Public license | ||
11 | for conditions under which this file may be redistributed. | ||
12 | ***************************************/ | ||
13 | |||
14 | |||
15 | amb | 8 | #include <assert.h> |
16 | amb | 2 | #include <math.h> |
17 | amb | 104 | #include <string.h> |
18 | amb | 2 | #include <stdlib.h> |
19 | |||
20 | amb | 39 | #include "nodes.h" |
21 | amb | 26 | #include "segments.h" |
22 | amb | 2 | #include "functions.h" |
23 | |||
24 | |||
25 | amb | 96 | /* Constants */ |
26 | |||
27 | /*+ The array size increment for segments - expect ~8,000,000 segments. +*/ | ||
28 | #define INCREMENT_SEGMENTS 1024*1024 | ||
29 | |||
30 | |||
31 | amb | 23 | /* Functions */ |
32 | amb | 2 | |
33 | amb | 104 | static int sort_by_id(SegmentX **a,SegmentX **b); |
34 | amb | 2 | |
35 | amb | 8 | |
36 | amb | 23 | /*++++++++++++++++++++++++++++++++++++++ |
37 | amb | 2 | Load in a segment list from a file. |
38 | |||
39 | amb | 23 | Segments* SaveSegmentList Returns the segment list that has just been loaded. |
40 | |||
41 | amb | 2 | const char *filename The name of the file to load. |
42 | ++++++++++++++++++++++++++++++++++++++*/ | ||
43 | |||
44 | amb | 23 | Segments *LoadSegmentList(const char *filename) |
45 | amb | 2 | { |
46 | amb | 88 | void *data; |
47 | Segments *segments; | ||
48 | |||
49 | segments=(Segments*)malloc(sizeof(Segments)); | ||
50 | |||
51 | data=MapFile(filename); | ||
52 | |||
53 | amb | 100 | if(!data) |
54 | return(NULL); | ||
55 | |||
56 | amb | 88 | /* Copy the Segments structure from the loaded data */ |
57 | |||
58 | *segments=*((Segments*)data); | ||
59 | |||
60 | /* Adjust the pointers in the Segments structure. */ | ||
61 | |||
62 | amb | 104 | segments->data=data; |
63 | amb | 88 | segments->segments=(Segment*)(data+(off_t)segments->segments); |
64 | |||
65 | return(segments); | ||
66 | amb | 2 | } |
67 | |||
68 | |||
69 | /*++++++++++++++++++++++++++++++++++++++ | ||
70 | amb | 97 | Allocate a new segment list. |
71 | |||
72 | SegmentsX *NewSegmentList Returns the segment list. | ||
73 | ++++++++++++++++++++++++++++++++++++++*/ | ||
74 | |||
75 | SegmentsX *NewSegmentList(void) | ||
76 | { | ||
77 | SegmentsX *segmentsx; | ||
78 | |||
79 | segmentsx=(SegmentsX*)malloc(sizeof(SegmentsX)); | ||
80 | |||
81 | segmentsx->sorted=0; | ||
82 | segmentsx->alloced=INCREMENT_SEGMENTS; | ||
83 | amb | 104 | segmentsx->xnumber=0; |
84 | amb | 97 | |
85 | segmentsx->xdata=(SegmentX*)malloc(segmentsx->alloced*sizeof(SegmentX)); | ||
86 | amb | 104 | segmentsx->sdata=NULL; |
87 | amb | 97 | |
88 | return(segmentsx); | ||
89 | } | ||
90 | |||
91 | |||
92 | /*++++++++++++++++++++++++++++++++++++++ | ||
93 | Free a segment list. | ||
94 | |||
95 | SegmentsX *segmentsx The list to be freed. | ||
96 | ++++++++++++++++++++++++++++++++++++++*/ | ||
97 | |||
98 | void FreeSegmentList(SegmentsX *segmentsx) | ||
99 | { | ||
100 | free(segmentsx->xdata); | ||
101 | amb | 104 | free(segmentsx->sdata); |
102 | amb | 97 | free(segmentsx); |
103 | } | ||
104 | |||
105 | |||
106 | /*++++++++++++++++++++++++++++++++++++++ | ||
107 | amb | 2 | Save the segment list to a file. |
108 | |||
109 | amb | 97 | SegmentsX* segmentsx The set of segments to save. |
110 | amb | 23 | |
111 | amb | 2 | const char *filename The name of the file to save. |
112 | ++++++++++++++++++++++++++++++++++++++*/ | ||
113 | |||
114 | amb | 97 | void SaveSegmentList(SegmentsX* segmentsx,const char *filename) |
115 | amb | 2 | { |
116 | amb | 88 | int i; |
117 | int fd; | ||
118 | Segments *segments=calloc(1,sizeof(Segments)); | ||
119 | amb | 2 | |
120 | amb | 104 | assert(segmentsx->sorted); /* Must be sorted */ |
121 | amb | 23 | |
122 | amb | 88 | /* Fill in a Segments structure with the offset of the real data in the file after |
123 | the Segment structure itself. */ | ||
124 | |||
125 | amb | 97 | segments->number=segmentsx->number; |
126 | amb | 88 | 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 | amb | 97 | WriteFile(fd,segments,sizeof(Segments)); |
134 | amb | 88 | |
135 | amb | 97 | for(i=0;i<segmentsx->number;i++) |
136 | amb | 104 | WriteFile(fd,&segmentsx->sdata[i]->segment,sizeof(Segment)); |
137 | amb | 88 | |
138 | amb | 97 | CloseFile(fd); |
139 | amb | 88 | |
140 | amb | 89 | /* Free the fake Segments */ |
141 | amb | 88 | |
142 | amb | 23 | free(segments); |
143 | amb | 2 | } |
144 | |||
145 | |||
146 | /*++++++++++++++++++++++++++++++++++++++ | ||
147 | Find the first segment with a particular starting node. | ||
148 | |||
149 | amb | 104 | SegmentX **FindFirstSegmentX Returns a pointer to the first extended segment with the specified id. |
150 | amb | 2 | |
151 | amb | 97 | SegmentsX* segmentsx The set of segments to process. |
152 | amb | 23 | |
153 | amb | 2 | node_t node The node to look for. |
154 | ++++++++++++++++++++++++++++++++++++++*/ | ||
155 | |||
156 | amb | 104 | SegmentX **FindFirstSegmentX(SegmentsX* segmentsx,node_t node) |
157 | amb | 2 | { |
158 | amb | 88 | int start=0; |
159 | amb | 97 | int end=segmentsx->number-1; |
160 | amb | 2 | int mid; |
161 | int found; | ||
162 | |||
163 | amb | 104 | assert(segmentsx->sorted); /* Must be sorted */ |
164 | |||
165 | amb | 2 | /* Binary search - search key exact match only is required. |
166 | * | ||
167 | * # <- start | Check mid and move start or end if it doesn't match | ||
168 | * # | | ||
169 | * # | Since an exact match is wanted we can set end=mid-1 | ||
170 | * # <- mid | or start=mid+1 because we know that mid doesn't match. | ||
171 | * # | | ||
172 | * # | Eventually either end=start or end=start+1 and one of | ||
173 | * # <- end | start or end is the wanted one. | ||
174 | */ | ||
175 | |||
176 | amb | 104 | if(end<start) /* There are no nodes */ |
177 | amb | 89 | return(NULL); |
178 | amb | 104 | else if(node<segmentsx->sdata[start]->node1) /* Check key is not before start */ |
179 | amb | 89 | return(NULL); |
180 | amb | 104 | else if(node>segmentsx->sdata[end]->node1) /* Check key is not after end */ |
181 | amb | 89 | return(NULL); |
182 | amb | 2 | else |
183 | { | ||
184 | do | ||
185 | { | ||
186 | amb | 104 | mid=(start+end)/2; /* Choose mid point */ |
187 | amb | 2 | |
188 | amb | 104 | if(segmentsx->sdata[mid]->node1<node) /* Mid point is too low */ |
189 | amb | 2 | start=mid; |
190 | amb | 104 | else if(segmentsx->sdata[mid]->node1>node) /* Mid point is too high */ |
191 | amb | 2 | end=mid; |
192 | amb | 104 | else /* Mid point is correct */ |
193 | amb | 2 | {found=mid; goto found;} |
194 | } | ||
195 | while((end-start)>1); | ||
196 | |||
197 | amb | 104 | if(segmentsx->sdata[start]->node1==node) /* Start is correct */ |
198 | amb | 2 | {found=start; goto found;} |
199 | |||
200 | amb | 104 | if(segmentsx->sdata[end]->node1==node) /* End is correct */ |
201 | amb | 2 | {found=end; goto found;} |
202 | } | ||
203 | |||
204 | amb | 89 | return(NULL); |
205 | amb | 2 | |
206 | found: | ||
207 | |||
208 | amb | 104 | while(found>0 && segmentsx->sdata[found-1]->node1==node) |
209 | amb | 2 | found--; |
210 | |||
211 | amb | 104 | return(&segmentsx->sdata[found]); |
212 | amb | 2 | } |
213 | |||
214 | |||
215 | /*++++++++++++++++++++++++++++++++++++++ | ||
216 | Find the next segment with a particular starting node. | ||
217 | |||
218 | amb | 104 | SegmentX **FindNextSegmentX Returns a pointer to the next segment with the same id. |
219 | amb | 89 | |
220 | amb | 104 | SegmentsX* segmentsx The set of segments to process. |
221 | amb | 89 | |
222 | amb | 104 | SegmentX **segmentx The current segment. |
223 | amb | 89 | ++++++++++++++++++++++++++++++++++++++*/ |
224 | |||
225 | amb | 104 | SegmentX **FindNextSegmentX(SegmentsX* segmentsx,SegmentX **segmentx) |
226 | amb | 89 | { |
227 | amb | 104 | SegmentX **next=segmentx+1; |
228 | amb | 89 | |
229 | amb | 104 | if((next-segmentsx->sdata)==segmentsx->number) |
230 | amb | 89 | return(NULL); |
231 | |||
232 | amb | 104 | if((*next)->node1==(*segmentx)->node1) |
233 | amb | 89 | return(next); |
234 | |||
235 | return(NULL); | ||
236 | } | ||
237 | |||
238 | |||
239 | /*++++++++++++++++++++++++++++++++++++++ | ||
240 | Find the next segment with a particular starting node. | ||
241 | |||
242 | amb | 88 | Segment *NextSegment Returns a pointer to the next segment with the same id. |
243 | amb | 2 | |
244 | amb | 23 | Segments* segments The set of segments to process. |
245 | |||
246 | amb | 2 | Segment *segment The current segment. |
247 | ++++++++++++++++++++++++++++++++++++++*/ | ||
248 | |||
249 | amb | 104 | Segment *NextSegment(Segments* segments,Segment *segment,index_t node) |
250 | amb | 2 | { |
251 | amb | 104 | index_t next; |
252 | amb | 2 | |
253 | amb | 104 | if(NODE(segment->node1)==node) |
254 | next=segment->next1; | ||
255 | else | ||
256 | next=segment->next2; | ||
257 | |||
258 | if(next==~0) | ||
259 | amb | 23 | return(NULL); |
260 | amb | 104 | else |
261 | return(LookupSegment(segments,next)); | ||
262 | amb | 89 | } |
263 | amb | 88 | |
264 | |||
265 | amb | 2 | /*++++++++++++++++++++++++++++++++++++++ |
266 | amb | 98 | Append a segment to a segment list. |
267 | amb | 2 | |
268 | amb | 104 | Segment *AppendSegment Returns the appended segment. |
269 | amb | 31 | |
270 | amb | 97 | SegmentsX* segmentsx The set of segments to process. |
271 | amb | 23 | |
272 | amb | 2 | node_t node1 The first node in the segment. |
273 | |||
274 | node_t node2 The second node in the segment. | ||
275 | ++++++++++++++++++++++++++++++++++++++*/ | ||
276 | |||
277 | amb | 98 | Segment *AppendSegment(SegmentsX* segmentsx,node_t node1,node_t node2) |
278 | amb | 2 | { |
279 | amb | 23 | /* Check that the array has enough space. */ |
280 | amb | 8 | |
281 | amb | 104 | if(segmentsx->xnumber==segmentsx->alloced) |
282 | amb | 4 | { |
283 | amb | 97 | segmentsx->alloced+=INCREMENT_SEGMENTS; |
284 | amb | 4 | |
285 | amb | 97 | segmentsx->xdata=(SegmentX*)realloc((void*)segmentsx->xdata,segmentsx->alloced*sizeof(SegmentX)); |
286 | amb | 4 | } |
287 | |||
288 | /* Insert the segment */ | ||
289 | |||
290 | amb | 104 | segmentsx->xdata[segmentsx->xnumber].node1=node1; |
291 | segmentsx->xdata[segmentsx->xnumber].node2=node2; | ||
292 | amb | 98 | |
293 | amb | 104 | memset(&segmentsx->xdata[segmentsx->xnumber].segment,0,sizeof(Segment)); |
294 | amb | 2 | |
295 | amb | 104 | segmentsx->xnumber++; |
296 | amb | 2 | |
297 | amb | 97 | segmentsx->sorted=0; |
298 | amb | 31 | |
299 | amb | 104 | return(&segmentsx->xdata[segmentsx->xnumber-1].segment); |
300 | amb | 2 | } |
301 | |||
302 | |||
303 | /*++++++++++++++++++++++++++++++++++++++ | ||
304 | Sort the segment list. | ||
305 | amb | 23 | |
306 | amb | 97 | SegmentsX* segmentsx The set of segments to process. |
307 | amb | 2 | ++++++++++++++++++++++++++++++++++++++*/ |
308 | |||
309 | amb | 97 | void SortSegmentList(SegmentsX* segmentsx) |
310 | amb | 2 | { |
311 | amb | 104 | int i; |
312 | amb | 39 | |
313 | amb | 104 | /* Allocate the arrays of pointers */ |
314 | amb | 8 | |
315 | amb | 104 | if(segmentsx->sorted) |
316 | segmentsx->sdata=realloc(segmentsx->sdata,segmentsx->xnumber*sizeof(SegmentX*)); | ||
317 | else | ||
318 | segmentsx->sdata=malloc(segmentsx->xnumber*sizeof(SegmentX*)); | ||
319 | |||
320 | segmentsx->number=0; | ||
321 | |||
322 | for(i=0;i<segmentsx->xnumber;i++) | ||
323 | if(segmentsx->xdata[i].node1!=~0) | ||
324 | { | ||
325 | segmentsx->sdata[segmentsx->number]=&segmentsx->xdata[i]; | ||
326 | segmentsx->number++; | ||
327 | } | ||
328 | |||
329 | qsort(segmentsx->sdata,segmentsx->number,sizeof(SegmentX*),(int (*)(const void*,const void*))sort_by_id); | ||
330 | |||
331 | amb | 97 | segmentsx->sorted=1; |
332 | amb | 2 | } |
333 | |||
334 | |||
335 | /*++++++++++++++++++++++++++++++++++++++ | ||
336 | Sort the segments into id order. | ||
337 | |||
338 | int sort_by_id Returns the comparison of the node fields. | ||
339 | |||
340 | amb | 104 | SegmentX **a The first Segment. |
341 | amb | 2 | |
342 | amb | 104 | SegmentX **b The second Segment. |
343 | amb | 2 | ++++++++++++++++++++++++++++++++++++++*/ |
344 | |||
345 | amb | 104 | static int sort_by_id(SegmentX **a,SegmentX **b) |
346 | amb | 2 | { |
347 | amb | 104 | node_t a_id1=(*a)->node1; |
348 | node_t b_id1=(*b)->node1; | ||
349 | amb | 2 | |
350 | amb | 39 | if(a_id1<b_id1) |
351 | return(-1); | ||
352 | else if(a_id1>b_id1) | ||
353 | return(1); | ||
354 | else /* if(a_id1==b_id1) */ | ||
355 | { | ||
356 | amb | 104 | node_t a_id2=(*a)->node2; |
357 | node_t b_id2=(*b)->node2; | ||
358 | |||
359 | amb | 39 | if(a_id2<b_id2) |
360 | return(-1); | ||
361 | amb | 104 | else if(a_id2>b_id2) |
362 | return(1); | ||
363 | amb | 88 | else |
364 | amb | 104 | { |
365 | distance_t a_distance=(*a)->segment.distance; | ||
366 | distance_t b_distance=(*b)->segment.distance; | ||
367 | |||
368 | if(a_distance<b_distance) | ||
369 | return(-1); | ||
370 | else if(a_distance>b_distance) | ||
371 | return(1); | ||
372 | else | ||
373 | return(0); | ||
374 | } | ||
375 | amb | 39 | } |
376 | amb | 2 | } |
377 | |||
378 | |||
379 | /*++++++++++++++++++++++++++++++++++++++ | ||
380 | amb | 39 | Remove bad segments (zero length or duplicated). |
381 | |||
382 | amb | 97 | SegmentsX *segmentsx The segments to modify. |
383 | amb | 39 | ++++++++++++++++++++++++++++++++++++++*/ |
384 | |||
385 | amb | 97 | void RemoveBadSegments(SegmentsX *segmentsx) |
386 | amb | 39 | { |
387 | int i; | ||
388 | int duplicate=0,loop=0; | ||
389 | |||
390 | amb | 104 | assert(segmentsx->sorted); /* Must be sorted */ |
391 | |||
392 | amb | 97 | for(i=0;i<segmentsx->number;i++) |
393 | amb | 39 | { |
394 | amb | 104 | if(i && segmentsx->sdata[i]->node1==segmentsx->sdata[i-1]->node1 && |
395 | segmentsx->sdata[i]->node2==segmentsx->sdata[i-1]->node2) | ||
396 | amb | 39 | { |
397 | duplicate++; | ||
398 | amb | 104 | segmentsx->sdata[i-1]->node1=~0; |
399 | amb | 39 | } |
400 | amb | 104 | else if(segmentsx->sdata[i]->node1==segmentsx->sdata[i]->node2) |
401 | amb | 39 | { |
402 | loop++; | ||
403 | amb | 104 | segmentsx->sdata[i]->node1=~0; |
404 | amb | 39 | } |
405 | |||
406 | if(!((i+1)%10000)) | ||
407 | { | ||
408 | printf("\rChecking: Segments=%d Duplicate=%d Loop=%d",i+1,duplicate,loop); | ||
409 | fflush(stdout); | ||
410 | } | ||
411 | } | ||
412 | |||
413 | amb | 97 | printf("\rChecked: Segments=%d Duplicate=%d Loop=%d \n",segmentsx->number,duplicate,loop); |
414 | amb | 39 | fflush(stdout); |
415 | } | ||
416 | |||
417 | |||
418 | /*++++++++++++++++++++++++++++++++++++++ | ||
419 | amb | 89 | Measure the segments. |
420 | amb | 23 | |
421 | amb | 97 | SegmentsX* segmentsx The set of segments to process. |
422 | amb | 23 | |
423 | amb | 97 | NodesX *nodesx The list of nodes to use. |
424 | amb | 8 | ++++++++++++++++++++++++++++++++++++++*/ |
425 | amb | 2 | |
426 | amb | 97 | void MeasureSegments(SegmentsX* segmentsx,NodesX *nodesx) |
427 | amb | 8 | { |
428 | int i; | ||
429 | amb | 2 | |
430 | amb | 104 | assert(segmentsx->sorted); /* Must be sorted */ |
431 | amb | 8 | |
432 | amb | 97 | for(i=0;i<segmentsx->number;i++) |
433 | amb | 8 | { |
434 | amb | 104 | NodeX *node1=FindNodeX(nodesx,segmentsx->sdata[i]->node1); |
435 | NodeX *node2=FindNodeX(nodesx,segmentsx->sdata[i]->node2); | ||
436 | amb | 8 | |
437 | amb | 104 | /* Set the distance but preserve the ONEWAY_* flags */ |
438 | amb | 8 | |
439 | amb | 104 | segmentsx->sdata[i]->segment.distance|=DistanceX(node1,node2); |
440 | amb | 69 | |
441 | amb | 54 | if(!((i+1)%10000)) |
442 | { | ||
443 | amb | 89 | printf("\rMeasuring Segments: Segments=%d",i+1); |
444 | fflush(stdout); | ||
445 | } | ||
446 | } | ||
447 | |||
448 | amb | 97 | printf("\rMeasured Segments: Segments=%d \n",segmentsx->number); |
449 | amb | 89 | fflush(stdout); |
450 | } | ||
451 | |||
452 | |||
453 | /*++++++++++++++++++++++++++++++++++++++ | ||
454 | amb | 104 | Make the segments all point the same way (node1<node2). |
455 | amb | 89 | |
456 | amb | 97 | SegmentsX* segmentsx The set of segments to process. |
457 | amb | 89 | |
458 | amb | 97 | NodesX *nodesx The list of nodes to use. |
459 | amb | 89 | ++++++++++++++++++++++++++++++++++++++*/ |
460 | |||
461 | amb | 104 | void RotateSegments(SegmentsX* segmentsx,NodesX *nodesx) |
462 | amb | 89 | { |
463 | amb | 104 | int i,rotated=0; |
464 | amb | 89 | |
465 | amb | 104 | assert(segmentsx->sorted); /* Must be sorted */ |
466 | amb | 89 | |
467 | amb | 97 | for(i=0;i<segmentsx->number;i++) |
468 | amb | 89 | { |
469 | amb | 104 | if(segmentsx->sdata[i]->node1>segmentsx->sdata[i]->node2) |
470 | { | ||
471 | segmentsx->sdata[i]->node1^=segmentsx->sdata[i]->node2; | ||
472 | segmentsx->sdata[i]->node2^=segmentsx->sdata[i]->node1; | ||
473 | segmentsx->sdata[i]->node1^=segmentsx->sdata[i]->node2; | ||
474 | amb | 89 | |
475 | amb | 104 | if(segmentsx->sdata[i]->segment.distance&(ONEWAY_2TO1|ONEWAY_1TO2)) |
476 | segmentsx->sdata[i]->segment.distance^=ONEWAY_2TO1|ONEWAY_1TO2; | ||
477 | amb | 89 | |
478 | amb | 104 | rotated++; |
479 | } | ||
480 | |||
481 | amb | 89 | if(!((i+1)%10000)) |
482 | { | ||
483 | amb | 104 | printf("\rRotating Segments: Segments=%d Rotated=%d",i+1,rotated); |
484 | amb | 54 | fflush(stdout); |
485 | } | ||
486 | amb | 8 | } |
487 | amb | 54 | |
488 | amb | 104 | printf("\rRotated Segments: Segments=%d Rotated=%d \n",segmentsx->number,rotated); |
489 | amb | 54 | fflush(stdout); |
490 | amb | 104 | } |
491 | amb | 90 | |
492 | amb | 104 | |
493 | /*++++++++++++++++++++++++++++++++++++++ | ||
494 | Mark the duplicate segments. | ||
495 | |||
496 | SegmentsX* segmentsx The set of segments to process. | ||
497 | |||
498 | NodesX *nodesx The list of nodes to use. | ||
499 | |||
500 | WaysX *waysx The list of ways to use. | ||
501 | ++++++++++++++++++++++++++++++++++++++*/ | ||
502 | |||
503 | void DeduplicateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx) | ||
504 | { | ||
505 | int i,duplicate=0; | ||
506 | |||
507 | assert(segmentsx->sorted); /* Must be sorted */ | ||
508 | |||
509 | for(i=1;i<segmentsx->number;i++) | ||
510 | amb | 90 | { |
511 | amb | 104 | if(segmentsx->sdata[i]->node1==segmentsx->sdata[i-1]->node1 && |
512 | segmentsx->sdata[i]->node2==segmentsx->sdata[i-1]->node2 && | ||
513 | segmentsx->sdata[i]->segment.node1==segmentsx->sdata[i-1]->segment.node1 && | ||
514 | segmentsx->sdata[i]->segment.node2==segmentsx->sdata[i-1]->segment.node2 && | ||
515 | segmentsx->sdata[i]->segment.distance==segmentsx->sdata[i-1]->segment.distance) | ||
516 | { | ||
517 | WayX *wayx1=LookupWayX(waysx,segmentsx->sdata[i-1]->segment.way); | ||
518 | WayX *wayx2=LookupWayX(waysx,segmentsx->sdata[i]->segment.way); | ||
519 | amb | 90 | |
520 | amb | 104 | if(wayx1==wayx2 || |
521 | (wayx1->way.type==wayx2->way.type && wayx1->way.allow==wayx2->way.allow && wayx1->way.limit==wayx2->way.limit)) | ||
522 | { | ||
523 | segmentsx->sdata[i-1]->node1=~0; | ||
524 | segmentsx->sdata[i-1]->node2=~0; | ||
525 | amb | 90 | |
526 | amb | 104 | duplicate++; |
527 | } | ||
528 | } | ||
529 | |||
530 | amb | 90 | if(!((i+1)%10000)) |
531 | { | ||
532 | amb | 104 | printf("\rDeduplicating Segments: Segments=%d Duplicate=%d",i+1,duplicate); |
533 | amb | 90 | fflush(stdout); |
534 | } | ||
535 | } | ||
536 | |||
537 | amb | 104 | printf("\rDeduplicated Segments: Segments=%d Duplicate=%d \n",segmentsx->number,duplicate); |
538 | amb | 90 | fflush(stdout); |
539 | amb | 104 | } |
540 | amb | 90 | |
541 | |||
542 | amb | 104 | /*++++++++++++++++++++++++++++++++++++++ |
543 | Assign the nodes indexes to the segments. | ||
544 | |||
545 | SegmentsX* segmentsx The set of segments to process. | ||
546 | |||
547 | NodesX *nodesx The list of nodes to use. | ||
548 | ++++++++++++++++++++++++++++++++++++++*/ | ||
549 | |||
550 | void IndexSegments(SegmentsX* segmentsx,NodesX *nodesx) | ||
551 | { | ||
552 | int i; | ||
553 | |||
554 | assert(segmentsx->sorted); /* Must be sorted */ | ||
555 | assert(nodesx->sorted); /* Must be sorted */ | ||
556 | |||
557 | /* Index the segments */ | ||
558 | |||
559 | for(i=0;i<nodesx->number;i++) | ||
560 | amb | 90 | { |
561 | amb | 104 | SegmentX *segmentx=LookupSegmentX(segmentsx,SEGMENT(nodesx->gdata[i]->node.firstseg)); |
562 | |||
563 | do | ||
564 | amb | 90 | { |
565 | amb | 104 | if(segmentx->node1==nodesx->gdata[i]->id) |
566 | amb | 90 | { |
567 | amb | 104 | segmentx->segment.node1|=i; |
568 | amb | 90 | |
569 | amb | 104 | if(segmentx->segment.next1==~0) |
570 | segmentx=NULL; | ||
571 | else | ||
572 | segmentx=LookupSegmentX(segmentsx,segmentx->segment.next1); | ||
573 | amb | 90 | } |
574 | amb | 104 | else |
575 | amb | 90 | { |
576 | amb | 104 | segmentx->segment.node2|=i; |
577 | amb | 90 | |
578 | amb | 104 | if(segmentx->segment.next2==~0) |
579 | segmentx=NULL; | ||
580 | else | ||
581 | segmentx=LookupSegmentX(segmentsx,segmentx->segment.next2); | ||
582 | amb | 90 | } |
583 | } | ||
584 | amb | 104 | while(segmentx); |
585 | amb | 90 | |
586 | if(!((i+1)%10000)) | ||
587 | { | ||
588 | amb | 104 | printf("\rIndexing Nodes: Nodes=%d",i+1); |
589 | amb | 90 | fflush(stdout); |
590 | } | ||
591 | } | ||
592 | |||
593 | amb | 104 | printf("\rIndexed Nodes: Nodes=%d \n",nodesx->number); |
594 | amb | 90 | fflush(stdout); |
595 | amb | 8 | } |
596 | |||
597 | |||
598 | /*++++++++++++++++++++++++++++++++++++++ | ||
599 | amb | 99 | Calculate the distance between two locations. |
600 | |||
601 | float Distance Returns the distance between the locations. | ||
602 | |||
603 | float lat1 The latitude of the first location. | ||
604 | |||
605 | float lon1 The longitude of the first location. | ||
606 | |||
607 | float lat2 The latitude of the second location. | ||
608 | |||
609 | float lon2 The longitude of the second location. | ||
610 | ++++++++++++++++++++++++++++++++++++++*/ | ||
611 | |||
612 | float Distance(float lat1,float lon1,float lat2,float lon2) | ||
613 | { | ||
614 | double radiant = M_PI / 180; | ||
615 | |||
616 | double dlon = radiant * (lon1 - lon2); | ||
617 | double dlat = radiant * (lat1 - lat2); | ||
618 | |||
619 | double a1,a2,a,sa,c,d; | ||
620 | |||
621 | if(dlon==0 && dlat==0) | ||
622 | return 0; | ||
623 | |||
624 | a1 = sin (dlat / 2); | ||
625 | a2 = sin (dlon / 2); | ||
626 | a = (a1 * a1) + cos (lat1 * radiant) * cos (lat2 * radiant) * a2 * a2; | ||
627 | sa = sqrt (a); | ||
628 | if (sa <= 1.0) | ||
629 | {c = 2 * asin (sa);} | ||
630 | else | ||
631 | {c = 2 * asin (1.0);} | ||
632 | d = 6378.137 * c; | ||
633 | |||
634 | return d; | ||
635 | } | ||
636 | |||
637 | |||
638 | /*++++++++++++++++++++++++++++++++++++++ | ||
639 | amb | 8 | Calculate the distance between two nodes. |
640 | |||
641 | amb | 99 | distance_t DistanceX Returns the distance between the extended nodes. |
642 | amb | 8 | |
643 | amb | 98 | NodeX *nodex1 The starting node. |
644 | amb | 2 | |
645 | amb | 98 | NodeX *nodex2 The end node. |
646 | amb | 2 | ++++++++++++++++++++++++++++++++++++++*/ |
647 | |||
648 | amb | 99 | distance_t DistanceX(NodeX *nodex1,NodeX *nodex2) |
649 | amb | 2 | { |
650 | double radiant = M_PI / 180; | ||
651 | |||
652 | amb | 99 | double dlon = radiant * (nodex1->longitude - nodex2->longitude); |
653 | double dlat = radiant * (nodex1->latitude - nodex2->latitude); | ||
654 | amb | 2 | |
655 | double a1,a2,a,sa,c,d; | ||
656 | |||
657 | if(dlon==0 && dlat==0) | ||
658 | return 0; | ||
659 | |||
660 | a1 = sin (dlat / 2); | ||
661 | a2 = sin (dlon / 2); | ||
662 | amb | 99 | a = (a1 * a1) + cos (nodex1->latitude * radiant) * cos (nodex2->latitude * radiant) * a2 * a2; |
663 | amb | 2 | sa = sqrt (a); |
664 | if (sa <= 1.0) | ||
665 | {c = 2 * asin (sa);} | ||
666 | else | ||
667 | {c = 2 * asin (1.0);} | ||
668 | amb | 5 | d = 6378.137 * c; |
669 | amb | 2 | |
670 | amb | 5 | return km_to_distance(d); |
671 | amb | 2 | } |
672 | amb | 63 | |
673 | |||
674 | /*++++++++++++++++++++++++++++++++++++++ | ||
675 | Calculate the duration of segment. | ||
676 | |||
677 | duration_t Duration Returns the duration of travel between the nodes. | ||
678 | |||
679 | Segment *segment The segment to traverse. | ||
680 | |||
681 | Way *way The way that the segment belongs to. | ||
682 | |||
683 | amb | 82 | Profile *profile The profile of the transport being used. |
684 | amb | 63 | ++++++++++++++++++++++++++++++++++++++*/ |
685 | |||
686 | amb | 82 | duration_t Duration(Segment *segment,Way *way,Profile *profile) |
687 | amb | 63 | { |
688 | amb | 82 | speed_t speed=profile->speed[HIGHWAY(way->type)]; |
689 | amb | 90 | distance_t distance=DISTANCE(segment->distance); |
690 | amb | 63 | |
691 | amb | 86 | return distance_speed_to_duration(distance,speed); |
692 | amb | 63 | } |
Properties
Name | Value |
---|---|
cvs:description | Segment data type. |