pygeodesy 24.10.10__py2.py3-none-any.whl → 24.11.11__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 (76) hide show
  1. {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/METADATA +12 -12
  2. PyGeodesy-24.11.11.dist-info/RECORD +118 -0
  3. {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/WHEEL +1 -1
  4. pygeodesy/__init__.py +14 -14
  5. pygeodesy/__main__.py +5 -5
  6. pygeodesy/albers.py +12 -17
  7. pygeodesy/azimuthal.py +51 -61
  8. pygeodesy/basics.py +60 -62
  9. pygeodesy/booleans.py +87 -79
  10. pygeodesy/cartesianBase.py +6 -6
  11. pygeodesy/constants.py +23 -19
  12. pygeodesy/css.py +7 -8
  13. pygeodesy/datums.py +3 -3
  14. pygeodesy/deprecated/__init__.py +1 -1
  15. pygeodesy/deprecated/classes.py +9 -9
  16. pygeodesy/deprecated/functions.py +6 -6
  17. pygeodesy/dms.py +250 -270
  18. pygeodesy/ecef.py +11 -14
  19. pygeodesy/ellipsoidalBase.py +106 -121
  20. pygeodesy/ellipsoidalBaseDI.py +114 -118
  21. pygeodesy/ellipsoidalExact.py +35 -37
  22. pygeodesy/ellipsoidalNvector.py +4 -4
  23. pygeodesy/ellipsoidalVincenty.py +2 -2
  24. pygeodesy/ellipsoids.py +10 -51
  25. pygeodesy/elliptic.py +14 -14
  26. pygeodesy/errors.py +28 -28
  27. pygeodesy/etm.py +92 -68
  28. pygeodesy/fmath.py +42 -40
  29. pygeodesy/formy.py +7 -6
  30. pygeodesy/fsums.py +72 -51
  31. pygeodesy/geodesici.py +43 -40
  32. pygeodesy/geodesicw.py +17 -16
  33. pygeodesy/geodesicx/__init__.py +2 -2
  34. pygeodesy/geodesicx/gxarea.py +3 -2
  35. pygeodesy/geodsolve.py +79 -39
  36. pygeodesy/geohash.py +2 -2
  37. pygeodesy/geoids.py +32 -31
  38. pygeodesy/heights.py +2 -2
  39. pygeodesy/internals.py +201 -147
  40. pygeodesy/interns.py +23 -20
  41. pygeodesy/karney.py +62 -13
  42. pygeodesy/ktm.py +11 -13
  43. pygeodesy/latlonBase.py +18 -20
  44. pygeodesy/lazily.py +210 -218
  45. pygeodesy/lcc.py +4 -4
  46. pygeodesy/ltp.py +10 -10
  47. pygeodesy/ltpTuples.py +74 -75
  48. pygeodesy/mgrs.py +20 -21
  49. pygeodesy/named.py +15 -10
  50. pygeodesy/nvectorBase.py +1 -1
  51. pygeodesy/osgr.py +9 -12
  52. pygeodesy/points.py +2 -2
  53. pygeodesy/props.py +35 -14
  54. pygeodesy/resections.py +9 -10
  55. pygeodesy/rhumb/__init__.py +1 -1
  56. pygeodesy/rhumb/bases.py +5 -5
  57. pygeodesy/rhumb/solve.py +9 -10
  58. pygeodesy/simplify.py +5 -5
  59. pygeodesy/solveBase.py +7 -25
  60. pygeodesy/sphericalBase.py +20 -23
  61. pygeodesy/sphericalNvector.py +103 -145
  62. pygeodesy/sphericalTrigonometry.py +68 -73
  63. pygeodesy/streprs.py +5 -5
  64. pygeodesy/trf.py +6 -4
  65. pygeodesy/triaxials.py +46 -9
  66. pygeodesy/units.py +5 -4
  67. pygeodesy/ups.py +6 -6
  68. pygeodesy/utily.py +2 -2
  69. pygeodesy/utm.py +7 -7
  70. pygeodesy/vector2d.py +13 -13
  71. pygeodesy/vector3d.py +19 -21
  72. pygeodesy/vector3dBase.py +21 -19
  73. pygeodesy/webmercator.py +4 -4
  74. pygeodesy/wgrs.py +4 -4
  75. PyGeodesy-24.10.10.dist-info/RECORD +0 -118
  76. {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/top_level.txt +0 -0
@@ -9,7 +9,7 @@ from __future__ import division as _; del _ # PYCHOK semicolon
9
9
 
10
10
  from pygeodesy.basics import isLatLon, _xsubclassof
11
11
  from pygeodesy.constants import EPS, MAX, PI, PI2, PI_4, isnear0, isnear1, \
12
- _EPSqrt as _TOL, _0_0, _0_5, _1_5, _3_0
12
+ _EPSqrt as _TOL, _0_0, _0_01, _1_0, _1_5, _3_0
13
13
  # from pygeodesy.dms import F_DMS # _MODS
14
14
  from pygeodesy.ellipsoidalBase import LatLonEllipsoidalBase, _TOL_M, property_RO
15
15
  from pygeodesy.errors import _AssertionError, IntersectionError, _IsnotError, \
@@ -34,11 +34,10 @@ from pygeodesy.utily import m2km, unroll180, _unrollon, _unrollon3, \
34
34
  from math import degrees, radians
35
35
 
36
36
  __all__ = _ALL_LAZY.ellipsoidalBaseDI
37
- __version__ = '24.09.26'
37
+ __version__ = '24.11.04'
38
38
 
39
- _polar__ = 'polar?'
40
- _B2END = _1_5 # _intersect3 bearing to pseudo-end point factor
41
- _TRIPS = 33 # _intersect3, _intersects2, _nearestOn interations, 6..9 sufficient?
39
+ _polar__ = 'polar?'
40
+ _TRIPS = 33 # _intersect3, _intersects2, _nearestOn interations, 6..9 sufficient?
42
41
 
43
42
 
44
43
  class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
@@ -52,13 +51,13 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
52
51
  method. See methods L{initialBearingTo} and L{finalBearingTo}
53
52
  for more details.
54
53
 
55
- @arg other: The other point (C{LatLon}).
54
+ @arg other: The other point (this C{LatLon}).
56
55
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
57
56
  B{C{other}} point (C{bool}).
58
57
 
59
58
  @return: A L{Bearing2Tuple}C{(initial, final)}.
60
59
 
61
- @raise TypeError: The B{C{other}} point is not C{LatLon}.
60
+ @raise TypeError: If B{C{other}} not this C{LatLon} class.
62
61
 
63
62
  @raise ValueError: If this and the B{C{other}} point's L{Datum}
64
63
  ellipsoids are not compatible.
@@ -69,13 +68,8 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
69
68
  def destination(self, distance, bearing, height=None):
70
69
  '''Compute the destination point after having travelled for
71
70
  the given distance from this point along a geodesic given
72
- by an initial bearing, using this C{Direct} method. See
73
- method L{destination2} for more details.
74
-
75
- @arg distance: Distance (C{meter}).
76
- @arg bearing: Initial bearing in (compass C{degrees360}).
77
- @kwarg height: Optional height, overriding the default
78
- height (C{meter}, same units as C{distance}).
71
+ by an initial bearing. See method L{destination2} for
72
+ further details.
79
73
 
80
74
  @return: The destination point (C{LatLon}).
81
75
  '''
@@ -84,15 +78,16 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
84
78
  def destination2(self, distance, bearing, height=None):
85
79
  '''Compute the destination point and the final bearing (reverse
86
80
  azimuth) after having travelled for the given distance from
87
- this point along a geodesic given by an initial bearing,
88
- using this C{Direct} method.
81
+ this point along a geodesic (line) given by an initial bearing
82
+ at this point.
89
83
 
90
- The distance must be in the same units as this point's datum
91
- axes, conventionally C{meter}. The distance is measured on
92
- the surface of the ellipsoid, ignoring this point's height.
84
+ The distance must be in the same units as this point's datum's
85
+ ellipsoid's axes, conventionally C{meter}. The distance is
86
+ measured on the surface of the ellipsoid, ignoring this point's
87
+ height.
93
88
 
94
89
  The initial and final bearing (forward and reverse azimuth)
95
- are in compass C{degrees360}.
90
+ are in compass C{degrees360}, clockwise from North.
96
91
 
97
92
  The destination point's height and datum are set to this
98
93
  point's height and datum, unless the former is overridden.
@@ -104,8 +99,7 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
104
99
 
105
100
  @return: A L{Destination2Tuple}C{(destination, final)}.
106
101
  '''
107
- r = self._Direct(distance, bearing, self.classof, height)
108
- return self._xnamed(r)
102
+ return self._Direct(distance, bearing, self.classof, height)
109
103
 
110
104
  def _Direct(self, distance, bearing, LL, height): # overloaded by I{Vincenty}
111
105
  '''(INTERNAL) I{Karney}'s C{Direct} method.
@@ -122,27 +116,26 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
122
116
  def _Direct2Tuple(self, LL, height, r):
123
117
  '''(INTERNAL) Helper for C{._Direct} result L{Destination2Tuple}.
124
118
  '''
125
- h = self.height if height is None else height
126
- d = LL(*_Wrap.latlon(r.lat, r.lon), height=h, **_xkwds_not(None,
127
- datum=self.datum, name=self.name,
128
- epoch=self.epoch, reframe=self.reframe))
129
- return Destination2Tuple(d, wrap360(r.final))
119
+ h = self._heigHt(height)
120
+ d = _xkwds_not(None, datum=self.datum, name=self.name,
121
+ epoch=self.epoch, reframe=self.reframe)
122
+ d = LL(*_Wrap.latlon(r.lat, r.lon), height=h, **d)
123
+ return Destination2Tuple(d, wrap360(r.final), name=self.name)
130
124
 
131
- def distanceTo(self, other, wrap=False, **unused): # ignore radius=R_M
125
+ def distanceTo(self, other, wrap=False, **unused): # radius=R_M
132
126
  '''Compute the distance between this and an other point along
133
- a geodesic, using this C{Inverse} method. See method
134
- L{distanceTo3} for more details.
127
+ a geodesic. See method L{distanceTo3} for more details.
135
128
 
136
- @arg other: The other point (C{LatLon}).
129
+ @arg other: The other point (this C{LatLon}).
137
130
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
138
131
  B{C{other}} point (C{bool}).
139
132
 
140
133
  @return: Distance (C{meter}).
141
134
 
142
- @raise TypeError: The B{C{other}} point is not C{LatLon}.
135
+ @raise TypeError: If B{C{other}} not this C{LatLon} class.
143
136
 
144
- @raise ValueError: If this and the B{C{other}} point's L{Datum}
145
- ellipsoids are not compatible.
137
+ @raise ValueError: This and the B{C{other}} point's L{Datum}
138
+ ellipsoids are incompatible.
146
139
  '''
147
140
  return self._Inverse(other, wrap, azis=False).distance
148
141
 
@@ -151,12 +144,13 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
151
144
  a geodesic between this and an other point, using this
152
145
  C{Inverse} method.
153
146
 
154
- The distance is in the same units as this point's datum axes,
155
- conventionally meter. The distance is measured on the surface
156
- of the ellipsoid, ignoring this point's height.
147
+ The distance is in the same units as this point's datum's
148
+ ellipsoid's axes, conventionally meter. The distance is
149
+ measured on the surface of the ellipsoid, ignoring this
150
+ point's height.
157
151
 
158
152
  The initial and final bearing (forward and reverse azimuth)
159
- are in compass C{degrees360} from North.
153
+ are in compass C{degrees360}, clockwise from North.
160
154
 
161
155
  @arg other: Destination point (C{LatLon}).
162
156
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
@@ -164,18 +158,18 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
164
158
 
165
159
  @return: A L{Distance3Tuple}C{(distance, initial, final)}.
166
160
 
167
- @raise TypeError: The B{C{other}} point is not C{LatLon}.
161
+ @raise TypeError: If B{C{other}} not this C{LatLon} class.
168
162
 
169
- @raise ValueError: If this and the B{C{other}} point's L{Datum}
163
+ @raise ValueError: This and the B{C{other}} point's L{Datum}
170
164
  ellipsoids are not compatible.
171
165
  '''
172
166
  return self._xnamed(self._Inverse(other, wrap))
173
167
 
174
168
  def finalBearingOn(self, distance, bearing):
175
169
  '''Compute the final bearing (reverse azimuth) after having
176
- travelled for the given distance along a geodesic given by
177
- an initial bearing from this point, using this C{Direct}
178
- method. See method L{destination2} for more details.
170
+ travelled for the given distance along a geodesic given
171
+ by an initial bearing from this point. See method
172
+ L{destination2} for more details.
179
173
 
180
174
  @arg distance: Distance (C{meter}).
181
175
  @arg bearing: Initial bearing (compass C{degrees360}).
@@ -187,8 +181,7 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
187
181
  def finalBearingTo(self, other, wrap=False):
188
182
  '''Compute the final bearing (reverse azimuth) after having
189
183
  travelled along a geodesic from this point to an other
190
- point, using this C{Inverse} method. See method
191
- L{distanceTo3} for more details.
184
+ point. See method L{distanceTo3} for more details.
192
185
 
193
186
  @arg other: The other point (C{LatLon}).
194
187
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll
@@ -196,10 +189,10 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
196
189
 
197
190
  @return: Final bearing (compass C{degrees360}).
198
191
 
199
- @raise TypeError: The B{C{other}} point is not C{LatLon}.
192
+ @raise TypeError: If B{C{other}} not this C{LatLon} class.
200
193
 
201
- @raise ValueError: If this and the B{C{other}} point's L{Datum}
202
- ellipsoids are not compatible.
194
+ @raise ValueError: This and the B{C{other}} point's L{Datum}
195
+ ellipsoids are incompatible.
203
196
  '''
204
197
  return self._Inverse(other, wrap).final
205
198
 
@@ -209,40 +202,38 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
209
202
  '''
210
203
  return None # PYCHOK no cover
211
204
 
212
- def _g_gl_p3(self, point, other, exact, wrap):
205
+ def _g_gl_p3(self, start, end, exact, wrap):
213
206
  '''(INTERNAL) Helper for methods C{.intersecant2} and C{.plumbTo}.
214
207
  '''
215
- p = _unrollon(self, self.others(point=point), wrap=wrap)
208
+ p = _unrollon(self, self.others(start=start), wrap=wrap)
216
209
  g = self.datum.ellipsoid.geodesic_(exact=exact)
217
- gl = g._DirectLine( p, other) if _isDegrees(other) else \
218
- g._InverseLine(p, self.others(other), wrap)
210
+ gl = g._DirectLine( p, end) if _isDegrees(end) else \
211
+ g._InverseLine(p, self.others(end=end), wrap)
219
212
  return g, gl, p
220
213
 
221
214
  def initialBearingTo(self, other, wrap=False):
222
215
  '''Compute the initial bearing (forward azimuth) to travel
223
- along a geodesic from this point to an other point,
224
- using this C{Inverse} method. See method L{distanceTo3}
225
- for more details.
216
+ along a geodesic from this point to an other point. See
217
+ method L{distanceTo3} for more details.
226
218
 
227
- @arg other: The other point (C{LatLon}).
219
+ @arg other: The other point (this C{LatLon}).
228
220
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll
229
221
  the B{C{other}} point (C{bool}).
230
222
 
231
223
  @return: Initial bearing (compass C{degrees360}).
232
224
 
233
- @raise TypeError: The B{C{other}} point is not C{LatLon}.
225
+ @raise TypeError: If B{C{other}} not this C{LatLon} class.
234
226
 
235
227
  @raise ValueError: If this and the B{C{other}} point's L{Datum}
236
- ellipsoids are not compatible.
228
+ ellipsoids are incompatible.
237
229
  '''
238
230
  return self._Inverse(other, wrap).initial
239
231
 
240
232
  def intermediateTo(self, other, fraction, height=None, wrap=False):
241
233
  '''Return the point at given fraction along the geodesic between
242
- this and an other point, using this C{Direct} and C{Inverse}
243
- methods.
234
+ this and an other point.
244
235
 
245
- @arg other: The other point (C{LatLon}).
236
+ @arg other: The other point (this C{LatLon}).
246
237
  @arg fraction: Fraction between both points (C{scalar}, 0.0
247
238
  at this and 1.0 at the other point.
248
239
  @kwarg height: Optional height, overriding the fractional
@@ -252,12 +243,12 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
252
243
 
253
244
  @return: Intermediate point (C{LatLon}).
254
245
 
255
- @raise TypeError: The B{C{other}} point is not C{LatLon}.
246
+ @raise TypeError: If B{C{other}} not this C{LatLon} class.
256
247
 
257
248
  @raise UnitError: Invalid B{C{fraction}} or B{C{height}}.
258
249
 
259
- @raise ValueError: If this and the B{C{other}} point's L{Datum}
260
- ellipsoids are not compatible.
250
+ @raise ValueError: This and the B{C{other}} point's L{Datum}
251
+ ellipsoids are incompatible.
261
252
 
262
253
  @see: Methods L{distanceTo3}, L{destination}, C{midpointTo} and
263
254
  C{rhumbMidpointTo}.
@@ -273,49 +264,47 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
273
264
  r = self.destination(t.distance * f, t.initial, height=h)
274
265
  return r
275
266
 
276
- def intersecant2(self, circle, point, other, exact=False, height=None, # PYCHOK signature
277
- wrap=False, tol=_TOL):
278
- '''Compute the intersections of a circle and a geodesic (line) given as
279
- two points or as a point and bearing.
267
+ def intersecant2(self, circle, start, end, exact=False, height=None, # PYCHOK signature
268
+ wrap=False, tol=_TOL):
269
+ '''Compute the intersections of a circle and a geodesic (line) given as two
270
+ points or as a point and a bearing from North.
280
271
 
281
272
  @arg circle: Radius of the circle centered at this location (C{meter},
282
273
  conventionally) or a point on the circle (this C{LatLon}).
283
- @arg point: A location on the geodesic (this C{LatLon}).
284
- @arg other: An other point on the geodesic (this C{LatLon}) or the
285
- (forward) bearing at the B{C{point}} (compass C{degrees}).
274
+ @arg start: Start point of the geodesic (line) (this C{LatLon}).
275
+ @arg end: End point of the geodesic (line) (this C{LatLon}) or the initial
276
+ bearing at the B{C{start}} point (compass C{degrees360}).
286
277
  @kwarg exact: Exact C{geodesic...} to use (C{bool} or C{Geodesic...}), see
287
- method L{Ellipsoid.geodesic_}.
278
+ method L{geodesic_<Ellipsoid.geodesic_>}.
288
279
  @kwarg height: Optional height for the intersection points (C{meter},
289
280
  conventionally) or C{None} for interpolated heights.
290
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{point}},
291
- B{C{circle}} and/or B{C{other}} (C{bool}).
281
+ @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{circle}},
282
+ B{C{start}} and/or B{C{end}} (C{bool}).
292
283
  @kwarg tol: Convergence tolerance (C{scalar}).
293
284
 
294
285
  @return: 2-Tuple of the intersection points (representing a geodesic chord),
295
- each an instance of this C{LatLon}. Both points are the same
286
+ each an instance of this C{LatLon} class. Both points are the same
296
287
  instance if the geodesic (line) is tangential to the circle.
297
288
 
298
289
  @raise IntersectionError: The circle and geodesic do not intersect.
299
290
 
300
- @raise TypeError: If B{C{point}} is not this C{LatLon} or B{C{circle}}
301
- or B{C{other}} invalid.
291
+ @raise TypeError: Invalid B{C{circle}}, B{C{start}} or B{C{end}}.
302
292
 
303
- @raise UnitError: Invalid B{C{circle}}, B{C{other}}, B{C{exact}} or
304
- B{C{height}}.
293
+ @raise UnitError: Invalid B{C{circle}}, B{C{end}}, B{C{exact}} or B{C{height}}.
305
294
 
306
295
  @see: Method L{rhumbIntersecant2<LatLonBase.rhumbIntersecant2>}.
307
296
  '''
308
297
  try:
309
- g, gl, p = self._g_gl_p3(point, other, exact, wrap)
298
+ g, gl, p = self._g_gl_p3(start, end, exact, wrap)
310
299
  r = Radius_(circle=circle) if _isRadius(circle) else \
311
300
  g._Inverse(self, self.others(circle=circle), wrap).s12
312
301
 
313
302
  P, Q = _MODS.geodesicw._Intersecant2(gl, self.lat, self.lon, r, tol=tol,
314
303
  form=_MODS.dms.F_DMS)
315
- return self._intersecend2(p, other, wrap, height, g, P, Q,
316
- self.intersecant2)
304
+ return self._intersecend2(p, end, wrap, height, g, P, Q,
305
+ self.intersecant2)
317
306
  except (TypeError, ValueError) as x:
318
- raise _xError(x, center=self, circle=circle, point=point, other=other,
307
+ raise _xError(x, center=self, circle=circle, start=start, end=end,
319
308
  exact=exact, wrap=wrap)
320
309
 
321
310
  def _Inverse(self, other, wrap, **unused): # azis=False, overloaded by I{Vincenty}
@@ -341,11 +330,15 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
341
330
  compute distances.
342
331
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{points}}
343
332
  (C{bool}).
333
+ @kwarg equidistant: An azimuthal equidistant projection (I{class} or function
334
+ L{pygeodesy.equidistant}) or C{None} for the preferred
335
+ L{Equidistant<pygeodesy.ellipsoidalBase.Equidistant>}.
336
+ @kwarg tol: Convergence tolerance (C{meter}, conventionally).
344
337
 
345
338
  @return: A L{NearestOn8Tuple}C{(closest, distance, fi, j, start, end,
346
339
  initial, final)} with C{distance} in C{meter}, conventionally
347
340
  and with the C{closest}, the C{start} the C{end} point each
348
- an instance of this C{LatLon}.
341
+ an instance of this C{LatLon} class.
349
342
 
350
343
  @raise PointsError: Insufficient number of B{C{points}}.
351
344
 
@@ -397,7 +390,7 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
397
390
 
398
391
  f, j = _fi_j2(f, len(Ps)) # like .vector3d.nearestOn6
399
392
 
400
- n = self.nearestOn8.__name__ # _dunder_nameof
393
+ n = self.nearestOn8.__name__ # _DUNDER_nameof
401
394
  c.rename(n)
402
395
  if s is not c:
403
396
  s = s.copy(name=n)
@@ -406,37 +399,37 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
406
399
  return NearestOn8Tuple(c, c3.distance, f, j, s, e, c3.initial, c3.final,
407
400
  iteration=m) # ._iteration for tests
408
401
 
409
- def plumbTo(self, point, other, exact=False, height=None, # PYCHOK signature
410
- wrap=False, tol=_TOL):
411
- '''Compute the I{perpendicular} intersection of a geodesic (line) with
412
- a geodesic from this point.
402
+ def plumbTo(self, start, end, exact=False, height=None, # PYCHOK signature
403
+ wrap=False, tol=_TOL):
404
+ '''Compute the intersection of a geodesic from this point I{perpendicular} to
405
+ a geodesic (line) given as two points or as a point and a bearing from North.
413
406
 
414
- @arg point: A location (C{LatLon}) on the geodesic (line).
415
- @arg other: An other point (C{LatLon}) on the geodesic (line) or the
416
- (forward) bearing at the B{C{point}} (compass C{degrees}).
407
+ @arg start: Start point of the geodesic (line) (this C{LatLon}).
408
+ @arg end: End point of the geodesic (line) (this C{LatLon}) or the initial
409
+ bearing at the B{C{start}} point (compass C{degrees360}).
417
410
  @kwarg exact: Exact C{geodesic...} to use (C{bool} or C{Geodesic...}),
418
411
  see method L{Ellipsoid.geodesic_}.
419
412
  @kwarg height: Optional height for the intersection point (C{meter},
420
413
  conventionally) or C{None} for an interpolated height.
421
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{point}}
422
- and/or B{C{other}} (C{bool}).
414
+ @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{start}}
415
+ and/or B{C{end}} point (C{bool}).
423
416
  @kwarg tol: Convergence tolerance (C{meter}).
424
417
 
425
- @return: The intersection point, an instance of this C{LatLon}.
418
+ @return: The intersection point, an instance of this C{LatLon} class.
426
419
 
427
- @raise TypeError: If B{C{point}} or B{C{other}} not this C{LatLon}.
420
+ @raise TypeError: If B{C{start}} or B{C{end}} not this C{LatLon} class.
428
421
 
429
- @raise UnitError: Invalid B{C{other}}, B{C{exact}} or B{C{height}}.
422
+ @raise UnitError: Invalid B{C{end}}, B{C{exact}} or B{C{height}}.
430
423
  '''
431
424
  try:
432
- g, gl, p = self._g_gl_p3(point, other, exact, wrap)
425
+ g, gl, p = self._g_gl_p3(start, end, exact, wrap)
433
426
 
434
427
  P = _MODS.geodesicw._PlumbTo(gl, self.lat, self.lon, tol=tol)
435
428
  h = self._havg(p, h=height)
436
429
  p = self.classof(P.lat2, P.lon2, datum=self.datum, height=h) # name=n
437
430
  p._iteration = P.iteration
438
431
  except (TypeError, ValueError) as x:
439
- raise _xError(x, plumb=self, point=point, other=other,
432
+ raise _xError(x, plumb=self, start=start, end=end,
440
433
  exact=exact, wrap=wrap)
441
434
  return p
442
435
 
@@ -446,6 +439,8 @@ class _Box(object):
446
439
 
447
440
  @see: Function C{_box4} in .clipy.py.
448
441
  '''
442
+ _1_01 = _1_0 + _0_01 # ~1% margin
443
+
449
444
  def __init__(self, center, distance):
450
445
  '''New L{_Box} around point.
451
446
 
@@ -454,8 +449,8 @@ class _Box(object):
454
449
  (C{meter}, conventionally)
455
450
  '''
456
451
  m = Radius_(distance=distance)
457
- E = center.ellipsoid() # XXX see above
458
- d = E.m2degrees(m) + _0_5 # some margin
452
+ E = center.ellipsoid()
453
+ d = E.m2degrees(m) * self._1_01
459
454
  self._N = center.lat + d
460
455
  self._S = center.lat - d
461
456
  self._E = center.lon + d
@@ -504,7 +499,7 @@ class _Tol(object):
504
499
  self._lat = fmean_(lat, *lats) if lats else lat
505
500
  self._r = max(EPS, E.rocMean(self._lat))
506
501
  self._m = max(EPS, tol_m)
507
- self._deg = max(EPS, degrees(self._m / self._r)) # avoid m2degrees!
502
+ self._deg = max(EPS, degrees(self._m / self._r)) # NOT E.m2degrees!
508
503
 
509
504
  @property_RO
510
505
  def degrees(self):
@@ -515,7 +510,7 @@ class _Tol(object):
515
510
  def degrees2m(self, deg):
516
511
  '''Convert B{C{deg}} to meter at the same C{lat} and earth radius.
517
512
  '''
518
- return self.radius * radians(deg) / PI2 # avoid degrees2m!
513
+ return self.radius * radians(deg) / PI2 # NOT E.degrees2m!
519
514
 
520
515
  def degError(self, Error=_ValueError):
521
516
  '''Compose an error with the C{deg}rees minimum.
@@ -523,7 +518,7 @@ class _Tol(object):
523
518
  return self.mError(self.degrees2m(self._min), Error=Error)
524
519
 
525
520
  def done(self, deg):
526
- '''Check C{deg} vs. tolerance and previous value.
521
+ '''Check C{deg} vs tolerance and previous value.
527
522
  '''
528
523
  if deg < self._deg or deg == self._prev:
529
524
  return True
@@ -533,7 +528,7 @@ class _Tol(object):
533
528
 
534
529
  @property_RO
535
530
  def lat(self):
536
- '''Get the mean latitude in C{degrees}.
531
+ '''Get the mean latitude in C{degrees}.
537
532
  '''
538
533
  return self._lat
539
534
 
@@ -560,8 +555,8 @@ class _Tol(object):
560
555
  def reset(self):
561
556
  '''Reset tolerances.
562
557
  '''
563
- self._min = MAX
564
- self._prev = None
558
+ self._min = MAX # delattrof()
559
+ self._prev = None # delattrof()
565
560
 
566
561
 
567
562
  def _Equidistant00(equidistant, p1):
@@ -585,7 +580,9 @@ def intersecant2(center, circle, point, other, **exact_height_wrap_tol):
585
580
  @arg point: A point of the geodesic (C{LatLon}, as B{C{center}}).
586
581
  @arg other: An other point of the geodesic (C{LatLon}, as B{C{center}}) or
587
582
  the (forward) bearing at the B{C{point}} (compass C{degrees}).
588
- @kwarg exact_height_wrap_tol: Optional keyword arguments, see below.
583
+ @kwarg exact_height_wrap_tol: Optional keyword arguments C{B{exact}=False},
584
+ C{B{height}=None}, C{B{wrap}=False} and C{B{tol}}, see method
585
+ L{intersecant2<LatLonEllipsoidalBaseDI.intersecant2>}.
589
586
 
590
587
  @raise NotImplementedError: Method C{intersecant2} not available.
591
588
 
@@ -601,7 +598,7 @@ def intersecant2(center, circle, point, other, **exact_height_wrap_tol):
601
598
 
602
599
 
603
600
  def _intersect3(s1, end1, s2, end2, height=None, wrap=False, # MCCABE 16 was=True
604
- equidistant=None, tol=_TOL_M, LatLon=None, **LatLon_kwds):
601
+ equidistant=None, tol=_TOL_M, LatLon=None, **LatLon_kwds):
605
602
  '''(INTERNAL) Intersect two (ellipsoidal) lines, see ellipsoidal method
606
603
  L{intersection3}, separated to allow callers to embellish any exceptions.
607
604
  '''
@@ -624,7 +621,7 @@ def _intersect3(s1, end1, s2, end2, height=None, wrap=False, # MCCABE 16 was=T
624
621
  # comparison in .sphericaltrigonometry._intb
625
622
  b, d = _b_d(s, e, w, t, h=t.height)
626
623
  m = s.ellipsoid().R2x * PI_4 # authalic exact
627
- d = min(max(d * _B2END, m), m * _3_0)
624
+ d = min(max(d * _1_5, m), m * _3_0)
628
625
  e = s.destination(d, e)
629
626
  return b, (_unrollon(s, e) if w else e)
630
627
 
@@ -697,7 +694,7 @@ def _intersect3(s1, end1, s2, end2, height=None, wrap=False, # MCCABE 16 was=T
697
694
 
698
695
 
699
696
  def _intersection3(start1, end1, start2, end2, height=None, wrap=False, # was=True
700
- equidistant=None, tol=_TOL_M, LatLon=None, **LatLon_kwds):
697
+ **equidistant_tol_LatLon_and_kwds):
701
698
  '''(INTERNAL) Iteratively compute the intersection point of two lines,
702
699
  each defined by two (ellipsoidal) points or an (ellipsoidal) start
703
700
  point and an initial bearing from North.
@@ -706,14 +703,13 @@ def _intersection3(start1, end1, start2, end2, height=None, wrap=False, # was=T
706
703
  s2 = s1.others(start2=start2)
707
704
  try:
708
705
  return _intersect3(s1, end1, s2, end2, height=height, wrap=wrap,
709
- equidistant=equidistant, tol=tol,
710
- LatLon=LatLon, **LatLon_kwds)
706
+ **equidistant_tol_LatLon_and_kwds)
711
707
  except (TypeError, ValueError) as x:
712
708
  raise _xError(x, start1=start1, end1=end1, start2=start2, end2=end2)
713
709
 
714
710
 
715
711
  def _intersections2(center1, radius1, center2, radius2, height=None, wrap=False, # was=True
716
- equidistant=None, tol=_TOL_M, LatLon=None, **LatLon_kwds):
712
+ **equidistant_tol_LatLon_and_kwds):
717
713
  '''(INTERNAL) Iteratively compute the intersection points of two circles,
718
714
  each defined by an (ellipsoidal) center point and a radius.
719
715
  '''
