pyedb 0.38.0__py3-none-any.whl → 0.39.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 (205) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/common/nets.py +53 -139
  3. pyedb/configuration/cfg_components.py +1 -1
  4. pyedb/configuration/cfg_general.py +4 -2
  5. pyedb/configuration/cfg_modeler.py +1 -1
  6. pyedb/configuration/cfg_package_definition.py +1 -1
  7. pyedb/configuration/cfg_padstacks.py +1 -1
  8. pyedb/configuration/cfg_ports_sources.py +56 -23
  9. pyedb/configuration/configuration.py +18 -1
  10. pyedb/dotnet/{application → database}/Variables.py +21 -21
  11. pyedb/dotnet/{edb_core → database}/cell/connectable.py +5 -5
  12. pyedb/dotnet/{edb_core → database}/cell/hierarchy/component.py +11 -11
  13. pyedb/dotnet/{edb_core → database}/cell/hierarchy/hierarchy_obj.py +1 -1
  14. pyedb/dotnet/{edb_core → database}/cell/hierarchy/model.py +1 -1
  15. pyedb/dotnet/{edb_core → database}/cell/layout.py +17 -17
  16. pyedb/dotnet/{edb_core → database}/cell/layout_obj.py +3 -3
  17. pyedb/dotnet/{edb_core → database}/cell/primitive/bondwire.py +1 -1
  18. pyedb/dotnet/{edb_core → database}/cell/primitive/path.py +4 -4
  19. pyedb/dotnet/{edb_core → database}/cell/primitive/primitive.py +14 -14
  20. pyedb/dotnet/{edb_core → database}/cell/terminal/bundle_terminal.py +2 -2
  21. pyedb/dotnet/{edb_core → database}/cell/terminal/edge_terminal.py +4 -4
  22. pyedb/dotnet/{edb_core → database}/cell/terminal/padstack_instance_terminal.py +2 -2
  23. pyedb/dotnet/{edb_core → database}/cell/terminal/pingroup_terminal.py +2 -2
  24. pyedb/dotnet/{edb_core → database}/cell/terminal/point_terminal.py +2 -2
  25. pyedb/dotnet/{edb_core → database}/cell/terminal/terminal.py +11 -11
  26. pyedb/dotnet/{edb_core → database}/cell/voltage_regulator.py +2 -2
  27. pyedb/dotnet/{edb_core → database}/components.py +101 -124
  28. pyedb/dotnet/{edb_core → database}/definition/component_def.py +5 -5
  29. pyedb/dotnet/{edb_core → database}/definition/component_model.py +1 -1
  30. pyedb/dotnet/{edb_core → database}/definition/definition_obj.py +1 -1
  31. pyedb/dotnet/{edb_core → database}/definition/definitions.py +2 -2
  32. pyedb/dotnet/{edb_core → database}/definition/package_def.py +4 -4
  33. pyedb/dotnet/{edb_core → database}/dotnet/database.py +8 -8
  34. pyedb/dotnet/{edb_core → database}/dotnet/primitive.py +9 -9
  35. pyedb/dotnet/{edb_core → database}/edb_data/control_file.py +12 -12
  36. pyedb/dotnet/{edb_core → database}/edb_data/hfss_extent_info.py +7 -7
  37. pyedb/dotnet/{edb_core → database}/edb_data/nets_data.py +10 -13
  38. pyedb/dotnet/{edb_core → database}/edb_data/padstacks_data.py +16 -16
  39. pyedb/dotnet/{edb_core → database}/edb_data/ports.py +4 -4
  40. pyedb/dotnet/{edb_core → database}/edb_data/primitives_data.py +5 -5
  41. pyedb/dotnet/{edb_core → database}/edb_data/raptor_x_simulation_setup_data.py +4 -4
  42. pyedb/dotnet/{edb_core → database}/edb_data/simulation_configuration.py +10 -10
  43. pyedb/dotnet/{edb_core → database}/edb_data/sources.py +4 -4
  44. pyedb/dotnet/{edb_core → database}/edb_data/variables.py +1 -1
  45. pyedb/dotnet/{edb_core → database}/geometry/polygon_data.py +4 -4
  46. pyedb/dotnet/{edb_core → database}/hfss.py +8 -8
  47. pyedb/dotnet/{edb_core → database}/layout_obj_instance.py +1 -1
  48. pyedb/dotnet/{edb_core → database}/layout_validation.py +2 -2
  49. pyedb/dotnet/{edb_core → database}/materials.py +23 -8
  50. pyedb/dotnet/{edb_core → database}/modeler.py +27 -27
  51. pyedb/dotnet/{edb_core → database}/net_class.py +8 -8
  52. pyedb/dotnet/{edb_core → database}/nets.py +12 -12
  53. pyedb/dotnet/{edb_core → database}/padstack.py +15 -15
  54. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/mesh_operation.py +1 -1
  55. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/settings.py +3 -3
  56. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/sim_setup_info.py +2 -2
  57. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/simulation_settings.py +1 -1
  58. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/siw_dc_ir_settings.py +1 -1
  59. pyedb/dotnet/{edb_core → database}/sim_setup_data/data/sweep_data.py +1 -1
  60. pyedb/dotnet/{edb_core → database}/siwave.py +10 -10
  61. pyedb/dotnet/{edb_core → database}/stackup.py +12 -12
  62. pyedb/dotnet/{edb_core → database}/utilities/hfss_simulation_setup.py +15 -15
  63. pyedb/dotnet/{edb_core → database}/utilities/obj_base.py +1 -1
  64. pyedb/dotnet/{edb_core → database}/utilities/simulation_setup.py +3 -3
  65. pyedb/dotnet/{edb_core → database}/utilities/siwave_simulation_setup.py +6 -6
  66. pyedb/dotnet/edb.py +117 -112
  67. pyedb/generic/design_types.py +26 -19
  68. pyedb/generic/general_methods.py +1 -1
  69. pyedb/generic/plot.py +0 -2
  70. pyedb/grpc/database/__init__.py +1 -0
  71. pyedb/grpc/database/components.py +2354 -0
  72. pyedb/grpc/database/control_file.py +1277 -0
  73. pyedb/grpc/database/definition/component_def.py +218 -0
  74. pyedb/grpc/database/definition/component_model.py +39 -0
  75. pyedb/grpc/database/definition/component_pin.py +32 -0
  76. pyedb/grpc/database/definition/materials.py +1207 -0
  77. pyedb/grpc/database/definition/n_port_component_model.py +34 -0
  78. pyedb/grpc/database/definition/package_def.py +227 -0
  79. pyedb/grpc/database/definition/padstack_def.py +842 -0
  80. pyedb/grpc/database/definitions.py +70 -0
  81. pyedb/grpc/database/general.py +43 -0
  82. pyedb/grpc/database/geometry/__init__.py +0 -0
  83. pyedb/grpc/database/geometry/arc_data.py +93 -0
  84. pyedb/grpc/database/geometry/point_3d_data.py +79 -0
  85. pyedb/grpc/database/geometry/point_data.py +30 -0
  86. pyedb/grpc/database/geometry/polygon_data.py +133 -0
  87. pyedb/grpc/database/hfss.py +1279 -0
  88. pyedb/grpc/database/hierarchy/__init__.py +0 -0
  89. pyedb/grpc/database/hierarchy/component.py +1301 -0
  90. pyedb/grpc/database/hierarchy/model.py +31 -0
  91. pyedb/grpc/database/hierarchy/netlist_model.py +30 -0
  92. pyedb/grpc/database/hierarchy/pin_pair_model.py +128 -0
  93. pyedb/grpc/database/hierarchy/pingroup.py +245 -0
  94. pyedb/grpc/database/hierarchy/s_parameter_model.py +33 -0
  95. pyedb/grpc/database/hierarchy/spice_model.py +48 -0
  96. pyedb/grpc/database/layers/__init__.py +0 -0
  97. pyedb/grpc/database/layers/layer.py +57 -0
  98. pyedb/grpc/database/layers/stackup_layer.py +410 -0
  99. pyedb/grpc/database/layout/__init__.py +0 -0
  100. pyedb/grpc/database/layout/cell.py +30 -0
  101. pyedb/grpc/database/layout/layout.py +196 -0
  102. pyedb/grpc/database/layout/voltage_regulator.py +149 -0
  103. pyedb/grpc/database/layout_validation.py +319 -0
  104. pyedb/grpc/database/modeler.py +1468 -0
  105. pyedb/grpc/database/net/__init__.py +0 -0
  106. pyedb/grpc/database/net/differential_pair.py +138 -0
  107. pyedb/grpc/database/net/extended_net.py +340 -0
  108. pyedb/grpc/database/net/net.py +198 -0
  109. pyedb/grpc/database/net/net_class.py +93 -0
  110. pyedb/grpc/database/nets.py +633 -0
  111. pyedb/grpc/database/padstacks.py +1500 -0
  112. pyedb/grpc/database/ports/__init__.py +0 -0
  113. pyedb/grpc/database/ports/ports.py +396 -0
  114. pyedb/grpc/database/primitive/__init__.py +3 -0
  115. pyedb/grpc/database/primitive/bondwire.py +181 -0
  116. pyedb/grpc/database/primitive/circle.py +75 -0
  117. pyedb/grpc/database/primitive/padstack_instance.py +1116 -0
  118. pyedb/grpc/database/primitive/path.py +346 -0
  119. pyedb/grpc/database/primitive/polygon.py +276 -0
  120. pyedb/grpc/database/primitive/primitive.py +739 -0
  121. pyedb/grpc/database/primitive/rectangle.py +146 -0
  122. pyedb/grpc/database/simulation_setup/__init__.py +0 -0
  123. pyedb/grpc/database/simulation_setup/adaptive_frequency.py +33 -0
  124. pyedb/grpc/database/simulation_setup/hfss_advanced_meshing_settings.py +32 -0
  125. pyedb/grpc/database/simulation_setup/hfss_advanced_settings.py +59 -0
  126. pyedb/grpc/database/simulation_setup/hfss_dcr_settings.py +35 -0
  127. pyedb/grpc/database/simulation_setup/hfss_general_settings.py +61 -0
  128. pyedb/grpc/database/simulation_setup/hfss_settings_options.py +78 -0
  129. pyedb/grpc/database/simulation_setup/hfss_simulation_settings.py +118 -0
  130. pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +355 -0
  131. pyedb/grpc/database/simulation_setup/hfss_solver_settings.py +34 -0
  132. pyedb/grpc/database/simulation_setup/mesh_operation.py +34 -0
  133. pyedb/grpc/database/simulation_setup/raptor_x_advanced_settings.py +34 -0
  134. pyedb/grpc/database/simulation_setup/raptor_x_general_settings.py +33 -0
  135. pyedb/grpc/database/simulation_setup/raptor_x_simulation_settings.py +64 -0
  136. pyedb/grpc/database/simulation_setup/raptor_x_simulation_setup.py +125 -0
  137. pyedb/grpc/database/simulation_setup/siwave_dcir_simulation_setup.py +34 -0
  138. pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +119 -0
  139. pyedb/grpc/database/simulation_setup/sweep_data.py +32 -0
  140. pyedb/grpc/database/siwave.py +1023 -0
  141. pyedb/grpc/database/source_excitations.py +2572 -0
  142. pyedb/grpc/database/stackup.py +2574 -0
  143. pyedb/grpc/database/terminal/__init__.py +0 -0
  144. pyedb/grpc/database/terminal/bundle_terminal.py +218 -0
  145. pyedb/grpc/database/terminal/edge_terminal.py +51 -0
  146. pyedb/grpc/database/terminal/padstack_instance_terminal.py +171 -0
  147. pyedb/grpc/database/terminal/pingroup_terminal.py +162 -0
  148. pyedb/grpc/database/terminal/point_terminal.py +99 -0
  149. pyedb/grpc/database/terminal/terminal.py +470 -0
  150. pyedb/grpc/database/utility/__init__.py +3 -0
  151. pyedb/grpc/database/utility/constants.py +25 -0
  152. pyedb/grpc/database/utility/heat_sink.py +124 -0
  153. pyedb/grpc/database/utility/hfss_extent_info.py +448 -0
  154. pyedb/grpc/database/utility/layout_statistics.py +277 -0
  155. pyedb/grpc/database/utility/rlc.py +80 -0
  156. pyedb/grpc/database/utility/simulation_configuration.py +3305 -0
  157. pyedb/grpc/database/utility/sources.py +388 -0
  158. pyedb/grpc/database/utility/sweep_data_distribution.py +83 -0
  159. pyedb/grpc/database/utility/xml_control_file.py +1277 -0
  160. pyedb/grpc/edb.py +4151 -0
  161. pyedb/grpc/edb_init.py +481 -0
  162. pyedb/grpc/rpc_session.py +177 -0
  163. pyedb/ipc2581/ecad/cad_data/assembly_drawing.py +3 -2
  164. pyedb/ipc2581/ecad/cad_data/feature.py +4 -3
  165. pyedb/ipc2581/ecad/cad_data/layer_feature.py +32 -20
  166. pyedb/ipc2581/ecad/cad_data/outline.py +3 -2
  167. pyedb/ipc2581/ecad/cad_data/package.py +4 -3
  168. pyedb/ipc2581/ecad/cad_data/path.py +82 -31
  169. pyedb/ipc2581/ecad/cad_data/polygon.py +122 -60
  170. pyedb/ipc2581/ecad/cad_data/profile.py +13 -12
  171. pyedb/ipc2581/ecad/cad_data/step.py +53 -21
  172. pyedb/ipc2581/ipc2581.py +47 -49
  173. pyedb/modeler/geometry_operators.py +1 -1
  174. {pyedb-0.38.0.dist-info → pyedb-0.39.0.dist-info}/METADATA +5 -2
  175. pyedb-0.39.0.dist-info/RECORD +288 -0
  176. pyedb-0.38.0.dist-info/RECORD +0 -195
  177. /pyedb/dotnet/{edb_core → database}/__init__.py +0 -0
  178. /pyedb/dotnet/{application → database/cell}/__init__.py +0 -0
  179. /pyedb/dotnet/{edb_core/cell → database/cell/hierarchy}/__init__.py +0 -0
  180. /pyedb/dotnet/{edb_core → database}/cell/hierarchy/netlist_model.py +0 -0
  181. /pyedb/dotnet/{edb_core → database}/cell/hierarchy/pin_pair_model.py +0 -0
  182. /pyedb/dotnet/{edb_core → database}/cell/hierarchy/s_parameter_model.py +0 -0
  183. /pyedb/dotnet/{edb_core → database}/cell/hierarchy/spice_model.py +0 -0
  184. /pyedb/dotnet/{edb_core → database}/cell/primitive/__init__.py +0 -0
  185. /pyedb/dotnet/{edb_core/cell/hierarchy → database/cell/terminal}/__init__.py +0 -0
  186. /pyedb/dotnet/{edb_core/cell/terminal → database/definition}/__init__.py +0 -0
  187. /pyedb/dotnet/{edb_core/definition → database/dotnet}/__init__.py +0 -0
  188. /pyedb/dotnet/{edb_core/dotnet → database/edb_data}/__init__.py +0 -0
  189. /pyedb/dotnet/{edb_core → database}/edb_data/design_options.py +0 -0
  190. /pyedb/dotnet/{edb_core → database}/edb_data/edbvalue.py +0 -0
  191. /pyedb/dotnet/{edb_core → database}/edb_data/layer_data.py +0 -0
  192. /pyedb/dotnet/{edb_core → database}/edb_data/utilities.py +0 -0
  193. /pyedb/dotnet/{edb_core → database}/general.py +0 -0
  194. /pyedb/dotnet/{edb_core/edb_data → database/geometry}/__init__.py +0 -0
  195. /pyedb/dotnet/{edb_core → database}/geometry/point_data.py +0 -0
  196. /pyedb/dotnet/{edb_core → database}/sim_setup_data/__init__.py +0 -0
  197. /pyedb/dotnet/{edb_core → database}/sim_setup_data/data/__init__.py +0 -0
  198. /pyedb/dotnet/{edb_core → database}/sim_setup_data/data/adaptive_frequency_data.py +0 -0
  199. /pyedb/dotnet/{edb_core/geometry → database/sim_setup_data/io}/__init__.py +0 -0
  200. /pyedb/dotnet/{edb_core → database}/sim_setup_data/io/siwave.py +0 -0
  201. /pyedb/dotnet/{edb_core → database}/utilities/__init__.py +0 -0
  202. /pyedb/dotnet/{edb_core → database}/utilities/heatsink.py +0 -0
  203. /pyedb/{dotnet/edb_core/sim_setup_data/io → grpc/database/definition}/__init__.py +0 -0
  204. {pyedb-0.38.0.dist-info → pyedb-0.39.0.dist-info}/LICENSE +0 -0
  205. {pyedb-0.38.0.dist-info → pyedb-0.39.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,346 @@
1
+ # Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
2
+ # SPDX-License-Identifier: MIT
3
+ #
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+ import math
23
+
24
+ from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
25
+ from ansys.edb.core.primitive.primitive import Path as GrpcPath
26
+ from ansys.edb.core.primitive.primitive import PathCornerType as GrpcPatCornerType
27
+ from ansys.edb.core.utility.value import Value as GrpcValue
28
+
29
+ from pyedb.grpc.database.primitive.primitive import Primitive
30
+
31
+
32
+ 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)
36
+ self._edb_object = edb_object
37
+ self._pedb = pedb
38
+
39
+ @property
40
+ def width(self):
41
+ """Path width.
42
+
43
+ Returns
44
+ -------
45
+ float
46
+ Path width or None.
47
+ """
48
+ return round(super().width.value, 9)
49
+
50
+ @width.setter
51
+ def width(self, value):
52
+ super(Path, self.__class__).width.__set__(self, GrpcValue(value))
53
+
54
+ @property
55
+ def length(self):
56
+ """Path length in meters.
57
+
58
+ Returns
59
+ -------
60
+ float
61
+ Path length in meters.
62
+ """
63
+ center_line_arcs = self._edb_object.cast().center_line.arc_data
64
+ path_length = 0.0
65
+ for arc in center_line_arcs:
66
+ path_length += arc.length
67
+ end_cap_style = self.get_end_cap_style()
68
+ if end_cap_style:
69
+ if not end_cap_style[0].value == 1:
70
+ path_length += self.width / 2
71
+ if not end_cap_style[1].value == 1:
72
+ path_length += self.width / 2
73
+ return round(path_length, 9)
74
+
75
+ def add_point(self, x, y, incremental=True):
76
+ """Add a point at the end of the path.
77
+
78
+ Parameters
79
+ ----------
80
+ x: str, int, float
81
+ X coordinate.
82
+ y: str, in, float
83
+ Y coordinate.
84
+ incremental: bool
85
+ Add point incrementally. If True, coordinates of the added point is incremental to the last point.
86
+ The default value is ``True``.
87
+
88
+ Returns
89
+ -------
90
+ bool
91
+ """
92
+ if incremental:
93
+ points = self.center_line
94
+ points.append([x, y])
95
+ points = GrpcPolygonData(points=points)
96
+ GrpcPath.create(
97
+ layout=self.layout,
98
+ layer=self.layer,
99
+ net=self.net,
100
+ )
101
+ self.center_line = points
102
+ return True
103
+
104
+ def clone(self):
105
+ """Clone a primitive object with keeping same definition and location.
106
+
107
+ Returns
108
+ -------
109
+ bool
110
+ ``True`` when successful, ``False`` when failed.
111
+ """
112
+ mapping = {
113
+ "round": GrpcPatCornerType.ROUND,
114
+ "mitter": GrpcPatCornerType.MITER,
115
+ "sharp": GrpcPatCornerType.SHARP,
116
+ }
117
+
118
+ cloned_path = GrpcPath.create(
119
+ layout=self._pedb.active_layout,
120
+ layer=self.layer,
121
+ net=self.net,
122
+ width=GrpcValue(self.width),
123
+ end_cap1=self.get_end_cap_style()[0],
124
+ end_cap2=self.get_end_cap_style()[1],
125
+ corner_style=mapping[self.corner_style],
126
+ points=GrpcPolygonData(self.center_line),
127
+ )
128
+ if not cloned_path.is_null:
129
+ return Path(self._pedb, cloned_path)
130
+
131
+ #
132
+
133
+ def create_edge_port(
134
+ self,
135
+ name,
136
+ position="End",
137
+ port_type="Wave",
138
+ reference_layer=None,
139
+ horizontal_extent_factor=5,
140
+ vertical_extent_factor=3,
141
+ pec_launch_width="0.01mm",
142
+ ):
143
+ """
144
+
145
+ Parameters
146
+ ----------
147
+ name : str
148
+ Name of the port.
149
+ position : str, optional
150
+ Position of the port. The default is ``"End"``, in which case the port is created at the end of the trace.
151
+ Options are ``"Start"`` and ``"End"``.
152
+ port_type : str, optional
153
+ Type of the port. The default is ``"Wave"``, in which case a wave port is created. Options are ``"Wave"``
154
+ and ``"Gap"``.
155
+ reference_layer : str, optional
156
+ Name of the references layer. The default is ``None``. Only available for gap port.
157
+ horizontal_extent_factor : int, optional
158
+ Horizontal extent factor of the wave port. The default is ``5``.
159
+ vertical_extent_factor : int, optional
160
+ Vertical extent factor of the wave port. The default is ``3``.
161
+ pec_launch_width : float, str, optional
162
+ Perfect electrical conductor width of the wave port. The default is ``"0.01mm"``.
163
+
164
+ Returns
165
+ -------
166
+ :class:`GapPort <pyedb.grpc.database.ports.port.GapPort>`
167
+
168
+ Examples
169
+ --------
170
+ >>> edbapp = pyedb.dotnet.Edb("myproject.aedb")
171
+ >>> sig = appedb.modeler.create_trace([[0, 0], ["9mm", 0]], "TOP", "1mm", "SIG", "Flat", "Flat")
172
+ >>> sig.create_edge_port("pcb_port", "end", "Wave", None, 8, 8)
173
+
174
+ """
175
+ center_line = self.center_line
176
+ pos = center_line[-1] if position.lower() == "end" else center_line[0]
177
+
178
+ # if port_type.lower() == "wave":
179
+ # return self._pedb.hfss.create_wave_port(
180
+ # self.id, pos, name, 50, horizontal_extent_factor, vertical_extent_factor, pec_launch_width
181
+ # )
182
+ # else:
183
+ return self._pedb.hfss.create_edge_port_vertical(
184
+ self.id,
185
+ pos,
186
+ name,
187
+ 50,
188
+ reference_layer,
189
+ hfss_type=port_type,
190
+ horizontal_extent_factor=horizontal_extent_factor,
191
+ vertical_extent_factor=vertical_extent_factor,
192
+ pec_launch_width=pec_launch_width,
193
+ )
194
+
195
+ def create_via_fence(self, distance, gap, padstack_name, net_name="GND"):
196
+ """Create via fences on both sides of the trace.
197
+
198
+ Parameters
199
+ ----------
200
+ distance: str, float
201
+ Distance between via fence and trace center line.
202
+ gap: str, float
203
+ Gap between vias.
204
+ padstack_name: str
205
+ Name of the via padstack.
206
+ net_name: str, optional
207
+ Name of the net.
208
+
209
+ """
210
+
211
+ def getAngle(v1, v2): # pragma: no cover
212
+ v1_mag = math.sqrt(v1[0] ** 2 + v1[1] ** 2)
213
+ v2_mag = math.sqrt(v2[0] ** 2 + v2[1] ** 2)
214
+ dotsum = v1[0] * v2[0] + v1[1] * v2[1]
215
+ if v1[0] * v2[1] - v1[1] * v2[0] > 0:
216
+ scale = 1
217
+ else:
218
+ scale = -1
219
+ dtheta = scale * math.acos(dotsum / (v1_mag * v2_mag))
220
+
221
+ return dtheta
222
+
223
+ def get_locations(line, gap): # pragma: no cover
224
+ location = [line[0]]
225
+ residual = 0
226
+
227
+ for n in range(len(line) - 1):
228
+ x0, y0 = line[n]
229
+ x1, y1 = line[n + 1]
230
+ length = math.sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2)
231
+ dx, dy = (x1 - x0) / length, (y1 - y0) / length
232
+ x = x0 - dx * residual
233
+ y = y0 - dy * residual
234
+ length = length + residual
235
+ while length >= gap:
236
+ x += gap * dx
237
+ y += gap * dy
238
+ location.append((x, y))
239
+ length -= gap
240
+
241
+ residual = length
242
+ return location
243
+
244
+ def get_parallet_lines(pts, distance): # pragma: no cover
245
+ leftline = []
246
+ rightline = []
247
+
248
+ x0, y0 = pts[0]
249
+ x1, y1 = pts[1]
250
+ vector = (x1 - x0, y1 - y0)
251
+ orientation1 = getAngle((1, 0), vector)
252
+
253
+ leftturn = orientation1 + math.pi / 2
254
+ righrturn = orientation1 - math.pi / 2
255
+ leftPt = (x0 + distance * math.cos(leftturn), y0 + distance * math.sin(leftturn))
256
+ leftline.append(leftPt)
257
+ rightPt = (x0 + distance * math.cos(righrturn), y0 + distance * math.sin(righrturn))
258
+ rightline.append(rightPt)
259
+
260
+ for n in range(1, len(pts) - 1):
261
+ x0, y0 = pts[n - 1]
262
+ x1, y1 = pts[n]
263
+ x2, y2 = pts[n + 1]
264
+
265
+ v1 = (x1 - x0, y1 - y0)
266
+ v2 = (x2 - x1, y2 - y1)
267
+ dtheta = getAngle(v1, v2)
268
+ orientation1 = getAngle((1, 0), v1)
269
+
270
+ leftturn = orientation1 + dtheta / 2 + math.pi / 2
271
+ righrturn = orientation1 + dtheta / 2 - math.pi / 2
272
+
273
+ distance2 = distance / math.sin((math.pi - dtheta) / 2)
274
+ leftPt = (x1 + distance2 * math.cos(leftturn), y1 + distance2 * math.sin(leftturn))
275
+ leftline.append(leftPt)
276
+ rightPt = (x1 + distance2 * math.cos(righrturn), y1 + distance2 * math.sin(righrturn))
277
+ rightline.append(rightPt)
278
+
279
+ x0, y0 = pts[-2]
280
+ x1, y1 = pts[-1]
281
+
282
+ vector = (x1 - x0, y1 - y0)
283
+ orientation1 = getAngle((1, 0), vector)
284
+ leftturn = orientation1 + math.pi / 2
285
+ righrturn = orientation1 - math.pi / 2
286
+ leftPt = (x1 + distance * math.cos(leftturn), y1 + distance * math.sin(leftturn))
287
+ leftline.append(leftPt)
288
+ rightPt = (x1 + distance * math.cos(righrturn), y1 + distance * math.sin(righrturn))
289
+ rightline.append(rightPt)
290
+ return leftline, rightline
291
+
292
+ distance = GrpcValue(distance).value
293
+ gap = GrpcValue(gap).value
294
+ center_line = self.center_line
295
+ leftline, rightline = get_parallet_lines(center_line, distance)
296
+ for x, y in get_locations(rightline, gap) + get_locations(leftline, gap):
297
+ self._pedb.padstacks.place([x, y], padstack_name, net_name=net_name)
298
+
299
+ @property
300
+ def center_line(self):
301
+ """Path center line
302
+
303
+ Returns
304
+ -------
305
+ List[float]
306
+
307
+ """
308
+ return self.get_center_line()
309
+
310
+ def get_center_line(self):
311
+ """Retrieve center line points list.
312
+
313
+ Returns
314
+ -------
315
+ List[List[float, float]].
316
+
317
+ """
318
+ return [[pt.x.value, pt.y.value] for pt in super().center_line.points]
319
+
320
+ # def set_center_line(self, value):
321
+ # if isinstance(value, list):
322
+ # points = [GrpcPointData(i) for i in value]
323
+ # polygon_data = GrpcPolygonData(points, False)
324
+ # super(Path, self.__class__).polygon_data.__set__(self, polygon_data)
325
+
326
+ @property
327
+ def corner_style(self):
328
+ """Path's corner style as string.
329
+
330
+ Returns
331
+ -------
332
+ str
333
+ Values supported for the setter `"round"`, `"mitter"`, `"sharp"`
334
+
335
+ """
336
+ return super().corner_style.name.lower()
337
+
338
+ @corner_style.setter
339
+ def corner_style(self, corner_type):
340
+ if isinstance(corner_type, str):
341
+ mapping = {
342
+ "round": GrpcPatCornerType.ROUND,
343
+ "mitter": GrpcPatCornerType.MITER,
344
+ "sharp": GrpcPatCornerType.SHARP,
345
+ }
346
+ self.corner_style = mapping[corner_type]
@@ -0,0 +1,276 @@
1
+ # Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
2
+ # SPDX-License-Identifier: MIT
3
+ #
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+
24
+ import math
25
+
26
+ from ansys.edb.core.geometry.point_data import PointData as GrpcPointData
27
+ from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
28
+ from ansys.edb.core.primitive.primitive import Polygon as GrpcPolygon
29
+ from ansys.edb.core.utility.value import Value as GrpcValue
30
+
31
+ from pyedb.grpc.database.primitive.primitive import Primitive
32
+
33
+
34
+ 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
+ self._pedb = pedb
39
+
40
+ @property
41
+ def type(self):
42
+ """Primitive type.
43
+
44
+ Return
45
+ ------
46
+ str
47
+ Polygon type.
48
+
49
+ """
50
+ return self.primitive_type.name.lower()
51
+
52
+ @property
53
+ def has_self_intersections(self):
54
+ """Check if Polygon has self intersections.
55
+
56
+ Returns
57
+ -------
58
+ bool
59
+ """
60
+ return self.polygon_data.has_self_intersections()
61
+
62
+ def fix_self_intersections(self):
63
+ """Remove self intersections if they exist.
64
+
65
+ Returns
66
+ -------
67
+ List[:class:`Polygon <ansys.edb.core.primitive.primitive.Polygon>`]
68
+ All new polygons created from the removal operation.
69
+
70
+ """
71
+ new_polys = []
72
+ if self.has_self_intersections:
73
+ new_polygons = self.polygon_data.remove_self_intersections()
74
+ self.polygon_data = new_polygons[0]
75
+ for p in new_polygons[1:]:
76
+ cloned_poly = self.create(
77
+ layout=self._pedb.active_layout, layer=self.layer.name, net=self.net, polygon_data=p
78
+ )
79
+ new_polys.append(cloned_poly)
80
+ return new_polys
81
+
82
+ def clone(self):
83
+ """Duplicate polygon.
84
+
85
+ Returns
86
+ -------
87
+ :class:`Polygon <ansys.edb.core.primitive.primitive.Polygon>`
88
+ Cloned polygon.
89
+
90
+ """
91
+ polygon_data = self.polygon_data
92
+ duplicated_polygon = self.create(
93
+ layout=self._pedb.active_layout, layer=self.layer, net=self.net, polygon_data=polygon_data
94
+ )
95
+ for void in self.voids:
96
+ duplicated_polygon.add_void(void)
97
+ return duplicated_polygon
98
+
99
+ def duplicate_across_layers(self, layers):
100
+ """Duplicate across layer a primitive object.
101
+
102
+ Parameters:
103
+
104
+ layers: list
105
+ list of str, with layer names
106
+
107
+ Returns
108
+ -------
109
+ bool
110
+ ``True`` when successful, ``False`` when failed.
111
+ """
112
+ for layer in layers:
113
+ if layer in self._pedb.stackup.layers:
114
+ duplicate_polygon = self.create(
115
+ layout=self._pedb.active_layout, layer=layer, net=self.net.name, polygon_data=self.polygon_data
116
+ )
117
+ if duplicate_polygon:
118
+ for void in self.voids:
119
+ duplicate_void = self.create(
120
+ layout=self._pedb.active_layout,
121
+ layer=layer,
122
+ net=self.net.name,
123
+ polygon_data=void.cast().polygon_data,
124
+ )
125
+ duplicate_polygon.add_void(duplicate_void)
126
+ else:
127
+ return False
128
+ return True
129
+
130
+ def move(self, vector):
131
+ """Move polygon along a vector.
132
+
133
+ Parameters
134
+ ----------
135
+ vector : List of float or str [x,y].
136
+
137
+ Returns
138
+ -------
139
+ bool
140
+ ``True`` when successful, ``False`` when failed.
141
+
142
+ Examples
143
+ --------
144
+ >>> edbapp = ansys.aedt.core.Edb("myproject.aedb")
145
+ >>> top_layer_polygon = [poly for poly in edbapp.modeler.polygons if poly.layer_name == "Top Layer"]
146
+ >>> for polygon in top_layer_polygon:
147
+ >>> polygon.move(vector=["2mm", "100um"])
148
+ """
149
+ if vector and isinstance(vector, list) and len(vector) == 2:
150
+ _vector = [GrpcValue(pt).value for pt in vector]
151
+ self.polygon_data = self.polygon_data.move(_vector)
152
+ return True
153
+ return False
154
+
155
+ def scale(self, factor, center=None):
156
+ """Scales the polygon relative to a center point by a factor.
157
+
158
+ Parameters
159
+ ----------
160
+ factor : float
161
+ Scaling factor.
162
+ center : List of float or str [x,y], optional
163
+ If None scaling is done from polygon center.
164
+
165
+ Returns
166
+ -------
167
+ bool
168
+ ``True`` when successful, ``False`` when failed.
169
+ """
170
+ if not isinstance(factor, str):
171
+ factor = float(factor)
172
+ if not center:
173
+ center = self.polygon_data.bounding_circle()[0]
174
+ if center:
175
+ self.polygon_data = self.polygon_data.scale(factor, center)
176
+ return True
177
+ else:
178
+ self._pedb.logger.error(f"Failed to evaluate center on primitive {self.id}")
179
+ elif isinstance(center, list) and len(center) == 2:
180
+ center = GrpcPointData([GrpcValue(center[0]), GrpcValue(center[1])])
181
+ self.polygon_data = self.polygon_data.scale(factor, center)
182
+ return True
183
+ return False
184
+
185
+ def rotate(self, angle, center=None):
186
+ """Rotate polygon around a center point by an angle.
187
+
188
+ Parameters
189
+ ----------
190
+ angle : float
191
+ Value of the rotation angle in degree.
192
+ center : List of float or str [x,y], optional
193
+ If None rotation is done from polygon center.
194
+
195
+ Returns
196
+ -------
197
+ bool
198
+ ``True`` when successful, ``False`` when failed.
199
+
200
+ Examples
201
+ --------
202
+ >>> edbapp = ansys.aedt.core.Edb("myproject.aedb")
203
+ >>> top_layer_polygon = [poly for poly in edbapp.modeler.polygons if poly.layer_name == "Top Layer"]
204
+ >>> for polygon in top_layer_polygon:
205
+ >>> polygon.rotate(angle=45)
206
+ """
207
+ if angle:
208
+ if not center:
209
+ center = self.polygon_data.bounding_circle()[0]
210
+ if center:
211
+ self.polygon_data = self.polygon_data.rotate(angle * math.pi / 180, center)
212
+ return True
213
+ elif isinstance(center, list) and len(center) == 2:
214
+ self.polygon_data = self.polygon_data.rotate(angle * math.pi / 180, center)
215
+ return True
216
+ return False
217
+
218
+ def move_layer(self, layer):
219
+ """Move polygon to given layer.
220
+
221
+ Parameters
222
+ ----------
223
+ layer : str
224
+ layer name.
225
+
226
+ Returns
227
+ -------
228
+ bool
229
+ ``True`` when successful, ``False`` when failed.
230
+ """
231
+ if layer and isinstance(layer, str) and layer in self._pedb.stackup.signal_layers:
232
+ self.layer = self._pedb.stackup.layers[layer]
233
+ return True
234
+ return False
235
+
236
+ def in_polygon(
237
+ self,
238
+ point_data,
239
+ include_partial=True,
240
+ ):
241
+ """Check if padstack Instance is in given polygon data.
242
+
243
+ Parameters
244
+ ----------
245
+ point_data : PointData Object or list of float
246
+ include_partial : bool, optional
247
+ Whether to include partial intersecting instances. The default is ``True``.
248
+
249
+ Returns
250
+ -------
251
+ bool
252
+ ``True`` when successful, ``False`` when failed.
253
+ """
254
+ int_val = 1 if self.polygon_data.is_inside(GrpcPointData(point_data)) else 0
255
+ if int_val == 0:
256
+ return False
257
+ else:
258
+ int_val = self.polygon_data.intersection_type(GrpcPolygonData(point_data))
259
+ # Intersection type:
260
+ # 0 = objects do not intersect
261
+ # 1 = this object fully inside other (no common contour points)
262
+ # 2 = other object fully inside this
263
+ # 3 = common contour points 4 = undefined intersection
264
+ if int_val == 0:
265
+ return False
266
+ elif include_partial:
267
+ return True
268
+ elif int_val < 3:
269
+ return True
270
+ else:
271
+ return False
272
+
273
+ def add_void(self, polygon):
274
+ if isinstance(polygon, list):
275
+ polygon = self._pedb.modeler.create_polygon(points=polygon, layer_name=self.layer.name)
276
+ return self._edb_object.add_void(polygon._edb_object)