]> git.street.me.uk Git - andy/viking.git/blobdiff - src/dems.c
Move split track menu options into a new submenu
[andy/viking.git] / src / dems.c
index d3d889460cd504e5ef5204c5349b221c1855ea86..08605e0d263b64aa957177cda5c19429723740c1 100644 (file)
@@ -1,6 +1,28 @@
+/*
+ * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
+ *
+ * Copyright (C) 2003-2008, Evan Battaglia <gtoevan@gmx.net>
+ * Copyright (C) 2007, Quy Tonthat <qtonthat@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
 #include <glib.h>
 
 #include "dems.h"
+#include "background.h"
 
 typedef struct {
   VikDEM *dem;
@@ -52,8 +74,11 @@ VikDEM *a_dems_load(const gchar *filename)
 void a_dems_unref(const gchar *filename)
 {
   LoadedDEM *ldem = (LoadedDEM *) g_hash_table_lookup ( loaded_dems, filename );
-  g_assert ( ldem );
-  ldem->ref_count --;
+  if ( !ldem ) {
+    /* This is fine - probably means the loaded list was aborted / not completed for some reason */
+    return;
+  }
+  ldem->ref_count--;
   if ( ldem->ref_count == 0 )
     g_hash_table_remove ( loaded_dems, filename );
 }
@@ -82,9 +107,11 @@ VikDEM *a_dems_get(const gchar *filename)
  * we need to know that they weren't referenced though when we
  * do the a_dems_list_free().
  */
-void a_dems_load_list ( GList **dems )
+int a_dems_load_list ( GList **dems, gpointer threaddata )
 {
   GList *iter = *dems;
+  guint dem_count = 0;
+  const guint dem_total = g_list_length ( *dems );
   while ( iter ) {
     if ( ! a_dems_load((const gchar *) (iter->data)) ) {
       GList *iter_temp = iter->next;
@@ -94,7 +121,16 @@ void a_dems_load_list ( GList **dems )
     } else {
       iter = iter->next;
     }
+    /* When running a thread - inform of progress */
+    if ( threaddata ) {
+      dem_count++;
+      /* NB Progress also detects abort request via the returned value */
+      int result = a_background_thread_progress ( threaddata, ((gdouble)dem_count) / dem_total );
+      if ( result != 0 )
+       return -1; /* Abort thread */
+    }
   }
+  return 0;
 }
 
 /* Takes a string list (GList of strings) of dems (filenames).
@@ -158,3 +194,60 @@ gint16 a_dems_list_get_elev_by_coord ( GList *dems, const VikCoord *coord )
   }
   return VIK_DEM_INVALID_ELEVATION;
 }
+
+typedef struct {
+  const VikCoord *coord;
+  VikDemInterpol method;
+  gint elev;
+} CoordElev;
+
+static gboolean get_elev_by_coord(gpointer key, LoadedDEM *ldem, CoordElev *ce)
+{
+  VikDEM *dem = ldem->dem;
+  gdouble lat, lon;
+
+  if ( dem->horiz_units == VIK_DEM_HORIZ_LL_ARCSECONDS ) {
+    struct LatLon ll_tmp;
+    vik_coord_to_latlon (ce->coord, &ll_tmp );
+    lat = ll_tmp.lat * 3600;
+    lon = ll_tmp.lon * 3600;
+  } else if (dem->horiz_units == VIK_DEM_HORIZ_UTM_METERS) {
+    static struct UTM utm_tmp;
+    if (utm_tmp.zone != dem->utm_zone)
+      return FALSE;
+    vik_coord_to_utm (ce->coord, &utm_tmp);
+    lat = utm_tmp.northing;
+    lon = utm_tmp.easting;
+  } else
+    return FALSE;
+
+  switch (ce->method) {
+    case VIK_DEM_INTERPOL_NONE:
+      ce->elev = vik_dem_get_east_north(dem, lon, lat);
+      break;
+    case VIK_DEM_INTERPOL_SIMPLE:
+      ce->elev = vik_dem_get_simple_interpol(dem, lon, lat);
+      break;
+    case VIK_DEM_INTERPOL_BEST:
+      ce->elev = vik_dem_get_shepard_interpol(dem, lon, lat);
+      break;
+  }
+  return (ce->elev != VIK_DEM_INVALID_ELEVATION);
+}
+
+/* TODO: keep a (sorted) linked list of DEMs and select the best resolution one */
+gint16 a_dems_get_elev_by_coord ( const VikCoord *coord, VikDemInterpol method )
+{
+  CoordElev ce;
+
+  if (!loaded_dems)
+    return VIK_DEM_INVALID_ELEVATION;
+
+  ce.coord = coord;
+  ce.method = method;
+  ce.elev = VIK_DEM_INVALID_ELEVATION;
+
+  if(!g_hash_table_find(loaded_dems, (GHRFunc)get_elev_by_coord, &ce))
+    return VIK_DEM_INVALID_ELEVATION;
+  return ce.elev;
+}