Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /trunk/src/routino.c
Parent Directory
|
Revision Log
Revision 1795 -
(show annotations)
(download)
(as text)
Thu Sep 3 18:12:28 2015 UTC (9 years, 6 months ago) by amb
File MIME type: text/x-csrc
File size: 20890 byte(s)
Thu Sep 3 18:12:28 2015 UTC (9 years, 6 months ago) by amb
File MIME type: text/x-csrc
File size: 20890 byte(s)
Add in an HTML-all linked list formats that includes the full set of points and the HTML directions for the important ones.
1 | /*************************************** |
2 | Routino library functions file. |
3 | |
4 | Part of the Routino routing software. |
5 | ******************/ /****************** |
6 | This file Copyright 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 | #include <stdlib.h> |
23 | |
24 | #include "routino.h" |
25 | |
26 | #include "types.h" |
27 | #include "nodes.h" |
28 | #include "segments.h" |
29 | #include "ways.h" |
30 | #include "relations.h" |
31 | |
32 | #include "fakes.h" |
33 | #include "results.h" |
34 | #include "functions.h" |
35 | #include "profiles.h" |
36 | #include "translations.h" |
37 | |
38 | |
39 | /* Global variables */ |
40 | |
41 | /*+ Contains the libroutino API version number. +*/ |
42 | DLL_PUBLIC int Routino_APIVersion=ROUTINO_API_VERSION; |
43 | |
44 | /*+ Contains the error number of the most recent Routino function (one of the ROUTINO_ERROR_* values). +*/ |
45 | DLL_PUBLIC int Routino_errno=ROUTINO_ERROR_NONE; |
46 | |
47 | /*+ The function to be called to report on the routing progress. +*/ |
48 | Routino_ProgressFunc progress_func=NULL; |
49 | |
50 | /*+ The current state of the routing progress. +*/ |
51 | double progress_value=0; |
52 | |
53 | /*+ Set when the progress callback returns false in the routing function. +*/ |
54 | int progress_abort=0; |
55 | |
56 | /*+ The option to calculate the quickest route insted of the shortest. +*/ |
57 | extern int option_quickest; |
58 | |
59 | /*+ The options to select the format of the file output. +*/ |
60 | extern int option_file_html,option_file_gpx_track,option_file_gpx_route,option_file_text,option_file_text_all,option_file_stdout; |
61 | |
62 | /*+ The options to select the format of the linked list output. +*/ |
63 | extern int option_list_html,option_list_html_all,option_list_text,option_list_text_all; |
64 | |
65 | |
66 | /* Static variables */ |
67 | |
68 | static distance_t distmax=km_to_distance(1); |
69 | |
70 | |
71 | /* Local types */ |
72 | |
73 | struct _Routino_Database |
74 | { |
75 | Nodes *nodes; |
76 | Segments *segments; |
77 | Ways *ways; |
78 | Relations *relations; |
79 | }; |
80 | |
81 | struct _Routino_Waypoint |
82 | { |
83 | index_t segment; |
84 | index_t node1,node2; |
85 | distance_t dist1,dist2; |
86 | }; |
87 | |
88 | |
89 | /*++++++++++++++++++++++++++++++++++++++ |
90 | Check the version of the library used by the caller against the library version |
91 | |
92 | int Routino_Check_API_Version Returns ROUTINO_ERROR_NONE if OK or ROUTINO_ERROR_WRONG_VERSION if there is an error. |
93 | |
94 | int caller_version The version of the API used in the caller. |
95 | |
96 | This function should not be called directly, use the macro Routino_CheckAPIVersion() which takes no arguments. |
97 | ++++++++++++++++++++++++++++++++++++++*/ |
98 | |
99 | DLL_PUBLIC int Routino_Check_API_Version(int caller_version) |
100 | { |
101 | if(caller_version==Routino_APIVersion) |
102 | return(ROUTINO_ERROR_NONE); |
103 | else |
104 | return(ROUTINO_ERROR_WRONG_API_VERSION); |
105 | } |
106 | |
107 | |
108 | /*++++++++++++++++++++++++++++++++++++++ |
109 | Load a database of files for Routino to use for routing. |
110 | |
111 | Routino_Database *Routino_LoadDatabase Returns a pointer to the database. |
112 | |
113 | const char *dirname The pathname of the directory containing the database files. |
114 | |
115 | const char *prefix The prefix of the database files. |
116 | ++++++++++++++++++++++++++++++++++++++*/ |
117 | |
118 | DLL_PUBLIC Routino_Database *Routino_LoadDatabase(const char *dirname,const char *prefix) |
119 | { |
120 | char *nodes_filename; |
121 | char *segments_filename; |
122 | char *ways_filename; |
123 | char *relations_filename; |
124 | Routino_Database *database=NULL; |
125 | |
126 | nodes_filename =FileName(dirname,prefix,"nodes.mem"); |
127 | segments_filename =FileName(dirname,prefix,"segments.mem"); |
128 | ways_filename =FileName(dirname,prefix,"ways.mem"); |
129 | relations_filename=FileName(dirname,prefix,"relations.mem"); |
130 | |
131 | if(!ExistsFile(nodes_filename) || !ExistsFile(nodes_filename) || !ExistsFile(nodes_filename) || !ExistsFile(nodes_filename)) |
132 | Routino_errno=ROUTINO_ERROR_NO_DATABASE_FILES; |
133 | else |
134 | { |
135 | database=calloc(sizeof(Routino_Database),1); |
136 | |
137 | database->nodes =LoadNodeList (nodes_filename); |
138 | database->segments =LoadSegmentList (segments_filename); |
139 | database->ways =LoadWayList (ways_filename); |
140 | database->relations=LoadRelationList(relations_filename); |
141 | } |
142 | |
143 | free(nodes_filename); |
144 | free(segments_filename); |
145 | free(ways_filename); |
146 | free(relations_filename); |
147 | |
148 | if(!database->nodes || !database->segments || !database->ways || !database->relations) |
149 | { |
150 | Routino_UnloadDatabase(database); |
151 | database=NULL; |
152 | |
153 | Routino_errno=ROUTINO_ERROR_BAD_DATABASE_FILES; |
154 | } |
155 | |
156 | if(database) |
157 | { |
158 | Routino_errno=ROUTINO_ERROR_NONE; |
159 | return(database); |
160 | } |
161 | else |
162 | return(NULL); |
163 | } |
164 | |
165 | |
166 | /*++++++++++++++++++++++++++++++++++++++ |
167 | Close the database files that were opened by a call to Routino_LoadDatabase(). |
168 | |
169 | Routino_Database *database The database to close. |
170 | ++++++++++++++++++++++++++++++++++++++*/ |
171 | |
172 | DLL_PUBLIC void Routino_UnloadDatabase(Routino_Database *database) |
173 | { |
174 | if(!database) |
175 | Routino_errno=ROUTINO_ERROR_NO_DATABASE; |
176 | else |
177 | { |
178 | if(database->nodes) DestroyNodeList (database->nodes); |
179 | if(database->segments) DestroySegmentList (database->segments); |
180 | if(database->ways) DestroyWayList (database->ways); |
181 | if(database->relations) DestroyRelationList(database->relations); |
182 | |
183 | free(database); |
184 | |
185 | Routino_errno=ROUTINO_ERROR_NONE; |
186 | } |
187 | } |
188 | |
189 | |
190 | /*++++++++++++++++++++++++++++++++++++++ |
191 | Parse a Routino XML file containing profiles, must be called before selecting a profile. |
192 | |
193 | int Routino_ParseXMLProfiles Returns non-zero in case of an error or zero if there was no error. |
194 | |
195 | const char *filename The full pathname of the file to read. |
196 | ++++++++++++++++++++++++++++++++++++++*/ |
197 | |
198 | DLL_PUBLIC int Routino_ParseXMLProfiles(const char *filename) |
199 | { |
200 | int retval; |
201 | |
202 | retval=ParseXMLProfiles(filename,NULL,1); |
203 | |
204 | if(retval==1) |
205 | retval=ROUTINO_ERROR_NO_PROFILES_XML; |
206 | else if(retval==2) |
207 | retval=ROUTINO_ERROR_BAD_PROFILES_XML; |
208 | |
209 | Routino_errno=retval; |
210 | return(retval); |
211 | } |
212 | |
213 | |
214 | /*++++++++++++++++++++++++++++++++++++++ |
215 | Return a list of the profile names that have been loaded from the XML file. |
216 | |
217 | char **Routino_GetProfileNames Returns a NULL terminated list of strings - all allocated. |
218 | ++++++++++++++++++++++++++++++++++++++*/ |
219 | |
220 | DLL_PUBLIC char **Routino_GetProfileNames(void) |
221 | { |
222 | Routino_errno=ROUTINO_ERROR_NONE; |
223 | |
224 | return(GetProfileNames()); |
225 | } |
226 | |
227 | |
228 | /*++++++++++++++++++++++++++++++++++++++ |
229 | Select a specific routing profile from the set of Routino profiles that have been loaded from the XML file or NULL in case of an error. |
230 | |
231 | Routino_Profile *Routino_GetProfile Returns a pointer to an internal data structure - do not free. |
232 | |
233 | const char *name The name of the profile to select. |
234 | ++++++++++++++++++++++++++++++++++++++*/ |
235 | |
236 | DLL_PUBLIC Routino_Profile *Routino_GetProfile(const char *name) |
237 | { |
238 | Profile *profile=GetProfile(name); |
239 | |
240 | if(profile) |
241 | Routino_errno=ROUTINO_ERROR_NONE; |
242 | else |
243 | Routino_errno=ROUTINO_ERROR_NO_SUCH_PROFILE; |
244 | |
245 | return(profile); |
246 | } |
247 | |
248 | |
249 | /*++++++++++++++++++++++++++++++++++++++ |
250 | Free the internal memory that was allocated for the Routino profiles loaded from the XML file. |
251 | ++++++++++++++++++++++++++++++++++++++*/ |
252 | |
253 | DLL_PUBLIC void Routino_FreeXMLProfiles(void) |
254 | { |
255 | Routino_errno=ROUTINO_ERROR_NONE; |
256 | |
257 | FreeXMLProfiles(); |
258 | } |
259 | |
260 | |
261 | /*++++++++++++++++++++++++++++++++++++++ |
262 | Parse a Routino XML file containing translations, must be called before selecting a translation. |
263 | |
264 | int Routino_ParseXMLTranslations Returns non-zero in case of an error or zero if there was no error. |
265 | |
266 | const char *filename The full pathname of the file to read. |
267 | ++++++++++++++++++++++++++++++++++++++*/ |
268 | |
269 | DLL_PUBLIC int Routino_ParseXMLTranslations(const char *filename) |
270 | { |
271 | int retval; |
272 | |
273 | retval=ParseXMLTranslations(filename,NULL,1); |
274 | |
275 | if(retval==1) |
276 | retval=ROUTINO_ERROR_NO_TRANSLATIONS_XML; |
277 | else if(retval==2) |
278 | retval=ROUTINO_ERROR_BAD_TRANSLATIONS_XML; |
279 | |
280 | Routino_errno=retval; |
281 | return(retval); |
282 | } |
283 | |
284 | |
285 | /*++++++++++++++++++++++++++++++++++++++ |
286 | Return a list of the translation languages that have been loaded from the XML file. |
287 | |
288 | char **Routino_GetTranslationLanguages Returns a NULL terminated list of strings - all allocated. |
289 | ++++++++++++++++++++++++++++++++++++++*/ |
290 | |
291 | DLL_PUBLIC char **Routino_GetTranslationLanguages(void) |
292 | { |
293 | Routino_errno=ROUTINO_ERROR_NONE; |
294 | |
295 | return(GetTranslationLanguages()); |
296 | } |
297 | |
298 | |
299 | /*++++++++++++++++++++++++++++++++++++++ |
300 | Return a list of the full names of the translation languages that have been loaded from the XML file. |
301 | |
302 | char **Routino_GetTranslationLanguageFullNames Returns a NULL terminated list of strings - all allocated. |
303 | ++++++++++++++++++++++++++++++++++++++*/ |
304 | |
305 | DLL_PUBLIC char **Routino_GetTranslationLanguageFullNames(void) |
306 | { |
307 | Routino_errno=ROUTINO_ERROR_NONE; |
308 | |
309 | return(GetTranslationLanguageFullNames()); |
310 | } |
311 | |
312 | |
313 | /*++++++++++++++++++++++++++++++++++++++ |
314 | Select a specific translation from the set of Routino translations that have been loaded from the XML file or NULL in case of an error. |
315 | |
316 | Routino_Translation *Routino_GetTranslation Returns a pointer to an internal data structure - do not free. |
317 | |
318 | const char *language The language to select (as a country code, e.g. 'en', 'de') or an empty string for the first in the file or NULL for the built-in English version. |
319 | ++++++++++++++++++++++++++++++++++++++*/ |
320 | |
321 | DLL_PUBLIC Routino_Translation *Routino_GetTranslation(const char *language) |
322 | { |
323 | Translation *translation=GetTranslation(language); |
324 | |
325 | if(translation) |
326 | Routino_errno=ROUTINO_ERROR_NONE; |
327 | else |
328 | Routino_errno=ROUTINO_ERROR_NO_SUCH_TRANSLATION; |
329 | |
330 | return(translation); |
331 | } |
332 | |
333 | |
334 | /*++++++++++++++++++++++++++++++++++++++ |
335 | Free the internal memory that was allocated for the Routino translations loaded from the XML file. |
336 | ++++++++++++++++++++++++++++++++++++++*/ |
337 | |
338 | DLL_PUBLIC void Routino_FreeXMLTranslations(void) |
339 | { |
340 | Routino_errno=ROUTINO_ERROR_NONE; |
341 | |
342 | FreeXMLTranslations(); |
343 | } |
344 | |
345 | |
346 | /*++++++++++++++++++++++++++++++++++++++ |
347 | Create a fully formed Routino Profile from a Routino User Profile. |
348 | |
349 | Routino_Profile *Routino_CreateProfileFromUserProfile Returns an allocated Routino Profile. |
350 | |
351 | Routino_UserProfile *profile The user specified profile to convert (not modified by this). |
352 | ++++++++++++++++++++++++++++++++++++++*/ |
353 | |
354 | DLL_PUBLIC Routino_Profile *Routino_CreateProfileFromUserProfile(Routino_UserProfile *profile) |
355 | { |
356 | Routino_Profile *rprofile=calloc(1,sizeof(Routino_Profile)); |
357 | int i; |
358 | |
359 | Routino_errno=ROUTINO_ERROR_NONE; |
360 | |
361 | if(profile->transport<=0 || profile->transport>=Transport_Count) |
362 | Routino_errno=ROUTINO_ERROR_BAD_USER_PROFILE; |
363 | else |
364 | rprofile->transport=profile->transport; |
365 | |
366 | for(i=1;i<Highway_Count;i++) |
367 | { |
368 | if(profile->highway[i]<0 || profile->highway[i]>1) |
369 | Routino_errno=ROUTINO_ERROR_BAD_USER_PROFILE; |
370 | else |
371 | rprofile->highway[i]=profile->highway[i]; |
372 | |
373 | if(profile->speed[i]<=0) |
374 | Routino_errno=ROUTINO_ERROR_BAD_USER_PROFILE; |
375 | else |
376 | rprofile->speed[i]=kph_to_speed(profile->speed[i]); |
377 | } |
378 | |
379 | for(i=1;i<Property_Count;i++) |
380 | { |
381 | if(profile->props[i]<0 || profile->props[i]>1) |
382 | Routino_errno=ROUTINO_ERROR_BAD_USER_PROFILE; |
383 | else |
384 | rprofile->props[i]=profile->props[i]; |
385 | } |
386 | |
387 | if(profile->weight<=0) |
388 | Routino_errno=ROUTINO_ERROR_BAD_USER_PROFILE; |
389 | else |
390 | rprofile->weight=tonnes_to_weight(profile->weight); |
391 | |
392 | if(profile->height<=0) |
393 | Routino_errno=ROUTINO_ERROR_BAD_USER_PROFILE; |
394 | else |
395 | rprofile->height=metres_to_height(profile->height); |
396 | |
397 | if(profile->width<=0) |
398 | Routino_errno=ROUTINO_ERROR_BAD_USER_PROFILE; |
399 | else |
400 | rprofile->width=metres_to_width(profile->width); |
401 | |
402 | if(profile->length<=0) |
403 | Routino_errno=ROUTINO_ERROR_BAD_USER_PROFILE; |
404 | else |
405 | rprofile->length=metres_to_length(profile->length); |
406 | |
407 | if(Routino_errno==ROUTINO_ERROR_NONE) |
408 | return(rprofile); |
409 | |
410 | free(rprofile); |
411 | return(NULL); |
412 | } |
413 | |
414 | |
415 | /*++++++++++++++++++++++++++++++++++++++ |
416 | Create a Routino User Profile from a Routino Profile loaded from an XML file. |
417 | |
418 | Routino_UserProfile *Routino_CreateUserProfileFromProfile Returns an allocated Routino User Profile. |
419 | |
420 | Routino_Profile *profile The Routino Profile to convert (not modified by this). |
421 | ++++++++++++++++++++++++++++++++++++++*/ |
422 | |
423 | DLL_PUBLIC Routino_UserProfile *Routino_CreateUserProfileFromProfile(Routino_Profile *profile) |
424 | { |
425 | Routino_UserProfile *uprofile=calloc(1,sizeof(Routino_UserProfile)); |
426 | int i; |
427 | |
428 | Routino_errno=ROUTINO_ERROR_NONE; |
429 | |
430 | uprofile->transport=profile->transport; |
431 | |
432 | for(i=1;i<Highway_Count;i++) |
433 | { |
434 | uprofile->highway[i]=profile->highway[i]; |
435 | |
436 | uprofile->speed[i]=speed_to_kph(profile->speed[i]); |
437 | } |
438 | |
439 | for(i=1;i<Property_Count;i++) |
440 | uprofile->props[i]=profile->props[i]; |
441 | |
442 | uprofile->weight=weight_to_tonnes(profile->weight); |
443 | |
444 | uprofile->height=height_to_metres(profile->height); |
445 | |
446 | uprofile->width=width_to_metres(profile->width); |
447 | |
448 | uprofile->length=length_to_metres(profile->length); |
449 | |
450 | return(uprofile); |
451 | } |
452 | |
453 | |
454 | /*++++++++++++++++++++++++++++++++++++++ |
455 | Validates that a selected routing profile is valid for use with the selected routing database. |
456 | |
457 | int Routino_ValidateProfile Returns zero if OK or something else in case of an error. |
458 | |
459 | Routino_Database *database The Routino database to use. |
460 | |
461 | Routino_Profile *profile The Routino profile to validate. |
462 | ++++++++++++++++++++++++++++++++++++++*/ |
463 | |
464 | DLL_PUBLIC int Routino_ValidateProfile(Routino_Database *database,Routino_Profile *profile) |
465 | { |
466 | Routino_errno=ROUTINO_ERROR_NONE; |
467 | |
468 | if(UpdateProfile(profile,database->ways)) |
469 | Routino_errno=ROUTINO_ERROR_PROFILE_DATABASE_ERR; |
470 | |
471 | return(Routino_errno); |
472 | } |
473 | |
474 | |
475 | /*++++++++++++++++++++++++++++++++++++++ |
476 | Finds the nearest point in the database to the specified latitude and longitude. |
477 | |
478 | Routino_Waypoint *Routino_FindWaypoint Returns a pointer to a newly allocated Routino waypoint or NULL if none could be found. |
479 | |
480 | Routino_Database *database The Routino database to use. |
481 | |
482 | Routino_Profile *profile The Routino profile to use. |
483 | |
484 | double latitude The latitude in degrees of the point. |
485 | |
486 | double longitude The longitude in degrees of the point. |
487 | ++++++++++++++++++++++++++++++++++++++*/ |
488 | |
489 | DLL_PUBLIC Routino_Waypoint *Routino_FindWaypoint(Routino_Database *database,Routino_Profile *profile,double latitude,double longitude) |
490 | { |
491 | distance_t dist; |
492 | Routino_Waypoint *waypoint; |
493 | |
494 | if(!database) |
495 | { |
496 | Routino_errno=ROUTINO_ERROR_NO_DATABASE; |
497 | return(NULL); |
498 | } |
499 | |
500 | if(!profile) |
501 | { |
502 | Routino_errno=ROUTINO_ERROR_NO_PROFILE; |
503 | return(NULL); |
504 | } |
505 | |
506 | if(!profile->allow) |
507 | { |
508 | Routino_errno=ROUTINO_ERROR_NOTVALID_PROFILE; |
509 | return(NULL); |
510 | } |
511 | |
512 | waypoint=calloc(sizeof(Routino_Waypoint),1); |
513 | |
514 | waypoint->segment=FindClosestSegment(database->nodes,database->segments,database->ways, |
515 | degrees_to_radians(latitude),degrees_to_radians(longitude),distmax,profile, |
516 | &dist,&waypoint->node1,&waypoint->node2,&waypoint->dist1,&waypoint->dist2); |
517 | |
518 | if(waypoint->segment==NO_SEGMENT) |
519 | { |
520 | free(waypoint); |
521 | |
522 | Routino_errno=ROUTINO_ERROR_NO_NEARBY_HIGHWAY; |
523 | return(NULL); |
524 | } |
525 | |
526 | Routino_errno=ROUTINO_ERROR_NONE; |
527 | return(waypoint); |
528 | } |
529 | |
530 | |
531 | /*++++++++++++++++++++++++++++++++++++++ |
532 | Calculate a route using a loaded database, chosen profile, chosen translation and set of waypoints. |
533 | |
534 | Routino_Output *Routino_CalculateRoute Returns the head of a linked list of route data (if requested) or NULL. |
535 | |
536 | Routino_Database *database The loaded database to use. |
537 | |
538 | Routino_Profile *profile The chosen routing profile to use. |
539 | |
540 | Routino_Translation *translation The chosen translation information to use. |
541 | |
542 | Routino_Waypoint **waypoints The set of waypoints. |
543 | |
544 | int nwaypoints The number of waypoints. |
545 | |
546 | int options The set of routing options (ROUTINO_ROUTE_*) ORed together. |
547 | |
548 | Routino_ProgressFunc progress A function to be called occasionally to report progress or NULL. |
549 | ++++++++++++++++++++++++++++++++++++++*/ |
550 | |
551 | DLL_PUBLIC Routino_Output *Routino_CalculateRoute(Routino_Database *database,Routino_Profile *profile,Routino_Translation *translation, |
552 | Routino_Waypoint **waypoints,int nwaypoints,int options,Routino_ProgressFunc progress) |
553 | { |
554 | int waypoint; |
555 | index_t start_node,finish_node=NO_NODE; |
556 | index_t join_segment=NO_SEGMENT; |
557 | Results **results; |
558 | Routino_Output *output=NULL; |
559 | |
560 | /* Check the input data */ |
561 | |
562 | if(!database) |
563 | { |
564 | Routino_errno=ROUTINO_ERROR_NO_DATABASE; |
565 | return(NULL); |
566 | } |
567 | |
568 | if(!profile) |
569 | { |
570 | Routino_errno=ROUTINO_ERROR_NO_PROFILE; |
571 | return(NULL); |
572 | } |
573 | |
574 | if(!profile->allow) |
575 | { |
576 | Routino_errno=ROUTINO_ERROR_NOTVALID_PROFILE; |
577 | return(NULL); |
578 | } |
579 | |
580 | if(!translation) |
581 | { |
582 | Routino_errno=ROUTINO_ERROR_NO_TRANSLATION; |
583 | return(NULL); |
584 | } |
585 | |
586 | /* Extract the options */ |
587 | |
588 | if(options&ROUTINO_ROUTE_QUICKEST) option_quickest=1; else option_quickest=0; |
589 | |
590 | if(options&ROUTINO_ROUTE_FILE_HTML) option_file_html=1; else option_file_html=0; |
591 | if(options&ROUTINO_ROUTE_FILE_GPX_TRACK) option_file_gpx_track=1; else option_file_gpx_track=0; |
592 | if(options&ROUTINO_ROUTE_FILE_GPX_ROUTE) option_file_gpx_route=1; else option_file_gpx_route=0; |
593 | if(options&ROUTINO_ROUTE_FILE_TEXT) option_file_text=1; else option_file_text=0; |
594 | if(options&ROUTINO_ROUTE_FILE_TEXT_ALL) option_file_text_all=1; else option_file_text_all=0; |
595 | |
596 | if(options&ROUTINO_ROUTE_FILE_STDOUT) option_file_stdout=1; else option_file_stdout=0; |
597 | |
598 | if(option_file_stdout && (option_file_html+option_file_gpx_track+option_file_gpx_route+option_file_text+option_file_text_all)!=1) |
599 | { |
600 | Routino_errno=ROUTINO_ERROR_BAD_OPTIONS; |
601 | return(NULL); |
602 | } |
603 | |
604 | if(options&ROUTINO_ROUTE_LIST_HTML) option_list_html=1; else option_list_html=0; |
605 | if(options&ROUTINO_ROUTE_LIST_HTML_ALL) option_list_html_all=1; else option_list_html_all=0; |
606 | if(options&ROUTINO_ROUTE_LIST_TEXT) option_list_text=1; else option_list_text=0; |
607 | if(options&ROUTINO_ROUTE_LIST_TEXT_ALL) option_list_text_all=1; else option_list_text_all=0; |
608 | |
609 | if((option_list_html+option_list_html_all+option_list_text+option_list_text_all)>1) |
610 | { |
611 | Routino_errno=ROUTINO_ERROR_BAD_OPTIONS; |
612 | return(NULL); |
613 | } |
614 | |
615 | /* Set up the progress callback */ |
616 | |
617 | progress_func=progress; |
618 | progress_value=0.0; |
619 | progress_abort=0; |
620 | |
621 | /* Loop through all pairs of waypoints */ |
622 | |
623 | results=calloc(sizeof(Results*),nwaypoints); |
624 | |
625 | for(waypoint=0;waypoint<nwaypoints;waypoint++) |
626 | { |
627 | if(progress_func) |
628 | { |
629 | progress_value=(double)waypoint/(double)(nwaypoints+1); |
630 | |
631 | if(!progress_func(progress_value)) |
632 | { |
633 | Routino_errno=ROUTINO_ERROR_PROGRESS_ABORTED; |
634 | goto tidy_and_exit; |
635 | } |
636 | } |
637 | |
638 | start_node=finish_node; |
639 | |
640 | finish_node=CreateFakes(database->nodes,database->segments,waypoint+1, |
641 | LookupSegment(database->segments,waypoints[waypoint]->segment,1), |
642 | waypoints[waypoint]->node1,waypoints[waypoint]->node2,waypoints[waypoint]->dist1,waypoints[waypoint]->dist2); |
643 | |
644 | if(waypoint==0) |
645 | continue; |
646 | |
647 | results[waypoint-1]=CalculateRoute(database->nodes,database->segments,database->ways,database->relations, |
648 | profile,start_node,join_segment,finish_node,waypoint,waypoint+1); |
649 | |
650 | if(!results[waypoint-1]) |
651 | { |
652 | if(progress_func && progress_abort) |
653 | Routino_errno=ROUTINO_ERROR_PROGRESS_ABORTED; |
654 | else |
655 | Routino_errno=ROUTINO_ERROR_NO_ROUTE_1+waypoint-1; |
656 | |
657 | goto tidy_and_exit; |
658 | } |
659 | |
660 | join_segment=results[waypoint-1]->last_segment; |
661 | } |
662 | |
663 | if(progress_func) |
664 | { |
665 | progress_value=(double)waypoint/(double)(nwaypoints+1); |
666 | |
667 | if(!progress_func(progress_value)) |
668 | { |
669 | Routino_errno=ROUTINO_ERROR_PROGRESS_ABORTED; |
670 | goto tidy_and_exit; |
671 | } |
672 | } |
673 | |
674 | /* Print the route */ |
675 | |
676 | output=PrintRoute(results,nwaypoints-1,database->nodes,database->segments,database->ways,profile,translation); |
677 | |
678 | if(progress_func && !progress_func(1.0)) |
679 | { |
680 | Routino_errno=ROUTINO_ERROR_PROGRESS_ABORTED; |
681 | goto tidy_and_exit; |
682 | } |
683 | |
684 | /* Tidy up and exit */ |
685 | |
686 | tidy_and_exit: |
687 | |
688 | DeleteFakeNodes(); |
689 | |
690 | for(waypoint=0;waypoint<nwaypoints;waypoint++) |
691 | if(results[waypoint]) |
692 | FreeResultsList(results[waypoint]); |
693 | |
694 | free(results); |
695 | |
696 | return(output); |
697 | } |
698 | |
699 | |
700 | /*++++++++++++++++++++++++++++++++++++++ |
701 | Delete the linked list created by Routino_CalculateRoute. |
702 | |
703 | Routino_Output *output The output to be deleted. |
704 | ++++++++++++++++++++++++++++++++++++++*/ |
705 | |
706 | DLL_PUBLIC void Routino_DeleteRoute(Routino_Output *output) |
707 | { |
708 | while(output) |
709 | { |
710 | Routino_Output *next=output->next; |
711 | |
712 | if(output->name) |
713 | free(output->name); |
714 | |
715 | if(output->desc1) |
716 | free(output->desc1); |
717 | |
718 | if(output->desc2) |
719 | free(output->desc2); |
720 | |
721 | if(output->desc3) |
722 | free(output->desc3); |
723 | |
724 | free(output); |
725 | |
726 | output=next; |
727 | } |
728 | } |