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

Contents of /navit/navit/map.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki