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

Contents of /navit/navit/map.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 27 - (show 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 /**
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