Exemplo n.º 1
0
def meanOf(points, datum=Datums.WGS84, height=None, LatLon=LatLon):
    '''Compute the geographic mean of several points.

       @param points: Points to be averaged (L{LatLon}[]).
       @keyword datum: Optional datum to use (L{Datum}).
       @keyword height: Optional height at mean point, overriding
                        the mean height (C{meter}).
       @keyword LatLon: Optional (sub-)class to return the mean
                        point (L{LatLon}) or C{None}.

       @return: Geographic mean point and mean height (B{C{LatLon}})
                or a L{LatLon3Tuple}C{(lat, lon, height)} if
                B{C{LatLon}} is C{None}.

       @raise ValueError: Insufficient number of B{C{points}}.
    '''
    _, points = _Nvll.points2(points, closed=False)
    # geographic mean
    m = sumOf(p.toNvector() for p in points)
    a, b, h = m.to3llh()

    if height is not None:
        h = height
    r = LatLon3Tuple(a, b, h) if LatLon is None else \
              LatLon(a, b, height=h, datum=datum)
    return _xnamed(r, meanOf.__name__)
Exemplo n.º 2
0
def meanOf(points, datum=Datums.WGS84, height=None, LatLon=LatLon):
    '''Compute the geographic mean of several points.

       @param points: Points to be averaged (L{LatLon}s).
       @keyword datum: Optional datum to use (L{Datum}).
       @keyword height: Optional height at mean point, overriding
                        the mean height (C{meter}).
       @keyword LatLon: Optional (sub-)class to return the mean
                        point (L{LatLon}) or C{None}.

       @return: Geographic mean point and mean height (I{LatLon})
                or 3-tuple (C{degrees90}, C{degrees180}, height)
                if I{LatLon} is C{None}.

       @raise ValueError: Insufficient number of I{points}.
    '''
    _, points = _Nvll.points2(points, closed=False)
    # geographic mean
    m = sumOf(p.toNvector() for p in points)
    a, b, h = m.to3llh()

    if height is not None:
        h = height
    return (a, b, h) if LatLon is None else LatLon(
            a, b, height=h, datum=datum)
Exemplo n.º 3
0
def meanOf(points, datum=Datums.WGS84):
    '''Return the geographic mean of the supplied points.

       @param points: Array of points to be averaged (L{LatLon}[]).
       @keyword datum: Optional datum to use (L{Datum}).

       @return: Point at geographic mean and mean height (L{LatLon}).

       @raise ValueError: Too few points.
    '''
    _, points = _Nvll.points(points, closed=False)
    # geographic mean
    m = sumOf(p.toNvector() for p in points)
    a, b, h = m.to3llh()
    return LatLon(a, b, height=h, datum=datum)
Exemplo n.º 4
0
def meanOf(points, height=None):
    '''Computes the geographic mean of the supplied points.

       @param points: Array of points to be averaged (L{LatLon}[]).
       @keyword height: Height to use inlieu of mean height (meter).

       @return: Point at geographic mean and mean height (L{LatLon}).

       @raise ValueError: Too few points.
    '''
    _, points = _Nvll.points(points, closed=False)
    # geographic mean
    m = sumOf(p.toNvector() for p in points)
    a, b, h = m.to3llh()
    return LatLon(a, b, height=h if height is None else height)
Exemplo n.º 5
0
def meanOf(points, height=None, LatLon=LatLon):
    '''Compute the geographic mean of the supplied points.

       @param points: Array of points to be averaged (L{LatLon}[]).
       @keyword height: Optional height, overriding the mean height (C{meter}).
       @keyword LatLon: Optional (sub-)class for the mean point (L{LatLon}).

       @return: Point at geographic mean and mean height (L{LatLon}).

       @raise ValueError: Insufficient number of I{points}.
    '''
    n, points = _Nvll.points2(points, closed=False)
    # geographic mean
    m = sumOf(points[i].toNvector() for i in range(n))
    a, b, h = m.to3llh()

    return LatLon(a, b, height=h if height is None else height)
