Skip to content

Commit

Permalink
Merge branch 'main' into retirieve_file_info
Browse files Browse the repository at this point in the history
  • Loading branch information
jgsdavies authored Sep 25, 2024
2 parents 596aada + 55aed7b commit accc463
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 24 deletions.
7 changes: 5 additions & 2 deletions src/ansys/motorcad/core/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ def __init__(self, motorcad_instance=None):
self._child_names = []
self._motorcad_instance = motorcad_instance
self._region_type = RegionType.adaptive

# expect other properties to be implemented here including number duplications, material etc
self.mesh_length = 0

def __eq__(self, other):
"""Override the default equals implementation for Region."""
Expand Down Expand Up @@ -187,6 +186,9 @@ def _from_json(cls, json, motorcad_instance=None):
new_region.parent_name = json["parent_name"]
new_region._child_names = json["child_names"]

if "mesh_length" in json:
new_region.mesh_length = json["mesh_length"]

return new_region

# method to convert python object to send to Motor-CAD
Expand All @@ -209,6 +211,7 @@ def _to_json(self):
"entities": _convert_entities_to_json(self.entities),
"parent_name": self.parent_name,
"region_type": self._region_type.value,
"mesh_length": self.mesh_length,
}

return region_dict
Expand Down
59 changes: 43 additions & 16 deletions src/ansys/motorcad/core/geometry_drawing.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

"""Unit containing region drawing functions."""
from copy import deepcopy
import warnings
from warnings import warn

from ansys.motorcad.core.geometry import Arc, Coordinate, Entity, Line, Region
Expand All @@ -35,6 +36,8 @@
except ImportError:
MATPLOTLIB_AVAILABLE = False

_MAX_RECURSION = 100


class _RegionDrawing:
def __init__(self, ax, stored_coords):
Expand All @@ -46,11 +49,25 @@ def _get_plot_range(self):
x_min, x_max = self.ax.get_xlim()
return x_max - x_min

def _find_coord_no_overlap(self, entity_coord):
def _find_coord_no_overlap(self, entity_coord, tried_coords, modifier):
# adjust depending on text size
# 0.04 good compromise
overlap_tol = 0.04
result = deepcopy(entity_coord)

recursion_depth = len(tried_coords)

if recursion_depth > _MAX_RECURSION:
return None

if entity_coord in tried_coords:
# Already tried this coordinate
# Might be flip-flopping between 2 points
# Add a small amount to how far we move the coord to try and force out of pattern
modifier += 0.01

tried_coords += [entity_coord]

for stored_coord in self.stored_coords:
difference = (entity_coord - stored_coord) / self._get_plot_range()

Expand All @@ -62,25 +79,35 @@ def _find_coord_no_overlap(self, entity_coord):
unit_vector = difference / abs(difference)

if abs(difference) < overlap_tol:
result += unit_vector * overlap_tol * self._get_plot_range() * 1.1
result = self._find_coord_no_overlap(result)
result += unit_vector * overlap_tol * self._get_plot_range() * (1.1 + modifier)
result = self._find_coord_no_overlap(result, tried_coords, modifier)
break
return result

def _plot_text_no_overlap(self, point, text, colour):
new_coord = self._find_coord_no_overlap(point)
self.stored_coords += [new_coord]
self.ax.annotate(
text,
xy=(point.x, point.y),
xytext=(
new_coord.x + 0.04 * self._get_plot_range(),
new_coord.y + 0.04 * self._get_plot_range(),
),
ha="right",
arrowprops=dict(arrowstyle="->", shrinkA=0, color=colour, alpha=0.5),
color=colour,
)
# Reset params for recursive function
tried_coords = []
modifier = 0

new_coord = self._find_coord_no_overlap(point, tried_coords, modifier)

if new_coord is None:
warning_str = "Failed to plot all labels on graph"
warnings.warn(warning_str)
self.ax.set_title("Warning : " + warning_str, color="red")
else:
self.stored_coords += [new_coord]
self.ax.annotate(
text,
xy=(point.x, point.y),
xytext=(
new_coord.x + 0.04 * self._get_plot_range(),
new_coord.y + 0.04 * self._get_plot_range(),
),
ha="right",
arrowprops=dict(arrowstyle="->", shrinkA=0, color=colour, alpha=0.5),
color=colour,
)

def draw_region(self, region, colour):
"""Draw a region."""
Expand Down
15 changes: 14 additions & 1 deletion src/ansys/motorcad/core/methods/adaptive_geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
# SOFTWARE.

"""Methods for adaptive geometry."""
from ansys.motorcad.core.geometry import Region
from warnings import warn

