pygeodesy 24.7.24__py2.py3-none-any.whl → 24.8.24__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. {PyGeodesy-24.7.24.dist-info → PyGeodesy-24.8.24.dist-info}/METADATA +20 -19
  2. {PyGeodesy-24.7.24.dist-info → PyGeodesy-24.8.24.dist-info}/RECORD +57 -57
  3. {PyGeodesy-24.7.24.dist-info → PyGeodesy-24.8.24.dist-info}/WHEEL +1 -1
  4. pygeodesy/__init__.py +26 -27
  5. pygeodesy/auxilats/auxAngle.py +2 -2
  6. pygeodesy/auxilats/auxDST.py +3 -3
  7. pygeodesy/azimuthal.py +4 -4
  8. pygeodesy/basics.py +3 -3
  9. pygeodesy/cartesianBase.py +6 -6
  10. pygeodesy/constants.py +11 -11
  11. pygeodesy/css.py +5 -5
  12. pygeodesy/ellipsoidalBase.py +18 -15
  13. pygeodesy/ellipsoidalExact.py +2 -2
  14. pygeodesy/ellipsoidalGeodSolve.py +2 -2
  15. pygeodesy/ellipsoidalKarney.py +2 -2
  16. pygeodesy/ellipsoidalNvector.py +2 -2
  17. pygeodesy/ellipsoidalVincenty.py +7 -6
  18. pygeodesy/ellipsoids.py +3 -3
  19. pygeodesy/epsg.py +3 -3
  20. pygeodesy/fmath.py +2 -1
  21. pygeodesy/formy.py +2 -2
  22. pygeodesy/fsums.py +4 -4
  23. pygeodesy/gars.py +66 -58
  24. pygeodesy/geodesici.py +4 -10
  25. pygeodesy/geodesicx/gx.py +3 -3
  26. pygeodesy/geodesicx/gxarea.py +3 -3
  27. pygeodesy/geodsolve.py +3 -3
  28. pygeodesy/geohash.py +491 -267
  29. pygeodesy/geoids.py +298 -316
  30. pygeodesy/heights.py +176 -194
  31. pygeodesy/internals.py +39 -6
  32. pygeodesy/interns.py +2 -3
  33. pygeodesy/karney.py +2 -2
  34. pygeodesy/latlonBase.py +14 -8
  35. pygeodesy/lazily.py +22 -21
  36. pygeodesy/ltp.py +6 -7
  37. pygeodesy/ltpTuples.py +12 -6
  38. pygeodesy/named.py +5 -4
  39. pygeodesy/namedTuples.py +14 -1
  40. pygeodesy/osgr.py +7 -7
  41. pygeodesy/points.py +2 -2
  42. pygeodesy/resections.py +7 -7
  43. pygeodesy/rhumb/solve.py +3 -3
  44. pygeodesy/simplify.py +10 -10
  45. pygeodesy/sphericalBase.py +3 -3
  46. pygeodesy/sphericalTrigonometry.py +2 -2
  47. pygeodesy/streprs.py +3 -3
  48. pygeodesy/triaxials.py +210 -204
  49. pygeodesy/units.py +36 -19
  50. pygeodesy/unitsBase.py +4 -4
  51. pygeodesy/utmupsBase.py +3 -3
  52. pygeodesy/vector2d.py +158 -51
  53. pygeodesy/vector3d.py +13 -52
  54. pygeodesy/vector3dBase.py +81 -63
  55. pygeodesy/webmercator.py +3 -3
  56. pygeodesy/wgrs.py +109 -101
  57. {PyGeodesy-24.7.24.dist-info → PyGeodesy-24.8.24.dist-info}/top_level.txt +0 -0
pygeodesy/vector3d.py CHANGED
@@ -3,8 +3,8 @@
3
3
 
4
4
  u'''Extended 3-D vector class L{Vector3d} and functions.
5
5
 
6
- Function L{intersection3d3}, L{intersections2}, L{parse3d}, L{sumOf},
7
- L{trilaterate2d2} and L{trilaterate3d2}.
6
+ Function L{intersection3d3}, L{intersections2}, L{parse3d}, L{sumOf} and
7
+ L{trilaterate3d2}.
8
8
  '''
