surface module¶
This is a collection of procedures for performing computations on a Bézier surface.
Note
In most of the procedures below both the number of nodes \(N\) and the degree \(d\) of a Bézier surface are provided. It is redundant to require both as arguments since \(N = \binom{d + 2}{2}\). However, both are provided as arguments to avoid unnecessary re-computation, i.e. we expect the caller to know both \(N\) and \(d\).
Procedures¶
-
void
compute_area
(int *num_edges, int *sizes, double **nodes_pointers, double *area, bool *not_implemented)¶ This computes the area of a curved polygon in \(\mathbf{R}^2\) via Green’s theorem. In order to do this, it assumes that the edges
- form a closed loop
- have no intersections with another edge (including self)
- are oriented in the direction of the exterior
Parameters: - num_edges (int*) – [Input] The number of edges \(N\) that bound the curved polygon.
- sizes (int*) – [Input] An array of the size (i.e. the number of nodes) of each of the \(N\) edges.
- nodes_pointers (double**) – [Input] An array of \(N\) pointers. Pointer \(j\) points to the start of the edge \(E_j\) along the boundary of the curved polygon.
- area (double*) – [Output] The computed area of the curved polygon. If
not_implemented
isTRUE
, then this is undefined. - not_implemented (bool*) – [Output] Indicates if a Green’s theorem implementation exists for each of the edges. (Currently, the only degrees supported are 1, 2, 3 and 4.)
Signature:
void compute_area(int *num_edges, int *sizes, double **nodes_pointers, double *area, bool *not_implemented);
-
void
compute_edge_nodes
(int *num_nodes, int *dimension, double *nodes, int *degree, double *nodes1, double *nodes2, double *nodes3)¶ Extracts the edge nodes from the control net of a Bézier surface. For example, if the control net of a quadratic surface is:
\[\left[\begin{array}{c c c c c c} v_{2,0,0} & v_{1,1,0} & v_{0,2,0} & v_{1,0,1} & v_{0,1,1} & v_{0,0,2} \end{array}\right] = \left[\begin{array}{c c c c c c} a & b & c & d & e & f \end{array}\right]\]then the edges are
\[\begin{split}\begin{align*} E_1 &= \left[\begin{array}{c c c} a & b & c \end{array}\right] \\ E_2 &= \left[\begin{array}{c c c} c & e & f \end{array}\right] \\ E_3 &= \left[\begin{array}{c c c} f & d & a \end{array}\right]. \end{align*}\end{split}\]Parameters: - num_nodes (int*) – [Input] The number of nodes \(N\) in the control net of the Bézier surface.
- dimension (int*) – [Input] The dimension \(D\) such that the surface lies in \(\mathbf{R}^D\).
- nodes (double*) – [Input] The actual control net of the Bézier surface as a \(D \times N\) array. This should be laid out in Fortran order, with \(D N\) total values.
- degree (int*) – [Input] The degree \(d\) of the Bézier surface.
- nodes1 (double*) – [Output] The control points of the first edge Bézier curve as a \(D \times (d + 1)\) array, laid out in Fortran order.
- nodes2 (double*) – [Output] The control points of the second edge Bézier curve as a \(D \times (d + 1)\) array, laid out in Fortran order.
- nodes3 (double*) – [Output] The control points of the third edge Bézier curve as a \(D \times (d + 1)\) array, laid out in Fortran order.
Signature:
void compute_edge_nodes(int *num_nodes, int *dimension, double *nodes, int *degree, double *nodes1, double *nodes2, double *nodes3);
-
void
de_casteljau_one_round
(int *num_nodes, int *dimension, double *nodes, int *degree, double *lambda1, double *lambda2, double *lambda3, double *new_nodes)¶ This performs a single round of the de Casteljau algorithm for evaluation in barycentric coordinates \(B(\lambda_1, \lambda_2, \lambda_3)\). This reduces the control net \(v_{i, j, k}^d\) to a lower degree control net
\[v_{i, j, k}^{d - 1} = \lambda_1 v_{i + 1, j, k}^d + \lambda_2 v_{i, j + 1, k}^d + \lambda_3 v_{i, j, k + 1}^d.\]Parameters: - num_nodes (int*) – [Input] The number of nodes \(N\) in the control net of the Bézier surface.
- dimension (int*) – [Input] The dimension \(D\) such that the surface lies in \(\mathbf{R}^D\).
- nodes (double*) – [Input] The actual control net of the Bézier surface as a \(D \times N\) array. This should be laid out in Fortran order, with \(D N\) total values.
- degree (int*) – [Input] The degree \(d\) of the Bézier surface.
- lambda1 (double*) – [Input] The first barycentric parameter along the reference triangle.
- lambda2 (double*) – [Input] The second barycentric parameter along the reference triangle.
- lambda3 (double*) – [Input] The third barycentric parameter along the reference triangle.
- new_nodes (double*) – [Output] The newly-formed degree \(d - 1\) control net. This will be a \(D \times (N - d - 1)\) array.
Signature:
void de_casteljau_one_round(int *num_nodes, int *dimension, double *nodes, int *degree, double *lambda1, double *lambda2, double *lambda3, double *new_nodes);
-
void
evaluate_barycentric
(int *num_nodes, int *dimension, double *nodes, int *degree, double *lambda1, double *lambda2, double *lambda3, double *point)¶ Evaluates a single point on a Bézier surface, with input in barycentric coordinates: \(B(\lambda_1, \lambda_2, \lambda_3)\).
Parameters: - num_nodes (int*) – [Input] The number of nodes \(N\) in the control net of the Bézier surface.
- dimension (int*) – [Input] The dimension \(D\) such that the surface lies in \(\mathbf{R}^D\).
- nodes (double*) – [Input] The actual control net of the Bézier surface as a \(D \times N\) array. This should be laid out in Fortran order, with \(D N\) total values.
- degree (int*) – [Input] The degree \(d\) of the Bézier surface.
- lambda1 (double*) – [Input] The first barycentric parameter along the reference triangle.
- lambda2 (double*) – [Input] The second barycentric parameter along the reference triangle.
- lambda3 (double*) – [Input] The third barycentric parameter along the reference triangle.
- point (double*) – [Output] A \(D \times 1\) array, will contain \(B(\lambda_1, \lambda_2, \lambda_3)\).
Signature:
void evaluate_barycentric(int *num_nodes, int *dimension, double *nodes, int *degree, double *lambda1, double *lambda2, double *lambda3, double *point);
-
void
evaluate_barycentric_multi
(int *num_nodes, int *dimension, double *nodes, int *degree, int *num_vals, double *param_vals, double *evaluated)¶ Evaluates many points on a Bézier surface, with input in barycentric coordinates: \(\left\{B(\lambda_{1,j}, \lambda_{2,j}, \lambda_{3,j})\right\}_j\).
Parameters: - num_nodes (int*) – [Input] The number of nodes \(N\) in the control net of the Bézier surface.
- dimension (int*) – [Input] The dimension \(D\) such that the surface lies in \(\mathbf{R}^D\).
- nodes (double*) – [Input] The actual control net of the Bézier surface as a \(D \times N\) array. This should be laid out in Fortran order, with \(D N\) total values.
- degree (int*) – [Input] The degree \(d\) of the Bézier surface.
- num_vals (int*) – [Input] The number of points \(k\) where \(B\) is being evaluated.
- param_vals (double*) – [Input] A \(k \times 3\) array of \(k\) triples of barycentric coordinates, laid out in Fortran order. This way, the first column contains all \(\lambda_1\) values in contiguous order, and similarly for the other columns.
- evaluated (double*) – [Output] A \(D \times k\) array of all evaluated points on the surface. Column \(j\) will contain \(B(\lambda_{1,j}, \lambda_{2,j}, \lambda_{3,j})\).
Signature:
void evaluate_barycentric_multi(int *num_nodes, int *dimension, double *nodes, int *degree, int *num_vals, double *param_vals, double *evaluated);
-
void
evaluate_cartesian_multi
(int *num_nodes, int *dimension, double *nodes, int *degree, int *num_vals, double *param_vals, double *evaluated)¶ Evaluates many points on a Bézier surface, with input in cartesian coordinates: \(\left\{B(s_j, t_j)\right\}_j\). Each input \((s, t)\) is equivalent to the barycentric input \(\lambda_1 = 1 - s - t\), \(\lambda_2 = s\) and \(\lambda_3 = t\).
Parameters: - num_nodes (int*) – [Input] The number of nodes \(N\) in the control net of the Bézier surface.
- dimension (int*) – [Input] The dimension \(D\) such that the surface lies in \(\mathbf{R}^D\).
- nodes (double*) – [Input] The actual control net of the Bézier surface as a \(D \times N\) array. This should be laid out in Fortran order, with \(D N\) total values.
- degree (int*) – [Input] The degree \(d\) of the Bézier surface.
- num_vals (int*) – [Input] The number of points \(k\) where \(B\) is being evaluated.
- param_vals (double*) – [Input] A \(k \times 2\) array of \(k\) pairs of cartesian coordinates, laid out in Fortran order. This way, the first column contains all \(s\)-values in contiguous order, and similarly for the other column.
- evaluated (double*) – [Output] A \(D \times k\) array of all evaluated points on the surface. Column \(j\) will contain \(B(s_j, t_j)\).
Signature:
void evaluate_cartesian_multi(int *num_nodes, int *dimension, double *nodes, int *degree, int *num_vals, double *param_vals, double *evaluated);
-
void
jacobian_both
(int *num_nodes, int *dimension, double *nodes, int *degree, double *new_nodes)¶ Computes control nets for both cartesian partial derivatives of a Bézier surface \(B_s(s, t)\) and \(B_t(s, t)\). Taking a single (partial) derivative lowers the degree by 1.
Parameters: - num_nodes (int*) – [Input] The number of nodes \(N\) in the control net of the Bézier surface.
- dimension (int*) – [Input] The dimension \(D\) such that the surface lies in \(\mathbf{R}^D\).
- nodes (double*) – [Input] The actual control net of the Bézier surface as a \(D \times N\) array. This should be laid out in Fortran order, with \(D N\) total values.
- degree (int*) – [Input] The degree \(d\) of the Bézier surface.
- new_nodes (double*) – [Output] The combined control nets \(B_s\) and \(B_t\) as a \((2D) \times (N - d - 1)\) array, laid out in Fortran order. The first \(D\) columns contain the control net of \(B_s\) and final \(D\) columns contain the control net of \(B_t\).
Signature:
void jacobian_both(int *num_nodes, int *dimension, double *nodes, int *degree, double *new_nodes);
-
void
jacobian_det
(int *num_nodes, double *nodes, int *degree, int *num_vals, double *param_vals, double *evaluated)¶ Computes \(\det(DB)\) at a many points \((s_j, t_j)\). This is only well-defined if \(\det(DB)\) has two rows, hence the surface must lie in \(\mathbf{R}^2\).
Parameters: - num_nodes (int*) – [Input] The number of nodes \(N\) in the control net of the Bézier surface.
- nodes (double*) – [Input] The actual control net of the Bézier surface as a \(2 \times N\) array. This should be laid out in Fortran order, with \(2 N\) total values.
- degree (int*) – [Input] The degree \(d\) of the Bézier surface.
- num_vals (int*) – [Input] The number of points \(k\) where \(\det(DB)\) is being evaluated.
- param_vals (double*) – [Input] A \(k \times 2\) array of \(k\) pairs of cartesian coordinates, laid out in Fortran order. This way, the first column contains all \(s\)-values in contiguous order, and similarly for the other column.
- evaluated (double*) – [Output] A \(k\) array of all evaluated determinants. The surface. The \(j\)-th value will be \(\det(DB(s_j, t_j))\).
Signature:
void jacobian_det(int *num_nodes, double *nodes, int *degree, int *num_vals, double *param_vals, double *evaluated);
-
void
specialize_surface
(int *num_nodes, int *dimension, double *nodes, int *degree, double *weights_a, double *weights_b, double *weights_c, double *specialized)¶ Changes the control net for a Bézier surface by specializing from the original triangle \((0, 0), (1, 0), (0, 1)\) to a new triangle \(p_1, p_2, p_3\).
Parameters: - num_nodes (int*) – [Input] The number of nodes \(N\) in the control net of the Bézier surface.
- dimension (int*) – [Input] The dimension \(D\) such that the surface lies in \(\mathbf{R}^D\).
- nodes (double*) – [Input] The actual control net of the Bézier surface as a \(D \times N\) array. This should be laid out in Fortran order, with \(D N\) total values.
- degree (int*) – [Input] The degree \(d\) of the Bézier surface.
- weights_a (double*) – [Input] A 3-array containing the barycentric weights for the first node \(p_1\) in the new triangle.
- weights_b (double*) – [Input] A 3-array containing the barycentric weights for the second node \(p_2\) in the new triangle.
- weights_c (double*) – [Input] A 3-array containing the barycentric weights for the third node \(p_3\) in the new triangle.
- specialized (double*) – [Input] The control net of the newly formed Bézier surface as a \(D \times N\) array.
Signature:
void specialize_surface(int *num_nodes, int *dimension, double *nodes, int *degree, double *weights_a, double *weights_b, double *weights_c, double *specialized);
-
void
subdivide_nodes_surface
(int *num_nodes, int *dimension, double *nodes, int *degree, double *nodes_a, double *nodes_b, double *nodes_c, double *nodes_d)¶ Subdivides a Bésurface into four sub-surfaces that cover the original surface. See
Surface.subdivide()
for more detailsParameters: - num_nodes (int*) – [Input] The number of nodes \(N\) in the control net of the Bézier surface.
- dimension (int*) – [Input] The dimension \(D\) such that the surface lies in \(\mathbf{R}^D\).
- nodes (double*) – [Input] The actual control net of the Bézier surface as a \(D \times N\) array. This should be laid out in Fortran order, with \(D N\) total values.
- degree (int*) – [Input] The degree \(d\) of the Bézier surface.
- nodes_a (double*) – [Output] The control net of the lower left sub-surface as a \(D \times N\) array, laid out in Fortran order.
- nodes_b (double*) – [Output] The control net of the central sub-surface as a \(D \times N\) array, laid out in Fortran order.
- nodes_c (double*) – [Output] The control net of the lower right sub-surface as a \(D \times N\) array, laid out in Fortran order.
- nodes_d (double*) – [Output] The control net of the upper left sub-surface as a \(D \times N\) array, laid out in Fortran order.
Signature:
void subdivide_nodes_surface(int *num_nodes, int *dimension, double *nodes, int *degree, double *nodes_a, double *nodes_b, double *nodes_c, double *nodes_d);