Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/output.c
Parent Directory
|
Revision Log
Revision 2192 -
(hide annotations)
(download)
(as text)
Wed Sep 18 15:49:21 2024 UTC (6 months, 1 week ago) by amb
File MIME type: text/x-csrc
File size: 49822 byte(s)
Wed Sep 18 15:49:21 2024 UTC (6 months, 1 week 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 | amb | 160 | /*************************************** |
2 | Routing output generator. | ||
3 | |||
4 | Part of the Routino routing software. | ||
5 | ******************/ /****************** | ||
6 | amb | 2188 | This file Copyright 2008-2017, 2019, 2024 Andrew M. Bishop |
7 | amb | 160 | |
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 | amb | 165 | #include <stdlib.h> |
24 | amb | 160 | #include <string.h> |
25 | amb | 164 | #include <ctype.h> |
26 | amb | 160 | #include <stdio.h> |
27 | amb | 316 | #include <math.h> |
28 | amb | 330 | #include <errno.h> |
29 | amb | 160 | |
30 | #include "types.h" | ||
31 | #include "nodes.h" | ||
32 | #include "segments.h" | ||
33 | #include "ways.h" | ||
34 | amb | 1878 | #include "relations.h" |
35 | amb | 449 | |
36 | #include "functions.h" | ||
37 | amb | 532 | #include "fakes.h" |
38 | amb | 449 | #include "translations.h" |
39 | amb | 160 | #include "results.h" |
40 | amb | 378 | #include "xmlparse.h" |
41 | amb | 160 | |
42 | amb | 1784 | #include "routino.h" |
43 | amb | 955 | |
44 | amb | 1784 | |
45 | /*+ To help when debugging +*/ | ||
46 | amb | 1564 | #define DEBUG 0 |
47 | |||
48 | amb | 927 | /* Constants */ |
49 | amb | 160 | |
50 | amb | 1784 | #define ROUTINO_POINT_IGNORE -1 /*+ Ignore this point. +*/ |
51 | amb | 927 | |
52 | amb | 955 | |
53 | amb | 360 | /* Global variables */ |
54 | |||
55 | amb | 160 | /*+ The option to calculate the quickest route insted of the shortest. +*/ |
56 | amb | 1784 | int option_quickest=0; |
57 | amb | 160 | |
58 | amb | 1784 | /*+ 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 | amb | 324 | |
61 | amb | 1784 | /*+ The options to select the format of the linked list output. +*/ |
62 | amb | 1795 | int option_list_html=0,option_list_html_all=0,option_list_text=0,option_list_text_all=0; |
63 | amb | 955 | |
64 | amb | 1784 | |
65 | amb | 360 | /* Local variables */ |
66 | |||
67 | amb | 171 | /*+ Heuristics for determining if a junction is important. +*/ |
68 | amb | 1677 | static const char junction_other_way[Highway_Count][Highway_Count]= |
69 | amb | 492 | { /* 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 | amb | 171 | }; |
84 | amb | 165 | |
85 | amb | 360 | |
86 | amb | 160 | /*++++++++++++++++++++++++++++++++++++++ |
87 | amb | 379 | Print the optimum route between two nodes. |
88 | |||
89 | amb | 1784 | Routino_Output *PrintRoute Returns a linked list of data structures representing the route if required. |
90 | |||
91 | amb | 1501 | Results **results The set of results to print (consecutive in array even if not consecutive waypoints). |
92 | amb | 379 | |
93 | int nresults The number of results in the list. | ||
94 | |||
95 | amb | 680 | Nodes *nodes The set of nodes to use. |
96 | amb | 379 | |
97 | Segments *segments The set of segments to use. | ||
98 | |||
99 | amb | 680 | Ways *ways The set of ways to use. |
100 | amb | 379 | |
101 | amb | 1878 | Relations *relations The set of relations to use. |
102 | |||
103 | amb | 379 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
104 | amb | 1784 | |
105 | Translation *translation The set of translated strings. | ||
106 | amb | 164 | ++++++++++++++++++++++++++++++++++++++*/ |
107 | amb | 160 | |
108 | amb | 1878 | Routino_Output *PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,Translation *translation) |
109 | amb | 164 | { |
110 | amb | 1784 | FILE *htmlfile=NULL,*gpxtrackfile=NULL,*gpxroutefile=NULL,*textfile=NULL,*textallfile=NULL; |
111 | amb | 1795 | Routino_Output *listhead=NULL,*htmllist=NULL, *textlist=NULL,*textalllist=NULL,*htmlalllist=NULL; |
112 | amb | 379 | |
113 | amb | 1784 | char *prev_bearing=NULL,*prev_wayname=NULL,*prev_waynameraw=NULL; |
114 | amb | 1539 | index_t prev_node=NO_NODE; |
115 | amb | 379 | distance_t cum_distance=0; |
116 | duration_t cum_duration=0; | ||
117 | amb | 922 | |
118 | amb | 1501 | int point=0; |
119 | amb | 683 | int point_count=0; |
120 | amb | 926 | int roundabout=0; |
121 | amb | 379 | |
122 | amb | 164 | /* Open the files */ |
123 | amb | 160 | |
124 | amb | 1784 | if(option_file_stdout) |
125 | amb | 160 | { |
126 | amb | 1784 | if(option_file_html) |
127 | amb | 1465 | htmlfile =stdout; |
128 | amb | 1784 | if(option_file_gpx_track) |
129 | amb | 1465 | gpxtrackfile=stdout; |
130 | amb | 1784 | if(option_file_gpx_route) |
131 | amb | 1465 | gpxroutefile=stdout; |
132 | amb | 1784 | if(option_file_text) |
133 | amb | 1465 | textfile =stdout; |
134 | amb | 1784 | if(option_file_text_all) |
135 | amb | 1465 | textallfile =stdout; |
136 | amb | 160 | } |
137 | else | ||
138 | { | ||
139 | amb | 1699 | #if defined(_MSC_VER) || defined(__MINGW32__) |
140 | const char *open_mode="wb"; | ||
141 | #else | ||
142 | const char *open_mode="w"; | ||
143 | #endif | ||
144 | |||
145 | amb | 1465 | if(option_quickest==0) |
146 | { | ||
147 | /* Print the result for the shortest route */ | ||
148 | amb | 160 | |
149 | amb | 1784 | if(option_file_html) |
150 | amb | 1699 | htmlfile =fopen("shortest.html",open_mode); |
151 | amb | 1784 | if(option_file_gpx_track) |
152 | amb | 1699 | gpxtrackfile=fopen("shortest-track.gpx",open_mode); |
153 | amb | 1784 | if(option_file_gpx_route) |
154 | amb | 1699 | gpxroutefile=fopen("shortest-route.gpx",open_mode); |
155 | amb | 1784 | if(option_file_text) |
156 | amb | 1699 | textfile =fopen("shortest.txt",open_mode); |
157 | amb | 1784 | if(option_file_text_all) |
158 | amb | 1699 | textallfile =fopen("shortest-all.txt",open_mode); |
159 | amb | 177 | |
160 | amb | 1784 | #ifndef LIBROUTINO |
161 | if(option_file_html && !htmlfile) | ||
162 | amb | 1465 | fprintf(stderr,"Warning: Cannot open file 'shortest.html' for writing [%s].\n",strerror(errno)); |
163 | amb | 1784 | if(option_file_gpx_track && !gpxtrackfile) |
164 | amb | 1465 | fprintf(stderr,"Warning: Cannot open file 'shortest-track.gpx' for writing [%s].\n",strerror(errno)); |
165 | amb | 1784 | if(option_file_gpx_route && !gpxroutefile) |
166 | amb | 1465 | fprintf(stderr,"Warning: Cannot open file 'shortest-route.gpx' for writing [%s].\n",strerror(errno)); |
167 | amb | 1784 | if(option_file_text && !textfile) |
168 | amb | 1465 | fprintf(stderr,"Warning: Cannot open file 'shortest.txt' for writing [%s].\n",strerror(errno)); |
169 | amb | 1784 | if(option_file_text_all && !textallfile) |
170 | amb | 1465 | fprintf(stderr,"Warning: Cannot open file 'shortest-all.txt' for writing [%s].\n",strerror(errno)); |
171 | amb | 1784 | #endif |
172 | amb | 1465 | } |
173 | else | ||
174 | { | ||
175 | /* Print the result for the quickest route */ | ||
176 | |||
177 | amb | 1784 | if(option_file_html) |
178 | amb | 1699 | htmlfile =fopen("quickest.html",open_mode); |
179 | amb | 1784 | if(option_file_gpx_track) |
180 | amb | 1699 | gpxtrackfile=fopen("quickest-track.gpx",open_mode); |
181 | amb | 1784 | if(option_file_gpx_route) |
182 | amb | 1699 | gpxroutefile=fopen("quickest-route.gpx",open_mode); |
183 | amb | 1784 | if(option_file_text) |
184 | amb | 1699 | textfile =fopen("quickest.txt",open_mode); |
185 | amb | 1784 | if(option_file_text_all) |
186 | amb | 1699 | textallfile =fopen("quickest-all.txt",open_mode); |
187 | amb | 1465 | |
188 | amb | 1784 | #ifndef LIBROUTINO |
189 | if(option_file_html && !htmlfile) | ||
190 | amb | 1465 | fprintf(stderr,"Warning: Cannot open file 'quickest.html' for writing [%s].\n",strerror(errno)); |
191 | amb | 1784 | if(option_file_gpx_track && !gpxtrackfile) |
192 | amb | 1465 | fprintf(stderr,"Warning: Cannot open file 'quickest-track.gpx' for writing [%s].\n",strerror(errno)); |
193 | amb | 1784 | if(option_file_gpx_route && !gpxroutefile) |
194 | amb | 1465 | fprintf(stderr,"Warning: Cannot open file 'quickest-route.gpx' for writing [%s].\n",strerror(errno)); |
195 | amb | 1784 | if(option_file_text && !textfile) |
196 | amb | 1465 | fprintf(stderr,"Warning: Cannot open file 'quickest.txt' for writing [%s].\n",strerror(errno)); |
197 | amb | 1784 | if(option_file_text_all && !textallfile) |
198 | amb | 1465 | fprintf(stderr,"Warning: Cannot open file 'quickest-all.txt' for writing [%s].\n",strerror(errno)); |
199 | amb | 1784 | #endif |
200 | amb | 1465 | } |
201 | amb | 160 | } |
202 | |||
203 | amb | 164 | /* Print the head of the files */ |
204 | amb | 160 | |
205 | amb | 323 | if(htmlfile) |
206 | { | ||
207 | amb | 1505 | 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 | amb | 1784 | 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 | amb | 1505 | fprintf(htmlfile,"<head>\n"); |
216 | fprintf(htmlfile,"<title>"); | ||
217 | amb | 1784 | fprintf(htmlfile,translation->html_title,option_quickest?translation->xml_route_quickest:translation->xml_route_shortest); |
218 | amb | 1505 | 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 | amb | 323 | fprintf(htmlfile,"<!--\n"); |
222 | amb | 376 | 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 | amb | 323 | fprintf(htmlfile,"-->\n"); |
238 | amb | 1505 | fprintf(htmlfile,"</style>\n"); |
239 | fprintf(htmlfile,"</head>\n"); | ||
240 | fprintf(htmlfile,"<body>\n"); | ||
241 | fprintf(htmlfile,"<h1>"); | ||
242 | amb | 1784 | fprintf(htmlfile,translation->html_title,option_quickest?translation->xml_route_quickest:translation->xml_route_shortest); |
243 | amb | 1505 | fprintf(htmlfile,"</h1>\n"); |
244 | amb | 323 | fprintf(htmlfile,"<table>\n"); |
245 | } | ||
246 | |||
247 | amb | 177 | 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 | amb | 160 | |
252 | amb | 177 | fprintf(gpxtrackfile,"<metadata>\n"); |
253 | amb | 1784 | 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 | amb | 376 | { |
256 | amb | 1784 | fprintf(gpxtrackfile,"<copyright author=\"%s\">\n",translation->xml_copyright_source[1]); |
257 | amb | 376 | |
258 | amb | 1784 | if(translation->xml_copyright_license[1]) |
259 | fprintf(gpxtrackfile,"<license>%s</license>\n",translation->xml_copyright_license[1]); | ||
260 | amb | 376 | |
261 | amb | 177 | fprintf(gpxtrackfile,"</copyright>\n"); |
262 | amb | 376 | } |
263 | amb | 177 | fprintf(gpxtrackfile,"</metadata>\n"); |
264 | amb | 160 | |
265 | amb | 177 | fprintf(gpxtrackfile,"<trk>\n"); |
266 | amb | 376 | fprintf(gpxtrackfile,"<name>"); |
267 | amb | 1784 | fprintf(gpxtrackfile,translation->gpx_name,option_quickest?translation->xml_route_quickest:translation->xml_route_shortest); |
268 | amb | 376 | fprintf(gpxtrackfile,"</name>\n"); |
269 | fprintf(gpxtrackfile,"<desc>"); | ||
270 | amb | 1784 | fprintf(gpxtrackfile,translation->gpx_desc,option_quickest?translation->xml_route_quickest:translation->xml_route_shortest); |
271 | amb | 376 | fprintf(gpxtrackfile,"</desc>\n"); |
272 | amb | 177 | } |
273 | amb | 160 | |
274 | amb | 177 | 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 | amb | 160 | |
279 | amb | 177 | fprintf(gpxroutefile,"<metadata>\n"); |
280 | amb | 1784 | 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 | amb | 376 | { |
283 | amb | 1784 | fprintf(gpxroutefile,"<copyright author=\"%s\">\n",translation->xml_copyright_source[1]); |
284 | amb | 376 | |
285 | amb | 1784 | if(translation->xml_copyright_license[1]) |
286 | fprintf(gpxroutefile,"<license>%s</license>\n",translation->xml_copyright_license[1]); | ||
287 | amb | 376 | |
288 | amb | 177 | fprintf(gpxroutefile,"</copyright>\n"); |
289 | amb | 376 | } |
290 | amb | 177 | fprintf(gpxroutefile,"</metadata>\n"); |
291 | amb | 160 | |
292 | amb | 177 | fprintf(gpxroutefile,"<rte>\n"); |
293 | amb | 360 | fprintf(gpxroutefile,"<name>"); |
294 | amb | 1784 | fprintf(gpxroutefile,translation->gpx_name,option_quickest?translation->xml_route_quickest:translation->xml_route_shortest); |
295 | amb | 360 | fprintf(gpxroutefile,"</name>\n"); |
296 | amb | 376 | fprintf(gpxroutefile,"<desc>"); |
297 | amb | 1784 | fprintf(gpxroutefile,translation->gpx_desc,option_quickest?translation->xml_route_quickest:translation->xml_route_shortest); |
298 | amb | 376 | fprintf(gpxroutefile,"</desc>\n"); |
299 | amb | 177 | } |
300 | amb | 160 | |
301 | amb | 177 | if(textfile) |
302 | { | ||
303 | amb | 1784 | 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 | amb | 177 | fprintf(textfile,"#\n"); |
313 | amb | 376 | |
314 | amb | 316 | 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 | amb | 177 | } |
318 | amb | 160 | |
319 | amb | 177 | if(textallfile) |
320 | { | ||
321 | amb | 1784 | 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 | amb | 177 | fprintf(textallfile,"#\n"); |
331 | amb | 376 | |
332 | amb | 316 | 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 | amb | 177 | } |
336 | amb | 160 | |
337 | amb | 1784 | /* Create the head of the linked list */ |
338 | |||
339 | if(option_list_html) | ||
340 | amb | 2188 | listhead=htmllist=calloc(1,sizeof(Routino_Output)); |
341 | amb | 1795 | if(option_list_html_all) |
342 | amb | 2188 | listhead=htmlalllist=htmllist=calloc(1,sizeof(Routino_Output)); |
343 | amb | 1784 | if(option_list_text) |
344 | amb | 2188 | listhead=textlist=calloc(1,sizeof(Routino_Output)); |
345 | amb | 1784 | if(option_list_text_all) |
346 | amb | 2188 | listhead=textalllist=calloc(1,sizeof(Routino_Output)); |
347 | amb | 1784 | |
348 | amb | 922 | /* Loop through all the sections of the route and print them */ |
349 | amb | 164 | |
350 | amb | 1501 | do |
351 | amb | 316 | { |
352 | amb | 1564 | int first=1; |
353 | amb | 922 | int next_point=point; |
354 | amb | 316 | distance_t junc_distance=0; |
355 | duration_t junc_duration=0; | ||
356 | Result *result; | ||
357 | amb | 160 | |
358 | amb | 1564 | #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 | amb | 922 | result=FindResult(results[point],results[point]->start_node,results[point]->prev_segment); |
374 | |||
375 | /* Print the start of the segment */ | ||
376 | |||
377 | amb | 324 | if(gpxtrackfile) |
378 | fprintf(gpxtrackfile,"<trkseg>\n"); | ||
379 | amb | 303 | |
380 | amb | 922 | /* Loop through all the points within a section of the route and print them */ |
381 | amb | 165 | |
382 | amb | 316 | do |
383 | amb | 160 | { |
384 | amb | 316 | double latitude,longitude; |
385 | amb | 1078 | Node *resultnodep=NULL; |
386 | amb | 922 | index_t realsegment=NO_SEGMENT,next_realsegment=NO_SEGMENT; |
387 | amb | 1078 | Segment *resultsegmentp=NULL,*next_resultsegmentp=NULL; |
388 | Way *resultwayp=NULL,*next_resultwayp=NULL; | ||
389 | amb | 922 | Result *next_result; |
390 | amb | 1784 | int important=ROUTINO_POINT_UNIMPORTANT; |
391 | amb | 160 | |
392 | amb | 922 | 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 | amb | 1784 | char *turn=NULL,*turnraw=NULL,*next_bearing=NULL,*next_bearingraw=NULL; |
398 | amb | 922 | |
399 | /* Calculate the information about this point */ | ||
400 | |||
401 | if(IsFakeNode(result->node)) | ||
402 | GetFakeLatLong(result->node,&latitude,&longitude); | ||
403 | amb | 316 | else |
404 | amb | 1447 | { |
405 | amb | 1078 | resultnodep=LookupNode(nodes,result->node,6); |
406 | amb | 171 | |
407 | amb | 1447 | GetLatLong(nodes,result->node,resultnodep,&latitude,&longitude); |
408 | } | ||
409 | |||
410 | amb | 922 | /* Calculate the next result */ |
411 | amb | 171 | |
412 | amb | 922 | next_result=result->next; |
413 | |||
414 | if(!next_result) | ||
415 | amb | 1501 | { |
416 | next_point++; | ||
417 | amb | 171 | |
418 | amb | 1501 | 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 | amb | 922 | /* Calculate the information about this segment */ |
426 | amb | 459 | |
427 | amb | 1580 | if(!first) /* not first point of a section of the route */ |
428 | amb | 169 | { |
429 | amb | 1580 | 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 | amb | 922 | |
440 | amb | 1580 | resultwayp=LookupWay(ways,resultsegmentp->way,1); |
441 | amb | 316 | |
442 | amb | 1168 | seg_distance+=DISTANCE(resultsegmentp->distance); |
443 | amb | 1078 | seg_duration+=Duration(resultsegmentp,resultwayp,profile); |
444 | amb | 922 | |
445 | /* Calculate the cumulative distance/duration */ | ||
446 | |||
447 | amb | 316 | junc_distance+=seg_distance; |
448 | junc_duration+=seg_duration; | ||
449 | cum_distance+=seg_distance; | ||
450 | cum_duration+=seg_duration; | ||
451 | amb | 922 | } |
452 | amb | 316 | |
453 | amb | 922 | /* Calculate the information about the next segment */ |
454 | amb | 316 | |
455 | amb | 922 | if(next_result) |
456 | { | ||
457 | if(IsFakeSegment(next_result->segment)) | ||
458 | { | ||
459 | amb | 1078 | next_resultsegmentp=LookupFakeSegment(next_result->segment); |
460 | amb | 922 | next_realsegment=IndexRealSegment(next_result->segment); |
461 | } | ||
462 | amb | 316 | else |
463 | amb | 303 | { |
464 | amb | 1078 | next_resultsegmentp=LookupSegment(segments,next_result->segment,1); |
465 | amb | 922 | next_realsegment=next_result->segment; |
466 | } | ||
467 | } | ||
468 | amb | 160 | |
469 | amb | 926 | /* Decide if this is a roundabout */ |
470 | |||
471 | if(next_result) | ||
472 | { | ||
473 | amb | 1078 | next_resultwayp=LookupWay(ways,next_resultsegmentp->way,2); |
474 | amb | 926 | |
475 | amb | 1174 | if(next_resultwayp->type&Highway_Roundabout) |
476 | amb | 926 | { |
477 | if(roundabout==0) | ||
478 | { | ||
479 | roundabout++; | ||
480 | amb | 1784 | important=ROUTINO_POINT_RB_ENTRY; |
481 | amb | 926 | } |
482 | else | ||
483 | { | ||
484 | amb | 1539 | Segment *segmentp; |
485 | amb | 926 | |
486 | amb | 1539 | if(resultnodep) |
487 | segmentp=FirstSegment(segments,resultnodep,3); | ||
488 | else | ||
489 | segmentp=FirstFakeSegment(result->node); | ||
490 | |||
491 | amb | 926 | do |
492 | { | ||
493 | amb | 1078 | index_t othernode=OtherNode(segmentp,result->node); |
494 | amb | 1539 | index_t thissegment; |
495 | amb | 926 | |
496 | amb | 1539 | if(IsFakeNode(result->node)) |
497 | thissegment=IndexFakeSegment(segmentp); | ||
498 | else | ||
499 | thissegment=IndexSegment(segments,segmentp); | ||
500 | |||
501 | amb | 1543 | 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 | amb | 926 | { |
508 | amb | 1989 | if(profile->transports!=Transports_Bicycle) |
509 | amb | 1543 | canexit=0; |
510 | else | ||
511 | { | ||
512 | Way *wayp=LookupWay(ways,segmentp->way,3); | ||
513 | |||
514 | amb | 1559 | if(!(wayp->type&Highway_CycleBothWays)) |
515 | amb | 1543 | canexit=0; |
516 | } | ||
517 | } | ||
518 | |||
519 | if(canexit) | ||
520 | { | ||
521 | amb | 1078 | Way *wayp=LookupWay(ways,segmentp->way,3); |
522 | amb | 926 | |
523 | amb | 1174 | if(!(wayp->type&Highway_Roundabout)) |
524 | amb | 1543 | { |
525 | roundabout++; | ||
526 | amb | 1784 | important=ROUTINO_POINT_RB_NOT_EXIT; |
527 | amb | 1543 | } |
528 | amb | 926 | } |
529 | amb | 1543 | } |
530 | amb | 926 | |
531 | amb | 1539 | if(resultnodep) |
532 | segmentp=NextSegment(segments,segmentp,result->node); | ||
533 | else | ||
534 | segmentp=NextFakeSegment(segmentp,result->node); | ||
535 | amb | 926 | } |
536 | amb | 1078 | while(segmentp); |
537 | amb | 926 | } |
538 | } | ||
539 | else | ||
540 | if(roundabout) | ||
541 | { | ||
542 | roundabout++; | ||
543 | amb | 1784 | important=ROUTINO_POINT_RB_EXIT; |
544 | amb | 926 | } |
545 | } | ||
546 | |||
547 | amb | 922 | /* Decide if this is an important junction */ |
548 | amb | 303 | |
549 | amb | 1539 | if(point_count==0) /* first point overall = Waypoint */ |
550 | amb | 1784 | important=ROUTINO_POINT_WAYPOINT; |
551 | amb | 1564 | else if(result->next==NULL) /* Waypoint */ |
552 | amb | 1784 | important=ROUTINO_POINT_WAYPOINT; |
553 | amb | 1564 | else if(first) /* first point of a section of the route */ |
554 | amb | 1784 | important=ROUTINO_POINT_IGNORE; |
555 | amb | 1539 | else if(roundabout) /* roundabout */ |
556 | ; | ||
557 | amb | 922 | else if(realsegment==next_realsegment) /* U-turn */ |
558 | amb | 1784 | important=ROUTINO_POINT_UTURN; |
559 | amb | 1078 | else if(resultnodep && (resultnodep->flags&NODE_MINIRNDBT)) |
560 | amb | 1784 | important=ROUTINO_POINT_MINI_RB; /* mini-roundabout */ |
561 | amb | 1935 | else if(resultnodep) |
562 | amb | 922 | { |
563 | amb | 1078 | Segment *segmentp=FirstSegment(segments,resultnodep,3); |
564 | amb | 316 | |
565 | amb | 922 | do |
566 | { | ||
567 | amb | 1078 | index_t seg=IndexSegment(segments,segmentp); |
568 | amb | 316 | |
569 | amb | 1543 | if(seg!=realsegment && IsNormalSegment(segmentp)) |
570 | { | ||
571 | int cango=1; | ||
572 | |||
573 | if(profile->oneway && IsOnewayTo(segmentp,result->node)) | ||
574 | amb | 922 | { |
575 | amb | 1989 | if(profile->transports!=Transports_Bicycle) |
576 | amb | 1543 | cango=0; |
577 | else | ||
578 | { | ||
579 | Way *wayp=LookupWay(ways,segmentp->way,3); | ||
580 | |||
581 | amb | 1559 | if(!(wayp->type&Highway_CycleBothWays)) |
582 | amb | 1543 | cango=0; |
583 | } | ||
584 | } | ||
585 | |||
586 | amb | 1878 | if(profile->turns && IsSuperNode(resultnodep) && IsTurnRestrictedNode(resultnodep)) |
587 | { | ||
588 | index_t turnrelation=FindFirstTurnRelation2(relations,result->node,realsegment); | ||
589 | |||
590 | amb | 1989 | if(turnrelation!=NO_RELATION && !IsTurnAllowed(relations,turnrelation,result->node,realsegment,seg,profile->transports)) |
591 | amb | 1878 | cango=0; |
592 | } | ||
593 | |||
594 | amb | 1543 | if(cango) |
595 | { | ||
596 | amb | 1078 | Way *wayp=LookupWay(ways,segmentp->way,3); |
597 | amb | 922 | |
598 | amb | 1074 | if(seg==next_realsegment) /* the next segment that we follow */ |
599 | amb | 922 | { |
600 | amb | 1078 | if(HIGHWAY(wayp->type)!=HIGHWAY(resultwayp->type)) |
601 | amb | 1784 | if(important<ROUTINO_POINT_CHANGE) |
602 | important=ROUTINO_POINT_CHANGE; | ||
603 | amb | 303 | } |
604 | amb | 922 | else /* a segment that we don't follow */ |
605 | { | ||
606 | amb | 1078 | if(junction_other_way[HIGHWAY(resultwayp->type)-1][HIGHWAY(wayp->type)-1]) |
607 | amb | 1784 | if(important<ROUTINO_POINT_JUNCT_IMPORT) |
608 | important=ROUTINO_POINT_JUNCT_IMPORT; | ||
609 | amb | 160 | |
610 | amb | 1784 | if(important<ROUTINO_POINT_JUNCT_CONT) |
611 | important=ROUTINO_POINT_JUNCT_CONT; | ||
612 | amb | 922 | } |
613 | } | ||
614 | amb | 1543 | } |
615 | amb | 922 | |
616 | amb | 1078 | segmentp=NextSegment(segments,segmentp,result->node); |
617 | amb | 303 | } |
618 | amb | 1078 | while(segmentp); |
619 | amb | 922 | } |
620 | amb | 169 | |
621 | amb | 922 | /* Calculate the strings to be used */ |
622 | amb | 169 | |
623 | amb | 1784 | if(!first && (textallfile || textalllist)) |
624 | amb | 922 | { |
625 | amb | 1078 | waynameraw=WayName(ways,resultwayp); |
626 | amb | 922 | if(!*waynameraw) |
627 | amb | 1784 | waynameraw=translation->raw_highway[HIGHWAY(resultwayp->type)]; |
628 | amb | 922 | |
629 | amb | 1078 | bearing_int=(int)BearingAngle(nodes,resultsegmentp,result->node); |
630 | amb | 922 | |
631 | amb | 1078 | seg_speed=profile->speed[HIGHWAY(resultwayp->type)]; |
632 | amb | 922 | } |
633 | |||
634 | amb | 1795 | if(next_result && (important>ROUTINO_POINT_JUNCT_CONT || htmlalllist)) |
635 | amb | 922 | { |
636 | amb | 1784 | if(!first && (htmlfile || htmllist || textfile || textlist)) |
637 | amb | 177 | { |
638 | amb | 1565 | 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 | amb | 1784 | turn =translation->xml_turn[((202+turn_int)/45)%8]; |
644 | turnraw=translation->notxml_turn[((202+turn_int)/45)%8]; | ||
645 | amb | 922 | } |
646 | amb | 303 | |
647 | amb | 1784 | if(gpxroutefile || htmlfile || htmllist) |
648 | amb | 922 | { |
649 | amb | 1078 | next_waynameraw=WayName(ways,next_resultwayp); |
650 | amb | 922 | if(!*next_waynameraw) |
651 | amb | 1784 | next_waynameraw=translation->raw_highway[HIGHWAY(next_resultwayp->type)]; |
652 | amb | 378 | |
653 | amb | 922 | next_wayname=ParseXML_Encode_Safe_XML(next_waynameraw); |
654 | } | ||
655 | amb | 411 | |
656 | amb | 1784 | if(htmlfile || htmllist || gpxroutefile || textfile || textlist) |
657 | amb | 922 | { |
658 | amb | 1580 | if(!first && DISTANCE(next_resultsegmentp->distance)==0) |
659 | amb | 1565 | 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 | amb | 1784 | 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 | amb | 922 | } |
666 | } | ||
667 | amb | 378 | |
668 | amb | 922 | /* Print out the important points (junctions / waypoints) */ |
669 | |||
670 | amb | 1784 | if(important>ROUTINO_POINT_JUNCT_CONT) |
671 | amb | 922 | { |
672 | if(htmlfile) | ||
673 | { | ||
674 | char *type; | ||
675 | |||
676 | amb | 1784 | if(important==ROUTINO_POINT_WAYPOINT) |
677 | amb | 1815 | { |
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 | amb | 1784 | else if(important==ROUTINO_POINT_MINI_RB) |
684 | type=translation->html_roundabout; | ||
685 | amb | 922 | else |
686 | amb | 1784 | type=translation->html_junction; |
687 | amb | 922 | |
688 | if(point_count>0) /* not the first point */ | ||
689 | { | ||
690 | amb | 1796 | /* <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 | amb | 1784 | fprintf(htmlfile,translation->html_segment, |
692 | (roundabout>1?translation->html_roundabout:prev_wayname), | ||
693 | amb | 922 | distance_to_km(junc_distance),duration_to_minutes(junc_duration)); |
694 | amb | 1784 | fprintf(htmlfile,translation->html_subtotal, |
695 | amb | 922 | distance_to_km(cum_distance),duration_to_minutes(cum_duration)); |
696 | } | ||
697 | amb | 378 | |
698 | amb | 1796 | /* <tr class='c'>*N*: *latitude* *longitude* */ |
699 | fprintf(htmlfile,"<tr class='c'><td>%d: %.6f %.6f\n", | ||
700 | amb | 922 | point_count+1, |
701 | radians_to_degrees(latitude),radians_to_degrees(longitude)); | ||
702 | amb | 378 | |
703 | amb | 922 | if(point_count==0) /* first point */ |
704 | { | ||
705 | amb | 1796 | /* <tr class='n'><td>Start at <span class='w'>Waypoint</span>, head <span class='b'>*heading*</span> */ |
706 | amb | 1784 | fprintf(htmlfile,translation->html_start, |
707 | amb | 1815 | type, |
708 | amb | 922 | next_bearing); |
709 | } | ||
710 | else if(next_result) /* middle point */ | ||
711 | { | ||
712 | amb | 1784 | if(roundabout>1 && important!=ROUTINO_POINT_WAYPOINT) |
713 | amb | 926 | { |
714 | amb | 1796 | /* <tr class='n'><td>leave roundabout, take <span class='t'>the *Nth* exit</span> heading <span class='b'>*heading*</span> */ |
715 | amb | 1784 | fprintf(htmlfile,translation->html_rbnode, |
716 | translation->html_roundabout, | ||
717 | translation->xml_ordinal[roundabout-2], | ||
718 | amb | 926 | next_bearing); |
719 | } | ||
720 | else | ||
721 | { | ||
722 | amb | 1815 | /* <tr class='n'><td>At *waypoint/roundabout/junction*, go <span class='t'>*direction*</span> heading <span class='b'>*heading*</span> */ |
723 | amb | 1784 | fprintf(htmlfile,translation->html_node, |
724 | amb | 926 | type, |
725 | turn, | ||
726 | next_bearing); | ||
727 | } | ||
728 | amb | 922 | } |
729 | else /* end point */ | ||
730 | { | ||
731 | amb | 1796 | /* <tr class='n'><td>Stop at <span class='w'>Waypoint</span> */ |
732 | amb | 1784 | fprintf(htmlfile,translation->html_stop, |
733 | amb | 1815 | type); |
734 | amb | 378 | |
735 | amb | 1796 | /* <tr class='t'><td><span class='j'>Total *distance* km, *time* minutes</span> */ |
736 | amb | 1784 | fprintf(htmlfile,translation->html_total, |
737 | amb | 922 | distance_to_km(cum_distance),duration_to_minutes(cum_duration)); |
738 | amb | 378 | } |
739 | amb | 1815 | |
740 | if(important==ROUTINO_POINT_WAYPOINT) | ||
741 | free(type); | ||
742 | amb | 922 | } |
743 | amb | 378 | |
744 | amb | 1784 | if(htmllist) |
745 | { | ||
746 | int strl; | ||
747 | char *type; | ||
748 | |||
749 | if(important==ROUTINO_POINT_WAYPOINT) | ||
750 | amb | 1815 | { |
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 | amb | 1784 | 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 | amb | 1795 | if(htmlalllist) |
782 | htmllist=htmlalllist; | ||
783 | amb | 1784 | |
784 | amb | 2188 | htmllist->next=calloc(1,sizeof(Routino_Output)); |
785 | amb | 1784 | htmllist=htmllist->next; |
786 | amb | 1795 | |
787 | if(htmlalllist) | ||
788 | htmlalllist=htmllist; | ||
789 | amb | 1784 | } |
790 | |||
791 | htmllist->lon=longitude; | ||
792 | htmllist->lat=latitude; | ||
793 | htmllist->type=important; | ||
794 | amb | 1795 | htmllist->dist=distance_to_km(cum_distance); |
795 | htmllist->time=duration_to_minutes(cum_duration); | ||
796 | amb | 1784 | |
797 | if(point_count==0) /* first point */ | ||
798 | { | ||
799 | /* Start: At Waypoint, head *heading* */ | ||
800 | strl=strlen(translation->nothtml_start)+ | ||
801 | amb | 1815 | strlen(type)+strlen(next_bearingraw)+1; |
802 | amb | 1784 | |
803 | htmllist->desc1=malloc(strl); | ||
804 | |||
805 | sprintf(htmllist->desc1,translation->nothtml_start, | ||
806 | amb | 1815 | type, |
807 | amb | 1784 | 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 | amb | 1815 | /* At: Waypoint/Roundabout/Junction, go *direction* heading *heading* */ |
829 | amb | 1784 | 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 | amb | 1815 | strlen(type)+1; |
848 | amb | 1784 | |
849 | htmllist->desc1=malloc(strl); | ||
850 | |||
851 | sprintf(htmllist->desc1,translation->nothtml_stop, | ||
852 | amb | 1815 | type); |
853 | amb | 1784 | |
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 | amb | 1815 | |
867 | if(important==ROUTINO_POINT_WAYPOINT) | ||
868 | free(type); | ||
869 | amb | 1784 | } |
870 | |||
871 | amb | 922 | if(gpxroutefile) |
872 | { | ||
873 | if(point_count>0) /* not first point */ | ||
874 | amb | 332 | { |
875 | amb | 378 | fprintf(gpxroutefile,"<desc>"); |
876 | amb | 1784 | fprintf(gpxroutefile,translation->gpx_step, |
877 | amb | 922 | prev_bearing, |
878 | prev_wayname, | ||
879 | amb | 378 | distance_to_km(junc_distance),duration_to_minutes(junc_duration)); |
880 | fprintf(gpxroutefile,"</desc></rtept>\n"); | ||
881 | amb | 922 | } |
882 | amb | 316 | |
883 | amb | 922 | if(point_count==0) /* first point */ |
884 | { | ||
885 | amb | 1815 | fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%02d</name>\n", |
886 | amb | 922 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
887 | amb | 1815 | translation->gpx_waypt,results[point]->start_waypoint); |
888 | amb | 922 | } |
889 | else if(!next_result) /* end point */ | ||
890 | { | ||
891 | amb | 1815 | fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%02d</name>\n", |
892 | amb | 922 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
893 | amb | 1815 | translation->gpx_waypt,results[point]->finish_waypoint); |
894 | amb | 922 | fprintf(gpxroutefile,"<desc>"); |
895 | amb | 1784 | fprintf(gpxroutefile,translation->gpx_final, |
896 | amb | 922 | distance_to_km(cum_distance),duration_to_minutes(cum_duration)); |
897 | fprintf(gpxroutefile,"</desc></rtept>\n"); | ||
898 | } | ||
899 | else /* middle point */ | ||
900 | { | ||
901 | amb | 1784 | if(important==ROUTINO_POINT_WAYPOINT) |
902 | amb | 1815 | fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%02d</name>\n", |
903 | amb | 378 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
904 | amb | 1815 | translation->gpx_waypt,results[point]->finish_waypoint); |
905 | amb | 332 | else |
906 | amb | 360 | fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%03d</name>\n", |
907 | amb | 378 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
908 | amb | 1815 | translation->gpx_trip,point_count); |
909 | amb | 332 | } |
910 | amb | 922 | } |
911 | amb | 316 | |
912 | amb | 922 | if(textfile) |
913 | { | ||
914 | char *type; | ||
915 | amb | 316 | |
916 | amb | 1784 | if(important==ROUTINO_POINT_WAYPOINT) |
917 | amb | 1815 | { |
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 | amb | 922 | else |
925 | type="Junct"; | ||
926 | amb | 316 | |
927 | amb | 922 | 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 | amb | 1815 | |
956 | if(important==ROUTINO_POINT_WAYPOINT) | ||
957 | free(type); | ||
958 | amb | 922 | } |
959 | amb | 322 | |
960 | amb | 1784 | 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 | amb | 2188 | textlist->next=calloc(1,sizeof(Routino_Output)); |
969 | amb | 1784 | |
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 | amb | 2188 | textlist->next=calloc(1,sizeof(Routino_Output)); |
983 | amb | 1784 | |
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 | amb | 922 | junc_distance=0; |
995 | junc_duration=0; | ||
996 | amb | 322 | |
997 | amb | 1784 | if(htmlfile || htmllist || gpxroutefile) |
998 | amb | 922 | { |
999 | if(prev_wayname) | ||
1000 | free(prev_wayname); | ||
1001 | amb | 322 | |
1002 | amb | 922 | if(next_wayname) |
1003 | prev_wayname=strcpy((char*)malloc(strlen(next_wayname)+1),next_wayname); | ||
1004 | else | ||
1005 | prev_wayname=NULL; | ||
1006 | amb | 316 | |
1007 | amb | 1784 | 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 | amb | 165 | } |
1015 | amb | 160 | |
1016 | amb | 922 | if(gpxroutefile) |
1017 | prev_bearing=next_bearing; | ||
1018 | amb | 926 | |
1019 | if(roundabout>1) | ||
1020 | roundabout=0; | ||
1021 | amb | 922 | } |
1022 | amb | 1795 | else |
1023 | { | ||
1024 | if(htmlalllist) | ||
1025 | { | ||
1026 | amb | 2188 | htmlalllist->next=calloc(1,sizeof(Routino_Output)); |
1027 | amb | 1795 | htmlalllist=htmlalllist->next; |
1028 | amb | 303 | |
1029 | amb | 1795 | 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 | amb | 922 | /* 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 | amb | 1784 | if(important>ROUTINO_POINT_IGNORE) |
1046 | amb | 922 | { |
1047 | amb | 316 | if(textallfile) |
1048 | { | ||
1049 | char *type; | ||
1050 | |||
1051 | amb | 1784 | if(important==ROUTINO_POINT_WAYPOINT) |
1052 | amb | 1815 | { |
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 | amb | 1784 | else if(important==ROUTINO_POINT_UTURN) |
1058 | amb | 926 | type="U-turn"; |
1059 | amb | 1784 | else if(important==ROUTINO_POINT_MINI_RB) |
1060 | amb | 929 | type="Mini-RB"; |
1061 | amb | 1784 | else if(important==ROUTINO_POINT_CHANGE) |
1062 | amb | 316 | type="Change"; |
1063 | amb | 1784 | else if(important==ROUTINO_POINT_JUNCT_CONT || important==ROUTINO_POINT_RB_NOT_EXIT) |
1064 | amb | 1075 | type="Junct-"; |
1065 | amb | 1784 | else if(important==ROUTINO_POINT_UNIMPORTANT) |
1066 | amb | 927 | type="Inter"; |
1067 | else | ||
1068 | amb | 316 | type="Junct"; |
1069 | |||
1070 | amb | 922 | if(point_count==0) /* first point */ |
1071 | amb | 474 | { |
1072 | amb | 2192 | 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 | amb | 474 | } |
1085 | amb | 927 | else /* not the first point */ |
1086 | amb | 378 | { |
1087 | amb | 2192 | 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 | amb | 378 | } |
1108 | amb | 1815 | |
1109 | if(important==ROUTINO_POINT_WAYPOINT) | ||
1110 | free(type); | ||
1111 | amb | 316 | } |
1112 | amb | 1784 | |
1113 | if(textalllist) | ||
1114 | { | ||
1115 | if(point_count==0) /* first point */ | ||
1116 | ; | ||
1117 | else /* not the first point */ | ||
1118 | { | ||
1119 | amb | 2188 | textalllist->next=calloc(1,sizeof(Routino_Output)); |
1120 | amb | 1784 | 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 | amb | 160 | } |
1134 | amb | 378 | |
1135 | amb | 922 | if(wayname && wayname!=waynameraw) |
1136 | free(wayname); | ||
1137 | amb | 160 | |
1138 | amb | 922 | result=next_result; |
1139 | amb | 323 | |
1140 | amb | 1784 | if(important>ROUTINO_POINT_JUNCT_CONT) |
1141 | amb | 922 | point_count++; |
1142 | amb | 1564 | |
1143 | first=0; | ||
1144 | amb | 922 | } |
1145 | while(point==next_point); | ||
1146 | amb | 171 | |
1147 | amb | 922 | /* Print the end of the segment */ |
1148 | amb | 171 | |
1149 | amb | 316 | if(gpxtrackfile) |
1150 | fprintf(gpxtrackfile,"</trkseg>\n"); | ||
1151 | amb | 160 | |
1152 | amb | 922 | point=next_point; |
1153 | amb | 1539 | |
1154 | if(result) | ||
1155 | prev_node=result->node; | ||
1156 | else | ||
1157 | prev_node=NO_NODE; | ||
1158 | amb | 160 | } |
1159 | amb | 1501 | while(point<nresults); |
1160 | amb | 160 | |
1161 | amb | 164 | /* Print the tail of the files */ |
1162 | |||
1163 | amb | 323 | if(htmlfile) |
1164 | { | ||
1165 | fprintf(htmlfile,"</table>\n"); | ||
1166 | amb | 376 | |
1167 | amb | 1784 | 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 | amb | 376 | { |
1171 | fprintf(htmlfile,"<p>\n"); | ||
1172 | fprintf(htmlfile,"<table class='c'>\n"); | ||
1173 | amb | 1784 | 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 | amb | 376 | fprintf(htmlfile,"</table>\n"); |
1180 | } | ||
1181 | |||
1182 | amb | 1505 | fprintf(htmlfile,"</body>\n"); |
1183 | fprintf(htmlfile,"</html>\n"); | ||
1184 | amb | 323 | } |
1185 | |||
1186 | amb | 177 | if(gpxtrackfile) |
1187 | { | ||
1188 | fprintf(gpxtrackfile,"</trk>\n"); | ||
1189 | fprintf(gpxtrackfile,"</gpx>\n"); | ||
1190 | } | ||
1191 | amb | 160 | |
1192 | amb | 177 | if(gpxroutefile) |
1193 | { | ||
1194 | fprintf(gpxroutefile,"</rte>\n"); | ||
1195 | fprintf(gpxroutefile,"</gpx>\n"); | ||
1196 | } | ||
1197 | amb | 160 | |
1198 | amb | 164 | /* Close the files */ |
1199 | |||
1200 | amb | 1784 | if(!option_file_stdout) |
1201 | amb | 1465 | { |
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 | amb | 1784 | |
1214 | return(listhead); | ||
1215 | amb | 160 | } |
Properties
Name | Value |
---|---|
cvs:description | New file to contain the function to print the output. |