9
9
 
10
10
  from pygeodesy.constants import EPS, EPS0, EPS1, EPS4, INT0, isnear0, \
@@ -31,7 +31,7 @@ from pygeodesy.vector3dBase import Vector3dBase
31
31
  # from math import fabs, sqrt # from .fmath
32
32
 
33
33
  __all__ = _ALL_LAZY.vector3d
34
- __version__ = '24.06.18'
34
+ __version__ = '24.08.18'
35
35
 
36
36
  _vector2d = _MODS.into(vector2d=__name__)
37
37
 
@@ -101,7 +101,7 @@ class Vector3d(Vector3dBase):
101
101
  or C{Vector4Tuple}).
102
102
  @arg point3: Third point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple}
103
103
  or C{Vector4Tuple}).
104
- @kwarg circum: If C{True} return the C{circumradius} and C{circumcenter},
104
+ @kwarg circum: If C{True}, return the C{circumradius} and C{circumcenter},
105
105
  always, ignoring the I{Meeus}' Type I case (C{bool}).
106
106
  @kwarg eps: Tolerance passed to function L{pygeodesy.trilaterate3d2}.
107
107
 
@@ -175,7 +175,7 @@ class Vector3d(Vector3dBase):
175
175
  or C{Vector4Tuple}).
176
176
  @arg point3: Third point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple}
177
177
  or C{Vector4Tuple}).
178
- @kwarg circum: If C{True} return the C{circumradius} and C{circumcenter}
178
+ @kwarg circum: If C{True}, return the C{circumradius} and C{circumcenter}
179
179
  always, overriding I{Meeus}' Type II case (C{bool}).
180
180
 
181
181
  @return: L{Meeus2Tuple}C{(radius, Type)}, with C{Type} the C{circumcenter}
@@ -199,7 +199,7 @@ class Vector3d(Vector3dBase):
199
199
  C{Vector4Tuple}).
200
200
  @arg point2: End point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple} or
201
201
  C{Vector4Tuple}).
202
- @kwarg within: If C{True} return the closest point between the given
202
+ @kwarg within: If C{True}, return the closest point between the given
203
203
  points, otherwise the closest point on the extended
204
204
  line through both points (C{bool}).
205
205
 
@@ -406,7 +406,7 @@ def _intersect3d3(start1, end1, start2, end2, eps=EPS, useZ=False): # MCCABE 16
406
406
  # Get the C{s1'} and C{e1'} corners of a right-angle
407
407
  # triangle with the hypotenuse thru C{s1} at bearing
408
408
  # C{b1} and the right angle at C{s2}
409
- dx, dy, d = s2.minus(s1).xyz
409
+ dx, dy, d = s2.minus(s1).xyz3
410
410
  if useZ and not isnear0(d): # not supported
411
411
  raise IntersectionError(useZ=d, bearing=b1)
412
412
  s, c = sincos2d(b1)
@@ -535,7 +535,7 @@ def intersections2(center1, radius1, center2, radius2, sphere=True, **Vector_and
535
535
  C{Vector3Tuple} or C{Vector4Tuple}).
536
536
  @arg radius2: Radius of the second sphere or circle (same units as the
537
537
  B{C{center1}} and B{C{center2}} coordinates).
538
- @kwarg sphere: If C{True} compute the center and radius of the intersection of
538
+ @kwarg sphere: If C{True}, compute the center and radius of the intersection of
539
539
  two spheres. If C{False}, ignore the C{z}-component and compute
540
540
  the intersection of two circles (C{bool}).
541
541
  @kwarg Vector_and_kwds: Optional class C{B{Vector}=None} to return the
@@ -657,7 +657,7 @@ def nearestOn(point, point1, point2, within=True, useZ=True, Vector=None, **Vect
657
657
  C{Vector4Tuple}).
658
658
  @arg point2: End point (C{Cartesian}, L{Vector3d}, C{Vector3Tuple} or
659
659
  C{Vector4Tuple}).
