Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /branches/MS-Windows/src/output.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1696 - (show annotations) (download) (as text)
Sat May 30 17:21:45 2015 UTC (9 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 38999 byte(s)
Open files in binary mode for MSVC and MinGW.

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

Properties

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