def _test(self, mlons, mlats, mdepths, slons, slats, sdepths, expected_mpoint_indices): mlons, mlats, mdepths = [ numpy.array(arr, float) for arr in (mlons, mlats, mdepths) ] slons, slats, sdepths = [ numpy.array(arr, float) for arr in (slons, slats, sdepths) ] actual_indices = geodetic.min_distance(mlons, mlats, mdepths, slons, slats, sdepths, indices=True) numpy.testing.assert_equal(actual_indices, expected_mpoint_indices) dists = geodetic.min_distance(mlons, mlats, mdepths, slons, slats, sdepths) expected_closest_mlons = mlons.flat[expected_mpoint_indices] expected_closest_mlats = mlats.flat[expected_mpoint_indices] expected_closest_mdepths = mdepths.flat[expected_mpoint_indices] expected_distances = geodetic.distance(expected_closest_mlons, expected_closest_mlats, expected_closest_mdepths, slons, slats, sdepths) self.assertTrue((dists == expected_distances).all()) # testing min_geodetic_distance with the same lons and lats min_geod_distance = geodetic.min_geodetic_distance( mlons, mlats, slons, slats) min_geo_distance2 = geodetic.min_distance(mlons, mlats, mdepths * 0, slons, slats, sdepths * 0) numpy.testing.assert_almost_equal(min_geod_distance, min_geo_distance2)
def _test(self, mlons, mlats, mdepths, slons, slats, sdepths, expected_mpoint_indices): mlons, mlats, mdepths = [numpy.array(arr, float) for arr in (mlons, mlats, mdepths)] slons, slats, sdepths = [numpy.array(arr, float) for arr in (slons, slats, sdepths)] actual_indices = geodetic.min_distance(mlons, mlats, mdepths, slons, slats, sdepths, indices=True) numpy.testing.assert_equal(actual_indices, expected_mpoint_indices) dists = geodetic.min_distance(mlons, mlats, mdepths, slons, slats, sdepths) expected_closest_mlons = mlons.flat[expected_mpoint_indices] expected_closest_mlats = mlats.flat[expected_mpoint_indices] expected_closest_mdepths = mdepths.flat[expected_mpoint_indices] expected_distances = geodetic.distance( expected_closest_mlons, expected_closest_mlats, expected_closest_mdepths, slons, slats, sdepths ) self.assertTrue((dists == expected_distances).all()) # testing min_geodetic_distance with the same lons and lats min_geod_distance = geodetic.min_geodetic_distance(mlons, mlats, slons, slats) min_geo_distance2 = geodetic.min_distance(mlons, mlats, mdepths * 0, slons, slats, sdepths * 0) numpy.testing.assert_almost_equal(min_geod_distance, min_geo_distance2)
def get_min_distance(self, mesh): """ Compute and return the minimum distance from the mesh to each point in another mesh. :returns: numpy array of distances in km of the same shape as ``mesh``. Method doesn't make any assumptions on arrangement of the points in either mesh and instead calculates the distance from each point of this mesh to each point of the target mesh and returns the lowest found for each. Uses :func:`nhlib.geo.geodetic.min_distance`. """ if self.depths is None: depths1 = numpy.zeros_like(self.lons) else: depths1 = self.depths if mesh.depths is None: depths2 = numpy.zeros_like(mesh.lons) else: depths2 = mesh.depths return geodetic.min_distance(self.lons, self.lats, depths1, mesh.lons, mesh.lats, depths2)
def _test(self, mlons, mlats, mdepths, slons, slats, sdepths, expected_mpoint_indexes): mlons, mlats, mdepths = map(numpy.array, (mlons, mlats, mdepths)) dists = geodetic.min_distance(mlons, mlats, mdepths, slons, slats, sdepths) expected_closest_mlons = mlons[expected_mpoint_indexes] expected_closest_mlats = mlats[expected_mpoint_indexes] expected_closest_mdepths = mdepths[expected_mpoint_indexes] expected_distances = geodetic.distance( expected_closest_mlons, expected_closest_mlats, expected_closest_mdepths, slons, slats, sdepths ) self.assertTrue((dists == expected_distances).all())
def _geodetic_min_distance(self, mesh, indices): """ Wrapper around :func:`nhlib.geo.geodetic.min_distance` for two meshes: either (or both, or neither) can have empty depths. """ if self.depths is None: depths1 = numpy.zeros_like(self.lons) else: depths1 = self.depths if mesh.depths is None: depths2 = numpy.zeros_like(mesh.lons) else: depths2 = mesh.depths return geodetic.min_distance(self.lons, self.lats, depths1, mesh.lons, mesh.lats, depths2, indices)
def get_joyner_boore_distance(self, mesh): """ Compute and return Joyner-Boore distance to each point of ``mesh``. Point's depth is ignored. See :meth:`nhlib.geo.surface.BaseSurface.get_joyner_boore_distance` for definition of this distance. :returns: numpy array of distances in km of the same shape as ``mesh``. Distance value is considered to be zero if a point lies inside the polygon enveloping the projection of the mesh or on one of its edges. """ bounding_mesh = self._get_bounding_mesh(with_depths=False) assert bounding_mesh.depths is None lons, lats = bounding_mesh.lons, bounding_mesh.lats depths = numpy.zeros_like(lons) proj = geo_utils.get_orthographic_projection( *geo_utils.get_spherical_bounding_box(lons, lats) ) xx, yy = proj(lons, lats) mesh_2d = numpy.array([xx, yy], dtype=float).transpose().copy() if len(xx) == 2: mesh_2d = shapely.geometry.LineString(mesh_2d) elif len(xx) == 1: mesh_2d = shapely.geometry.Point(*mesh_2d) elif len(xx) > 2: mesh_2d = shapely.geometry.Polygon(mesh_2d) mesh_lons, mesh_lats = mesh.lons.flatten(), mesh.lats.flatten() mesh_xx, mesh_yy = proj(mesh_lons, mesh_lats) distances = [] for i in xrange(len(mesh_lons)): point_2d = shapely.geometry.Point(mesh_xx[i], mesh_yy[i]) dist = mesh_2d.distance(point_2d) if dist < 500: # if the distance is below threshold of 500 kilometers, # consider the distance measured on the projection accurate # enough (an error doesn't exceed half km). distances.append(dist) else: # ... otherwise get the precise distance between bounding mesh # projection and the point projection using pure numerical way distances.append(geodetic.min_distance( lons, lats, depths, mesh_lons[i], mesh_lats[i], 0 )) return numpy.array(distances).reshape(mesh.shape)