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 310 - (show annotations) (download) (as text)
Fri Dec 11 19:27:39 2009 UTC (15 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 24402 byte(s)
Added a new function to sort variable length data - simplifies the compacting of
ways, reduces memory usage potentially required for it and simplifies the code.

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

Properties

Name Value
cvs:description Extended segments functions.