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 88 - (show annotations) (download) (as text)
Tue Jan 27 18:22:37 2009 UTC (16 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 11443 byte(s)
Intermediate version while transitioning data format for nodes and segments.

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

Properties

Name Value
cvs:description Segment data type.