660
- @kwarg within: If C{True} return the closest point between both given
660
+ @kwarg within: If C{True}, return the closest point between both given
661
661
  points, otherwise the closest point on the extended line
662
662
  through both points (C{bool}).
663
663
  @kwarg useZ: If C{True}, use the Z components, otherwise force C{z=INT0} (C{bool}).
@@ -836,45 +836,6 @@ def sumOf(vectors, Vector=Vector3d, **Vector_kwds):
836
836
  Vector(x, y, z, **_xkwds(Vector_kwds, name__=sumOf)) # .__name__
837
837
 
838
838
 
839
- def trilaterate2d2(x1, y1, radius1, x2, y2, radius2, x3, y3, radius3,
840
- eps=None, **Vector_and_kwds):
841
- '''Trilaterate three circles, each given as a (2-D) center and a radius.
842
-
843
- @arg x1: Center C{x} coordinate of the 1st circle (C{scalar}).
844
- @arg y1: Center C{y} coordinate of the 1st circle (C{scalar}).
845
- @arg radius1: Radius of the 1st circle (C{scalar}).
846
- @arg x2: Center C{x} coordinate of the 2nd circle (C{scalar}).
847
- @arg y2: Center C{y} coordinate of the 2nd circle (C{scalar}).
848
- @arg radius2: Radius of the 2nd circle (C{scalar}).
849
- @arg x3: Center C{x} coordinate of the 3rd circle (C{scalar}).
850
- @arg y3: Center C{y} coordinate of the 3rd circle (C{scalar}).
851
- @arg radius3: Radius of the 3rd circle (C{scalar}).
852
- @kwarg eps: Tolerance to check the trilaterated point I{delta} on all
853
- 3 circles (C{scalar}) or C{None} for no checking.
854
- @kwarg Vector_and_kwds: Optional class C{B{Vector}=None} to return the
855
- trilateration and optional, additional B{C{Vector}}
856
- keyword arguments, otherwise (L{Vector3d}).
857
-
858
- @return: Trilaterated point as C{B{Vector}(x, y, **B{Vector_kwds})}
859
- or L{Vector2Tuple}C{(x, y)} if C{B{Vector} is None}..
860
-
861
- @raise IntersectionError: No intersection, near-concentric or -colinear
862
- centers, trilateration failed some other way
863
- or the trilaterated point is off one circle
864
- by more than B{C{eps}}.
865
-
866
- @raise UnitError: Invalid B{C{radius1}}, B{C{radius2}} or B{C{radius3}}.
867
-
868
- @see: U{Issue #49<https://GitHub.com/mrJean1/PyGeodesy/issues/49>},
869
- U{Find X location using 3 known (X,Y) location using trilateration
870
- <https://math.StackExchange.com/questions/884807>} and function
871
- L{pygeodesy.trilaterate3d2}.
872
- '''
873
- return _vector2d._trilaterate2d2(x1, y1, radius1,
874
- x2, y2, radius2,
875
- x3, y3, radius3, eps=eps, **Vector_and_kwds)
876
-
877
-
878
839
  def trilaterate3d2(center1, radius1, center2, radius2, center3, radius3,
879
840
  eps=EPS, **Vector_and_kwds):
880
841
  '''Trilaterate three spheres, each given as a (3-D) center and a radius.
@@ -893,10 +854,10 @@ def trilaterate3d2(center1, radius1, center2, radius2, center3, radius3,
893
854
  and C{z}).
894
855
  @kwarg eps: Pertubation tolerance (C{scalar}), same units as C{x},
895
856
  C{y} and C{z} or C{None} for no pertubations.
896
- @kwarg Vector_and_kwds: Optional class C{B{Vector}=None} to return the
897
- trilateration and optional, additional B{C{Vector}}
898
- keyword arguments, otherwise B{C{center1}}'s
899
- (sub-)class.
857
+ @kwarg Vector_and_kwds: Optional class C{B{Vector}=None} to return
858
+ the trilateration and optional, additional
859
+ B{C{Vector}} keyword arguments, otherwise
860
+ the B{C{center1}}'s (sub-)class.
900
861
 
901
862
  @return: 2-Tuple with two trilaterated points, each a B{C{Vector}}
902
863
  instance. Both points are the same instance if all three
pygeodesy/vector3dBase.py CHANGED
@@ -8,11 +8,11 @@ A pure Python implementation of vector-based functions by I{(C) Chris Veness
8
8
  <https://www.Movable-Type.co.UK/scripts/latlong-vectors.html>}.
9
9
  '''
