Coverage for pybelbg / __pygeodesy.py: 96%
91 statements
« prev ^ index » next coverage.py v7.14.0, created at 2026-07-31 12:43 -0400
« prev ^ index » next coverage.py v7.14.0, created at 2026-07-31 12:43 -0400
2# -*- coding: utf-8 -*-
4u'''(INTERNAL) C{pybelbg} access to some private C{pygeodesy} attributes.
5'''
6import os.path as os_path
7import sys # PYCHOK used!
9_missing_ = 'missing' # PYCHOK used!
10_requires = '26.7.27' # in README.rst, requirements.txt, setup.py
13def _PyGeodesy_dir(requires):
14 # Adjust sys.path to enable import pygeodesy
15 d = None
16 try:
17 from pygeodesy import version as _v
18 except ImportError:
19 _v = _missing_
20 # PYTHONPATH=.../PyBeLBG for development ONLY
21 p = os_path.abspath(__file__)
22 p = os_path.dirname(p) # pybelbg_abspath
23 p = os_path.dirname(p) # PyBeLBG
24 p = os_path.dirname(p) # ../
25 g = os_path.join(p, 'PyGeodesy')
26 if g != p and g not in sys.path:
27 sys.path.insert(0, g)
28 try:
29 from pygeodesy import version as _v # PYCHOK redef
30 d = g
31 except ImportError:
32 pass
33# finally:
34# try:
35# sys.path.remove(g)
36# except ValueError:
37# pass
39 def _t(v):
40 return tuple(map(int, v.split('.'))) # _DOT_
42 if _v == _missing_ or _t(_v) < _t(requires):
43 _v = ' %s, need %s or newer' % (_v, requires)
44 raise ImportError('pygeodesy' + _v)
46 return d # or None
48_PyGeodesy_dir = _PyGeodesy_dir(_requires) # PYCHOK path or None
50from pygeodesy.basics import _xinstanceof, _xsubclassof # noqa: F401
51from pygeodesy.constants import (_1_0, _3600_0, # noqa: F401
52 _isNAN, _isNAN0) # noqa: F401
53from pygeodesy.ellipsoidalBase import LatLonEllipsoidalBase as _LLEB # noqa: F401
54from pygeodesy.errors import _ValueError, _xkwds # noqa: F401
55from pygeodesy.internals import machine, _secs2str, _versions # noqa: F401
56from pygeodesy.interns import (_COMMA_, _DASH_, _easting_, # noqa: F401
57 _H_, _height_, _lat_, _lon_, _N_, # noqa: F401
58 _name_, _northing_, _SPACE_) # noqa: F401
59from pygeodesy.lazily import _ALL_DOCS, _ALL_OTHER, _FOR_DOCS # noqa: F401
60from pygeodesy.named import _NamedBase, _NamedTuple, _Pass # noqa: F401
61from pygeodesy.namedTuples import (EasNor2Tuple, LatLon2Tuple, PhiLam2Tuple,
62 _isinside, _resize4)
63from pygeodesy.streprs import Fmt # noqa: F401
65from pygeodesy import (Datums, Easting, Height, Lamd, Lat, Lon, Meter,
66 NAN, Northing, Phid, Property_RO)
69class BeLBGError(_ValueError):
70 '''Error raised for C{pybelbg}, C{hBG18}, unzip and other issues.
71 '''
72 pass
75class BeLBG7Tuple(_NamedTuple):
76 '''7-Tuple C{(easting, northing, H, lat, lon, height, beLBG)} with I{local}
77 Belgian C{easting}, C{northing} and orthometric height C{H}, geodetic C{lat},
78 C{lon} and ellipsoidal C{height} and C{beLBG} the C{Be*LBG} instance with
79 C{lat} and C{lon} in C{degrees} and with C{easting}, C{northing}, C{H} and
80 C{height} in C{meter}, conventionally.
81 '''
82 _Names_ = (_easting_, _northing_, _H_, _lat_, _lon_, _height_, 'beLBG')
83 _Units_ = ( Easting, Northing, Height, Lat, Lon, Height, _Pass)
85 @Property_RO
86 def datum(self):
87 '''Get the C{beLBG}'s datum (C{Datum}).
88 '''
89 return self.beLBG.datum # PYCHOK beLBG
91# def diff(self, other, datum=None, **name):
92# '''Return the difference between this and an C{other} C{BeLBG7Tuple}.
93#
94# @kwarg datum: Datum C{diff} (C{Datum}, None or NAN).
95# @kwarg name: Optional name (C{str}).
96#
97# @return: An L{BeLBG7Tuple} with the C{fabs(diff)} for each item,
98# except C{datum} as B{C{datum}}.
99# '''
100# def _diff(a, b):
101# try:
102# return fabs(a - b)
103# except TypeError:
104# return datum
105#
106# _xinstanceof(BeLBG7Tuple, other=other)
107# t = map2(_diff, self, other)
108# return BeLBG7Tuple(t, **name)
110 @Property_RO
111 def eastingnorthing(self):
112 '''Get easting and northing (L{EasNor2Tuple}C{(easting, northing)}).
113 '''
114 return EasNor2Tuple(self.easting, self.northing, name=self.name)
116 @Property_RO
117 def eastingnorthingHeight(self):
118 '''Get easting, northing and orthometric height (L{EasNorH3Tuple}C{(easting, northing, H)}).
119 '''
120 return EasNorH3Tuple(self.easting, self.northing, self.H, name=self.name)
122# def isinside2(self, asLb=False):
123# '''Return 2-tuple C{(region4, bounds4)}, each C{True} if this point is
124# inside this C{region4} respectively C{bounds4} otherwise C{False}.
125# '''
126# t = (self.easting, self.northing) if asLB else (self.lat, self.lon)
127# return (self.beLBG.region4(asLb)(*t),
128# self.beLBG.bounds4(asLb)(*t))
130 @Property_RO
131 def lam(self):
132 '''Get the longitude (B{C{radians}}).
133 '''
134 return Lamd(self.lon) # PYCHOK lon
136 @Property_RO
137 def latlon(self):
138 '''Get the lat-, longitude in C{degrees} (L{LatLon2Tuple}C{(lat, lon)}).
139 '''
140 return LatLon2Tuple(self.lat, self.lon, name=self.name)
142 @Property_RO
143 def latlonheight(self):
144 '''Get the lat-, longitude in C{degrees} and height (L{LatLon3Tuple}C{(lat, lon, height)}).
145 '''
146 return self.latlon.to3Tuple(self.height)
148 @Property_RO
149 def latlonheightdatum(self):
150 '''Get the lat-, longitude in C{degrees} with height and datum (L{LatLon4Tuple}C{(lat, lon, height, datum)}).
151 '''
152 return self.latlonheight.to4Tuple(self.datum)
154 @Property_RO
155 def latlonNgeoid(self):
156 '''Get the lat-, longitude in C{degrees} and geoid height (L{LatLonN3Tuple}C{(lat, lon, N)}).
157 '''
158 return LatLonN3Tuple(self.lat, self.lon, self.N, name=self.name)
160 @Property_RO
161 def N(self):
162 '''Get the geoid height C{N} (C{meter}, conventionally).
163 '''
164 N = self.height - self.H
165 return NAN if _isNAN(N) else Height(N=N)
167 @Property_RO
168 def phi(self):
169 '''Get the latitude (B{C{radians}}).
170 '''
171 return Phid(self.lat) # PYCHOK lat
173 @Property_RO
174 def philam(self):
175 '''Get the lat- and longitude in C{radians} (L{PhiLam2Tuple}C{(phi, lam)}).
176 '''
177 return PhiLam2Tuple(self.phi, self.lam, name=self.name) # PYCHOK lam, phi
179 @Property_RO
180 def philamheight(self):
181 '''Get the lat-, longitude in C{radians} and height (L{PhiLam3Tuple}C{(phi, lam, height)}).
182 '''
183 return self.philam.to3Tuple(self.height) # PYCHOK height
185 @Property_RO
186 def philamheightdatum(self):
187 '''Get the lat-, longitude in C{radians} with height and datum (L{PhiLamn4Tuple}C{(phi, lam, height, datum)}).
188 '''
189 return self.philamheight.to4Tuple(self.datum)
191# def toDatum(self, datum2, name=NN):
192# '''Convert this C{lat}, C{lon} and C{height} to B{C{datum2}}.
193#
194# @arg datum2: Datum to convert I{to} (L{Datum}).
195# @kwarg name: Optional name (C{str}), overriding this name.
196#
197# @return: An L{BeLBG7Tuple} with transformed C{lat}, C{lon} and C{height}
198# or this L{BeLBG7Tuple} if this.datum is B{C{datum2}}.
199# '''
200# _xinstanceof(Datum, datum2=datum2)
201# if self.datum is datum2 or self.datum == datum2: # PYCHOK datum
202# return self
203# g = self.toLatLon(_LLEB).toDatum(datum2)
204# h = NAN if _isNAN(self.height) else g.height # PYCHOK preserve height NAN
205# return self.dup(lat=g.lat, lon=g.lon, datum=g.datum, height=h,
206# name=name or self.name)
208# def toLatLon(self, LatLon, **LatLon_kwds):
209# '''Return this C{lat}, C{lon}, C{datum} and C{height} as B{C{LatLon}}.
210#
211# @arg LatLon: An ellipsoidal C{LatLon} class (C{pygeodesy.ellipsoidal*}).
212# @kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword arguments.
213#
214# @return: An B{C{LatLon}} instance.
215#
216# @raise TypeError: B{C{LatLon}} not ellipsoidal or an other issue.
217# '''
218# _xsubclassof(_LLEB, LatLon=LatLon)
219# h = _isNAN0(self.height) # PYCHOK height
220# kwds = _xkwds(LatLon_kwds, name=self.name, height=h)
221# return LatLon(self.lat, self.lon, datum=self.datum, **kwds) # PYCHOK datum
223# @Property_RO
224# def xy(self):
225# '''Get the I{local} easting, northing) coordinates (L{Vector2Tuple}C{(x, y)}).
226# '''
227# return Vector2Tuple(self.easting, self.northing, name=self.name)
229# @Property_RO
230# def xyz(self):
231# '''Get the I{local} easting, northing and (orthometric) height (L{Vector3Tuple}C{(x, y, z)}).
232# '''
233# return Vector3Tuple(self.easting, self.northing, self.H, name=self.name)
236class EasNorH3Tuple(_NamedTuple):
237 '''3-Tuple C{(easting, northing, H)}, all in C{meter}, conventionally
238 with orthometric height C{H}.
239 '''
240 _Names_ = EasNor2Tuple._Names_ + (_H_,)
241 _Units_ = EasNor2Tuple._Units_ + (Height,)
244class LatLonN3Tuple(_NamedTuple): # XXX move to pygeodesy
245 '''3-tuple C{(lat, lon, N)} with geoid height C{N} in C{meter}, conventionally.
246 '''
247 _Names_ = (_lat_, _lon_, _N_)
248 _Units_ = ( Lat, Lon, Height)
251class Lb4Tuple(_NamedTuple):
252 '''4-Tuple C{(minE, minN, maxE, maxN)} with local C{Lambert} lower-left
253 C{(minE, minN)} and upper-right C{(maxE, maxN)} bounds in C{meter},
254 conventionally.
255 '''
256 _Names_ = ('minE', 'minN', 'maxE', 'maxN')
257 _Units_ = ( Easting, Northing, Easting, Northing)
259 def isinside(self, easting, northing, eps=0):
260 '''Are B{C{easting}} and B{C{northing}} inside these C{Lambert} bounds?
262 @arg easting: Easting (C{meter}).
263 @arg northing: Northing (C{meter}).
264 @kwarg eps: Over-/undersize the C{Lb} bounds (C{meter}).
266 @return: C{False} if B{C{easting}} or B{C{northing}} is C{NAN}
267 or outsize these C{Lb} bounds, C{True} otherwise.
268 '''
269 z = Meter(eps=eps) if eps else 0
270 return _isinside(Easting(easting), Northing(northing), z, self)
272 def resize(self, eps):
273 '''Get these C{Lambert} bounds, over- or undersized by C{B{eps}}.
275 @arg eps: In- or decrease (C{meter}).
277 @return: An L{Lb4Tuple}C{(minE, minN, maxE, maxN)} with all
278 4 bounds resized.
279 '''
280 return _resize4(self, Meter(eps=eps))
283def _all_OTHER(*objs): # PYCHOK shared
284 # collect all __all__ lists or tuples
285 _all = _ALL_OTHER(*objs)
286 _all__all__.extend(_all)
287 return _all
289_all__all__ = [] # PYCHOK in .__init__
291__all__ = _all_OTHER(machine, BeLBGError, BeLBG7Tuple, Datums,
292 EasNorH3Tuple, LatLonN3Tuple, Lb4Tuple)
293__version__ = '26.07.29'
295# **) MIT License
296#
297# Copyright (C) 2026-2026 -- mrJean1 at Gmail -- All Rights Reserved.
298#
299# Permission is hereby granted, free of charge, to any person obtaining a
300# copy of this software and associated documentation files (the "Software"),
301# to deal in the Software without restriction, including without limitation
302# the rights to use, copy, modify, merge, publish, distribute, sublicense,
303# and/or sell copies of the Software, and to permit persons to whom the
304# Software is furnished to do so, subject to the following conditions:
305#
306# The above copyright notice and this permission notice shall be included
307# in all copies or substantial portions of the Software.
308#
309# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
310# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
311# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
312# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
313# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
314# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
315# OTHER DEALINGS IN THE SOFTWARE.