Beispiel #1
0
def nearest_edge(elon, elat, poly):
    """
    Return the distance from a point to the nearest edge of a
    polygon.

    Args:
        elon (float): The longitude of the reference point.
        elat (float): The latitude of the reference point.
        poly (Polygon): An instance of a shapely Polygon.

    Returns:
        float: The distance (in km) from the reference point to the
        nearest edge (or vertex) of the polygon.
    """
    elon_arr = np.array([elon])
    elat_arr = np.array([elat])
    x, y = poly.exterior.xy
    nearest = 99999.
    for ix in range(1, len(x) - 1):
        dd = min_distance_to_segment(np.array(x[ix - 1:ix + 1]),
                                     np.array(y[ix - 1:ix + 1]), elon_arr,
                                     elat_arr)
        if np.abs(dd[0]) < nearest:
            nearest = dd[0]
    return nearest
 def test_three(self):
     # Positive distance halfspace - outside segment
     dist = geodetic.min_distance_to_segment(self.slons,
                                             self.slats,
                                             lons=numpy.array([3.0]),
                                             lats=numpy.array([0.0]))
     self.assertAlmostEqual(dist, 186.394507344)
Beispiel #3
0
 def test_four(self):
     # Negative distance halfspace - outside segment
     dist = float(geodetic.min_distance_to_segment(
         self.slons, self.slats,
         lons=numpy.array([-2.0]),
         lats=numpy.array([0.5])))
     self.assertAlmostEqual(dist, -125.802091893)
 def test_two(self):
     # Negative distance halfspace - within segment
     dist = geodetic.min_distance_to_segment(self.slons,
                                             self.slats,
                                             lons=numpy.array([0.0]),
                                             lats=numpy.array([2.0]))
     self.assertAlmostEqual(dist, -205.18959626)
 def test_one(self):
     # Positive distance halfspace - within segment
     dist = geodetic.min_distance_to_segment(self.slons,
                                             self.slats,
                                             lons=numpy.array([0.0]),
                                             lats=numpy.array([-2.0]))
     self.assertAlmostEqual(dist, 219.90986712)
Beispiel #6
0
def nearest_edge(elon, elat, poly):
    """
    Return the distance from a point to the nearest edge of a
    polygon.

    Args:
        elon (float): The longitude of the reference point.
        elat (float): The latitude of the reference point.
        poly (Polygon): An instance of a shapely Polygon.

    Returns:
        float: The distance (in km) from the reference point to the
        nearest edge (or vertex) of the polygon.
    """
    elon_arr = np.array([elon])
    elat_arr = np.array([elat])
    x, y = poly.exterior.xy
    nearest = 99999.
    for ix in range(1, len(x) - 1):
        dd = min_distance_to_segment(np.array(x[ix - 1:ix + 1]),
                                     np.array(y[ix - 1:ix + 1]),
                                     elon_arr, elat_arr)
        if np.abs(dd[0]) < nearest:
            nearest = dd[0]
    return nearest
Beispiel #7
0
def get_min_distance(line, pnts):
    """
    Get distances between a line and a set of points

    :parameter line:
        An instance of :class:`openquake.hazardlib.geo.line.Line`
    :parameter pnts:
        A nx2 array
    """
    #
    #
    assert isinstance(pnts, numpy.ndarray)
    coo = numpy.array([(pnt.longitude, pnt.latitude) for pnt in line.points])
    #
    # this handles the case of a multiine
    if len(coo[:, 0]) > 2:
        cx = numpy.stack((coo[:-1, 0], coo[1:, 0]))
    else:
        cx = [coo[:, 0]]
    if len(coo[:, 0]) > 2:
        cy = list(numpy.stack((coo[:-1, 1], coo[1:, 1])))
    else:
        cy = [
         coo[:, 1]]
    #
    # calculate distances
    distances = numpy.zeros_like(pnts[:, 0])
    distances[:] = 1e+100
    for segx, segy in zip(cx, cy):
        sdx = segx[1] - segx[0]
        sdy = segy[1] - segy[0]
        pdx = segx[0] - pnts[:, 0]
        pdy = segy[0] - pnts[:, 1]
        dot1 = sdx * pdx + sdy * pdy
        pdx = segx[1] - pnts[:, 0]
        pdy = segy[1] - pnts[:, 1]
        dot2 = sdx * pdx + sdy * pdy
        idx = numpy.nonzero((numpy.sign(dot1) < 0) & (numpy.sign(dot2) > 0))
        dst = min_distance_to_segment(segx, segy, pnts[idx[0], 0],
                                      pnts[idx[0], 1])
        distances[idx[0]] = dst
    return distances
