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 552 - (show annotations) (download) (as text)
Mon Dec 20 17:38:29 2010 UTC (14 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 24030 byte(s)
Don't maintain a copy of the whole set of Nodes along with the NodeXs but
generate the Node from the NodeX when written to disk.  Create a lookup table
between the original index and the geographically sorted index.

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

Properties

Name Value
cvs:description Extended segments functions.