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 311 - (show annotations) (download) (as text)
Sat Dec 12 11:08:50 2009 UTC (15 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 24286 byte(s)
Add some FILESORT_* #defines and use them.

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

Properties

Name Value
cvs:description Extended segments functions.