Beispiel #8
0
    def get_rx_distance(self, mesh):
        """
        Compute distance between each point of mesh and surface's great circle
        arc.

        Distance is measured perpendicular to the rupture strike, from
        the surface projection of the updip edge of the rupture, with
        the down dip direction being positive (this distance is usually
        called ``Rx``).

        In other words, is the horizontal distance to top edge of rupture
        measured perpendicular to the strike. Values on the hanging wall
        are positive, values on the footwall are negative.

        :param mesh:
            :class:`~openquake.hazardlib.geo.mesh.Mesh` of points to calculate
            Rx-distance to.
        :returns:
            Numpy array of distances in km.
        """
        top_edge = self.mesh[0:1]
        dists = []

        ia = 0
        ib = top_edge.lons.shape[1] - 2
        if (self.__class__.__name__ == 'KiteSurface'):
            idxs = numpy.nonzero(numpy.isfinite(top_edge.lons[0, :]))[0]
            ia = min(idxs)
            ib = sorted(idxs)[-2]

        if top_edge.lons.shape[1] < 3:
            i = 0

            if ((self.__class__.__name__ == 'KiteSurface')
                    and (numpy.isnan(top_edge.lons[0, i])
                         or numpy.isnan(top_edge.lons[0, i + 1]))):
                msg = 'Rx calculation. Top of rupture has less than two points'
                raise ValueError(msg)

            p1 = Point(top_edge.lons[0, i], top_edge.lats[0, i],
                       top_edge.depths[0, i])
            p2 = Point(top_edge.lons[0, i + 1], top_edge.lats[0, i + 1],
                       top_edge.depths[0, i + 1])
            azimuth = p1.azimuth(p2)
            dists.append(
                geodetic.distance_to_arc(p1.longitude, p1.latitude, azimuth,
                                         mesh.lons, mesh.lats))

        else:

            for i in range(top_edge.lons.shape[1] - 1):

                if ((self.__class__.__name__ == 'KiteSurface')
                        and (numpy.isnan(top_edge.lons[0, i])
                             or numpy.isnan(top_edge.lons[0, i + 1]))):
                    continue

                p1 = Point(top_edge.lons[0, i], top_edge.lats[0, i],
                           top_edge.depths[0, i])
                p2 = Point(top_edge.lons[0, i + 1], top_edge.lats[0, i + 1],
                           top_edge.depths[0, i + 1])

                # Swapping
                if i == 0:
                    pt = p1
                    p1 = p2
                    p2 = pt

                # Computing azimuth and distance
                if i == ia or i == ib:
                    azimuth = p1.azimuth(p2)
                    tmp = geodetic.distance_to_semi_arc(
                        p1.longitude, p1.latitude, azimuth, mesh.lons,
                        mesh.lats)
                else:
                    tmp = geodetic.min_distance_to_segment(
                        numpy.array([p1.longitude, p2.longitude]),
                        numpy.array([p1.latitude, p2.latitude]), mesh.lons,
                        mesh.lats)
                # Correcting the sign of the distance
                if i == 0:
                    tmp *= -1
                dists.append(tmp)

        # Computing distances
        dists = numpy.array(dists)
        iii = abs(dists).argmin(axis=0)
        dst = dists[iii, list(range(dists.shape[1]))]

        if numpy.any(numpy.isnan(dst)):
            raise ValueError('NaN in Rx')

        return dst
