pygeodesy 25.9.9__py2.py3-none-any.whl → 25.11.5__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.
pygeodesy/units.py CHANGED
@@ -820,6 +820,11 @@ def _isMeter(obj, iscalar=True):
820
820
  return isinstance(obj, _Meters) or (iscalar and _isScalar(obj))
821
821
 
822
822
 
823
+ def _isRadians(obj, iscalar=True):
824
+ # Check for valid radian types.
825
+ return isinstance(obj, _Radians) or (iscalar and _isScalar(obj))
826
+
827
+
823
828
  def _isRadius(obj, iscalar=True):
824
829
  # Check for valid earth radius types.
825
830
  return isinstance(obj, _Radii) or (iscalar and _isScalar(obj))
pygeodesy/utily.py CHANGED
@@ -28,7 +28,7 @@ from math import acos, asin, asinh, atan2 as _atan2, cos, degrees, fabs, \
28
28
  radians, sin, sinh, tan as _tan # pow
29
29
 
30
30
  __all__ = _ALL_LAZY.utily
31
- __version__ = '25.09.09'
31
+ __version__ = '25.10.29'
32
32
 
33
33
  # sqrt(3) <https://WikiPedia.org/wiki/Square_root_of_3>
34
34
  _COS_30, _SIN_30 = 0.86602540378443864676, _0_5 # sqrt(3) / 2
@@ -807,15 +807,16 @@ def _sin0cos2(q, r, sign):
807
807
  return s, c
808
808
 
809
809
 
810
- def SinCos2(x):
810
+ def SinCos2(x, unit=Radians):
811
811
  '''Get C{sin} and C{cos} of I{typed} angle.
812
812
 
813
813
  @arg x: Angle (L{Degrees}, L{Radians} or scalar C{radians}).
814
+ @kwarg unit: The C{B{x}} unit (L{Degrees}, L{Radians}).
814
815
 
815
816
  @return: 2-Tuple (C{sin(B{x})}, C{cos(B{x})}).
816
817
  '''
