Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add methods to reflect geometry in a layer or canvas about a line #97

Merged
merged 1 commit into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions mahautils/shapes/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,35 @@ def plot(self, units: Optional[str] = None,

return None

def reflect(self, pntA: Union[Array_Float2, 'CartesianPoint2D'],
pntB: Union[Array_Float2, 'CartesianPoint2D']) -> None:
"""Reflects all shapes in all layers of the canvas about a line
specified by two points

Parameters
----------
pntA : list or tuple or CartesianPoint2D
One point on the line across which the shape is to be reflected
pntB : list or tuple or CartesianPoint2D
Another point on the line across which the shape is to be reflected
"""
for layer in self:
layer.reflect(pntA=pntA, pntB=pntB)

def reflect_x(self) -> None:
"""Reflects all shapes in all layers of the canvas about
the :math:`x`-axis
"""
for layer in self:
layer.reflect_x()

def reflect_y(self) -> None:
"""Reflects all shapes in all layers of the canvas about
the :math:`y`-axis
"""
for layer in self:
layer.reflect_y()

def rotate(self, center: Union[Array_Float2, CartesianPoint2D],
angle: float, angle_units: str = 'rad') -> None:
"""Rotates all shapes in all layers of the canvas a given angle in
Expand Down
26 changes: 26 additions & 0 deletions mahautils/shapes/layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,32 @@ def plot(self, units: Optional[str] = None,

return None

def reflect(self, pntA: Union[Array_Float2, 'CartesianPoint2D'],
pntB: Union[Array_Float2, 'CartesianPoint2D']) -> None:
"""Reflects all shapes in the layer about a line specified by two points

Parameters
----------
pntA : list or tuple or CartesianPoint2D
One point on the line across which the shape is to be reflected
pntB : list or tuple or CartesianPoint2D
Another point on the line across which the shape is to be reflected
"""
for shape in self:
shape.reflect(pntA=pntA, pntB=pntB)

def reflect_x(self) -> None:
"""Reflects all shapes in the layer about the :math:`x`-axis
"""
for shape in self:
shape.reflect_x()

def reflect_y(self) -> None:
"""Reflects all shapes in the layer about the :math:`y`-axis
"""
for shape in self:
shape.reflect_y()

def rotate(self, center: Union[Array_Float2, CartesianPoint2D],
angle: float, angle_units: str = 'rad') -> None:
"""Rotates all shapes in the layer a given angle in the :math:`xy`-plane
Expand Down
34 changes: 32 additions & 2 deletions tests/shapes/test_canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,41 @@ def setUp(self):
self.layer2 = Layer()
self.canvas = Canvas(self.layer1, self.layer2)

self.layer1.reflect = Mock()
self.layer2.reflect = Mock()

self.layer1.reflect_x = Mock()
self.layer2.reflect_x = Mock()

self.layer1.reflect_y = Mock()
self.layer2.reflect_y = Mock()

self.layer1.rotate = Mock()
self.layer1.rotate = Mock()
self.layer2.rotate = Mock()

self.layer1.translate = Mock()
self.layer1.translate = Mock()
self.layer2.translate = Mock()

def test_reflect(self):
# Verifies that reflecting a canvas reflects all layers in the canvas
self.canvas.reflect(pntA=(1, 2), pntB=(3, 4))

self.layer1.reflect.assert_called_once_with(pntA=(1, 2), pntB=(3, 4))
self.layer2.reflect.assert_called_once_with(pntA=(1, 2), pntB=(3, 4))

def test_reflect_x(self):
# Verifies that reflecting a canvas reflects all layers in the canvas
self.canvas.reflect_x()

self.layer1.reflect_x.assert_called_once()
self.layer2.reflect_x.assert_called_once()

def test_reflect_y(self):
# Verifies that reflecting a canvas reflects all layers in the canvas
self.canvas.reflect_y()

self.layer1.reflect_y.assert_called_once()
self.layer2.reflect_y.assert_called_once()

def test_rotate(self):
# Verifies that rotating a canvas rotates all layers in the canvas
Expand Down
36 changes: 36 additions & 0 deletions tests/shapes/test_layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,18 @@ def setUp(self):

self.layer = Layer(self.circle1, self.circle2, self.closed_shape)

self.circle1.reflect = Mock()
self.circle2.reflect = Mock()
self.closed_shape.reflect = Mock()

self.circle1.reflect_x = Mock()
self.circle2.reflect_x = Mock()
self.closed_shape.reflect_x = Mock()

self.circle1.reflect_y = Mock()
self.circle2.reflect_y = Mock()
self.closed_shape.reflect_y = Mock()

self.circle1.rotate = Mock()
self.circle2.rotate = Mock()
self.closed_shape.rotate = Mock()
Expand All @@ -289,6 +301,30 @@ def setUp(self):
self.circle2.translate = Mock()
self.closed_shape.translate = Mock()

def test_reflect(self):
# Verifies that reflecting a layer reflects all shapes in the layer
self.layer.reflect(pntA=(1, 2), pntB=(3, 4))

self.circle1.reflect.assert_called_once_with(pntA=(1, 2), pntB=(3, 4))
self.circle2.reflect.assert_called_once_with(pntA=(1, 2), pntB=(3, 4))
self.closed_shape.reflect.assert_called_once_with(pntA=(1, 2), pntB=(3, 4))

def test_reflect_x(self):
# Verifies that reflecting a layer reflects all shapes in the layer
self.layer.reflect_x()

self.circle1.reflect_x.assert_called_once()
self.circle2.reflect_x.assert_called_once()
self.closed_shape.reflect_x.assert_called_once()

def test_reflect_y(self):
# Verifies that reflecting a layer reflects all shapes in the layer
self.layer.reflect_y()

self.circle1.reflect_y.assert_called_once()
self.circle2.reflect_y.assert_called_once()
self.closed_shape.reflect_y.assert_called_once()

def test_rotate(self):
# Verifies that rotating a layer rotates all shapes in the layer
self.layer.rotate(center=(5, 6), angle=700, angle_units='mm')
Expand Down