pygeodesy 24.11.11__py2.py3-none-any.whl → 25.1.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.
Files changed (118) hide show
  1. {PyGeodesy-24.11.11.dist-info → PyGeodesy-25.1.5.dist-info}/METADATA +34 -35
  2. PyGeodesy-25.1.5.dist-info/RECORD +118 -0
  3. {PyGeodesy-24.11.11.dist-info → PyGeodesy-25.1.5.dist-info}/WHEEL +1 -1
  4. pygeodesy/__init__.py +19 -19
  5. pygeodesy/__main__.py +1 -1
  6. pygeodesy/albers.py +5 -5
  7. pygeodesy/auxilats/_CX_4.py +1 -1
  8. pygeodesy/auxilats/_CX_6.py +1 -1
  9. pygeodesy/auxilats/_CX_8.py +1 -1
  10. pygeodesy/auxilats/_CX_Rs.py +1 -1
  11. pygeodesy/auxilats/__init__.py +1 -1
  12. pygeodesy/auxilats/__main__.py +1 -1
  13. pygeodesy/auxilats/auxAngle.py +5 -5
  14. pygeodesy/auxilats/auxDLat.py +6 -6
  15. pygeodesy/auxilats/auxDST.py +2 -2
  16. pygeodesy/auxilats/auxLat.py +5 -5
  17. pygeodesy/auxilats/auxily.py +2 -2
  18. pygeodesy/azimuthal.py +5 -5
  19. pygeodesy/basics.py +60 -8
  20. pygeodesy/booleans.py +1 -1
  21. pygeodesy/cartesianBase.py +22 -61
  22. pygeodesy/clipy.py +1 -1
  23. pygeodesy/constants.py +5 -5
  24. pygeodesy/css.py +1 -1
  25. pygeodesy/datums.py +1 -1
  26. pygeodesy/deprecated/__init__.py +2 -2
  27. pygeodesy/deprecated/bases.py +1 -1
  28. pygeodesy/deprecated/classes.py +86 -2
  29. pygeodesy/deprecated/consterns.py +1 -1
  30. pygeodesy/deprecated/datum.py +5 -5
  31. pygeodesy/deprecated/functions.py +42 -8
  32. pygeodesy/deprecated/nvector.py +1 -1
  33. pygeodesy/deprecated/rhumbBase.py +1 -1
  34. pygeodesy/deprecated/rhumbaux.py +1 -1
  35. pygeodesy/deprecated/rhumbsolve.py +1 -1
  36. pygeodesy/deprecated/rhumbx.py +1 -1
  37. pygeodesy/dms.py +1 -1
  38. pygeodesy/ecef.py +53 -56
  39. pygeodesy/elevations.py +1 -1
  40. pygeodesy/ellipsoidalBase.py +3 -3
  41. pygeodesy/ellipsoidalBaseDI.py +1 -1
  42. pygeodesy/ellipsoidalExact.py +1 -1
  43. pygeodesy/ellipsoidalGeodSolve.py +1 -1
  44. pygeodesy/ellipsoidalKarney.py +1 -1
  45. pygeodesy/ellipsoidalNvector.py +1 -1
  46. pygeodesy/ellipsoidalVincenty.py +6 -5
  47. pygeodesy/ellipsoids.py +4 -5
  48. pygeodesy/elliptic.py +6 -6
  49. pygeodesy/epsg.py +1 -1
  50. pygeodesy/errors.py +1 -1
  51. pygeodesy/etm.py +5 -5
  52. pygeodesy/fmath.py +18 -17
  53. pygeodesy/formy.py +409 -555
  54. pygeodesy/frechet.py +29 -86
  55. pygeodesy/fstats.py +1 -1
  56. pygeodesy/fsums.py +32 -33
  57. pygeodesy/gars.py +1 -1
  58. pygeodesy/geodesici.py +7 -7
  59. pygeodesy/geodesicw.py +1 -1
  60. pygeodesy/geodesicx/_C4_24.py +2 -2
  61. pygeodesy/geodesicx/_C4_27.py +2 -2
  62. pygeodesy/geodesicx/_C4_30.py +2 -2
  63. pygeodesy/geodesicx/__init__.py +2 -2
  64. pygeodesy/geodesicx/__main__.py +4 -5
  65. pygeodesy/geodesicx/gx.py +6 -5
  66. pygeodesy/geodesicx/gxarea.py +2 -2
  67. pygeodesy/geodesicx/gxbases.py +2 -2
  68. pygeodesy/geodesicx/gxline.py +16 -12
  69. pygeodesy/geodsolve.py +1 -1
  70. pygeodesy/geohash.py +1 -1
  71. pygeodesy/geoids.py +277 -203
  72. pygeodesy/hausdorff.py +23 -81
  73. pygeodesy/heights.py +115 -150
  74. pygeodesy/internals.py +1 -1
  75. pygeodesy/interns.py +2 -3
  76. pygeodesy/iters.py +1 -1
  77. pygeodesy/karney.py +3 -3
  78. pygeodesy/ktm.py +16 -15
  79. pygeodesy/latlonBase.py +323 -409
  80. pygeodesy/lazily.py +53 -44
  81. pygeodesy/lcc.py +1 -1
  82. pygeodesy/ltp.py +46 -50
  83. pygeodesy/ltpTuples.py +147 -130
  84. pygeodesy/mgrs.py +1 -1
  85. pygeodesy/named.py +149 -3
  86. pygeodesy/namedTuples.py +58 -7
  87. pygeodesy/nvectorBase.py +122 -105
  88. pygeodesy/osgr.py +1 -1
  89. pygeodesy/points.py +1 -1
  90. pygeodesy/props.py +1 -1
  91. pygeodesy/resections.py +18 -17
  92. pygeodesy/rhumb/__init__.py +1 -1
  93. pygeodesy/rhumb/aux_.py +2 -2
  94. pygeodesy/rhumb/bases.py +2 -2
  95. pygeodesy/rhumb/ekx.py +4 -4
  96. pygeodesy/rhumb/solve.py +1 -1
  97. pygeodesy/simplify.py +289 -401
  98. pygeodesy/solveBase.py +1 -1
  99. pygeodesy/sphericalBase.py +1 -1
  100. pygeodesy/sphericalNvector.py +5 -5
  101. pygeodesy/sphericalTrigonometry.py +7 -6
  102. pygeodesy/streprs.py +10 -5
  103. pygeodesy/trf.py +1 -1
  104. pygeodesy/triaxials.py +23 -16
  105. pygeodesy/units.py +16 -16
  106. pygeodesy/unitsBase.py +1 -1
  107. pygeodesy/ups.py +4 -4
  108. pygeodesy/utily.py +341 -211
  109. pygeodesy/utm.py +5 -5
  110. pygeodesy/utmups.py +1 -1
  111. pygeodesy/utmupsBase.py +1 -1
  112. pygeodesy/vector2d.py +5 -5
  113. pygeodesy/vector3d.py +14 -3
  114. pygeodesy/vector3dBase.py +5 -5
  115. pygeodesy/webmercator.py +1 -1
  116. pygeodesy/wgrs.py +1 -1
  117. PyGeodesy-24.11.11.dist-info/RECORD +0 -118
  118. {PyGeodesy-24.11.11.dist-info → PyGeodesy-25.1.5.dist-info}/top_level.txt +0 -0
