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 1795 - (show annotations) (download) (as text)
Thu Sep 3 18:12:28 2015 UTC (9 years, 6 months ago) by amb
File MIME type: text/x-csrc
File size: 47003 byte(s)
Add in an HTML-all linked list formats that includes the full set of
points and the HTML directions for the important ones.

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 #include "routino.h"
42
43
44 /*+ To help when debugging +*/
45 #define DEBUG 0
46
47 /* Constants */
48
49 #define ROUTINO_POINT_IGNORE -1 /*+ Ignore this point. +*/
50
51
52 /* Global variables */
53
54 /*+ The option to calculate the quickest route insted of the shortest. +*/
55 int option_quickest=0;
56
57 /*+ The options to select the format of the file output. +*/
58 int option_file_html=0,option_file_gpx_track=0,option_file_gpx_route=0,option_file_text=0,option_file_text_all=0,option_file_stdout=0;
59
60 /*+ The options to select the format of the linked list output. +*/
61 int option_list_html=0,option_list_html_all=0,option_list_text=0,option_list_text_all=0;
62
63
64 /* Local variables */
65
66 /*+ Heuristics for determining if a junction is important. +*/
67 static const char junction_other_way[Highway_Count][Highway_Count]=
68 { /* M, T, P, S, T, U, R, S, T, C, P, S, F = Way type of route not taken */
69 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Motorway */
70 { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Trunk */
71 { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Primary */
72 { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Secondary */
73 { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Tertiary */
74 { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1 }, /* Unclassified */
75 { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1 }, /* Residential */
76 { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1 }, /* Service */
77 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1 }, /* Track */
78 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1 }, /* Cycleway */
79 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Path */
80 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Steps */
81 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Ferry */
82 };
83
84
85 /*++++++++++++++++++++++++++++++++++++++
86 Print the optimum route between two nodes.
87
88 Routino_Output *PrintRoute Returns a linked list of data structures representing the route if required.
89
90 Results **results The set of results to print (consecutive in array even if not consecutive waypoints).
91
92 int nresults The number of results in the list.
93
94 Nodes *nodes The set of nodes to use.
95
96 Segments *segments The set of segments to use.
97
98 Ways *ways The set of ways to use.
99
100 Profile *profile The profile containing the transport type, speeds and allowed highways.
101
102 Translation *translation The set of translated strings.
103 ++++++++++++++++++++++++++++++++++++++*/
104
105 Routino_Output *PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,Ways *ways,Profile *profile,Translation *translation)
106 {
107 FILE *htmlfile=NULL,*gpxtrackfile=NULL,*gpxroutefile=NULL,*textfile=NULL,*textallfile=NULL;
108 Routino_Output *listhead=NULL,*htmllist=NULL, *textlist=NULL,*textalllist=NULL,*htmlalllist=NULL;
109
110 char *prev_bearing=NULL,*prev_wayname=NULL,*prev_waynameraw=NULL;
111 index_t prev_node=NO_NODE;
112 distance_t cum_distance=0;
113 duration_t cum_duration=0;
114
115 int point=0;
116 int segment_count=0,route_count=0;
117 int point_count=0;
118 int roundabout=0;
119
120 /* Open the files */
121
122 if(option_file_stdout)
123 {
124 if(option_file_html)
125 htmlfile =stdout;
126 if(option_file_gpx_track)
127 gpxtrackfile=stdout;
128 if(option_file_gpx_route)
129 gpxroutefile=stdout;
130 if(option_file_text)
131 textfile =stdout;
132 if(option_file_text_all)
133 textallfile =stdout;
134 }
135 else
136 {
137 #if defined(_MSC_VER) || defined(__MINGW32__)
138 const char *open_mode="wb";
139 #else
140 const char *open_mode="w";
141 #endif
142
143 if(option_quickest==0)
144 {
145 /* Print the result for the shortest route */
146
147 if(option_file_html)
148 htmlfile =fopen("shortest.html",open_mode);
149 if(option_file_gpx_track)
150 gpxtrackfile=fopen("shortest-track.gpx",open_mode);
151 if(option_file_gpx_route)
152 gpxroutefile=fopen("shortest-route.gpx",open_mode);
153 if(option_file_text)
154 textfile =fopen("shortest.txt",open_mode);
155 if(option_file_text_all)
156 textallfile =fopen("shortest-all.txt",open_mode);
157
158 #ifndef LIBROUTINO
159 if(option_file_html && !htmlfile)
160 fprintf(stderr,"Warning: Cannot open file 'shortest.html' for writing [%s].\n",strerror(errno));
161 if(option_file_gpx_track && !gpxtrackfile)
162 fprintf(stderr,"Warning: Cannot open file 'shortest-track.gpx' for writing [%s].\n",strerror(errno));
163 if(option_file_gpx_route && !gpxroutefile)
164 fprintf(stderr,"Warning: Cannot open file 'shortest-route.gpx' for writing [%s].\n",strerror(errno));
165 if(option_file_text && !textfile)
166 fprintf(stderr,"Warning: Cannot open file 'shortest.txt' for writing [%s].\n",strerror(errno));
167 if(option_file_text_all && !textallfile)
168 fprintf(stderr,"Warning: Cannot open file 'shortest-all.txt' for writing [%s].\n",strerror(errno));
169 #endif
170 }
171 else
172 {
173 /* Print the result for the quickest route */
174
175 if(option_file_html)
176 htmlfile =fopen("quickest.html",open_mode);
177 if(option_file_gpx_track)
178 gpxtrackfile=fopen("quickest-track.gpx",open_mode);
179 if(option_file_gpx_route)
180 gpxroutefile=fopen("quickest-route.gpx",open_mode);
181 if(option_file_text)
182 textfile =fopen("quickest.txt",open_mode);
183 if(option_file_text_all)
184 textallfile =fopen("quickest-all.txt",open_mode);
185
186 #ifndef LIBROUTINO
187 if(option_file_html && !htmlfile)
188 fprintf(stderr,"Warning: Cannot open file 'quickest.html' for writing [%s].\n",strerror(errno));
189 if(option_file_gpx_track && !gpxtrackfile)
190 fprintf(stderr,"Warning: Cannot open file 'quickest-track.gpx' for writing [%s].\n",strerror(errno));
191 if(option_file_gpx_route && !gpxroutefile)
192 fprintf(stderr,"Warning: Cannot open file 'quickest-route.gpx' for writing [%s].\n",strerror(errno));
193 if(option_file_text && !textfile)
194 fprintf(stderr,"Warning: Cannot open file 'quickest.txt' for writing [%s].\n",strerror(errno));
195 if(option_file_text_all && !textallfile)
196 fprintf(stderr,"Warning: Cannot open file 'quickest-all.txt' for writing [%s].\n",strerror(errno));
197 #endif
198 }
199 }
200
201 /* Print the head of the files */
202
203 if(htmlfile)
204 {
205 fprintf(htmlfile,"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n");
206 fprintf(htmlfile,"<html>\n");
207 if(translation->xml_copyright_creator[0] && translation->xml_copyright_creator[1])
208 fprintf(htmlfile,"<!-- %s : %s -->\n",translation->xml_copyright_creator[0],translation->xml_copyright_creator[1]);
209 if(translation->xml_copyright_source[0] && translation->xml_copyright_source[1])
210 fprintf(htmlfile,"<!-- %s : %s -->\n",translation->xml_copyright_source[0],translation->xml_copyright_source[1]);
211 if(translation->xml_copyright_license[0] && translation->xml_copyright_license[1])
212 fprintf(htmlfile,"<!-- %s : %s -->\n",translation->xml_copyright_license[0],translation->xml_copyright_license[1]);
213 fprintf(htmlfile,"<head>\n");
214 fprintf(htmlfile,"<title>");
215 fprintf(htmlfile,translation->html_title,option_quickest?translation->xml_route_quickest:translation->xml_route_shortest);
216 fprintf(htmlfile,"</title>\n");
217 fprintf(htmlfile,"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
218 fprintf(htmlfile,"<style type=\"text/css\">\n");
219 fprintf(htmlfile,"<!--\n");
220 fprintf(htmlfile," table {table-layout: fixed; border: none; border-collapse: collapse;}\n");
221 fprintf(htmlfile," table.c {color: grey; font-size: x-small;} /* copyright */\n");
222 fprintf(htmlfile," tr {border: 0px;}\n");
223 fprintf(htmlfile," tr.c {display: none;} /* coords */\n");
224 fprintf(htmlfile," tr.n {} /* node */\n");
225 fprintf(htmlfile," tr.s {} /* segment */\n");
226 fprintf(htmlfile," tr.t {font-weight: bold;} /* total */\n");
227 fprintf(htmlfile," td.l {font-weight: bold;}\n");
228 fprintf(htmlfile," td.r {}\n");
229 fprintf(htmlfile," span.w {font-weight: bold;} /* waypoint */\n");
230 fprintf(htmlfile," span.h {text-decoration: underline;} /* highway */\n");
231 fprintf(htmlfile," span.d {} /* segment distance */\n");
232 fprintf(htmlfile," span.j {font-style: italic;} /* total journey distance */\n");
233 fprintf(htmlfile," span.t {font-variant: small-caps;} /* turn */\n");
234 fprintf(htmlfile," span.b {font-variant: small-caps;} /* bearing */\n");
235 fprintf(htmlfile,"-->\n");
236 fprintf(htmlfile,"</style>\n");
237 fprintf(htmlfile,"</head>\n");
238 fprintf(htmlfile,"<body>\n");
239 fprintf(htmlfile,"<h1>");
240 fprintf(htmlfile,translation->html_title,option_quickest?translation->xml_route_quickest:translation->xml_route_shortest);
241 fprintf(htmlfile,"</h1>\n");
242 fprintf(htmlfile,"<table>\n");
243 }
244
245 if(gpxtrackfile)
246 {
247 fprintf(gpxtrackfile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
248 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");
249
250 fprintf(gpxtrackfile,"<metadata>\n");
251 fprintf(gpxtrackfile,"<desc>%s : %s</desc>\n",translation->xml_copyright_creator[0],translation->xml_copyright_creator[1]);
252 if(translation->xml_copyright_source[1])
253 {
254 fprintf(gpxtrackfile,"<copyright author=\"%s\">\n",translation->xml_copyright_source[1]);
255
256 if(translation->xml_copyright_license[1])
257 fprintf(gpxtrackfile,"<license>%s</license>\n",translation->xml_copyright_license[1]);
258
259 fprintf(gpxtrackfile,"</copyright>\n");
260 }
261 fprintf(gpxtrackfile,"</metadata>\n");
262
263 fprintf(gpxtrackfile,"<trk>\n");
264 fprintf(gpxtrackfile,"<name>");
265 fprintf(gpxtrackfile,translation->gpx_name,option_quickest?translation->xml_route_quickest:translation->xml_route_shortest);
266 fprintf(gpxtrackfile,"</name>\n");
267 fprintf(gpxtrackfile,"<desc>");
268 fprintf(gpxtrackfile,translation->gpx_desc,option_quickest?translation->xml_route_quickest:translation->xml_route_shortest);
269 fprintf(gpxtrackfile,"</desc>\n");
270 }
271
272 if(gpxroutefile)
273 {
274 fprintf(gpxroutefile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
275 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");
276
277 fprintf(gpxroutefile,"<metadata>\n");
278 fprintf(gpxroutefile,"<desc>%s : %s</desc>\n",translation->xml_copyright_creator[0],translation->xml_copyright_creator[1]);
279 if(translation->xml_copyright_source[1])
280 {
281 fprintf(gpxroutefile,"<copyright author=\"%s\">\n",translation->xml_copyright_source[1]);
282
283 if(translation->xml_copyright_license[1])
284 fprintf(gpxroutefile,"<license>%s</license>\n",translation->xml_copyright_license[1]);
285
286 fprintf(gpxroutefile,"</copyright>\n");
287 }
288 fprintf(gpxroutefile,"</metadata>\n");
289
290 fprintf(gpxroutefile,"<rte>\n");
291 fprintf(gpxroutefile,"<name>");
292 fprintf(gpxroutefile,translation->gpx_name,option_quickest?translation->xml_route_quickest:translation->xml_route_shortest);
293 fprintf(gpxroutefile,"</name>\n");
294 fprintf(gpxroutefile,"<desc>");
295 fprintf(gpxroutefile,translation->gpx_desc,option_quickest?translation->xml_route_quickest:translation->xml_route_shortest);
296 fprintf(gpxroutefile,"</desc>\n");
297 }
298
299 if(textfile)
300 {
301 if(translation->raw_copyright_creator[0] && translation->raw_copyright_creator[1])
302 fprintf(textfile,"# %s : %s\n",translation->raw_copyright_creator[0],translation->raw_copyright_creator[1]);
303 if(translation->raw_copyright_source[0] && translation->raw_copyright_source[1])
304 fprintf(textfile,"# %s : %s\n",translation->raw_copyright_source[0],translation->raw_copyright_source[1]);
305 if(translation->raw_copyright_license[0] && translation->raw_copyright_license[1])
306 fprintf(textfile,"# %s : %s\n",translation->raw_copyright_license[0],translation->raw_copyright_license[1]);
307 if((translation->raw_copyright_creator[0] && translation->raw_copyright_creator[1]) ||
308 (translation->raw_copyright_source[0] && translation->raw_copyright_source[1]) ||
309 (translation->raw_copyright_license[0] && translation->raw_copyright_license[1]))
310 fprintf(textfile,"#\n");
311
312 fprintf(textfile,"#Latitude\tLongitude\tSection \tSection \tTotal \tTotal \tPoint\tTurn\tBearing\tHighway\n");
313 fprintf(textfile,"# \t \tDistance\tDuration\tDistance\tDuration\tType \t \t \t \n");
314 /* "%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" */
315 }
316
317 if(textallfile)
318 {
319 if(translation->raw_copyright_creator[0] && translation->raw_copyright_creator[1])
320 fprintf(textallfile,"# %s : %s\n",translation->raw_copyright_creator[0],translation->raw_copyright_creator[1]);
321 if(translation->raw_copyright_source[0] && translation->raw_copyright_source[1])
322 fprintf(textallfile,"# %s : %s\n",translation->raw_copyright_source[0],translation->raw_copyright_source[1]);
323 if(translation->raw_copyright_license[0] && translation->raw_copyright_license[1])
324 fprintf(textallfile,"# %s : %s\n",translation->raw_copyright_license[0],translation->raw_copyright_license[1]);
325 if((translation->raw_copyright_creator[0] && translation->raw_copyright_creator[1]) ||
326 (translation->raw_copyright_source[0] && translation->raw_copyright_source[1]) ||
327 (translation->raw_copyright_license[0] && translation->raw_copyright_license[1]))
328 fprintf(textallfile,"#\n");
329
330 fprintf(textallfile,"#Latitude\tLongitude\t Node\tType\tSegment\tSegment\tTotal\tTotal \tSpeed\tBearing\tHighway\n");
331 fprintf(textallfile,"# \t \t \t \tDist \tDurat'n\tDist \tDurat'n\t \t \t \n");
332 /* "%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" */
333 }
334
335 /* Create the head of the linked list */
336
337 if(option_list_html)
338 listhead=htmllist=calloc(sizeof(Routino_Output),1);
339 if(option_list_html_all)
340 listhead=htmlalllist=htmllist=calloc(sizeof(Routino_Output),1);
341 if(option_list_text)
342 listhead=textlist=calloc(sizeof(Routino_Output),1);
343 if(option_list_text_all)
344 listhead=textalllist=calloc(sizeof(Routino_Output),1);
345
346 /* Loop through all the sections of the route and print them */
347
348 do
349 {
350 int first=1;
351 int next_point=point;
352 distance_t junc_distance=0;
353 duration_t junc_duration=0;
354 Result *result;
355
356 #if DEBUG
357 printf("Route section %d - waypoint %d to waypoint %d\n",point,results[point]->start_waypoint,results[point]->finish_waypoint);
358 printf(" start_node=%"Pindex_t" prev_segment=%"Pindex_t"\n",results[point]->start_node,results[point]->prev_segment);
359 printf(" finish_node=%"Pindex_t" last_segment=%"Pindex_t"\n",results[point]->finish_node,results[point]->last_segment);
360
361 Result *r=FindResult(results[point],results[point]->start_node,results[point]->prev_segment);
362
363 while(r)
364 {
365 printf(" node=%"Pindex_t" segment=%"Pindex_t" score=%f\n",r->node,r->segment,r->score);
366
367 r=r->next;
368 }
369 #endif
370
371 result=FindResult(results[point],results[point]->start_node,results[point]->prev_segment);
372
373 /* Print the start of the segment */
374
375 if(gpxtrackfile)
376 fprintf(gpxtrackfile,"<trkseg>\n");
377
378 /* Loop through all the points within a section of the route and print them */
379
380 do
381 {
382 double latitude,longitude;
383 Node *resultnodep=NULL;
384 index_t realsegment=NO_SEGMENT,next_realsegment=NO_SEGMENT;
385 Segment *resultsegmentp=NULL,*next_resultsegmentp=NULL;
386 Way *resultwayp=NULL,*next_resultwayp=NULL;
387 Result *next_result;
388 int important=ROUTINO_POINT_UNIMPORTANT;
389
390 distance_t seg_distance=0;
391 duration_t seg_duration=0;
392 speed_t seg_speed=0;
393 char *waynameraw=NULL,*wayname=NULL,*next_waynameraw=NULL,*next_wayname=NULL;
394 int bearing_int=0,turn_int=0,next_bearing_int=0;
395 char *turn=NULL,*turnraw=NULL,*next_bearing=NULL,*next_bearingraw=NULL;
396
397 /* Calculate the information about this point */
398
399 if(IsFakeNode(result->node))
400 GetFakeLatLong(result->node,&latitude,&longitude);
401 else
402 {
403 resultnodep=LookupNode(nodes,result->node,6);
404
405 GetLatLong(nodes,result->node,resultnodep,&latitude,&longitude);
406 }
407
408 /* Calculate the next result */
409
410 next_result=result->next;
411
412 if(!next_result)
413 {
414 next_point++;
415
416 if(next_point<nresults)
417 {
418 next_result=FindResult(results[next_point],results[next_point]->start_node,results[next_point]->prev_segment);
419 next_result=next_result->next;
420 }
421 }
422
423 /* Calculate the information about this segment */
424
425 if(!first) /* not first point of a section of the route */
426 {
427 if(IsFakeSegment(result->segment))
428 {
429 resultsegmentp=LookupFakeSegment(result->segment);
430 realsegment=IndexRealSegment(result->segment);
431 }
432 else
433 {
434 resultsegmentp=LookupSegment(segments,result->segment,2);
435 realsegment=result->segment;
436 }
437
438 resultwayp=LookupWay(ways,resultsegmentp->way,1);
439
440 seg_distance+=DISTANCE(resultsegmentp->distance);
441 seg_duration+=Duration(resultsegmentp,resultwayp,profile);
442
443 /* Calculate the cumulative distance/duration */
444
445 junc_distance+=seg_distance;
446 junc_duration+=seg_duration;
447 cum_distance+=seg_distance;
448 cum_duration+=seg_duration;
449 }
450
451 /* Calculate the information about the next segment */
452
453 if(next_result)
454 {
455 if(IsFakeSegment(next_result->segment))
456 {
457 next_resultsegmentp=LookupFakeSegment(next_result->segment);
458 next_realsegment=IndexRealSegment(next_result->segment);
459 }
460 else
461 {
462 next_resultsegmentp=LookupSegment(segments,next_result->segment,1);
463 next_realsegment=next_result->segment;
464 }
465 }
466
467 /* Decide if this is a roundabout */
468
469 if(next_result)
470 {
471 next_resultwayp=LookupWay(ways,next_resultsegmentp->way,2);
472
473 if(next_resultwayp->type&Highway_Roundabout)
474 {
475 if(roundabout==0)
476 {
477 roundabout++;
478 important=ROUTINO_POINT_RB_ENTRY;
479 }
480 else
481 {
482 Segment *segmentp;
483
484 if(resultnodep)
485 segmentp=FirstSegment(segments,resultnodep,3);
486 else
487 segmentp=FirstFakeSegment(result->node);
488
489 do
490 {
491 index_t othernode=OtherNode(segmentp,result->node);
492 index_t thissegment;
493
494 if(IsFakeNode(result->node))
495 thissegment=IndexFakeSegment(segmentp);
496 else
497 thissegment=IndexSegment(segments,segmentp);
498
499 if(othernode!=prev_node && othernode!=next_result->node &&
500 thissegment!=realsegment && IsNormalSegment(segmentp))
501 {
502 int canexit=1;
503
504 if(profile->oneway && IsOnewayTo(segmentp,result->node))
505 {
506 if(profile->allow!=Transports_Bicycle)
507 canexit=0;
508 else
509 {
510 Way *wayp=LookupWay(ways,segmentp->way,3);
511
512 if(!(wayp->type&Highway_CycleBothWays))
513 canexit=0;
514 }
515 }
516
517 if(canexit)
518 {
519 Way *wayp=LookupWay(ways,segmentp->way,3);
520
521 if(!(wayp->type&Highway_Roundabout))
522 {
523 roundabout++;
524 important=ROUTINO_POINT_RB_NOT_EXIT;
525 }
526 }
527 }
528
529 if(resultnodep)
530 segmentp=NextSegment(segments,segmentp,result->node);
531 else
532 segmentp=NextFakeSegment(segmentp,result->node);
533 }
534 while(segmentp);
535 }
536 }
537 else
538 if(roundabout)
539 {
540 roundabout++;
541 important=ROUTINO_POINT_RB_EXIT;
542 }
543 }
544
545 /* Decide if this is an important junction */
546
547 if(point_count==0) /* first point overall = Waypoint */
548 important=ROUTINO_POINT_WAYPOINT;
549 else if(result->next==NULL) /* Waypoint */
550 important=ROUTINO_POINT_WAYPOINT;
551 else if(first) /* first point of a section of the route */
552 important=ROUTINO_POINT_IGNORE;
553 else if(roundabout) /* roundabout */
554 ;
555 else if(realsegment==next_realsegment) /* U-turn */
556 important=ROUTINO_POINT_UTURN;
557 else if(resultnodep && (resultnodep->flags&NODE_MINIRNDBT))
558 important=ROUTINO_POINT_MINI_RB; /* mini-roundabout */
559 else
560 {
561 Segment *segmentp=FirstSegment(segments,resultnodep,3);
562
563 do
564 {
565 index_t seg=IndexSegment(segments,segmentp);
566
567 if(seg!=realsegment && IsNormalSegment(segmentp))
568 {
569 int cango=1;
570
571 if(profile->oneway && IsOnewayTo(segmentp,result->node))
572 {
573 if(profile->allow!=Transports_Bicycle)
574 cango=0;
575 else
576 {
577 Way *wayp=LookupWay(ways,segmentp->way,3);
578
579 if(!(wayp->type&Highway_CycleBothWays))
580 cango=0;
581 }
582 }
583
584 if(cango)
585 {
586 Way *wayp=LookupWay(ways,segmentp->way,3);
587
588 if(seg==next_realsegment) /* the next segment that we follow */
589 {
590 if(HIGHWAY(wayp->type)!=HIGHWAY(resultwayp->type))
591 if(important<ROUTINO_POINT_CHANGE)
592 important=ROUTINO_POINT_CHANGE;
593 }
594 else /* a segment that we don't follow */
595 {
596 if(junction_other_way[HIGHWAY(resultwayp->type)-1][HIGHWAY(wayp->type)-1])
597 if(important<ROUTINO_POINT_JUNCT_IMPORT)
598 important=ROUTINO_POINT_JUNCT_IMPORT;
599
600 if(important<ROUTINO_POINT_JUNCT_CONT)
601 important=ROUTINO_POINT_JUNCT_CONT;
602 }
603 }
604 }
605
606 segmentp=NextSegment(segments,segmentp,result->node);
607 }
608 while(segmentp);
609 }
610
611 /* Calculate the strings to be used */
612
613 if(!first && (textallfile || textalllist))
614 {
615 waynameraw=WayName(ways,resultwayp);
616 if(!*waynameraw)
617 waynameraw=translation->raw_highway[HIGHWAY(resultwayp->type)];
618
619 bearing_int=(int)BearingAngle(nodes,resultsegmentp,result->node);
620
621 seg_speed=profile->speed[HIGHWAY(resultwayp->type)];
622 }
623
624 if(next_result && (important>ROUTINO_POINT_JUNCT_CONT || htmlalllist))
625 {
626 if(!first && (htmlfile || htmllist || textfile || textlist))
627 {
628 if(DISTANCE(resultsegmentp->distance)==0 || DISTANCE(next_resultsegmentp->distance)==0)
629 turn_int=0;
630 else
631 turn_int=(int)TurnAngle(nodes,resultsegmentp,next_resultsegmentp,result->node);
632
633 turn =translation->xml_turn[((202+turn_int)/45)%8];
634 turnraw=translation->notxml_turn[((202+turn_int)/45)%8];
635 }
636
637 if(gpxroutefile || htmlfile || htmllist)
638 {
639 next_waynameraw=WayName(ways,next_resultwayp);
640 if(!*next_waynameraw)
641 next_waynameraw=translation->raw_highway[HIGHWAY(next_resultwayp->type)];
642
643 next_wayname=ParseXML_Encode_Safe_XML(next_waynameraw);
644 }
645
646 if(htmlfile || htmllist || gpxroutefile || textfile || textlist)
647 {
648 if(!first && DISTANCE(next_resultsegmentp->distance)==0)
649 next_bearing_int=(int)BearingAngle(nodes,resultsegmentp,result->node);
650 else
651 next_bearing_int=(int)BearingAngle(nodes,next_resultsegmentp,next_result->node);
652
653 next_bearing =translation->xml_heading[(4+(22+next_bearing_int)/45)%8];
654 next_bearingraw=translation->notxml_heading[(4+(22+next_bearing_int)/45)%8];
655 }
656 }
657
658 /* Print out the important points (junctions / waypoints) */
659
660 if(important>ROUTINO_POINT_JUNCT_CONT)
661 {
662 if(htmlfile)
663 {
664 char *type;
665
666 if(important==ROUTINO_POINT_WAYPOINT)
667 type=translation->html_waypoint;
668 else if(important==ROUTINO_POINT_MINI_RB)
669 type=translation->html_roundabout;
670 else
671 type=translation->html_junction;
672
673 if(point_count>0) /* not the first point */
674 {
675 /* <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>] */
676 fprintf(htmlfile,translation->html_segment,
677 (roundabout>1?translation->html_roundabout:prev_wayname),
678 distance_to_km(junc_distance),duration_to_minutes(junc_duration));
679 fprintf(htmlfile,translation->html_subtotal,
680 distance_to_km(cum_distance),duration_to_minutes(cum_duration));
681 }
682
683 /* <tr class='c'><td class='l'>*N*:<td class='r'>*latitude* *longitude* */
684 fprintf(htmlfile,"<tr class='c'><td class='l'>%d:<td class='r'>%.6f %.6f\n",
685 point_count+1,
686 radians_to_degrees(latitude),radians_to_degrees(longitude));
687
688 if(point_count==0) /* first point */
689 {
690 /* <tr class='n'><td class='l'>Start:<td class='r'>At <span class='w'>Waypoint</span>, head <span class='b'>*heading*</span> */
691 fprintf(htmlfile,translation->html_start,
692 translation->html_waypoint,
693 next_bearing);
694 }
695 else if(next_result) /* middle point */
696 {
697 if(roundabout>1 && important!=ROUTINO_POINT_WAYPOINT)
698 {
699 /* <tr class='n'><td class='l'>Leave:<td class='r'>Roundabout, take <span class='t'>the *Nth* exit</span> heading <span class='b'>*heading*</span> */
700 fprintf(htmlfile,translation->html_rbnode,
701 translation->html_roundabout,
702 translation->xml_ordinal[roundabout-2],
703 next_bearing);
704 }
705 else
706 {
707 /* <tr class='n'><td class='l'>At:<td class='r'>Junction, go <span class='t'>*direction*</span> heading <span class='b'>*heading*</span> */
708 fprintf(htmlfile,translation->html_node,
709 type,
710 turn,
711 next_bearing);
712 }
713 }
714 else /* end point */
715 {
716 /* <tr class='n'><td class='l'>Stop:<td class='r'>At <span class='w'>Waypoint</span> */
717 fprintf(htmlfile,translation->html_stop,
718 translation->html_waypoint);
719
720 /* <tr class='t'><td class='l'>Total:<td class='r'><span class='j'>*distance* km, *time* minutes</span> */
721 fprintf(htmlfile,translation->html_total,
722 distance_to_km(cum_distance),duration_to_minutes(cum_duration));
723 }
724 }
725
726 if(htmllist)
727 {
728 int strl;
729 char *type;
730
731 if(important==ROUTINO_POINT_WAYPOINT)
732 type=translation->nothtml_waypoint;
733 else if(important==ROUTINO_POINT_MINI_RB)
734 type=translation->nothtml_roundabout;
735 else
736 type=translation->nothtml_junction;
737
738 if(point_count>0) /* not the first point */
739 {
740 /* Follow: *highway name* for *distance* km, *time* min */
741 strl=strlen(translation->nothtml_segment)+
742 strlen(roundabout>1?translation->nothtml_roundabout:prev_waynameraw)+8+8+1;
743
744 htmllist->desc2=malloc(strl);
745
746 sprintf(htmllist->desc2,translation->nothtml_segment,
747 (roundabout>1?translation->nothtml_roundabout:prev_waynameraw),
748 distance_to_km(junc_distance),duration_to_minutes(junc_duration));
749
750 /* *distance* km, *time* minutes */
751 strl=strlen(translation->nothtml_subtotal)+8+8+1;
752
753 htmllist->desc3=malloc(strl);
754
755 sprintf(htmllist->desc3,translation->nothtml_subtotal,
756 distance_to_km(cum_distance),duration_to_minutes(cum_duration));
757
758 if(htmlalllist)
759 htmllist=htmlalllist;
760
761 htmllist->next=calloc(sizeof(Routino_Output),1);
762 htmllist=htmllist->next;
763
764 if(htmlalllist)
765 htmlalllist=htmllist;
766 }
767
768 htmllist->lon=longitude;
769 htmllist->lat=latitude;
770 htmllist->type=important;
771 htmllist->dist=distance_to_km(cum_distance);
772 htmllist->time=duration_to_minutes(cum_duration);
773
774 if(point_count==0) /* first point */
775 {
776 /* Start: At Waypoint, head *heading* */
777 strl=strlen(translation->nothtml_start)+
778 strlen(translation->nothtml_waypoint)+strlen(next_bearingraw)+1;
779
780 htmllist->desc1=malloc(strl);
781
782 sprintf(htmllist->desc1,translation->nothtml_start,
783 translation->nothtml_waypoint,
784 next_bearingraw);
785
786 htmllist->name=strcpy(malloc(strlen(next_waynameraw)+1),next_waynameraw);
787 }
788 else if(next_result) /* middle point */
789 {
790 if(roundabout>1 && important!=ROUTINO_POINT_WAYPOINT)
791 {
792 /* At: Roundabout, take the *Nth* exit heading *heading* */
793 strl=strlen(translation->nothtml_rbnode)+
794 strlen(translation->nothtml_roundabout)+strlen(translation->notxml_ordinal[roundabout-2])+strlen(next_bearingraw)+1;
795
796 htmllist->desc1=malloc(strl);
797
798 sprintf(htmllist->desc1,translation->nothtml_rbnode,
799 translation->nothtml_roundabout,
800 translation->notxml_ordinal[roundabout-2],
801 next_bearingraw);
802 }
803 else
804 {
805 /* At: Junction, go *direction* heading *heading* */
806 strl=strlen(translation->nothtml_node)+
807 strlen(type)+strlen(turnraw)+strlen(next_bearingraw)+1;
808
809 htmllist->desc1=malloc(strl);
810
811 sprintf(htmllist->desc1,translation->nothtml_node,
812 type,
813 turnraw,
814 next_bearingraw);
815 }
816
817 htmllist->turn=turn_int;
818 htmllist->name=strcpy(malloc(strlen(next_waynameraw)+1),next_waynameraw);
819 }
820 else /* end point */
821 {
822 /* Stop: At Waypoint */
823 strl=strlen(translation->nothtml_stop)+
824 strlen(translation->nothtml_waypoint)+1;
825
826 htmllist->desc1=malloc(strl);
827
828 sprintf(htmllist->desc1,translation->nothtml_stop,
829 translation->nothtml_waypoint);
830
831 /* Total: *distance* km, *time* minutes */
832 strl=strlen(translation->nothtml_total)+8+8+1;
833
834 htmllist->desc2=malloc(strl);
835
836 sprintf(htmllist->desc2,translation->nothtml_total,
837 distance_to_km(cum_distance),duration_to_minutes(cum_duration));
838
839 htmllist->turn=turn_int;
840 }
841
842 htmllist->bearing=next_bearing_int;
843 }
844
845 if(gpxroutefile)
846 {
847 if(point_count>0) /* not first point */
848 {
849 fprintf(gpxroutefile,"<desc>");
850 fprintf(gpxroutefile,translation->gpx_step,
851 prev_bearing,
852 prev_wayname,
853 distance_to_km(junc_distance),duration_to_minutes(junc_duration));
854 fprintf(gpxroutefile,"</desc></rtept>\n");
855 }
856
857 if(point_count==0) /* first point */
858 {
859 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s</name>\n",
860 radians_to_degrees(latitude),radians_to_degrees(longitude),
861 translation->gpx_start);
862 }
863 else if(!next_result) /* end point */
864 {
865 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s</name>\n",
866 radians_to_degrees(latitude),radians_to_degrees(longitude),
867 translation->gpx_finish);
868 fprintf(gpxroutefile,"<desc>");
869 fprintf(gpxroutefile,translation->gpx_final,
870 distance_to_km(cum_distance),duration_to_minutes(cum_duration));
871 fprintf(gpxroutefile,"</desc></rtept>\n");
872 }
873 else /* middle point */
874 {
875 if(important==ROUTINO_POINT_WAYPOINT)
876 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%d</name>\n",
877 radians_to_degrees(latitude),radians_to_degrees(longitude),
878 translation->gpx_inter,++segment_count);
879 else
880 fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%03d</name>\n",
881 radians_to_degrees(latitude),radians_to_degrees(longitude),
882 translation->gpx_trip,++route_count);
883 }
884 }
885
886 if(textfile)
887 {
888 char *type;
889
890 if(important==ROUTINO_POINT_WAYPOINT)
891 type="Waypt";
892 else
893 type="Junct";
894
895 if(point_count==0) /* first point */
896 {
897 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",
898 radians_to_degrees(latitude),radians_to_degrees(longitude),
899 0.0,0.0,0.0,0.0,
900 type,
901 ((22+next_bearing_int)/45+4)%8-4,
902 next_waynameraw);
903 }
904 else if(!next_result) /* end point */
905 {
906 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",
907 radians_to_degrees(latitude),radians_to_degrees(longitude),
908 distance_to_km(junc_distance),duration_to_minutes(junc_duration),
909 distance_to_km(cum_distance),duration_to_minutes(cum_duration),
910 type);
911 }
912 else /* middle point */
913 {
914 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",
915 radians_to_degrees(latitude),radians_to_degrees(longitude),
916 distance_to_km(junc_distance),duration_to_minutes(junc_duration),
917 distance_to_km(cum_distance),duration_to_minutes(cum_duration),
918 type,
919 (22+turn_int)/45,
920 ((22+next_bearing_int)/45+4)%8-4,
921 next_waynameraw);
922 }
923 }
924
925 if(textlist)
926 {
927 textlist->lon=longitude;
928 textlist->lat=latitude;
929 textlist->type=important;
930
931 if(point_count==0) /* first point */
932 {
933 textlist->next=calloc(sizeof(Routino_Output),1);
934
935 textlist->bearing=next_bearing_int;
936 textlist->name=strcpy(malloc(strlen(next_waynameraw)+1),next_waynameraw);
937 }
938 else if(!next_result) /* end point */
939 {
940 textlist->next=NULL;
941
942 textlist->dist=distance_to_km(cum_distance);
943 textlist->time=duration_to_minutes(cum_duration);
944 }
945 else /* middle point */
946 {
947 textlist->next=calloc(sizeof(Routino_Output),1);
948
949 textlist->dist=distance_to_km(cum_distance);
950 textlist->time=duration_to_minutes(cum_duration);
951 textlist->turn=turn_int;
952 textlist->bearing=next_bearing_int;
953 textlist->name=strcpy(malloc(strlen(next_waynameraw)+1),next_waynameraw);
954 }
955
956 textlist=textlist->next;
957 }
958
959 junc_distance=0;
960 junc_duration=0;
961
962 if(htmlfile || htmllist || gpxroutefile)
963 {
964 if(prev_wayname)
965 free(prev_wayname);
966
967 if(next_wayname)
968 prev_wayname=strcpy((char*)malloc(strlen(next_wayname)+1),next_wayname);
969 else
970 prev_wayname=NULL;
971
972 if(prev_waynameraw)
973 free(prev_waynameraw);
974
975 if(next_waynameraw)
976 prev_waynameraw=strcpy((char*)malloc(strlen(next_waynameraw)+1),next_waynameraw);
977 else
978 prev_waynameraw=NULL;
979 }
980
981 if(gpxroutefile)
982 prev_bearing=next_bearing;
983
984 if(roundabout>1)
985 roundabout=0;
986 }
987 else
988 {
989 if(htmlalllist)
990 {
991 htmlalllist->next=calloc(sizeof(Routino_Output),1);
992 htmlalllist=htmlalllist->next;
993
994 htmlalllist->lon=longitude;
995 htmlalllist->lat=latitude;
996 htmlalllist->type=important;
997 htmlalllist->dist=distance_to_km(cum_distance);
998 htmlalllist->time=duration_to_minutes(cum_duration);
999 htmlalllist->turn=turn_int;
1000 htmlalllist->bearing=next_bearing_int;
1001 }
1002 }
1003
1004 /* Print out all of the results */
1005
1006 if(gpxtrackfile)
1007 fprintf(gpxtrackfile,"<trkpt lat=\"%.6f\" lon=\"%.6f\"/>\n",
1008 radians_to_degrees(latitude),radians_to_degrees(longitude));
1009
1010 if(important>ROUTINO_POINT_IGNORE)
1011 {
1012 if(textallfile)
1013 {
1014 char *type;
1015
1016 if(important==ROUTINO_POINT_WAYPOINT)
1017 type="Waypt";
1018 else if(important==ROUTINO_POINT_UTURN)
1019 type="U-turn";
1020 else if(important==ROUTINO_POINT_MINI_RB)
1021 type="Mini-RB";
1022 else if(important==ROUTINO_POINT_CHANGE)
1023 type="Change";
1024 else if(important==ROUTINO_POINT_JUNCT_CONT || important==ROUTINO_POINT_RB_NOT_EXIT)
1025 type="Junct-";
1026 else if(important==ROUTINO_POINT_UNIMPORTANT)
1027 type="Inter";
1028 else
1029 type="Junct";
1030
1031 if(point_count==0) /* first point */
1032 {
1033 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",
1034 radians_to_degrees(latitude),radians_to_degrees(longitude),
1035 IsFakeNode(result->node)?(NODE_FAKE-result->node):result->node,
1036 (resultnodep && IsSuperNode(resultnodep))?'*':' ',type,
1037 0.0,0.0,0.0,0.0);
1038 }
1039 else /* not the first point */
1040 {
1041 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",
1042 radians_to_degrees(latitude),radians_to_degrees(longitude),
1043 IsFakeNode(result->node)?(NODE_FAKE-result->node):result->node,
1044 (resultnodep && IsSuperNode(resultnodep))?'*':' ',type,
1045 distance_to_km(seg_distance),duration_to_minutes(seg_duration),
1046 distance_to_km(cum_distance),duration_to_minutes(cum_duration),
1047 speed_to_kph(seg_speed),
1048 bearing_int,
1049 waynameraw);
1050 }
1051 }
1052
1053 if(textalllist)
1054 {
1055 if(point_count==0) /* first point */
1056 ;
1057 else /* not the first point */
1058 {
1059 textalllist->next=calloc(sizeof(Routino_Output),1);
1060 textalllist=textalllist->next;
1061
1062 textalllist->dist=distance_to_km(cum_distance);
1063 textalllist->time=duration_to_minutes(cum_duration);
1064 textalllist->speed=speed_to_kph(seg_speed);
1065 textalllist->bearing=next_bearing_int;
1066 textalllist->name=strcpy(malloc(strlen(waynameraw)+1),waynameraw);
1067 }
1068
1069 textalllist->lon=longitude;
1070 textalllist->lat=latitude;
1071 textalllist->type=important;
1072 }
1073 }
1074
1075 if(wayname && wayname!=waynameraw)
1076 free(wayname);
1077
1078 result=next_result;
1079
1080 if(important>ROUTINO_POINT_JUNCT_CONT)
1081 point_count++;
1082
1083 first=0;
1084 }
1085 while(point==next_point);
1086
1087 /* Print the end of the segment */
1088
1089 if(gpxtrackfile)
1090 fprintf(gpxtrackfile,"</trkseg>\n");
1091
1092 point=next_point;
1093
1094 if(result)
1095 prev_node=result->node;
1096 else
1097 prev_node=NO_NODE;
1098 }
1099 while(point<nresults);
1100
1101 /* Print the tail of the files */
1102
1103 if(htmlfile)
1104 {
1105 fprintf(htmlfile,"</table>\n");
1106
1107 if((translation->xml_copyright_creator[0] && translation->xml_copyright_creator[1]) ||
1108 (translation->xml_copyright_source[0] && translation->xml_copyright_source[1]) ||
1109 (translation->xml_copyright_license[0] && translation->xml_copyright_license[1]))
1110 {
1111 fprintf(htmlfile,"<p>\n");
1112 fprintf(htmlfile,"<table class='c'>\n");
1113 if(translation->xml_copyright_creator[0] && translation->xml_copyright_creator[1])
1114 fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translation->xml_copyright_creator[0],translation->xml_copyright_creator[1]);
1115 if(translation->xml_copyright_source[0] && translation->xml_copyright_source[1])
1116 fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translation->xml_copyright_source[0],translation->xml_copyright_source[1]);
1117 if(translation->xml_copyright_license[0] && translation->xml_copyright_license[1])
1118 fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translation->xml_copyright_license[0],translation->xml_copyright_license[1]);
1119 fprintf(htmlfile,"</table>\n");
1120 }
1121
1122 fprintf(htmlfile,"</body>\n");
1123 fprintf(htmlfile,"</html>\n");
1124 }
1125
1126 if(gpxtrackfile)
1127 {
1128 fprintf(gpxtrackfile,"</trk>\n");
1129 fprintf(gpxtrackfile,"</gpx>\n");
1130 }
1131
1132 if(gpxroutefile)
1133 {
1134 fprintf(gpxroutefile,"</rte>\n");
1135 fprintf(gpxroutefile,"</gpx>\n");
1136 }
1137
1138 /* Close the files */
1139
1140 if(!option_file_stdout)
1141 {
1142 if(htmlfile)
1143 fclose(htmlfile);
1144 if(gpxtrackfile)
1145 fclose(gpxtrackfile);
1146 if(gpxroutefile)
1147 fclose(gpxroutefile);
1148 if(textfile)
1149 fclose(textfile);
1150 if(textallfile)
1151 fclose(textallfile);
1152 }
1153
1154 return(listhead);
1155 }

Properties

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