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 257 - (hide annotations) (download) (as text)
Mon Sep 7 19:01:59 2009 UTC (15 years, 6 months ago) by amb
File MIME type: text/x-csrc
File size: 25949 byte(s)
Fixed slim mode for segments and nodes (slim now means mapping only one file
into RAM at a time and none when creating the final output).

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

Properties

Name Value
cvs:description Extended segments functions.