10
10
 
11
- from pygeodesy.basics import _copysign, islistuple, isscalar, map1, \
12
- map2, _signOf, _zip
11
+ from pygeodesy.basics import _copysign, islistuple, isscalar, map1, map2, \
12
+ _signOf, _zip
13
13
  from pygeodesy.constants import EPS, EPS0, INT0, PI, PI2, _copysignINF, \
14
14
  _float0, isnear0, isnear1, isneg0, \
15
- _pos_self, _0_0, _1_0
15
+ _pos_self, _1_0
16
16
  from pygeodesy.errors import CrossError, VectorError, _xcallable, _xError
17
17
  from pygeodesy.fmath import euclid_, fdot, hypot_, hypot2_
18
18
  from pygeodesy.interns import _coincident_, _colinear_, _COMMASPACE_, _xyz_
@@ -24,13 +24,12 @@ from pygeodesy.props import deprecated_method, Property, Property_RO, \
24
24
  property_doc_, property_RO, _update_all
25
25
  from pygeodesy.streprs import Fmt, strs, unstr
26
26
  from pygeodesy.units import Float, Scalar
27
- # from pygeodesy.utily import sincos2 # _MODS
27
+ from pygeodesy.utily import sincos2, atan2, fabs
28
28
 
29
- # from builtints import hash, int, isinstance, map, max, round, type, zip
30
- from math import atan2, ceil, fabs, floor, trunc
29
+ from math import ceil as _ceil, floor as _floor, trunc as _trunc
31
30
 
32
31
  __all__ = _ALL_LAZY.vector3dBase
33
- __version__ = '24.06.11'
32
+ __version__ = '24.08.18'
34
33
 
35
34
 
36
35
  class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
@@ -61,7 +60,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
61
60
  @kwarg ll: Optional latlon reference (C{LatLon}).
62
61
  @kwarg name: Optional C{B{name}=NN} (C{str}).
63
62
 
64
- @raise VectorError: Invalid B{C{x_xyz}}.
63
+ @raise VectorError: Invalid B{C{x_xyz}}, B{C{y}} or B{C{z}}.
65
64
  '''
66
65
  self._x, \
67
66
  self._y, \
@@ -90,6 +89,8 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
90
89
 
91
90
  def __bool__(self): # PYCHOK PyChecker
92
91
  '''Is this vector non-zero?
92
+
93
+ @see: Method C{bools}.
93
94
  '''
94
95
  return bool(self.x or self.y or self.z)
95
96
 
@@ -98,7 +99,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
98
99
 
99
100
  @return: Ceil-ed (L{Vector3d}).
100
101
  '''
101
- return self._mapped(ceil)
102
+ return self._mapped(_ceil)
102
103
 
103
104
  def __cmp__(self, other): # Python 2-
104
105
  '''Compare this and an other vector (L{Vector3d}).
@@ -127,15 +128,15 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
127
128
  return self.isequalTo(other, eps=EPS0)
128
129
 
129
130
  def __float__(self): # PYCHOK no cover
130
- '''Not implemented.'''
131
- return _NotImplemented(self)
131
+ '''Not implemented, see method C{float}.'''
132
+ return _NotImplemented(self) # must return C{float}
132
133
 
133
134
  def __floor__(self): # PYCHOK no cover
134
135
  '''Return a vector with the C{floor} of these components.
135
136
 
136
137
  @return: Floor-ed (L{Vector3d}).
