pygeodesy 25.5.25__py2.py3-none-any.whl → 25.5.28__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/__init__.py CHANGED
@@ -604,7 +604,7 @@ else:
604
604
 
605
605
  from pygeodesy.internals import _version2, _DOT_ # noqa: E402
606
606
  # from pygeodesy.interns import _DOT_ # from .internals
607
- __version__ = '25.05.25'
607
+ __version__ = '25.05.28'
608
608
  # see setup.py for similar logic
609
609
  version = _DOT_(*_version2(__version__, n=3))
610
610
 
pygeodesy/__main__.py CHANGED
@@ -5,7 +5,7 @@ u'''Print L{pygeodesy} version, etc. using C{python -m pygeodesy}.
5
5
  '''
6
6
 
7
7
  __all__ = ()
8
- __version__ = '25.04.12'
8
+ __version__ = '25.06.26'
9
9
 
10
10
  from os.path import basename, dirname
11
11
 
@@ -28,6 +28,7 @@ def _main(): # PYCHOK no cover
28
28
  ('isLazy', isLazy),
29
29
  ('_isfrozen', _isfrozen),
30
30
  ('_floats', len(constants._floats)),
31
+ # ('_interns', len(interns.__dict__) - 22),
31
32
  (_DALL_, len(_all_imports())),
32
33
  (_DEPRECATED_, len(_all_deprecates()))))
33
34
 
pygeodesy/booleans.py CHANGED
@@ -45,7 +45,7 @@ from pygeodesy.utily import fabs, _unrollon, _Wrap
45
45
  # from math import fabs # from .utily
46
46
 
47
47
  __all__ = _ALL_LAZY.booleans
48
- __version__ = '25.05.12'
48
+ __version__ = '25.05.26'
49
49
 
50
50
  _0EPS = EPS # near-zero, positive
51
51
  _EPS0 = -EPS # near-zero, negative
@@ -199,8 +199,8 @@ class _LatLonBool(_Named):
199
199
 
200
200
  def __sub__(self, other):
201
201
  _other(self, other)
202
- return self.__class__(self.y - other.y, # classof
203
- self.x - other.x)
202
+ return type(self)(self.y - other.y, # classof
203
+ self.x - other.x)
204
204
 
205
205
  def _2A(self, p2, p3):
206
206
  # I{Signed} area of a triangle, I{doubled}.
@@ -314,7 +314,7 @@ class LatLonFHP(_LatLonBool):
314
314
 
315
315
  def __add__(self, other):
316
316
  _other(self, other)
317
- return self.__class__(self.y + other.y, self.x + other.x)
317
+ return type(self)(self.y + other.y, self.x + other.x)
318
318
 
319
319
  def __mod__(self, other): # cross product
320
320
  _other(self, other)
@@ -326,7 +326,7 @@ class LatLonFHP(_LatLonBool):
326
326
 
327
327
  def __rmul__(self, other): # scalar product
328
328
  _xscalar(other=other)
329
- return self.__class__(self.y * other, self.x * other)
329
+ return type(self)(self.y * other, self.x * other)
330
330
 
331
331
  # def _edge2(self):
332
332
  # # Return the start and end point of the
@@ -959,7 +959,7 @@ class _CompositeBase(_Named):
959
959
  # Return a new instance
960
960
  _g = kwds.get
961
961
  kwds = dict((n, _g(n, v)) for n, v in dflts.items())
962
- return self.__class__(corners or (), **kwds)
962
+ return type(self)(corners or (), **kwds)
963
963
 
964
964
  @property_RO
965
965
  def _clipids(self): # PYCHOK no cover
@@ -1549,7 +1549,7 @@ class _EdgeFHP(object):
1549
1549
  dq = q2 - q1
1550
1550
  dq2 = dq * dq # dot product, hypot2
1551
1551
  if dq2 > EPS2: # like ._clip
1552
- T, _E = None, _EdgeFHP # self.__class__
1552
+ T, _E = None, _EdgeFHP # type(self)
1553
1553
  p1, p2 = self._p1_p2
1554
1554
  ap1 = p1._2A(q1, q2)
1555
1555
  ap2_1 = p2._2A(q1, q2) - ap1
@@ -1750,8 +1750,8 @@ class _BooleanBase(object):
1750
1750
 
1751
1751
  def _boolean4(self, other, op):
1752
1752
  # Set up a new C{Boolean[FHP|GH]}.
1753
- C = self.__class__
1754
- kwds = C._kwds(self, op)
1753
+ C = type(self)
1754
+ kwds = C._kwds(self, op) # PYCHOK in _Composite[FHP|GH]
1755
1755
  a = C(self, **kwds)
