From d735fa11647ee9b479dad52d235b2d6092f67c2c Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Wed, 23 Aug 2023 12:59:40 +0200 Subject: [PATCH] Methods to access polygon arc data (#3413) * fix * fix * fix * fix * fix * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix * fix * fix * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix * Update pyaedt/edb_core/dotnet/database.py Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> * Update pyaedt/edb_core/edb_data/primitives_data.py Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> * Update pyaedt/edb_core/edb_data/primitives_data.py Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> * Update pyaedt/edb_core/edb_data/primitives_data.py Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> * Update pyaedt/edb_core/dotnet/database.py Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> * fix * fix * fix * Update pyaedt/edb_core/dotnet/database.py Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> * Update pyaedt/edb_core/edb_data/primitives_data.py Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> * fix * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update pyaedt/edb_core/dotnet/database.py Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> * fix * fix * fix * fix * Update pyaedt/edb_core/dotnet/database.py Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --------- Co-authored-by: ring630 <@gmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- _unittest/test_00_EDB.py | 8 +++ pyaedt/edb.py | 4 +- pyaedt/edb_core/components.py | 4 +- pyaedt/edb_core/dotnet/database.py | 34 +++++---- pyaedt/edb_core/dotnet/primitive.py | 9 +-- pyaedt/edb_core/edb_data/primitives_data.py | 76 +++++++++++++++++---- pyaedt/edb_core/layout.py | 2 +- 7 files changed, 103 insertions(+), 34 deletions(-) diff --git a/_unittest/test_00_EDB.py b/_unittest/test_00_EDB.py index acd339d5af3..cef62129ae0 100644 --- a/_unittest/test_00_EDB.py +++ b/_unittest/test_00_EDB.py @@ -978,6 +978,8 @@ def test_084_primitives_area(self): i += 1 assert self.edbapp.modeler.primitives[i].bbox assert self.edbapp.modeler.primitives[i].center + assert self.edbapp.modeler.primitives[i].get_closest_point((0, 0)) + assert self.edbapp.modeler.primitives[i].polygon_data def test_085_short_component(self): assert self.edbapp.components.short_component_pins("U12", width=0.2e-3) @@ -2746,3 +2748,9 @@ def test_143_add_layer_api_with_control_file(self): use_q3d=True, ) assert setup.sweeps + + def test_144_arc_data(self): + assert len(self.edbapp.nets["1.2V_DVDDL"].primitives[0].arcs) > 0 + assert self.edbapp.nets["1.2V_DVDDL"].primitives[0].arcs[0].start + assert self.edbapp.nets["1.2V_DVDDL"].primitives[0].arcs[0].end + assert self.edbapp.nets["1.2V_DVDDL"].primitives[0].arcs[0].height diff --git a/pyaedt/edb.py b/pyaedt/edb.py index 530ec87f17d..f068b51771e 100644 --- a/pyaedt/edb.py +++ b/pyaedt/edb.py @@ -1978,7 +1978,7 @@ def subtract(poly, voids): return poly.Subtract(convert_py_list_to_net_list(poly), convert_py_list_to_net_list(voids)) def clean_prim(prim_1): # pragma: no cover - pdata = prim_1.polygon_data + pdata = prim_1.polygon_data.edb_api int_data = _poly.GetIntersectionType(pdata) if int_data == 2: return @@ -1995,7 +1995,7 @@ def clean_prim(prim_1): # pragma: no cover # points = list(p.Points) list_void = [] if voids: - voids_data = [void.polygon_data for void in voids] + voids_data = [void.polygon_data.edb_api for void in voids] list_prims = subtract(p, voids_data) for prim in list_prims: if not prim.IsNull(): diff --git a/pyaedt/edb_core/components.py b/pyaedt/edb_core/components.py index 7095d1d9425..20afa025359 100644 --- a/pyaedt/edb_core/components.py +++ b/pyaedt/edb_core/components.py @@ -2469,8 +2469,8 @@ def short_component_pins(self, component_name, pins_to_short=None, width=1e-3): elif pars: delta_pins.append(1.5 * pars[0]) w = min(pars[0], w) - elif pad.polygon_data: - bbox = pad.polygon_data.GetBBox() + elif pad.polygon_data.edb_api: # pragma: no cover + bbox = pad.polygon_data.edb_api.GetBBox() lower = [bbox.Item1.X.ToDouble(), bbox.Item1.Y.ToDouble()] upper = [bbox.Item2.X.ToDouble(), bbox.Item2.Y.ToDouble()] pars = [abs(lower[0] - upper[0]), abs(lower[1] - upper[1])] diff --git a/pyaedt/edb_core/dotnet/database.py b/pyaedt/edb_core/dotnet/database.py index b06d63b0f06..f0527335342 100644 --- a/pyaedt/edb_core/dotnet/database.py +++ b/pyaedt/edb_core/dotnet/database.py @@ -53,7 +53,7 @@ def pin_group(self): return self._hierarchy.PinGroup -class PolygonDataDotNet: +class PolygonDataDotNet: # pragma: no cover """Polygon Data.""" def __getattr__(self, key): # pragma: no cover @@ -65,17 +65,23 @@ def __getattr__(self, key): # pragma: no cover except AttributeError: raise AttributeError("Attribute not present") - def __init__(self, pdata): - self.dotnetobj = pdata.Geometry.PolygonData - self.edb_api = pdata + def __init__(self, pedb, api_object=None): + self._pedb = pedb + self.dotnetobj = pedb.edb_api.geometry.api_class.PolygonData + self.edb_api = api_object @property def api_class(self): # pragma: no cover - """Return Ansys.Ansoft.Edb class object.""" + """:class:`Ansys.Ansoft.Edb` class object.""" return self.dotnetobj + @property + def arcs(self): # pragma: no cover + """List of Edb.Geometry.ArcData.""" + return list(self.edb_api.GetArcData()) + def get_bbox_of_boxes(self, points): - """Edb Dotnet Api Database `Edb.Geometry.GetBBoxOfBoxes`. + """Get the EDB .NET API ``Edb.Geometry.GetBBoxOfBoxes`` database. Parameters ---------- @@ -105,7 +111,9 @@ def create_from_bbox(self, points): from pyaedt.generic.clr_module import Tuple if isinstance(points, (tuple, list)): - points = Tuple[self.edb_api.Geometry.PointData, self.edb_api.Geometry.PointData](points[0], points[1]) + points = Tuple[self._pedb.edb_api.Geometry.PointData, self._pedb.edb_api.Geometry.PointData]( + points[0], points[1] + ) return self.dotnetobj.CreateFromBBox(points) def create_from_arcs(self, arcs, flag): @@ -220,8 +228,8 @@ def is_power_ground(self): @property def _api_get_extended_net(self): - """The ExtendedNet this Net belongs to if it belongs to a ExtendedNet. If it doesn't belong to an ExtendedNet, - a null ExtendedNet is returned + """Extended net this net belongs to if it belongs to an extended net. + If it does not belong to an extendednet, a null extended net is returned. """ return self.net_obj.GetExtendedNet() @@ -497,8 +505,8 @@ def __getattr__(self, key): except AttributeError: try: return getattr(self.geometry, key) - except AttributeError: - raise AttributeError("Attribute not present") + except AttributeError: # pragma: no cover + raise AttributeError("Attribute {} not present".format(key)) def __init__(self, app): self._app = app @@ -545,10 +553,10 @@ def polygon_data(self): ------- :class:`pyaedt.edb_core.dotnet.PolygonDataDotNet` """ - return PolygonDataDotNet(self.edb_api) + return PolygonDataDotNet(self._app) def arc_data(self, point1, point2, rotation=None, center=None, height=None): - """Compute Edb ArcData. + """Compute EBD arc data. Parameters ---------- diff --git a/pyaedt/edb_core/dotnet/primitive.py b/pyaedt/edb_core/dotnet/primitive.py index 5e753850f73..63289fa9c62 100644 --- a/pyaedt/edb_core/dotnet/primitive.py +++ b/pyaedt/edb_core/dotnet/primitive.py @@ -1,5 +1,6 @@ """Primitive.""" from pyaedt.edb_core.dotnet.database import NetDotNet +from pyaedt.edb_core.dotnet.database import PolygonDataDotNet from pyaedt.edb_core.general import convert_py_list_to_net_list from pyaedt.modeler.geometry_operators import GeometryOperators @@ -41,8 +42,8 @@ def __getattr__(self, key): obj = self.api try: return getattr(obj, key) - except AttributeError: - raise AttributeError("Attribute not present") + except AttributeError: # pragma: no cover + raise AttributeError("Attribute {} not present".format(key)) def __init__(self, api, prim_object=None): self._app = api @@ -102,8 +103,8 @@ def net(self, value): @property def polygon_data(self): - """:class:`PolygonData `: Outer contour of the Polygon object.""" - return self.prim_obj.GetPolygonData() + """:class:`pyaedt.edb_core.dotnet.database.PolygonDataDotNet`: Outer contour of the Polygon object.""" + return PolygonDataDotNet(self._app, self.prim_obj.GetPolygonData()) @polygon_data.setter def polygon_data(self, poly): diff --git a/pyaedt/edb_core/edb_data/primitives_data.py b/pyaedt/edb_core/edb_data/primitives_data.py index 264c6c0b27e..0d484fbf752 100644 --- a/pyaedt/edb_core/edb_data/primitives_data.py +++ b/pyaedt/edb_core/edb_data/primitives_data.py @@ -325,7 +325,7 @@ def bbox(self): [lower_left x, lower_left y, upper right x, upper right y] """ - bbox = self.polygon_data.GetBBox() + bbox = self.polygon_data.edb_api.GetBBox() return [bbox.Item1.X.ToDouble(), bbox.Item1.Y.ToDouble(), bbox.Item2.X.ToDouble(), bbox.Item2.Y.ToDouble()] @property @@ -400,14 +400,14 @@ def subtract(self, primitives): if isinstance(prim, EDBPrimitives): primi_polys.append(prim.primitive_object.GetPolygonData()) for void in prim.voids: - voids_of_prims.append(void.polygon_data) + voids_of_prims.append(void.polygon_data.edb_api) else: try: primi_polys.append(prim.GetPolygonData()) except: primi_polys.append(prim) for v in self.voids[:]: - primi_polys.append(v.polygon_data) + primi_polys.append(v.polygon_data.edb_api) primi_polys = poly.Unite(convert_py_list_to_net_list(primi_polys)) p_to_sub = poly.Unite(convert_py_list_to_net_list([poly] + voids_of_prims)) list_poly = poly.Subtract(p_to_sub, primi_polys) @@ -596,7 +596,7 @@ def intersection_type(self, primitive): poly = primitive.polygon_data except AttributeError: pass - return int(self.polygon_data.GetIntersectionType(poly)) + return int(self.polygon_data.edb_api.GetIntersectionType(poly.edb_api)) @pyaedt_function_handler() def is_intersecting(self, primitive): @@ -624,10 +624,10 @@ def get_closest_point(self, point): ------- list of float """ - if isinstance(point, list): + if isinstance(point, (list, tuple)): point = self._app.edb_api.geometry.point_data(self._app.edb_value(point[0]), self._app.edb_value(point[1])) - p0 = self.polygon_data.GetClosestPoint(point) + p0 = self.polygon_data.edb_api.GetClosestPoint(point) return [p0.X.ToDouble(), p0.Y.ToDouble()] @pyaedt_function_handler() @@ -657,9 +657,7 @@ def get_closest_arc_midpoint(self, point): @property def arcs(self): """Get the Primitive Arc Data.""" - arcs = [] - if self.polygon_data.IsClosed(): - arcs = [EDBArcs(self, i) for i in list(self.polygon_data.GetArcData())] + arcs = [EDBArcs(self, i) for i in self.polygon_data.arcs] return arcs @property @@ -783,12 +781,12 @@ def clone(self): ``True`` when successful, ``False`` when failed. """ cloned_poly = self._app.edb_api.cell.primitive.polygon.create( - self._app.active_layout, self.layer_name, self.net, self.polygon_data + self._app.active_layout, self.layer_name, self.net, self.polygon_data.edb_api ) if cloned_poly: for void in self.voids: cloned_void = self._app.edb_api.cell.primitive.polygon.create( - self._app.active_layout, self.layer_name, self.net, void.polygon_data + self._app.active_layout, self.layer_name, self.net, void.polygon_data.edb_api ) # cloned_void cloned_poly.prim_obj.AddVoid(cloned_void.prim_obj) @@ -818,7 +816,7 @@ def in_polygon( point_data = self._app.edb_api.geometry.point_data( self._app.edb_value(point_data[0]), self._app.edb_value(point_data[1]) ) - int_val = int(self.polygon_data.PointInPolygon(point_data)) + int_val = int(self.polygon_data.edb_api.PointInPolygon(point_data)) # Intersection type: # 0 = objects do not intersect @@ -894,6 +892,60 @@ def __init__(self, app, arc): self._app = app self.arc_object = arc + @property + def start(self): + """Get the coordinates of the starting point. + + Returns + ------- + list + List containing the X and Y coordinates of the starting point. + + + Examples + -------- + >>> appedb = Edb(fpath, edbversion="2023.2") + >>> start_coordinate = appedb.nets["V1P0_S0"].primitives[0].arcs[0].start + >>> print(start_coordinate) + [x_value, y_value] + """ + point = self.arc_object.Start + return [point.X.ToDouble(), point.Y.ToDouble()] + + @property + def end(self): + """Get the coordinates of the ending point. + + Returns + ------- + list + List containing the X and Y coordinates of the ending point. + + Examples + -------- + >>> appedb = Edb(fpath, edbversion="2023.2") + >>> end_coordinate = appedb.nets["V1P0_S0"].primitives[0].arcs[0].end + """ + point = self.arc_object.End + return [point.X.ToDouble(), point.Y.ToDouble()] + + @property + def height(self): + """Get the height of the arc. + + Returns + ------- + float + Height of the arc. + + + Examples + -------- + >>> appedb = Edb(fpath, edbversion="2023.2") + >>> arc_height = appedb.nets["V1P0_S0"].primitives[0].arcs[0].height + """ + return self.arc_object.Height + @property def center(self): """Arc center. diff --git a/pyaedt/edb_core/layout.py b/pyaedt/edb_core/layout.py index 2f502c12af4..61825a16fde 100644 --- a/pyaedt/edb_core/layout.py +++ b/pyaedt/edb_core/layout.py @@ -1185,7 +1185,7 @@ def defeature_polygon(self, poly, tolerance=0.001): ``True`` when successful, ``False`` when failed. """ poly_data = poly.polygon_data - new_poly = poly_data.Defeature(tolerance) + new_poly = poly_data.edb_api.Defeature(tolerance) poly.polygon_data = new_poly return True