* fix conffiles
[navit-package] / navit / map.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301, USA.
18  */
19
20 /** @file
21  *
22  * @brief Contains code that makes navit able to load maps
23  *
24  * This file contains the code that makes navit able to load maps. Because
25  * navit is able to open maps in different formats, this code does not handle
26  * any map format itself. This is done by map plugins which register to this
27  * code by calling plugin_register_map_type().
28  *
29  * When opening a new map, the map plugin will return a pointer to a map_priv
30  * struct, which can be defined by the map plugin and contains whatever private
31  * data the map plugin needs to access the map. This pointer will also be used
32  * as a "handle" to access the map opened.
33  *
34  * A common task is to create a "map rect". A map rect is a rectangular part of
35  * the map, that one can for example retrieve items from. It is not possible to
36  * retrieve items directly from the complete map. Creating a map rect returns a
37  * pointer to a map_rect_priv, which contains private data for the map rect and
38  * will be used as "handle" for this map rect.
39  */
40
41 #include <glib.h>
42 #include <string.h>
43 #include "debug.h"
44 #include "coord.h"
45 #include "projection.h"
46 #include "item.h"
47 #include "map.h"
48 #include "maptype.h"
49 #include "transform.h"
50 #include "plugin.h"
51 #include "callback.h"
52 #include "country.h"
53
54 /**
55  * @brief Holds information about a map
56  *
57  * This structure holds information about a map.
58  */
59 struct map {
60         struct map_methods meth;                        /**< Structure with pointers to the map plugin's functions */
61         struct map_priv *priv;                          /**< Private data of the map, only known to the map plugin */
62         struct attr **attrs;                            /**< Attributes of this map */
63         struct callback_list *attr_cbl;         /**< List of callbacks that are called when attributes change */
64 };
65
66 /**
67  * @brief Describes a rectangular extract of a map
68  *
69  * This structure describes a rectangular extract of a map.
70  */
71 struct map_rect {
72         struct map *m;                          /**< The map this extract is from */
73         struct map_rect_priv *priv; /**< Private data of this map rect, only known to the map plugin */
74 };
75
76 /**
77  * @brief Opens a new map
78  *
79  * This function opens a new map based on the attributes passed. This function
80  * takes the attribute "attr_type" to determine which type of map to open and passes
81  * all attributes to the map plugin's function that was specified in the
82  * plugin_register_new_map_type()-call.
83  *
84  * Note that every plugin should accept an attribute of type "attr_data" to be passed
85  * with the filename of the map to be opened as value.
86  *
87  * @param attrs Attributes specifying which map to open, see description
88  * @return The opened map or NULL on failure
89  */
90 struct map *
91 map_new(struct attr *parent, struct attr **attrs)
92 {
93         struct map *m;
94         struct map_priv *(*maptype_new)(struct map_methods *meth, struct attr **attrs);
95         struct attr *type=attr_search(attrs, NULL, attr_type);
96
97         if (! type) {
98                 dbg(0,"missing type\n");
99                 return NULL;
100         }
101         maptype_new=plugin_get_map_type(type->u.str);
102         if (! maptype_new) {
103                 dbg(0,"invalid type '%s'\n", type->u.str);
104                 return NULL;
105         }
106
107         m=g_new0(struct map, 1);
108         m->attrs=attr_list_dup(attrs);
109         m->priv=maptype_new(&m->meth, attrs);
110         if (! m->priv) {
111                 g_free(m);
112                 m=NULL;
113         }
114         if (m)
115                 m->attr_cbl=callback_list_new();
116         return m;
117 }
118
119 /**
120  * @brief Gets an attribute from a map
121  *
122  * @param this_ The map the attribute should be read from
123  * @param type The type of the attribute to be read
124  * @param attr Pointer to an attrib-structure where the attribute should be written to
125  * @param iter (NOT IMPLEMENTED) Used to iterate through all attributes of a type. Set this to NULL to get the first attribute, set this to an attr_iter to get the next attribute
126  * @return True if the attribute type was found, false if not
127  */
128 int
129 map_get_attr(struct map *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
130 {
131         return attr_generic_get_attr(this_->attrs, NULL, type, attr, iter);
132 }
133
134 /**
135  * @brief Sets an attribute of a map
136  *
137  * This sets an attribute of a map, overwriting an attribute of the same type if it
138  * already exists. This function also calls all the callbacks that are registred
139  * to be called when attributes change.
140  *
141  * @param this_ The map to set the attribute of
142  * @param attr The attribute to set
143  * @return True if the attr could be set, false otherwise
144  */
145 int
146 map_set_attr(struct map *this_, struct attr *attr)
147 {
148         this_->attrs=attr_generic_set_attr(this_->attrs, attr);
149         if (this_->meth.map_set_attr)
150                 this_->meth.map_set_attr(this_->priv, attr);
151         callback_list_call_attr_2(this_->attr_cbl, attr->type, this_, attr);
152         return 1;
153 }
154
155 /**
156  * @brief Registers a new callback for attribute-change
157  *
158  * This function registers a new callback function that should be called if the attributes
159  * of the map change.
160  *
161  * @param this_ The map to associate the callback with
162  * @param cb The callback to add
163  */
164 void
165 map_add_callback(struct map *this_, struct callback *cb)
166 {
167         callback_list_add(this_->attr_cbl, cb);
168 }
169
170 /**
171  * @brief Removes a callback from the list of attribute-change callbacks
172  *
173  * This function removes one callback from the list of callbacks functions that should be called
174  * when attributes of the map change.
175  *
176  * @param this_ The map to remove the callback from
177  * @param cb The callback to remove
178  */
179 void
180 map_remove_callback(struct map *this_, struct callback *cb)
181 {
182         callback_list_remove(this_->attr_cbl, cb);
183 }
184
185
186 /**
187  * @brief Checks if strings from a map have to be converted
188  *
189  * @param this_ Map to be checked for the need to convert strings
190  * @return True if strings from the map have to be converted, false otherwise
191  */
192 int
193 map_requires_conversion(struct map *this_)
194 {
195         return (this_->meth.charset != NULL && strcmp(this_->meth.charset, "utf-8"));
196 }
197
198 /**
199  * @brief Converts a string from a map
200  *
201  * @param this_ The map the string to be converted is from
202  * @param str The string to be converted
203  * @return The converted string. It has to be map_convert_free()d after use.
204  */
205 char *
206 map_convert_string(struct map *this_, char *str)
207 {
208         return g_convert(str, -1,"utf-8",this_->meth.charset,NULL,NULL,NULL);
209 }
210
211 /**
212  * @brief Frees the memory allocated for a converted string
213  *
214  * @param str The string to be freed
215  */
216 void
217 map_convert_free(char *str)
218 {
219         g_free(str);
220 }
221
222 /**
223  * @brief Returns the projection of a map
224  *
225  * @param this_ The map to return the projection of
226  * @return The projection of the map
227  */
228 enum projection
229 map_projection(struct map *this_)
230 {
231         return this_->meth.pro;
232 }
233
234 /**
235  * @brief Sets the projection of a map
236  *
237  * @param this_ The map to set the projection of
238  * @param pro The projection to be set
239  */
240 void
241 map_set_projection(struct map *this_, enum projection pro)
242 {
243         this_->meth.pro=pro;
244 }
245
246 /**
247  * @brief Destroys an opened map
248  *
249  * @param m The map to be destroyed
250  */
251 void
252 map_destroy(struct map *m)
253 {
254         m->meth.map_destroy(m->priv);
255         attr_list_free(m->attrs);
256         g_free(m);
257 }
258
259 /**
260  * @brief Creates a new map rect
261  *
262  * This creates a new map rect, which can be used to retrieve items from a map. If
263  * sel is a linked-list of selections, all of them will be used. If you pass NULL as
264  * sel, this means "get me the whole map".
265  *
266  * @param m The map to build the rect on
267  * @param sel Map selection to choose the rectangle - may be NULL, see description
268  * @return A new map rect
269  */
270 struct map_rect *
271 map_rect_new(struct map *m, struct map_selection *sel)
272 {
273         struct map_rect *mr;
274
275 #if 0
276         printf("map_rect_new 0x%x,0x%x-0x%x,0x%x\n", r->lu.x, r->lu.y, r->rl.x, r->rl.y);
277 #endif
278         mr=g_new0(struct map_rect, 1);
279         mr->m=m;
280         mr->priv=m->meth.map_rect_new(m->priv, sel);
281         if (! mr->priv) {
282                 g_free(mr);
283                 mr=NULL;
284         }
285
286         return mr;
287 }
288
289 /**
290  * @brief Gets the next item from a map rect
291  *
292  * Returns an item from a map rect and advances the "item pointer" one step further,
293  * so that at the next call the next item is returned. Returns NULL if there are no more items.
294  *
295  * @param mr The map rect to return an item from
296  * @return An item from the map rect
297  */
298 struct item *
299 map_rect_get_item(struct map_rect *mr)
300 {
301         struct item *ret;
302         dbg_assert(mr != NULL);
303         dbg_assert(mr->m != NULL);
304         dbg_assert(mr->m->meth.map_rect_get_item != NULL);
305         ret=mr->m->meth.map_rect_get_item(mr->priv);
306         if (ret)
307                 ret->map=mr->m;
308         return ret;
309 }
310
311 /**
312  * @brief Returns the item specified by the ID
313  *
314  * @param mr The map rect to search for the item
315  * @param id_hi High part of the ID to be found
316  * @param id_lo Low part of the ID to be found
317  * @return The item with the specified ID or NULL if not found
318  */
319 struct item *
320 map_rect_get_item_byid(struct map_rect *mr, int id_hi, int id_lo)
321 {
322         struct item *ret=NULL;
323         dbg_assert(mr != NULL);
324         dbg_assert(mr->m != NULL);
325         if (mr->m->meth.map_rect_get_item_byid)
326                 ret=mr->m->meth.map_rect_get_item_byid(mr->priv, id_hi, id_lo);
327         if (ret)
328                 ret->map=mr->m;
329         return ret;
330 }
331
332 /**
333  * @brief Destroys a map rect
334  *
335  * @param mr The map rect to be destroyed
336  */
337 void
338 map_rect_destroy(struct map_rect *mr)
339 {
340         if (mr) {
341                 mr->m->meth.map_rect_destroy(mr->priv);
342                 g_free(mr);
343         }
344 }
345
346 /**
347  * @brief Holds information about a search on a map
348  *
349  * This structure holds information about a search performed on a map. This can be
350  * used as "handle" to retrieve items from a search.
351  */
352 struct map_search {
353         struct map *m;
354         struct attr search_attr;
355         void *priv;
356 };
357
358 /**
359  * @brief Starts a search on a map
360  *
361  * This function starts a search on a map. What attributes one can search for depends on the
362  * map plugin.
363  *
364  * The OSM/binfile plugin currently supports: attr_town_name, attr_street_name
365  * The MG plugin currently supports: ttr_town_postal, attr_town_name, attr_street_name
366  *
367  * If you enable partial matches bear in mind that the search matches only the begin of the
368  * strings - a search for a street named "street" would match to "streetfoo", but not to
369  * "somestreet". Search is case insensitive.
370  *
371  * The item passed to this function specifies a "superior item" to "search within" - e.g. a town 
372  * in which we want to search for a street, or a country in which to search for a town.
373  *
374  * Please also note that the search for countries is not handled by map plugins but by navit internally -
375  * have a look into country.c for details. Because of that every map plugin has to accept a country item
376  * to be passed as "superior item".
377  * 
378  * Note: If you change something here, please make sure to also update the documentation of mapset_search_new()
379  * in mapset.c!
380  *
381  * @param m The map that should be searched
382  * @param item Specifies a superior item to "search within" (see description)
383  * @param search_attr Attribute specifying what to search for. See description.
384  * @param partial Set this to true to also have partial matches. See description.
385  * @return A new map search struct for this search
386  */
387 struct map_search *
388 map_search_new(struct map *m, struct item *item, struct attr *search_attr, int partial)
389 {
390         struct map_search *this_;
391         dbg(1,"enter(%p,%p,%p,%d)\n", m, item, search_attr, partial);
392         dbg(1,"0x%x 0x%x 0x%x\n", attr_country_all, search_attr->type, attr_country_name);
393         this_=g_new0(struct map_search,1);
394         this_->m=m;
395         this_->search_attr=*search_attr;
396         if ((search_attr->type >= attr_country_all && search_attr->type <= attr_country_name) || search_attr->type == attr_country_id)
397                 this_->priv=country_search_new(&this_->search_attr, partial);
398         else {
399                 if (m->meth.map_search_new) {
400                         if (m->meth.charset)
401                                 this_->search_attr.u.str=g_convert(this_->search_attr.u.str, -1,m->meth.charset,"utf-8",NULL,NULL,NULL);
402                         this_->priv=m->meth.map_search_new(m->priv, item, &this_->search_attr, partial);
403                         if (! this_->priv) {
404                                 g_free(this_);
405                                 this_=NULL;
406                         }
407                 } else {
408                         g_free(this_);
409                         this_=NULL;
410                 }
411         }
412         return this_;
413 }
414
415 /**
416  * @brief Returns an item from a map search
417  *
418  * This returns an item of the result of a search on a map and advances the "item pointer" one step,
419  * so that at the next call the next item will be returned. If there are no more items in the result
420  * NULL is returned.
421  *
422  * @param this_ Map search struct of the search
423  * @return One item of the result
424  */
425 struct item *
426 map_search_get_item(struct map_search *this_)
427 {
428         struct item *ret;
429
430         if (! this_)
431                 return NULL;
432         if ((this_->search_attr.type >= attr_country_all && this_->search_attr.type <= attr_country_name) || this_->search_attr.type == attr_country_id)
433                 return country_search_get_item(this_->priv);
434         ret=this_->m->meth.map_search_get_item(this_->priv);
435         if (ret)
436                 ret->map=this_->m;
437         return ret;
438 }
439
440 /**
441  * @brief Destroys a map search struct
442  *
443  * @param this_ The map search struct to be destroyed
444  */
445 void
446 map_search_destroy(struct map_search *this_)
447 {
448         if (! this_)
449                 return;
450         if (this_->search_attr.type >= attr_country_all && this_->search_attr.type <= attr_country_name)
451                 country_search_destroy(this_->priv);
452         else {
453                 if (this_->m->meth.charset)
454                                 g_free(this_->search_attr.u.str);
455                 this_->m->meth.map_search_destroy(this_->priv);
456         }
457         g_free(this_);
458 }
459
460 /**
461  * @brief Creates a new rectangular map selection
462  *
463  * @param center Coordinates of the center of the new rectangle
464  * @param distance Distance of the rectangle's borders from the center
465  * @param order Desired order of the new selection
466  * @return The new map selection
467  */
468 struct map_selection *
469 map_selection_rect_new(struct pcoord *center, int distance, int order)
470 {
471         struct map_selection *ret=g_new0(struct map_selection, 1);
472         ret->order=order;
473         ret->range=item_range_all;
474         ret->u.c_rect.lu.x=center->x-distance;
475         ret->u.c_rect.lu.y=center->y+distance;
476         ret->u.c_rect.rl.x=center->x+distance;
477         ret->u.c_rect.rl.y=center->y-distance;
478         return ret;
479 }
480
481 /**
482  * @brief Duplicates a map selection, transforming coordinates
483  *
484  * This duplicates a map selection and at the same time transforms the internal
485  * coordinates of the selection from one projection to another.
486  *
487  * @param sel The map selection to be duplicated
488  * @param from The projection used for the selection at the moment
489  * @param to The projection that should be used for the duplicated selection
490  * @return A duplicated, transformed map selection
491  */
492 struct map_selection *
493 map_selection_dup_pro(struct map_selection *sel, enum projection from, enum projection to)
494 {
495         struct map_selection *next,**last;
496         struct map_selection *ret=NULL;
497         last=&ret;
498         while (sel) {
499                 next = g_new(struct map_selection, 1);
500                 *next=*sel;
501                 if (from != projection_none || to != projection_none) {
502                         transform_from_to(&sel->u.c_rect.lu, from, &next->u.c_rect.lu, to);
503                         transform_from_to(&sel->u.c_rect.rl, from, &next->u.c_rect.rl, to);
504                 }
505                 *last=next;
506                 last=&next->next;
507                 sel = sel->next;
508         }
509         return ret;
510 }
511
512 /**
513  * @brief Duplicates a map selection
514  *
515  * @param sel The map selection to duplicate
516  * @return The duplicated map selection
517  */
518 struct map_selection *
519 map_selection_dup(struct map_selection *sel)
520 {
521         return map_selection_dup_pro(sel, projection_none, projection_none);
522 }
523
524 /**
525  * @brief Destroys a map selection
526  *
527  * @param sel The map selection to be destroyed
528  */
529 void
530 map_selection_destroy(struct map_selection *sel)
531 {
532         struct map_selection *next;
533         while (sel) {
534                 next = sel->next;
535                 g_free(sel);
536                 sel = next;
537         }
538 }
539
540 /**
541  * @brief Checks if a selection contains a rectangle containing an item
542  *
543  * This function checks if a selection contains a rectangle which exactly contains
544  * an item. The rectangle is automatically built around the given item.
545  *
546  * @param sel The selection to be checked
547  * @param item The item that the rectangle should be built around
548  * @return True if the rectangle is within the selection, false otherwise
549  */
550 int
551 map_selection_contains_item_rect(struct map_selection *sel, struct item *item)
552 {
553         struct coord c;
554         struct coord_rect r;
555         int count=0;
556         while (item_coord_get(item, &c, 1)) {
557                 if (! count) {
558                         r.lu=c;
559                         r.rl=c;
560                 } else
561                         coord_rect_extend(&r, &c);
562                 count++;
563         }
564         if (! count)
565                 return 0;
566         return map_selection_contains_rect(sel, &r);
567
568 }
569
570
571 /**
572  * @brief Checks if a selection contains a item range
573  *
574  * This function checks if a selection contains at least one of the items in range
575  *
576  * @param sel The selection to be checked
577  * @param follow Whether the next pointer of the selection should be followed
578  * @param ranges The item ranges to be checked
579  * @count the number of elements in ranges
580  * @return True if there is a match, false otherwise
581  */
582
583 int
584 map_selection_contains_item_range(struct map_selection *sel, int follow, struct item_range *range, int count)
585 {
586         int i;
587         if (! sel)
588                 return 1;
589         while (sel) {
590                 for (i = 0 ; i < count ; i++) {
591                         if (item_range_intersects_range(&sel->range, &range[i]))
592                                 return 1;
593                 }
594                 if (! follow)
595                         break;
596                 sel=sel->next;
597         }
598         return 0;
599 }
600 /**
601  * @brief Checks if a selection contains a item 
602  *
603  * This function checks if a selection contains a item type
604  *
605  * @param sel The selection to be checked
606  * @param follow Whether the next pointer of the selection should be followed
607  * @param item The item type to be checked
608  * @return True if there is a match, false otherwise
609  */
610
611 int
612 map_selection_contains_item(struct map_selection *sel, int follow, enum item_type type)
613 {
614         if (! sel)
615                 return 1;
616         while (sel) {
617                 if (item_range_contains_item(&sel->range, type))
618                         return 1;
619                 if (! follow)
620                         break;
621                 sel=sel->next;
622         }
623         return 0;
624 }
625
626
627
628 /**
629  * @brief Checks if a pointer points to the private data of a map
630  *
631  * @param map The map whose private data should be checked.
632  * @param priv The private data that should be checked.
633  * @return True if priv is the private data of map
634  */
635 int
636 map_priv_is(struct map *map, struct map_priv *priv)
637 {
638         return (map->priv == priv);
639 }
640
641 void
642 map_dump_filedesc(struct map *map, FILE *out)
643 {
644         struct map_rect *mr=map_rect_new(map, NULL);
645         struct item *item;
646
647         while ((item = map_rect_get_item(mr))) 
648                 item_dump_filedesc(item, map, out);
649         map_rect_destroy(mr);
650 }
651
652 void
653 map_dump_file(struct map *map, const char *file)
654 {
655         FILE *f;
656         f=fopen(file,"w");
657         if (f) {
658                 map_dump_filedesc(map, f);
659                 fclose(f);
660         } else 
661                 dbg(0,"failed to open file '%s'\n",file);
662 }
663
664 void
665 map_dump(struct map *map)
666 {
667         map_dump_filedesc(map, stdout);
668 }