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 2192 - (show annotations) (download) (as text)
Wed Sep 18 15:49:21 2024 UTC (5 months, 4 weeks ago) by amb
File MIME type: text/x-csrc
File size: 49822 byte(s)
Fix compilation warnings if index_t is changed to a 64-bit type but
preserve formatting of fake nodes (shown as negative).

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

Properties

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