pygeodesy/named.py CHANGED
@@ -15,6 +15,7 @@ standard Python C{namedtuple}s.
15
15
 
16
16
  from pygeodesy.basics import isidentifier, iskeyword, isstr, itemsorted, len2, \
17
17
  _xcopy, _xdup, _xinstanceof, _xsubclassof, _zip
18
+ # from pygeodesy.ecef import EcefKarney # _MODS
18
19
  from pygeodesy.errors import _AssertionError, _AttributeError, _incompatible, \
19
20
  _IndexError, _KeyError, LenError, _NameError, \
20
21
  _NotImplementedError, _TypeError, _TypesError, \
@@ -28,14 +29,16 @@ from pygeodesy.interns import MISSING, NN, _AT_, _COLON_, _COLONSPACE_, _COMMA_,
28
29
  _NL_, _NN_, _no_, _other_, _s_, _SPACE_, _std_, \
29
30
  _UNDER_, _vs_
30
31
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
32
+ # from pygeodesy.ltp import Ltp, _toLocal, _toLtp # _MODS
33
+ # from pygeodesy.ltpTuples import Aer, Enu, Ned # _MODS
31
34
  from pygeodesy.props import _allPropertiesOf_n, deprecated_method, _hasProperty, \
32
35
  _update_all, property_doc_, Property_RO, property_RO, \
