Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/segments.c
Parent Directory
|
Revision Log
Revision 59 -
(hide annotations)
(download)
(as text)
Tue Jan 20 17:37:20 2009 UTC (16 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 10290 byte(s)
Tue Jan 20 17:37:20 2009 UTC (16 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 10290 byte(s)
Remove duration from segment, calculate duration depending on speed.
1 | amb | 2 | /*************************************** |
2 | amb | 59 | $Header: /home/amb/CVS/routino/src/segments.c,v 1.12 2009-01-20 17:37:20 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 | amb | 2 | |
218 | amb | 23 | segments->number++; |
219 | amb | 2 | |
220 | amb | 23 | segments->sorted=0; |
221 | amb | 31 | |
222 | return(&segments->segments->segments[segments->number-1]); | ||
223 | amb | 2 | } |
224 | |||
225 | |||
226 | /*++++++++++++++++++++++++++++++++++++++ | ||
227 | Sort the segment list. | ||
228 | amb | 23 | |
229 | SegmentsMem* segments The set of segments to process. | ||
230 | amb | 2 | ++++++++++++++++++++++++++++++++++++++*/ |
231 | |||
232 | amb | 23 | void SortSegmentList(SegmentsMem* segments) |
233 | amb | 2 | { |
234 | amb | 39 | #ifdef NBINS_SEGMENTS |
235 | int i,bin=0; | ||
236 | #endif | ||
237 | |||
238 | amb | 23 | qsort(segments->segments->segments,segments->number,sizeof(Segment),(int (*)(const void*,const void*))sort_by_id); |
239 | amb | 8 | |
240 | amb | 39 | while(segments->segments->segments[segments->number-1].node1==~0) |
241 | segments->number--; | ||
242 | |||
243 | amb | 23 | segments->sorted=1; |
244 | amb | 39 | |
245 | /* Make it searchable */ | ||
246 | |||
247 | segments->segments->number=segments->number; | ||
248 | |||
249 | #ifdef NBINS_SEGMENTS | ||
250 | for(i=0;i<segments->number;i++) | ||
251 | for(;bin<=(segments->segments->segments[i].node1%NBINS_SEGMENTS);bin++) | ||
252 | segments->segments->offset[bin]=i; | ||
253 | |||
254 | for(;bin<=NBINS_SEGMENTS;bin++) | ||
255 | segments->segments->offset[bin]=segments->number; | ||
256 | #endif | ||
257 | amb | 2 | } |
258 | |||
259 | |||
260 | /*++++++++++++++++++++++++++++++++++++++ | ||
261 | Sort the segments into id order. | ||
262 | |||
263 | int sort_by_id Returns the comparison of the node fields. | ||
264 | |||
265 | Segment *a The first Segment. | ||
266 | |||
267 | Segment *b The second Segment. | ||
268 | ++++++++++++++++++++++++++++++++++++++*/ | ||
269 | |||
270 | static int sort_by_id(Segment *a,Segment *b) | ||
271 | { | ||
272 | node_t a_id1=a->node1,a_id2=a->node2; | ||
273 | node_t b_id1=b->node1,b_id2=b->node2; | ||
274 | |||
275 | amb | 23 | #ifdef NBINS_SEGMENTS |
276 | int a_bin=a->node1%NBINS_SEGMENTS; | ||
277 | int b_bin=b->node1%NBINS_SEGMENTS; | ||
278 | |||
279 | if(a_bin!=b_bin) | ||
280 | return(a_bin-b_bin); | ||
281 | #endif | ||
282 | |||
283 | amb | 39 | if(a_id1<b_id1) |
284 | return(-1); | ||
285 | else if(a_id1>b_id1) | ||
286 | return(1); | ||
287 | else /* if(a_id1==b_id1) */ | ||
288 | { | ||
289 | if(a_id2<b_id2) | ||
290 | return(-1); | ||
291 | else if(a_id2>b_id2) | ||
292 | return(1); | ||
293 | else | ||
294 | return(0); | ||
295 | } | ||
296 | amb | 2 | } |
297 | |||
298 | |||
299 | /*++++++++++++++++++++++++++++++++++++++ | ||
300 | amb | 39 | Remove bad segments (zero length or duplicated). |
301 | |||
302 | SegmentsMem *segments The segments to modify. | ||
303 | ++++++++++++++++++++++++++++++++++++++*/ | ||
304 | |||
305 | void RemoveBadSegments(SegmentsMem *segments) | ||
306 | { | ||
307 | int i; | ||
308 | int duplicate=0,loop=0; | ||
309 | node_t node1=~0,node2=~0; | ||
310 | |||
311 | for(i=0;i<segments->number;i++) | ||
312 | { | ||
313 | Segment *segment=&segments->segments->segments[i]; | ||
314 | |||
315 | if(segment->node1==node1 && segment->node2==node2) | ||
316 | { | ||
317 | duplicate++; | ||
318 | segment->node1=~0; | ||
319 | } | ||
320 | else if(segment->node1==segment->node2) | ||
321 | { | ||
322 | loop++; | ||
323 | segment->node1=~0; | ||
324 | } | ||
325 | |||
326 | node1=segment->node1; | ||
327 | node2=segment->node2; | ||
328 | |||
329 | if(!((i+1)%10000)) | ||
330 | { | ||
331 | printf("\rChecking: Segments=%d Duplicate=%d Loop=%d",i+1,duplicate,loop); | ||
332 | fflush(stdout); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | printf("\rChecked: Segments=%d Duplicate=%d Loop=%d \n",segments->number,duplicate,loop); | ||
337 | fflush(stdout); | ||
338 | } | ||
339 | |||
340 | |||
341 | /*++++++++++++++++++++++++++++++++++++++ | ||
342 | amb | 8 | Assign the lengths and durations to all of the segments. |
343 | amb | 23 | |
344 | SegmentsMem* segments The set of segments to process. | ||
345 | |||
346 | Nodes *nodes The list of nodes to use. | ||
347 | |||
348 | Ways *ways The list of ways to use. | ||
349 | amb | 8 | ++++++++++++++++++++++++++++++++++++++*/ |
350 | amb | 2 | |
351 | amb | 23 | void FixupSegmentLengths(SegmentsMem* segments,Nodes *nodes,Ways *ways) |
352 | amb | 8 | { |
353 | int i; | ||
354 | amb | 2 | |
355 | amb | 23 | assert(segments->sorted); /* Must be sorted */ |
356 | amb | 8 | |
357 | amb | 23 | for(i=0;i<segments->number;i++) |
358 | amb | 8 | { |
359 | amb | 23 | Node *node1=FindNode(nodes,segments->segments->segments[i].node1); |
360 | Node *node2=FindNode(nodes,segments->segments->segments[i].node2); | ||
361 | amb | 8 | |
362 | amb | 59 | if(segments->segments->segments[i].distance!=INVALID_DISTANCE) |
363 | segments->segments->segments[i].distance=Distance(node1,node2); | ||
364 | amb | 8 | |
365 | amb | 54 | if(!((i+1)%10000)) |
366 | { | ||
367 | printf("\rMeasuring Segments: Segments=%d",i+1); | ||
368 | fflush(stdout); | ||
369 | } | ||
370 | amb | 8 | } |
371 | amb | 54 | |
372 | printf("\rMeasured Segments: Segments=%d \n",segments->number); | ||
373 | fflush(stdout); | ||
374 | amb | 8 | } |
375 | |||
376 | |||
377 | /*++++++++++++++++++++++++++++++++++++++ | ||
378 | Calculate the distance between two nodes. | ||
379 | |||
380 | distance_t Distance Returns the distance between the nodes. | ||
381 | |||
382 | amb | 2 | Node *node1 The starting node. |
383 | |||
384 | Node *node2 The end node. | ||
385 | ++++++++++++++++++++++++++++++++++++++*/ | ||
386 | |||
387 | amb | 8 | distance_t Distance(Node *node1,Node *node2) |
388 | amb | 2 | { |
389 | double radiant = M_PI / 180; | ||
390 | |||
391 | double dlon = radiant * (node1->longitude - node2->longitude); | ||
392 | double dlat = radiant * (node1->latitude - node2->latitude); | ||
393 | |||
394 | double a1,a2,a,sa,c,d; | ||
395 | |||
396 | if(dlon==0 && dlat==0) | ||
397 | return 0; | ||
398 | |||
399 | a1 = sin (dlat / 2); | ||
400 | a2 = sin (dlon / 2); | ||
401 | a = (a1 * a1) + cos (node1->latitude * radiant) * cos (node2->latitude * radiant) * a2 * a2; | ||
402 | sa = sqrt (a); | ||
403 | if (sa <= 1.0) | ||
404 | {c = 2 * asin (sa);} | ||
405 | else | ||
406 | {c = 2 * asin (1.0);} | ||
407 | amb | 5 | d = 6378.137 * c; |
408 | amb | 2 | |
409 | amb | 5 | return km_to_distance(d); |
410 | amb | 2 | } |
Properties
Name | Value |
---|---|
cvs:description | Segment data type. |