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
vec1orvec2is 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
valueis 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)^TsinceB^TandA^Twill be C-contiguous without a copy, then the productP = B^T A^Twill be C-contiguous and we can return the viewP^Twithout 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
valueis in \(\left[0, 1\right]\).Allows a little bit of wiggle room outside the interval. A value within
wiggleof0.0will be converted to0.0and 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
valueif it’s in the interval, or0.0or1.0if the value lies slightly outside. If thevalueis too far outside the unit interval, will be NaN.Boolean indicating if the
valueis 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
bisectbuiltin 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.ConvexHullcan do this as well (via Qhull), but that would require a hard dependency onscipyand 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 nvs.n^2vs.naren’t that relevant.- Parameters:
points (numpy.ndarray) – A
2 x Narray (float64) of points.- Returns:
The
2 x Narray (float64) of ordered points in the polygonal convex hull.- Return type:
- bezier.hazmat.helpers.is_separating(direction, polygon1, polygon2)
Checks if a given
directionis 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 Narray (float64) of ordered points in a polygon.polygon2 (numpy.ndarray) – A
2 x Narray (float64) of ordered points in a polygon.
- Returns:
Flag indicating if
directionis 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 Narray (float64) of ordered points in a polygon.polygon2 (numpy.ndarray) – A
2 x Narray (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 todgetrfanddgetrs. 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 2array of real numbers.rhs (numpy.ndarray) – A 1D array of 2 real numbers.
- Returns:
A triple of
A flag indicating if
lhsis 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:
NotImplementedErrorCustom exception to indicate the given degree is unsupported.
This is intentionally a subclass of a
NotImplementedErrorsince 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.