Exemplo n.º 6
0
def meanOf(points, datum=Datums.WGS84, height=None, LatLon=LatLon):
    '''Compute the geographic mean of the supplied points.

       @param points: Array of points to be averaged (L{LatLon}[]).
       @keyword datum: Optional datum to use (L{Datum}).
       @keyword height: Optional height, overriding the mean height (meter).
       @keyword LatLon: Optional LatLon class for the mean point (L{LatLon}).

       @return: Point at geographic mean and mean height (L{LatLon}).

       @raise ValueError: Insufficient number of I{points}.
    '''
    _, points = _Nvll.points(points, closed=False)
    # geographic mean
    m = sumOf(p.toNvector() for p in points)
    a, b, h = m.to3llh()

    if height is not None:
        h = height
    return LatLon(a, b, height=h, datum=datum)
Exemplo n.º 7
0
def intersection(start1, end1, start2, end2, height=None, LatLon=LatLon):
    '''Locate the intersection of two paths each defined by two
       points or by a start point and an initial bearing.

       @param start1: Start point of the first path (L{LatLon}).
       @param end1: End point of the first path (L{LatLon}) or
                    the initial bearing at the first start point
                    (compass C{degrees360}).
       @param start2: Start point of the second path (L{LatLon}).
       @param end2: End point of the second path (L{LatLon}) or
                    the initial bearing at the second start point
                    (compass C{degrees360}).
       @keyword height: Optional height at the intersection point,
                        overriding the mean height (C{meter}).
       @keyword LatLon: Optional (sub-)class to return the
                        intersection point (L{LatLon}).

       @return: The intersection point (B{C{LatLon}}) or 3-tuple
                (C{degrees90}, C{degrees180}, height) if B{C{LatLon}}
                is C{None} or C{None} if no unique intersection
                exists.

       @raise TypeError: If B{C{start*}} or B{C{end*}} is not L{LatLon}.

       @raise ValueError: Intersection is ambiguous or infinite or
                          the paths are parallel, coincident or null.

       @example:

       >>> p = LatLon(51.8853, 0.2545)
       >>> q = LatLon(49.0034, 2.5735)
       >>> i = intersection(p, 108.55, q, 32.44)  # 50.9076°N, 004.5086°E
    '''
    _Nvll.others(start1, name='start1')
    _Nvll.others(start2, name='start2')

    # If gc1 and gc2 are great circles through start and end points
    # (or defined by start point and bearing), then the candidate
    # intersections are simply gc1 × gc2 and gc2 × gc1.  Most of the
    # work is deciding the correct intersection point to select!  If
    # bearing is given, that determines the intersection, but if both
    # paths are defined by start/end points, take closer intersection.
    gc1, s1, e1 = _Nvll._gc3(start1, end1, 'end1')
    gc2, s2, e2 = _Nvll._gc3(start2, end2, 'end2')

    hs = start1.height, start2.height
    # there are two (antipodal) candidate intersection
    # points ... we have to choose the one to return
    i1 = gc1.cross(gc2, raiser='paths')
    # postpone computing i2 until needed
    # i2 = gc2.cross(gc1, raiser='paths')

    # selection of intersection point depends on how
    # paths are defined (by bearings or endpoints)
    if e1 and e2:  # endpoint+endpoint
        d = sumOf((s1, s2, e1, e2)).dot(i1)
        hs += end1.height, end2.height
    elif e1 and not e2:  # endpoint+bearing
        # gc2 x v2 . i1 +ve means v2 bearing points to i1
        d = gc2.cross(s2).dot(i1)
        hs += end1.height,
    elif e2 and not e1:  # bearing+endpoint
        # gc1 x v1 . i1 +ve means v1 bearing points to i1
        d = gc1.cross(s1).dot(i1)
        hs += end2.height,
    else:  # bearing+bearing
        # if gc x v . i1 is +ve, initial bearing is
        # towards i1, otherwise towards antipodal i2
        d1 = gc1.cross(s1).dot(i1)  # +ve means p1 bearing points to i1
        d2 = gc2.cross(s2).dot(i1)  # +ve means p2 bearing points to i1
        if d1 > 0 and d2 > 0:
            d = 1  # both point to i1
        elif d1 < 0 and d2 < 0:
            d = -1  # both point to i2
        else:  # d1, d2 opposite signs
            # intersection is at further-away intersection
            # point, take opposite intersection from mid-
            # point of v1 and v2 [is this always true?]
            d = -s1.plus(s2).dot(i1)

    h = fmean(hs) if height is None else height
    i = i1 if d > 0 else gc2.cross(gc1, raiser='paths')
    return i.toLatLon(height=h,
                      LatLon=LatLon)  # Nvector(i.x, i.y, i.z).toLatLon(...)