from ansys.motorcad.core.geometry import Region, RegionMagnet
from ansys.motorcad.core.rpc_client_core import is_running_in_internal_scripting


Expand Down Expand Up @@ -118,6 +120,17 @@ def set_region(self, region):
Motor-CAD region object.
"""
self.connection.ensure_version_at_least("2024.0")

if isinstance(region, RegionMagnet):
if (region._br_multiplier != 0.0) or (region._magnet_angle != 0.0):
# User has changed magnet properties that do not exist in older Motor-CAD API
if not self.connection.check_version_at_least("2024.2"):
warn("Setting magnet properties is only available in Motor-CAD 2024R2 or later")

if region.mesh_length != 0:
if not self.connection.check_version_at_least("2025"):
warn("Setting region mesh length is only available in Motor-CAD 2025R1 or later")

raw_region = region._to_json()

method = "SetRegion"
Expand Down
20 changes: 20 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,
)
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 @@ -351,6 +352,7 @@ def test_region_from_json():
"parent_name": "Insulation",
"child_names": ["Duct", "Duct_1"],
"region type": "Adaptive Region",
"mesh_length": 0.035,
}

test_region = geometry.Region()
Expand All @@ -364,6 +366,7 @@ def test_region_from_json():
test_region.entities = []
test_region.parent_name = "Insulation"
test_region._child_names = ["Duct", "Duct_1"]
test_region.mesh_length = 0.035

region = geometry.Region._from_json(raw_region)

Expand All @@ -382,6 +385,7 @@ def test_region_to_json():
"entities": [],
"parent_name": "Insulation",
"region_type": "Adaptive Region",
"mesh_length": 0.035,
}

test_region = geometry.Region()
Expand All @@ -394,6 +398,7 @@ def test_region_to_json():
test_region.duplications = 10
test_region.entities = []
test_region.parent_name = "Insulation"
test_region.mesh_length = 0.035

assert test_region._to_json() == raw_region

Expand Down Expand Up @@ -1906,3 +1911,18 @@ def test_get_set_region_magnet(mc):
assert magnet.br_value == 1.31
assert magnet.br_used == 1.31 * 2
assert magnet.region_type == RegionType.magnet


def test_get_set_region_compatibility(mc, monkeypatch):
monkeypatch.setattr(mc.connection, "program_version", "2024.1")
monkeypatch.setattr(rpc_client_core, "DONT_CHECK_MOTORCAD_VERSION", False)
test_region = RegionMagnet()
test_region.br_multiplier = 2
with pytest.warns(UserWarning):
mc.set_region(test_region)

test_region = Region()
test_region.mesh_length = 0.1

with pytest.warns(UserWarning):
mc.set_region(test_region)
41 changes: 36 additions & 5 deletions tests/test_geometry_drawing.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from matplotlib import pyplot as plt
import pytest

from ansys.motorcad.core.geometry import Coordinate, Line, Region
import ansys.motorcad.core.geometry_drawing
from ansys.motorcad.core.geometry_drawing import draw_objects

# from matplotlib import pyplot as plt
# import pytest
#
# from ansys.motorcad.core.geometry import Arc, Coordinate, Line
# from ansys.motorcad.core.geometry_drawing import draw_objects, draw_objects_debug
# from ansys.motorcad.core.rpc_client_core import DEFAULT_INSTANCE, set_default_instance

drawing_flag = False
Expand All @@ -35,6 +36,36 @@ def set_drawing_flag(*args, **kwargs):
drawing_flag = True


def create_triangle_reg(bottom_left_coord):
region = Region()
region.name = "region " + str(bottom_left_coord)
c1 = bottom_left_coord
c2 = bottom_left_coord + Coordinate(10, 0)
c3 = bottom_left_coord + Coordinate(5, 5)
region.add_entity(Line(c1, c2))
region.add_entity(Line(c2, c3))
region.add_entity(Line(c3, c1))
return region


def test_label_recursion(monkeypatch):
# Stop plt.show() blocking tests
global drawing_flag
drawing_flag = False
monkeypatch.setattr(plt, "show", set_drawing_flag)

# add your geometry template here using PyMotorCAD
r1 = create_triangle_reg(Coordinate(0, 0))
r2 = create_triangle_reg(Coordinate(0, 0.2))
r3 = create_triangle_reg(Coordinate(0, 0.1))

draw_objects([r1, r2, r3])

monkeypatch.setattr(ansys.motorcad.core.geometry_drawing, "_MAX_RECURSION", 1)
with pytest.warns():
draw_objects([r1, r2, r3])


# def test_draw_objects_debug(mc, monkeypatch):
# # Just check it runs for now
# # Stop plt.show() blocking tests
Expand Down

0 comments on commit accc463

Please sign in to comment.