/* GNOME canvas based interface to a map using a simple cylindrical proj */ /* */ /* Copyright (C) 1999 Red Hat, Incorportated */ /* Original work by Michael Fulbright */ #include #include #include "gnome-map.h" /* look in for valid values */ #define MAP_CURSOR GDK_LEFT_PTR /** * gnome_map_set_image: * @map: Map to apply image to. * @imagefile: Filename of image for map. * * This function sets the image used for the map to @imagefile. It is * assumed that this image is a simple cylindrical projection. * * Return value: 0 on success, -1 if image could not be loaded **/ static gint gnome_map_set_image ( GnomeMap *map, gchar *imagefile ) { g_return_val_if_fail ( map != NULL, -1 ); g_return_val_if_fail ( map->image == NULL, -1 ); /* load map image */ if (map->aa) map->image = gnome_canvas_load_alpha (imagefile); else map->image = gdk_imlib_load_image (imagefile); if (!map->image) return -1; return 0; } static void canvas_realize_event (GtkWidget *canvas, gpointer *data) { GdkCursor *ptrcursor; ptrcursor = gdk_cursor_new (MAP_CURSOR); if (!ptrcursor) { g_warning ("Unable to load new cursor %d for map\n", MAP_CURSOR); return; } gdk_window_set_cursor (canvas->window, ptrcursor); gdk_cursor_destroy (ptrcursor); } /** * gnome_map_new: * @imagefile: File to be used map image. * @width: Width of map view in pixels. * @height: Height of map view in pixels. * @antialias: Boolean used to set map to use antialias canvas or not. * * Creates a new map, using anti-aliased or normal canvas based on the * value of @antialias. Of anti-aliased maps the image file must be * in PNG format (this is a gnome-canvas limitation as of gnome-libs 1.0.10). * If @width and @height are both <= 0, then the map image size is used. * If only one of @width or @height is > 0, then the unspecified * dimension is scaled (perserving the aspect of the original image). * * Return value: The newly-created map structure or NULL if image couldn't * be loaded. **/ GnomeMap * gnome_map_new ( gchar *imagefile, gint width, gint height, gboolean aa ) { GnomeCanvasGroup *canvas_root; GnomeMap *map; gint h, w; map = g_new0 ( GnomeMap, 1 ); map->aa = aa; if ( gnome_map_set_image ( map, imagefile ) < 0 ) { g_free (map); return NULL; } /* create a canvas */ if (aa) { gtk_widget_push_visual (gdk_rgb_get_visual ()); gtk_widget_push_colormap (gdk_rgb_get_cmap ()); map->canvas = gnome_canvas_new_aa (); } else { gtk_widget_push_visual (gdk_imlib_get_visual ()); gtk_widget_push_colormap (gdk_imlib_get_colormap ()); map->canvas = gnome_canvas_new (); } /* set map size and scaling */ if ( width <= 0 && height <= 0 ) { w = map->image->rgb_width; h = map->image->rgb_height; } else if ( width > 0 && height <= 0 ) { w = width; h = (int)(((float)w/(float)map->image->rgb_width)*map->image->rgb_height); } else if ( width <= 0 && height > 0 ) { h = height; w = (int)(((float)h/(float)map->image->rgb_height)*map->image->rgb_width); } else { w = width; h = height; } map->width = w; map->height = h; map->long1 = -180.0; map->lat1 = -90.0; map->long2 = 180.0; map->lat2 = 90.0; gtk_widget_set_usize (map->canvas, w, h); gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (map->canvas), 1.0); gnome_canvas_set_scroll_region (GNOME_CANVAS (map->canvas), 0.0, 0.0, (double)w, (double)h); gtk_widget_show(map->canvas); /* Setup canvas items */ canvas_root = gnome_canvas_root (GNOME_CANVAS (map->canvas)); map->image_item = gnome_canvas_item_new (canvas_root, gnome_canvas_image_get_type (), "image", map->image, "x", 0.0, "y", 0.0, "width", (double) w, "height", (double) h, "anchor", GTK_ANCHOR_NW, NULL); /* grap realize signal so we can set cursor for map */ gtk_signal_connect (GTK_OBJECT (map->canvas), "realize", (GtkSignalFunc) canvas_realize_event, NULL); /* restore to original */ gtk_widget_pop_colormap (); gtk_widget_pop_visual (); return map; } /** * gnome_map_get_image_size: Get the unscaled image size of map image. * @map: The map which image size is desired for. * @width: Width of map in pixels. * @height: Height of map in pixels. * * Given the GnomeMap @map, this function returns the dimensions of the * original unscaled map image. * * Return value: None. **/ void gnome_map_get_image_size ( GnomeMap *map, gint *width, gint *height ) { g_return_if_fail ( map != NULL || map->image != NULL); g_return_if_fail ( width != NULL || height != NULL ); *width = map->image->rgb_width; *height = map->image->rgb_width; } /** * gnome_map_set_size: Set screen dimensions (in pixels) of map view. * @map: Map to apply dimensions to. * @width: Desired width of map view. * @height: Desired height of map view. * * Given a map which has an image associated with it via the * gnome_map_set_image() call, set the onscreen size of the map view widget. * * Return value: None. **/ void gnome_map_set_size ( GnomeMap *map, gint width, gint height ) { g_return_if_fail ( map != NULL ); g_return_if_fail ( map->canvas != NULL ); g_return_if_fail ( map->image != NULL ); g_return_if_fail ( width > 0 ); g_return_if_fail ( height > 0 ); } /** * gnome_map_xlat_map2screen: Convert from map coordinates to screen coordinates. * @map: Map to apply dimensions to. * @longitude: Longitude coordinate to convert (in degrees). * @latitude: Latitude coordinate to convert (in degrees). * @sx: Converted screen coordinate. * @sy: Converted screen coordinate. * * A (longitude, latitude) pair is converted to a (x, y) canvas coordinate. * (An obvious improvement to the gnome-map would be to just let the * canvas do the mapping internally. If this change is made this function * will still work but will be a small stub). * * Return value: None. **/ void gnome_map_xlat_map2screen ( GnomeMap *map, double longitude, double latitude, double *sx, double *sy ) { g_return_if_fail ( map != NULL ); *sx = (map->width/2.0 + (map->width/2.0)*longitude/180.0); *sy = (map->height/2.0 - (map->height/2.0)*latitude/90.0); } /** * gnome_map_xlat_screen2map: Convert from screen coordinates to map coordinates. * @map: Map to apply dimensions to. * @sx: Screen coordinate to convert. * @sy: Screen coordinate to convert. * @longitude: Converted longitude coordinate (in degrees). * @latitude: Converted latitude coordinate (in degrees). * * A (x, y) canvas coordinate is converted to a (longitude, latitude) pair. * (An obvious improvement to the gnome-map would be to just let the * canvas do the mapping internally. If this change is made this function * will still work but will be a small stub). * * Return value: None. **/ void gnome_map_xlat_screen2map ( GnomeMap *map, double sx, double sy, double *longitude, double *latitude) { g_return_if_fail ( map != NULL ); *longitude = ( sx - (double)map->width/2.0)/((double)map->width/2.0)*180.0; *latitude = ((double)map->height/2.0-sy)/((double)map->height/2.0)*90.0; } /** * gnome_map_set_view: Set view of map in map coordinates. * @map: Map to apply dimensions to. * @longitude1: Longitude of corner 1. * @latitude1: Latitude of corner 1. * @longitude2: Longitude of corner 2. * @latitude2: Latitude of corner 2. * * Sets view of map to a box defined by the two corners given in map * coordinates. * * Return value: None. **/ void gnome_map_set_view ( GnomeMap *map, double longitude1, double latitude1, double longitude2, double latitude2) { double x1, y1, x2, y2; double scale; g_return_if_fail ( map != NULL ); g_return_if_fail ( longitude1 >= -180.0 && longitude1 <= 180.0 ); g_return_if_fail ( longitude2 >= -180.0 && longitude2 <= 180.0 ); g_return_if_fail ( latitude1 >= -90.0 && latitude1 <= 90.0 ); g_return_if_fail ( latitude2 >= -90.0 && latitude2 <= 90.0 ); gnome_map_xlat_map2screen (map, longitude1, latitude1, &x1, &y1); gnome_map_xlat_map2screen (map, longitude2, latitude2, &x2, &y2); gnome_canvas_set_scroll_region (GNOME_CANVAS(map->canvas), x1, y1, x2, y2); if (longitude1 < longitude2) { map->long1 = longitude1; map->long2 = longitude2; } else { map->long1 = longitude2; map->long2 = longitude1; } if (latitude1 < latitude2) { map->lat1 = latitude1; map->lat2 = latitude2; } else { map->lat1 = latitude2; map->lat2 = latitude1; } scale = ((double)map->width)/fabs(x1-x2); gnome_canvas_set_pixels_per_unit (GNOME_CANVAS(map->canvas), scale); } /** * gnome_map_is_loc_in_view: Test to see if location is on current view * @map: Map to apply dimensions to. * @longitude: Longitude of location to test. * @latitude: Latitude of location to test. * * Tests whether (longitude, latitude) is within current map view. * * Return value: TRUE is visible, FALSE if not. **/ gboolean gnome_map_is_loc_in_view (GnomeMap *map, double longitude, double latitude) { return !(longitude < map->long1 || longitude > map->long2 || latitude < map->lat1 || latitude > map->lat2); }