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

Split and repeat on boundary method #352

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a883d9c
Fixed get_coordinate_from_distance() _BaseArc class method so that co…
JackB-Ansys Jul 5, 2024
2c3f618
Added corner rounding class method for Region
JackB-Ansys Jul 5, 2024
26d8f90
Added corner rounding class method for Region
JackB-Ansys Jul 8, 2024
33c9ff5
Updated corner rounding class method for Region
JackB-Ansys Jul 8, 2024
e294440
Updated corner rounding class method for Region
JackB-Ansys Jul 8, 2024
28355e5
Added test for corner rounding class method for Region
JackB-Ansys Jul 8, 2024
0c1f1c3
Added test for updated get_coordinate_from_distance() class method fo…
JackB-Ansys Jul 9, 2024
ca7f2a0
Merge remote-tracking branch 'refs/remotes/origin/main' into corner_r…
JackB-Ansys Jul 9, 2024
0a5432e
Merge remote-tracking branch 'refs/remotes/origin/main' into fix_coor…
JackB-Ansys Jul 9, 2024
8c2f2fa
Fixed missing import for test
JackB-Ansys Jul 9, 2024
716a33d
Added another test for when ref coordinate is start of arc
JackB-Ansys Jul 9, 2024
f8d3e8f
Added another test to cover clockwise drawn arcs
JackB-Ansys Jul 9, 2024
3c6a518
Merge branch 'refs/heads/fix_coord_from_dist' into split_and_repeat_o…
JackB-Ansys Jul 11, 2024
9f2b38d
Merge branch 'refs/heads/corner_rounding' into split_and_repeat_on_bo…
JackB-Ansys Jul 11, 2024
d945bd2
Added class method for arc get_intersects_with_line()
JackB-Ansys Jul 11, 2024
2ff1f6e
Changed method for Boundary Split. Simpler with no mirroring required…
JackB-Ansys Jul 17, 2024
ea62c2e
Merge remote-tracking branch 'refs/remotes/origin/main' into split_an…
JackB-Ansys Jul 31, 2024
5684779
Merge branch 'main' into split_and_repeat_on_boundary_method
jgsdavies Aug 20, 2024
2f1345c
Merge branch 'main' into split_and_repeat_on_boundary_method
jgsdavies Sep 17, 2024
b1c077e
merge from main
jgsdavies Oct 7, 2024
19fa75f
Merge branch 'main' into split_and_repeat_on_boundary_method
jgsdavies Oct 30, 2024
e81edab
Merge branch 'main' into split_and_repeat_on_boundary_method
jgsdavies Nov 12, 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
180 changes: 179 additions & 1 deletion src/ansys/motorcad/core/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from cmath import polar, rect
from copy import deepcopy
from enum import Enum
from math import atan2, cos, degrees, inf, isclose, radians, sin, sqrt
from math import atan2, cos, degrees, inf, isclose, pi, radians, sin, sqrt

GEOM_TOLERANCE = 1e-6

Expand Down Expand Up @@ -404,6 +404,74 @@
united_region = self.motorcad_instance.unite_regions(self, regions)
self.update(united_region)

def boundary_split(self, region=None):
"""Split and repeat a region that overhangs the boundary.

Parameters
----------
region : ansys.motorcad.core.geometry.Region
Motor-CAD region object whose boundary self overhangs
"""
if not region:
try:
region = self.parent
except:
raise Exception(

Check warning on line 419 in src/ansys/motorcad/core/geometry.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/motorcad/core/geometry.py#L415-L419

Added lines #L415 - L419 were not covered by tests
"You must set the parent region of "
+ str(self.name)
+ "or provide a region whose boundary "
+ str(self.name)
+ " overhangs."
)

duplication_number = region.duplications
mc = self.motorcad_instance

Check warning on line 428 in src/ansys/motorcad/core/geometry.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/motorcad/core/geometry.py#L427-L428

Added lines #L427 - L428 were not covered by tests

# get the portion of self that overhangs the region boundary
self_overhang = deepcopy(self)
try:
self_overhang.subtract(region)
except Exception as e:
if "Unable to subtract" in str(e):
raise Exception(

Check warning on line 436 in src/ansys/motorcad/core/geometry.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/motorcad/core/geometry.py#L431-L436

Added lines #L431 - L436 were not covered by tests
str(self.name) + " does not overhang the boundary of " + str(region.name)
)

# get the portion of self that is within the region boundary
self_within = deepcopy(self)
self_within.subtract(self_overhang)

