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 885 - (show annotations) (download) (as text)
Sat Oct 29 15:20:30 2011 UTC (13 years, 5 months ago) by amb
File MIME type: text/x-csrc
File size: 8524 byte(s)
Rationalise and reduce the usage of LookUpNode() function.

1 /***************************************
2 Segment data type functions.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2008-2011 Andrew M. Bishop
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU Affero General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ***************************************/
21
22
23 #include <sys/types.h>
24 #include <stdlib.h>
25 #include <math.h>
26
27 #include "types.h"
28 #include "nodes.h"
29 #include "segments.h"
30 #include "ways.h"
31 #include "fakes.h"
32
33 #include "files.h"
34 #include "profiles.h"
35
36
37 /*++++++++++++++++++++++++++++++++++++++
38 Load in a segment list from a file.
39
40 Segments *LoadSegmentList Returns the segment list that has just been loaded.
41
42 const char *filename The name of the file to load.
43 ++++++++++++++++++++++++++++++++++++++*/
44
45 Segments *LoadSegmentList(const char *filename)
46 {
47 Segments *segments;
48 #if SLIM
49 int i;
50 #endif
51
52 segments=(Segments*)malloc(sizeof(Segments));
53
54 #if !SLIM
55
56 segments->data=MapFile(filename);
57
58 /* Copy the SegmentsFile structure from the loaded data */
59
60 segments->file=*((SegmentsFile*)segments->data);
61
62 /* Set the pointers in the Segments structure. */
63
64 segments->segments=(Segment*)(segments->data+sizeof(SegmentsFile));
65
66 #else
67
68 segments->fd=ReOpenFile(filename);
69
70 /* Copy the SegmentsFile header structure from the loaded data */
71
72 ReadFile(segments->fd,&segments->file,sizeof(SegmentsFile));
73
74 for(i=0;i<sizeof(segments->cached)/sizeof(segments->cached[0]);i++)
75 segments->incache[i]=NO_SEGMENT;
76
77 #endif
78
79 return(segments);
80 }
81
82
83 /*++++++++++++++++++++++++++++++++++++++
84 Find the closest segment from a specified node heading in a particular direction and optionally profile.
85
86 index_t FindClosestSegmentHeading Returns the closest heading segment index.
87
88 Nodes *nodes The set of nodes to use.
89
90 Segments *segments The set of segments to use.
91
92 Ways *ways The set of ways to use.
93
94 index_t node1 The node to start from.
95
96 double heading The desired heading from the node.
97
98 Profile *profile The profile of the mode of transport (or NULL).
99 ++++++++++++++++++++++++++++++++++++++*/
100
101 index_t FindClosestSegmentHeading(Nodes *nodes,Segments *segments,Ways *ways,index_t node1,double heading,Profile *profile)
102 {
103 Segment *segment;
104 index_t best_seg=NO_SEGMENT;
105 double best_difference=360;
106
107 if(IsFakeNode(node1))
108 segment=FirstFakeSegment(node1);
109 else
110 {
111 Node *node=LookupNode(nodes,node1,3);
112
113 segment=FirstSegment(segments,node,1);
114 }
115
116 while(segment)
117 {
118 Way *way;
119 index_t node2,seg2;
120 double bearing,difference;
121
122 node2=OtherNode(segment,node1); /* need this here because we use node2 at the end of the loop */
123
124 if(!IsNormalSegment(segment))
125 goto endloop;
126
127 if(profile->oneway && IsOnewayFrom(segment,node1))
128 goto endloop;
129
130 if(IsFakeNode(node1) || IsFakeNode(node2))
131 seg2=IndexFakeSegment(segment);
132 else
133 seg2=IndexSegment(segments,segment);
134
135 way=LookupWay(ways,segment->way,1);
136
137 if(!(way->allow&profile->allow))
138 goto endloop;
139
140 bearing=BearingAngle(nodes,segment,node1);
141
142 difference=(heading-bearing);
143
144 if(difference<-180) difference+=360;
145 if(difference> 180) difference-=360;
146
147 if(difference<0) difference=-difference;
148
149 if(difference<best_difference)
150 {
151 best_difference=difference;
152 best_seg=seg2;
153 }
154
155 endloop:
156
157 if(IsFakeNode(node1))
158 segment=NextFakeSegment(segment,node1);
159 else if(IsFakeNode(node2))
160 segment=NULL; /* cannot call NextSegment() with a fake segment */
161 else
162 segment=NextSegment(segments,segment,node1);
163 }
164
165 return(best_seg);
166 }
167
168
169 /*++++++++++++++++++++++++++++++++++++++
170 Calculate the distance between two locations.
171
172 distance_t Distance Returns the distance between the locations.
173
174 double lat1 The latitude of the first location.
175
176 double lon1 The longitude of the first location.
177
178 double lat2 The latitude of the second location.
179
180 double lon2 The longitude of the second location.
181 ++++++++++++++++++++++++++++++++++++++*/
182
183 distance_t Distance(double lat1,double lon1,double lat2,double lon2)
184 {
185 double dlon = lon1 - lon2;
186 double dlat = lat1 - lat2;
187
188 double a1,a2,a,sa,c,d;
189
190 if(dlon==0 && dlat==0)
191 return 0;
192
193 a1 = sin (dlat / 2);
194 a2 = sin (dlon / 2);
195 a = (a1 * a1) + cos (lat1) * cos (lat2) * a2 * a2;
196 sa = sqrt (a);
197 if (sa <= 1.0)
198 {c = 2 * asin (sa);}
199 else
200 {c = 2 * asin (1.0);}
201 d = 6378.137 * c;
202
203 return km_to_distance(d);
204 }
205
206
207 /*++++++++++++++++++++++++++++++++++++++
208 Calculate the duration of travel on a segment.
209
210 duration_t Duration Returns the duration of travel.
211
212 Segment *segment The segment to traverse.
213
214 Way *way The way that the segment belongs to.
215
216 Profile *profile The profile of the transport being used.
217 ++++++++++++++++++++++++++++++++++++++*/
218
219 duration_t Duration(Segment *segment,Way *way,Profile *profile)
220 {
221 speed_t speed1=way->speed;
222 speed_t speed2=profile->speed[HIGHWAY(way->type)];
223 distance_t distance=DISTANCE(segment->distance);
224
225 if(speed1==0)
226 {
227 if(speed2==0)
228 return(hours_to_duration(10));
229 else
230 return distance_speed_to_duration(distance,speed2);
231 }
232 else /* if(speed1!=0) */
233 {
234 if(speed2==0)
235 return distance_speed_to_duration(distance,speed1);
236 else if(speed1<=speed2)
237 return distance_speed_to_duration(distance,speed1);
238 else
239 return distance_speed_to_duration(distance,speed2);
240 }
241 }
242
243
244 /*++++++++++++++++++++++++++++++++++++++
245 Calculate the angle to turn at a junction from segment1 to segment2 at node.
246
247 double TurnAngle Returns a value in the range -180 to +180 indicating the angle to turn.
248
249 Nodes *nodes The set of nodes to use.
250
251 Segment *segment1 The current segment.
252
253 Segment *segment2 The next segment.
254
255 index_t node The node at which they join.
256
257 Straight ahead is zero, turning to the right is positive (e.g. +90 degrees) and turning to the left is negative (e.g. -90 degrees).
258 Angles are calculated using flat Cartesian lat/long grid approximation (after scaling longitude due to latitude).
259 ++++++++++++++++++++++++++++++++++++++*/
260
261 double TurnAngle(Nodes *nodes,Segment *segment1,Segment *segment2,index_t node)
262 {
263 double lat1,latm,lat2;
264 double lon1,lonm,lon2;
265 double angle1,angle2,angle;
266 index_t node1,node2;
267
268 node1=OtherNode(segment1,node);
269 node2=OtherNode(segment2,node);
270
271 if(IsFakeNode(node1))
272 GetFakeLatLong(node1,&lat1,&lon1);
273 else
274 GetLatLong(nodes,node1,&lat1,&lon1);
275
276 if(IsFakeNode(node))
277 GetFakeLatLong(node,&latm,&lonm);
278 else
279 GetLatLong(nodes,node,&latm,&lonm);
280
281 if(IsFakeNode(node2))
282 GetFakeLatLong(node2,&lat2,&lon2);
283 else
284 GetLatLong(nodes,node2,&lat2,&lon2);
285
286 angle1=atan2((lonm-lon1)*cos(latm),(latm-lat1));
287 angle2=atan2((lon2-lonm)*cos(latm),(lat2-latm));
288
289 angle=angle2-angle1;
290
291 angle=radians_to_degrees(angle);
292
293 if(angle<-180) angle+=360;
294 if(angle> 180) angle-=360;
295
296 return(angle);
297 }
298
299
300 /*++++++++++++++++++++++++++++++++++++++
301 Calculate the bearing of a segment when heading to the given node.
302
303 double BearingAngle Returns a value in the range 0 to 359 indicating the bearing.
304
305 Nodes *nodes The set of nodes to use.
306
307 Segment *segment The segment.
308
309 index_t node The node to finish.
310
311 Angles are calculated using flat Cartesian lat/long grid approximation (after scaling longitude due to latitude).
312 ++++++++++++++++++++++++++++++++++++++*/
313
314 double BearingAngle(Nodes *nodes,Segment *segment,index_t node)
315 {
316 double lat1,lat2;
317 double lon1,lon2;
318 double angle;
319 index_t node1,node2;
320
321 node1=node;
322 node2=OtherNode(segment,node);
323
324 if(IsFakeNode(node1))
325 GetFakeLatLong(node1,&lat1,&lon1);
326 else
327 GetLatLong(nodes,node1,&lat1,&lon1);
328
329 if(IsFakeNode(node2))
330 GetFakeLatLong(node2,&lat2,&lon2);
331 else
332 GetLatLong(nodes,node2,&lat2,&lon2);
333
334 angle=atan2((lat2-lat1),(lon2-lon1)*cos(lat1));
335
336 angle=radians_to_degrees(angle);
337
338 angle=270-angle;
339
340 if(angle< 0) angle+=360;
341 if(angle>360) angle-=360;
342
343 return(angle);
344 }

Properties

Name Value
cvs:description Segment data type.