Exemplo n.º 1
0
    def testNvectorBase(self, module, **kwds):

        try:
            Nvector = module.Nvector
            c = Nvector.__name__
        except AttributeError:
            Nvector = module.NvectorBase
            c = 'Vector4Tuple'
        self.subtitle(module, Nvector.__name__)

        v = Nvector(0.500, 0.500, 0.707, **kwds)
        s = module.sumOf((v, v), h=0, name='sumOf')
        self.test('sumOf', s.__class__.__name__, c)

        p = v.toLatLon(LatLon=None)
        c = v.toCartesian(Cartesian=None)
        self.test('ecef.x, .y, .z', fstr(p[:3], prec=5), fstr(c[:3], prec=5))
        self.test('ecef.lat, .lon', fstr(p[3:5], prec=6), fstr(c[3:5], prec=6))
        self.test('ecef.height',
                  fstr(p.height, prec=6),
                  fstr(c.height, prec=6),
                  known=True)
        if c.M is not None:
            self.test('ecef.M', fstr(p.M, prec=9), fstr(c.M, prec=9))

        if coverage:
            from pygeodesy.namedTuples import LatLon2Tuple, LatLon3Tuple, \
                                              PhiLam2Tuple, PhiLam3Tuple

            self.test('.isEllipsoidal', v.isEllipsoidal, not v.isSpherical)
            self.test('.isSpherical', v.isSpherical, not v.isEllipsoidal)

            self.test('.latlon', v.latlon, LatLon2Tuple(v.lat, v.lon))
            self.test('.philam', v.philam, PhiLam2Tuple(v.phi, v.lam))

            self.test('.latlonheight',
                      v.latlonheight,
                      LatLon3Tuple(v.lat, v.lon, v.h),
                      known=v.h in (0, 0.0, NEG0))
            self.test('.philamheight',
                      v.philamheight,
                      PhiLam3Tuple(v.phi, v.lam, v.h),
                      known=v.h in (0, 0.0, NEG0))

            t = v.parse('0.5, 0.5, 0.707')
            self.test('parse', t, v)
            self.test('cmp', t.cmp(v), 0)

            self.test('eq', t == v, True)
            self.test('ge', t >= v, True)
            self.test('gt', t > v, False)
            self.test('le', t <= v, True)
            self.test('lt', t < v, False)
            self.test('ne', t != v, False)

            m = t * 2
            self.test('*', m, '(1.0, 1.0, 1.414)')
            self.test('+', t + v, m)
            self.test('/', m / 2, t)
            self.test('-', m - t, t)

            m = v.__matmul__(t)
            self.test('@', m, '(0.0, 0.0, 0.0)')
            r = t.__rmatmul__(m)
            self.test('@', r, m)

            r = v.rotate(m, 45)
            self.test('rotate', r, '(0.26268, 0.26268, 0.37143)')

            r.crosserrors = True
            self.test('crosserrors', r.crosserrors, True)

            try:
                self.test('0', v.dividedBy(0), VectorError.__name__)
            except Exception as x:
                self.test('0', str(x), 'factor (0): float division by zero')

            t = vector3d.intersections2(Nvector(0, 0, 0),
                                        500,
                                        Nvector(1000, 0, 0),
                                        500,
                                        sphere=False)
            self.test('intersections2', t[0], t[1])  # abutting

            p1, p2 = Nvector(-100, -100, -100), Nvector(100, 100, 100)
            t = vector3d.nearestOn(Nvector(0, 0, 0), p1, p2)
            self.test('nearestOn', t, Nvector(0, 0, 0))
            t = vector3d.nearestOn(Nvector(-200, -200, 0), p1, p2)
            self.test('nearestOn', t is p1, True)
            t = vector3d.nearestOn(Nvector(200, 200, 0), p1, p2)
            self.test('nearestOn', t, p2)
            self.test('nearestOn', t is p2, True)
            t = vector3d.iscolinearWith(Nvector(200, 200, 0), p1, p2)
            self.test('iscolinearWith', t, False)
            t = vector3d.iscolinearWith(Nvector(0, 0, 0), p1, p2)
            self.test('iscolinearWith', t, True)
