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 330 - (hide annotations) (download) (as text)
Sat Mar 20 12:24:20 2010 UTC (15 years ago) by amb
File MIME type: text/x-csrc
File size: 25524 byte(s)
Improve the error messages by adding strerror() to them.

1 amb 160 /***************************************
2 amb 330 $Header: /home/amb/CVS/routino/src/output.c,v 1.22 2010-03-20 12:24:20 amb Exp $
3 amb 160
4     Routing output generator.
5    
6     Part of the Routino routing software.
7     ******************/ /******************
8 amb 330 This file Copyright 2008-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 330 #include <errno.h>
31 amb 164 #include <sys/types.h>
32     #include <sys/stat.h>
33     #include <unistd.h>
34 amb 160
35     #include "types.h"
36     #include "functions.h"
37     #include "nodes.h"
38     #include "segments.h"
39     #include "ways.h"
40     #include "results.h"
41    
42    
43     /*+ The option to calculate the quickest route insted of the shortest. +*/
44     extern int option_quickest;
45    
46 amb 324 /*+ The options to select the format of the output. +*/
47     extern int option_html,option_gpx_track,option_gpx_route,option_text,option_text_all;
48    
49 amb 164 /*+ The files to write to. +*/
50 amb 323 static FILE *htmlfile=NULL,*gpxtrackfile=NULL,*gpxroutefile=NULL,*textfile=NULL,*textallfile=NULL;
51 amb 160
52 amb 171 /*+ Heuristics for determining if a junction is important. +*/
53 amb 300 static char junction_other_way[Way_Count][Way_Count]=
54 amb 306 { /* M, T, P, S, T, U, R, S, T, C, P, S = Way type of route not taken */
55 amb 316 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Motorway */
56     { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Trunk */
57     { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Primary */
58 amb 306 { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Secondary */
59 amb 316 { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, /* Tertiary */
60     { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 }, /* Unclassified */
61     { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }, /* Residential */
62     { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, /* Service */
63     { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 }, /* Track */
64     { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 }, /* Cycleway */
65 amb 306 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Path */
66     { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Steps */
67 amb 171 };
68 amb 165
69 amb 316 static int junction_angle(Nodes *nodes,Segment *segment1,Segment *segment2,index_t node);
70     static int bearing_angle(Nodes *nodes,Segment *segment,index_t node);
71 amb 171
72 amb 322 static char *junction_instruction[]={"Very sharp left","Sharp left","Left","Slight left","Straight on","Slight right","Right","Sharp right","Very sharp right"};
73     static char *bearing_instruction[]={"South","South-West","West","North-West","North","North-East","East","South-East","South"};
74 amb 316
75 amb 322
76 amb 160 /*++++++++++++++++++++++++++++++++++++++
77 amb 164 Open the files and print the head.
78 amb 160
79 amb 164 const char *copyright The name of a file that might exist and contain copyright information.
80     ++++++++++++++++++++++++++++++++++++++*/
81 amb 160
82 amb 164 void PrintRouteHead(const char *copyright)
83     {
84     char *source=NULL,*license=NULL;
85 amb 160
86 amb 164 if(copyright)
87     {
88     struct stat buf;
89 amb 160
90 amb 164 if(!stat(copyright,&buf))
91     {
92     FILE *file=fopen(copyright,"r");
93     char *string=(char*)malloc(buf.st_size+1);
94     char *p;
95 amb 160
96 amb 164 fread(string,buf.st_size,1,file);
97     string[buf.st_size]=0;
98 amb 160
99 amb 164 p=string;
100     while(*p)
101     {
102     if(!strncmp(p,"Source:",7))
103     {
104     p+=7;
105     while(*p==' ' || *p=='t')
106     p++;
107     source=p;
108     while(*p && *p!='\r' && *p!='\n')
109     p++;
110     while(*p=='\r' || *p=='\n')
111     *p++=0;
112     }
113     else if(!strncmp(p,"License:",8) || !strncmp(p,"Licence:",8))
114     {
115     p+=8;
116     while(*p==' ' || *p=='t')
117     p++;
118     license=p;
119     while(*p && *p!='\r' && *p!='\n')
120     p++;
121     while(*p=='\r' || *p=='\n')
122     *p++=0;
123     }
124     else
125     {
126     while(*p && *p!='\r' && *p!='\n')
127     p++;
128     while(*p=='\r' || *p=='\n')
129     *p++=0;
130     }
131     }
132 amb 160
133 amb 164 fclose(file);
134     }
135     }
136 amb 160
137 amb 164 /* Open the files */
138 amb 160
139     if(option_quickest==0)
140     {
141     /* Print the result for the shortest route */
142    
143 amb 324 if(option_html)
144     htmlfile =fopen("shortest.html","w");
145     if(option_gpx_track)
146     gpxtrackfile=fopen("shortest-track.gpx","w");
147     if(option_gpx_route)
148     gpxroutefile=fopen("shortest-route.gpx","w");
149     if(option_text)
150     textfile =fopen("shortest.txt","w");
151     if(option_text_all)
152     textallfile =fopen("shortest-all.txt","w");
153 amb 177
154 amb 324 if(option_html && !htmlfile)
155 amb 330 fprintf(stderr,"Warning: Cannot open file 'shortest.html' for writing [%s].\n",strerror(errno));
156 amb 324 if(option_gpx_track && !gpxtrackfile)
157 amb 330 fprintf(stderr,"Warning: Cannot open file 'shortest-track.gpx' for writing [%s].\n",strerror(errno));
158 amb 324 if(option_gpx_route && !gpxroutefile)
159 amb 330 fprintf(stderr,"Warning: Cannot open file 'shortest-route.gpx' for writing [%s].\n",strerror(errno));
160 amb 324 if(option_text && !textfile)
161 amb 330 fprintf(stderr,"Warning: Cannot open file 'shortest.txt' for writing [%s].\n",strerror(errno));
162 amb 324 if(option_text_all && !textallfile)
163 amb 330 fprintf(stderr,"Warning: Cannot open file 'shortest-all.txt' for writing [%s].\n",strerror(errno));
164 amb 160 }
165     else
166     {
167     /* Print the result for the quickest route */
168    
169 amb 324 if(option_html)
170     htmlfile =fopen("quickest.html","w");
171     if(option_gpx_track)
172     gpxtrackfile=fopen("quickest-track.gpx","w");
173     if(option_gpx_route)
174     gpxroutefile=fopen("quickest-route.gpx","w");
175     if(option_text)
176     textfile =fopen("quickest.txt","w");
177     if(option_text_all)
178     textallfile =fopen("quickest-all.txt","w");
179 amb 177
180 amb 324 if(option_html && !htmlfile)
181 amb 330 fprintf(stderr,"Warning: Cannot open file 'quickest.html' for writing [%s].\n",strerror(errno));
182 amb 324 if(option_gpx_track && !gpxtrackfile)
183 amb 330 fprintf(stderr,"Warning: Cannot open file 'quickest-track.gpx' for writing [%s].\n",strerror(errno));
184 amb 324 if(option_gpx_route && !gpxroutefile)
185 amb 330 fprintf(stderr,"Warning: Cannot open file 'quickest-route.gpx' for writing [%s].\n",strerror(errno));
186 amb 324 if(option_text && !textfile)
187 amb 330 fprintf(stderr,"Warning: Cannot open file 'quickest.txt' for writing [%s].\n",strerror(errno));
188 amb 324 if(option_text_all && !textallfile)
189 amb 330 fprintf(stderr,"Warning: Cannot open file 'quickest-all.txt' for writing [%s].\n",strerror(errno));
190 amb 160 }
191    
192 amb 164 /* Print the head of the files */
193 amb 160
194 amb 323 if(htmlfile)
195     {
196     fprintf(htmlfile,"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
197     fprintf(htmlfile,"<HTML>\n");
198     fprintf(htmlfile,"<HEAD>\n");
199     if(source)
200     fprintf(htmlfile,"<!-- Source: %s -->\n",source);
201     if(license)
202     fprintf(htmlfile,"<!-- License: %s -->\n",license);
203     fprintf(htmlfile,"<TITLE>Routino: %s Route</TITLE>\n",option_quickest?"Quickest":"Shortest");
204     fprintf(htmlfile,"<STYLE type='text/css'>\n");
205     fprintf(htmlfile,"<!--\n");
206     fprintf(htmlfile," table {table-layout: fixed; border: none; border-collapse: collapse;}\n");
207     fprintf(htmlfile," tr {border: 0px;}\n");
208     fprintf(htmlfile," td.l {font-weight: bold;}\n");
209     fprintf(htmlfile," td.r {}\n");
210     fprintf(htmlfile," span.w {font-weight: bold;}\n");
211     fprintf(htmlfile," span.d {}\n");
212     fprintf(htmlfile," span.dt {}\n");
213     fprintf(htmlfile," span.t {font-variant: small-caps;}\n");
214     fprintf(htmlfile," span.b {font-variant: small-caps;}\n");
215     fprintf(htmlfile,"-->\n");
216     fprintf(htmlfile,"</STYLE>\n");
217     fprintf(htmlfile,"</HEAD>\n");
218     fprintf(htmlfile,"<BODY>\n");
219     fprintf(htmlfile,"<H1>Routino: %s Route</H1>\n",option_quickest?"Quickest":"Shortest");
220     fprintf(htmlfile,"<table>\n");
221     }
222    
223 amb 177 if(gpxtrackfile)
224     {
225     fprintf(gpxtrackfile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
226     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");
227 amb 160
228 amb 177 fprintf(gpxtrackfile,"<metadata>\n");
229     fprintf(gpxtrackfile,"<desc><![CDATA[%s route between 'start' and 'finish' waypoints]]></desc>\n",option_quickest?"Quickest":"Shortest");
230     if(source)
231     fprintf(gpxtrackfile,"<copyright author=\"%s\">\n",source);
232     if(license)
233     fprintf(gpxtrackfile,"<license>%s</license>\n",license);
234     if(source)
235     fprintf(gpxtrackfile,"</copyright>\n");
236     fprintf(gpxtrackfile,"</metadata>\n");
237 amb 160
238 amb 177 fprintf(gpxtrackfile,"<trk>\n");
239     }
240 amb 160
241 amb 177 if(gpxroutefile)
242     {
243     fprintf(gpxroutefile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
244     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");
245 amb 160
246 amb 177 fprintf(gpxroutefile,"<metadata>\n");
247     fprintf(gpxroutefile,"<desc><![CDATA[%s route between 'start' and 'finish' waypoints]]></desc>\n",option_quickest?"Quickest":"Shortest");
248     if(source)
249     fprintf(gpxroutefile,"<copyright author=\"%s\">\n",source);
250     if(license)
251     fprintf(gpxroutefile,"<license>%s</license>\n",license);
252     if(source)
253     fprintf(gpxroutefile,"</copyright>\n");
254     fprintf(gpxroutefile,"</metadata>\n");
255 amb 160
256 amb 177 fprintf(gpxroutefile,"<rte>\n");
257     fprintf(gpxroutefile,"<name>%s route</name>\n",option_quickest?"Quickest":"Shortest");
258     }
259 amb 160
260 amb 177 if(textfile)
261     {
262     if(source)
263     fprintf(textfile,"# Source: %s\n",source);
264     if(license)
265     fprintf(textfile,"# License: %s\n",license);
266     if(source || license)
267     fprintf(textfile,"#\n");
268 amb 316 fprintf(textfile,"#Latitude\tLongitude\tSection \tSection \tTotal \tTotal \tPoint\tTurn\tBearing\tHighway\n");
269     fprintf(textfile,"# \t \tDistance\tDuration\tDistance\tDuration\tType \t \t \t \n");
270     /* "%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" */
271 amb 177 }
272 amb 160
273 amb 177 if(textallfile)
274     {
275     if(source)
276     fprintf(textallfile,"# Source: %s\n",source);
277     if(license)
278     fprintf(textallfile,"# License: %s\n",license);
279     if(source || license)
280     fprintf(textallfile,"#\n");
281 amb 316 fprintf(textallfile,"#Latitude\tLongitude\t Node\tType\tSegment\tSegment\tTotal\tTotal \tSpeed\tBearing\tHighway\n");
282     fprintf(textallfile,"# \t \t \t \tDist \tDurat'n\tDist \tDurat'n\t \t \t \n");
283     /* "%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" */
284 amb 177 }
285 amb 164 }
286 amb 160
287 amb 164
288     /*++++++++++++++++++++++++++++++++++++++
289     Print the optimum route between two nodes.
290    
291 amb 316 Results **results The set of results to print (some may be NULL - ignore them).
292 amb 164
293 amb 316 int nresults The number of results in the list.
294    
295 amb 164 Nodes *nodes The list of nodes.
296    
297     Segments *segments The set of segments to use.
298    
299     Ways *ways The list of ways.
300    
301     Profile *profile The profile containing the transport type, speeds and allowed highways.
302     ++++++++++++++++++++++++++++++++++++++*/
303    
304 amb 316 void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,Ways *ways,Profile *profile)
305 amb 164 {
306 amb 316 int point=1;
307     distance_t cum_distance=0;
308     duration_t cum_duration=0;
309 amb 219 double finish_lat,finish_lon;
310 amb 316 int segment_count=0;
311     int route_count=0;
312 amb 164
313 amb 316 while(!results[point])
314     point++;
315 amb 164
316 amb 316 while(point<=nresults)
317     {
318     int nextpoint=point;
319     double start_lat,start_lon;
320     distance_t junc_distance=0;
321     duration_t junc_duration=0;
322     Result *result;
323 amb 160
324 amb 324 if(gpxtrackfile)
325     fprintf(gpxtrackfile,"<trkseg>\n");
326 amb 303
327 amb 316 if(IsFakeNode(results[point]->start))
328     GetFakeLatLong(results[point]->start,&start_lat,&start_lon);
329     else
330     GetLatLong(nodes,results[point]->start,&start_lat,&start_lon);
331 amb 165
332 amb 316 if(IsFakeNode(results[point]->finish))
333     GetFakeLatLong(results[point]->finish,&finish_lat,&finish_lon);
334 amb 303 else
335 amb 316 GetLatLong(nodes,results[point]->finish,&finish_lat,&finish_lon);
336 amb 160
337 amb 316 result=FindResult(results[point],results[point]->start);
338 amb 160
339 amb 316 do
340 amb 160 {
341 amb 316 double latitude,longitude;
342     Result *nextresult;
343 amb 160
344 amb 316 if(result->node==results[point]->start)
345     {latitude=start_lat; longitude=start_lon;}
346     else if(result->node==results[point]->finish)
347     {latitude=finish_lat; longitude=finish_lon;}
348     else
349     GetLatLong(nodes,result->node,&latitude,&longitude);
350 amb 171
351 amb 316 if(gpxtrackfile)
352     fprintf(gpxtrackfile,"<trkpt lat=\"%.6f\" lon=\"%.6f\"/>\n",
353     radians_to_degrees(latitude),radians_to_degrees(longitude));
354 amb 171
355 amb 316 nextresult=FindResult(results[point],result->next);
356 amb 171
357 amb 316 if(!nextresult)
358     for(nextpoint=point+1;nextpoint<=nresults;nextpoint++)
359     if(results[nextpoint])
360     {
361     nextresult=FindResult(results[nextpoint],results[nextpoint]->start);
362     nextresult=FindResult(results[nextpoint],nextresult->next);
363     break;
364     }
365 amb 171
366 amb 316 if(result->node!=results[point]->start)
367 amb 169 {
368 amb 316 distance_t seg_distance=0;
369     duration_t seg_duration=0;
370     Way *resultway;
371     int important=0;
372 amb 171
373 amb 316 /* Get the properties of this segment */
374    
375     resultway=LookupWay(ways,result->segment->way);
376    
377     seg_distance+=DISTANCE(result->segment->distance);
378     seg_duration+=Duration(result->segment,resultway,profile);
379     junc_distance+=seg_distance;
380     junc_duration+=seg_duration;
381     cum_distance+=seg_distance;
382     cum_duration+=seg_duration;
383    
384     /* Decide if this is an important junction */
385    
386     if(result->node==results[point]->finish)
387     important=10;
388     else
389 amb 303 {
390 amb 316 Segment *segment=FirstSegment(segments,nodes,result->node);
391 amb 160
392 amb 316 do
393     {
394     index_t othernode=OtherNode(segment,result->node);
395 amb 303
396 amb 316 if(othernode!=result->prev && segment!=result->segment)
397     if(IsNormalSegment(segment) && (!profile->oneway || !IsOnewayTo(segment,result->node)))
398 amb 303 {
399 amb 316 Way *way=LookupWay(ways,segment->way);
400    
401     if(othernode==result->next) /* the next segment that we follow */
402     {
403     if(HIGHWAY(way->type)!=HIGHWAY(resultway->type))
404     if(important<2)
405     important=2;
406     }
407     else /* a segment that we don't follow */
408     {
409     if(junction_other_way[HIGHWAY(resultway->type)-1][HIGHWAY(way->type)-1])
410     if(important<3)
411     important=3;
412    
413     if(important<1)
414     important=1;
415     }
416 amb 303 }
417 amb 160
418 amb 316 segment=NextSegment(segments,segment,result->node);
419     }
420     while(segment);
421 amb 303 }
422 amb 169
423 amb 316 /* Print out the important points (junctions / waypoints) */
424 amb 169
425 amb 316 if(important>1 && important<10)
426 amb 177 {
427 amb 316 /* Don't print the intermediate finish points (the final finish point is special) */
428 amb 303
429 amb 177 if(gpxroutefile)
430     fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>TRIP%03d</name></rtept>\n",
431 amb 198 radians_to_degrees(latitude),radians_to_degrees(longitude),
432 amb 177 ++route_count);
433     }
434 amb 316
435     if(important>1)
436 amb 165 {
437 amb 322 /* Do print the intermediate finish points (because they have correct junction distances) */
438 amb 316
439 amb 322 if(htmlfile)
440     {
441     char *type;
442 amb 316
443 amb 322 if(important==10)
444     type="<span class='w'>Waypoint</span>";
445     else
446     type="Junction";
447 amb 316
448 amb 322 fprintf(htmlfile,"<tr><td class='l'>Follow:<td class='r'>'%s' for <span class='d'>%6.3f km, %4.1f min</span> <span='td'>[%5.1f km, %4.0f min]</span>\n",
449     WayName(ways,resultway),
450     distance_to_km(junc_distance),duration_to_minutes(junc_duration),
451     distance_to_km(cum_distance),duration_to_minutes(cum_duration));
452    
453     if(nextresult)
454     fprintf(htmlfile,"<tr><td class='l'>At:<td class='r'>%s, turn <span class='t'>%s</span> and head <span class='b'>%s</span>\n",
455     type,
456     junction_instruction[(4+(22+junction_angle(nodes,result->segment,nextresult->segment,result->node))/45)%8],
457     bearing_instruction[(4+(22+bearing_angle(nodes,nextresult->segment,result->next))/45)%8]);
458     else
459     fprintf(htmlfile,"<tr><td class='l'>Stop:<td class='r'><span class='w'>Waypoint</span>\n");
460     }
461    
462 amb 316 if(textfile)
463     {
464 amb 322 char *type;
465    
466     if(important==10)
467     type="Waypt";
468     else
469     type="Junct";
470    
471 amb 316 if(nextresult)
472     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",
473     radians_to_degrees(latitude),radians_to_degrees(longitude),
474     distance_to_km(junc_distance),duration_to_minutes(junc_duration),
475     distance_to_km(cum_distance),duration_to_minutes(cum_duration),
476     type,
477     (22+junction_angle(nodes,result->segment,nextresult->segment,result->node))/45,
478     ((22+bearing_angle(nodes,nextresult->segment,nextresult->node))/45+4)%8-4,
479     WayName(ways,resultway));
480     else
481     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",
482     radians_to_degrees(latitude),radians_to_degrees(longitude),
483     distance_to_km(junc_distance),duration_to_minutes(junc_duration),
484     distance_to_km(cum_distance),duration_to_minutes(cum_duration),
485     type,
486     WayName(ways,resultway));
487     }
488    
489     junc_distance=0;
490     junc_duration=0;
491 amb 165 }
492 amb 160
493 amb 316 /* Print out all of the results */
494 amb 303
495 amb 316 if(textallfile)
496     {
497     char *type;
498    
499     if(important==10)
500     type="Waypt";
501     else if(important==2)
502     type="Change";
503     else if(important>=1)
504     type="Junct";
505     else
506     type="Inter";
507    
508     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",
509 amb 198 radians_to_degrees(latitude),radians_to_degrees(longitude),
510 amb 316 IsFakeNode(result->node)?-(result->node&(~NODE_SUPER)):result->node,
511     (!IsFakeNode(result->node) && IsSuperNode(nodes,result->node))?'*':' ',type,
512     distance_to_km(seg_distance),duration_to_minutes(seg_duration),
513 amb 177 distance_to_km(cum_distance),duration_to_minutes(cum_duration),
514 amb 316 profile->speed[HIGHWAY(resultway->type)],
515     bearing_angle(nodes,result->segment,result->node),
516 amb 177 WayName(ways,resultway));
517 amb 316 }
518 amb 160 }
519 amb 316 else if(!cum_distance)
520     {
521     /* Print out the very first start point */
522 amb 160
523 amb 323 if(htmlfile)
524     fprintf(htmlfile,"<tr><td class='l'>Start:<td class='r'><span class='w'>Waypoint</span>, head <span class='b'>%s</span>\n",
525     bearing_instruction[(4+(22+bearing_angle(nodes,nextresult->segment,result->next))/45)%8]);
526    
527 amb 316 if(gpxroutefile)
528     fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>START</name></rtept>\n",
529     radians_to_degrees(latitude),radians_to_degrees(longitude));
530 amb 171
531 amb 316 if(textfile)
532     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",
533     radians_to_degrees(latitude),radians_to_degrees(longitude),
534     0.0,0.0,0.0,0.0,
535     "Waypt",
536     (22+bearing_angle(nodes,nextresult->segment,result->next))/45);
537 amb 171
538 amb 316 if(textallfile)
539     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",
540     radians_to_degrees(latitude),radians_to_degrees(longitude),
541     IsFakeNode(result->node)?-(result->node&(~NODE_SUPER)):result->node,
542     (!IsFakeNode(result->node) && IsSuperNode(nodes,result->node))?'*':' ',"Waypt",
543     0.0,0.0,0.0,0.0);
544     }
545     else
546     {
547     /* Print out the intermediate start points */
548 amb 160
549 amb 316 if(gpxroutefile)
550     fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>INTER%d</name></rtept>\n",
551     radians_to_degrees(latitude),radians_to_degrees(longitude),
552     ++segment_count);
553     }
554 amb 160
555 amb 316 result=nextresult;
556 amb 160 }
557 amb 316 while(point==nextpoint);
558 amb 171
559 amb 316 if(gpxtrackfile)
560     fprintf(gpxtrackfile,"</trkseg>\n");
561 amb 160
562 amb 316 point=nextpoint;
563 amb 160 }
564 amb 165
565 amb 316 /* Print the very final point in the route */
566    
567     if(gpxroutefile)
568     fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>FINISH</name></rtept>\n",
569     radians_to_degrees(finish_lat),radians_to_degrees(finish_lon));
570 amb 164 }
571 amb 160
572 amb 164
573     /*++++++++++++++++++++++++++++++++++++++
574     Print the tail and close the files.
575     ++++++++++++++++++++++++++++++++++++++*/
576    
577     void PrintRouteTail(void)
578     {
579     /* Print the tail of the files */
580    
581 amb 323 if(htmlfile)
582     {
583     fprintf(htmlfile,"</table>\n");
584     fprintf(htmlfile,"</BODY>\n");
585     fprintf(htmlfile,"</HTML>\n");
586     }
587    
588 amb 177 if(gpxtrackfile)
589     {
590     fprintf(gpxtrackfile,"</trk>\n");
591     fprintf(gpxtrackfile,"</gpx>\n");
592     }
593 amb 160
594 amb 177 if(gpxroutefile)
595     {
596     fprintf(gpxroutefile,"</rte>\n");
597     fprintf(gpxroutefile,"</gpx>\n");
598     }
599 amb 160
600 amb 164 /* Close the files */
601    
602 amb 323 if(htmlfile)
603     fclose(htmlfile);
604 amb 177 if(gpxtrackfile)
605     fclose(gpxtrackfile);
606     if(gpxroutefile)
607     fclose(gpxroutefile);
608     if(textfile)
609     fclose(textfile);
610     if(textallfile)
611     fclose(textallfile);
612 amb 160 }
613 amb 316
614    
615     /*++++++++++++++++++++++++++++++++++++++
616     Calculate the angle to turn at a junction from segment1 to segment2 at node.
617    
618     int junction_angle Returns a value in the range -4 to +4 indicating the angle to turn.
619    
620     Nodes *nodes The set of nodes.
621    
622     Segment *segment1 The current segment.
623    
624     Segment *segment2 The next segment.
625    
626     index_t node The node at which they join.
627    
628     Straight ahead is zero, turning to the right is positive (90 degrees) and turning to the left is negative.
629     Angles are calculated using flat Cartesian lat/long grid approximation (after scaling longitude due to latitude).
630     ++++++++++++++++++++++++++++++++++++++*/
631    
632     static int junction_angle(Nodes *nodes,Segment *segment1,Segment *segment2,index_t node)
633     {
634     double lat1,latm,lat2;
635     double lon1,lonm,lon2;
636     double angle1,angle2,angle;
637     index_t node1,node2;
638    
639     node1=OtherNode(segment1,node);
640     node2=OtherNode(segment2,node);
641    
642     if(IsFakeNode(node1))
643     GetFakeLatLong(node1,&lat1,&lon1);
644     else
645     GetLatLong(nodes,node1,&lat1,&lon1);
646    
647     if(IsFakeNode(node))
648     GetFakeLatLong(node,&latm,&lonm);
649     else
650     GetLatLong(nodes,node,&latm,&lonm);
651    
652     if(IsFakeNode(node2))
653     GetFakeLatLong(node2,&lat2,&lon2);
654     else
655     GetLatLong(nodes,node2,&lat2,&lon2);
656    
657     angle1=atan2((lonm-lon1)*cos(latm),(latm-lat1));
658     angle2=atan2((lon2-lonm)*cos(latm),(lat2-latm));
659    
660     angle=angle2-angle1;
661    
662     angle=radians_to_degrees(angle);
663    
664     angle=round(angle);
665    
666     if(angle<-180) angle+=360;
667     if(angle> 180) angle-=360;
668    
669     return((int)angle);
670     }
671    
672    
673     /*++++++++++++++++++++++++++++++++++++++
674     Calculate the bearing of a segment from the given node.
675    
676     int bearing_angle Returns a value in the range 0 to 359 indicating the bearing.
677    
678     Nodes *nodes The set of nodes.
679    
680     Segment *segment The segment.
681    
682     index_t node The node to start.
683    
684     Angles are calculated using flat Cartesian lat/long grid approximation (after scaling longitude due to latitude).
685     ++++++++++++++++++++++++++++++++++++++*/
686    
687     static int bearing_angle(Nodes *nodes,Segment *segment,index_t node)
688     {
689     double lat1,lat2;
690     double lon1,lon2;
691     double angle;
692     index_t node1,node2;
693    
694     node1=node;
695     node2=OtherNode(segment,node);
696    
697     if(IsFakeNode(node1))
698     GetFakeLatLong(node1,&lat1,&lon1);
699     else
700     GetLatLong(nodes,node1,&lat1,&lon1);
701    
702     if(IsFakeNode(node2))
703     GetFakeLatLong(node2,&lat2,&lon2);
704     else
705     GetLatLong(nodes,node2,&lat2,&lon2);
706    
707     angle=atan2((lat2-lat1),(lon2-lon1)*cos(lat1));
708    
709     angle=radians_to_degrees(angle);
710    
711     angle=round(270-angle);
712    
713     if(angle< 0) angle+=360;
714     if(angle>360) angle-=360;
715    
716     return((int)angle);
717     }

Properties

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