]> err.no Git - mapper/blob - src/map-poi.c
Allow a bit faster movement for the random gps simulator.
[mapper] / src / map-poi.c
1 /*
2  * This file is part of mapper
3  *
4  * Copyright (C) 2007 Kaj-Michael Lang
5  * Copyright (C) 2006-2007 John Costigan.
6  *
7  * POI and GPS-Info code originally written by Cezary Jackiewicz.
8  *
9  * Default map data provided by http://www.openstreetmap.org/
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #include <config.h>
27
28 #include <gtk/gtk.h>
29
30 #include "utils.h"
31 #include "poi.h"
32 #include "gps.h"
33 #include "map.h"
34 #include "settings.h"
35 #include "mapper-types.h"
36 #include "ui-common.h"
37 #include "map-poi.h"
38 #include "latlon.h"
39 #include "osm-db.h"
40
41 #define POI_FONT_SIZE_BIG (10)
42 #define POI_FONT_SIZE_SMALL (8)
43
44 /* POI icon text pango stuff */
45 static PangoContext *context = NULL;
46 static PangoLayout *layout = NULL;
47 static PangoFontDescription *fontdesc = NULL;
48 static GdkGC *poi_gc;
49 static GtkListStore *poi_store=NULL;
50 static gint last_zoom=-1;
51 static guint prev_ux=0, prev_uy=0;
52
53 /****************************************************************************/
54
55 gboolean 
56 map_poi_init(GtkWidget *map_widget)
57 {
58 context=gtk_widget_get_pango_context(map_widget);
59 layout=pango_layout_new(context);
60 fontdesc=pango_font_description_new();
61 pango_font_description_set_family(fontdesc,"Sans Serif");
62 pango_font_description_set_size(fontdesc, POI_FONT_SIZE_SMALL*PANGO_SCALE);
63 pango_layout_set_font_description (layout, fontdesc);
64 pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
65 pango_layout_set_width(layout, 80*PANGO_SCALE);
66 poi_gc=gdk_gc_new(map_widget->window);
67 return TRUE;
68 }
69
70 void
71 map_poi_deinit(void)
72 {
73 map_poi_cache_clear();
74 #if 0
75 g_object_unref(layout);
76 g_object_unref(fontdesc);
77 g_object_unref(poi_gc);
78 #endif
79 }
80
81 static void 
82 map_poi_title(gint x, gint y, GdkGC *gc, gchar *title)
83 {
84 gint w,h;
85
86 pango_layout_set_text(layout, title, -1);
87 pango_layout_get_pixel_size(layout, &w, &h);
88 gdk_draw_layout(_map_pixmap, gc, x-(w>>1), y-h-_draw_width, layout);
89 }
90
91 /** 
92  * Set POI color from given #rrggbb string, fallback to default if it fails
93  */
94 static inline GdkGC *
95 map_set_poi_fg_color_from_string(gchar *hexcolor, GdkGC *def)
96 {
97 GdkColor color;
98
99 if (!hexcolor)
100         return def;
101
102 if (gdk_color_parse(hexcolor, &color)) {
103         gdk_gc_set_rgb_fg_color(poi_gc, &color);
104         return poi_gc;
105 }
106
107 return def;
108 }
109
110 void
111 map_poi_cache_clear(void)
112 {
113 if (poi_store==NULL)
114         return;
115
116 gtk_list_store_clear(poi_store);
117 g_object_unref(G_OBJECT(poi_store));
118 poi_store=NULL;
119 }
120
121 static gboolean
122 map_poi_reload_poi(guint unitx, guint unity, gdouble lat1, gdouble lon1, gdouble lat2, gdouble lon2)
123 {
124 guint pois;
125
126 /* Reload POIs if we zoom out or have moved */
127 if ((last_zoom<_zoom || prev_ux!=unitx || prev_uy!=unity) && poi_store!=NULL) {
128         g_printf("Reloading POIs\n");
129         map_poi_cache_clear();
130 } else {
131         g_printf("Using cached POIs\n");
132 }
133
134 if (poi_store==NULL) {
135         if (poi_get_list_inside(lat1, lon1, lat2, lon2, &poi_store, &pois)==FALSE)
136                 return FALSE;
137 }
138 return TRUE;
139 }
140
141 gboolean
142 map_poi_find_at_latlon(gdouble lat, gdouble lon, guint *poi_id)
143 {
144 GtkTreeIter iter;
145 gboolean found=FALSE;
146 gboolean valid;
147 gdouble pdist=99999.0;
148
149 if (_poi_zoom <= _zoom) 
150         return FALSE;
151
152 #if 0
153 if (_zoom>5)
154         return FALSE;
155 #endif
156
157 if (poi_store==NULL)
158         return FALSE;
159
160 valid=gtk_tree_model_get_iter_first(GTK_TREE_MODEL(poi_store), &iter);
161 if (valid==FALSE)
162         return FALSE;
163
164 while (valid) {
165         gdouble tmp, plat, plon;
166         guint id;
167
168         gtk_tree_model_get(GTK_TREE_MODEL(poi_store),
169                         &iter,
170                         ITEM_ID, &id,
171                         ITEM_LAT, &plat,
172                         ITEM_LON, &plon,
173                         -1);
174
175         /* XXX: Use quicker and simple distance check */
176         tmp=calculate_distance(lat, lon, plat, plon);
177         if ((tmp<pdist) && (tmp<0.011)) {
178                 found=TRUE;
179                 pdist=tmp;
180                 *poi_id=id;
181         }
182
183         valid=gtk_tree_model_iter_next(GTK_TREE_MODEL(poi_store), &iter);
184 }
185
186 return found;
187 }
188
189 /**
190  * Render all the POI data.
191  * This should be done before rendering track data.
192  */
193 void
194 map_render_all_pois(guint width, guint height)
195 {
196 GdkPixbuf *pixbuf = NULL;
197 GtkTreeIter iter;
198 guint unitx, unity;
199 gint poix, poiy;
200 gdouble lat1, lat2, lon1, lon2;
201 gboolean valid;
202
203 if (_poi_zoom <= _zoom) 
204         return;
205
206 unitx = x2unit(0);
207 unity = y2unit(height);
208 unit2latlon(unitx, unity, lat1, lon1);
209
210 unitx = x2unit(width);
211 unity = y2unit(0);
212 unit2latlon(unitx, unity, lat2, lon2);
213
214 if (map_poi_reload_poi(unitx, unity, lat1, lon1, lat2, lon2)==FALSE)
215         return;
216
217 valid=gtk_tree_model_get_iter_first(GTK_TREE_MODEL(poi_store), &iter);
218 if (!valid)
219         return;
220
221 if (_zoom<2) {
222         pango_font_description_set_size(fontdesc, POI_FONT_SIZE_BIG*PANGO_SCALE);
223         pango_layout_set_font_description (layout, fontdesc);
224         pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
225 } else {
226         pango_font_description_set_size(fontdesc, POI_FONT_SIZE_SMALL*PANGO_SCALE);
227         pango_layout_set_font_description (layout, fontdesc);
228         pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
229 }
230
231 last_zoom=_zoom;
232 prev_ux=unitx;
233 prev_uy=unity;
234
235 while (valid) {
236         GdkGC *gc;
237         gchar *label; 
238         gchar *icon=NULL, *color=NULL;
239
240         gtk_tree_model_get(GTK_TREE_MODEL(poi_store),
241                         &iter,
242                         ITEM_LAT, &lat1,
243                         ITEM_LON, &lon1,
244                         ITEM_LABEL, &label,
245                         ITEM_ICON, &icon,
246                         ITEM_COLOR, &color,
247                         -1);
248
249         pixbuf=poi_get_icon(icon, _zoom<2 ? TRUE : FALSE);
250         gc=map_set_poi_fg_color_from_string(color, _gc[COLORABLE_POI]);
251
252         latlon2unit(lat1, lon1, unitx, unity);
253         poix=unit2bufx(unitx);
254         poiy=unit2bufy(unity);
255
256         if (!pixbuf) {
257                 /* No icon for POI or for category - draw default. */
258                 gdk_draw_arc(_map_pixmap, gc, FALSE, poix - _draw_width, poiy - _draw_width,
259                         (MAX_ZOOM-_zoom)/6 * _draw_width, (MAX_ZOOM-_zoom)/6 * _draw_width, 0, 360 * 64);
260         } else {
261                 guint w,h;
262                 w=gdk_pixbuf_get_width(pixbuf);
263                 h=gdk_pixbuf_get_height(pixbuf);
264                 gdk_draw_pixbuf(_map_pixmap, gc, pixbuf, 0, 0, poix-w/2, poiy-h/2, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);
265 #if 0
266                 /* Draw rectangle around icon. Not really need with the square icons */
267                 if (_zoom<2)
268                         gdk_draw_rectangle(_map_pixmap, gc, FALSE, poix-w/2-1, poiy-h/2-1, w+1, h+1);
269 #endif
270         }
271
272         if (_zoom<3 && label) {
273                 map_poi_title(poix, poiy, gc, label);
274         }
275
276         valid=gtk_tree_model_iter_next(GTK_TREE_MODEL(poi_store), &iter);
277 }
278 }