Routino SVN Repository Browser

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

ViewVC logotype

Contents of /trunk/src/segments.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download) (as text)
Sun Jan 11 09:28:31 2009 UTC (16 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 9876 byte(s)
Working version with supersegments and junctions.

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

Properties

Name Value
cvs:description Segment data type.