geop_ops_extrude_revolve/
cube.rs1use crate::{
7 common::{Profile, polygon},
8 extrude::{ExtrudeNames, extrude},
9};
10use geop_core_math::{
11 geop_error::GeopResult,
12 primitives::CoordinateSystem,
13 scalars::Scalar,
14 vector::{Vector2, Vector3},
15};
16use geop_core_part::{Namer, Part};
17use geop_core_topology::SolidId;
18
19pub fn cube_solid<S: Scalar>(
26 part: &mut Part<S>,
27 name: &str,
28 min: Vector3<S>,
29 max: Vector3<S>,
30) -> GeopResult<SolidId> {
31 let (x0, y0, z0) = (min[0], min[1], max[2]);
32 let (x1, y1) = (max[0], max[1]);
33
34 let origin = Vector3::from_array([x0, y0, z0]);
38 let u = Vector3::from_array([x1.sub(x0), S::ZERO, S::ZERO]);
39 let v = Vector3::from_array([S::ZERO, y1.sub(y0), S::ZERO]);
40 let w = Vector3::from_array([S::ZERO, S::ZERO, min[2].sub(z0)]);
41 let coordinate_system = CoordinateSystem::try_new(origin, u, v, w)?;
42
43 let outer = [
46 Vector2::from_array([S::ZERO, S::ZERO]),
47 Vector2::from_array([S::ONE, S::ZERO]),
48 Vector2::from_array([S::ONE, S::ONE]),
49 Vector2::from_array([S::ZERO, S::ONE]),
50 ];
51
52 let namer = Namer::new("cube", name)?;
53 extrude(
54 part,
55 &ExtrudeNames::single(&namer),
56 &coordinate_system,
57 &Profile::closed(polygon(&outer)?),
58 &[],
59 )
60}
61
62#[cfg(test)]
63mod tests {
64 use super::cube_solid;
65 use geop_core_math::{for_all_scalars, scalars::Scalar, vector::Vector3};
66 use geop_core_part::Part;
67 use geop_core_topology::contains::shell::{PointClassification, shell_contains};
68
69 const MAX: usize = 200;
70 const EPS: f64 = 1e-3;
71 const SEED: u64 = 7;
72
73 fn check_cube_has_expected_entity_counts<S: Scalar>() {
74 let mut part = Part::<S>::new();
75 cube_solid(
76 &mut part,
77 "t1",
78 Vector3::from_array([S::ZERO; 3]),
79 Vector3::from_array([S::ONE; 3]),
80 )
81 .unwrap();
82 let model = part.topology();
83
84 assert_eq!(model.faces.len(), 6);
89 assert_eq!(model.vertices.len(), 8);
90 assert_eq!(model.edges.len(), 12);
91 assert_eq!(model.coedges.len(), 24);
92 assert_eq!(model.shells.len(), 1);
93 assert_eq!(model.solids.len(), 1);
94 for face in model.faces.values() {
95 assert!(face.holes.is_empty());
96 }
97 for edge_id in model.edges.keys() {
98 assert_eq!(model.coedges_of_edge(*edge_id).len(), 2);
99 }
100 }
101 #[test]
102 fn cube_has_expected_entity_counts() {
103 for_all_scalars!(check_cube_has_expected_entity_counts);
104 }
105
106 fn check_cube_center_is_inside<S: Scalar>() {
107 let mut part = Part::<S>::new();
108 let solid_id = cube_solid(
109 &mut part,
110 "t2",
111 Vector3::from_array([S::ZERO; 3]),
112 Vector3::from_array([S::ONE; 3]),
113 )
114 .unwrap();
115 let model = part.topology();
116 let shell_id = model.get_solid(solid_id).unwrap().shells[0];
117 let p = Vector3::from_array([S::from_f64(0.5); 3]);
118 assert_eq!(
119 shell_contains(&model, shell_id, p, MAX, S::from_f64(EPS), SEED).unwrap(),
120 PointClassification::Inside
121 );
122 }
123 #[test]
124 fn cube_center_is_inside() {
125 for_all_scalars!(check_cube_center_is_inside);
126 }
127
128 fn check_cube_outside_point_is_outside<S: Scalar>() {
129 let mut part = Part::<S>::new();
130 let solid_id = cube_solid(
131 &mut part,
132 "t3",
133 Vector3::from_array([S::ZERO; 3]),
134 Vector3::from_array([S::ONE; 3]),
135 )
136 .unwrap();
137 let model = part.topology();
138 let shell_id = model.get_solid(solid_id).unwrap().shells[0];
139 let p = Vector3::from_array([S::from_f64(-5.0), S::from_f64(0.5), S::from_f64(0.5)]);
140 assert_eq!(
141 shell_contains(&model, shell_id, p, MAX, S::from_f64(EPS), SEED).unwrap(),
142 PointClassification::Outside
143 );
144 }
145 #[test]
146 fn cube_outside_point_is_outside() {
147 for_all_scalars!(check_cube_outside_point_is_outside);
148 }
149
150 fn check_rasterize_topology_cube<S: Scalar>() {
151 let mut part = Part::<S>::new();
152 cube_solid(
153 &mut part,
154 "t4",
155 Vector3::from_array([S::ZERO; 3]),
156 Vector3::from_array([S::ONE; 3]),
157 )
158 .unwrap();
159 let model = part.topology();
160
161 let scene = geop_ops_rasterize::rasterize_topology(&model, 8).unwrap();
162 assert!(!scene.points.is_empty());
163 assert!(!scene.lines.is_empty());
164 assert!(!scene.triangles_transparent.is_empty());
165 assert!(!scene.labels.is_empty());
166
167 std::fs::create_dir_all("outputs").unwrap();
168 scene.save_to_file("outputs/cube_topology.html").unwrap();
169 }
170 #[test]
171 fn rasterize_topology_cube() {
172 for_all_scalars!(check_rasterize_topology_cube);
173 }
174}