nodeslicer/tests/test_arrange.py
2026-06-08 14:35:35 +03:00

175 lines
5.9 KiB
Python

import numpy as np
import unittest
from unittest.mock import MagicMock
import sys
from pathlib import Path
# Add workspace directory to sys.path to resolve root package name (NodeSlicer)
PROJECT_ROOT = Path(__file__).resolve().parent.parent
sys.path.append(str(PROJECT_ROOT.parent))
# Define dummy classes to avoid metaclass conflicts
class DummyNodeSocket: pass
class DummyNode: pass
class DummyObject: pass
class DummyMesh: pass
class DummyNodeSocketShader: pass
class DummyNodeCustomGroup: pass
class DummyNodeTree: pass
class DummyOperator: pass
class DummyMenu: pass
class DummyPanel: pass
class DummyPropertyGroup: pass
mock_types = MagicMock()
mock_types.NodeSocket = DummyNodeSocket
mock_types.Node = DummyNode
mock_types.Object = DummyObject
mock_types.Mesh = DummyMesh
mock_types.NodeSocketShader = DummyNodeSocketShader
mock_types.NodeCustomGroup = DummyNodeCustomGroup
mock_types.NodeTree = DummyNodeTree
mock_types.Operator = DummyOperator
mock_types.Menu = DummyMenu
mock_types.Panel = DummyPanel
mock_types.PropertyGroup = DummyPropertyGroup
# Mock bpy and its subpackages before importing core modules
mock_bpy = MagicMock()
mock_bpy.context.scene = MagicMock()
mock_bpy.context.scene.unit_settings.scale_length = 0.001
mock_bpy.types = mock_types
sys.modules['bpy'] = mock_bpy
sys.modules['bpy.types'] = mock_types
sys.modules['bpy.props'] = MagicMock()
sys.modules['bpy.utils'] = MagicMock()
sys.modules['bpy.utils.previews'] = MagicMock()
sys.modules['bpy.app'] = MagicMock()
sys.modules['bpy.app.handlers'] = MagicMock()
# Import the actual classes to test
from NodeSlicer.core.nodeslicer.nodes.mesh import SLICENODE_ArrangeMesh
from NodeSlicer.infra.blender.blender_mesh_capture import SlicingGroup, SlicingCollection, SlicingObject
class TestArrangeMesh(unittest.TestCase):
def test_arrange_mesh_simple(self):
# Create a SlicingObject with a single triangle
so = SlicingObject()
so.name = "part1"
so.mesh = np.array([[[10.0, 10.0, 0.0],
[20.0, 10.0, 0.0],
[15.0, 20.0, 0.0],
[0.0, 0.0, 1.0]]], dtype=np.float64)
# Create SlicingCollection
sc = SlicingCollection([], "coll1")
sc.objects = [so]
# Create SlicingGroup
sg = SlicingGroup([])
sg.collections = {"coll1": sc}
# Mock node inputs resolution
node = SLICENODE_ArrangeMesh()
node.method = 'NFP'
# We override resolve to simulate inputs
def mock_resolve(fieldname):
if fieldname == "Slicing Group":
return sg
elif fieldname == "Bed X":
return 250.0
elif fieldname == "Bed Y":
return 250.0
elif fieldname == "Spacing":
return 2.0
return None
node.resolve = mock_resolve
# Evaluate output
result_group = node.evaluate_output("Slicing Group")
self.assertIsNotNone(result_group)
self.assertIn("coll1", result_group.collections)
arranged_sc = result_group.collections["coll1"]
# The bounding box should now be centered on the 250x250 bed
self.assertEqual(arranged_sc.min_x, 120.0)
self.assertEqual(arranged_sc.min_y, 120.0)
self.assertEqual(arranged_sc.max_x, 130.0)
self.assertEqual(arranged_sc.max_y, 130.0)
# Check normal remains unchanged
self.assertTrue(np.allclose(arranged_sc.objects[0].mesh[0, 3, :], [0.0, 0.0, 1.0]))
def test_arrange_mesh_bl(self):
so = SlicingObject()
so.name = "part1"
so.mesh = np.array([[[10.0, 10.0, 0.0],
[20.0, 10.0, 0.0],
[15.0, 20.0, 0.0],
[0.0, 0.0, 1.0]]], dtype=np.float64)
sc = SlicingCollection([], "coll1")
sc.objects = [so]
sg = SlicingGroup([])
sg.collections = {"coll1": sc}
node = SLICENODE_ArrangeMesh()
node.method = 'BL'
def mock_resolve(fieldname):
if fieldname == "Slicing Group":
return sg
elif fieldname == "Bed X":
return 250.0
elif fieldname == "Bed Y":
return 250.0
elif fieldname == "Spacing":
return 2.0
return None
node.resolve = mock_resolve
result_group = node.evaluate_output("Slicing Group")
self.assertIsNotNone(result_group)
arranged_sc = result_group.collections["coll1"]
self.assertGreaterEqual(arranged_sc.min_x, 0.0)
self.assertGreaterEqual(arranged_sc.min_y, 0.0)
def test_arrange_mesh_djd(self):
so = SlicingObject()
so.name = "part1"
so.mesh = np.array([[[10.0, 10.0, 0.0],
[20.0, 10.0, 0.0],
[15.0, 20.0, 0.0],
[0.0, 0.0, 1.0]]], dtype=np.float64)
sc = SlicingCollection([], "coll1")
sc.objects = [so]
sg = SlicingGroup([])
sg.collections = {"coll1": sc}
node = SLICENODE_ArrangeMesh()
node.method = 'DJD'
def mock_resolve(fieldname):
if fieldname == "Slicing Group":
return sg
elif fieldname == "Bed X":
return 250.0
elif fieldname == "Bed Y":
return 250.0
elif fieldname == "Spacing":
return 2.0
return None
node.resolve = mock_resolve
result_group = node.evaluate_output("Slicing Group")
self.assertIsNotNone(result_group)
arranged_sc = result_group.collections["coll1"]
self.assertEqual(arranged_sc.min_x, 120.0)
self.assertEqual(arranged_sc.min_y, 120.0)
if __name__ == '__main__':
unittest.main()