Check warning on line 442 in src/ansys/motorcad/core/geometry.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/motorcad/core/geometry.py#L441-L442

Added lines #L441 - L442 were not covered by tests

# check whether self crosses the upper or lower boundary
# if it crosses the lower boundary, set e = 1 so that we rotate by a positive angle
# if it doesn't cross the lower boundary, it must cross the upper boundary so rotate by
# a negative angle
e = -1
self_name = self.name
self_within.name = self_name
self_number = int("".join(filter(str.isdigit, self_name)))
string_1 = "_" + str(self_number)
string_2 = "_" + str(self_number + 1)

Check warning on line 453 in src/ansys/motorcad/core/geometry.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/motorcad/core/geometry.py#L448-L453

Added lines #L448 - L453 were not covered by tests

if string_1 in self_name:
self_overhang.name = self_name.replace(string_1, string_2)

Check warning on line 456 in src/ansys/motorcad/core/geometry.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/motorcad/core/geometry.py#L455-L456

Added lines #L455 - L456 were not covered by tests
else:
self_overhang.name = self_name + "_boundary_split"

Check warning on line 458 in src/ansys/motorcad/core/geometry.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/motorcad/core/geometry.py#L458

Added line #L458 was not covered by tests

for entity in self.entities:
if entity.start.y < 0 or entity.end.y < 0:
e = 1
if string_1 in self_name:
self_within.name = self_name.replace(string_1, string_2)

Check warning on line 464 in src/ansys/motorcad/core/geometry.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/motorcad/core/geometry.py#L460-L464

Added lines #L460 - L464 were not covered by tests
else:
self_within.name = self_name + "_boundary_split"
self_overhang.name = self_name

Check warning on line 467 in src/ansys/motorcad/core/geometry.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/motorcad/core/geometry.py#L466-L467

Added lines #L466 - L467 were not covered by tests

# rotate the portion of self that overhangs the region boundary to the opposite boundary
self_overhang.rotate(Coordinate(0, 0), e * 360 / duplication_number)

Check warning on line 470 in src/ansys/motorcad/core/geometry.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/motorcad/core/geometry.py#L470

Added line #L470 was not covered by tests

self.update(self_within)
return self_overhang

Check warning on line 473 in src/ansys/motorcad/core/geometry.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/motorcad/core/geometry.py#L472-L473

Added lines #L472 - L473 were not covered by tests

def collides(self, regions):
"""Check whether any of the specified regions collide with self.

Expand Down Expand Up @@ -570,6 +638,88 @@
# Check Arc is still valid
_ = entity.centre

def round_corner(self, corner_coordinate, radius):
"""Round the corner of a region.

Parameters
----------
corner_coordinate : ansys.motorcad.core.geometry.Coordinate
Coordinate of the corner to be rounded.
radius : float
Radius by which the corner will be rounded.
"""
adj_entities = []
entity_indicies = []
coordinates = []
# Get entities at corner
for index in range(len(self.entities)):
i = self.entities[index]
if i.coordinate_on_entity(corner_coordinate):
# coordinates.append(i.get_coordinate_from_distance(corner_coordinate, distance))
adj_entities.append(i)
entity_indicies.append(index)
if not adj_entities:
raise Exception(
"Failed to find point on entity in region. "
"You must specify a corner in this region."
)
if len(adj_entities) == 1:
raise Exception(
"Point found on only one entity in region. "
"You must specify a corner in this region."
)
# if first and last entities, swap the positions
if entity_indicies[0] == 0 and entity_indicies[1] == len(self.entities) - 1:
entity_indicies[0], entity_indicies[1] = entity_indicies[1], entity_indicies[0]
adj_entities[0], adj_entities[1] = adj_entities[1], adj_entities[0]
# Calculate distances for adjacent entities
if type(adj_entities[0]) == Line:
angle_1 = degrees(
atan2(
adj_entities[0].start.y - adj_entities[0].end.y,
adj_entities[0].start.x - adj_entities[0].end.x,
)
)
else: # Arc
point_on_curve = adj_entities[0].get_coordinate_from_distance(corner_coordinate, 0.01)
angle_1 = degrees(

Check warning on line 685 in src/ansys/motorcad/core/geometry.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/motorcad/core/geometry.py#L684-L685

Added lines #L684 - L685 were not covered by tests
atan2(
point_on_curve.y - adj_entities[0].end.y,
point_on_curve.x - adj_entities[0].end.x,
)
)
if type(adj_entities[1]) == Line:
angle_2 = degrees(
atan2(
adj_entities[1].end.y - adj_entities[1].start.y,
adj_entities[1].end.x - adj_entities[1].start.x,
)
)
else: # Arc
point_on_curve = adj_entities[1].get_coordinate_from_distance(corner_coordinate, 0.01)
angle_2 = degrees(

Check warning on line 700 in src/ansys/motorcad/core/geometry.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/motorcad/core/geometry.py#L699-L700

Added lines #L699 - L700 were not covered by tests
atan2(
point_on_curve.y - adj_entities[1].start.y,
point_on_curve.x - adj_entities[1].start.x,
)
)

corner_angle = abs(angle_1 - angle_2)
arc_angle = 90 + (90 - corner_angle)
half_chord = radius * sin(radians(arc_angle) / 2)
distance = abs(half_chord / (sin(radians(corner_angle) / 2)))

for index in range(len(adj_entities)):
j = adj_entities[index]
coordinates.append(j.get_coordinate_from_distance(corner_coordinate, distance))
if j.start == corner_coordinate:
j.start = coordinates[index]
elif j.end == corner_coordinate:
j.end = coordinates[index]

corner_arc = Arc(coordinates[0], coordinates[1], radius=radius)
self.insert_entity(entity_indicies[0] + 1, corner_arc)

def find_entity_from_coordinates(self, coordinate_1, coordinate_2):
"""Search through region to find an entity with start and end coordinates.

