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

Contents of /navit/navit/map.c

Parent Directory Parent Directory | Revision Log Revision Log


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