137
138
  '''
138
- return self._mapped(floor)
139
+ return self._mapped(_floor)
139
140
 
140
141
  def __floordiv__(self, other): # PYCHOK no cover
141
142
  '''Not implemented.'''
@@ -215,13 +216,8 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
215
216
  return self._xyz(self.times(scalar))
216
217
 
217
218
  def __int__(self): # PYCHOK no cover
218
- '''Return a vector with the C{int} of these components.
219
-
220
- @return: Int-ed (L{Vector3d}).
221
- '''
222
- v = self.classof(_0_0)
223
- v._x, v._y, v._z = map2(int, self.xyz)
224
- return v
219
+ '''Not implemented, see method C{ints}.'''
220
+ return _NotImplemented(self) # must return C{int}
225
221
 
226
222
  def __ipow__(self, other, *mod): # PYCHOK no cover
227
223
  '''Not implemented.'''
@@ -239,7 +235,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
239
235
  # def __iter__(self):
240
236
  # '''Return an C{iter}ator over this vector's components.
241
237
  # '''
242
- # return iter(self.xyz)
238
+ # return iter(self.xyz3)
243
239
 
244
240
  def __itruediv__(self, scalar):
245
241
  '''Divide this vector by a scalar I{in-place}, C{this /= B{scalar}}.
@@ -315,9 +311,9 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
315
311
  def __neg__(self):
316
312
  '''Return the opposite of this vector.
317
313
 
318
- @return: This instance negated (L{Vector3d})
314
+ @return: A negated copy (L{Vector3d})
319
315
  '''
320
- return self.classof(-self.x, -self.y, -self.z)
316
+ return self.negate()
321
317
 
322
318
  def __pos__(self): # PYCHOK no cover
323
319
  '''Return this vector I{as-is} or a copy.
@@ -370,7 +366,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
370
366
  @return: Rounded (L{Vector3d}).
371
367
  '''
372
368
  # <https://docs.Python.org/3.12/reference/datamodel.html?#object.__round__>
373
- return self.classof(*(round(_, *ndigits) for _ in self.xyz))
369
+ return self.classof(*(round(_, *ndigits) for _ in self.xyz3))
374
370
 
375
371
  def __rpow__(self, other, *mod): # PYCHOK no cover
376
372
  '''Not implemented.'''
@@ -423,7 +419,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
423
419
 
424
420
  @return: Trunc-ed (L{Vector3d}).
425
421
  '''
426
- return self._mapped(trunc)
422
+ return self._mapped(_trunc)
427
423
 
428
424
  if _sys_version_info2 < (3, 0): # PYCHOK no cover
429
425
  # <https://docs.Python.org/2/library/operator.html#mapping-operators-to-functions>
@@ -484,9 +480,14 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
484
480
  _f2 = fun2
485
481
 
486
482
  xyz = _xyz3(self.apply, other_x, *y_z)
487
- xyz = (_f2(a, b) for a, b in _zip(self.xyz, xyz)) # strict=True
483
+ xyz = (_f2(a, b) for a, b in _zip(self.xyz3, xyz)) # strict=True
488
484
  return self.classof(*xyz)
489
485
 
486
+ def bools(self):
487
+ '''Return the vector with C{bool} components.
488
+ '''
489
+ return self._mapped(bool)
490
+
490
491
  def cross(self, other, raiser=None, eps0=EPS): # raiser=NN
491
492
  '''Compute the cross product of this and an other vector.
492
493
 
@@ -502,11 +503,11 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
502
503
 
503
504
  @raise TypeError: Incompatible B{C{other}} C{type}.
504
505
  '''
505
- X, Y, Z = self.others(other).xyz
506
- x, y, z = self.xyz
507
- xyz = ((y * Z - Y * z),
508
- (z * X - Z * x),
509
- (x * Y - X * y))
506
+ X, Y, Z = self.others(other).xyz3
507
+ x, y, z = self.xyz3
508
+ xyz = ((y * Z - z * Y),
509
+ (z * X - x * Z),
510
+ (x * Y - y * X))
510
511
 
511
512
  if raiser and self.crosserrors and eps0 > 0 \
512
513
  and max(map(fabs, xyz)) < eps0:
@@ -516,7 +517,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
516
517
  t = _coincident_ if t else _colinear_
517
518
  raise CrossError(raiser, s, other=r, txt=t)
