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 1164 - (show annotations) (download) (as text)
Tue Nov 20 15:24:30 2012 UTC (12 years, 3 months ago) by amb
File MIME type: text/x-csrc
File size: 8513 byte(s)
Replace the 32-bit combined distance and flags in the segment with 16 bits for
each.

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

Properties

Name Value
cvs:description Segment data type.