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 99 - (hide annotations) (download) (as text)
Wed Feb 4 18:23:33 2009 UTC (16 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 15167 byte(s)
Sort the nodes geographically and take coordinates as command line arguments.

1 amb 2 /***************************************
2 amb 99 $Header: /home/amb/CVS/routino/src/segments.c,v 1.28 2009-02-04 18:23:33 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 98 SegmentX *FindFirstSegmentX 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 98 SegmentX *FindFirstSegmentX(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 98 SegmentX *FindNextSegmentX Returns a pointer to the next segment with the same id.
211 amb 89
212 amb 98 SegmentsX* segmentss The set of segments to process.
213 amb 89
214 amb 98 SegmentX *segmentx The current segment.
215 amb 89 ++++++++++++++++++++++++++++++++++++++*/
216    
217 amb 98 SegmentX *FindNextSegmentX(SegmentsX* segmentsx,SegmentX *segmentx)
218 amb 89 {
219 amb 98 SegmentX *next=segmentx+1;
220 amb 89
221 amb 97 if(IndexSegmentX(segmentsx,next)==segmentsx->number)
222 amb 89 return(NULL);
223    
224 amb 98 if(next->node1==segmentx->node1)
225 amb 89 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 amb 98 Append a segment to a segment list.
257 amb 2
258 amb 98 Segment *AppendSegmentX 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    
267 amb 98 Segment *AppendSegment(SegmentsX* segmentsx,node_t node1,node_t node2)
268 amb 2 {
269 amb 23 /* Check that the array has enough space. */
270 amb 8
271 amb 97 if(segmentsx->number==segmentsx->alloced)
272 amb 4 {
273 amb 97 segmentsx->alloced+=INCREMENT_SEGMENTS;
274 amb 4
275 amb 97 segmentsx->xdata=(SegmentX*)realloc((void*)segmentsx->xdata,segmentsx->alloced*sizeof(SegmentX));
276 amb 4 }
277    
278     /* Insert the segment */
279    
280 amb 97 segmentsx->xdata[segmentsx->number].node1=node1;
281     segmentsx->xdata[segmentsx->number].node2=node2;
282 amb 98
283 amb 97 segmentsx->xdata[segmentsx->number].segment.distance=0;
284 amb 2
285 amb 97 segmentsx->number++;
286 amb 2
287 amb 97 segmentsx->sorted=0;
288 amb 31
289 amb 98 return(&segmentsx->xdata[segmentsx->number-1].segment);
290 amb 2 }
291    
292    
293     /*++++++++++++++++++++++++++++++++++++++
294     Sort the segment list.
295 amb 23
296 amb 97 SegmentsX* segmentsx The set of segments to process.
297 amb 2 ++++++++++++++++++++++++++++++++++++++*/
298    
299 amb 97 void SortSegmentList(SegmentsX* segmentsx)
300 amb 2 {
301 amb 97 qsort(segmentsx->xdata,segmentsx->number,sizeof(SegmentX),(int (*)(const void*,const void*))sort_by_id);
302 amb 39
303 amb 97 while(segmentsx->xdata[segmentsx->number-1].node1==~0)
304     segmentsx->number--;
305 amb 8
306 amb 97 segmentsx->sorted=1;
307 amb 2 }
308    
309    
310     /*++++++++++++++++++++++++++++++++++++++
311     Sort the segments into id order.
312    
313     int sort_by_id Returns the comparison of the node fields.
314    
315 amb 97 SegmentX *a The first Segment.
316 amb 2
317 amb 97 SegmentX *b The second Segment.
318 amb 2 ++++++++++++++++++++++++++++++++++++++*/
319    
320 amb 97 static int sort_by_id(SegmentX *a,SegmentX *b)
321 amb 2 {
322     node_t a_id1=a->node1,a_id2=a->node2;
323     node_t b_id1=b->node1,b_id2=b->node2;
324    
325 amb 39 if(a_id1<b_id1)
326     return(-1);
327     else if(a_id1>b_id1)
328     return(1);
329     else /* if(a_id1==b_id1) */
330     {
331     if(a_id2<b_id2)
332     return(-1);
333 amb 88 else
334 amb 39 return(1);
335     }
336 amb 2 }
337    
338    
339     /*++++++++++++++++++++++++++++++++++++++
340 amb 39 Remove bad segments (zero length or duplicated).
341    
342 amb 97 SegmentsX *segmentsx The segments to modify.
343 amb 39 ++++++++++++++++++++++++++++++++++++++*/
344    
345 amb 97 void RemoveBadSegments(SegmentsX *segmentsx)
346 amb 39 {
347     int i;
348     int duplicate=0,loop=0;
349     node_t node1=~0,node2=~0;
350    
351 amb 97 for(i=0;i<segmentsx->number;i++)
352 amb 39 {
353 amb 97 if(segmentsx->xdata[i].node1==node1 && segmentsx->xdata[i].node2==node2)
354 amb 39 {
355     duplicate++;
356 amb 97 segmentsx->xdata[i].node1=~0;
357 amb 39 }
358 amb 97 else if(segmentsx->xdata[i].node1==segmentsx->xdata[i].node2)
359 amb 39 {
360     loop++;
361 amb 97 segmentsx->xdata[i].node1=~0;
362 amb 39 }
363    
364 amb 97 node1=segmentsx->xdata[i].node1;
365     node2=segmentsx->xdata[i].node2;
366 amb 39
367     if(!((i+1)%10000))
368     {
369     printf("\rChecking: Segments=%d Duplicate=%d Loop=%d",i+1,duplicate,loop);
370     fflush(stdout);
371     }
372     }
373    
374 amb 97 printf("\rChecked: Segments=%d Duplicate=%d Loop=%d \n",segmentsx->number,duplicate,loop);
375 amb 39 fflush(stdout);
376     }
377    
378    
379     /*++++++++++++++++++++++++++++++++++++++
380 amb 89 Measure the segments.
381 amb 23
382 amb 97 SegmentsX* segmentsx The set of segments to process.
383 amb 23
384 amb 97 NodesX *nodesx The list of nodes to use.
385 amb 8 ++++++++++++++++++++++++++++++++++++++*/
386 amb 2
387 amb 97 void MeasureSegments(SegmentsX* segmentsx,NodesX *nodesx)
388 amb 8 {
389     int i;
390 amb 2
391 amb 97 assert(segmentsx->sorted); /* Must be sorted */
392 amb 8
393 amb 97 for(i=0;i<segmentsx->number;i++)
394 amb 8 {
395 amb 98 NodeX *node1=FindNodeX(nodesx,segmentsx->xdata[i].node1);
396     NodeX *node2=FindNodeX(nodesx,segmentsx->xdata[i].node2);
397 amb 8
398 amb 82 /* Set the distance but preserve the ONEWAY_OPPOSITE flag */
399 amb 8
400 amb 99 segmentsx->xdata[i].segment.distance|=DistanceX(node1,node2);
401 amb 69
402 amb 54 if(!((i+1)%10000))
403     {
404 amb 89 printf("\rMeasuring Segments: Segments=%d",i+1);
405     fflush(stdout);
406     }
407     }
408    
409 amb 97 printf("\rMeasured Segments: Segments=%d \n",segmentsx->number);
410 amb 89 fflush(stdout);
411     }
412    
413    
414     /*++++++++++++++++++++++++++++++++++++++
415     Fix the segment indexes to the nodes.
416    
417 amb 97 SegmentsX* segmentsx The set of segments to process.
418 amb 89
419 amb 97 NodesX *nodesx The list of nodes to use.
420 amb 90
421 amb 97 SegmentsX* supersegmentsx The set of super-segments to append.
422 amb 89 ++++++++++++++++++++++++++++++++++++++*/
423    
424 amb 97 void FixupSegments(SegmentsX* segmentsx,NodesX *nodesx,SegmentsX* supersegmentsx)
425 amb 89 {
426 amb 90 int i,j,n;
427 amb 89
428 amb 97 assert(segmentsx->sorted); /* Must be sorted */
429     assert(supersegmentsx->sorted); /* Must be sorted */
430 amb 89
431 amb 97 for(i=0;i<segmentsx->number;i++)
432 amb 89 {
433 amb 98 NodeX *node1=FindNodeX(nodesx,segmentsx->xdata[i].node1);
434     NodeX *node2=FindNodeX(nodesx,segmentsx->xdata[i].node2);
435 amb 89
436 amb 97 segmentsx->xdata[i].segment.node1=IndexNodeX(nodesx,node1)|SUPER_FLAG;
437     segmentsx->xdata[i].segment.node2=IndexNodeX(nodesx,node2);
438 amb 89
439     if(!((i+1)%10000))
440     {
441 amb 88 printf("\rFixing Segments: Segments=%d",i+1);
442 amb 54 fflush(stdout);
443     }
444 amb 8 }
445 amb 54
446 amb 97 printf("\rFixed Segments: Segments=%d \n",segmentsx->number);
447 amb 54 fflush(stdout);
448 amb 90
449 amb 97 for(i=0;i<supersegmentsx->number;i++)
450 amb 90 {
451 amb 98 NodeX *node1=FindNodeX(nodesx,supersegmentsx->xdata[i].node1);
452     NodeX *node2=FindNodeX(nodesx,supersegmentsx->xdata[i].node2);
453 amb 90
454 amb 97 supersegmentsx->xdata[i].segment.node1=IndexNodeX(nodesx,node1);
455     supersegmentsx->xdata[i].segment.node2=IndexNodeX(nodesx,node2)|SUPER_FLAG;
456 amb 90
457     if(!((i+1)%10000))
458     {
459     printf("\rFixing Super-Segments: Super-Segments=%d",i+1);
460     fflush(stdout);
461     }
462     }
463    
464 amb 97 printf("\rFixed Super-Segments: Super-Segments=%d \n",supersegmentsx->number);
465 amb 90 fflush(stdout);
466    
467 amb 97 n=segmentsx->number;
468 amb 90
469     for(i=0,j=0;i<n;i++)
470     {
471 amb 97 while(j<supersegmentsx->number)
472 amb 90 {
473 amb 97 if(segmentsx->xdata[i].node1==supersegmentsx->xdata[j].node1 &&
474     segmentsx->xdata[i].node2==supersegmentsx->xdata[j].node2)
475 amb 90 {
476 amb 97 segmentsx->xdata[i].segment.node2|=SUPER_FLAG;
477 amb 90 j++;
478     break;
479     }
480 amb 97 else if(segmentsx->xdata[i].node1==supersegmentsx->xdata[j].node1 &&
481     segmentsx->xdata[i].node2>supersegmentsx->xdata[j].node2)
482 amb 90 {
483 amb 98 Segment *supersegment=AppendSegment(segmentsx,supersegmentsx->xdata[j].node1,supersegmentsx->xdata[j].node2);
484 amb 90
485 amb 98 *supersegment=supersegmentsx->xdata[j].segment;
486 amb 90 }
487 amb 97 else if(segmentsx->xdata[i].node1>supersegmentsx->xdata[j].node1)
488 amb 90 {
489 amb 98 Segment *supersegment=AppendSegment(segmentsx,supersegmentsx->xdata[j].node1,supersegmentsx->xdata[j].node2);
490 amb 90
491 amb 98 *supersegment=supersegmentsx->xdata[j].segment;
492 amb 90 }
493     else
494     break;
495    
496     j++;
497     }
498    
499     if(!((i+1)%10000))
500     {
501 amb 97 printf("\rMerging Segments: Segments=%d Super-Segment=%d Total=%d",i+1,j+1,segmentsx->number);
502 amb 90 fflush(stdout);
503     }
504     }
505    
506 amb 97 printf("\rMerged Segments: Segments=%d Super-Segment=%d Total=%d \n",n,supersegmentsx->number,segmentsx->number);
507 amb 90 fflush(stdout);
508 amb 8 }
509    
510    
511     /*++++++++++++++++++++++++++++++++++++++
512 amb 99 Calculate the distance between two locations.
513    
514     float Distance Returns the distance between the locations.
515    
516     float lat1 The latitude of the first location.
517    
518     float lon1 The longitude of the first location.
519    
520     float lat2 The latitude of the second location.
521    
522     float lon2 The longitude of the second location.
523     ++++++++++++++++++++++++++++++++++++++*/
524    
525     float Distance(float lat1,float lon1,float lat2,float lon2)
526     {
527     double radiant = M_PI / 180;
528    
529     double dlon = radiant * (lon1 - lon2);
530     double dlat = radiant * (lat1 - lat2);
531    
532     double a1,a2,a,sa,c,d;
533    
534     if(dlon==0 && dlat==0)
535     return 0;
536    
537     a1 = sin (dlat / 2);
538     a2 = sin (dlon / 2);
539     a = (a1 * a1) + cos (lat1 * radiant) * cos (lat2 * radiant) * a2 * a2;
540     sa = sqrt (a);
541     if (sa <= 1.0)
542     {c = 2 * asin (sa);}
543     else
544     {c = 2 * asin (1.0);}
545     d = 6378.137 * c;
546    
547     return d;
548     }
549    
550    
551     /*++++++++++++++++++++++++++++++++++++++
552 amb 8 Calculate the distance between two nodes.
553    
554 amb 99 distance_t DistanceX Returns the distance between the extended nodes.
555 amb 8
556 amb 98 NodeX *nodex1 The starting node.
557 amb 2
558 amb 98 NodeX *nodex2 The end node.
559 amb 2 ++++++++++++++++++++++++++++++++++++++*/
560    
561 amb 99 distance_t DistanceX(NodeX *nodex1,NodeX *nodex2)
562 amb 2 {
563     double radiant = M_PI / 180;
564    
565 amb 99 double dlon = radiant * (nodex1->longitude - nodex2->longitude);
566     double dlat = radiant * (nodex1->latitude - nodex2->latitude);
567 amb 2
568     double a1,a2,a,sa,c,d;
569    
570     if(dlon==0 && dlat==0)
571     return 0;
572    
573     a1 = sin (dlat / 2);
574     a2 = sin (dlon / 2);
575 amb 99 a = (a1 * a1) + cos (nodex1->latitude * radiant) * cos (nodex2->latitude * radiant) * a2 * a2;
576 amb 2 sa = sqrt (a);
577     if (sa <= 1.0)
578     {c = 2 * asin (sa);}
579     else
580     {c = 2 * asin (1.0);}
581 amb 5 d = 6378.137 * c;
582 amb 2
583 amb 5 return km_to_distance(d);
584 amb 2 }
585 amb 63
586    
587     /*++++++++++++++++++++++++++++++++++++++
588     Calculate the duration of segment.
589    
590     duration_t Duration Returns the duration of travel between the nodes.
591    
592     Segment *segment The segment to traverse.
593    
594     Way *way The way that the segment belongs to.
595    
596 amb 82 Profile *profile The profile of the transport being used.
597 amb 63 ++++++++++++++++++++++++++++++++++++++*/
598    
599 amb 82 duration_t Duration(Segment *segment,Way *way,Profile *profile)
600 amb 63 {
601 amb 82 speed_t speed=profile->speed[HIGHWAY(way->type)];
602 amb 90 distance_t distance=DISTANCE(segment->distance);
603 amb 63
604 amb 86 return distance_speed_to_duration(distance,speed);
605 amb 63 }

Properties

Name Value
cvs:description Segment data type.