'''The base class to represent a list of points.''' import numpy as np import mt.base.casting as _bc from ..geo import TwoD from ..geond import PointList, castable_ndarray_PointList __all__ = ['PointList2d'] class PointList2d(TwoD, PointList): '''A list of 2D points. See PointList for more details.''' pass _bc.register_castable(np.ndarray, PointList2d, lambda x: castable_ndarray_PointList(x, 2)) _bc.register_cast(np.ndarray, PointList2d, lambda x: PointList2d(x, check=False)) _bc.register_cast(PointList2d, PointList, lambda x: PointList(x.points, check=False)) _bc.register_cast(PointList, PointList2d, lambda x: PointList2d(x.points, check=False)) _bc.register_castable(PointList, PointList2d, lambda x: x.ndim == 2)
points : `numpy.ndarray(shape=(N,2))` The list of 2D vertices in numpy. ''' # ----- internal representations ----- @property def shapely(self): '''Shapely representation for fast intersection operations.''' if not hasattr(self, '_shapely'): import shapely.geometry as _sg self._shapely = _sg.Polygon(self.points) self._shapely = self._shapely.buffer( 0.0001 ) # to clean up any (multi and/or non-simple) polygon into a simple polygon return self._shapely _bc.register_castable(np.ndarray, Polygon, lambda x: castable_ndarray_PointList(x, 2)) _bc.register_cast(np.ndarray, Polygon, lambda x: Polygon(x, check=False)) _bc.register_cast(PointList2d, Polygon, lambda x: Polygon(x.points, check=False)) # ----- joining volumes ----- register_join_volume(Rect, Polygon, join_volume_shapely) register_join_volume(Polygon, Rect, join_volume_shapely) register_join_volume(Polygon, Polygon, join_volume_shapely)
'''Raw moments up to 2nd order of 3D points.''' from mt import np import sys as _sys import mt.base.casting as _bc from ..geo import ThreeD from ..geond import Moments, moments_from_pointlist from .point_list import PointList3d __all__ = ['Moments3d'] class Moments3d(ThreeD, Moments): '''Raw moments up to 2nd order of points living in 3D. See Moments for more details.''' def __repr__(self): return "Moments3d(m0={}, mean={}, cov={})".format(self.m0, self.mean, self.cov.tolist()) _bc.register_cast(Moments3d, Moments, lambda x: Moments(x.m0, x.m1, x.m2)) _bc.register_cast(Moments, Moments3d, lambda x: Moments3d(x.m0, x.m1, x.m2)) _bc.register_castable(Moments, Moments3d, lambda x: x.ndim==3) _bc.register_cast(PointList3d, Moments3d, moments_from_pointlist)
'''Returns an axis-aligned ellipse bounded by the given axis-aligned rectangle x.''' if not isinstance(x, Rect): raise ValueError("Input type must be a `Rect`, '{}' given.".format( x.__class__)) return Ellipse( Aff2d(linear=Lin2d(scale=[x.w / 2, x.h / 2]), offset=x.center_pt)) # ----- casting ----- register_cast( Ellipse, Hyperellipsoid, lambda x: Hyperellipsoid(cast(x.aff_tfm, Aff), make_normalised=False)) register_cast(Hyperellipsoid, Ellipse, lambda x: Ellipse(cast(x.aff_tfm, Aff2d), make_normalised=False)) register_castable(Hyperellipsoid, Ellipse, lambda x: x.ndim == 2) def cast_Ellipse_to_Moments2d(obj): '''Extracts Moments2d from an Ellipse instance.''' a = np.pi / 4 moments = Moments2d(np.pi, [0, 0], [[a, 0], [0, a]]) # unit circle's moments return transform(obj.aff_tfm, moments) # transform register_cast(Ellipse, Moments2d, cast_Ellipse_to_Moments2d) def approx_Moments2d_to_Ellipse(obj): '''Approximates a Moments2d instance with a normalised Ellipse that has the same mean and covariance as the mean and covariance of the instance.'''
self.offset = offset self.linear = linear def __repr__(self): return "Aff2d(offset={}, linear={})".format(self.offset, self.linear) # ----- casting ----- _bc.register_cast( Aff2d, Aff, lambda x: Aff(weights=x.weight, bias=x.offset, check_shapes=False)) _bc.register_cast( Aff, Aff2d, lambda x: Aff2d(offset=x.bias, linear=Lin2d.from_matrix(x.weight))) _bc.register_castable(Aff, Aff2d, lambda x: x.ndim == 2) # ----- transform functions ----- def transform_Aff2d_on_Moments2d(aff_tfm, moments): '''Transform a Moments2d using a 2D affine transformation. Parameters ---------- aff_tfm : Aff2d 2D affine transformation moments : Moments2d 2D moments Returns
if not isinstance(other, Dlt): return super(Dlt, self).multiply(other) return Dlt(self << other.offset, self.scale*other.scale) multiply.__doc__ = Aff.multiply.__doc__ def invert(self): return Dlt(-self.offset/self.scale, 1/self.scale) invert.__doc__ = Aff.invert.__doc__ # ----- casting ----- _bc.register_cast(Dlt, Aff, lambda x: Aff(weight=x.weight, bias=x.bias, check_shapes=False)) _bc.register_cast(Aff, Dlt, lambda x: Dlt(offset=x.bias, scale=np.diagonal(x.weight))) _bc.register_castable(Aff, Dlt, lambda x: np.count_nonzero(x.weight - np.diag(np._diagonal(x.weight))) > 0) # ----- transform functions ----- def transform_Dlt_on_Moments(dlt_tfm, moments): '''Transform the Moments using an affine transformation. Parameters ---------- dlt_tfm : Dlt general dilatation moments : Moments general moments
import mt.base.casting as _bc from ..geo import TwoD from ..geond import Moments, moments_from_pointlist from .point_list import PointList2d __all__ = ['Moments2d'] class Moments2d(TwoD, Moments): '''Raw moments up to 2nd order of points living in 2D. See Moments for more details. Examples -------- >>> import numpy as np >>> from mt.geo2d.moments import Moments2d >>> gm.Moments2d(10, np.array([2,3]), np.array([[1,2],[3,4]])) Moments2d(m0=10.0, mean=[0.2 0.3], cov=[[0.06, 0.14], [0.24, 0.31000000000000005]]) ''' def __repr__(self): return "Moments2d(m0={}, mean={}, cov={})".format( self.m0, self.mean, self.cov.tolist()) _bc.register_cast(Moments2d, Moments, lambda x: Moments(x.m0, x.m1, x.m2)) _bc.register_cast(Moments, Moments2d, lambda x: Moments2d(x.m0, x.m1, x.m2)) _bc.register_castable(Moments, Moments2d, lambda x: x.ndim == 2) _bc.register_cast(PointList2d, Moments2d, moments_from_pointlist)
'''Returns the dimension of the bias vector. Raises ValueError if it is not 3.''' if self.bias.shape[0] != 3: raise ValueError("Expected bias dim to be 3, but seeing {}.".format(self.bias.shape[0])) # ----- methods ----- def __repr__(self): return "Aff3d(weight_diagonal={}, bias={})".format(self.weight.diagonal(), self.bias) # ----- casting ----- _bc.register_cast(Aff3d, Aff, lambda x: Aff(weights=x.weight, bias=x.offset, check_shapes=False)) _bc.register_cast(Aff, Aff3d, lambda x: Aff3d(weight=x.weight, bias=x.bias, check_shape=False)) _bc.register_castable(Aff, Aff3d, lambda x: x.ndim==3) # ----- transform functions ----- def transform_Aff3d_on_Moments3d(aff_tfm, moments): '''Transform a Moments3d using a 3D affine transformation. Parameters ---------- aff_tfm : Aff3d 3D affine transformation moments : Moments3d 3D moments
'''The base class to represent a point. For efficiency reasons, please try to bunch points into arrays or lists and use appropriate representations instead of using single points implemented here. ''' import numpy as _np import mt.base.casting as _bc from ..geo import ThreeD from ..geond import Point, castable_ndarray_Point __all__ = ['Point3d'] class Point3d(ThreeD, Point): '''A 3D point. See Point for more details.''' pass _bc.register_castable(_np.ndarray, Point3d, lambda x: castable_ndarray_Point(x, 3)) _bc.register_cast(_np.ndarray, Point3d, lambda x: Point3d(x, check=False)) _bc.register_cast(Point3d, Point, lambda x: Point(x.point, check=False)) _bc.register_cast(Point, Point3d, lambda x: Point3d(x.point, check=False)) _bc.register_castable(Point, Point3d, lambda x: x.ndim == 3)