def test(self): lon, lat = geodetic.point_at(10.0, 20.0, 30.0, 50.0) self.assertAlmostEqual(lon, 10.239856504796101, places=6) self.assertAlmostEqual(lat, 20.38925590463351, places=6) lon, lat = geodetic.point_at(-13.5, 22.4, -140.0, 120.0) self.assertAlmostEqual(lon, -14.245910669126582, places=6) self.assertAlmostEqual(lat, 21.57159463157223, places=6)
def point_at(self, horizontal_distance, vertical_increment, azimuth): """ Compute the point with given horizontal, vertical distances and azimuth from this point. :param horizontal_distance: Horizontal distance, in km. :type horizontal_distance: float :param vertical_increment: Vertical increment, in km. When positive, the new point has a greater depth. When negative, the new point has a smaller depth. :type vertical_increment: float :type azimuth: Azimuth, in decimal degrees. :type azimuth: float :returns: The point at the given distances. :rtype: Instance of :class:`Point` """ lon, lat = geodetic.point_at(self.longitude, self.latitude, azimuth, horizontal_distance) return Point(lon, lat, self.depth + vertical_increment)
def translate(self, p1, p2): """ Translate the surface for a specific distance along a specific azimuth direction. Parameters are two points (instances of :class:`nhlib.geo.point.Point`) representing the direction and an azimuth for translation. The resulting surface corner points will be that far along that azimuth from respective corner points of this surface as ``p2`` is located with respect to ``p1``. :returns: A new :class:`PlanarSurface` object with the same mesh spacing, dip, strike, width, length and depth but with corners longitudes and latitudes translated. """ azimuth = geodetic.azimuth(p1.longitude, p1.latitude, p2.longitude, p2.latitude) distance = geodetic.geodetic_distance(p1.longitude, p1.latitude, p2.longitude, p2.latitude) # avoid calling PlanarSurface's constructor nsurf = object.__new__(PlanarSurface) # but do call BaseSurface's one BaseSurface.__init__(nsurf) nsurf.mesh_spacing = self.mesh_spacing nsurf.dip = self.dip nsurf.strike = self.strike nsurf.corner_lons, nsurf.corner_lats = geodetic.point_at( self.corner_lons, self.corner_lats, azimuth, distance ) nsurf.corner_depths = self.corner_depths.copy() nsurf._init_plane() nsurf.width = self.width nsurf.length = self.length return nsurf
def discretize(self, mesh_spacing): """ Get a mesh of uniformly spaced points inside the polygon area with distance of ``mesh_spacing`` km between. :returns: An instance of :class:`~nhlib.geo.mesh.Mesh` that holds the points data. Mesh is created with no depth information (all the points are on the Earth surface). """ self._init_polygon2d() west, east, north, south = self._bbox lons = [] lats = [] # we cover the bounding box (in spherical coordinates) from highest # to lowest latitude and from left to right by longitude. we step # by mesh spacing distance (linear measure). we check each point # if it is inside the polygon and yield the point object, if so. # this way we produce an uniformly-spaced mesh regardless of the # latitude. latitude = north while latitude > south: longitude = west while utils.get_longitudinal_extent(longitude, east) > 0: # we use Cartesian space just for checking if a point # is inside of the polygon. x, y = self._projection(longitude, latitude) if self._polygon2d.contains(shapely.geometry.Point(x, y)): lons.append(longitude) lats.append(latitude) # move by mesh spacing along parallel... longitude, _, = geodetic.point_at(longitude, latitude, 90, mesh_spacing) # ... and by the same distance along meridian in outer one _, latitude = geodetic.point_at(west, latitude, 180, mesh_spacing) lons = numpy.array(lons) lats = numpy.array(lats) return Mesh(lons, lats, depths=None)
def get_middle_point(lon1, lat1, lon2, lat2): """ Given two points return the point exactly in the middle lying on the same great circle arc. Parameters are point coordinates in degrees. :returns: Tuple of longitude and latitude of the point in the middle. """ if lon1 == lon2 and lat1 == lat2: return lon1, lat1 dist = geodetic.geodetic_distance(lon1, lat1, lon2, lat2) azimuth = geodetic.azimuth(lon1, lat1, lon2, lat2) return geodetic.point_at(lon1, lat1, azimuth, dist / 2.0)
def test_zero_distance(self): lon, lat = geodetic.point_at(1.3, -5.6, -35.0, 0) self.assertAlmostEqual(lon, 1.3) self.assertAlmostEqual(lat, -5.6)