Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /trunk/src/output.c
Parent Directory
|
Revision Log
Revision 1680 -
(show annotations)
(download)
(as text)
Tue May 26 17:28:56 2015 UTC (9 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 38816 byte(s)
Tue May 26 17:28:56 2015 UTC (9 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 38816 byte(s)
Merge branch 'MSVC' back into the trunk.
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(option_quickest==0) |
137 | { |
138 | /* Print the result for the shortest route */ |
139 | |
140 | if(option_html) |
141 | htmlfile =fopen("shortest.html","w"); |
142 | if(option_gpx_track) |
143 | gpxtrackfile=fopen("shortest-track.gpx","w"); |
144 | if(option_gpx_route) |
145 | gpxroutefile=fopen("shortest-route.gpx","w"); |
146 | if(option_text) |
147 | textfile =fopen("shortest.txt","w"); |
148 | if(option_text_all) |
149 | textallfile =fopen("shortest-all.txt","w"); |
150 | |
151 | if(option_html && !htmlfile) |
152 | fprintf(stderr,"Warning: Cannot open file 'shortest.html' for writing [%s].\n",strerror(errno)); |
153 | if(option_gpx_track && !gpxtrackfile) |
154 | fprintf(stderr,"Warning: Cannot open file 'shortest-track.gpx' for writing [%s].\n",strerror(errno)); |
155 | if(option_gpx_route && !gpxroutefile) |
156 | fprintf(stderr,"Warning: Cannot open file 'shortest-route.gpx' for writing [%s].\n",strerror(errno)); |
157 | if(option_text && !textfile) |
158 | fprintf(stderr,"Warning: Cannot open file 'shortest.txt' for writing [%s].\n",strerror(errno)); |
159 | if(option_text_all && !textallfile) |
160 | fprintf(stderr,"Warning: Cannot open file 'shortest-all.txt' for writing [%s].\n",strerror(errno)); |
161 | } |
162 | else |
163 | { |
164 | /* Print the result for the quickest route */ |
165 | |
166 | if(option_html) |
167 | htmlfile =fopen("quickest.html","w"); |
168 | if(option_gpx_track) |
169 | gpxtrackfile=fopen("quickest-track.gpx","w"); |
170 | if(option_gpx_route) |
171 | gpxroutefile=fopen("quickest-route.gpx","w"); |
172 | if(option_text) |
173 | textfile =fopen("quickest.txt","w"); |
174 | if(option_text_all) |
175 | textallfile =fopen("quickest-all.txt","w"); |
176 | |
177 | if(option_html && !htmlfile) |
178 | fprintf(stderr,"Warning: Cannot open file 'quickest.html' for writing [%s].\n",strerror(errno)); |
179 | if(option_gpx_track && !gpxtrackfile) |
180 | fprintf(stderr,"Warning: Cannot open file 'quickest-track.gpx' for writing [%s].\n",strerror(errno)); |
181 | if(option_gpx_route && !gpxroutefile) |
182 | fprintf(stderr,"Warning: Cannot open file 'quickest-route.gpx' for writing [%s].\n",strerror(errno)); |
183 | if(option_text && !textfile) |
184 | fprintf(stderr,"Warning: Cannot open file 'quickest.txt' for writing [%s].\n",strerror(errno)); |
185 | if(option_text_all && !textallfile) |
186 | fprintf(stderr,"Warning: Cannot open file 'quickest-all.txt' for writing [%s].\n",strerror(errno)); |
187 | } |
188 | } |
189 | |
190 | /* Print the head of the files */ |
191 | |
192 | if(htmlfile) |
193 | { |
194 | fprintf(htmlfile,"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n"); |
195 | fprintf(htmlfile,"<html>\n"); |
196 | if(translate_xml_copyright_creator[0] && translate_xml_copyright_creator[1]) |
197 | fprintf(htmlfile,"<!-- %s : %s -->\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]); |
198 | if(translate_xml_copyright_source[0] && translate_xml_copyright_source[1]) |
199 | fprintf(htmlfile,"<!-- %s : %s -->\n",translate_xml_copyright_source[0],translate_xml_copyright_source[1]); |
200 | if(translate_xml_copyright_license[0] && translate_xml_copyright_license[1]) |
201 | fprintf(htmlfile,"<!-- %s : %s -->\n",translate_xml_copyright_license[0],translate_xml_copyright_license[1]); |
202 | fprintf(htmlfile,"<head>\n"); |
203 | fprintf(htmlfile,"<title>"); |
204 | fprintf(htmlfile,translate_html_title,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); |
205 | fprintf(htmlfile,"</title>\n"); |
206 | fprintf(htmlfile,"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"); |
207 | fprintf(htmlfile,"<style type=\"text/css\">\n"); |
208 | fprintf(htmlfile,"<!--\n"); |
209 | fprintf(htmlfile," table {table-layout: fixed; border: none; border-collapse: collapse;}\n"); |
210 | fprintf(htmlfile," table.c {color: grey; font-size: x-small;} /* copyright */\n"); |
211 | fprintf(htmlfile," tr {border: 0px;}\n"); |
212 | fprintf(htmlfile," tr.c {display: none;} /* coords */\n"); |
213 | fprintf(htmlfile," tr.n {} /* node */\n"); |
214 | fprintf(htmlfile," tr.s {} /* segment */\n"); |
215 | fprintf(htmlfile," tr.t {font-weight: bold;} /* total */\n"); |
216 | fprintf(htmlfile," td.l {font-weight: bold;}\n"); |
217 | fprintf(htmlfile," td.r {}\n"); |
218 | fprintf(htmlfile," span.w {font-weight: bold;} /* waypoint */\n"); |
219 | fprintf(htmlfile," span.h {text-decoration: underline;} /* highway */\n"); |
220 | fprintf(htmlfile," span.d {} /* segment distance */\n"); |
221 | fprintf(htmlfile," span.j {font-style: italic;} /* total journey distance */\n"); |
222 | fprintf(htmlfile," span.t {font-variant: small-caps;} /* turn */\n"); |
223 | fprintf(htmlfile," span.b {font-variant: small-caps;} /* bearing */\n"); |
224 | fprintf(htmlfile,"-->\n"); |
225 | fprintf(htmlfile,"</style>\n"); |
226 | fprintf(htmlfile,"</head>\n"); |
227 | fprintf(htmlfile,"<body>\n"); |
228 | fprintf(htmlfile,"<h1>"); |
229 | fprintf(htmlfile,translate_html_title,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); |
230 | fprintf(htmlfile,"</h1>\n"); |
231 | fprintf(htmlfile,"<table>\n"); |
232 | } |
233 | |
234 | if(gpxtrackfile) |
235 | { |
236 | fprintf(gpxtrackfile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); |
237 | 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"); |
238 | |
239 | fprintf(gpxtrackfile,"<metadata>\n"); |
240 | fprintf(gpxtrackfile,"<desc>%s : %s</desc>\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]); |
241 | if(translate_xml_copyright_source[1]) |
242 | { |
243 | fprintf(gpxtrackfile,"<copyright author=\"%s\">\n",translate_xml_copyright_source[1]); |
244 | |
245 | if(translate_xml_copyright_license[1]) |
246 | fprintf(gpxtrackfile,"<license>%s</license>\n",translate_xml_copyright_license[1]); |
247 | |
248 | fprintf(gpxtrackfile,"</copyright>\n"); |
249 | } |
250 | fprintf(gpxtrackfile,"</metadata>\n"); |
251 | |
252 | fprintf(gpxtrackfile,"<trk>\n"); |
253 | fprintf(gpxtrackfile,"<name>"); |
254 | fprintf(gpxtrackfile,translate_gpx_name,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); |
255 | fprintf(gpxtrackfile,"</name>\n"); |
256 | fprintf(gpxtrackfile,"<desc>"); |
257 | fprintf(gpxtrackfile,translate_gpx_desc,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); |
258 | fprintf(gpxtrackfile,"</desc>\n"); |
259 | } |
260 | |
261 | if(gpxroutefile) |
262 | { |
263 | fprintf(gpxroutefile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); |
264 | 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"); |
265 | |
266 | fprintf(gpxroutefile,"<metadata>\n"); |
267 | fprintf(gpxroutefile,"<desc>%s : %s</desc>\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]); |
268 | if(translate_xml_copyright_source[1]) |
269 | { |
270 | fprintf(gpxroutefile,"<copyright author=\"%s\">\n",translate_xml_copyright_source[1]); |
271 | |
272 | if(translate_xml_copyright_license[1]) |
273 | fprintf(gpxroutefile,"<license>%s</license>\n",translate_xml_copyright_license[1]); |
274 | |
275 | fprintf(gpxroutefile,"</copyright>\n"); |
276 | } |
277 | fprintf(gpxroutefile,"</metadata>\n"); |
278 | |
279 | fprintf(gpxroutefile,"<rte>\n"); |
280 | fprintf(gpxroutefile,"<name>"); |
281 | fprintf(gpxroutefile,translate_gpx_name,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); |
282 | fprintf(gpxroutefile,"</name>\n"); |
283 | fprintf(gpxroutefile,"<desc>"); |
284 | fprintf(gpxroutefile,translate_gpx_desc,option_quickest?translate_xml_route_quickest:translate_xml_route_shortest); |
285 | fprintf(gpxroutefile,"</desc>\n"); |
286 | } |
287 | |
288 | if(textfile) |
289 | { |
290 | if(translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1]) |
291 | fprintf(textfile,"# %s : %s\n",translate_raw_copyright_creator[0],translate_raw_copyright_creator[1]); |
292 | if(translate_raw_copyright_source[0] && translate_raw_copyright_source[1]) |
293 | fprintf(textfile,"# %s : %s\n",translate_raw_copyright_source[0],translate_raw_copyright_source[1]); |
294 | if(translate_raw_copyright_license[0] && translate_raw_copyright_license[1]) |
295 | fprintf(textfile,"# %s : %s\n",translate_raw_copyright_license[0],translate_raw_copyright_license[1]); |
296 | if((translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1]) || |
297 | (translate_raw_copyright_source[0] && translate_raw_copyright_source[1]) || |
298 | (translate_raw_copyright_license[0] && translate_raw_copyright_license[1])) |
299 | fprintf(textfile,"#\n"); |
300 | |
301 | fprintf(textfile,"#Latitude\tLongitude\tSection \tSection \tTotal \tTotal \tPoint\tTurn\tBearing\tHighway\n"); |
302 | fprintf(textfile,"# \t \tDistance\tDuration\tDistance\tDuration\tType \t \t \t \n"); |
303 | /* "%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" */ |
304 | } |
305 | |
306 | if(textallfile) |
307 | { |
308 | if(translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1]) |
309 | fprintf(textallfile,"# %s : %s\n",translate_raw_copyright_creator[0],translate_raw_copyright_creator[1]); |
310 | if(translate_raw_copyright_source[0] && translate_raw_copyright_source[1]) |
311 | fprintf(textallfile,"# %s : %s\n",translate_raw_copyright_source[0],translate_raw_copyright_source[1]); |
312 | if(translate_raw_copyright_license[0] && translate_raw_copyright_license[1]) |
313 | fprintf(textallfile,"# %s : %s\n",translate_raw_copyright_license[0],translate_raw_copyright_license[1]); |
314 | if((translate_raw_copyright_creator[0] && translate_raw_copyright_creator[1]) || |
315 | (translate_raw_copyright_source[0] && translate_raw_copyright_source[1]) || |
316 | (translate_raw_copyright_license[0] && translate_raw_copyright_license[1])) |
317 | fprintf(textallfile,"#\n"); |
318 | |
319 | fprintf(textallfile,"#Latitude\tLongitude\t Node\tType\tSegment\tSegment\tTotal\tTotal \tSpeed\tBearing\tHighway\n"); |
320 | fprintf(textallfile,"# \t \t \t \tDist \tDurat'n\tDist \tDurat'n\t \t \t \n"); |
321 | /* "%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" */ |
322 | } |
323 | |
324 | /* Loop through all the sections of the route and print them */ |
325 | |
326 | do |
327 | { |
328 | int first=1; |
329 | int next_point=point; |
330 | distance_t junc_distance=0; |
331 | duration_t junc_duration=0; |
332 | Result *result; |
333 | |
334 | #if DEBUG |
335 | printf("Route section %d - waypoint %d to waypoint %d\n",point,results[point]->start_waypoint,results[point]->finish_waypoint); |
336 | printf(" start_node=%"Pindex_t" prev_segment=%"Pindex_t"\n",results[point]->start_node,results[point]->prev_segment); |
337 | printf(" finish_node=%"Pindex_t" last_segment=%"Pindex_t"\n",results[point]->finish_node,results[point]->last_segment); |
338 | |
339 | Result *r=FindResult(results[point],results[point]->start_node,results[point]->prev_segment); |
340 | |
341 | while(r) |
342 | { |
343 | printf(" node=%"Pindex_t" segment=%"Pindex_t" score=%f\n",r->node,r->segment,r->score); |
344 | |
345 | r=r->next; |
346 | } |
347 | #endif |
348 | |
349 | result=FindResult(results[point],results[point]->start_node,results[point]->prev_segment); |
350 | |
351 | /* Print the start of the segment */ |
352 | |
353 | if(gpxtrackfile) |
354 | fprintf(gpxtrackfile,"<trkseg>\n"); |
355 | |
356 | /* Loop through all the points within a section of the route and print them */ |
357 | |
358 | do |
359 | { |
360 | double latitude,longitude; |
361 | Node *resultnodep=NULL; |
362 | index_t realsegment=NO_SEGMENT,next_realsegment=NO_SEGMENT; |
363 | Segment *resultsegmentp=NULL,*next_resultsegmentp=NULL; |
364 | Way *resultwayp=NULL,*next_resultwayp=NULL; |
365 | Result *next_result; |
366 | int important=IMP_UNIMPORTANT; |
367 | |
368 | distance_t seg_distance=0; |
369 | duration_t seg_duration=0; |
370 | speed_t seg_speed=0; |
371 | char *waynameraw=NULL,*wayname=NULL,*next_waynameraw=NULL,*next_wayname=NULL; |
372 | int bearing_int=0,turn_int=0,next_bearing_int=0; |
373 | char *turn=NULL,*next_bearing=NULL; |
374 | |
375 | /* Calculate the information about this point */ |
376 | |
377 | if(IsFakeNode(result->node)) |
378 | GetFakeLatLong(result->node,&latitude,&longitude); |
379 | else |
380 | { |
381 | resultnodep=LookupNode(nodes,result->node,6); |
382 | |
383 | GetLatLong(nodes,result->node,resultnodep,&latitude,&longitude); |
384 | } |
385 | |
386 | /* Calculate the next result */ |
387 | |
388 | next_result=result->next; |
389 | |
390 | if(!next_result) |
391 | { |
392 | next_point++; |
393 | |
394 | if(next_point<nresults) |
395 | { |
396 | next_result=FindResult(results[next_point],results[next_point]->start_node,results[next_point]->prev_segment); |
397 | next_result=next_result->next; |
398 | } |
399 | } |
400 | |
401 | /* Calculate the information about this segment */ |
402 | |
403 | if(!first) /* not first point of a section of the route */ |
404 | { |
405 | if(IsFakeSegment(result->segment)) |
406 | { |
407 | resultsegmentp=LookupFakeSegment(result->segment); |
408 | realsegment=IndexRealSegment(result->segment); |
409 | } |
410 | else |
411 | { |
412 | resultsegmentp=LookupSegment(segments,result->segment,2); |
413 | realsegment=result->segment; |
414 | } |
415 | |
416 | resultwayp=LookupWay(ways,resultsegmentp->way,1); |
417 | |
418 | seg_distance+=DISTANCE(resultsegmentp->distance); |
419 | seg_duration+=Duration(resultsegmentp,resultwayp,profile); |
420 | |
421 | /* Calculate the cumulative distance/duration */ |
422 | |
423 | junc_distance+=seg_distance; |
424 | junc_duration+=seg_duration; |
425 | cum_distance+=seg_distance; |
426 | cum_duration+=seg_duration; |
427 | } |
428 | |
429 | /* Calculate the information about the next segment */ |
430 | |
431 | if(next_result) |
432 | { |
433 | if(IsFakeSegment(next_result->segment)) |
434 | { |
435 | next_resultsegmentp=LookupFakeSegment(next_result->segment); |
436 | next_realsegment=IndexRealSegment(next_result->segment); |
437 | } |
438 | else |
439 | { |
440 | next_resultsegmentp=LookupSegment(segments,next_result->segment,1); |
441 | next_realsegment=next_result->segment; |
442 | } |
443 | } |
444 | |
445 | /* Decide if this is a roundabout */ |
446 | |
447 | if(next_result) |
448 | { |
449 | next_resultwayp=LookupWay(ways,next_resultsegmentp->way,2); |
450 | |
451 | if(next_resultwayp->type&Highway_Roundabout) |
452 | { |
453 | if(roundabout==0) |
454 | { |
455 | roundabout++; |
456 | important=IMP_RB_ENTRY; |
457 | } |
458 | else |
459 | { |
460 | Segment *segmentp; |
461 | |
462 | if(resultnodep) |
463 | segmentp=FirstSegment(segments,resultnodep,3); |
464 | else |
465 | segmentp=FirstFakeSegment(result->node); |
466 | |
467 | do |
468 | { |
469 | index_t othernode=OtherNode(segmentp,result->node); |
470 | index_t thissegment; |
471 | |
472 | if(IsFakeNode(result->node)) |
473 | thissegment=IndexFakeSegment(segmentp); |
474 | else |
475 | thissegment=IndexSegment(segments,segmentp); |
476 | |
477 | if(othernode!=prev_node && othernode!=next_result->node && |
478 | thissegment!=realsegment && IsNormalSegment(segmentp)) |
479 | { |
480 | int canexit=1; |
481 | |
482 | if(profile->oneway && IsOnewayTo(segmentp,result->node)) |
483 | { |
484 | if(profile->allow!=Transports_Bicycle) |
485 | canexit=0; |
486 | else |
487 | { |
488 | Way *wayp=LookupWay(ways,segmentp->way,3); |
489 | |
490 | if(!(wayp->type&Highway_CycleBothWays)) |
491 | canexit=0; |
492 | } |
493 | } |
494 | |
495 | if(canexit) |
496 | { |
497 | Way *wayp=LookupWay(ways,segmentp->way,3); |
498 | |
499 | if(!(wayp->type&Highway_Roundabout)) |
500 | { |
501 | roundabout++; |
502 | important=IMP_RB_NOT_EXIT; |
503 | } |
504 | } |
505 | } |
506 | |
507 | if(resultnodep) |
508 | segmentp=NextSegment(segments,segmentp,result->node); |
509 | else |
510 | segmentp=NextFakeSegment(segmentp,result->node); |
511 | } |
512 | while(segmentp); |
513 | } |
514 | } |
515 | else |
516 | if(roundabout) |
517 | { |
518 | roundabout++; |
519 | important=IMP_RB_EXIT; |
520 | } |
521 | } |
522 | |
523 | /* Decide if this is an important junction */ |
524 | |
525 | if(point_count==0) /* first point overall = Waypoint */ |
526 | important=IMP_WAYPOINT; |
527 | else if(result->next==NULL) /* Waypoint */ |
528 | important=IMP_WAYPOINT; |
529 | else if(first) /* first point of a section of the route */ |
530 | important=IMP_IGNORE; |
531 | else if(roundabout) /* roundabout */ |
532 | ; |
533 | else if(realsegment==next_realsegment) /* U-turn */ |
534 | important=IMP_UTURN; |
535 | else if(resultnodep && (resultnodep->flags&NODE_MINIRNDBT)) |
536 | important=IMP_MINI_RB; /* mini-roundabout */ |
537 | else |
538 | { |
539 | Segment *segmentp=FirstSegment(segments,resultnodep,3); |
540 | |
541 | do |
542 | { |
543 | index_t seg=IndexSegment(segments,segmentp); |
544 | |
545 | if(seg!=realsegment && IsNormalSegment(segmentp)) |
546 | { |
547 | int cango=1; |
548 | |
549 | if(profile->oneway && IsOnewayTo(segmentp,result->node)) |
550 | { |
551 | if(profile->allow!=Transports_Bicycle) |
552 | cango=0; |
553 | else |
554 | { |
555 | Way *wayp=LookupWay(ways,segmentp->way,3); |
556 | |
557 | if(!(wayp->type&Highway_CycleBothWays)) |
558 | cango=0; |
559 | } |
560 | } |
561 | |
562 | if(cango) |
563 | { |
564 | Way *wayp=LookupWay(ways,segmentp->way,3); |
565 | |
566 | if(seg==next_realsegment) /* the next segment that we follow */ |
567 | { |
568 | if(HIGHWAY(wayp->type)!=HIGHWAY(resultwayp->type)) |
569 | if(important<IMP_CHANGE) |
570 | important=IMP_CHANGE; |
571 | } |
572 | else /* a segment that we don't follow */ |
573 | { |
574 | if(junction_other_way[HIGHWAY(resultwayp->type)-1][HIGHWAY(wayp->type)-1]) |
575 | if(important<IMP_JUNCT_IMPORT) |
576 | important=IMP_JUNCT_IMPORT; |
577 | |
578 | if(important<IMP_JUNCT_CONT) |
579 | important=IMP_JUNCT_CONT; |
580 | } |
581 | } |
582 | } |
583 | |
584 | segmentp=NextSegment(segments,segmentp,result->node); |
585 | } |
586 | while(segmentp); |
587 | } |
588 | |
589 | /* Calculate the strings to be used */ |
590 | |
591 | if(!first && textallfile) |
592 | { |
593 | waynameraw=WayName(ways,resultwayp); |
594 | if(!*waynameraw) |
595 | waynameraw=translate_raw_highway[HIGHWAY(resultwayp->type)]; |
596 | |
597 | bearing_int=(int)BearingAngle(nodes,resultsegmentp,result->node); |
598 | |
599 | seg_speed=profile->speed[HIGHWAY(resultwayp->type)]; |
600 | } |
601 | |
602 | if(next_result && important>IMP_JUNCT_CONT) |
603 | { |
604 | if(!first && (htmlfile || textfile)) |
605 | { |
606 | if(DISTANCE(resultsegmentp->distance)==0 || DISTANCE(next_resultsegmentp->distance)==0) |
607 | turn_int=0; |
608 | else |
609 | turn_int=(int)TurnAngle(nodes,resultsegmentp,next_resultsegmentp,result->node); |
610 | |
611 | turn=translate_xml_turn[((202+turn_int)/45)%8]; |
612 | } |
613 | |
614 | if(gpxroutefile || htmlfile) |
615 | { |
616 | next_waynameraw=WayName(ways,next_resultwayp); |
617 | if(!*next_waynameraw) |
618 | next_waynameraw=translate_raw_highway[HIGHWAY(next_resultwayp->type)]; |
619 | |
620 | next_wayname=ParseXML_Encode_Safe_XML(next_waynameraw); |
621 | } |
622 | |
623 | if(htmlfile || gpxroutefile || textfile) |
624 | { |
625 | if(!first && DISTANCE(next_resultsegmentp->distance)==0) |
626 | next_bearing_int=(int)BearingAngle(nodes,resultsegmentp,result->node); |
627 | else |
628 | next_bearing_int=(int)BearingAngle(nodes,next_resultsegmentp,next_result->node); |
629 | |
630 | next_bearing=translate_xml_heading[(4+(22+next_bearing_int)/45)%8]; |
631 | } |
632 | } |
633 | |
634 | /* Print out the important points (junctions / waypoints) */ |
635 | |
636 | if(important>IMP_JUNCT_CONT) |
637 | { |
638 | if(htmlfile) |
639 | { |
640 | char *type; |
641 | |
642 | if(important==IMP_WAYPOINT) |
643 | type=translate_html_waypoint; |
644 | else if(important==IMP_MINI_RB) |
645 | type=translate_html_roundabout; |
646 | else |
647 | type=translate_html_junction; |
648 | |
649 | if(point_count>0) /* not the first point */ |
650 | { |
651 | /* <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>] */ |
652 | fprintf(htmlfile,"<tr class='s'><td class='l'>%s:<td class='r'>",translate_html_segment[0]); |
653 | fprintf(htmlfile,translate_html_segment[1], |
654 | (roundabout>1?translate_html_roundabout:prev_wayname), |
655 | distance_to_km(junc_distance),duration_to_minutes(junc_duration)); |
656 | fprintf(htmlfile," [<span class='j'>"); |
657 | fprintf(htmlfile,translate_html_total[1], |
658 | distance_to_km(cum_distance),duration_to_minutes(cum_duration)); |
659 | fprintf(htmlfile,"</span>]\n"); |
660 | } |
661 | |
662 | /* <tr class='c'><td class='l'>*N*:<td class='r'>*latitude* *longitude* */ |
663 | fprintf(htmlfile,"<tr class='c'><td class='l'>%d:<td class='r'>%.6f %.6f\n", |
664 | point_count+1, |
665 | radians_to_degrees(latitude),radians_to_degrees(longitude)); |
666 | |
667 | if(point_count==0) /* first point */ |
668 | { |
669 | /* <tr class='n'><td class='l'>Start:<td class='r'>At <span class='w'>Waypoint</span>, head <span class='b'>*heading*</span> */ |
670 | fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_start[0]); |
671 | fprintf(htmlfile,translate_html_start[1], |
672 | translate_html_waypoint, |
673 | next_bearing); |
674 | fprintf(htmlfile,"\n"); |
675 | } |
676 | else if(next_result) /* middle point */ |
677 | { |
678 | if(roundabout>1 && important!=IMP_WAYPOINT) |
679 | { |
680 | /* <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> */ |
681 | fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_rbnode[0]); |
682 | fprintf(htmlfile,translate_html_rbnode[1], |
683 | translate_html_roundabout, |
684 | translate_xml_ordinal[roundabout-2], |
685 | next_bearing); |
686 | fprintf(htmlfile,"\n"); |
687 | } |
688 | else |
689 | { |
690 | /* <tr class='n'><td class='l'>At:<td class='r'>Junction, go <span class='t'>*direction*</span> heading <span class='b'>*heading*</span> */ |
691 | fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_node[0]); |
692 | fprintf(htmlfile,translate_html_node[1], |
693 | type, |
694 | turn, |
695 | next_bearing); |
696 | fprintf(htmlfile,"\n"); |
697 | } |
698 | } |
699 | else /* end point */ |
700 | { |
701 | /* <tr class='n'><td class='l'>Stop:<td class='r'>At <span class='w'>Waypoint</span> */ |
702 | fprintf(htmlfile,"<tr class='n'><td class='l'>%s:<td class='r'>",translate_html_stop[0]); |
703 | fprintf(htmlfile,translate_html_stop[1], |
704 | translate_html_waypoint); |
705 | fprintf(htmlfile,"\n"); |
706 | |
707 | /* <tr class='t'><td class='l'>Total:<td class='r'><span class='j'>*distance* km, *time* minutes</span> */ |
708 | fprintf(htmlfile,"<tr class='t'><td class='l'>%s:<td class='r'><span class='j'>",translate_html_total[0]); |
709 | fprintf(htmlfile,translate_html_total[1], |
710 | distance_to_km(cum_distance),duration_to_minutes(cum_duration)); |
711 | fprintf(htmlfile,"</span>\n"); |
712 | } |
713 | } |
714 | |
715 | if(gpxroutefile) |
716 | { |
717 | if(point_count>0) /* not first point */ |
718 | { |
719 | fprintf(gpxroutefile,"<desc>"); |
720 | fprintf(gpxroutefile,translate_gpx_step, |
721 | prev_bearing, |
722 | prev_wayname, |
723 | distance_to_km(junc_distance),duration_to_minutes(junc_duration)); |
724 | fprintf(gpxroutefile,"</desc></rtept>\n"); |
725 | } |
726 | |
727 | if(point_count==0) /* first point */ |
728 | { |
729 | fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s</name>\n", |
730 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
731 | translate_gpx_start); |
732 | } |
733 | else if(!next_result) /* end 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_finish); |
738 | fprintf(gpxroutefile,"<desc>"); |
739 | fprintf(gpxroutefile,translate_gpx_final, |
740 | distance_to_km(cum_distance),duration_to_minutes(cum_duration)); |
741 | fprintf(gpxroutefile,"</desc></rtept>\n"); |
742 | } |
743 | else /* middle point */ |
744 | { |
745 | if(important==IMP_WAYPOINT) |
746 | fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%d</name>\n", |
747 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
748 | translate_gpx_inter,++segment_count); |
749 | else |
750 | fprintf(gpxroutefile,"<rtept lat=\"%.6f\" lon=\"%.6f\"><name>%s%03d</name>\n", |
751 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
752 | translate_gpx_trip,++route_count); |
753 | } |
754 | } |
755 | |
756 | if(textfile) |
757 | { |
758 | char *type; |
759 | |
760 | if(important==IMP_WAYPOINT) |
761 | type="Waypt"; |
762 | else |
763 | type="Junct"; |
764 | |
765 | if(point_count==0) /* first point */ |
766 | { |
767 | 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", |
768 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
769 | 0.0,0.0,0.0,0.0, |
770 | type, |
771 | ((22+next_bearing_int)/45+4)%8-4, |
772 | next_waynameraw); |
773 | } |
774 | else if(!next_result) /* end point */ |
775 | { |
776 | 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", |
777 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
778 | distance_to_km(junc_distance),duration_to_minutes(junc_duration), |
779 | distance_to_km(cum_distance),duration_to_minutes(cum_duration), |
780 | type); |
781 | } |
782 | else /* middle point */ |
783 | { |
784 | 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", |
785 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
786 | distance_to_km(junc_distance),duration_to_minutes(junc_duration), |
787 | distance_to_km(cum_distance),duration_to_minutes(cum_duration), |
788 | type, |
789 | (22+turn_int)/45, |
790 | ((22+next_bearing_int)/45+4)%8-4, |
791 | next_waynameraw); |
792 | } |
793 | } |
794 | |
795 | junc_distance=0; |
796 | junc_duration=0; |
797 | |
798 | if(htmlfile || gpxroutefile) |
799 | { |
800 | if(prev_wayname) |
801 | free(prev_wayname); |
802 | |
803 | if(next_wayname) |
804 | prev_wayname=strcpy((char*)malloc(strlen(next_wayname)+1),next_wayname); |
805 | else |
806 | prev_wayname=NULL; |
807 | |
808 | if(next_wayname && next_wayname!=next_waynameraw) |
809 | free(next_wayname); |
810 | } |
811 | |
812 | if(gpxroutefile) |
813 | prev_bearing=next_bearing; |
814 | |
815 | if(roundabout>1) |
816 | roundabout=0; |
817 | } |
818 | |
819 | /* Print out all of the results */ |
820 | |
821 | if(gpxtrackfile) |
822 | fprintf(gpxtrackfile,"<trkpt lat=\"%.6f\" lon=\"%.6f\"/>\n", |
823 | radians_to_degrees(latitude),radians_to_degrees(longitude)); |
824 | |
825 | if(important>IMP_IGNORE) |
826 | { |
827 | if(textallfile) |
828 | { |
829 | char *type; |
830 | |
831 | if(important==IMP_WAYPOINT) |
832 | type="Waypt"; |
833 | else if(important==IMP_UTURN) |
834 | type="U-turn"; |
835 | else if(important==IMP_MINI_RB) |
836 | type="Mini-RB"; |
837 | else if(important==IMP_CHANGE) |
838 | type="Change"; |
839 | else if(important==IMP_JUNCT_CONT || important==IMP_RB_NOT_EXIT) |
840 | type="Junct-"; |
841 | else if(important==IMP_UNIMPORTANT) |
842 | type="Inter"; |
843 | else |
844 | type="Junct"; |
845 | |
846 | if(point_count==0) /* first point */ |
847 | { |
848 | 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", |
849 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
850 | IsFakeNode(result->node)?(NODE_FAKE-result->node):result->node, |
851 | (resultnodep && IsSuperNode(resultnodep))?'*':' ',type, |
852 | 0.0,0.0,0.0,0.0); |
853 | } |
854 | else /* not the first point */ |
855 | { |
856 | 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", |
857 | radians_to_degrees(latitude),radians_to_degrees(longitude), |
858 | IsFakeNode(result->node)?(NODE_FAKE-result->node):result->node, |
859 | (resultnodep && IsSuperNode(resultnodep))?'*':' ',type, |
860 | distance_to_km(seg_distance),duration_to_minutes(seg_duration), |
861 | distance_to_km(cum_distance),duration_to_minutes(cum_duration), |
862 | speed_to_kph(seg_speed), |
863 | bearing_int, |
864 | waynameraw); |
865 | } |
866 | } |
867 | } |
868 | |
869 | if(wayname && wayname!=waynameraw) |
870 | free(wayname); |
871 | |
872 | result=next_result; |
873 | |
874 | if(important>IMP_JUNCT_CONT) |
875 | point_count++; |
876 | |
877 | first=0; |
878 | } |
879 | while(point==next_point); |
880 | |
881 | /* Print the end of the segment */ |
882 | |
883 | if(gpxtrackfile) |
884 | fprintf(gpxtrackfile,"</trkseg>\n"); |
885 | |
886 | point=next_point; |
887 | |
888 | if(result) |
889 | prev_node=result->node; |
890 | else |
891 | prev_node=NO_NODE; |
892 | } |
893 | while(point<nresults); |
894 | |
895 | /* Print the tail of the files */ |
896 | |
897 | if(htmlfile) |
898 | { |
899 | fprintf(htmlfile,"</table>\n"); |
900 | |
901 | if((translate_xml_copyright_creator[0] && translate_xml_copyright_creator[1]) || |
902 | (translate_xml_copyright_source[0] && translate_xml_copyright_source[1]) || |
903 | (translate_xml_copyright_license[0] && translate_xml_copyright_license[1])) |
904 | { |
905 | fprintf(htmlfile,"<p>\n"); |
906 | fprintf(htmlfile,"<table class='c'>\n"); |
907 | if(translate_xml_copyright_creator[0] && translate_xml_copyright_creator[1]) |
908 | fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_xml_copyright_creator[0],translate_xml_copyright_creator[1]); |
909 | if(translate_xml_copyright_source[0] && translate_xml_copyright_source[1]) |
910 | fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_xml_copyright_source[0],translate_xml_copyright_source[1]); |
911 | if(translate_xml_copyright_license[0] && translate_xml_copyright_license[1]) |
912 | fprintf(htmlfile,"<tr><td class='l'>%s:<td class='r'>%s\n",translate_xml_copyright_license[0],translate_xml_copyright_license[1]); |
913 | fprintf(htmlfile,"</table>\n"); |
914 | } |
915 | |
916 | fprintf(htmlfile,"</body>\n"); |
917 | fprintf(htmlfile,"</html>\n"); |
918 | } |
919 | |
920 | if(gpxtrackfile) |
921 | { |
922 | fprintf(gpxtrackfile,"</trk>\n"); |
923 | fprintf(gpxtrackfile,"</gpx>\n"); |
924 | } |
925 | |
926 | if(gpxroutefile) |
927 | { |
928 | fprintf(gpxroutefile,"</rte>\n"); |
929 | fprintf(gpxroutefile,"</gpx>\n"); |
930 | } |
931 | |
932 | /* Close the files */ |
933 | |
934 | if(!option_stdout) |
935 | { |
936 | if(htmlfile) |
937 | fclose(htmlfile); |
938 | if(gpxtrackfile) |
939 | fclose(gpxtrackfile); |
940 | if(gpxroutefile) |
941 | fclose(gpxroutefile); |
942 | if(textfile) |
943 | fclose(textfile); |
944 | if(textallfile) |
945 | fclose(textallfile); |
946 | } |
947 | } |
Properties
Name | Value |
---|---|
cvs:description | New file to contain the function to print the output. |