/** * 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 gdouble vik_coord_diff_safe(const VikCoord *c1, const VikCoord *c2) { struct LatLon a, b; vik_coord_to_latlon ( c1, &a ); vik_coord_to_latlon ( c2, &b ); return a_coords_latlon_diff ( &a, &b ); }
gdouble vik_coord_diff(const VikCoord *c1, const VikCoord *c2) { if ( c1->mode == c2->mode ) return vik_coord_diff_safe ( c1, c2 ); if ( c1->mode == VIK_COORD_UTM ) return a_coords_utm_diff ( (const struct UTM *) c1, (const struct UTM *) c2 ); else return a_coords_latlon_diff ( (const struct LatLon *) c1, (const struct LatLon *) c2 ); }
double a_coords_utm_diff( const struct UTM *utm1, const struct UTM *utm2 ) { static struct LatLon tmp1, tmp2; if ( utm1->zone == utm2->zone ) { return sqrt ( pow ( utm1->easting - utm2->easting, 2 ) + pow ( utm1->northing - utm2->northing, 2 ) ); } else { a_coords_utm_to_latlon ( utm1, &tmp1 ); a_coords_utm_to_latlon ( utm2, &tmp2 ); return a_coords_latlon_diff ( &tmp1, &tmp2 ); } }
static gboolean dem_get_ref_points_elev_dist(VikDEM *dem, gdouble east, gdouble north, /* in seconds */ gint16 *elevs, gint16 *dists) { int i; int cols[4], rows[4]; struct LatLon ll[4]; struct LatLon pos; if ( east > dem->max_east || east < dem->min_east || north > dem->max_north || north < dem->min_north ) return FALSE; /* got nothing */ pos.lon = east/3600; pos.lat = north/3600; /* order of the data: sw, nw, ne, se */ /* sw */ cols[0] = (gint) floor((east - dem->min_east) / dem->east_scale); rows[0] = (gint) floor((north - dem->min_north) / dem->north_scale); ll[0].lon = (dem->min_east + dem->east_scale*cols[0])/3600; ll[0].lat = (dem->min_north + dem->north_scale*rows[0])/3600; /* nw */ cols[1] = cols[0]; rows[1] = rows[0] + 1; ll[1].lon = ll[0].lon; ll[1].lat = ll[0].lat + (gdouble)dem->north_scale/3600; /* ne */ cols[2] = cols[0] + 1; rows[2] = rows[0] + 1; ll[2].lon = ll[0].lon + (gdouble)dem->east_scale/3600; ll[2].lat = ll[0].lat + (gdouble)dem->north_scale/3600; /* se */ cols[3] = cols[0] + 1; rows[3] = rows[0]; ll[3].lon = ll[0].lon + (gdouble)dem->east_scale/3600; ll[3].lat = ll[0].lat; for (i = 0; i < 4; i++) { if ((elevs[i] = vik_dem_get_xy(dem, cols[i], rows[i])) == VIK_DEM_INVALID_ELEVATION) return FALSE; dists[i] = a_coords_latlon_diff(&pos, &ll[i]); } #if 0 /* debug */ for (i = 0; i < 4; i++) fprintf(stderr, "%f:%f:%d:%d ", ll[i].lat, ll[i].lon, dists[i], elevs[i]); fprintf(stderr, " north_scale=%f\n", dem->north_scale); #endif return TRUE; /* all OK */ }