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 447 - (show annotations) (download) (as text)
Sun Jul 11 08:16:32 2010 UTC (14 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 24778 byte(s)
Change the names of the temporary files.

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

Properties

Name Value
cvs:description Extended segments functions.