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

Fix percentage distance methods #339

Merged
merged 25 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4569d36
Corrected calculation of arc length
JackB-Ansys Jul 15, 2024
cd113d4
Corrected make percentage method use percentage not fraction
JackB-Ansys Jul 15, 2024
abfe2a3
Deprecated get_coordinate_from_percentage_distance methods. Replaced …
JackB-Ansys Jul 15, 2024
0f9f663
update tests
JackB-Ansys Jul 17, 2024
4009764
Merge remote-tracking branch 'refs/remotes/origin/main' into fix_perc…
JackB-Ansys Aug 14, 2024
6f112a0
Added deprecation warnings
JackB-Ansys Aug 14, 2024
35e19a5
Added more tests for updated get_coordinate_from_distance method (new…
JackB-Ansys Aug 14, 2024
6ab1540
Added more tests for updated get_coordinate_from_distance method (tes…
JackB-Ansys Aug 15, 2024
3343f34
Added more tests for updated get_coordinate_from_distance method (tes…
JackB-Ansys Aug 15, 2024
ffa98dc
Merge branch 'main' into fix_percentage_distance_methods
jgsdavies Aug 20, 2024
741b597
Merge branch 'main' into fix_percentage_distance_methods
jgsdavies Sep 17, 2024
da2b09d
Merge branch 'main' into fix_percentage_distance_methods
jgsdavies Oct 7, 2024
ade8649
Added test for arc with negative radius for deprecated get_coordinate…
JackB-Ansys Oct 22, 2024
a39970c
Added tests to check error is raised when no distance, percentage or …
JackB-Ansys Oct 22, 2024
7045440
Merge remote-tracking branch 'refs/remotes/origin/main' into fix_perc…
JackB-Ansys Oct 22, 2024
ab64e0f
Merge remote-tracking branch 'refs/remotes/origin/main' into fix_perc…
JackB-Ansys Oct 30, 2024
3aed80b
Merge remote-tracking branch 'refs/remotes/origin/main' into fix_perc…
JackB-Ansys Nov 4, 2024
53fec21
Merge branch 'main' into fix_percentage_distance_methods
jgsdavies Nov 12, 2024
0ffb4f0
Merge branch 'main' into fix_percentage_distance_methods
james-packer Nov 22, 2024
387299e
Update src/ansys/motorcad/core/geometry.py
JackB-Ansys Nov 26, 2024
6c19450
Update src/ansys/motorcad/core/geometry.py
JackB-Ansys Nov 26, 2024
bd63100
Update src/ansys/motorcad/core/geometry.py
JackB-Ansys Nov 26, 2024
87d9ff9
Update src/ansys/motorcad/core/geometry.py
JackB-Ansys Nov 26, 2024
b95a925
Update src/ansys/motorcad/core/geometry.py
JackB-Ansys Nov 26, 2024
c5c03fa
Merge branch 'main' into fix_percentage_distance_methods
james-packer Nov 26, 2024
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
114 changes: 85 additions & 29 deletions src/ansys/motorcad/core/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from copy import deepcopy
from enum import Enum
from math import atan2, cos, degrees, inf, isclose, radians, sin, sqrt
from warnings import warn

GEOM_TOLERANCE = 1e-6

Expand Down Expand Up @@ -1039,51 +1040,74 @@ def mirror(self, mirror_line):
else:
raise Exception("Line can only be mirrored about Line()")

def get_coordinate_from_percentage_distance(self, ref_coordinate, percentage):
"""Get the coordinate at the percentage distance along the line from the reference.
def get_coordinate_from_percentage_distance(self, ref_coordinate, fraction):
"""Get the coordinate at a fractional distance along the line from the reference coord.

.. note::
JackB-Ansys marked this conversation as resolved.
Show resolved Hide resolved
This method is deprecated. Use the :func:`Line.get_coordinate_from_distance`
method with the `fraction = ` or `percentage =` argument.

Parameters
----------
ref_coordinate : Coordinate
Entity reference coordinate.

percentage : float
Percentage distance along Line.
fraction : float
Fractional distance along Line.

Returns
-------
Coordinate
Coordinate at percentage distance along Line.
Coordinate at fractional distance along Line.
"""
if ref_coordinate == self.end:
coordinate_1 = self.end
coordinate_2 = self.start
else:
coordinate_1 = self.start
coordinate_2 = self.end

t = (self.length * percentage) / self.length
x = ((1 - t) * coordinate_1.x) + (t * coordinate_2.x)
y = ((1 - t) * coordinate_1.y) + (t * coordinate_2.y)

return Coordinate(x, y)
warn(
"get_coordinate_from_percentage_distance() WILL BE DEPRECATED SOON - "
"USE get_coordinate_from_distance instead with the `fraction = ` or `percentage = ` "
"optional argument",
DeprecationWarning,
)
return self.get_coordinate_from_distance(ref_coordinate, fraction=fraction)

def get_coordinate_from_distance(self, ref_coordinate, distance):
def get_coordinate_from_distance(
JackB-Ansys marked this conversation as resolved.
Show resolved Hide resolved
self, ref_coordinate, distance=None, fraction=None, percentage=None
):
"""Get the coordinate at the specified distance along the line from the reference.

Parameters
----------
ref_coordinate : Coordinate
Entity reference coordinate.

distance : float
distance : float, optional
Distance along Line.

fraction : float, optional
Fractional distance along Line.

percentage : float, optional
Percentage distance along Line.

Returns
-------
Coordinate
Coordinate at distance along Line.
"""
if not distance and not fraction and not percentage:
JackB-Ansys marked this conversation as resolved.
Show resolved Hide resolved
raise Exception("You must provide either a distance, fraction or percentage.")

if distance and fraction:
warn("Both distance and fraction provided. Using distance.", UserWarning)
if distance and percentage:
warn("Both distance and percentage provided. Using distance.", UserWarning)

if not distance:
if fraction and percentage:
warn("Both fraction and percentage provided. Using fraction.", UserWarning)
if fraction:
distance = self.length * fraction
elif percentage:
distance = self.length * (percentage / 100)

if ref_coordinate == self.end:
coordinate_1 = self.end
coordinate_2 = self.start
Expand Down Expand Up @@ -1218,42 +1242,74 @@ def midpoint(self):
x_shift, y_shift = rt_to_xy(abs(self.radius), angle)
return Coordinate(self.centre.x + x_shift, self.centre.y + y_shift)

def get_coordinate_from_percentage_distance(self, ref_coordinate, percentage):
"""Get the coordinate at the percentage distance along the arc from the reference coord.
def get_coordinate_from_percentage_distance(self, ref_coordinate, fraction):
"""Get the coordinate at a fractional distance along the arc from the reference coord.

.. note::
This method is deprecated. Use the :func:`Arc.get_coordinate_from_distance`
method with the `fraction = ` or `percentage =` argument.

Parameters
----------
ref_coordinate : Coordinate
Entity reference coordinate.

percentage : float
Percentage distance along Arc.
fraction : float
Fractional distance along Arc.

Returns
-------
Coordinate
Coordinate at percentage distance along Arc.
Coordinate at fractional distance along Arc.
"""
length = self.length * percentage

return self.get_coordinate_from_distance(ref_coordinate, length)
warn(
"get_coordinate_from_percentage_distance() WILL BE DEPRECATED SOON - "
"USE get_coordinate_from_distance instead with the `fraction = ` or `percentage = ` "
"optional argument",
DeprecationWarning,
)
return self.get_coordinate_from_distance(ref_coordinate, fraction=fraction)

def get_coordinate_from_distance(self, ref_coordinate, distance):
def get_coordinate_from_distance(
self, ref_coordinate, distance=None, fraction=None, percentage=None
):
"""Get the coordinate at the specified distance along the arc from the reference coordinate.

Parameters
----------
ref_coordinate : Coordinate
Entity reference coordinate.

distance : float
distance : float, optional
Distance along arc.

fraction : float, optional
Fractional distance along Arc.

percentage : float, optional
Percentage distance along Arc.

Returns
-------
Coordinate
Coordinate at distance along Arc.
"""
if not distance and not fraction and not percentage:
raise Exception("You must provide either a distance, fraction or percentage.")

if distance and fraction:
warn("Both distance and fraction provided. Using distance.", UserWarning)
if distance and percentage:
warn("Both distance and percentage provided. Using distance.", UserWarning)

if not distance:
if fraction and percentage:
warn("Both fraction and percentage provided. Using fraction.", UserWarning)
if fraction:
distance = self.length * fraction
elif percentage:
distance = self.length * (percentage / 100)

ref_coordinate_angle = atan2(
(ref_coordinate.y - self.centre.y), (ref_coordinate.x - self.centre.x)
)
Expand Down
122 changes: 114 additions & 8 deletions tests/test_geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -573,9 +573,56 @@ def test_line_get_coordinate_from_percentage_distance():
def test_line_get_coordinate_from_distance():
line = geometry.Line(geometry.Coordinate(0, 0), geometry.Coordinate(2, 0))

# test using the 'distance' argument
assert line.get_coordinate_from_distance(geometry.Coordinate(0, 0), 1) == geometry.Coordinate(
1, 0
)
# test using the 'fraction' argument
assert line.get_coordinate_from_distance(
geometry.Coordinate(0, 0), fraction=0.5
) == geometry.Coordinate(1, 0)
# test using the 'percentage' argument
assert line.get_coordinate_from_distance(
geometry.Coordinate(0, 0), percentage=50
) == geometry.Coordinate(1, 0)

# test that warnings are raised when multiple arguments are given
# distance and fraction
with pytest.warns(UserWarning) as record:
coord = line.get_coordinate_from_distance(geometry.Coordinate(0, 0), 1, fraction=0.6)
assert "Both distance and fraction provided" in record[0].message.args[0]
# check that distance is used
assert coord == line.get_coordinate_from_distance(geometry.Coordinate(0, 0), 1)

# distance and percentage
with pytest.warns(UserWarning) as record:
coord = line.get_coordinate_from_distance(geometry.Coordinate(0, 0), 1, percentage=40)
assert "Both distance and percentage provided" in record[0].message.args[0]
# check that distance is used
assert coord == line.get_coordinate_from_distance(geometry.Coordinate(0, 0), 1)

# fraction and percentage
with pytest.warns(UserWarning) as record:
coord = line.get_coordinate_from_distance(
geometry.Coordinate(0, 0), fraction=0.6, percentage=40
)
assert "Both fraction and percentage provided" in record[0].message.args[0]
# check that fraction is used
assert coord == line.get_coordinate_from_distance(geometry.Coordinate(0, 0), fraction=0.6)

# distance, fraction and percentage
with pytest.warns(UserWarning) as record:
coord = line.get_coordinate_from_distance(geometry.Coordinate(0, 0), 1, 0.6, 40)
assert "Both distance and fraction provided" in record[0].message.args[0]
# check that both warnings are given
assert "Both distance and percentage provided" in record[1].message.args[0]
# check that distance is used
assert coord == line.get_coordinate_from_distance(geometry.Coordinate(0, 0), 1)

# neither distance, fraction or percentage are provided
with pytest.raises(Exception) as e_info:
coord = line.get_coordinate_from_distance(line.start)
assert "provide either a distance, fraction or percentage" in str(e_info)


def test_line_length():
Expand All @@ -584,14 +631,14 @@ def test_line_length():
assert line.length == sqrt(2)


def test_arc_get_coordinate_from_percentage_distance():
def test_arc_get_coordinate_from_fractional_distance():
JackB-Ansys marked this conversation as resolved.
Show resolved Hide resolved
arc = geometry.Arc(
geometry.Coordinate(-1, 0), geometry.Coordinate(1, 0), geometry.Coordinate(0, 0), 1
)

coord = arc.get_coordinate_from_percentage_distance(geometry.Coordinate(-1, 0), 0.5)
assert isclose(coord.x, 0, abs_tol=1e-12)
assert isclose(coord.y, -1, abs_tol=1e-12)
coord_1 = arc.get_coordinate_from_percentage_distance(geometry.Coordinate(-1, 0), 0.5)
assert isclose(coord_1.x, 0, abs_tol=1e-12)
assert isclose(coord_1.y, -1, abs_tol=1e-12)

# test an arc that failed with the old definition of get_coordinate_from_percentage_distance()
arc_2 = geometry.Arc(geometry.Coordinate(62, 20), geometry.Coordinate(56, 33), radius=45)
Expand All @@ -603,32 +650,49 @@ def test_arc_get_coordinate_from_percentage_distance():
assert math.isclose(arc_2.start.y, coord_3.y, abs_tol=1e-12)
# test arc drawn clockwise
arc_4 = geometry.Arc(geometry.Coordinate(56, 33), geometry.Coordinate(62, 20), radius=45)
coord_4 = arc_4.get_coordinate_from_distance(arc_4.end, 1e-13)
coord_4 = arc_4.get_coordinate_from_percentage_distance(arc_4.end, 1e-13)
assert math.isclose(arc_4.end.x, coord_4.x, abs_tol=1e-12)
assert math.isclose(arc_4.end.y, coord_4.y, abs_tol=1e-12)
coord_5 = arc_4.get_coordinate_from_distance(arc_4.start, 1e-13)
coord_5 = arc_4.get_coordinate_from_percentage_distance(arc_4.start, 1e-13)
assert math.isclose(arc_4.start.x, coord_5.x, abs_tol=1e-12)
assert math.isclose(arc_4.start.y, coord_5.y, abs_tol=1e-12)
# test arc with negative radius
arc_6 = geometry.Arc(
geometry.Coordinate(-1, 0), geometry.Coordinate(1, 0), geometry.Coordinate(0, 0), -1
)
coord_6 = arc_6.get_coordinate_from_percentage_distance(Coordinate(-1, 0), 0.5)
assert math.isclose(coord_6.x, 0, abs_tol=1e-12)
assert math.isclose(coord_6.y, 1, abs_tol=1e-12)


def test_arc_get_coordinate_from_distance():
arc = geometry.Arc(
geometry.Coordinate(-1, 0), geometry.Coordinate(1, 0), geometry.Coordinate(0, 0), 1
)

# test using the 'distance' argument
coord = arc.get_coordinate_from_distance(geometry.Coordinate(-1, 0), math.pi / 2)
assert math.isclose(coord.x, 0, abs_tol=1e-12)
assert math.isclose(coord.y, -1, abs_tol=1e-12)

# test an arc that failed with the old definition of get_coordinate_from_distance()
# test for an arc with negative radius using the 'distance' argument
arc_1 = geometry.Arc(
geometry.Coordinate(-1, 0), geometry.Coordinate(1, 0), geometry.Coordinate(0, 0), -1
)
coord_1 = arc_1.get_coordinate_from_distance(geometry.Coordinate(-1, 0), math.pi / 2)
assert math.isclose(coord_1.x, 0, abs_tol=1e-12)
assert math.isclose(coord_1.y, 1, abs_tol=1e-12)

# test an arc that failed with the old definition of get_coordinate_from_distance() using the
# 'distance' argument
arc_2 = geometry.Arc(geometry.Coordinate(62, 20), geometry.Coordinate(56, 33), radius=45)
coord_2 = arc_2.get_coordinate_from_distance(arc_2.end, 1e-15)
assert math.isclose(arc_2.end.x, coord_2.x, abs_tol=1e-12)
assert math.isclose(arc_2.end.y, coord_2.y, abs_tol=1e-12)
coord_3 = arc_2.get_coordinate_from_distance(arc_2.start, 1e-15)
assert math.isclose(arc_2.start.x, coord_3.x, abs_tol=1e-12)
assert math.isclose(arc_2.start.y, coord_3.y, abs_tol=1e-12)
# test arc drawn clockwise
# test arc drawn clockwise using the 'distance' argument
arc_4 = geometry.Arc(geometry.Coordinate(56, 33), geometry.Coordinate(62, 20), radius=45)
coord_4 = arc_4.get_coordinate_from_distance(arc_4.end, 1e-15)
assert math.isclose(arc_4.end.x, coord_4.x, abs_tol=1e-12)
Expand All @@ -640,6 +704,48 @@ def test_arc_get_coordinate_from_distance():
assert math.isclose(60.389142028418, coord_6.x, abs_tol=1e-12)
assert math.isclose(24.730689908764, coord_6.y, abs_tol=1e-12)

# test using the 'fraction' argument
coord_7 = arc.get_coordinate_from_distance(geometry.Coordinate(-1, 0), fraction=0.5)
assert isclose(coord_7.x, 0, abs_tol=1e-12)
assert isclose(coord_7.y, -1, abs_tol=1e-12)

# test using the 'percentage' argument
coord_8 = arc.get_coordinate_from_distance(geometry.Coordinate(-1, 0), percentage=50)
assert isclose(coord_8.x, 0, abs_tol=1e-12)
assert isclose(coord_8.y, -1, abs_tol=1e-12)

# test that warnings are raised when multiple arguments are given
# distance and fraction
with pytest.warns(UserWarning) as record:
coord = arc.get_coordinate_from_distance(arc.start, 1, fraction=0.6)
assert "Both distance and fraction provided" in record[0].message.args[0]
# check that distance is used
assert coord == arc.get_coordinate_from_distance(arc.start, 1)
# distance and percentage
with pytest.warns(UserWarning) as record:
coord = arc.get_coordinate_from_distance(arc.start, 1, percentage=40)
assert "Both distance and percentage provided" in record[0].message.args[0]
# check that distance is used
assert coord == arc.get_coordinate_from_distance(arc.start, 1)
# fraction and percentage
with pytest.warns(UserWarning) as record:
coord = arc.get_coordinate_from_distance(arc.start, fraction=0.6, percentage=40)
assert "Both fraction and percentage provided" in record[0].message.args[0]
# check that fraction is used
assert coord == arc.get_coordinate_from_distance(arc.start, fraction=0.6)
# distance, fraction and percentage
with pytest.warns(UserWarning) as record:
coord = arc.get_coordinate_from_distance(arc.start, 1, 0.6, 40)
assert "Both distance and fraction provided" in record[0].message.args[0]
# check that both warnings are given
assert "Both distance and percentage provided" in record[1].message.args[0]
# check that distance is used
assert coord == arc.get_coordinate_from_distance(arc.start, 1)
# neither distance, fraction or percentage are provided
with pytest.raises(Exception) as e_info:
coord = arc.get_coordinate_from_distance(arc.start)
assert "provide either a distance, fraction or percentage" in str(e_info)


def test_arc_length():
arc = geometry.Arc(
Expand Down
Loading