Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /trunk/src/output.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 383 - (show annotations) (download) (as text)
Tue Apr 27 16:28:19 2010 UTC (14 years, 11 months ago) by amb
File MIME type: text/x-csrc
File size: 32188 byte(s)
Fix mistake of writing GPX information to wrong file.

1 /***************************************
2 $Header: /home/amb/CVS/routino/src/output.c,v 1.31 2010-04-27 16:28:19 amb Exp $
3
4 Routing output generator.
5
6 Part of the Routino routing software.
7 ******************/ /******************
8 This file Copyright 2008-2010 Andrew M. Bishop
9
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 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <stdio.h>
29 #include <math.h>
30 #include <errno.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34
35 #include "types.h"
36 #include "functions.h"
37 #include "translations.h"
38 #include "nodes.h"
39 #include "segments.h"
40 #include "ways.h"
41 #include "results.h"
42 #include "xmlparse.h"
43
44
45 /* Global variables */
46
47 /*+ The option to calculate the quickest route insted of the shortest. +*/
48 extern int option_quickest;
49
50 /*+ 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 /* Local variables */
54
55 /*+ Heuristics for determining if a junction is important. +*/
56 static char junction_other_way[Way_Count][Way_Count]=
57 { /* M, T, P, S, T, U, R, S, T, C, P, S = Way type of route not taken */
58 { 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 { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Secondary */
62 { 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 { 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 };
71
72
73 /* Local functions */
74
75 static int turn_angle(Nodes *nodes,Segment *segment1,Segment *segment2,index_t node);
76 static int bearing_angle(Nodes *nodes,Segment *segment,index_t node);
77
78
79 /*++++++++++++++++++++++++++++++++++++++
80 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 ++++++++++++++++++++++++++++++++++++++*/
94
95 void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,Ways *ways,Profile *profile)
96 {
97 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 /* Open the files */
107
108 if(option_quickest==0)
109 {
110 /* Print the result for the shortest route */
111
112 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
123 if(option_html && !htmlfile)
124 fprintf(stderr,"Warning: Cannot open file 'shortest.html' for writing [%s].\n",strerror(errno));
125 if(option_gpx_track && !gpxtrackfile)
126 fprintf(stderr,"Warning: Cannot open file 'shortest-track.gpx' for writing [%s].\n",strerror(errno));
127 if(option_gpx_route && !gpxroutefile)
128 fprintf(stderr,"Warning: Cannot open file 'shortest-route.gpx' for writing [%s].\n",strerror(errno));
129 if(option_text && !textfile)
130 fprintf(stderr,"Warning: Cannot open file 'shortest.txt' for writing [%s].\n",strerror(errno));
131 if(option_text_all && !textallfile)
132 fprintf(stderr,"Warning: Cannot open file 'shortest-all.txt' for writing [%s].\n",strerror(errno));
133 }
134 else
135 {
136 /* Print the result for the quickest route */
137
138 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
149 if(option_html && !htmlfile)
150 fprintf(stderr,"Warning: Cannot open file 'quickest.html' for writing [%s].\n",strerror(errno));
151 if(option_gpx_track && !gpxtrackfile)
152 fprintf(stderr,"Warning: Cannot open file 'quickest-track.gpx' for writing [%s].\n",strerror(errno));
153 if(option_gpx_route && !gpxroutefile)
154 fprintf(stderr,"Warning: Cannot open file 'quickest-route.gpx' for writing [%s].\n",strerror(errno));
155 if(option_text && !textfile)
156 fprintf(stderr,"Warning: Cannot open file 'quickest.txt' for writing [%s].\n",strerror(errno));
157 if(option_text_all && !textallfile)
158 fprintf(stderr,"Warning: Cannot open file 'quickest-all.txt' for writing [%s].\n",strerror(errno));
159 }
160
161 /* Print the head of the files */
162
163 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 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 fprintf(htmlfile,"<HEAD>\n");
174 fprintf(htmlfile,"<TITLE>");
175 fprintf(htmlfile,translate_html_title,option_quickest?translate_route_quickest:translate_route_shortest);
176 fprintf(htmlfile,"</TITLE>\n");
177 fprintf(htmlfile,"<STYLE type='text/css'>\n");
178 fprintf(htmlfile,"<!--\n");
179 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 fprintf(htmlfile,"-->\n");
195 fprintf(htmlfile,"</STYLE>\n");
196 fprintf(htmlfile,"</HEAD>\n");
197 fprintf(htmlfile,"<BODY>\n");
198 fprintf(htmlfile,"<H1>");
199 fprintf(htmlfile,translate_html_title,option_quickest?translate_route_quickest:translate_route_shortest);
200 fprintf(htmlfile,"</H1>\n");
201 fprintf(htmlfile,"<table>\n");
202 }
203
204 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
209 fprintf(gpxtrackfile,"<metadata>\n");
210 fprintf(gpxtrackfile,"<desc>%s : %s</desc>\n",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 fprintf(gpxtrackfile,"</copyright>\n");
219 }
220 fprintf(gpxtrackfile,"</metadata>\n");
221
222 fprintf(gpxtrackfile,"<trk>\n");
223 fprintf(gpxtrackfile,"<name>");
224 fprintf(gpxtrackfile,translate_gpx_name,option_quickest?translate_route_quickest:translate_route_shortest);
225 fprintf(gpxtrackfile,"</name>\n");
226 fprintf(gpxtrackfile,"<desc>");
227 fprintf(gpxtrackfile,translate_gpx_desc,option_quickest?translate_route_quickest:translate_route_shortest);
228 fprintf(gpxtrackfile,"</desc>\n");
229 }
230
231 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
236 fprintf(gpxroutefile,"<metadata>\n");
237 fprintf(gpxroutefile,"<desc>%s : %s</desc>\n",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 fprintf(gpxroutefile,"</copyright>\n");
246 }
247 fprintf(gpxroutefile,"</metadata>\n");
248
249 fprintf(gpxroutefile,"<rte>\n");
250 fprintf(gpxroutefile,"<name>");
251 fprintf(gpxroutefile,translate_gpx_name,option_quickest?translate_route_quickest:translate_route_shortest);
252 fprintf(gpxroutefile,"</name>\n");
253 fprintf(gpxroutefile,"<desc>");
254 fprintf(gpxroutefile,translate_gpx_desc,option_quickest?translate_route_quickest:translate_route_shortest);
255 fprintf(gpxroutefile,"</desc>\n");
256 }
257
258 if(textfile)
259 {
260 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 fprintf(textfile,"#\n");
270
271 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 }
275
276 if(textallfile)
277 {
278 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 fprintf(textallfile,"#\n");
288
289 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 }
293
294 /* Loop through the segments of the route and print it */
295
296 while(!results[point])
297 point++;
298
299 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
307 if(gpxtrackfile)
308 fprintf(gpxtrackfile,"<trkseg>\n");
309
310 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
315 if(IsFakeNode(results[point]->finish))
316 GetFakeLatLong(results[point]->finish,&finish_lat,&finish_lon);
317 else
318 GetLatLong(nodes,results[point]->finish,&finish_lat,&finish_lon);
319
320 result=FindResult(results[point],results[point]->start);
321
322 do
323 {
324 double latitude,longitude;
325 Result *nextresult;
326
327 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
334 if(gpxtrackfile)
335 fprintf(gpxtrackfile,"<trkpt lat=\"%.6f\" lon=\"%.6f\"/>\n",
336 radians_to_degrees(latitude),radians_to_degrees(longitude));
337
338 nextresult=FindResult(results[point],result->next);
339
340 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
349 if(result->node!=results[point]->start)
350 {
351 distance_t seg_distance=0;
352 duration_t seg_duration=0;
353 Way *resultway;
354 int important=0;
355
356 /* 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 /* 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 {
379 Segment *segment=FirstSegment(segments,nodes,result->node);
380
381 do
382 {
383 index_t othernode=OtherNode(segment,result->node);
384
385 if(othernode!=result->prev && segment!=result->segment)
386 if(IsNormalSegment(segment) && (!profile->oneway || !IsOnewayTo(segment,result->node)))
387 {
388 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 }
406
407 segment=NextSegment(segments,segment,result->node);
408 }
409 while(segment);
410 }
411
412 /* Print out the important points (junctions / waypoints) */
413
414 if(important>1)
415 {
416 /* Print the intermediate finish points (because they have correct junction distances) */
417
418 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 fprintf(htmlfile," [<span class='j'>");
435 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 if(gpxroutefile)
477 {
478 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 fprintf(gpxroutefile,translate_gpx_step,
489 bearing_str,
490 waynamexml,
491 distance_to_km(junc_distance),duration_to_minutes(junc_duration));
492 fprintf(gpxroutefile,"</desc></rtept>\n");
493
494 if(!nextresult)
495 {
496 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s</name>\n",
497 radians_to_degrees(finish_lat),radians_to_degrees(finish_lon),
498 translate_gpx_finish);
499 fprintf(gpxroutefile,"<desc>");
500 fprintf(gpxroutefile,translate_gpx_final,
501 distance_to_km(cum_distance),duration_to_minutes(cum_duration));
502 fprintf(gpxroutefile,"</desc></rtept>\n");
503 }
504 else if(important==10)
505 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%d</name>\n",
506 radians_to_degrees(latitude),radians_to_degrees(longitude),
507 translate_gpx_inter,++segment_count);
508 else
509 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%03d</name>\n",
510 radians_to_degrees(latitude),radians_to_degrees(longitude),
511 translate_gpx_trip,++route_count);
512 }
513
514 if(textfile)
515 {
516 char *type;
517
518 if(important==10)
519 type="Waypt";
520 else
521 type="Junct";
522
523 if(!wayname)
524 wayname=WayName(ways,resultway);
525
526 if(nextresult)
527 {
528 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
534 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
540 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 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 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 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 }
557
558 junc_distance=0;
559 junc_duration=0;
560 }
561
562 /* Print out all of the results */
563
564 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 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 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 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 }
596
597 if(waynamexml && waynamexml!=wayname)
598 free(waynamexml);
599 }
600 else if(!cum_distance)
601 {
602 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 /* Print out the very first start point */
606
607 if(htmlfile)
608 {
609 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 }
617
618 if(gpxroutefile)
619 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s</name>\n",
620 radians_to_degrees(latitude),radians_to_degrees(longitude),
621 translate_gpx_start);
622
623 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 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
630 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 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 }
637
638 result=nextresult;
639 }
640 while(point==nextpoint);
641
642 if(gpxtrackfile)
643 fprintf(gpxtrackfile,"</trkseg>\n");
644
645 point=nextpoint;
646 }
647
648 /* Print the tail of the files */
649
650 if(htmlfile)
651 {
652 fprintf(htmlfile,"</table>\n");
653
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 fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_copyright_creator[0],translate_copyright_creator[1]);
662 if(translate_copyright_source[0] && translate_copyright_source[1])
663 fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_copyright_source[0],translate_copyright_source[1]);
664 if(translate_copyright_license[0] && translate_copyright_license[1])
665 fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_copyright_license[0],translate_copyright_license[1]);
666 fprintf(htmlfile,"</table>\n");
667 }
668
669 fprintf(htmlfile,"</BODY>\n");
670 fprintf(htmlfile,"</HTML>\n");
671 }
672
673 if(gpxtrackfile)
674 {
675 fprintf(gpxtrackfile,"</trk>\n");
676 fprintf(gpxtrackfile,"</gpx>\n");
677 }
678
679 if(gpxroutefile)
680 {
681 fprintf(gpxroutefile,"</rte>\n");
682 fprintf(gpxroutefile,"</gpx>\n");
683 }
684
685 /* Close the files */
686
687 if(htmlfile)
688 fclose(htmlfile);
689 if(gpxtrackfile)
690 fclose(gpxtrackfile);
691 if(gpxroutefile)
692 fclose(gpxroutefile);
693 if(textfile)
694 fclose(textfile);
695 if(textallfile)
696 fclose(textallfile);
697 }
698
699
700 /*++++++++++++++++++++++++++++++++++++++
701 Calculate the angle to turn at a junction from segment1 to segment2 at node.
702
703 int turn_angle Returns a value in the range -4 to +4 indicating the angle to turn.
704
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 static int turn_angle(Nodes *nodes,Segment *segment1,Segment *segment2,index_t node)
718 {
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.