def nearestOn2(point, points, closed=False, radius=R_M, LatLon=LatLon, **options): '''Locate the point on a polygon closest to an other point. Distances are approximated by function L{equirectangular_}, subject to the supplied I{options}. @param point: The other, reference point (L{LatLon}). @param points: The polygon points (L{LatLon}[]). @keyword closed: Optionally, close the polygon (C{bool}). @keyword radius: Optional, mean earth radius (C{meter}). @keyword LatLon: Optional (sub-)class for the closest point (L{LatLon}) or C{None}. @keyword options: Optional keyword arguments for function L{equirectangular_}. @return: 2-Tuple (I{closest}, I{distance}) of the closest point on the polygon and the distance to that point. The I{closest} as I{LatLon} or a 2-tuple (lat, lon) if I{LatLon} is C{None}. The I{distance} is the L{equirectangular_} distance between the I{closest} and reference I{point} in C{meter}, same units as I{radius}. @raise LimitError: Lat- and/or longitudinal delta exceeds I{limit}, see function L{equirectangular_}. @raise TypeError: Some I{points} are not C{LatLon}. @raise ValueError: Insufficient number of I{points}. @see: Functions L{equirectangular_} and L{nearestOn3}. ''' a, b, d, _ = nearestOn4(point, points, closed=closed, **options) ll = (a, b) if LatLon is None else LatLon(a, b) return ll, degrees2m(d, radius=radius)
def nearestOn3(self, points, closed=False, radius=R_M, **options): '''Locate the point on a polygon closest to this point. Distances are approximated by function L{equirectangular_}, subject to the supplied I{options}. @param points: The polygon points (L{LatLon}[]). @keyword closed: Optionally, close the polygon (C{bool}). @keyword radius: Optional, mean earth radius (C{meter}). @keyword options: Optional keyword arguments for function L{equirectangular_}. @return: 3-Tuple (I{closest}, I{distance}, I{angle}) of the closest point (L{LatLon}) on the polygon, the distance and the compass angle to the I{closest} point. The I{distance} is the L{equirectangular_} distance between this and the I{closest} point in C{meter}, same units as I{radius}. The I{angle} from this to the I{closest} point is in compass C{degrees360}, like function L{compassAngle}. @raise LimitError: Lat- and/or longitudinal delta exceeds I{limit}, see function L{equirectangular_}. @raise TypeError: Some I{points} are not C{LatLon}. @raise ValueError: Insufficient number of I{points}. @see: Functions L{compassAngle}, L{equirectangular_} and L{nearestOn4}. ''' a, b, d, c = nearestOn4(self, points, closed=closed, **options) return self.classof(a, b), degrees2m(d, radius=radius), c
def nearestOn3(self, points, closed=False, radius=R_M, **options): '''Locate the point on a polygon closest to this point. Distances are approximated by function L{equirectangular_}, subject to the supplied B{C{options}}. @param points: The polygon points (L{LatLon}[]). @keyword closed: Optionally, close the polygon (C{bool}). @keyword radius: Optional, mean earth radius (C{meter}). @keyword options: Optional keyword arguments for function L{equirectangular_}. @return: A L{NearestOn3Tuple}C{(closest, distance, angle)} where C{distance} is the L{equirectangular_} distance between this and the C{closest} point in C{meter}, same units as B{C{radius}}. The C{angle} from this to the C{closest} point is in compass C{degrees360}, like function L{compassAngle}. @raise LimitError: Lat- and/or longitudinal delta exceeds B{C{limit}}, see function L{equirectangular_}. @raise TypeError: Some B{C{points}} are not C{LatLon}. @raise ValueError: Insufficient number of B{C{points}}. @see: Functions L{compassAngle}, L{equirectangular_} and L{nearestOn5}. ''' a, b, d, c, h = _nearestOn5(self, points, closed=closed, **options) return NearestOn3Tuple(self.classof(a, b, height=h), degrees2m(d, radius=radius), c)
def nearestOn2(point, points, closed=False, radius=R_M, LatLon=LatLon, **options): '''DEPRECATED, use function L{sphericalTrigonometry.nearestOn3}. @return: ... I{closest} as I{LatLon} or a 2-tuple (lat, lon) without the height if I{LatLon} is C{None} ... ''' a, b, d, _, h = _nearestOn5(point, points, closed=closed, **options) ll = (a, b) if LatLon is None else LatLon(a, b, height=h) return ll, degrees2m(d, radius=radius)
def perimeterOf(points, closed=False, adjust=True, radius=R_M, wrap=True): '''Approximate the perimeter of a path or polygon. @param points: The path or polygon points (C{LatLon}[]). @keyword closed: Optionally, close the path or polygon (C{bool}). @keyword adjust: Adjust the wrapped, unrolled longitudinal delta by the cosine of the mean latitude (C{bool}). @keyword radius: Optional, mean earth radius (C{meter}). @keyword wrap: Wrap lat-, wrap and unroll longitudes (C{bool}). @return: Approximate perimeter (C{meter}, same units as I{radius}). @raise TypeError: Some I{points} are not C{LatLon}. @raise ValueError: Insufficient number of I{points}. @note: This perimeter is based on the L{equirectangular_} distance approximation and is ill-suited for regions exceeding several hundred Km or Miles or with near-polar latitudes. @see: L{sphericalTrigonometry.perimeterOf} and L{ellipsoidalKarney.perimeterOf}. ''' pts = LatLon2psxy(points, closed=closed, radius=None, wrap=False) def _degs(n, pts, closed): # angular edge lengths in degrees i, m = _imdex2(closed, n) x1, y1, _ = pts[i] u = 0 # previous x2's unroll/wrap for i in range(m, n): x2, y2, _ = pts[i] w = wrap if (not closed or i < (n - 1)) else False # apply previous x2's unroll/wrap to new x1 _, dy, dx, u = equirectangular_(y1, x1 + u, y2, x2, adjust=adjust, limit=None, wrap=w) yield hypot(dx, dy) x1, y1 = x2, y2 d = fsum(_degs(len(pts), pts, closed)) return degrees2m(d, radius)
def nearestOn3(point, points, closed=False, radius=R_M, LatLon=LatLon, **options): '''Locate the point on a polygon closest to an other, reference point. Distances are approximated by function L{equirectangular_}, subject to the supplied B{C{options}}. @param point: The other, reference point (L{LatLon}). @param points: The polygon points (L{LatLon}[]). @keyword closed: Optionally, close the polygon (C{bool}). @keyword radius: Optional, mean earth radius (C{meter}). @keyword LatLon: Optional (sub-)class to return the closest point (L{LatLon}) or C{None}. @keyword options: Optional keyword arguments for function L{equirectangular_}. @return: A L{NearestOn3Tuple}C{(closest, distance, angle)}. The C{distance} is the L{equirectangular_} distance between the C{closest} and reference B{C{point}} in C{meter}, same units as B{C{radius}}. The C{angle} from the reference B{C{point}} to the C{closest} is in compass C{degrees360}, like function L{compassAngle}. The C{height} is the (interpolated) height at the C{closest} point. @raise LimitError: Lat- and/or longitudinal delta exceeds the B{C{limit}}, see function L{equirectangular_}. @raise TypeError: Some I{points} are not C{LatLon}. @raise ValueError: Insufficient number of B{C{points}}. @see: Functions L{equirectangular_} and L{nearestOn5}. ''' a, b, d, c, h = _nearestOn5(point, points, closed=closed, LatLon=None, **options) r = LatLon3Tuple(a, b, h) if LatLon is None else \ LatLon(a, b, height=h) r = NearestOn3Tuple(r, degrees2m(d, radius=radius), c) return _xnamed(r, nearestOn3.__name__)
def equirectangular(lat1, lon1, lat2, lon2, radius=R_M, **options): '''Compute the distance between two points using the U{Equirectangular Approximation / Projection <http://www.Movable-Type.co.UK/scripts/latlong.html>}. @param lat1: Start latitude (C{degrees}). @param lon1: Start longitude (C{degrees}). @param lat2: End latitude (C{degrees}). @param lon2: End longitude (C{degrees}). @keyword radius: Optional, mean earth radius (C{meter}). @keyword options: Optional keyword arguments for function L{equirectangular_}. @return: Distance (C{meter}, same units as I{radius}). @see: Function L{equirectangular_} for more details, the available I{options}, errors, restrictions and other, approximate or accurate distance functions. ''' _, dy, dx, _ = equirectangular_(lat1, lon1, lat2, lon2, **options) return degrees2m(hypot(dx, dy), radius=radius)
def nearestOn3(point, points, closed=False, radius=R_M, LatLon=LatLon, **options): '''Locate the point on a polygon closest to an other, reference point. Distances are approximated by function L{equirectangular_}, subject to the supplied I{options}. @param point: The other, reference point (L{LatLon}). @param points: The polygon points (L{LatLon}[]). @keyword closed: Optionally, close the polygon (C{bool}). @keyword radius: Optional, mean earth radius (C{meter}). @keyword LatLon: Optional (sub-)class to return the closest point (L{LatLon}) or C{None}. @keyword options: Optional keyword arguments for function L{equirectangular_}. @return: 3-Tuple (I{closest}, I{distance}, I{angle}) of the closest point (L{LatLon}) on the polygon, the distance and the compass angle to the I{closest} point. The I{closest} is an instance of I{LatLon} or a 3-tuple (lat, lon, I{height}) if I{LatLon} is C{None}. The I{distance} is the L{equirectangular_} distance between the I{closest} and reference I{point} in C{meter}, same units as I{radius}. The I{angle} from the reference I{point} to the I{closest} is in compass C{degrees360}, like function L{compassAngle}. The I{height} is the (interpolated) height at the I{closest} point. @raise LimitError: Lat- and/or longitudinal delta exceeds I{limit}, see function L{equirectangular_}. @raise TypeError: Some I{points} are not C{LatLon}. @raise ValueError: Insufficient number of I{points}. @see: Functions L{equirectangular_} and L{nearestOn5}. ''' a, b, d, c, h = _nearestOn5(point, points, closed=closed, **options) llh = (a, b, h) if LatLon is None else LatLon(a, b, height=h) return llh, degrees2m(d, radius=radius), c
def __init__(self, latlons, closed=False, radius=None, wrap=True): '''Handle C{LatLon} points as pseudo-xy coordinates. @note: The C{LatLon} latitude is considered the pseudo-y and longitude the pseudo-x coordinate. Similarly, 2-tuples (x, y) are (longitude, latitude). @param latlons: Points C{list}, C{sequence}, C{set}, C{tuple}, etc. (I{LatLon[]}). @keyword closed: Optionally, close the polygon (C{bool}). @keyword radius: Optional, mean earth radius (C{meter}). @keyword wrap: Wrap lat- and longitudes (C{bool}). @raise TypeError: Some I{latlons} are not C{LatLon}. @raise ValueError: Insufficient number of I{latlons}. ''' self._closed = closed self._len, self._array = points2(latlons, closed=closed) if radius: self._radius = radius self._deg2m = degrees2m(1.0, radius) self._wrap = wrap