Coverage for pygeodesy/ltp.py : 98%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: utf-8 -*-
I{Local cartesian} and I{local tangent plane} classes L{LocalCartesian} and L{Ltp}, L{LocalError} and L{Attitude} and L{Frustum}.
@see: U{Local tangent plane coordinates<https://WikiPedia.org/wiki/Local_tangent_plane_coordinates>} and class L{LocalCartesian}, transcoded from I{Charles Karney}'s C++ classU{LocalCartesian <https://GeographicLib.SourceForge.io/html/classGeographicLib_1_1LocalCartesian.html>}. '''
# from pygeodesy.fmath import fdot # from .vector3d _M_, _name_, _0_, _0_0, _0_5, _2_0, _90_0, _180_0 _NamedBase, _XyzLocals4, _XyzLocals5, Xyz4Tuple # from pygeodesy.named import _NamedBase # from .ltpTuples # from pygeodesy.namedTuples import Vector3Tuple # from .vector3d wrap180, wrap360
# Half a field-of-view in degrees raise _ValueError(**fov)
'''The orientation of a plane or camera in space. '''
'''New L{Attitude}.
@kwarg alt_attitude: An altitude (C{meter}) above earth or an attitude (L{Attitude} or L{Attitude4Tuple}) with the C{B{alt}itude}, B{C{tilt}}, B{C{yaw}} and B{C{roll}}. @kwarg tilt: Pitch, elevation from horizontal (C{degrees180}), negative down (clockwise rotation along and around the x- or East axis). @kwarg yaw: Bearing, heading (compass C{degrees360}), clockwise from North (counter-clockwise rotation along and around the z- or Up axis). @kwarg roll: Roll, bank (C{degrees180}), positive to the right and down (clockwise rotation along and around the y- or North axis). @kwarg name: Optional name C{str}).
@raise AttitudeError: Invalid B{C{alt_attitude}}, B{C{tilt}}, B{C{yaw}} or B{C{roll}}.
@see: U{Principal axes<https://WikiPedia.org/wiki/Aircraft_principal_axes>} and U{Yaw, pitch, and roll rotations<http://Planning.CS.UIUC.edu/node102.html>}. ''' else: except AttributeError: raise AttitudeError(alt=alt_attitude, tilt=tilt, yaw=yaw, rol=roll)
def alt(self, alt): # PYCHOK no cover a = Meter(alt=alt, Error=AttitudeError) self._update(a != self.alt) self._alt = a
'''Return this attitude's alt[itude], tilt, yaw and roll as an L{Attitude4Tuple}. '''
'''Get the 3x3 rotation matrix C{R(yaw)·R(tilt)·R(roll)}, aka I{ZYX} (C{float}, row-order).
@see: The matrix M of case 10 in U{Appendix A <https://ntrs.NASA.gov/api/citations/19770019231/downloads/19770019231.pdf>}. '''
# to follow the definitions of rotation angles alpha, beta and gamma: # negate yaw since yaw is counter-clockwise around the z-axis, swap # tilt and roll since tilt is around the x- and roll around the y-axis (sa * cb, sa * sb * sg, ca * cg, sa * sb * cg, -ca * sg), ( -sb, cb * sg, cb * cg))
'''Transform a (local) cartesian by this attitude's matrix.
@arg x_xyz: X component of vector (C{scalar}) or (3-D) vector (C{Cartesian}, L{Vector3d} or L{Vector3Tuple}). @kwarg y: Y component of vector (C{scalar}), same units as B{C{x}}. @kwarg z: Z component of vector (C{scalar}), same units as B{C{x}}. @kwarg Vector: Class to return transformed point (C{Cartesian}, L{Vector3d} or C{Vector3Tuple}) or C{None}. @kwarg Vector_kwds: Optional, additional B{C{Vector}} keyword arguments, ignored if C{B{Vector} is None}.
@return: A B{C{Vector}} instance or a L{Vector3Tuple}C{(x, y, z)} if C{B{Vector}=None}.
@see: U{Yaw, pitch, and roll rotations<http://Planning.CS.UIUC.edu/node102.html>}. ''' except AttributeError: x, y, z = map1(float, x_xyz, y, z)
Vector(X, Y, Z, **_xkwds(Vector_kwds, name=self.name))
'''Format this attitude as string.
@kwarg prec: The C{float} precision, number of decimal digits (0..9). Trailing zero decimals are stripped for B{C{prec}} values of 1 and above, but kept for negative B{C{prec}} values. @kwarg sep: Separator to join (C{str}).
@return: This attitude (C{str}). '''
'''Get this attitude's (3-D) directional vector (L{Vector3d}).
@see: U{Yaw, pitch, and roll rotations<http://Planning.CS.UIUC.edu/node102.html>}. '''
'''An L{Attitude} or L{Attitude4Tuple} issue. '''
'''A rectangular pyramid, typically representing a camera's I{field-of-view} (fov) and the intersection with (or projection to) a I{local tangent plane}.
@see: U{Viewing frustum<https://WikiPedia.org/wiki/Viewing_frustum>}. '''
'''New L{Frustum}.
@arg hfov: Horizontal field-of-view (C{degrees180}). @arg vfov: Vertical field-of-view (C{degrees180}). @kwarg ltp: Optional I{local tangent plane} (L{Ltp}).
@raise UnitError: Invalid B{C{hfov}} or B{C{vfov}}.
@raise ValueError: Invalid B{C{hfov}} or B{C{vfov}}. '''
self._ltp = _xLtp(ltp)
'''Compute the center and corners of the intersection with (or projection to) the I{local tangent plane} (LTP).
@arg alt_attitude: An altitude (C{meter}) above I{local tangent plane} or an attitude (L{Attitude} or L{Attitude4Tuple}) with the C{B{alt}itude}, B{C{tilt}}, B{C{yaw}} and B{C{roll}}. @kwarg tilt: Pitch, elevation from horizontal (C{degrees}), negative down (clockwise rotation along and around the x- or East axis). @kwarg yaw: Bearing, heading (compass C{degrees}), clockwise from North (counter-clockwise rotation along and around the z- or Up axis). @kwarg roll: Roll, bank (C{degrees}), positive to the right and down (clockwise rotation along and around the y- or North axis). @kwarg z: Optional height of the footprint (C{meter}) above I{local tangent plane}. @kwarg ltp: The I{local tangent plane} (L{Ltp}), overriding this frustum's C{ltp}.
@return: A L{Footprint5Tuple}C{(center, upperleft, upperight, loweright, lowerleft)} with the C{center} and 4 corners each an L{Xyz4Tuple}.
@raise TypeError: Invalid B{C{ltp}}.
@raise UnitError: Invalid B{C{altitude}}, B{C{tilt}}, B{C{roll}} or B{C{z}}.
@raise ValueError: If B{C{altitude}} too low, B{C{z}} too high or B{C{tilt}} or B{C{roll}} -including B{C{vfov}} respectively B{C{hfov}}- over the horizon.
@see: U{Principal axes<https://WikiPedia.org/wiki/Aircraft_principal_axes>}. ''' # left and right corners, or swapped else: # roll
# rotate (x, y)'s by bearing, clockwise fsum1_(y * c, -x * s), z, ltp)
except AttributeError: a, t, y, r = alt_attitude, tilt, yaw, roll
raise _ValueError(altitude=a) if z: # PYCHOK no cover z = Meter(z=z) a -= z if a < EPS: # z above a raise _ValueError(altitude_z=a) else:
raise _ValueError(tilt=t)
# center and corners, clockwise from upperleft, rolled + _xy2(a, e + self._v_2, -self._h_2, -self._tan_h_2, r) # swapped # turn center and corners by yaw, clockwise
'''Get the horizontal C{fov} (C{degrees}). '''
'''Get the I{local tangent plane} (L{Ltp}) or C{None}. '''
'''Convert this frustum to a "hfov, vfov, ltp" string.
@kwarg prec: Number of (decimal) digits, unstripped (0..8 or C{None}). @kwarg fmt: Optional, C{float} format (C{str}). @kwarg sep: Separator to join (C{str}).
@return: Frustum in the specified form (C{str}). ''' t += self.ltp,
'''Get the vertical C{fov} (C{degrees}). '''
'''A L{LocalCartesian} or L{Ltp} related issue. '''
'''Conversion between geodetic C{(lat, lon, height)} and I{local cartesian} C{(x, y, z)} coordinates with I{geodetic} origin C{(lat0, lon0, height0)}, transcoded from I{Karney}'s C++ class U{LocalCartesian <https://GeographicLib.SourceForge.io/html/classGeographicLib_1_1LocalCartesian.html>}.
The C{z} axis is normal to the ellipsoid, the C{y} axis points due North. The plane C{z = -height0} is tangent to the ellipsoid.
The conversions all take place via geocentric coordinates using a geocentric L{EcefKarney}, by default the WGS84 datum/ellipsoid.
@see: Class L{Ltp}. '''
'''New L{LocalCartesian} converter.
@kwarg latlonh0: Either a C{LatLon}, L{Ltp}, L{Ecef9Tuple} or C{scalar} latitude of the (goedetic) origin (C{degrees}). @kwarg lon0: Optional C{scalar} longitude of the (goedetic) origin C{scalar} B{C{latlonh0}} (C{degrees}). @kwarg height0: Optional origin height (C{meter}), vertically above (or below) the surface of the ellipsoid. @kwarg ecef: An ECEF converter (L{EcefKarney}). @kwarg name: Optional name (C{str}).
@raise LocalError: If B{C{latlonh0}} not C{LatLon}, L{Ecef9Tuple}, C{scalar} or invalid or if B{C{lon0}} not C{scalar} for C{scalar} B{C{latlonh0}} or invalid or if B{C{height0}} invalid.
@raise TypeError: Invalid B{C{ecef}}, not L{EcefKarney}.
@note: If BC{latlonh0} is L{Ltp}, only the lat-, longitude and height are duplicated, I{not} the ECEF converter. ''' else: if ecef: # PYCHOK no cover _xinstanceof(EcefKarney, ecef=ecef) self._ecef = ecef
'''Compare this and an other instance.
@arg other: The other ellipsoid (L{LocalCartesian} or L{Ltp}).
@return: C{True} if equal, C{False} otherwise. ''' return other is self or (isinstance(other, self.__class__) and self.ecef == other.ecef and self._t0 == other._t0)
'''Get the ECEF converter's datum (L{Datum}). '''
'''Get the ECEF converter (L{EcefKarney}). '''
'''(INTERNAL) Convert geocentric/geodetic to local, like I{forward}.
@arg ecef: Geocentric (and geodetic) (L{Ecef9Tuple}). @arg Xyz: An L{XyzLocal}, L{Enu} or L{Ned} I{class} or C{None}. @arg Xyz_kwds: B{C{Xyz}} keyword arguments, ignored if C{B{Xyz} is None}.
@return: An C{B{Xyz}(x, y, z, ltp, **B{Xyz_kwds}} instance or if C{B{Xyz} is None}, an L{Local9Tuple}C{(x, y, z, lat, lon, height, ltp, ecef, M)} with this C{ltp}, B{C{ecef}} (L{Ecef9Tuple}) converted to this C{datum} and C{M=None}, always. ''' ecef = ecef.toDatum(ltp.datum) ltp, ecef, None, name=ecef.name) raise _TypesError(_Xyz_, Xyz, *_XyzLocals4)
'''Convert I{geodetic} C{(lat, lon, height)} to I{local} cartesian C{(x, y, z)}.
@arg latlonh: Either a C{LatLon}, a L{Ltp}, an L{Ecef9Tuple} or C{scalar} (geodetic) latitude (C{degrees}). @kwarg lon: Optional C{scalar} (geodetic) longitude for C{scalar} B{C{latlonh}} (C{degrees}). @kwarg height: Optional height (C{meter}), vertically above (or below) the surface of the ellipsoid. @kwarg M: Optionally, return the rotation L{EcefMatrix} (C{bool}). @kwarg name: Optional name (C{str}).
@return: A L{Local9Tuple}C{(x, y, z, lat, lon, height, ltp, ecef, M)} with I{local} C{x}, C{y}, C{z}, I{geodetic} C{(lat}, C{lon}, C{height}, this C{ltp}, C{ecef} (L{Ecef9Tuple}) with I{geocentric} C{x}, C{y}, C{z} (and I{geodetic} C{lat}, C{lon}, C{height}) and the I{concatenated} rotation matrix C{M} (L{EcefMatrix}) if requested.
@raise LocalError: If B{C{latlonh}} not C{scalar}, C{LatLon}, L{Ltp}, L{Ecef9Tuple} or invalid or if B{C{lon}} not C{scalar} for C{scalar} B{C{latlonh}} or invalid or if B{C{height}} invalid. '''
'''Get origin's height (C{meter}). '''
'''Get origin's latitude (C{degrees}). '''
'''(INTERNAL) Convert I{local} to geocentric/geodetic, like I{.reverse}.
@arg local: Local (L{XyzLocal}, L{Enu}, L{Ned}, L{Aer} or L{Local9Tuple}). @kwarg nine: Return 3- or 9-tuple (C{bool}). @kwarg M: Include the rotation matrix (C{bool}).
@return: A I{geocentric} 3-tuple C{(x, y, z)} or if C{B{nine}=True}, an L{Ecef9Tuple}C{(x, y, z, lat, lon, height, C, M, datum)}, optionally including rotation matrix C{M} or C{None}. '''
'''Get origin's longitude (C{degrees}). '''
'''Get the rotation matrix (C{EcefMatrix}). '''
'''Reset the (geodetic) origin.
@kwarg latlonh0: Either a C{LatLon}, an L{Ecef9Tuple} or C{scalar} latitude of the origin (C{degrees}). @kwarg lon0: Optional C{scalar} longitude of the origin for C{scalar} B{C{latlonh0}} (C{degrees}). @kwarg height0: Optional origin height (C{meter}), vertically above (or below) the surface of the ellipsoid. @kwarg name: Optional, new name (C{str}).
@raise LocalError: If B{C{latlonh0}} not C{LatLon}, L{Ecef9Tuple}, C{scalar} or invalid or if B{C{lon0}} not C{scalar} for C{scalar} B{C{latlonh0}} or invalid or if B{C{height0}} invalid. '''
suffix=_0_, Error=LocalError, name=name) else: n = self.name
'''Convert I{local} C{(x, y, z)} to I{geodetic} C{(lat, lon, height)}.
@arg xyz: A I{local} (L{XyzLocal}, L{Enu}, L{Ned}, L{Aer}, L{Local9Tuple}) or local C{x} coordinate (C{scalar}). @kwarg y: Local C{y} coordinate for C{scalar} B{C{xyz}} and B{C{z}} (C{meter}). @kwarg z: Local C{z} coordinate for C{scalar} B{C{xyz}} and B{C{y}} (C{meter}). @kwarg M: Optionally, return the I{concatenated} rotation L{EcefMatrix}, I{iff avaialble} (C{bool}). @kwarg name: Optional name (C{str}).
@return: An L{Local9Tuple}C{(x, y, z, lat, lon, height, ltp, ecef, M)} with I{local} C{x}, C{y}, C{z}, I{geodetic} C{lat}, C{lon}, C{height}, this C{ltp}, an C{ecef} (L{Ecef9Tuple}) with the I{geocentric} C{x}, C{y}, C{z} (and I{geodetic} C{lat}, C{lon}, C{height}) and the I{concatenated} rotation matrix C{M} (L{EcefMatrix}) if requested.
@raise LocalError: Invalid B{C{xyz}} or C{scalar} C{x} or B{C{y}} and/or B{C{z}} not C{scalar} for C{scalar} B{C{xyz}}. '''
'''Return this L{LocalCartesian} as a string.
@kwarg prec: Precision, number of (decimal) digits (0..9).
@return: This L{LocalCartesian} representation (C{str}). '''
'''(INTERNAL) Get C{(x0, y0, z0)} as L{Vector3Tuple}. '''
'''A I{local tangent plan} LTP, a sub-class of C{LocalCartesian} with configurable ECEF converter and without optional rotation matrix. ''' '''New C{Ltp}.
@kwarg latlonh0: Either a C{LatLon}, L{Ltp}, L{Ecef9Tuple} or C{scalar} latitude of the (goedetic) origin (C{degrees}). @kwarg lon0: Optional C{scalar} longitude of the (goedetic) origin for C{scalar} B{C{latlonh0}} (C{degrees}). @kwarg height0: Optional origin height (C{meter}), vertically above (or below) the surface of the ellipsoid. @kwarg ecef: Optional ECEF converter (L{EcefKarney}, l{EcefFarrell21}, L{EcefFarrell22}, L{EcefSudano}, L{EcefVeness} or L{EcefYou} I{instance}), overriding default L{EcefKarney}C{(datum=Datums.WGS84)}. @kwarg name: Optional name (C{str}).
@return: New instance (C{Ltp}).
@raise LocalError: If B{C{latlonh0}} not C{LatLon}, L{Ecef9Tuple}, C{scalar} or invalid or if B{C{lon0}} not C{scalar} for C{scalar} B{C{latlonh0}} or invalid or if B{C{height0}} invalid.
@raise TypeError: Invalid B{C{ecef}}. '''
'''Get this LTP's ECEF converter (C{Ecef...} I{instance}). '''
'''Set this LTP's ECEF converter.
@arg ecef: New ECEF converter (C{Ecef...} I{instance}).
@raise TypeError: Invalid B{C{ecef}}. ''' if ecef != self._ecef: # PYCHOK no cover self._ecef = ecef self.reset(self._t0)
'''Convert an attitude oriention into a (3-D) direction vector.
@kwarg tilt: Pitch, elevation from horizontal (C{degrees}), negative down (clockwise rotation along and around the x-axis). @kwarg yaw: Bearing, heading (compass C{degrees360}), clockwise from North (counter-clockwise rotation along and around the z-axis). @kwarg roll: Roll, bank (C{degrees}), positive to the right and down (clockwise rotation along and around the y-axis).
@return: A named B{C{Vector}} instance or if B{C{Vector}} is C{None}, a named L{Vector3Tuple}C{(x, y, z)}.
@see: U{Yaw, pitch, and roll rotations<http://Planning.CS.UIUC.edu/node102.html>} and function L{pygeodesy.hartzell} argument C{los}. ''' Vector3Tuple(d.x, d.y, d.z, name=d.name) if Vector is None else Vector(d.x, d.y, d.z, **_xkwds(Vector_kwds, name=d.name))) # PYCHOK indent
'''(INTERNAL) Validate B{C{ltp}}. ''' raise _TypesError(_ltp_, ltp, Ltp, LocalCartesian)
# **) MIT License # # Copyright (C) 2016-2022 -- mrJean1 at Gmail -- All Rights Reserved. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. |