Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Annotation of /trunk/src/segmentsx.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 258 - (hide annotations) (download) (as text)
Tue Sep 15 11:39:50 2009 UTC (15 years, 6 months ago) by amb
File MIME type: text/x-csrc
File size: 26046 byte(s)
Some bug fixes and some missing unmap function calls.

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

Properties

Name Value
cvs:description Extended segments functions.