1756
1756
  b = _other(self, other)
1757
1757
  return a, b, C, kwds
@@ -1964,7 +1964,7 @@ def _min_max_eps2(*xs):
1964
1964
  def _other(this, other):
1965
1965
  '''(INTERNAL) Check for compatible C{type}s.
1966
1966
  '''
1967
- C = this.__class__
1967
+ C = type(this)
1968
1968
  if isinstance(other, C):
1969
1969
  return other
1970
1970
  raise _IsnotError(C, other=other)
pygeodesy/constants.py CHANGED
@@ -1,8 +1,8 @@
1
1
 
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
- u'''Single-instance C{float} and C{int} constants across C{pygeodesy} modules and
5
- related functions L{pygeodesy.float_}, L{pygeodesy.isclose}, L{pygeodesy.isfinite},
4
+ u'''Single-instance C{float} and C{int} constants across C{pygeodesy} modules and related
5
+ functions L{pygeodesy.float_}, L{pygeodesy.float0_}, L{pygeodesy.isclose}, L{pygeodesy.isfinite},
6
6
  L{pygeodesy.isinf}, L{pygeodesy.isint0}, L{pygeodesy.isnan}, L{pygeodesy.isnear0},
7
7
  L{pygeodesy.isnear1}, L{pygeodesy.isnear90}, L{pygeodesy.isneg0}, L{pygeodesy.isninf},
8
8
  L{pygeodesy.isnon0} and L{pygeodesy.remainder}.
@@ -26,7 +26,7 @@ except ImportError: # Python 2-
26
26
  _inf, _nan = float(_INF_), float(_NAN_)
27
27
 
28
28
  __all__ = _ALL_LAZY.constants
29
- __version__ = '25.05.12'
29
+ __version__ = '25.05.26'
30
30
 
31
31
 
32
32
  def _copysign_0_0(y):
@@ -495,12 +495,12 @@ def _umod_PI2(rad):
495
495
 
496
496
  if __name__ == _DMAIN_:
497
497
 
498
- def _main(locals):
498
+ def _main(globalocals):
499
499
  from pygeodesy import itemsorted, printf
500
500
  from pygeodesy.interns import _DALL_, _UNDER_
501
501
 
502
502
  t = n = v = []
503
- for n, v in itemsorted(locals):
503
+ for n, v in itemsorted(globalocals):
504
504
  if isinstance(v, (Float, Int, Radius)):
505
505
  printf('%9s: %r', n, v.toRepr(std=False))
506
506
  if v.name != n:
@@ -512,7 +512,7 @@ if __name__ == _DMAIN_:
512
512
  t.append(typename(float_))
513
513
  printf('%s = %r', _DALL_, tuple(t))
514
514
 
515
- _main(locals())
515
+ _main(globals()) # or locals()
516
516
 
517
517
  # **) MIT License
518
518
  #
pygeodesy/css.py CHANGED
@@ -470,7 +470,7 @@ class Css(_NamedBase):
470
470
  # h=self.height, cs0=self.cs0,
471
471
  # name=_name__(name, _or_nameof(self)))
472
472
  # args, kwds = _args_kwds(**kwds)
473
- # return self.__class__(*args, **kwds) # .classof
473
+ # return type(self)(*args, **kwds) # .classof
474
474
 
475
475
  @Property_RO
476
476
  def easting(self):
@@ -24,7 +24,7 @@ from pygeodesy.points import _areaError, ispolar # PYCHOK exported
24
24
  # from math import fabs # from .karney
25
25
 
26
26
  __all__ = _ALL_LAZY.ellipsoidalExact
27
- __version__ = '25.05.12'
27
+ __version__ = '25.05.28'
28
28
 
29
29
 
30
30
  class Cartesian(CartesianEllipsoidalBase):
@@ -88,17 +88,19 @@ class LatLon(LatLonEllipsoidalBaseDI):
88
88
  return LatLonEllipsoidalBaseDI.toCartesian(self, **kwds)
89
89
 
90
90
 