Expand Down Expand Up @@ -1210,6 +1360,34 @@
) # sign of the radius accounts for clockwise/anticlockwise arcs
return self.centre + Coordinate(*rt_to_xy(abs(self.radius), degrees(angle)))

def get_intersects_with_line(self, line, tolerance=0.0001):
"""Get if a line intersects with this arc.

Parameters
----------
line : ansys.motorcad.core.geometry.Line
Check if this Line entity intersects with self

Returns
-------
bool
"""
start = self.start
end = self.end
points = 1 / tolerance # 10000
length = 2 * pi * self.radius * (abs(self.total_angle) / 360)
line_crossed = False
for i in range(int(points)):
point_1 = self.get_coordinate_from_distance(start, (i * (length / points)))
point_2 = self.get_coordinate_from_distance(point_1, length / points)
tangent = Line(point_1, point_2)
intersection = tangent.get_line_intersection(line)
if intersection == None:
pass
elif tangent.coordinate_on_entity(intersection):
line_crossed = True
return line_crossed

Check warning on line 1389 in src/ansys/motorcad/core/geometry.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/motorcad/core/geometry.py#L1375-L1389

Added lines #L1375 - L1389 were not covered by tests

def mirror(self, mirror_line):
"""Mirror arc about a line.

Expand Down
32 changes: 32 additions & 0 deletions tests/test_geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
_orientation_of_three_points,
rt_to_xy,
)
from ansys.motorcad.core.geometry_shapes import eq_triangle_h
import ansys.motorcad.core.rpc_client_core as rpc_client_core
from ansys.motorcad.core.rpc_client_core import DEFAULT_INSTANCE, set_default_instance

Expand Down Expand Up @@ -1232,6 +1233,37 @@ def test_edit_point():
assert region.entities[2].start == ref_region.entities[2].start + translate


def test_round_corner():
radius = 0.5
triangle_1 = eq_triangle_h(5, 15, 45)
triangle_2 = eq_triangle_h(5, 15, 45)
for index in reversed(range(3)):
triangle_1.round_corner(triangle_1.entities[index].end, radius)
# draw_objects([triangle_1, triangle_2])

assert triangle_1.is_closed()
for i in range(3):
# check that the entities making up the rounded triangle are of the expected types
assert type(triangle_1.entities[2 * i]) == Line
assert type(triangle_1.entities[2 * i + 1]) == Arc
# check that the midpoints of the shortened lines are the same as the original lines
assert triangle_1.entities[2 * i].midpoint == triangle_2.entities[i].midpoint

# check that the original corner coordinates are not on any of the rounded triangle's entities
corners = []
for i in range(3):
corners.append(triangle_2.entities[i].end)
for entity in triangle_1.entities:
for i in range(3):
assert not entity.coordinate_on_entity(corners[i])

# check exception is raised when a point that is not a corner is specified
with pytest.raises(Exception):
triangle_1.round_corner(corners[0], radius)
with pytest.raises(Exception):
triangle_1.round_corner(triangle_1.entities[0].midpoint, radius)


def test_subtract_regions(mc):
"""Test subtract rectangle from square to create cut out in square as shown below"""
# Before After
Expand Down
Loading