pyedb 0.56.0__py3-none-any.whl → 0.58.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pyedb might be problematic. Click here for more details.

Files changed (110) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/configuration/cfg_data.py +3 -0
  3. pyedb/configuration/cfg_pin_groups.py +2 -0
  4. pyedb/configuration/cfg_terminals.py +232 -0
  5. pyedb/configuration/configuration.py +146 -3
  6. pyedb/dotnet/clr_module.py +1 -2
  7. pyedb/dotnet/database/Variables.py +30 -22
  8. pyedb/dotnet/database/cell/hierarchy/component.py +2 -8
  9. pyedb/dotnet/database/cell/layout.py +5 -1
  10. pyedb/dotnet/database/cell/primitive/primitive.py +2 -2
  11. pyedb/dotnet/database/cell/terminal/bundle_terminal.py +12 -0
  12. pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
  13. pyedb/dotnet/database/cell/terminal/terminal.py +38 -0
  14. pyedb/dotnet/database/components.py +15 -19
  15. pyedb/dotnet/database/dotnet/database.py +1 -0
  16. pyedb/dotnet/database/edb_data/control_file.py +19 -8
  17. pyedb/dotnet/database/edb_data/nets_data.py +3 -3
  18. pyedb/dotnet/database/edb_data/padstacks_data.py +39 -14
  19. pyedb/dotnet/database/edb_data/ports.py +0 -25
  20. pyedb/dotnet/database/edb_data/primitives_data.py +3 -3
  21. pyedb/dotnet/database/edb_data/raptor_x_simulation_setup_data.py +18 -19
  22. pyedb/dotnet/database/edb_data/simulation_configuration.py +3 -3
  23. pyedb/dotnet/database/edb_data/sources.py +21 -2
  24. pyedb/dotnet/database/general.py +1 -6
  25. pyedb/dotnet/database/hfss.py +9 -8
  26. pyedb/dotnet/database/layout_validation.py +14 -3
  27. pyedb/dotnet/database/materials.py +1 -3
  28. pyedb/dotnet/database/modeler.py +7 -3
  29. pyedb/dotnet/database/nets.py +27 -19
  30. pyedb/dotnet/database/padstack.py +4 -2
  31. pyedb/dotnet/database/sim_setup_data/io/siwave.py +54 -1
  32. pyedb/dotnet/database/siwave.py +4 -3
  33. pyedb/dotnet/database/stackup.py +55 -58
  34. pyedb/dotnet/database/utilities/heatsink.py +0 -1
  35. pyedb/dotnet/database/utilities/hfss_simulation_setup.py +81 -0
  36. pyedb/dotnet/database/utilities/simulation_setup.py +7 -5
  37. pyedb/dotnet/database/utilities/siwave_cpa_simulation_setup.py +1 -0
  38. pyedb/dotnet/database/utilities/siwave_simulation_setup.py +264 -13
  39. pyedb/dotnet/edb.py +65 -47
  40. pyedb/exceptions.py +1 -2
  41. pyedb/extensions/create_cell_array.py +67 -49
  42. pyedb/generic/data_handlers.py +13 -23
  43. pyedb/generic/design_types.py +9 -35
  44. pyedb/generic/filesystem.py +4 -2
  45. pyedb/generic/general_methods.py +28 -41
  46. pyedb/generic/plot.py +8 -23
  47. pyedb/generic/process.py +78 -10
  48. pyedb/grpc/database/_typing.py +0 -0
  49. pyedb/grpc/database/components.py +14 -13
  50. pyedb/grpc/database/control_file.py +27 -40
  51. pyedb/grpc/database/definition/materials.py +1 -1
  52. pyedb/grpc/database/definition/package_def.py +6 -3
  53. pyedb/grpc/database/definition/padstack_def.py +14 -12
  54. pyedb/grpc/database/hfss.py +1 -4
  55. pyedb/grpc/database/hierarchy/component.py +5 -13
  56. pyedb/grpc/database/hierarchy/pingroup.py +16 -3
  57. pyedb/grpc/database/layers/layer.py +1 -2
  58. pyedb/grpc/database/layers/stackup_layer.py +42 -19
  59. pyedb/grpc/database/layout/layout.py +43 -27
  60. pyedb/grpc/database/layout/voltage_regulator.py +6 -1
  61. pyedb/grpc/database/layout_validation.py +5 -2
  62. pyedb/grpc/database/modeler.py +254 -252
  63. pyedb/grpc/database/net/differential_pair.py +9 -2
  64. pyedb/grpc/database/net/extended_net.py +24 -9
  65. pyedb/grpc/database/net/net.py +14 -5
  66. pyedb/grpc/database/net/net_class.py +24 -7
  67. pyedb/grpc/database/nets.py +11 -43
  68. pyedb/grpc/database/padstacks.py +67 -119
  69. pyedb/grpc/database/primitive/bondwire.py +3 -67
  70. pyedb/grpc/database/primitive/circle.py +42 -3
  71. pyedb/grpc/database/primitive/padstack_instance.py +58 -31
  72. pyedb/grpc/database/primitive/path.py +160 -11
  73. pyedb/grpc/database/primitive/polygon.py +73 -7
  74. pyedb/grpc/database/primitive/primitive.py +2 -2
  75. pyedb/grpc/database/primitive/rectangle.py +105 -4
  76. pyedb/grpc/database/simulation_setup/hfss_general_settings.py +0 -2
  77. pyedb/grpc/database/simulation_setup/hfss_settings_options.py +0 -4
  78. pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +79 -0
  79. pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +1 -0
  80. pyedb/grpc/database/simulation_setup/sweep_data.py +1 -3
  81. pyedb/grpc/database/siwave.py +6 -13
  82. pyedb/grpc/database/source_excitations.py +46 -63
  83. pyedb/grpc/database/stackup.py +55 -60
  84. pyedb/grpc/database/terminal/bundle_terminal.py +10 -3
  85. pyedb/grpc/database/terminal/padstack_instance_terminal.py +9 -11
  86. pyedb/grpc/database/terminal/pingroup_terminal.py +8 -1
  87. pyedb/grpc/database/terminal/point_terminal.py +30 -0
  88. pyedb/grpc/database/terminal/terminal.py +35 -10
  89. pyedb/grpc/database/utility/heat_sink.py +0 -1
  90. pyedb/grpc/database/utility/hfss_extent_info.py +2 -2
  91. pyedb/grpc/database/utility/xml_control_file.py +19 -8
  92. pyedb/grpc/edb.py +63 -32
  93. pyedb/grpc/edb_init.py +1 -0
  94. pyedb/ipc2581/ecad/cad_data/layer_feature.py +6 -2
  95. pyedb/ipc2581/ecad/cad_data/step.py +1 -1
  96. pyedb/ipc2581/ipc2581.py +8 -7
  97. pyedb/libraries/common.py +3 -4
  98. pyedb/libraries/rf_libraries/base_functions.py +7 -16
  99. pyedb/libraries/rf_libraries/planar_antennas.py +3 -21
  100. pyedb/misc/aedtlib_personalib_install.py +2 -2
  101. pyedb/misc/downloads.py +19 -3
  102. pyedb/misc/misc.py +5 -2
  103. pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +3 -2
  104. pyedb/misc/siw_feature_config/xtalk_scan/scan_config.py +0 -1
  105. pyedb/misc/utilities.py +0 -1
  106. pyedb/modeler/geometry_operators.py +3 -2
  107. {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/METADATA +6 -7
  108. {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/RECORD +110 -108
  109. {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/WHEEL +0 -0
  110. {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/licenses/LICENSE +0 -0
@@ -21,10 +21,10 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  from ansys.edb.core.primitive.bondwire import (
24
+ Bondwire as GrpcBondWire,
24
25
  BondwireCrossSectionType as GrpcBondwireCrossSectionType,
26
+ BondwireType as GrpcBondWireType,
25
27
  )
26
- from ansys.edb.core.primitive.bondwire import Bondwire as GrpcBondWire
27
- from ansys.edb.core.primitive.bondwire import BondwireType as GrpcBondWireType
28
28
 
29
29
  from pyedb.grpc.database.utility.value import Value
30
30
 
@@ -36,6 +36,7 @@ class Bondwire(GrpcBondWire):
36
36
  super().__init__(edb_object.msg)
37
37
  self._pedb = _pedb
38
38
  self._edb_object = edb_object
39
+ # TODO add create and delete methods to keep cache in sync
39
40
 
40
41
  @property
41
42
  def material(self):
@@ -53,25 +54,6 @@ class Bondwire(GrpcBondWire):
53
54
  def material(self, value):
54
55
  self.set_material(value)
55
56
 
56
- # def __create(self, **kwargs):
57
- # return Bondwire.create(
58
- # self._pedb.layout,
59
- # kwargs.get("net"),
60
- # self._bondwire_type[kwargs.get("bondwire_type")],
61
- # kwargs.get("definition_name"),
62
- # kwargs.get("placement_layer"),
63
- # kwargs.get("width"),
64
- # kwargs.get("material"),
65
- # kwargs.get("start_context"),
66
- # kwargs.get("start_layer_name"),
67
- # kwargs.get("start_x"),
68
- # kwargs.get("start_y"),
69
- # kwargs.get("end_context"),
70
- # kwargs.get("end_layer_name"),
71
- # kwargs.get("end_x"),
72
- # kwargs.get("end_y"),
73
- # )
74
-
75
57
  @property
76
58
  def type(self):
77
59
  """str: Bondwire-type of a bondwire object. Supported values for setter: `"apd"`, `"jedec4"`, `"jedec5"`,
@@ -120,28 +102,6 @@ class Bondwire(GrpcBondWire):
120
102
  def cross_section_height(self, cross_section_height):
121
103
  super(Bondwire, self.__class__).cross_section_height.__set__(self, Value(cross_section_height))
122
104
 
123
- # @property
124
- # def trajectory(self):
125
- # """Get trajectory parameters of a bondwire object.
126
- #
127
- # Returns
128
- # -------
129
- # tuple[float, float, float, float]
130
- #
131
- # Returns a tuple of the following format:
132
- # **(x1, y1, x2, y2)**
133
- # **x1** : X value of the start point.
134
- # **y1** : Y value of the start point.
135
- # **x1** : X value of the end point.
136
- # **y1** : Y value of the end point.
137
- # """
138
- # return [Value(i) for i in self.get_traj()]
139
- #
140
- # @trajectory.setter
141
- # def trajectory(self, value):
142
- # values = [Value(i) for i in value]
143
- # self.set_traj(values[0], values[1], values[2], values[3])
144
-
145
105
  @property
146
106
  def width(self):
147
107
  """:class:`Value <ansys.edb.utility.Value>`: Width of a bondwire object.
@@ -156,27 +116,3 @@ class Bondwire(GrpcBondWire):
156
116
  @width.setter
157
117
  def width(self, width):
158
118
  super(Bondwire, self.__class__).width.__set__(self, Value(width))
159
-
160
- # @property
161
- # def start_elevation(self):
162
- # layer = self.get_start_elevation(self._pedb.active_cell)
163
- # return layer.name
164
- #
165
- # @start_elevation.setter
166
- # def start_elevation(self, layer):
167
- # if not layer in self._pedb.stackup.layers:
168
- # return
169
- # layer = self._pedb.stackup.layers[layer]
170
- # self.set_start_elevation(self._pedb.active_cell, layer)
171
- #
172
- # @property
173
- # def end_elevation(self):
174
- # layer = self.get_end_elevation(self._pedb.active_cell)
175
- # return layer.name
176
- #
177
- # @end_elevation.setter
178
- # def end_elevation(self, layer):
179
- # if not layer in self._pedb.stackup.layers:
180
- # return
181
- # layer = self._pedb.stackup.layers[layer]
182
- # self.set_end_elevation(self._pedb.active_cell, layer)
@@ -21,18 +21,57 @@
21
21
  # SOFTWARE.
22
22
 
23
23
 
24
+ from typing import Union
25
+
24
26
  from ansys.edb.core.primitive.circle import Circle as GrpcCircle
25
27
 
28
+ from pyedb.grpc.database.layers.layer import Layer
29
+ from pyedb.grpc.database.net.net import Net
26
30
  from pyedb.grpc.database.primitive.primitive import Primitive
27
31
  from pyedb.grpc.database.utility.value import Value
28
32
 
29
33
 
30
34
  class Circle(GrpcCircle, Primitive):
31
- def __init__(self, pedb, edb_object):
32
- GrpcCircle.__init__(self, edb_object.msg)
33
- Primitive.__init__(self, pedb, edb_object)
35
+ def __init__(self, pedb, edb_object=None):
36
+ if edb_object:
37
+ GrpcCircle.__init__(self, edb_object.msg)
38
+ Primitive.__init__(self, pedb, edb_object)
34
39
  self._pedb = pedb
35
40
 
41
+ def create(
42
+ self,
43
+ layout=None,
44
+ layer: Union[str, Layer] = None,
45
+ net: Union[str, Net, None] = None,
46
+ center_x: float = None,
47
+ center_y: float = None,
48
+ radius: float = 0.0,
49
+ ):
50
+ if not layout:
51
+ layout = self._pedb.active_layout
52
+ if not layer:
53
+ raise ValueError("Layer must be provided to create a circle.")
54
+ if center_x is None or center_y is None:
55
+ raise ValueError("Center x and y values must be provided to create a circle.")
56
+ edb_object = GrpcCircle.create(
57
+ layout=layout,
58
+ layer=layer,
59
+ net=net,
60
+ center_x=Value(center_x),
61
+ center_y=Value(center_y),
62
+ radius=Value(radius),
63
+ )
64
+ new_circle = Circle(self._pedb, edb_object)
65
+ GrpcCircle.__init__(self, edb_object.msg)
66
+ Primitive.__init__(self, self._pedb, edb_object)
67
+ self._pedb.modeler._add_primitive(new_circle)
68
+ return new_circle
69
+
70
+ def delete(self):
71
+ """Delete the circle from the layout."""
72
+ self._pedb.modeler._remove_primitive(self)
73
+ super().delete()
74
+
36
75
  def get_parameters(self) -> tuple[float, float, float]:
37
76
  """Returns parameters.
38
77
 
@@ -28,8 +28,7 @@ from ansys.edb.core.database import ProductIdType as GrpcProductIdType
28
28
  from ansys.edb.core.geometry.point_data import PointData as GrpcPointData
29
29
  from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
30
30
  from ansys.edb.core.hierarchy.pin_group import PinGroup as GrpcPinGroup
31
- from ansys.edb.core.hierarchy.structure3d import MeshClosure as GrpcMeshClosure
32
- from ansys.edb.core.hierarchy.structure3d import Structure3D as GrpcStructure3D
31
+ from ansys.edb.core.hierarchy.structure3d import MeshClosure as GrpcMeshClosure, Structure3D as GrpcStructure3D
33
32
  from ansys.edb.core.primitive.padstack_instance import (
34
33
  PadstackInstance as GrpcPadstackInstance,
35
34
  )
@@ -123,6 +122,47 @@ class PadstackInstance(GrpcPadstackInstance):
123
122
  term = PadstackInstanceTerminal(self._pedb, term)
124
123
  return term if not term.is_null else None
125
124
 
125
+ @property
126
+ def side_number(self):
127
+ """Return the number of sides meshed of the padstack instance.
128
+ Returns
129
+ -------
130
+ int
131
+ Number of sides meshed of the padstack instance.
132
+ """
133
+ side_value = self.get_product_property(GrpcProductIdType.HFSS_3D_LAYOUT, 21)
134
+ if side_value:
135
+ return int(re.search(r"(?m)^\s*sid=(\d+)", side_value).group(1))
136
+ return 0
137
+
138
+ @side_number.setter
139
+ def side_number(self, value):
140
+ """Set the number of sides meshed of the padstack instance.
141
+
142
+ Parameters
143
+ ----------
144
+ value : int
145
+ Number of sides to mesh the padstack instance.
146
+
147
+ Returns
148
+ -------
149
+ bool
150
+ True if successful, False otherwise.
151
+ """
152
+ if isinstance(value, int) and 3 <= value <= 64:
153
+ prop_string = f"$begin ''\n\tsid={value}\n\tmat='copper'\n\tvs='Wirebond'\n$end ''\n"
154
+ self.set_product_property(GrpcProductIdType.HFSS_3D_LAYOUT, 21, prop_string)
155
+ else:
156
+ raise ValueError("Number of sides must be an integer between 3 and 64")
157
+
158
+ def delete(self):
159
+ """Delete the padstack instance."""
160
+ try:
161
+ self._pedb.padstacks._instances.pop(self.edb_uid, None)
162
+ except Exception:
163
+ self._pedb.padstacks.clear_instances_cache()
164
+ super().delete()
165
+
126
166
  def set_backdrill_top(self, drill_depth, drill_diameter, offset=0.0):
127
167
  """Set backdrill from top.
128
168
 
@@ -144,7 +184,7 @@ class PadstackInstance(GrpcPadstackInstance):
144
184
  True if success, False otherwise.
145
185
  """
146
186
  warnings.warn(
147
- "`set_backdrill_top` is deprecated. Use `set_back_drill_by_depth` or " "`set_back_drill_by_layer` instead.",
187
+ "`set_backdrill_top` is deprecated. Use `set_back_drill_by_depth` or `set_back_drill_by_layer` instead.",
148
188
  DeprecationWarning,
149
189
  )
150
190
  if isinstance(drill_depth, str):
@@ -179,8 +219,7 @@ class PadstackInstance(GrpcPadstackInstance):
179
219
  True if success, False otherwise.
180
220
  """
181
221
  warnings.warn(
182
- "`set_backdrill_bottom` is deprecated. Use `set_back_drill_by_depth` or "
183
- "`set_back_drill_by_layer` instead.",
222
+ "`set_backdrill_bottom` is deprecated. Use `set_back_drill_by_depth` or `set_back_drill_by_layer` instead.",
184
223
  DeprecationWarning,
185
224
  )
186
225
  if isinstance(drill_depth, str):
@@ -761,18 +800,6 @@ class PadstackInstance(GrpcPadstackInstance):
761
800
  def aedt_name(self, value):
762
801
  self.set_product_property(GrpcProductIdType.DESIGNER, 11, value)
763
802
 
764
- @property
765
- def side_number(self) -> int:
766
- if not self._side_number:
767
- prop_string = "$begin ''\n\tsid=3\n\tmat='copper'\n\tvs='Wirebond'\n$end ''\n"
768
- self.set_product_property(GrpcProductIdType.HFSS_3D_LAYOUT, 21, prop_string)
769
- self._side_number = self.get_product_property(GrpcProductIdType.HFSS_3D_LAYOUT, 21)
770
- return self._side_number
771
-
772
- @side_number.setter
773
- def side_number(self, value):
774
- self._side_number = self.set_product_property(GrpcProductIdType.HFSS_3D_LAYOUT, 21, value)
775
-
776
803
  def split(self) -> list:
777
804
  """Split padstack instance into multiple instances. The new instances only connect adjacent layers."""
778
805
  pdef_name = self.padstack_definition
@@ -826,21 +853,21 @@ class PadstackInstance(GrpcPadstackInstance):
826
853
  rad_l = rad_large
827
854
 
828
855
  layout = self._pedb.active_layout
829
- cloned_circle = Circle.create(
830
- layout,
831
- self.start_layer,
832
- self.net,
833
- Value(self.position[0]),
834
- Value(self.position[1]),
835
- Value(rad_u),
856
+ cloned_circle = Circle(self._pedb).create(
857
+ layout=layout,
858
+ layer=self.start_layer,
859
+ net=self.net,
860
+ center_x=Value(self.position[0]),
861
+ center_y=Value(self.position[1]),
862
+ radius=Value(rad_u),
836
863
  )
837
- cloned_circle2 = Circle.create(
838
- layout,
839
- self.stop_layer,
840
- self.net,
841
- Value(self.position[0]),
842
- Value(self.position[1]),
843
- Value(rad_l),
864
+ cloned_circle2 = Circle(self._pedb).create(
865
+ layout=layout,
866
+ layer=self.stop_layer,
867
+ net=self.net,
868
+ center_x=Value(self.position[0]),
869
+ center_y=Value(self.position[1]),
870
+ radius=Value(rad_l),
844
871
  )
845
872
 
846
873
  s3d = GrpcStructure3D.create(layout, generate_unique_name("via3d_" + self.aedt_name.replace("via_", ""), n=3))
@@ -20,19 +20,25 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
  import math
23
+ from typing import Union
23
24
 
24
25
  from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
25
- from ansys.edb.core.primitive.path import Path as GrpcPath
26
- from ansys.edb.core.primitive.path import PathCornerType as GrpcPatCornerType
26
+ from ansys.edb.core.primitive.path import (
27
+ Path as GrpcPath,
28
+ PathCornerType as GrpcPathCornerType,
29
+ PathEndCapType as GrpcPathEndCapType,
30
+ )
27
31
 
32
+ from pyedb.grpc.database.layers.layer import Layer
28
33
  from pyedb.grpc.database.primitive.primitive import Primitive
29
34
  from pyedb.grpc.database.utility.value import Value
30
35
 
31
36
 
32
37
  class Path(GrpcPath, Primitive):
33
- def __init__(self, pedb, edb_object):
34
- GrpcPath.__init__(self, edb_object.msg)
35
- Primitive.__init__(self, pedb, edb_object)
38
+ def __init__(self, pedb, edb_object=None):
39
+ if edb_object:
40
+ GrpcPath.__init__(self, edb_object.msg)
41
+ Primitive.__init__(self, pedb, edb_object)
36
42
  self._edb_object = edb_object
37
43
  self._pedb = pedb
38
44
 
@@ -72,6 +78,105 @@ class Path(GrpcPath, Primitive):
72
78
  path_length += self.width / 2
73
79
  return round(path_length, 9)
74
80
 
81
+ def create(
82
+ self,
83
+ layout=None,
84
+ layer: Union[str, Layer] = None,
85
+ net: Union[str, "Net"] = None,
86
+ width: float = 100e-6,
87
+ end_cap1: Union[str, GrpcPathEndCapType] = "flat",
88
+ end_cap2: Union[str, GrpcPathEndCapType] = "flat",
89
+ corner_style: Union[str, GrpcPathCornerType] = "sharp",
90
+ points: Union[list, GrpcPolygonData] = None,
91
+ ):
92
+ """
93
+ Create a path in the specified layout, layer, and net with the given parameters.
94
+
95
+ Parameters
96
+ ----------
97
+ layout : Layout, optional
98
+ The layout in which the path will be created. If not provided, the active layout of the `pedb` instance
99
+ will be used.
100
+ layer : Union[str, Layer], optional
101
+ The layer in which the path will be created. This parameter is required and must be specified.
102
+ net : Union[str, Net], optional
103
+ The net to which the path will belong. If not provided, the path will not be associated with a net.
104
+ width : float, optional
105
+ The width of the path in meters. The default value is `100e-6`.
106
+ end_cap1 : str, optional
107
+ The style of the first end cap. Options are `"flat"`, `"round"`, `"extended"`, and `"clipped"`.
108
+ The default value is `"flat"`.
109
+ end_cap2 : str, optional
110
+ The style of the second end cap. Options are `"flat"`, `"round"`, `"extended"`, and `"clipped"`.
111
+ The default value is `"flat"`.
112
+ corner_style : str, optional
113
+ The style of the path corners. Options are `"sharp"`, `"round"`, and `"mitter"`.
114
+ The default value is `"sharp"`.
115
+ points : Union[list, GrpcPolygonData], optional
116
+ The points defining the path. This can be a list of points or an instance of `GrpcPolygonData`.
117
+ This parameter is required and must be specified.
118
+
119
+ Returns
120
+ -------
121
+ :class:`Path <pyedb.grpc.database.primitive.path.Path>`
122
+ The created path object.
123
+
124
+ Raises
125
+ ------
126
+ ValueError
127
+ If the `points` parameter is not provided.
128
+
129
+ Notes
130
+ -----
131
+ - If `points` is provided as a list, it will be converted to a `GrpcPolygonData` object.
132
+ - The created path is added to the modeler primitives of the `pedb` instance.
133
+
134
+ """
135
+ if layout is None:
136
+ layout = self._pedb.active_layout
137
+ end_cap_mapping = {
138
+ "flat": GrpcPathEndCapType.FLAT,
139
+ "round": GrpcPathEndCapType.ROUND,
140
+ "extended": GrpcPathEndCapType.EXTENDED,
141
+ "clipped": GrpcPathEndCapType.CLIPPED,
142
+ }
143
+ corner_style_mapping = {
144
+ "round": GrpcPathCornerType.ROUND,
145
+ "mitter": GrpcPathCornerType.MITER,
146
+ "sharp": GrpcPathCornerType.SHARP,
147
+ }
148
+ if isinstance(end_cap1, str):
149
+ end_cap1 = end_cap_mapping[end_cap1.lower()]
150
+ if isinstance(end_cap2, str):
151
+ end_cap2 = end_cap_mapping[end_cap2.lower()]
152
+ if isinstance(corner_style, str):
153
+ corner_style = corner_style_mapping[corner_style.lower()]
154
+ if not points:
155
+ raise ValueError("Points are required to create a path.")
156
+ if isinstance(points, list):
157
+ points = GrpcPolygonData(points=points)
158
+ self._edb_object = super().create(
159
+ layout=layout,
160
+ layer=layer,
161
+ net=net,
162
+ width=Value(width),
163
+ end_cap1=end_cap1,
164
+ end_cap2=end_cap2,
165
+ corner_style=corner_style,
166
+ points=points,
167
+ )
168
+
169
+ # keeping cache synced
170
+ new_path = Path(self._pedb, self._edb_object)
171
+ self._pedb.modeler._add_primitive(new_path)
172
+ return new_path
173
+
174
+ def delete(self):
175
+ """Delete the path object."""
176
+ # keeping cache synced
177
+ self._pedb.modeler._remove_primitive(self)
178
+ super().delete()
179
+
75
180
  def add_point(self, x, y, incremental=True) -> bool:
76
181
  """Add a point at the end of the path.
77
182
 
@@ -110,9 +215,9 @@ class Path(GrpcPath, Primitive):
110
215
  ``True`` when successful, ``False`` when failed.
111
216
  """
112
217
  mapping = {
113
- "round": GrpcPatCornerType.ROUND,
114
- "mitter": GrpcPatCornerType.MITER,
115
- "sharp": GrpcPatCornerType.SHARP,
218
+ "round": GrpcPathCornerType.ROUND,
219
+ "mitter": GrpcPathCornerType.MITER,
220
+ "sharp": GrpcPathCornerType.SHARP,
116
221
  }
117
222
 
118
223
  cloned_path = GrpcPath.create(
@@ -339,8 +444,52 @@ class Path(GrpcPath, Primitive):
339
444
  def corner_style(self, corner_type):
340
445
  if isinstance(corner_type, str):
341
446
  mapping = {
342
- "round": GrpcPatCornerType.ROUND,
343
- "mitter": GrpcPatCornerType.MITER,
344
- "sharp": GrpcPatCornerType.SHARP,
447
+ "round": GrpcPathCornerType.ROUND,
448
+ "mitter": GrpcPathCornerType.MITER,
449
+ "sharp": GrpcPathCornerType.SHARP,
345
450
  }
346
451
  self.corner_style = mapping[corner_type]
452
+
453
+ @property
454
+ def end_cap1(self) -> str:
455
+ """Path's start style as string.
456
+
457
+ Returns
458
+ -------
459
+ str
460
+ Values supported for the setter `"flat"`, `"round"`, `"extended"`
461
+
462
+ """
463
+ return self.get_end_cap_style()[0].name.lower()
464
+
465
+ @end_cap1.setter
466
+ def end_cap1(self, end_cap_style):
467
+ if isinstance(end_cap_style, str):
468
+ mapping = {
469
+ "flat": GrpcPathEndCapType.FLAT,
470
+ "round": GrpcPathEndCapType.ROUND,
471
+ "extended": GrpcPathEndCapType.EXTENDED,
472
+ }
473
+ self.set_end_cap_style(mapping[end_cap_style], self.get_end_cap_style()[1].value)
474
+
475
+ @property
476
+ def end_cap2(self) -> str:
477
+ """Path's end style as string.
478
+
479
+ Returns
480
+ -------
481
+ str
482
+ Values supported for the setter `"flat"`, `"round"`, `"extended"`
483
+
484
+ """
485
+ return self.get_end_cap_style()[1].name.lower()
486
+
487
+ @end_cap2.setter
488
+ def end_cap2(self, end_cap_style):
489
+ if isinstance(end_cap_style, str):
490
+ mapping = {
491
+ "flat": GrpcPathEndCapType.FLAT,
492
+ "round": GrpcPathEndCapType.ROUND,
493
+ "extended": GrpcPathEndCapType.EXTENDED,
494
+ }
495
+ self.set_end_cap_style(self.get_end_cap_style()[0].value, mapping[end_cap_style])
@@ -22,19 +22,23 @@
22
22
 
23
23
 
24
24
  import math
25
+ from typing import Union
25
26
 
26
27
  from ansys.edb.core.geometry.point_data import PointData as GrpcPointData
27
28
  from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
28
29
  from ansys.edb.core.primitive.polygon import Polygon as GrpcPolygon
29
30
 
31
+ from pyedb.grpc.database.layers.layer import Layer
32
+ from pyedb.grpc.database.layout.layout import Layout
30
33
  from pyedb.grpc.database.primitive.primitive import Primitive
31
34
  from pyedb.grpc.database.utility.value import Value
32
35
 
33
36
 
34
37
  class Polygon(GrpcPolygon, Primitive):
35
- def __init__(self, pedb, edb_object):
36
- GrpcPolygon.__init__(self, edb_object.msg)
37
- Primitive.__init__(self, pedb, edb_object)
38
+ def __init__(self, pedb, edb_object=None):
39
+ if edb_object:
40
+ GrpcPolygon.__init__(self, edb_object.msg)
41
+ Primitive.__init__(self, pedb, edb_object)
38
42
  self._pedb = pedb
39
43
 
40
44
  @property
@@ -59,6 +63,67 @@ class Polygon(GrpcPolygon, Primitive):
59
63
  """
60
64
  return self.polygon_data.has_self_intersections()
61
65
 
66
+ def create(
67
+ self, layout: Layout = None, layer: Union[str, Layer] = None, net: Union[str, "Net"] = None, polygon_data=None
68
+ ):
69
+ """
70
+ Create a polygon in the specified layout, layer, and net using the provided polygon data.
71
+
72
+ Parameters
73
+ ----------
74
+ layout : Layout, optional
75
+ The layout in which the polygon will be created. If not provided, the active layout of the `pedb`
76
+ instance will be used.
77
+ layer : Union[str, Layer], optional
78
+ The layer in which the polygon will be created. This parameter is required and must be specified.
79
+ net : Union[str, Net], optional
80
+ The net to which the polygon will belong. If not provided, the polygon will not be associated with a
81
+ net.
82
+ polygon_data : list or GrpcPolygonData, optional
83
+ The data defining the polygon. This can be a list of points or an instance of `GrpcPolygonData`.
84
+ This parameter is required and must be specified.
85
+
86
+ Returns
87
+ -------
88
+ :class:`Polygon <ansys.edb.core.primitive.polygon.Polygon>`
89
+ The created polygon object.
90
+
91
+ Raises
92
+ ------
93
+ ValueError
94
+ If the `layer` parameter is not provided.
95
+ ValueError
96
+ If the `polygon_data` parameter is not provided.
97
+
98
+ Notes
99
+ -----
100
+ - If `polygon_data` is provided as a list, it will be converted to a `GrpcPolygonData` object.
101
+ - The created polygon is added to the modeler primitives of the `pedb` instance.
102
+
103
+ """
104
+ if not layout:
105
+ layout = self._pedb.active_layout
106
+ if not layer:
107
+ raise ValueError("Layer is required to create a polygon.")
108
+ if not polygon_data:
109
+ raise ValueError("Polygon data or point list is required to create a polygon.")
110
+ if isinstance(polygon_data, list):
111
+ polygon_data = GrpcPolygonData(polygon_data)
112
+
113
+ # call into the gRPC layer to actually create the polygon
114
+ edb_object = super().create(layout=layout, layer=layer, net=net, polygon_data=polygon_data)
115
+ new_polygon = Polygon(self._pedb, edb_object)
116
+ # keep modeler cache in sync
117
+ self._pedb.modeler._add_primitive(new_polygon)
118
+
119
+ return new_polygon
120
+
121
+ def delete(self):
122
+ """Delete polygon from layout."""
123
+ # keeping cache in sync
124
+ self._pedb.modeler._remove_primitive(self)
125
+ super().delete()
126
+
62
127
  def fix_self_intersections(self) -> list[any]:
63
128
  """Remove self intersections if they exist.
64
129
 
@@ -88,13 +153,14 @@ class Polygon(GrpcPolygon, Primitive):
88
153
  Cloned polygon.
89
154
 
90
155
  """
156
+ voids = self.voids
91
157
  polygon_data = self.polygon_data
92
- duplicated_polygon = self.create(
158
+ cloned_polygon = self.create(
93
159
  layout=self._pedb.active_layout, layer=self.layer, net=self.net, polygon_data=polygon_data
94
160
  )
95
- for void in self.voids:
96
- duplicated_polygon.add_void(void)
97
- return duplicated_polygon
161
+ for void in voids:
162
+ cloned_polygon.add_void(void)
163
+ return cloned_polygon
98
164
 
99
165
  def duplicate_across_layers(self, layers) -> bool:
100
166
  """Duplicate across layer a primitive object.
@@ -39,8 +39,8 @@ class Primitive(GrpcPrimitive):
39
39
  >>> from pyedb import Edb
40
40
  >>> edb = Edb(myedb, edbversion="2021.2")
41
41
  >>> edb_prim = edb.modeler.primitives[0]
42
- >>> edb_prim.is_void # Class Property
43
- >>> edb_prim.IsVoid() # EDB Object Property
42
+ >>> edb_prim.is_void # Class Property
43
+ >>> edb_prim.IsVoid() # EDB Object Property
44
44
  """
45
45
 
46
46
  def __init__(self, pedb, edb_object):