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 471 - (show annotations) (download) (as text)
Wed Aug 4 16:44:52 2010 UTC (14 years, 7 months ago) by amb
File MIME type: text/x-csrc
File size: 33244 byte(s)
Change the way that fake nodes and segments are recognised (allows nearly 4G
nodes to be stored instead of 2G nodes).

1 /***************************************
2 $Header: /home/amb/CVS/routino/src/output.c,v 1.37 2010-08-04 16:44:52 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 Segment *nextresultsegment;
329
330 if(result->node==results[point]->start)
331 {latitude=start_lat; longitude=start_lon;}
332 else if(result->node==results[point]->finish)
333 {latitude=finish_lat; longitude=finish_lon;}
334 else
335 GetLatLong(nodes,result->node,&latitude,&longitude);
336
337 if(gpxtrackfile)
338 fprintf(gpxtrackfile,"<trkpt lat=\"%.6f\" lon=\"%.6f\"/>\n",
339 radians_to_degrees(latitude),radians_to_degrees(longitude));
340
341 nextresult=FindResult(results[point],result->next);
342
343 if(!nextresult)
344 for(nextpoint=point+1;nextpoint<=nresults;nextpoint++)
345 if(results[nextpoint])
346 {
347 nextresult=FindResult(results[nextpoint],results[nextpoint]->start);
348 nextresult=FindResult(results[nextpoint],nextresult->next);
349 break;
350 }
351
352 if(nextresult)
353 {
354 if(IsFakeSegment(nextresult->segment))
355 nextresultsegment=LookupFakeSegment(nextresult->segment);
356 else
357 nextresultsegment=LookupSegment(segments,nextresult->segment,2);
358 }
359 else
360 nextresultsegment=NULL;
361
362 if(result->node!=results[point]->start)
363 {
364 distance_t seg_distance=0;
365 duration_t seg_duration=0;
366 Segment *resultsegment;
367 Way *resultway;
368 int important=0;
369
370 /* Cache the values to be printed rather than calculating them repeatedly for each output format */
371
372 char *waynameraw=NULL,*wayname=NULL,*waynamexml=NULL;
373 int bearing_int=0,bearing_next_int=0,turn_int=0;
374 char *bearing_str=NULL,*bearing_next_str=NULL,*turn_str=NULL;
375
376 /* Get the properties of this segment */
377
378 if(IsFakeSegment(result->segment))
379 resultsegment=LookupFakeSegment(result->segment);
380 else
381 resultsegment=LookupSegment(segments,result->segment,3);
382 resultway=LookupWay(ways,resultsegment->way,1);
383
384 seg_distance+=DISTANCE(resultsegment->distance);
385 seg_duration+=Duration(resultsegment,resultway,profile);
386 junc_distance+=seg_distance;
387 junc_duration+=seg_duration;
388 cum_distance+=seg_distance;
389 cum_duration+=seg_duration;
390
391 /* Decide if this is an important junction */
392
393 if(result->node==results[point]->finish)
394 important=10;
395 else
396 {
397 Segment *segment=FirstSegment(segments,nodes,result->node);
398
399 do
400 {
401 index_t othernode=OtherNode(segment,result->node);
402
403 if(othernode!=result->prev && segment!=resultsegment)
404 if(IsNormalSegment(segment) && (!profile->oneway || !IsOnewayTo(segment,result->node)))
405 {
406 Way *way=LookupWay(ways,segment->way,2);
407
408 if(othernode==result->next) /* the next segment that we follow */
409 {
410 if(HIGHWAY(way->type)!=HIGHWAY(resultway->type))
411 if(important<2)
412 important=2;
413 }
414 else /* a segment that we don't follow */
415 {
416 if(junction_other_way[HIGHWAY(resultway->type)-1][HIGHWAY(way->type)-1])
417 if(important<3)
418 important=3;
419
420 if(important<1)
421 important=1;
422 }
423 }
424
425 segment=NextSegment(segments,segment,result->node);
426 }
427 while(segment);
428 }
429
430 /* Print out the important points (junctions / waypoints) */
431
432 if(important>1)
433 {
434 /* Print the intermediate finish points (because they have correct junction distances) */
435
436 if(htmlfile)
437 {
438 char *type;
439
440 if(important==10)
441 type=translate_html_waypoint;
442 else
443 type=translate_html_junction;
444
445 if(!waynameraw)
446 {
447 waynameraw=WayNameRaw(ways,resultway);
448 if(!*waynameraw)
449 waynameraw=translate_highway[HIGHWAY(resultway->type)];
450 }
451
452 if(!waynamexml)
453 waynamexml=ParseXML_Encode_Safe_XML(waynameraw);
454
455 fprintf(htmlfile,"<tr class='s'><td class='l'>%s:<td class='r'>",translate_html_segment[0]);
456 fprintf(htmlfile,translate_html_segment[1],
457 waynamexml,
458 distance_to_km(junc_distance),duration_to_minutes(junc_duration));
459 fprintf(htmlfile," [<span class='j'>");
460 fprintf(htmlfile,translate_html_total[1],
461 distance_to_km(cum_distance),duration_to_minutes(cum_duration));
462 fprintf(htmlfile,"</span>]\n");
463
464 fprintf(htmlfile,"<tr class='c'><td class='l'><td class='r'>%.6f %.6f\n",
465 radians_to_degrees(latitude),radians_to_degrees(longitude));
466
467 if(nextresult)
468 {
469 if(!turn_str)
470 {
471 turn_int=turn_angle(nodes,resultsegment,nextresultsegment,result->node);
472 turn_str=translate_turn[(4+(22+turn_int)/45)%8];
473 }
474
475 if(!bearing_next_str)
476 {
477 bearing_next_int=bearing_angle(nodes,nextresultsegment,nextresult->node);
478 bearing_next_str=translate_heading[(4+(22+bearing_next_int)/45)%8];
479 }
480
481 fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_node[0]);
482 fprintf(htmlfile,translate_html_node[1],
483 type,
484 turn_str,
485 bearing_next_str);
486 fprintf(htmlfile,"\n");
487 }
488 else
489 {
490 fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_stop[0]);
491 fprintf(htmlfile,translate_html_stop[1],
492 translate_html_waypoint);
493 fprintf(htmlfile,"\n");
494 fprintf(htmlfile,"<tr class='t'><td class='l'>%s:<td class='r'><span class='j'>",translate_html_total[0]);
495 fprintf(htmlfile,translate_html_total[1],
496 distance_to_km(cum_distance),duration_to_minutes(cum_duration));
497 fprintf(htmlfile,"</span>\n");
498 }
499 }
500
501 if(gpxroutefile)
502 {
503 if(!waynameraw)
504 {
505 waynameraw=WayNameRaw(ways,resultway);
506 if(!*waynameraw)
507 waynameraw=translate_highway[HIGHWAY(resultway->type)];
508 }
509
510 if(!waynamexml)
511 waynamexml=ParseXML_Encode_Safe_XML(waynameraw);
512
513 if(!bearing_str)
514 {
515 bearing_int=bearing_angle(nodes,resultsegment,result->node);
516 bearing_str=translate_heading[(4+(22+bearing_int)/45)%8];
517 }
518
519 fprintf(gpxroutefile,"<desc>");
520 fprintf(gpxroutefile,translate_gpx_step,
521 bearing_str,
522 waynamexml,
523 distance_to_km(junc_distance),duration_to_minutes(junc_duration));
524 fprintf(gpxroutefile,"</desc></rtept>\n");
525
526 if(!nextresult)
527 {
528 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s</name>\n",
529 radians_to_degrees(finish_lat),radians_to_degrees(finish_lon),
530 translate_gpx_finish);
531 fprintf(gpxroutefile,"<desc>");
532 fprintf(gpxroutefile,translate_gpx_final,
533 distance_to_km(cum_distance),duration_to_minutes(cum_duration));
534 fprintf(gpxroutefile,"</desc></rtept>\n");
535 }
536 else if(important==10)
537 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%d</name>\n",
538 radians_to_degrees(latitude),radians_to_degrees(longitude),
539 translate_gpx_inter,++segment_count);
540 else
541 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%03d</name>\n",
542 radians_to_degrees(latitude),radians_to_degrees(longitude),
543 translate_gpx_trip,++route_count);
544 }
545
546 if(textfile)
547 {
548 char *type;
549
550 if(important==10)
551 type="Waypt";
552 else
553 type="Junct";
554
555 if(!wayname)
556 wayname=(char*)WayNameHighway(ways,resultway);
557
558 if(nextresult)
559 {
560 if(!turn_str)
561 {
562 turn_int=turn_angle(nodes,resultsegment,nextresultsegment,result->node);
563 turn_str=translate_turn[(4+(22+turn_int)/45)%8];
564 }
565
566 if(!bearing_next_str)
567 {
568 bearing_next_int=bearing_angle(nodes,nextresultsegment,nextresult->node);
569 bearing_next_str=translate_heading[(4+(22+bearing_next_int)/45)%8];
570 }
571
572 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",
573 radians_to_degrees(latitude),radians_to_degrees(longitude),
574 distance_to_km(junc_distance),duration_to_minutes(junc_duration),
575 distance_to_km(cum_distance),duration_to_minutes(cum_duration),
576 type,
577 (22+turn_int)/45,
578 ((22+bearing_next_int)/45+4)%8-4,
579 wayname);
580 }
581 else
582 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",
583 radians_to_degrees(latitude),radians_to_degrees(longitude),
584 distance_to_km(junc_distance),duration_to_minutes(junc_duration),
585 distance_to_km(cum_distance),duration_to_minutes(cum_duration),
586 type,
587 wayname);
588 }
589
590 junc_distance=0;
591 junc_duration=0;
592 }
593
594 /* Print out all of the results */
595
596 if(textallfile)
597 {
598 char *type;
599
600 if(important==10)
601 type="Waypt";
602 else if(important==2)
603 type="Change";
604 else if(important>=1)
605 type="Junct";
606 else
607 type="Inter";
608
609 if(!wayname)
610 wayname=(char*)WayNameHighway(ways,resultway);
611
612 if(!bearing_str)
613 {
614 bearing_int=bearing_angle(nodes,resultsegment,result->node);
615 bearing_str=translate_heading[(4+(22+bearing_int)/45)%8];
616 }
617
618 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",
619 radians_to_degrees(latitude),radians_to_degrees(longitude),
620 IsFakeNode(result->node)?(NODE_FAKE-result->node):result->node,
621 (!IsFakeNode(result->node) && IsSuperNode(nodes,result->node))?'*':' ',type,
622 distance_to_km(seg_distance),duration_to_minutes(seg_duration),
623 distance_to_km(cum_distance),duration_to_minutes(cum_duration),
624 profile->speed[HIGHWAY(resultway->type)],
625 bearing_int,
626 wayname);
627 }
628
629 if(waynamexml && waynamexml!=waynameraw)
630 free(waynamexml);
631 }
632 else if(!cum_distance)
633 {
634 int bearing_next_int=bearing_angle(nodes,nextresultsegment,nextresult->node);
635 char *bearing_next_str=translate_heading[(4+(22+bearing_next_int)/45)%8];
636
637 /* Print out the very first start point */
638
639 if(htmlfile)
640 {
641 fprintf(htmlfile,"<tr class='c'><td class='l'><td class='r'>%.6f %.6f\n",
642 radians_to_degrees(latitude),radians_to_degrees(longitude));
643 fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_start[0]);
644 fprintf(htmlfile,translate_html_start[1],
645 translate_html_waypoint,
646 bearing_next_str);
647 fprintf(htmlfile,"\n");
648 }
649
650 if(gpxroutefile)
651 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s</name>\n",
652 radians_to_degrees(latitude),radians_to_degrees(longitude),
653 translate_gpx_start);
654
655 if(textfile)
656 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",
657 radians_to_degrees(latitude),radians_to_degrees(longitude),
658 0.0,0.0,0.0,0.0,
659 "Waypt",
660 (22+bearing_next_int)/45);
661
662 if(textallfile)
663 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",
664 radians_to_degrees(latitude),radians_to_degrees(longitude),
665 IsFakeNode(result->node)?(NODE_FAKE-result->node):result->node,
666 (!IsFakeNode(result->node) && IsSuperNode(nodes,result->node))?'*':' ',"Waypt",
667 0.0,0.0,0.0,0.0);
668 }
669
670 result=nextresult;
671 }
672 while(point==nextpoint);
673
674 if(gpxtrackfile)
675 fprintf(gpxtrackfile,"</trkseg>\n");
676
677 point=nextpoint;
678 }
679
680 /* Print the tail of the files */
681
682 if(htmlfile)
683 {
684 fprintf(htmlfile,"</table>\n");
685
686 if((translate_copyright_creator[0] && translate_copyright_creator[1]) ||
687 (translate_copyright_source[0] && translate_copyright_source[1]) ||
688 (translate_copyright_license[0] && translate_copyright_license[1]))
689 {
690 fprintf(htmlfile,"<p>\n");
691 fprintf(htmlfile,"<table class='c'>\n");
692 if(translate_copyright_creator[0] && translate_copyright_creator[1])
693 fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_copyright_creator[0],translate_copyright_creator[1]);
694 if(translate_copyright_source[0] && translate_copyright_source[1])
695 fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_copyright_source[0],translate_copyright_source[1]);
696 if(translate_copyright_license[0] && translate_copyright_license[1])
697 fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_copyright_license[0],translate_copyright_license[1]);
698 fprintf(htmlfile,"</table>\n");
699 }
700
701 fprintf(htmlfile,"</BODY>\n");
702 fprintf(htmlfile,"</HTML>\n");
703 }
704
705 if(gpxtrackfile)
706 {
707 fprintf(gpxtrackfile,"</trk>\n");
708 fprintf(gpxtrackfile,"</gpx>\n");
709 }
710
711 if(gpxroutefile)
712 {
713 fprintf(gpxroutefile,"</rte>\n");
714 fprintf(gpxroutefile,"</gpx>\n");
715 }
716
717 /* Close the files */
718
719 if(htmlfile)
720 fclose(htmlfile);
721 if(gpxtrackfile)
722 fclose(gpxtrackfile);
723 if(gpxroutefile)
724 fclose(gpxroutefile);
725 if(textfile)
726 fclose(textfile);
727 if(textallfile)
728 fclose(textallfile);
729 }
730
731
732 /*++++++++++++++++++++++++++++++++++++++
733 Calculate the angle to turn at a junction from segment1 to segment2 at node.
734
735 int turn_angle Returns a value in the range -4 to +4 indicating the angle to turn.
736
737 Nodes *nodes The set of nodes.
738
739 Segment *segment1 The current segment.
740
741 Segment *segment2 The next segment.
742
743 index_t node The node at which they join.
744
745 Straight ahead is zero, turning to the right is positive (90 degrees) and turning to the left is negative.
746 Angles are calculated using flat Cartesian lat/long grid approximation (after scaling longitude due to latitude).
747 ++++++++++++++++++++++++++++++++++++++*/
748
749 static int turn_angle(Nodes *nodes,Segment *segment1,Segment *segment2,index_t node)
750 {
751 double lat1,latm,lat2;
752 double lon1,lonm,lon2;
753 double angle1,angle2,angle;
754 index_t node1,node2;
755
756 node1=OtherNode(segment1,node);
757 node2=OtherNode(segment2,node);
758
759 if(IsFakeNode(node1))
760 GetFakeLatLong(node1,&lat1,&lon1);
761 else
762 GetLatLong(nodes,node1,&lat1,&lon1);
763
764 if(IsFakeNode(node))
765 GetFakeLatLong(node,&latm,&lonm);
766 else
767 GetLatLong(nodes,node,&latm,&lonm);
768
769 if(IsFakeNode(node2))
770 GetFakeLatLong(node2,&lat2,&lon2);
771 else
772 GetLatLong(nodes,node2,&lat2,&lon2);
773
774 angle1=atan2((lonm-lon1)*cos(latm),(latm-lat1));
775 angle2=atan2((lon2-lonm)*cos(latm),(lat2-latm));
776
777 angle=angle2-angle1;
778
779 angle=radians_to_degrees(angle);
780
781 angle=round(angle);
782
783 if(angle<-180) angle+=360;
784 if(angle> 180) angle-=360;
785
786 return((int)angle);
787 }
788
789
790 /*++++++++++++++++++++++++++++++++++++++
791 Calculate the bearing of a segment from the given node.
792
793 int bearing_angle Returns a value in the range 0 to 359 indicating the bearing.
794
795 Nodes *nodes The set of nodes.
796
797 Segment *segment The segment.
798
799 index_t node The node to start.
800
801 Angles are calculated using flat Cartesian lat/long grid approximation (after scaling longitude due to latitude).
802 ++++++++++++++++++++++++++++++++++++++*/
803
804 static int bearing_angle(Nodes *nodes,Segment *segment,index_t node)
805 {
806 double lat1,lat2;
807 double lon1,lon2;
808 double angle;
809 index_t node1,node2;
810
811 node1=node;
812 node2=OtherNode(segment,node);
813
814 if(IsFakeNode(node1))
815 GetFakeLatLong(node1,&lat1,&lon1);
816 else
817 GetLatLong(nodes,node1,&lat1,&lon1);
818
819 if(IsFakeNode(node2))
820 GetFakeLatLong(node2,&lat2,&lon2);
821 else
822 GetLatLong(nodes,node2,&lat2,&lon2);
823
824 angle=atan2((lat2-lat1),(lon2-lon1)*cos(lat1));
825
826 angle=radians_to_degrees(angle);
827
828 angle=round(270-angle);
829
830 if(angle< 0) angle+=360;
831 if(angle>360) angle-=360;
832
833 return((int)angle);
834 }

Properties

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