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 640 - (show annotations) (download) (as text)
Wed Feb 23 19:46:11 2011 UTC (14 years ago) by amb
File MIME type: text/x-csrc
File size: 24800 byte(s)
Fix latent bug that can occur when de-duplicating segments.

1 /***************************************
2 Extended Segment data type functions.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2008-2011 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 <stdio.h>
27 #include <string.h>
28 #include <sys/stat.h>
29
30 #include "types.h"
31 #include "nodes.h"
32 #include "segments.h"
33 #include "ways.h"
34
35 #include "nodesx.h"
36 #include "segmentsx.h"
37 #include "waysx.h"
38
39 #include "types.h"
40
41 #include "files.h"
42 #include "logging.h"
43 #include "sorting.h"
44
45
46 /* Variables */
47
48 /*+ The command line '--tmpdir' option or its default value. +*/
49 extern char *option_tmpdirname;
50
51 /* Local Functions */
52
53 static int sort_by_id(SegmentX *a,SegmentX *b);
54
55 static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2);
56
57
58 /*++++++++++++++++++++++++++++++++++++++
59 Allocate a new segment list (create a new file or open an existing one).
60
61 SegmentsX *NewSegmentList Returns the segment list.
62
63 int append Set to 1 if the file is to be opened for appending (now or later).
64 ++++++++++++++++++++++++++++++++++++++*/
65
66 SegmentsX *NewSegmentList(int append)
67 {
68 SegmentsX *segmentsx;
69
70 segmentsx=(SegmentsX*)calloc(1,sizeof(SegmentsX));
71
72 assert(segmentsx); /* Check calloc() worked */
73
74 segmentsx->filename=(char*)malloc(strlen(option_tmpdirname)+32);
75
76 if(append)
77 sprintf(segmentsx->filename,"%s/segmentsx.input.tmp",option_tmpdirname);
78 else
79 sprintf(segmentsx->filename,"%s/segmentsx.%p.tmp",option_tmpdirname,segmentsx);
80
81 segmentsx->sfilename=(char*)malloc(strlen(option_tmpdirname)+32);
82
83 sprintf(segmentsx->sfilename,"%s/segments.%p.tmp",option_tmpdirname,segmentsx);
84
85 if(append)
86 {
87 off_t size;
88
89 segmentsx->fd=OpenFileAppend(segmentsx->filename);
90
91 size=SizeFile(segmentsx->filename);
92
93 segmentsx->xnumber=size/sizeof(SegmentX);
94 }
95 else
96 segmentsx->fd=OpenFileNew(segmentsx->filename);
97
98 return(segmentsx);
99 }
100
101
102 /*++++++++++++++++++++++++++++++++++++++
103 Free a segment list.
104
105 SegmentsX *segmentsx The list to be freed.
106
107 int keep Set to 1 if the file is to be kept.
108 ++++++++++++++++++++++++++++++++++++++*/
109
110 void FreeSegmentList(SegmentsX *segmentsx,int keep)
111 {
112 if(!keep)
113 DeleteFile(segmentsx->filename);
114
115 free(segmentsx->filename);
116
117 if(segmentsx->idata)
118 free(segmentsx->idata);
119
120 if(segmentsx->firstnode)
121 free(segmentsx->firstnode);
122
123 DeleteFile(segmentsx->sfilename);
124
125 free(segmentsx->sfilename);
126
127 free(segmentsx);
128 }
129
130
131 /*++++++++++++++++++++++++++++++++++++++
132 Append a single segment to an unsorted segment list.
133
134 SegmentsX* segmentsx The set of segments to process.
135
136 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 ++++++++++++++++++++++++++++++++++++++*/
144
145 void AppendSegment(SegmentsX* segmentsx,way_t way,node_t node1,node_t node2,distance_t distance)
146 {
147 SegmentX segmentx;
148
149 segmentx.node1=node1;
150 segmentx.node2=node2;
151 segmentx.way=way;
152 segmentx.distance=distance;
153
154 WriteFile(segmentsx->fd,&segmentx,sizeof(SegmentX));
155
156 segmentsx->xnumber++;
157
158 assert(segmentsx->xnumber<SEGMENT_FAKE); /* SEGMENT_FAKE marks the high-water mark for real segments. */
159 }
160
161
162 /*++++++++++++++++++++++++++++++++++++++
163 Sort the segment list.
164
165 SegmentsX* segmentsx The set of segments to process.
166 ++++++++++++++++++++++++++++++++++++++*/
167
168 void SortSegmentList(SegmentsX* segmentsx)
169 {
170 int fd;
171
172 /* Print the start message */
173
174 printf_first("Sorting Segments");
175
176 /* Close the file (finished appending) */
177
178 segmentsx->fd=CloseFile(segmentsx->fd);
179
180 /* Re-open the file read-only and a new file writeable */
181
182 segmentsx->fd=ReOpenFile(segmentsx->filename);
183
184 DeleteFile(segmentsx->filename);
185
186 fd=OpenFileNew(segmentsx->filename);
187
188 /* Sort by node indexes */
189
190 filesort_fixed(segmentsx->fd,fd,sizeof(SegmentX),(int (*)(const void*,const void*))sort_by_id,NULL);
191
192 segmentsx->number=segmentsx->xnumber;
193
194 /* Close the files */
195
196 segmentsx->fd=CloseFile(segmentsx->fd);
197 CloseFile(fd);
198
199 /* Print the final message */
200
201 printf_last("Sorted Segments: Segments=%d",segmentsx->xnumber);
202 }
203
204
205 /*++++++++++++++++++++++++++++++++++++++
206 Sort the segments into id order (node1 then node2).
207
208 int sort_by_id Returns the comparison of the node fields.
209
210 SegmentX *a The first segment.
211
212 SegmentX *b The second segment.
213 ++++++++++++++++++++++++++++++++++++++*/
214
215 static int sort_by_id(SegmentX *a,SegmentX *b)
216 {
217 node_t a_id1=a->node1;
218 node_t b_id1=b->node1;
219
220 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 {
226 node_t a_id2=a->node2;
227 node_t b_id2=b->node2;
228
229 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
238 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 }
246 }
247
248
249 /*++++++++++++++++++++++++++++++++++++++
250 Find the first segment index with a particular starting node.
251
252 index_t IndexFirstSegmentX1 Returns the index of the first extended segment with the specified id.
253
254 SegmentsX* segmentsx The set of segments to process.
255
256 node_t node The node to look for.
257 ++++++++++++++++++++++++++++++++++++++*/
258
259 index_t IndexFirstSegmentX1(SegmentsX* segmentsx,node_t node)
260 {
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 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 else
284 {
285 do
286 {
287 mid=(start+end)/2; /* Choose mid point */
288
289 if(segmentsx->idata[mid]<node) /* Mid point is too low */
290 start=mid;
291 else if(segmentsx->idata[mid]>node) /* Mid point is too high */
292 end=mid;
293 else /* Mid point is correct */
294 {found=mid; goto found;}
295 }
296 while((end-start)>1);
297
298 if(segmentsx->idata[start]==node) /* Start is correct */
299 {found=start; goto found;}
300
301 if(segmentsx->idata[end]==node) /* End is correct */
302 {found=end; goto found;}
303 }
304
305 return(NO_SEGMENT);
306
307 found:
308
309 while(found>0 && segmentsx->idata[found-1]==node)
310 found--;
311
312 return(found);
313 }
314
315
316 /*++++++++++++++++++++++++++++++++++++++
317 Find the first segment index with a particular starting node index.
318
319 index_t IndexFirstSegmentX2 Returns the index of the first extended segment with the specified id.
320
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 Find the next segment index with a particular starting node.
339
340 index_t IndexNextSegmentX1 Returns the index of the next segment with the same id.
341
342 SegmentsX* segmentsx The set of segments to process.
343
344 index_t segindex The current segment index.
345
346 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 index_t nodeindex The node index.
372 ++++++++++++++++++++++++++++++++++++++*/
373
374 index_t IndexNextSegmentX2(SegmentsX* segmentsx,index_t segindex,index_t nodeindex)
375 {
376 segindex++;
377
378 if(segindex==segmentsx->firstnode[nodeindex+1])
379 return(NO_SEGMENT);
380 else
381 return(segindex);
382 }
383
384
385 /*++++++++++++++++++++++++++++++++++++++
386 Remove bad segments (duplicated, zero length or missing nodes).
387
388 NodesX *nodesx The nodes to check.
389
390 SegmentsX *segmentsx The segments to modify.
391 ++++++++++++++++++++++++++++++++++++++*/
392
393 void RemoveBadSegments(NodesX *nodesx,SegmentsX *segmentsx)
394 {
395 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
400 /* Print the start message */
401
402 printf_first("Checking Segments: Segments=0 Duplicate=0 Loop=0 Missing-Node=0");
403
404 /* 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 /* Re-open the file read-only and a new file writeable */
411
412 segmentsx->fd=ReOpenFile(segmentsx->filename);
413
414 DeleteFile(segmentsx->filename);
415
416 fd=OpenFileNew(segmentsx->filename);
417
418 /* Modify the on-disk image */
419
420 while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
421 {
422 if(prevnode1==segmentx.node1 && prevnode2==segmentx.node2)
423 duplicate++;
424 else if(segmentx.node1==segmentx.node2)
425 loop++;
426 else if(IndexNodeX(nodesx,segmentx.node1)==NO_NODE ||
427 IndexNodeX(nodesx,segmentx.node2)==NO_NODE)
428 missing++;
429 else
430 {
431 WriteFile(fd,&segmentx,sizeof(SegmentX));
432
433 segmentsx->idata[good]=segmentx.node1;
434 good++;
435
436 prevnode1=segmentx.node1;
437 prevnode2=segmentx.node2;
438 }
439
440 total++;
441
442 if(!(total%10000))
443 printf_middle("Checking Segments: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d",total,duplicate,loop,missing);
444 }
445
446 segmentsx->number=good;
447
448 /* Close the files */
449
450 segmentsx->fd=CloseFile(segmentsx->fd);
451 CloseFile(fd);
452
453 /* Print the final message */
454
455 printf_last("Checked Segments: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d",total,duplicate,loop,missing);
456 }
457
458
459 /*++++++++++++++++++++++++++++++++++++++
460 Measure the segments and replace node/way ids with indexes.
461
462 SegmentsX* segmentsx The set of segments to process.
463
464 NodesX *nodesx The list of nodes to use.
465
466 WaysX *waysx The list of ways to use.
467 ++++++++++++++++++++++++++++++++++++++*/
468
469 void UpdateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx)
470 {
471 index_t index=0;
472 int i,fd;
473 SegmentX segmentx;
474
475 /* Print the start message */
476
477 printf_first("Measuring Segments: Segments=0");
478
479 /* Map into memory / open the file */
480
481 #if !SLIM
482 nodesx->xdata=MapFile(nodesx->filename);
483 #else
484 nodesx->fd=ReOpenFile(nodesx->filename);
485 #endif
486
487 /* Free the now-unneeded index */
488
489 free(segmentsx->idata);
490 segmentsx->idata=NULL;
491
492 /* 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 /* Re-open the file read-only and a new file writeable */
504
505 segmentsx->fd=ReOpenFile(segmentsx->filename);
506
507 DeleteFile(segmentsx->filename);
508
509 fd=OpenFileNew(segmentsx->filename);
510
511 /* Modify the on-disk image */
512
513 while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
514 {
515 index_t node1=IndexNodeX(nodesx,segmentx.node1);
516 index_t node2=IndexNodeX(nodesx,segmentx.node2);
517 index_t way =IndexWayX (waysx ,segmentx.way);
518
519 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 /* Set the distance but preserve the ONEWAY_* flags */
529
530 segmentx.distance|=DISTANCE(DistanceX(nodex1,nodex2));
531
532 /* 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 WriteFile(fd,&segmentx,sizeof(SegmentX));
540
541 index++;
542
543 if(!(index%10000))
544 printf_middle("Measuring Segments: Segments=%d",index);
545 }
546
547 /* Close the files */
548
549 segmentsx->fd=CloseFile(segmentsx->fd);
550 CloseFile(fd);
551
552 /* Free the other now-unneeded indexes */
553
554 free(nodesx->idata);
555 nodesx->idata=NULL;
556
557 free(waysx->idata);
558 waysx->idata=NULL;
559
560 /* Unmap from memory / close the file */
561
562 #if !SLIM
563 nodesx->xdata=UnmapFile(nodesx->filename);
564 #else
565 nodesx->fd=CloseFile(nodesx->fd);
566 #endif
567
568 /* Print the final message */
569
570 printf_last("Measured Segments: Segments=%d",segmentsx->number);
571 }
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 printf_first("Rotating Segments: Segments=0 Rotated=0");
589
590 /* Close the file (finished appending) */
591
592 segmentsx->fd=CloseFile(segmentsx->fd);
593
594 /* Re-open the file read-only and a new file writeable */
595
596 segmentsx->fd=ReOpenFile(segmentsx->filename);
597
598 DeleteFile(segmentsx->filename);
599
600 fd=OpenFileNew(segmentsx->filename);
601
602 /* Modify the on-disk image */
603
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 }
619
620 WriteFile(fd,&segmentx,sizeof(SegmentX));
621
622 index++;
623
624 if(!(index%10000))
625 printf_middle("Rotating Segments: Segments=%d Rotated=%d",index,rotated);
626 }
627
628 /* Close the files */
629
630 segmentsx->fd=CloseFile(segmentsx->fd);
631 CloseFile(fd);
632
633 /* Print the final message */
634
635 printf_last("Rotated Segments: Segments=%d Rotated=%d",index,rotated);
636 }
637
638
639 /*++++++++++++++++++++++++++++++++++++++
640 Remove the duplicate segments.
641
642 SegmentsX* segmentsx The set of segments to process.
643
644 NodesX *nodesx The list of nodes to use.
645
646 WaysX *waysx The list of ways to use.
647 ++++++++++++++++++++++++++++++++++++++*/
648
649 void DeduplicateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx)
650 {
651 int duplicate=0,good=0;
652 index_t firstindex=0,index=0;
653 int i,fd;
654 SegmentX prevsegmentx[16],segmentx;
655
656 /* Print the start message */
657
658 printf_first("Deduplicating Segments: Segments=0 Duplicate=0");
659
660 /* Map into memory / open the file */
661
662 #if !SLIM
663 waysx->xdata=MapFile(waysx->filename);
664 #else
665 waysx->fd=ReOpenFile(waysx->filename);
666 #endif
667
668 /* 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 /* Re-open the file read-only and a new file writeable */
678
679 segmentsx->fd=ReOpenFile(segmentsx->filename);
680
681 DeleteFile(segmentsx->filename);
682
683 fd=OpenFileNew(segmentsx->filename);
684
685 /* Modify the on-disk image */
686
687 while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
688 {
689 int isduplicate=0;
690
691 if(index && segmentx.node1==prevsegmentx[0].node1 &&
692 segmentx.node2==prevsegmentx[0].node2)
693 {
694 index_t previndex=firstindex;
695
696 while(previndex<index)
697 {
698 int offset=previndex-firstindex;
699
700 if(DISTFLAG(segmentx.distance)==DISTFLAG(prevsegmentx[offset].distance))
701 {
702 WayX *wayx1=LookupWayX(waysx,prevsegmentx[offset].way,1);
703 WayX *wayx2=LookupWayX(waysx, segmentx .way,2);
704
705 if(!WaysCompare(&wayx1->way,&wayx2->way))
706 {
707 isduplicate=1;
708 break;
709 }
710 }
711
712 previndex++;
713 }
714
715 assert((index-firstindex)<(sizeof(prevsegmentx)/sizeof(prevsegmentx[0])));
716
717 prevsegmentx[index-firstindex]=segmentx;
718 }
719 else
720 {
721 firstindex=index;
722 prevsegmentx[0]=segmentx;
723 }
724
725 if(isduplicate)
726 duplicate++;
727 else
728 {
729 WriteFile(fd,&segmentx,sizeof(SegmentX));
730
731 if(good<segmentsx->firstnode[segmentx.node1])
732 segmentsx->firstnode[segmentx.node1]=good;
733
734 good++;
735 }
736
737 index++;
738
739 if(!(index%10000))
740 printf_middle("Deduplicating Segments: Segments=%d Duplicate=%d",index,duplicate);
741 }
742
743 segmentsx->number=good;
744
745 /* Close the files */
746
747 segmentsx->fd=CloseFile(segmentsx->fd);
748 CloseFile(fd);
749
750 /* Fix-up the firstnode index for the missing nodes */
751
752 segmentsx->firstnode[nodesx->number]=segmentsx->number;
753
754 for(i=nodesx->number-1;i>=0;i--)
755 if(segmentsx->firstnode[i]==NO_SEGMENT)
756 segmentsx->firstnode[i]=segmentsx->firstnode[i+1];
757
758 /* Unmap from memory / close the file */
759
760 #if !SLIM
761 waysx->xdata=UnmapFile(waysx->filename);
762 #else
763 waysx->fd=CloseFile(waysx->fd);
764 #endif
765
766 /* Print the final message */
767
768 printf_last("Deduplicated Segments: Segments=%d Duplicate=%d Unique=%d",index,duplicate,good);
769 }
770
771
772 /*++++++++++++++++++++++++++++++++++++++
773 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 index_t i;
783
784 if(segmentsx->number==0 || waysx->number==0)
785 return;
786
787 /* Print the start message */
788
789 printf_first("Creating Real Segments: Segments=0");
790
791 /* Map into memory / open the files */
792
793 #if !SLIM
794 waysx->xdata=MapFile(waysx->filename);
795 #else
796 waysx->fd=ReOpenFile(waysx->filename);
797 #endif
798
799 /* Free the unneeded memory */
800
801 free(segmentsx->firstnode);
802 segmentsx->firstnode=NULL;
803
804 /* Re-open the file */
805
806 segmentsx->fd=ReOpenFile(segmentsx->filename);
807
808 /* Open the file for the segments */
809
810 segmentsx->sfd=OpenFileNew(segmentsx->sfilename);
811
812 /* Loop through and fill */
813
814 for(i=0;i<segmentsx->number;i++)
815 {
816 SegmentX segmentx;
817 Segment segment;
818 WayX *wayx;
819
820 ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX));
821
822 wayx=LookupWayX(waysx,segmentx.way,1);
823
824 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 if(!((i+1)%10000))
835 printf_middle("Creating Real Segments: Segments=%d",i+1);
836 }
837
838 /* Unmap from memory / close the files */
839
840 #if !SLIM
841 waysx->xdata=UnmapFile(waysx->filename);
842 #else
843 waysx->fd=CloseFile(waysx->fd);
844 #endif
845
846 /* Close the files */
847
848 segmentsx->fd=CloseFile(segmentsx->fd);
849 segmentsx->sfd=CloseFile(segmentsx->sfd);
850
851 /* Print the final message */
852
853 printf_last("Creating Real Segments: Segments=%d",segmentsx->number);
854 }
855
856
857 /*++++++++++++++++++++++++++++++++++++++
858 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 index_t i;
868
869 if(nodesx->number==0 || segmentsx->number==0)
870 return;
871
872 /* Print the start message */
873
874 printf_first("Indexing Nodes: Nodes=0");
875
876 /* Map into memory / open the files */
877
878 #if !SLIM
879 nodesx->xdata=MapFile(nodesx->filename);
880 segmentsx->xdata=MapFile(segmentsx->filename);
881 segmentsx->sdata=MapFileWriteable(segmentsx->sfilename);
882 #else
883 nodesx->fd=ReOpenFile(nodesx->filename);
884 segmentsx->fd=ReOpenFile(segmentsx->filename);
885 segmentsx->sfd=ReOpenFileWriteable(segmentsx->sfilename);
886 #endif
887
888 /* Index the segments */
889
890 for(i=0;i<nodesx->number;i++)
891 {
892 NodeX *nodex=LookupNodeX(nodesx,nodesx->gdata[i],1);
893 index_t index=nodex->id;
894
895 do
896 {
897 SegmentX *segmentx=LookupSegmentX(segmentsx,index,1);
898 Segment *segment =LookupSegmentXSegment(segmentsx,index,1);
899
900 if(segmentx->node1==i)
901 {
902 segment->node1=nodesx->gdata[i];
903
904 PutBackSegmentXSegment(segmentsx,index,1);
905
906 index++;
907
908 if(index>=segmentsx->number)
909 break;
910
911 segmentx=LookupSegmentX(segmentsx,index,1);
912
913 if(segmentx->node1!=i)
914 break;
915 }
916 else
917 {
918 segment->node2=nodesx->gdata[i];
919
920 PutBackSegmentXSegment(segmentsx,index,1);
921
922 if(segment->next2==NO_NODE)
923 break;
924 else
925 index=segment->next2;
926 }
927 }
928 while(1);
929
930 if(!((i+1)%10000))
931 printf_middle("Indexing Nodes: Nodes=%d",i+1);
932 }
933
934 /* Unmap from memory / close the files */
935
936 #if !SLIM
937 nodesx->xdata=UnmapFile(nodesx->filename);
938 segmentsx->xdata=UnmapFile(segmentsx->filename);
939 segmentsx->sdata=UnmapFile(segmentsx->sfilename);
940 #else
941 nodesx->fd=CloseFile(nodesx->fd);
942 segmentsx->fd=CloseFile(segmentsx->fd);
943 segmentsx->sfd=CloseFile(segmentsx->sfd);
944 #endif
945
946 /* Print the final message */
947
948 printf_last("Indexed Nodes: Nodes=%d",nodesx->number);
949 }
950
951
952 /*++++++++++++++++++++++++++++++++++++++
953 Save the segment list to a file.
954
955 SegmentsX* segmentsx The set of segments to save.
956
957 const char *filename The name of the file to save.
958 ++++++++++++++++++++++++++++++++++++++*/
959
960 void SaveSegmentList(SegmentsX* segmentsx,const char *filename)
961 {
962 index_t i;
963 int fd;
964 SegmentsFile segmentsfile={0};
965 int super_number=0,normal_number=0;
966
967 /* Print the start message */
968
969 printf_first("Writing Segments: Segments=0");
970
971 /* Re-open the file */
972
973 segmentsx->sfd=ReOpenFile(segmentsx->sfilename);
974
975 /* Write out the segments data */
976
977 fd=OpenFileNew(filename);
978
979 SeekFile(fd,sizeof(SegmentsFile));
980
981 for(i=0;i<segmentsx->number;i++)
982 {
983 Segment segment;
984
985 ReadFile(segmentsx->sfd,&segment,sizeof(Segment));
986
987 if(IsSuperSegment(&segment))
988 super_number++;
989 if(IsNormalSegment(&segment))
990 normal_number++;
991
992 WriteFile(fd,&segment,sizeof(Segment));
993
994 if(!((i+1)%10000))
995 printf_middle("Writing Segments: Segments=%d",i+1);
996 }
997
998 /* Write out the header structure */
999
1000 segmentsfile.number=segmentsx->number;
1001 segmentsfile.snumber=super_number;
1002 segmentsfile.nnumber=normal_number;
1003
1004 SeekFile(fd,0);
1005 WriteFile(fd,&segmentsfile,sizeof(SegmentsFile));
1006
1007 CloseFile(fd);
1008
1009 /* Close the file */
1010
1011 segmentsx->sfd=CloseFile(segmentsx->sfd);
1012
1013 /* Print the final message */
1014
1015 printf_last("Wrote Segments: Segments=%d",segmentsx->number);
1016 }
1017
1018
1019 /*++++++++++++++++++++++++++++++++++++++
1020 Calculate the distance between two nodes.
1021
1022 distance_t DistanceX Returns the distance between the extended nodes.
1023
1024 NodeX *nodex1 The starting node.
1025
1026 NodeX *nodex2 The end node.
1027 ++++++++++++++++++++++++++++++++++++++*/
1028
1029 static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2)
1030 {
1031 double dlon = latlong_to_radians(nodex1->longitude) - latlong_to_radians(nodex2->longitude);
1032 double dlat = latlong_to_radians(nodex1->latitude) - latlong_to_radians(nodex2->latitude);
1033 double lat1 = latlong_to_radians(nodex1->latitude);
1034 double lat2 = latlong_to_radians(nodex2->latitude);
1035
1036 double a1,a2,a,sa,c,d;
1037
1038 if(dlon==0 && dlat==0)
1039 return 0;
1040
1041 a1 = sin (dlat / 2);
1042 a2 = sin (dlon / 2);
1043 a = (a1 * a1) + cos (lat1) * cos (lat2) * a2 * a2;
1044 sa = sqrt (a);
1045 if (sa <= 1.0)
1046 {c = 2 * asin (sa);}
1047 else
1048 {c = 2 * asin (1.0);}
1049 d = 6378.137 * c;
1050
1051 return km_to_distance(d);
1052 }

Properties

Name Value
cvs:description Extended segments functions.