/[zanavi_public1]/navit/navit/map.c
ZANavi

Contents of /navit/navit/map.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki