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/segments.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 97 - (hide annotations) (download) (as text)
Sun Feb 1 17:11:08 2009 UTC (16 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 14889 byte(s)
Rename some variable types.

1 amb 2 /***************************************
2 amb 97 $Header: /home/amb/CVS/routino/src/segments.c,v 1.26 2009-02-01 17:11:08 amb Exp $
3 amb 2
4     Segment data type functions.
5     ******************/ /******************
6     Written by Andrew M. Bishop
7    
8 amb 4 This file Copyright 2008,2009 Andrew M. Bishop
9 amb 2 It may be distributed under the GNU Public License, version 2, or
10     any higher version. See section COPYING of the GNU Public license
11     for conditions under which this file may be redistributed.
12     ***************************************/
13    
14    
15 amb 8 #include <assert.h>
16 amb 2 #include <math.h>
17     #include <stdlib.h>
18    
19 amb 39 #include "nodes.h"
20 amb 26 #include "segments.h"
21 amb 2 #include "functions.h"
22    
23    
24 amb 96 /* Constants */
25    
26     /*+ The array size increment for segments - expect ~8,000,000 segments. +*/
27     #define INCREMENT_SEGMENTS 1024*1024
28    
29    
30 amb 23 /* Functions */
31 amb 2
32 amb 97 static int sort_by_id(SegmentX *a,SegmentX *b);
33 amb 2
34 amb 8
35 amb 23 /*++++++++++++++++++++++++++++++++++++++
36 amb 2 Load in a segment list from a file.
37    
38 amb 23 Segments* SaveSegmentList Returns the segment list that has just been loaded.
39    
40 amb 2 const char *filename The name of the file to load.
41     ++++++++++++++++++++++++++++++++++++++*/
42    
43 amb 23 Segments *LoadSegmentList(const char *filename)
44 amb 2 {
45 amb 88 void *data;
46     Segments *segments;
47    
48     segments=(Segments*)malloc(sizeof(Segments));
49    
50     data=MapFile(filename);
51    
52     /* Copy the Segments structure from the loaded data */
53    
54     *segments=*((Segments*)data);
55    
56     /* Adjust the pointers in the Segments structure. */
57    
58     segments->data =data;
59     segments->segments=(Segment*)(data+(off_t)segments->segments);
60    
61     return(segments);
62 amb 2 }
63    
64    
65     /*++++++++++++++++++++++++++++++++++++++
66 amb 97 Allocate a new segment list.
67    
68     SegmentsX *NewSegmentList Returns the segment list.
69     ++++++++++++++++++++++++++++++++++++++*/
70    
71     SegmentsX *NewSegmentList(void)
72     {
73     SegmentsX *segmentsx;
74    
75     segmentsx=(SegmentsX*)malloc(sizeof(SegmentsX));
76    
77     segmentsx->sorted=0;
78     segmentsx->alloced=INCREMENT_SEGMENTS;
79     segmentsx->number=0;
80    
81     segmentsx->xdata=(SegmentX*)malloc(segmentsx->alloced*sizeof(SegmentX));
82    
83     return(segmentsx);
84     }
85    
86    
87     /*++++++++++++++++++++++++++++++++++++++
88     Free a segment list.
89    
90     SegmentsX *segmentsx The list to be freed.
91     ++++++++++++++++++++++++++++++++++++++*/
92    
93     void FreeSegmentList(SegmentsX *segmentsx)
94     {
95     free(segmentsx->xdata);
96     free(segmentsx);
97     }
98    
99    
100     /*++++++++++++++++++++++++++++++++++++++
101 amb 2 Save the segment list to a file.
102    
103 amb 97 SegmentsX* segmentsx The set of segments to save.
104 amb 23
105 amb 2 const char *filename The name of the file to save.
106     ++++++++++++++++++++++++++++++++++++++*/
107    
108 amb 97 void SaveSegmentList(SegmentsX* segmentsx,const char *filename)
109 amb 2 {
110 amb 88 int i;
111     int fd;
112     Segments *segments=calloc(1,sizeof(Segments));
113 amb 2
114 amb 97 assert(segmentsx->sorted); /* Must be sorted */
115 amb 23
116 amb 88 /* Fill in a Segments structure with the offset of the real data in the file after
117     the Segment structure itself. */
118    
119 amb 97 segments->number=segmentsx->number;
120 amb 88 segments->data=NULL;
121     segments->segments=(void*)sizeof(Segments);
122    
123     /* Write out the Segments structure and then the real data. */
124    
125     fd=OpenFile(filename);
126    
127 amb 97 WriteFile(fd,segments,sizeof(Segments));
128 amb 88
129 amb 97 for(i=0;i<segmentsx->number;i++)
130     WriteFile(fd,&segmentsx->xdata[i].segment,sizeof(Segment));
131 amb 88
132 amb 97 CloseFile(fd);
133 amb 88
134 amb 89 /* Free the fake Segments */
135 amb 88
136 amb 23 free(segments);
137 amb 2 }
138    
139    
140     /*++++++++++++++++++++++++++++++++++++++
141     Find the first segment with a particular starting node.
142    
143 amb 97 SegmentX *FindFirstSegment Returns the first extended segment with the specified id.
144 amb 2
145 amb 97 SegmentsX* segmentsx The set of segments to process.
146 amb 23
147 amb 2 node_t node The node to look for.
148     ++++++++++++++++++++++++++++++++++++++*/
149    
150 amb 97 SegmentX *FindFirstSegment(SegmentsX* segmentsx,node_t node)
151 amb 2 {
152 amb 88 int start=0;
153 amb 97 int end=segmentsx->number-1;
154 amb 2 int mid;
155     int found;
156    
157     /* Binary search - search key exact match only is required.
158     *
159     * # <- start | Check mid and move start or end if it doesn't match
160     * # |
161     * # | Since an exact match is wanted we can set end=mid-1
162     * # <- mid | or start=mid+1 because we know that mid doesn't match.
163     * # |
164     * # | Eventually either end=start or end=start+1 and one of
165     * # <- end | start or end is the wanted one.
166     */
167    
168 amb 23 if(end<start) /* There are no nodes */
169 amb 89 return(NULL);
170 amb 97 else if(node<segmentsx->xdata[start].node1) /* Check key is not before start */
171 amb 89 return(NULL);
172 amb 97 else if(node>segmentsx->xdata[end].node1) /* Check key is not after end */
173 amb 89 return(NULL);
174 amb 2 else
175     {
176     do
177     {
178 amb 23 mid=(start+end)/2; /* Choose mid point */
179 amb 2
180 amb 97 if(segmentsx->xdata[mid].node1<node) /* Mid point is too low */
181 amb 2 start=mid;
182 amb 97 else if(segmentsx->xdata[mid].node1>node) /* Mid point is too high */
183 amb 2 end=mid;
184 amb 23 else /* Mid point is correct */
185 amb 2 {found=mid; goto found;}
186     }
187     while((end-start)>1);
188    
189 amb 97 if(segmentsx->xdata[start].node1==node) /* Start is correct */
190 amb 2 {found=start; goto found;}
191    
192 amb 97 if(segmentsx->xdata[end].node1==node) /* End is correct */
193 amb 2 {found=end; goto found;}
194     }
195    
196 amb 89 return(NULL);
197 amb 2
198     found:
199    
200 amb 97 while(found>0 && segmentsx->xdata[found-1].node1==node)
201 amb 2 found--;
202    
203 amb 97 return(&segmentsx->xdata[found]);
204 amb 2 }
205    
206    
207     /*++++++++++++++++++++++++++++++++++++++
208     Find the next segment with a particular starting node.
209    
210 amb 97 SegmentX *NextSegment Returns a pointer to the next segment with the same id.
211 amb 89
212 amb 97 SegmentsX* segments The set of segments to process.
213 amb 89
214 amb 97 SegmentX *segmentex The current segment.
215 amb 89 ++++++++++++++++++++++++++++++++++++++*/
216    
217 amb 97 SegmentX *FindNextSegment(SegmentsX* segmentsx,SegmentX *segmentex)
218 amb 89 {
219 amb 97 SegmentX *next=segmentex+1;
220 amb 89
221 amb 97 if(IndexSegmentX(segmentsx,next)==segmentsx->number)
222 amb 89 return(NULL);
223    
224     if(next->node1==segmentex->node1)
225     return(next);
226    
227     return(NULL);
228     }
229    
230    
231     /*++++++++++++++++++++++++++++++++++++++
232     Find the next segment with a particular starting node.
233    
234 amb 88 Segment *NextSegment Returns a pointer to the next segment with the same id.
235 amb 2
236 amb 23 Segments* segments The set of segments to process.
237    
238 amb 2 Segment *segment The current segment.
239     ++++++++++++++++++++++++++++++++++++++*/
240    
241 amb 88 Segment *NextSegment(Segments* segments,Segment *segment)
242 amb 2 {
243     Segment *next=segment+1;
244    
245 amb 89 if(IndexSegment(segments,next)==segments->number)
246 amb 23 return(NULL);
247 amb 2
248 amb 90 if(NODE(next->node1)==NODE(segment->node1))
249 amb 2 return(next);
250    
251     return(NULL);
252 amb 89 }
253 amb 88
254    
255 amb 2 /*++++++++++++++++++++++++++++++++++++++
256     Append a segment to a newly created segment list (unsorted).
257    
258 amb 97 SegmentX *AppendSegment Returns the appended segment.
259 amb 31
260 amb 97 SegmentsX* segmentsx The set of segments to process.
261 amb 23
262 amb 2 node_t node1 The first node in the segment.
263    
264     node_t node2 The second node in the segment.
265    
266 amb 96 index_t way The index of the way that the pair of segments are connected by.
267 amb 2 ++++++++++++++++++++++++++++++++++++++*/
268    
269 amb 97 SegmentX *AppendSegment(SegmentsX* segmentsx,node_t node1,node_t node2,index_t way)
270 amb 2 {
271 amb 23 /* Check that the array has enough space. */
272 amb 8
273 amb 97 if(segmentsx->number==segmentsx->alloced)
274 amb 4 {
275 amb 97 segmentsx->alloced+=INCREMENT_SEGMENTS;
276 amb 4
277 amb 97 segmentsx->xdata=(SegmentX*)realloc((void*)segmentsx->xdata,segmentsx->alloced*sizeof(SegmentX));
278 amb 4 }
279    
280     /* Insert the segment */
281    
282 amb 97 segmentsx->xdata[segmentsx->number].node1=node1;
283     segmentsx->xdata[segmentsx->number].node2=node2;
284     segmentsx->xdata[segmentsx->number].segment.way=way;
285     segmentsx->xdata[segmentsx->number].segment.distance=0;
286 amb 2
287 amb 97 segmentsx->number++;
288 amb 2
289 amb 97 segmentsx->sorted=0;
290 amb 31
291 amb 97 return(&segmentsx->xdata[segmentsx->number-1]);
292 amb 2 }
293    
294    
295     /*++++++++++++++++++++++++++++++++++++++
296     Sort the segment list.
297 amb 23
298 amb 97 SegmentsX* segmentsx The set of segments to process.
299 amb 2 ++++++++++++++++++++++++++++++++++++++*/
300    
301 amb 97 void SortSegmentList(SegmentsX* segmentsx)
302 amb 2 {
303 amb 97 qsort(segmentsx->xdata,segmentsx->number,sizeof(SegmentX),(int (*)(const void*,const void*))sort_by_id);
304 amb 39
305 amb 97 while(segmentsx->xdata[segmentsx->number-1].node1==~0)
306     segmentsx->number--;
307 amb 8
308 amb 97 segmentsx->sorted=1;
309 amb 2 }
310    
311    
312     /*++++++++++++++++++++++++++++++++++++++
313     Sort the segments into id order.
314    
315     int sort_by_id Returns the comparison of the node fields.
316    
317 amb 97 SegmentX *a The first Segment.
318 amb 2
319 amb 97 SegmentX *b The second Segment.
320 amb 2 ++++++++++++++++++++++++++++++++++++++*/
321    
322 amb 97 static int sort_by_id(SegmentX *a,SegmentX *b)
323 amb 2 {
324     node_t a_id1=a->node1,a_id2=a->node2;
325     node_t b_id1=b->node1,b_id2=b->node2;
326    
327 amb 39 if(a_id1<b_id1)
328     return(-1);
329     else if(a_id1>b_id1)
330     return(1);
331     else /* if(a_id1==b_id1) */
332     {
333     if(a_id2<b_id2)
334     return(-1);
335 amb 88 else
336 amb 39 return(1);
337     }
338 amb 2 }
339    
340    
341     /*++++++++++++++++++++++++++++++++++++++
342 amb 39 Remove bad segments (zero length or duplicated).
343    
344 amb 97 SegmentsX *segmentsx The segments to modify.
345 amb 39 ++++++++++++++++++++++++++++++++++++++*/
346    
347 amb 97 void RemoveBadSegments(SegmentsX *segmentsx)
348 amb 39 {
349     int i;
350     int duplicate=0,loop=0;
351     node_t node1=~0,node2=~0;
352    
353 amb 97 for(i=0;i<segmentsx->number;i++)
354 amb 39 {
355 amb 97 if(segmentsx->xdata[i].node1==node1 && segmentsx->xdata[i].node2==node2)
356 amb 39 {
357     duplicate++;
358 amb 97 segmentsx->xdata[i].node1=~0;
359 amb 39 }
360 amb 97 else if(segmentsx->xdata[i].node1==segmentsx->xdata[i].node2)
361 amb 39 {
362     loop++;
363 amb 97 segmentsx->xdata[i].node1=~0;
364 amb 39 }
365    
366 amb 97 node1=segmentsx->xdata[i].node1;
367     node2=segmentsx->xdata[i].node2;
368 amb 39
369     if(!((i+1)%10000))
370     {
371     printf("\rChecking: Segments=%d Duplicate=%d Loop=%d",i+1,duplicate,loop);
372     fflush(stdout);
373     }
374     }
375    
376 amb 97 printf("\rChecked: Segments=%d Duplicate=%d Loop=%d \n",segmentsx->number,duplicate,loop);
377 amb 39 fflush(stdout);
378     }
379    
380    
381     /*++++++++++++++++++++++++++++++++++++++
382 amb 89 Measure the segments.
383 amb 23
384 amb 97 SegmentsX* segmentsx The set of segments to process.
385 amb 23
386 amb 97 NodesX *nodesx The list of nodes to use.
387 amb 8 ++++++++++++++++++++++++++++++++++++++*/
388 amb 2
389 amb 97 void MeasureSegments(SegmentsX* segmentsx,NodesX *nodesx)
390 amb 8 {
391     int i;
392 amb 2
393 amb 97 assert(segmentsx->sorted); /* Must be sorted */
394 amb 8
395 amb 97 for(i=0;i<segmentsx->number;i++)
396 amb 8 {
397 amb 97 NodeX *node1=FindNode(nodesx,segmentsx->xdata[i].node1);
398     NodeX *node2=FindNode(nodesx,segmentsx->xdata[i].node2);
399 amb 8
400 amb 82 /* Set the distance but preserve the ONEWAY_OPPOSITE flag */
401 amb 8
402 amb 97 segmentsx->xdata[i].segment.distance|=Distance(&node1->node,&node2->node);
403 amb 69
404 amb 54 if(!((i+1)%10000))
405     {
406 amb 89 printf("\rMeasuring Segments: Segments=%d",i+1);
407     fflush(stdout);
408     }
409     }
410    
411 amb 97 printf("\rMeasured Segments: Segments=%d \n",segmentsx->number);
412 amb 89 fflush(stdout);
413     }
414    
415    
416     /*++++++++++++++++++++++++++++++++++++++
417     Fix the segment indexes to the nodes.
418    
419 amb 97 SegmentsX* segmentsx The set of segments to process.
420 amb 89
421 amb 97 NodesX *nodesx The list of nodes to use.
422 amb 90
423 amb 97 SegmentsX* supersegmentsx The set of super-segments to append.
424 amb 89 ++++++++++++++++++++++++++++++++++++++*/
425    
426 amb 97 void FixupSegments(SegmentsX* segmentsx,NodesX *nodesx,SegmentsX* supersegmentsx)
427 amb 89 {
428 amb 90 int i,j,n;
429 amb 89
430 amb 97 assert(segmentsx->sorted); /* Must be sorted */
431     assert(supersegmentsx->sorted); /* Must be sorted */
432 amb 89
433 amb 97 for(i=0;i<segmentsx->number;i++)
434 amb 89 {
435 amb 97 NodeX *node1=FindNode(nodesx,segmentsx->xdata[i].node1);
436     NodeX *node2=FindNode(nodesx,segmentsx->xdata[i].node2);
437 amb 89
438 amb 97 segmentsx->xdata[i].segment.node1=IndexNodeX(nodesx,node1)|SUPER_FLAG;
439     segmentsx->xdata[i].segment.node2=IndexNodeX(nodesx,node2);
440 amb 89
441     if(!((i+1)%10000))
442     {
443 amb 88 printf("\rFixing Segments: Segments=%d",i+1);
444 amb 54 fflush(stdout);
445     }
446 amb 8 }
447 amb 54
448 amb 97 printf("\rFixed Segments: Segments=%d \n",segmentsx->number);
449 amb 54 fflush(stdout);
450 amb 90
451 amb 97 for(i=0;i<supersegmentsx->number;i++)
452 amb 90 {
453 amb 97 NodeX *node1=FindNode(nodesx,supersegmentsx->xdata[i].node1);
454     NodeX *node2=FindNode(nodesx,supersegmentsx->xdata[i].node2);
455 amb 90
456 amb 97 supersegmentsx->xdata[i].segment.node1=IndexNodeX(nodesx,node1);
457     supersegmentsx->xdata[i].segment.node2=IndexNodeX(nodesx,node2)|SUPER_FLAG;
458 amb 90
459     if(!((i+1)%10000))
460     {
461     printf("\rFixing Super-Segments: Super-Segments=%d",i+1);
462     fflush(stdout);
463     }
464     }
465    
466 amb 97 printf("\rFixed Super-Segments: Super-Segments=%d \n",supersegmentsx->number);
467 amb 90 fflush(stdout);
468    
469 amb 97 n=segmentsx->number;
470 amb 90
471     for(i=0,j=0;i<n;i++)
472     {
473 amb 97 while(j<supersegmentsx->number)
474 amb 90 {
475 amb 97 if(segmentsx->xdata[i].node1==supersegmentsx->xdata[j].node1 &&
476     segmentsx->xdata[i].node2==supersegmentsx->xdata[j].node2)
477 amb 90 {
478 amb 97 segmentsx->xdata[i].segment.node2|=SUPER_FLAG;
479 amb 90 j++;
480     break;
481     }
482 amb 97 else if(segmentsx->xdata[i].node1==supersegmentsx->xdata[j].node1 &&
483     segmentsx->xdata[i].node2>supersegmentsx->xdata[j].node2)
484 amb 90 {
485 amb 97 SegmentX *supersegmentex=AppendSegment(segmentsx,supersegmentsx->xdata[j].node1,supersegmentsx->xdata[j].node2,supersegmentsx->xdata[j].segment.way);
486 amb 90
487 amb 97 supersegmentex->segment.node1=supersegmentsx->xdata[j].segment.node1;
488     supersegmentex->segment.node2=supersegmentsx->xdata[j].segment.node2;
489     supersegmentex->segment.distance=supersegmentsx->xdata[j].segment.distance;
490 amb 90 }
491 amb 97 else if(segmentsx->xdata[i].node1>supersegmentsx->xdata[j].node1)
492 amb 90 {
493 amb 97 SegmentX *supersegmentex=AppendSegment(segmentsx,supersegmentsx->xdata[j].node1,supersegmentsx->xdata[j].node2,supersegmentsx->xdata[j].segment.way);
494 amb 90
495 amb 97 supersegmentex->segment.node1=supersegmentsx->xdata[j].segment.node1;
496     supersegmentex->segment.node2=supersegmentsx->xdata[j].segment.node2;
497     supersegmentex->segment.distance=supersegmentsx->xdata[j].segment.distance;
498 amb 90 }
499     else
500     break;
501    
502     j++;
503     }
504    
505     if(!((i+1)%10000))
506     {
507 amb 97 printf("\rMerging Segments: Segments=%d Super-Segment=%d Total=%d",i+1,j+1,segmentsx->number);
508 amb 90 fflush(stdout);
509     }
510     }
511    
512 amb 97 printf("\rMerged Segments: Segments=%d Super-Segment=%d Total=%d \n",n,supersegmentsx->number,segmentsx->number);
513 amb 90 fflush(stdout);
514 amb 8 }
515    
516    
517     /*++++++++++++++++++++++++++++++++++++++
518     Calculate the distance between two nodes.
519    
520     distance_t Distance Returns the distance between the nodes.
521    
522 amb 2 Node *node1 The starting node.
523    
524     Node *node2 The end node.
525     ++++++++++++++++++++++++++++++++++++++*/
526    
527 amb 8 distance_t Distance(Node *node1,Node *node2)
528 amb 2 {
529     double radiant = M_PI / 180;
530    
531     double dlon = radiant * (node1->longitude - node2->longitude);
532     double dlat = radiant * (node1->latitude - node2->latitude);
533    
534     double a1,a2,a,sa,c,d;
535    
536     if(dlon==0 && dlat==0)
537     return 0;
538    
539     a1 = sin (dlat / 2);
540     a2 = sin (dlon / 2);
541     a = (a1 * a1) + cos (node1->latitude * radiant) * cos (node2->latitude * radiant) * a2 * a2;
542     sa = sqrt (a);
543     if (sa <= 1.0)
544     {c = 2 * asin (sa);}
545     else
546     {c = 2 * asin (1.0);}
547 amb 5 d = 6378.137 * c;
548 amb 2
549 amb 5 return km_to_distance(d);
550 amb 2 }
551 amb 63
552    
553     /*++++++++++++++++++++++++++++++++++++++
554     Calculate the duration of segment.
555    
556     duration_t Duration Returns the duration of travel between the nodes.
557    
558     Segment *segment The segment to traverse.
559    
560     Way *way The way that the segment belongs to.
561    
562 amb 82 Profile *profile The profile of the transport being used.
563 amb 63 ++++++++++++++++++++++++++++++++++++++*/
564    
565 amb 82 duration_t Duration(Segment *segment,Way *way,Profile *profile)
566 amb 63 {
567 amb 82 speed_t speed=profile->speed[HIGHWAY(way->type)];
568 amb 90 distance_t distance=DISTANCE(segment->distance);
569 amb 63
570 amb 86 return distance_speed_to_duration(distance,speed);
571 amb 63 }

Properties

Name Value
cvs:description Segment data type.