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 256 - (show annotations) (download) (as text)
Sun Sep 6 15:51:09 2009 UTC (15 years, 7 months ago) by amb
File MIME type: text/x-csrc
File size: 25832 byte(s)
Slim version of segments code (still very slow and only works on simple cases).

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

Properties

Name Value
cvs:description Extended segments functions.