def altitude_range(rpc, x, y, w, h, margin_top=0, margin_bottom=0): """ Computes an altitude range using SRTM data. Args: rpc: instance of the rpc_model.RPCModel class x, y, w, h: four integers defining a rectangular region of interest (ROI) in the image. (x, y) is the top-left corner, and (w, h) are the dimensions of the rectangle. margin_top: margin (in meters) to add to the upper bound of the range margin_bottom: margin (usually negative) to add to the lower bound of the range Returns: lower and upper bounds on the altitude of the world points that are imaged by the RPC projection function in the provided ROI. To compute these bounds, we use SRTM data. The altitudes are computed with respect to the WGS84 reference ellipsoid. """ # TODO: iterate the procedure used here to get a finer estimation of the # bounding box on the ellipsoid and thus of the altitude range. For flat # regions it will not improve much, but for mountainous regions there is a # lot to improve. # find bounding box on the ellipsoid (in geodesic coordinates) lon_m, lon_M, lat_m, lat_M = geodesic_bounding_box(rpc, x, y, w, h) # if bounding box is out of srtm domain, return coarse altitude estimation if (lat_m < -60 or lat_M > 60 or cfg['disable_srtm']): print("WARNING: returning coarse range from rpc") return altitude_range_coarse(rpc, cfg['rpc_alt_range_scale_factor']) # sample the bounding box with regular step of 3 arcseconds (srtm # resolution) ellipsoid_points = sample_bounding_box(lon_m, lon_M, lat_m, lat_M) # compute srtm height on all these points srtm = common.run_binary_on_list_of_points(ellipsoid_points, 'srtm4', env_var=('SRTM4_CACHE', cfg['srtm_dir'])) h = np.ravel(srtm) # srtm data may contain 'nan' values (meaning no data is available there). # These points are most likely water (sea) and thus their height with # respect to geoid is 0. Thus we replace the nans with 0. # TODO: this should not be zero, but the geoid/ellipsoid offset srtm[np.isnan(h)] = 0 # extract extrema (and add a +-100m security margin) h_m = np.round(h.min()) + margin_bottom h_M = np.round(h.max()) + margin_top return h_m, h_M
def geocentric_to_geodetic(x, y, z): """ Converts geocentric cartesian coordinates to WGS84 ellipsoidal coordinates. Args: x, y, z: the cartesian coordinates of the input point, expressed in the geocentric frame. Returns: lat: latitude, in degrees between -90 and 90 lon: longitude, between -180 and 180 alt: altitude, in meters, above the WGS84 reference ellipsoid The conversion is made by a commandline tool, CartConvert, which is part of the GeographicLib library: http://geographiclib.sourceforge.net/html/intro.html """ pts = np.vstack([x, y, z]).T out = common.run_binary_on_list_of_points(pts, 'CartConvert', '-r') return out[:, 0], out[:, 1], out[:, 2]
def geodetic_to_geocentric(lat, lon, alt): """ Converts WGS84 ellipsoidal coordinates to geocentric cartesian coordinates. Args: lat: latitude, in degrees between -90 and 90 lon: longitude, between -180 and 180 alt: altitude, in meters, above the WGS84 reference ellipsoid Returns: x, y, z: the cartesian coordinates of the input point, expressed in the geocentric frame. The conversion is made by a commandline tool, CartConvert, which is part of the GeographicLib library: http://geographiclib.sourceforge.net/html/intro.html """ pts = np.vstack([lat, lon, alt]).T out = common.run_binary_on_list_of_points(pts, 'CartConvert') return out[:, 0], out[:, 1], out[:, 2]