first commit
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
"""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()
|
||||
Reference in New Issue
Block a user