123 lines
5.2 KiB
Python
123 lines
5.2 KiB
Python
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
import svg2gcode
|
|
|
|
|
|
class DrawingBoundsTests(unittest.TestCase):
|
|
def setUp(self):
|
|
self.directory = tempfile.TemporaryDirectory()
|
|
self.addCleanup(self.directory.cleanup)
|
|
self.source = Path(self.directory.name) / "drawing.svg"
|
|
self.output = Path(self.directory.name) / "drawing.gcode"
|
|
for name, value in (
|
|
("bed_max_x", 200),
|
|
("bed_max_y", 280),
|
|
("units", "mm"),
|
|
("auto_scale", False),
|
|
):
|
|
patcher = patch.object(svg2gcode, name, value)
|
|
patcher.start()
|
|
self.addCleanup(patcher.stop)
|
|
|
|
def write_line(self, x1, y1, x2, y2, width=200, height=280, transform=""):
|
|
self.source.write_text(
|
|
f'<svg xmlns="http://www.w3.org/2000/svg" '
|
|
f'width="{width}" height="{height}">'
|
|
f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" '
|
|
f'transform="{transform}"/></svg>'
|
|
)
|
|
|
|
def test_exact_boundaries_are_allowed(self):
|
|
self.write_line(0, 0, 200, 280)
|
|
shapes = svg2gcode.get_shapes(self.source, False)
|
|
self.assertIn((0, 280), shapes[0])
|
|
self.assertIn((200, 0), shapes[0])
|
|
|
|
def test_each_boundary_is_enforced(self):
|
|
for x, y in ((-0.0001, 100), (200.0001, 100),
|
|
(100, -0.0001), (100, 280.0001)):
|
|
with self.subTest(x=x, y=y):
|
|
self.write_line(10, 10, x, y)
|
|
with self.assertRaisesRegex(ValueError, "outside bed limits"):
|
|
svg2gcode.get_shapes(self.source, False)
|
|
|
|
def test_transformed_coordinates_are_checked(self):
|
|
self.write_line(10, 10, 20, 20, transform="translate(200, 0)")
|
|
with self.assertRaisesRegex(ValueError, "outside bed limits"):
|
|
svg2gcode.get_shapes(self.source, False)
|
|
|
|
def test_points_are_converted_before_checking(self):
|
|
self.write_line(0, 0, 500, 500, width=500, height=500)
|
|
with patch.object(svg2gcode, "units", "points"):
|
|
shapes = svg2gcode.get_shapes(self.source, False)
|
|
self.assertAlmostEqual(shapes[0][-1][0], 500 * 0.352778)
|
|
|
|
def test_auto_scaling_is_applied_before_checking(self):
|
|
self.write_line(0, 0, 400, 560, width=400, height=560)
|
|
shapes = svg2gcode.get_shapes(self.source, True)
|
|
self.assertTrue(all(0 <= x <= 200 and 0 <= y <= 280
|
|
for shape in shapes for x, y in shape))
|
|
self.assertEqual(shapes[0], [(0, 280), (200, 0)])
|
|
|
|
def test_fitting_preserves_in_bounds_coordinates(self):
|
|
self.write_line(10, 10, 20, 20)
|
|
self.assertEqual(svg2gcode.get_shapes(self.source, True),
|
|
svg2gcode.get_shapes(self.source, False))
|
|
|
|
def test_negative_coordinates_are_shifted_and_scaled(self):
|
|
self.write_line(-100, -100, 300, 300, height=200)
|
|
shapes = svg2gcode.get_shapes(self.source, True)
|
|
self.assertEqual(shapes[0], [(0, 200), (200, 0)])
|
|
|
|
def test_horizontal_vertical_and_single_point_drawings(self):
|
|
for coords, expected in (
|
|
((-100, 100, 300, 100), [(0, 0), (200, 0)]),
|
|
((100, -100, 100, 300), [(0, 280), (0, 0)]),
|
|
((300, 100, 300, 100), [(0, 0)]),
|
|
):
|
|
with self.subTest(coords=coords):
|
|
self.write_line(*coords)
|
|
self.assertEqual(svg2gcode.get_shapes(self.source, True)[0],
|
|
expected)
|
|
|
|
def test_fitting_uses_drawing_not_canvas_dimensions(self):
|
|
self.write_line(10, 300, 20, 350, width=500, height=500)
|
|
self.assertEqual(svg2gcode.get_shapes(self.source, True)[0],
|
|
[(10, 200), (20, 150)])
|
|
|
|
def test_fitting_transformed_coordinates(self):
|
|
self.write_line(10, 10, 20, 20, transform="translate(200, 0)")
|
|
shapes = svg2gcode.get_shapes(self.source, True)
|
|
self.assertTrue(all(0 <= x <= 200 and 0 <= y <= 280
|
|
for shape in shapes for x, y in shape))
|
|
|
|
def test_invalid_bed_dimensions_are_rejected(self):
|
|
self.write_line(10, 10, 20, 20)
|
|
for dimension in (0, -1, float("inf")):
|
|
with patch.object(svg2gcode, "bed_max_x", dimension):
|
|
with self.assertRaisesRegex(ValueError, "Bed dimensions"):
|
|
svg2gcode.get_shapes(self.source, True)
|
|
|
|
def test_canvas_size_alone_does_not_reject_in_bounds_drawing(self):
|
|
self.write_line(10, 300, 20, 350, width=500, height=500)
|
|
self.assertTrue(svg2gcode.get_shapes(self.source, False))
|
|
|
|
def test_failure_does_not_create_or_overwrite_output(self):
|
|
self.write_line(10, 10, 201, 20)
|
|
with patch.object(svg2gcode, "optimise_path") as optimise_path:
|
|
with self.assertRaisesRegex(ValueError, "X201.000000"):
|
|
svg2gcode.main(self.source, self.output)
|
|
self.assertFalse(self.output.exists())
|
|
self.output.write_text("existing output")
|
|
with self.assertRaises(ValueError):
|
|
svg2gcode.main(self.source, self.output)
|
|
self.assertEqual(self.output.read_text(), "existing output")
|
|
optimise_path.assert_not_called()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|