Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /trunk/src/segmentsx.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1090 - (show annotations) (download) (as text)
Wed Oct 17 18:13:51 2012 UTC (12 years, 5 months ago) by amb
File MIME type: text/x-csrc
File size: 23450 byte(s)
Rename the WayX->prop entry to WayX->cid to disambiguate it.

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

Properties

Name Value
cvs:description Extended segments functions.