use halfedge::{
build_cube, build_icosphere,
geometry::{edge_length_stats, mesh_volume, surface_area},
io::{format_obj, format_stl_binary, parse_obj, parse_stl_binary},
isotropic_remesh,
topology_ops::{flip_edge, split_edge},
traversal::is_closed,
validate_mesh, validate_topology,
};
#[test]
fn workflow_icosphere_validate_geometry_export_reimport() {
let mesh = build_icosphere(1);
assert!(mesh.vertex_count() > 0);
assert!(mesh.face_count() > 0);
assert!(validate_mesh(&mesh).is_ok());
assert!(validate_topology(&mesh).is_empty());
assert!(is_closed(&mesh));
let area = surface_area(&mesh);
assert!(area > 0.0);
let volume = mesh_volume(&mesh);
assert!(volume.abs() > 0.0);
let stats = edge_length_stats(&mesh);
assert!(stats.count > 0);
let obj_text = format_obj(&mesh);
assert!(obj_text.contains("v "));
assert!(obj_text.contains("f "));
let mesh2 = parse_obj(&obj_text).expect("OBJ roundtrip 应成功");
assert_eq!(mesh2.vertex_count(), mesh.vertex_count());
assert_eq!(mesh2.face_count(), mesh.face_count());
let stl_bytes = format_stl_binary(&mesh);
let mesh3 = parse_stl_binary(&stl_bytes, mesh.face_count()).expect("STL roundtrip 应成功");
assert_eq!(mesh3.vertex_count(), mesh.vertex_count());
assert_eq!(mesh3.face_count(), mesh.face_count());
}
#[test]
fn workflow_topology_operations_chain() {
let mut mesh = build_icosphere(0);
let he = mesh.halfedge_ids().next().expect("网格非空");
if split_edge(&mut mesh, he).is_ok() {
assert!(mesh.vertex_count() > 0);
assert!(validate_mesh(&mesh).is_ok());
}
let he2 = mesh.halfedge_ids().find(|&h| {
if let Some(h_data) = mesh.get_halfedge(h) {
h_data.face.is_some() && h_data.twin.is_some()
} else {
false
}
});
if let Some(he2) = he2 {
let _ = flip_edge(&mut mesh, he2);
assert!(validate_mesh(&mesh).is_ok());
}
let _stats = isotropic_remesh(&mut mesh, None, 2, false);
assert!(validate_mesh(&mesh).is_ok());
assert!(is_closed(&mesh));
}
#[test]
fn workflow_cube_geometry_correctness() {
let cube = build_cube(1.0);
assert!(validate_mesh(&cube).is_ok());
let volume = mesh_volume(&cube);
assert!(
(volume.abs() - 1.0).abs() < 0.01,
"立方体体积应 ≈ 1.0,实际 {}",
volume
);
let area = surface_area(&cube);
assert!(
(area - 6.0).abs() < 0.01,
"立方体表面积应 ≈ 6.0,实际 {}",
area
);
}
#[test]
fn workflow_multi_format_roundtrip() {
use halfedge::io::{format_off, format_ply, parse_off, parse_ply};
let mesh = build_icosphere(0);
let v_count = mesh.vertex_count();
let f_count = mesh.face_count();
let obj = format_obj(&mesh);
let from_obj = parse_obj(&obj).expect("OBJ 解析");
assert_eq!(from_obj.vertex_count(), v_count);
assert_eq!(from_obj.face_count(), f_count);
let ply = format_ply(&mesh);
let from_ply = parse_ply(&ply).expect("PLY 解析");
assert_eq!(from_ply.vertex_count(), v_count);
assert_eq!(from_ply.face_count(), f_count);
let off = format_off(&mesh);
let from_off = parse_off(&off).expect("OFF 解析");
assert_eq!(from_off.vertex_count(), v_count);
assert_eq!(from_off.face_count(), f_count);
}