Exemplo n.º 8
0
def intersection(start1, end1, start2, end2):
    '''Locates the intersection of two paths each defined by
       two points or by a start point and an initial bearing.

       @param start1: Start point of the first path (L{LatLon}).
       @param end1: End point of first path (L{LatLon}) or the
                    initial bearing at the first start point
                    (compass degrees).
       @param start2: Start point of the second path (L{LatLon}).
       @param end2: End point of second path (L{LatLon}) or the
                    initial bearing at the second start point
                    (compass degrees).

       @return: Intersection point (L{LatLon}) or None if no
                unique intersection exists.

       @raise TypeError: Start or end point is not L{LatLon}.

       @example:

       >>> p = LatLon(51.8853, 0.2545)
       >>> q = LatLon(49.0034, 2.5735)
       >>> i = intersection(p, 108.55, q, 32.44)  # 50.9076°N, 004.5086°E
    '''
    _Nvll.others(start1, name='start1')
    _Nvll.others(start2, name='start2')

    # If gc1 and gc2 are great circles through start and end points
    # (or defined by start point and bearing), then the candidate
    # intersections are simply gc1 × gc2 and gc2 × gc1.  Most of the
    # work is deciding the correct intersection point to select!  If
    # bearing is given, that determines the intersection, but if both
    # paths are defined by start/end points, take closer intersection.
    gc1, s1, e1 = _Nvll._gc3(start1, end1, 'end1')
    gc2, s2, e2 = _Nvll._gc3(start2, end2, 'end2')

    # there are two (antipodal) candidate intersection
    # points ... we have to choose the one to return
    i1 = gc1.cross(gc2)
    i2 = gc2.cross(gc1)

    # selection of intersection point depends on how
    # paths are defined (by bearings or endpoints)
    if e1 and e2:  # endpoint+endpoint
        d = sumOf((s1, s2, e1, e2)).dot(i1)
    elif e1 and not e2:  # endpoint+bearing
        # gc2 x v2 . i1 +ve means v2 bearing points to i1
        d = gc2.cross(s2).dot(i1)
    elif e2 and not e1:  # bearing+endpoint
        # gc1 x v1 . i1 +ve means v1 bearing points to i1
        d = gc1.cross(s1).dot(i1)
    else:  # bearing+bearing
        # if gc x v . i1 is +ve, initial bearing is
        # towards i1, otherwise towards antipodal i2
        d1 = gc1.cross(s1).dot(i1)  # +ve means p1 bearing points to i1
        d2 = gc2.cross(s2).dot(i1)  # +ve means p2 bearing points to i1
        if d1 > 0 and d2 > 0:
            d = 1  # both point to i1
        elif d1 < 0 and d2 < 0:
            d = -1  # both point to i2
        else:  # d1, d2 opposite signs
            # intersection is at further-away intersection
            # point, take opposite intersection from mid-
            # point of v1 and v2 [is this always true?]
            d = -s1.plus(s2).dot(i1)

    i = i1 if d > 0 else i2
    return Nvector(i.x, i.y, i.z).toLatLon()