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 378 - (show annotations) (download) (as text)
Sat Apr 24 15:49:37 2010 UTC (14 years, 11 months ago) by amb
File MIME type: text/x-csrc
File size: 32467 byte(s)
Added translations for the HTML output.

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

Properties

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