518
519
 
519
- return self.classof(*xyz)
520
+ return self.classof(*xyz) # name__=self.cross
520
521
 
521
522
  @property_doc_('''raise or ignore L{CrossError} exceptions (C{bool}).''')
522
523
  def crosserrors(self):
@@ -556,8 +557,8 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
556
557
 
557
558
  @raise TypeError: Incompatible B{C{other}} C{type}.
558
559
  '''
559
- return self.length2 if other is self else \
560
- fdot(self.xyz, *self.others(other).xyz)
560
+ return self.length2 if other is self else fdot(
561
+ self.xyz3, *self.others(other).xyz3)
561
562
 
562
563
  @deprecated_method
563
564
  def equals(self, other, units=False): # PYCHOK no cover
@@ -572,21 +573,31 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
572
573
  @see: Properties C{length} and C{length2} and function
573
574
  L{pygeodesy.euclid_}.
574
575
  '''
575
- return Float(euclid=euclid_(self.x, self.y, self.z))
576
+ return Float(euclid=euclid_(*self.xyz3))
576
577
 
577
578
  def equirectangular(self, other):
578
- '''I{Approximate} the different between this and an other vector.
579
+ '''I{Approximate} the difference between this and an other vector.
579
580
 
580
581
  @arg other: Vector to subtract (C{Vector3dBase}).
581
582
 
582
- @return: The lenght I{squared} of the difference (C{Float}).
583
+ @return: The length I{squared} of the difference (C{Float}).
583
584
 
584
585
  @raise TypeError: Incompatible B{C{other}} C{type}.
585
586
 
586
587
  @see: Property C{length2}.
587
588
  '''
588
589
  d = self.minus(other)
589
- return Float(equirectangular=hypot2_(d.x, d.y, d.z))
590
+ return Float(equirectangular=hypot2_(*d.xyz3))
591
+
592
+ def fabs(self):
593
+ '''Return the vector with C{fabs} components.
594
+ '''
595
+ return self._mapped(fabs)
596
+
597
+ def floats(self):
598
+ '''Return the vector with C{float} components.
599
+ '''
600
+ return self._mapped(_float0)
590
601
 
591
602
  @Property
592
603
  def _fromll(self):
@@ -604,7 +615,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
604
615
  def homogeneous(self):
605
616
  '''Get this vector's homogeneous representation (L{Vector3d}).
606
617
  '''
607
- x, y, z = self.xyz
618
+ x, y, z = self.xyz3
608
619
  if z:
609
620
  x = x / z # /= chokes PyChecker
610
621
  y = y / z
@@ -639,6 +650,11 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
639
650
  r = self.plus(r.minus(self)._times(f))
640
651
  return r
641
652
 
653
+ def ints(self):
654
+ '''Return the vector with C{int} components.
655
+ '''
656
+ return self._mapped(int)
657
+
642
658
  def isconjugateTo(self, other, minum=1, eps=EPS):
643
659
  '''Determine whether this and an other vector are conjugates.
644
660
 
@@ -657,7 +673,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
657
673
  '''
658
674
  self.others(other)
659
675
  n = 0
660
- for a, b in zip(self.xyz, other.xyz):
676
+ for a, b in zip(self.xyz3, other.xyz3):
661
677
  if fabs(a + b) < eps and ((a < 0 and b > 0) or
662
678
  (a > 0 and b < 0)):
663
679
  n += 1 # conjugate
@@ -685,7 +701,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
685
701
  d = self.unit().minus(other.unit())
686
702
  else:
687
703
  d = self.minus(other)
688
- return max(map(fabs, d.xyz)) < eps
704
+ return max(map(fabs, d.xyz3)) < eps
689
705
 
690
706
  @Property_RO
691
707
  def length(self): # __dict__ value overwritten by Property_RO C{_united}
@@ -704,9 +720,9 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
704
720
  return Float(length2=hypot2_(self.x, self.y, self.z))
705
721
 
706
722
  def _mapped(self, func):
707
- '''(INTERNAL) Map these components.
723
+ '''(INTERNAL) Apply C{func} to all components.
708
724
  '''