91
- def areaOf(points, datum=_WGS84, wrap=True):
91
+ def areaOf(points, datum=_WGS84, wrap=True, polar=False):
92
92
  '''Compute the area of an (ellipsoidal) polygon or composite.
93
93
 
94
- @arg points: The polygon points (L{LatLon}[], L{BooleanFHP} or
95
- L{BooleanGH}).
94
+ @arg points: The polygon points (L{LatLon}[], L{BooleanFHP} or L{BooleanGH}).
96
95
  @kwarg datum: Optional datum (L{Datum}).
97
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
98
- B{C{points}} (C{bool}).
96
+ @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{points}}
97
+ (C{bool}).
98
+ @kwarg polar: Use C{B{polar}=True} if the polygon encloses a pole (C{bool}), see
99
+ function L{ispolar<pygeodesy.points.ispolar>} and U{area of a polygon
100
+ enclosing a pole<https://GeographicLib.SourceForge.io/C++/doc/
101
+ classGeographicLib_1_1GeodesicExact.html#a3d7a9155e838a09a48dc14d0c3fac525>}.
99
102
 
100
- @return: Area (C{meter} I{squared}, same units as the B{C{datum}}'s
101
- ellipsoid axes).
103
+ @return: Area (C{meter} I{squared}, same units as the B{C{datum}}'s ellipsoid axes).
102
104
 
103
105
  @raise PointsError: Insufficient number of B{C{points}}.
104
106
 
@@ -110,12 +112,8 @@ def areaOf(points, datum=_WGS84, wrap=True):
110
112
  @see: Functions L{pygeodesy.areaOf}, L{ellipsoidalGeodSolve.areaOf},
111
113
  L{ellipsoidalKarney.areaOf}, L{sphericalNvector.areaOf} and
112
114
  L{sphericalTrigonometry.areaOf}.
113
-
114
- @note: The U{area of a polygon enclosing a pole<https://GeographicLib.SourceForge.io/
115
- C++/doc/classGeographicLib_1_1GeodesicExact.html#a3d7a9155e838a09a48dc14d0c3fac525>}
116
- can be found by adding half the datum's ellipsoid surface area to the polygon's area.
117
115
  '''
118
- return fabs(_polygon(datum.ellipsoid.geodesicx, points, True, False, wrap))
116
+ return fabs(_polygon(datum.ellipsoid.geodesicx, points, True, False, wrap, polar))
119
117
 
120
118
 
