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.
Parameters: Returns: Indicating if the value is in the interval.
Return type:
-
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.
Parameters: nodes (numpy.ndarray) – A set of points. Returns: The left, right, bottom and top bounds for the box. Return type: Tuple
float
,float
,float
,float
-
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: - The
-
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
.Parameters: Returns: Indicating if the value is contained.
Return type:
-
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: numpy.ndarray
-
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: - direction (numpy.ndarray) – A 1D
-
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: - polygon1 (numpy.ndarray) – A
-
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: - We seek to avoid exceptions as part of the control flow (which is
what
-
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: -
args
-
with_traceback
() Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
-