33
- _update_attrs
36
+ _update_attrs, property_ROver
34
37
  from pygeodesy.streprs import attrs, Fmt, lrstrip, pairs, reprs, unstr
35
38
  # from pygeodesy.units import _toUnit # _MODS
36
39
 
37
40
  __all__ = _ALL_LAZY.named
38
- __version__ = '24.10.14'
41
+ __version__ = '24.12.05'
39
42
 
40
43
  _COMMANL_ = _COMMA_ + _NL_
41
44
  _COMMASPACEDOT_ = _COMMASPACE_ + _DOT_
@@ -896,6 +899,148 @@ class _NamedEnumItem(_NamedBase):
896
899
  raise _AssertionError(t)
897
900
 
898
901
 
902
+ class _NamedLocal(object):
903
+ '''(INTERNAL) Base class for C{CartesianBase}, C{Ecef9Tuple} and C{LatLonBase}.
904
+ '''
905
+
906
+ @property_ROver
907
+ def Ecef(self):
908
+ '''Get the ECEF I{class} (L{EcefKarney}), I{once}.
909
+ '''
910
+ return _MODS.ecef.EcefKarney
911
+
912
+ @property_RO
913
+ def _ecef9(self):
914
+ '''I{Must be overloaded}.'''
915
+ notOverloaded(self)
916
+
917
+ @Property_RO
918
+ def _Ltp(self):
919
+ '''(INTERNAL) Cache this instance' LTP (L{Ltp}).
920
+ '''
921
+ return self._ltp.Ltp(self._ecef9, ecef=self.Ecef(self.datum), name=self.name)
922
+
923
+ @property_ROver
924
+ def _ltp(self):
925
+ '''(INTERNAL) Get module L{pygeodesy.ltp}, I{once}.
926
+ '''
927
+ return _MODS.ltp
928
+
929
+ def _ltp_toLocal(self, ltp, Xyz_kwds, **Xyz): # overloaded in C{Ecef9Tuple}
930
+ '''(INTERNAL) Invoke C{ltp._toLocal}.
931
+ '''
932
+ Xyz_ = self._ltp_toLocal2(Xyz_kwds, **Xyz)
933
+ return self._ltp._toLocal(self, ltp, *Xyz_) # self._ecef9
934
+
935
+ def _ltp_toLocal2(self, Xyz_kwds, _None=None, **Xyz):
936
+ '''(INTERNAL) Return 2-tuple C{(Xyz_Class, Xyz_kwds)}.
937
+ '''
938
+ C, _ = Xyz_ = _xkwds_pop2(Xyz_kwds, **Xyz)
939
+ if C is not _None: # validate C
940
+ n, X = _xkwds_item2(Xyz)
941
+ if X is not C:
942
+ _xsubclassof(X, **{n: C})
943
+ return Xyz_
944
+
945
+ @property_ROver
946
+ def _ltpTuples(self):
947
+ '''(INTERNAL) Get module L{pygeodesy.ltpTuples}, I{once}.
948
+ '''
949
+ return _MODS.ltpTuples
950
+
951
+ def toAer(self, ltp=None, **Aer_and_kwds):
952
+ '''Convert this instance to I{local} I{Azimuth, Elevation, slant Range} (AER) components.
953
+
954
+ @kwarg ltp: The I{local tangent plane} (LTP) to use (L{Ltp}), overriding this
955
+ instance' L{LTP<pygeodesy.named._NamedLocal.toLtp>}.
956
+ @kwarg Aer_and_kwds: Optional AER class C{B{Aer}=}L{Aer<pygeodesy.ltpTuples.Aer>}
957
+ to use and optionally, additional B{C{Aer}} keyword arguments.
958
+
959
+ @return: An B{C{Aer}} instance.
960
+
961
+ @raise TypeError: Invalid B{C{ltp}}.
962
+
963
+ @see: Method L{toLocal<pygeodesy.named._NamedLocal.toLocal>}.
964
+ '''
965
+ return self._ltp_toLocal(ltp, Aer_and_kwds, Aer=self._ltpTuples.Aer)
966
+
967
+ def toEnu(self, ltp=None, **Enu_and_kwds):
968
+ '''Convert this instance to I{local} I{East, North, Up} (ENU) components.
969
+
970
+ @kwarg ltp: The I{local tangent plane} (LTP) to use (L{Ltp}), overriding this
971
+ instance' L{LTP<pygeodesy.named._NamedLocal.toLtp>}.
972
+ @kwarg Enu_and_kwds: Optional ENU class C{B{Enu}=}L{Enu<pygeodesy.ltpTuples.Enu>}
973
+ to use and optionally, additional B{C{Enu}} keyword arguments.
974
+
975
+ @return: An B{C{Enu}} instance.
976
+
977
+ @raise TypeError: Invalid B{C{ltp}}.
978
+
979
+ @see: Method L{toLocal<pygeodesy.named._NamedLocal.toLocal>}.
980
+ '''
981
+ return self._ltp_toLocal(ltp, Enu_and_kwds, Enu=self._ltpTuples.Enu)
982
+
983
+ def toLocal(self, Xyz=None, ltp=None, **Xyz_kwds):
984
+ '''Convert this instance to I{local} components in a I{local tangent plane} (LTP)
985
+
986
+ @kwarg Xyz: Optional I{local} components class (L{XyzLocal}, L{Aer},
987
+ L{Enu}, L{Ned}) or C{None}.
988
+ @kwarg ltp: The I{local tangent plane} (LTP) to use (L{Ltp}), overriding this
989
+ cartesian's L{LTP<pygeodesy.named._NamedLocal.toLtp>}.
990
+ @kwarg Xyz_kwds: Optionally, additional B{C{Xyz}} keyword arguments, ignored
991
+ if C{B{Xyz} is None}.
992
+
993
+ @return: An B{C{Xyz}} instance or a L{Local9Tuple}C{(x, y, z, lat, lon,
994
+ height, ltp, ecef, M)} if C{B{Xyz} is None} (with C{M=None}).
995
+
996
+ @raise TypeError: Invalid B{C{ltp}}.
997
+ '''
998
+ return self._ltp_toLocal(ltp, Xyz_kwds, Xyz=Xyz, _None=Xyz)
999
+
1000
+ def toLtp(self, Ecef=None, **name):
1001
+ '''Return the I{local tangent plane} (LTP) for this instance.
1002
+
1003
+ @kwarg Ecef: Optional ECEF I{class} (L{EcefKarney}, ... L{EcefYou}), overriding
1004
+ this instance' L{Ecef<pygeodesy.named._NamedLocal.Ecef>}.
1005
+ @kwarg name: Optional C{B{name}=NN} (C{str}).
1006
+
1007
+ @return: An B{C{Ltp}} instance.
1008
+ '''
1009
+ return self._ltp._toLtp(self, Ecef, self._ecef9, name) # needs self.Ecef and self._Ltp
1010
+
1011
+ def toNed(self, ltp=None, **Ned_and_kwds):
1012
+ '''Convert this instance to I{local} I{North, East, Down} (NED) components.
1013
+
1014
+ @kwarg ltp: The I{local tangent plane} (LTP) to use (L{Ltp}), overriding this
1015
+ instance' L{LTP<pygeodesy.named._NamedLocal.toLtp>}.
1016
+ @kwarg Ned_and_kwds: Optional NED class C{B{Ned}=}L{Ned<pygeodesy.ltpTuples.Ned>}
1017
+ to use and optionally, additional B{C{Ned}} keyword arguments.
1018
+
1019
+ @return: An B{C{Ned}} instance.
1020
+
1021
+ @raise TypeError: Invalid B{C{ltp}}.
1022
+
1023
+ @see: Method L{toLocal<pygeodesy.named._NamedLocal.toLocal>}.
1024
+ '''
1025
+ return self._ltp_toLocal(ltp, Ned_and_kwds, Ned=self._ltpTuples.Ned)
1026
+
1027
+ def toXyz(self, ltp=None, **Xyz_and_kwds):
1028
+ '''Convert this instance to I{local} I{X, Y, Z} (XYZ) components.
1029
+
1030
+ @kwarg ltp: The I{local tangent plane} (LTP) to use (L{Ltp}), overriding this
1031
+ instance' L{LTP<pygeodesy.named._NamedLocal.toLtp>}.
1032
+ @kwarg Xyz_and_kwds: Optional XYZ class C{B{Xyz}=}L{Xyz<pygeodesy.ltpTuples.XyzLocal>}
1033
+ to use and optionally, additional B{C{Xyz}} keyword arguments.
1034
+
1035
+ @return: An B{C{Xyz}} instance.
1036
+
1037
+ @raise TypeError: Invalid B{C{ltp}}.
1038
+
1039
+ @see: Method L{toLocal<pygeodesy.named._NamedLocal.toLocal>}.
1040
+ '''
1041
+ return self._ltp_toLocal(ltp, Xyz_and_kwds, Xyz=self._ltpTuples.XyzLocal)
1042
+
1043
+
899
1044
  # from pygeodesy.props import _NamedProperty
