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
UnitVector
class 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
UnitVector
wraps around an numpy array, stored in thevector
attribute, 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
100
points 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
up
to get adown
vector.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 withup
as 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.