]> git.street.me.uk Git - andy/viking.git/blobdiff - src/vikgeoreflayer.c
Use the correct definition.
[andy/viking.git] / src / vikgeoreflayer.c
index 8b9bb4720bc75759a55482d08b19db39b3affa94..7874e01172d8f405c2b1085f2a7167eed78aa7b4 100644 (file)
@@ -37,6 +37,8 @@
 #include "ui_util.h"
 #include "preferences.h"
 #include "icons/icons.h"
+#include "vikmapslayer.h"
+
 /*
 static VikLayerParamData image_default ( void )
 {
@@ -278,6 +280,22 @@ static gboolean georef_layer_set_param ( VikGeorefLayer *vgl, guint16 id, VikLay
   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;
@@ -286,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 : "";
@@ -338,6 +360,39 @@ static VikGeorefLayer *georef_layer_new ( VikViewport *vvp )
   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 )
@@ -437,7 +492,7 @@ 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 )
+    if ( vgl->pixbuf && vgl->alpha <= 255 )
       vgl->pixbuf = ui_pixbuf_set_alpha ( vgl->pixbuf, vgl->alpha );
   }
   /* should find length and width here too */
@@ -731,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 );
@@ -923,16 +967,20 @@ 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 )
+    if ( vgl->pixbuf && vgl->alpha <= 255 )
       vgl->pixbuf = ui_pixbuf_set_alpha ( vgl->pixbuf, vgl->alpha );
-    if ( vgl->scaled && vgl->alpha < 255 )
+    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)) );
@@ -1060,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;
+}