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 619 - (show annotations) (download) (as text)
Sun Jan 30 15:19:42 2011 UTC (14 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 33779 byte(s)
Correct comments.

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

Properties

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