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