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 558 - (show annotations) (download) (as text)
Mon Dec 20 19:25:03 2010 UTC (14 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 24684 byte(s)
Handle the SegmentX Segment in the same way as the other data structures (map
into memory when used, open/close the file if slim).  Create the real nodes
without mapping the segments into memory.

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