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 379 - (hide annotations) (download) (as text)
Sat Apr 24 16:47:56 2010 UTC (14 years, 11 months ago) by amb
File MIME type: text/x-csrc
File size: 32184 byte(s)
Merged the three functions to output the head/body/tail of the results back into
a single function.

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

Properties

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