axiolid_nurbs/
surface_transform.rs1use axiolid_contracts::GeomResult;
4use axiolid_core::{Point3, Scalar};
5use axiolid_curve::BSplineCurve;
6use axiolid_evaluate::surface::bspline_jet;
7use axiolid_surface::BSplineSurface;
8
9use crate::{axis::reverse_axis, transform::insert_knot3};
10
11pub fn insert_surface_knot_u(
15 surface: &BSplineSurface,
16 parameter: Scalar,
17) -> GeomResult<BSplineSurface> {
18 bspline_jet(surface, parameter, 0.0)?;
19 let columns = (0..surface.control_points[0].len())
20 .map(|v| insert_knot3(&u_curve(surface, v), parameter))
21 .collect::<GeomResult<Vec<_>>>()?;
22 let u_count = columns[0].control_points.len();
23 let control_points = (0..u_count)
24 .map(|u| {
25 columns
26 .iter()
27 .map(|column| column.control_points[u])
28 .collect()
29 })
30 .collect();
31 let weights = surface.weights.as_ref().map(|_| {
32 (0..u_count)
33 .map(|u| {
34 columns
35 .iter()
36 .map(|column| column.weights.as_ref().expect("source was rational")[u])
37 .collect()
38 })
39 .collect()
40 });
41 Ok(BSplineSurface {
42 u_degree: surface.u_degree,
43 v_degree: surface.v_degree,
44 control_points,
45 u_knots: columns[0].knots.clone(),
46 u_multiplicities: columns[0].multiplicities.clone(),
47 v_knots: surface.v_knots.clone(),
48 v_multiplicities: surface.v_multiplicities.clone(),
49 weights,
50 knot_spec: surface.knot_spec,
51 u_closed: surface.u_closed,
52 v_closed: surface.v_closed,
53 self_intersect: surface.self_intersect,
54 })
55}
56
57pub fn insert_surface_knot_v(
61 surface: &BSplineSurface,
62 parameter: Scalar,
63) -> GeomResult<BSplineSurface> {
64 bspline_jet(surface, 0.0, parameter)?;
65 let rows = (0..surface.control_points.len())
66 .map(|u| insert_knot3(&v_curve(surface, u), parameter))
67 .collect::<GeomResult<Vec<_>>>()?;
68 let control_points = rows.iter().map(|row| row.control_points.clone()).collect();
69 let weights = surface.weights.as_ref().map(|_| {
70 rows.iter()
71 .map(|row| row.weights.as_ref().expect("source was rational").clone())
72 .collect()
73 });
74 Ok(BSplineSurface {
75 u_degree: surface.u_degree,
76 v_degree: surface.v_degree,
77 control_points,
78 u_knots: surface.u_knots.clone(),
79 u_multiplicities: surface.u_multiplicities.clone(),
80 v_knots: rows[0].knots.clone(),
81 v_multiplicities: rows[0].multiplicities.clone(),
82 weights,
83 knot_spec: surface.knot_spec,
84 u_closed: surface.u_closed,
85 v_closed: surface.v_closed,
86 self_intersect: surface.self_intersect,
87 })
88}
89
90pub fn reverse_surface_u(surface: &BSplineSurface) -> GeomResult<BSplineSurface> {
92 bspline_jet(surface, 0.0, 0.0)?;
93 let mut result = surface.clone();
94 result.control_points.reverse();
95 if let Some(weights) = &mut result.weights {
96 weights.reverse();
97 }
98 (result.u_knots, result.u_multiplicities) =
99 reverse_axis(&surface.u_knots, &surface.u_multiplicities)?;
100 Ok(result)
101}
102
103pub fn reverse_surface_v(surface: &BSplineSurface) -> GeomResult<BSplineSurface> {
105 bspline_jet(surface, 0.0, 0.0)?;
106 let mut result = surface.clone();
107 for row in &mut result.control_points {
108 row.reverse();
109 }
110 if let Some(weights) = &mut result.weights {
111 for row in weights {
112 row.reverse();
113 }
114 }
115 (result.v_knots, result.v_multiplicities) =
116 reverse_axis(&surface.v_knots, &surface.v_multiplicities)?;
117 Ok(result)
118}
119
120pub(crate) fn u_curve(surface: &BSplineSurface, v: usize) -> BSplineCurve<Point3> {
121 BSplineCurve {
122 degree: surface.u_degree,
123 control_points: surface.control_points.iter().map(|row| row[v]).collect(),
124 knots: surface.u_knots.clone(),
125 multiplicities: surface.u_multiplicities.clone(),
126 weights: surface
127 .weights
128 .as_ref()
129 .map(|rows| rows.iter().map(|row| row[v]).collect()),
130 knot_spec: surface.knot_spec,
131 closed: surface.u_closed,
132 self_intersect: surface.self_intersect,
133 }
134}
135
136fn v_curve(surface: &BSplineSurface, u: usize) -> BSplineCurve<Point3> {
137 BSplineCurve {
138 degree: surface.v_degree,
139 control_points: surface.control_points[u].clone(),
140 knots: surface.v_knots.clone(),
141 multiplicities: surface.v_multiplicities.clone(),
142 weights: surface.weights.as_ref().map(|rows| rows[u].clone()),
143 knot_spec: surface.knot_spec,
144 closed: surface.v_closed,
145 self_intersect: surface.self_intersect,
146 }
147}