Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /branches/destination-access/src/segments.c
Parent Directory
|
Revision Log
Revision 681 -
(hide annotations)
(download)
(as text)
Sun Apr 24 18:01:24 2011 UTC (13 years, 10 months ago) by amb
Original Path: trunk/src/segments.c
File MIME type: text/x-csrc
File size: 9455 byte(s)
Sun Apr 24 18:01:24 2011 UTC (13 years, 10 months ago) by amb
Original Path: trunk/src/segments.c
File MIME type: text/x-csrc
File size: 9455 byte(s)
Make the comments more consistent.
1 | amb | 2 | /*************************************** |
2 | Segment data type functions. | ||
3 | amb | 151 | |
4 | Part of the Routino routing software. | ||
5 | amb | 2 | ******************/ /****************** |
6 | amb | 669 | This file Copyright 2008-2011 Andrew M. Bishop |
7 | amb | 2 | |
8 | amb | 151 | 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 | amb | 2 | ***************************************/ |
21 | |||
22 | |||
23 | amb | 214 | #include <sys/types.h> |
24 | amb | 2 | #include <stdlib.h> |
25 | amb | 669 | #include <math.h> |
26 | amb | 2 | |
27 | amb | 109 | #include "types.h" |
28 | amb | 39 | #include "nodes.h" |
29 | amb | 26 | #include "segments.h" |
30 | amb | 109 | #include "ways.h" |
31 | amb | 672 | #include "fakes.h" |
32 | amb | 449 | |
33 | #include "files.h" | ||
34 | amb | 109 | #include "profiles.h" |
35 | amb | 2 | |
36 | |||
37 | amb | 23 | /*++++++++++++++++++++++++++++++++++++++ |
38 | amb | 2 | Load in a segment list from a file. |
39 | |||
40 | amb | 681 | Segments *LoadSegmentList Returns the segment list that has just been loaded. |
41 | amb | 23 | |
42 | amb | 2 | const char *filename The name of the file to load. |
43 | ++++++++++++++++++++++++++++++++++++++*/ | ||
44 | |||
45 | amb | 23 | Segments *LoadSegmentList(const char *filename) |
46 | amb | 2 | { |
47 | amb | 88 | Segments *segments; |
48 | |||
49 | segments=(Segments*)malloc(sizeof(Segments)); | ||
50 | |||
51 | amb | 459 | #if !SLIM |
52 | amb | 88 | |
53 | amb | 459 | segments->data=MapFile(filename); |
54 | amb | 88 | |
55 | amb | 459 | /* Copy the SegmentsFile structure from the loaded data */ |
56 | amb | 88 | |
57 | amb | 459 | segments->file=*((SegmentsFile*)segments->data); |
58 | amb | 88 | |
59 | amb | 459 | /* Set the pointers in the Segments structure. */ |
60 | amb | 88 | |
61 | amb | 459 | 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 | amb | 88 | return(segments); |
78 | amb | 2 | } |
79 | |||
80 | |||
81 | /*++++++++++++++++++++++++++++++++++++++ | ||
82 | Find the next segment with a particular starting node. | ||
83 | |||
84 | amb | 680 | Segment *NextSegment Returns a pointer to the next segment. |
85 | amb | 2 | |
86 | amb | 681 | Segments *segments The set of segments to use. |
87 | amb | 23 | |
88 | amb | 2 | Segment *segment The current segment. |
89 | amb | 228 | |
90 | amb | 680 | index_t node The wanted node. |
91 | amb | 2 | ++++++++++++++++++++++++++++++++++++++*/ |
92 | |||
93 | amb | 681 | Segment *NextSegment(Segments *segments,Segment *segment,index_t node) |
94 | amb | 2 | { |
95 | amb | 208 | if(segment->node1==node) |
96 | amb | 128 | { |
97 | amb | 459 | #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 | amb | 128 | segment++; |
110 | amb | 459 | if(IndexSegment(segments,segment)>=segments->file.number || segment->node1!=node) |
111 | amb | 128 | return(NULL); |
112 | else | ||
113 | return(segment); | ||
114 | amb | 459 | #endif |
115 | amb | 128 | } |
116 | amb | 104 | else |
117 | amb | 128 | { |
118 | amb | 680 | if(segment->next2==NO_SEGMENT) |
119 | amb | 128 | return(NULL); |
120 | else | ||
121 | amb | 459 | return(LookupSegment(segments,segment->next2,1)); |
122 | amb | 128 | } |
123 | amb | 89 | } |
124 | amb | 675 | |
125 | |||
126 | amb | 2 | /*++++++++++++++++++++++++++++++++++++++ |
127 | amb | 675 | 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 | amb | 681 | Nodes *nodes The set of nodes to use. |
132 | amb | 675 | |
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 | amb | 681 | index_t FindClosestSegmentHeading(Nodes *nodes,Segments *segments,Ways *ways,index_t node1,double heading,Profile *profile) |
145 | amb | 675 | { |
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 | amb | 99 | Calculate the distance between two locations. |
210 | |||
211 | amb | 114 | distance_t Distance Returns the distance between the locations. |
212 | amb | 99 | |
213 | amb | 219 | double lat1 The latitude of the first location. |
214 | amb | 99 | |
215 | amb | 219 | double lon1 The longitude of the first location. |
216 | amb | 99 | |
217 | amb | 219 | double lat2 The latitude of the second location. |
218 | amb | 99 | |
219 | amb | 219 | double lon2 The longitude of the second location. |
220 | amb | 99 | ++++++++++++++++++++++++++++++++++++++*/ |
221 | |||
222 | amb | 219 | distance_t Distance(double lat1,double lon1,double lat2,double lon2) |
223 | amb | 99 | { |
224 | amb | 219 | double dlon = lon1 - lon2; |
225 | double dlat = lat1 - lat2; | ||
226 | amb | 99 | |
227 | amb | 219 | double a1,a2,a,sa,c,d; |
228 | amb | 99 | |
229 | if(dlon==0 && dlat==0) | ||
230 | return 0; | ||
231 | |||
232 | amb | 219 | a1 = sin (dlat / 2); |
233 | a2 = sin (dlon / 2); | ||
234 | a = (a1 * a1) + cos (lat1) * cos (lat2) * a2 * a2; | ||
235 | sa = sqrt (a); | ||
236 | amb | 99 | if (sa <= 1.0) |
237 | amb | 219 | {c = 2 * asin (sa);} |
238 | amb | 99 | else |
239 | amb | 219 | {c = 2 * asin (1.0);} |
240 | amb | 99 | d = 6378.137 * c; |
241 | |||
242 | amb | 114 | return km_to_distance(d); |
243 | amb | 99 | } |
244 | |||
245 | |||
246 | /*++++++++++++++++++++++++++++++++++++++ | ||
247 | amb | 680 | Calculate the duration of travel on a segment. |
248 | amb | 63 | |
249 | amb | 680 | duration_t Duration Returns the duration of travel. |
250 | amb | 63 | |
251 | Segment *segment The segment to traverse. | ||
252 | |||
253 | Way *way The way that the segment belongs to. | ||
254 | |||
255 | amb | 82 | Profile *profile The profile of the transport being used. |
256 | amb | 63 | ++++++++++++++++++++++++++++++++++++++*/ |
257 | |||
258 | amb | 82 | duration_t Duration(Segment *segment,Way *way,Profile *profile) |
259 | amb | 63 | { |
260 | amb | 137 | speed_t speed1=way->speed; |
261 | speed_t speed2=profile->speed[HIGHWAY(way->type)]; | ||
262 | amb | 90 | distance_t distance=DISTANCE(segment->distance); |
263 | amb | 63 | |
264 | amb | 137 | 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 | amb | 63 | } |
281 | amb | 672 | |
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 | amb | 681 | Nodes *nodes The set of nodes to use. |
289 | amb | 672 | |
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 | amb | 675 | Calculate the bearing of a segment when heading to the given node. |
341 | amb | 672 | |
342 | double BearingAngle Returns a value in the range 0 to 359 indicating the bearing. | ||
343 | |||
344 | amb | 681 | Nodes *nodes The set of nodes to use. |
345 | amb | 672 | |
346 | Segment *segment The segment. | ||
347 | |||
348 | amb | 675 | index_t node The node to finish. |
349 | amb | 672 | |
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. |