Exemplo n.º 2
0
    def testCartesian(self, module, Sph=False, Nv=True):  # MCCABE 45

        self.subtitle(module, 'Cartesian')

        Cartesian = module.Cartesian
        LatLon = module.LatLon
        Nvector = module.Nvector if Nv else Vector4Tuple

        datum = Datums.Sphere if Sph else Datums.WGS84
        datum2 = None if Sph else Datums.WGS72
        # <https://www.Movable-Type.co.UK/scripts/geodesy/docs/
        #        latlon-nvector-ellipsoidal.js.html#line309>
        c = Cartesian(3980581, 97, 4966825, datum=datum)
        self.test('Cartesian0', c.toStr(prec=0), '[3980581, 97, 4966825]')
        self.test('Cartesian4', c.toStr(prec=4),
                  '[3980581.0, 97.0, 4966825.0]')

        self.test('isEllipsoidal', c.isEllipsoidal, not Sph)
        self.test('isSpherical', c.isSpherical, Sph)
        self.testCopy(c)

        n = c.toNvector()  # (x=0.622818, y=0.00002, z=0.782367, h=0.242887)
        t = n.classname  # Nvector.__name__
        if Nv:
            self.test(
                t, repr(n), 'Nvector(0.62538, 0.00002, 0.78032, -5918.38)'
                if Sph else 'Nvector(0.62282, 0.00002, 0.78237, +0.24)')
            self.test(
                t + '3', n.toStr(prec=3), '(0.625, 0.0, 0.78, -5918.38)'
                if Sph else '(0.623, 0.0, 0.782, +0.24)')
            self.test(
                t + '6', n.toStr(prec=6),
                '(0.625377, 0.000015, 0.780323, -5918.38)' if Sph else
                '(0.622818, 0.000015, 0.782367, +0.24)')  # PYCHOK attribute
        else:
            self.test(
                t,
                repr(n),
                '(x=0.6253769790183048, y=1.5239375097448227e-05, z=0.7803227754472505, h=-5918.3802583276365)'
                if Sph else
                '(x=0.6228177647454303, y=1.517701139112776e-05, z=0.782366941841975, h=0.24288680875513333)',
                known=True)

        for ll in (
            (50.0379, 8.5622),  # FRA
            (51.47, 0.4543),  # LHR
                # <https://www.EdWilliams.org/avform.htm#XTE>
            (degrees(0.709186), -degrees(1.287762)),  # JFK
            (33. + 57. / 60, -(118. + 24. / 60)),  # LAX
                # <https://GeographicLib.SourceForge.io/html/python/examples.html>
            (-41.32, 174.81),  # WNZ, Wellington, NZ
            (40.96, 5.50),  # SAL, Salamanca, Spain
            (40.1, 116.6),  # BJS, Beijing Airport
            (37.6, -122.4)):  # SFO
            if datum2:
                t = c.convertDatum(datum2).convertDatum(datum)
                self.test('convertDatum', t, c)  # PYCHOK attribute
            p = LatLon(*ll)
            q = p.toCartesian().toLatLon()
            t = str(q)
            self.test('LatLon', t, p,
                      known=t.endswith('m'))  # PYCHOK attribute

        # c = Cartesian(3980581, 97, 4966825, datum=datum)
        t = c.copy()
        self.test('copy', t.isequalTo(c), True)
        self.test('__eq__', t == c, True)
        self.test('__ne__', t != c, False)

        if hasattr(Cartesian, 'convertRefFrame'):
            pass  # PYCHOK attribute

        for B in (False, True):  # check return types
            t = c.__class__
            self.test('Cartesian', t, t)
            # self.testReturnType(c.Ecef,             Ecef,       c.Ecef.__name__)
            self.testReturnType(c.latlon, LatLon2Tuple, 'latlon')
            self.testReturnType(c.latlonheight, LatLon3Tuple, 'latlonheight')
            self.testReturnType(c.latlonheightdatum, LatLon4Tuple,
                                'latlonheightdatum')
            self.testReturnType(c.isequalTo(c), bool, 'isequalTo')
            self.testReturnType(c.philam, PhiLam2Tuple, 'philam')
            self.testReturnType(c.philamheight, PhiLam3Tuple, 'philamheight')
            self.testReturnType(c.philamheightdatum, PhiLam4Tuple,
                                'philamheightdatum')
            self.testReturnType(c.to3llh(), LatLon4Tuple, 'to3llh')
            self.testReturnType(c.toEcef(), Ecef9Tuple, 'toEcef')
            self.testReturnType(c.toLatLon(), Ecef9Tuple if B else LatLon,
                                'toLatLon')
            self.testReturnType(c.toNvector(), Vector4Tuple if B else Nvector,
                                'toNvector')
            self.testReturnType(c.xyz, Vector3Tuple, 'xyz')
            c = CartesianBase(c)  # PYCHOK attribute

        if hasattr(Cartesian, 'intersections2'):
            # <https://GIS.StackExchange.com/questions/48937/calculating-intersection-of-two-circles>
            c = Cartesian(-0.00323306, -0.7915, 0.61116)
            self.test('intersections2', c.toLatLon(height=0),
                      '37.673442°N, 090.234036°W')
            d = Cartesian(-0.0134464, -0.807775, 0.589337)
            self.test('intersections2', d.toLatLon(height=0),
                      '36.109987°N, 090.95367°W')
            x, y = c.intersections2(0.0312705, d, 0.0421788,
                                    radius=None)  # radii in radians
            self.test('intersections2', x.toStr(prec=6),
                      '[-0.032779, -0.784769, 0.61892]'
                      )  # -0.0327606, -0.784759, 0.618935
            self.test('intersections2', x.toLatLon(height=0),
                      '38.237342°N, 092.391779°W')  # 38.23838°N, 092.390487°W
            if y is not x:
                self.test('intersections2', y.toStr(prec=6),
                          '[0.025768, -0.798347, 0.601646]'
                          )  # 0.0257661, -0.798332, 0.601666
                self.test(
                    'intersections2', y.toLatLon(height=0),
                    '36.987868°N, 088.151309°W')  # 36.98931°N, 088.151425°W

        try:
            from pygeodesy.vector3d import intersections2

            u = Vector3Tuple(-0.00323306, -0.7915, 0.61116)
            v = Vector3Tuple(-0.0134464, -0.807775, 0.589337)
            c, r = intersections2(u, 0.0312705, v, 0.0421788, sphere=True)
            self.test('intersections2', c.toStr(prec=6),
                      '(-0.0035, -0.791926, 0.610589)')
            self.test('intersections2',
                      r.toStr(prec=6),
                      '0.031261',
                      known=True)  # XXX G and g formats may add 1 decimal
            v1, v2 = intersections2(u, 0.0312705, v, 0.0421788, sphere=False)
            self.test('intersections2', v1.toStr(prec=6),
                      '(-0.021973, -0.766467, 0)')
            if v2 is not v1:
                self.test('intersections2', v2.toStr(prec=6),
                          '(0.027459, -0.797488, 0)')
        except ImportError:
            pass
