Struct truck_geometry::BSplineCurve [−][src]
B-spline curve
Examples
use truck_geometry::*; // the knot vector let knot_vec = KnotVec::from( vec![0.0, 0.0, 0.0, 0.25, 0.25, 0.5, 0.5, 0.75, 0.75, 1.0, 1.0, 1.0] ); // sign up the control points in the vector of all points let ctrl_pts = vec![ // the vector of the indices of control points Vector4::new(0.0, -2.0, 0.0, 2.0), Vector4::new(1.0, -1.0, 0.0, 1.0), Vector4::new(1.0, 0.0, 0.0, 1.0), Vector4::new(1.0, 1.0, 0.0, 1.0), Vector4::new(0.0, 2.0, 0.0, 2.0), Vector4::new(-1.0, 1.0, 0.0, 1.0), Vector4::new(-1.0, 0.0, 0.0, 1.0), Vector4::new(-1.0, -1.0, 0.0, 1.0), Vector4::new(0.0, -2.0, 0.0, 2.0), ]; // construct the B-spline curve let bspline = BSplineCurve::new(knot_vec, ctrl_pts); // This B-spline curve is a nurbs representation of the unit circle. const N : usize = 100; // sample size in test for i in 0..N { let t = 1.0 / (N as f64) * (i as f64); let v = bspline.subs(t); // We can use the instances as a function. let c = (v[0] / v[3]).powi(2) + (v[1] / v[3]).powi(2); f64::assert_near2(&c, &1.0); }
Implementations
impl<V> BSplineCurve<V>
[src]
pub fn new(knot_vec: KnotVec, control_points: Vec<V>) -> BSplineCurve<V>
[src]
constructor.
Arguments
knot_vec
- the knot vectorcontrol_points
- the vector of the control points
Panics
Panics occurs if:
- There are no control points.
- The number of knots is more than the one of control points.
- The range of the knot vector is zero.
pub fn try_new(
knot_vec: KnotVec,
control_points: Vec<V>
) -> Result<BSplineCurve<V>>
[src]
knot_vec: KnotVec,
control_points: Vec<V>
) -> Result<BSplineCurve<V>>
constructor.
Arguments
knot_vec
- the knot vectorcontrol_points
- the vector of the control points
Failures
- If there are no control points, returns
Error::EmptyControlPoints
. - If the number of knots is more than the one of control points, returns
Error::TooShortKnotVector
. - If the range of the knot vector is zero, returns
Error::ZeroRange
.
pub const fn new_unchecked(
knot_vec: KnotVec,
control_points: Vec<V>
) -> BSplineCurve<V>
[src]
knot_vec: KnotVec,
control_points: Vec<V>
) -> BSplineCurve<V>
constructor.
Arguments
knot_vec
- the knot vectorcontrol_points
- the vector of the control points
Remarks
This method is prepared only for performance-critical development and is not recommended.
This method does NOT check the rules for constructing B-spline curve.
The programmer must guarantee these conditions before using this method.
pub fn debug_new(knot_vec: KnotVec, control_points: Vec<V>) -> BSplineCurve<V>
[src]
constructor.
Arguments
knot_vec
- the knot vectorcontrol_points
- the vector of the control points
Remarks
This method checks the rules for constructing B-spline curve in the debug mode.
The programmer must guarantee these conditions before using this method.
pub fn knot_vec(&self) -> &KnotVec
[src]
Returns the reference of the knot vector
pub fn knot(&self, idx: usize) -> f64
[src]
Returns the idx
th knot
pub fn control_points(&self) -> &Vec<V>ⓘ
[src]
Returns the reference of the control points.
pub fn control_point(&self, idx: usize) -> &V
[src]
Returns the reference of the control point corresponding to the index idx
.
pub fn control_point_mut(&mut self, idx: usize) -> &mut V
[src]
Returns the mutable reference of the control point corresponding to index idx
.
pub fn control_points_mut(&mut self) -> impl Iterator<Item = &mut V>
[src]
Returns the iterator on all control points
pub fn transform_control_points<F: FnMut(&mut V)>(&mut self, f: F)
[src]
Apply the given transformation to all control points.
pub fn degree(&self) -> usize
[src]
Returns the degree of B-spline curve
Examples
use truck_geometry::*; let knot_vec = KnotVec::bezier_knot(2); let ctrl_pts = vec![Vector2::new(1.0, 2.0), Vector2::new(2.0, 3.0), Vector2::new(3.0, 4.0)]; let bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); assert_eq!(bspcurve.degree(), 2);
pub fn invert(&mut self) -> &mut Self
[src]
Inverts a curve
Examples
use truck_geometry::*; let knot_vec = KnotVec::uniform_knot(2, 2); let ctrl_pts = vec![Vector2::new(1.0, 2.0), Vector2::new(2.0, 3.0), Vector2::new(3.0, 4.0), Vector2::new(4.0, 5.0)]; let bspcurve0 = BSplineCurve::new(knot_vec, ctrl_pts); let mut bspcurve1 = bspcurve0.clone(); bspcurve1.invert(); const N: usize = 100; // sample size for i in 0..=N { let t = (i as f64) / (N as f64); Vector2::assert_near2(&bspcurve0.subs(t), &bspcurve1.subs(1.0 - t)); }
pub fn is_clamped(&self) -> bool
[src]
Returns whether the knot vector is clamped or not.
pub fn knot_normalize(&mut self) -> &mut Self
[src]
Normalizes the knot vector
pub fn knot_translate(&mut self, x: f64) -> &mut Self
[src]
Translates the knot vector
impl<V: VectorSpace<Scalar = f64>> BSplineCurve<V>
[src]
pub fn subs(&self, t: f64) -> V
[src]
Substitutes to B-spline curve.
Examples
use truck_geometry::*; let knot_vec = KnotVec::from(vec![-1.0, -1.0, -1.0, 1.0, 1.0, 1.0]); let ctrl_pts = vec![Vector2::new(-1.0, 1.0), Vector2::new(0.0, -1.0), Vector2::new(1.0, 1.0)]; let bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); // bspcurve coincides with (t, t * t) in the range [-1.0..1.0]. const N: usize = 100; // sample size for i in 0..=N { let t = -1.0 + 2.0 * (i as f64) / (N as f64); Vector2::assert_near2(&bspcurve.subs(t), &Vector2::new(t, t * t)); }
pub fn der(&self, t: f64) -> V
[src]
Substitutes to the derived B-spline curve.
Examples
use truck_geometry::*; let knot_vec = KnotVec::bezier_knot(2); let ctrl_pts = vec![Vector2::new(0.0, 0.0), Vector2::new(0.5, 0.0), Vector2::new(1.0, 1.0)]; let bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); // `bpscurve = (t, t^2), derived = (1, 2t)` const N : usize = 100; // sample size for i in 0..=N { let t = 1.0 / (N as f64) * (i as f64); Vector2::assert_near2(&bspcurve.der(t), &Vector2::new(1.0, 2.0 * t)); }
pub fn get_closure(&self) -> impl Fn(f64) -> V + '_
[src]
Returns the closure of substitution.
Examples
The following test code is the same test with the one of BSplineCurve::subs()
.
use truck_geometry::*; let knot_vec = KnotVec::from(vec![-1.0, -1.0, -1.0, 1.0, 1.0, 1.0]); let ctrl_pts = vec![Vector2::new(-1.0, 1.0), Vector2::new(0.0, -1.0), Vector2::new(1.0, 1.0)]; let bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); const N: usize = 100; // sample size let get_t = |i: usize| -1.0 + 2.0 * (i as f64) / (N as f64); let res: Vec<_> = (0..=N).map(get_t).map(bspcurve.get_closure()).collect(); let ans: Vec<_> = (0..=N).map(get_t).map(|t| Vector2::new(t, t * t)).collect(); res.iter().zip(&ans).for_each(|(v0, v1)| Vector2::assert_near2(v0, v1));
pub fn derivation(&self) -> BSplineCurve<V>
[src]
Returns the derived B-spline curve.
Examples
use truck_geometry::*; let knot_vec = KnotVec::bezier_knot(2); let ctrl_pts = vec![Vector2::new(0.0, 0.0), Vector2::new(0.5, 0.0), Vector2::new(1.0, 1.0)]; let bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); let derived = bspcurve.derivation(); // `bpscurve = (t, t^2), derived = (1, 2t)` const N : usize = 100; // sample size for i in 0..=N { let t = 1.0 / (N as f64) * (i as f64); Vector2::assert_near2(&derived.subs(t), &Vector2::new(1.0, 2.0 * t)); }
impl<V: VectorSpace<Scalar = f64> + Tolerance> BSplineCurve<V>
[src]
pub fn is_const(&self) -> bool
[src]
Returns whether all control points are the same or not. If the knot vector is clamped, it means whether the curve is constant or not.
Examples
use truck_geometry::*; let knot_vec = KnotVec::bezier_knot(2); let pt = Vector2::new(1.0, 2.0); let mut ctrl_pts = vec![pt.clone(), pt.clone(), pt.clone()]; let const_bspcurve = BSplineCurve::new(knot_vec.clone(), ctrl_pts.clone()); assert!(const_bspcurve.is_const()); ctrl_pts.push(Vector2::new(2.0, 3.0)); let bspcurve = BSplineCurve::new(knot_vec.clone(), ctrl_pts.clone()); assert!(!bspcurve.is_const());
Remarks
If the knot vector is not clamped and the BSpline basis function is not partition of unity, then perhaps returns true even if the curve is not constant.
use truck_geometry::*; let knot_vec = KnotVec::uniform_knot(1, 5); let ctrl_pts = vec![Vector2::new(1.0, 2.0), Vector2::new(1.0, 2.0)]; let bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); // bspcurve is not constant. assert_eq!(bspcurve.subs(0.0), Vector2::new(0.0, 0.0)); assert_ne!(bspcurve.subs(0.5), Vector2::new(0.0, 0.0)); // bspcurve.is_const() is true assert!(bspcurve.is_const());
pub fn add_knot(&mut self, x: f64) -> &mut Self
[src]
Adds a knot x
, and do not change self
as a curve.
Examples
use truck_geometry::*; let knot_vec = KnotVec::bezier_knot(2); let ctrl_pts = vec![Vector2::new(-1.0, 1.0), Vector2::new(0.0, -1.0), Vector2::new(1.0, 1.0)]; let mut bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); let org_curve = bspcurve.clone(); // add 4 knots bspcurve.add_knot(0.5).add_knot(0.5).add_knot(0.25).add_knot(0.75); assert_eq!(bspcurve.knot_vec().len(), org_curve.knot_vec().len() + 4); // bspcurve does not change as a curve assert!(bspcurve.near2_as_curve(&org_curve));
Remarks
If the added knot x
is out of the range of the knot vector, then the knot vector will extended.
use truck_geometry::*; let knot_vec = KnotVec::bezier_knot(2); let ctrl_pts = vec![Vector2::new(-1.0, 1.0), Vector2::new(0.0, -1.0), Vector2::new(1.0, 1.0)]; let mut bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); assert_eq!(bspcurve.knot_vec().range_length(), 1.0); assert_eq!(bspcurve.front(), Point2::new(-1.0, 1.0)); assert_eq!(bspcurve.back(), Point2::new(1.0, 1.0)); // add knots out of the range of the knot vectors. bspcurve.add_knot(-1.0).add_knot(2.0); assert_eq!(bspcurve.knot_vec().range_length(), 3.0); assert_eq!(bspcurve.front(), Point2::new(0.0, 0.0)); assert_eq!(bspcurve.back(), Point2::new(0.0, 0.0));
pub fn remove_knot(&mut self, idx: usize) -> &mut Self
[src]
Removes a knot corresponding to the indices idx
, and do not change self
as a curve.
If cannot remove the knot, do not change self
and return self
.
Examples
use truck_geometry::*; let knot_vec = KnotVec::bezier_knot(2); let ctrl_pts = vec![Vector2::new(-1.0, 1.0), Vector2::new(0.0, -1.0), Vector2::new(1.0, 1.0)]; let mut bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); let org_curve = bspcurve.clone(); // add knots and remove them. bspcurve.add_knot(0.5).add_knot(0.5).add_knot(0.25).add_knot(0.75); bspcurve.remove_knot(3).remove_knot(3).remove_knot(3).remove_knot(3); assert!(bspcurve.near2_as_curve(&org_curve)); assert_eq!(bspcurve.knot_vec().len(), org_curve.knot_vec().len())
pub fn try_remove_knot(&mut self, idx: usize) -> Result<&mut BSplineCurve<V>>
[src]
Removes a knot corresponding to the indice idx
, and do not change self
as a curve.
If the knot cannot be removed, returns
Error::CannotRemoveKnot
.
Examples
use truck_geometry::*; use errors::Error; let knot_vec = KnotVec::bezier_knot(2); let ctrl_pts = vec![Vector2::new(-1.0, 1.0), Vector2::new(0.0, -1.0), Vector2::new(1.0, 1.0)]; let mut bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); let org_curve = bspcurve.clone(); bspcurve.add_knot(0.5).add_knot(0.5).add_knot(0.25).add_knot(0.75); assert!(bspcurve.try_remove_knot(3).is_ok()); assert_eq!(bspcurve.try_remove_knot(2), Err(Error::CannotRemoveKnot(2)));
pub fn elevate_degree(&mut self) -> &mut Self
[src]
elevate 1 degree.
Examples
use truck_geometry::*; let knot_vec = KnotVec::bezier_knot(1); let ctrl_pts = vec![Vector2::new(0.0, 0.0), Vector2::new(1.0, 1.0)]; let mut bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); bspcurve.elevate_degree(); assert_eq!(bspcurve.degree(), 2); assert_eq!(bspcurve.knot_vec(), &KnotVec::bezier_knot(2)); assert_eq!(bspcurve.control_point(1), &Vector2::new(0.5, 0.5));
pub fn clamp(&mut self) -> &mut Self
[src]
Makes the B-spline curve clamped
Examples
use truck_geometry::*; let knot_vec = KnotVec::from(vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]); let ctrl_pts = vec![Vector2::new(0.0, 1.0), Vector2::new(1.0, 2.0), Vector2::new(2.0, 3.0)]; let mut bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); assert!(!bspcurve.is_clamped()); bspcurve.clamp(); assert!(bspcurve.is_clamped()); assert_eq!(bspcurve.knot_vec().len(), 10);
pub fn optimize(&mut self) -> &mut Self
[src]
Repeats Self::try_remove_knot()
from the back knot in turn until the knot cannot be removed.
Examples
use truck_geometry::*; let knot_vec = KnotVec::bezier_knot(2); let ctrl_pts = vec![Vector2::new(1.0, 2.0), Vector2::new(2.0, 3.0), Vector2::new(3.0, 4.0)]; let mut bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); let org_curve = bspcurve.clone(); // add 4 new knots bspcurve.add_knot(0.5).add_knot(0.5).add_knot(0.25).add_knot(0.75); assert_eq!(bspcurve.knot_vec().len(), KnotVec::bezier_knot(2).len() + 4); // By the optimization, added knots are removed. bspcurve.optimize(); assert_eq!(bspcurve.knot_vec(), &KnotVec::bezier_knot(2)); assert!(bspcurve.near2_as_curve(&org_curve));
pub fn syncro_degree(&mut self, other: &mut Self)
[src]
Makes two splines having the same degrees.
Examples
use truck_geometry::*; let knot_vec0 = KnotVec::bezier_knot(1); let ctrl_pts0 = vec![Vector2::new(1.0, 2.0), Vector2::new(2.0, 3.0)]; let mut bspcurve0 = BSplineCurve::new(knot_vec0, ctrl_pts0); let knot_vec1 = KnotVec::bezier_knot(2); let ctrl_pts1 = vec![Vector2::new(1.0, 2.0), Vector2::new(2.0, 3.0), Vector2::new(3.0, 4.0)]; let mut bspcurve1 = BSplineCurve::new(knot_vec1, ctrl_pts1); assert_ne!(bspcurve0.degree(), bspcurve1.degree()); let org_curve0 = bspcurve0.clone(); let org_curve1 = bspcurve1.clone(); bspcurve0.syncro_degree(&mut bspcurve1); assert_eq!(bspcurve0.degree(), bspcurve1.degree()); assert!(bspcurve0.near2_as_curve(&org_curve0)); assert!(bspcurve1.near2_as_curve(&org_curve1));
pub fn syncro_knots(&mut self, other: &mut BSplineCurve<V>)
[src]
Makes two splines having the same normalized knot vectors.
Examples
use truck_geometry::*; let knot_vec0 = KnotVec::from(vec![0.0, 0.0, 0.0, 0.5, 1.0, 1.0, 1.0]); let ctrl_pts0 = vec![Vector2::new(0.0, 0.0), Vector2::new(1.0, 1.0), Vector2::new(2.0, 2.0), Vector2::new(3.0, 3.0)]; let mut bspcurve0 = BSplineCurve::new(knot_vec0, ctrl_pts0); let mut org_curve0 = bspcurve0.clone(); let knot_vec1 = KnotVec::from(vec![0.0, 0.0, 1.0, 3.0, 4.0, 4.0]); let ctrl_pts1 = vec![Vector2::new(0.0, 0.0), Vector2::new(1.0, 1.0), Vector2::new(2.0, 2.0), Vector2::new(3.0, 3.0)]; let mut bspcurve1 = BSplineCurve::new(knot_vec1, ctrl_pts1); let mut org_curve1 = bspcurve1.clone(); bspcurve0.syncro_knots(&mut bspcurve1); // The knot vectors are made the same. assert_eq!(bspcurve0.knot_vec(), bspcurve1.knot_vec()); assert_eq!( bspcurve0.knot_vec().as_slice(), &[0.0, 0.0, 0.0, 0.25, 0.5, 0.75, 1.0, 1.0, 1.0] ); // The degrees are not changed. assert_eq!(bspcurve0.degree(), org_curve0.degree()); assert_eq!(bspcurve1.degree(), org_curve1.degree()); // The knot vector is normalized, however, the shape of curve is not changed. assert!(bspcurve0.near2_as_curve(org_curve0.knot_normalize())); assert!(bspcurve1.near2_as_curve(org_curve1.knot_normalize()));
pub fn cut(&mut self, t: f64) -> BSplineCurve<V>
[src]
Cuts the curve to two curves at the parameter t
Examples
use truck_geometry::*; let knot_vec = KnotVec::uniform_knot(2, 3); let ctrl_pts = vec![ Vector2::new(0.0, 0.0), Vector2::new(1.0, 0.0), Vector2::new(2.0, 2.0), Vector2::new(4.0, 3.0), Vector2::new(5.0, 6.0), ]; let bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); let mut part0 = bspcurve.clone(); let part1 = part0.cut(0.56); const N: usize = 100; for i in 0..=N { let t = 0.56 * (i as f64) / (N as f64); Vector2::assert_near2(&bspcurve.subs(t), &part0.subs(t)); } for i in 0..=N { let t = 0.56 + 0.44 * (i as f64) / (N as f64); Vector2::assert_near2(&bspcurve.subs(t), &part1.subs(t)); }
pub fn bezier_decomposition(&self) -> Vec<BSplineCurve<V>>ⓘ
[src]
Separates self
into Bezier curves by each knots.
Examples
use truck_geometry::*; let knot_vec = KnotVec::uniform_knot(2, 2); let ctrl_pts = vec![Vector2::new(0.0, 1.0), Vector2::new(1.0, 2.0), Vector2::new(2.0, 3.0), Vector2::new(3.0, 4.0)]; let bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); let beziers = bspcurve.bezier_decomposition(); const N: usize = 100; for i in 0..=N { let t = 0.5 * (i as f64) / (N as f64); Vector2::assert_near2(&bspcurve.subs(t), &beziers[0].subs(t)); } for i in 0..=N { let t = 0.5 + 0.5 * (i as f64) / (N as f64); Vector2::assert_near2(&bspcurve.subs(t), &beziers[1].subs(t)); }
pub fn try_concat(&mut self, other: &mut BSplineCurve<V>) -> Result<&mut Self>
[src]
Concats two B-spline curves.
Examples
use truck_geometry::*; let knot_vec = KnotVec::uniform_knot(2, 3); let ctrl_pts = vec![ Vector2::new(0.0, 0.0), Vector2::new(1.0, 0.0), Vector2::new(2.0, 2.0), Vector2::new(4.0, 3.0), Vector2::new(5.0, 6.0), ]; let bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); let mut part0 = bspcurve.clone(); let mut part1 = part0.cut(0.56); part0.try_concat(&mut part1).unwrap(); assert!(bspcurve.near2_as_curve(&part0));
Failure
If the back of the knot vector of self
does not coincides with the front of the one of other
,
returns Error::DifferentBackFront
.
use truck_geometry::*; use errors::Error; let knot_vec0 = KnotVec::from(vec![0.0, 0.0, 1.0, 1.0]); let ctrl_pts0 = vec![Vector2::new(0.0, 0.0), Vector2::new(1.0, 1.0)]; let mut bspcurve0 = BSplineCurve::new(knot_vec0, ctrl_pts0); let knot_vec1 = KnotVec::from(vec![2.0, 2.0, 3.0, 3.0]); let ctrl_pts1 = vec![Vector2::new(1.0, 1.0), Vector2::new(2.0, 2.0)]; let mut bspcurve1 = BSplineCurve::new(knot_vec1, ctrl_pts1); assert_eq!(bspcurve0.try_concat(&mut bspcurve1), Err(Error::DifferentBackFront(1.0, 2.0)));
Remarks
Unlike Vec::append()
, this method does not change other
as a curve.
However, side effects, such as degree synchronization, or knot vector clamped, do occur.
use truck_geometry::*; let knot_vec0 = KnotVec::bezier_knot(2); let ctrl_pts0 = vec![Vector2::new(0.0, 0.0), Vector2::new(0.0, 1.0), Vector2::new(2.0, 2.0)]; let mut bspcurve0 = BSplineCurve::new(knot_vec0, ctrl_pts0); let knot_vec1 = KnotVec::bezier_knot(1); let ctrl_pts1 = vec![Vector2::new(2.0, 2.0), Vector2::new(3.0, 3.0)]; let mut bspcurve1 = BSplineCurve::new(knot_vec1, ctrl_pts1); bspcurve1.knot_translate(1.0); let org_curve1 = bspcurve1.clone(); bspcurve0.try_concat(&mut bspcurve1).unwrap(); // do not change bspcurve as a curve assert!(bspcurve1.near2_as_curve(&org_curve1)); // The degree is changed. assert_ne!(bspcurve1.degree(), org_curve1.degree());
pub fn concat(&mut self, other: &mut Self) -> &mut Self
[src]
Concats two B-spline curves.
Examples
use truck_geometry::*; let knot_vec = KnotVec::from( vec![0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0] ); let ctrl_pts = vec![ Vector2::new(0.0, 0.0), Vector2::new(1.0, 0.0), Vector2::new(2.0, 2.0), Vector2::new(4.0, 3.0), Vector2::new(5.0, 6.0), ]; let bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); let mut part0 = bspcurve.clone(); let mut part1 = part0.cut(1.8); part0.concat(&mut part1); assert!(bspcurve.near2_as_curve(&part0));
Panics
Panic occurs if the back of the knot vector of self
does not coincides
with the front of the one of other
use truck_geometry::*; let knot_vec0 = KnotVec::from(vec![0.0, 0.0, 1.0, 1.0]); let ctrl_pts0 = vec![Vector2::new(0.0, 0.0), Vector2::new(1.0, 1.0)]; let mut bspcurve0 = BSplineCurve::new(knot_vec0, ctrl_pts0); let knot_vec1 = KnotVec::from(vec![2.0, 2.0, 3.0, 3.0]); let ctrl_pts1 = vec![Vector2::new(1.0, 1.0), Vector2::new(2.0, 2.0)]; let mut bspcurve1 = BSplineCurve::new(knot_vec1, ctrl_pts1); bspcurve0.concat(&mut bspcurve1);
Remarks
Unlike Vec::append()
, this method does not change other
as a curve.
However, side effects, such as degree synchronization, or knot vector clamped, do occur.
use truck_geometry::*; let knot_vec0 = KnotVec::bezier_knot(2); let ctrl_pts0 = vec![Vector2::new(0.0, 0.0), Vector2::new(0.0, 1.0), Vector2::new(2.0, 2.0)]; let mut bspcurve0 = BSplineCurve::new(knot_vec0, ctrl_pts0); let knot_vec1 = KnotVec::bezier_knot(1); let ctrl_pts1 = vec![Vector2::new(2.0, 2.0), Vector2::new(3.0, 3.0)]; let mut bspcurve1 = BSplineCurve::new(knot_vec1, ctrl_pts1); bspcurve1.knot_translate(1.0); let org_curve1 = bspcurve1.clone(); bspcurve0.concat(&mut bspcurve1); // do not change bspcurve as a curve assert!(bspcurve1.near2_as_curve(&org_curve1)); // The degree is changed. assert_ne!(bspcurve1.degree(), org_curve1.degree());
pub fn make_locally_injective(&mut self) -> &mut Self
[src]
Makes the curve locally injective.
Example
use truck_geometry::*; const N : usize = 100; // sample size for test let knot_vec = KnotVec::from( vec![0.0, 0.0, 0.0, 1.0, 3.0, 4.0, 4.0, 4.0] ); let ctrl_pts = vec![ Vector3::new(1.0, 0.0, 0.0), Vector3::new(0.0, 1.0, 0.0), Vector3::new(0.0, 1.0, 0.0), Vector3::new(0.0, 1.0, 0.0), Vector3::new(0.0, 0.0, 1.0), ]; let mut bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); let mut flag = false; for i in 0..=N { let t = 4.0 * (i as f64) / (N as f64); flag = flag || bspcurve.subs(t).near(&bspcurve.subs(t + 1.0 / (N as f64))); } // There exists t such that bspcurve(t) == bspcurve(t + 0.01). assert!(flag); bspcurve.make_locally_injective().knot_normalize(); let mut flag = false; for i in 0..=N { let t = 1.0 * (i as f64) / (N as f64); flag = flag || bspcurve.subs(t).near(&bspcurve.subs(t + 1.0 / (N as f64))); } // There does not exist t such that bspcurve(t) == bspcurve(t + 0.01). assert!(!flag);
Remarks
If self
is a constant curve, then does nothing.
use truck_geometry::*; let knot_vec = KnotVec::from(vec![0.0, 0.0, 0.0, 1.0, 2.0, 2.0, 2.0]); let ctrl_pts = vec![Vector2::new(1.0, 1.0); 4]; let mut bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); let org_curve = bspcurve.clone(); bspcurve.make_locally_injective(); assert_eq!(bspcurve, org_curve);
pub fn near_as_curve(&self, other: &BSplineCurve<V>) -> bool
[src]
Determine whether self
and other
is near as the B-spline curves or not.
Divides each knot interval into the number of degree equal parts,
and check |self(t) - other(t)| < TOLERANCE
for each end points t
.
Examples
use truck_geometry::*; let knot_vec = KnotVec::from( vec![0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 4.0, 4.0] ); let ctrl_pts = vec![ Vector2::new(1.0, 1.0), Vector2::new(3.0, 2.0), Vector2::new(2.0, 3.0), Vector2::new(4.0, 5.0), Vector2::new(5.0, 4.0), Vector2::new(1.0, 1.0), ]; let bspcurve0 = BSplineCurve::new(knot_vec, ctrl_pts); let mut bspcurve1 = bspcurve0.clone(); assert!(bspcurve0.near_as_curve(&bspcurve1)); *bspcurve1.control_point_mut(1) += Vector2::new(0.01, 0.0002); assert!(!bspcurve0.near_as_curve(&bspcurve1));
pub fn near2_as_curve(&self, other: &BSplineCurve<V>) -> bool
[src]
Determines self
and other
is near in square order as the B-spline curves or not.
Divide each knot interval into the number of degree equal parts,
and check |self(t) - other(t)| < TOLERANCE
for each end points t
.
Examples
use truck_geometry::*; let eps = TOLERANCE; let knot_vec = KnotVec::from( vec![0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 4.0, 4.0] ); let ctrl_pts = vec![ Vector2::new(1.0, 1.0), Vector2::new(3.0, 2.0), Vector2::new(2.0, 3.0), Vector2::new(4.0, 5.0), Vector2::new(5.0, 4.0), Vector2::new(1.0, 1.0), ]; let bspcurve0 = BSplineCurve::new(knot_vec, ctrl_pts); let mut bspcurve1 = bspcurve0.clone(); assert!(bspcurve0.near_as_curve(&bspcurve1)); *bspcurve1.control_point_mut(1) += Vector2::new(eps, 0.0); assert!(!bspcurve0.near2_as_curve(&bspcurve1));
impl<V: InnerSpace<Scalar = f64> + Tolerance> BSplineCurve<V>
[src]
pub fn search_nearest_parameter(&self, point: V, hint: f64) -> Option<f64>
[src]
Searches the parameter t
which minimize |self(t) - point|
by Newton's method
with initial guess hint
. If the repeated trial does not converge, then returns None
.
Examples
use truck_geometry::*; let knot_vec = KnotVec::from( vec![0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0] ); let ctrl_pts = vec![ Vector3::new(0.0, 0.0, 0.0), Vector3::new(1.0, 0.0, 0.0), Vector3::new(1.0, 1.0, 0.0), Vector3::new(0.0, 1.0, 0.0), Vector3::new(0.0, 1.0, 1.0), ]; let bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); let pt = bspcurve.subs(1.2); let t = bspcurve.search_nearest_parameter(pt, 0.8).unwrap(); assert_eq!(t, 1.2);
Remarks
It may converge to a local solution depending on the hint.
use truck_geometry::*; let knot_vec = KnotVec::from( vec![0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0] ); let ctrl_pts = vec![ Vector3::new(0.0, 0.0, 0.0), Vector3::new(1.0, 0.0, 0.0), Vector3::new(1.0, 1.0, 0.0), Vector3::new(0.0, 1.0, 0.0), Vector3::new(0.0, 1.0, 1.0), ]; let bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); let pt = Vector3::new(0.0, 0.5, 1.0); let t = bspcurve.search_nearest_parameter(pt, 0.8).unwrap(); let pt0 = bspcurve.subs(t); let pt1 = bspcurve.subs(3.0); // the point corresponding the obtained parameter is not // the globally nearest point in the curve. assert!((pt0 - pt).magnitude() > (pt1 - pt).magnitude());
pub fn is_arc_of(&self, curve: &BSplineCurve<V>, hint: f64) -> Option<f64>
[src]
Determines whether self
is an arc of curve
by repeating applying Newton method.
The parameter hint
is the init value, required that curve.subs(hint)
is the front point of self
.
If self
is an arc of curve
, then returns Some(t)
such that curve.subs(t)
coincides with
the back point of self
. Otherwise, returns None
.
Examples
use truck_geometry::*; let knot_vec = KnotVec::from( vec![0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0] ); let ctrl_pts = vec![ Vector3::new(0.0, 0.0, 0.0), Vector3::new(1.0, 0.0, 0.0), Vector3::new(1.0, 1.0, 0.0), Vector3::new(0.0, 1.0, 0.0), Vector3::new(0.0, 1.0, 1.0), ]; let bspcurve = BSplineCurve::new(knot_vec, ctrl_pts); let mut part = bspcurve.clone().cut(0.6); part.cut(2.8); let t = part.is_arc_of(&bspcurve, 0.6).unwrap(); f64::assert_near2(&t, &2.8); // hint is required the init value. assert!(part.is_arc_of(&bspcurve, 0.7).is_none()); // normal failure *part.control_point_mut(2) += Vector3::new(1.0, 2.0, 3.0); assert!(part.is_arc_of(&bspcurve, 0.6).is_none());
impl<V> BSplineCurve<V> where
V: MetricSpace<Metric = f64> + Index<usize, Output = f64> + Bounded<f64> + Copy,
[src]
V: MetricSpace<Metric = f64> + Index<usize, Output = f64> + Bounded<f64> + Copy,
pub fn roughly_bounding_box(&self) -> BoundingBox<V>
[src]
Returns the bounding box including all control points.
Trait Implementations
impl<V: Clone> Clone for BSplineCurve<V>
[src]
fn clone(&self) -> BSplineCurve<V>
[src]
pub fn clone_from(&mut self, source: &Self)
1.0.0[src]
impl<V: TangentSpace<f64>> Curve for BSplineCurve<V> where
V::Space: EuclideanSpace<Scalar = f64, Diff = V>,
[src]
V::Space: EuclideanSpace<Scalar = f64, Diff = V>,
type Point = V::Space
The curve is in the space of Self::Point
.
type Vector = V
The derivation vector of the curve.
fn subs(&self, t: f64) -> Self::Point
[src]
fn der(&self, t: f64) -> Self::Vector
[src]
fn parameter_range(&self) -> (f64, f64)
[src]
fn inverse(&self) -> Self
[src]
pub fn front(&self) -> Self::Point
[src]
pub fn back(&self) -> Self::Point
[src]
impl<V: Debug> Debug for BSplineCurve<V>
[src]
impl<'de, V> Deserialize<'de> for BSplineCurve<V> where
V: Deserialize<'de>,
[src]
V: Deserialize<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error> where
__D: Deserializer<'de>,
[src]
__D: Deserializer<'de>,
impl Mul<&'_ BSplineCurve<Vector2<f64>>> for Matrix2
[src]
type Output = BSplineCurve<Vector2>
The resulting type after applying the *
operator.
fn mul(self, spline: &BSplineCurve<Vector2>) -> Self::Output
[src]
impl Mul<&'_ BSplineCurve<Vector3<f64>>> for Matrix3
[src]
type Output = BSplineCurve<Vector3>
The resulting type after applying the *
operator.
fn mul(self, spline: &BSplineCurve<Vector3>) -> Self::Output
[src]
impl Mul<&'_ BSplineCurve<Vector4<f64>>> for Matrix4
[src]
type Output = BSplineCurve<Vector4>
The resulting type after applying the *
operator.
fn mul(self, spline: &BSplineCurve<Vector4>) -> Self::Output
[src]
impl Mul<BSplineCurve<Vector2<f64>>> for Matrix2
[src]
type Output = BSplineCurve<Vector2>
The resulting type after applying the *
operator.
fn mul(self, spline: BSplineCurve<Vector2>) -> Self::Output
[src]
impl Mul<BSplineCurve<Vector3<f64>>> for Matrix3
[src]
type Output = BSplineCurve<Vector3>
The resulting type after applying the *
operator.
fn mul(self, spline: BSplineCurve<Vector3>) -> Self::Output
[src]
impl Mul<BSplineCurve<Vector4<f64>>> for Matrix4
[src]
type Output = BSplineCurve<Vector4>
The resulting type after applying the *
operator.
fn mul(self, spline: BSplineCurve<Vector4>) -> Self::Output
[src]
impl Mul<f64> for &BSplineCurve<Vector2>
[src]
type Output = BSplineCurve<Vector2>
The resulting type after applying the *
operator.
fn mul(self, scalar: f64) -> Self::Output
[src]
impl Mul<f64> for BSplineCurve<Vector2>
[src]
type Output = BSplineCurve<Vector2>
The resulting type after applying the *
operator.
fn mul(self, scalar: f64) -> Self::Output
[src]
impl Mul<f64> for &BSplineCurve<Vector3>
[src]
type Output = BSplineCurve<Vector3>
The resulting type after applying the *
operator.
fn mul(self, scalar: f64) -> Self::Output
[src]
impl Mul<f64> for BSplineCurve<Vector3>
[src]
type Output = BSplineCurve<Vector3>
The resulting type after applying the *
operator.
fn mul(self, scalar: f64) -> Self::Output
[src]
impl Mul<f64> for &BSplineCurve<Vector4>
[src]
type Output = BSplineCurve<Vector4>
The resulting type after applying the *
operator.
fn mul(self, scalar: f64) -> Self::Output
[src]
impl Mul<f64> for BSplineCurve<Vector4>
[src]
type Output = BSplineCurve<Vector4>
The resulting type after applying the *
operator.
fn mul(self, scalar: f64) -> Self::Output
[src]
impl<V: InnerSpace<Scalar = f64>> ParameterDivision1D for BSplineCurve<V>
[src]
fn parameter_division(&self, tol: f64) -> Vec<f64>ⓘ
[src]
impl<V: PartialEq> PartialEq<BSplineCurve<V>> for BSplineCurve<V>
[src]
fn eq(&self, other: &BSplineCurve<V>) -> bool
[src]
fn ne(&self, other: &BSplineCurve<V>) -> bool
[src]
impl<V> Serialize for BSplineCurve<V> where
V: Serialize,
[src]
V: Serialize,
fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error> where
__S: Serializer,
[src]
__S: Serializer,
impl<V> StructuralPartialEq for BSplineCurve<V>
[src]
impl<V> TryFrom<CurveCollector<V>> for BSplineCurve<V>
[src]
Auto Trait Implementations
impl<V> RefUnwindSafe for BSplineCurve<V> where
V: RefUnwindSafe,
[src]
V: RefUnwindSafe,
impl<V> Send for BSplineCurve<V> where
V: Send,
[src]
V: Send,
impl<V> Sync for BSplineCurve<V> where
V: Sync,
[src]
V: Sync,
impl<V> Unpin for BSplineCurve<V> where
V: Unpin,
[src]
V: Unpin,
impl<V> UnwindSafe for BSplineCurve<V> where
V: UnwindSafe,
[src]
V: UnwindSafe,
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> DeserializeOwned for T where
T: for<'de> Deserialize<'de>,
[src]
T: for<'de> Deserialize<'de>,
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> ToOwned for T where
T: Clone,
[src]
T: Clone,
type Owned = T
The resulting type after obtaining ownership.
pub fn to_owned(&self) -> T
[src]
pub fn clone_into(&self, target: &mut T)
[src]
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,