Source code for geosoft.gxpy.geometry_utility
"""
Geometry utilities.
:Constants:
:SPLINE_LINEAR: `geosoft.gxapi.VVU_SPL_LINEAR`
:SPLINE_CUBIC: `geosoft.gxapi.VVU_SPL_CUBIC`
:SPLINE_AKIMA: `geosoft.gxapi.VVU_SPL_AKIMA`
:SPLINE_NEAREST: `geosoft.gxapi.VVU_SPL_NEAREST`
.. seealso:: `geosoft.gxpy.geometry`
.. note::
Regression tests provide usage examples:
`Tests <https://github.com/GeosoftInc/gxpy/blob/master/geosoft/gxpy/tests/test_geometry_utility.py>`_
"""
import numpy as np
import geosoft
import geosoft.gxapi as gxapi
from . import vv as gxvv
from . import geometry as gxgeo
__version__ = geosoft.__version__
SPLINE_LINEAR = gxapi.VVU_SPL_LINEAR
SPLINE_CUBIC = gxapi.VVU_SPL_CUBIC
SPLINE_AKIMA = gxapi.VVU_SPL_AKIMA
SPLINE_NEAREST = gxapi.VVU_SPL_NEAREST
def _t(s):
return geosoft.gxpy.system.translate(s)
[docs]class GeometryUtilityException(geosoft.GXRuntimeError):
"""
Exceptions from `geosoft.gxpy.geometry_utility`.
.. versionadded:: 9.4
"""
pass
[docs]def resample(pp, interval, spline=SPLINE_CUBIC, closed=None):
"""
Return points resampled at a constant separation along the trace of points.
:param pp: `geosoft.gxpy.geometry.PPoint` instance, or a 2D numpy array.
:param interval: constant sampling interval
:param spline: spline method, one of:
============== ========================================================
SPLINE_LINEAR points will be along linear line segments between points
SPLINE_CUBIC use a minimum-curvature smooth spline
SPLINE_AKIMA us an Akima spline, which will not over-shoot data
SPLINE_NEAREST assign the nearest value
============== ========================================================
:param closed: `True` to close the line. Smooth splines will appear continuous at the join if closed.
If not specified and the first and last points are the same, `True` is assumed.
:return: `geosoft.gxpy.geometry.PPoint` instance, or a 2D numpy array, matching the type passed.
.. versionadded:: 9.4
"""
if interval <= 0:
raise GeometryUtilityException(_t('Interval must be > 0'))
if isinstance(pp, gxgeo.PPoint):
xyz = pp.xyz
else:
if not isinstance(pp, np.ndarray):
pp = np.array(pp, dtype=np.float64)
if pp.ndim == 1:
pp = pp.reshape(len(pp), 1)
if pp.shape[1] >= 3:
xyz = pp[:, :3]
else:
xyz = np.zeros((len(pp), 3), dtype=np.float64)
xyz[:, :pp.shape[1]] = pp
if len(xyz) < 2:
return pp.copy()
# closed?
already_closed = tuple(xyz[0]) == tuple(xyz[-1])
last_point = -1
if len(xyz) == 2:
if already_closed:
return pp.copy()
if closed is None:
closed = False
if spline in (SPLINE_AKIMA, SPLINE_CUBIC):
spline = SPLINE_LINEAR
if closed:
_xyz = np.zeros(len(xyz) + 1)
_xyz[:-1] = xyz
_xyz[-1] = xyz[0]
xyz = _xyz
else:
if closed is None:
closed = already_closed
if closed:
# add points to ensure continuously smooth on ends
if already_closed:
closed_xyz = np.empty((len(xyz) + 4, 3))
closed_xyz[-2:] = xyz[1:3]
closed_xyz[0:2] = xyz[-3:-1]
else:
closed_xyz = np.empty((len(xyz) + 5, 3))
closed_xyz[-3:] = xyz[:3]
closed_xyz[0:2] = xyz[-2:]
closed_xyz[2: 2 + len(xyz)] = xyz
xyz = closed_xyz
last_point = -3
# get vvs
vvx, vvy, vvz = gxvv.vvset_from_np(xyz)
# calculate distance
vvd = gxvv.GXvv(dtype=np.float64)
gxapi.GXVVU.distance_3d(vvx.gxvv, vvy.gxvv, vvz.gxvv, 0., vvd.gxvv)
# make up a sampling vector
if closed:
start = vvd[2][0]
d = vvd[last_point][0] - start
else:
start = 0.
d = vvd[-1][0]
nd = int(d / interval) + 1
if closed:
nd += 1
nps = np.arange(nd, dtype=np.float64) * interval + start
vvs = gxvv.GXvv(nps)
# spline locations
vvxd = gxvv.GXvv(dtype=np.float64)
gxapi.GXVVU.spline2(vvd.gxvv, vvx.gxvv, vvs.gxvv, vvxd.gxvv, spline)
vvyd = gxvv.GXvv(dtype=np.float64)
gxapi.GXVVU.spline2(vvd.gxvv, vvy.gxvv, vvs.gxvv, vvyd.gxvv, spline)
vvzd = gxvv.GXvv(dtype=np.float64)
gxapi.GXVVU.spline2(vvd.gxvv, vvz.gxvv, vvs.gxvv, vvzd.gxvv, spline)
xyz = gxvv.np_from_vvset((vvxd, vvyd, vvzd))
if closed:
xyz[-1] = xyz[0]
if tuple(xyz[-1]) == tuple(xyz[-2]):
xyz = xyz[:-1]
if isinstance(pp, gxgeo.PPoint):
return gxgeo.PPoint(xyz, coordinate_system=pp.coordinate_system)
else:
return xyz[:, :pp.shape[1]]