Exemplo n.º 3
0
def intersections2(lat1, lon1, radius1,
                   lat2, lon2, radius2, datum=None, wrap=True):
    '''Conveniently compute the intersections of two circles each defined
       by (geodetic/-centric) center point and a radius, using either ...

       1) L{vector3d.intersections2} for small distances or if no B{C{datum}}
       is specified, or ...

       2) L{sphericalTrigonometry.intersections2} for a spherical B{C{datum}}
       or if B{C{datum}} is a C{scalar} representing the earth radius, or ...

       3) L{ellipsoidalKarney.intersections2} for an ellipsoidal B{C{datum}}
       and if I{Karney}'s U{geographiclib<https://PyPI.org/project/geographiclib/>}
       is installed, or ...

       4) L{ellipsoidalVincenty.intersections2} if B{C{datum}} is ellipsoidal
       otherwise.

       @arg lat1: Latitude of the first circle center (C{degrees}).
       @arg lon1: Longitude of the first circle center (C{degrees}).
       @arg radius1: Radius of the first circle (C{meter}, conventionally).
       @arg lat2: Latitude of the second circle center (C{degrees}).
       @arg lon2: Longitude of the second circle center (C{degrees}).
       @arg radius2: Radius of the second circle (C{meter}, same units as B{C{radius1}}).
       @kwarg datum: Optional ellipsoidal or spherical datum (L{Datum},
                     L{Ellipsoid}, L{Ellipsoid2}, L{a_f2Tuple} or
                     C{scalar} earth radius in C{meter}, same units as
                     B{C{radius1}} and B{C{radius2}}) or C{None}.
       @kwarg wrap: Wrap and unroll longitudes (C{bool}).

       @return: 2-Tuple of the intersection points, each a
                L{LatLon2Tuple}C{(lat, lon)}.  For abutting circles,
                the intersection points are the same instance.

       @raise IntersectionError: Concentric, antipodal, invalid or
                                 non-intersecting circles or no
                                 convergence.

       @raise TypeError: Invalid B{C{datum}}.

       @raise UnitError: Invalid B{C{lat1}}, B{C{lon1}}, B{C{radius1}}
                         B{C{lat2}}, B{C{lon2}} or B{C{radius2}}.
    '''
    if datum is None or euclidean(lat1, lon1, lat1, lon2, radius=R_M,
                                  adjust=True, wrap=wrap) < _D_I2_:
        import pygeodesy.vector3d as m

        def _V2T(x, y, _, **unused):  # _ == z unused
            return _xnamed(LatLon2Tuple(y, x), intersections2.__name__)

        r1 = m2degrees(Radius_(radius1=radius1), radius=R_M, lat=lat1)
        r2 = m2degrees(Radius_(radius2=radius2), radius=R_M, lat=lat2)

        _, lon2 = unroll180(lon1, lon2, wrap=wrap)
        t = m.intersections2(m.Vector3d(lon1, lat1, 0), r1,
                             m.Vector3d(lon2, lat2, 0), r2, sphere=False,
                               Vector=_V2T)

    else:
        def _LL2T(lat, lon, **unused):
            return _xnamed(LatLon2Tuple(lat, lon), intersections2.__name__)

        d = _spherical_datum(datum, name=intersections2.__name__)
        if d.isSpherical:
            import pygeodesy.sphericalTrigonometry as m
        elif d.isEllipsoidal:
            try:
                if d.ellipsoid.geodesic:
                    pass
                import pygeodesy.ellipsoidalKarney as m
            except ImportError:
                import pygeodesy.ellipsoidalVincenty as m
        else:
            raise _AssertionError(datum=d)

        t = m.intersections2(m.LatLon(lat1, lon1, datum=d), radius1,
                             m.LatLon(lat2, lon2, datum=d), radius2, wrap=wrap,
                               LatLon=_LL2T, height=0)
    return t