Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /branches/destination-access/src/segments.c
Parent Directory
|
Revision Log
Revision 675 -
(show annotations)
(download)
(as text)
Fri Apr 22 13:59:27 2011 UTC (13 years, 10 months ago) by amb
Original Path: trunk/src/segments.c
File MIME type: text/x-csrc
File size: 9469 byte(s)
Fri Apr 22 13:59:27 2011 UTC (13 years, 10 months ago) by amb
Original Path: trunk/src/segments.c
File MIME type: text/x-csrc
File size: 9469 byte(s)
Add in the option to specify an initial heading.
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 | |
49 | segments=(Segments*)malloc(sizeof(Segments)); |
50 | |
51 | #if !SLIM |
52 | |
53 | segments->data=MapFile(filename); |
54 | |
55 | /* Copy the SegmentsFile structure from the loaded data */ |
56 | |
57 | segments->file=*((SegmentsFile*)segments->data); |
58 | |
59 | /* Set the pointers in the Segments structure. */ |
60 | |
61 | segments->segments=(Segment*)(segments->data+sizeof(SegmentsFile)); |
62 | |
63 | #else |
64 | |
65 | segments->fd=ReOpenFile(filename); |
66 | |
67 | /* Copy the SegmentsFile header structure from the loaded data */ |
68 | |
69 | ReadFile(segments->fd,&segments->file,sizeof(SegmentsFile)); |
70 | |
71 | segments->incache[0]=NO_SEGMENT; |
72 | segments->incache[1]=NO_SEGMENT; |
73 | segments->incache[2]=NO_SEGMENT; |
74 | |
75 | #endif |
76 | |
77 | return(segments); |
78 | } |
79 | |
80 | |
81 | /*++++++++++++++++++++++++++++++++++++++ |
82 | Find the next segment with a particular starting node. |
83 | |
84 | Segment *NextSegment Returns a pointer to the next segment with the same id. |
85 | |
86 | Segments* segments The set of segments to process. |
87 | |
88 | Segment *segment The current segment. |
89 | |
90 | index_t node The current node. |
91 | ++++++++++++++++++++++++++++++++++++++*/ |
92 | |
93 | Segment *NextSegment(Segments* segments,Segment *segment,index_t node) |
94 | { |
95 | if(segment->node1==node) |
96 | { |
97 | #if SLIM |
98 | index_t index=IndexSegment(segments,segment); |
99 | index++; |
100 | |
101 | if(index>=segments->file.number) |
102 | return(NULL); |
103 | segment=LookupSegment(segments,index,1); |
104 | if(segment->node1!=node) |
105 | return(NULL); |
106 | else |
107 | return(segment); |
108 | #else |
109 | segment++; |
110 | if(IndexSegment(segments,segment)>=segments->file.number || segment->node1!=node) |
111 | return(NULL); |
112 | else |
113 | return(segment); |
114 | #endif |
115 | } |
116 | else |
117 | { |
118 | if(segment->next2==NO_NODE) |
119 | return(NULL); |
120 | else |
121 | return(LookupSegment(segments,segment->next2,1)); |
122 | } |
123 | } |
124 | |
125 | |
126 | /*++++++++++++++++++++++++++++++++++++++ |
127 | Find the closest segment from a specified node heading in a particular direction and optionally profile. |
128 | |
129 | index_t FindClosestSegmentHeading Returns the closest heading segment index. |
130 | |
131 | Nodes* nodes The set of nodes to search. |
132 | |
133 | Segments *segments The set of segments to use. |
134 | |
135 | Ways *ways The set of ways to use. |
136 | |
137 | index_t node1 The node to start from. |
138 | |
139 | double heading The desired heading from the node. |
140 | |
141 | Profile *profile The profile of the mode of transport (or NULL). |
142 | ++++++++++++++++++++++++++++++++++++++*/ |
143 | |
144 | index_t FindClosestSegmentHeading(Nodes* nodes,Segments *segments,Ways *ways,index_t node1,double heading,Profile *profile) |
145 | { |
146 | Segment *segment; |
147 | index_t best_seg=NO_SEGMENT; |
148 | double best_difference=360; |
149 | |
150 | if(IsFakeNode(node1)) |
151 | segment=FirstFakeSegment(node1); |
152 | else |
153 | segment=FirstSegment(segments,nodes,node1); |
154 | |
155 | while(segment) |
156 | { |
157 | Way *way; |
158 | index_t node2,seg2; |
159 | double bearing,difference; |
160 | |
161 | node2=OtherNode(segment,node1); /* need this here because we use node2 at the end of the loop */ |
162 | |
163 | if(!IsNormalSegment(segment)) |
164 | goto endloop; |
165 | |
166 | if(profile->oneway && IsOnewayFrom(segment,node1)) |
167 | goto endloop; |
168 | |
169 | if(IsFakeNode(node1) || IsFakeNode(node2)) |
170 | seg2=IndexFakeSegment(segment); |
171 | else |
172 | seg2=IndexSegment(segments,segment); |
173 | |
174 | way=LookupWay(ways,segment->way,1); |
175 | |
176 | if(!(way->allow&profile->allow)) |
177 | goto endloop; |
178 | |
179 | bearing=BearingAngle(nodes,segment,node1); |
180 | |
181 | difference=(heading-bearing); |
182 | |
183 | if(difference<-180) difference+=360; |
184 | if(difference> 180) difference-=360; |
185 | |
186 | if(difference<0) difference=-difference; |
187 | |
188 | if(difference<best_difference) |
189 | { |
190 | best_difference=difference; |
191 | best_seg=seg2; |
192 | } |
193 | |
194 | endloop: |
195 | |
196 | if(IsFakeNode(node1)) |
197 | segment=NextFakeSegment(segment,node1); |
198 | else if(IsFakeNode(node2)) |
199 | segment=NULL; /* cannot call NextSegment() with a fake segment */ |
200 | else |
201 | segment=NextSegment(segments,segment,node1); |
202 | } |
203 | |
204 | return(best_seg); |
205 | } |
206 | |
207 | |
208 | /*++++++++++++++++++++++++++++++++++++++ |
209 | Calculate the distance between two locations. |
210 | |
211 | distance_t Distance Returns the distance between the locations. |
212 | |
213 | double lat1 The latitude of the first location. |
214 | |
215 | double lon1 The longitude of the first location. |
216 | |
217 | double lat2 The latitude of the second location. |
218 | |
219 | double lon2 The longitude of the second location. |
220 | ++++++++++++++++++++++++++++++++++++++*/ |
221 | |
222 | distance_t Distance(double lat1,double lon1,double lat2,double lon2) |
223 | { |
224 | double dlon = lon1 - lon2; |
225 | double dlat = lat1 - lat2; |
226 | |
227 | double a1,a2,a,sa,c,d; |
228 | |
229 | if(dlon==0 && dlat==0) |
230 | return 0; |
231 | |
232 | a1 = sin (dlat / 2); |
233 | a2 = sin (dlon / 2); |
234 | a = (a1 * a1) + cos (lat1) * cos (lat2) * a2 * a2; |
235 | sa = sqrt (a); |
236 | if (sa <= 1.0) |
237 | {c = 2 * asin (sa);} |
238 | else |
239 | {c = 2 * asin (1.0);} |
240 | d = 6378.137 * c; |
241 | |
242 | return km_to_distance(d); |
243 | } |
244 | |
245 | |
246 | /*++++++++++++++++++++++++++++++++++++++ |
247 | Calculate the duration of segment. |
248 | |
249 | duration_t Duration Returns the duration of travel between the nodes. |
250 | |
251 | Segment *segment The segment to traverse. |
252 | |
253 | Way *way The way that the segment belongs to. |
254 | |
255 | Profile *profile The profile of the transport being used. |
256 | ++++++++++++++++++++++++++++++++++++++*/ |
257 | |
258 | duration_t Duration(Segment *segment,Way *way,Profile *profile) |
259 | { |
260 | speed_t speed1=way->speed; |
261 | speed_t speed2=profile->speed[HIGHWAY(way->type)]; |
262 | distance_t distance=DISTANCE(segment->distance); |
263 | |
264 | if(speed1==0) |
265 | { |
266 | if(speed2==0) |
267 | return(hours_to_duration(10)); |
268 | else |
269 | return distance_speed_to_duration(distance,speed2); |
270 | } |
271 | else /* if(speed1!=0) */ |
272 | { |
273 | if(speed2==0) |
274 | return distance_speed_to_duration(distance,speed1); |
275 | else if(speed1<=speed2) |
276 | return distance_speed_to_duration(distance,speed1); |
277 | else |
278 | return distance_speed_to_duration(distance,speed2); |
279 | } |
280 | } |
281 | |
282 | |
283 | /*++++++++++++++++++++++++++++++++++++++ |
284 | Calculate the angle to turn at a junction from segment1 to segment2 at node. |
285 | |
286 | double TurnAngle Returns a value in the range -180 to +180 indicating the angle to turn. |
287 | |
288 | Nodes *nodes The set of nodes. |
289 | |
290 | Segment *segment1 The current segment. |
291 | |
292 | Segment *segment2 The next segment. |
293 | |
294 | index_t node The node at which they join. |
295 | |
296 | 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). |
297 | Angles are calculated using flat Cartesian lat/long grid approximation (after scaling longitude due to latitude). |
298 | ++++++++++++++++++++++++++++++++++++++*/ |
299 | |
300 | double TurnAngle(Nodes *nodes,Segment *segment1,Segment *segment2,index_t node) |
301 | { |
302 | double lat1,latm,lat2; |
303 | double lon1,lonm,lon2; |
304 | double angle1,angle2,angle; |
305 | index_t node1,node2; |
306 | |
307 | node1=OtherNode(segment1,node); |
308 | node2=OtherNode(segment2,node); |
309 | |
310 | if(IsFakeNode(node1)) |
311 | GetFakeLatLong(node1,&lat1,&lon1); |
312 | else |
313 | GetLatLong(nodes,node1,&lat1,&lon1); |
314 | |
315 | if(IsFakeNode(node)) |
316 | GetFakeLatLong(node,&latm,&lonm); |
317 | else |
318 | GetLatLong(nodes,node,&latm,&lonm); |
319 | |
320 | if(IsFakeNode(node2)) |
321 | GetFakeLatLong(node2,&lat2,&lon2); |
322 | else |
323 | GetLatLong(nodes,node2,&lat2,&lon2); |
324 | |
325 | angle1=atan2((lonm-lon1)*cos(latm),(latm-lat1)); |
326 | angle2=atan2((lon2-lonm)*cos(latm),(lat2-latm)); |
327 | |
328 | angle=angle2-angle1; |
329 | |
330 | angle=radians_to_degrees(angle); |
331 | |
332 | if(angle<-180) angle+=360; |
333 | if(angle> 180) angle-=360; |
334 | |
335 | return(angle); |
336 | } |
337 | |
338 | |
339 | /*++++++++++++++++++++++++++++++++++++++ |
340 | Calculate the bearing of a segment when heading to the given node. |
341 | |
342 | double BearingAngle Returns a value in the range 0 to 359 indicating the bearing. |
343 | |
344 | Nodes *nodes The set of nodes. |
345 | |
346 | Segment *segment The segment. |
347 | |
348 | index_t node The node to finish. |
349 | |
350 | Angles are calculated using flat Cartesian lat/long grid approximation (after scaling longitude due to latitude). |
351 | ++++++++++++++++++++++++++++++++++++++*/ |
352 | |
353 | double BearingAngle(Nodes *nodes,Segment *segment,index_t node) |
354 | { |
355 | double lat1,lat2; |
356 | double lon1,lon2; |
357 | double angle; |
358 | index_t node1,node2; |
359 | |
360 | node1=node; |
361 | node2=OtherNode(segment,node); |
362 | |
363 | if(IsFakeNode(node1)) |
364 | GetFakeLatLong(node1,&lat1,&lon1); |
365 | else |
366 | GetLatLong(nodes,node1,&lat1,&lon1); |
367 | |
368 | if(IsFakeNode(node2)) |
369 | GetFakeLatLong(node2,&lat2,&lon2); |
370 | else |
371 | GetLatLong(nodes,node2,&lat2,&lon2); |
372 | |
373 | angle=atan2((lat2-lat1),(lon2-lon1)*cos(lat1)); |
374 | |
375 | angle=radians_to_degrees(angle); |
376 | |
377 | angle=270-angle; |
378 | |
379 | if(angle< 0) angle+=360; |
380 | if(angle>360) angle-=360; |
381 | |
382 | return(angle); |
383 | } |
Properties
Name | Value |
---|---|
cvs:description | Segment data type. |