1#![deny(
18 clippy::unwrap_used,
19 clippy::expect_used,
20 clippy::indexing_slicing,
21 clippy::panic,
22 clippy::unreachable
23)]
24
25use anyhow::{bail, Result};
26
27mod catia;
28pub mod creo;
29mod earcut;
30mod f3d;
31mod gltf;
32mod helpers;
33mod inventor;
34mod jt;
35mod jt10;
36mod model;
37mod obj;
38mod off;
39mod p21;
40mod ply;
41mod pn;
42mod points;
43pub mod render;
44pub mod rhino;
45mod sketchup;
46mod step;
47mod stl;
48mod sw;
49mod tessellated;
50#[cfg(test)]
51mod test_support;
52mod three_ds;
53mod three_mf;
54
55pub(crate) use helpers::*;
56pub use model::{color_map, Field, Mesh, MAX_FIELDS, MAX_POINTS, MAX_TRIANGLES};
57pub use step::MAX_STEP_BYTES;
58
59pub fn read(format: &str, data: &[u8]) -> Result<Mesh> {
61 let mesh = match format {
62 "stl" => stl::read(data)?,
63 "obj" => obj::read(data)?,
64 "ply" => ply::read(data)?,
65 "off" => off::read(data)?,
66 "3mf" => three_mf::read_3mf(data)?,
67 "amf" => three_mf::read_amf(data)?,
68 "gltf" | "glb" => gltf::read(data)?,
69 "3ds" => three_ds::read(data)?,
70 "pts" | "xyz" => points::read_text(data)?,
71 "las" => points::read_las(data)?,
72 "step" => step::read(data)?,
73 "nx-part" => jt::read_nx(data)?,
74 "jt" => jt10::read(data)?,
75 "solidworks-part" => sw::read_part(data)?,
76 "creo-part" => creo::read_part(data)?,
77 "solidworks-assembly" => bail!(
78 "A SOLIDWORKS assembly is shown with the previews of its parts (found by file name)."
79 ),
80 "rhino" => rhino::read(data)?,
81 "inventor-part" => inventor::read_part(data)?,
82 "inventor-assembly" => bail!(
83 "An Inventor assembly is shown with the previews of its parts (found by file name)."
84 ),
85 "catia-part" => catia::read_part(data)?,
86 "creo-assembly" => bail!(
87 "A Creo assembly is shown with the previews of its parts (found by file name)."
88 ),
89 "catia-product" => bail!(
90 "A CATIA product is shown with the previews of its parts (found by document or part number)."
91 ),
92 "sketchup" => sketchup::read(data)?,
93 "fusion-design" => f3d::read_f3d(data)?,
94 "vtk-legacy" => crate::simmesh::vtk_legacy(data)?,
95 "vtk-unstructured" | "vtk-polydata" => crate::simmesh::vtk_xml(data)?,
96 "calculix-frd" => crate::simmesh::frd(data)?,
97 other => bail!("No 3D preview for the format '{other}'."),
98 };
99 mesh.check()?;
100 Ok(mesh)
101}
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106
107 #[test]
108 fn step_box_is_tessellated() {
109 let mesh = read("step", include_bytes!("../tests/fixtures/cube.step")).unwrap();
110 assert!(
111 mesh.triangle_count() >= 12,
112 "{} triangles",
113 mesh.triangle_count()
114 );
115 let b = mesh.bounds();
116 assert!((b[3] - b[0] - 10.0).abs() < 1e-3, "{b:?}");
117 assert!(read(
118 "step",
119 b"ISO-10303-21;\nHEADER;\nENDSEC;\nDATA;\nENDSEC;\nEND-ISO-10303-21;\n"
120 )
121 .is_err());
122 assert!(read("step", b"not a step file").is_err());
123 }
124
125 #[test]
126 fn read_dispatches_by_format_and_checks_the_result() {
127 let err = read("dwg", b"").unwrap_err().to_string();
128 assert!(err.contains("No 3D preview for the format 'dwg'"), "{err}");
129 let err = read("solidworks-assembly", b"").unwrap_err().to_string();
130 assert!(err.contains("previews of its parts"), "{err}");
131 assert_eq!(
133 read("glb", b"{ not json").unwrap_err().to_string(),
134 read("gltf", b"{ not json").unwrap_err().to_string()
135 );
136 let ply = b"ply\nformat ascii 1.0\nelement vertex 0\nproperty float x\nproperty float y\nproperty float z\nend_header\n";
139 let err = read("ply", ply).unwrap_err().to_string();
140 assert!(err.contains("no geometry"), "{err}");
141 }
142}