@@ -721,15 +717,14 @@ def _intersections2(center1, radius1, center2, radius2, height=None, wrap=False,
721
717
  c2 = c1.others(center2=center2)
722
718
  try:
723
719
  return _intersects2(c1, radius1, c2, radius2, height=height, wrap=wrap,
724
- equidistant=equidistant, tol=tol,
725
- LatLon=LatLon, **LatLon_kwds)
720
+ **equidistant_tol_LatLon_and_kwds)
726
721
  except (TypeError, ValueError) as x:
727
722
  raise _xError(x, center1=center1, radius1=radius1,
728
723
  center2=center2, radius2=radius2)
729
724
 
730
725
 
731
726
  def _intersects2(c1, radius1, c2, radius2, height=None, wrap=False, # MCCABE 16 was=True
732
- equidistant=None, tol=_TOL_M, LatLon=None, **LatLon_kwds):
727
+ equidistant=None, tol=_TOL_M, LatLon=None, **LatLon_kwds):
733
728
  '''(INTERNAL) Intersect two (ellipsoidal) circles, see L{_intersections2}
734
729
  above, separated to allow callers to embellish any exceptions.
735
730
  '''
@@ -771,7 +766,7 @@ def _intersects2(c1, radius1, c2, radius2, height=None, wrap=False, # MCCABE 16
771
766
 
772
767
  # gu-/estimate initial intersections, spherically ...
773
768
  t1, t2 = _si2(_LLS(c1), r1, _LLS(c2), r2, radius=e.radius,
774
- height=height, wrap=False, too_d=m) # unrolled already
769
+ height=height, too_d=m, wrap=False) # unrolled already
775
770
  h, n = t1.height, t1.name
776
771
 
777
772
  # ... and iterate as Karney describes, for references
@@ -886,6 +881,7 @@ def _nearestOn3(p, p1, p2, A, within=True, height=None, tol=_TOL_M,
886
881
 
887
882
 
888
883
  __all__ += _ALL_DOCS(LatLonEllipsoidalBaseDI, intersecant2)
884
+ del _1_0, _0_01
889
885
 
890
886
  # **) MIT License
891
887
  #