Source code for buffalo_wings.airfoil.internal.curve

"""Classes associated with general curves."""

from abc import ABC, abstractmethod

import numpy as np
from scipy.integrate import quad

from buffalo_wings.internal.numeric import as_float_array, as_float_scalar
from buffalo_wings.type_aliases import FloatArray, FloatInput, FloatScalar


[docs] class Curve(ABC): """ Base class for 1-d curves. Curves can be interrogated based on their natural parameterization, using the parameter, t. """ # # Parametric interface #
[docs] @abstractmethod def xy(self, t: FloatInput) -> tuple[FloatArray, FloatArray]: """ Calculate the coordinates of geometry at parameter location. Parameters ---------- t : numpy.ndarray Parameter for desired locations. Returns ------- numpy.ndarray X-coordinate of point. numpy.ndarray Y-coordinate of point. """
[docs] @abstractmethod def xy_t(self, t: FloatInput) -> tuple[FloatArray, FloatArray]: """ Calculate rates of change of the coordinates at parameter location. Parameters ---------- t : numpy.ndarray Parameter for desired locations. Returns ------- numpy.ndarray Parametric rate of change of the x-coordinate of point. numpy.ndarray Parametric rate of change of the y-coordinate of point. """
[docs] @abstractmethod def xy_tt(self, t: FloatInput) -> tuple[FloatArray, FloatArray]: """ Calculate second derivative of the coordinates at parameter location. Parameters ---------- t : numpy.ndarray Parameter for desired locations. Returns ------- numpy.ndarray Parametric second derivative of the x-coordinate of point. numpy.ndarray Parametric second derivative of the y-coordinate of point. """
[docs] def normal(self, t: FloatInput) -> tuple[FloatArray, FloatArray]: """ Calculate the unit normal at parameter location. Parameters ---------- t : numpy.ndarray Parameter for desired locations. Returns ------- numpy.ndarray, numpy.ndarray Unit normal at point. """ sx, sy = self.tangent(t) nx = -sy ny = sx return nx, ny
[docs] def tangent(self, t: FloatInput) -> tuple[FloatArray, FloatArray]: """ Calculate the unit tangent at parameter location. Parameters ---------- t : numpy.ndarray Parameter for desired locations. Returns ------- numpy.ndarray, numpy.ndarray Unit tangent at point. """ sx, sy = self.xy_t(t) temp = np.sqrt(sx**2 + sy**2) sx = as_float_array(np.divide(sx, temp)) sy = as_float_array(np.divide(sy, temp)) return sx, sy
[docs] def k(self, t: FloatInput) -> FloatArray: """ Calculate the curvature at parameter location. Parameters ---------- t : numpy.ndarray Parameter for desired locations. Returns ------- numpy.ndarray Curvature of surface at point. """ xt, yt = self.xy_t(t) xtt, ytt = self.xy_tt(t) return (xt * ytt - yt * xtt) / (xt**2 + yt**2) ** (3 / 2)
[docs] def arc_length(self, t_s: FloatScalar, t_e: FloatInput) -> FloatArray: """ Calculate the arc-length distance between two points on surface. Parameters ---------- t_s : float Start point of distance calculation. t_e : numpy.ndarray End point of distance calculation. Returns ------- numpy.ndarray Distance from start point to end point. """ def fun(t: float) -> float: xt, yt = self.xy_t(t) return as_float_scalar(np.sqrt(xt**2 + yt**2)) t_begin = float(t_s) t_e = as_float_array(t_e) it = np.nditer([t_e, None]) with it: for ti, alen in it: segment_ends = [x for x in self.joints() if t_begin < x < ti] segment_ends.append(float(ti)) segment_start = t_begin alen[...] = 0.0 for t_end in segment_ends: alen[...] += quad(fun, segment_start, t_end)[0] segment_start = t_end return it.operands[1]
[docs] @abstractmethod def joints(self) -> list[float]: """ Return the locations of any joints/discontinuities in the curve. The resulting list needs to contain any parametric locations where some non-standard discontinuity (slope, curvature, etc.) occurs as well as the end points for the curve (if they exist). Returns ------- List[float] Parametric coordinates of any discontinuities. """