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 262 - (hide annotations) (download) (as text)
Thu Sep 17 12:55:15 2009 UTC (15 years, 6 months ago) by amb
File MIME type: text/x-csrc
File size: 26134 byte(s)
Added the slim mode to Ways as well.

1 amb 110 /***************************************
2 amb 262 $Header: /home/amb/CVS/routino/src/segmentsx.c,v 1.36 2009-09-17 12:55:15 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 262 /* Close the files and re-open them */
465    
466     CloseFile(segmentsx->fd);
467     segmentsx->fd=ReOpenFile(segmentsx->filename);
468    
469 amb 256 /* Allocate the array of indexes */
470 amb 110
471 amb 256 segmentsx->n1data=(index_t*)malloc(segmentsx->xnumber*sizeof(index_t));
472 amb 110
473 amb 256 assert(segmentsx->n1data); /* Check malloc() worked */
474 amb 243
475 amb 257 segmentsx->xdata=MapFile(segmentsx->filename);
476 amb 110
477 amb 256 for(i=0;i<segmentsx->xnumber;i++)
478     segmentsx->n1data[i]=i;
479 amb 110
480 amb 256 segmentsx->number=segmentsx->xnumber;
481    
482     printf("\rSorted Segments (pre-sort) \n");
483     fflush(stdout);
484    
485     ReSortSegmentList(segmentsx);
486     }
487    
488    
489     /*+ A temporary file-local variable for use by the sort function. +*/
490     static SegmentsX *sortsegmentsx;
491    
492    
493     /*++++++++++++++++++++++++++++++++++++++
494     Sort the segment list again.
495    
496     SegmentsX* segmentsx The set of segments to process.
497     ++++++++++++++++++++++++++++++++++++++*/
498    
499     void ReSortSegmentList(SegmentsX* segmentsx)
500     {
501     assert(segmentsx->n1data); /* Must have n1data filled in => initially sorted */
502 amb 257 assert(segmentsx->xdata); /* Must have xdata filled in => mapped from file */
503 amb 256
504     printf("Sorting Segments");
505     fflush(stdout);
506    
507     sortsegmentsx=segmentsx;
508    
509     qsort(segmentsx->n1data,segmentsx->number,sizeof(index_t),(int (*)(const void*,const void*))sort_by_id1_and_distance);
510    
511     while(segmentsx->n1data[segmentsx->number-1]==NO_SEGMENT)
512     segmentsx->number--;
513    
514 amb 227 printf("\rSorted Segments \n");
515     fflush(stdout);
516 amb 110 }
517    
518    
519     /*++++++++++++++++++++++++++++++++++++++
520 amb 256 Sort the segment list for the first time (i.e. create the sortable indexes).
521    
522     SegmentsX* segmentsx The set of segments to process.
523     ++++++++++++++++++++++++++++++++++++++*/
524    
525     void FinalSortSegmentList(SegmentsX* segmentsx)
526     {
527     index_t i;
528    
529     assert(segmentsx->n1data); /* Must have n1data filled in => initially sorted */
530     assert(!segmentsx->n2data); /* Must not have n2data filled in => not finally sorted */
531    
532     ReSortSegmentList(segmentsx);
533    
534     printf("Sorting Segments (post-sort)");
535     fflush(stdout);
536    
537     /* Allocate the array of indexes */
538    
539     segmentsx->n2data=(index_t*)malloc(segmentsx->xnumber*sizeof(index_t));
540    
541     assert(segmentsx->n2data); /* Check malloc() worked */
542    
543     for(i=0;i<segmentsx->number;i++)
544     segmentsx->n2data[i]=segmentsx->n1data[i];
545    
546     sortsegmentsx=segmentsx;
547    
548     qsort(segmentsx->n2data,segmentsx->number,sizeof(index_t),(int (*)(const void*,const void*))sort_by_id2_and_distance);
549    
550 amb 258 if(option_slim)
551     segmentsx->xdata=UnmapFile(segmentsx->filename);
552    
553 amb 256 printf("\rSorted Segments (post-sort) \n");
554     fflush(stdout);
555     }
556    
557    
558     /*++++++++++++++++++++++++++++++++++++++
559 amb 229 Sort the segments into id order (node1 then node2) and then distance order.
560 amb 110
561 amb 229 int sort_by_id1_and_distance Returns the comparison of the node fields.
562 amb 110
563 amb 256 index_t *a The first segment index.
564 amb 110
565 amb 256 index_t *b The second segment index.
566 amb 110 ++++++++++++++++++++++++++++++++++++++*/
567    
568 amb 256 static int sort_by_id1_and_distance(index_t *a,index_t *b)
569 amb 110 {
570 amb 256 if(*a==NO_SEGMENT)
571     return(1);
572     else if(*b==NO_SEGMENT)
573 amb 110 return(-1);
574 amb 256 else
575 amb 110 {
576 amb 257 SegmentX *segmentx_a=&sortsegmentsx->xdata[*a];
577     SegmentX *segmentx_b=&sortsegmentsx->xdata[*b];
578 amb 110
579 amb 256 node_t a_id1=segmentx_a->node1;
580     node_t b_id1=segmentx_b->node1;
581    
582     if(a_id1<b_id1)
583 amb 110 return(-1);
584 amb 256 else if(a_id1>b_id1)
585 amb 110 return(1);
586 amb 256 else /* if(a_id1==b_id1) */
587 amb 110 {
588 amb 256 node_t a_id2=segmentx_a->node2;
589     node_t b_id2=segmentx_b->node2;
590 amb 110
591 amb 256 if(a_id2<b_id2)
592 amb 110 return(-1);
593 amb 256 else if(a_id2>b_id2)
594 amb 110 return(1);
595     else
596 amb 256 {
597     distance_t a_distance=segmentx_a->distance;
598     distance_t b_distance=segmentx_b->distance;
599    
600     if(a_distance<b_distance)
601     return(-1);
602     else if(a_distance>b_distance)
603     return(1);
604     else
605     return(0);
606     }
607 amb 110 }
608     }
609     }
610    
611    
612     /*++++++++++++++++++++++++++++++++++++++
613 amb 229 Sort the segments into id order (node2 then node1) and then distance order.
614    
615     int sort_by_id2_and_distance Returns the comparison of the node fields.
616    
617 amb 256 index_t *a The first segment index.
618 amb 229
619 amb 256 index_t *b The second segment index.
620 amb 229 ++++++++++++++++++++++++++++++++++++++*/
621    
622 amb 256 static int sort_by_id2_and_distance(index_t *a,index_t *b)
623 amb 229 {
624 amb 257 SegmentX *segmentx_a=&sortsegmentsx->xdata[*a];
625     SegmentX *segmentx_b=&sortsegmentsx->xdata[*b];
626 amb 229
627 amb 256 node_t a_id2=segmentx_a->node2;
628     node_t b_id2=segmentx_b->node2;
629    
630 amb 229 if(a_id2<b_id2)
631     return(-1);
632     else if(a_id2>b_id2)
633     return(1);
634     else /* if(a_id2==b_id2) */
635     {
636 amb 256 node_t a_id1=segmentx_a->node1;
637     node_t b_id1=segmentx_b->node1;
638 amb 229
639     if(a_id1<b_id1)
640     return(-1);
641     else if(a_id1>b_id1)
642     return(1);
643     else
644     {
645 amb 256 distance_t a_distance=segmentx_a->distance;
646     distance_t b_distance=segmentx_b->distance;
647 amb 229
648     if(a_distance<b_distance)
649     return(-1);
650     else if(a_distance>b_distance)
651     return(1);
652     else
653     return(0);
654     }
655     }
656     }
657    
658    
659     /*++++++++++++++++++++++++++++++++++++++
660 amb 110 Remove bad segments (zero length or duplicated).
661    
662 amb 195 NodesX *nodesx The nodes to check.
663    
664 amb 110 SegmentsX *segmentsx The segments to modify.
665     ++++++++++++++++++++++++++++++++++++++*/
666    
667 amb 204 void RemoveBadSegments(NodesX *nodesx,SegmentsX *segmentsx)
668 amb 110 {
669 amb 214 index_t i;
670 amb 195 int duplicate=0,loop=0,missing=0;
671 amb 256 SegmentX *prevsegmentx=NULL;
672 amb 110
673 amb 243 assert(segmentsx->n1data); /* Must have n1data filled in => sorted by node 1 */
674 amb 257 assert(segmentsx->xdata); /* Must have xdata filled in => mapped from file */
675 amb 110
676 amb 227 printf("Checking: Segments=0 Duplicate=0 Loop=0 Missing-Node=0");
677     fflush(stdout);
678    
679 amb 110 for(i=0;i<segmentsx->number;i++)
680     {
681 amb 257 SegmentX *segmentx=&segmentsx->xdata[segmentsx->n1data[i]];
682 amb 256
683 amb 257 if(segmentx->node1==segmentx->node2)
684 amb 110 {
685 amb 257 loop++;
686     segmentsx->n1data[i]=NO_SEGMENT;
687     }
688     else if(i && segmentx->node1==prevsegmentx->node1 &&
689     segmentx->node2==prevsegmentx->node2)
690     {
691 amb 110 duplicate++;
692 amb 256 segmentsx->n1data[i-1]=NO_SEGMENT;
693 amb 110 }
694 amb 256 else if(IndexNodeX(nodesx,segmentx->node1)==NO_NODE ||
695     IndexNodeX(nodesx,segmentx->node2)==NO_NODE)
696 amb 195 {
697     missing++;
698 amb 256 segmentsx->n1data[i]=NO_SEGMENT;
699 amb 195 }
700 amb 110
701 amb 256 prevsegmentx=segmentx;
702    
703 amb 110 if(!((i+1)%10000))
704     {
705 amb 195 printf("\rChecking: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d",i+1,duplicate,loop,missing);
706 amb 110 fflush(stdout);
707     }
708     }
709    
710 amb 195 printf("\rChecked: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d \n",segmentsx->number,duplicate,loop,missing);
711 amb 110 fflush(stdout);
712     }
713    
714    
715     /*++++++++++++++++++++++++++++++++++++++
716     Measure the segments.
717    
718     SegmentsX* segmentsx The set of segments to process.
719    
720     NodesX *nodesx The list of nodes to use.
721     ++++++++++++++++++++++++++++++++++++++*/
722    
723     void MeasureSegments(SegmentsX* segmentsx,NodesX *nodesx)
724     {
725 amb 256 index_t i=0;
726     int fd;
727     SegmentX segmentx;
728 amb 110
729 amb 227 printf("Measuring Segments: Segments=0");
730     fflush(stdout);
731    
732 amb 257 if(option_slim)
733     nodesx->xdata=MapFile(nodesx->filename);
734    
735 amb 258 if(!option_slim)
736     segmentsx->xdata=UnmapFile(segmentsx->filename);
737    
738 amb 256 DeleteFile(segmentsx->filename);
739    
740     fd=OpenFile(segmentsx->filename);
741     SeekFile(segmentsx->fd,0);
742    
743     while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
744 amb 110 {
745 amb 257 index_t index1=IndexNodeX(nodesx,segmentx.node1);
746     index_t index2=IndexNodeX(nodesx,segmentx.node2);
747 amb 110
748 amb 257 if(index1!=NO_NODE && index2!=NO_NODE)
749     {
750     NodeX *nodex1=&nodesx->xdata[IndexNodeX(nodesx,segmentx.node1)];
751     NodeX *nodex2=&nodesx->xdata[IndexNodeX(nodesx,segmentx.node2)];
752 amb 110
753 amb 257 /* Set the distance but preserve the ONEWAY_* flags */
754    
755 amb 256 segmentx.distance|=DISTANCE(DistanceX(nodex1,nodex2));
756 amb 257 }
757 amb 110
758 amb 256 WriteFile(fd,&segmentx,sizeof(SegmentX));
759    
760     i++;
761    
762     if(!(i%10000))
763 amb 110 {
764 amb 256 printf("\rMeasuring Segments: Segments=%d",i);
765 amb 110 fflush(stdout);
766     }
767     }
768    
769 amb 256 CloseFile(segmentsx->fd);
770     CloseFile(fd);
771    
772     segmentsx->fd=ReOpenFile(segmentsx->filename);
773    
774     if(!option_slim)
775     segmentsx->xdata=MapFile(segmentsx->filename);
776    
777 amb 257 if(option_slim)
778     nodesx->xdata=UnmapFile(nodesx->filename);
779    
780 amb 256 printf("\rMeasured Segments: Segments=%d \n",segmentsx->xnumber);
781 amb 110 fflush(stdout);
782     }
783    
784    
785     /*++++++++++++++++++++++++++++++++++++++
786     Mark the duplicate segments.
787    
788     SegmentsX* segmentsx The set of segments to process.
789    
790     WaysX *waysx The list of ways to use.
791     ++++++++++++++++++++++++++++++++++++++*/
792    
793 amb 212 void DeduplicateSegments(SegmentsX* segmentsx,WaysX *waysx)
794 amb 110 {
795 amb 214 index_t i;
796     int duplicate=0;
797 amb 256 SegmentX *prevsegmentx;
798 amb 110
799 amb 243 assert(segmentsx->n1data); /* Must have n1data filled in => sorted by node 1 */
800 amb 257 assert(segmentsx->xdata); /* Must have xdata filled in => mapped from file */
801 amb 110
802 amb 227 printf("Deduplicating Segments: Segments=0 Duplicate=0");
803     fflush(stdout);
804    
805 amb 257 prevsegmentx=&segmentsx->xdata[segmentsx->n1data[0]];
806 amb 256
807 amb 110 for(i=1;i<segmentsx->number;i++)
808     {
809 amb 257 SegmentX *segmentx=&segmentsx->xdata[segmentsx->n1data[i]];
810 amb 256
811     if(segmentx->node1==prevsegmentx->node1 &&
812     segmentx->node2==prevsegmentx->node2 &&
813     DISTFLAG(segmentx->distance)==DISTFLAG(prevsegmentx->distance))
814 amb 110 {
815 amb 262 WayX *wayx1=LookupWayX(waysx,IndexWayX(waysx,prevsegmentx->way),1);
816     WayX *wayx2=LookupWayX(waysx,IndexWayX(waysx, segmentx->way),2);
817 amb 110
818 amb 262 if(!WaysCompare(&wayx1->way,&wayx2->way))
819 amb 110 {
820 amb 256 segmentsx->n1data[i-1]=NO_SEGMENT;
821 amb 110
822     duplicate++;
823     }
824     }
825    
826 amb 256 prevsegmentx=segmentx;
827    
828 amb 110 if(!((i+1)%10000))
829     {
830     printf("\rDeduplicating Segments: Segments=%d Duplicate=%d",i+1,duplicate);
831     fflush(stdout);
832     }
833     }
834    
835 amb 229 printf("\rDeduplicated Segments: Segments=%d Duplicate=%d Unique=%d\n",segmentsx->number,duplicate,segmentsx->number-duplicate);
836 amb 110 fflush(stdout);
837     }
838    
839    
840     /*++++++++++++++++++++++++++++++++++++++
841 amb 209 Create the real segments data.
842    
843     SegmentsX* segmentsx The set of segments to use.
844    
845     WaysX* waysx The set of ways to use.
846     ++++++++++++++++++++++++++++++++++++++*/
847    
848     void CreateRealSegments(SegmentsX *segmentsx,WaysX *waysx)
849     {
850 amb 214 index_t i;
851 amb 209
852 amb 243 assert(segmentsx->n1data); /* Must have n1data filled in => sorted by node 1 */
853     assert(!segmentsx->sdata); /* Must not have sdata filled in => no real segments */
854 amb 213
855 amb 227 printf("Creating Real Segments: Segments=0");
856     fflush(stdout);
857    
858 amb 209 /* Allocate the memory */
859    
860     segmentsx->sdata=(Segment*)malloc(segmentsx->number*sizeof(Segment));
861    
862 amb 243 assert(segmentsx->sdata); /* Check malloc() worked */
863    
864 amb 209 /* Loop through and allocate. */
865    
866     for(i=0;i<segmentsx->number;i++)
867     {
868 amb 257 SegmentX *segmentx=LookupSegmentX(segmentsx,segmentsx->n1data[i]);
869 amb 262 WayX *wayx=LookupWayX(waysx,IndexWayX(waysx,segmentx->way),1);
870 amb 209
871     segmentsx->sdata[i].node1=0;
872     segmentsx->sdata[i].node2=0;
873     segmentsx->sdata[i].next2=NO_NODE;
874 amb 262 segmentsx->sdata[i].way=wayx->cid;
875 amb 256 segmentsx->sdata[i].distance=segmentx->distance;
876 amb 209
877     if(!((i+1)%10000))
878     {
879     printf("\rCreating Real Segments: Segments=%d",i+1);
880     fflush(stdout);
881     }
882     }
883    
884     printf("\rCreating Real Segments: Segments=%d \n",segmentsx->number);
885     fflush(stdout);
886     }
887    
888    
889     /*++++++++++++++++++++++++++++++++++++++
890 amb 110 Assign the nodes indexes to the segments.
891    
892     SegmentsX* segmentsx The set of segments to process.
893    
894     NodesX *nodesx The list of nodes to use.
895     ++++++++++++++++++++++++++++++++++++++*/
896    
897     void IndexSegments(SegmentsX* segmentsx,NodesX *nodesx)
898     {
899 amb 214 index_t i;
900 amb 110
901 amb 243 assert(segmentsx->n1data); /* Must have n1data filled in => sorted by node 1 */
902     assert(segmentsx->sdata); /* Must have sdata filled in => real segments */
903     assert(nodesx->gdata); /* Must have gdata filled in => sorted geographically */
904 amb 110
905 amb 227 printf("Indexing Nodes: Nodes=0");
906     fflush(stdout);
907    
908 amb 110 /* Index the segments */
909    
910     for(i=0;i<nodesx->number;i++)
911     {
912 amb 257 Node *node =&nodesx->ndata[nodesx->gdata[i]];
913 amb 212 index_t index=SEGMENT(node->firstseg);
914 amb 110
915     do
916     {
917 amb 257 SegmentX *segmentx=LookupSegmentX(segmentsx,segmentsx->n1data[index]);
918 amb 256
919 amb 257 if(segmentx->node1==nodesx->idata[nodesx->gdata[i]])
920 amb 110 {
921 amb 209 segmentsx->sdata[index].node1=i;
922 amb 110
923 amb 209 index++;
924 amb 128
925 amb 256 if(index>=segmentsx->number)
926 amb 209 break;
927 amb 256
928 amb 257 segmentx=LookupSegmentX(segmentsx,segmentsx->n1data[index]);
929 amb 256
930 amb 257 if(segmentx->node1!=nodesx->idata[nodesx->gdata[i]])
931 amb 256 break;
932 amb 110 }
933     else
934     {
935 amb 209 segmentsx->sdata[index].node2=i;
936 amb 110
937 amb 209 if(segmentsx->sdata[index].next2==NO_NODE)
938     break;
939 amb 110 else
940 amb 209 index=segmentsx->sdata[index].next2;
941 amb 110 }
942     }
943 amb 209 while(1);
944 amb 110
945     if(!((i+1)%10000))
946     {
947     printf("\rIndexing Nodes: Nodes=%d",i+1);
948     fflush(stdout);
949     }
950     }
951    
952     printf("\rIndexed Nodes: Nodes=%d \n",nodesx->number);
953     fflush(stdout);
954     }
955    
956    
957     /*++++++++++++++++++++++++++++++++++++++
958     Calculate the distance between two nodes.
959    
960     distance_t DistanceX Returns the distance between the extended nodes.
961    
962     NodeX *nodex1 The starting node.
963    
964     NodeX *nodex2 The end node.
965     ++++++++++++++++++++++++++++++++++++++*/
966    
967 amb 228 static distance_t DistanceX(NodeX *nodex1,NodeX *nodex2)
968 amb 110 {
969 amb 223 double dlon = latlong_to_radians(nodex1->longitude) - latlong_to_radians(nodex2->longitude);
970     double dlat = latlong_to_radians(nodex1->latitude) - latlong_to_radians(nodex2->latitude);
971     double lat1 = latlong_to_radians(nodex1->latitude);
972     double lat2 = latlong_to_radians(nodex2->latitude);
973 amb 110
974 amb 219 double a1,a2,a,sa,c,d;
975 amb 110
976     if(dlon==0 && dlat==0)
977     return 0;
978    
979 amb 219 a1 = sin (dlat / 2);
980     a2 = sin (dlon / 2);
981     a = (a1 * a1) + cos (lat1) * cos (lat2) * a2 * a2;
982     sa = sqrt (a);
983 amb 110 if (sa <= 1.0)
984 amb 219 {c = 2 * asin (sa);}
985 amb 110 else
986 amb 219 {c = 2 * asin (1.0);}
987 amb 110 d = 6378.137 * c;
988    
989     return km_to_distance(d);
990     }

Properties

Name Value
cvs:description Extended segments functions.