Files
cadcraft/crates/engine/tests/it/polyface_explode.rs
T
2034d6899e Polyface meshes stay one object through DXF and DWG (#2600)
* Polyface meshes stay one object through DXF and DWG

A polyface mesh (POLYLINE flag 64) was read as loose 3D faces. It is now
read, drawn, exploded into its 3D faces and written back as a POLYLINE.
Hidden edges aren't drawn. A mesh too large for the 16-bit groups 71-74
is saved as 3D faces.

Split from #1005.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* A polyface face ends at its first zero index

A face record with a gap ([1, 2, 0, 3]) has two corners and is dropped,
not read as a triangle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Polyface meshes: write only faces that name their vertices; ID gives their Z

The writer drops the faces the reader would drop, so no record names a
missing vertex, and the 16-bit check only needs the counts. ID and DIST
give a mesh the Z of its nearest visible edge, as they do for 3D faces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-11-01 14:40:30 -05:00

33 lines
1.3 KiB
Rust

//! EXPLODE turns a polyface mesh into its 3D faces, as AutoCAD does; hidden edges stay hidden.
use cadcraft_engine::Session;
use cadcraft_engine::doc::{Common, EntityKind, PolyfaceMesh, Space};
use cadcraft_geom::Vec3;
use serde_json::json;
#[test]
fn exploding_a_polyface_mesh_gives_its_3d_faces() {
let mut s = Session::new();
let mesh = PolyfaceMesh {
vertices: vec![Vec3::new(0.0, 0.0, 0.0), Vec3::new(10.0, 0.0, 0.0), Vec3::new(10.0, 10.0, 2.0), Vec3::new(0.0, 10.0, 2.0)],
faces: vec![[1, 2, -3, 0], [3, 4, -1, 0]],
};
let h = s.doc_mut().unwrap().add(&Space::Model, Common::default(), EntityKind::PolyfaceMesh(mesh)).unwrap();
s.execute("explode", &json!({"handles": [h.hex()]})).unwrap();
let faces: Vec<_> = s
.doc()
.unwrap()
.model
.iter()
.filter_map(|e| match &e.kind {
EntityKind::Face3d(f) => Some(f.clone()),
_ => None,
})
.collect();
assert_eq!(faces.len(), 2);
assert!(s.doc().unwrap().model.iter().all(|e| !matches!(e.kind, EntityKind::PolyfaceMesh(_))));
// The diagonal starts at the third corner of the first triangle: edge 3 (and the closing 4th) hidden.
assert_eq!(faces[0].corners[2], Vec3::new(10.0, 10.0, 2.0));
assert_eq!(faces[0].hidden_edges, 4 | 8);
}