709
- return self.classof(*map2(func, self.xyz))
725
+ return self.classof(*map2(func, self.xyz3))
710
726
 
711
727
  def minus(self, other):
712
728
  '''Subtract an other vector from this vector.
@@ -717,8 +733,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
717
733
 
718
734
  @raise TypeError: Incompatible B{C{other}} C{type}.
719
735
  '''
720
- xyz = self.others(other).xyz
721
- return self._minus(*xyz)
736
+ return self._minus(*self.others(other).xyz3)
722
737
 
723
738
  def _minus(self, x, y, z):
724
739
  '''(INTERNAL) Helper for methods C{.minus} and C{.minus_}.
@@ -742,19 +757,17 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
742
757
  return self._minus(*_xyz3(self.minus_, other_x, *y_z))
743
758
 
744
759
  def negate(self):
745
- '''Return this vector in opposite direction.
760
+ '''Return the opposite of this vector.
746
761
 
747
- @return: New, opposite vector (L{Vector3d}).
762
+ @return: A negated copy (L{Vector3d})
748
763
  '''
749
764
  return self.classof(-self.x, -self.y, -self.z)
750
765
 
751
- __neg__ = negate # PYCHOK no cover
752
-
753
766
  @Property_RO
754
767
  def _N_vector(self):
755
768
  '''(INTERNAL) Get the (C{nvectorBase._N_vector_})
756
769
  '''
757
- return _MODS.nvectorBase._N_vector_(*self.xyz, name=self.name)
770
+ return _MODS.nvectorBase._N_vector_(*self.xyz3, name=self.name)
758
771
 
759
772
  def _other_cmp(self, other):
760
773
  '''(INTERNAL) Return the value for comparison.
@@ -786,8 +799,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
786
799
 
787
800
  @raise TypeError: Incompatible B{C{other}} C{type}.
788
801
  '''
789
- xyz = self.others(other).xyz
790
- return self._plus(*xyz)
802
+ return self._plus(*self.others(other).xyz3)
791
803
 
792
804
  sum = plus # alternate name
793
805
 