900
1045
 
901
1046
 
@@ -1450,11 +1595,12 @@ def _xvalid(name, underOK=False):
1450
1595
  __all__ += _ALL_DOCS(_Named,
1451
1596
  _NamedBase, # _NamedDict,
1452
1597
  _NamedEnum, _NamedEnumItem,
1598
+ _NamedLocal,
1453
1599
  _NamedTuple)
1454
1600
 
1455
1601
  # **) MIT License
1456
1602
  #
1457
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
1603
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
1458
1604
  #
1459
1605
  # Permission is hereby granted, free of charge, to any person obtaining a
1460
1606
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/namedTuples.py CHANGED
@@ -8,10 +8,11 @@ are all instances of some C{Named...Tuple} class, all sub-classes
8
8
  of C{_NamedTuple} defined in C{pygeodesy.named}.
9
9
  '''
10
10
 
11
- from pygeodesy.basics import isinstanceof, map1, _xinstanceof
11
+ from pygeodesy.basics import isinstanceof, issubclassof, map1, _xinstanceof
12
+ # from pygeodesy.cartesianBase import CartesianBase # _MODS
12
13
  # from pygeodesy.constants import INT0 # from .units
13
14
  # from pygeodesy.dms import toDMS # _MODS
14
- from pygeodesy.errors import _xattr, _xkwds, _xkwds_not, _ALL_LAZY, _MODS
15
+ from pygeodesy.errors import _TypeError, _xattr, _xkwds, _xkwds_not
15
16
  from pygeodesy.interns import NN, _1_, _2_, _a_, _A_, _area_, _angle_, _b_, _B_, \
16
17
  _band_, _c_, _C_, _D_, _datum_, _distance_, _E_, \
17
18
  _easting_, _end_, _fi_, _gamma_, _h_, _height_, \
@@ -19,8 +20,8 @@ from pygeodesy.interns import NN, _1_, _2_, _a_, _A_, _area_, _angle_, _b_, _B_,
19
20
  _n_, _northing_, _number_, _outside_, _phi_, \
20
21
  _point_, _precision_, _points_, _radius_, _scale_, \
21
22
  _start_, _x_, _y_, _z_, _zone_
22
- # from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS # from .errors
23
- from pygeodesy.named import _NamedTuple, _Pass
23
+ # from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS # from .named
24
+ from pygeodesy.named import _NamedTuple, _Pass, _ALL_LAZY, _MODS
24
25
  from pygeodesy.props import deprecated_property_RO, property_RO
25
26
  from pygeodesy.units import Band, Bearing, Degrees, Degrees2, Easting, FIx, \
26
27
  Height, Int, Lam, Lat, Lon, Meter, Meter2, \
@@ -28,7 +29,7 @@ from pygeodesy.units import Band, Bearing, Degrees, Degrees2, Easting, FIx, \
28
29
  Radius, Scalar, Str, INT0
29
30
 
30
31
  __all__ = _ALL_LAZY.namedTuples
31
- __version__ = '24.08.18'
32
+ __version__ = '24.11.22'
32
33
 
33
34
  # __DUNDER gets mangled in class
34
35
  _closest_ = 'closest'
@@ -636,6 +637,17 @@ class Vector2Tuple(_NamedTuple):
636
637
  _Names_ = (_x_, _y_)
637
638
  _Units_ = ( Scalar, Scalar)
638
639
 
640
+ def toCartesian(self, Cartesian, **Cartesian_kwds):
641
+ '''Return this C{Vector2Tuple} as a C{Cartesian}.
642
+
643
+ @arg Cartesian: The C{Cartesian} class to use.
644
+ @kwarg Cartesian_kwds: Optional, additional C{Cartesian}
645
+ keyword arguments.
646
+
647
+ @return: The C{B{Cartesian}} instance with C{z=0}.
648
+ '''
649
+ return _v2Cls(self.xyz, Cartesian, Cartesian_kwds)
650
+
639
651
  def to3Tuple(self, z=INT0, **name):
640
652
  '''Extend this L{Vector2Tuple} to a L{Vector3Tuple}.
