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/output.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 316 - (hide annotations) (download) (as text)
Wed Jan 13 18:49:41 2010 UTC (15 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 21041 byte(s)
Change the test output formats to add turn, node type and bearing information.

1 amb 160 /***************************************
2 amb 316 $Header: /home/amb/CVS/routino/src/output.c,v 1.18 2010-01-13 18:49:41 amb Exp $
3 amb 160
4     Routing output generator.
5    
6     Part of the Routino routing software.
7     ******************/ /******************
8 amb 316 This file Copyright 2008,2009,2010 Andrew M. Bishop
9 amb 160
10     This program is free software: you can redistribute it and/or modify
11     it under the terms of the GNU Affero General Public License as published by
12     the Free Software Foundation, either version 3 of the License, or
13     (at your option) any later version.
14    
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18     GNU Affero General Public License for more details.
19    
20     You should have received a copy of the GNU Affero General Public License
21     along with this program. If not, see <http://www.gnu.org/licenses/>.
22     ***************************************/
23    
24    
25 amb 165 #include <stdlib.h>
26 amb 160 #include <string.h>
27 amb 164 #include <ctype.h>
28 amb 160 #include <stdio.h>
29 amb 316 #include <math.h>
30 amb 164 #include <sys/types.h>
31     #include <sys/stat.h>
32     #include <unistd.h>
33 amb 160
34     #include "types.h"
35     #include "functions.h"
36     #include "nodes.h"
37     #include "segments.h"
38     #include "ways.h"
39     #include "results.h"
40    
41    
42     /*+ The option to calculate the quickest route insted of the shortest. +*/
43     extern int option_quickest;
44    
45 amb 164 /*+ The files to write to. +*/
46     static FILE *gpxtrackfile=NULL,*gpxroutefile=NULL,*textfile=NULL,*textallfile=NULL;
47 amb 160
48 amb 171 /*+ Heuristics for determining if a junction is important. +*/
49 amb 300 static char junction_other_way[Way_Count][Way_Count]=
50 amb 306 { /* M, T, P, S, T, U, R, S, T, C, P, S = Way type of route not taken */
51 amb 316 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Motorway */
52     { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Trunk */
53     { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Primary */
54 amb 306 { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Secondary */
55 amb 316 { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, /* Tertiary */
56     { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 }, /* Unclassified */
57     { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }, /* Residential */
58     { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, /* Service */
59     { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 }, /* Track */
60     { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 }, /* Cycleway */
61 amb 306 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Path */
62     { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Steps */
63 amb 171 };
64 amb 165
65 amb 316 static int junction_angle(Nodes *nodes,Segment *segment1,Segment *segment2,index_t node);
66     static int bearing_angle(Nodes *nodes,Segment *segment,index_t node);
67 amb 171
68 amb 316
69 amb 160 /*++++++++++++++++++++++++++++++++++++++
70 amb 164 Open the files and print the head.
71 amb 160
72 amb 164 const char *copyright The name of a file that might exist and contain copyright information.
73     ++++++++++++++++++++++++++++++++++++++*/
74 amb 160
75 amb 164 void PrintRouteHead(const char *copyright)
76     {
77     char *source=NULL,*license=NULL;
78 amb 160
79 amb 164 if(copyright)
80     {
81     struct stat buf;
82 amb 160
83 amb 164 if(!stat(copyright,&buf))
84     {
85     FILE *file=fopen(copyright,"r");
86     char *string=(char*)malloc(buf.st_size+1);
87     char *p;
88 amb 160
89 amb 164 fread(string,buf.st_size,1,file);
90     string[buf.st_size]=0;
91 amb 160
92 amb 164 p=string;
93     while(*p)
94     {
95     if(!strncmp(p,"Source:",7))
96     {
97     p+=7;
98     while(*p==' ' || *p=='t')
99     p++;
100     source=p;
101     while(*p && *p!='\r' && *p!='\n')
102     p++;
103     while(*p=='\r' || *p=='\n')
104     *p++=0;
105     }
106     else if(!strncmp(p,"License:",8) || !strncmp(p,"Licence:",8))
107     {
108     p+=8;
109     while(*p==' ' || *p=='t')
110     p++;
111     license=p;
112     while(*p && *p!='\r' && *p!='\n')
113     p++;
114     while(*p=='\r' || *p=='\n')
115     *p++=0;
116     }
117     else
118     {
119     while(*p && *p!='\r' && *p!='\n')
120     p++;
121     while(*p=='\r' || *p=='\n')
122     *p++=0;
123     }
124     }
125 amb 160
126 amb 164 fclose(file);
127     }
128     }
129 amb 160
130 amb 164 /* Open the files */
131 amb 160
132     if(option_quickest==0)
133     {
134     /* Print the result for the shortest route */
135    
136     gpxtrackfile=fopen("shortest-track.gpx","w");
137     gpxroutefile=fopen("shortest-route.gpx","w");
138     textfile =fopen("shortest.txt","w");
139     textallfile =fopen("shortest-all.txt","w");
140 amb 177
141     if(!gpxtrackfile)
142     fprintf(stderr,"Warning: Cannot open file 'shortest-track.gpx' to write.\n");
143     if(!gpxroutefile)
144     fprintf(stderr,"Warning: Cannot open file 'shortest-route.gpx' to write.\n");
145     if(!textfile)
146     fprintf(stderr,"Warning: Cannot open file 'shortest.txt' to write.\n");
147     if(!textallfile)
148     fprintf(stderr,"Warning: Cannot open file 'shortest-all.txt' to write.\n");
149 amb 160 }
150     else
151     {
152     /* Print the result for the quickest route */
153    
154     gpxtrackfile=fopen("quickest-track.gpx","w");
155     gpxroutefile=fopen("quickest-route.gpx","w");
156     textfile =fopen("quickest.txt","w");
157     textallfile =fopen("quickest-all.txt","w");
158 amb 177
159     if(!gpxtrackfile)
160     fprintf(stderr,"Warning: Cannot open file 'quickest-track.gpx' to write.\n");
161     if(!gpxroutefile)
162     fprintf(stderr,"Warning: Cannot open file 'quickest-route.gpx' to write.\n");
163     if(!textfile)
164     fprintf(stderr,"Warning: Cannot open file 'quickest.txt' to write.\n");
165     if(!textallfile)
166     fprintf(stderr,"Warning: Cannot open file 'quickest-all.txt' to write.\n");
167 amb 160 }
168    
169 amb 164 /* Print the head of the files */
170 amb 160
171 amb 177 if(gpxtrackfile)
172     {
173     fprintf(gpxtrackfile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
174     fprintf(gpxtrackfile,"<gpx version=\"1.1\" creator=\"Routino\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.topografix.com/GPX/1/1\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">\n");
175 amb 160
176 amb 177 fprintf(gpxtrackfile,"<metadata>\n");
177     fprintf(gpxtrackfile,"<desc><![CDATA[%s route between 'start' and 'finish' waypoints]]></desc>\n",option_quickest?"Quickest":"Shortest");
178     if(source)
179     fprintf(gpxtrackfile,"<copyright author=\"%s\">\n",source);
180     if(license)
181     fprintf(gpxtrackfile,"<license>%s</license>\n",license);
182     if(source)
183     fprintf(gpxtrackfile,"</copyright>\n");
184     fprintf(gpxtrackfile,"</metadata>\n");
185 amb 160
186 amb 177 fprintf(gpxtrackfile,"<trk>\n");
187     }
188 amb 160
189 amb 177 if(gpxroutefile)
190     {
191     fprintf(gpxroutefile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
192     fprintf(gpxroutefile,"<gpx version=\"1.1\" creator=\"Routino\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.topografix.com/GPX/1/1\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">\n");
193 amb 160
194 amb 177 fprintf(gpxroutefile,"<metadata>\n");
195     fprintf(gpxroutefile,"<desc><![CDATA[%s route between 'start' and 'finish' waypoints]]></desc>\n",option_quickest?"Quickest":"Shortest");
196     if(source)
197     fprintf(gpxroutefile,"<copyright author=\"%s\">\n",source);
198     if(license)
199     fprintf(gpxroutefile,"<license>%s</license>\n",license);
200     if(source)
201     fprintf(gpxroutefile,"</copyright>\n");
202     fprintf(gpxroutefile,"</metadata>\n");
203 amb 160
204 amb 177 fprintf(gpxroutefile,"<rte>\n");
205     fprintf(gpxroutefile,"<name>%s route</name>\n",option_quickest?"Quickest":"Shortest");
206     }
207 amb 160
208 amb 177 if(textfile)
209     {
210     if(source)
211     fprintf(textfile,"# Source: %s\n",source);
212     if(license)
213     fprintf(textfile,"# License: %s\n",license);
214     if(source || license)
215     fprintf(textfile,"#\n");
216 amb 316 fprintf(textfile,"#Latitude\tLongitude\tSection \tSection \tTotal \tTotal \tPoint\tTurn\tBearing\tHighway\n");
217     fprintf(textfile,"# \t \tDistance\tDuration\tDistance\tDuration\tType \t \t \t \n");
218     /* "%10.6f\t%11.6f\t%6.3f km\t%4.1f min\t%5.1f km\t%4.0f min\t%s\t %+d\t %+d\t%s\n" */
219 amb 177 }
220 amb 160
221 amb 177 if(textallfile)
222     {
223     if(source)
224     fprintf(textallfile,"# Source: %s\n",source);
225     if(license)
226     fprintf(textallfile,"# License: %s\n",license);
227     if(source || license)
228     fprintf(textallfile,"#\n");
229 amb 316 fprintf(textallfile,"#Latitude\tLongitude\t Node\tType\tSegment\tSegment\tTotal\tTotal \tSpeed\tBearing\tHighway\n");
230     fprintf(textallfile,"# \t \t \t \tDist \tDurat'n\tDist \tDurat'n\t \t \t \n");
231     /* "%10.6f\t%11.6f\t%8d%c\t%s\t%5.3f\t%5.2f\t%5.2f\t%5.1f\t%3d\t%4d\t%s\n" */
232 amb 177 }
233 amb 164 }
234 amb 160
235 amb 164
236     /*++++++++++++++++++++++++++++++++++++++
237     Print the optimum route between two nodes.
238    
239 amb 316 Results **results The set of results to print (some may be NULL - ignore them).
240 amb 164
241 amb 316 int nresults The number of results in the list.
242    
243 amb 164 Nodes *nodes The list of nodes.
244    
245     Segments *segments The set of segments to use.
246    
247     Ways *ways The list of ways.
248    
249     Profile *profile The profile containing the transport type, speeds and allowed highways.
250     ++++++++++++++++++++++++++++++++++++++*/
251    
252 amb 316 void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,Ways *ways,Profile *profile)
253 amb 164 {
254 amb 316 int point=1;
255     distance_t cum_distance=0;
256     duration_t cum_duration=0;
257 amb 219 double finish_lat,finish_lon;
258 amb 316 int segment_count=0;
259     int route_count=0;
260 amb 164
261 amb 316 while(!results[point])
262     point++;
263 amb 164
264 amb 316 while(point<=nresults)
265     {
266     int nextpoint=point;
267     double start_lat,start_lon;
268     distance_t junc_distance=0;
269     duration_t junc_duration=0;
270     Result *result;
271 amb 160
272 amb 316 fprintf(gpxtrackfile,"<trkseg>\n");
273 amb 303
274 amb 316 if(IsFakeNode(results[point]->start))
275     GetFakeLatLong(results[point]->start,&start_lat,&start_lon);
276     else
277     GetLatLong(nodes,results[point]->start,&start_lat,&start_lon);
278 amb 165
279 amb 316 if(IsFakeNode(results[point]->finish))
280     GetFakeLatLong(results[point]->finish,&finish_lat,&finish_lon);
281 amb 303 else
282 amb 316 GetLatLong(nodes,results[point]->finish,&finish_lat,&finish_lon);
283 amb 160
284 amb 316 result=FindResult(results[point],results[point]->start);
285 amb 160
286 amb 316 do
287 amb 160 {
288 amb 316 double latitude,longitude;
289     Result *nextresult;
290 amb 160
291 amb 316 if(result->node==results[point]->start)
292     {latitude=start_lat; longitude=start_lon;}
293     else if(result->node==results[point]->finish)
294     {latitude=finish_lat; longitude=finish_lon;}
295     else
296     GetLatLong(nodes,result->node,&latitude,&longitude);
297 amb 171
298 amb 316 if(gpxtrackfile)
299     fprintf(gpxtrackfile,"<trkpt lat=\"%.6f\" lon=\"%.6f\"/>\n",
300     radians_to_degrees(latitude),radians_to_degrees(longitude));
301 amb 171
302 amb 316 nextresult=FindResult(results[point],result->next);
303 amb 171
304 amb 316 if(!nextresult)
305     for(nextpoint=point+1;nextpoint<=nresults;nextpoint++)
306     if(results[nextpoint])
307     {
308     nextresult=FindResult(results[nextpoint],results[nextpoint]->start);
309     nextresult=FindResult(results[nextpoint],nextresult->next);
310     break;
311     }
312 amb 171
313 amb 316 if(result->node!=results[point]->start)
314 amb 169 {
315 amb 316 distance_t seg_distance=0;
316     duration_t seg_duration=0;
317     Way *resultway;
318     int important=0;
319 amb 171
320 amb 316 /* Get the properties of this segment */
321    
322     resultway=LookupWay(ways,result->segment->way);
323    
324     seg_distance+=DISTANCE(result->segment->distance);
325     seg_duration+=Duration(result->segment,resultway,profile);
326     junc_distance+=seg_distance;
327     junc_duration+=seg_duration;
328     cum_distance+=seg_distance;
329     cum_duration+=seg_duration;
330    
331     /* Decide if this is an important junction */
332    
333     if(result->node==results[point]->finish)
334     important=10;
335     else
336 amb 303 {
337 amb 316 Segment *segment=FirstSegment(segments,nodes,result->node);
338 amb 160
339 amb 316 do
340     {
341     index_t othernode=OtherNode(segment,result->node);
342 amb 303
343 amb 316 if(othernode!=result->prev && segment!=result->segment)
344     if(IsNormalSegment(segment) && (!profile->oneway || !IsOnewayTo(segment,result->node)))
345 amb 303 {
346 amb 316 Way *way=LookupWay(ways,segment->way);
347    
348     if(othernode==result->next) /* the next segment that we follow */
349     {
350     if(HIGHWAY(way->type)!=HIGHWAY(resultway->type))
351     if(important<2)
352     important=2;
353     }
354     else /* a segment that we don't follow */
355     {
356     if(junction_other_way[HIGHWAY(resultway->type)-1][HIGHWAY(way->type)-1])
357     if(important<3)
358     important=3;
359    
360     if(important<1)
361     important=1;
362     }
363 amb 303 }
364 amb 160
365 amb 316 segment=NextSegment(segments,segment,result->node);
366     }
367     while(segment);
368 amb 303 }
369 amb 169
370 amb 316 /* Print out the important points (junctions / waypoints) */
371 amb 169
372 amb 316 if(important>1 && important<10)
373 amb 177 {
374 amb 316 /* Don't print the intermediate finish points (the final finish point is special) */
375 amb 303
376 amb 177 if(gpxroutefile)
377     fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>TRIP%03d</name></rtept>\n",
378 amb 198 radians_to_degrees(latitude),radians_to_degrees(longitude),
379 amb 177 ++route_count);
380     }
381 amb 316
382     if(important>1)
383 amb 165 {
384 amb 316 char *type;
385    
386     if(important==10)
387     type="Waypt";
388     else
389     type="Junct";
390    
391     /* Do print the intermediate finish points (because they have correct junction distances) */
392    
393     if(textfile)
394     {
395     if(nextresult)
396     fprintf(textfile,"%10.6f\t%11.6f\t%6.3f km\t%4.1f min\t%5.1f km\t%4.0f min\t%s\t %+d\t %+d\t%s\n",
397     radians_to_degrees(latitude),radians_to_degrees(longitude),
398     distance_to_km(junc_distance),duration_to_minutes(junc_duration),
399     distance_to_km(cum_distance),duration_to_minutes(cum_duration),
400     type,
401     (22+junction_angle(nodes,result->segment,nextresult->segment,result->node))/45,
402     ((22+bearing_angle(nodes,nextresult->segment,nextresult->node))/45+4)%8-4,
403     WayName(ways,resultway));
404     else
405     fprintf(textfile,"%10.6f\t%11.6f\t%6.3f km\t%4.1f min\t%5.1f km\t%4.0f min\t%s\t\t\t%s\n",
406     radians_to_degrees(latitude),radians_to_degrees(longitude),
407     distance_to_km(junc_distance),duration_to_minutes(junc_duration),
408     distance_to_km(cum_distance),duration_to_minutes(cum_duration),
409     type,
410     WayName(ways,resultway));
411     }
412    
413     junc_distance=0;
414     junc_duration=0;
415 amb 165 }
416 amb 160
417 amb 316 /* Print out all of the results */
418 amb 303
419 amb 316 if(textallfile)
420     {
421     char *type;
422    
423     if(important==10)
424     type="Waypt";
425     else if(important==2)
426     type="Change";
427     else if(important>=1)
428     type="Junct";
429     else
430     type="Inter";
431    
432     fprintf(textallfile,"%10.6f\t%11.6f\t%8d%c\t%s\t%5.3f\t%5.2f\t%5.2f\t%5.1f\t%3d\t%4d\t%s\n",
433 amb 198 radians_to_degrees(latitude),radians_to_degrees(longitude),
434 amb 316 IsFakeNode(result->node)?-(result->node&(~NODE_SUPER)):result->node,
435     (!IsFakeNode(result->node) && IsSuperNode(nodes,result->node))?'*':' ',type,
436     distance_to_km(seg_distance),duration_to_minutes(seg_duration),
437 amb 177 distance_to_km(cum_distance),duration_to_minutes(cum_duration),
438 amb 316 profile->speed[HIGHWAY(resultway->type)],
439     bearing_angle(nodes,result->segment,result->node),
440 amb 177 WayName(ways,resultway));
441 amb 316 }
442 amb 160 }
443 amb 316 else if(!cum_distance)
444     {
445     /* Print out the very first start point */
446 amb 160
447 amb 316 if(gpxroutefile)
448     fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>START</name></rtept>\n",
449     radians_to_degrees(latitude),radians_to_degrees(longitude));
450 amb 171
451 amb 316 if(textfile)
452     fprintf(textfile,"%10.6f\t%11.6f\t%6.3f km\t%4.1f min\t%5.1f km\t%4.0f min\t%s\t\t +%d\t\n",
453     radians_to_degrees(latitude),radians_to_degrees(longitude),
454     0.0,0.0,0.0,0.0,
455     "Waypt",
456     (22+bearing_angle(nodes,nextresult->segment,result->next))/45);
457 amb 171
458 amb 316 if(textallfile)
459     fprintf(textallfile,"%10.6f\t%11.6f\t%8d%c\t%s\t%5.3f\t%5.2f\t%5.2f\t%5.1f\t\t\t\n",
460     radians_to_degrees(latitude),radians_to_degrees(longitude),
461     IsFakeNode(result->node)?-(result->node&(~NODE_SUPER)):result->node,
462     (!IsFakeNode(result->node) && IsSuperNode(nodes,result->node))?'*':' ',"Waypt",
463     0.0,0.0,0.0,0.0);
464     }
465     else
466     {
467     /* Print out the intermediate start points */
468 amb 160
469 amb 316 if(gpxroutefile)
470     fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>INTER%d</name></rtept>\n",
471     radians_to_degrees(latitude),radians_to_degrees(longitude),
472     ++segment_count);
473     }
474 amb 160
475 amb 316 result=nextresult;
476 amb 160 }
477 amb 316 while(point==nextpoint);
478 amb 171
479 amb 316 if(gpxtrackfile)
480     fprintf(gpxtrackfile,"</trkseg>\n");
481 amb 160
482 amb 316 point=nextpoint;
483 amb 160 }
484 amb 165
485 amb 316 /* Print the very final point in the route */
486    
487     if(gpxroutefile)
488     fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>FINISH</name></rtept>\n",
489     radians_to_degrees(finish_lat),radians_to_degrees(finish_lon));
490 amb 164 }
491 amb 160
492 amb 164
493     /*++++++++++++++++++++++++++++++++++++++
494     Print the tail and close the files.
495     ++++++++++++++++++++++++++++++++++++++*/
496    
497     void PrintRouteTail(void)
498     {
499     /* Print the tail of the files */
500    
501 amb 177 if(gpxtrackfile)
502     {
503     fprintf(gpxtrackfile,"</trk>\n");
504     fprintf(gpxtrackfile,"</gpx>\n");
505     }
506 amb 160
507 amb 177 if(gpxroutefile)
508     {
509     fprintf(gpxroutefile,"</rte>\n");
510     fprintf(gpxroutefile,"</gpx>\n");
511     }
512 amb 160
513 amb 164 /* Close the files */
514    
515 amb 177 if(gpxtrackfile)
516     fclose(gpxtrackfile);
517     if(gpxroutefile)
518     fclose(gpxroutefile);
519     if(textfile)
520     fclose(textfile);
521     if(textallfile)
522     fclose(textallfile);
523 amb 160 }
524 amb 316
525    
526     /*++++++++++++++++++++++++++++++++++++++
527     Calculate the angle to turn at a junction from segment1 to segment2 at node.
528    
529     int junction_angle Returns a value in the range -4 to +4 indicating the angle to turn.
530    
531     Nodes *nodes The set of nodes.
532    
533     Segment *segment1 The current segment.
534    
535     Segment *segment2 The next segment.
536    
537     index_t node The node at which they join.
538    
539     Straight ahead is zero, turning to the right is positive (90 degrees) and turning to the left is negative.
540     Angles are calculated using flat Cartesian lat/long grid approximation (after scaling longitude due to latitude).
541     ++++++++++++++++++++++++++++++++++++++*/
542    
543     static int junction_angle(Nodes *nodes,Segment *segment1,Segment *segment2,index_t node)
544     {
545     double lat1,latm,lat2;
546     double lon1,lonm,lon2;
547     double angle1,angle2,angle;
548     index_t node1,node2;
549    
550     node1=OtherNode(segment1,node);
551     node2=OtherNode(segment2,node);
552    
553     if(IsFakeNode(node1))
554     GetFakeLatLong(node1,&lat1,&lon1);
555     else
556     GetLatLong(nodes,node1,&lat1,&lon1);
557    
558     if(IsFakeNode(node))
559     GetFakeLatLong(node,&latm,&lonm);
560     else
561     GetLatLong(nodes,node,&latm,&lonm);
562    
563     if(IsFakeNode(node2))
564     GetFakeLatLong(node2,&lat2,&lon2);
565     else
566     GetLatLong(nodes,node2,&lat2,&lon2);
567    
568     angle1=atan2((lonm-lon1)*cos(latm),(latm-lat1));
569     angle2=atan2((lon2-lonm)*cos(latm),(lat2-latm));
570    
571     angle=angle2-angle1;
572    
573     angle=radians_to_degrees(angle);
574    
575     angle=round(angle);
576    
577     if(angle<-180) angle+=360;
578     if(angle> 180) angle-=360;
579    
580     return((int)angle);
581     }
582    
583    
584     /*++++++++++++++++++++++++++++++++++++++
585     Calculate the bearing of a segment from the given node.
586    
587     int bearing_angle Returns a value in the range 0 to 359 indicating the bearing.
588    
589     Nodes *nodes The set of nodes.
590    
591     Segment *segment The segment.
592    
593     index_t node The node to start.
594    
595     Angles are calculated using flat Cartesian lat/long grid approximation (after scaling longitude due to latitude).
596     ++++++++++++++++++++++++++++++++++++++*/
597    
598     static int bearing_angle(Nodes *nodes,Segment *segment,index_t node)
599     {
600     double lat1,lat2;
601     double lon1,lon2;
602     double angle;
603     index_t node1,node2;
604    
605     node1=node;
606     node2=OtherNode(segment,node);
607    
608     if(IsFakeNode(node1))
609     GetFakeLatLong(node1,&lat1,&lon1);
610     else
611     GetLatLong(nodes,node1,&lat1,&lon1);
612    
613     if(IsFakeNode(node2))
614     GetFakeLatLong(node2,&lat2,&lon2);
615     else
616     GetLatLong(nodes,node2,&lat2,&lon2);
617    
618     angle=atan2((lat2-lat1),(lon2-lon1)*cos(lat1));
619    
620     angle=radians_to_degrees(angle);
621    
622     angle=round(270-angle);
623    
624     if(angle< 0) angle+=360;
625     if(angle>360) angle-=360;
626    
627     return((int)angle);
628     }

Properties

Name Value
cvs:description New file to contain the function to print the output.