pyedb 0.22.1__py3-none-any.whl → 0.24.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.
- pyedb/__init__.py +1 -1
- pyedb/configuration/cfg_components.py +1 -1
- pyedb/configuration/cfg_ports_sources.py +3 -3
- pyedb/configuration/configuration.py +2 -2
- pyedb/dotnet/edb.py +55 -56
- pyedb/dotnet/edb_core/cell/hierarchy/component.py +1 -1
- pyedb/dotnet/edb_core/cell/hierarchy/hierarchy_obj.py +11 -0
- pyedb/dotnet/edb_core/cell/layout.py +30 -23
- pyedb/dotnet/edb_core/cell/layout_obj.py +0 -9
- pyedb/dotnet/edb_core/cell/primitive/__init__.py +3 -0
- pyedb/dotnet/edb_core/cell/{primitive.py → primitive/bondwire.py} +1 -146
- pyedb/dotnet/edb_core/cell/primitive/path.py +351 -0
- pyedb/dotnet/edb_core/cell/primitive/primitive.py +895 -0
- pyedb/dotnet/edb_core/cell/terminal/bundle_terminal.py +0 -4
- pyedb/dotnet/edb_core/cell/terminal/edge_terminal.py +1 -1
- pyedb/dotnet/edb_core/cell/terminal/terminal.py +1 -1
- pyedb/dotnet/edb_core/components.py +26 -18
- pyedb/dotnet/edb_core/dotnet/database.py +1 -23
- pyedb/dotnet/edb_core/dotnet/primitive.py +3 -139
- pyedb/dotnet/edb_core/edb_data/nets_data.py +1 -11
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py +12 -38
- pyedb/dotnet/edb_core/edb_data/primitives_data.py +56 -868
- pyedb/dotnet/edb_core/edb_data/simulation_configuration.py +0 -18
- pyedb/dotnet/edb_core/geometry/polygon_data.py +43 -0
- pyedb/dotnet/edb_core/hfss.py +27 -23
- pyedb/dotnet/edb_core/layout_validation.py +3 -3
- pyedb/dotnet/edb_core/materials.py +1 -1
- pyedb/dotnet/edb_core/modeler.py +65 -82
- pyedb/dotnet/edb_core/nets.py +8 -7
- pyedb/dotnet/edb_core/padstack.py +16 -17
- pyedb/dotnet/edb_core/siwave.py +2 -2
- pyedb/dotnet/edb_core/stackup.py +64 -87
- pyedb/ipc2581/ecad/cad_data/layer_feature.py +1 -1
- pyedb/ipc2581/ecad/cad_data/polygon.py +2 -2
- pyedb/ipc2581/ecad/cad_data/step.py +3 -3
- pyedb/ipc2581/ipc2581.py +2 -2
- pyedb/siwave.py +99 -0
- {pyedb-0.22.1.dist-info → pyedb-0.24.0.dist-info}/METADATA +3 -3
- {pyedb-0.22.1.dist-info → pyedb-0.24.0.dist-info}/RECORD +41 -38
- {pyedb-0.22.1.dist-info → pyedb-0.24.0.dist-info}/LICENSE +0 -0
- {pyedb-0.22.1.dist-info → pyedb-0.24.0.dist-info}/WHEEL +0 -0
|
@@ -22,17 +22,13 @@
|
|
|
22
22
|
|
|
23
23
|
import math
|
|
24
24
|
|
|
25
|
-
from pyedb.dotnet.edb_core.cell.primitive import Primitive
|
|
25
|
+
from pyedb.dotnet.edb_core.cell.primitive.primitive import Primitive
|
|
26
26
|
from pyedb.dotnet.edb_core.dotnet.primitive import (
|
|
27
27
|
BondwireDotNet,
|
|
28
28
|
CircleDotNet,
|
|
29
|
-
PathDotNet,
|
|
30
|
-
PolygonDataDotNet,
|
|
31
|
-
PolygonDotNet,
|
|
32
29
|
RectangleDotNet,
|
|
33
30
|
TextDotNet,
|
|
34
31
|
)
|
|
35
|
-
from pyedb.dotnet.edb_core.general import convert_py_list_to_net_list
|
|
36
32
|
from pyedb.modeler.geometry_operators import GeometryOperators
|
|
37
33
|
|
|
38
34
|
|
|
@@ -43,846 +39,36 @@ def cast(raw_primitive, core_app):
|
|
|
43
39
|
-------
|
|
44
40
|
Primitive
|
|
45
41
|
"""
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return EdbCircle(raw_primitive.prim_obj, core_app)
|
|
42
|
+
prim_type = raw_primitive.GetPrimitiveType()
|
|
43
|
+
if prim_type == prim_type.Rectangle:
|
|
44
|
+
return EdbRectangle(raw_primitive, core_app)
|
|
45
|
+
elif prim_type == prim_type.Polygon:
|
|
46
|
+
return EdbPolygon(raw_primitive, core_app)
|
|
47
|
+
elif prim_type == prim_type.Bondwire:
|
|
48
|
+
return EdbBondwire(raw_primitive, core_app)
|
|
49
|
+
elif prim_type == prim_type.Text:
|
|
50
|
+
return EdbText(raw_primitive, core_app)
|
|
51
|
+
elif prim_type == prim_type.Circle:
|
|
52
|
+
return EdbCircle(raw_primitive, core_app)
|
|
58
53
|
else:
|
|
59
|
-
|
|
60
|
-
prim_type = raw_primitive.GetPrimitiveType()
|
|
61
|
-
if prim_type == prim_type.Rectangle:
|
|
62
|
-
return EdbRectangle(raw_primitive, core_app)
|
|
63
|
-
elif prim_type == prim_type.Polygon:
|
|
64
|
-
return EdbPolygon(raw_primitive, core_app)
|
|
65
|
-
elif prim_type == prim_type.Path:
|
|
66
|
-
return EdbPath(raw_primitive, core_app)
|
|
67
|
-
elif prim_type == prim_type.Bondwire:
|
|
68
|
-
return EdbBondwire(raw_primitive, core_app)
|
|
69
|
-
elif prim_type == prim_type.Text:
|
|
70
|
-
return EdbText(raw_primitive, core_app)
|
|
71
|
-
elif prim_type == prim_type.Circle:
|
|
72
|
-
return EdbCircle(raw_primitive, core_app)
|
|
73
|
-
else:
|
|
74
|
-
return None
|
|
75
|
-
except:
|
|
76
|
-
return None
|
|
77
|
-
|
|
54
|
+
return None
|
|
78
55
|
|
|
79
|
-
class EDBPrimitives(Primitive):
|
|
80
|
-
"""Manages EDB functionalities for a primitives.
|
|
81
|
-
It Inherits EDB Object properties.
|
|
82
|
-
|
|
83
|
-
Examples
|
|
84
|
-
--------
|
|
85
|
-
>>> from pyedb import Edb
|
|
86
|
-
>>> edb = Edb(myedb, edbversion="2021.2")
|
|
87
|
-
>>> edb_prim = edb.modeler.primitives[0]
|
|
88
|
-
>>> edb_prim.is_void # Class Property
|
|
89
|
-
>>> edb_prim.IsVoid() # EDB Object Property
|
|
90
|
-
"""
|
|
91
56
|
|
|
57
|
+
class EdbRectangle(Primitive, RectangleDotNet):
|
|
92
58
|
def __init__(self, raw_primitive, core_app):
|
|
93
59
|
Primitive.__init__(self, core_app, raw_primitive)
|
|
60
|
+
RectangleDotNet.__init__(self, core_app, raw_primitive)
|
|
94
61
|
|
|
95
|
-
def area(self, include_voids=True):
|
|
96
|
-
"""Return the total area.
|
|
97
|
-
|
|
98
|
-
Parameters
|
|
99
|
-
----------
|
|
100
|
-
include_voids : bool, optional
|
|
101
|
-
Either if the voids have to be included in computation.
|
|
102
|
-
The default value is ``True``.
|
|
103
|
-
|
|
104
|
-
Returns
|
|
105
|
-
-------
|
|
106
|
-
float
|
|
107
|
-
"""
|
|
108
|
-
area = self.primitive_object.GetPolygonData().Area()
|
|
109
|
-
if include_voids:
|
|
110
|
-
for el in self.primitive_object.Voids:
|
|
111
|
-
area -= el.GetPolygonData().Area()
|
|
112
|
-
return area
|
|
113
|
-
|
|
114
|
-
@property
|
|
115
|
-
def is_negative(self):
|
|
116
|
-
"""Determine whether this primitive is negative.
|
|
117
|
-
|
|
118
|
-
Returns
|
|
119
|
-
-------
|
|
120
|
-
bool
|
|
121
|
-
True if it is negative, False otherwise.
|
|
122
|
-
"""
|
|
123
|
-
return self.primitive_object.GetIsNegative()
|
|
124
|
-
|
|
125
|
-
@is_negative.setter
|
|
126
|
-
def is_negative(self, value):
|
|
127
|
-
self.primitive_object.SetIsNegative(value)
|
|
128
|
-
|
|
129
|
-
@staticmethod
|
|
130
|
-
def _eval_arc_points(p1, p2, h, n=6, tol=1e-12):
|
|
131
|
-
"""Get the points of the arc
|
|
132
|
-
|
|
133
|
-
Parameters
|
|
134
|
-
----------
|
|
135
|
-
p1 : list
|
|
136
|
-
Arc starting point.
|
|
137
|
-
p2 : list
|
|
138
|
-
Arc ending point.
|
|
139
|
-
h : float
|
|
140
|
-
Arc height.
|
|
141
|
-
n : int
|
|
142
|
-
Number of points to generate along the arc.
|
|
143
|
-
tol : float
|
|
144
|
-
Geometric tolerance.
|
|
145
|
-
|
|
146
|
-
Returns
|
|
147
|
-
-------
|
|
148
|
-
list, list
|
|
149
|
-
Points generated along the arc.
|
|
150
|
-
"""
|
|
151
|
-
# fmt: off
|
|
152
|
-
if abs(h) < tol:
|
|
153
|
-
return [], []
|
|
154
|
-
elif h > 0:
|
|
155
|
-
reverse = False
|
|
156
|
-
x1 = p1[0]
|
|
157
|
-
y1 = p1[1]
|
|
158
|
-
x2 = p2[0]
|
|
159
|
-
y2 = p2[1]
|
|
160
|
-
else:
|
|
161
|
-
reverse = True
|
|
162
|
-
x1 = p2[0]
|
|
163
|
-
y1 = p2[1]
|
|
164
|
-
x2 = p1[0]
|
|
165
|
-
y2 = p1[1]
|
|
166
|
-
h *= -1
|
|
167
|
-
xa = (x2 - x1) / 2
|
|
168
|
-
ya = (y2 - y1) / 2
|
|
169
|
-
xo = x1 + xa
|
|
170
|
-
yo = y1 + ya
|
|
171
|
-
a = math.sqrt(xa ** 2 + ya ** 2)
|
|
172
|
-
if a < tol:
|
|
173
|
-
return [], []
|
|
174
|
-
r = (a ** 2) / (2 * h) + h / 2
|
|
175
|
-
if abs(r - a) < tol:
|
|
176
|
-
b = 0
|
|
177
|
-
th = 2 * math.asin(1) # chord angle
|
|
178
|
-
else:
|
|
179
|
-
b = math.sqrt(r ** 2 - a ** 2)
|
|
180
|
-
th = 2 * math.asin(a / r) # chord angle
|
|
181
|
-
|
|
182
|
-
# center of the circle
|
|
183
|
-
xc = xo + b * ya / a
|
|
184
|
-
yc = yo - b * xa / a
|
|
185
|
-
|
|
186
|
-
alpha = math.atan2((y1 - yc), (x1 - xc))
|
|
187
|
-
xr = []
|
|
188
|
-
yr = []
|
|
189
|
-
for i in range(n):
|
|
190
|
-
i += 1
|
|
191
|
-
dth = (float(i) / (n + 1)) * th
|
|
192
|
-
xi = xc + r * math.cos(alpha - dth)
|
|
193
|
-
yi = yc + r * math.sin(alpha - dth)
|
|
194
|
-
xr.append(xi)
|
|
195
|
-
yr.append(yi)
|
|
196
|
-
|
|
197
|
-
if reverse:
|
|
198
|
-
xr.reverse()
|
|
199
|
-
yr.reverse()
|
|
200
|
-
# fmt: on
|
|
201
|
-
return xr, yr
|
|
202
|
-
|
|
203
|
-
def _get_points_for_plot(self, my_net_points, num):
|
|
204
|
-
"""
|
|
205
|
-
Get the points to be plotted.
|
|
206
|
-
"""
|
|
207
|
-
# fmt: off
|
|
208
|
-
x = []
|
|
209
|
-
y = []
|
|
210
|
-
for i, point in enumerate(my_net_points):
|
|
211
|
-
if not self.is_arc(point):
|
|
212
|
-
x.append(point.X.ToDouble())
|
|
213
|
-
y.append(point.Y.ToDouble())
|
|
214
|
-
# i += 1
|
|
215
|
-
else:
|
|
216
|
-
arc_h = point.GetArcHeight().ToDouble()
|
|
217
|
-
p1 = [my_net_points[i - 1].X.ToDouble(), my_net_points[i - 1].Y.ToDouble()]
|
|
218
|
-
if i + 1 < len(my_net_points):
|
|
219
|
-
p2 = [my_net_points[i + 1].X.ToDouble(), my_net_points[i + 1].Y.ToDouble()]
|
|
220
|
-
else:
|
|
221
|
-
p2 = [my_net_points[0].X.ToDouble(), my_net_points[0].Y.ToDouble()]
|
|
222
|
-
x_arc, y_arc = self._eval_arc_points(p1, p2, arc_h, num)
|
|
223
|
-
x.extend(x_arc)
|
|
224
|
-
y.extend(y_arc)
|
|
225
|
-
# i += 1
|
|
226
|
-
# fmt: on
|
|
227
|
-
return x, y
|
|
228
|
-
|
|
229
|
-
@property
|
|
230
|
-
def bbox(self):
|
|
231
|
-
"""Return the primitive bounding box points. Lower left corner, upper right corner.
|
|
232
|
-
|
|
233
|
-
Returns
|
|
234
|
-
-------
|
|
235
|
-
list
|
|
236
|
-
[lower_left x, lower_left y, upper right x, upper right y]
|
|
237
|
-
|
|
238
|
-
"""
|
|
239
|
-
bbox = self.polygon_data.edb_api.GetBBox()
|
|
240
|
-
return [bbox.Item1.X.ToDouble(), bbox.Item1.Y.ToDouble(), bbox.Item2.X.ToDouble(), bbox.Item2.Y.ToDouble()]
|
|
241
|
-
|
|
242
|
-
@property
|
|
243
|
-
def center(self):
|
|
244
|
-
"""Return the primitive bounding box center coordinate.
|
|
245
|
-
|
|
246
|
-
Returns
|
|
247
|
-
-------
|
|
248
|
-
list
|
|
249
|
-
[x, y]
|
|
250
|
-
|
|
251
|
-
"""
|
|
252
|
-
bbox = self.bbox
|
|
253
|
-
return [(bbox[0] + bbox[2]) / 2, (bbox[1] + bbox[3]) / 2]
|
|
254
|
-
|
|
255
|
-
def is_arc(self, point):
|
|
256
|
-
"""Either if a point is an arc or not.
|
|
257
|
-
|
|
258
|
-
Returns
|
|
259
|
-
-------
|
|
260
|
-
bool
|
|
261
|
-
"""
|
|
262
|
-
return point.IsArc()
|
|
263
|
-
|
|
264
|
-
def get_connected_object_id_set(self):
|
|
265
|
-
"""Produce a list of all geometries physically connected to a given layout object.
|
|
266
|
-
|
|
267
|
-
Returns
|
|
268
|
-
-------
|
|
269
|
-
list
|
|
270
|
-
Found connected objects IDs with Layout object.
|
|
271
|
-
"""
|
|
272
|
-
layoutInst = self.primitive_object.GetLayout().GetLayoutInstance()
|
|
273
|
-
layoutObjInst = layoutInst.GetLayoutObjInstance(self.primitive_object, None) # 2nd arg was []
|
|
274
|
-
return [loi.GetLayoutObj().GetId() for loi in layoutInst.GetConnectedObjects(layoutObjInst).Items]
|
|
275
|
-
|
|
276
|
-
def convert_to_polygon(self):
|
|
277
|
-
"""Convert path to polygon.
|
|
278
|
-
|
|
279
|
-
Returns
|
|
280
|
-
-------
|
|
281
|
-
bool, :class:`dotnet.edb_core.edb_data.primitives.EDBPrimitives`
|
|
282
|
-
Polygon when successful, ``False`` when failed.
|
|
283
|
-
|
|
284
|
-
"""
|
|
285
|
-
if self.type == "Path":
|
|
286
|
-
polygon_data = self.primitive_object.GetPolygonData()
|
|
287
|
-
polygon = self._app.modeler.create_polygon(polygon_data, self.layer_name, [], self.net_name)
|
|
288
|
-
self.primitive_object.Delete()
|
|
289
|
-
return polygon
|
|
290
|
-
else:
|
|
291
|
-
return False
|
|
292
|
-
|
|
293
|
-
def subtract(self, primitives):
|
|
294
|
-
"""Subtract active primitive with one or more primitives.
|
|
295
62
|
|
|
296
|
-
|
|
297
|
-
----------
|
|
298
|
-
primitives : :class:`dotnet.edb_core.edb_data.EDBPrimitives` or EDB PolygonData or EDB Primitive or list
|
|
299
|
-
|
|
300
|
-
Returns
|
|
301
|
-
-------
|
|
302
|
-
List of :class:`dotnet.edb_core.edb_data.EDBPrimitives`
|
|
303
|
-
"""
|
|
304
|
-
poly = self.primitive_object.GetPolygonData()
|
|
305
|
-
if not isinstance(primitives, list):
|
|
306
|
-
primitives = [primitives]
|
|
307
|
-
primi_polys = []
|
|
308
|
-
voids_of_prims = []
|
|
309
|
-
for prim in primitives:
|
|
310
|
-
if isinstance(prim, EDBPrimitives):
|
|
311
|
-
primi_polys.append(prim.primitive_object.GetPolygonData())
|
|
312
|
-
for void in prim.voids:
|
|
313
|
-
voids_of_prims.append(void.polygon_data.edb_api)
|
|
314
|
-
else:
|
|
315
|
-
try:
|
|
316
|
-
primi_polys.append(prim.GetPolygonData())
|
|
317
|
-
except:
|
|
318
|
-
primi_polys.append(prim)
|
|
319
|
-
for v in self.voids[:]:
|
|
320
|
-
primi_polys.append(v.polygon_data.edb_api)
|
|
321
|
-
primi_polys = poly.Unite(convert_py_list_to_net_list(primi_polys))
|
|
322
|
-
p_to_sub = poly.Unite(convert_py_list_to_net_list([poly] + voids_of_prims))
|
|
323
|
-
list_poly = poly.Subtract(p_to_sub, primi_polys)
|
|
324
|
-
new_polys = []
|
|
325
|
-
if list_poly:
|
|
326
|
-
for p in list_poly:
|
|
327
|
-
if p.IsNull():
|
|
328
|
-
continue
|
|
329
|
-
new_polys.append(
|
|
330
|
-
cast(
|
|
331
|
-
self._app.modeler.create_polygon(p, self.layer_name, net_name=self.net_name, voids=[]),
|
|
332
|
-
self._app,
|
|
333
|
-
)
|
|
334
|
-
)
|
|
335
|
-
self.delete()
|
|
336
|
-
for prim in primitives:
|
|
337
|
-
if isinstance(prim, EDBPrimitives):
|
|
338
|
-
prim.delete()
|
|
339
|
-
else:
|
|
340
|
-
try:
|
|
341
|
-
prim.Delete()
|
|
342
|
-
except AttributeError:
|
|
343
|
-
continue
|
|
344
|
-
return new_polys
|
|
345
|
-
|
|
346
|
-
def intersect(self, primitives):
|
|
347
|
-
"""Intersect active primitive with one or more primitives.
|
|
348
|
-
|
|
349
|
-
Parameters
|
|
350
|
-
----------
|
|
351
|
-
primitives : :class:`dotnet.edb_core.edb_data.EDBPrimitives` or EDB PolygonData or EDB Primitive or list
|
|
352
|
-
|
|
353
|
-
Returns
|
|
354
|
-
-------
|
|
355
|
-
List of :class:`dotnet.edb_core.edb_data.EDBPrimitives`
|
|
356
|
-
"""
|
|
357
|
-
poly = self.primitive_object.GetPolygonData()
|
|
358
|
-
if not isinstance(primitives, list):
|
|
359
|
-
primitives = [primitives]
|
|
360
|
-
primi_polys = []
|
|
361
|
-
for prim in primitives:
|
|
362
|
-
if isinstance(prim, EDBPrimitives):
|
|
363
|
-
primi_polys.append(prim.primitive_object.GetPolygonData())
|
|
364
|
-
else:
|
|
365
|
-
try:
|
|
366
|
-
primi_polys.append(prim.GetPolygonData())
|
|
367
|
-
except:
|
|
368
|
-
primi_polys.append(prim)
|
|
369
|
-
list_poly = poly.Intersect(convert_py_list_to_net_list([poly]), convert_py_list_to_net_list(primi_polys))
|
|
370
|
-
new_polys = []
|
|
371
|
-
if list_poly:
|
|
372
|
-
voids = self.voids
|
|
373
|
-
for p in list_poly:
|
|
374
|
-
if p.IsNull():
|
|
375
|
-
continue
|
|
376
|
-
list_void = []
|
|
377
|
-
void_to_subtract = []
|
|
378
|
-
if voids:
|
|
379
|
-
for void in voids:
|
|
380
|
-
void_pdata = void.prim_obj.GetPolygonData()
|
|
381
|
-
int_data2 = p.GetIntersectionType(void_pdata)
|
|
382
|
-
if int_data2 > 2 or int_data2 == 1:
|
|
383
|
-
void_to_subtract.append(void_pdata)
|
|
384
|
-
elif int_data2 == 2:
|
|
385
|
-
list_void.append(void_pdata)
|
|
386
|
-
if void_to_subtract:
|
|
387
|
-
polys_cleans = p.Subtract(
|
|
388
|
-
convert_py_list_to_net_list(p), convert_py_list_to_net_list(void_to_subtract)
|
|
389
|
-
)
|
|
390
|
-
for polys_clean in polys_cleans:
|
|
391
|
-
if not polys_clean.IsNull():
|
|
392
|
-
void_to_append = [v for v in list_void if polys_clean.GetIntersectionType(v) == 2]
|
|
393
|
-
new_polys.append(
|
|
394
|
-
cast(
|
|
395
|
-
self._app.modeler.create_polygon(
|
|
396
|
-
polys_clean, self.layer_name, net_name=self.net_name, voids=void_to_append
|
|
397
|
-
),
|
|
398
|
-
self._app,
|
|
399
|
-
)
|
|
400
|
-
)
|
|
401
|
-
else:
|
|
402
|
-
new_polys.append(
|
|
403
|
-
cast(
|
|
404
|
-
self._app.modeler.create_polygon(
|
|
405
|
-
p, self.layer_name, net_name=self.net_name, voids=list_void
|
|
406
|
-
),
|
|
407
|
-
self._app,
|
|
408
|
-
)
|
|
409
|
-
)
|
|
410
|
-
else:
|
|
411
|
-
new_polys.append(
|
|
412
|
-
cast(
|
|
413
|
-
self._app.modeler.create_polygon(
|
|
414
|
-
p, self.layer_name, net_name=self.net_name, voids=list_void
|
|
415
|
-
),
|
|
416
|
-
self._app,
|
|
417
|
-
)
|
|
418
|
-
)
|
|
419
|
-
self.delete()
|
|
420
|
-
for prim in primitives:
|
|
421
|
-
if isinstance(prim, EDBPrimitives):
|
|
422
|
-
prim.delete()
|
|
423
|
-
else:
|
|
424
|
-
try:
|
|
425
|
-
prim.Delete()
|
|
426
|
-
except AttributeError:
|
|
427
|
-
continue
|
|
428
|
-
return new_polys
|
|
429
|
-
|
|
430
|
-
def unite(self, primitives):
|
|
431
|
-
"""Unite active primitive with one or more primitives.
|
|
432
|
-
|
|
433
|
-
Parameters
|
|
434
|
-
----------
|
|
435
|
-
primitives : :class:`dotnet.edb_core.edb_data.EDBPrimitives` or EDB PolygonData or EDB Primitive or list
|
|
436
|
-
|
|
437
|
-
Returns
|
|
438
|
-
-------
|
|
439
|
-
List of :class:`dotnet.edb_core.edb_data.EDBPrimitives`
|
|
440
|
-
"""
|
|
441
|
-
poly = self.primitive_object.GetPolygonData()
|
|
442
|
-
if not isinstance(primitives, list):
|
|
443
|
-
primitives = [primitives]
|
|
444
|
-
primi_polys = []
|
|
445
|
-
for prim in primitives:
|
|
446
|
-
if isinstance(prim, EDBPrimitives):
|
|
447
|
-
primi_polys.append(prim.primitive_object.GetPolygonData())
|
|
448
|
-
else:
|
|
449
|
-
try:
|
|
450
|
-
primi_polys.append(prim.GetPolygonData())
|
|
451
|
-
except:
|
|
452
|
-
primi_polys.append(prim)
|
|
453
|
-
list_poly = poly.Unite(convert_py_list_to_net_list([poly] + primi_polys))
|
|
454
|
-
new_polys = []
|
|
455
|
-
if list_poly:
|
|
456
|
-
voids = self.voids
|
|
457
|
-
for p in list_poly:
|
|
458
|
-
if p.IsNull():
|
|
459
|
-
continue
|
|
460
|
-
list_void = []
|
|
461
|
-
if voids:
|
|
462
|
-
for void in voids:
|
|
463
|
-
void_pdata = void.primitive_object.GetPolygonData()
|
|
464
|
-
int_data2 = p.GetIntersectionType(void_pdata)
|
|
465
|
-
if int_data2 > 1:
|
|
466
|
-
list_void.append(void_pdata)
|
|
467
|
-
new_polys.append(
|
|
468
|
-
cast(
|
|
469
|
-
self._app.modeler.create_polygon(p, self.layer_name, net_name=self.net_name, voids=list_void),
|
|
470
|
-
self._app,
|
|
471
|
-
)
|
|
472
|
-
)
|
|
473
|
-
self.delete()
|
|
474
|
-
for prim in primitives:
|
|
475
|
-
if isinstance(prim, EDBPrimitives):
|
|
476
|
-
prim.delete()
|
|
477
|
-
else:
|
|
478
|
-
try:
|
|
479
|
-
prim.Delete()
|
|
480
|
-
except AttributeError:
|
|
481
|
-
continue
|
|
482
|
-
return new_polys
|
|
483
|
-
|
|
484
|
-
def intersection_type(self, primitive):
|
|
485
|
-
"""Get intersection type between actual primitive and another primitive or polygon data.
|
|
486
|
-
|
|
487
|
-
Parameters
|
|
488
|
-
----------
|
|
489
|
-
primitive : :class:`pyaeedt.edb_core.edb_data.primitives_data.EDBPrimitives` or `PolygonData`
|
|
490
|
-
|
|
491
|
-
Returns
|
|
492
|
-
-------
|
|
493
|
-
int
|
|
494
|
-
Intersection type:
|
|
495
|
-
0 - objects do not intersect,
|
|
496
|
-
1 - this object fully inside other (no common contour points),
|
|
497
|
-
2 - other object fully inside this,
|
|
498
|
-
3 - common contour points,
|
|
499
|
-
4 - undefined intersection.
|
|
500
|
-
"""
|
|
501
|
-
poly = primitive
|
|
502
|
-
try:
|
|
503
|
-
poly = primitive.polygon_data
|
|
504
|
-
except AttributeError:
|
|
505
|
-
pass
|
|
506
|
-
return int(self.polygon_data.edb_api.GetIntersectionType(poly.edb_api))
|
|
507
|
-
|
|
508
|
-
def is_intersecting(self, primitive):
|
|
509
|
-
"""Check if actual primitive and another primitive or polygon data intesects.
|
|
510
|
-
|
|
511
|
-
Parameters
|
|
512
|
-
----------
|
|
513
|
-
primitive : :class:`pyaeedt.edb_core.edb_data.primitives_data.EDBPrimitives` or `PolygonData`
|
|
514
|
-
|
|
515
|
-
Returns
|
|
516
|
-
-------
|
|
517
|
-
bool
|
|
518
|
-
"""
|
|
519
|
-
return True if self.intersection_type(primitive) >= 1 else False
|
|
520
|
-
|
|
521
|
-
def get_closest_point(self, point):
|
|
522
|
-
"""Get the closest point of the primitive to the input data.
|
|
523
|
-
|
|
524
|
-
Parameters
|
|
525
|
-
----------
|
|
526
|
-
point : list of float or PointData
|
|
527
|
-
|
|
528
|
-
Returns
|
|
529
|
-
-------
|
|
530
|
-
list of float
|
|
531
|
-
"""
|
|
532
|
-
if isinstance(point, (list, tuple)):
|
|
533
|
-
point = self._app.edb_api.geometry.point_data(self._app.edb_value(point[0]), self._app.edb_value(point[1]))
|
|
534
|
-
|
|
535
|
-
p0 = self.polygon_data.edb_api.GetClosestPoint(point)
|
|
536
|
-
return [p0.X.ToDouble(), p0.Y.ToDouble()]
|
|
537
|
-
|
|
538
|
-
def get_closest_arc_midpoint(self, point):
|
|
539
|
-
"""Get the closest arc midpoint of the primitive to the input data.
|
|
540
|
-
|
|
541
|
-
Parameters
|
|
542
|
-
----------
|
|
543
|
-
point : list of float or PointData
|
|
544
|
-
|
|
545
|
-
Returns
|
|
546
|
-
-------
|
|
547
|
-
list of float
|
|
548
|
-
"""
|
|
549
|
-
if isinstance(point, self._app.edb_api.geometry.geometry.PointData):
|
|
550
|
-
point = [point.X.ToDouble(), point.Y.ToDouble()]
|
|
551
|
-
dist = 1e12
|
|
552
|
-
out = None
|
|
553
|
-
for arc in self.arcs:
|
|
554
|
-
mid_point = arc.mid_point
|
|
555
|
-
mid_point = [mid_point.X.ToDouble(), mid_point.Y.ToDouble()]
|
|
556
|
-
if GeometryOperators.points_distance(mid_point, point) < dist:
|
|
557
|
-
out = arc.mid_point
|
|
558
|
-
dist = GeometryOperators.points_distance(mid_point, point)
|
|
559
|
-
return [out.X.ToDouble(), out.Y.ToDouble()]
|
|
560
|
-
|
|
561
|
-
@property
|
|
562
|
-
def voids(self):
|
|
563
|
-
""":obj:`list` of :class:`Primitive <ansys.edb.primitive.Primitive>`: List of void\
|
|
564
|
-
primitive objects inside the primitive.
|
|
565
|
-
|
|
566
|
-
Read-Only.
|
|
567
|
-
"""
|
|
568
|
-
return [cast(void, self._app) for void in self.prim_obj.Voids]
|
|
569
|
-
|
|
570
|
-
@property
|
|
571
|
-
def arcs(self):
|
|
572
|
-
"""Get the Primitive Arc Data."""
|
|
573
|
-
arcs = [EDBArcs(self, i) for i in self.polygon_data.arcs]
|
|
574
|
-
return arcs
|
|
575
|
-
|
|
576
|
-
@property
|
|
577
|
-
def longest_arc(self):
|
|
578
|
-
"""Get the longest arc."""
|
|
579
|
-
len = 0
|
|
580
|
-
arc = None
|
|
581
|
-
for i in self.arcs:
|
|
582
|
-
if i.is_segment and i.length > len:
|
|
583
|
-
arc = i
|
|
584
|
-
len = i.length
|
|
585
|
-
return arc
|
|
586
|
-
|
|
587
|
-
@property
|
|
588
|
-
def shortest_arc(self):
|
|
589
|
-
"""Get the longest arc."""
|
|
590
|
-
len = 1e12
|
|
591
|
-
arc = None
|
|
592
|
-
for i in self.arcs:
|
|
593
|
-
if i.is_segment and i.length < len:
|
|
594
|
-
arc = i
|
|
595
|
-
len = i.length
|
|
596
|
-
return arc
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
class EdbPath(EDBPrimitives, PathDotNet):
|
|
63
|
+
class EdbCircle(Primitive, CircleDotNet):
|
|
600
64
|
def __init__(self, raw_primitive, core_app):
|
|
601
|
-
|
|
602
|
-
PathDotNet.__init__(self, self._app, raw_primitive)
|
|
603
|
-
|
|
604
|
-
@property
|
|
605
|
-
def width(self):
|
|
606
|
-
"""Path width.
|
|
607
|
-
|
|
608
|
-
Returns
|
|
609
|
-
-------
|
|
610
|
-
float
|
|
611
|
-
Path width or None.
|
|
612
|
-
"""
|
|
613
|
-
if self.type == "Path":
|
|
614
|
-
return self.primitive_object.GetWidth()
|
|
615
|
-
return
|
|
616
|
-
|
|
617
|
-
@width.setter
|
|
618
|
-
def width(self, value):
|
|
619
|
-
if self.type == "Path":
|
|
620
|
-
if isinstance(value, (int, str, float)):
|
|
621
|
-
self.primitive_object.SetWidth(self._app.edb_value(value))
|
|
622
|
-
else:
|
|
623
|
-
self.primitive_object.SetWidth(value)
|
|
624
|
-
|
|
625
|
-
@property
|
|
626
|
-
def length(self):
|
|
627
|
-
"""Path length in meters.
|
|
628
|
-
|
|
629
|
-
Returns
|
|
630
|
-
-------
|
|
631
|
-
float
|
|
632
|
-
Path length in meters.
|
|
633
|
-
"""
|
|
634
|
-
center_line_arcs = list(self.api_object.GetCenterLine().GetArcData())
|
|
635
|
-
path_length = 0.0
|
|
636
|
-
for arc in center_line_arcs:
|
|
637
|
-
path_length += arc.GetLength()
|
|
638
|
-
if self.end_cap_style[0]:
|
|
639
|
-
if not self.end_cap_style[1].value__ == 1:
|
|
640
|
-
path_length += self.width / 2
|
|
641
|
-
if not self.end_cap_style[2].value__ == 1:
|
|
642
|
-
path_length += self.width / 2
|
|
643
|
-
return path_length
|
|
644
|
-
|
|
645
|
-
def add_point(self, x, y, incremental=False):
|
|
646
|
-
"""Add a point at the end of the path.
|
|
647
|
-
|
|
648
|
-
Parameters
|
|
649
|
-
----------
|
|
650
|
-
x: str, int, float
|
|
651
|
-
X coordinate.
|
|
652
|
-
y: str, in, float
|
|
653
|
-
Y coordinate.
|
|
654
|
-
incremental: bool
|
|
655
|
-
Add point incrementally. If True, coordinates of the added point is incremental to the last point.
|
|
656
|
-
The default value is ``False``.
|
|
657
|
-
|
|
658
|
-
Returns
|
|
659
|
-
-------
|
|
660
|
-
bool
|
|
661
|
-
"""
|
|
662
|
-
center_line = PolygonDataDotNet(self._pedb, self._edb_object.GetCenterLine())
|
|
663
|
-
center_line.add_point(x, y, incremental)
|
|
664
|
-
return self._edb_object.SetCenterLine(center_line.edb_api)
|
|
665
|
-
|
|
666
|
-
def get_center_line(self, to_string=False):
|
|
667
|
-
"""Get the center line of the trace.
|
|
668
|
-
|
|
669
|
-
Parameters
|
|
670
|
-
----------
|
|
671
|
-
to_string : bool, optional
|
|
672
|
-
Type of return. The default is ``"False"``.
|
|
673
|
-
|
|
674
|
-
Returns
|
|
675
|
-
-------
|
|
676
|
-
list
|
|
677
|
-
|
|
678
|
-
"""
|
|
679
|
-
if to_string:
|
|
680
|
-
return [[p.X.ToString(), p.Y.ToString()] for p in list(self.primitive_object.GetCenterLine().Points)]
|
|
681
|
-
else:
|
|
682
|
-
return [[p.X.ToDouble(), p.Y.ToDouble()] for p in list(self.primitive_object.GetCenterLine().Points)]
|
|
683
|
-
|
|
684
|
-
def clone(self):
|
|
685
|
-
"""Clone a primitive object with keeping same definition and location.
|
|
686
|
-
|
|
687
|
-
Returns
|
|
688
|
-
-------
|
|
689
|
-
bool
|
|
690
|
-
``True`` when successful, ``False`` when failed.
|
|
691
|
-
"""
|
|
692
|
-
center_line = self.center_line
|
|
693
|
-
width = self.width
|
|
694
|
-
corner_style = self.corner_style
|
|
695
|
-
end_cap_style = self.end_cap_style
|
|
696
|
-
cloned_path = self._app.edb_api.cell.primitive.path.create(
|
|
697
|
-
self._app.active_layout,
|
|
698
|
-
self.layer_name,
|
|
699
|
-
self.net,
|
|
700
|
-
width,
|
|
701
|
-
end_cap_style[1],
|
|
702
|
-
end_cap_style[2],
|
|
703
|
-
corner_style,
|
|
704
|
-
center_line,
|
|
705
|
-
)
|
|
706
|
-
if cloned_path:
|
|
707
|
-
return cloned_path
|
|
708
|
-
|
|
709
|
-
#
|
|
710
|
-
|
|
711
|
-
def create_edge_port(
|
|
712
|
-
self,
|
|
713
|
-
name,
|
|
714
|
-
position="End",
|
|
715
|
-
port_type="Wave",
|
|
716
|
-
reference_layer=None,
|
|
717
|
-
horizontal_extent_factor=5,
|
|
718
|
-
vertical_extent_factor=3,
|
|
719
|
-
pec_launch_width="0.01mm",
|
|
720
|
-
):
|
|
721
|
-
"""
|
|
722
|
-
|
|
723
|
-
Parameters
|
|
724
|
-
----------
|
|
725
|
-
name : str
|
|
726
|
-
Name of the port.
|
|
727
|
-
position : str, optional
|
|
728
|
-
Position of the port. The default is ``"End"``, in which case the port is created at the end of the trace.
|
|
729
|
-
Options are ``"Start"`` and ``"End"``.
|
|
730
|
-
port_type : str, optional
|
|
731
|
-
Type of the port. The default is ``"Wave"``, in which case a wave port is created. Options are ``"Wave"``
|
|
732
|
-
and ``"Gap"``.
|
|
733
|
-
reference_layer : str, optional
|
|
734
|
-
Name of the references layer. The default is ``None``. Only available for gap port.
|
|
735
|
-
horizontal_extent_factor : int, optional
|
|
736
|
-
Horizontal extent factor of the wave port. The default is ``5``.
|
|
737
|
-
vertical_extent_factor : int, optional
|
|
738
|
-
Vertical extent factor of the wave port. The default is ``3``.
|
|
739
|
-
pec_launch_width : float, str, optional
|
|
740
|
-
Perfect electrical conductor width of the wave port. The default is ``"0.01mm"``.
|
|
741
|
-
|
|
742
|
-
Returns
|
|
743
|
-
-------
|
|
744
|
-
:class:`dotnet.edb_core.edb_data.sources.ExcitationPorts`
|
|
745
|
-
|
|
746
|
-
Examples
|
|
747
|
-
--------
|
|
748
|
-
>>> edbapp = pyedb.dotnet.Edb("myproject.aedb")
|
|
749
|
-
>>> sig = appedb.modeler.create_trace([[0, 0], ["9mm", 0]], "TOP", "1mm", "SIG", "Flat", "Flat")
|
|
750
|
-
>>> sig.create_edge_port("pcb_port", "end", "Wave", None, 8, 8)
|
|
751
|
-
|
|
752
|
-
"""
|
|
753
|
-
center_line = self.get_center_line()
|
|
754
|
-
pos = center_line[-1] if position.lower() == "end" else center_line[0]
|
|
755
|
-
|
|
756
|
-
if port_type.lower() == "wave":
|
|
757
|
-
return self._app.hfss.create_wave_port(
|
|
758
|
-
self.id, pos, name, 50, horizontal_extent_factor, vertical_extent_factor, pec_launch_width
|
|
759
|
-
)
|
|
760
|
-
else:
|
|
761
|
-
return self._app.hfss.create_edge_port_vertical(self.id, pos, name, 50, reference_layer)
|
|
762
|
-
|
|
763
|
-
def create_via_fence(self, distance, gap, padstack_name, net_name="GND"):
|
|
764
|
-
"""Create via fences on both sides of the trace.
|
|
765
|
-
|
|
766
|
-
Parameters
|
|
767
|
-
----------
|
|
768
|
-
distance: str, float
|
|
769
|
-
Distance between via fence and trace center line.
|
|
770
|
-
gap: str, float
|
|
771
|
-
Gap between vias.
|
|
772
|
-
padstack_name: str
|
|
773
|
-
Name of the via padstack.
|
|
774
|
-
net_name: str, optional
|
|
775
|
-
Name of the net.
|
|
776
|
-
|
|
777
|
-
Returns
|
|
778
|
-
-------
|
|
779
|
-
"""
|
|
780
|
-
|
|
781
|
-
def getAngle(v1, v2): # pragma: no cover
|
|
782
|
-
v1_mag = math.sqrt(v1[0] ** 2 + v1[1] ** 2)
|
|
783
|
-
v2_mag = math.sqrt(v2[0] ** 2 + v2[1] ** 2)
|
|
784
|
-
dotsum = v1[0] * v2[0] + v1[1] * v2[1]
|
|
785
|
-
if v1[0] * v2[1] - v1[1] * v2[0] > 0:
|
|
786
|
-
scale = 1
|
|
787
|
-
else:
|
|
788
|
-
scale = -1
|
|
789
|
-
dtheta = scale * math.acos(dotsum / (v1_mag * v2_mag))
|
|
790
|
-
|
|
791
|
-
return dtheta
|
|
792
|
-
|
|
793
|
-
def getLocations(line, gap): # pragma: no cover
|
|
794
|
-
location = [line[0]]
|
|
795
|
-
residual = 0
|
|
796
|
-
|
|
797
|
-
for n in range(len(line) - 1):
|
|
798
|
-
x0, y0 = line[n]
|
|
799
|
-
x1, y1 = line[n + 1]
|
|
800
|
-
length = math.sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2)
|
|
801
|
-
dx, dy = (x1 - x0) / length, (y1 - y0) / length
|
|
802
|
-
x = x0 - dx * residual
|
|
803
|
-
y = y0 - dy * residual
|
|
804
|
-
length = length + residual
|
|
805
|
-
while length >= gap:
|
|
806
|
-
x += gap * dx
|
|
807
|
-
y += gap * dy
|
|
808
|
-
location.append((x, y))
|
|
809
|
-
length -= gap
|
|
810
|
-
|
|
811
|
-
residual = length
|
|
812
|
-
return location
|
|
813
|
-
|
|
814
|
-
def getParalletLines(pts, distance): # pragma: no cover
|
|
815
|
-
leftline = []
|
|
816
|
-
rightline = []
|
|
817
|
-
|
|
818
|
-
x0, y0 = pts[0]
|
|
819
|
-
x1, y1 = pts[1]
|
|
820
|
-
vector = (x1 - x0, y1 - y0)
|
|
821
|
-
orientation1 = getAngle((1, 0), vector)
|
|
822
|
-
|
|
823
|
-
leftturn = orientation1 + math.pi / 2
|
|
824
|
-
righrturn = orientation1 - math.pi / 2
|
|
825
|
-
leftPt = (x0 + distance * math.cos(leftturn), y0 + distance * math.sin(leftturn))
|
|
826
|
-
leftline.append(leftPt)
|
|
827
|
-
rightPt = (x0 + distance * math.cos(righrturn), y0 + distance * math.sin(righrturn))
|
|
828
|
-
rightline.append(rightPt)
|
|
829
|
-
|
|
830
|
-
for n in range(1, len(pts) - 1):
|
|
831
|
-
x0, y0 = pts[n - 1]
|
|
832
|
-
x1, y1 = pts[n]
|
|
833
|
-
x2, y2 = pts[n + 1]
|
|
834
|
-
|
|
835
|
-
v1 = (x1 - x0, y1 - y0)
|
|
836
|
-
v2 = (x2 - x1, y2 - y1)
|
|
837
|
-
dtheta = getAngle(v1, v2)
|
|
838
|
-
orientation1 = getAngle((1, 0), v1)
|
|
839
|
-
|
|
840
|
-
leftturn = orientation1 + dtheta / 2 + math.pi / 2
|
|
841
|
-
righrturn = orientation1 + dtheta / 2 - math.pi / 2
|
|
842
|
-
|
|
843
|
-
distance2 = distance / math.sin((math.pi - dtheta) / 2)
|
|
844
|
-
leftPt = (x1 + distance2 * math.cos(leftturn), y1 + distance2 * math.sin(leftturn))
|
|
845
|
-
leftline.append(leftPt)
|
|
846
|
-
rightPt = (x1 + distance2 * math.cos(righrturn), y1 + distance2 * math.sin(righrturn))
|
|
847
|
-
rightline.append(rightPt)
|
|
848
|
-
|
|
849
|
-
x0, y0 = pts[-2]
|
|
850
|
-
x1, y1 = pts[-1]
|
|
851
|
-
|
|
852
|
-
vector = (x1 - x0, y1 - y0)
|
|
853
|
-
orientation1 = getAngle((1, 0), vector)
|
|
854
|
-
leftturn = orientation1 + math.pi / 2
|
|
855
|
-
righrturn = orientation1 - math.pi / 2
|
|
856
|
-
leftPt = (x1 + distance * math.cos(leftturn), y1 + distance * math.sin(leftturn))
|
|
857
|
-
leftline.append(leftPt)
|
|
858
|
-
rightPt = (x1 + distance * math.cos(righrturn), y1 + distance * math.sin(righrturn))
|
|
859
|
-
rightline.append(rightPt)
|
|
860
|
-
return leftline, rightline
|
|
861
|
-
|
|
862
|
-
distance = self._pedb.edb_value(distance).ToDouble()
|
|
863
|
-
gap = self._pedb.edb_value(gap).ToDouble()
|
|
864
|
-
center_line = self.get_center_line()
|
|
865
|
-
leftline, rightline = getParalletLines(center_line, distance)
|
|
866
|
-
for x, y in getLocations(rightline, gap) + getLocations(leftline, gap):
|
|
867
|
-
self._pedb.padstacks.place([x, y], padstack_name, net_name=net_name)
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
class EdbRectangle(EDBPrimitives, RectangleDotNet):
|
|
871
|
-
def __init__(self, raw_primitive, core_app):
|
|
872
|
-
EDBPrimitives.__init__(self, raw_primitive, core_app)
|
|
873
|
-
RectangleDotNet.__init__(self, self._app, raw_primitive)
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
class EdbCircle(EDBPrimitives, CircleDotNet):
|
|
877
|
-
def __init__(self, raw_primitive, core_app):
|
|
878
|
-
EDBPrimitives.__init__(self, raw_primitive, core_app)
|
|
65
|
+
Primitive.__init__(self, core_app, raw_primitive)
|
|
879
66
|
CircleDotNet.__init__(self, self._app, raw_primitive)
|
|
880
67
|
|
|
881
68
|
|
|
882
|
-
class EdbPolygon(
|
|
69
|
+
class EdbPolygon(Primitive):
|
|
883
70
|
def __init__(self, raw_primitive, core_app):
|
|
884
|
-
|
|
885
|
-
PolygonDotNet.__init__(self, self._app, raw_primitive)
|
|
71
|
+
Primitive.__init__(self, core_app, raw_primitive)
|
|
886
72
|
|
|
887
73
|
def clone(self):
|
|
888
74
|
"""Clone a primitive object with keeping same definition and location.
|
|
@@ -892,18 +78,12 @@ class EdbPolygon(EDBPrimitives, PolygonDotNet):
|
|
|
892
78
|
bool
|
|
893
79
|
``True`` when successful, ``False`` when failed.
|
|
894
80
|
"""
|
|
895
|
-
|
|
896
|
-
self.
|
|
81
|
+
return self._pedb.modeler.create_polygon(
|
|
82
|
+
main_shape=self.polygon_data._edb_object,
|
|
83
|
+
layer_name=self.layer_name,
|
|
84
|
+
net_name=self.net_name,
|
|
85
|
+
voids=self.voids,
|
|
897
86
|
)
|
|
898
|
-
if cloned_poly:
|
|
899
|
-
for void in self.voids:
|
|
900
|
-
cloned_void = self._app.edb_api.cell.primitive.polygon.create(
|
|
901
|
-
self._app.active_layout, self.layer_name, self.net, void.polygon_data.edb_api
|
|
902
|
-
)
|
|
903
|
-
# cloned_void
|
|
904
|
-
cloned_poly.prim_obj.AddVoid(cloned_void.prim_obj)
|
|
905
|
-
return cloned_poly
|
|
906
|
-
return False
|
|
907
87
|
|
|
908
88
|
@property
|
|
909
89
|
def has_self_intersections(self):
|
|
@@ -913,7 +93,7 @@ class EdbPolygon(EDBPrimitives, PolygonDotNet):
|
|
|
913
93
|
-------
|
|
914
94
|
bool
|
|
915
95
|
"""
|
|
916
|
-
return self.polygon_data.
|
|
96
|
+
return self.polygon_data._edb_object.HasSelfIntersections()
|
|
917
97
|
|
|
918
98
|
def fix_self_intersections(self):
|
|
919
99
|
"""Remove self intersections if they exists.
|
|
@@ -925,8 +105,8 @@ class EdbPolygon(EDBPrimitives, PolygonDotNet):
|
|
|
925
105
|
"""
|
|
926
106
|
new_polys = []
|
|
927
107
|
if self.has_self_intersections:
|
|
928
|
-
new_polygons = list(self.polygon_data.
|
|
929
|
-
self.
|
|
108
|
+
new_polygons = list(self.polygon_data._edb_object.RemoveSelfIntersections())
|
|
109
|
+
self._edb_object.SetPolygonData(new_polygons[0])
|
|
930
110
|
for p in new_polygons[1:]:
|
|
931
111
|
cloned_poly = self._app.edb_api.cell.primitive.polygon.create(
|
|
932
112
|
self._app.active_layout, self.layer_name, self.net, p
|
|
@@ -949,15 +129,17 @@ class EdbPolygon(EDBPrimitives, PolygonDotNet):
|
|
|
949
129
|
"""
|
|
950
130
|
for layer in layers:
|
|
951
131
|
if layer in self._pedb.stackup.layers:
|
|
952
|
-
duplicate_polygon = self.
|
|
953
|
-
self.
|
|
132
|
+
duplicate_polygon = self._pedb.modeler.create_polygon(
|
|
133
|
+
self.polygon_data._edb_object, layer, net_name=self.net.name
|
|
954
134
|
)
|
|
955
135
|
if duplicate_polygon:
|
|
956
136
|
for void in self.voids:
|
|
957
|
-
duplicate_void = self.
|
|
958
|
-
|
|
137
|
+
duplicate_void = self._pedb.modeler.create_polygon(
|
|
138
|
+
void.polygon_data._edb_object,
|
|
139
|
+
layer,
|
|
140
|
+
net_name=self.net.name,
|
|
959
141
|
)
|
|
960
|
-
duplicate_polygon.
|
|
142
|
+
duplicate_polygon._edb_object.AddVoid(duplicate_void._edb_object)
|
|
961
143
|
else:
|
|
962
144
|
return False
|
|
963
145
|
return True
|
|
@@ -985,9 +167,11 @@ class EdbPolygon(EDBPrimitives, PolygonDotNet):
|
|
|
985
167
|
_vector = self._edb.Geometry.PointData(
|
|
986
168
|
self._edb.Utility.Value(vector[0]), self._edb.Utility.Value(vector[1])
|
|
987
169
|
)
|
|
988
|
-
polygon_data = self._edb.Geometry.PolygonData.CreateFromArcs(
|
|
170
|
+
polygon_data = self._edb.Geometry.PolygonData.CreateFromArcs(
|
|
171
|
+
self.polygon_data._edb_object.GetArcData(), True
|
|
172
|
+
)
|
|
989
173
|
polygon_data.Move(_vector)
|
|
990
|
-
return self.
|
|
174
|
+
return self._edb_object.SetPolygonData(polygon_data)
|
|
991
175
|
return False
|
|
992
176
|
|
|
993
177
|
def rotate(self, angle, center=None):
|
|
@@ -1013,18 +197,20 @@ class EdbPolygon(EDBPrimitives, PolygonDotNet):
|
|
|
1013
197
|
>>> polygon.rotate(angle=45)
|
|
1014
198
|
"""
|
|
1015
199
|
if angle:
|
|
1016
|
-
polygon_data = self._edb.Geometry.PolygonData.CreateFromArcs(
|
|
200
|
+
polygon_data = self._edb.Geometry.PolygonData.CreateFromArcs(
|
|
201
|
+
self.polygon_data._edb_object.GetArcData(), True
|
|
202
|
+
)
|
|
1017
203
|
if not center:
|
|
1018
204
|
center = polygon_data.GetBoundingCircleCenter()
|
|
1019
205
|
if center:
|
|
1020
206
|
polygon_data.Rotate(angle * math.pi / 180, center)
|
|
1021
|
-
return self.
|
|
207
|
+
return self._edb_object.SetPolygonData(polygon_data)
|
|
1022
208
|
elif isinstance(center, list) and len(center) == 2:
|
|
1023
209
|
center = self._edb.Geometry.PointData(
|
|
1024
210
|
self._edb.Utility.Value(center[0]), self._edb.Utility.Value(center[1])
|
|
1025
211
|
)
|
|
1026
212
|
polygon_data.Rotate(angle * math.pi / 180, center)
|
|
1027
|
-
return self.
|
|
213
|
+
return self._edb_object.SetPolygonData(polygon_data)
|
|
1028
214
|
return False
|
|
1029
215
|
|
|
1030
216
|
def move_layer(self, layer):
|
|
@@ -1041,7 +227,9 @@ class EdbPolygon(EDBPrimitives, PolygonDotNet):
|
|
|
1041
227
|
``True`` when successful, ``False`` when failed.
|
|
1042
228
|
"""
|
|
1043
229
|
if layer and isinstance(layer, str) and layer in self._pedb.stackup.signal_layers:
|
|
1044
|
-
polygon_data = self._edb.Geometry.PolygonData.CreateFromArcs(
|
|
230
|
+
polygon_data = self._edb.Geometry.PolygonData.CreateFromArcs(
|
|
231
|
+
self.polygon_data._edb_object.GetArcData(), True
|
|
232
|
+
)
|
|
1045
233
|
moved_polygon = self._pedb.modeler.create_polygon(
|
|
1046
234
|
main_shape=polygon_data, net_name=self.net_name, layer_name=layer
|
|
1047
235
|
)
|
|
@@ -1072,7 +260,7 @@ class EdbPolygon(EDBPrimitives, PolygonDotNet):
|
|
|
1072
260
|
point_data = self._app.edb_api.geometry.point_data(
|
|
1073
261
|
self._app.edb_value(point_data[0]), self._app.edb_value(point_data[1])
|
|
1074
262
|
)
|
|
1075
|
-
int_val = int(self.polygon_data.
|
|
263
|
+
int_val = int(self.polygon_data._edb_object.PointInPolygon(point_data))
|
|
1076
264
|
|
|
1077
265
|
# Intersection type:
|
|
1078
266
|
# 0 = objects do not intersect
|
|
@@ -1094,7 +282,7 @@ class EdbPolygon(EDBPrimitives, PolygonDotNet):
|
|
|
1094
282
|
#
|
|
1095
283
|
# Parameters
|
|
1096
284
|
# ----------
|
|
1097
|
-
# point_list : list or :class:`dotnet.edb_core.edb_data.primitives_data.
|
|
285
|
+
# point_list : list or :class:`dotnet.edb_core.edb_data.primitives_data.Primitive` or EDB Primitive Object
|
|
1098
286
|
# Point list in the format of `[[x1,y1], [x2,y2],..,[xn,yn]]`.
|
|
1099
287
|
#
|
|
1100
288
|
# Returns
|
|
@@ -1111,7 +299,7 @@ class EdbPolygon(EDBPrimitives, PolygonDotNet):
|
|
|
1111
299
|
# prim = self._app.edb_api.cell.primitive.polygon.create(
|
|
1112
300
|
# self._app.active_layout, self.layer_name, self.primitive_object.GetNet(), _poly
|
|
1113
301
|
# )
|
|
1114
|
-
# elif isinstance(point_list,
|
|
302
|
+
# elif isinstance(point_list, Primitive):
|
|
1115
303
|
# prim = point_list.primitive_object
|
|
1116
304
|
# else:
|
|
1117
305
|
# prim = point_list
|
|
@@ -1120,14 +308,14 @@ class EdbPolygon(EDBPrimitives, PolygonDotNet):
|
|
|
1120
308
|
|
|
1121
309
|
class EdbText(Primitive, TextDotNet):
|
|
1122
310
|
def __init__(self, raw_primitive, core_app):
|
|
1123
|
-
|
|
1124
|
-
TextDotNet.__init__(self, self._app
|
|
311
|
+
Primitive.__init__(self, raw_primitive, core_app)
|
|
312
|
+
TextDotNet.__init__(self, raw_primitive, self._app)
|
|
1125
313
|
|
|
1126
314
|
|
|
1127
315
|
class EdbBondwire(Primitive, BondwireDotNet):
|
|
1128
316
|
def __init__(self, raw_primitive, core_app):
|
|
1129
|
-
|
|
1130
|
-
BondwireDotNet.__init__(self, self._app
|
|
317
|
+
Primitive.__init__(self, raw_primitive, core_app)
|
|
318
|
+
BondwireDotNet.__init__(self, raw_primitive, self._app)
|
|
1131
319
|
|
|
1132
320
|
|
|
1133
321
|
class EDBArcs(object):
|
|
@@ -1160,7 +348,7 @@ class EDBArcs(object):
|
|
|
1160
348
|
|
|
1161
349
|
Examples
|
|
1162
350
|
--------
|
|
1163
|
-
>>> appedb = Edb(fpath, edbversion="2024.
|
|
351
|
+
>>> appedb = Edb(fpath, edbversion="2024.2")
|
|
1164
352
|
>>> start_coordinate = appedb.nets["V1P0_S0"].primitives[0].arcs[0].start
|
|
1165
353
|
>>> print(start_coordinate)
|
|
1166
354
|
[x_value, y_value]
|
|
@@ -1179,7 +367,7 @@ class EDBArcs(object):
|
|
|
1179
367
|
|
|
1180
368
|
Examples
|
|
1181
369
|
--------
|
|
1182
|
-
>>> appedb = Edb(fpath, edbversion="2024.
|
|
370
|
+
>>> appedb = Edb(fpath, edbversion="2024.2")
|
|
1183
371
|
>>> end_coordinate = appedb.nets["V1P0_S0"].primitives[0].arcs[0].end
|
|
1184
372
|
"""
|
|
1185
373
|
point = self.arc_object.End
|
|
@@ -1197,7 +385,7 @@ class EDBArcs(object):
|
|
|
1197
385
|
|
|
1198
386
|
Examples
|
|
1199
387
|
--------
|
|
1200
|
-
>>> appedb = Edb(fpath, edbversion="2024.
|
|
388
|
+
>>> appedb = Edb(fpath, edbversion="2024.2")
|
|
1201
389
|
>>> arc_height = appedb.nets["V1P0_S0"].primitives[0].arcs[0].height
|
|
1202
390
|
"""
|
|
1203
391
|
return self.arc_object.Height
|