Source code for buffalo_wings.airfoil.internal.bezier.bezier_curve_1d

"""One-dimensional Bezier curves used by CST geometry helpers."""

from __future__ import annotations

from collections.abc import Sequence

from buffalo_core.typing import FloatArray, FloatInput, FloatScalar

from .bezier_common import (
    BezierDemotionContinuity,
    bezier_degree,
    demote_bezier_coefficients,
    evaluate_bernstein,
    evaluate_bernstein_u,
    evaluate_bernstein_uu,
    promote_bezier_coefficients,
    validate_bezier_coefficients,
)

type BezierCurve1DInput = Sequence[FloatScalar] | FloatArray


[docs] class BezierCurve1D: """One-dimensional Bezier curve.""" def __init__(self, *, coefficients: BezierCurve1DInput) -> None: """ Initialize one one-dimensional Bezier curve. Parameters ---------- coefficients : Sequence[FloatScalar] | FloatArray Bernstein coefficients ordered from ``u = 0`` to ``u = 1``. Raises ------ ValueError If ``coefficients`` is empty or does not have shape ``(n,)``. """ coefficient_array = validate_bezier_coefficients( coefficients, name="BezierCurve1D coefficients", ) if coefficient_array.size == 0: msg = "BezierCurve1D requires at least one coefficient." raise ValueError(msg) if coefficient_array.ndim != 1: msg = "BezierCurve1D coefficients must have shape (n,)." raise ValueError(msg) self._coefficients = coefficient_array @property def coefficients(self) -> FloatArray: """ Return the stored Bernstein coefficients. This property exposes the stored read-only ``(n,)`` Bernstein coefficient array. """ return self._coefficients @property def degree(self) -> int: """ Return the Bezier degree. This property reports the polynomial degree of the one-dimensional Bezier curve. """ return bezier_degree(self.coefficients)
[docs] def evaluate(self, u: FloatInput) -> FloatArray: """ Evaluate the one-dimensional Bezier curve. Parameters ---------- u : FloatInput Parameter values, typically in ``[0, 1]``. Returns ------- FloatArray Curve values at ``u`` with the same broadcasted shape as the normalized input. """ return evaluate_bernstein(self.coefficients, u)
[docs] def evaluate_u(self, u: FloatInput) -> FloatArray: """ Evaluate the first derivative of the one-dimensional curve. Parameters ---------- u : FloatInput Parameter values, typically in ``[0, 1]``. Returns ------- FloatArray First derivative values at ``u`` with the same broadcasted shape as the normalized input. """ return evaluate_bernstein_u(self.coefficients, u)
[docs] def evaluate_uu(self, u: FloatInput) -> FloatArray: """ Evaluate the second derivative of the one-dimensional curve. Parameters ---------- u : FloatInput Parameter values, typically in ``[0, 1]``. Returns ------- FloatArray Second derivative values at ``u`` with the same broadcasted shape as the normalized input. """ return evaluate_bernstein_uu(self.coefficients, u)
[docs] def promote_degree(self, *, count: int = 1) -> BezierCurve1D: """ Raise the Bezier degree without changing the represented curve. This operation is exact. Parameters ---------- count : int, default=1 Number of degree-elevation steps to apply. Returns ------- BezierCurve1D Elevated one-dimensional Bezier curve. """ coefficients = promote_bezier_coefficients( self.coefficients, count=count, ) return BezierCurve1D(coefficients=coefficients)
[docs] def demote_degree( self, *, count: int = 1, continuity: BezierDemotionContinuity = "NOT_CONNECTED", ) -> BezierCurve1D: """ Lower the Bezier degree with constrained least-squares demotion. This operation is intentionally approximate. It solves a constrained least-squares degree-reduction problem and does not guarantee exact preservation of the original curve, except in the special cases where the original curve is exactly reducible to the requested lower degree. Parameters ---------- count : int, default=1 Number of degree-reduction steps to apply. continuity : {"NOT_CONNECTED", "C0", "C1", "C2"}, default="NOT_CONNECTED" Symmetric endpoint continuity to preserve during each demotion step. ``"NOT_CONNECTED"`` leaves the endpoints unconstrained. ``"C0"``, ``"C1"``, and ``"C2"`` preserve endpoint value, value-plus-first-derivative, and value-plus-first-two-derivatives, respectively, when the current degree allows it. Returns ------- BezierCurve1D Reduced-degree one-dimensional Bezier curve produced by a constrained least-squares approximate demotion. """ coefficients = demote_bezier_coefficients( self.coefficients, count=count, continuity=continuity, ) return BezierCurve1D(coefficients=coefficients)