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 53 - (hide annotations) (download) (as text)
Sun Jan 18 09:09:28 2009 UTC (16 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 11075 byte(s)
Fix for changes made to ways.

1 amb 2 /***************************************
2 amb 53 $Header: /home/amb/CVS/routino/src/segments.c,v 1.10 2009-01-18 09:09:28 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 23 /* Functions */
25 amb 2
26 amb 23 static int sort_by_id(Segment *a,Segment *b);
27 amb 2
28 amb 8
29 amb 23 /*++++++++++++++++++++++++++++++++++++++
30     Allocate a new segment list.
31 amb 8
32 amb 23 SegmentsMem *NewSegmentList Returns the segment list.
33     ++++++++++++++++++++++++++++++++++++++*/
34 amb 2
35 amb 23 SegmentsMem *NewSegmentList(void)
36     {
37     SegmentsMem *segments;
38 amb 2
39 amb 23 segments=(SegmentsMem*)malloc(sizeof(SegmentsMem));
40 amb 2
41 amb 23 segments->alloced=INCREMENT_SEGMENTS;
42     segments->number=0;
43     segments->sorted=0;
44    
45     segments->segments=(Segments*)malloc(sizeof(Segments)+segments->alloced*sizeof(Segment));
46    
47     return(segments);
48     }
49    
50    
51 amb 2 /*++++++++++++++++++++++++++++++++++++++
52     Load in a segment list from a file.
53    
54 amb 23 Segments* SaveSegmentList Returns the segment list that has just been loaded.
55    
56 amb 2 const char *filename The name of the file to load.
57     ++++++++++++++++++++++++++++++++++++++*/
58    
59 amb 23 Segments *LoadSegmentList(const char *filename)
60 amb 2 {
61 amb 23 return((Segments*)MapFile(filename));
62 amb 2 }
63    
64    
65     /*++++++++++++++++++++++++++++++++++++++
66     Save the segment list to a file.
67    
68 amb 23 Segments* SaveSegmentList Returns the segment list that has just been saved.
69    
70     SegmentsMem* segments The set of segments to save.
71    
72 amb 2 const char *filename The name of the file to save.
73     ++++++++++++++++++++++++++++++++++++++*/
74    
75 amb 23 Segments *SaveSegmentList(SegmentsMem* segments,const char *filename)
76 amb 2 {
77 amb 23 assert(segments->sorted); /* Must be sorted */
78 amb 2
79 amb 23 if(WriteFile(filename,(void*)segments->segments,sizeof(Segments)-sizeof(segments->segments->segments)+segments->number*sizeof(Segment)))
80     assert(0);
81    
82     free(segments->segments);
83     free(segments);
84    
85     return(LoadSegmentList(filename));
86 amb 2 }
87    
88    
89     /*++++++++++++++++++++++++++++++++++++++
90     Find the first segment with a particular starting node.
91    
92     Segment *FindFirstSegment Returns a pointer to the first segment with the specified id.
93    
94 amb 23 Segments* segments The set of segments to process.
95    
96 amb 2 node_t node The node to look for.
97     ++++++++++++++++++++++++++++++++++++++*/
98    
99 amb 23 Segment *FindFirstSegment(Segments* segments,node_t node)
100 amb 2 {
101 amb 23 #ifdef NBINS_SEGMENTS
102     int bin=node%NBINS_SEGMENTS;
103     int start=segments->offset[bin];
104     int end=segments->offset[bin+1]-1;
105     #else
106 amb 2 int start=0;
107 amb 23 int end=segments->number-1;
108     #endif
109 amb 2 int mid;
110     int found;
111    
112     /* Binary search - search key exact match only is required.
113     *
114     * # <- start | Check mid and move start or end if it doesn't match
115     * # |
116     * # | Since an exact match is wanted we can set end=mid-1
117     * # <- mid | or start=mid+1 because we know that mid doesn't match.
118     * # |
119     * # | Eventually either end=start or end=start+1 and one of
120     * # <- end | start or end is the wanted one.
121     */
122    
123 amb 23 if(end<start) /* There are no nodes */
124 amb 2 return(NULL);
125 amb 23 else if(node<segments->segments[start].node1) /* Check key is not before start */
126 amb 2 return(NULL);
127 amb 23 else if(node>segments->segments[end].node1) /* Check key is not after end */
128 amb 2 return(NULL);
129     else
130     {
131     do
132     {
133 amb 23 mid=(start+end)/2; /* Choose mid point */
134 amb 2
135 amb 23 if(segments->segments[mid].node1<node) /* Mid point is too low */
136 amb 2 start=mid;
137 amb 23 else if(segments->segments[mid].node1>node) /* Mid point is too high */
138 amb 2 end=mid;
139 amb 23 else /* Mid point is correct */
140 amb 2 {found=mid; goto found;}
141     }
142     while((end-start)>1);
143    
144 amb 23 if(segments->segments[start].node1==node) /* Start is correct */
145 amb 2 {found=start; goto found;}
146    
147 amb 23 if(segments->segments[end].node1==node) /* End is correct */
148 amb 2 {found=end; goto found;}
149     }
150    
151     return(NULL);
152    
153     found:
154    
155 amb 23 while(found>0 && segments->segments[found-1].node1==node)
156 amb 2 found--;
157    
158 amb 23 return(&segments->segments[found]);
159 amb 2 }
160    
161    
162     /*++++++++++++++++++++++++++++++++++++++
163     Find the next segment with a particular starting node.
164    
165 amb 23 Segment *FindNextSegment Returns a pointer to the next segment with the same id.
166 amb 2
167 amb 23 Segments* segments The set of segments to process.
168    
169 amb 2 Segment *segment The current segment.
170     ++++++++++++++++++++++++++++++++++++++*/
171    
172 amb 23 Segment *FindNextSegment(Segments* segments,Segment *segment)
173 amb 2 {
174     Segment *next=segment+1;
175    
176 amb 23 if((next-segments->segments)==segments->number)
177     return(NULL);
178 amb 2
179     if(next->node1==segment->node1)
180     return(next);
181    
182     return(NULL);
183     }
184    
185    
186     /*++++++++++++++++++++++++++++++++++++++
187     Append a segment to a newly created segment list (unsorted).
188    
189 amb 31 Segment *AppendSegment Returns the appended segment.
190    
191 amb 23 SegmentsMem* segments The set of segments to process.
192    
193 amb 2 node_t node1 The first node in the segment.
194    
195     node_t node2 The second node in the segment.
196    
197 amb 5 way_t way The way that the pair of segments are connected by.
198 amb 2 ++++++++++++++++++++++++++++++++++++++*/
199    
200 amb 31 Segment *AppendSegment(SegmentsMem* segments,node_t node1,node_t node2,way_t way)
201 amb 2 {
202 amb 23 /* Check that the array has enough space. */
203 amb 8
204 amb 23 if(segments->number==segments->alloced)
205 amb 4 {
206 amb 23 segments->alloced+=INCREMENT_SEGMENTS;
207 amb 4
208 amb 23 segments->segments=(Segments*)realloc((void*)segments->segments,sizeof(Segments)+segments->alloced*sizeof(Segment));
209 amb 4 }
210    
211     /* Insert the segment */
212    
213 amb 23 segments->segments->segments[segments->number].node1=node1;
214     segments->segments->segments[segments->number].node2=node2;
215     segments->segments->segments[segments->number].way=way;
216     segments->segments->segments[segments->number].distance=0;
217     segments->segments->segments[segments->number].duration=0;
218 amb 2
219 amb 23 segments->number++;
220 amb 2
221 amb 23 segments->sorted=0;
222 amb 31
223     return(&segments->segments->segments[segments->number-1]);
224 amb 2 }
225    
226    
227     /*++++++++++++++++++++++++++++++++++++++
228     Sort the segment list.
229 amb 23
230     SegmentsMem* segments The set of segments to process.
231 amb 2 ++++++++++++++++++++++++++++++++++++++*/
232    
233 amb 23 void SortSegmentList(SegmentsMem* segments)
234 amb 2 {
235 amb 39 #ifdef NBINS_SEGMENTS
236     int i,bin=0;
237     #endif
238    
239 amb 23 qsort(segments->segments->segments,segments->number,sizeof(Segment),(int (*)(const void*,const void*))sort_by_id);
240 amb 8
241 amb 39 while(segments->segments->segments[segments->number-1].node1==~0)
242     segments->number--;
243    
244 amb 23 segments->sorted=1;
245 amb 39
246     /* Make it searchable */
247    
248     segments->segments->number=segments->number;
249    
250     #ifdef NBINS_SEGMENTS
251     for(i=0;i<segments->number;i++)
252     for(;bin<=(segments->segments->segments[i].node1%NBINS_SEGMENTS);bin++)
253     segments->segments->offset[bin]=i;
254    
255     for(;bin<=NBINS_SEGMENTS;bin++)
256     segments->segments->offset[bin]=segments->number;
257     #endif
258 amb 2 }
259    
260    
261     /*++++++++++++++++++++++++++++++++++++++
262     Sort the segments into id order.
263    
264     int sort_by_id Returns the comparison of the node fields.
265    
266     Segment *a The first Segment.
267    
268     Segment *b The second Segment.
269     ++++++++++++++++++++++++++++++++++++++*/
270    
271     static int sort_by_id(Segment *a,Segment *b)
272     {
273     node_t a_id1=a->node1,a_id2=a->node2;
274     node_t b_id1=b->node1,b_id2=b->node2;
275    
276 amb 23 #ifdef NBINS_SEGMENTS
277     int a_bin=a->node1%NBINS_SEGMENTS;
278     int b_bin=b->node1%NBINS_SEGMENTS;
279    
280     if(a_bin!=b_bin)
281     return(a_bin-b_bin);
282     #endif
283    
284 amb 39 if(a_id1<b_id1)
285     return(-1);
286     else if(a_id1>b_id1)
287     return(1);
288     else /* if(a_id1==b_id1) */
289     {
290     if(a_id2<b_id2)
291     return(-1);
292     else if(a_id2>b_id2)
293     return(1);
294     else
295     return(0);
296     }
297 amb 2 }
298    
299    
300     /*++++++++++++++++++++++++++++++++++++++
301 amb 39 Remove bad segments (zero length or duplicated).
302    
303     SegmentsMem *segments The segments to modify.
304     ++++++++++++++++++++++++++++++++++++++*/
305    
306     void RemoveBadSegments(SegmentsMem *segments)
307     {
308     int i;
309     int duplicate=0,loop=0;
310     node_t node1=~0,node2=~0;
311    
312     for(i=0;i<segments->number;i++)
313     {
314     Segment *segment=&segments->segments->segments[i];
315    
316     if(segment->node1==node1 && segment->node2==node2)
317     {
318     duplicate++;
319     segment->node1=~0;
320     }
321     else if(segment->node1==segment->node2)
322     {
323     loop++;
324     segment->node1=~0;
325     }
326    
327     node1=segment->node1;
328     node2=segment->node2;
329    
330     if(!((i+1)%10000))
331     {
332     printf("\rChecking: Segments=%d Duplicate=%d Loop=%d",i+1,duplicate,loop);
333     fflush(stdout);
334     }
335     }
336    
337     printf("\rChecked: Segments=%d Duplicate=%d Loop=%d \n",segments->number,duplicate,loop);
338     fflush(stdout);
339     }
340    
341    
342     /*++++++++++++++++++++++++++++++++++++++
343 amb 8 Assign the lengths and durations to all of the segments.
344 amb 23
345     SegmentsMem* segments The set of segments to process.
346    
347     Nodes *nodes The list of nodes to use.
348    
349     Ways *ways The list of ways to use.
350 amb 8 ++++++++++++++++++++++++++++++++++++++*/
351 amb 2
352 amb 23 void FixupSegmentLengths(SegmentsMem* segments,Nodes *nodes,Ways *ways)
353 amb 8 {
354     int i;
355 amb 2
356 amb 23 assert(segments->sorted); /* Must be sorted */
357 amb 8
358 amb 23 for(i=0;i<segments->number;i++)
359 amb 8 {
360 amb 30 speed_t speed;
361 amb 39 distance_t distance=INVALID_SHORT_DISTANCE;
362     duration_t duration=INVALID_SHORT_DURATION;
363 amb 23 Node *node1=FindNode(nodes,segments->segments->segments[i].node1);
364     Node *node2=FindNode(nodes,segments->segments->segments[i].node2);
365     Way *way=FindWay(ways,segments->segments->segments[i].way);
366 amb 8
367 amb 30 if(way->limit)
368     speed=way->limit;
369     else
370     speed=way->speed;
371 amb 8
372 amb 53 if(Way_TYPE(way->type)<Way_Service &&
373     segments->segments->segments[i].distance!=INVALID_SHORT_DISTANCE)
374 amb 30 {
375     distance=Distance(node1,node2);
376     duration=hours_to_duration(distance_to_km(distance)/speed);
377 amb 26
378 amb 39 if(distance>=INVALID_SHORT_DISTANCE)
379 amb 30 {
380     fprintf(stderr,"\nSegment too long (%d->%d) = %.1f km\n",node1->id,node2->id,distance_to_km(distance));
381 amb 39 distance=INVALID_SHORT_DISTANCE;
382 amb 30 }
383    
384 amb 39 if(duration>=INVALID_SHORT_DURATION)
385 amb 30 {
386     fprintf(stderr,"\nSegment too long (%d->%d) = %.1f mins\n",node1->id,node2->id,duration_to_minutes(duration));
387 amb 39 duration=INVALID_SHORT_DURATION;
388 amb 30 }
389 amb 26 }
390    
391 amb 23 segments->segments->segments[i].distance=distance;
392     segments->segments->segments[i].duration=duration;
393 amb 8 }
394     }
395    
396    
397     /*++++++++++++++++++++++++++++++++++++++
398     Calculate the distance between two nodes.
399    
400     distance_t Distance Returns the distance between the nodes.
401    
402 amb 2 Node *node1 The starting node.
403    
404     Node *node2 The end node.
405     ++++++++++++++++++++++++++++++++++++++*/
406    
407 amb 8 distance_t Distance(Node *node1,Node *node2)
408 amb 2 {
409     double radiant = M_PI / 180;
410    
411     double dlon = radiant * (node1->longitude - node2->longitude);
412     double dlat = radiant * (node1->latitude - node2->latitude);
413    
414     double a1,a2,a,sa,c,d;
415    
416     if(dlon==0 && dlat==0)
417     return 0;
418    
419     a1 = sin (dlat / 2);
420     a2 = sin (dlon / 2);
421     a = (a1 * a1) + cos (node1->latitude * radiant) * cos (node2->latitude * radiant) * a2 * a2;
422     sa = sqrt (a);
423     if (sa <= 1.0)
424     {c = 2 * asin (sa);}
425     else
426     {c = 2 * asin (1.0);}
427 amb 5 d = 6378.137 * c;
428 amb 2
429 amb 5 return km_to_distance(d);
430 amb 2 }

Properties

Name Value
cvs:description Segment data type.