From 45e4726600809574435cc08a9f2319ef59402670 Mon Sep 17 00:00:00 2001 From: maxcapodi78 Date: Thu, 26 Oct 2023 09:41:51 +0200 Subject: [PATCH 1/4] Now PyAEDT Cutout keeps the path as lines after the cutout instead of converting them to polygon data. --- _unittest/test_00_EDB.py | 10 +++++++++- pyaedt/edb.py | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/_unittest/test_00_EDB.py b/_unittest/test_00_EDB.py index c47d1346d6b..a8cd886173a 100644 --- a/_unittest/test_00_EDB.py +++ b/_unittest/test_00_EDB.py @@ -720,7 +720,15 @@ def test_063_create_custom_cutout(self): edbapp.nets.nets assert edbapp.cutout( signal_list=["1V0"], - reference_list=["GND"], + reference_list=[ + "GND", + "LVDS_CH08_N", + "LVDS_CH08_P", + "LVDS_CH10_N", + "LVDS_CH10_P", + "LVDS_CH04_P", + "LVDS_CH04_N", + ], extent_type="Bounding", number_of_threads=4, extent_defeature=0.001, diff --git a/pyaedt/edb.py b/pyaedt/edb.py index 667b2ea3104..6fc0f9f58a3 100644 --- a/pyaedt/edb.py +++ b/pyaedt/edb.py @@ -2026,6 +2026,7 @@ def _create_cutout_multithread( i.net_object.Delete() reference_pinsts = [] reference_prims = [] + reference_paths = [] for i in self.padstacks.instances.values(): net_name = i.net_name id = i.id @@ -2039,7 +2040,10 @@ def _create_cutout_multithread( if net_name not in all_list: i.delete() elif net_name in reference_list and not i.is_void: - reference_prims.append(i) + if i.type == "Path": + reference_paths.append(i) + else: + reference_prims.append(i) self.logger.info_timer("Net clean up") self.logger.reset_timer() @@ -2087,6 +2091,12 @@ def intersect(poly1, poly2): def subtract(poly, voids): return poly.Subtract(convert_py_list_to_net_list(poly), convert_py_list_to_net_list(voids)) + def clip_path(path): + result = path._edb_object.SetClipInfo(_poly, True) + if not result: + self.logger.info("Failed to clip path {}. Clipping as polygon.".format(path.id)) + reference_prims.append(path) + def clean_prim(prim_1): # pragma: no cover pdata = prim_1.polygon_data.edb_api int_data = _poly.GetIntersectionType(pdata) @@ -2132,6 +2142,9 @@ def pins_clean(pinst): self.logger.info_timer("Padstack Instances removal completed") self.logger.reset_timer() + with ThreadPoolExecutor(number_of_threads) as pool: + pool.map(lambda item: clip_path(item), reference_paths) + with ThreadPoolExecutor(number_of_threads) as pool: pool.map(lambda item: clean_prim(item), reference_prims) From 44d17fffdc3deca779c72fbecb1f7a6b6f47e34d Mon Sep 17 00:00:00 2001 From: maxcapodi78 Date: Thu, 26 Oct 2023 13:44:51 +0200 Subject: [PATCH 2/4] added flag in cutout method to keep back compatibility --- _unittest/test_00_EDB.py | 2 ++ pyaedt/edb.py | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/_unittest/test_00_EDB.py b/_unittest/test_00_EDB.py index a8cd886173a..2f99f60c74d 100644 --- a/_unittest/test_00_EDB.py +++ b/_unittest/test_00_EDB.py @@ -733,11 +733,13 @@ def test_063_create_custom_cutout(self): number_of_threads=4, extent_defeature=0.001, preserve_components_with_model=True, + keep_lines_as_path=True, ) assert "A0_N" not in edbapp.nets.nets assert isinstance(edbapp.nets.find_and_fix_disjoint_nets("GND", order_by_area=True), list) assert isinstance(edbapp.nets.find_and_fix_disjoint_nets("GND", keep_only_main_net=True), list) assert isinstance(edbapp.nets.find_and_fix_disjoint_nets("GND", clean_disjoints_less_than=0.005), list) + edbapp.close() @pytest.mark.skipif(sys.version_info < (3, 8), reason="Method works in CPython only") diff --git a/pyaedt/edb.py b/pyaedt/edb.py index 6fc0f9f58a3..e6571e0bb21 100644 --- a/pyaedt/edb.py +++ b/pyaedt/edb.py @@ -1585,6 +1585,7 @@ def cutout( maximum_iterations=10, preserve_components_with_model=False, simple_pad_check=True, + keep_lines_as_path=False, ): """Create a cutout using an approach entirely based on PyAEDT. This method replaces all legacy cutout methods in PyAEDT. @@ -1656,6 +1657,11 @@ def cutout( Whether to use the center of the pad to find the intersection with extent or use the bounding box. Second method is much slower and requires to disable multithread on padstack removal. Default is `True`. + keep_lines_as_path : bool, optional + Whether to keep the lines as Path after they are cutout or convert them to PolygonData. + This feature works only in Electronics Desktop (3D Layout). + If the flag is set to True it can cause issues in SiWave once the Edb is imported. + Default is ``False`` to generate PolygonData of cut lines. Returns ------- @@ -1745,6 +1751,7 @@ def cutout( preserve_components_with_model=preserve_components_with_model, include_partial=include_partial_instances, simple_pad_check=simple_pad_check, + keep_lines_as_path=keep_lines_as_path, ) if self.are_port_reference_terminals_connected(): if output_aedb_path: @@ -1784,6 +1791,7 @@ def cutout( preserve_components_with_model=preserve_components_with_model, include_partial=include_partial_instances, simple_pad_check=simple_pad_check, + keep_lines_as_path=keep_lines_as_path, ) if result and not open_cutout_at_end and self.edbpath != legacy_path: self.save_edb() @@ -1989,6 +1997,7 @@ def _create_cutout_multithread( preserve_components_with_model=False, include_partial=False, simple_pad_check=True, + keep_lines_as_path=False, ): if is_ironpython: # pragma: no cover self.logger.error("Method working only in Cpython") @@ -2040,7 +2049,7 @@ def _create_cutout_multithread( if net_name not in all_list: i.delete() elif net_name in reference_list and not i.is_void: - if i.type == "Path": + if keep_lines_as_path and i.type == "Path": reference_paths.append(i) else: reference_prims.append(i) @@ -2096,6 +2105,14 @@ def clip_path(path): if not result: self.logger.info("Failed to clip path {}. Clipping as polygon.".format(path.id)) reference_prims.append(path) + else: + center_points = list(path._edb_object.GetCenterLine().Points) + new_points = [] + for i in range(len(center_points)): + if _poly.PointInPolygon(center_points[i]): + new_points.append(i) + if not new_points: + prims_to_delete.append(path) def clean_prim(prim_1): # pragma: no cover pdata = prim_1.polygon_data.edb_api @@ -2142,9 +2159,11 @@ def pins_clean(pinst): self.logger.info_timer("Padstack Instances removal completed") self.logger.reset_timer() - with ThreadPoolExecutor(number_of_threads) as pool: - pool.map(lambda item: clip_path(item), reference_paths) + # with ThreadPoolExecutor(number_of_threads) as pool: + # pool.map(lambda item: clip_path(item), reference_paths) + for item in reference_paths: + clip_path(item) with ThreadPoolExecutor(number_of_threads) as pool: pool.map(lambda item: clean_prim(item), reference_prims) @@ -2153,6 +2172,7 @@ def pins_clean(pinst): for prim in prims_to_delete: prim.delete() + self.logger.info_timer("Primitives cleanup completed") self.logger.reset_timer() @@ -2188,6 +2208,7 @@ def create_cutout_multithread( remove_single_pin_components=False, use_pyaedt_extent_computing=False, extent_defeature=0, + keep_lines_as_path=False, ): """Create a cutout using an approach entirely based on pyaedt. It does in sequence: @@ -2228,6 +2249,11 @@ def create_cutout_multithread( extent_defeature : float, optional Defeature the cutout before applying it to produce simpler geometry for mesh (Experimental). It applies only to Conforming bounding box. Default value is ``0`` which disable it. + keep_lines_as_path : bool, optional + Whether to keep the lines as Path after they are cutout or convert them to PolygonData. + This feature works only in Electronics Desktop (3D Layout). + If the flag is set to True it can cause issues in SiWave once the Edb is imported. + Default is ``False`` to generate PolygonData of cut lines. Returns ------- @@ -2267,6 +2293,7 @@ def create_cutout_multithread( remove_single_pin_components=remove_single_pin_components, use_pyaedt_extent_computing=use_pyaedt_extent_computing, extent_defeature=extent_defeature, + keep_lines_as_path=keep_lines_as_path, ) @pyaedt_function_handler() From f2a1dfffa30635a14eff063dffef501a64b9dae3 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Thu, 26 Oct 2023 14:36:36 +0200 Subject: [PATCH 3/4] Update pyaedt/edb.py --- pyaedt/edb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyaedt/edb.py b/pyaedt/edb.py index e6571e0bb21..35af09608aa 100644 --- a/pyaedt/edb.py +++ b/pyaedt/edb.py @@ -1660,7 +1660,7 @@ def cutout( keep_lines_as_path : bool, optional Whether to keep the lines as Path after they are cutout or convert them to PolygonData. This feature works only in Electronics Desktop (3D Layout). - If the flag is set to True it can cause issues in SiWave once the Edb is imported. + If the flag is set to ``True`` it can cause issues in SiWave once the Edb is imported. Default is ``False`` to generate PolygonData of cut lines. Returns From 8eb40042c6e6c5b335be68d21c1bcc30feba154d Mon Sep 17 00:00:00 2001 From: maxcapodi78 Date: Thu, 26 Oct 2023 16:00:32 +0200 Subject: [PATCH 4/4] added flag in cutout method to keep back compatibility --- pyaedt/edb.py | 13 +++++-------- pyaedt/edb_core/dotnet/primitive.py | 8 ++++---- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/pyaedt/edb.py b/pyaedt/edb.py index e6571e0bb21..840e4482b98 100644 --- a/pyaedt/edb.py +++ b/pyaedt/edb.py @@ -2101,18 +2101,15 @@ def subtract(poly, voids): return poly.Subtract(convert_py_list_to_net_list(poly), convert_py_list_to_net_list(voids)) def clip_path(path): + pdata = path.polygon_data.edb_api + int_data = _poly.GetIntersectionType(pdata) + if int_data == 0: + prims_to_delete.append(path) + return result = path._edb_object.SetClipInfo(_poly, True) if not result: self.logger.info("Failed to clip path {}. Clipping as polygon.".format(path.id)) reference_prims.append(path) - else: - center_points = list(path._edb_object.GetCenterLine().Points) - new_points = [] - for i in range(len(center_points)): - if _poly.PointInPolygon(center_points[i]): - new_points.append(i) - if not new_points: - prims_to_delete.append(path) def clean_prim(prim_1): # pragma: no cover pdata = prim_1.polygon_data.edb_api diff --git a/pyaedt/edb_core/dotnet/primitive.py b/pyaedt/edb_core/dotnet/primitive.py index 63289fa9c62..abe6b6ef61f 100644 --- a/pyaedt/edb_core/dotnet/primitive.py +++ b/pyaedt/edb_core/dotnet/primitive.py @@ -746,7 +746,7 @@ def end_cap_style(self): **end_cap2** : End cap style of path end end cap. """ - return self.prim_obj.GetEndCapStyle() + return self._edb_object.GetEndCapStyle() @end_cap_style.setter def end_cap_style(self, end_cap1, end_cap2): @@ -759,7 +759,7 @@ def end_cap_style(self, end_cap1, end_cap2): end_cap2: :class:`PathEndCapType` End cap style of path end end cap. """ - self.prim_obj.SetEndCapStyle(end_cap1, end_cap2) + self._edb_object.SetEndCapStyle(end_cap1, end_cap2) @property def get_clip_info(self): @@ -777,7 +777,7 @@ def get_clip_info(self): **keep_inside** : Indicates whether the part of the path inside the polygon is preserved. """ - return self.prim_obj.GetClipInfo() + return self._edb_object.GetClipInfo() @get_clip_info.setter def get_clip_info(self, clipping_poly, keep_inside=True): @@ -790,7 +790,7 @@ def get_clip_info(self, clipping_poly, keep_inside=True): keep_inside: bool Indicates whether the part of the path inside the polygon should be preserved. """ - self.prim_obj.SetClipInfo( + self._edb_object.SetClipInfo( clipping_poly, keep_inside, )