Coverage for pygeodesy/resections.py : 99%

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} is 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>}. '''
_0_0, _0_5, _1_0, _N_1_0, _2_0, _N_2_0, _4_0, _360_0 _d_, _invalid_, _negative_, _not_, _rIn_, _SPACE_ # from pygeodesy.lazily import _ALL_LAZY # from .basics # 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. '''
'''Error raised for issues in L{pygeodesy.resections}. '''
'''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} in C{meter}, conventionally. '''
'''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 corners C{A}, C{B} and C{C} in C{radians} and the C{InCircle} radius C{rIn} aka C{inradius} in C{meter}, conventionally. '''
'''2-Tuple C{(a, radA)} with triangle side C{a} in C{meter}, conventionally and angle C{radA} at the opposite triangle corner in C{radians}. '''
'''4-Tuple C{(a, b, radC, d)} with interior angle C{radC} at triangle corner C{C} in C{radians}with the length of triangle sides C{a} and C{b} and with triangle height C{d} perpendicular to triangle side C{c}, in the same units as triangle sides C{a} and C{b}. '''
'''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=INT0} (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: 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.collins5}, L{pygeodesy.pierlot} and L{pygeodesy.tienstra7}. '''
raise ValueError(_or(_coincident_, _colinear_))
raise ValueError(_negative_) raise ValueError(_invalid_)
# x, y, _ = H1.minus(H2).xyz 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=INT0} (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: 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} in C{meter}, conventionally.
@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.tienstra7}. '''
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=INT0} (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.collins5} and L{pygeodesy.tienstra7}. '''
raise ValueError(_or(_coincident_, _colinear_)) # cot31 = (1 - cot12 * cot23) / (cot12 + cot32) raise ValueError(_or(_colinear_, _coincident_))
# x23 = x3_ - cot23 * y3_ # y23 = y3_ + cot23 * x3_
raise ValueError(_or(_coincident_, _colinear_, _concyclic_)) y3_ * y1_, -cot31 * (x3_ * y1_))
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 the triangle side between corners C{B} and C{C} and opposite of triangle corner C{A} (C{scalar}, non-negative C{meter}, conventionally). @arg b: Length of the triangle side between corners C{C} and C{A} and 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} (non-negative C{degrees}). @arg alpha: Angle subtended by triangle side B{C{b}} (non-negative C{degrees}). @arg beta: Angle subtended by triangle side B{C{a}} (non-negative C{degrees}).
@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 triangle sides 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_))
else: raise ValueError(_or(_colinear_, _coincident_))
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=INT0} (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, with triangle angles C{A} at B{C{pointA}}, C{B} at B{C{pointB}} and C{C} at B{C{pointC}} in C{degrees} and with triangle sides C{a}, C{b} and C{c} in C{meter}, conventionally.
@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.collins5} 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 = fsum_(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 one 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 in C{radians} at triangle corner C{C}, opposite triangle side B{C{c}}.
@raise TriangleError: Invalid or negative B{C{a}}, B{C{b}} or B{C{c}}.
@see: Functions L{pygeodesy.triAngle4} and L{pygeodesy.triSide}. ''' 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.
@arg a: Length of the triangle side opposite of triangle corner C{A} (C{scalar}, non-negative C{meter}, conventionally). @arg b: Length of the triangle side opposite of triangle corner C{B} (C{scalar}, non-negative C{meter}, conventionally). @arg c: Length of the triangle side opposite of triangle corner C{C} (C{scalar}, non-negative C{meter}, conventionally).
@return: L{TriAngle4Tuple}C{(radA, radB, radC, rIn)} with angles C{radA}, C{radB} and C{radC} at triangle corners C{A}, C{B} and C{C}, all in C{radians} and the C{InCircle} radius C{rIn} aka C{inradius}, same units as triangle sides B{C{a}}, B{C{b}} and B{C{c}}.
@raise TriangleError: Invalid or negative B{C{a}}, B{C{b}} or B{C{c}}.
@see: Function L{pygeodesy.triAngle}. '''
raise ValueError(_negative_) raise ValueError(_coincident_) raise ValueError(_colinear_) raise ValueError(_negative_) else: # 0 <= c <= EPS0
except (TypeError, ValueError) as x: raise TriangleError(a=a, b=b, c=c, txt=str(x))
'''Compute one side 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 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 triangle corner C{C} and angle B{C{radC}}, same units as B{C{a}} and B{C{b}}.
@raise TriangleError: Invalid B{C{a}}, B{C{b}} or B{C{radC}}.
@see: Functions L{pygeodesy.sqrt_a}, L{pygeodesy.triAngle}, L{pygeodesy.triSide2} and L{pygeodesy.triSide4}. ''' 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_)
elif c2 < 0: raise ValueError(_invalid_) return hypot(a, b)
'''Compute one side and the opposite angle of a triangle.
@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} in C{radians} and 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.
@see: Functions L{pygeodesy.sqrt_a}, L{pygeodesy.triSide} and L{pygeodesy.triSide4}. ''' 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_) raise ValueError(_invalid_) else: raise ValueError(_invalid_) else:
'''Compute two sides and the height of a triangle.
@arg radA: Angle at triangle corner C{A}, opposite triangle side C{a} (non-negative C{radians}). @arg radB: Angle at triangle corner C{B}, opposite triangle side C{b} (non-negative C{radians}). @arg c: Length of triangle side between triangle 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 the same units as B{C{c}} and interior angle C{radC} in C{radians} at triangle corner C{C}, opposite triangle side B{C{c}}.
@raise TriangleError: Invalid or negative B{C{radA}}, B{C{radB}} or B{C{c}}.
@see: U{Triangulation, Surveying<https://WikiPedia.org/wiki/Triangulation_(surveying)>} and functions L{pygeodesy.sqrt_a}, L{pygeodesy.triSide} and L{pygeodesy.triSide2}. ''' raise ValueError(_negative_) raise ValueError(_invalid_) name=triSide4.__name__)
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 the triangle side between corners C{B} and C{C} and opposite of triangle corner C{A} (C{scalar}, non-negative C{meter}, conventionally). @arg b: Length of the triangle side between corners C{C} and C{A} and opposite of triangle corner C{B} (C{scalar}, non-negative C{meter}, conventionally). @arg c: Length of the triangle side between corners C{A} and C{B} and 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(_R3__ + _not_(callable.__name__)) elif d0 < 0: raise ValueError(_negative_)
_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?
# **) 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. |