Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /branches/MS-Windows/src/output.c
Parent Directory
|
Revision Log
Revision 1696 -
(show annotations)
(download)
(as text)
Sat May 30 17:21:45 2015 UTC (9 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 38999 byte(s)
Sat May 30 17:21:45 2015 UTC (9 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 38999 byte(s)
Open files in binary mode for MSVC and MinGW.
1 | /*************************************** |
2 | Routing output generator. |
3 | |
4 | Part of the Routino routing software. |
5 | ******************/ /****************** |
6 | This file Copyright 2008-2015 Andrew M. Bishop |
7 | |
8 | This program is free software: you can redistribute it and/or modify |
9 | it under the terms of the GNU Affero General Public License as published by |
10 | the Free Software Foundation, either version 3 of the License, or |
11 | (at your option) any later version. |
12 | |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU Affero General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU Affero General Public License |
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | ***************************************/ |
21 | |
22 | |
23 | #include <stdlib.h> |
24 | #include <string.h> |
25 | #include <ctype.h> |
26 | #include <stdio.h> |
27 | #include <math.h> |
28 | #include <errno.h> |
29 | |
30 | #include "types.h" |
31 | #include "nodes.h" |
32 | #include "segments.h" |
33 | #include "ways.h" |
34 | |
35 | #include "functions.h" |
36 | #include "fakes.h" |
37 | #include "translations.h" |
38 | #include "results.h" |
39 | #include "xmlparse.h" |
40 | |
41 | |
42 | #define DEBUG 0 |
43 | |
44 | /* Constants */ |
45 | |
46 | #define IMP_IGNORE -1 /*+ Ignore this point. +*/ |
47 | #define IMP_UNIMPORTANT 0 /*+ An unimportant, intermediate, node. +*/ |
48 | #define IMP_RB_NOT_EXIT 1 /*+ A roundabout exit that is not taken. +*/ |
49 | #define IMP_JUNCT_CONT 2 /*+ An un-interesting junction where the route continues without comment. +*/ |
50 | #define IMP_CHANGE 3 /*+ The highway changes type but nothing else happens. +*/ |
51 | #define IMP_JUNCT_IMPORT 4 /*+ An interesting junction to be described. +*/ |
52 | #define IMP_RB_ENTRY 5 /*+ The entrance to a roundabout. +*/ |
53 | #define IMP_RB_EXIT 6 /*+ The exit from a roundabout. +*/ |
54 | #define IMP_MINI_RB 7 /*+ The location of a mini-roundabout. +*/ |
55 | #define IMP_UTURN 8 /*+ The location of a U-turn. +*/ |
56 | #define IMP_WAYPOINT 9 /*+ A waypoint. +*/ |
57 | |
58 | |
59 | /* Global variables */ |
60 | |
61 | /*+ The option to calculate the quickest route insted of the shortest. +*/ |
62 | extern int option_quickest; |
63 | |
64 | /*+ The options to select the format of the output. +*/ |
65 | extern int option_html,option_gpx_track,option_gpx_route,option_text,option_text_all,option_stdout; |
66 | |
67 | |
68 | /* Local variables */ |
69 | |
70 | /*+ Heuristics for determining if a junction is important. +*/ |
71 | static const char junction_other_way[Highway_Count][Highway_Count]= |
72 | { /* M, T, P, S, T, U, R, S, T, C, P, S, F = Way type of route not taken */ |
73 | { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Motorway */ |
74 | { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Trunk */ |
75 | { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Primary */ |
76 | { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Secondary */ |
77 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Tertiary */ |
78 | { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1 }, /* Unclassified */ |
79 | { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1 }, /* Residential */ |
80 | { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1 }, /* Service */ |
81 | { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1 }, /* Track */ |
82 | { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1 }, /* Cycleway */ |
83 | { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Path */ |
84 | { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Steps */ |
85 | { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Ferry */ |
86 | }; |
87 | |
88 | |
89 | /*++++++++++++++++++++++++++++++++++++++ |
90 | Print the optimum route between two nodes. |
91 | |
92 | Results **results The set of results to print (consecutive in array even if not consecutive waypoints). |
93 | |
94 | int nresults The number of results in the list. |
95 | |
96 | Nodes *nodes The set of nodes to use. |
97 | |
98 | Segments *segments The set of segments to use. |
99 | |
100 | Ways *ways The set of ways to use. |
101 | |
102 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
103 | ++++++++++++++++++++++++++++++++++++++*/ |
104 | |
105 | void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,Ways *ways,Profile *profile) |
106 | { |
107 | FILE *htmlfile=NULL,*gpxtrackfile=NULL,*gpxroutefile=NULL,*textfile=NULL,*textallfile=NULL; |
108 | |
109 | char *prev_bearing=NULL,*prev_wayname=NULL; |
110 | index_t prev_node=NO_NODE; |
111 | distance_t cum_distance=0; |
112 | duration_t cum_duration=0; |
113 | |
114 | int point=0; |
115 | int segment_count=0,route_count=0; |
116 | int point_count=0; |
117 | int roundabout=0; |
118 | |
119 | /* Open the files */ |
120 | |
121 | if(option_stdout) |
122 | { |
123 | if(option_html) |
124 | htmlfile =stdout; |
125 | if(option_gpx_track) |
126 | gpxtrackfile=stdout; |
127 | if(option_gpx_route) |
128 | gpxroutefile=stdout; |
129 | if(option_text) |
130 | textfile =stdout; |
131 | if(option_text_all) |
132 | textallfile =stdout; |
133 | } |
134 | else |
135 | { |
136 | #if defined(_MSC_VER) || defined(__MINGW32__) |
137 | const char *open_mode="wb"; |
138 | #else |
139 | const char *open_mode="w"; |
140 | #endif |
141 | |
142 | if(option_quickest==0) |
143 | { |
144 | /* Print the result for the shortest route */ |
145 | |
146 | if(option_html) |
147 | htmlfile =fopen("shortest.html",open_mode); |
148 | if(option_gpx_track) |
149 | gpxtrackfile=fopen("shortest-track.gpx",open_mode); |
150 | if(option_gpx_route) |
151 | gpxroutefile=fopen("shortest-route.gpx",open_mode); |
152 | if(option_text) |
153 | textfile =fopen("shortest.txt",open_mode); |
154 | if(option_text_all) |
155 | textallfile =fopen("shortest-all.txt",open_mode); |
156 | |
157 | if(option_html && !htmlfile) |
158 | fprintf(stderr,"Warning: Cannot open file 'shortest.html' for writing [%s].\n",strerror(errno)); |
159 | if(option_gpx_track && !gpxtrackfile) |
160 | fprintf(stderr,"Warning: Cannot open file 'shortest-track.gpx' for writing [%s].\n",strerror(errno)); |
161 | if(option_gpx_route && !gpxroutefile) |
162 | fprintf(stderr,"Warning: Cannot open file 'shortest-route.gpx' for writing [%s].\n",strerror(errno)); |
163 | if(option_text && !textfile) |
164 | fprintf(stderr,"Warning: Cannot open file 'shortest.txt' for writing [%s].\n",strerror(errno)); |
165 | if(option_text_all && !textallfile) |
166 | fprintf(stderr,"Warning: Cannot open file 'shortest-all.txt' for writing [%s].\n",strerror(errno)); |
167 | } |
168 | else |
169 | { |
170 | /* Print the result for the quickest route */ |
171 | |
172 | if(option_html) |
173 | htmlfile =fopen("quickest.html",open_mode); |
174 | if(option_gpx_track) |
175 | gpxtrackfile=fopen("quickest-track.gpx",open_mode); |
176 | if(option_gpx_route) |
177 | gpxroutefile=fopen("quickest-route.gpx",open_mode); |
178 | if(option_text) |
179 | textfile =fopen("quickest.txt",open_mode); |
180 | if(option_text_all) |
181 | textallfile =fopen("quickest-all.txt",open_mode); |
182 | |
183 | if(option_html && !htmlfile) |
184 | fprintf(stderr,"Warning: Cannot open file 'quickest.html' for writing [%s].\n",strerror(errno)); |
185 | if(option_gpx_track && !gpxtrackfile) |
186 | fprintf(stderr,"Warning: Cannot open file 'quickest-track.gpx' for writing [%s].\n",strerror(errno)); |
187 | if(option_gpx_route && !gpxroutefile) |
188 | fprintf(stderr,"Warning: Cannot open file 'quickest-route.gpx' for writing [%s].\n",strerror(errno)); |
189 | if(option_text && !textfile) |
190 | fprintf(stderr,"Warning: Cannot open file 'quickest.txt' for writing [%s].\n",strerror(errno)); |
191 | if(option_text_all && !textallfile) |
192 | fprintf(stderr,"Warning: Cannot open file 'quickest-all.txt' for writing [%s].\n",strerror(errno)); |
193 | } |
194 | } |
195 | |
196 | /* Print the head of the files */ |
197 | |
198 | if(htmlfile) |
199 | { |
200 | fprintf(htmlfile,"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n"); |
201 | fprintf(htmlfile,"<html>\n"); |
202 | if(translate_xml_copyright_creator[0] && translate_xml_copyright_creator[1]) |
203 | fprintf(htmlfile,"<!-- %s : %s -->\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]); |
204 | if(translate_xml_copyright_source[0] && translate_xml_copyright_source[1]) |
205 | fprintf(htmlfile,"<!-- %s : %s -->\n",translate_xml_copyright_source[0],translate_xml_copyright_source[1]); |
206 | if(translate_xml_copyright_license[0] && translate_xml_copyright_license[1]) |
207 | fprintf(htmlfile,"<!-- %s : %s -->\n",translate_xml_copyright_license[0],translate_xml_copyright_license[1]); |
208 | fprintf(htmlfile,"<head>\n"); |
209 | fprintf(htmlfile,"<title>"); |
210 | fprintf(htmlfile,translate_html_title,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); |
211 | fprintf(htmlfile,"</title>\n"); |
212 | fprintf(htmlfile,"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"); |
213 | fprintf(htmlfile,"<style type=\"text/css\">\n"); |
214 | fprintf(htmlfile,"<!--\n"); |
215 | fprintf(htmlfile," table {table-layout: fixed; border: none; border-collapse: collapse;}\n"); |
216 | fprintf(htmlfile," table.c {color: grey; font-size: x-small;} /* copyright */\n"); |
217 | fprintf(htmlfile," tr {border: 0px;}\n"); |
218 | fprintf(htmlfile," tr.c {display: none;} /* coords */\n"); |
219 | fprintf(htmlfile," tr.n {} /* node */\n"); |
220 | fprintf(htmlfile," tr.s {} /* segment */\n"); |
221 | fprintf(htmlfile," tr.t {font-weight: bold;} /* total */\n"); |
222 | fprintf(htmlfile," td.l {font-weight: bold;}\n"); |
223 | fprintf(htmlfile," td.r {}\n"); |
224 | fprintf(htmlfile," span.w {font-weight: bold;} /* waypoint */\n"); |
225 | fprintf(htmlfile," span.h {text-decoration: underline;} /* highway */\n"); |
226 | fprintf(htmlfile," span.d {} /* segment distance */\n"); |
227 | fprintf(htmlfile," span.j {font-style: italic;} /* total journey distance */\n"); |
228 | fprintf(htmlfile," span.t {font-variant: small-caps;} /* turn */\n"); |
229 | fprintf(htmlfile," span.b {font-variant: small-caps;} /* bearing */\n"); |
230 | fprintf(htmlfile,"-->\n"); |
231 | fprintf(htmlfile,"</style>\n"); |
232 | fprintf(htmlfile,"</head>\n"); |
233 | fprintf(htmlfile,"<body>\n"); |
234 | fprintf(htmlfile,"<h1>"); |
235 | fprintf(htmlfile,translate_html_title,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); |
236 | fprintf(htmlfile,"</h1>\n"); |
237 | fprintf(htmlfile,"<table>\n"); |
238 | } |
239 | |
240 | if(gpxtrackfile) |
241 | { |
242 | fprintf(gpxtrackfile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); |
243 | 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"); |
244 | |
245 | fprintf(gpxtrackfile,"<metadata>\n"); |
246 | fprintf(gpxtrackfile,"<desc>%s : %s</desc>\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]); |
247 | if(translate_xml_copyright_source[1]) |
248 | { |
249 | fprintf(gpxtrackfile,"<copyright author=\"%s\">\n",translate_xml_copyright_source[1]); |
250 | |
251 | if(translate_xml_copyright_license[1]) |
252 | fprintf(gpxtrackfile,"<license>%s</license>\n",translate_xml_copyright_license[1]); |
253 | |
254 | fprintf(gpxtrackfile,"</copyright>\n"); |
255 | } |
256 | fprintf(gpxtrackfile,"</metadata>\n"); |
257 | |
258 | fprintf(gpxtrackfile,"<trk>\n"); |
259 | fprintf(gpxtrackfile,"<name>"); |
260 | fprintf(gpxtrackfile,translate_gpx_name,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); |
261 | fprintf(gpxtrackfile,"</name>\n"); |
262 | fprintf(gpxtrackfile,"<desc>"); |
263 | fprintf(gpxtrackfile,translate_gpx_desc,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); |
264 | fprintf(gpxtrackfile,"</desc>\n"); |
265 | } |
266 | |
267 | if(gpxroutefile) |
268 | { |
269 | fprintf(gpxroutefile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); |
270 | 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"); |
271 | |
272 | fprintf(gpxroutefile,"<metadata>\n"); |
273 | fprintf(gpxroutefile,"<desc>%s : %s</desc>\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]); |
274 | if(translate_xml_copyright_source[1]) |
275 | { |
276 | fprintf(gpxroutefile,"<copyright author=\"%s\">\n",translate_xml_copyright_source[1]); |
277 | |
278 | if(translate_xml_copyright_license[1]) |
279 | fprintf(gpxroutefile,"<license>%s</license>\n",translate_xml_copyright_license[1]); |
280 | |
281 | fprintf(gpxroutefile,"</copyright>\n"); |
282 | } |
283 | fprintf(gpxroutefile,"</metadata>\n"); |
284 | |
285 | fprintf(gpxroutefile,"<rte>\n"); |
286 | fprintf(gpxroutefile,"<name>"); |
287 | fprintf(gpxroutefile,translate_gpx_name,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); |
288 | fprintf(gpxroutefile,"</name>\n"); |
289 | fprintf(gpxroutefile,"<desc>"); |
290 | fprintf(gpxroutefile,translate_gpx_desc,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); |
291 | fprintf(gpxroutefile,"</desc>\n"); |
292 | } |
293 | |
294 | if(textfile) |
295 | { |
296 | if(translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1]) |
297 | fprintf(textfile,"# %s : %s\n",translate_raw_copyright_creator[0],translate_raw_copyright_creator[1]); |
298 | if(translate_raw_copyright_source[0] && translate_raw_copyright_source[1]) |
299 | fprintf(textfile,"# %s : %s\n",translate_raw_copyright_source[0],translate_raw_copyright_source[1]); |
300 | if(translate_raw_copyright_license[0] && translate_raw_copyright_license[1]) |
301 | fprintf(textfile,"# %s : %s\n",translate_raw_copyright_license[0],translate_raw_copyright_license[1]); |
302 | if((translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1]) || |
303 | (translate_raw_copyright_source[0] && translate_raw_copyright_source[1]) || |
304 | (translate_raw_copyright_license[0] && translate_raw_copyright_license[1])) |
305 | fprintf(textfile,"#\n"); |
306 | |
307 | fprintf(textfile,"#Latitude\tLongitude\tSection \tSection \tTotal \tTotal \tPoint\tTurn\tBearing\tHighway\n"); |
308 | fprintf(textfile,"# \t \tDistance\tDuration\tDistance\tDuration\tType \t \t \t \n"); |
309 | /* "%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" */ |
310 | } |
311 | |
312 | if(textallfile) |
313 | { |
314 | if(translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1]) |
315 | fprintf(textallfile,"# %s : %s\n",translate_raw_copyright_creator[0],translate_raw_copyright_creator[1]); |
316 | if(translate_raw_copyright_source[0] && translate_raw_copyright_source[1]) |
317 | fprintf(textallfile,"# %s : %s\n",translate_raw_copyright_source[0],translate_raw_copyright_source[1]); |
318 | if(translate_raw_copyright_license[0] && translate_raw_copyright_license[1]) |
319 | fprintf(textallfile,"# %s : %s\n",translate_raw_copyright_license[0],translate_raw_copyright_license[1]); |
320 | if((translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1]) || |
321 | (translate_raw_copyright_source[0] && translate_raw_copyright_source[1]) || |
322 | (translate_raw_copyright_license[0] && translate_raw_copyright_license[1])) |
323 | fprintf(textallfile,"#\n"); |
324 | |
325 | fprintf(textallfile,"#Latitude\tLongitude\t Node\tType\tSegment\tSegment\tTotal\tTotal \tSpeed\tBearing\tHighway\n"); |
326 | fprintf(textallfile,"# \t \t \t \tDist \tDurat'n\tDist \tDurat'n\t \t \t \n"); |
327 | /* "%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" */ |
328 | } |
329 | |
330 | /* Loop through all the sections of the route and print them */ |
331 | |
332 | do |
333 | { |
334 | int first=1; |
335 | int next_point=point; |
336 | distance_t junc_distance=0; |
337 | duration_t junc_duration=0; |
338 | Result *result; |
339 | |
340 | #if DEBUG |
341 | printf("Route section %d - waypoint %d to waypoint %d\n",point,results[point]->start_waypoint,results[point]->finish_waypoint); |
342 | printf(" start_node=%"Pindex_t" prev_segment=%"Pindex_t"\n",results[point]->start_node,results[point]->prev_segment); |
343 | printf(" finish_node=%"Pindex_t" last_segment=%"Pindex_t"\n",results[point]->finish_node,results[point]->last_segment); |
344 | |
345 | Result *r=FindResult(results[point],results[point]->start_node,results[point]->prev_segment); |
346 | |
347 | while(r) |
348 | { |
349 | printf(" node=%"Pindex_t" segment=%"Pindex_t" score=%f\n",r->node,r->segment,r->score); |
350 | |
351 | r=r->next; |
352 | } |
353 | #endif |
354 | |
355 | result=FindResult(results[point],results[point]->start_node,results[point]->prev_segment); |
356 | |
357 | /* Print the start of the segment */ |
358 | |
359 | if(gpxtrackfile) |
360 | fprintf(gpxtrackfile,"<trkseg>\n"); |
361 | |
362 | /* Loop through all the points within a section of the route and print them */ |
363 | |
364 | do |
365 | { |
366 | double latitude,longitude; |
367 | Node *resultnodep=NULL; |
368 | index_t realsegment=NO_SEGMENT,next_realsegment=NO_SEGMENT; |
369 | Segment *resultsegmentp=NULL,*next_resultsegmentp=NULL; |
370 | Way *resultwayp=NULL,*next_resultwayp=NULL; |
371 | Result *next_result; |
372 | int important=IMP_UNIMPORTANT; |
373 | |
374 | distance_t seg_distance=0; |
375 | duration_t seg_duration=0; |
376 | speed_t seg_speed=0; |
377 | char *waynameraw=NULL,*wayname=NULL,*next_waynameraw=NULL,*next_wayname=NULL; |
378 | int bearing_int=0,turn_int=0,next_bearing_int=0; |
379 | char *turn=NULL,*next_bearing=NULL; |
380 | |
381 | /* Calculate the information about this point */ |
382 | |
383 | if(IsFakeNode(result->node)) |
384 | GetFakeLatLong(result->node,&latitude,&longitude); |
385 | else |
386 | { |
387 | resultnodep=LookupNode(nodes,result->node,6); |
388 | |
389 | GetLatLong(nodes,result->node,resultnodep,&latitude,&longitude); |
390 | } |
391 | |
392 | /* Calculate the next result */ |
393 | |
394 | next_result=result->next; |
395 | |
396 | if(!next_result) |
397 | { |
398 | next_point++; |
399 | |
400 | if(next_point<nresults) |
401 | { |
402 | next_result=FindResult(results[next_point],results[next_point]->start_node,results[next_point]->prev_segment); |
403 | next_result=next_result->next; |
404 | } |
405 | } |
406 | |
407 | /* Calculate the information about this segment */ |
408 | |
409 | if(!first) /* not first point of a section of the route */ |
410 | { |
411 | if(IsFakeSegment(result->segment)) |
412 | { |
413 | resultsegmentp=LookupFakeSegment(result->segment); |
414 | realsegment=IndexRealSegment(result->segment); |
415 | } |
416 | else |
417 | { |
418 | resultsegmentp=LookupSegment(segments,result->segment,2); |
419 | realsegment=result->segment; |
420 | } |
421 | |
422 | resultwayp=LookupWay(ways,resultsegmentp->way,1); |
423 | |
424 | seg_distance+=DISTANCE(resultsegmentp->distance); |
425 | seg_duration+=Duration(resultsegmentp,resultwayp,profile); |
426 | |
427 | /* Calculate the cumulative distance/duration */ |
428 | |
429 | junc_distance+=seg_distance; |
430 | junc_duration+=seg_duration; |
431 | cum_distance+=seg_distance; |
432 | cum_duration+=seg_duration; |
433 | } |
434 | |
435 | /* Calculate the information about the next segment */ |
436 | |
437 | if(next_result) |
438 | { |
439 | if(IsFakeSegment(next_result->segment)) |
440 | { |
441 | next_resultsegmentp=LookupFakeSegment(next_result->segment); |
442 | next_realsegment=IndexRealSegment(next_result->segment); |
443 | } |
444 | else |
445 | { |
446 | next_resultsegmentp=LookupSegment(segments,next_result->segment,1); |
447 | next_realsegment=next_result->segment; |
448 | } |
449 | } |
450 | |
451 | /* Decide if this is a roundabout */ |
452 | |
453 | if(next_result) |
454 | { |
455 | next_resultwayp=LookupWay(ways,next_resultsegmentp->way,2); |
456 | |
457 | if(next_resultwayp->type&Highway_Roundabout) |
458 | { |
459 | if(roundabout==0) |
460 | { |
461 | roundabout++; |
462 | important=IMP_RB_ENTRY; |
463 | } |
464 | else |
465 | { |
466 | Segment *segmentp; |
467 | |
468 | if(resultnodep) |
469 | segmentp=FirstSegment(segments,resultnodep,3); |
470 | else |
471 | segmentp=FirstFakeSegment(result->node); |
472 | |
473 | do |
474 | { |
475 | index_t othernode=OtherNode(segmentp,result->node); |
476 | index_t thissegment; |
477 | |
478 | if(IsFakeNode(result->node)) |
479 | thissegment=IndexFakeSegment(segmentp); |
480 | else |
481 | thissegment=IndexSegment(segments,segmentp); |
482 | |
483 | if(othernode!=prev_node && othernode!=next_result->node && |
484 | thissegment!=realsegment && IsNormalSegment(segmentp)) |
485 | { |
486 | int canexit=1; |
487 | |
488 | if(profile->oneway && IsOnewayTo(segmentp,result->node)) |
489 | { |
490 | if(profile->allow!=Transports_Bicycle) |
491 | canexit=0; |
492 | else |
493 | { |
494 | Way *wayp=LookupWay(ways,segmentp->way,3); |
495 | |
496 | if(!(wayp->type&Highway_CycleBothWays)) |
497 | canexit=0; |
498 | } |
499 | } |
500 | |
501 | if(canexit) |
502 | { |
503 | Way *wayp=LookupWay(ways,segmentp->way,3); |
504 | |
505 | if(!(wayp->type&Highway_Roundabout)) |
506 | { |
507 | roundabout++; |
508 | important=IMP_RB_NOT_EXIT; |
509 | } |
510 | } |
511 | } |
512 | |
513 | if(resultnodep) |
514 | segmentp=NextSegment(segments,segmentp,result->node); |
515 | else |
516 | segmentp=NextFakeSegment(segmentp,result->node); |
517 | } |
518 | while(segmentp); |
519 | } |
520 | } |
521 | else |
522 | if(roundabout) |
523 | { |
524 | roundabout++; |
525 | important=IMP_RB_EXIT; |
526 | } |
527 | } |
528 | |
529 | /* Decide if this is an important junction */ |
530 | |
531 | if(point_count==0) /* first point overall = Waypoint */ |
532 | important=IMP_WAYPOINT; |
533 | else if(result->next==NULL) /* Waypoint */ |
534 | important=IMP_WAYPOINT; |
535 | else if(first) /* first point of a section of the route */ |
536 | important=IMP_IGNORE; |
537 | else if(roundabout) /* roundabout */ |
538 | ; |
539 | else if(realsegment==next_realsegment) /* U-turn */ |
540 | important=IMP_UTURN; |
541 | else if(resultnodep && (resultnodep->flags&NODE_MINIRNDBT)) |
542 | important=IMP_MINI_RB; /* mini-roundabout */ |
543 | else |
544 | { |
545 | Segment *segmentp=FirstSegment(segments,resultnodep,3); |
546 | |
547 | do |
548 | { |
549 | index_t seg=IndexSegment(segments,segmentp); |
550 | |
551 | if(seg!=realsegment && IsNormalSegment(segmentp)) |
552 | { |
553 | int cango=1; |
554 | |
555 | if(profile->oneway && IsOnewayTo(segmentp,result->node)) |
556 | { |
557 | if(profile->allow!=Transports_Bicycle) |
558 | cango=0; |
559 | else |
560 | { |
561 | Way *wayp=LookupWay(ways,segmentp->way,3); |
562 | |
563 | if(!(wayp->type&Highway_CycleBothWays)) |
564 | cango=0; |
565 | } |
566 | } |
567 | |
568 | if(cango) |
569 | { |
570 | Way *wayp=LookupWay(ways,segmentp->way,3); |
571 | |
572 | if(seg==next_realsegment) /* the next segment that we follow */ |
573 | { |
574 | if(HIGHWAY(wayp->type)!=HIGHWAY(resultwayp->type)) |
575 | if(important<IMP_CHANGE) |
576 | important=IMP_CHANGE; |
577 | } |
578 | else /* a segment that we don't follow */ |
579 | { |
580 | if(junction_other_way[HIGHWAY(resultwayp->type)-1][HIGHWAY(wayp->type)-1]) |
581 | if(important<IMP_JUNCT_IMPORT) |
582 | important=IMP_JUNCT_IMPORT; |
583 | |
584 | if(important<IMP_JUNCT_CONT) |
585 | important=IMP_JUNCT_CONT; |
586 | } |
587 | } |
588 | } |
589 | |
590 | segmentp=NextSegment(segments,segmentp,result->node); |
591 | } |
592 | while(segmentp); |
593 | } |
594 | |
595 | /* Calculate the strings to be used */ |
596 | |
597 | if(!first && textallfile) |
598 | { |
599 | waynameraw=WayName(ways,resultwayp); |
600 | if(!*waynameraw) |
601 | waynameraw=translate_raw_highway[HIGHWAY(resultwayp->type)]; |
602 | |
603 | bearing_int=(int)BearingAngle(nodes,resultsegmentp,result->node); |
604 | |
605 | seg_speed=profile->speed[HIGHWAY(resultwayp->type)]; |
606 | } |
607 | |
608 | if(next_result && important>IMP_JUNCT_CONT) |
609 | { |
610 | if(!first && (htmlfile || textfile)) |
611 | { |
612 | if(DISTANCE(resultsegmentp->distance)==0 || DISTANCE(next_resultsegmentp->distance)==0) |
613 | turn_int=0; |
614 | else |
615 | turn_int=(int)TurnAngle(nodes,resultsegmentp,next_resultsegmentp,result->node); |
616 | |
617 | turn=translate_xml_turn[((202+turn_int)/45)%8]; |
618 | } |
619 | |
620 | if(gpxroutefile || htmlfile) |
621 | { |
622 | next_waynameraw=WayName(ways,next_resultwayp); |
623 | if(!*next_waynameraw) |
624 | next_waynameraw=translate_raw_highway[HIGHWAY(next_resultwayp->type)]; |
625 | |
626 | next_wayname=ParseXML_Encode_Safe_XML(next_waynameraw); |
627 | } |
628 | |
629 | if(htmlfile || gpxroutefile || textfile) |
630 | { |
631 | if(!first && DISTANCE(next_resultsegmentp->distance)==0) |
632 | next_bearing_int=(int)BearingAngle(nodes,resultsegmentp,result->node); |
633 | else |
634 | next_bearing_int=(int)BearingAngle(nodes,next_resultsegmentp,next_result->node); |
635 | |
636 | next_bearing=translate_xml_heading[(4+(22+next_bearing_int)/45)%8]; |
637 | } |
638 | } |
639 | |
640 | /* Print out the important points (junctions / waypoints) */ |
641 | |
642 | if(important>IMP_JUNCT_CONT) |
643 | { |
644 | if(htmlfile) |
645 | { |
646 | char *type; |
647 | |
648 | if(important==IMP_WAYPOINT) |
649 | type=translate_html_waypoint; |
650 | else if(important==IMP_MINI_RB) |
651 | type=translate_html_roundabout; |
652 | else |
653 | type=translate_html_junction; |
654 | |
655 | if(point_count>0) /* not the first point */ |
656 | { |
657 | /* <tr class='s'><td class='l'>Follow:<td class='r'><span class='h'>*highway name*</span> for <span class='d'>*distance* km, *time* min</span> [<span class='j'>*distance* km, *time* minutes</span>] */ |
658 | fprintf(htmlfile,"<tr class='s'><td class='l'>%s:<td class='r'>",translate_html_segment[0]); |
659 | fprintf(htmlfile,translate_html_segment[1], |
660 | (roundabout>1?translate_html_roundabout:prev_wayname), |
661 | distance_to_km(junc_distance),duration_to_minutes(junc_duration)); |
662 | fprintf(htmlfile," [<span class='j'>"); |
663 | fprintf(htmlfile,translate_html_total[1], |
664 | distance_to_km(cum_distance),duration_to_minutes(cum_duration)); |
665 | fprintf(htmlfile,"</span>]\n"); |
666 | } |
667 | |
668 | /* <tr class='c'><td class='l'>*N*:<td class='r'>*latitude* *longitude* */ |
669 | fprintf(htmlfile,"<tr class='c'><td class='l'>%d:<td class='r'>%.6f %.6f\n", |
670 | point_count+1, |
671 | radians_to_degrees(latitude),radians_to_degrees(longitude)); |
672 | |
673 | if(point_count==0) /* first point */ |
674 | { |
675 | /* <tr class='n'><td class='l'>Start:<td class='r'>At <span class='w'>Waypoint</span>, head <span class='b'>*heading*</span> */ |
676 | fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_start[0]); |
677 | fprintf(htmlfile,translate_html_start[1], |
678 | translate_html_waypoint, |
679 | next_bearing); |
680 | fprintf(htmlfile,"\n"); |
681 | } |
682 | else if(next_result) /* middle point */ |
683 | { |
684 | if(roundabout>1 && important!=IMP_WAYPOINT) |
685 | { |
686 | /* <tr class='n'><td class='l'>At:<td class='r'>Roundabout, take <span class='t'>the *Nth* exit</span> heading <span class='b'>*heading*</span> */ |
687 | fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_rbnode[0]); |
688 | fprintf(htmlfile,translate_html_rbnode[1], |
689 | translate_html_roundabout, |
690 | translate_xml_ordinal[roundabout-2], |
691 | next_bearing); |
692 | fprintf(htmlfile,"\n"); |
693 | } |
694 | else |
695 | { |
696 | /* <tr class='n'><td class='l'>At:<td class='r'>Junction, go <span class='t'>*direction*</span> heading <span class='b'>*heading*</span> */ |
697 | fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_node[0]); |
698 | fprintf(htmlfile,translate_html_node[1], |
699 | type, |
700 | turn, |
701 | next_bearing); |
702 | fprintf(htmlfile,"\n"); |
703 | } |
704 | } |
705 | else /* end point */ |
706 | { |
707 | /* <tr class='n'><td class='l'>Stop:<td class='r'>At <span class='w'>Waypoint</span> */ |
708 | fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_stop[0]); |
709 | fprintf(htmlfile,translate_html_stop[1], |
710 | translate_html_waypoint); |
711 | fprintf(htmlfile,"\n"); |
712 | |
713 | /* <tr class='t'><td class='l'>Total:<td class='r'><span class='j'>*distance* km, *time* minutes</span> */ |
714 | fprintf(htmlfile,"<tr class='t'><td class='l'>%s:<td class='r'><span class='j'>",translate_html_total[0]); |
715 | fprintf(htmlfile,translate_html_total[1], |
716 | distance_to_km(cum_distance),duration_to_minutes(cum_duration)); |
717 | fprintf(htmlfile,"</span>\n"); |
718 | } |
719 | } |
720 | |
721 | if(gpxroutefile) |
722 | { |
723 | if(point_count>0) /* not first point */ |
724 | { |
725 | fprintf(gpxroutefile,"<desc>"); |
726 | fprintf(gpxroutefile,translate_gpx_step, |
727 | prev_bearing, |
728 | prev_wayname, |
729 | distance_to_km(junc_distance),duration_to_minutes(junc_duration)); |
730 | fprintf(gpxroutefile,"</desc></rtept>\n"); |
731 | } |
732 | |
733 | if(point_count==0) /* first point */ |
734 | { |
735 | fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s</name>\n", |
736 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
737 | translate_gpx_start); |
738 | } |
739 | else if(!next_result) /* end point */ |
740 | { |
741 | fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s</name>\n", |
742 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
743 | translate_gpx_finish); |
744 | fprintf(gpxroutefile,"<desc>"); |
745 | fprintf(gpxroutefile,translate_gpx_final, |
746 | distance_to_km(cum_distance),duration_to_minutes(cum_duration)); |
747 | fprintf(gpxroutefile,"</desc></rtept>\n"); |
748 | } |
749 | else /* middle point */ |
750 | { |
751 | if(important==IMP_WAYPOINT) |
752 | fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%d</name>\n", |
753 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
754 | translate_gpx_inter,++segment_count); |
755 | else |
756 | fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%03d</name>\n", |
757 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
758 | translate_gpx_trip,++route_count); |
759 | } |
760 | } |
761 | |
762 | if(textfile) |
763 | { |
764 | char *type; |
765 | |
766 | if(important==IMP_WAYPOINT) |
767 | type="Waypt"; |
768 | else |
769 | type="Junct"; |
770 | |
771 | if(point_count==0) /* first point */ |
772 | { |
773 | 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", |
774 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
775 | 0.0,0.0,0.0,0.0, |
776 | type, |
777 | ((22+next_bearing_int)/45+4)%8-4, |
778 | next_waynameraw); |
779 | } |
780 | else if(!next_result) /* end point */ |
781 | { |
782 | 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", |
783 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
784 | distance_to_km(junc_distance),duration_to_minutes(junc_duration), |
785 | distance_to_km(cum_distance),duration_to_minutes(cum_duration), |
786 | type); |
787 | } |
788 | else /* middle point */ |
789 | { |
790 | 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", |
791 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
792 | distance_to_km(junc_distance),duration_to_minutes(junc_duration), |
793 | distance_to_km(cum_distance),duration_to_minutes(cum_duration), |
794 | type, |
795 | (22+turn_int)/45, |
796 | ((22+next_bearing_int)/45+4)%8-4, |
797 | next_waynameraw); |
798 | } |
799 | } |
800 | |
801 | junc_distance=0; |
802 | junc_duration=0; |
803 | |
804 | if(htmlfile || gpxroutefile) |
805 | { |
806 | if(prev_wayname) |
807 | free(prev_wayname); |
808 | |
809 | if(next_wayname) |
810 | prev_wayname=strcpy((char*)malloc(strlen(next_wayname)+1),next_wayname); |
811 | else |
812 | prev_wayname=NULL; |
813 | |
814 | if(next_wayname && next_wayname!=next_waynameraw) |
815 | free(next_wayname); |
816 | } |
817 | |
818 | if(gpxroutefile) |
819 | prev_bearing=next_bearing; |
820 | |
821 | if(roundabout>1) |
822 | roundabout=0; |
823 | } |
824 | |
825 | /* Print out all of the results */ |
826 | |
827 | if(gpxtrackfile) |
828 | fprintf(gpxtrackfile,"<trkpt lat=\"%.6f\" lon=\"%.6f\"/>\n", |
829 | radians_to_degrees(latitude),radians_to_degrees(longitude)); |
830 | |
831 | if(important>IMP_IGNORE) |
832 | { |
833 | if(textallfile) |
834 | { |
835 | char *type; |
836 | |
837 | if(important==IMP_WAYPOINT) |
838 | type="Waypt"; |
839 | else if(important==IMP_UTURN) |
840 | type="U-turn"; |
841 | else if(important==IMP_MINI_RB) |
842 | type="Mini-RB"; |
843 | else if(important==IMP_CHANGE) |
844 | type="Change"; |
845 | else if(important==IMP_JUNCT_CONT || important==IMP_RB_NOT_EXIT) |
846 | type="Junct-"; |
847 | else if(important==IMP_UNIMPORTANT) |
848 | type="Inter"; |
849 | else |
850 | type="Junct"; |
851 | |
852 | if(point_count==0) /* first point */ |
853 | { |
854 | fprintf(textallfile,"%10.6f\t%11.6f\t%8d%c\t%s\t%5.3f\t%5.2f\t%5.2f\t%5.1f\t\t\t\n", |
855 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
856 | IsFakeNode(result->node)?(NODE_FAKE-result->node):result->node, |
857 | (resultnodep && IsSuperNode(resultnodep))?'*':' ',type, |
858 | 0.0,0.0,0.0,0.0); |
859 | } |
860 | else /* not the first point */ |
861 | { |
862 | fprintf(textallfile,"%10.6f\t%11.6f\t%8d%c\t%s\t%5.3f\t%5.2f\t%5.2f\t%5.1f\t%3d\t%4d\t%s\n", |
863 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
864 | IsFakeNode(result->node)?(NODE_FAKE-result->node):result->node, |
865 | (resultnodep && IsSuperNode(resultnodep))?'*':' ',type, |
866 | distance_to_km(seg_distance),duration_to_minutes(seg_duration), |
867 | distance_to_km(cum_distance),duration_to_minutes(cum_duration), |
868 | speed_to_kph(seg_speed), |
869 | bearing_int, |
870 | waynameraw); |
871 | } |
872 | } |
873 | } |
874 | |
875 | if(wayname && wayname!=waynameraw) |
876 | free(wayname); |
877 | |
878 | result=next_result; |
879 | |
880 | if(important>IMP_JUNCT_CONT) |
881 | point_count++; |
882 | |
883 | first=0; |
884 | } |
885 | while(point==next_point); |
886 | |
887 | /* Print the end of the segment */ |
888 | |
889 | if(gpxtrackfile) |
890 | fprintf(gpxtrackfile,"</trkseg>\n"); |
891 | |
892 | point=next_point; |
893 | |
894 | if(result) |
895 | prev_node=result->node; |
896 | else |
897 | prev_node=NO_NODE; |
898 | } |
899 | while(point<nresults); |
900 | |
901 | /* Print the tail of the files */ |
902 | |
903 | if(htmlfile) |
904 | { |
905 | fprintf(htmlfile,"</table>\n"); |
906 | |
907 | if((translate_xml_copyright_creator[0] && translate_xml_copyright_creator[1]) || |
908 | (translate_xml_copyright_source[0] && translate_xml_copyright_source[1]) || |
909 | (translate_xml_copyright_license[0] && translate_xml_copyright_license[1])) |
910 | { |
911 | fprintf(htmlfile,"<p>\n"); |
912 | fprintf(htmlfile,"<table class='c'>\n"); |
913 | if(translate_xml_copyright_creator[0] && translate_xml_copyright_creator[1]) |
914 | fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]); |
915 | if(translate_xml_copyright_source[0] && translate_xml_copyright_source[1]) |
916 | fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_xml_copyright_source[0],translate_xml_copyright_source[1]); |
917 | if(translate_xml_copyright_license[0] && translate_xml_copyright_license[1]) |
918 | fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_xml_copyright_license[0],translate_xml_copyright_license[1]); |
919 | fprintf(htmlfile,"</table>\n"); |
920 | } |
921 | |
922 | fprintf(htmlfile,"</body>\n"); |
923 | fprintf(htmlfile,"</html>\n"); |
924 | } |
925 | |
926 | if(gpxtrackfile) |
927 | { |
928 | fprintf(gpxtrackfile,"</trk>\n"); |
929 | fprintf(gpxtrackfile,"</gpx>\n"); |
930 | } |
931 | |
932 | if(gpxroutefile) |
933 | { |
934 | fprintf(gpxroutefile,"</rte>\n"); |
935 | fprintf(gpxroutefile,"</gpx>\n"); |
936 | } |
937 | |
938 | /* Close the files */ |
939 | |
940 | if(!option_stdout) |
941 | { |
942 | if(htmlfile) |
943 | fclose(htmlfile); |
944 | if(gpxtrackfile) |
945 | fclose(gpxtrackfile); |
946 | if(gpxroutefile) |
947 | fclose(gpxroutefile); |
948 | if(textfile) |
949 | fclose(textfile); |
950 | if(textallfile) |
951 | fclose(textallfile); |
952 | } |
953 | } |
Properties
Name | Value |
---|---|
cvs:description | New file to contain the function to print the output. |