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 603 - (show annotations) (download) (as text)
Sat Jan 15 22:22:57 2011 UTC (14 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 33700 byte(s)
Change the results structure to contain next segment and rename elements to
clarify prev/next node and prev/next segment.

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))
314 GetFakeLatLong(results[point]->start,&start_lat,&start_lon);
315 else
316 GetLatLong(nodes,results[point]->start,&start_lat,&start_lon);
317
318 if(IsFakeNode(results[point]->finish))
319 GetFakeLatLong(results[point]->finish,&finish_lat,&finish_lon);
320 else
321 GetLatLong(nodes,results[point]->finish,&finish_lat,&finish_lon);
322
323 result=FindResult(results[point],results[point]->start);
324
325 do
326 {
327 double latitude,longitude;
328 Result *nextresult;
329 Segment *nextresultsegment;
330
331 if(result->node==results[point]->start)
332 {latitude=start_lat; longitude=start_lon;}
333 else if(result->node==results[point]->finish)
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=FindResult(results[point],result->next_node);
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);
349 nextresult=FindResult(results[nextpoint],nextresult->next_node);
350 break;
351 }
352
353 if(nextresult)
354 {
355 if(IsFakeSegment(nextresult->prev_seg))
356 nextresultsegment=LookupFakeSegment(nextresult->prev_seg);
357 else
358 nextresultsegment=LookupSegment(segments,nextresult->prev_seg,2);
359 }
360 else
361 nextresultsegment=NULL;
362
363 if(result->node!=results[point]->start)
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->prev_seg))
381 resultsegment=LookupFakeSegment(result->prev_seg);
382 else
383 resultsegment=LookupSegment(segments,result->prev_seg,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)
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 -4 to +4 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 (90 degrees) and turning to the left is negative.
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.