]> git.street.me.uk Git - andy/viking.git/blobdiff - src/vikgeoreflayer.c
Use the correct definition.
[andy/viking.git] / src / vikgeoreflayer.c
index 5aed453d8c8afb265bfcd243f1d8cb1fa7c70e29..7874e01172d8f405c2b1085f2a7167eed78aa7b4 100644 (file)
 #include <stdlib.h>
 #include <ctype.h>
 
+#include "ui_util.h"
 #include "preferences.h"
 #include "icons/icons.h"
+#include "vikmapslayer.h"
+
 /*
 static VikLayerParamData image_default ( void )
 {
@@ -53,6 +56,7 @@ VikLayerParam georef_layer_params[] = {
   { VIK_LAYER_GEOREF, "mpp_northing", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
   { VIK_LAYER_GEOREF, "corner_zone", VIK_LAYER_PARAM_UINT, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
   { VIK_LAYER_GEOREF, "corner_letter_as_int", VIK_LAYER_PARAM_UINT, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
+  { VIK_LAYER_GEOREF, "alpha", VIK_LAYER_PARAM_UINT, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
 };
 
 enum {
@@ -63,6 +67,7 @@ enum {
   PARAM_MN,
   PARAM_CZ,
   PARAM_CL,
+  PARAM_AA,
   NUM_PARAMS };
 
 static const gchar* georef_layer_tooltip ( VikGeorefLayer *vgl );
@@ -129,6 +134,8 @@ VikLayerInterface vik_georef_layer_interface = {
   (VikLayerFuncDraw)                    georef_layer_draw,
   (VikLayerFuncChangeCoordMode)         NULL,
 
+  (VikLayerFuncGetTimestamp)            NULL,
+
   (VikLayerFuncSetMenuItemsSelection)   NULL,
   (VikLayerFuncGetMenuItemsSelection)   NULL,
 
@@ -186,6 +193,8 @@ struct _VikGeorefLayer {
   VikLayer vl;
   gchar *image;
   GdkPixbuf *pixbuf;
+  guint8 alpha;
+
   struct UTM corner; // Top Left
   gdouble mpp_easting, mpp_northing;
   struct LatLon ll_br; // Bottom Right
@@ -265,11 +274,28 @@ static gboolean georef_layer_set_param ( VikGeorefLayer *vgl, guint16 id, VikLay
     case PARAM_ME: vgl->mpp_easting = data.d; break;
     case PARAM_CZ: if ( data.u <= 60 ) vgl->corner.zone = data.u; break;
     case PARAM_CL: if ( data.u >= 65 || data.u <= 90 ) vgl->corner.letter = data.u; break;
+    case PARAM_AA: if ( data.u <= 255 ) vgl->alpha = data.u; break;
     default: break;
   }
   return TRUE;
 }
 
+static void create_image_file ( VikGeorefLayer *vgl )
+{
+  // Create in .viking-maps
+  gchar *filename = g_strconcat ( maps_layer_default_dir(), vik_layer_get_name(VIK_LAYER(vgl)), ".jpg", NULL );
+  GError *error = NULL;
+  gdk_pixbuf_save ( vgl->pixbuf, filename, "jpeg", &error, NULL );
+  if ( error ) {
+    g_warning ( "%s", error->message );
+    g_error_free ( error );
+  }
+  else
+    vgl->image = g_strdup ( filename );
+
+  g_free ( filename );
+}
+
 static VikLayerParamData georef_layer_get_param ( VikGeorefLayer *vgl, guint16 id, gboolean is_file_operation )
 {
   VikLayerParamData rv;
@@ -278,14 +304,18 @@ static VikLayerParamData georef_layer_get_param ( VikGeorefLayer *vgl, guint16 i
     case PARAM_IMAGE: {
       gboolean set = FALSE;
       if ( is_file_operation ) {
+        if ( vgl->pixbuf && !vgl->image ) {
+          // Force creation of image file
+          create_image_file ( vgl );
+        }
         if ( a_vik_get_file_ref_format() == VIK_FILE_REF_FORMAT_RELATIVE ) {
           gchar *cwd = g_get_current_dir();
           if ( cwd ) {
             rv.s = file_GetRelativeFilename ( cwd, vgl->image );
-           if ( !rv.s ) rv.s = "";
-            set = TRUE;
-         }
-       }
+            if ( !rv.s ) rv.s = "";
+              set = TRUE;
+          }
+        }
       }
       if ( !set )
         rv.s = vgl->image ? vgl->image : "";
@@ -297,6 +327,7 @@ static VikLayerParamData georef_layer_get_param ( VikGeorefLayer *vgl, guint16 i
     case PARAM_ME: rv.d = vgl->mpp_easting; break;
     case PARAM_CZ: rv.u = vgl->corner.zone; break;
     case PARAM_CL: rv.u = vgl->corner.letter; break;
+    case PARAM_AA: rv.u = vgl->alpha; break;
     default: break;
   }
   return rv;
@@ -325,9 +356,43 @@ static VikGeorefLayer *georef_layer_new ( VikViewport *vvp )
   vgl->scaled_height = 0;
   vgl->ll_br.lat = 0.0;
   vgl->ll_br.lon = 0.0;
+  vgl->alpha = 255;
   return vgl;
 }
 
+/**
+ * Return mpp for the given coords, coord mode and image size.
+ */
+static void georef_layer_mpp_from_coords ( VikCoordMode mode, struct LatLon ll_tl, struct LatLon ll_br, guint width, guint height, gdouble *xmpp, gdouble *ympp )
+{
+  struct LatLon ll_tr;
+  ll_tr.lat = ll_tl.lat;
+  ll_tr.lon = ll_br.lon;
+
+  struct LatLon ll_bl;
+  ll_bl.lat = ll_br.lat;
+  ll_bl.lon = ll_tl.lon;
+
+  // UTM mode should be exact MPP
+  gdouble factor = 1.0;
+  if ( mode == VIK_COORD_LATLON ) {
+    // NB the 1.193 - is at the Equator.
+    // http://wiki.openstreetmap.org/wiki/Zoom_levels
+
+    // Convert from actual image MPP to Viking 'pixelfact'
+    gdouble mid_lat = (ll_bl.lat + ll_tr.lat ) / 2.0;
+    // Protect against div by zero (but shouldn't have 90 degrees for mid latitude...)
+    if ( fabs(mid_lat) < 89.9 )
+      factor = cos(DEG2RAD(mid_lat)) * 1.193;
+  }
+
+  gdouble diffx = a_coords_latlon_diff ( &ll_tl, &ll_tr );
+  *xmpp = (diffx / width) / factor;
+
+  gdouble diffy = a_coords_latlon_diff ( &ll_tl, &ll_bl );
+  *ympp = (diffy / height) / factor;
+}
+
 static void georef_layer_draw ( VikGeorefLayer *vgl, VikViewport *vp )
 {
   if ( vgl->pixbuf )
@@ -426,6 +491,9 @@ static void georef_layer_load_image ( VikGeorefLayer *vgl, VikViewport *vp, gboo
   {
     vgl->width = gdk_pixbuf_get_width ( vgl->pixbuf );
     vgl->height = gdk_pixbuf_get_height ( vgl->pixbuf );
+
+    if ( vgl->pixbuf && vgl->alpha <= 255 )
+      vgl->pixbuf = ui_pixbuf_set_alpha ( vgl->pixbuf, vgl->alpha );
   }
   /* should find length and width here too */
 }
@@ -718,19 +786,8 @@ static void calculate_mpp_from_coords ( GtkWidget *ww, VikGeorefLayer *vgl )
     struct LatLon ll_tl = get_ll_tl (vgl);
     struct LatLon ll_br = get_ll_br (vgl);
 
-    struct LatLon ll_tr;
-    ll_tr.lat = ll_tl.lat;
-    ll_tr.lon = ll_br.lon;
-
-    struct LatLon ll_bl;
-    ll_bl.lat = ll_br.lat;
-    ll_bl.lon = ll_tl.lon;
-
-    gdouble diffx = a_coords_latlon_diff ( &ll_tl, &ll_tr );
-    gdouble xmpp = diffx / width;
-
-    gdouble diffy = a_coords_latlon_diff ( &ll_tl, &ll_bl );
-    gdouble ympp = diffy / height;
+    gdouble xmpp, ympp;
+    georef_layer_mpp_from_coords ( VIK_COORD_LATLON, ll_tl, ll_br, width, height, &xmpp, &ympp );
 
     gtk_spin_button_set_value ( GTK_SPIN_BUTTON(vgl->cw.x_spin), xmpp );
     gtk_spin_button_set_value ( GTK_SPIN_BUTTON(vgl->cw.y_spin), ympp );
@@ -868,6 +925,15 @@ static gboolean georef_layer_dialog ( VikGeorefLayer *vgl, gpointer vp, GtkWindo
   gtk_notebook_append_page(GTK_NOTEBOOK(cw.tabs), GTK_WIDGET(table_ll), gtk_label_new(_("Latitude/Longitude")));
   gtk_box_pack_start ( dgbox, cw.tabs, TRUE, TRUE, 0 );
 
+  GtkWidget *alpha_hbox = gtk_hbox_new ( FALSE, 0 );
+  // GTK3 => GtkWidget *alpha_scale = gtk_scale_new_with_range ( GTK_ORIENTATION_HORIZONTAL, 0, 255, 1 );
+  GtkWidget *alpha_scale = gtk_hscale_new_with_range ( 0, 255, 1 );
+  gtk_scale_set_digits ( GTK_SCALE(alpha_scale), 0 );
+  gtk_range_set_value ( GTK_RANGE(alpha_scale), vgl->alpha );
+  gtk_box_pack_start ( GTK_BOX(alpha_hbox), gtk_label_new(_("Alpha:")), TRUE, TRUE, 0 );
+  gtk_box_pack_start ( GTK_BOX(alpha_hbox), alpha_scale, TRUE, TRUE, 0 );
+  gtk_box_pack_start ( dgbox, alpha_hbox, TRUE, TRUE, 0 );
+
   vgl->cw = cw;
 
   g_signal_connect ( G_OBJECT(vgl->cw.tabs), "switch-page", G_CALLBACK(switch_tab), vgl );
@@ -901,12 +967,22 @@ static gboolean georef_layer_dialog ( VikGeorefLayer *vgl, gpointer vp, GtkWindo
     vgl->mpp_northing = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(cw.y_spin) );
     vgl->ll_br = get_ll_br (vgl);
     check_br_is_good_or_msg_user ( vgl );
-    if ( g_strcmp0 (vgl->image, vik_file_entry_get_filename(VIK_FILE_ENTRY(cw.imageentry)) ) != 0 )
+    // TODO check if image has changed otherwise no need to regenerate pixbuf
+    if ( !vgl->pixbuf )
     {
-      georef_layer_set_image ( vgl, vik_file_entry_get_filename(VIK_FILE_ENTRY(cw.imageentry)) );
-      georef_layer_load_image ( vgl, VIK_VIEWPORT(vp), FALSE );
+      if ( g_strcmp0 (vgl->image, vik_file_entry_get_filename(VIK_FILE_ENTRY(cw.imageentry)) ) != 0 )
+      {
+        georef_layer_set_image ( vgl, vik_file_entry_get_filename(VIK_FILE_ENTRY(cw.imageentry)) );
+        georef_layer_load_image ( vgl, VIK_VIEWPORT(vp), FALSE );
+      }
     }
 
+    vgl->alpha = (guint8) gtk_range_get_value ( GTK_RANGE(alpha_scale) );
+    if ( vgl->pixbuf && vgl->alpha <= 255 )
+      vgl->pixbuf = ui_pixbuf_set_alpha ( vgl->pixbuf, vgl->alpha );
+    if ( vgl->scaled && vgl->alpha <= 255 )
+      vgl->scaled = ui_pixbuf_set_alpha ( vgl->scaled, vgl->alpha );
+
     a_settings_set_integer ( VIK_SETTINGS_GEOREF_TAB, gtk_notebook_get_current_page(GTK_NOTEBOOK(cw.tabs)) );
 
     gtk_widget_destroy ( GTK_WIDGET(dialog) );
@@ -1032,3 +1108,67 @@ static gboolean georef_layer_move_press ( VikGeorefLayer *vgl, GdkEventButton *e
   vgl->click_y = event->y;
   return TRUE;
 }
+
+static void goto_center_ll ( VikViewport *vp,
+                             struct LatLon ll_tl,
+                             struct LatLon ll_br )
+{
+  VikCoord vc_center;
+  struct LatLon ll_center;
+
+  ll_center.lat = (ll_tl.lat + ll_br.lat) / 2.0;
+  ll_center.lon = (ll_tl.lon + ll_br.lon) / 2.0;
+
+  vik_coord_load_from_latlon ( &vc_center, vik_viewport_get_coord_mode (vp), &ll_center );
+  vik_viewport_set_center_coord ( vp, &vc_center, TRUE );
+}
+
+/**
+ *
+ */
+VikGeorefLayer *vik_georef_layer_create ( VikViewport *vp,
+                                          VikLayersPanel *vlp,
+                                          const gchar *name,
+                                          GdkPixbuf *pixbuf,
+                                          VikCoord *coord_tl,
+                                          VikCoord *coord_br )
+{
+  VikGeorefLayer *vgl = georef_layer_new ( vp );
+  vik_layer_rename ( VIK_LAYER(vgl), name );
+
+  vgl->pixbuf = pixbuf;
+
+  vik_coord_to_utm ( coord_tl, &(vgl->corner) );
+  vik_coord_to_latlon ( coord_br, &(vgl->ll_br) );
+
+  if ( vgl->pixbuf ) {
+    vgl->width = gdk_pixbuf_get_width ( vgl->pixbuf );
+    vgl->height = gdk_pixbuf_get_height ( vgl->pixbuf );
+
+    if ( vgl->width > 0 && vgl->height > 0 ) {
+
+      struct LatLon ll_tl;
+      vik_coord_to_latlon ( coord_tl, &ll_tl);
+      struct LatLon ll_br;
+      vik_coord_to_latlon ( coord_br, &ll_br);
+
+      VikCoordMode mode = vik_viewport_get_coord_mode (vp);
+
+      gdouble xmpp, ympp;
+      georef_layer_mpp_from_coords ( mode, ll_tl, ll_br, vgl->width, vgl->height, &xmpp, &ympp );
+      vgl->mpp_easting = xmpp;
+      vgl->mpp_northing = ympp;
+
+      goto_center_ll ( vp, ll_tl, ll_br);
+      // Set best zoom level
+      struct LatLon maxmin[2] = { ll_tl, ll_br };
+      vu_zoom_to_show_latlons ( vik_viewport_get_coord_mode(vp), vp, maxmin );
+
+      return vgl;
+    }
+  }
+
+  // Bad image
+  georef_layer_free ( vgl );
+  return NULL;
+}