def testGeohash(self): # geohash module tests LL = ellipsoidalVincenty.LatLon cn = classname(LL(0, 0)) g = Geohash('geek') self.test('Geohash', repr(g), "Geohash('geek')") self.test('Geohash', g, 'geek') self.test('Geohash', Geohash(g), 'geek') self.test('bounds', g.bounds(LL), '(%s(65°23′26.25″N, 017°55′46.88″W), %s(65°33′59.06″N, 017°34′41.25″W))' % (cn, cn)) self.test('toLatLon', g.toLatLon(LL), '65.478516°N, 017.753906°W') self.test('latlon', fStr(g.latlon, prec=7), '65.4785156, -17.7539062') self.test('ab', fStr(g.ab, prec=7), '1.1428157, -0.3098641') g = Geohash(LL(65.390625, -17.929689), precision=9) self.test('Geohash', g, 'geehpbpbp') self.test('toLatLon', g.toLatLon(LL), '65.390625°N, 017.929689°W') self.test('latlon', fStr(g.latlon, prec=8), '65.390625, -17.929689') self.test('ab', fStr(g.ab, prec=7), '1.1412817, -0.3129321') self.test('decode', geohash.decode(g), "('65.390646', '-17.929709')") self.test('decode_error', fStr(geohash.decode_error(g), fmt='%*e'), '2.145767e-05, 2.145767e-05') self.test('distance1', g.distance1('geehpb'), '2758.887', fmt='%.3f') self.test('distance2', g.distance2('geehpb'), '682.760', fmt='%.3f') self.test('distance3', g.distance3('geehpb'), '397.404', fmt='%.3f') self.test('sizes', fStr(g.sizes, prec=1), '4.8, 4.8') for g in ('u120fxw', 'geek', 'fur', 'geehpbpbp', 'u4pruydqqvj8', 'bgr96qxvpd46', '0123456789', 'zzzzzz'): self.test('encode-decode', geohash.encode(*geohash.decode(g)), g) for p in range(8, 13): g = Geohash(LL(57.64911, 10.40744), precision=p) # Jutland, Denamrk self.test('Geohash', g, 'u4pruydqqvj8'[:p], ) self.test('N.E.S.W', g.N.E.S.W == g, 'True') self.test('E.S.W.N', g.E.S.W.N == g, 'True') self.test('S.W.N.E', g.S.W.N.E == g, 'True') self.test('W.N.E.S', g.W.N.E.S == g, 'True') self.test('N.E.S.S.W.W.N.N.E.S', g.N.E.S.S.W.W.N.N.E.S == g, True) # MCCABE Law of Demeter self.test('encode', geohash.encode(52.205, 0.1188), 'u120fxw') self.test('decode', geohash.decode('u120fxw'), "('52.205', '0.1188')") self.test('decode_error', fStr(geohash.decode_error('u120fxw'), fmt='%*e'), '6.866455e-04, 6.866455e-04') self.test('distance1', geohash.distance1('u120fxw', 'u120fxws0'), '486.710', fmt='%.3f') self.test('distance2', geohash.distance2('u120fxw', 'u120fxws0'), '3.374', fmt='%.3f') self.test('distance3', geohash.distance3('u120fxw', 'u120fxws0'), '2.798', fmt='%.3f') self.test('sizes', fStr(geohash.sizes('u120fxw'), prec=1), '153.0, 153.0') g = Geohash('52.5009, 13.354') self.test('Geohash', g, 'u336xv') e = geohash.encode(52.5009, 13.354) self.test('encode', e, 'u336xv') self.test('equal', g == e, True) self.test('sizes', fStr(geohash.sizes(g), prec=1), '610.0, 1220.0') self.test('encode', geohash.encode(69.6, -45.7), 'fur') self.test('decode', geohash.decode('fur'), "('69.6', '-45.7')") self.test('decode', geohash.decode('fu'), "('70.3', '-51')") self.test('decode', geohash.decode('f'), "('68', '-68')") self.test('decode_error', geohash.decode_error('fur'), '(0.703125, 0.703125)') self.test('decode_error', geohash.decode_error('fu'), '(2.8125, 5.625)') self.test('decode_error', geohash.decode_error('f'), '(22.5, 22.5)')
def test2(self, pts, npt, psxy=False): clas_ = classname(pts) + '.' def _test(name, *args, **kwds): # prefix class to test name self.test(clas_ + name, *args, **kwds) if Sequence: # check abstact base class conformance _test('ABC', isinstance(pts, Sequence), True) e = pts.epsilon _test('epsilon', e, EPS) pts.epsilon = 0 _test('epsilon', pts.epsilon, 0.0) pts.epsilon = e n = len(pts) // 6 # 0 < some number < len(pts) _test('len', len(pts), len(npt)) _test('iter', len(tuple(iter(pts))), len(npt)) if hasattr(npt, 'shape'): _test('shape', npt.shape, pts.shape) _test('slice1', len(pts[:n]), n) _test('slice2', type(pts[1:n:2]), type(pts)) _test('slice3', pts[1:n][0], pts[1]) _test('strepr', str(pts), repr(pts)) if hasattr(pts, 'subset'): _test('subset', type(pts.subset(range(n))), type(npt)) # , nt=1) for i, p in ((10, (52.224006, -0.707747)), (20, (52.232688, -0.714608)), (30, (52.234375, -0.714348)), (40, (52.237239, -0.712557)), (50, (52.24023, -0.709919)), (60, (52.240745, -0.707042))): if psxy: _test('find LL', pts.find(LatLon_(*p)), i) # coverage p = tuple(reversed(p)) # flip to x, y tuple _test('find LL', pts.find(LatLon_(*p)), -1) # coverage _test('count', pts.count(p), 1) _test('index', pts.index(p), i) _test('rfind', pts.rfind(p), i) _test('in', p in pts, True) p = tuple(reversed(p)) _test('count', pts.count(p), 0) _test('find', pts.find(p), -1) _test('rfind', pts.rfind(p), -1) _test('not in', p not in pts, True) pts = pts[::6] for i, p in enumerate(pts): _test('enumerate[%s]' % (i, ), p, pts[i]) i = len(pts) for p in reversed(pts): i -= 1 _test('reversed[%s]' % (i, ), p, pts[i])
def testGeohash(self, LL): cn = classname(LL(0, 0)) g = Geohash('geek') self.test('Geohash', repr(g), "Geohash('geek')") self.test('Geohash', g, 'geek') self.test('Geohash', Geohash(g), 'geek') self.test( 'bounds', g.bounds(LL), '(%s(65°23′26.25″N, 017°55′46.88″W), %s(65°33′59.06″N, 017°34′41.25″W))' % (cn, cn)) self.test('toLatLon', g.toLatLon(LL), '65.478516°N, 017.753906°W') self.test('latlon', fStr(g.latlon, prec=7), '65.4785156, -17.7539062') self.test('ab', fStr(g.ab, prec=7), '1.1428157, -0.3098641') self.testCopy(g) g = Geohash(LL(65.390625, -17.929689), precision=9) self.test('Geohash', g, 'geehpbpbp') self.test('toLatLon', g.toLatLon(LL), '65.390625°N, 017.929689°W') self.test('latlon', fStr(g.latlon, prec=8), '65.390625, -17.929689') self.test('ab', fStr(g.ab, prec=7), '1.1412817, -0.3129321') self.test('decode', geohash.decode(g), "('65.390646', '-17.929709')") self.test('decode_error', fStr(geohash.decode_error(g), fmt='%*e'), '2.145767e-05, 2.145767e-05') self.test('distance1', g.distance1('geehpb'), '2758.887', fmt='%.3f') self.test('distance2', g.distance2('geehpb'), '682.760', fmt='%.3f') self.test('distance3', g.distance3('geehpb'), '397.404', fmt='%.3f') self.test('sizes', fStr(g.sizes, prec=1), '4.8, 4.8') self.testCopy(g) for d in (g.neighbors, geohash.neighbors(g)): self.test('N', d.N, g.N) self.test('NE', d.NE, g.NE) self.test('E', d.E, g.E) self.test('SE', d.SE, g.SE) self.test('S', d.S, g.S) self.test('SW', d.SW, g.SW) self.test('W', d.W, g.W) self.test('NW', d.NW, g.NW) self.test('N', d['N'], g.N) self.test('NE', d['NE'], g.NE) self.test('E', d['E'], g.E) self.test('SE', d['SE'], g.SE) self.test('S', d['S'], g.S) self.test('SW', d['SW'], g.SW) self.test('W', d['W'], g.W) self.test('NW', d['NW'], g.NW) for g in ('u120fxw', 'geek', 'fur', 'geehpbpbp', 'u4pruydqqvj8', 'bgr96qxvpd46', '0123456789', 'zzzzzz'): self.test('encode-decode', geohash.encode(*geohash.decode(g)), g) for p in range(8, 13): g = Geohash(LL(57.64911, 10.40744), precision=p) # Jutland, Denamrk self.test( 'Geohash', g, 'u4pruydqqvj8'[:p], ) self.test('N.E.S.W', g.N.E.S.W == g, 'True') self.test('E.S.W.N', g.E.S.W.N == g, 'True') self.test('S.W.N.E', g.S.W.N.E == g, 'True') self.test('W.N.E.S', g.W.N.E.S == g, 'True') self.test('N.E.S.S.W.W.N.N.E.S', g.N.E.S.S.W.W.N.N.E.S == g, True) # MCCABE Law of Demeter self.test('encode', geohash.encode(52.205, 0.1188), 'u120fxw') self.test('decode', geohash.decode('u120fxw'), "('52.205', '0.1188')") self.test('decode_error', fStr(geohash.decode_error('u120fxw'), fmt='%*e'), '6.866455e-04, 6.866455e-04') self.test('distance1', geohash.distance1('u120fxw', 'u120fxws0'), '486.710', fmt='%.3f') self.test('distance2', geohash.distance2('u120fxw', 'u120fxws0'), '3.374', fmt='%.3f') self.test('distance3', geohash.distance3('u120fxw', 'u120fxws0'), '2.798', fmt='%.3f') self.test('sizes', fStr(geohash.sizes('u120fxw'), prec=1), '153.0, 153.0') g = Geohash('52.5009, 13.354') self.test('Geohash', g, 'u336xv') e = geohash.encode(52.5009, 13.354) self.test('encode', e, 'u336xv') self.test('equal', g == e, True) self.test('sizes', fStr(geohash.sizes(g), prec=1), '610.0, 1220.0') self.test('encode', geohash.encode(69.6, -45.7), 'fur') self.test('decode', geohash.decode('fur'), "('69.6', '-45.7')") self.test('decode', geohash.decode('fu'), "('70.3', '-51')") self.test('decode', geohash.decode('f'), "('68', '-68')") self.test('decode_error', geohash.decode_error('fur'), '(0.703125, 0.703125)') self.test('decode_error', geohash.decode_error('fu'), '(2.8125, 5.625)') self.test('decode_error', geohash.decode_error('f'), '(22.5, 22.5)') for t in range(0, 14): r = geohash.resolution2(t, t) p = geohash.precision(*r) self.test('precision', t, p, known=t < 1 or t > 12) b = fStr(r, prec=t + 1) self.test('resolution', b, b) # just to show
def testSpherical(self, module, Sph=True): # MCCABE 13 self.subtitle(module, 'Spherical') LatLon, Vct = module.LatLon, not Sph p = LatLon(51.8853, 0.2545) self.test('isSpherical', p.isSpherical, True) self.test('isEllipsoidal', p.isEllipsoidal, False) q = LatLon(49.0034, 2.5735) self.test('isSpherical', q.isSpherical, True) self.test('isEllipsoidal', q.isEllipsoidal, False) i = p.intersection(108.55, q, 32.44) self.test('intersection1', i.toStr(F_D), '50.907608°N, 004.508575°E') # 50.9076°N, 004.5086°E # Trig self.test('intersection1', i.toStr(F_DMS), '50°54′27.39″N, 004°30′30.87″E') self.test('intersection1', isinstance(i, LatLon), True) REO = LatLon(42.600, -117.866) BKE = LatLon(44.840, -117.806) i = REO.intersection(51, BKE, 137) self.test('intersection2', isinstance(i, LatLon), True) self.test('intersection2', i.toStr(F_D), '43.5719°N, 116.188757°W') # 43.572°N, 116.189°W self.test('intersection2', i.toStr(F_DMS), '43°34′18.84″N, 116°11′19.53″W') # <https://GitHub.com/ChrisVeness/geodesy/issues/46> p = LatLon(51.8853, 0.2545) q = LatLon(51.8763, 0.2545) # identical lon i = p.intersection(110.8878, q, 54.4525) self.test('intersection3', i, '51.882166°N, 000.267801°E') # 51°52′55.8″N, 000°16′04.08″E? p = LatLon(+30, 0) q = LatLon(-30, 0) # identical, zero lon i = p.intersection(135, q, 45) self.test('intersection4', i, '00.0°N, 026.565051°E', known=abs(i.lat) < 1e-6) p = LatLon(0, -30) q = LatLon(0, +30) # identical, zero lat i = p.intersection(45, q, 315) self.test('intersection5', i, '26.565051°N, 000.0°W', known=abs(i.lon) < 1e-6) # <https://GitHub.com/ChrisVeness/geodesy/blob/master/test/latlon-vectors-tests.js> STN = LatLon(51.8853, 0.2545) CDG = LatLon(49.0034, 2.5735) i = STN.intersection(108.547, CDG, 32.435) self.test('intersection6', i, '50.907809°N, 004.50841°E') # 50.9078°N, 004.5084°E # <https://GitHub.com/ChrisVeness/geodesy/blob/master/test/latlon-vectors-tests.js> # <https://GitHub.com/ChrisVeness/geodesy/blob/master/test/latlon-spherical-tests.js> N, E, S, W, p, q = 0, 90, 180, 270, LatLon(0, 1), LatLon(1, 0) self.test('toward 1,1 N,E nearest', p.intersection(N, q, E), '00.999848°N, 001.0°E') self.test('toward 1,1 E,N nearest', q.intersection(E, p, N), '00.999848°N, 001.0°E') self.test('toward 1,1 N,E antipodal', LatLon(2, 1).intersection(N, q, E), '00.999848°S, 179.0°W') self.test('toward/away 1,1 N,W antipodal', p.intersection(N, q, W), '00.999848°S, 179.0°W', known=Sph) self.test('toward/away 1,1 W,N antipodal', q.intersection(W, p, N), '00.999848°S, 179.0°W') self.test('toward/away 1,1 S,E antipodal', p.intersection(S, q, E), '00.999848°S, 179.0°W') self.test('toward/away 1,1 E,S antipodal', q.intersection(E, p, S), '00.999848°S, 179.0°W', known=Sph) self.test('away 1,1 S,W antipodal', p.intersection(S, q, W), '00.999848°S, 179.0°W') self.test('away 1,1 W,S antipodal', q.intersection(W, p, S), '00.999848°S, 179.0°W') self.test('1E/90E N,E antipodal', p.intersection(N, LatLon(1, 90), E), '00.017454°S, 179.0°W', known=Sph) self.test('1E/90E N,E nearest', p.intersection(N, LatLon(1, 92), E), '00.017454°N, 179.0°W') # <https://GitHub.com/ChrisVeness/geodesy/blob/master/test/latlon-vectors-tests.js> p, r = LatLon(1, 3), LatLon(2, 2) self.test('brng+end 1a', q.intersection(p, r, S), '01.000305°N, 002.0°E') self.test('brng+end 1b', r.intersection(S, q, p), '01.000305°N, 002.0°E') self.test('brng+end 2a', q.intersection(p, r, N), '01.000305°S, 178.0°W') self.test('brng+end 2b', r.intersection(N, q, p), '01.000305°S, 178.0°W') i = LatLon(1, 1).intersection(LatLon(2, 2), LatLon(1, 4), LatLon(2, 3)) self.test('intersection7', i, '02.499372°N, 002.5°E') # 02.4994°N, 002.5°E' p = LatLon(0, 0) self.test('maxLat0', p.maxLat(0), '90.0') self.test('maxLat1', p.maxLat(1), '89.0') self.test('maxLat90', p.maxLat(90), '0.0') self.test('minLat0', p.minLat(0), '-90.0') self.test('minLat1', p.minLat(1), '-89.0') self.test('minLat90', p.minLat(90), '-0.0', known=True) self.test('parse', p.parse('0, 0'), p) # coverage if hasattr(LatLon, 'crossingParallels'): ps = p.crossingParallels(LatLon(60, 30), 30) t = ', '.join(map(lonDMS, ps)) self.test('crossingParallels', t, '009°35′38.65″E, 170°24′21.35″E') if hasattr(LatLon, 'intersections2'): n = 'intersections2 (%s)' % (LatLon.__module__, ) def _100p2(t, r, *s): e = max(abs(a.distanceTo(b) - r) for a in s for b in t) / r return e, '%g (%% of radius)' % (e, ) # percentages # <https://GIS.StackExchange.com/questions/48937/calculating-intersection-of-two-circles> p = LatLon(37.673442, -90.234036) # (-0.00323306, -0.7915, 0.61116) q = LatLon(36.109997, -90.953669) # (-0.0134464, -0.807775, 0.589337) t = p.intersections2(0.0312705, q, 0.0421788, radius=None, height=0) # radii in radians self.test(n, latlonDMS(t, form=F_D, sep=', '), '36.98931°N, 088.151425°W, 38.23838°N, 092.390487°W') t = LatLon(30, 0).intersections2(PI_4, LatLon(-30, 0), PI_4, radius=None) # radii in radians s = latlonDMS(t, form=F_D, sep=', ') self.test(n, s, '00.0°N, 035.26439°W, 00.0°N, 035.26439°E', known='S, ' in s) t = LatLon(0, 40).intersections2(PI_4, LatLon(0, -40), PI_4, radius=None) # radii in radians s = latlonDMS(t, form=F_D, sep=', ') self.test(n, s, '22.622036°N, 000.0°E, 22.622036°S, 000.0°E', known='W' in s) t = LatLon(30, 20).intersections2(PI_4, LatLon(-30, -20), PI_4, radius=None) # radii in radians s = latlonDMS(t, form=F_D, sep=', ') self.test(n, s, '14.612841°N, 026.110934°W, 14.612841°S, 026.110934°E') t = LatLon(0, 0).intersections2(PI_4, LatLon(0, 22.5), PI_4 / 2, radius=None) # abutting s = latlonDMS(t, form=F_D, sep=', ') self.test(n, s, '00.000001°S, 045.0°E, 00.000001°N, 045.0°E', known=True) # N-S # centers at 2 opposite corners of a "square" and # radius equal to length of square side, expecting # the other 2 as the intersections ... but the # longitudes are farther and farther out for d in range(5, 66, 5): p = LatLon(d, -d) q = LatLon(-d, d) r = radians(2 * d) * R_M t = p.intersections2(r, q, r, radius=R_M) if t[0] is t[1]: s = latlonDMS(t[:1], form=F_D, sep=', ') + ' abutting' else: s = latlonDMS(t, form=F_D, sep=', ') d = '%s %d' % (n, d) self.test(d, s, s) _, s = _100p2(t, r, q, p) self.test(d, s, s) d_m = 5e-5 # 50 micrometer # courtesy Samuel Čavoj <https://GitHub.com/mrJean1/PyGeodesy/issues/41>} R = RandomLatLon(LatLon, 178, 178) # +/- 89 r = R() s = latlonDMS(r, form=F_D) + ' Random +/- 89' self.test(n, s, s) for _ in range(12): p, q = R(), R() try: # see .testEllipsoidal i1, i2 = p.intersections2(r.distanceTo(p), q, r.distanceTo(q), radius=R_M) d, d2 = r.distanceTo(i1), r.distanceTo(i2) if d2 < d: d, i1, i2 = d2, i2, i1 s = '%s d %g meter' % (latlonDMS( (i1, i2), form=F_D, sep=', '), d) self.test(n, s, s) if d > d_m: raise IntersectionError(d=d, fmt_name_value='%s (%g)', txt='over') except IntersectionError as x: self.test(n, str(x), 'd < %g m' % (d_m), known=True) # too distant, near concetric, etc. if hasattr(LatLon, 'isenclosedBy'): p = LatLon(45.1, 1.1) b = LatLon(45, 1), LatLon(45, 2), LatLon(46, 2), LatLon(46, 1) for _ in self.testiter(): self.test('isenclosedBy', p.isenclosedBy(b), True) b = LatLon(45, 1), LatLon(45, 3), LatLon(46, 2), LatLon(47, 3), LatLon(47, 1) for _ in self.testiter(): try: self.test('isenclosedBy', p.isenclosedBy(b), True) # Nvector except ValueError as x: t = str(x).replace(',)', ')') self.test( 'isenclosedBy', t, 'points[3] (%s(47°00′00.0″N, 003°00′00.0″E)): not convex' % (classname(p), )) p = LatLon(51.127, 1.338) q = LatLon(50.964, 1.853) b = p.rhumbBearingTo(q) self.test('rhumbBearingTo', b, 116.722, fmt='%.3f') # 116.7 d = p.rhumbDestination(40300, 116.7) self.test('rhumbDestination', d, '50.964155°N, 001.853°E') # 50.9642°N, 001.8530°E self.test('rhumbDestination', isinstance(d, LatLon), True) d = p.rhumbDistanceTo(q) self.test('rhumbDistanceTo', d, 40307.8, fmt='%.1f') # XXX 40310 ? m = p.rhumbMidpointTo(q) self.test('rhumbMidpointo', m, '51.0455°N, 001.595727°E') self.test('rhumbMidpointo', isinstance(m, LatLon), True) b = LatLon(45, 1), LatLon(45, 2), LatLon(46, 2), LatLon(46, 1) self.test('areaOf', module.areaOf(b), '8.66605875e+09', fmt='%.8e') # 8666058750.718977 self.test('perimeterOf', module.perimeterOf(b, closed=True), '3.78258541e+05', fmt='%.8e') self.test('perimeterOf', module.perimeterOf(b, closed=False), '2.67063461e+05', fmt='%.8e') c = LatLon(0, 0), LatLon(1, 0), LatLon(0, 1) self.test('areaOf', module.areaOf(c), '6.18e+09', fmt='%.2e') self.test('perimeterOf', module.perimeterOf(c, closed=True), '3.79639757e+05', fmt='%.8e') self.test('perimeterOf', module.perimeterOf(c, closed=False), '2.68444678e+05', fmt='%.8e') if hasattr(module, 'nearestOn2'): c, d = module.nearestOn2(p, b) self.test( 'nearestOn2', c, '46.000996°N, 001.353049°E' if Vct else '46.0°N, 001.369324°E') self.test('nearestOn2', d, '569987.49' if Vct else '570101.83', fmt='%.2f') d = p.distanceTo(c) self.test('distanceTo', d, '569987.49' if Vct else '570101.82', fmt='%.2f') p = LatLon(47, 3) c, d = module.nearestOn2(p, b) self.test('nearestOn2', c, '46.0°N, 002.0°E' if Vct else '46.0°N, 002.0°E') self.test('nearestOn2', d, '134989.80' if Vct else '134992.48', fmt='%.2f') d = p.distanceTo(c) self.test('distanceTo', d, '134989.80' if Vct else '134989.80', fmt='%.2f') p = LatLon(45, 2) b = LatLon(45, 1), LatLon(47, 3) if Vct: c, d = module.nearestOn2(p, b) self.test('nearestOn2', c, '45.330691°N, 001.318551°E') self.test('distance', d, '64856.28', fmt='%.2f') else: c, d, a = p.nearestOn3(b, adjust=False) self.test('nearestOn3', c, '45.5°N, 001.5°E') self.test('distance', d, '78626.79', fmt='%.2f') self.test('angle', a, '315.00', fmt='%.2f') a = p.compassAngleTo(c, adjust=False) self.test('compassAngleTo', a, '315.00', fmt='%.2f') c, d, a = p.nearestOn3(b, adjust=True) self.test('nearestOn3', c, '45.331319°N, 001.331319°E') self.test('distance', d, '64074.48', fmt='%.2f') self.test('angle', a, '305.10', fmt='%.2f') d = p.distanceTo(c) self.test('distanceTo', d, '64856.28' if Vct else '64074.12', fmt='%.2f') a = p.compassAngleTo(c) # adjust=True self.test('compassAngleTo', a, '304.54' if Vct else '305.10', fmt='%.2f') # TrigTrue vs Nvector closests p = LatLon(45.330691, 001.318551) d = p.distanceTo(LatLon(45.331319, 001.331319)) self.test('difference', d, '1000.53', fmt='%.2f') # PYCHOK test attr? if Sph: # check nearestOn2/3 with closest on the segment b = LatLon(0, 1), LatLon(2, 3), LatLon(4, 5), LatLon(6, 7), LatLon(8, 9) for i in range(8): p = LatLon(i + 2, i) c, d, a = p.nearestOn3(b, adjust=False) t = LatLon(p.lat - 1.5, p.lon + 1.5).toStr(F_D, prec=6) self.test('nearestOn3', c.toStr(F_D, prec=6), t) self.test('distance', d, '235880.385', fmt='%.3f') self.test('angle', a, '135.00', fmt='%.2f') n = module.meanOf(b) # coverage self.test('meanOf', n.toStr(F_D, prec=6), '04.004858°N, 004.990226°E') n = module.nearestOn3(p, b, LatLon=LatLon, adjust=False)[0] # coverage self.test('nearestOn3', n, '07.5°N, 008.5°E') c = p.toCartesian() # coverage self.test('toCartesian', c, '[6245667.211, 766871.506, 996645.349]') if hasattr(module, 'ispolar'): p = LatLon(85, 90), LatLon(85, 0), LatLon(85, -90), LatLon(85, -180) for _ in self.testiter(): self.test('ispolar', module.ispolar(p), 'True') # PYCHOK test attr? p = LatLon(85, 90), LatLon(85, 0), LatLon(85, -180) for _ in self.testiter(): self.test('ispolar', module.ispolar(p), 'True', known=True) # PYCHOK test attr? p = [LatLon(*ll) for ll in Antarctica] # PYCHOK test attr? for _ in self.testiter(): self.test('ispolar', module.ispolar(p), 'True', known=Vct) # PYCHOK test attr? if hasattr(LatLon, 'nearestOn'): # <https://GitHub.com/mrJean1/PyGeodesy/issues/25> a = LatLon(1, 1, height=100) b = LatLon(2, 2, height=200) t = LatLon(1, 2).nearestOn(a, b).toStr(form=F_D, prec=1) self.test('nearestOn', t, '01.5°N, 001.5°E, +149.99m') # PYCHOK test attr? t = LatLon(1, 2).nearestOn2([a, b])[0].toStr(form=F_D, prec=1) self.test('nearestOn2', t, '01.5°N, 001.5°E, +149.99m') # PYCHOK test attr? t = a.midpointTo(b).toStr(form=F_D, prec=1) self.test('midpointTo', t, '01.5°N, 001.5°E, +150.00m') # PYCHOK test attr?
def testLatLon(self, module, Sph=False, Nv=True): # MCCABE 45 self.subtitle(module, 'LatLon') LatLon = module.LatLon # basic LatLon class tests p = LatLon(52.20472, 0.14056) self.test('isEllipsoidal', p.isEllipsoidal, not Sph) self.test('isSpherical', p.isSpherical, Sph) self.test('lat/lonDMS', p, '52.20472°N, 000.14056°E') # 52.20472°N, 000.14056°E self.test('lat/lonDMS F_DM', p.toStr(F_DM, 3), '''52°12.283'N, 000°08.434'E''') self.test('lat/lonDMS F_DM', p.toStr(F_DM, 4), '''52°12.2832'N, 000°08.4336'E''') self.test('lat/lonDMS F_DMS', p.toStr(F_DMS, 0), '''52°12'17"N, 000°08'26"E''') self.test('lat/lonDMS F_DMS', p.toStr(F_DMS, 1), '''52°12'17.0"N, 000°08'26.0"E''') self.test('lat/lonDMS F_RAD', p.toStr(F_RAD, 6), '0.911144N, 0.002453E') q = LatLon(*map(degrees, p.to2ab())) self.test('isequalTo', q.isequalTo(p), True) self.test('latlon2', fStr(q.latlon2(5)), '52.20472, 0.14056') self.test('latlon2', fStr(q.latlon2(4)), '52.2047, 0.1406') self.test('latlon2', fStr(q.latlon2(3)), '52.205, 0.141') self.test('latlon2', fStr(q.latlon2(2)), '52.2, 0.14') self.test('latlon2', fStr(q.latlon2(1)), '52.2, 0.1') self.test('latlon2', fStr(q.latlon2()), '52.0, 0.0') FRA = LatLon(50.0379, 8.5622) LHR = LatLon(51.47, 0.4543) # <http://www.EdWilliams.org/avform.htm#XTE> JFK = LatLon(degrees(0.709186), -degrees(1.287762)) LAX = LatLon(33.+57./60, -(118.+24./60)) Rav = m2NM(6366710) # avg. earth radius in NM # <http://GeographicLib.SourceForge.io/html/python/examples.html> WNZ = LatLon(-41.32, 174.81) # Wellington, NZ SAL = LatLon(40.96, 5.50) # Salamanca, Spain BJS = LatLon(40.1, 116.6) # Beijing Airport SFO = LatLon(37.6, -122.4) # San Francisco p = LatLon(52.205, 0.119) q = LatLon(48.857, 2.351) self.test('isequalTo', p.isequalTo(q), False) a = p.antipode() self.test('antipode1', a, '52.205°S, 179.881°W') self.test('antipode2', a.isantipodeTo(p), True) b = a.antipode() self.test('antipode3', b, '52.205°N, 000.119°E') self.test('antipode4', a.isantipodeTo(b), True) self.test('antipode5', b, p) if hasattr(LatLon, 'initialBearingTo'): b = p.initialBearingTo(q) self.test('initialBearingTo', b, 156.1666 if Sph else 156.1106, fmt='%.4f') # 156.2 b = p.finalBearingTo(q) self.test('finalBearingTo', b, 157.8904 if Sph else 157.8345, fmt='%.4f') b = LAX.initialBearingTo(JFK) self.test('initialBearingTo', b, 65.8921 if Sph else 65.9335, fmt='%.4f') # PYCHOK test attr? b = LAX.finalBearingTo(JFK) self.test('finalBearingTo', b, 93.8581 if Sph else 93.9034, fmt='%.4f') # PYCHOK test attr? if hasattr(LatLon, 'bearingTo2'): b = p.bearingTo2(q) self.test('bearingTo2', fStr(b, prec=4), '156.1666, 157.8904' if Sph else '156.1106, 157.8345') # 156.2 # <http://blog.Element84.com/determining-if-a-spherical-polygon-contains-a-pole.html> b = LatLon(85, -135), LatLon(85, -45), LatLon(85, 45), LatLon(85, 135), LatLon(85, -135) self.test('ispolar', ispolar(b), True) # PYCHOK test attr? c = p.copy() self.test('copy', p.isequalTo(c), 'True') d = p.equirectangularTo(q) self.test('equirectangularTo', d, '404329.56', fmt='%.2f') if hasattr(LatLon, 'distanceTo'): d = p.distanceTo(q) self.test('distanceTo', d, '404279.720589' if Sph else '404607.805988', fmt='%.6f') # 404300 d = q.distanceTo(p) self.test('distanceTo', d, '404279.720589' if Sph else '404607.805988', fmt='%.6f') # 404300 d = LAX.distanceTo(JFK, radius=R_NM) if Sph else LAX.distanceTo(JFK) self.test('distanceTo', d, 2145 if Sph else 3981601, fmt='%.0f') # PYCHOK test attr? if not Nv: # <http://GeographicLib.SourceForge.io/html/python/examples.html> self.test('antipodal', WNZ.isantipodeTo(SAL, eps=0.1), False) d = WNZ.distanceTo(SAL, wrap=False) self.test('distanceTo dateline', d, 19119590.551 if Sph else 19959679.267, fmt='%.3f', known=True) # PYCHOK test attr? d = WNZ.distanceTo(SAL, wrap=True) self.test('distanceTo unrolled', d, 19119590.551 if Sph else 19959679.267, fmt='%.3f', known=True) # PYCHOK test attr? self.test('antipodal', BJS.isantipodeTo(SFO, eps=0.1), False) d = BJS.distanceTo(SFO, wrap=False) self.test('distanceTo dateline', d, 9491735 if Sph else 9513998, fmt='%.0f') # PYCHOK test attr? d = BJS.distanceTo(SFO, wrap=True) self.test('distanceTo unrolled', d, 9491735 if Sph else 9513998, fmt='%.0f') # PYCHOK test attr? if hasattr(LatLon, 'distanceTo3') and not Sph: for w in (False, True): d = WNZ.distanceTo3(SAL, wrap=w) # XXX expected values? self.test('distanceTo3 dateline', fStr(d, prec=4), '19125097.7012, 270.7159, 276.0288', known=True) # PYCHOK test attr? d = BJS.distanceTo3(SFO, wrap=w) self.test('distanceTo3 dateline', fStr(d, prec=4), '9513997.9901, 42.9164, 138.8903') # PYCHOK test attr? if hasattr(LatLon, 'intermediateTo'): i = p.intermediateTo(q, 0.25) self.test('intermediateTo', i, '51.372084°N, 000.707337°E' if Sph else '51.372294°N, 000.707192°E') self.test('intermediateTo', isinstance(i, LatLon), True) if hasattr(p, 'distanceTo'): d = p.distanceTo(q) self.test('intermediateTo', d, '404279.721', fmt='%.3f') # PYCHOK test attr? i = p.intermediateTo(q, 5) self.test('intermediateTo+5', i, '35.160975°N, 008.989542°E' if Sph else '35.560239°N, 008.833512°E') if hasattr(p, 'distanceTo'): self.test('intermediateTo+5', p.distanceTo(i) / d, '5.000', fmt='%.3f') # PYCHOK test attr? i = p.intermediateTo(q, -4) self.test('intermediateTo-4', i, '64.911647°N, 013.726301°W' if Sph else '64.570387°N, 013.156352°W') if hasattr(p, 'distanceTo'): self.test('intermediateTo-4', p.distanceTo(i) / d, '4.000', fmt='%.3f') # PYCHOK test attr? # courtesy of <http://GitHub.com/bakakaldsas> i = LatLon(52, 0, 100).intermediateTo(LatLon(48, 2, 200), 0.25) self.test('intermediateTo-h', i.height, '125.000', fmt='%.3f') # PYCHOK test attr? if hasattr(LatLon, 'intermediateChordTo'): i = p.intermediateChordTo(q, 0.25) self.test('intermediateChordTo', i, '51.372294°N, 000.707192°E') self.test('intermediateChordTo', isinstance(i, LatLon), True) # PYCHOK test attr? # courtesy of <http://GitHub.com/bakakaldsas> i = LatLon(52, 0, 100).intermediateChordTo(LatLon(48, 2, 200), 0.25) self.test('intermediateChordTo-h', i.height, '125.000', fmt='%.3f') # PYCHOK test attr? if hasattr(LatLon, 'midpointTo'): m = p.midpointTo(q) self.test('midpointTo', m, '50.536327°N, 001.274614°E') # PYCHOK test attr? # 50.5363°N, 001.2746°E if hasattr(LatLon, 'destination'): p = LatLon(51.4778, -0.0015) d = p.destination(7794, 300.7) self.test('destination', d, '51.513546°N, 000.098345°W' if Sph else '51.513526°N, 000.098038°W') # 51.5135°N, 0.0983°W ??? self.test('destination', d.toStr(F_DMS, 0), '51°30′49″N, 000°05′54″W' if Sph else '51°30′49″N, 000°05′53″W') # <http://www.EdWilliams.org/avform.htm#LL> d = LAX.destination(100, 66, radius=R_NM) if Sph else LAX.destination(100, 66) self.test('destination', d.toStr(F_DM, prec=0), "34°37′N, 116°33′W" if Sph else "33°57′N, 118°24′W") self.test('destination', d, '34.613647°N, 116.55116°W' if Sph else '33.950367°N, 118.399012°W') self.test('destination', d.toStr(F_RAD, prec=6), '0.604122N, 2.034201W' if Sph else '0.592546N, 2.066453W') # PYCHOK expected # <http://GeographicLib.SourceForge.io/html/python/examples.html> d = LatLon(-32.06, -115.74).destination(20e6, 225).toStr(F_D, prec=8) self.test('destination', d, '31.96383509°N, 064.37329146°E' if Sph else '32.11195529°N, 063.95925278°E', known=True) # PYCHOK test attr? if hasattr(LatLon, 'alongTrackDistanceTo'): s = LatLon(53.3206, -1.7297) e = LatLon(53.1887, 0.1334) p = LatLon(53.2611, -0.7972) try: d = p.alongTrackDistanceTo(s, 96) self.test('alongTrackDistanceTo', d, 62331.59, fmt='%.2f') # 62331 except TypeError as x: self.test('alongTrackDistanceTo', x, 'type(end) mismatch: int vs ' + classname(p)) # PYCHOK test attr? d = p.alongTrackDistanceTo(s, e) self.test('alongTrackDistanceTo', d, 62331.58, fmt='%.2f') # <http://www.EdWilliams.org/avform.htm#XTE> p = LatLon(34.5, -116.5) # 34:30N, 116:30W d = p.alongTrackDistanceTo(LAX, JFK, radius=Rav) self.test('alongTrackDistanceTo', d, 99.588, fmt='%.3f') # NM # courtesy of Rimvydas Naktinis p = LatLon(53.36366, -1.83883) d = p.alongTrackDistanceTo(s, e) self.test('alongTrackDistanceTo', d, -7702.7, fmt='%.1f') p = LatLon(53.35423, -1.60881) d = p.alongTrackDistanceTo(s, e) self.test('alongTrackDistanceTo', d, 7587.6, fmt='%.1f') # PYCHOK test attr? if hasattr(LatLon, 'crossTrackDistanceTo'): s = LatLon(53.3206, -1.7297) e = LatLon(53.1887, 0.1334) p = LatLon(53.2611, -0.7972) try: d = p.crossTrackDistanceTo(s, 96) self.test('crossTrackDistanceTo', d, -305.67, fmt='%.2f') # -305.7 except TypeError as x: self.test('crossTrackDistanceTo', x, 'type(end) mismatch: int vs ' + classname(p)) # PYCHOK test attr? d = p.crossTrackDistanceTo(s, e) self.test('crossTrackDistanceTo', d, -307.55, fmt='%.2f') # -307.5 # <http://www.EdWilliams.org/avform.htm#XTE> p = LatLon(34.5, -116.5) # 34:30N, 116:30W d = p.crossTrackDistanceTo(LAX, JFK, radius=Rav) self.test('crossTrackDistanceTo', d, 7.4524, fmt='%.4f') # PYCHOK test attr? # XXX 7.4512 NM if hasattr(LatLon, 'greatCircle'): p = LatLon(53.3206, -1.7297) gc = p.greatCircle(96.0) self.test('greatCircle', gc, '(-0.79408, 0.12856, 0.59406)') # PYCHOK test attr? if hasattr(LatLon, 'greatCircleTo'): p = LatLon(53.3206, -1.7297) q = LatLon(53.1887, 0.1334) gc = p.greatCircleTo(q) self.test('greatCircleTo', gc, '(-0.79408, 0.12859, 0.59406)') # PYCHOK test attr? if isclockwise: f = LatLon(45,1), LatLon(45,2), LatLon(46,2), LatLon(46,1) for _ in self.testiter(): self.test('isclockwise', isclockwise(f), False) # PYCHOK test attr? t = LatLon(45,1), LatLon(46,1), LatLon(46,2), LatLon(45,1) for _ in self.testiter(): self.test('isclockwise', isclockwise(t), True) # PYCHOK test attr? for _ in self.testiter(): try: self.test('isclockwise', isclockwise(t[:2]), ValueError) except ValueError as x: self.test('isclockwise', x, 'too few points: 2') # PYCHOK test attr? # <http://blog.Element84.com/determining-if-a-spherical-polygon-contains-a-pole.html> p = LatLon(85, -135), LatLon(85, -45), LatLon(85, 45), LatLon(85, 135), LatLon(85, -135) for _ in self.testiter(): try: self.test('isclockwise', isclockwise(p), ValueError) # PYCHOK test attr? except ValueError as x: # polar or zero area: LatLon2psxy((LatLon(85°00′00.0″N, 135°00′00.0″W), ...)[4], ... self.test('isclockwise', str(x).split(':')[0], 'polar or zero area') # PYCHOK test attr? if isconvex: f = LatLon(45,1), LatLon(46,2), LatLon(45,2), LatLon(46,1) for _ in self.testiter(): self.test('isconvex', isconvex(f), False) # PYCHOK test attr? t = LatLon(45,1), LatLon(46,1), LatLon(46,2), LatLon(45,1) for _ in self.testiter(): self.test('isconvex', isconvex(t), True) # PYCHOK test attr? for _ in self.testiter(): try: self.test('isconvex', isconvex(t[:2]), ValueError) except ValueError as x: self.test('isconvex', x, 'too few points: 2') # PYCHOK test attr? if isenclosedBy: b = LatLon(45, 1), LatLon(45, 2), LatLon(46, 2), LatLon(46, 1) for _ in self.testiter(): self.test('isenclosedBy1', isenclosedBy(LatLon(45.5, 1.5), b), True) # PYCHOK test attr? for _ in self.testiter(): # on polygon point is outside self.test('isenclosedBy2', isenclosedBy((46, 2), b), False) # PYCHOK test attr? for _ in self.testiter(): # on polygon point is outside self.test('isenclosedBy3', isenclosedBy((46, 1), b), False) # PYCHOK test attr? for _ in self.testiter(): # on polygon edge is outside self.test('isenclosedBy4', isenclosedBy((46, 1.5), b), False) # PYCHOK test attr? for _ in self.testiter(): # on polygon is False self.test('isenclosedBy5', isenclosedBy((45.5, 1), b), False) # PYCHOK test attr? p = LatLon(85, 90), LatLon(85, 0), LatLon(85, -90), LatLon(85, -180) for _ in self.testiter(): self.test('isenclosedBy6', isenclosedBy((90, 0), p), 'True') # PYCHOK test attr? p = LatLon(85, 90), LatLon(85, 0), LatLon(85, -90) for _ in self.testiter(): self.test('isenclosedBy7', isenclosedBy((90, 0), p), 'True') # PYCHOK test attr? if hasattr(LatLon, 'initialBearingTo'): b = LHR.initialBearingTo(FRA) self.test('initialBearingTo', b, 102.432182 if Sph else 102.392291, fmt='%.6f') # PYCHOK test attr? a = LHR.compassAngleTo(FRA, adjust=False) self.test('compassAngleTo', a, 100.017, fmt='%.3f') a = LHR.compassAngleTo(FRA) # adjust=True self.test('compassAngleTo', a, 105.599, fmt='%.3f') if hasattr(LatLon, 'initialBearingTo'): b = FRA.initialBearingTo(LHR) self.test('initialBearingTo', b, 288.715918 if Sph else 288.676039, fmt='%.6f') # PYCHOK test attr? a = FRA.compassAngleTo(LHR, adjust=False) self.test('compassAngleTo', a, 280.017, fmt='%.3f') a = FRA.compassAngleTo(LHR) # adjust=True self.test('compassAngleTo', a, 285.599, fmt='%.3f') d = LHR.equirectangularTo(FRA) self.test('equirectangularTo', m2km(d), 592.185, fmt='%.3f') if hasattr(LatLon, 'distanceTo'): d = LHR.distanceTo(FRA) self.test('distanceTo', m2km(d), 591.831 if Sph else 593.571, fmt='%.3f') # PYCHOK test attr? p = LatLon(0, 0) for a, b, d in ((1, 0, 0.0), ( 1, 1, 45.0), ( 0, 1, 90.0), (-1, 0, 180.0), (-1, -1, 225.0), (1, -1, 315.0), ( 0, -1, 270.0), (90, -1, 359.4)): q = LatLon(p.lat + a, p.lon + b) if not Nv: b = p.initialBearingTo(q) self.test('bearingTo', b, d, fmt='%.1f', known=True) c = p.compassAngleTo(q, adjust=False) self.test('compassAngleTo', c, d, fmt='%.1f') p = LatLon(52, 0) q = LatLon(p.lat + 1, p.lon + 1) # 45 unadjusted if not Nv: b = p.initialBearingTo(q) self.test('bearingTo', b, 31.0, fmt='%.0f') c = p.compassAngleTo(q, adjust=True) self.test('compassAngleTo', c, 31.0, fmt='%.0f') c = p.compassAngleTo(q, adjust=False) self.test('compassAngleTo', c, 45.0, fmt='%.0f')
def testSpherical(self, module, Sph=True): # MCCABE 13 self.subtitle(module, 'Spherical') LatLon, Vct = module.LatLon, not Sph p = LatLon(51.8853, 0.2545) self.test('isSpherical', p.isSpherical, True) self.test('isEllipsoidal', p.isEllipsoidal, False) q = LatLon(49.0034, 2.5735) self.test('isSpherical', q.isSpherical, True) self.test('isEllipsoidal', q.isEllipsoidal, False) i = p.intersection(108.55, q, 32.44) self.test('intersection1', i.toStr(F_D), '50.907608°N, 004.508575°E') # 50.9076°N, 004.5086°E # Trig self.test('intersection1', i.toStr(F_DMS), '50°54′27.39″N, 004°30′30.87″E') self.test('intersection1', isinstance(i, LatLon), True) REO = LatLon(42.600, -117.866) BKE = LatLon(44.840, -117.806) i = REO.intersection(51, BKE, 137) self.test('intersection2', isinstance(i, LatLon), True) self.test('intersection2', i.toStr(F_D), '43.5719°N, 116.188757°W') # 43.572°N, 116.189°W self.test('intersection2', i.toStr(F_DMS), '43°34′18.84″N, 116°11′19.53″W') # <http://GitHub.com/ChrisVeness/geodesy/issues/46> p = LatLon(51.8853, 0.2545) q = LatLon(51.8763, 0.2545) # identical lon i = p.intersection(110.8878, q, 54.4525) self.test('intersection3', i, '51.882166°N, 000.267801°E') # 51°52′55.8″N, 000°16′04.08″E? p = LatLon(+30, 0) q = LatLon(-30, 0) # indential, zero lon i = p.intersection(135, q, 45) self.test('intersection4', i, '00.0°N, 026.565051°E', known=isWindows) p = LatLon(0, -30) q = LatLon(0, +30) # identical, zero lat i = p.intersection(45, q, 315) self.test('intersection5', i, '26.565051°N, 000.0°W', known=isWindows) # <http://GitHub.com/ChrisVeness/geodesy/blob/master/test/latlon-vectors-tests.js> STN = LatLon(51.8853, 0.2545) CDG = LatLon(49.0034, 2.5735) i = STN.intersection(108.547, CDG, 32.435) self.test('intersection6', i, '50.907809°N, 004.50841°E') # 50.9078°N, 004.5084°E # <http://GitHub.com/ChrisVeness/geodesy/blob/master/test/latlon-vectors-tests.js> # <http://GitHub.com/ChrisVeness/geodesy/blob/master/test/latlon-spherical-tests.js> N, E, S, W, p, q = 0, 90, 180, 270, LatLon(0, 1), LatLon(1, 0) self.test('toward 1,1 N,E nearest', p.intersection(N, q, E), '00.999848°N, 001.0°E') self.test('toward 1,1 E,N nearest', q.intersection(E, p, N), '00.999848°N, 001.0°E') self.test('toward 1,1 N,E antipodal', LatLon(2, 1).intersection(N, q, E), '00.999848°S, 179.0°W') self.test('toward/away 1,1 N,W antipodal', p.intersection(N, q, W), '00.999848°S, 179.0°W', known=Sph) self.test('toward/away 1,1 W,N antipodal', q.intersection(W, p, N), '00.999848°S, 179.0°W') self.test('toward/away 1,1 S,E antipodal', p.intersection(S, q, E), '00.999848°S, 179.0°W') self.test('toward/away 1,1 E,S antipodal', q.intersection(E, p, S), '00.999848°S, 179.0°W', known=Sph) self.test('away 1,1 S,W antipodal', p.intersection(S, q, W), '00.999848°S, 179.0°W') self.test('away 1,1 W,S antipodal', q.intersection(W, p, S), '00.999848°S, 179.0°W') self.test('1E/90E N,E antipodal', p.intersection(N, LatLon(1, 90), E), '00.017454°S, 179.0°W', known=Sph) self.test('1E/90E N,E nearest', p.intersection(N, LatLon(1, 92), E), '00.017454°N, 179.0°W') # <http://GitHub.com/ChrisVeness/geodesy/blob/master/test/latlon-vectors-tests.js> p, r = LatLon(1, 3), LatLon(2, 2) self.test('brng+end 1a', q.intersection(p, r, S), '01.000305°N, 002.0°E') self.test('brng+end 1b', r.intersection(S, q, p), '01.000305°N, 002.0°E') self.test('brng+end 2a', q.intersection(p, r, N), '01.000305°S, 178.0°W') self.test('brng+end 2b', r.intersection(N, q, p), '01.000305°S, 178.0°W') i = LatLon(1, 1).intersection(LatLon(2, 2), LatLon(1, 4), LatLon(2, 3)) self.test('intersection7', i, '02.499372°N, 002.5°E') # 02.4994°N, 002.5°E' p = LatLon(0, 0) self.test('maxLat0', p.maxLat( 0), '90.0') self.test('maxLat1', p.maxLat( 1), '89.0') self.test('maxLat90', p.maxLat(90), '0.0') if hasattr(LatLon, 'crossingParallels'): ps = p.crossingParallels(LatLon(60, 30), 30) t = ', '.join(map(lonDMS, ps)) self.test('crossingParallels', t, '009°35′38.65″E, 170°24′21.35″E') if hasattr(LatLon, 'isenclosedBy'): p = LatLon(45.1, 1.1) b = LatLon(45, 1), LatLon(45, 2), LatLon(46, 2), LatLon(46, 1) for _ in self.testiter(): self.test('isenclosedBy', p.isenclosedBy(b), True) b = LatLon(45, 1), LatLon(45, 3), LatLon(46, 2), LatLon(47, 3), LatLon(47, 1) for _ in self.testiter(): try: self.test('isenclosedBy', p.isenclosedBy(b), True) # Nvector except ValueError as x: t = ' '.join(str(x).split()[:3] + ['...)']) self.test('isenclosedBy', t, 'non-convex: (%s(45°00′00.0″N, 001°00′00.0″E), ...)' % (classname(p),)) p = LatLon(51.127, 1.338) q = LatLon(50.964, 1.853) b = p.rhumbBearingTo(q) self.test('rhumbBearingTo', b, 116.722, fmt='%.3f') # 116.7 d = p.rhumbDestination(40300, 116.7) self.test('rhumbDestination', d, '50.964155°N, 001.853°E') # 50.9642°N, 001.8530°E self.test('rhumbDestination', isinstance(d, LatLon), True) d = p.rhumbDistanceTo(q) self.test('rhumbDistanceTo', d, 40307.8, fmt='%.1f') # XXX 40310 ? m = p.rhumbMidpointTo(q) self.test('rhumbMidpointo', m, '51.0455°N, 001.595727°E') self.test('rhumbMidpointo', isinstance(m, LatLon), True) b = LatLon(45, 1), LatLon(45, 2), LatLon(46, 2), LatLon(46, 1) self.test('areaOf', module.areaOf(b), '8.6660587507e+09', fmt='%.10e') # 8666058750.718977 c = LatLon(0, 0), LatLon(1, 0), LatLon(0, 1) self.test('areaOf', module.areaOf(c), '6.18e+09', fmt='%.2e') if hasattr(module, 'nearestOn2'): c, d = module.nearestOn2(p, b) self.test('nearestOn2', c, '46.000996°N, 001.353049°E' if Vct else '46.0°N, 001.369324°E') self.test('nearestOn2', d, '569987.49' if Vct else '570101.83', fmt='%.2f') d = p.distanceTo(c) self.test('distanceTo', d, '569987.49' if Vct else '570101.82', fmt='%.2f') p = LatLon(47, 3) c, d = module.nearestOn2(p, b) self.test('nearestOn2', c, '46.0°N, 002.0°E' if Vct else '46.0°N, 002.0°E') self.test('nearestOn2', d, '134989.80' if Vct else '134992.48', fmt='%.2f') d = p.distanceTo(c) self.test('distanceTo', d, '134989.80' if Vct else '134989.80', fmt='%.2f') p = LatLon(45, 2) b = LatLon(45, 1), LatLon(47, 3) if Vct: c, d = module.nearestOn2(p, b) self.test('nearestOn2', c, '45.330691°N, 001.318551°E') self.test('distance', d, '64856.28', fmt='%.2f') else: c, d, a = p.nearestOn3(b, adjust=False) self.test('nearestOn3', c, '45.5°N, 001.5°E') self.test('distance', d, '78626.79', fmt='%.2f') self.test('angle', a, '315.00', fmt='%.2f') a = p.compassAngleTo(c, adjust=False) self.test('compassAngleTo', a, '315.00', fmt='%.2f') c, d, a = p.nearestOn3(b, adjust=True) self.test('nearestOn3', c, '45.331319°N, 001.331319°E') self.test('distance', d, '64074.48', fmt='%.2f') self.test('angle', a, '305.10', fmt='%.2f') d = p.distanceTo(c) self.test('distanceTo', d, '64856.28' if Vct else '64074.12', fmt='%.2f') a = p.compassAngleTo(c) # adjust=True self.test('compassAngleTo', a, '304.54' if Vct else '305.10', fmt='%.2f') # TrigTrue vs Nvector closests p = LatLon(45.330691, 001.318551) d = p.distanceTo(LatLon(45.331319, 001.331319)) self.test('difference', d, '1000.53', fmt='%.2f') # PYCHOK test attr? if Sph: # check nearestOn2/3 with closest on the segment b = LatLon(0, 1), LatLon(2, 3), LatLon(4, 5), LatLon(6, 7), LatLon(8, 9) for i in range(8): p = LatLon(i + 2, i) c, d, a = p.nearestOn3(b, adjust=False) q = LatLon(p.lat - 1.5, p.lon + 1.5) self.test('nearestOn3', c.toStr(F_D, prec=6), q.toStr(F_D, prec=6)) self.test('distance', d, '235880.385', fmt='%.3f') self.test('angle', a, '135.00', fmt='%.2f') if hasattr(module, 'ispolar'): p = LatLon(85, 90), LatLon(85, 0), LatLon(85, -90), LatLon(85, -180) for _ in self.testiter(): self.test('ispolar', module.ispolar(p), 'True') # PYCHOK test attr? p = LatLon(85, 90), LatLon(85, 0), LatLon(85, -180) for _ in self.testiter(): self.test('ispolar', module.ispolar(p), 'True', known=True) # PYCHOK test attr? p = [LatLon(*ll) for ll in Antarctica] # PYCHOK test attr? for _ in self.testiter(): self.test('ispolar', module.ispolar(p), 'True', known=Vct) # PYCHOK test attr?
def testGreatCircle(self, module): # spherical only self.subtitle(module, 'GreatCircle') LatLon = module.LatLon # Indian Pond, in Piermond, NH. My old Boy Scout Camp IndianPond = LatLon(43.930912, -72.053811) Eiffel = LatLon(48.858158, 2.294825) Versailles = LatLon(48.804766, 2.120339) StGermain = LatLon(48.897728, 2.094977) Orly = LatLon(48.747114, 2.400526) # distance between the Eiffel Tower and Versailles in meter dEiffelToVersailles = 14084.280704919687 xEiffelToVersailles = '%.6f' # '%.8f' # initial and final bearings between Eiffel tower and Versailles ibEiffelToVersailles = 245.13460296861962 fbEiffelToVersailles = 245.00325395138532 xbEiffelToVersailles = '%.8f' # '%.14f' # initial and final bearing between Versailles and Eiffel tower ibVersaillesToEiffel = 65.003253951385318 fbVersaillesToEiffel = 65.134602968619618 xbVersaillesToEiffel = '%.9f' # '%.15f' xMidpoint = '%.8f' c = crosserrors(False) # no CrossErrors! # initial bearing for two locations that are the same b = IndianPond.initialBearingTo(IndianPond) self.test('InitialBearingSameLocations', b, 0.0, prec=1) # initial bearing for two locations that are the equal b = IndianPond.initialBearingTo(IndianPond.copy()) self.test('InitialBearingEqualLocations', b, 0.0, prec=1) # final bearing for two locations that are the same b = IndianPond.finalBearingTo(IndianPond) self.test('FinalBearingSameLocations', b, 180.0, prec=1) # 0.0 # final bearing for two locations that are the equal b = IndianPond.finalBearingTo(IndianPond.copy()) self.test('FinalBearingEqualLocations', b, 180.0, prec=1) # 0.0 c = crosserrors(c) # with CrossErrors! try: # should raise CrossError b = str(IndianPond.initialBearingTo(IndianPond, raiser=True)) except CrossError as x: b = str(x) self.test( 'FinalBearingCrossError', b, 'points (%s(43°55′51.28″N, 072°03′13.72″W)): coincident' % (classname(IndianPond), )) # distance for two locations that are the same d = IndianPond.distanceTo(IndianPond) self.test('DistanceSameLocations', d, 0.0, prec=1) # distance for two locations that are equal d = IndianPond.distanceTo(IndianPond.copy()) self.test('DistanceEqualLocations', d, 0.0, prec=1) # distance between Eiffel Tower and Versailles d = Eiffel.distanceTo(Versailles) self.test('DistanceEiffelToVersailles', d, dEiffelToVersailles, fmt=xEiffelToVersailles, known=True) # distance between Versailles and Eiffel Tower d = Versailles.distanceTo(Eiffel) self.test('DistanceVersaillesToEiffel', d, dEiffelToVersailles, fmt=xEiffelToVersailles, known=True) # initial bearing between Eiffel Tower and Versailles b = Eiffel.initialBearingTo(Versailles) self.test('InitialBearingEiffelToVersailles', b, ibEiffelToVersailles, fmt=xbEiffelToVersailles) self.test('InitialBearingEiffelToVersailles(DMS)', bearingDMS(b, F_DMS, prec=4), '245°08′04.5707″') # initial bearing between Versailles and Eiffel Tower b = Versailles.initialBearingTo(Eiffel) self.test('InitialBearingVersaillesToEiffel', b, ibVersaillesToEiffel, fmt=xbVersaillesToEiffel) self.test('InitialBearingVersaillesToEiffel(DMS)', bearingDMS(b, F_DMS, prec=4), '65°00′11.7142″') # final bearing between Eiffel Tower and Versailles b = Eiffel.finalBearingTo(Versailles) self.test('FinalBearingEiffelToVersailles', b, fbEiffelToVersailles, fmt=xbEiffelToVersailles) self.test('FinalBearingEiffelToVersailles(DMS)', bearingDMS(b, F_DMS, prec=4), '245°00′11.7142″') # final bearing between Versailles and Eiffel Tower b = Versailles.finalBearingTo(Eiffel) self.test('FinalBearingVersaillesToEiffel', b, fbVersaillesToEiffel, fmt=xbVersaillesToEiffel) self.test('FinalBearingVersaillesToEiffel(DMS)', bearingDMS(b, F_DMS, prec=4), '65°08′04.5707″') # generating a location for Versailles based on bearing and distance v = Eiffel.destination(dEiffelToVersailles, ibEiffelToVersailles) self.test('GenerateLocationVersailles', v, str(Versailles)) # generating a location for Eiffel based on bearing and distance. e = Versailles.destination(dEiffelToVersailles, ibVersaillesToEiffel) self.test('GenerateLocationEiffel', e, str(Eiffel)) # midpoint between the Eiffel and Versailles a = Eiffel.midpointTo(Versailles) b = Eiffel.destination(dEiffelToVersailles / 2.0, ibEiffelToVersailles) self.test('MidpointEiffelToVersailles', a, str(b)) self.test('MidpointEiffelToVersailles(DMS)', a.toStr(F_DMS, prec=4), '48°49′53.3817″N, 002°12′27.1279″E') a = Eiffel.distanceTo(a) m = Versailles.distanceTo(b) self.test('MidpointEiffelToVersailles(m)', a, m, fmt=xMidpoint, known=True) # midpoint between Versailles and the Eiffel Tower a = Versailles.midpointTo(Eiffel) b = Versailles.destination(dEiffelToVersailles / 2.0, ibVersaillesToEiffel) self.test('MidpointVersaillesToEiffel', a, str(b), known=True) self.test('MidpointVersaillesToEiffel(DMS)', a.toStr(F_DMS, prec=4), '48°49′53.3817″N, 002°12′27.1279″E') a = Versailles.distanceTo(a) m = Eiffel.distanceTo(b) self.test('MidpointVersaillesToEiffel(m)', a, m, fmt=xMidpoint, known=True) # intersection. b = StGermain.initialBearingTo(Orly) i = StGermain.intersection(b, Eiffel, ibEiffelToVersailles) self.test( 'Intersection', i.toStr(F_D, prec=9), '48.83569095°N, 002.221252031°E') # '48.83569094988361°N, ... self.test('Intersection', i.toStr(F_D, prec=13), '48.8356909498836°N, 002.2212520313074°E' ) # 002.2212520313073583°E' # cross-track distance test of a point 90° and 200 meters away m = Eiffel.midpointTo(Versailles) b = Eiffel.initialBearingTo(Versailles) p = m.destination(200.0, (b + 90) % 360.0) d = p.crossTrackDistanceTo(Eiffel, Versailles) self.test('CrossTrackDistance200m+90°', d, 200.0, prec=1) # cross-track distance test of a point 270° and 200 meters away m = Eiffel.midpointTo(Versailles) b = Eiffel.initialBearingTo(Versailles) p = m.destination(200.0, (b + 270) % 360.0) d = p.crossTrackDistanceTo(Eiffel, Versailles) self.test('CrossTrackDistance200m+270°', d, -200.0, prec=1) # cross-track distance that should be very close to 0 m = Eiffel.midpointTo(Versailles) d = abs(m.crossTrackDistanceTo(Eiffel, Versailles)) self.test('CrossTrackDistanceCloseToZero', d, '0.0000000', fmt='%.7f')
def testSpherical(self, module, Vct=False): # MCCABE 13 self.subtitle(module, 'Spherical') LatLon = module.LatLon p = LatLon(51.8853, 0.2545) self.test('isSpherical', p.isSpherical, True) self.test('isEllipsoidal', p.isEllipsoidal, False) q = LatLon(49.0034, 2.5735) self.test('isSpherical', q.isSpherical, True) self.test('isEllipsoidal', q.isEllipsoidal, False) i = p.intersection(108.55, q, 32.44) self.test('intersection', i.toStr(F_D), '50.907608°N, 004.508575°E') # 50.9076°N, 004.5086°E # Trig self.test('intersection', i.toStr(F_DMS), '50°54′27.39″N, 004°30′30.87″E') self.test('intersection', isinstance(i, LatLon), True) REO = LatLon(42.600, -117.866) BKE = LatLon(44.840, -117.806) i = REO.intersection(51, BKE, 137) self.test('intersection', isinstance(i, LatLon), True) self.test('intersection', i.toStr(F_D), '43.5719°N, 116.188757°W') # 43.572°N, 116.189°W self.test('intersection', i.toStr(F_DMS), '43°34′18.84″N, 116°11′19.53″W') # <http://GitHub.com/ChrisVeness/geodesy/issues/46> p = LatLon(51.8853, 0.2545) q = LatLon(51.8763, 0.2545) # identical lon i = p.intersection(110.8878, q, 54.4525) self.test('intersection', i, '51.882166°N, 000.267801°E') # 51°52′55.8″N, 000°16′04.08″E? p = LatLon(+30, 0) q = LatLon(-30, 0) # indential, zero lon i = p.intersection(135, q, 45) self.test('intersection', i, '00.0°N, 026.565051°E', known=isWindows) p = LatLon(0, -30) q = LatLon(0, +30) # identical, zero lat i = p.intersection(45, q, 315) self.test('intersection', i, '26.565051°N, 000.0°W', known=isWindows) p = LatLon(0, 0) self.test('maxLat0', p.maxLat( 0), '90.0') self.test('maxLat1', p.maxLat( 1), '89.0') self.test('maxLat90', p.maxLat(90), '0.0') if hasattr(LatLon, 'crossingParallels'): ps = p.crossingParallels(LatLon(60, 30), 30) t = ', '.join(map(lonDMS, ps)) self.test('crossingParallels', t, '009°35′38.65″E, 170°24′21.35″E') if hasattr(LatLon, 'isenclosedBy'): p = LatLon(45.1, 1.1) b = LatLon(45, 1), LatLon(45, 2), LatLon(46, 2), LatLon(46, 1) for _ in self.testiter(): self.test('isenclosedBy', p.isenclosedBy(b), True) b = LatLon(45, 1), LatLon(45, 3), LatLon(46, 2), LatLon(47, 3), LatLon(47, 1) for _ in self.testiter(): try: self.test('isenclosedBy', p.isenclosedBy(b), True) # Nvector except ValueError as x: t = ' '.join(str(x).split()[:3] + ['...)']) self.test('isenclosedBy', t, 'non-convex: (%s(45°00′00.0″N, 001°00′00.0″E), ...)' % (classname(p),)) p = LatLon(51.127, 1.338) q = LatLon(50.964, 1.853) b = p.rhumbBearingTo(q) self.test('rhumbBearingTo', b, 116.722, fmt='%.3f') # 116.7 d = p.rhumbDestination(40300, 116.7) self.test('rhumbDestination', d, '50.964155°N, 001.853°E') # 50.9642°N, 001.8530°E self.test('rhumbDestination', isinstance(d, LatLon), True) d = p.rhumbDistanceTo(q) self.test('rhumbDistanceTo', d, 40307.8, fmt='%.1f') # XXX 40310 ? m = p.rhumbMidpointTo(q) self.test('rhumbMidpointo', m, '51.0455°N, 001.595727°E') self.test('rhumbMidpointo', isinstance(m, LatLon), True) b = LatLon(45, 1), LatLon(45, 2), LatLon(46, 2), LatLon(46, 1) self.test('areaOf', module.areaOf(b), '8.6660587507e+09', fmt='%.10e') # 8666058750.718977 c = LatLon(0, 0), LatLon(1, 0), LatLon(0, 1) self.test('areaOf', module.areaOf(c), '6.18e+09', fmt='%.2e') if hasattr(module, 'nearestOn2'): c, d = module.nearestOn2(p, b) self.test('nearestOn2', c, '46.000996°N, 001.353049°E' if Vct else '46.0°N, 001.369324°E') self.test('nearestOn2', d, '569987.49' if Vct else '570101.83', fmt='%.2f') d = p.distanceTo(c) self.test('distanceTo', d, '569987.49' if Vct else '570101.82', fmt='%.2f') p = LatLon(47, 3) c, d = module.nearestOn2(p, b) self.test('nearestOn2', c, '46.0°N, 002.0°E' if Vct else '46.0°N, 002.0°E') self.test('nearestOn2', d, '134989.80' if Vct else '134992.48', fmt='%.2f') d = p.distanceTo(c) self.test('distanceTo', d, '134989.80' if Vct else '134989.80', fmt='%.2f') p = LatLon(45, 2) b = LatLon(45, 1), LatLon(47, 3) if Vct: c, d = module.nearestOn2(p, b) self.test('nearestOn2', c, '45.330691°N, 001.318551°E') self.test('distanceTo2', d, '64856.28', fmt='%.2f') else: c, d = module.nearestOn2(p, b, adjust=False) self.test('nearestOn2', c, '45.5°N, 001.5°E') self.test('distanceTo2', d, '78626.79', fmt='%.2f') c, d = module.nearestOn2(p, b, adjust=True) self.test('nearestOn2', c, '45.331319°N, 001.331319°E') self.test('distanceTo2', d, '64074.48', fmt='%.2f') d = p.distanceTo(c) self.test('distanceTo', d, '64856.28' if Vct else '64074.12', fmt='%.2f') # TrigTrue vs Nvector closests p = LatLon(45.330691, 001.318551) d = p.distanceTo(LatLon(45.331319, 001.331319)) self.test('difference', d, '1000.53', fmt='%.2f') # PYCHOK test attr? if not Vct: # check nearestOn2 with closest on the segment b = LatLon(0, 1), LatLon(2, 3), LatLon(4, 5), LatLon(6, 7), LatLon(8, 9) for i in range(8): p = LatLon(i + 2, i) c, d = module.nearestOn2(p, b, adjust=False) p.lat -= 1.5 p.lon += 1.5 self.test('nearestOn2', c.toStr(F_D, prec=6), p.toStr(F_D, prec=6)) self.test('neartesOn2', d, '235880.385', fmt='%.3f') if hasattr(module, 'ispolar'): p = LatLon(85, 90), LatLon(85, 0), LatLon(85, -90), LatLon(85, -180) for _ in self.testiter(): self.test('ispolar', module.ispolar(p), 'True') # PYCHOK test attr? p = LatLon(85, 90), LatLon(85, 0), LatLon(85, -180) for _ in self.testiter(): self.test('ispolar', module.ispolar(p), 'True', known=True) # PYCHOK test attr? p = [LatLon(*ll) for ll in Antarctica] # PYCHOK test attr? for _ in self.testiter(): self.test('ispolar', module.ispolar(p), 'True', known=Vct) # PYCHOK test attr?
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'): n = classname(Cartesian(0, 0, 0), prefixed=True) + '.intersections2' # <https://GIS.StackExchange.com/questions/48937/calculating-intersection-of-two-circles> c = Cartesian(-0.00323306, -0.7915, 0.61116) self.test(n, c.toLatLon(height=0), '37.673442°N, 090.234036°W') d = Cartesian(-0.0134464, -0.807775, 0.589337) self.test(n, 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(n, x.toStr(prec=6), '[-0.032779, -0.784769, 0.61892]' ) # -0.0327606, -0.784759, 0.618935 self.test(n, x.toLatLon(height=0), '38.237342°N, 092.391779°W') # 38.23838°N, 092.390487°W if y is not x: self.test(n, y.toStr(prec=6), '[0.025768, -0.798347, 0.601646]' ) # 0.0257661, -0.798332, 0.601666 self.test( n, y.toLatLon(height=0), '36.987868°N, 088.151309°W') # 36.98931°N, 088.151425°W try: from pygeodesy import trilaterate3d2 # with earth ... equivalent to Cartesian.intersections2? n = modulename(trilaterate3d2, prefixed=True) i, j = trilaterate3d2(c, 0.0312705, d, 0.0421788, Cartesian(0, 0, 0), 1) # radians self.test(n, i.toStr(prec=6), '[-0.032779, -0.784769, 0.61892]', known=x.minus(i).length < 5e-5) self.test(n, j.toStr(prec=6), '[0.025768, -0.798347, 0.601646]', known=y.minus(j).length < 5e-5) except ImportError as x: self.skip(str(x), n=2) try: from pygeodesy.vector3d import intersections2 n = modulename(intersections2, prefixed=True) 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(n, c.toStr(prec=6), '(-0.0035, -0.791926, 0.610589)') self.test(n, r.toStr(prec=6), '0.0312613', known=True) # XXX G and g formats may add 1 decimal v1, v2 = intersections2(u, 0.0312705, v, 0.0421788, sphere=False) self.test(n, v1.toStr(prec=6), '(-0.021973, -0.766467, 0.0)') if v2 is not v1: self.test(n, v2.toStr(prec=6), '(0.027459, -0.797488, 0.0)') except ImportError as x: self.skip(str(x), n=4)