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 449 - (show annotations) (download) (as text)
Mon Jul 12 17:59:42 2010 UTC (14 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 32710 byte(s)
Create a files.h header and put some of the most heavily used files.c functions
into it and make them inline.

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

Properties

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