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 346 - (hide annotations) (download) (as text)
Thu Apr 1 18:24:39 2010 UTC (14 years, 11 months ago) by amb
File MIME type: text/x-csrc
File size: 25892 byte(s)
Wrap GPX descriptions in CDATA.

1 amb 160 /***************************************
2 amb 346 $Header: /home/amb/CVS/routino/src/output.c,v 1.25 2010-04-01 18:24:39 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 amb 331 FILE *file=fopen(copyright,"r");
89 amb 160
90 amb 331 if(file)
91 amb 164 {
92 amb 331 off_t size=SizeFile(copyright);
93     char *string=(char*)malloc(size+1);
94 amb 164 char *p;
95 amb 160
96 amb 331 fread(string,size,1,file);
97     string[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 332 if(important>1)
426 amb 177 {
427 amb 332 /* Print the intermediate finish points (because they have correct junction distances) */
428 amb 303
429 amb 177 if(gpxroutefile)
430 amb 332 {
431 amb 346 fprintf(gpxroutefile,"<desc><![CDATA[%s on '%s' for %.3f km, %.1f min]]></desc></rtept>\n",
432 amb 332 bearing_instruction[(4+(22+bearing_angle(nodes,result->segment,result->node))/45)%8],
433     WayName(ways,resultway),
434     distance_to_km(junc_distance),duration_to_minutes(junc_duration));
435 amb 316
436 amb 332 if(!nextresult)
437     {
438     fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>FINISH</name>\n",
439     radians_to_degrees(finish_lat),radians_to_degrees(finish_lon));
440 amb 346 fprintf(gpxroutefile,"<desc><![CDATA[Total Journey %.1f km, %.0f min]]></desc></rtept>\n",
441 amb 332 distance_to_km(cum_distance),duration_to_minutes(cum_duration));
442     }
443     else if(important==10)
444     fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>INTER%d</name>\n",
445     radians_to_degrees(latitude),radians_to_degrees(longitude),
446     ++segment_count);
447     else
448     fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>TRIP%03d</name>\n",
449     radians_to_degrees(latitude),radians_to_degrees(longitude),
450     ++route_count);
451     }
452 amb 316
453 amb 322 if(htmlfile)
454     {
455     char *type;
456 amb 316
457 amb 322 if(important==10)
458     type="<span class='w'>Waypoint</span>";
459     else
460     type="Junction";
461 amb 316
462 amb 332 fprintf(htmlfile,"<tr><td class='l'>Follow:<td class='r'>'%s' for <span class='d'>%.3f km, %.1f min</span> <span='td'>[%.1f km, %.0f min]</span>\n",
463 amb 322 WayName(ways,resultway),
464     distance_to_km(junc_distance),duration_to_minutes(junc_duration),
465     distance_to_km(cum_distance),duration_to_minutes(cum_duration));
466    
467     if(nextresult)
468     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",
469     type,
470     junction_instruction[(4+(22+junction_angle(nodes,result->segment,nextresult->segment,result->node))/45)%8],
471     bearing_instruction[(4+(22+bearing_angle(nodes,nextresult->segment,result->next))/45)%8]);
472     else
473     fprintf(htmlfile,"<tr><td class='l'>Stop:<td class='r'><span class='w'>Waypoint</span>\n");
474     }
475    
476 amb 316 if(textfile)
477     {
478 amb 322 char *type;
479    
480     if(important==10)
481     type="Waypt";
482     else
483     type="Junct";
484    
485 amb 316 if(nextresult)
486     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",
487     radians_to_degrees(latitude),radians_to_degrees(longitude),
488     distance_to_km(junc_distance),duration_to_minutes(junc_duration),
489     distance_to_km(cum_distance),duration_to_minutes(cum_duration),
490     type,
491     (22+junction_angle(nodes,result->segment,nextresult->segment,result->node))/45,
492     ((22+bearing_angle(nodes,nextresult->segment,nextresult->node))/45+4)%8-4,
493     WayName(ways,resultway));
494     else
495     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",
496     radians_to_degrees(latitude),radians_to_degrees(longitude),
497     distance_to_km(junc_distance),duration_to_minutes(junc_duration),
498     distance_to_km(cum_distance),duration_to_minutes(cum_duration),
499     type,
500     WayName(ways,resultway));
501     }
502    
503     junc_distance=0;
504     junc_duration=0;
505 amb 165 }
506 amb 160
507 amb 316 /* Print out all of the results */
508 amb 303
509 amb 316 if(textallfile)
510     {
511     char *type;
512    
513     if(important==10)
514     type="Waypt";
515     else if(important==2)
516     type="Change";
517     else if(important>=1)
518     type="Junct";
519     else
520     type="Inter";
521    
522     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",
523 amb 198 radians_to_degrees(latitude),radians_to_degrees(longitude),
524 amb 316 IsFakeNode(result->node)?-(result->node&(~NODE_SUPER)):result->node,
525     (!IsFakeNode(result->node) && IsSuperNode(nodes,result->node))?'*':' ',type,
526     distance_to_km(seg_distance),duration_to_minutes(seg_duration),
527 amb 177 distance_to_km(cum_distance),duration_to_minutes(cum_duration),
528 amb 316 profile->speed[HIGHWAY(resultway->type)],
529     bearing_angle(nodes,result->segment,result->node),
530 amb 177 WayName(ways,resultway));
531 amb 316 }
532 amb 160 }
533 amb 316 else if(!cum_distance)
534     {
535     /* Print out the very first start point */
536 amb 160
537 amb 323 if(htmlfile)
538     fprintf(htmlfile,"<tr><td class='l'>Start:<td class='r'><span class='w'>Waypoint</span>, head <span class='b'>%s</span>\n",
539     bearing_instruction[(4+(22+bearing_angle(nodes,nextresult->segment,result->next))/45)%8]);
540    
541 amb 316 if(gpxroutefile)
542 amb 332 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>START</name>\n",
543 amb 316 radians_to_degrees(latitude),radians_to_degrees(longitude));
544 amb 171
545 amb 316 if(textfile)
546     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",
547     radians_to_degrees(latitude),radians_to_degrees(longitude),
548     0.0,0.0,0.0,0.0,
549     "Waypt",
550     (22+bearing_angle(nodes,nextresult->segment,result->next))/45);
551 amb 171
552 amb 316 if(textallfile)
553     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",
554     radians_to_degrees(latitude),radians_to_degrees(longitude),
555     IsFakeNode(result->node)?-(result->node&(~NODE_SUPER)):result->node,
556     (!IsFakeNode(result->node) && IsSuperNode(nodes,result->node))?'*':' ',"Waypt",
557     0.0,0.0,0.0,0.0);
558     }
559 amb 160
560 amb 316 result=nextresult;
561 amb 160 }
562 amb 316 while(point==nextpoint);
563 amb 171
564 amb 316 if(gpxtrackfile)
565     fprintf(gpxtrackfile,"</trkseg>\n");
566 amb 160
567 amb 316 point=nextpoint;
568 amb 160 }
569 amb 164 }
570 amb 160
571 amb 164
572     /*++++++++++++++++++++++++++++++++++++++
573     Print the tail and close the files.
574     ++++++++++++++++++++++++++++++++++++++*/
575    
576     void PrintRouteTail(void)
577     {
578     /* Print the tail of the files */
579    
580 amb 323 if(htmlfile)
581     {
582     fprintf(htmlfile,"</table>\n");
583     fprintf(htmlfile,"</BODY>\n");
584     fprintf(htmlfile,"</HTML>\n");
585     }
586    
587 amb 177 if(gpxtrackfile)
588     {
589     fprintf(gpxtrackfile,"</trk>\n");
590     fprintf(gpxtrackfile,"</gpx>\n");
591     }
592 amb 160
593 amb 177 if(gpxroutefile)
594     {
595     fprintf(gpxroutefile,"</rte>\n");
596     fprintf(gpxroutefile,"</gpx>\n");
597     }
598 amb 160
599 amb 164 /* Close the files */
600    
601 amb 323 if(htmlfile)
602     fclose(htmlfile);
603 amb 177 if(gpxtrackfile)
604     fclose(gpxtrackfile);
605     if(gpxroutefile)
606     fclose(gpxroutefile);
607     if(textfile)
608     fclose(textfile);
609     if(textallfile)
610     fclose(textallfile);
611 amb 160 }
612 amb 316
613    
614     /*++++++++++++++++++++++++++++++++++++++
615     Calculate the angle to turn at a junction from segment1 to segment2 at node.
616    
617     int junction_angle Returns a value in the range -4 to +4 indicating the angle to turn.
618    
619     Nodes *nodes The set of nodes.
620    
621     Segment *segment1 The current segment.
622    
623     Segment *segment2 The next segment.
624    
625     index_t node The node at which they join.
626    
627     Straight ahead is zero, turning to the right is positive (90 degrees) and turning to the left is negative.
628     Angles are calculated using flat Cartesian lat/long grid approximation (after scaling longitude due to latitude).
629     ++++++++++++++++++++++++++++++++++++++*/
630    
631     static int junction_angle(Nodes *nodes,Segment *segment1,Segment *segment2,index_t node)
632     {
633     double lat1,latm,lat2;
634     double lon1,lonm,lon2;
635     double angle1,angle2,angle;
636     index_t node1,node2;
637    
638     node1=OtherNode(segment1,node);
639     node2=OtherNode(segment2,node);
640    
641     if(IsFakeNode(node1))
642     GetFakeLatLong(node1,&lat1,&lon1);
643     else
644     GetLatLong(nodes,node1,&lat1,&lon1);
645    
646     if(IsFakeNode(node))
647     GetFakeLatLong(node,&latm,&lonm);
648     else
649     GetLatLong(nodes,node,&latm,&lonm);
650    
651     if(IsFakeNode(node2))
652     GetFakeLatLong(node2,&lat2,&lon2);
653     else
654     GetLatLong(nodes,node2,&lat2,&lon2);
655    
656     angle1=atan2((lonm-lon1)*cos(latm),(latm-lat1));
657     angle2=atan2((lon2-lonm)*cos(latm),(lat2-latm));
658    
659     angle=angle2-angle1;
660    
661     angle=radians_to_degrees(angle);
662    
663     angle=round(angle);
664    
665     if(angle<-180) angle+=360;
666     if(angle> 180) angle-=360;
667    
668     return((int)angle);
669     }
670    
671    
672     /*++++++++++++++++++++++++++++++++++++++
673     Calculate the bearing of a segment from the given node.
674    
675     int bearing_angle Returns a value in the range 0 to 359 indicating the bearing.
676    
677     Nodes *nodes The set of nodes.
678    
679     Segment *segment The segment.
680    
681     index_t node The node to start.
682    
683     Angles are calculated using flat Cartesian lat/long grid approximation (after scaling longitude due to latitude).
684     ++++++++++++++++++++++++++++++++++++++*/
685    
686     static int bearing_angle(Nodes *nodes,Segment *segment,index_t node)
687     {
688     double lat1,lat2;
689     double lon1,lon2;
690     double angle;
691     index_t node1,node2;
692    
693     node1=node;
694     node2=OtherNode(segment,node);
695    
696     if(IsFakeNode(node1))
697     GetFakeLatLong(node1,&lat1,&lon1);
698     else
699     GetLatLong(nodes,node1,&lat1,&lon1);
700    
701     if(IsFakeNode(node2))
702     GetFakeLatLong(node2,&lat2,&lon2);
703     else
704     GetLatLong(nodes,node2,&lat2,&lon2);
705    
706     angle=atan2((lat2-lat1),(lon2-lon1)*cos(lat1));
707    
708     angle=radians_to_degrees(angle);
709    
710     angle=round(270-angle);
711    
712     if(angle< 0) angle+=360;
713     if(angle>360) angle-=360;
714    
715     return((int)angle);
716     }

Properties

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