robot_description_builder/link/geometry/
box_geometry.rs1use super::{GeometryInterface, GeometryShapeContainer};
2use crate::transform::Mirror;
3
4#[cfg(feature = "urdf")]
5use crate::to_rdf::to_urdf::ToURDF;
6#[cfg(feature = "xml")]
7use quick_xml::{events::attributes::Attribute, name::QName};
8
9#[derive(Debug, PartialEq, Clone)]
14pub struct BoxGeometry {
15 pub side1: f32,
18 pub side2: f32,
20 pub side3: f32,
22}
23
24impl BoxGeometry {
25 pub fn new(side1: f32, side2: f32, side3: f32) -> Self {
27 Self {
29 side1,
30 side2,
31 side3,
32 }
33 }
34}
35
36impl GeometryInterface for BoxGeometry {
37 fn volume(&self) -> f32 {
38 self.side1 * self.side2 * self.side3
39 }
40
41 fn surface_area(&self) -> f32 {
42 2f32 * (self.side1 * self.side2 + self.side1 * self.side3 + self.side2 * self.side3)
43 }
44
45 fn boxed_clone(&self) -> Box<dyn GeometryInterface + Sync + Send> {
46 Box::new(self.clone())
47 }
48
49 fn bounding_box(&self) -> (f32, f32, f32) {
50 (self.side1, self.side2, self.side3)
51 }
52
53 fn shape_container(&self) -> GeometryShapeContainer {
54 self.clone().into()
55 }
56}
57
58impl Mirror for BoxGeometry {
59 fn mirrored(&self, _mirror_matrix: &nalgebra::Matrix3<f32>) -> Self {
60 self.clone()
61 }
62}
63
64#[cfg(feature = "urdf")]
65impl ToURDF for BoxGeometry {
66 fn to_urdf(
67 &self,
68 writer: &mut quick_xml::Writer<std::io::Cursor<Vec<u8>>>,
69 _urdf_config: &crate::to_rdf::to_urdf::URDFConfig,
70 ) -> Result<(), quick_xml::Error> {
71 let element = writer.create_element("geometry");
72 element.write_inner_content(|writer| -> quick_xml::Result<()> {
73 writer
74 .create_element("box")
75 .with_attribute(Attribute {
76 key: QName(b"size"),
77 value: format!("{} {} {}", self.side1, self.side2, self.side3)
78 .as_bytes()
79 .into(),
80 })
81 .write_empty()?;
82 Ok(())
83 })?;
84 Ok(())
85 }
86}
87
88impl From<BoxGeometry> for Box<dyn GeometryInterface + Sync + Send> {
89 fn from(value: BoxGeometry) -> Self {
90 Box::new(value)
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 #[cfg(feature = "xml")]
97 use std::io::Seek;
98 use test_log::test;
99
100 use crate::link::geometry::{
101 box_geometry::BoxGeometry, geometry_shape_data::GeometryShapeContainer, GeometryInterface,
102 };
103 #[cfg(feature = "urdf")]
104 use crate::to_rdf::to_urdf::{ToURDF, URDFConfig};
105
106 #[test]
107 fn volume() {
108 assert_eq!(BoxGeometry::new(1.0, 1.0, 1.0).volume(), 1.0);
109 assert_eq!(BoxGeometry::new(1.0, 2.0, 3.0).volume(), 6.0);
110 assert_eq!(BoxGeometry::new(9.0, 20.0, 100.0).volume(), 18000.0);
111 assert_eq!(BoxGeometry::new(4.5, 20.0, 100.0).volume(), 9000.0);
112 }
113
114 #[test]
115 fn surface_area() {
116 assert_eq!(BoxGeometry::new(1.0, 1.0, 1.0).surface_area(), 6.);
117 assert_eq!(BoxGeometry::new(1.0, 2.0, 3.0).surface_area(), 22.);
118 assert_eq!(BoxGeometry::new(9.0, 20.0, 100.0).surface_area(), 6160.);
119 assert_eq!(BoxGeometry::new(4.5, 20.0, 100.0).surface_area(), 5080.);
120 }
121
122 #[test]
123 fn boxed_clone() {
124 assert_eq!(
125 BoxGeometry::new(1.0, 1.0, 1.0).boxed_clone(),
126 BoxGeometry::new(1.0, 1.0, 1.0).into()
127 );
128 assert_eq!(
129 BoxGeometry::new(1.0, 2.0, 3.0).boxed_clone(),
130 BoxGeometry::new(1.0, 2.0, 3.0).into()
131 );
132 assert_eq!(
133 BoxGeometry::new(9.0, 20.0, 100.0).boxed_clone(),
134 BoxGeometry::new(9.0, 20.0, 100.0).into()
135 );
136 assert_eq!(
137 BoxGeometry::new(4.5, 20.0, 100.0).boxed_clone(),
138 BoxGeometry::new(4.5, 20.0, 100.0).into()
139 );
140 }
141
142 #[test]
143 fn bounding_box() {
144 assert_eq!(
145 BoxGeometry::new(1.0, 1.0, 1.0).bounding_box(),
146 (1.0, 1.0, 1.0)
147 );
148 assert_eq!(
149 BoxGeometry::new(1.0, 2.0, 3.0).bounding_box(),
150 (1.0, 2.0, 3.0)
151 );
152 assert_eq!(
153 BoxGeometry::new(9.0, 20.0, 100.0).bounding_box(),
154 (9.0, 20.0, 100.0)
155 );
156 assert_eq!(
157 BoxGeometry::new(4.5, 20.0, 100.0).bounding_box(),
158 (4.5, 20.0, 100.0)
159 );
160 }
161
162 #[test]
163 fn get_shape() {
164 assert_eq!(
165 BoxGeometry::new(1.0, 1.0, 1.0).shape_container(),
166 GeometryShapeContainer::Box(BoxGeometry::new(1.0, 1.0, 1.0))
167 );
168 assert_eq!(
169 BoxGeometry::new(1.0, 2.0, 3.0).shape_container(),
170 GeometryShapeContainer::Box(BoxGeometry::new(1.0, 2.0, 3.0))
171 );
172 assert_eq!(
173 BoxGeometry::new(9.0, 20.0, 100.0).shape_container(),
174 GeometryShapeContainer::Box(BoxGeometry::new(9.0, 20.0, 100.0))
175 );
176 assert_eq!(
177 BoxGeometry::new(4.5, 20.0, 100.0).shape_container(),
178 GeometryShapeContainer::Box(BoxGeometry::new(4.5, 20.0, 100.0))
179 );
180 }
181
182 #[cfg(feature = "urdf")]
183 #[test]
184 fn to_urdf() {
185 {
186 let mut writer = quick_xml::Writer::new(std::io::Cursor::new(Vec::new()));
187 assert!(BoxGeometry::new(1.0, 1.0, 1.0)
188 .to_urdf(&mut writer, &URDFConfig::default())
189 .is_ok());
190
191 writer.get_mut().rewind().unwrap();
192
193 assert_eq!(
194 std::io::read_to_string(writer.into_inner()).unwrap(),
195 String::from(r#"<geometry><box size="1 1 1"/></geometry>"#)
196 );
197 }
198 {
199 let mut writer = quick_xml::Writer::new(std::io::Cursor::new(Vec::new()));
200 assert!(BoxGeometry::new(1.0, 2.0, 3.0)
201 .to_urdf(&mut writer, &URDFConfig::default())
202 .is_ok());
203
204 writer.get_mut().rewind().unwrap();
205
206 assert_eq!(
207 std::io::read_to_string(writer.into_inner()).unwrap(),
208 String::from(r#"<geometry><box size="1 2 3"/></geometry>"#)
209 );
210 }
211 {
212 let mut writer = quick_xml::Writer::new(std::io::Cursor::new(Vec::new()));
213 assert!(BoxGeometry::new(9.0, 20.0, 100.0)
214 .to_urdf(&mut writer, &URDFConfig::default())
215 .is_ok());
216
217 writer.get_mut().rewind().unwrap();
218
219 assert_eq!(
220 std::io::read_to_string(writer.into_inner()).unwrap(),
221 String::from(r#"<geometry><box size="9 20 100"/></geometry>"#)
222 );
223 }
224 {
225 let mut writer = quick_xml::Writer::new(std::io::Cursor::new(Vec::new()));
226 assert!(BoxGeometry::new(4.5, 20.0, 100.0)
227 .to_urdf(&mut writer, &URDFConfig::default())
228 .is_ok());
229
230 writer.get_mut().rewind().unwrap();
231
232 assert_eq!(
233 std::io::read_to_string(writer.into_inner()).unwrap(),
234 String::from(r#"<geometry><box size="4.5 20 100"/></geometry>"#)
235 );
236 }
237 }
238}