817
- return sincos2d(x) if isinstanceof(x, Degrees, Degrees_) else (
818
- # sincos2(x) if isinstanceof(x, Radians, Radians_) else
818
+ return sincos2d(x) if unit is Degrees or isinstanceof(x, Degrees, Degrees_) else (
819
+ # sincos2(x) if unit is Radians or isinstanceof(x, Radians, Radians_) else
819
820
  sincos2(Radians(x))) # assume C{radians}
820
821
 
821
822
 
pygeodesy/vector2d.py CHANGED
@@ -641,7 +641,7 @@ def triaxum5(points, useZ=True):
641
641
  A = []
642
642
  for i, p in enumerate(ps):
643
643
  v = _otherV3d(useZ=useZ, i=i, points=p)
644
- A.append(v.x2y2z2)
644
+ A.append(v.x2y2z23)
645
645
 
646
646
  with _numpy(triaxum5, n=n) as _np:
647
647
  A = _np.array(A)
pygeodesy/vector3dBase.py CHANGED
@@ -10,9 +10,9 @@ A pure Python implementation of vector-based functions by I{(C) Chris Veness
10
10
 
11
11
  from pygeodesy.basics import _copysign, islistuple, isscalar, \
12
12
  map1, map2, _signOf, _zip
13
- from pygeodesy.constants import EPS, EPS0, INT0, PI, PI2, \
14
- _1_0, isnear0, isnear1, isneg0, \
15
- _copysignINF, _float0, _pos_self
13
+ from pygeodesy.constants import EPS, EPS0, INT0, PI, PI2, _1_0, \
14
+ _copysignINF, isnear0, isnear1, \
15
+ _flipsign, _float0, _pos_self
16
16
  from pygeodesy.errors import CrossError, VectorError, _xcallable, _xError
17
17
  from pygeodesy.fmath import euclid_, fdot, fdot_, hypot_, hypot2_ # _MODS.fmath.fma
18
18
  from pygeodesy.interns import _coincident_, _colinear_, _COMMASPACE_, _xyz_
@@ -29,7 +29,7 @@ from pygeodesy.utily import atan2, sincos2, fabs
29
29
  from math import ceil as _ceil, floor as _floor, trunc as _trunc
30
30
 
31
31
  __all__ = _ALL_LAZY.vector3dBase
32
- __version__ = '25.08.31'
32
+ __version__ = '25.10.25'
33
33
 
34
34
 
35
35
  class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
@@ -112,9 +112,20 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
112
112
 
113
113
  cmp = __cmp__
114
114
 
115
- def __divmod__(self, other): # PYCHOK no cover
116
- '''Not implemented.'''
117
- return _NotImplemented(self, other)
115
+ def __divmod__(self, scalar): # PYCHOK no cover
116
+ '''Apply C{scalar} divmod to this vector's components.
117
+
118
+ @arg scalar: Divisor (C{scalar}).
119
+
120
+ @return: 2-Tuple C{(d, m)} each a L{Vector3d}.
121
+ '''
122
+ s = Scalar(divisor=scalar)
123
+ d, m = [], []
124
+ for x in self.xyz3:
125
+ q, r = divmod(x, s)
126
+ d.append(q)
127
+ m.append(r)
128
+ return self.classof(d), self.classof(m)
118
129
 
119
130
  def __eq__(self, other):
120
131
  '''Is this vector equal to an other vector?
@@ -132,15 +143,22 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
132
143
  return _NotImplemented(self) # must return C{float}
133
144
 
134
145
  def __floor__(self): # PYCHOK no cover
135
- '''Return a vector with the C{floor} of these components.
146
+ '''Return a vector with the C{floor} of each components.
136
147
 
137
148
  @return: Floor-ed (L{Vector3d}).
138
149
  '''
139
150
  return self._mapped(_floor)
140
151
 
141
- def __floordiv__(self, other): # PYCHOK no cover
142
- '''Not implemented.'''
143
- return _NotImplemented(self, other)
152
+ def __floordiv__(self, scalar): # PYCHOK no cover
153
+ '''Floor-divide this vector by a scalar, C{this // B{scalar}}.
154
+
155
+ @arg scalar: The divisor (C{scalar}).
156
+
157
+ @return: Floored quotient (L{Vector3d}).
158
+
159
+ @raise TypeError: Non-scalar B{C{scalar}}.
160
+ '''
161
+ return self.floorDividedBy(scalar)
144
162
 
145
163
  def __ge__(self, other):
146
164
  '''Is this vector longer than or equal to an other vector?
@@ -183,9 +201,14 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
183
201
  '''
184
202
  return self._xyz(self.plus(other))
185
203
 
186
- def __ifloordiv__(self, other): # PYCHOK no cover
187
- '''Not implemented.'''
188
- return _NotImplemented(self, other)
204
+ def __ifloordiv__(self, scalar): # PYCHOK no cover
205
+ '''Floor-divide this vector by a scalar I{in-place}, C{this //= B{scalar}}.
206
+
207
+ @arg scalar: The divisor (C{scalar}).
208
+
209
+ @raise TypeError: Non-scalar B{C{scalar}}.
210
+ '''
211
+ return self._xyz(self.floorDividedBy(scalar))
189
212
 
190
213
  def __imatmul__(self, other): # PYCHOK Python 3.5+
191
214
  '''Cross multiply this and an other vector I{in-place}, C{this @= B{other}}.
@@ -215,9 +238,16 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
215
238
  '''Not implemented, see method C{ints}.'''
216
239
  return _NotImplemented(self) # must return C{int}
217
240
 
218
- def __ipow__(self, other, *mod): # PYCHOK no cover
219
- '''Not implemented.'''
220
- return _NotImplemented(self, other, *mod)
241
+ def __ipow__(self, scalar, *mod): # PYCHOK no cover
242
+ '''Raise each component I{in-place} as C{pow(C, B{scalar})}.
243
+
244
+ @arg scalar: Exponent (C{scalar}).
245
+
246
+ @return: Power (L{Vector3d}).
247
+
248
+ @raise TypeError: Non-scalar B{C{scalar}}.
249
+ '''
250
+ return self._xyz(self.pow(scalar, *mod))
221
251
 
222
252
  def __isub__(self, other):
223
253
  '''Subtract an other vector from this one I{in-place}, C{this -= B{other}}.
@@ -280,9 +310,19 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
280
310
  '''
281
311
  return self.cross(other)
282
312
 
283
- def __mod__(self, other): # PYCHOK no cover
284
- '''Not implemented.'''
285
- return _NotImplemented(self, other)
313
+ def __mod__(self, modulus): # PYCHOK no cover
314
+ '''Apply C{scalar} modulo to this vector's components.
315
+
316
+ @arg modulus: Modulus (C{scalar}).
317
+
318
+ @return: Modulo (L{Vector3d}).
319
+ '''
320
+ m = Scalar(modulus=modulus)
321
+
322
+ def _mod(x):
323
+ return x % m
324
+
325
+ return self._mapped(_mod)
286
326
 
287
327
  def __mul__(self, scalar):
288
328
  '''Multiply this vector by a scalar, C{this * B{scalar}}.
@@ -318,13 +358,29 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
318
358
  '''
319
359
  return self if _pos_self else self.copy()
320
360
 
321
- def __pow__(self, other, *mod): # PYCHOK no cover
322
- '''Not implemented.'''
323
- return _NotImplemented(self, other, *mod)
361
+ def __pow__(self, scalar, *mod): # PYCHOK no cover
362
+ '''Return a vector with components as C{pow(C, B{scalar})}.
363
+
364
+ @arg scalar: Exponent (C{scalar}).
365
+
366
+ @return: Power (L{Vector3d}).
367
+
368
+ @raise TypeError: Non-scalar B{C{scalar}}.
369
+ '''
370
+ return self.pow(scalar, *mod)
324
371
 
325
- __radd__ = __add__ # PYCHOK no cover
372
+ def __radd__(self, other): # PYCHOK no cover
373
+ '''Add this vector to an other vector, C{B{other} + this}.
374
+
375
+ @arg other: The other vector (L{Vector3d}).
376
+
377
+ @return: Sum (L{Vector3d}).
378
+
379
+ @raise TypeError: Incompatible B{C{other}} C{type}.
380
+ '''
381
+ return self.others(other).plus(self)
326
382
 
327
- def __rdivmod__ (self, other): # PYCHOK no cover
383
+ def __rdivmod__(self, other):
328
384
  '''Not implemented.'''
329
385
  return _NotImplemented(self, other)
330
386
 
@@ -333,7 +389,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
333
389
  # '''
334
390
  # return self.toRepr()
335
391
 
336
- def __rfloordiv__(self, other): # PYCHOK no cover
392
+ def __rfloordiv__(self, other):
337
393
  '''Not implemented.'''
338
394
  return _NotImplemented(self, other)
339
395
 
@@ -348,11 +404,11 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
348
404
  '''
349
405
  return self.others(other).cross(self)
350
406
 
351
- def __rmod__(self, other): # PYCHOK no cover
407
+ def __rmod__(self, other):
352
408
  '''Not implemented.'''
353
409
  return _NotImplemented(self, other)
354
410
 
355
- __rmul__ = __mul__
411
+ __rmul__ = __mul__ # scalar other
356
412
 
357
413
  def __round__(self, *ndigits): # PYCHOK no cover
358
414
  '''Return a vector with these components C{rounded}.
@@ -361,8 +417,11 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
361
417
 
362
418
  @return: Rounded (L{Vector3d}).
363
419
  '''
420
+ def _rnd(x):
421
+ return round(x, *ndigits)
422
+
364
423
  # <https://docs.Python.org/3.12/reference/datamodel.html?#object.__round__>
365
- return self.classof(*(round(_, *ndigits) for _ in self.xyz3))
424
+ return self._mapped(_rnd)
366
425
 
367
426
  def __rpow__(self, other, *mod): # PYCHOK no cover
368
427
  '''Not implemented.'''
@@ -379,9 +438,9 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
379
438
  '''
380
439
  return self.others(other).minus(self)
381
440
 
382
- def __rtruediv__(self, scalar): # PYCHOK no cover
441
+ def __rtruediv__(self, other):
383
442
  '''Not implemented.'''
384
- return _NotImplemented(self, scalar)
443
+ return _NotImplemented(self, other)
385
444
 
386
445
  # def __str__(self):
387
446
  # '''Return the default C{str(self)}.
@@ -527,22 +586,39 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
527
586
  '''
528
587
  self._crosserrors = bool(raiser)
529
588
 
530
- def dividedBy(self, divisor):
589
+ def dividedBy(self, scalar):
531
590
  '''Divide this vector by a scalar.
532
591
 
533
- @arg divisor: The divisor (C{scalar}).
592
+ @arg scalar: The divisor (C{scalar}).
534
593
 
535
594
  @return: New, scaled vector (L{Vector3d}).
536
595
 
537
- @raise TypeError: Non-scalar B{C{divisor}}.
596
+ @raise TypeError: Non-scalar B{C{scalar}}.
538
597
 
539
- @raise VectorError: Invalid or zero B{C{divisor}}.
598
+ @raise VectorError: Invalid or zero B{C{scalar}}.
540
599
  '''
541
- d = Scalar(divisor=divisor)
600
+ d = Scalar(divisor=scalar)
542
601
  try:
543
602
  return self._times(_1_0 / d)
544
603
  except (ValueError, ZeroDivisionError) as x:
545
- raise VectorError(divisor=divisor, cause=x)
604
+ raise VectorError(divisor=scalar, cause=x)
605
+
606
+ def dividedBy_(self, scalar_x, *y_z):
607
+ '''Divide this vector by separate X, Y and Z divisors.
608
+
609
+ @arg scalar_x: X divisor (C{scalar}) or a vector's
610
+ X, Y, and Z components as divisors
611
+ (C{Cartesian}, L{Ecef9Tuple}, C{Nvector},
612
+ L{Vector3d}, L{Vector3Tuple}, L{Vector4Tuple}).
613
+ @arg y_z: Y and Z divisors (C{scalar}, C{scalar}), ignored
614
+ if B{C{scalar_x}} is not C{scalar}.
615
+
616
+ @return: New, scaled vector (L{Vector3d}).
617
+
618
+ @raise VectorError: Invalid B{C{scalar_x}} or B{C{y_z}}.
619
+ '''
620
+ x, y, z = _xyz3(self.dividedBy_, scalar_x, *y_z)
621
+ return self.classof(self.x / x, self.y / y, self.z / z)
546
622
 
547
623
  def dot(self, other):
548
624
  '''Compute the dot (scalar) product of this and an other vector.
@@ -595,6 +671,43 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
595
671
  '''
596
672
  return self._mapped(_float0)
597
673
 
674
+ def floorDividedBy(self, scalar):
675
+ '''Floor-divide this vector by a scalar.
676
+
677
+ @arg scalar: The divisor (C{scalar}).
678
+
679
+ @return: New, scaled vector (L{Vector3d}).
680
+
681
+ @raise TypeError: Non-scalar B{C{scalar}}.
682
+
683
+ @raise VectorError: Invalid or zero B{C{scalar}}.
684
+ '''
685
+ d = Scalar(divisor=scalar)
686
+ try:
687
+ def _floor_d(x):
688
+ return x // d
689
+
690
+ return self._mapped(_floor_d)
691
+ except (ValueError, ZeroDivisionError) as x:
692
+ raise VectorError(divisor=scalar, cause=x)
693
+
694
+ def floorDividedBy_(self, scalar_x, *y_z):
695
+ '''Floor-divide this vector by separate X, Y and Z divisors.
696
+
697
+ @arg scalar_x: X divisor (C{scalar}) or a vector's
698
+ X, Y, and Z components as divisors
699
+ (C{Cartesian}, L{Ecef9Tuple}, C{Nvector},
700
+ L{Vector3d}, L{Vector3Tuple}, L{Vector4Tuple}).
701
+ @arg y_z: Y and Z divisors (C{scalar}, C{scalar}), ignored
702
+ if B{C{scalar_x}} is not C{scalar}.
703
+
704
+ @return: New, scaled vector (L{Vector3d}).
705
+
706
+ @raise VectorError: Invalid B{C{scalar_x}} or B{C{y_z}}.
707
+ '''
708
+ x, y, z = _xyz3(self.floorDividedBy_, scalar_x, *y_z)
709
+ return self.classof(self.x // x, self.y // y, self.z // z)
710
+
598
711
  @Property
599
712
  def _fromll(self):
600
713
  '''(INTERNAL) Get the latlon reference (C{LatLon}) or C{None}.
@@ -617,11 +730,8 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
617
730
  y = y / z
618
731
  # z = _1_0
619
732
  else:
620
- if isneg0(z):
621
- x = -x
622
- y = -y
623
- x = _copysignINF(x)
624
- y = _copysignINF(y)
733
+ x = _copysignINF(_flipsign(x, z))
734
+ y = _copysignINF(_flipsign(y, z))
625
735
  # z = NAN
626
736
  return self.classof(x, y, _1_0)
627
737
 
@@ -705,7 +815,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
705
815
 
706
816
  @see: Properties L{length2} and L{euclid}.
707
817
  '''
708
- return Float(length=hypot_(self.x, self.y, self.z))
818
+ return Float(length=hypot_(*self.xyz3))
709
819
 
710
820
  @Property_RO
711
821
  def length2(self): # __dict__ value overwritten by Property_RO C{_united}
@@ -713,7 +823,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
713
823
 
714
824
  @see: Property L{length} and method C{equirectangular}.
715
825
  '''
716
- return Float(length2=hypot2_(self.x, self.y, self.z))
826
+ return Float(length2=hypot2_(*self.xyz3))
717
827
 
718
828
  def _mapped(self, func):
719
829
  '''(INTERNAL) Apply C{func} to all components.
@@ -815,12 +925,28 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
815
925
  @arg y_z: Y and Z components (C{scalar}, C{scalar}),
816
926
  ignored if B{C{other_x}} is not C{scalar}.
817
927
 
818
- @return: New, vectiorial vector (L{Vector3d}).
928
+ @return: New, vectorial vector (L{Vector3d}).
819
929
 
820
930
  @raise ValueError: Invalid B{C{other_x}} or B{C{y_z}}.
821
931
  '''
822
932
  return self._plus(*_xyz3(self.plus_, other_x, *y_z))
823
933
 
934
+ def pow(self, scalar, *mod):
935
+ '''Raise each X, Y and Z to C{scalar} power.
936
+
937
+ @arg scalar: Exponent (C{scalar}).
938
+
939
+ @return: Power (L{Vector3d}).
940
+
941
+ @raise TypeError: Non-scalar B{C{scalar}}.
942
+ '''
943
+ p = Scalar(power=scalar)
944
+
945
+ def _pow(x):
946
+ return pow(x, p, *mod)
947
+
948
+ return self._mapped(_pow)
949
+
824
950
  def rotate(self, axis, theta, fma=False):
825
951
  '''Rotate this vector around an axis by a specified angle.
826
952
 
@@ -863,6 +989,16 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
863
989
  '''DEPRECATED, use method C{rotate}.'''
864
990
  return self.rotate(axis, theta) # PYCHOK no cover
865
991
 
992
+ def _roty(self, *pos, **name):
993
+ '''(INTERNAL) Prolate rotation, for C{+1 if pos else -1}.
994
+ '''
995
+ v = self.copy(**name)
996
+ if pos:
997
+ x, _, z = v.xyz3
998
+ _update_all(v, needed=3)
999
+ v._x, v._z = (-z, x) if pos[0] else (z, -x)
1000
+ return v
1001
+
866
1002
  def times(self, factor):
867
1003
  '''Multiply this vector by a scalar.
868
1004
 
@@ -989,8 +1125,10 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
989
1125
  def _xyz(self, x_xyz, *y_z):
990
1126
  '''(INTERNAL) Set the C{_x}, C{_y} and C{_z} attributes.
991
1127
  '''
992
- _update_all(self, needed=3)
993
- self._x, self._y, self._z = _xyz3(_xyz_, x_xyz, *y_z)
1128
+ xyz = _xyz3(_xyz_, x_xyz, *y_z)
1129
+ if self.xyz3 != xyz:
1130
+ _update_all(self, needed=3)
1131
+ self._x, self._y, self._z = xyz
994
1132
  return self
995
1133
 
996
1134
  @property_RO
@@ -999,9 +1137,15 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
999
1137
  '''
1000
1138
  return self.x, self.y, self.z
1001
1139
 
1002
- @property_RO
1140
+ @Property_RO
1003
1141
  def x2y2z2(self):
1004
- '''Get the X, Y and Z components I{squared} (3-tuple C{(x**2, y**2, z**2)}).
1142
+ '''Get the X, Y and Z components, I{squared} (L{Vector3Tuple}).
1143
+ '''
1144
+ return _MODS.namedTuples.Vector3Tuple(*self.x2y2z23, name=self.name)
1145
+
1146
+ @property_RO
1147
+ def x2y2z23(self):
1148
+ '''Get the X, Y and Z components, I{squared} (3-tuple C{(x**2, y**2, z**2)}).
1005
1149
  '''
1006
1150
  return self.x**2, self.y**2, self.z**2
1007
1151
 
@@ -1037,7 +1181,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
1037
1181
 
1038
1182
 
1039
1183
  def _xyz3(where, x_xyz, *y_z): # in .cartesianBase._rtp3
1040
- '''(INTERNAL) Get , Y and Z as 3-tuple C{(x, y, z)}.
1184
+ '''(INTERNAL) Get X, Y and Z as 3-tuple C{(x, y, z)}.
1041
1185
  '''
1042
1186
  try:
1043
1187
  xyz3 = map1(_float0, x_xyz, *y_z) if y_z else ( # islistuple for Vector*Tuple
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pygeodesy
3
- Version: 25.9.9
3
+ Version: 25.11.5
4
4
  Summary: Pure Python geodesy tools
5
5
  Home-page: https://GitHub.com/mrJean1/PyGeodesy
6
6
  Author: Jean M. Brouwers
@@ -8,7 +8,7 @@ Author-email: mrJean1@Gmail.com
8
8
  Maintainer: Jean M. Brouwers
9
9
  Maintainer-email: mrJean1@Gmail.com
10
10
  License: MIT
11
- Keywords: AER Albers altitude Andoyer annulus antipode area attitude Authalic auxiliary azimuth azimuthal azimuth-elevation-range bearing bank Barsky Barth beta bi-quadratic boolean cached Cagnoli cartesian Cassini Cassini-Soldner chord circle-intersections circumcenter circumcircle circumradius clip Cohen Cohen-Sutherland Collins composite conformal conic constants contact-triangle Cook Correia cosines-law coverage curvature cylindrical datum deprecation deficit development discrete distance Douglas earth east-north-up eccentricity ECEF elevation ellipsoid ellipsoidal-latitude-beta ellipsoidal-longitude-omega elliptic ENU EPSG equal-area equidistant equirectangular ETM ETRF Euclidean even-odd-rule ExactTM excess Farrell Farrell-Barth Ferrari-solution Field-Of-View flattening fma fmath footpoint footprint Forster Forster-Hormann-Popa Forsythe FOV fractional Frechet Fréchet frustum Fsum fused-multiply-add GARS geocentric GeoConvert GeodesicExact geodesy geodetic GeodSolve GeodTest geographiclib Geohash geoid geoidHeight GeoidHeights georef Girard gnomonic gons grades gradians Greiner Greiner-Hormann Hartzell Hausdorff Haversine heading hectare height Heikkinen Heron Hodgman horizon Hormann Hubeny IDW incenter incirle infix_@_operator inradius intermediate interpolate intersect intersection intersection3d intersections IntersectTool Inverse-Distance-Weighting Isometric ITRF Jacobi Jacobi-Conformal Jarque-Bera Jekel Karney Krueger Krüger kurtosis Lambert latitude law-of-cosines least-squares Lesh L_Huilier LHuilier Liang Liang-Barsky linearize Line-Of-Sight LocalCartesian local-tangent-plane local-x-y-z longitude LOS loxodrome lstsq LTP lune LV03 LV95 mean memoize memoized Mercator Meeus MGRS nearest NED Niemeyer non-finite normalize Norrdine north-east-down numpy n-vector Nvector oblate omega orthographic orthometric-height OSGB OSGR overlap parallel parallel-of-latitude Parametric path-intersection perimeter Peucker Pierlot pitch plumb Point-Of-View polar Popa POV precision-cubic-root precision-hypotenuse precision-powers precision-running-summation precision-square-root precision-summation prolate Pseudo-Mercator pygeodesy PyInstaller PyPy quartic radical radii radius Ramer Ramer-Douglas-Peucker Rectifying Reduced resect resection Rey-Jer Reumann Reumann-Witkam rho-theta-phi rhumb RhumbSolve running-linear-regression running-statistics running-stats running-summation scipy secant semi-perimeter sexagecimal simplify skewness Snellius Snellius-Pothenot Snyder Soddy Soddy-circles Soldner sphere sphere-intersections spherical-deficit spherical-excess spherical-polar spherical-triangle squared-quartic standard-deviation stereographic Sudano surface-area Sutherland Sutherland-Hodgman tangent-circles Terrestrial-Reference-Frame Thomas Tienstra tilt TMcoords TMExact toise transverse TransverseMercatorExact TRF triangle triangulate triaxial triaxial-ellipsoid trigonometry trilaterate trilaterate-2d trilaterate-3d TwoProduct TwoSum umbilic-point unit unroll UPS UTM UTM/UPS variance velocities Veness Vermeille viewing-frustum Vincenty Visvalingam Visvalingam-Whyatt volume volumetric Web-Mercator Welford WGRS WGS Whyatt Wildberger Witkam winding-number XYZ yaw You zenzi-cubic zenzi-quartic
11
+ Keywords: AER Albers altitude Andoyer annulus antipode area attitude Authalic auxiliary azimuth azimuthal azimuth-elevation-range bearing bank Barsky Barth beta bi-quadratic boolean cached Cagnoli cartesian Cassini Cassini-Soldner chord circle-intersections circumcenter circumcircle circumradius clip Cohen Cohen-Sutherland Collins composite conformal conformal-sphere conic constants contact-triangle Cook Correia cosines-law coverage curvature cylindrical datum deprecation deficit development discrete distance Douglas earth east-north-up eccentricity ECEF elevation ellipsoid ellipsoidal-latitude-beta ellipsoidal-longitude-omega elliptic ENU EPSG equal-area equidistant equirectangular ETM ETRF Euclidean even-odd-rule ExactTM excess Farrell Farrell-Barth Ferrari-solution Field-Of-View flattening fma fmath footpoint footprint Forster Forster-Hormann-Popa Forsythe FOV fractional Frechet Fréchet frustum Fsum fused-multiply-add GARS geocentric GeoConvert GeodesicExact geodesy geodetic GeodSolve GeodTest geographiclib Geohash geoid geoidHeight GeoidHeights georef Girard gnomonic gons grades gradians Greiner Greiner-Hormann Hartzell Hausdorff Haversine heading hectare height Heikkinen Heron Hodgman horizon Hormann Hubeny IDW incenter incirle infix_@_operator inradius intermediate interpolate intersect intersection intersection3d intersections IntersectTool Inverse-Distance-Weighting Isometric ITRF Jacobi Jacobi-Conformal Jarque-Bera Jekel Karney Krueger Krüger kurtosis Lambert latitude law-of-cosines least-squares Lesh L_Huilier LHuilier Liang Liang-Barsky linearize Line-Of-Sight LocalCartesian local-tangent-plane local-x-y-z longitude LOS loxodrome lstsq LTP lune LV03 LV95 mean memoize memoized Mercator Meeus MGRS nearest NED Niemeyer non-finite normalize Norrdine north-east-down numpy n-vector Nvector oblate omega orthographic orthometric-height OSGB OSGR overlap parallel parallel-of-latitude Parametric path-intersection perimeter Peucker Pierlot pitch plumb Point-Of-View polar Popa POV precision-cubic-root precision-hypotenuse precision-powers precision-running-summation precision-square-root precision-summation prolate Pseudo-Mercator pygeodesy PyInstaller PyPy quartic radical radii radius Ramer Ramer-Douglas-Peucker Rectifying Reduced resect resection Rey-Jer Reumann Reumann-Witkam rho-theta-phi rhumb RhumbSolve running-linear-regression running-statistics running-stats running-summation scipy secant semi-perimeter sexagecimal simplify skewness Snellius Snellius-Pothenot Snyder Soddy Soddy-circles Soldner sphere sphere-intersections spherical-deficit spherical-excess spherical-polar spherical-triangle squared-quartic standard-deviation stereographic Sudano surface-area Sutherland Sutherland-Hodgman tangent-circles Terrestrial-Reference-Frame Thomas Tienstra tilt TMcoords TMExact toise transverse TransverseMercatorExact TRF triangle triangulate triaxial triaxial-ellipsoid trigonometry trilaterate trilaterate-2d trilaterate-3d TwoProduct TwoSum umbilic-point unit unroll UPS UTM UTM/UPS variance velocities Veness Vermeille viewing-frustum Vincenty Visvalingam Visvalingam-Whyatt volume volumetric Web-Mercator Welford WGRS WGS Whyatt Wildberger Witkam winding-number XYZ yaw You zenzi-cubic zenzi-quartic
12
12
  Classifier: Development Status :: 5 - Production/Stable
13
13
  Classifier: Environment :: Console
14
14
  Classifier: Intended Audience :: Developers
@@ -16,7 +16,6 @@ Classifier: License :: OSI Approved :: MIT License
16
16
  Classifier: Operating System :: OS Independent
17
17
  Classifier: Programming Language :: Python
18
18
  Classifier: Programming Language :: Python :: 2.7
19
- Classifier: Programming Language :: Python :: 3.10
20
19
  Classifier: Programming Language :: Python :: 3.11
21
20
  Classifier: Programming Language :: Python :: 3.12
22
21
  Classifier: Programming Language :: Python :: 3.13
@@ -43,7 +42,7 @@ provides a geodetic LatLon_ and a geocentric Cartesian_ class with methods and f
43
42
  distance, surface area, perimeter, forward and reverse azimuth, initial and final bearing, intermediate
44
43
  and nearest points, intersections of geodesic, great circle and rhumb lines, circle intersections and
45
44
  secants, `3-point resections`_, triangulation, trilateration (by intersection, by overlap and in
46
- 3d), conversions and unrolling, among other things.
45
+ 3d), among other things.
47
46
 
48
47
  Also included are modules for conversions to and from `Cassini-Soldner`_, ECEF_ (Earth-Centered,
49
48
  Earth-Fixed cartesian), UTM_ (Universal Transverse Mercator and Exact_), UPS_ (Universal Polar
@@ -60,8 +59,9 @@ operations between (composite) polygons, functions to simplify_ or linearize a p
60
59
  points (or a `numpy array`_), including implementations of the `Ramer-Douglas-Peucker`_,
61
60
  `Visvalingam-Whyatt`_ and `Reumann-Witkam`_ algorithms and modified versions of the former.
62
61
 
63
- Plus modules and classes to interpolate_ the Height_ of *LatLon* points and Geoid_ models, compute
64
- various Fréchet_ or Hausdorff_ distances or perform *boolean* operations between (composite) polygons.
62
+ Plus modules and classes to interpolate_ the Height_ of *LatLon* points and Geoid_ models, to compute
63
+ various Fréchet_ or Hausdorff_ distances or to perform *boolean* operations between (composite)
64
+ polygons of *LatLon* points.
65
65
 
66
66
  For further details see the documentation_, the descriptions of `Latitude/Longitude`_, Vincenty_ and
67
67
  `Vector-based`_ geodesy, the original `JavaScript source`_ or docs_ and *Karney*\'s Python geographiclib_
@@ -120,22 +120,22 @@ test results (on macOS only) and the complete documentation_ generated by Epydoc
120
120
  Tests
121
121
  =====
122
122
 
123
- The tests ran with Python 3.13.7 (with geographiclib_ 2.1), 3.12.7 (with geographiclib_ 2.0, numpy_ 2.1.0,
124
- scipy_ 1.14.1, GeodSolve_ 2.5, IntersectTool_ 2.5 and RhumbSolve_ 2.5), 3.11.5 (with geographiclib_ 2.0,
125
- numpy_ 1.24.2 and scipy_ 1.10.1), Python 3.10.8 (with geographiclib_ 2.0, numpy_ 1.23.3, scipy_ 1.9.1,
126
- GeoConvert_ 2.5, GeodSolve_ 2.5), Python 3.9.6 and Python 2.7.18 (with geographiclib_ 1.50, numpy_ 1.16.6,
127
- scipy_ 1.2.2, GeoConvert_ 2.5, GeodSolve_ 2.5, IntersectTool_ 2.5 and RhumbSolve_ 2.5), all on macOS 15.6.1
128
- Sequoia in 64-bit.
123
+ The tests ran with Python 3.14 (with geographiclib_ 2.1), Python 3.13.7 (with geographiclib_ 2.1,
124
+ numpy_ 2.3.3, scipy_ 1.16.2, GeoConvert_ 2.5 and GeodSolve_ 2.5), Python 3.12.7 (with geographiclib_ 2.0,
125
+ numpy_ 2.1.0, scipy_ 1.14.1, GeodSolve_ 2.5, IntersectTool_ 2.5 and RhumbSolve_ 2.5), Python 3.11.5 (with
126
+ geographiclib_ 2.0, numpy_ 1.24.2 and scipy_ 1.10.1) and with Python 2.7.18 (with geographiclib_ 1.50,
127
+ numpy_ 1.16.6, scipy_ 1.2.2, GeoConvert_ 2.5, GeodSolve_ 2.5, IntersectTool_ 2.5 and RhumbSolve_ 2.5),
128
+ all on macOS 26.0.1 Tahoe in 64-bit.
129
129
 
130
130
  All tests ran with and without ``lazy import`` for Python 3 and with command line option ``-W default``
131
131
  and env variable ``PYGEODESY_WARNINGS=on`` for all Python versions. The results of those tests are
132
132
  included in the distribution files.
133
133
 
134
- Python 3.13.7, 3.12.7, 3.11.5 and 3.10.8 run on Apple M4 Si (``arm64``), *natively*. Python 2.7.18 runs
134
+ Python 3.14, 3.13.7, 3.12.7 and 3.11.5 run on Apple Si M4 (``arm64``), *natively*. Python 2.7.18 runs
135
135
  on Intel (``x86_64``) or Intel *emulation* (\"``arm64_x86_64``\", see function `pygeodesy.machine`_).
136
136
 
137
- Test coverage has been measured with coverage_ 7.6.1 using Python 3.13.7, 3.12.7, 3.11.5 and 3.10.8. The
138
- complete coverage report in HTML and a PDF summary are included in the distribution files.
137
+ Test coverage has been measured with coverage_ 7.10.7 using Python 3.14, 3.13.7 and 3.12.7. The complete
138
+ coverage report in HTML and a PDF summary are included in the distribution files.
139
139
 
140
140
  The tests also ran with Python 3.13.7 (and geographiclib_ 2.1) on `Debian 12`_ in 64-bit only and with
141
141
  Python 3.12.8 (and geographiclib_ 2.0) on `Windows 2019Server`_ in 64-bit only and with Python 2.7.18
@@ -144,13 +144,13 @@ Python 3.12.8 (and geographiclib_ 2.0) on `Windows 2019Server`_ in 64-bit only a
144
144
  A single-File and single-Directory application with ``pygeodesy`` has been bundled using PyInstaller_ 3.4
145
145
  and 64-bit Python 3.7.4 and 3.7.3 on macOS 10.13.6 High Sierra.
146
146
 
147
- Previously, the tests were run with Python 3.13.0-5, 3.12.0-6, 3.11.2-4, 3.10.1-7, 3.9.1, 3.8.7, 3.7.1, 2.7.15,
147
+ Previously, the tests were run with Python 3.13.0-6, 3.12.0-6, 3.11.2-4, 3.10.1-7, 3.9.1, 3.8.7, 3.7.1, 2.7.15,
148
148
  PyPy_ 7.3.12 (Python 3.10.12), 7.3.1 (Python 3.6.9) and PyPy_ 7.1.1 (Python 2.7.13) (and geographiclib_ 1.52,
149
149
  numpy_ 1.16.3, 1.16.4, 1.16.6, 1.19.0, 1.19.4, 1.19.5 or 1.22.4 and scipy_ 1.2.1, 1.4.1, 1.5.2 or 1.8.1) on
150
150
  Ubuntu 16.04, with Python 3.10.0-1, 3.9.0-5, 3.8.0-6, 3.7.2-6, 3.7.0, 3.6.2-5, 3.5.3, 2.7.13-17, 2.7.10
151
151
  and 2.6.9 (and numpy_ 1.19.0, 1.16.5, 1.16.2, 1.15.2, 1.14.0, 1.13.1, 1.8.0rc1 or 1.6.2 and scipy_ 1.5.0),
152
152
  PyPy_ 7.3.0 (Python 2.7.13 and 3.6.9), PyPy_ 6.0.0 (Python 2.7.13 and 3.5.3) and `Intel-Python`_ 3.5.3 (and
153
- numpy_ 1.11.3) on macOS 15.0-5 Sequoia, 14.0-6.1 Sonoma, 13.0-5.2 Ventura, 12.1-6 Monterey, 11.0-5.2-6.1 Big
153
+ numpy_ 1.11.3) on macOS 15.0-6 Sequoia, 14.0-6.1 Sonoma, 13.0-5.2 Ventura, 12.1-6 Monterey, 11.0-5.2-6.1 Big
154
154
  Sur (aka 10.16), 10.15.3, 10.15.5-7 Catalina, 10.14 Mojave, 10.13.6 High Sierra and 10.12 Sierra, MacOS X
155
155
  10.11 El Capitan and/or MacOS X 10.10 Yosemite, with Pythonista_ 3.2 (with geographiclib 1.50 or 1.49 and
156
156
  numpy 1.8.0) on iOS 14.4.2, 11.4.1, 12.0-3 on iPad4, iPhone6, iPhone10 and/or iPhone12, with Pythonista_ 3.1
@@ -160,12 +160,12 @@ Server 2012R2, Windows 10 Pro and 32-bit Python 2.6.6 on Windows XP SP3.
160
160
  Notes
161
161
  =====
162
162
 
163
- All Python source code has been statically checked_ with Ruff_ using Python 3.13.5 and with PyChecker_, PyFlakes_,
164
- PyCodeStyle_ (formerly Pep8) and McCabe_ using Python 2.7.18, both in 64-bit on macOS 15.6.1 Sequoia only.
163
+ All Python source code has been statically checked_ with Ruff_ using Python 3.13.7 and with PyChecker_, PyFlakes_,
164
+ PyCodeStyle_ (formerly Pep8) and McCabe_ using Python 2.7.18, both in 64-bit on macOS 26.0.1 Tahoe only.
165
165
 
166
166
  For a summary of all *Karney*-based functionality in ``pygeodesy``, see module karney_.
167
167
 
168
- *Last updated: Sep 09, 2025.*
168
+ *Last updated: Nov 05, 2025.*
169
169
 
170
170
  License
171
171
  =======