121
119
  def intersection3(start1, end1, start2, end2, height=None, wrap=False, # was=True
@@ -216,13 +214,14 @@ def intersections2(center1, radius1, center2, radius2, height=None, wrap=False,
216
214
  equidistant=equidistant, tol=tol, **kwds)
217
215
 
218
216
 
219
- def isclockwise(points, datum=_WGS84, wrap=True):
217
+ def isclockwise(points, datum=_WGS84, wrap=True, polar=False):
220
218
  '''Determine the direction of a path or polygon.
221
219
 
222
220
  @arg points: The path or polygon points (C{LatLon}[]).
223
221
  @kwarg datum: Optional datum (L{Datum}).
224
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
225
- B{C{points}} (C{bool}).
222
+ @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{points}} (C{bool}).
223
+ @kwarg polar: Use C{B{polar}=True} if the C{B{points}} enclose a pole (C{bool}),
224
+ see function U{ispolar<pygeodeys.points.ispolar>}.
226
225
 
227
226
  @return: C{True} if B{C{points}} are clockwise, C{False} otherwise.
228
227
 
@@ -234,7 +233,7 @@ def isclockwise(points, datum=_WGS84, wrap=True):
234
233
 
235
234
  @see: L{pygeodesy.isclockwise}.
236
235
  '''
237
- a = _polygon(datum.ellipsoid.geodesicx, points, True, False, wrap)
236
+ a = _polygon(datum.ellipsoid.geodesicx, points, True, False, wrap, polar)
238
237
  if a < 0:
239
238
  return True
240
239
  elif a > 0:
@@ -288,29 +287,25 @@ def nearestOn(point, point1, point2, within=True, height=None, wrap=False,
288
287
  def perimeterOf(points, closed=False, datum=_WGS84, wrap=True):
289
288
  '''Compute the perimeter of an (ellipsoidal) polygon or composite.
290
289
 
291
- @arg points: The polygon points (L{LatLon}[], L{BooleanFHP} or
292
- L{BooleanGH}).
290
+ @arg points: The polygon points (L{LatLon}[], L{BooleanFHP} or L{BooleanGH}).
293
291
  @kwarg closed: Optionally, close the polygon (C{bool}).
294
292
  @kwarg datum: Optional datum (L{Datum}).
295
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
296
- B{C{points}} (C{bool}).
293
+ @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{points}} (C{bool}).
297
294
 
298
- @return: Perimeter (C{meter}, same units as the B{C{datum}}'s
299
- ellipsoid axes).
295
+ @return: Perimeter (C{meter}, same units as the B{C{datum}}'s ellipsoid axes).
300
296
 
301
297
  @raise PointsError: Insufficient number of B{C{points}}.
302
298
 
303
299
  @raise TypeError: Some B{C{points}} are not L{LatLon}.
304
300
 
305
- @raise ValueError: Invalid C{B{wrap}=False}, unwrapped, unrolled
306
- longitudes not supported or C{B{closed}=False}
307
- with C{B{points}} a composite.
301
+ @raise ValueError: Invalid C{B{wrap}=False}, unwrapped, unrolled longitudes not
302
+ supported or C{B{closed}=False} with C{B{points}} a composite.
308
303
 
309
304
  @see: Functions L{pygeodesy.perimeterOf}, L{ellipsoidalGeodSolve.perimeterOf},
310
305
  L{ellipsoidalKarney.perimeterOf}, L{sphericalNvector.perimeterOf} and
311
306
  L{sphericalTrigonometry.perimeterOf}.
312
307
  '''
313
- return _polygon(datum.ellipsoid.geodesicx, points, closed, True, wrap)
308
+ return _polygon(datum.ellipsoid.geodesicx, points, closed, True, wrap, False)
314
309
 
315
310
 
316
311
  __all__ += _ALL_OTHER(Cartesian, LatLon, # classes
@@ -24,7 +24,7 @@ from pygeodesy.points import _areaError, ispolar # PYCHOK exported
24
24
  # from math import fabs # from .karney
25
25
 
26
26
  __all__ = _ALL_LAZY.ellipsoidalGeodSolve
27
- __version__ = '24.08.13'
27
+ __version__ = '25.05.28'
28
28
 
29
29
 
30
30
  class Cartesian(CartesianEllipsoidalBase):
@@ -87,12 +87,16 @@ class LatLon(LatLonEllipsoidalBaseDI):
87
87
  return LatLonEllipsoidalBaseDI.toCartesian(self, **kwds)
88
88
 
89
89
 
90
- def areaOf(points, datum=_WGS84, wrap=True):
90
+ def areaOf(points, datum=_WGS84, wrap=True, polar=False):
91
91
  '''Compute the area of an (ellipsoidal) polygon or composite.
92
92
 
93
93
  @arg points: The polygon points (L{LatLon}[], L{BooleanFHP} or L{BooleanGH}).
94
94
  @kwarg datum: Optional datum (L{Datum}).
95
95
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{points}} (C{bool}).
96
+ @kwarg polar: Use C{B{polar}=True} if the polygon encloses a pole (C{bool}), see
97
+ function L{ispolar<pygeodesy.points.ispolar>} and U{area of a polygon
98
+ enclosing a pole<https://GeographicLib.SourceForge.io/C++/doc/
99
+ classGeographicLib_1_1GeodesicExact.html#a3d7a9155e838a09a48dc14d0c3fac525>}.
96
100
 
97
101
  @return: Area (C{meter}, same as units of the B{C{datum}}'s ellipsoid axes, I{squared}).
98
102
 
@@ -105,7 +109,7 @@ def areaOf(points, datum=_WGS84, wrap=True):
105
109
  @see: Functions L{pygeodesy.areaOf}, L{ellipsoidalExact.areaOf}, L{ellipsoidalKarney.areaOf},
106
110
  L{sphericalNvector.areaOf} and L{sphericalTrigonometry.areaOf}.
107
111
  '''
108
- return fabs(_polygon(datum.ellipsoid.geodsolve, points, True, False, wrap))
112
+ return fabs(_polygon(datum.ellipsoid.geodsolve, points, True, False, wrap, polar))
109
113
 
110
114
 
111
115
  def intersection3(start1, end1, start2, end2, height=None, wrap=False, # was=True
@@ -209,13 +213,14 @@ def intersections2(center1, radius1, center2, radius2, height=None, wrap=False,
209
213
  equidistant=equidistant, tol=tol, LatLon=LatLon, **LatLon_kwds)
210
214
 
211
215
 
212
- def isclockwise(points, datum=_WGS84, wrap=True):
216
+ def isclockwise(points, datum=_WGS84, wrap=True, polar=False):
213
217
  '''Determine the direction of a path or polygon.
214
218
 
215
219
  @arg points: The path or polygon points (C{LatLon}[]).
216
220
  @kwarg datum: Optional datum (L{Datum}).
217
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
218
- B{C{points}} (C{bool}).
221
+ @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{points}} (C{bool}).
222
+ @kwarg polar: Use C{B{polar}=True} if the C{B{points}} enclose a pole (C{bool}),
223
+ see function U{ispolar<pygeodeys.points.ispolar>}.
219
224
 
220
225
  @return: C{True} if B{C{points}} are clockwise, C{False} otherwise.
221
226
 
@@ -223,12 +228,11 @@ def isclockwise(points, datum=_WGS84, wrap=True):
223
228
 
224
229
  @raise TypeError: Some B{C{points}} are not C{LatLon}.
225
230
 
226
- @raise ValueError: The B{C{points}} enclose a pole or zero
227
- area.
231
+ @raise ValueError: The B{C{points}} enclose a pole or zero area.
228
232
 
229
233
  @see: L{pygeodesy.isclockwise}.
230
234
  '''
231
- a = _polygon(datum.ellipsoid.geodsolve, points, True, False, wrap)
235
+ a = _polygon(datum.ellipsoid.geodsolve, points, True, False, wrap, polar)
232
236
  if a < 0:
233
237
  return True
234
238
  elif a > 0:
@@ -282,29 +286,25 @@ def nearestOn(point, point1, point2, within=True, height=None, wrap=False,
282
286
  def perimeterOf(points, closed=False, datum=_WGS84, wrap=True):
283
287
  '''Compute the perimeter of an (ellipsoidal) polygon or composite.
284
288
 
285
- @arg points: The polygon points (L{LatLon}[], L{BooleanFHP} or
286
- L{BooleanGH}).
289
+ @arg points: The polygon points (L{LatLon}[], L{BooleanFHP} or L{BooleanGH}).
287
290
  @kwarg closed: Optionally, close the polygon (C{bool}).
288
291
  @kwarg datum: Optional datum (L{Datum}).
289
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
290
- B{C{points}} (C{bool}).
292
+ @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{points}} (C{bool}).
291
293
 
292
- @return: Perimeter (C{meter}, same as units of the B{C{datum}}'s
293
- ellipsoid axes).
294
+ @return: Perimeter (C{meter}, same as units of the B{C{datum}}'s ellipsoid axes).
294
295
 
295
296
  @raise PointsError: Insufficient number of B{C{points}}.
296
297
 
297
298
  @raise TypeError: Some B{C{points}} are not L{LatLon}.
298
299
 
299
- @raise ValueError: Invalid C{B{wrap}=False}, unwrapped, unrolled
300
- longitudes not supported or C{B{closed}=False}
301
- with C{B{points}} a composite.
300
+ @raise ValueError: Invalid C{B{wrap}=False}, unwrapped, unrolled longitudes not
301
+ supported or C{B{closed}=False} with C{B{points}} a composite.
302
302
 
303
303
  @see: Functions L{pygeodesy.perimeterOf}, L{ellipsoidalExact.perimeterOf},
304
304
  L{ellipsoidalKarney.perimeterOf}, L{sphericalNvector.perimeterOf}
305
305
  and L{sphericalTrigonometry.perimeterOf}.
306
306
  '''
307
- return _polygon(datum.ellipsoid.geodsolve, points, closed, True, wrap)
307
+ return _polygon(datum.ellipsoid.geodsolve, points, closed, True, wrap, False)
308
308
 
309
309
 
310
310
  __all__ += _ALL_OTHER(Cartesian, LatLon, # classes
@@ -42,7 +42,7 @@ from pygeodesy.props import deprecated_method, Property_RO
42
42
  # from math import fabs # from .karney
43
43
 
44
44
  __all__ = _ALL_LAZY.ellipsoidalKarney
45
- __version__ = '24.08.13'
45
+ __version__ = '25.05.27'
46
46
 
47
47
 
48
48
  class Cartesian(CartesianEllipsoidalBase):
@@ -110,13 +110,17 @@ class LatLon(LatLonEllipsoidalBaseDI):
110
110
  return LatLonEllipsoidalBaseDI.toCartesian(self, **kwds)
111
111
 
112
112
 
113
- def areaOf(points, datum=_WGS84, wrap=True):
113
+ def areaOf(points, datum=_WGS84, wrap=True, polar=False):
114
114
  '''Compute the area of an (ellipsoidal) polygon or composite using I{Karney}'s
115
115
  U{geographiclib<https://PyPI.org/project/geographiclib>} package.
116
116
 
117
117
  @arg points: The polygon points (L{LatLon}[], L{BooleanFHP} or L{BooleanGH}).
118
118
  @kwarg datum: Optional datum (L{Datum}).
119
119
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{points}} (C{bool}).
120
+ @kwarg polar: Use C{B{polar}=True} if the polygon encloses a pole (C{bool}), see
121
+ function L{ispolar<pygeodesy.points.ispolar>} and U{area of a polygon
122
+ enclosing a pole<https://GeographicLib.SourceForge.io/C++/doc/
123
+ classGeographicLib_1_1GeodesicExact.html#a3d7a9155e838a09a48dc14d0c3fac525>}.
120
124
 
121
125
  @return: Area (C{meter}, same as units of the B{C{datum}}'s ellipsoid axes, I{squared}).
122
126
 
@@ -131,12 +135,8 @@ def areaOf(points, datum=_WGS84, wrap=True):
131
135
 
132
136
  @see: Functions L{pygeodesy.areaOf}, L{ellipsoidalExact.areaOf}, L{ellipsoidalGeodSolve.areaOf},
133
137
  L{sphericalNvector.areaOf} and L{sphericalTrigonometry.areaOf}.
134
-
135
- @note: The U{area of a polygon enclosing a pole<https://GeographicLib.SourceForge.io/
136
- C++/doc/classGeographicLib_1_1GeodesicExact.html#a3d7a9155e838a09a48dc14d0c3fac525>}
137
- can be found by adding half the datum's ellipsoid surface area to the polygon's area.
138
138
  '''
139
- return fabs(_polygon(datum.ellipsoid.geodesic, points, True, False, wrap))
139
+ return fabs(_polygon(datum.ellipsoid.geodesic, points, True, False, wrap, polar))
140
140
 
141
141
 
142
142
  def intersection3(start1, end1, start2, end2, height=None, wrap=False, # was=True
@@ -240,19 +240,19 @@ def intersections2(center1, radius1, center2, radius2, height=None, wrap=False,
240
240
  equidistant=equidistant, tol=tol, LatLon=LatLon, **LatLon_kwds)
241
241
 
242
242
 
243
- def isclockwise(points, datum=_WGS84, wrap=True):
243
+ def isclockwise(points, datum=_WGS84, wrap=True, polar=False):
244
244
  '''Determine the direction of a path or polygon using I{Karney}'s
245
245
  U{geographiclib<https://PyPI.org/project/geographiclib>} package.
246
246
 
247
247
  @arg points: The path or polygon points (C{LatLon}[]).
248
248
  @kwarg datum: Optional datum (L{Datum}).
249
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
250
- B{C{points}} (C{bool}).
249
+ @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{points}} (C{bool}).
250
+ @kwarg polar: Use C{B{polar}=True} if the C{B{points}} enclose a pole (C{bool}),
251
+ see function U{ispolar<pygeodeys.points.ispolar>}.
251
252
 
252
253
  @return: C{True} if B{C{points}} are clockwise, C{False} otherwise.
253
254
 
254
- @raise ImportError: Package U{geographiclib
255
- <https://PyPI.org/project/geographiclib>}
255
+ @raise ImportError: Package U{geographiclib<https://PyPI.org/project/geographiclib>}
256
256
  not installed or not found.
257
257
 
258
258
  @raise PointsError: Insufficient number of B{C{points}}.
@@ -263,7 +263,7 @@ def isclockwise(points, datum=_WGS84, wrap=True):
263
263
 
264
264
  @see: L{pygeodesy.isclockwise}.
265
265
  '''
266
- a = _polygon(datum.ellipsoid.geodesic, points, True, False, wrap)
266
+ a = _polygon(datum.ellipsoid.geodesic, points, True, False, wrap, polar)
267
267
  if a < 0:
268
268
  return True
269
269
  elif a > 0:
@@ -322,34 +322,29 @@ def perimeterOf(points, closed=False, datum=_WGS84, wrap=True):
322
322
  '''Compute the perimeter of an (ellipsoidal) polygon or composite using I{Karney}'s
323
323
  U{geographiclib<https://PyPI.org/project/geographiclib>} package.
324
324
 
325
- @arg points: The polygon points (L{LatLon}[], L{BooleanFHP} or
326
- L{BooleanGH}).
325
+ @arg points: The polygon points (L{LatLon}[], L{BooleanFHP} or L{BooleanGH}).
327
326
  @kwarg closed: Optionally, close the polygon (C{bool}).
328
327
  @kwarg datum: Optional datum (L{Datum}).
329
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
330
- B{C{points}} (C{bool}).
328
+ @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{points}} (C{bool}).
331
329
 
332
- @return: Perimeter (C{meter}, same as units of the B{C{datum}}'s
333
- ellipsoid axes).
330
+ @return: Perimeter (C{meter}, same as units of the B{C{datum}}'s ellipsoid axes).
334
331
 
335
- @raise ImportError: Package U{geographiclib
336
- <https://PyPI.org/project/geographiclib>}
332
+ @raise ImportError: Package U{geographiclib<https://PyPI.org/project/geographiclib>}
337
333
  not installed or not found.
338
334
 
339
335
  @raise PointsError: Insufficient number of B{C{points}}.
340
336
 
341
- @raise TypeError: Some B{C{points}} are not L{LatLon} or C{B{closed}=False}
342
- with B{C{points}} a composite.
337
+ @raise TypeError: Some B{C{points}} are not L{LatLon} or C{B{closed}=False} with
338
+ B{C{points}} a composite.
343
339
 
344
- @raise ValueError: Invalid C{B{wrap}=False}, unwrapped, unrolled
345
- longitudes not supported or C{B{closed}=False}
346
- with C{B{points}} a composite.
340
+ @raise ValueError: Invalid C{B{wrap}=False}, unwrapped, unrolled longitudes not
341
+ supported or C{B{closed}=False} with C{B{points}} a composite.
347
342
 
348
343
  @see: Functions L{pygeodesy.perimeterOf}, L{ellipsoidalExact.perimeterOf},
349
344
  L{ellipsoidalGeodSolve.perimeterOf}, L{sphericalNvector.perimeterOf}
350
345
  and L{sphericalTrigonometry.perimeterOf}.
351
346
  '''
352
- return _polygon(datum.ellipsoid.geodesic, points, closed, True, wrap)
347
+ return _polygon(datum.ellipsoid.geodesic, points, closed, True, wrap, False)
353
348
 
354
349
 
355
350
  __all__ += _ALL_OTHER(Cartesian, LatLon, # classes
@@ -76,7 +76,7 @@ from pygeodesy.utily import atan2, atan2b, atan2d, sincos2, sincos2d, \
76
76
  from math import cos, degrees, fabs, radians, tan as _tan
77
77
 
78
78
  __all__ = _ALL_LAZY.ellipsoidalVincenty
79
- __version__ = '25.05.23'
79
+ __version__ = '25.05.26'
80
80
 
81
81
  _antipodal_to_ = _SPACE_(_antipodal_, _to_)
82
82
 
@@ -349,13 +349,6 @@ def _c2sm2(c2sm):
349
349
  return c2sm**2 * _2_0 - _1_0
350
350
 
351
351
 
352
- def _ellipsoidal(): # helper for areaOf and perimeterOf
353
- try:
354
- return _MODS.ellipsoidalKarney
355
- except ImportError:
356
- return _MODS.ellipsoidalExact
357
-
358
-
359
352
  def _Dl(f, ca2, sa, s, cs, ss, c2sm, dl=_0_0):
360
353
  # C{Dl}
361
354
  if f and sa:
@@ -385,6 +378,14 @@ def _Ecef():
385
378
  return E
386
379
 
387
380
 
381
+ def _ellipsoidalOf(_Of, points, **kwds): # helper for DEPRECATED areaOf and perimeterOf
382
+ try:
383
+ r = getattr(_MODS.ellipsoidalKarney, _Of.__name__)(points, **kwds)
384
+ except ImportError: # no geographiclib
385
+ r = getattr(_MODS.ellipsoidalExact, _Of.__name__)(points, **kwds)
386
+ return r
387
+
388
+
388
389
  def _sincos22(sa):
389
390
  # 2-Tuple C{(sin(a), cos(a)**2)}
390
391
  ca2 = _1_0 - sa**2
@@ -403,10 +404,10 @@ def _sincostan3r(a, f):
403
404
 
404
405
 
405
406
  @deprecated_function
406
- def areaOf(points, **datum_wrap):
407
+ def areaOf(points, **datum_wrap_polar):
407
408
  '''DEPRECATED, use function L{ellipsoidalExact.areaOf} or L{ellipsoidalKarney.areaOf}.
408
409
  '''
409
- return _ellipsoidal().areaOf(points, **datum_wrap)
410
+ return _ellipsoidalOf(areaOf, points, **datum_wrap_polar)
410
411
 
411
412
 
412
413
  def intersection3(start1, end1, start2, end2, height=None, wrap=False, # was=True
@@ -562,7 +563,7 @@ def nearestOn(point, point1, point2, within=True, height=None, wrap=False,
562
563
  def perimeterOf(points, **closed_datum_wrap):
563
564
  '''DEPRECATED, use function L{ellipsoidalExact.perimeterOf} or L{ellipsoidalKarney.perimeterOf}.
564
565
  '''
565
- return _ellipsoidal().perimeterOf(points, **closed_datum_wrap)
566
+ return _ellipsoidalOf(perimeterOf, points, **closed_datum_wrap)
566
567
 
567
568
 
568
569
  __all__ += _ALL_DOCS(Cartesian, LatLon, intersecant2, # from .ellipsoidalBaseDI
pygeodesy/elliptic.py CHANGED
@@ -99,7 +99,7 @@ from math import asin, asinh, atan, ceil, cosh, fabs, floor, radians, \
99
99
  sin, sinh, sqrt, tan, tanh # tan as _tan
100
100
 
101
101
  __all__ = _ALL_LAZY.elliptic
102
- __version__ = '25.05.12'
102
+ __version__ = '25.05.28'
103
103
 
104
104
  _TolRD = zqrt(EPS * 0.002)
105
105
  _TolRF = zqrt(EPS * 0.030)
@@ -165,9 +165,9 @@ class Elliptic(_Named):
165
165
  that case, we have C{Π(φ, 0, k) = F(φ, k), G(φ, 0, k) =
166
166
  E(φ, k)} and C{H(φ, 0, k) = F(φ, k) - D(φ, k)}.
167
167
  '''
168
- self.reset(k2=k2, alpha2=alpha2, kp2=kp2, alphap2=alphap2)
169
168
  if name:
170
169
  self.name = name
170
+ self.reset(k2=k2, alpha2=alpha2, kp2=kp2, alphap2=alphap2)
171
171
 
172
172
  @Property_RO
173
173
  def alpha2(self):
@@ -760,15 +760,20 @@ class Elliptic(_Named):
760
760
  that these conditions are met to enable accuracy to be
761
761
  maintained, e.g., when C{k} is very close to unity.
762
762
  '''
763
+ def _1p2(kp2, k2):
764
+ return (_1_0 - k2) if kp2 is None else kp2
765
+
766
+ def _S(**kwds):
767
+ return Scalar_(Error=EllipticError, **kwds)
768
+
763
769
  if self.__dict__:
764
770
  _update_all(self, _Named.iteration._uname, Base=Property_RO)
765
771
 
766
- self._k2 = Scalar_(k2=k2, Error=EllipticError, low=None, high=_1_0)
767
- self._kp2 = Scalar_(kp2=((_1_0 - k2) if kp2 is None else kp2), Error=EllipticError)
772
+ self._k2 = _S(k2 = k2, low=None, high=_1_0)
773
+ self._kp2 = _S(kp2=_1p2(kp2, k2)) # low=_0_0
768
774
 
769
- self._alpha2 = Scalar_(alpha2=alpha2, Error=EllipticError, low=None, high=_1_0)
770
- self._alphap2 = Scalar_(alphap2=((_1_0 - alpha2) if alphap2 is None else alphap2),
771
- Error=EllipticError)
775
+ self._alpha2 = _S(alpha2 = alpha2, low=None, high=_1_0)
776
+ self._alphap2 = _S(alphap2=_1p2(alphap2, alpha2)) # low=_0_0
772
777
 
773
778
  # Values of complete elliptic integrals for k = 0,1 and alpha = 0,1
774
779
  # K E D
@@ -1120,11 +1125,11 @@ def _rC(unused, x, y):
1120
1125
  '''(INTERNAL) Defined only for C{y != 0} and C{x >= 0}.
1121
1126
  '''
1122
1127
  d = x - y
1123
- if d < 0: # catch NaN
1128
+ if x < y: # catch NaN
1124
1129
  # <https://DLMF.NIST.gov/19.2.E18>
1125
- d = -d
1130
+ d = y - x
1126
1131
  r = atan(sqrt(d / x)) if x > 0 else PI_2
1127
- elif d == 0: # XXX d < EPS0? or EPS02 or _EPSmin
1132
+ elif x == y: # XXX d < EPS0? or EPS02 or _EPSmin
1128
1133
  d, r = y, _1_0
1129
1134
  elif y > 0: # <https://DLMF.NIST.gov/19.2.E19>
1130
1135
  r = asinh(sqrt(d / y)) # atanh(sqrt((x - y) / x))
pygeodesy/frechet.py CHANGED
@@ -101,7 +101,7 @@ from collections import defaultdict as _defaultdict
101
101
  # from math import radians # from .points
102
102
 
103
103
  __all__ = _ALL_LAZY.frechet
104
- __version__ = '25.05.21'
104
+ __version__ = '25.05.26'
105
105
 
106
106
  _formy = _MODS.into(formy=__name__)
107
107
 
@@ -153,7 +153,7 @@ class Frechet(_Named):
153
153
  @raise FrechetError: Insufficient number of B{C{point1s}} or an invalid
154
154
  B{C{point1}}, B{C{fraction}} or B{C{units}}.
155
155
  '''
156
- name, kwds = _name2__(**name__kwds) # name__=self.__class__
156
+ name, kwds = _name2__(**name__kwds) # name__=type(self)
157
157
  if name:
158
158
  self.name = name
159
159