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 1680 - (show annotations) (download) (as text)
Tue May 26 17:28:56 2015 UTC (9 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 38816 byte(s)
Merge branch 'MSVC' back into the trunk.

1 /***************************************
2 Routing output generator.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2008-2015 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
30 #include "types.h"
31 #include "nodes.h"
32 #include "segments.h"
33 #include "ways.h"
34
35 #include "functions.h"
36 #include "fakes.h"
37 #include "translations.h"
38 #include "results.h"
39 #include "xmlparse.h"
40
41
42 #define DEBUG 0
43
44 /* Constants */
45
46 #define IMP_IGNORE -1 /*+ Ignore this point. +*/
47 #define IMP_UNIMPORTANT 0 /*+ An unimportant, intermediate, node. +*/
48 #define IMP_RB_NOT_EXIT 1 /*+ A roundabout exit that is not taken. +*/
49 #define IMP_JUNCT_CONT 2 /*+ An un-interesting junction where the route continues without comment. +*/
50 #define IMP_CHANGE 3 /*+ The highway changes type but nothing else happens. +*/
51 #define IMP_JUNCT_IMPORT 4 /*+ An interesting junction to be described. +*/
52 #define IMP_RB_ENTRY 5 /*+ The entrance to a roundabout. +*/
53 #define IMP_RB_EXIT 6 /*+ The exit from a roundabout. +*/
54 #define IMP_MINI_RB 7 /*+ The location of a mini-roundabout. +*/
55 #define IMP_UTURN 8 /*+ The location of a U-turn. +*/
56 #define IMP_WAYPOINT 9 /*+ A waypoint. +*/
57
58
59 /* Global variables */
60
61 /*+ The option to calculate the quickest route insted of the shortest. +*/
62 extern int option_quickest;
63
64 /*+ The options to select the format of the output. +*/
65 extern int option_html,option_gpx_track,option_gpx_route,option_text,option_text_all,option_stdout;
66
67
68 /* Local variables */
69
70 /*+ Heuristics for determining if a junction is important. +*/
71 static const char junction_other_way[Highway_Count][Highway_Count]=
72 { /* M, T, P, S, T, U, R, S, T, C, P, S, F = Way type of route not taken */
73 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Motorway */
74 { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Trunk */
75 { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Primary */
76 { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Secondary */
77 { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Tertiary */
78 { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1 }, /* Unclassified */
79 { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1 }, /* Residential */
80 { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1 }, /* Service */
81 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1 }, /* Track */
82 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1 }, /* Cycleway */
83 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Path */
84 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Steps */
85 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Ferry */
86 };
87
88
89 /*++++++++++++++++++++++++++++++++++++++
90 Print the optimum route between two nodes.
91
92 Results **results The set of results to print (consecutive in array even if not consecutive waypoints).
93
94 int nresults The number of results in the list.
95
96 Nodes *nodes The set of nodes to use.
97
98 Segments *segments The set of segments to use.
99
100 Ways *ways The set of ways to use.
101
102 Profile *profile The profile containing the transport type, speeds and allowed highways.
103 ++++++++++++++++++++++++++++++++++++++*/
104
105 void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,Ways *ways,Profile *profile)
106 {
107 FILE *htmlfile=NULL,*gpxtrackfile=NULL,*gpxroutefile=NULL,*textfile=NULL,*textallfile=NULL;
108
109 char *prev_bearing=NULL,*prev_wayname=NULL;
110 index_t prev_node=NO_NODE;
111 distance_t cum_distance=0;
112 duration_t cum_duration=0;
113
114 int point=0;
115 int segment_count=0,route_count=0;
116 int point_count=0;
117 int roundabout=0;
118
119 /* Open the files */
120
121 if(option_stdout)
122 {
123 if(option_html)
124 htmlfile =stdout;
125 if(option_gpx_track)
126 gpxtrackfile=stdout;
127 if(option_gpx_route)
128 gpxroutefile=stdout;
129 if(option_text)
130 textfile =stdout;
131 if(option_text_all)
132 textallfile =stdout;
133 }
134 else
135 {
136 if(option_quickest==0)
137 {
138 /* Print the result for the shortest route */
139
140 if(option_html)
141 htmlfile =fopen("shortest.html","w");
142 if(option_gpx_track)
143 gpxtrackfile=fopen("shortest-track.gpx","w");
144 if(option_gpx_route)
145 gpxroutefile=fopen("shortest-route.gpx","w");
146 if(option_text)
147 textfile =fopen("shortest.txt","w");
148 if(option_text_all)
149 textallfile =fopen("shortest-all.txt","w");
150
151 if(option_html && !htmlfile)
152 fprintf(stderr,"Warning: Cannot open file 'shortest.html' for writing [%s].\n",strerror(errno));
153 if(option_gpx_track && !gpxtrackfile)
154 fprintf(stderr,"Warning: Cannot open file 'shortest-track.gpx' for writing [%s].\n",strerror(errno));
155 if(option_gpx_route && !gpxroutefile)
156 fprintf(stderr,"Warning: Cannot open file 'shortest-route.gpx' for writing [%s].\n",strerror(errno));
157 if(option_text && !textfile)
158 fprintf(stderr,"Warning: Cannot open file 'shortest.txt' for writing [%s].\n",strerror(errno));
159 if(option_text_all && !textallfile)
160 fprintf(stderr,"Warning: Cannot open file 'shortest-all.txt' for writing [%s].\n",strerror(errno));
161 }
162 else
163 {
164 /* Print the result for the quickest route */
165
166 if(option_html)
167 htmlfile =fopen("quickest.html","w");
168 if(option_gpx_track)
169 gpxtrackfile=fopen("quickest-track.gpx","w");
170 if(option_gpx_route)
171 gpxroutefile=fopen("quickest-route.gpx","w");
172 if(option_text)
173 textfile =fopen("quickest.txt","w");
174 if(option_text_all)
175 textallfile =fopen("quickest-all.txt","w");
176
177 if(option_html && !htmlfile)
178 fprintf(stderr,"Warning: Cannot open file 'quickest.html' for writing [%s].\n",strerror(errno));
179 if(option_gpx_track && !gpxtrackfile)
180 fprintf(stderr,"Warning: Cannot open file 'quickest-track.gpx' for writing [%s].\n",strerror(errno));
181 if(option_gpx_route && !gpxroutefile)
182 fprintf(stderr,"Warning: Cannot open file 'quickest-route.gpx' for writing [%s].\n",strerror(errno));
183 if(option_text && !textfile)
184 fprintf(stderr,"Warning: Cannot open file 'quickest.txt' for writing [%s].\n",strerror(errno));
185 if(option_text_all && !textallfile)
186 fprintf(stderr,"Warning: Cannot open file 'quickest-all.txt' for writing [%s].\n",strerror(errno));
187 }
188 }
189
190 /* Print the head of the files */
191
192 if(htmlfile)
193 {
194 fprintf(htmlfile,"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n");
195 fprintf(htmlfile,"<html>\n");
196 if(translate_xml_copyright_creator[0] && translate_xml_copyright_creator[1])
197 fprintf(htmlfile,"<!-- %s : %s -->\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]);
198 if(translate_xml_copyright_source[0] && translate_xml_copyright_source[1])
199 fprintf(htmlfile,"<!-- %s : %s -->\n",translate_xml_copyright_source[0],translate_xml_copyright_source[1]);
200 if(translate_xml_copyright_license[0] && translate_xml_copyright_license[1])
201 fprintf(htmlfile,"<!-- %s : %s -->\n",translate_xml_copyright_license[0],translate_xml_copyright_license[1]);
202 fprintf(htmlfile,"<head>\n");
203 fprintf(htmlfile,"<title>");
204 fprintf(htmlfile,translate_html_title,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest);
205 fprintf(htmlfile,"</title>\n");
206 fprintf(htmlfile,"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
207 fprintf(htmlfile,"<style type=\"text/css\">\n");
208 fprintf(htmlfile,"<!--\n");
209 fprintf(htmlfile," table {table-layout: fixed; border: none; border-collapse: collapse;}\n");
210 fprintf(htmlfile," table.c {color: grey; font-size: x-small;} /* copyright */\n");
211 fprintf(htmlfile," tr {border: 0px;}\n");
212 fprintf(htmlfile," tr.c {display: none;} /* coords */\n");
213 fprintf(htmlfile," tr.n {} /* node */\n");
214 fprintf(htmlfile," tr.s {} /* segment */\n");
215 fprintf(htmlfile," tr.t {font-weight: bold;} /* total */\n");
216 fprintf(htmlfile," td.l {font-weight: bold;}\n");
217 fprintf(htmlfile," td.r {}\n");
218 fprintf(htmlfile," span.w {font-weight: bold;} /* waypoint */\n");
219 fprintf(htmlfile," span.h {text-decoration: underline;} /* highway */\n");
220 fprintf(htmlfile," span.d {} /* segment distance */\n");
221 fprintf(htmlfile," span.j {font-style: italic;} /* total journey distance */\n");
222 fprintf(htmlfile," span.t {font-variant: small-caps;} /* turn */\n");
223 fprintf(htmlfile," span.b {font-variant: small-caps;} /* bearing */\n");
224 fprintf(htmlfile,"-->\n");
225 fprintf(htmlfile,"</style>\n");
226 fprintf(htmlfile,"</head>\n");
227 fprintf(htmlfile,"<body>\n");
228 fprintf(htmlfile,"<h1>");
229 fprintf(htmlfile,translate_html_title,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest);
230 fprintf(htmlfile,"</h1>\n");
231 fprintf(htmlfile,"<table>\n");
232 }
233
234 if(gpxtrackfile)
235 {
236 fprintf(gpxtrackfile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
237 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");
238
239 fprintf(gpxtrackfile,"<metadata>\n");
240 fprintf(gpxtrackfile,"<desc>%s : %s</desc>\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]);
241 if(translate_xml_copyright_source[1])
242 {
243 fprintf(gpxtrackfile,"<copyright author=\"%s\">\n",translate_xml_copyright_source[1]);
244
245 if(translate_xml_copyright_license[1])
246 fprintf(gpxtrackfile,"<license>%s</license>\n",translate_xml_copyright_license[1]);
247
248 fprintf(gpxtrackfile,"</copyright>\n");
249 }
250 fprintf(gpxtrackfile,"</metadata>\n");
251
252 fprintf(gpxtrackfile,"<trk>\n");
253 fprintf(gpxtrackfile,"<name>");
254 fprintf(gpxtrackfile,translate_gpx_name,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest);
255 fprintf(gpxtrackfile,"</name>\n");
256 fprintf(gpxtrackfile,"<desc>");
257 fprintf(gpxtrackfile,translate_gpx_desc,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest);
258 fprintf(gpxtrackfile,"</desc>\n");
259 }
260
261 if(gpxroutefile)
262 {
263 fprintf(gpxroutefile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
264 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");
265
266 fprintf(gpxroutefile,"<metadata>\n");
267 fprintf(gpxroutefile,"<desc>%s : %s</desc>\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]);
268 if(translate_xml_copyright_source[1])
269 {
270 fprintf(gpxroutefile,"<copyright author=\"%s\">\n",translate_xml_copyright_source[1]);
271
272 if(translate_xml_copyright_license[1])
273 fprintf(gpxroutefile,"<license>%s</license>\n",translate_xml_copyright_license[1]);
274
275 fprintf(gpxroutefile,"</copyright>\n");
276 }
277 fprintf(gpxroutefile,"</metadata>\n");
278
279 fprintf(gpxroutefile,"<rte>\n");
280 fprintf(gpxroutefile,"<name>");
281 fprintf(gpxroutefile,translate_gpx_name,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest);
282 fprintf(gpxroutefile,"</name>\n");
283 fprintf(gpxroutefile,"<desc>");
284 fprintf(gpxroutefile,translate_gpx_desc,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest);
285 fprintf(gpxroutefile,"</desc>\n");
286 }
287
288 if(textfile)
289 {
290 if(translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1])
291 fprintf(textfile,"# %s : %s\n",translate_raw_copyright_creator[0],translate_raw_copyright_creator[1]);
292 if(translate_raw_copyright_source[0] && translate_raw_copyright_source[1])
293 fprintf(textfile,"# %s : %s\n",translate_raw_copyright_source[0],translate_raw_copyright_source[1]);
294 if(translate_raw_copyright_license[0] && translate_raw_copyright_license[1])
295 fprintf(textfile,"# %s : %s\n",translate_raw_copyright_license[0],translate_raw_copyright_license[1]);
296 if((translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1]) ||
297 (translate_raw_copyright_source[0] && translate_raw_copyright_source[1]) ||
298 (translate_raw_copyright_license[0] && translate_raw_copyright_license[1]))
299 fprintf(textfile,"#\n");
300
301 fprintf(textfile,"#Latitude\tLongitude\tSection \tSection \tTotal \tTotal \tPoint\tTurn\tBearing\tHighway\n");
302 fprintf(textfile,"# \t \tDistance\tDuration\tDistance\tDuration\tType \t \t \t \n");
303 /* "%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" */
304 }
305
306 if(textallfile)
307 {
308 if(translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1])
309 fprintf(textallfile,"# %s : %s\n",translate_raw_copyright_creator[0],translate_raw_copyright_creator[1]);
310 if(translate_raw_copyright_source[0] && translate_raw_copyright_source[1])
311 fprintf(textallfile,"# %s : %s\n",translate_raw_copyright_source[0],translate_raw_copyright_source[1]);
312 if(translate_raw_copyright_license[0] && translate_raw_copyright_license[1])
313 fprintf(textallfile,"# %s : %s\n",translate_raw_copyright_license[0],translate_raw_copyright_license[1]);
314 if((translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1]) ||
315 (translate_raw_copyright_source[0] && translate_raw_copyright_source[1]) ||
316 (translate_raw_copyright_license[0] && translate_raw_copyright_license[1]))
317 fprintf(textallfile,"#\n");
318
319 fprintf(textallfile,"#Latitude\tLongitude\t Node\tType\tSegment\tSegment\tTotal\tTotal \tSpeed\tBearing\tHighway\n");
320 fprintf(textallfile,"# \t \t \t \tDist \tDurat'n\tDist \tDurat'n\t \t \t \n");
321 /* "%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" */
322 }
323
324 /* Loop through all the sections of the route and print them */
325
326 do
327 {
328 int first=1;
329 int next_point=point;
330 distance_t junc_distance=0;
331 duration_t junc_duration=0;
332 Result *result;
333
334 #if DEBUG
335 printf("Route section %d - waypoint %d to waypoint %d\n",point,results[point]->start_waypoint,results[point]->finish_waypoint);
336 printf(" start_node=%"Pindex_t" prev_segment=%"Pindex_t"\n",results[point]->start_node,results[point]->prev_segment);
337 printf(" finish_node=%"Pindex_t" last_segment=%"Pindex_t"\n",results[point]->finish_node,results[point]->last_segment);
338
339 Result *r=FindResult(results[point],results[point]->start_node,results[point]->prev_segment);
340
341 while(r)
342 {
343 printf(" node=%"Pindex_t" segment=%"Pindex_t" score=%f\n",r->node,r->segment,r->score);
344
345 r=r->next;
346 }
347 #endif
348
349 result=FindResult(results[point],results[point]->start_node,results[point]->prev_segment);
350
351 /* Print the start of the segment */
352
353 if(gpxtrackfile)
354 fprintf(gpxtrackfile,"<trkseg>\n");
355
356 /* Loop through all the points within a section of the route and print them */
357
358 do
359 {
360 double latitude,longitude;
361 Node *resultnodep=NULL;
362 index_t realsegment=NO_SEGMENT,next_realsegment=NO_SEGMENT;
363 Segment *resultsegmentp=NULL,*next_resultsegmentp=NULL;
364 Way *resultwayp=NULL,*next_resultwayp=NULL;
365 Result *next_result;
366 int important=IMP_UNIMPORTANT;
367
368 distance_t seg_distance=0;
369 duration_t seg_duration=0;
370 speed_t seg_speed=0;
371 char *waynameraw=NULL,*wayname=NULL,*next_waynameraw=NULL,*next_wayname=NULL;
372 int bearing_int=0,turn_int=0,next_bearing_int=0;
373 char *turn=NULL,*next_bearing=NULL;
374
375 /* Calculate the information about this point */
376
377 if(IsFakeNode(result->node))
378 GetFakeLatLong(result->node,&latitude,&longitude);
379 else
380 {
381 resultnodep=LookupNode(nodes,result->node,6);
382
383 GetLatLong(nodes,result->node,resultnodep,&latitude,&longitude);
384 }
385
386 /* Calculate the next result */
387
388 next_result=result->next;
389
390 if(!next_result)
391 {
392 next_point++;
393
394 if(next_point<nresults)
395 {
396 next_result=FindResult(results[next_point],results[next_point]->start_node,results[next_point]->prev_segment);
397 next_result=next_result->next;
398 }
399 }
400
401 /* Calculate the information about this segment */
402
403 if(!first) /* not first point of a section of the route */
404 {
405 if(IsFakeSegment(result->segment))
406 {
407 resultsegmentp=LookupFakeSegment(result->segment);
408 realsegment=IndexRealSegment(result->segment);
409 }
410 else
411 {
412 resultsegmentp=LookupSegment(segments,result->segment,2);
413 realsegment=result->segment;
414 }
415
416 resultwayp=LookupWay(ways,resultsegmentp->way,1);
417
418 seg_distance+=DISTANCE(resultsegmentp->distance);
419 seg_duration+=Duration(resultsegmentp,resultwayp,profile);
420
421 /* Calculate the cumulative distance/duration */
422
423 junc_distance+=seg_distance;
424 junc_duration+=seg_duration;
425 cum_distance+=seg_distance;
426 cum_duration+=seg_duration;
427 }
428
429 /* Calculate the information about the next segment */
430
431 if(next_result)
432 {
433 if(IsFakeSegment(next_result->segment))
434 {
435 next_resultsegmentp=LookupFakeSegment(next_result->segment);
436 next_realsegment=IndexRealSegment(next_result->segment);
437 }
438 else
439 {
440 next_resultsegmentp=LookupSegment(segments,next_result->segment,1);
441 next_realsegment=next_result->segment;
442 }
443 }
444
445 /* Decide if this is a roundabout */
446
447 if(next_result)
448 {
449 next_resultwayp=LookupWay(ways,next_resultsegmentp->way,2);
450
451 if(next_resultwayp->type&Highway_Roundabout)
452 {
453 if(roundabout==0)
454 {
455 roundabout++;
456 important=IMP_RB_ENTRY;
457 }
458 else
459 {
460 Segment *segmentp;
461
462 if(resultnodep)
463 segmentp=FirstSegment(segments,resultnodep,3);
464 else
465 segmentp=FirstFakeSegment(result->node);
466
467 do
468 {
469 index_t othernode=OtherNode(segmentp,result->node);
470 index_t thissegment;
471
472 if(IsFakeNode(result->node))
473 thissegment=IndexFakeSegment(segmentp);
474 else
475 thissegment=IndexSegment(segments,segmentp);
476
477 if(othernode!=prev_node && othernode!=next_result->node &&
478 thissegment!=realsegment && IsNormalSegment(segmentp))
479 {
480 int canexit=1;
481
482 if(profile->oneway && IsOnewayTo(segmentp,result->node))
483 {
484 if(profile->allow!=Transports_Bicycle)
485 canexit=0;
486 else
487 {
488 Way *wayp=LookupWay(ways,segmentp->way,3);
489
490 if(!(wayp->type&Highway_CycleBothWays))
491 canexit=0;
492 }
493 }
494
495 if(canexit)
496 {
497 Way *wayp=LookupWay(ways,segmentp->way,3);
498
499 if(!(wayp->type&Highway_Roundabout))
500 {
501 roundabout++;
502 important=IMP_RB_NOT_EXIT;
503 }
504 }
505 }
506
507 if(resultnodep)
508 segmentp=NextSegment(segments,segmentp,result->node);
509 else
510 segmentp=NextFakeSegment(segmentp,result->node);
511 }
512 while(segmentp);
513 }
514 }
515 else
516 if(roundabout)
517 {
518 roundabout++;
519 important=IMP_RB_EXIT;
520 }
521 }
522
523 /* Decide if this is an important junction */
524
525 if(point_count==0) /* first point overall = Waypoint */
526 important=IMP_WAYPOINT;
527 else if(result->next==NULL) /* Waypoint */
528 important=IMP_WAYPOINT;
529 else if(first) /* first point of a section of the route */
530 important=IMP_IGNORE;
531 else if(roundabout) /* roundabout */
532 ;
533 else if(realsegment==next_realsegment) /* U-turn */
534 important=IMP_UTURN;
535 else if(resultnodep && (resultnodep->flags&NODE_MINIRNDBT))
536 important=IMP_MINI_RB; /* mini-roundabout */
537 else
538 {
539 Segment *segmentp=FirstSegment(segments,resultnodep,3);
540
541 do
542 {
543 index_t seg=IndexSegment(segments,segmentp);
544
545 if(seg!=realsegment && IsNormalSegment(segmentp))
546 {
547 int cango=1;
548
549 if(profile->oneway && IsOnewayTo(segmentp,result->node))
550 {
551 if(profile->allow!=Transports_Bicycle)
552 cango=0;
553 else
554 {
555 Way *wayp=LookupWay(ways,segmentp->way,3);
556
557 if(!(wayp->type&Highway_CycleBothWays))
558 cango=0;
559 }
560 }
561
562 if(cango)
563 {
564 Way *wayp=LookupWay(ways,segmentp->way,3);
565
566 if(seg==next_realsegment) /* the next segment that we follow */
567 {
568 if(HIGHWAY(wayp->type)!=HIGHWAY(resultwayp->type))
569 if(important<IMP_CHANGE)
570 important=IMP_CHANGE;
571 }
572 else /* a segment that we don't follow */
573 {
574 if(junction_other_way[HIGHWAY(resultwayp->type)-1][HIGHWAY(wayp->type)-1])
575 if(important<IMP_JUNCT_IMPORT)
576 important=IMP_JUNCT_IMPORT;
577
578 if(important<IMP_JUNCT_CONT)
579 important=IMP_JUNCT_CONT;
580 }
581 }
582 }
583
584 segmentp=NextSegment(segments,segmentp,result->node);
585 }
586 while(segmentp);
587 }
588
589 /* Calculate the strings to be used */
590
591 if(!first && textallfile)
592 {
593 waynameraw=WayName(ways,resultwayp);
594 if(!*waynameraw)
595 waynameraw=translate_raw_highway[HIGHWAY(resultwayp->type)];
596
597 bearing_int=(int)BearingAngle(nodes,resultsegmentp,result->node);
598
599 seg_speed=profile->speed[HIGHWAY(resultwayp->type)];
600 }
601
602 if(next_result && important>IMP_JUNCT_CONT)
603 {
604 if(!first && (htmlfile || textfile))
605 {
606 if(DISTANCE(resultsegmentp->distance)==0 || DISTANCE(next_resultsegmentp->distance)==0)
607 turn_int=0;
608 else
609 turn_int=(int)TurnAngle(nodes,resultsegmentp,next_resultsegmentp,result->node);
610
611 turn=translate_xml_turn[((202+turn_int)/45)%8];
612 }
613
614 if(gpxroutefile || htmlfile)
615 {
616 next_waynameraw=WayName(ways,next_resultwayp);
617 if(!*next_waynameraw)
618 next_waynameraw=translate_raw_highway[HIGHWAY(next_resultwayp->type)];
619
620 next_wayname=ParseXML_Encode_Safe_XML(next_waynameraw);
621 }
622
623 if(htmlfile || gpxroutefile || textfile)
624 {
625 if(!first && DISTANCE(next_resultsegmentp->distance)==0)
626 next_bearing_int=(int)BearingAngle(nodes,resultsegmentp,result->node);
627 else
628 next_bearing_int=(int)BearingAngle(nodes,next_resultsegmentp,next_result->node);
629
630 next_bearing=translate_xml_heading[(4+(22+next_bearing_int)/45)%8];
631 }
632 }
633
634 /* Print out the important points (junctions / waypoints) */
635
636 if(important>IMP_JUNCT_CONT)
637 {
638 if(htmlfile)
639 {
640 char *type;
641
642 if(important==IMP_WAYPOINT)
643 type=translate_html_waypoint;
644 else if(important==IMP_MINI_RB)
645 type=translate_html_roundabout;
646 else
647 type=translate_html_junction;
648
649 if(point_count>0) /* not the first point */
650 {
651 /* <tr class='s'><td class='l'>Follow:<td class='r'><span class='h'>*highway name*</span> for <span class='d'>*distance* km, *time* min</span> [<span class='j'>*distance* km, *time* minutes</span>] */
652 fprintf(htmlfile,"<tr class='s'><td class='l'>%s:<td class='r'>",translate_html_segment[0]);
653 fprintf(htmlfile,translate_html_segment[1],
654 (roundabout>1?translate_html_roundabout:prev_wayname),
655 distance_to_km(junc_distance),duration_to_minutes(junc_duration));
656 fprintf(htmlfile," [<span class='j'>");
657 fprintf(htmlfile,translate_html_total[1],
658 distance_to_km(cum_distance),duration_to_minutes(cum_duration));
659 fprintf(htmlfile,"</span>]\n");
660 }
661
662 /* <tr class='c'><td class='l'>*N*:<td class='r'>*latitude* *longitude* */
663 fprintf(htmlfile,"<tr class='c'><td class='l'>%d:<td class='r'>%.6f %.6f\n",
664 point_count+1,
665 radians_to_degrees(latitude),radians_to_degrees(longitude));
666
667 if(point_count==0) /* first point */
668 {
669 /* <tr class='n'><td class='l'>Start:<td class='r'>At <span class='w'>Waypoint</span>, head <span class='b'>*heading*</span> */
670 fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_start[0]);
671 fprintf(htmlfile,translate_html_start[1],
672 translate_html_waypoint,
673 next_bearing);
674 fprintf(htmlfile,"\n");
675 }
676 else if(next_result) /* middle point */
677 {
678 if(roundabout>1 && important!=IMP_WAYPOINT)
679 {
680 /* <tr class='n'><td class='l'>At:<td class='r'>Roundabout, take <span class='t'>the *Nth* exit</span> heading <span class='b'>*heading*</span> */
681 fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_rbnode[0]);
682 fprintf(htmlfile,translate_html_rbnode[1],
683 translate_html_roundabout,
684 translate_xml_ordinal[roundabout-2],
685 next_bearing);
686 fprintf(htmlfile,"\n");
687 }
688 else
689 {
690 /* <tr class='n'><td class='l'>At:<td class='r'>Junction, go <span class='t'>*direction*</span> heading <span class='b'>*heading*</span> */
691 fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_node[0]);
692 fprintf(htmlfile,translate_html_node[1],
693 type,
694 turn,
695 next_bearing);
696 fprintf(htmlfile,"\n");
697 }
698 }
699 else /* end point */
700 {
701 /* <tr class='n'><td class='l'>Stop:<td class='r'>At <span class='w'>Waypoint</span> */
702 fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_stop[0]);
703 fprintf(htmlfile,translate_html_stop[1],
704 translate_html_waypoint);
705 fprintf(htmlfile,"\n");
706
707 /* <tr class='t'><td class='l'>Total:<td class='r'><span class='j'>*distance* km, *time* minutes</span> */
708 fprintf(htmlfile,"<tr class='t'><td class='l'>%s:<td class='r'><span class='j'>",translate_html_total[0]);
709 fprintf(htmlfile,translate_html_total[1],
710 distance_to_km(cum_distance),duration_to_minutes(cum_duration));
711 fprintf(htmlfile,"</span>\n");
712 }
713 }
714
715 if(gpxroutefile)
716 {
717 if(point_count>0) /* not first point */
718 {
719 fprintf(gpxroutefile,"<desc>");
720 fprintf(gpxroutefile,translate_gpx_step,
721 prev_bearing,
722 prev_wayname,
723 distance_to_km(junc_distance),duration_to_minutes(junc_duration));
724 fprintf(gpxroutefile,"</desc></rtept>\n");
725 }
726
727 if(point_count==0) /* first point */
728 {
729 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s</name>\n",
730 radians_to_degrees(latitude),radians_to_degrees(longitude),
731 translate_gpx_start);
732 }
733 else if(!next_result) /* end point */
734 {
735 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s</name>\n",
736 radians_to_degrees(latitude),radians_to_degrees(longitude),
737 translate_gpx_finish);
738 fprintf(gpxroutefile,"<desc>");
739 fprintf(gpxroutefile,translate_gpx_final,
740 distance_to_km(cum_distance),duration_to_minutes(cum_duration));
741 fprintf(gpxroutefile,"</desc></rtept>\n");
742 }
743 else /* middle point */
744 {
745 if(important==IMP_WAYPOINT)
746 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%d</name>\n",
747 radians_to_degrees(latitude),radians_to_degrees(longitude),
748 translate_gpx_inter,++segment_count);
749 else
750 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%03d</name>\n",
751 radians_to_degrees(latitude),radians_to_degrees(longitude),
752 translate_gpx_trip,++route_count);
753 }
754 }
755
756 if(textfile)
757 {
758 char *type;
759
760 if(important==IMP_WAYPOINT)
761 type="Waypt";
762 else
763 type="Junct";
764
765 if(point_count==0) /* first point */
766 {
767 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%s\n",
768 radians_to_degrees(latitude),radians_to_degrees(longitude),
769 0.0,0.0,0.0,0.0,
770 type,
771 ((22+next_bearing_int)/45+4)%8-4,
772 next_waynameraw);
773 }
774 else if(!next_result) /* end point */
775 {
776 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\n",
777 radians_to_degrees(latitude),radians_to_degrees(longitude),
778 distance_to_km(junc_distance),duration_to_minutes(junc_duration),
779 distance_to_km(cum_distance),duration_to_minutes(cum_duration),
780 type);
781 }
782 else /* middle point */
783 {
784 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",
785 radians_to_degrees(latitude),radians_to_degrees(longitude),
786 distance_to_km(junc_distance),duration_to_minutes(junc_duration),
787 distance_to_km(cum_distance),duration_to_minutes(cum_duration),
788 type,
789 (22+turn_int)/45,
790 ((22+next_bearing_int)/45+4)%8-4,
791 next_waynameraw);
792 }
793 }
794
795 junc_distance=0;
796 junc_duration=0;
797
798 if(htmlfile || gpxroutefile)
799 {
800 if(prev_wayname)
801 free(prev_wayname);
802
803 if(next_wayname)
804 prev_wayname=strcpy((char*)malloc(strlen(next_wayname)+1),next_wayname);
805 else
806 prev_wayname=NULL;
807
808 if(next_wayname && next_wayname!=next_waynameraw)
809 free(next_wayname);
810 }
811
812 if(gpxroutefile)
813 prev_bearing=next_bearing;
814
815 if(roundabout>1)
816 roundabout=0;
817 }
818
819 /* Print out all of the results */
820
821 if(gpxtrackfile)
822 fprintf(gpxtrackfile,"<trkpt lat=\"%.6f\" lon=\"%.6f\"/>\n",
823 radians_to_degrees(latitude),radians_to_degrees(longitude));
824
825 if(important>IMP_IGNORE)
826 {
827 if(textallfile)
828 {
829 char *type;
830
831 if(important==IMP_WAYPOINT)
832 type="Waypt";
833 else if(important==IMP_UTURN)
834 type="U-turn";
835 else if(important==IMP_MINI_RB)
836 type="Mini-RB";
837 else if(important==IMP_CHANGE)
838 type="Change";
839 else if(important==IMP_JUNCT_CONT || important==IMP_RB_NOT_EXIT)
840 type="Junct-";
841 else if(important==IMP_UNIMPORTANT)
842 type="Inter";
843 else
844 type="Junct";
845
846 if(point_count==0) /* first point */
847 {
848 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",
849 radians_to_degrees(latitude),radians_to_degrees(longitude),
850 IsFakeNode(result->node)?(NODE_FAKE-result->node):result->node,
851 (resultnodep && IsSuperNode(resultnodep))?'*':' ',type,
852 0.0,0.0,0.0,0.0);
853 }
854 else /* not the first point */
855 {
856 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",
857 radians_to_degrees(latitude),radians_to_degrees(longitude),
858 IsFakeNode(result->node)?(NODE_FAKE-result->node):result->node,
859 (resultnodep && IsSuperNode(resultnodep))?'*':' ',type,
860 distance_to_km(seg_distance),duration_to_minutes(seg_duration),
861 distance_to_km(cum_distance),duration_to_minutes(cum_duration),
862 speed_to_kph(seg_speed),
863 bearing_int,
864 waynameraw);
865 }
866 }
867 }
868
869 if(wayname && wayname!=waynameraw)
870 free(wayname);
871
872 result=next_result;
873
874 if(important>IMP_JUNCT_CONT)
875 point_count++;
876
877 first=0;
878 }
879 while(point==next_point);
880
881 /* Print the end of the segment */
882
883 if(gpxtrackfile)
884 fprintf(gpxtrackfile,"</trkseg>\n");
885
886 point=next_point;
887
888 if(result)
889 prev_node=result->node;
890 else
891 prev_node=NO_NODE;
892 }
893 while(point<nresults);
894
895 /* Print the tail of the files */
896
897 if(htmlfile)
898 {
899 fprintf(htmlfile,"</table>\n");
900
901 if((translate_xml_copyright_creator[0] && translate_xml_copyright_creator[1]) ||
902 (translate_xml_copyright_source[0] && translate_xml_copyright_source[1]) ||
903 (translate_xml_copyright_license[0] && translate_xml_copyright_license[1]))
904 {
905 fprintf(htmlfile,"<p>\n");
906 fprintf(htmlfile,"<table class='c'>\n");
907 if(translate_xml_copyright_creator[0] && translate_xml_copyright_creator[1])
908 fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]);
909 if(translate_xml_copyright_source[0] && translate_xml_copyright_source[1])
910 fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_xml_copyright_source[0],translate_xml_copyright_source[1]);
911 if(translate_xml_copyright_license[0] && translate_xml_copyright_license[1])
912 fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_xml_copyright_license[0],translate_xml_copyright_license[1]);
913 fprintf(htmlfile,"</table>\n");
914 }
915
916 fprintf(htmlfile,"</body>\n");
917 fprintf(htmlfile,"</html>\n");
918 }
919
920 if(gpxtrackfile)
921 {
922 fprintf(gpxtrackfile,"</trk>\n");
923 fprintf(gpxtrackfile,"</gpx>\n");
924 }
925
926 if(gpxroutefile)
927 {
928 fprintf(gpxroutefile,"</rte>\n");
929 fprintf(gpxroutefile,"</gpx>\n");
930 }
931
932 /* Close the files */
933
934 if(!option_stdout)
935 {
936 if(htmlfile)
937 fclose(htmlfile);
938 if(gpxtrackfile)
939 fclose(gpxtrackfile);
940 if(gpxroutefile)
941 fclose(gpxroutefile);
942 if(textfile)
943 fclose(textfile);
944 if(textallfile)
945 fclose(textallfile);
946 }
947 }

Properties

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