[utils.transform] better input validation in normalize_mirror and apply_transform
This commit is contained in:
parent
20f37ea0f7
commit
d366db5a62
2 changed files with 32 additions and 2 deletions
|
|
@ -5,7 +5,7 @@ from numpy.testing import assert_equal, assert_allclose
|
||||||
from numpy import pi
|
from numpy import pi
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ..utils import remove_duplicate_vertices, remove_colinear_vertices, poly_contains_points, rotation_matrix_2d, apply_transforms, DeferredDict
|
from ..utils import remove_duplicate_vertices, remove_colinear_vertices, poly_contains_points, rotation_matrix_2d, apply_transforms, normalize_mirror, DeferredDict
|
||||||
from ..file.utils import tmpfile
|
from ..file.utils import tmpfile
|
||||||
from ..utils.curves import bezier
|
from ..utils.curves import bezier
|
||||||
from ..error import PatternError
|
from ..error import PatternError
|
||||||
|
|
@ -94,6 +94,28 @@ def test_apply_transforms_advanced() -> None:
|
||||||
assert_allclose(combined[0], [0, 10, pi / 2, 1, 1], atol=1e-10)
|
assert_allclose(combined[0], [0, 10, pi / 2, 1, 1], atol=1e-10)
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_transforms_empty_inputs() -> None:
|
||||||
|
empty_outer = apply_transforms(numpy.empty((0, 5)), [[1, 2, 0, 0, 1]])
|
||||||
|
assert empty_outer.shape == (0, 5)
|
||||||
|
|
||||||
|
empty_inner = apply_transforms([[1, 2, 0, 0, 1]], numpy.empty((0, 5)))
|
||||||
|
assert empty_inner.shape == (0, 5)
|
||||||
|
|
||||||
|
both_empty_tensor = apply_transforms(numpy.empty((0, 5)), numpy.empty((0, 5)), tensor=True)
|
||||||
|
assert both_empty_tensor.shape == (0, 0, 5)
|
||||||
|
|
||||||
|
|
||||||
|
def test_normalize_mirror_validates_length() -> None:
|
||||||
|
with pytest.raises(ValueError, match='2-item sequence'):
|
||||||
|
normalize_mirror(())
|
||||||
|
|
||||||
|
with pytest.raises(ValueError, match='2-item sequence'):
|
||||||
|
normalize_mirror((True,))
|
||||||
|
|
||||||
|
with pytest.raises(ValueError, match='2-item sequence'):
|
||||||
|
normalize_mirror((True, False, True))
|
||||||
|
|
||||||
|
|
||||||
def test_bezier_validates_weight_length() -> None:
|
def test_bezier_validates_weight_length() -> None:
|
||||||
with pytest.raises(PatternError, match='one entry per control point'):
|
with pytest.raises(PatternError, match='one entry per control point'):
|
||||||
bezier([[0, 0], [1, 1]], [0, 0.5, 1], weights=[1])
|
bezier([[0, 0], [1, 1]], [0, 0.5, 1], weights=[1])
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,10 @@ def normalize_mirror(mirrored: Sequence[bool]) -> tuple[bool, float]:
|
||||||
`angle_to_rotate` in radians
|
`angle_to_rotate` in radians
|
||||||
"""
|
"""
|
||||||
|
|
||||||
mirrored_x, mirrored_y = mirrored
|
if len(mirrored) != 2:
|
||||||
|
raise ValueError(f'mirrored must be a 2-item sequence, got length {len(mirrored)}')
|
||||||
|
|
||||||
|
mirrored_x, mirrored_y = (bool(value) for value in mirrored)
|
||||||
mirror_x = (mirrored_x != mirrored_y) # XOR
|
mirror_x = (mirrored_x != mirrored_y) # XOR
|
||||||
angle = numpy.pi if mirrored_y else 0
|
angle = numpy.pi if mirrored_y else 0
|
||||||
return mirror_x, angle
|
return mirror_x, angle
|
||||||
|
|
@ -111,6 +114,11 @@ def apply_transforms(
|
||||||
if inner.shape[1] == 4:
|
if inner.shape[1] == 4:
|
||||||
inner = numpy.pad(inner, ((0, 0), (0, 1)), constant_values=1.0)
|
inner = numpy.pad(inner, ((0, 0), (0, 1)), constant_values=1.0)
|
||||||
|
|
||||||
|
if outer.shape[0] == 0 or inner.shape[0] == 0:
|
||||||
|
if tensor:
|
||||||
|
return numpy.empty((outer.shape[0], inner.shape[0], 5))
|
||||||
|
return numpy.empty((0, 5))
|
||||||
|
|
||||||
# If mirrored, flip y's
|
# If mirrored, flip y's
|
||||||
xy_mir = numpy.tile(inner[:, :2], (outer.shape[0], 1, 1)) # dims are outer, inner, xyrm
|
xy_mir = numpy.tile(inner[:, :2], (outer.shape[0], 1, 1)) # dims are outer, inner, xyrm
|
||||||
xy_mir[outer[:, 3].astype(bool), :, 1] *= -1
|
xy_mir[outer[:, 3].astype(bool), :, 1] *= -1
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue