def test_2_DTrans(self): a = pya.DTrans() b = pya.DTrans(pya.DTrans.M135, pya.DPoint(17, 5)) ma = pya.DCplxTrans(a, 0.5) mb = pya.DCplxTrans(b, 2.0) u = pya.DCplxTrans(a) self.assertEqual(str(ma), "r0 *0.5 0,0") self.assertEqual(str(mb), "m135 *2 17,5") self.assertEqual(ma == mb, False) self.assertEqual(ma == ma, True) self.assertEqual(ma != mb, True) self.assertEqual(ma != ma, False) i = mb.inverted() self.assertEqual(str(i), "m135 *0.5 2.5,8.5") self.assertEqual(str(pya.DCplxTrans.from_s(str(i))), str(i)) self.assertEqual(i * mb == u, True) self.assertEqual(mb * i == u, True) self.assertEqual(str(mb.trans(pya.DPoint(1, 0))), "17,3") self.assertEqual(str(mb.ctrans(2)), "4.0") self.assertEqual(str(i.ctrans(2)), "1.0")
def tr_back(obj,itr=False): trs=[pya.DCplxTrans(1,0,False,-pc.x,-pc.y), pya.DCplxTrans(1,deltaangle,False,0,0)] if itr:trs=[pya.ICplxTrans.from_dtrans(tr) for tr in trs] for tr in trs: obj=obj.transformed(tr) return obj
def TurningInterpolation(self, radius): #radius非负向右,负是向左 angle = 90 delta = self.pointr.distance(self.pointl) dx = (self.pointr.x - self.pointl.x) / delta dy = (self.pointr.y - self.pointl.y) / delta dtheta = atan2(dy, dx) * 180 / pi centerx = self.pointr.x + (radius - delta / 2) * dx centery = self.pointr.y + (radius - delta / 2) * dy n = ceil(1.3 * (abs(radius) + delta / 2) * angle * pi / 180 / self.pointdistance) + 2 if True: rsgn = (radius > 0) - (radius < 0) pointr2 = pya.DPoint(centerx - rsgn * (radius - delta / 2) * dy, centery + rsgn * (radius - delta / 2) * dx) pointl2 = pya.DPoint(centerx - rsgn * (radius + delta / 2) * dy, centery + rsgn * (radius + delta / 2) * dx) arc1 = BasicPainter.arc_NewtonInterpolation( n, abs(radius) + delta / 2, abs(radius) - delta / 2) trans = pya.DCplxTrans(1, 180 + dtheta + 45 * rsgn, False, centerx, centery) arc1.transform(trans) self.outputlist.append(arc1) self.pointr = pointr2 self.pointl = pointl2
def DrawElectrode(x, y, angle, widout=20000, widin=10000, wid=368000, length=360000, midwid=200000, midlength=200000, narrowlength=120000): tr = pya.DCplxTrans(1, angle, False, x, y) pts = [] pts.append(pya.DPoint(0, widout / 2)) pts.append(pya.DPoint(0, widin / 2)) pts.append(pya.DPoint(narrowlength, midwid / 2)) pts.append(pya.DPoint(narrowlength + midlength, midwid / 2)) pts.append(pya.DPoint(narrowlength + midlength, -midwid / 2)) pts.append(pya.DPoint(narrowlength, -midwid / 2)) pts.append(pya.DPoint(0, -widin / 2)) pts.append(pya.DPoint(0, -widout / 2)) pts.append(pya.DPoint(narrowlength, -wid / 2)) pts.append(pya.DPoint(length, -wid / 2)) pts.append(pya.DPoint(length, wid / 2)) pts.append(pya.DPoint(narrowlength, wid / 2)) polygon1 = pya.DPolygon(pts).transformed(tr) return polygon1, (pya.DPoint(x, y), angle, widout, widin)
def constructors1(self, pointc=pya.DPoint(0, 0), angle=0, widout=20000, widin=10000, bgn_ext=0): tr = pya.DCplxTrans(1, angle, False, pointc) self.edgeout = pya.DEdge(0, widout / 2, 0, -widout / 2).transformed(tr) self.edgein = pya.DEdge(bgn_ext, widin / 2, bgn_ext, -widin / 2).transformed(tr)
def Narrow(self,widout,widin,length=6000): assert(self.end_ext==0) centerx,centery,angle=self.Getinfo()[0:3] tr=pya.DCplxTrans(1,angle,False,centerx,centery) edgeout=pya.DEdge(length,-widout/2,length,widout/2).transformed(tr) edgein=pya.DEdge(length,-widin/2,length,widin/2).transformed(tr) self.regionlistout.append(pya.DPolygon([self.painterout.pointl,self.painterout.pointr,edgeout.p1,edgeout.p2])) self.regionlistin.append(pya.DPolygon([self.painterin.pointl,self.painterin.pointr,edgein.p1,edgein.p2])) self.painterout.Setpoint(edgeout.p1,edgeout.p2) self.painterin.Setpoint(edgein.p1,edgein.p2) return length
def Connection(x, y=0, angle=0, mod=48): if isinstance(x, CavityBrush): brush = x tr = brush.DCplxTrans mod = brush.widout else: tr = pya.DCplxTrans(1, angle, False, x, y) pts = [] if mod == 48: pts.append(pya.DPoint(0, -57000)) pts.append(pya.DPoint(0, -8000)) pts.append(pya.DPoint(16000, -8000)) pts.append(pya.DPoint(16000, -52000)) pts.append(pya.DPoint(62000, -52000)) pts.append(pya.DPoint(62000, -32000)) pts.append(pya.DPoint(32000, -32000)) pts.append(pya.DPoint(32000, 32000)) pts.append(pya.DPoint(62000, 32000)) pts.append(pya.DPoint(62000, 52000)) pts.append(pya.DPoint(16000, 52000)) pts.append(pya.DPoint(16000, 8000)) pts.append(pya.DPoint(0, 8000)) pts.append(pya.DPoint(0, 57000)) pts.append(pya.DPoint(67000, 57000)) pts.append(pya.DPoint(67000, 27000)) pts.append(pya.DPoint(37000, 27000)) pts.append(pya.DPoint(37000, -27000)) pts.append(pya.DPoint(67000, -27000)) pts.append(pya.DPoint(67000, -57000)) if mod == 8: pts.append(pya.DPoint(0, -57000)) pts.append(pya.DPoint(0, -2010)) pts.append(pya.DPoint(224, -2007)) pts.append(pya.DPoint(2000, -2000)) pts.append(pya.DPoint(2000, -52000)) pts.append(pya.DPoint(60000, -52000)) pts.append(pya.DPoint(60000, -32000)) pts.append(pya.DPoint(6000, -32000)) pts.append(pya.DPoint(6000, 32000)) pts.append(pya.DPoint(60000, 32000)) pts.append(pya.DPoint(60000, 52000)) pts.append(pya.DPoint(2000, 52000)) pts.append(pya.DPoint(2000, 2000)) pts.append(pya.DPoint(0, 2000)) pts.append(pya.DPoint(0, 57000)) pts.append(pya.DPoint(65000, 57000)) pts.append(pya.DPoint(65000, 27000)) pts.append(pya.DPoint(11000, 27000)) pts.append(pya.DPoint(11000, -27000)) pts.append(pya.DPoint(65000, -27000)) pts.append(pya.DPoint(65000, -57000)) polygon1 = pya.DPolygon(pts).transformed(tr) return polygon1
def __init__(self,pointc=pya.DPoint(0,8000),angle=0,widout=20000,widin=10000,bgn_ext=0,end_ext=0): self.regionlistout=[] self.regionlistin=[] self.path=lambda painter:None self.bgn_ext=bgn_ext self.end_ext=end_ext tr=pya.DCplxTrans(1,angle,False,pointc) edgeout=pya.DEdge(0,-widout/2,0,widout/2).transformed(tr) edgein=pya.DEdge(bgn_ext,-widin/2,bgn_ext,widin/2).transformed(tr) self.painterout=LinePainter(edgeout.p1,edgeout.p2) self.painterin=LinePainter(edgein.p1,edgein.p2) self.centerlineinfos=[]
def test_4_Trans(self): a = pya.Trans() m = pya.CplxTrans(a, 1.1) da = pya.DTrans() dm = pya.DCplxTrans(da, 1.1) self.assertEqual(str(m), "r0 *1.1 0,0") self.assertEqual(str(pya.DCplxTrans.from_s(str(m))), str(m)) self.assertEqual(str(m.trans(pya.Point(5, -7))), "5.5,-7.7") im = pya.ICplxTrans(a, 0.5) im_old = im.dup() self.assertEqual(str(im), "r0 *0.5 0,0") self.assertEqual(str(pya.ICplxTrans.from_s(str(im))), str(im)) self.assertEqual(str(im.trans(pya.Point(5, -7))), "3,-4") im = pya.ICplxTrans(m) self.assertEqual(str(im), "r0 *1.1 0,0") self.assertEqual(str(im.trans(pya.Point(5, -7))), "6,-8") im = pya.ICplxTrans(dm) self.assertEqual(str(im), "r0 *1.1 0,0") self.assertEqual(str(im.trans(pya.Point(5, -7))), "6,-8") im.assign(im_old) self.assertEqual(str(im), "r0 *0.5 0,0") self.assertEqual(str(im.trans(pya.Point(5, -7))), "3,-4") self.assertEqual(str(pya.ICplxTrans(5, -7)), "r0 *1 5,-7") self.assertEqual(str(pya.ICplxTrans(pya.ICplxTrans.R180, 1.5, 5, -7)), "r180 *1.5 5,-7") self.assertEqual( str(pya.ICplxTrans(pya.ICplxTrans.R180, 1.5, pya.Point(5, -7))), "r180 *1.5 5,-7") self.assertEqual( str(pya.ICplxTrans(pya.ICplxTrans.R180, 1.5, pya.Vector(5, -7))), "r180 *1.5 5,-7") self.assertEqual( str(pya.ICplxTrans(pya.ICplxTrans.R180, 1.5, pya.DVector(5, -7))), "r180 *1.5 5,-7") self.assertEqual(str(pya.ICplxTrans(pya.ICplxTrans.R180, 1.5)), "r180 *1.5 0,0") c = pya.ICplxTrans.from_dtrans(pya.DCplxTrans.M135) self.assertEqual(str(c), "m135 *1 0,0") c = pya.ICplxTrans.from_trans(pya.CplxTrans.M135) self.assertEqual(str(c), "m135 *1 0,0")
def Connection(x,y,angle,mod=48): tr=pya.DCplxTrans(1,angle,False,x,y) pts=[] if mod==48: pts.append(pya.DPoint(0,-57000)) pts.append(pya.DPoint(0,-8000)) pts.append(pya.DPoint(16000,-8000)) pts.append(pya.DPoint(16000,-52000)) pts.append(pya.DPoint(62000,-52000)) pts.append(pya.DPoint(62000,-32000)) pts.append(pya.DPoint(32000,-32000)) pts.append(pya.DPoint(32000,32000)) pts.append(pya.DPoint(62000,32000)) pts.append(pya.DPoint(62000,52000)) pts.append(pya.DPoint(16000,52000)) pts.append(pya.DPoint(16000,8000)) pts.append(pya.DPoint(0,8000)) pts.append(pya.DPoint(0,57000)) pts.append(pya.DPoint(67000,57000)) pts.append(pya.DPoint(67000,27000)) pts.append(pya.DPoint(37000,27000)) pts.append(pya.DPoint(37000,-27000)) pts.append(pya.DPoint(67000,-27000)) pts.append(pya.DPoint(67000,-57000)) if mod==8: pts.append(pya.DPoint(0,-57000)) pts.append(pya.DPoint(0,-2010)) pts.append(pya.DPoint(224,-2007)) pts.append(pya.DPoint(2000,-2000)) pts.append(pya.DPoint(2000,-52000)) pts.append(pya.DPoint(60000,-52000)) pts.append(pya.DPoint(60000,-32000)) pts.append(pya.DPoint(6000,-32000)) pts.append(pya.DPoint(6000,32000)) pts.append(pya.DPoint(60000,32000)) pts.append(pya.DPoint(60000,52000)) pts.append(pya.DPoint(2000,52000)) pts.append(pya.DPoint(2000,2000)) pts.append(pya.DPoint(0,2000)) pts.append(pya.DPoint(0,57000)) pts.append(pya.DPoint(65000,57000)) pts.append(pya.DPoint(65000,27000)) pts.append(pya.DPoint(11000,27000)) pts.append(pya.DPoint(11000,-27000)) pts.append(pya.DPoint(65000,-27000)) pts.append(pya.DPoint(65000,-57000)) polygon1=pya.DPolygon(pts).transformed(tr) return polygon1
def scanBoxes(cellList=None, layerList=None, layermod='in', position='leftdown'): if cellList == None: cellList = [IO.top] if layerList == None: layerList = [(0, 1)] _layerlist = [] for ii in layerList: if type(ii) == str: if IO.layout.find_layer(ii) != None: _layerlist.append(IO.layout.find_layer(ii)) else: if IO.layout.find_layer(ii[0], ii[1]) != None: _layerlist.append(IO.layout.find_layer(ii[0], ii[1])) layers = [ index for index in IO.layout.layer_indices() if index in _layerlist ] if layermod == 'in' else [ index for index in IO.layout.layer_indices() if index not in _layerlist ] region = pya.Region() for cell in cellList: for layer in layers: s = cell.begin_shapes_rec(layer) region.insert(s) region.merge() pts = [] for polygon in region.each(): print(polygon) try: polygon = polygon.bbox() finally: pass print(polygon) pt = polygon.p1 if position == 'leftdown' else polygon.center() pts.append(pt) output = [] layer = IO.layout.layer(0, 2) cell = IO.layout.create_cell("boxMarks") IO.auxiliary.insert(pya.CellInstArray(cell.cell_index(), pya.Trans())) painter = PcellPainter() for index, pt in enumerate(pts, 1): name = "M" + str(index) painter.DrawText(cell, layer, name, pya.DCplxTrans(100, 0, False, pt.x, pt.y)) output.append([name, {"x": pt.x, "y": pt.y}]) return output
def TurningInterpolation(self, radius, angle=90): #有待改进 #radius非负向右,负是向左 pass if angle < 0: angle = -angle radius = -radius angle = 90 delta = self.pointr.distance(self.pointl) dx = (self.pointr.x - self.pointl.x) / delta dy = (self.pointr.y - self.pointl.y) / delta dtheta = atan2(dy, dx) * 180 / pi centerx = self.pointr.x + (radius - delta / 2) * dx centery = self.pointr.y + (radius - delta / 2) * dy n = int( ceil(1.3 * (abs(radius) + delta / 2) * angle * pi / 180 / IO.pointdistance) + 2) # rsgn = (radius > 0) - (radius < 0) pointr2 = pya.DPoint(centerx - rsgn * (radius - delta / 2) * dy, centery + rsgn * (radius - delta / 2) * dx) pointl2 = pya.DPoint(centerx - rsgn * (radius + delta / 2) * dy, centery + rsgn * (radius + delta / 2) * dx) pts1 = BasicPainter.arc_NewtonInterpolation(n, abs(radius) + delta / 2) pts2 = BasicPainter.arc_NewtonInterpolation(n, abs(radius) - delta / 2) pts1.extend(reversed(pts2)) arc1 = pya.DPolygon(pts1) trans = pya.DCplxTrans(1, 180 + dtheta + 45 * rsgn, False, centerx, centery) arc1.transform(trans) self.outputlist.append(arc1) self.pointr = pointr2 self.pointl = pointl2 pts3 = BasicPainter.arc_NewtonInterpolation(n, abs(radius)) cpts = [ pya.DEdge(pya.DPoint(), pt).transformed(trans).p2 for pt in pts3 ] if abs(cpts[-1].distance(self.pointr) - delta / 2) < IO.pointdistance: if self.centerlinepts == []: self.centerlinepts = cpts else: self.centerlinepts.extend(cpts[1:]) else: if self.centerlinepts == []: self.centerlinepts = cpts[::-1] else: self.centerlinepts.extend(cpts[-2::-1]) return pi * 0.5 * abs(radius)
def test_5_CplxTrans_Hash(self): t1 = pya.DCplxTrans(pya.DTrans(pya.DTrans.M135, pya.DPoint(17, 5)), 1.0) t2a = pya.DCplxTrans( pya.DTrans(pya.DTrans.M135, pya.DPoint(17 + 1e-7, 5)), 1.0) t2b = pya.DCplxTrans(pya.DTrans(pya.DTrans.M135, pya.DPoint(17, 5)), 1.0 + 1e-11) t2c = pya.DCplxTrans(pya.DTrans(pya.DTrans.M135, pya.DPoint(17, 5)), 1.0) t2c.angle = t2c.angle + 1e-11 t3a = pya.DCplxTrans( pya.DTrans(pya.DTrans.M135, pya.DPoint(17 + 1e-4, 5)), 1.0) t3b = pya.DCplxTrans(pya.DTrans(pya.DTrans.M135, pya.DPoint(17, 5)), 1.0 + 1e-4) t3c = pya.DCplxTrans(pya.DTrans(pya.DTrans.M135, pya.DPoint(17, 5)), 1.0) t3c.angle = t3c.angle + 1e-4 t4 = pya.DCplxTrans(pya.DTrans(pya.DTrans.R90, pya.DPoint(18, 5)), 1.0) self.assertEqual(t1.hash() == t2a.hash(), True) self.assertEqual(t1.hash() == t2b.hash(), True) self.assertEqual(t1.hash() == t2c.hash(), True) self.assertEqual(t1.hash() == t3a.hash(), False) self.assertEqual(t1.hash() == t3b.hash(), False) self.assertEqual(t1.hash() == t3c.hash(), False) self.assertEqual(t3a.hash() == t3b.hash(), False) self.assertEqual(t3a.hash() == t3c.hash(), False) self.assertEqual(t3b.hash() == t3c.hash(), False) self.assertEqual(t1.hash() == t4.hash(), False) # Transformations can't be used as hash keys currently if False: h = {t1: "t1", t3a: "t3a", t3b: "t3b", t3c: "t3c", t4: "t4"} self.assertEqual(h[t1], "t1") self.assertEqual(h[t2a], "t1") self.assertEqual(h[t2b], "t1") self.assertEqual(h[t2c], "t1") self.assertEqual(h[t3a], "t3a") self.assertEqual(h[t3b], "t3b") self.assertEqual(h[t3c], "t3c") self.assertEqual(h[t4], "t4")
def Connection(x, widin=16000, widout=114000, linewid=5000, slength1=16000, slength2=16000, clength=30000, cwid=54000, y=0, angle=0): if isinstance(x, CavityBrush): brush = x tr = brush.DCplxTrans else: tr = pya.DCplxTrans(1, angle, False, x, y) pts = [ pya.DPoint(0, widin / 2), pya.DPoint(slength1, widin / 2), pya.DPoint(slength1, widout / 2 - linewid), pya.DPoint(slength1 + slength2 + clength, widout / 2 - linewid), pya.DPoint(slength1 + slength2 + clength, cwid / 2 + linewid), pya.DPoint(slength1 + slength2, cwid / 2 + linewid), # pya.DPoint(slength1 + slength2, -(cwid / 2 + linewid)), pya.DPoint(slength1 + slength2 + clength, -(cwid / 2 + linewid)), pya.DPoint(slength1 + slength2 + clength, -(widout / 2 - linewid)), pya.DPoint(slength1, -(widout / 2 - linewid)), pya.DPoint(slength1, -widin / 2), pya.DPoint(0, -widin / 2), # pya.DPoint(0, -widout / 2), pya.DPoint(slength1 + slength2 + clength + linewid, -widout / 2), pya.DPoint(slength1 + slength2 + clength + linewid, -cwid / 2), pya.DPoint(slength1 + slength2 + linewid, -cwid / 2), # pya.DPoint(slength1 + slength2 + linewid, cwid / 2), pya.DPoint(slength1 + slength2 + clength + linewid, cwid / 2), pya.DPoint(slength1 + slength2 + clength + linewid, widout / 2), pya.DPoint(0, widout / 2), ] polygon1 = pya.DPolygon(pts).transformed(tr) return polygon1
def move(self, x: float = 0, y: float = 0, rot: int = 0, mirrx: bool = False, mag: float = 1): """Moves an instance. Units of microns relative to origin. :param x: x position where to move :type x: float :param y: y position where to move :type y: float :param rot: Rotation of the object in degrees :type rot: int :param mirrx: Mirror at x-axis if True :type mirrx: bool :param mag: Magnification of the Cell. This feature is not tested well. :type mag: float """ if self.connection: raise ValueError( 'Cannot connect to a port of another instance and move the same instance. These operations are mutually exlusive' ) self.movement = pya.DCplxTrans(mag, rot, mirrx, x, y)
] polygon1 = pya.Polygon(pts) top.shapes(l1).insert(polygon1) #DPath dpts = [ pya.DPoint(0.4, 0), pya.DPoint(50, 0), pya.DPoint(50, 50), pya.DPoint(40.5, 60.6), pya.DPoint(0, 50) ] dpath1 = pya.DPath(dpts, 4, 5, 0, True) top.shapes(l1).insert(pya.Path.from_dpath(dpath1)) #DCplxTrans #倍数,逆时针度数,是否绕x翻转,平移x,平移y tr = pya.DCplxTrans(10, 45, False, 1000, 1000) #xxx.transform(tr)#本身改变 #xxx.transformed(tr)本身不变返回新的 #对一个点pt做变换的方法 #pya.DEdge(pya.DPoint(),pt).transformed(DCplxTrans).p2 #DText text1 = pya.DText("TEST_Text", pya.DTrans(-10, -10), 100, 1) top.shapes(l1).insert(pya.Text.from_dtext(text1)) #a text can be printed @ruby #it dose not work in python #lib.layout.pcell_declaration can't be found ''' begin ly = RBA::Layout.new top = ly.add_cell("TOP")
def test_1_DPolygon(self): a = pya.DPolygon() self.assertEqual( str(a), "()" ) self.assertEqual( str(pya.DPolygon.from_s(str(a))), str(a) ) self.assertEqual( a.is_box(), False ) b = a.dup() a = pya.DPolygon( [ pya.DPoint( 0, 1 ), pya.DPoint( 1, 5 ), pya.DPoint( 5, 5 ) ] ) self.assertEqual( str(a), "(0,1;1,5;5,5)" ) self.assertEqual( str(a * 2), "(0,2;2,10;10,10)" ) self.assertEqual( str(pya.DPolygon.from_s(str(a))), str(a) ) self.assertEqual( a.is_box(), False ) self.assertEqual( a.num_points_hull(), 3 ) c = a.dup() self.assertEqual( a == b, False ) self.assertEqual( a == c, True ) self.assertEqual( a != b, True ) self.assertEqual( a != c, False ) a = pya.DPolygon( pya.DBox( 5, -10, 20, 15 ) ) self.assertEqual( a.is_box(), True ) self.assertEqual( str(a), "(5,-10;5,15;20,15;20,-10)" ) self.assertEqual( str(pya.Polygon(a)), "(5,-10;5,15;20,15;20,-10)" ) self.assertEqual( a.num_points_hull(), 4 ) self.assertEqual( a.area(), 15*25 ) self.assertEqual( a.perimeter(), 80 ) self.assertEqual( a.inside( pya.DPoint( 10, 0 ) ), True ) self.assertEqual( a.inside( pya.DPoint( 5, 0 ) ), True ) self.assertEqual( a.inside( pya.DPoint( 30, 0 ) ), False ) arr = [] for p in a.each_point_hull(): arr.append( str(p) ) self.assertEqual( arr, ["5,-10", "5,15", "20,15", "20,-10"] ) b = a.dup() self.assertEqual( str(a.moved( pya.DPoint( 0, 1 ) )), "(5,-9;5,16;20,16;20,-9)" ) self.assertEqual( str(a.moved( 0, 1 )), "(5,-9;5,16;20,16;20,-9)" ) aa = a.dup() aa.move( 1, 0 ) self.assertEqual( str(aa), "(6,-10;6,15;21,15;21,-10)" ) a.move( pya.DPoint( 1, 0 ) ) self.assertEqual( str(a), "(6,-10;6,15;21,15;21,-10)" ) b = b.transformed( pya.DTrans( pya.DTrans.R0, pya.DPoint( 1, 0 )) ) self.assertEqual( str(b), "(6,-10;6,15;21,15;21,-10)" ) m = pya.DCplxTrans( pya.DTrans(), 1.5 ) self.assertEqual( type(a.transformed(m)).__name__, "DPolygon" ) self.assertEqual( str(a.transformed(m)), "(9,-15;9,22.5;31.5,22.5;31.5,-15)" ) m = pya.VCplxTrans( 1000.0 ) self.assertEqual( type(a.transformed(m)).__name__, "Polygon" ) self.assertEqual( str(a.transformed(m)), "(6000,-10000;6000,15000;21000,15000;21000,-10000)" ) a.hull = [ pya.DPoint( 0, 1 ), pya.DPoint( 1, 1 ), pya.DPoint( 1, 5 ) ] self.assertEqual( str(a.bbox()), "(0,1;1,5)" ) self.assertEqual( a.holes(), 0 ) a.insert_hole( [ pya.DPoint( 1, 2 ), pya.DPoint( 2, 2 ), pya.DPoint( 2, 6 ) ] ) self.assertEqual( str(a), "(0,1;1,5;1,1/1,2;2,2;2,6)" ) self.assertEqual( str(pya.DPolygon.from_s(str(a))), str(a) ) self.assertEqual( a.area(), 0 ) self.assertEqual( a.num_points_hole(0), 3 ) self.assertEqual( a.holes(), 1 ) self.assertEqual( str(a.point_hull(1)), "1,5" ) self.assertEqual( str(a.point_hull(0)), "0,1" ) self.assertEqual( str(a.point_hull(100)), "0,0" ) self.assertEqual( str(a.point_hole(0, 100)), "0,0" ) self.assertEqual( str(a.point_hole(0, 1)), "2,2" ) self.assertEqual( str(a.point_hole(1, 1)), "0,0" ) a.compress(False); self.assertEqual( str(a), "(0,1;1,5;1,1/1,2;2,2;2,6)" ) a.compress(True); self.assertEqual( str(a), "(0,1;1,5;1,1/1,2;2,2;2,6)" ) b = a.dup() b.assign_hole(0, pya.DBox( 10, 20, 20, 60 )) self.assertEqual( str(b), "(0,1;1,5;1,1/10,20;20,20;20,60;10,60)" ) b.insert_hole(pya.DBox( 10, 20, 20, 60 )) self.assertEqual( str(b), "(0,1;1,5;1,1/10,20;20,20;20,60;10,60/10,20;20,20;20,60;10,60)" ) self.assertEqual( b.is_box(), False ) b = a.dup() b.assign_hole(0, [ pya.DPoint( 10, 20 ), pya.DPoint( 20, 20 ), pya.DPoint( 20, 60 ) ]) self.assertEqual( str(b), "(0,1;1,5;1,1/10,20;20,20;20,60)" ) b.assign_hole(1, [ pya.DPoint( 15, 25 ), pya.DPoint( 25, 25 ), pya.DPoint( 25, 65 ) ]) self.assertEqual( str(b), "(0,1;1,5;1,1/10,20;20,20;20,60)" ) b.insert_hole( [ pya.DPoint( 1, 2 ), pya.DPoint( 2, 2 ), pya.DPoint( 2, 6 ) ] ) self.assertEqual( str(b), "(0,1;1,5;1,1/1,2;2,2;2,6/10,20;20,20;20,60)" ) b.assign_hole(0, [ pya.DPoint( 15, 25 ), pya.DPoint( 25, 25 ), pya.DPoint( 25, 65 ) ]) self.assertEqual( str(b), "(0,1;1,5;1,1/15,25;25,25;25,65/10,20;20,20;20,60)" ) arr = [] for p in a.each_point_hole(0): arr.append( str(p) ) self.assertEqual( arr, ["1,2", "2,2", "2,6"] ) arr = [] for p in a.each_edge(): arr.append( str(p) ) self.assertEqual( arr, ["(0,1;1,5)", "(1,5;1,1)", "(1,1;0,1)", "(1,2;2,2)", "(2,2;2,6)", "(2,6;1,2)"] ) # Ellipse constructor p = pya.DPolygon.ellipse( pya.DBox(-10000, -20000, 30000, 40000), 200 ) self.assertEqual(p.num_points(), 200) self.assertEqual(str(p.bbox()), "(-10000,-20000;30000,40000)") self.assertEqual(int(p.area()), 1884645544) # roughly box.area*PI/4 p = pya.DPolygon.ellipse( pya.DBox(-10000, -20000, 30000, 40000), 4 ) self.assertEqual(str(p), "(10000,-20000;-10000,10000;10000,40000;30000,10000)")
def Connection(x, widin=16000, widout=114000, linewid=5000, slength1=16000, slength2=16000, clength=30000, cwid=54000, clengthplus=0, turningRadiusPlus=5000, y=0, angle=0): ''' 画腔到比特的连接(更复杂的版本),第一个参数是笔刷或坐标,返回图形 ''' if isinstance(x, CavityBrush): brush = x tr = brush.DCplxTrans else: tr = pya.DCplxTrans(1, angle, False, x, y) oldpointdistance = IO.pointdistance IO.pointdistance = max(100, int(IO.pointdistance / 10)) try: rp = turningRadiusPlus r = turningRadiusPlus + linewid / 2 polygons = [] pts = [ pya.DPoint(0, widin / 2), pya.DPoint(slength1, widin / 2), pya.DPoint(slength1, widout / 2), pya.DPoint(0, widout / 2), ] polygons.append(pya.DPolygon(pts)) pts = [ pya.DPoint(0, -widin / 2), pya.DPoint(slength1, -widin / 2), pya.DPoint(slength1, -widout / 2), pya.DPoint(0, -widout / 2), ] polygons.append(pya.DPolygon(pts)) dx = widout / 2 - cwid / 2 - 2 * linewid tangle = 90 - atan2(clengthplus, dx) * 180 / pi lp = LinePainter(pointl=pya.DPoint(slength1, widout / 2), pointr=pya.DPoint(slength1, widout / 2 - linewid)) # lp._Straight(-1) lp._Straight(1) # lp.Straight(slength2 + clength - rp * tan(tangle / 2 * pi / 180)) lp.Turning(r, tangle) lp.Straight(-rp * tan(tangle / 2 * pi / 180) + dx / sin(tangle * pi / 180) - rp / tan(tangle / 2 * pi / 180)) lp.Turning(r, 180 - tangle) lp.Straight(-rp / tan(tangle / 2 * pi / 180) + clengthplus + clength - linewid) # lp.Turning(-linewid / 2, 90) lp._Straight(-linewid) lp.Straight(linewid + cwid) lp.Turning(-linewid / 2, 90) lp._Straight(-linewid) lp.Straight(linewid) # lp.Straight(-rp / tan(tangle / 2 * pi / 180) + clengthplus + clength - linewid) lp.Turning(r, 180 - tangle) lp.Straight(-rp * tan(tangle / 2 * pi / 180) + dx / sin(tangle * pi / 180) - rp / tan(tangle / 2 * pi / 180)) lp.Turning(r, tangle) lp.Straight(slength2 + clength - rp * tan(tangle / 2 * pi / 180)) # lp._Straight(1) lp._Straight(-1) # polygons.extend(lp.outputlist) except: raise finally: IO.pointdistance = oldpointdistance return [p.transformed(tr) for p in polygons]
def test_5_CplxTrans_FuzzyCompare(self): t1 = pya.DCplxTrans(pya.DTrans(pya.DTrans.M135, pya.DPoint(17, 5)), 1.0) t2a = pya.DCplxTrans( pya.DTrans(pya.DTrans.M135, pya.DPoint(17 + 1e-7, 5)), 1.0) t2b = pya.DCplxTrans(pya.DTrans(pya.DTrans.M135, pya.DPoint(17, 5)), 1.0 + 1e-11) t2c = pya.DCplxTrans(pya.DTrans(pya.DTrans.M135, pya.DPoint(17, 5)), 1.0) t2c.angle = t2c.angle + 1e-11 t3a = pya.DCplxTrans( pya.DTrans(pya.DTrans.M135, pya.DPoint(17 + 1e-4, 5)), 1.0) t3b = pya.DCplxTrans(pya.DTrans(pya.DTrans.M135, pya.DPoint(17, 5)), 1.0 + 1e-4) t3c = pya.DCplxTrans(pya.DTrans(pya.DTrans.M135, pya.DPoint(17, 5)), 1.0) t3c.angle = t3c.angle + 1e-4 t4 = pya.DCplxTrans(pya.DTrans(pya.DTrans.R90, pya.DPoint(18, 5)), 1.0) self.assertEqual(t1 == t2a, True) self.assertEqual(t1 != t2a, False) self.assertEqual(t1 < t2a, False) self.assertEqual(t2a < t1, False) self.assertEqual(t1 == t2b, True) self.assertEqual(t1 != t2b, False) self.assertEqual(t1 < t2b, False) self.assertEqual(t2b < t1, False) self.assertEqual(t1 == t2c, True) self.assertEqual(t1 != t2c, False) self.assertEqual(t1 < t2c, False) self.assertEqual(t2c < t1, False) self.assertEqual(t1 == t3a, False) self.assertEqual(t1 != t3a, True) self.assertEqual(t1 < t3a, True) self.assertEqual(t3a < t1, False) self.assertEqual(t1 == t3b, False) self.assertEqual(t1 != t3b, True) self.assertEqual(t1 < t3b, False) self.assertEqual(t3b < t1, True) self.assertEqual(t1 == t3c, False) self.assertEqual(t1 != t3c, True) self.assertEqual(t1 < t3c, True) self.assertEqual(t3c < t1, False) self.assertEqual(t3a == t3b, False) self.assertEqual(t3a != t3b, True) self.assertEqual(t3a < t3b, False) self.assertEqual(t3b < t3a, True) self.assertEqual(t3a == t3c, False) self.assertEqual(t3a != t3c, True) self.assertEqual(t3a < t3c, False) self.assertEqual(t3c < t3a, True) self.assertEqual(t3b == t3c, False) self.assertEqual(t3b != t3c, True) self.assertEqual(t3b < t3c, True) self.assertEqual(t3c < t3b, False) self.assertEqual(t1 == t4, False) self.assertEqual(t1 != t4, True) self.assertEqual(t1 < t4, True) self.assertEqual(t4 < t1, False)
width = 8000 height = 28000 filename = 'abc.gds' outputfile = '' if noguitest: layout, top = paintlib.IO.Start("gds") else: layout, top = paintlib.IO.Start("guiopen") layout.dbu = 0.001 # 设置单位长度为1nm paintlib.IO.pointdistance = 1000 paintlib.IO.SetWoringDir(__file__) if noguitest: painter = paintlib.TransfilePainter(filename=filename) painter.DrawGds(top, 'sourcefile', pya.DCplxTrans()) def extractABFromGDS(sourceLayerList=[(2, 0)]): output = [] layers = paintlib.Collision.getLayers(layerList=sourceLayerList, layermod='in') for layer in layers: it = paintlib.IO.top.begin_shapes_rec(layer) while not it.at_end(): shape_ = it.shape() area_ = shape_.area() if width * height * 0.98 < area_ < width * height * 1.02: # return shape_ r = dict(
def test_3_DTrans(self): c = pya.DCplxTrans(5.0, -7.0) self.assertEqual(str(c), "r0 *1 5,-7") c = pya.DCplxTrans(pya.DCplxTrans.M135) self.assertEqual(str(c), "m135 *1 0,0") self.assertEqual(c.is_unity(), False) self.assertEqual(c.is_ortho(), True) self.assertEqual(c.is_mag(), False) self.assertEqual(c.is_mirror(), True) self.assertEqual(c.rot(), pya.DCplxTrans.M135.rot()) self.assertEqual(str(c.s_trans()), "m135 0,0") self.assertAlmostEqual(c.angle, 270) self.assertEqual(str(c.trans(pya.DEdge(0, 1, 2, 3))), "(-3,-2;-1,0)") self.assertEqual(str((c * pya.DEdge(0, 1, 2, 3))), "(-3,-2;-1,0)") self.assertEqual(str(c.trans(pya.DBox(0, 1, 2, 3))), "(-3,-2;-1,0)") self.assertEqual(str((c * pya.DBox(0, 1, 2, 3))), "(-3,-2;-1,0)") self.assertEqual(str(c.trans(pya.DText("text", pya.DVector(0, 1)))), "('text',m135 -1,0)") self.assertEqual(str((c * pya.DText("text", pya.DVector(0, 1)))), "('text',m135 -1,0)") self.assertEqual( str( c.trans( pya.DPolygon([ pya.DPoint(0, 1), pya.DPoint(2, -3), pya.DPoint(4, 5) ]))), "(-5,-4;-1,0;3,-2)") self.assertEqual( str((c * pya.DPolygon( [pya.DPoint(0, 1), pya.DPoint(2, -3), pya.DPoint(4, 5)]))), "(-5,-4;-1,0;3,-2)") self.assertEqual( str(c.trans(pya.DPath( [pya.DPoint(0, 1), pya.DPoint(2, 3)], 10))), "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false") self.assertEqual( str((c * pya.DPath( [pya.DPoint(0, 1), pya.DPoint(2, 3)], 10))), "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false") c = pya.DCplxTrans.from_itrans(pya.CplxTrans.M135) self.assertEqual(str(c), "m135 *1 0,0") c = pya.DCplxTrans(1.5) self.assertEqual(str(c), "r0 *1.5 0,0") self.assertEqual(c.is_unity(), False) self.assertEqual(c.is_ortho(), True) self.assertEqual(c.is_mag(), True) self.assertEqual(c.is_mirror(), False) self.assertEqual(c.rot(), pya.DCplxTrans.R0.rot()) self.assertEqual(str(c.s_trans()), "r0 0,0") self.assertAlmostEqual(c.angle, 0) c = pya.DCplxTrans(0.75, 45, True, 2.5, -12.5) self.assertEqual(str(c), "m22.5 *0.75 2.5,-12.5") c = pya.DCplxTrans(0.75, 45, True, pya.DPoint(2.5, -12.5)) self.assertEqual(str(c), "m22.5 *0.75 2.5,-12.5") self.assertEqual(c.is_unity(), False) self.assertEqual(c.is_ortho(), False) self.assertEqual(c.is_mag(), True) self.assertEqual(c.rot(), pya.DCplxTrans.M0.rot()) self.assertEqual(str(c.s_trans()), "m0 2.5,-12.5") self.assertAlmostEqual(c.angle, 45) self.assertEqual(str(c.ctrans(5)), "3.75") self.assertEqual(str(c.trans(pya.DPoint(12, 16))), "17.3492424049,-14.6213203436") self.assertEqual(str(pya.DCplxTrans()), "r0 *1 0,0") self.assertEqual(pya.DCplxTrans().is_unity(), True) self.assertEqual((c * c.inverted()).is_unity(), True) c.mirror = False self.assertEqual(str(c), "r45 *0.75 2.5,-12.5") c.mag = 1.5 self.assertEqual(str(c), "r45 *1.5 2.5,-12.5") c.disp = pya.DPoint(-1.0, 5.5) self.assertEqual(str(c), "r45 *1.5 -1,5.5") self.assertEqual(c.mag, 1.5) c.angle = 60 self.assertEqual(str(c), "r60 *1.5 -1,5.5") self.assertEqual(("%g" % c.angle), "60") # Constructor variations self.assertEqual(str(pya.ICplxTrans()), "r0 *1 0,0") self.assertEqual(str(pya.ICplxTrans(1.5)), "r0 *1.5 0,0") self.assertEqual(str(pya.ICplxTrans(pya.Trans(1, False, 10, 20), 1.5)), "r90 *1.5 10,20") self.assertEqual(str(pya.ICplxTrans(pya.Trans(1, False, 10, 20))), "r90 *1 10,20") self.assertEqual( str(pya.ICplxTrans(1.5, 80, True, pya.Vector(100, 200))), "m40 *1.5 100,200") self.assertEqual(str(pya.ICplxTrans(1.5, 80, True, 100, 200)), "m40 *1.5 100,200") self.assertEqual(str(pya.ICplxTrans(pya.Vector(100, 200))), "r0 *1 100,200") self.assertEqual(str(pya.ICplxTrans(100, 200)), "r0 *1 100,200") self.assertEqual(str(pya.ICplxTrans(pya.ICplxTrans(100, 200))), "r0 *1 100,200") self.assertEqual(str(pya.ICplxTrans(pya.ICplxTrans(100, 200), 1.5)), "r0 *1.5 150,300") self.assertEqual( str( pya.ICplxTrans(pya.ICplxTrans(100, 200), 1.5, pya.Vector(10, 20))), "r0 *1.5 160,320") self.assertEqual( str(pya.ICplxTrans(pya.ICplxTrans(100, 200), 1.5, 10, 20)), "r0 *1.5 160,320") self.assertEqual(str(pya.DCplxTrans()), "r0 *1 0,0") self.assertEqual(str(pya.DCplxTrans(1.5)), "r0 *1.5 0,0") self.assertEqual( str(pya.DCplxTrans(pya.DTrans(1, False, 0.01, 0.02), 1.5)), "r90 *1.5 0.01,0.02") self.assertEqual(str(pya.DCplxTrans(pya.DTrans(1, False, 0.01, 0.02))), "r90 *1 0.01,0.02") self.assertEqual( str(pya.DCplxTrans(1.5, 80, True, pya.DVector(0.1, 0.2))), "m40 *1.5 0.1,0.2") self.assertEqual(str(pya.DCplxTrans(1.5, 80, True, 0.1, 0.2)), "m40 *1.5 0.1,0.2") self.assertEqual(str(pya.DCplxTrans(pya.DVector(0.1, 0.2))), "r0 *1 0.1,0.2") self.assertEqual(str(pya.DCplxTrans(0.1, 0.2)), "r0 *1 0.1,0.2") self.assertEqual(str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2))), "r0 *1 0.1,0.2") self.assertEqual(str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2), 1.5)), "r0 *1.5 0.15,0.3") self.assertEqual( str( pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2), 1.5, pya.DVector(0.01, 0.02))), "r0 *1.5 0.16,0.32") self.assertEqual( str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2), 1.5, 0.01, 0.02)), "r0 *1.5 0.16,0.32")
import paintlib layout, top = paintlib.IO.Start("guinew") # 在当前的图上继续画,如果没有就创建一个新的 layout.dbu = 0.001 # 设置单位长度为1nm paintlib.IO.pointdistance = 1000 # 设置腔的精度,转弯处相邻两点的距离 paintlib.IO.SetWoringDir(__file__) TBD = paintlib.TBD.init(6876587) filepath = paintlib.IO.path + '/demos/' # %% layer = layout.layer(10, 10) layer1 = layout.layer(10, 3) layer2 = layout.layer(10, 2) painter6 = paintlib.TransfilePainter(filepath + "CascadeRoutePaths.gds") tr = pya.DCplxTrans(1, 0, False, 0, 0) painter6.DrawGds(top, "layout0", tr) cell = layout.create_cell("border") top.insert(pya.CellInstArray(cell.cell_index(), pya.Trans(0, 400000))) border = paintlib.BasicPainter.Border(leng=4550000, siz=4550000, wed=50000) paintlib.BasicPainter.Draw(cell, layout.layer(0, 3), border) cell = layout.create_cell("lines") top.insert(pya.CellInstArray(cell.cell_index(), pya.Trans())) inputs = [{ "section": "Filter1", "PositionIn": [-2647, 3324, 180, "5105"], "PositionOut": [0, 3310, 90, "5105"]
layer1, paintlib.CavityBrush(pointc=pya.DPoint(800000, -70000), angle=0, widout=24000, widin=8000, bgn_ext=0), xfunc, yfunc, pointnumber=100, startlength=10000, deltalength=100000, number=10, lengthlist=[50000, 40000, 5000, 40000, 20000]) paintlib.PcellPainter().DrawText(cell5, layer2, "y=10*x*(x-0.333)*(x-0.6666)*(x-1)", pya.DCplxTrans(30, 25, False, 800000, 0)) # def getSpiralFunc(a, angle0, angle1): from math import cos, sin, pi, sqrt def f(t): return (angle0 * (1 - t) + angle1 * t) / 180 * pi def xfunc(t): theta = f(t) return a * sqrt(abs(theta)) * cos(theta) * (-1 if theta < 0 else 1) def yfunc(t): theta = f(t)
def test_2_ShapesFromNet(self): ut_testsrc = os.getenv("TESTSRC") ly = pya.Layout() ly.read( os.path.join(ut_testsrc, "testdata", "algo", "device_extract_l1_with_inv_nodes.gds")) l2n = pya.LayoutToNetlist( pya.RecursiveShapeIterator(ly, ly.top_cell(), [])) # only plain backend connectivity rmetal1 = l2n.make_polygon_layer(ly.layer(6, 0), "metal1") rmetal1_lbl = l2n.make_text_layer(ly.layer(6, 1), "metal1_lbl") rvia1 = l2n.make_polygon_layer(ly.layer(7, 0), "via1") rmetal2 = l2n.make_polygon_layer(ly.layer(8, 0), "metal2") rmetal2_lbl = l2n.make_text_layer(ly.layer(8, 1), "metal2_lbl") # Intra-layer l2n.connect(rmetal1) l2n.connect(rvia1) l2n.connect(rmetal2) # Inter-layer l2n.connect(rmetal1, rvia1) l2n.connect(rvia1, rmetal2) l2n.connect(rmetal1, rmetal1_lbl) # attaches labels l2n.connect(rmetal2, rmetal2_lbl) # attaches labels # Perform netlist extraction l2n.extract_netlist() self.assertEqual( str(l2n.netlist()), """circuit TRANS ($1=$1,$2=$2); end; circuit INV2 (OUT=OUT,$2=$3,$3=$4); subcircuit TRANS $1 ($1=$4,$2=OUT); subcircuit TRANS $2 ($1=$3,$2=OUT); subcircuit TRANS $3 ($1=$2,$2=$4); subcircuit TRANS $4 ($1=$2,$2=$3); end; circuit RINGO (); subcircuit INV2 $1 (OUT='FB,OSC',$2=VSS,$3=VDD); subcircuit INV2 $2 (OUT=$I20,$2=VSS,$3=VDD); subcircuit INV2 $3 (OUT=$I19,$2=VSS,$3=VDD); subcircuit INV2 $4 (OUT=$I21,$2=VSS,$3=VDD); subcircuit INV2 $5 (OUT=$I22,$2=VSS,$3=VDD); subcircuit INV2 $6 (OUT=$I23,$2=VSS,$3=VDD); subcircuit INV2 $7 (OUT=$I24,$2=VSS,$3=VDD); subcircuit INV2 $8 (OUT=$I25,$2=VSS,$3=VDD); subcircuit INV2 $9 (OUT=$I26,$2=VSS,$3=VDD); subcircuit INV2 $10 (OUT=$I27,$2=VSS,$3=VDD); end; """) self.assertEqual(str(l2n.probe_net(rmetal2, pya.DPoint(0.0, 1.8))), "RINGO:FB,OSC") sc_path = [] self.assertEqual( str(l2n.probe_net(rmetal2, pya.DPoint(0.0, 1.8), sc_path)), "RINGO:FB,OSC") self.assertEqual(len(sc_path), 0) self.assertEqual(repr(l2n.probe_net(rmetal2, pya.DPoint(-2.0, 1.8))), "None") n = l2n.probe_net(rmetal1, pya.Point(2600, 1000), None) self.assertEqual(str(n), "INV2:$2") sc_path = [] n = l2n.probe_net(rmetal1, pya.Point(2600, 1000), sc_path) self.assertEqual(str(n), "INV2:$2") self.assertEqual(len(sc_path), 1) a = [] t = pya.DCplxTrans() for sc in sc_path: a.append(sc.expanded_name()) t = t * sc.trans self.assertEqual(",".join(a), "$2") self.assertEqual(str(t), "r0 *1 2.64,0") self.assertEqual( str(l2n.shapes_of_net(n, rmetal1, True)), "(-980,-420;-980,2420;-620,2420;-620,-420);(-800,820;-800,1180;580,1180;580,820);(-980,2420;-980,3180;-620,3180;-620,2420);(-980,-380;-980,380;-620,380;-620,-380)" ) shapes = pya.Shapes() l2n.shapes_of_net(n, rmetal1, True, shapes) r = pya.Region() for s in shapes.each(): r.insert(s.polygon) self.assertEqual( str(r), "(-980,-420;-980,2420;-620,2420;-620,-420);(-800,820;-800,1180;580,1180;580,820);(-980,2420;-980,3180;-620,3180;-620,2420);(-980,-380;-980,380;-620,380;-620,-380)" )
def DCplxTrans(self): return pya.DCplxTrans(1, self.angle, False, self.centerx, self.centery)
def produce_impl(self): #Calculate layout database unit #dbu = self.layout.dbu dbu = 1 size = [] if len(self.size) < 2: if self.debug: print("Size < 2 dimension") if len(self.size) == 0: if self.debug: print( "paramter size has been adjusted to default - invalid data have provided" ) size = [100.0, 100.0] else: if self.debug: print("Size has been adjusted to {}:{}".format( self.size[0] / dbu, self.size[0] / dbu)) size.append(float(self.size[0]) / dbu) size.append(float(self.size[0]) / dbu) else: size.append(float(self.size[0]) / dbu) size.append(float(self.size[1]) / dbu) ovSize = [] if len(self.ovsize) < 2: if self.debug: print("overal size < 2 dimension") if len(self.ovsize) == 0: if self.debug: print( "paramter size has been adjusted to default - invalid data have provided" ) ovSize = [100.0, 100.0] else: ovSize.append(float(self.ovsize[0]) / dbu) ovSize.append(float(self.ovsize[0]) / dbu) else: ovSize.append(float(self.ovsize[0]) / dbu) ovSize.append(float(self.ovsize[1]) / dbu) armLenght = self.armLenght / dbu armWidth = self.armWidth / dbu activeArea = [size[0] - self.actOffset, size[1] - self.actOffset] woW = self.woW / dbu woOP = self.woOP / dbu # Membrane Geometry: ## arm location on a rectangle = edgeArmOffset edgeArmOffset = armWidth / 2 * math.sqrt(2) if self.debug: print("Size 0:{:.3f}, {}, {}".format(size[0], armLenght, armWidth)) ## arm starts at following points pointArmA = pya.DPoint(size[0] / 2 - edgeArmOffset, size[1] / 2) pointArmD = pya.DPoint(size[0] / 2, size[1] / 2 - edgeArmOffset) ## arm ends in the point P - might be usefull as a connector point pointP = pya.DPoint(size[0] / 2 + armLenght / math.sqrt(2), size[1] / 2 + armLenght / math.sqrt(2)) ## arm edge points offsets from the center point P armEndPointoffset = armWidth / 2 / math.sqrt(2) ## Arm edge points in relation to the P point pointArmB = pya.DPoint(pointP.x - armEndPointoffset, pointP.y + armEndPointoffset) pointArmC = pya.DPoint(pointP.x + armEndPointoffset, pointP.y - armEndPointoffset) ## Lets Try to assemble the membrane as 1/4 polyPoints = [] polyPoints.append(pya.DPoint(0.0, 0.0)) polyPoints.append(pya.DPoint(0.0, size[1] / 2)) polyPoints.append(pointArmA) polyPoints.append(pointArmB) polyPoints.append(pointArmC) polyPoints.append(pointArmD) polyPoints.append(pya.DPoint(size[0] / 2, 0.0)) #Lets put it there shapeSet = [] Poly = pya.DPolygon(polyPoints) shapeSet.append(Poly) t = pya.DCplxTrans(1.0, 180, False, 0.0, 0.0) Poly1 = pya.DPolygon(polyPoints) Poly1.transform(t) shapeSet.append(Poly1) t = pya.DCplxTrans(1.0, 0, True, 0.0, 0.0) Poly2 = pya.DPolygon(polyPoints) Poly2.transform(t) shapeSet.append(Poly2) t = pya.DCplxTrans(1.0, 180, True, 0.0, 0.0) Poly3 = pya.DPolygon(polyPoints) Poly3.transform(t) shapeSet.append(Poly3) tr = pya.DCplxTrans(1000.0) region = pya.Region(shapeSet) region.merge() region.transform(tr) self.cell.shapes(self.l_layer).insert(region) #Active Area if self.showAct: actBox = pya.DBox(-activeArea[0] / 2, -activeArea[1] / 2, activeArea[0] / 2, activeArea[1] / 2) self.cell.shapes(self.la_layer).insert(actBox) # Etch area - a rectangele limited by the membrane shape and P point etchBox = pya.DBox(-pointP.x, -pointP.y, pointP.x, pointP.y) etchRegion = pya.Region(etchBox) etchRegion.transform(tr) tempRegion = region ^ etchRegion etchRegion = tempRegion & etchRegion self.cell.shapes(self.ool_layer).insert(etchRegion) # Heater wire if self.genHeater: if self.heatType == 0: #Hilbert is defined only for square areas. We would fit whatever is smaller if activeArea[0] != activeArea[1]: if (activeArea[0] > activeArea[1]): wireArea = activeArea[1] / 2 else: wireArea = activeArea[0] / 2 else: wireArea = activeArea[0] / 2 #issue num2: # the diagonal contact placemnet is required # so we have to calculate space for the return path # segment separation 1sqg => seg = wireArea / 2^n + 1 Hcnt = 2**self.heatOrder + 1 Hseg = wireArea / (Hcnt) print("Hseq: {:.3f}".format(Hseg)) wireAreaRed = wireArea - Hseg a = wireAreaRed + wireAreaRed * 1j b = wireAreaRed - wireAreaRed * 1j z = 0 for i in range(1, self.heatOrder + 1): w = 1j * z.conjugate() z = numpy.array([w - a, z - b, z + a, b - w]) / 2 z = z.flatten() X = [x.real for x in z] Y = [x.imag for x in z] heatPoints = [] for i in range(0, len(X)): heatPoints.append(pya.DPoint(X[i], Y[i])) #lets add the return path # start with calculation of intersection to the beam # linEqa = -1*(pointP.y / pointP.x) - valid only for Square # #print("Linear equation is y = {:.3f}.x".format(linEqa)) heatInitial = heatPoints[0] pointS1 = pya.DPoint(-size[0] / 2, size[1] / 2) #pointS2 = pya.DPoint(activeArea[0]/2, -activeArea[1]/2) if self.debug: print("P:{:.3f},{:.3f} ; S:{:.3f},{:.3f}".format( -pointP.x, pointP.y, pointS1.x, pointS1.y)) linEqa = (pointP.y - pointS1.y) / (-pointP.x - pointS1.x) linEqb = pointP.y - linEqa * -pointP.x if self.debug: print("Line equation is: y={:.3f}x+{:.3f}".format( linEqa, linEqb)) heatPoints.insert( 0, pya.DPoint(heatPoints[0].x - 2 * Hseg, heatPoints[0].y)) heatPoints.insert( 0, pya.DPoint(heatPoints[0].x, linEqa * (heatPoints[0].x + Hseg) + linEqb)) heatPoints.append(pya.DPoint(heatPoints[len(heatPoints)-1].x, \ linEqa*(heatPoints[len(heatPoints)-1].x+Hseg)-linEqb)) heatPoints.append(pya.DPoint(pointP.x - Hseg, -pointP.y)) #arm contacts heatPoints.insert(0, pya.DPoint(-pointP.x - Hseg, pointP.y)) #probably somewhere here is a good time to calculate perforations # teoretically first opening should be -Heg/2 to the left of the very first # point and should repeat in X and Y axis with interval of Hseg # # center is HeatPoints[2] -Hseg/2 ? if self.perfAct: perfW = self.perfSize / 2 / dbu #perfCenter = pya.DPoint(heatPoints[2].x - Hseg, heatPoints[2].y - Hseg) #perfBox = pya.DBox(perfCenter.x-perfW, perfCenter.y-perfW, perfCenter.x+perfW, perfCenter.y-perfW) elCell = self.layout.create_cell("Perforator") perfBox = pya.DPolygon( pya.DBox(-perfW, -perfW, perfW, perfW)) if self.roundPath: perfBox = perfBox.round_corners(Hseg / 2, Hseg / 2, 32) elCell.shapes(self.perfl_layer).insert(perfBox) #lets make an array of them x_vect = pya.DVector(2 * Hseg, 0.0) y_vect = pya.DVector(0.0, 2 * Hseg) t = pya.DCplxTrans(heatInitial.x, heatInitial.y + Hseg) perfArr = pya.DCellInstArray(elCell.cell_index(), t, x_vect, y_vect, Hcnt - 1, Hcnt - 2) self.cell.insert(perfArr) #move to the right coordinates pathT = pya.DCplxTrans(Hseg, 0) heatPath = pya.DPath(heatPoints, self.heatW) heatPathT = heatPath.transformed(pathT) if self.roundPath: heatPathT = heatPath.round_corners(Hseg / 2, 32, 0.001) heatCenter = heatPathT.bbox().center() print(heatCenter) print("Rounded Path center: {}:{}".format( heatCenter.x, heatCenter.y)) pathTr = pya.DCplxTrans(-heatCenter.x, -heatCenter.y) heatPathT = heatPathT.transformed(pathTr) self.cell.shapes(self.heatl_layer).insert(heatPathT) else: print("Wire definition has not been found!") #TODO ... other types of heaters if self.genWO: #we would make a wire connection from the P point to the edge of the membrane # overpass on both sides as an option # it has to be realized as a set of the 4 path print("Overal size: {}:{}".format(ovSize[0], ovSize[1])) woPathA = pya.DPath( [pointP, pya.DPoint(ovSize[0] / 2, ovSize[1] / 2)], woW, woOP, woOP) woPathB = pya.DPath([pya.DPoint(-pointP.x, pointP.y), pya.DPoint(-ovSize[0]/2, ovSize[1]/2)],\ woW, woOP, woOP) woPathC = pya.DPath([pya.DPoint(-pointP.x, -pointP.y), pya.DPoint(-ovSize[0]/2, -ovSize[1]/2)],\ woW, woOP, woOP) woPathD = pya.DPath([pya.DPoint(pointP.x, -pointP.y), pya.DPoint(ovSize[0]/2, -ovSize[1]/2)],\ woW, woOP, woOP) self.cell.shapes(self.cntl_layer).insert(woPathA) self.cell.shapes(self.cntl_layer).insert(woPathB) self.cell.shapes(self.cntl_layer).insert(woPathC) self.cell.shapes(self.cntl_layer).insert(woPathD) if self.genCnt: # Ok that would be fun ... # so at first we should be able to find how many of the IGC we would be able to fit # in between of the perforations (maybe we should count also for the minimal separation) # principally: # single IGS pair consists of 2 wires and 2 gaps = IGSpairW? # testing condition is therefore IGSCnt = floor((Hseg - perfW) / IGSpairW) cntW = self.cntW / dbu cntSp = self.cntSp / dbu cntB = self.cntB / dbu cntBunchW = 2 * (cntW + cntSp) cntCnt = math.floor((2 * Hseg - 2 * perfW) / cntBunchW) if self.debug: print("IDC W={}".format(cntBunchW)) print("IDCs per bunch: {}".format(cntCnt)) if cntCnt == 0: print( "Error: Interdigital contacts with given specs could not be realized because of geometric containts!" ) else: #lets make a subcell with interdigital pair # so first calculate the active area - contact bars to get the lenght # contacts singles cntCell = self.layout.create_cell("IDC_subcell") cntArrCell = self.layout.create_cell("IDC_cell") #cntLenght = activeArea - 2*cntB - cntSp cntPath_p1 = pya.DPoint((cntSp + cntW) / 2, activeArea[1] / 2 - cntB) cntPath_p2 = pya.DPoint((cntSp + cntW) / 2, -activeArea[1] / 2 + cntSp + cntB) #TODO tohle je asi blbe ... cntPath_pA = [cntPath_p1, cntPath_p2] cntPath_pB = [cntPath_p1 * -1, cntPath_p2 * -1] cntPath_A = pya.DPath(cntPath_pA, cntW, 0.0, 0.0) cntPath_B = pya.DPath(cntPath_pB, cntW, 0.0, 0.0) cntCell.shapes(self.idcl_layer).insert(cntPath_A) cntCell.shapes(self.idcl_layer).insert(cntPath_B) #now lets make bunches of cntCnt and center them # TODO: tady jsem skoncil ... potreba projit odstavec pod #BEGIN x_vect = pya.DVector(cntBunchW, 0.0) y_vect = pya.DVector(0.0, 0.0) if self.debug: print("IDC bunch Vectors: {}, {}, {}, {}".format(\ x_vect.x, x_vect.y, y_vect.x, y_vect.y)) t = pya.DCplxTrans(0, 0) cntArr = pya.DCellInstArray(cntCell.cell_index(), t, x_vect, y_vect, cntCnt, 1) #center the origins on top of each other # here we have a bunch of IDCs cntArr_center = cntArr.bbox(self.layout).center() if self.debug: print("Bunch center: {},{}".format(cntArr_center.x, cntArr_center.y)) t = pya.DCplxTrans(1.0, 0, False, -cntArr_center.x, -cntArr_center.y) cntArr.transform(t) cntArrCell.insert(cntArr) # move the array to the position of Hilb. initial and paste it into the overal array a_vect = pya.DVector(2 * Hseg, 0.0) b_vect = pya.DVector(0.0, 0.0) cntLoct = pya.DCplxTrans(1.0, 0, False, heatInitial.x - Hseg, 0.0) cntArrAll = pya.DCellInstArray(cntArrCell.cell_index(), cntLoct, a_vect, b_vect, Hcnt, 1) self.cell.insert(cntArrAll) #Top and bottom contact # by principle the bar-contact should be horizontally oriented across the active zone # then they should continue to the respective P-points (upright, lowerleft) # Contact bar would be a box from the edge to the edge of active area with a width of # cntB # pointCNT1A = pya.DPoint(activeArea[0]/2, activeArea[1]/2) # if self.debug: # print("P:{:.3f},{:.3f} ; CNT:{:.3f},{:.3f}".format(-pointP.x, pointP.y, pointCNT1A.x, pointCNT1A.y)) # linCntEqa = (pointP.y-pointCNT1A.y)/(-pointP.x-pointCNT1A.x) # linCntEqb = pointP.y - linCntEqa*-pointP.x # if self.debug: # print("CNT line equation is: y={:.3f}x+{:.3f}".format(linEqa,linEqb)) # pointCNT1B = # Contact Bars cntBarW = self.cntB / dbu cntWoW = self.cntWO / dbu shapeSetCNT = [] #cntBarA shapeSetCNT.append(pya.DBox(-activeArea[0]/2, activeArea[1]/2-cntBarW,\ activeArea[0]/2, activeArea[1]/2)) #cntBarB shapeSetCNT.append(pya.DBox(-activeArea[0]/2, -activeArea[1]/2,\ activeArea[0]/2, -activeArea[1]/2+cntBarW)) pointS2 = pya.DPoint(activeArea[0] / 2, activeArea[1] / 2) #cntWOPathA shapeSetCNT.append( pya.DPath([pointS2, pointP], cntWoW, cntWoW / 2, cntWoW).polygon()) #cntWOPathB shapeSetCNT.append( pya.DPath([-pointS2, -pointP], cntWoW, cntWoW / 2, cntWoW).polygon()) for shape in shapeSetCNT: self.cell.shapes(self.idcl_layer).insert(shape) #Vias #TODO: repair position of the vias cntViaW = cntWoW * 0.9 / 2 # 10% smaller then the wire tr = pya.DCplxTrans(1.0, 45.0, False, pya.DVector(pointP)) cntViaA = pya.DPolygon(pya.DBox(-cntViaW, -cntViaW,\ cntViaW, cntViaW)).transform(tr) tr = pya.DCplxTrans(1.0, 45.0, False, pya.DVector(-pointP)) cntViaB = pya.DPolygon(pya.DBox(-cntViaW, -cntViaW,\ cntViaW, cntViaW)).transformed(tr) self.cell.shapes(self.lvia_layer).insert(cntViaA) self.cell.shapes(self.lvia_layer).insert(cntViaB)
def tr_to(obj,itr=False): trs=[pya.DCplxTrans(1,-deltaangle,False,pc.x,pc.y)] if itr:trs=[pya.ICplxTrans.from_dtrans(tr) for tr in trs] for tr in trs: obj=obj.transformed(tr) return obj
def produce_impl(self): size = [] if len(self.size) < 2: if self.debug: print("Size < 2 dimension") if len(self.size) == 0: if self.debug: print( "paramter size has been adjusted to default - invalid data have provided" ) size = [100.0, 100.0] else: if self.debug: print("Size has been adjusted to {}:{}".format( self.size[0] / dbu, self.size[0] / dbu)) size.append(float(self.size[0])) size.append(float(self.size[0])) else: size.append(float(self.size[0])) size.append(float(self.size[1])) ovSize = [] if len(self.ovsize) < 2: if self.debug: print("overal size < 2 dimension") if len(self.ovsize) == 0: if self.debug: print( "paramter size has been adjusted to default - invalid data have provided" ) ovSize = [100.0, 100.0] else: ovSize.append(float(self.ovsize[0])) ovSize.append(float(self.ovsize[0])) else: ovSize.append(float(self.ovsize[0])) ovSize.append(float(self.ovsize[1])) #armLenght = self.armLenght armWidth = self.armWidth armBSS = self.armBMS activeArea = [size[0] - self.actOffset, size[1] - self.actOffset] #woW = self.woW/dbu #woOP = self.woOP/dbu # Membrane Geometry: memParts = [] # Firstly generate the centerpart memCenter = pya.Polygon( pya.DPolygon( pya.DBox(-size[0] / 2, -size[1] / 2, size[0] / 2, size[1] / 2))) memParts.append(memParts) # Time for beams # Calculate the BeamArmcenter to the membrane edge, alias beam to memrane spacing memBMS = [(ovSize[0]-size[0]/2) -armBSS -armWidth/2,\ (ovSize[1]-size[1]/2) -armBSS -armWidth/2] memBeam1 = pya.Polygon(pya.DPath([\ pya.DPoint((size[0]-armWidth)/2, size[1]/2),\ pya.DPoint((size[0]-armWidth)/2, size[1]/2+memBMS[1]),\ pya.DPoint(-ovSize[0]/2, size[1]/2+memBMS[1])], armWidth).polygon()) memParts.append(memBeam1) memBeam2 = pya.Polygon(pya.DPath([\ pya.DPoint(-size[0]/2, (size[1]/2)-armWidth/2),\ pya.DPoint(-size[0]-memBMS[0], size[1]/2-armWidth/2),\ pya.DPoint(-size[0]-memBMS[0], -ovSize[1]/2)], armWidth).polygon()) memParts.append(memBeam2) memBeam3 = pya.Polygon(pya.DPath([\ pya.DPoint((-size[0]+armWidth)/2, -size[1]/2),\ pya.DPoint((-size[0]+armWidth)/2, -size[1]/2-memBMS[1]),\ pya.DPoint(ovSize[0]/2, -size[1]/2-memBMS[1])], armWidth).polygon()) memParts.append(memBeam3) memBeam4 = pya.Polygon(pya.DPath([\ pya.DPoint(size[0]/2, (-size[1]-armWidth)/2),\ pya.DPoint(size[0]+memBMS[0], -size[1]/2+armWidth/2),\ pya.DPoint(size[0]+memBMS[0], ovSize[1]/2)], armWidth).polygon()) memParts.append(memBeam4) #here it would be probably useful to put them all into one polygon object (hopefully it\ # would work ;)) if self.debug: print(memParts) for member in memParts: self.cell.shapes(self.l_layer).insert(member) tr = pya.DCplxTrans(1000.0) #workaround for difference in DBU region = pya.Region(memParts) region.merge() region.transform(tr) self.cell.shapes(self.l_layer).insert(region) #Active Area actBox = pya.DBox(-activeArea[0]/2, -activeArea[1]/2,\ activeArea[0]/2, activeArea[1]/2) if self.showAct: self.cell.shapes(self.la_layer).insert(actBox) # Etch area - in this variant the overal size of membrane etchRegion = pya.Region(actBox) etchRegion.transform(tr) tempRegion = region ^ etchRegion etchRegion = tempRegion & etchRegion self.cell.shapes(self.ool_layer).insert(etchRegion)