@@ -825,21 +837,21 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
825
837
  U{Quaternion-derived rotation matrix<https://WikiPedia.org/wiki/
826
838
  Quaternions_and_spatial_rotation#Quaternion-derived_rotation_matrix>}.
827
839
  '''
828
- s, c = _MODS.utily.sincos2(theta) # rotation angle
840
+ s, c = sincos2(theta) # rotation angle
829
841
  d = _1_0 - c
830
842
  if d or s:
831
843
  p = self.unit().xyz # point being rotated
832
844
  r = self.others(axis=axis).unit() # axis being rotated around
833
845
 
834
- ax, ay, az = r.xyz # quaternion-derived rotation matrix
835
- bx, by, bz = r.times(d).xyz
836
- sx, sy, sz = r.times(s).xyz
846
+ ax, ay, az = r.xyz3 # quaternion-derived rotation matrix
847
+ bx, by, bz = r.times(d).xyz3
848
+ sx, sy, sz = r.times(s).xyz3
837
849
 
838
850
  x = fdot(p, ax * bx + c, ax * by - sz, ax * bz + sy)
839
851
  y = fdot(p, ay * bx + sz, ay * by + c, ay * bz - sx)
840
852
  z = fdot(p, az * bx - sy, az * by + sx, az * bz + c)
841
853
  else: # unrotated
842
- x, y, z = self.xyz
854
+ x, y, z = self.xyz3
843
855
  return self.classof(x, y, z)
844
856
 
845
857
  @deprecated_method
@@ -911,7 +923,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
911
923
 
912
924
  @return: Vector as "(x, y, z)" (C{str}).
913
925
  '''
914
- t = sep.join(strs(self.xyz, prec=prec))
926
+ t = sep.join(strs(self.xyz3, prec=prec))
915
927
  return (fmt % (t,)) if fmt else t
916
928
 
917
929
  def unit(self, ll=None):
@@ -960,7 +972,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
960
972
  def xyz(self):
961
973
  '''Get the X, Y and Z components (L{Vector3Tuple}C{(x, y, z)}).
962
974
  '''
963
- return _MODS.namedTuples.Vector3Tuple(self.x, self.y, self.z, name=self.name)
975
+ return _MODS.namedTuples.Vector3Tuple(*self.xyz3, name=self.name)
964
976
 
965
977
  @xyz.setter # PYCHOK setter!
966
978
  def xyz(self, xyz):
@@ -977,6 +989,12 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
977
989
  self._x, self._y, self._z = _xyz3(_xyz_, x_xyz, *y_z)
978
990
  return self
979
991
 
992
+ @property_RO
993
+ def xyz3(self):
994
+ '''Get the X, Y and Z components as C{3-tuple}.
995
+ '''
996
+ return self.x, self.y, self.z
997
+
980
998
  @property_RO
981
999
  def x2y2z2(self):
982
1000
  '''Get the X, Y and Z components I{squared} (3-tuple C{(x**2, y**2, z**2)}).
@@ -1015,15 +1033,15 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
1015
1033
 
1016
1034
 
1017
1035
  def _xyz3(where, x_xyz, *y_z): # in .cartesianBase._rtp3
1018
- '''(INTERNAL) Helper for C{Vector3dBase.__init__}, C{-.apply}, C{-.times_} and C{-._xyz}.
1036
+ '''(INTERNAL) Get , Y and Z as 3-tuple C{(x, y, z)}.
1019
1037
  '''
1020
1038
  try:
1021
- x_y_z = map1(_float0, x_xyz, *y_z) if y_z else ( # islistuple for VectorXTuple
1022
- map2(_float0, x_xyz[:3]) if islistuple(x_xyz, minum=3) else
1023
- x_xyz.xyz)
1039
+ xyz3 = map1(_float0, x_xyz, *y_z) if y_z else ( # islistuple for Vector*Tuple
1040
+ map2(_float0, x_xyz[:3]) if islistuple(x_xyz, minum=3) else
1041
+ x_xyz.xyz) # .xyz3
1024
1042
  except (AttributeError, TypeError, ValueError) as x:
1025
1043
  raise _xError(x, unstr(where, x_xyz, *y_z))
1026
- return x_y_z
1044
+ return xyz3
1027
1045
 
1028
1046
 
1029
1047
  __all__ += _ALL_DOCS(Vector3dBase)
pygeodesy/webmercator.py CHANGED
@@ -36,7 +36,7 @@ from pygeodesy.utily import degrees90, degrees180
36
36
  from math import atan, atanh, exp, radians, sin, tanh
37
37
 
38
38
  __all__ = _ALL_LAZY.webmercator
39
- __version__ = '24.06.11'
39
+ __version__ = '24.08.13'
40
40
 
41
41
  # _FalseEasting = 0 # false Easting (C{meter})
42
42
  # _FalseNorthing = 0 # false Northing (C{meter})
@@ -207,7 +207,7 @@ class Wm(_NamedBase):
207
207
  @kwarg prec: Number of (decimal) digits, unstripped (C{int}).
208
208
  @kwarg fmt: Enclosing backets format (C{str}).
209
209
  @kwarg sep: Optional separator between name:value pairs (C{str}).
210
- @kwarg radius: If C{True} include the radius (C{bool}) or
210
+ @kwarg radius: If C{True}, include the radius (C{bool}) or
211
211
  C{scalar} to override this WM's radius.
212
212
 
213
213
  @return: This WM as "[x:meter, y:meter]" (C{str}) or as "[x:meter,
@@ -227,7 +227,7 @@ class Wm(_NamedBase):
227
227
  @kwarg fmt: Optional C{float} format (C{letter}).
228
228
  @kwarg sep: Optional separator to join (C{str}) or C{None}
229
229
  to return an unjoined C{tuple} of C{str}s.
230
- @kwarg radius: If C{True} include the radius (C{bool}) or
230
+ @kwarg radius: If C{True}, include the radius (C{bool}) or
231
231
  C{scalar} to override this WM's radius.
232
232
 
233
233
  @return: This WM as "meter meter" (C{str}) or as "meter meter