コード例 #1
0
    def initialBearingTo(self, other, wrap=False, raiser=False):
        '''Compute the initial bearing (forward azimuth) from this
           to an other point.

           @param other: The other point (spherical L{LatLon}).
           @keyword wrap: Wrap and unroll longitudes (C{bool}).
           @keyword raiser: Optionally, raise L{CrossError} (C{bool}),
                            use I{raiser}=C{True} for behavior like
                            C{sphericalNvector.LatLon.initialBearingTo}.

           @return: Initial bearing (compass C{degrees360}).

           @raise CrossError: If this and the I{other} point coincide,
                              provided I{raiser} is C{True} and
                              L{crosserrors} is C{True}.

           @raise TypeError: The I{other} point is not L{LatLon}.

           @example:

           >>> p1 = LatLon(52.205, 0.119)
           >>> p2 = LatLon(48.857, 2.351)
           >>> b = p1.initialBearingTo(p2)  # 156.2

           @JSname: I{bearingTo}.
        '''
        self.others(other)

        a1, b1 = self.to2ab()
        a2, b2 = other.to2ab()

        # XXX behavior like sphericalNvector.LatLon.initialBearingTo
        if raiser and crosserrors() and max(abs(a2 - a1), abs(b2 - b1)) < EPS:
            raise CrossError('%s %s: %r' % ('coincident', 'points', other))

        return degrees(bearing_(a1, b1, a2, b2, final=False, wrap=wrap))
コード例 #2
0
def isconvex_(points, adjust=False, wrap=True):
    '''Determine whether a polygon is convex and clockwise.

       @param points: The polygon points (C{LatLon}[]).
       @keyword adjust: Adjust the wrapped, unrolled longitudinal delta
                        by the cosine of the mean latitude (C{bool}).
       @keyword wrap: Wrap lat-, wrap and unroll longitudes (C{bool}).

       @return: C{+1} if I{points} are convex clockwise, C{-1} for
                convex counter-clockwise I{points}, C{0} otherwise.

       @raise CrossError: Some I{points} are colinear.

       @raise TypeError: Some I{points} are not C{LatLon}.

       @raise ValueError: Insufficient number of I{points}.

       @example:

       >>> t = LatLon(45,1), LatLon(46,1), LatLon(46,2)
       >>> isconvex_(t)  # +1

       >>> f = LatLon(45,1), LatLon(46,2), LatLon(45,2), LatLon(46,1)
       >>> isconvex_(f)  # 0
    '''
    def _unroll_adjust(x1, y1, x2, y2, wrap):
        x21, x2 = unroll180(x1, x2, wrap=wrap)
        if adjust:
            x21 *= cos(radians(y1 + y2) * 0.5)
        return x21, x2

    pts = LatLon2psxy(points, closed=True, radius=None, wrap=wrap)
    c, n, s = crosserrors(), len(pts), 0

    x1, y1, _ = pts[n - 2]
    x2, y2, _ = pts[n - 1]
    x21, x2 = _unroll_adjust(x1, y1, x2, y2, False)

    for i in range(n):
        x3, y3, ll = pts[i]
        x32, x3 = _unroll_adjust(x2, y2, x3, y3, wrap if i <
                                 (n - 2) else False)

        # get the sign of the distance from point
        # x3, y3 to the line from x1, y1 to x2, y2
        # <http://WikiPedia.org/wiki/Distance_from_a_point_to_a_line>
        s3 = fdot((x3, y3, x1, y1), y2 - y1, -x21, -y2, x2)
        if s3 > 0:  # x3, y3 on the right
            if s < 0:  # non-convex
                return 0
            s = +1

        elif s3 < 0:  # x3, y3 on the left
            if s > 0:  # non-convex
                return 0
            s = -1

        elif c and fdot((x32, y1 - y2), y3 - y2, -x21) < 0:
            # colinear u-turn: x3, y3 not on the
            # opposite side of x2, y2 as x1, y1
            raise CrossError('%s %s: %r' % ('colinear', 'point', ll))

        x1, y1, x2, y2, x21 = x2, y2, x3, y3, x32

    return s  # all points on the same side