use nalgebra::{
allocator::Allocator, DefaultAllocator, DimName, DimNameDiff, DimNameSub, OPoint, OVector, U1,
};
use crate::misc::FloatingPoint;
use super::NurbsCurve;
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(bound(
serialize = "T: serde::Serialize, NurbsCurve<T, D>: serde::Serialize",
deserialize = "T: serde::Deserialize<'de>, NurbsCurve<T, D>: serde::Deserialize<'de>"
))
)]
pub struct TrimmedCurve<T: FloatingPoint, D: DimName>
where
DefaultAllocator: Allocator<D>,
{
curve: NurbsCurve<T, D>,
domain: Option<(T, T)>,
}
impl<T: FloatingPoint, D: DimName> TrimmedCurve<T, D>
where
DefaultAllocator: Allocator<D>,
{
pub fn new(curve: NurbsCurve<T, D>, domain: (T, T)) -> Self {
Self {
curve,
domain: Some(domain),
}
}
pub fn from_curve(curve: NurbsCurve<T, D>) -> Self {
Self {
curve,
domain: None,
}
}
pub fn curve(&self) -> &NurbsCurve<T, D> {
&self.curve
}
pub fn curve_mut(&mut self) -> &mut NurbsCurve<T, D> {
&mut self.curve
}
pub fn into_curve(self) -> NurbsCurve<T, D> {
self.curve
}
pub fn domain(&self) -> (T, T) {
self.domain.unwrap_or_else(|| self.curve.knots_domain())
}
pub fn explicit_domain(&self) -> Option<(T, T)> {
self.domain
}
pub fn set_domain(&mut self, domain: Option<(T, T)>) {
self.domain = domain;
}
pub fn is_full_domain(&self) -> bool {
self.domain.is_none()
}
pub fn degree(&self) -> usize {
self.curve.degree()
}
pub fn knots_domain(&self) -> (T, T) {
self.domain()
}
pub fn knots(&self) -> &crate::knot::KnotVector<T> {
self.curve.knots()
}
pub fn control_points(&self) -> &Vec<nalgebra::OPoint<T, D>> {
self.curve.control_points()
}
pub fn control_points_iter_mut(&mut self) -> impl Iterator<Item = &mut nalgebra::OPoint<T, D>> {
self.curve.control_points_iter_mut()
}
pub fn weights(&self) -> Vec<T>
where
D: DimNameSub<U1>,
DefaultAllocator: Allocator<DimNameDiff<D, U1>>,
{
self.curve.weights()
}
pub fn dehomogenized_control_points(&self) -> Vec<OPoint<T, DimNameDiff<D, U1>>>
where
D: DimNameSub<U1>,
DefaultAllocator: Allocator<DimNameDiff<D, U1>>,
{
self.curve.dehomogenized_control_points()
}
}
impl<T: FloatingPoint, D: DimName> From<NurbsCurve<T, D>> for TrimmedCurve<T, D>
where
DefaultAllocator: Allocator<D>,
{
fn from(curve: NurbsCurve<T, D>) -> Self {
Self::from_curve(curve)
}
}
impl<T: FloatingPoint, D: DimName> std::ops::Deref for TrimmedCurve<T, D>
where
DefaultAllocator: Allocator<D>,
{
type Target = NurbsCurve<T, D>;
fn deref(&self) -> &NurbsCurve<T, D> {
&self.curve
}
}
impl<T: FloatingPoint, D: DimName> std::ops::DerefMut for TrimmedCurve<T, D>
where
DefaultAllocator: Allocator<D>,
{
fn deref_mut(&mut self) -> &mut NurbsCurve<T, D> {
&mut self.curve
}
}
impl<T: FloatingPoint, D: DimName> TrimmedCurve<T, D>
where
D: DimNameSub<U1>,
DefaultAllocator: Allocator<D> + Allocator<DimNameDiff<D, U1>>,
{
pub fn point_at(&self, t: T) -> OPoint<T, DimNameDiff<D, U1>> {
self.curve.point_at(t)
}
pub fn start_point(&self) -> OPoint<T, DimNameDiff<D, U1>> {
self.curve.point_at(self.domain().0)
}
pub fn end_point(&self) -> OPoint<T, DimNameDiff<D, U1>> {
self.curve.point_at(self.domain().1)
}
pub fn tangent_at(&self, t: T) -> OVector<T, DimNameDiff<D, U1>> {
self.curve.tangent_at(t)
}
}
pub type TrimmedCurve2D<T> = TrimmedCurve<T, nalgebra::U3>;
pub type TrimmedCurve3D<T> = TrimmedCurve<T, nalgebra::U4>;