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 club target shape. #224

Merged
merged 4 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions src/data_morph/shapes/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class ShapeFactory:
'rectangle': polygons.Rectangle,
'rings': circles.Rings,
'star': polygons.Star,
'club': points.Club,
}

AVAILABLE_SHAPES: list[str] = sorted(_SHAPE_MAPPING.keys())
Expand Down
83 changes: 83 additions & 0 deletions src/data_morph/shapes/points.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,3 +304,86 @@ def distance(self, x: Number, y: Number) -> int:
Always returns 0 to allow for scattering of the points.
"""
return 0


class Club(PointCollection):
"""
Class for the club shape.

.. plot::
:scale: 75
:caption:
This shape is generated using the panda dataset.

from data_morph.data.loader import DataLoader
from data_morph.shapes.points import Club

_ = Club(DataLoader.load_dataset('panda')).plot()

Parameters
----------
dataset : Dataset
The starting dataset to morph into other shapes.
"""

def __init__(self, dataset: Dataset) -> None:
x_bounds = dataset.data_bounds.x_bounds
y_bounds = dataset.data_bounds.y_bounds

x_shift = sum(x_bounds) / 2
y_shift = sum(y_bounds) / 2
scale_factor = min(x_bounds.range, y_bounds.range) / 75

# params for lobes
r = 15 * scale_factor
kevin1kevin1k marked this conversation as resolved.
Show resolved Hide resolved
top_lobe_y_offset = 18 * scale_factor
bottom_lobes_x_offset = 15 * scale_factor
bottom_lobes_y_offset = 9 * scale_factor

t = np.linspace(0, (2 - 1 / 3) * np.pi, num=30)

# top lobe
angle_offset = -1 / 3 * np.pi
x_top = r * np.cos(t + angle_offset)
y_top = r * np.sin(t + angle_offset) + top_lobe_y_offset

# bottom left lobe
angle_offset = 1 / 3 * np.pi
x_bottom_left = r * np.cos(t + angle_offset) - bottom_lobes_x_offset
y_bottom_left = r * np.sin(t + angle_offset) - bottom_lobes_y_offset

# bottom right lobe
angle_offset = np.pi
x_bottom_right = r * np.cos(t + angle_offset) + bottom_lobes_x_offset
y_bottom_right = r * np.sin(t + angle_offset) - bottom_lobes_y_offset

x_lobes = [x_top, x_bottom_left, x_bottom_right]
y_lobes = [y_top, y_bottom_left, y_bottom_right]

# params for the stem
stem_x_offset = 8 * scale_factor
stem_y_offset = 34 * scale_factor
stem_scaler = 0.35 / scale_factor
stem_x_pad = 1.5 * scale_factor

# stem bottom
x_line = np.linspace(-stem_x_offset, stem_x_offset, num=8)
y_line = np.repeat(-stem_y_offset, 8)

# left part of the stem
t_left = np.linspace(-(stem_x_offset - stem_x_pad), -stem_x_pad, num=6)
x_left = t_left
y_left = stem_scaler * np.power(t_left + stem_x_offset, 2) - stem_y_offset
kevin1kevin1k marked this conversation as resolved.
Show resolved Hide resolved

# right part of the stem
t_right = np.linspace(stem_x_pad, stem_x_offset - stem_x_pad, num=6)
x_right = t_right
y_right = stem_scaler * np.power(t_right - stem_x_offset, 2) - stem_y_offset
kevin1kevin1k marked this conversation as resolved.
Show resolved Hide resolved

x_stem = [x_line, x_left, x_right]
y_stem = [y_line, y_left, y_right]

xs = x_shift + np.concatenate(x_lobes + x_stem)
ys = y_shift + np.concatenate(y_lobes + y_stem)

super().__init__(*np.stack([xs, ys], axis=1))
17 changes: 17 additions & 0 deletions tests/shapes/test_points.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,20 @@ class TestUpParabola(ParabolaTestBase):
positive_quadratic_term = True
x_index = 0
y_index = 1


class TestClub(PointsModuleTestBase):
"""Test the Club class."""

shape_name = 'club'
distance_test_cases = [
[(19.639387, 73.783711), 0.0], # top lobe
[(12.730310, 60.295844), 0.0], # bottom left lobe
[(27.630301, 60.920443), 0.0], # bottom right lobe
[(20.304761, 55.933333), 0.0], # top of stem
[(18.8, 57.076666), 0.0], # left part of stem
[(20.933333, 57.823333), 0.0], # right part of stem
[(0, 0), 58.717591],
[(20, 50), 5.941155],
[(10, 80), 10.288055],
]
Loading