Beispiel #9
0
    def get_rx_distance(self, mesh):
        """
        Compute distance between each point of mesh and surface's great circle
        arc.

        Distance is measured perpendicular to the rupture strike, from
        the surface projection of the updip edge of the rupture, with
        the down dip direction being positive (this distance is usually
        called ``Rx``).

        In other words, is the horizontal distance to top edge of rupture
        measured perpendicular to the strike. Values on the hanging wall
        are positive, values on the footwall are negative.

        :param mesh:
            :class:`~openquake.hazardlib.geo.mesh.Mesh` of points to calculate
            Rx-distance to.
        :returns:
            Numpy array of distances in km.
        """
        top_edge = self.mesh[0:1]

        dists = []
        if top_edge.lons.shape[1] < 3:

            i = 0
            p1 = Point(top_edge.lons[0, i], top_edge.lats[0, i],
                       top_edge.depths[0, i])
            p2 = Point(top_edge.lons[0, i + 1], top_edge.lats[0, i + 1],
                       top_edge.depths[0, i + 1])
            azimuth = p1.azimuth(p2)
            dists.append(
                geodetic.distance_to_arc(p1.longitude, p1.latitude, azimuth,
                                         mesh.lons, mesh.lats))

        else:

            for i in range(top_edge.lons.shape[1] - 1):
                p1 = Point(top_edge.lons[0, i], top_edge.lats[0, i],
                           top_edge.depths[0, i])
                p2 = Point(top_edge.lons[0, i + 1], top_edge.lats[0, i + 1],
                           top_edge.depths[0, i + 1])
                # Swapping
                if i == 0:
                    pt = p1
                    p1 = p2
                    p2 = pt

                # Computing azimuth and distance
                if i == 0 or i == top_edge.lons.shape[1] - 2:
                    azimuth = p1.azimuth(p2)
                    tmp = geodetic.distance_to_semi_arc(
                        p1.longitude, p1.latitude, azimuth, mesh.lons,
                        mesh.lats)
                else:
                    tmp = geodetic.min_distance_to_segment(
                        numpy.array([p1.longitude, p2.longitude]),
                        numpy.array([p1.latitude, p2.latitude]), mesh.lons,
                        mesh.lats)
                # Correcting the sign of the distance
                if i == 0:
                    tmp *= -1
                dists.append(tmp)

        # Computing distances
        dists = numpy.array(dists)
        iii = abs(dists).argmin(axis=0)
        dst = dists[iii, list(range(dists.shape[1]))]

        return dst
 def test_three(self):
     # Positive distance halfspace - outside segment
     dist = float(geodetic.min_distance_to_segment(
         self.slons, self.slats, lons=numpy.array([3.0]),
         lats=numpy.array([0.0])))
     self.assertAlmostEqual(dist, 186.394507344)
 def test_two(self):
     # Negative distance halfspace - within segment
     dist = float(geodetic.min_distance_to_segment(
         self.slons, self.slats, lons=numpy.array([0.0]),
         lats=numpy.array([2.0])))
     self.assertAlmostEqual(dist, -205.18959626)
 def test_one(self):
     # Positive distance halfspace - within segment
     dist = float(geodetic.min_distance_to_segment(
         self.slons, self.slats, lons=numpy.array([0.0]),
         lats=numpy.array([-2.0])))
     self.assertAlmostEqual(dist, 219.90986712)
