It looks like you're new here. If you want to get involved, click one of these buttons!
Hello,
I did not find anything comparable yet. The PCell Library is, from what I read here, not for scripting. So I leave this piece of code here. Hope you enjoy. I am happy for feedback.
class SimpleGeometry:
import pya as pya
import numpy as np
def __init__(self,layout):
self.dbu=layout.dbu
def circle(self,rad=1,npts=100):
"""
creates a klayout database object Polygon with points of a circle outline
origin is 0,0
units in microns
@param rad: radius 1
@type rad:float
@param npts: number of points
@return: Polygon of shape
@rtype: pya:Polygon
"""
out=[]
delta_phi=(2*np.pi)/npts
rad_dbu=int(rad/self.dbu)
for i in range(0, npts):
out.append(
Point.new(rad_dbu * np.cos(i * delta_phi),
rad_dbu * np.sin(i * delta_phi)))
return pya.Polygon.new(out)
def torus(self,rad1=10,rad2=1,start_phi=0,end_phi=90,npts=100):
"""
creates a klayout database object Polygon with points of a torus outline
origin is 0,0
units in microns
@param rad1: radius 1
@type rad1:float
@param rad2: radius 2
@type rad2:float
@param start_phi: starting angle
@param end_phi: end angle
@param npts: number of points
@return: Polygon of shape
@rtype: pya:Polygon
"""
out = []
delta_phi = ((start_phi - end_phi) / 360 * 2 * np.pi) / npts
rad1_dbu = int(rad1 / self.dbu)
rad2_dbu = int(rad2 / self.dbu)
for i in range(0, npts + 1):
out.append(
pya.Point.new(rad1_dbu * np.cos(i * delta_phi),
rad1_dbu * np.sin(i * delta_phi)))
for i in range(npts, -1, -1):
out.append(
pya.Point.new(rad2_dbu * np.cos(i * delta_phi),
rad2_dbu * np.sin(i * delta_phi)))
return pya.Polygon.new(out)
def ellipse(self,rad1=0.5,rad2=1,npts=100):
"""
creates a klayout database object Polygon with points of an ellipse outline
origin is 0,0
units in microns
@param rad1: radius 1 in x direction
@type rad1:float
@param rad2: radius 2 in y direction
@type rad2:float
@param npts: number of points
@return: Polygon of shape
@rtype: pya:Polygon
"""
out = []
delta_phi = (2 * np.pi) / npts
rad1_dbu = int(rad1 / self.dbu)
rad2_dbu = int(rad2 / self.dbu)
for i in range(0, npts):
out.append(
pya.Point.new(rad1_dbu * np.cos(i * delta_phi),
rad2_dbu * np.sin(i * delta_phi)))
return pya.Polygon.new(out)
def box(self,*args):
"""
args: width, height
Returns box object with origin at lower left corner
If only one argument is passed, a square with length of parameter 1 is returned
@param args: length in x direction, length in y direction
@type args: float
@return: box of shape
@rtype: pya:Box
"""
if len(args) < 1:
raise Exception('At least one argument is expected')
if len(args) > 2:
raise Exception('Maximum of two arguments is expected')
if len(args) < 2:
a = args[0]
b = a
else:
a = args[0]
b = args[1]
return pya.Box.new(int(0), int(0), int(a/self.dbu), int(b/self.dbu))
*edit: renamed def Box -> def box to avoid confusion with the box object
and implemented import of dependencies
Comments
@LeoPh Thank you for sharing this code!
Actually you are right, the CIRCLE PCell is way too heavy for scripting a simple circle.
But there actually is a simple solution for generating circles and ellipses:
The torus however is nice One could do that with a boolean, but coding it explicitly makes some sense here.
Plus, owning the code opens space for individual adjustments - e.g. whether the polygon provides an inner or outer approximation of the circle or whether it satisfies special tangential constraints.
Thanks,
Matthias