truck_geometry/errors.rs
1use thiserror::Error;
2
3/// Error handler for [`Error`](./errors/enum.Error.html)
4pub type Result<T> = std::result::Result<T, Error>;
5
6/// Geometrical Errors
7#[derive(Debug, PartialEq, Error)]
8pub enum Error {
9 /// The following operations are failed if the knot vector has zero range.
10 /// * Creating `BSplineCurve` or `BSplineSurface`,
11 /// * Calculating bspline basis functions, or
12 /// * Normalizing the knot vector.
13 /// # Examples
14 /// ```
15 /// use truck_geometry::prelude::*;
16 /// use truck_geometry::errors::Error;
17 /// let mut knot_vec = KnotVec::from(vec![0.0, 0.0, 0.0, 0.0]);
18 /// assert_eq!(knot_vec.try_normalize(), Err(Error::ZeroRange));
19 /// assert_eq!(knot_vec.try_bspline_basis_functions(1, 0.0), Err(Error::ZeroRange));
20 ///
21 /// let ctrl_pts = vec![Vector2::new(0.0, 0.0), Vector2::new(1.0, 1.0)];
22 /// assert!(matches!(BSplineCurve::try_new(knot_vec, ctrl_pts), Err(Error::ZeroRange)));
23 /// ```
24 #[error("This knot vector consists single value.")]
25 ZeroRange,
26 /// Fails concatting two knot vectors if there is a difference between the back knot of
27 /// the former knot vector and the front knot of the latter knot vector.
28 /// # Examples
29 /// ```
30 /// use truck_geometry::prelude::*;
31 /// use truck_geometry::errors::Error;
32 /// let mut knot_vec0 = KnotVec::from(vec![0.0, 0.0, 1.0, 1.0]);
33 /// let knot_vec1 = KnotVec::from(vec![2.0, 2.0, 3.0, 3.0]);
34 /// assert!(matches!(knot_vec0.try_concat(&knot_vec1, 1), Err(Error::DifferentBackFront(1.0, 2.0))));
35 /// ```
36 #[error("Cannot concat two knot vectors whose the back of the first and the front of the second are different.
37the back of the first knot vector: {0}
38the front of the second knot vector: {1}")]
39 DifferentBackFront(f64, f64),
40 /// If the knot vector is not clamped, then one cannot concat the vector with another knot vector.
41 /// # Examples
42 /// ```
43 /// use truck_geometry::prelude::*;
44 /// use truck_geometry::errors::Error;
45 /// let mut knot_vec0 = KnotVec::from(vec![0.0, 0.0, 1.0, 1.0]);
46 /// let knot_vec1 = KnotVec::from(vec![2.0, 2.0, 3.0, 3.0]);
47 /// assert!(matches!(knot_vec0.try_concat(&knot_vec1, 2), Err(Error::NotClampedKnotVector)));
48 /// ```
49 #[error("This knot vector is not clamped.")]
50 NotClampedKnotVector,
51 /// Creating a knot vector by `KnotVec::try_from()` is failed if the given vector is not sorted.
52 /// `<KnotVec as From<Vec<f64>>>::from()` does not panic by this error because sorts the given
53 /// vector before creating the knot vector. So, `KnotVec::try_from()` is more efficient than
54 /// `<KnotVec as From<Vec<f64>>>::from()`.
55 /// # Examples
56 /// ```
57 /// use truck_geometry::prelude::*;
58 /// use truck_geometry::errors::Error;
59 /// use std::convert::*;
60 ///
61 /// assert!(matches!(KnotVec::try_from(vec![1.0, 3.0, 0.0, 2.0]), Err(Error::NotSortedVector)));
62 /// assert_eq!(
63 /// <KnotVec as From<Vec<f64>>>::from(vec![1.0, 3.0, 0.0, 2.0]),
64 /// KnotVec::try_from(vec![0.0, 1.0, 2.0, 3.0]).unwrap(),
65 /// );
66 /// ```
67 #[error("This knot vector is not sorted.")]
68 NotSortedVector,
69 /// The given degree is too large to calculate bspline basis functions.
70 /// # Examples
71 /// ```
72 /// use truck_geometry::prelude::*;
73 /// use truck_geometry::errors::Error;
74 ///
75 /// // a knot vector with length = 4.
76 /// let knot_vec = KnotVec::from(vec![0.0, 0.0, 1.0, 1.0]);
77 /// assert!(matches!(
78 /// knot_vec.try_bspline_basis_functions(5, 0.5),
79 /// Err(Error::TooLargeDegree(4, 5)),
80 /// ));
81 /// ```
82 #[error(
83 "This knot vector is too short compared to the degree.
84the length of knot_vec: {0}
85the degree: {1}"
86 )]
87 TooLargeDegree(usize, usize),
88 /// The specified knot cannot be removed.
89 /// # Examples
90 /// ```
91 /// use truck_geometry::prelude::*;
92 /// use truck_geometry::errors::Error;
93 /// let knot_vec = KnotVec::bezier_knot(2);
94 /// let ctrl_pts = vec![Vector2::new(-1.0, 1.0), Vector2::new(0.0, -1.0), Vector2::new(1.0, 1.0)];
95 /// let mut bspcurve = BSplineCurve::new(knot_vec, ctrl_pts);
96 /// let org_curve = bspcurve.clone();
97 /// bspcurve.add_knot(0.5).add_knot(0.5).add_knot(0.25).add_knot(0.75);
98 /// assert!(bspcurve.try_remove_knot(3).is_ok());
99 /// assert!(matches!(bspcurve.try_remove_knot(2), Err(Error::CannotRemoveKnot(2))));
100 /// ```
101 #[error("The {0}th knot in this knot vector cannot be removed.")]
102 CannotRemoveKnot(usize),
103 /// Empty vector of points cannot construct B-spline.
104 /// # Examples
105 /// ```
106 /// use truck_geometry::prelude::*;
107 /// use truck_geometry::errors::Error;
108 ///
109 /// let knot_vec = KnotVec::bezier_knot(2);
110 /// let ctrl_pts: Vec<Vector4> = Vec::new();
111 /// assert!(matches!(
112 /// BSplineCurve::try_new(knot_vec, ctrl_pts),
113 /// Err(Error::EmptyControlPoints),
114 /// ));
115 /// ```
116 #[error("The control point must not be empty.")]
117 EmptyControlPoints,
118 /// The knot vector of B-spline curves or B-spline surfaces must be longer than the corresponded
119 /// array of control points.
120 /// # Examples
121 /// ```
122 /// use truck_geometry::prelude::*;
123 /// use truck_geometry::errors::Error;
124 /// let knot_vec = KnotVec::from(vec![0.0, 1.0, 2.0]);
125 /// let ctrl_pts = vec![Vector2::new(0.0, 0.0), Vector2::new(0.0, 0.0), Vector2::new(0.0, 0.0), Vector2::new(0.0, 0.0)];
126 /// assert!(matches!(
127 /// BSplineCurve::try_new(knot_vec, ctrl_pts),
128 /// Err(Error::TooShortKnotVector(3, 4)),
129 /// ));
130 /// ```
131 #[error(
132 "The knot vector must be more than the control points.
133the length of knot_vec: {0}
134the number of control points: {1}"
135 )]
136 TooShortKnotVector(usize, usize),
137 /// The length of the given arrays of control points to create a B-spline surface is irregular.
138 /// # Examples
139 /// ```
140 /// use truck_geometry::prelude::*;
141 /// use truck_geometry::errors::Error;
142 /// let knot_vecs = (KnotVec::bezier_knot(2), KnotVec::bezier_knot(2));
143 /// let ctrl_pts = vec![
144 /// vec![Vector2::new(1.0, 2.0), Vector2::new(1.0, 2.0)], // length = 2
145 /// vec![Vector2::new(1.0, 2.0)] // length = 1
146 /// ];
147 /// assert!(matches!(
148 /// BSplineSurface::try_new(knot_vecs, ctrl_pts),
149 /// Err(Error::IrregularControlPoints),
150 /// ));
151 /// ```
152 #[error("The number of control points is irregular")]
153 IrregularControlPoints,
154 /// The vector of control points and the one of weights have different length.
155 /// # Examples
156 /// ```
157 /// use truck_geometry::prelude::*;
158 /// use truck_geometry::errors::Error;
159 /// let bspcurve = BSplineCurve::new(
160 /// KnotVec::bezier_knot(2),
161 /// vec![Point2::new(0.0, 1.0), Point2::new(2.0, 3.0), Point2::new(4.0, 5.0)],
162 /// );
163 /// let weights = vec![1.0, 2.0]; // less than control points
164 ///
165 /// assert!(matches!(
166 /// NurbsCurve::<Vector3>::try_from_bspline_and_weights(bspcurve, weights),
167 /// Err(Error::DifferentLength),
168 /// ));
169 /// ```
170 #[error("The vector of control points and the one of weights have different length.")]
171 DifferentLength,
172}
173
174#[test]
175#[rustfmt::skip]
176fn print_messages() {
177 use std::io::Write;
178 let stderr = &mut std::io::stderr();
179 writeln!(stderr, "****** test of the expressions of error messages ******\n").unwrap();
180 writeln!(stderr, "{}\n", Error::ZeroRange).unwrap();
181 writeln!(stderr, "{}\n", Error::DifferentBackFront(0.0, 1.0)).unwrap();
182 writeln!(stderr, "{}\n", Error::NotClampedKnotVector).unwrap();
183 writeln!(stderr, "{}\n", Error::NotSortedVector).unwrap();
184 writeln!(stderr, "{}\n", Error::TooLargeDegree(1, 2)).unwrap();
185 writeln!(stderr, "{}\n", Error::CannotRemoveKnot(7)).unwrap();
186 writeln!(stderr, "{}\n", Error::EmptyControlPoints).unwrap();
187 writeln!(stderr, "{}\n", Error::TooShortKnotVector(1, 2)).unwrap();
188 writeln!(stderr, "{}\n", Error::IrregularControlPoints).unwrap();
189 writeln!(stderr, "*******************************************************").unwrap();
190}