Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /trunk/src/output.c
Parent Directory
|
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)
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. |