Files
cadSet/SimpleCADAPI/test/test_internal_mesh.py
T
2026-07-22 19:38:36 +08:00

88 lines
2.9 KiB
Python

import simplecadapi as scad
import simplecadapi._mesh as _mesh
def _write_cached_mesh_as_obj(solid, path):
mesh = _mesh.cached_mesh(solid)
assert mesh is not None
lines = ["# SimpleCAD internal cached mesh OBJ"]
for x, y, z in mesh.vertices:
lines.append(f"v {x:.9g} {y:.9g} {z:.9g}")
for a, b, c in mesh.triangles:
lines.append(f"f {int(a) + 1} {int(b) + 1} {int(c) + 1}")
path.write_text("\n".join(lines) + "\n", encoding="utf-8")
return mesh
def test_solid_creation_attaches_internal_mesh_cache():
solid = scad.make_box_rsolid(width=10.0, height=20.0, depth=30.0)
mesh = _mesh.cached_mesh(solid)
assert mesh is not None
assert _mesh.mesh_error(solid) is None
assert mesh.vertex_count > 0
assert mesh.triangle_count > 0
assert mesh.vertices.shape[1] == 3
assert mesh.triangles.shape[1] == 3
assert int(mesh.triangles.min()) >= 0
assert int(mesh.triangles.max()) < mesh.vertex_count
def test_internal_mesh_preserves_face_triangle_ranges():
solid = scad.make_box_rsolid(width=10.0, height=20.0, depth=30.0)
mesh = _mesh.cached_mesh(solid)
assert mesh is not None
ranges = mesh.face_triangle_ranges
assert len(ranges) == len(solid.get_faces())
assert sum(item.count for item in ranges) == mesh.triangle_count
assert [item.face_index for item in ranges] == list(range(len(ranges)))
assert all(item.source_topo_id for item in ranges)
def test_internal_mesh_bounds_track_solid_extent():
solid = scad.make_box_rsolid(width=10.0, height=20.0, depth=30.0)
mesh = _mesh.cached_mesh(solid)
assert mesh is not None
lower, upper = mesh.bounds
assert lower == (-5.0, -10.0, 0.0)
assert upper == (5.0, 10.0, 30.0)
def test_transformed_solid_keeps_mesh_cache_on_transformed_geometry():
solid = scad.make_box_rsolid(width=10.0, height=20.0, depth=30.0)
translated = scad.translate_shape(shape=solid, vector=(1.0, 2.0, 3.0))
mesh = _mesh.cached_mesh(translated)
assert mesh is not None
lower, upper = mesh.bounds
assert lower == (-4.0, -8.0, 3.0)
assert upper == (6.0, 12.0, 33.0)
def test_mesh_internals_are_not_top_level_public_api():
assert not hasattr(scad, "tessellate_rmesh")
assert "tessellate_rmesh" not in scad.__all__
assert "TriMesh" not in scad.__all__
def test_cached_mesh_can_export_obj_without_public_stl_api(tmp_path):
solid = scad.make_cylinder_rsolid(radius=3.0, height=5.0)
output_path = tmp_path / "cached_mesh.obj"
mesh = _write_cached_mesh_as_obj(solid, output_path)
content = output_path.read_text(encoding="utf-8")
vertex_lines = [line for line in content.splitlines() if line.startswith("v ")]
face_lines = [line for line in content.splitlines() if line.startswith("f ")]
assert len(vertex_lines) == mesh.vertex_count
assert len(face_lines) == mesh.triangle_count
assert content.startswith("# SimpleCAD internal cached mesh OBJ\n")