bezier.hazmat.helpers module
Pure Python generic geometry and floating point helpers.
- bezier.hazmat.helpers.vector_close(vec1, vec2, eps=9.094947017729282e-13)
Checks that two vectors are equal to some threshold.
Does so by computing \(s_1 = \|v_1\|_2\) and \(s_2 = \|v_2\|_2\) and then checking if
\[\|v_1 - v_2\|_2 \leq \varepsilon \min(s_1, s_2)\]where \(\varepsilon = 2^{-40} \approx 10^{-12}\) is a fixed threshold. In the rare case that one of
vec1
orvec2
is the zero vector (i.e. when \(\min(s_1, s_2) = 0\)) instead checks that the other vector is close enough to zero:\[\|v_1\|_2 = 0 \Longrightarrow \|v_2\|_2 \leq \varepsilon\]Note
This function assumes that both vectors have finite values, i.e. that no NaN or infinite numbers occur. NumPy provides
numpy.allclose()
for coverage of all cases.Note
There is also a Fortran implementation of this function, which will be used if it can be built.
- Parameters:
vec1 (numpy.ndarray) – First vector (1D) for comparison.
vec2 (numpy.ndarray) – Second vector (1D) for comparison.
eps (float) – Error threshold. Defaults to \(2^{-40}\).
- Returns:
Flag indicating if they are close to precision.
- Return type:
- bezier.hazmat.helpers.in_interval(value, start, end)
Checks if a
value
is an interval (inclusive).Note
The current implementation does the most basic check, however, in the future, a more generic check may be desired that allows wiggle room around the endpoints to account for round-off.
Note
There is also a Fortran implementation of this function, which will be used if it can be built.
- bezier.hazmat.helpers.bbox(nodes)
Get the bounding box for set of points.
Note
There is also a Fortran implementation of this function, which will be used if it can be built.
- bezier.hazmat.helpers.contains_nd(nodes, point)
Predicate indicating if a point is within a bounding box.
Note
There is also a Fortran implementation of this function, which will be used if it can be built.
- Parameters:
nodes (numpy.ndarray) – A set of points.
point (numpy.ndarray) – A 1D NumPy array representing a point in the same dimension as
nodes
.
- Returns:
Indicating containment.
- Return type:
- bezier.hazmat.helpers.cross_product(vec0, vec1)
Compute the cross product of vectors in \(\mathbf{R}^2\).
Utilizes the fact that
\[\begin{split}\left[\begin{array}{c} A \\ B \\ 0 \end{array}\right] \times \left[\begin{array}{c} C \\ D \\ 0 \end{array}\right] = \left[\begin{array}{c} 0 \\ 0 \\ AD - BC \end{array}\right]\end{split}\]and just returns the \(z\) component.
Note
There is also a Fortran implementation of this function, which will be used if it can be built.
- Parameters:
vec0 (numpy.ndarray) – A vector as a 1D NumPy array with two values.
vec1 (numpy.ndarray) – A vector as a 1D NumPy array with two values.
- Returns:
The cross product (or rather, its \(z\) component).
- Return type:
- bezier.hazmat.helpers.matrix_product(mat1, mat2)
Compute the product of two Fortran contiguous matrices.
This is to avoid the overhead of NumPy converting to C-contiguous before computing a matrix product.
Does so via
A B = (B^T A^T)^T
sinceB^T
andA^T
will be C-contiguous without a copy, then the productP = B^T A^T
will be C-contiguous and we can return the viewP^T
without a copy.- Parameters:
mat1 (numpy.ndarray) – The left-hand side matrix.
mat2 (numpy.ndarray) – The right-hand side matrix.
- Returns:
The product of the two matrices.
- Return type:
- bezier.hazmat.helpers.wiggle_interval(value, wiggle=5.684341886080802e-14)
Check if
value
is in \(\left[0, 1\right]\).Allows a little bit of wiggle room outside the interval. A value within
wiggle
of0.0
will be converted to0.0
and similar for1.0
.Note
There is also a Fortran implementation of this function, which will be used if it can be built.
- Parameters:
- Returns:
Pair of
The
value
if it’s in the interval, or0.0
or1.0
if the value lies slightly outside. If thevalue
is too far outside the unit interval, will be NaN.Boolean indicating if the
value
is inside the unit interval.
- Return type:
- bezier.hazmat.helpers.cross_product_compare(start, candidate1, candidate2)
Compare two relative changes by their cross-product.
This is meant to be a way to determine which vector is more “inside” relative to
start
.Note
This is a helper for
simple_convex_hull()
.- Parameters:
start (numpy.ndarray) – The start vector (as 1D NumPy array with 2 elements).
candidate1 (numpy.ndarray) – The first candidate vector (as 1D NumPy array with 2 elements).
candidate2 (numpy.ndarray) – The second candidate vector (as 1D NumPy array with 2 elements).
- Returns:
The cross product of the two differences.
- Return type:
- bezier.hazmat.helpers.in_sorted(values, value)
Checks if a value is in a sorted list.
Uses the
bisect
builtin to find the insertion point forvalue
.
- bezier.hazmat.helpers.simple_convex_hull(points)
Compute the convex hull for a set of points.
This uses Andrew’s monotone chain convex hull algorithm and this code used a wikibooks implementation as motivation. The code there is licensed CC BY-SA 3.0.
Note
There is also a Fortran implementation of this function, which will be used if it can be built. Note that
scipy.spatial.ConvexHull
can do this as well (via Qhull), but that would require a hard dependency onscipy
and that helper computes much more than we need.Note
This computes the convex hull in a “naive” way. It’s expected that internal callers of this function will have a small number of points so
n log n
vs.n^2
vs.n
aren’t that relevant.- Parameters:
points (numpy.ndarray) – A
2 x N
array (float64
) of points.- Returns:
The
2 x N
array (float64
) of ordered points in the polygonal convex hull.- Return type:
- bezier.hazmat.helpers.is_separating(direction, polygon1, polygon2)
Checks if a given
direction
is a separating line for two polygons.Note
This is a helper for
polygon_collide()
.- Parameters:
direction (numpy.ndarray) – A 1D
2
-array (float64
) of a potential separating line for the two polygons.polygon1 (numpy.ndarray) – A
2 x N
array (float64
) of ordered points in a polygon.polygon2 (numpy.ndarray) – A
2 x N
array (float64
) of ordered points in a polygon.
- Returns:
Flag indicating if
direction
is a separating line.- Return type:
- bezier.hazmat.helpers.polygon_collide(polygon1, polygon2)
Determines if two convex polygons collide.
This code uses the Separating axis theorem (SAT) to quickly determine if the polygons intersect. See also.
Note
There is also a Fortran implementation of this function, which will be used if it can be built.
- Parameters:
polygon1 (numpy.ndarray) – A
2 x N
array (float64
) of ordered points in a polygon.polygon2 (numpy.ndarray) – A
2 x N
array (float64
) of ordered points in a polygon.
- Returns:
Flag indicating if the two polygons collide.
- Return type:
- bezier.hazmat.helpers.solve2x2(lhs, rhs)
Solve a square 2 x 2 system via LU factorization.
This is meant to be a stand-in for LAPACK’s
dgesv
, which just wraps two calls todgetrf
anddgetrs
. We wrap for two reasons:We seek to avoid exceptions as part of the control flow (which is what
numpy.linalg.solve()
does).We seek to avoid excessive type- and size-checking, since this special case is already known.
- Parameters:
lhs (numpy.ndarray) – A
2 x 2
array of real numbers.rhs (numpy.ndarray) – A 1D array of 2 real numbers.
- Returns:
A triple of
A flag indicating if
lhs
is a singular matrix.The first component of the solution.
The second component of the solution.
- Return type:
- exception bezier.hazmat.helpers.UnsupportedDegree(degree, supported=())
Bases:
NotImplementedError
Custom exception to indicate the given degree is unsupported.
This is intentionally a subclass of a
NotImplementedError
since it’s intended to indicate a lack of an implementation. For example,Curve.reduce_()
uses hard-coded matrices for a small subset of possible degrees, so the implementation is degree-specific:>>> import bezier >>> import numpy as np >>> degree = 5 >>> nodes = np.empty((2, degree + 1), order="F") >>> curve = bezier.Curve(nodes, degree=degree) >>> curve.reduce_() Traceback (most recent call last): ... bezier.hazmat.helpers.UnsupportedDegree: The only degrees supported at this time are 1, 2, 3 and 4 (degree=5)
- Parameters:
- add_note()
Exception.add_note(note) – add a note to the exception
- args
- with_traceback()
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.