641
653
 
@@ -649,6 +661,18 @@ class Vector2Tuple(_NamedTuple):
649
661
  '''
650
662
  return self._xtend(Vector3Tuple, z, **name)
651
663
 
664
+ @property_RO
665
+ def xyz(self):
666
+ '''Get X, Y and Z=0 components (C{Vector3Tuple}).
667
+ '''
668
+ return Vector3Tuple(*self.xyz3)
669
+
670
+ @property_RO
671
+ def xyz3(self):
672
+ '''Get X, Y and Z=0 components as C{3-tuple}.
673
+ '''
674
+ return self.x, self.y, INT0
675
+
652
676
 
653
677
  class Vector3Tuple(_NamedTuple):
654
678
  '''3-Tuple C{(x, y, z)} of (geocentric) components, all in
@@ -657,6 +681,17 @@ class Vector3Tuple(_NamedTuple):
657
681
  _Names_ = (_x_, _y_, _z_)
658
682
  _Units_ = ( Scalar, Scalar, Scalar)
659
683
 
684
+ def toCartesian(self, Cartesian, **Cartesian_kwds):
685
+ '''Return this C{Vector3Tuple} as a C{Cartesian}.
686
+
687
+ @arg Cartesian: The C{Cartesian} class to use.
688
+ @kwarg Cartesian_kwds: Optional, additional C{Cartesian}
689
+ keyword arguments.
690
+
691
+ @return: The C{B{Cartesian}} instance.
692
+ '''
693
+ return _v2Cls(self, Cartesian, Cartesian_kwds)
694
+
660
695
  def to4Tuple(self, h=INT0, **name):