Beispiel #13
0
    def get_rx_distance(self, mesh):
        """
        See :meth:`superclass method
        <.base.BaseSurface.get_rx_distance>`
        for spec of input and result values.

        The method extracts the top edge of the surface. For each point in mesh
        it computes the Rx distance to each segment the top edge is made
        of. The calculation is done by calling the function
        :func:`openquake.hazardlib.geo.geodetic.distance_to_arc`. The final Rx
        distance matrix is then constructed by taking, for each point in mesh,
        the minimum Rx distance value computed.
        """
        top_edge = self.get_mesh()[0:1]

        dists = []
        if top_edge.lons.shape[1] < 3:

            i = 0
            p1 = Point(
                top_edge.lons[0, i],
                top_edge.lats[0, i],
                top_edge.depths[0, i]
            )
            p2 = Point(
                top_edge.lons[0, i + 1], top_edge.lats[0, i + 1],
                top_edge.depths[0, i + 1]
            )
            azimuth = p1.azimuth(p2)
            dists.append(
                geodetic.distance_to_arc(
                    p1.longitude, p1.latitude, azimuth,
                    mesh.lons, mesh.lats
                )
            )

        else:

            for i in range(top_edge.lons.shape[1] - 1):
                p1 = Point(
                    top_edge.lons[0, i],
                    top_edge.lats[0, i],
                    top_edge.depths[0, i]
                )
                p2 = Point(
                    top_edge.lons[0, i + 1],
                    top_edge.lats[0, i + 1],
                    top_edge.depths[0, i + 1]
                )
                # Swapping
                if i == 0:
                    pt = p1
                    p1 = p2
                    p2 = pt

                # Computing azimuth and distance
                if i == 0 or i == top_edge.lons.shape[1] - 2:
                    azimuth = p1.azimuth(p2)
                    tmp = geodetic.distance_to_semi_arc(p1.longitude,
                                                        p1.latitude,
                                                        azimuth,
                                                        mesh.lons, mesh.lats)
                else:
                    tmp = geodetic.min_distance_to_segment([p1.longitude,
                                                            p2.longitude],
                                                           [p1.latitude,
                                                            p2.latitude],
                                                           mesh.lons,
                                                           mesh.lats)
                # Correcting the sign of the distance
                if i == 0:
                    tmp *= -1
                dists.append(tmp)

        # Computing distances
        dists = numpy.array(dists)
        iii = abs(dists).argmin(axis=0)
        dst = dists[iii, list(range(dists.shape[1]))]

        return dst
Beispiel #14
0
    def get_rx_distance(self, mesh):
        """
        Compute distance between each point of mesh and surface's great circle
        arc.

        Distance is measured perpendicular to the rupture strike, from
        the surface projection of the updip edge of the rupture, with
        the down dip direction being positive (this distance is usually
        called ``Rx``).

        In other words, is the horizontal distance to top edge of rupture
        measured perpendicular to the strike. Values on the hanging wall
        are positive, values on the footwall are negative.

        :param mesh:
            :class:`~openquake.hazardlib.geo.mesh.Mesh` of points to calculate
            Rx-distance to.
        :returns:
            Numpy array of distances in km.
        """
        top_edge = self.mesh[0:1]

        dists = []
        if top_edge.lons.shape[1] < 3:

            i = 0
            p1 = Point(
                top_edge.lons[0, i],
                top_edge.lats[0, i],
                top_edge.depths[0, i]
            )
            p2 = Point(
                top_edge.lons[0, i + 1], top_edge.lats[0, i + 1],
                top_edge.depths[0, i + 1]
            )
            azimuth = p1.azimuth(p2)
            dists.append(
                geodetic.distance_to_arc(
                    p1.longitude, p1.latitude, azimuth,
                    mesh.lons, mesh.lats
                )
            )

        else:

            for i in range(top_edge.lons.shape[1] - 1):
                p1 = Point(
                    top_edge.lons[0, i],
                    top_edge.lats[0, i],
                    top_edge.depths[0, i]
                )
                p2 = Point(
                    top_edge.lons[0, i + 1],
                    top_edge.lats[0, i + 1],
                    top_edge.depths[0, i + 1]
                )
                # Swapping
                if i == 0:
                    pt = p1
                    p1 = p2
                    p2 = pt

                # Computing azimuth and distance
                if i == 0 or i == top_edge.lons.shape[1] - 2:
                    azimuth = p1.azimuth(p2)
                    tmp = geodetic.distance_to_semi_arc(p1.longitude,
                                                        p1.latitude,
                                                        azimuth,
                                                        mesh.lons, mesh.lats)
                else:
                    tmp = geodetic.min_distance_to_segment(
                        numpy.array([p1.longitude, p2.longitude]),
                        numpy.array([p1.latitude, p2.latitude]),
                        mesh.lons, mesh.lats)
                # Correcting the sign of the distance
                if i == 0:
                    tmp *= -1
                dists.append(tmp)

        # Computing distances
        dists = numpy.array(dists)
        iii = abs(dists).argmin(axis=0)
        dst = dists[iii, list(range(dists.shape[1]))]

        return dst