Coverage for pygeodesy/resections.py : 94%

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 -*-
survey functions L{snellius3} and L{wildberger3} and triangle functions L{triAngle}, L{triAngle4}, L{triSide}, L{triSide2} and L{triSide4}.
@note: Function L{pierlot} transcoded with permission from U{triangulationPierlot <http://www.Telecom.ULg.ac.BE/triangulation/doc/total_8c.html>} and U{Pierlot <http://www.Telecom.ULg.ac.BE/publi/publications/pierlot/Pierlot2014ANewThree>}. '''
hypot, hypot2_ _b_, _B_, _c_, _C_, _coincident_, _colinear_, _d_, \ _invalid_, _negative_, _not_, _rIn_, _SPACE_, \ _0_0, _0_5, _1_0, _N_1_0, _2_0, _N_2_0, _4_0, _360_0 # from pygeodesy.streprs import Fmt # from .named
'''5-Tuple C{(pointP, pointH, a, b, c)} with survey C{pointP}, auxiliary C{pointH}, each an instance of B{C{pointA}}'s (sub-)class and triangle sides C{a}, C{b} and C{c} in C{meter}, conventionally. '''
'''3-Tuple C{(PA, PB, PC)} with distance from survey point C{P} to each of the triangle corners C{A}, C{B} and C{C}. '''
'''7-Tuple C{(pointP, A, B, C, a, b, c)} with survey C{pointP}, interior triangle angles C{A}, C{B} and C{C} in C{degrees} and triangle sides C{a}, C{b} and C{c} in C{meter}, conventionally. '''
'''4-Tuple C{(radA, radB, radC, rIn)} with the interior angles at triangle corner C{A}, C{B} and C{C} and the C{InCircle} radius C{rIn} aka C{inradius}. '''
'''2-Tuple C{(a, radA)} with triangle side C{a} (C{meter} conventionally) and the opposite triangle angle C{radA} (C{radians}). '''
'''4-Tuple C{(a, b, radC, d)} with the length of triangle sides C{a} and C{b}, the interior angle C{radC} at triangle corner C{radC} (C{radians}) and triangle height C{d}, perpendicular to triangle side C{c}. '''
'''3-Point resection using U{Cassini<https://NL.WikiPedia.org/wiki/Achterwaartse_insnijding>}'s method.
@arg pointA: First point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple}, C{Vector4Tuple} or C{Vector2Tuple} if C{B{useZ}=False}). @arg pointB: Second point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple}, C{Vector4Tuple} or C{Vector2Tuple} if C{B{useZ}=False}). @arg pointC: Center point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple}, C{Vector4Tuple} or C{Vector2Tuple} if C{B{useZ}=False}). @arg alpha: Angle subtended by triangle side B{C{pointA}} to B{C{pointC}} (C{degrees}, non-negative). @arg beta: Angle subtended by triangle side B{C{pointB}} to B{C{pointC}} (C{degrees}, non-negative). @kwarg useZ: If C{True}, use and interpolate the Z component, otherwise force C{z=0} (C{bool}). @kwarg Clas: Optional class to return the survey and auxiliary point or C{None} for B{C{pointA}}'s (sub-)class. @kwarg Clas_kwds: Optional additional keyword argument for the survey and auxiliary point instance.
@note: Typically, B{C{pointC}} is between B{C{pointA}} and B{C{pointB}}.
@return: The survey point, an instance of B{C{Clas}} or if C{B{Clas} is None} of B{C{pointA}}'s (sub-)class.
@raise ResectionError: Near-coincident, -colinear or -concyclic points or negative or invalid B{C{alpha}} or B{C{beta}}.
@raise TypeError: Invalid B{C{pointA}}, B{C{pointB}} or B{C{pointM}}.
@see: U{Three Point Resection Problem<https://Dokumen.tips/documents/ three-point-resection-problem-introduction-kaestner-burkhardt-method.html>} and functions L{pygeodesy.collins}, L{pygeodesy.pierlot} and L{pygeodesy.tienstra}. '''
raise ValueError(_or(_coincident_, _colinear_))
raise ValueError(_negative_) raise ValueError(_invalid_)
raise ValueError(_SPACE_(_concyclic_, (x, y)))
raise ValueError(_SPACE_(_concyclic_, (m, n, N)))
except (TypeError, ValueError) as x: raise ResectionError(pointA=pointA, pointB=pointB, pointC=pointC, alpha=alpha, beta=beta, txt=str(x))
'''3-Point resection using U{Collins<https://Dokumen.tips/documents/ three-point-resection-problem-introduction-kaestner-burkhardt-method.html>}' method.
@arg pointA: First point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple}, C{Vector4Tuple} or C{Vector2Tuple} if C{B{useZ}=False}). @arg pointB: Second point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple}, C{Vector4Tuple} or C{Vector2Tuple} if C{B{useZ}=False}). @arg pointC: Center point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple}, C{Vector4Tuple} or C{Vector2Tuple} if C{B{useZ}=False}). @arg alpha: Angle subtended by triangle side C{b} from B{C{pointA}} to B{C{pointC}} (C{degrees}, non-negative). @arg beta: Angle subtended by triangle side C{a} from B{C{pointB}} to B{C{pointC}} (C{degrees}, non-negative). @kwarg useZ: If C{True}, use and interpolate the Z component, otherwise force C{z=0} (C{bool}). @kwarg Clas: Optional class to return the survey point or C{None} for B{C{pointA}}'s (sub-)class. @kwarg Clas_kwds: Optional additional keyword argument for the survey point instance.
@note: Typically, B{C{pointC}} is between B{C{pointA}} and B{C{pointB}}.
@return: L{Collins5Tuple}C{(pointP, pointH, a, b, c)} with survey C{pointP}, auxiliary C{pointH}, each an instance of B{C{Clas}} or if C{B{Clas} is None} of B{C{pointA}}'s (sub-)class and triangle sides C{a}, C{b} and C{c}.
@raise ResectionError: Near-coincident, -colinear or -concyclic points or negative or invalid B{C{alpha}} or B{C{beta}}.
@raise TypeError: Invalid B{C{pointA}}, B{C{pointB}} or B{C{pointM}}.
@see: U{Collins' methode<https://NL.WikiPedia.org/wiki/Achterwaartse_insnijding>} and functions L{pygeodesy.cassini}, L{pygeodesy.pierlot} and L{pygeodesy.tienstra}. '''
raise ValueError(_negative_)
raise ValueError(_or(_coincident_, _colinear_, _concyclic_))
# za, a = _azi_len2(C, B, PI2)
# d = c * sin(PI - rb) / srH # B.minus(H).length
# d = a * sin(za - zh) / sin(rb) # B.minus(P).length
except (TypeError, ValueError) as x: raise ResectionError(pointA=pointA, pointB=pointB, pointC=pointC, alpha=alpha, beta=beta, txt=str(x))
'''3-Point resection using U{Pierlot<http://www.Telecom.ULg.ac.BE/publi/publications/ pierlot/Pierlot2014ANewThree>}'s method C{ToTal}.
@arg point1: First point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple}, C{Vector4Tuple} or C{Vector2Tuple} if C{B{useZ}=False}). @arg point2: Second point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple}, C{Vector4Tuple} or C{Vector2Tuple} if C{B{useZ}=False}). @arg point3: Third point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple}, C{Vector4Tuple} or C{Vector2Tuple} if C{B{useZ}=False}). @arg alpha12: Angle subtended from B{C{point1}} to B{C{point2}} (C{degrees}). @arg alpha23: Angle subtended from B{C{point2}} to B{C{point3}} (C{degrees}). @kwarg useZ: If C{True}, interpolate the Z component, otherwise use C{z=0} (C{bool}). @kwarg Clas: Optional class to return the survey point or C{None} for B{C{point1}}'s (sub-)class. @kwarg Clas_kwds: Optional additional keyword arguments for the survey point instance.
@note: Points B{C{point1}}, B{C{point2}} and B{C{point3}} are ordered counter-clockwise, typically.
@return: The survey (or robot) point, an instance of B{C{Clas}} or if C{B{Clas} is None} of B{C{point1}}'s (sub-)class.
@raise ResectionError: Near-coincident, -colinear or -concyclic points or invalid B{C{alpha12}} or B{C{alpha23}}.
@raise TypeError: Invalid B{C{point1}}, B{C{point2}} or B{C{point3}}.
@see: U{V. Pierlot, M. Van Droogenbroeck, "A New Three Object Triangulation Algorithm for Mobile Robot Positioning"<https://ORBi.ULiege.BE/ bitstream/2268/157469/1/Pierlot2014ANewThree.pdf>}, U{Vincent Pierlot, Marc Van Droogenbroeck, "18 Triangulation Algorithms for 2D Positioning (also known as the Resection Problem)"<http://www.Telecom.ULg.ac.BE/ triangulation>} and functions L{pygeodesy.cassini}, L{pygeodesy.collins} and L{pygeodesy.tienstra}. '''
raise ValueError(_or(_coincident_, _colinear_)) # cot31 = (1 - cot12 * cot23) / (cot12 + cot32) raise ValueError(_or(_coincident_, _colinear_))
raise ValueError(_or(_coincident_, _colinear_, _concyclic_)) y3_ * y1_, -cot31 * (x3_ * y1_)) / d
except (TypeError, ValueError) as x: raise ResectionError(point1=point1, point2=point2, point3=point3, alpha12=alpha12, alpha23=alpha23, txt=str(x))
'''Snellius' surveying using U{Snellius Pothenot<https://WikiPedia.org/wiki/Snellius–Pothenot_problem>}.
@arg a: Length of triangle side C{BC}, opposite of triangle corner C{A} (C{scalar}, non-negative C{meter} conventionally). @arg b: Length of triangle side C{AC}, opposite of triangle corner C{B} (C{scalar}, non-negative C{meter} conventionally). @arg degC: Angle at triangle corner C{C}, opposite triangle side C{c} (C{degrees}, non-negative). @arg alpha: Angle subtended by triangle side B{C{b}} (C{degrees}, non-negative). @kwarg beta: Angle subtended by triangle side B{C{a}} (C{degrees}, non-negative).
@return: L{Survey3Tuple}C{(PA, PB, PC)} with distance from survey point C{P} to each of the triangle corners C{A}, C{B} and C{C} (same units as B{C{a}}, B{C{b}} and B{C{c}}).
@raise TriangleError: Invalid B{C{a}}, B{C{b}} or B{C{degC}} or negative B{C{alpha}} or B{C{beta}}.
@see: Function L{pygeodesy.wildberger3}. ''' raise ValueError(_negative_)
raise ValueError(_or(_coincident_, _colinear_))
(b * sin(x) / sa))
except (TypeError, ValueError) as x: raise TriangleError(a=a, b=b, degC=degC, alpha=alpha, beta=beta, txt=str(x))
useZ=False, Clas=None, **Clas_kwds): '''3-Point resection using U{Tienstra<https://WikiPedia.org/wiki/Tienstra_formula>}'s formula.
@arg pointA: First point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple}, C{Vector4Tuple} or C{Vector2Tuple} if C{B{useZ}=False}). @arg pointB: Second point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple}, C{Vector4Tuple} or C{Vector2Tuple} if C{B{useZ}=False}). @arg pointC: Third point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple}, C{Vector4Tuple} or C{Vector2Tuple} if C{B{useZ}=False}). @arg alpha: Angle subtended by triangle side C{a} from B{C{pointB}} to B{C{pointC}} (C{degrees}, non-negative). @kwarg beta: Angle subtended by triangle side C{b} from B{C{pointA}} to B{C{pointC}} (C{degrees}, non-negative) or C{None} if C{B{gamma} is not None}. @kwarg gamma: Angle subtended by triangle side C{c} from B{C{pointA}} to B{C{pointB}} (C{degrees}, non-negative) or C{None} if C{B{beta} is not None}. @kwarg useZ: If C{True}, use and interpolate the Z component, otherwise force C{z=0} (C{bool}). @kwarg Clas: Optional class to return the survey point or C{None} for B{C{pointA}}'s (sub-)class. @kwarg Clas_kwds: Optional additional keyword arguments for the survey point instance.
@note: Points B{C{pointA}}, B{C{pointB}} and B{C{pointC}} are ordered clockwise.
@return: L{Tienstra7Tuple}C{(pointP, A, B, C, a, b, c)} with survey C{pointP}, an instance of B{C{Clas}} or if C{B{Clas} is None} of B{C{pointA}}'s (sub-)class and triangle angle C{A} at B{C{pointA}}, C{B} at B{C{pointB}} and C{C} at B{C{pointC}} in C{degrees} and triangle sides C{a}, C{b} and C{c}.
@raise ResectionError: Near-coincident, -colinear or -concyclic points or sum of B{C{alpha}}, B{C{beta}} and B{C{gamma}} not C{360} or negative B{C{alpha}}, B{C{beta}} or B{C{gamma}}.
@raise TypeError: Invalid B{C{pointA}}, B{C{pointB}} or B{C{pointC}}.
@see: U{3-Point Resection Solver<http://MesaMike.org/geocache/GC1B0Q9/tienstra/>}, U{V. Pierlot, M. Van Droogenbroeck, "A New Three Object Triangulation..." <http://www.Telecom.ULg.ac.BE/publi/publications/pierlot/Pierlot2014ANewThree/>}, U{18 Triangulation Algorithms...<http://www.Telecom.ULg.ac.BE/triangulation/>} and functions L{pygeodesy.cassini}, L{pygeodesy.collins} and L{pygeodesy.pierlot}. '''
raise ValueError(Fmt.PARENSPACED(concyclic=N)) # k = 1 / (cot(r) - cot(s)) # = 1 / (cos(r) / sin(r) - cos(s) / sin(s)) # = 1 / (cos(r) * sin(s) - cos(s) * sin(r)) / (sin(r) * sin(s)) # = sin(r) * sin(s) / (cos(r) * sin(s) - cos(s) * sin(r)) raise ValueError(Fmt.PARENSPACED(cotan=N))
raise ValueError(_and(Fmt.EQUAL(beta=beta), Fmt.EQUAL(gamma=gamma))) sc = fsum1_(PI2, -sa, -sb) else: # subtended angles must add to 360 degrees raise ValueError(Fmt.EQUAL(sum=degrees(r))) raise ValueError(_negative_)
# triangle sides
raise ValueError(Fmt.EQUAL(K=k))
except (TypeError, ValueError) as x: raise ResectionError(pointA=pointA, pointB=pointB, pointC=pointC, alpha=alpha, beta=beta, gamma=gamma, txt=str(x))
'''Compute an interior angle of a triangle.
@arg a: Adjacent triangle side length (C{scalar}, non-negative C{meter} conventionally). @arg b: Adjacent triangle side length (C{scalar}, non-negative C{meter} conventionally). @arg c: Opposite triangle side length (C{scalar}, non-negative C{meter} conventionally).
@return: Angle at triangle corner C{C}, opposite triangle side B{C{c}} (C{radians}).
@raise TriangleError: Invalid B{C{a}}, B{C{b}} or B{C{c}}.
@see: Function L{pygeodesy.triSide}. ''' try: return _triAngle(a, b, c) except (TypeError, ValueError) as x: raise TriangleError(a=a, b=b, c=c, tx=str(x))
# (INTERNAL) To allow callers to embellish errors raise ValueError(_negative_) raise ValueError(_coincident_) raise ValueError(_coincident_)
'''Compute the angles of a triangle side.
@arg a: Length of triangle side C{BC}, opposite of triangle corner C{A} (C{scalar}, non-negative C{meter} conventionally). @arg b: Length of triangle side C{AC}, opposite of triangle corner C{B} (C{scalar}, non-negative C{meter} conventionally). @arg c: Length of triangle side C{AB}, opposite of triangle corner C{C} (C{scalar}, non-negative C{meter} conventionally).
@return: L{TriAngle4Tuple}C{(radA, radB, radC, rIn)} with the triangle angles at corner C{A}, C{B} and C{C} (each in radians) and the C{InCircle} radius C{rIn} aka C{inradius} (same units and triangle sides B{C{a}}, B{C{b}} and B{C{c}}).
@raise TriangleError: Invalid B{C{a}}, B{C{b}} or B{C{b}}. '''
raise ValueError(_negative_) raise ValueError(_coincident_) raise ValueError(_colinear_) elif c < 0: raise ValueError(_negative_) else: # 0 <= c <= EPS0 rA = rB = PI_2 rC = r = _0_0
except (TypeError, ValueError) as x: raise TriangleError(a=a, b=b, c=c, txt=str(x))
'''Compute the length of a triangle side.
@arg a: Adjacent triangle side length (C{scalar}, non-negative C{meter} conventionally). @arg b: Adjacent triangle side length (C{scalar}, non-negative C{meter} conventionally). @arg radC: Angle included by sides B{C{a}} and B{C{b}}, opposite triangle side C{c} (C{radians}).
@return: Length of triangle side C{c}, opposite angle B{C{rC}} (same units as B{C{a}} and B{C{b}}).
@raise TriangleError: Invalid B{C{a}}, B{C{b}} or B{C{radC}}. ''' except (TypeError, ValueError) as x: raise TriangleError(a=a, b=b, radC=radC, txt=str(x))
# (INTERNAL) To allow callers to embellish errors raise ValueError(_negative_)
return abs(a - b) return hypot(a, b)
c = _0_0 raise ValueError(_invalid_) else:
'''Compute the length of a triangle side and the angle.
@arg b: Adjacent triangle side length (C{scalar}, non-negative C{meter} conventionally). @arg c: Adjacent triangle side length (C{scalar}, non-negative C{meter} conventionally). @arg radB: Angle included by sides B{C{a}} and B{C{c}}, opposite triangle side C{b} (C{radians}).
@return: L{TriSide2Tuple}C{(a, radA)} with triangle angle C{radA} (radians) and the length of the opposite triangle side C{a} (same units as B{C{b}} and B{C{c}}).
@raise TriangleError: Invalid B{C{b}} or B{C{c}} or either B{C{b}} or B{C{radB}} near zero and not both. ''' try: return _triSide2(b, c, radB) except (TypeError, ValueError) as x: raise TriangleError(b=b, c=c, radB=radB, txt=str(x))
# (INTERNAL) To allow callers to embellish errors raise ValueError(_negative_) if not isnear0(b): raise ValueError(_invalid_) if cB < 0: a, rA = (b + c), PI else: a, rA = abs(b - c), _0_0 raise ValueError(_invalid_) else:
'''Compute the length of two triangle sides and the triangle height.
@arg radA: Angle at triangle corner C{A}, opposite triangle side C{a} (C{scalar}, non-negative). @arg radB: Angle at triangle corner C{B}, opposite triangle side C{b} (C{scalar}, non-negative). @arg c: Length of triangle side between corners C{A} and C{B}, (C{scalar}, non-negative C{meter} conventionally).
@return: L{TriSide4Tuple}C{(a, b, radC, d)} with triangle sides C{a} and C{b} and triangle height C{d} perpendicular to triangle side B{C{c}} (all in same units as B{C{c}}) and the interior angle at triangle corner C{C} (C{radians}), opposite of triangle side B{C{c}}.
@raise TriangleError: Invalid B{C{a}} or B{C{b}}.
@see: Function L{pygeodesy.triSide} and U{Triangulation, Surveying <https://WikiPedia.org/wiki/Triangulation_(surveying)>}. ''' raise ValueError(_negative_) raise ValueError(_invalid_)
except (TypeError, ValueError) as x: raise TriangleError(radA=radA, radB=radB, c=c, txt=str(x))
'''Snellius' surveying using U{Rational Trigonometry<https://WikiPedia.org/wiki/Snellius–Pothenot_problem>}.
@arg a: Length of triangle side C{BC}, opposite of triangle corner C{A} (C{scalar}, non-negative C{meter} conventionally). @arg b: Length of triangle side C{AC}, opposite of triangle corner C{B} (C{scalar}, non-negative C{meter} conventionally). @arg c: Length of triangle side C{AB}, opposite of triangle corner C{C} (C{scalar}, non-negative C{meter} conventionally). @arg alpha: Angle subtended by triangle side B{C{b}} (C{degrees}, non-negative). @arg beta: Angle subtended by triangle side B{C{a}} (C{degrees}, non-negative). @kwarg R3: Callable to determine C{R3} from C{(R3 - C)**2 = D}, typically standard function C{min} or C{max}, invoked with 2 arguments.
@return: L{Survey3Tuple}C{(PA, PB, PC)} with distance from survey point C{P} to each of the triangle corners C{A}, C{B} and C{C} (same units as B{C{a}}, B{C{b}} and B{C{c}}).
@raise TriangleError: Invalid B{C{a}}, B{C{b}} or B{C{c}} or negative B{C{alpha}} or B{C{beta}} or B{C{R3}} not C{callable}.
@see: U{Wildberger, Norman J.<https://math.sc.chula.ac.th/cjm/content/ survey-article-greek-geometry-rational-trigonometry-and-snellius-–-pothenot-surveying>}, U{Devine Proportions, page 252<http://www.ms.LT/derlius/WildbergerDivineProportions.pdf>} and function L{pygeodesy.snellius3}. '''
raise ValueError(_coincident_)
raise ValueError(_negative_)
raise ValueError(_or(_coincident_, _colinear_))
raise ValueError(_coincident_)
raise ValueError(_SPACE_(_R3_, _not_(callable.__name__))) elif d0 < 0: raise ValueError(_negative_) else: # isnear0(sqrt(d0)) r3 = c0
_triSide2(a, pb, rb).a)
except (TypeError, ValueError) as x: raise TriangleError(a=a, b=b, c=c, alpha=alpha, beta=beta, R3=R3, txt=str(x))
# interpolate z or coplanar with A, B and C? t = A.z, B.z, C.z v = Vector3d(x, y, fmean(t)) return fidw(t, (v.minus(A).length, v.minus(B).length, v.minus(C).length))
# **) 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. |