661
696
  '''Extend this L{Vector3Tuple} to a L{Vector4Tuple}.
662
697
 
@@ -690,6 +725,17 @@ class Vector4Tuple(_NamedTuple): # .nvector.py
690
725
  _Names_ = (_x_, _y_, _z_, _h_)
691
726
  _Units_ = ( Scalar, Scalar, Scalar, Height)
692
727
 
728
+ def toCartesian(self, Cartesian, **Cartesian_kwds):
729
+ '''Return this C{Vector4Tuple} as a C{Cartesian}.
730
+
731
+ @arg Cartesian: The C{Cartesian} class to use.
732
+ @kwarg Cartesian_kwds: Optional, additional C{Cartesian}
733
+ keyword arguments.
734
+
735
+ @return: The C{B{Cartesian}} instance.
736
+ '''
737
+ return _v2Cls(self, Cartesian, Cartesian_kwds)
738
+
693
739
  def to3Tuple(self):
694
740
  '''Reduce this L{Vector4Tuple} to a L{Vector3Tuple}.
695
741
 
@@ -701,7 +747,7 @@ class Vector4Tuple(_NamedTuple): # .nvector.py
701
747
  def xyz(self):
702
748
  '''Get X, Y and Z components (L{Vector3Tuple}).
703
749
  '''
704
- return Vector3Tuple(*self[:3])
750
+ return Vector3Tuple(*self.xyz)
705
751
 
706
752
  @property_RO
707
753
  def xyz3(self):
@@ -710,9 +756,14 @@ class Vector4Tuple(_NamedTuple): # .nvector.py
710
756
  return tuple(self[:3])
711
757
 
712
758
 
759
+ def _v2Cls(v, Cls, Cartesian_kwds): # in .vector3d
760
+ if issubclassof(Cls, _MODS.cartesianBase.CartesianBase): # _MODS.vector3d.Vector3d)
761
+ return Cls(v, **Cartesian_kwds)
762
+ raise _TypeError(Cartesian=Cls, **Cartesian_kwds)
763
+
713
764
  # **) MIT License
714
765
  #
715
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
766
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
716
767
  #
717
768
  # Permission is hereby granted, free of charge, to any person obtaining a
718
769
  # copy of this software and associated documentation files (the "Software"),