pyedb 0.23.0__py3-none-any.whl → 0.25.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 (38) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/component_libraries/ansys_components.py +48 -2
  3. pyedb/configuration/cfg_operations.py +38 -4
  4. pyedb/configuration/cfg_ports_sources.py +16 -2
  5. pyedb/configuration/configuration.py +8 -0
  6. pyedb/dotnet/edb.py +39 -37
  7. pyedb/dotnet/edb_core/cell/hierarchy/hierarchy_obj.py +11 -0
  8. pyedb/dotnet/edb_core/cell/layout.py +47 -23
  9. pyedb/dotnet/edb_core/cell/layout_obj.py +0 -9
  10. pyedb/dotnet/edb_core/cell/primitive/__init__.py +3 -0
  11. pyedb/dotnet/edb_core/cell/{primitive.py → primitive/bondwire.py} +1 -146
  12. pyedb/dotnet/edb_core/cell/primitive/path.py +351 -0
  13. pyedb/dotnet/edb_core/cell/primitive/primitive.py +895 -0
  14. pyedb/dotnet/edb_core/cell/terminal/bundle_terminal.py +0 -4
  15. pyedb/dotnet/edb_core/cell/terminal/edge_terminal.py +1 -1
  16. pyedb/dotnet/edb_core/cell/terminal/terminal.py +2 -2
  17. pyedb/dotnet/edb_core/components.py +48 -25
  18. pyedb/dotnet/edb_core/dotnet/database.py +1 -23
  19. pyedb/dotnet/edb_core/dotnet/primitive.py +3 -139
  20. pyedb/dotnet/edb_core/edb_data/nets_data.py +1 -11
  21. pyedb/dotnet/edb_core/edb_data/padstacks_data.py +10 -24
  22. pyedb/dotnet/edb_core/edb_data/primitives_data.py +56 -868
  23. pyedb/dotnet/edb_core/geometry/polygon_data.py +43 -0
  24. pyedb/dotnet/edb_core/hfss.py +26 -22
  25. pyedb/dotnet/edb_core/layout_validation.py +3 -3
  26. pyedb/dotnet/edb_core/modeler.py +64 -81
  27. pyedb/dotnet/edb_core/nets.py +5 -4
  28. pyedb/dotnet/edb_core/padstack.py +12 -13
  29. pyedb/dotnet/edb_core/siwave.py +1 -1
  30. pyedb/dotnet/edb_core/stackup.py +3 -3
  31. pyedb/ipc2581/ecad/cad_data/layer_feature.py +1 -1
  32. pyedb/ipc2581/ecad/cad_data/polygon.py +2 -2
  33. pyedb/ipc2581/ecad/cad_data/step.py +2 -2
  34. pyedb/siwave.py +99 -0
  35. {pyedb-0.23.0.dist-info → pyedb-0.25.0.dist-info}/METADATA +4 -4
  36. {pyedb-0.23.0.dist-info → pyedb-0.25.0.dist-info}/RECORD +38 -35
  37. {pyedb-0.23.0.dist-info → pyedb-0.25.0.dist-info}/LICENSE +0 -0
  38. {pyedb-0.23.0.dist-info → pyedb-0.25.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
- if isinstance(raw_primitive, RectangleDotNet):
47
- return EdbRectangle(raw_primitive.prim_obj, core_app)
48
- elif isinstance(raw_primitive, PolygonDotNet):
49
- return EdbPolygon(raw_primitive.prim_obj, core_app)
50
- elif isinstance(raw_primitive, PathDotNet):
51
- return EdbPath(raw_primitive.prim_obj, core_app)
52
- elif isinstance(raw_primitive, BondwireDotNet):
53
- return EdbBondwire(raw_primitive.prim_obj, core_app)
54
- elif isinstance(raw_primitive, TextDotNet):
55
- return EdbText(raw_primitive.prim_obj, core_app)
56
- elif isinstance(raw_primitive, CircleDotNet):
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
- try:
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
- Parameters
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
- EDBPrimitives.__init__(self, raw_primitive, core_app)
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(EDBPrimitives, PolygonDotNet):
69
+ class EdbPolygon(Primitive):
883
70
  def __init__(self, raw_primitive, core_app):
884
- EDBPrimitives.__init__(self, raw_primitive, core_app)
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
- cloned_poly = self._app.edb_api.cell.primitive.polygon.create(
896
- self._app.active_layout, self.layer_name, self.net, self.polygon_data.edb_api
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.edb_api.HasSelfIntersections()
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.edb_api.RemoveSelfIntersections())
929
- self.polygon_data = new_polygons[0]
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._app.edb_api.cell.primitive.polygon.create(
953
- self._app.active_layout, layer, self.net, self.polygon_data.edb_api
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._app.edb_api.cell.primitive.polygon.create(
958
- self._app.active_layout, layer, self.net, void.polygon_data.edb_api
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.prim_obj.AddVoid(duplicate_void.prim_obj)
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(self.polygon_data.edb_api.GetArcData(), True)
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.api_object.SetPolygonData(polygon_data)
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(self.polygon_data.edb_api.GetArcData(), True)
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.api_object.SetPolygonData(polygon_data)
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.api_object.SetPolygonData(polygon_data)
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(self.polygon_data.edb_api.GetArcData(), True)
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.edb_api.PointInPolygon(point_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.EDBPrimitives` or EDB Primitive Object
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, EDBPrimitives):
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
- EDBPrimitives.__init__(self, raw_primitive, core_app)
1124
- TextDotNet.__init__(self, self._app, raw_primitive)
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
- EDBPrimitives.__init__(self, raw_primitive, core_app)
1130
- BondwireDotNet.__init__(self, self._app, raw_primitive)
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.1")
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.1")
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.1")
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