Routino SVN Repository Browser

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

ViewVC logotype

Contents of /branches/destination-access/src/output.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1829 - (show annotations) (download) (as text)
Sat Oct 17 14:17:17 2015 UTC (9 years, 5 months ago) by amb
File MIME type: text/x-csrc
File size: 48075 byte(s)
Merge trunk back into routino-destination branch after completing the
loop and reverse changes.

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

Properties

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