Files
cad-Integration/SimpleCADAPI-master/test/test_rearchitecture_2_0_structural_remaining.py
2026-07-22 13:48:46 +08:00

142 lines
5.7 KiB
Python

"""TDD coverage for the remaining structural 2.0 items."""
from __future__ import annotations
import json
import unittest
import simplecadapi as scad
from simplecadapi.graph import GraphSession
class TestRemainingStructuralKernel(unittest.TestCase):
def test_curve_builders_return_ocp_wrapped_shapes(self):
shapes = [
scad.make_line_redge((0, 0, 0), (1, 0, 0)),
scad.make_circle_redge((0, 0, 0), 1.0),
scad.make_three_point_arc_redge((0, 0, 0), (1, 1, 0), (2, 0, 0)),
scad.make_angle_arc_redge((0, 0, 0), 1.0, 0.0, 1.57),
scad.make_spline_redge(
control_points=[(0, 0, 0), (0.6, 1, 0), (1.4, 1, 0), (2, 0, 0)]
),
scad.make_helix_rwire(1.0, 3.0, 0.5),
]
for shape in shapes:
self.assertTrue(hasattr(shape, "wrapped"))
self.assertFalse(hasattr(shape, "cq_edge"))
self.assertFalse(hasattr(shape, "cq_wire"))
def test_loft_sweep_and_helical_sweep_do_not_depend_on_cadquery_feature_builders(
self,
):
rect1 = scad.make_rectangle_rwire(2.0, 2.0, center=(0, 0, 0))
rect2 = scad.make_rectangle_rwire(1.0, 1.0, center=(0, 0, 2.0))
profile = scad.make_circle_rface((0, 0, 0), 0.5)
path = scad.make_segment_rwire((0, 0, 0), (0, 0, 3.0))
helix_profile = scad.make_rectangle_rwire(0.4, 0.2)
loft = scad.loft_rsolid([rect1, rect2])
sweep = scad.sweep_rsolid(profile, path)
helical = scad.helical_sweep_rsolid(
helix_profile, pitch=1.0, height=2.0, radius=1.0
)
for solid in (loft, sweep, helical):
self.assertIsInstance(solid, scad.Solid)
self.assertTrue(hasattr(solid, "wrapped"))
self.assertFalse(hasattr(solid, "cq_solid"))
class TestRemainingStructuralSemanticAndFrame(unittest.TestCase):
def test_semantic_delta_uses_higher_level_entity_types(self):
with GraphSession() as session:
face = scad.make_circle_rface((0, 0, 0), 2.0)
scad.extrude_rsolid(face, (0, 0, 1), 3.0)
nodes = session.graph.topological_order()
created_entity_types = {
ref.entity_type
for node in nodes
if node.semantic_delta is not None
for ref in node.semantic_delta.created
}
self.assertIn("Sketch", created_entity_types)
self.assertIn("Feature", created_entity_types)
self.assertNotEqual(created_entity_types, {"ShapeOutput"})
def test_graph_session_owns_independent_frame_graph(self):
with GraphSession() as session:
with scad.SimpleWorkplane(origin=(1.0, 2.0, 3.0)):
scad.make_point_rvertex(1.0, 0.0, 0.0)
self.assertTrue(hasattr(session, "frame_graph"))
self.assertGreaterEqual(session.frame_graph.node_count, 1)
def test_session_and_model_export_include_frame_graph(self):
with GraphSession() as session:
with scad.SimpleWorkplane(origin=(1.0, 2.0, 3.0)):
scad.make_point_rvertex(1.0, 0.0, 0.0)
session_payload = scad.import_session_json(scad.export_session_json(session))
self.assertIn("frame_graph", session_payload)
self.assertGreaterEqual(session_payload["frame_graph"].node_count, 1)
model_payload = scad.import_model_json(scad.export_model_json(session))
self.assertIn("frame_graph", model_payload)
self.assertGreaterEqual(model_payload["frame_graph"].node_count, 1)
raw_model = json.loads(scad.export_model_json(session))
self.assertIn("frame_graph", raw_model)
self.assertGreaterEqual(len(raw_model["frame_graph"]["nodes"]), 1)
def test_model_export_includes_semantic_entity_registry_for_sketch_and_feature(
self,
):
with GraphSession() as session:
face = scad.make_circle_rface((0.0, 0.0, 0.0), 2.0)
scad.extrude_rsolid(face, (0.0, 0.0, 1.0), 3.0)
raw = json.loads(scad.export_model_json(session))
self.assertIn("semantic_entity_registry", raw)
entity_types = {item["entity_type"] for item in raw["semantic_entity_registry"]}
self.assertIn("Sketch", entity_types)
self.assertIn("Feature", entity_types)
self.assertNotIn("AssemblyConstraint", entity_types)
class TestHelicalSweepMacroRecording(unittest.TestCase):
def test_helical_sweep_expands_to_helix_plus_sweep_nodes(self):
with GraphSession() as session:
profile = scad.make_rectangle_rwire(0.4, 0.2)
result = scad.helical_sweep_rsolid(
profile, pitch=1.0, height=2.0, radius=1.0
)
self.assertIsInstance(result, scad.Solid)
ops = [node.op for node in session.graph.topological_order()]
self.assertIn("make_helix_redge", ops)
self.assertIn("make_wire_from_edges_rwire", ops)
self.assertIn("make_sweep_rsolid", ops)
self.assertNotIn("helical_sweep", ops)
def test_helical_sweep_roundtrip_replays_as_macro_graph(self):
with GraphSession() as session:
profile = scad.make_rectangle_rwire(0.4, 0.2)
swept = scad.helical_sweep_rsolid(
profile, pitch=1.0, height=2.0, radius=1.0
)
restored = scad.import_graph_json(scad.export_graph_json(session.graph))
ops = [node.op for node in restored.topological_order()]
self.assertIn("make_helix_redge", ops)
self.assertIn("make_wire_from_edges_rwire", ops)
self.assertIn("make_sweep_rsolid", ops)
self.assertNotIn("helical_sweep", ops)
replayed = scad.replay_graph(restored)
self.assertEqual(len(replayed), 1)
self.assertAlmostEqual(replayed[0].get_volume(), swept.get_volume(), places=4)
if __name__ == "__main__":
unittest.main()