Geometry API reference¶
- motmot.geometry.closest(points, target)[source]¶
Select from points the point which is closest to to.
- Parameters
points – An array of vertices to choose from.
target – A single target vertex to be closest to.
- Returns
One vertex from points.
- motmot.geometry.furthest(points, direction, n=None, return_projection=False, return_args=False)[source]¶
Select the point the furthest in direction.
- Parameters
points (numpy.ndarray) – Some points.
direction (numpy.ndarray or UnitVector) – A direction.
n (int or None) – Specify the furthest n points instead of just one.
return_projection (bool) – If true, also return the projection of the furthest point(s).
return_args (bool) – If true, also return the index(es) similar to
numpy.argmax().
- motmot.geometry.get_components(points, *unit_vectors)[source]¶
Get the inner product for each unit vector as separate arrays.
- Parameters
points (numpy.ndarray) –
*unit_vectors (numpy.ndarray or UnitVector) –
- Returns
Projections for each unit vector.
- Return type
- motmot.geometry.get_components_zipped(points, *unit_vectors)[source]¶
Get the inner product for each unit vector.
- Parameters
points –
*unit_vectors (numpy.ndarray or UnitVector) –
- Returns
Projections as one array.
- Return type
The unit-vector iteration corresponds to the last axis of the output. i.e
out[..., i] == inner_product(unit_vectors[i], points)
The more linear-algebra savvy developer will know that this is just a matrix multiplication. This function is purely to reduce confusion for those (like me) who can never remember if you pre or post multiply and when to transpose.
- motmot.geometry.inner_product(a, b, keepdims=False)[source]¶
Calculates the scalar/inner/interior/dot/”whatever you want to call it” product of vectors a and b, returning a scalar.
Arguments a and b must be numpy-broadcastable.
See also
The
UnitVectorclass for a more convenient way to perform multipleinner_product()calls.
- motmot.geometry.magnitude(vector, keepdims=False)[source]¶
Calculate the hypotenuse/magnitude/length of a vector.
- motmot.geometry.magnitude_sqr(vector, keepdims=False)[source]¶
Calculate the square of the hypotenuse of a vector.
This is faster than
magnitude()because it skips taking the square root and can be used to compare or sort distances.
- motmot.geometry.normalise(vector)[source]¶
Modify in-place vector so that it has magnitude
1.0.- Parameters
vector (numpy.ndarray) – Vector(s) to normalise.
- Returns
The original magnitudes of vector.
- Return type
See also
normalised()which leaves the original as-is.
- motmot.geometry.normalised(vector)[source]¶
Return a normalised copy of vector.
See also
normalise()to modify in-place.
- motmot.geometry.snap_to_plane(point, origin, normal)[source]¶
Map point to its nearest point on a plane.
- Parameters
point – A vertex or vertices to move.
origin – The plane’s origin. Or any point already on the plane(s).
normal – A unit normal to the plane.
- Return type
- Returns
The translated points.
Alternatively, you may think of this as move point along normal until the resulting output point satisfies:
inner_product(normal, output) == inner_product(normal, point)
- motmot.geometry.unzip(points)[source]¶
Separate each component from an array of points.
- Parameters
points – Some points.
- Return type
- Returns
Each axis separately as a tuple.
This is the inverse of
zip().
- motmot.geometry.zip(*axes)[source]¶
Combine separate x, y, z arrays into a single points array.
- Parameters
axes – Each separate axis to combine.
- Return type
- Returns
A single array with
shape[-1] == len(axes).
All axes must have the matching or broadcast-able shapes. The number of axes doesn’t have to be 3.
>>> zip(np.arange(5), np.arange(-2, 3)) array([[ 0, -2], [ 1, -1], [ 2, 0], [ 3, 1], [ 4, 2]]) >>> zip(np.arange(10), 4, np.arange(-5, 5)) array([[ 0, 4, -5], [ 1, 4, -4], [ 2, 4, -3], [ 3, 4, -2], [ 4, 4, -1], [ 5, 4, 0], [ 6, 4, 1], [ 7, 4, 2], [ 8, 4, 3], [ 9, 4, 4]])
See also
unzip()for the reverse.This function is similar to
numpy.c_except that it is not limited to 2D arrays.
- class motmot.geometry.UnitVector(vector)[source]¶
Unit vectors symbolise directions.
A
UnitVectorwraps around an numpy array, stored in thevectorattribute, which contains the actual data. It behaves exactly like an array but with extra methods.It is also callable, which applies the inner-product.
Usage Example:
Suppose we have a point cloud of
100points calledpoints.import numpy as np from motmot import geometry points = np.random.uniform(-30, 30, (100, 3))
In a wonky coordinate system that has been so that up is actually the diagonal unit-vector below.
\[\begin{bmatrix} \frac{3}{5}\quad \frac{4}{5}\quad 0 \end{bmatrix}\]Which is passed to Python using the following. Note that the vector is normalised automatically.
>>> up = geometry.UnitVector([3, 4, 0]) >>> up UnitVector([0.6 0.8 0. ])
This can do everything a numpy array can do. Any outputs produced are of type
numpy.ndarray.>>> up * 2 array([1.2, 1.6, 0. ]) >>> up + 1 array([1.6, 1.8, 1. ]) >>> up + up array([1.2, 1.6, 0. ])
There is one exception to the above: Negating it returns another
UnitVector.>>> -up UnitVector([-0.6 -0.8 -0. ])
To get the heights of points use the inner product.
heights = up.inner_product(points)
A typical 3D analysis will involve lots of inner-product calls so the above gets combersome pretty quickly. For convenience, you may instead call the vector directly.
heights = up(points)
Once you have your heights, the following numpy functions are your friends:
heights.min() # minimum height heights.max() # maximum height heights.mean() # average height heights.ptp() # `peak to peak` equivalent to max - min
Get the highest point using:
highest = up.furthest(points)
Or:
highest, max_height = up.furthest(points, return_projection=True)
If you actually want the lowest then invert
upto get adownvector.lowest = (-up).furthest(points)
Methods
get_component()andremove_component()split a point into parts parallel and perpendicular toup.Methods
with_()andmatch()return points modified to have specified heights. They both have the effect of mapping the input onto a plane withupas the plane normal.# Get `points` but with a height of 10. up.with_projection(points, 10) # Get `points` but with the same height as ``points[0]``. up.match_projection(points, points[0])
- __init__(vector)[source]¶
- Parameters
vector (numpy.ndarray or UnitVector or str or list or tuple) – The direction as a vector, or an axis name as a string.
vector is normalised automatically.
The str axis name format is an optional sign (+-) followed by any of
'ijkxyz'. Whitespaces and case are ignored.>>> UnitVector("Z") UnitVector([0. 0. 1.]) >>> UnitVector("+x") UnitVector([1. 0. 0.]) >>> UnitVector("-y") UnitVector([ 0. -1. 0.]) >>> UnitVector("-j") UnitVector([ 0. -1. 0.])
- furthest(points, n=None, return_projection=False, return_args=False)[source]¶
Select, from points, the point with the highest projection in this direction.
- inner_product(vector, keepdims=False)¶
Call self as a function.
- match(point, target_point)[source]¶
Translate point so that
self(point) == self(target_point)Or the returned point is inline with target_point.
- matched_sign(vector)[source]¶
Return a reversed copy of vector if
self(vector) < 0. i.e if the angle between this vector and vector is more than 180°.
- vector: numpy.ndarray¶
The raw numpy vector.