def round(self, polygon, npoints, radius): ''' 返回一个pya.DPolygon的圆滑版 ''' param = { "polygon": pya.DPolygon([ pya.DPoint(pt.x * IO.layout.dbu, pt.y * IO.layout.dbu) for pt in polygon.each_point_hull() ]), "npoints": npoints, "layer": IO.layer, "radius": radius * IO.layout.dbu } pv = [] for p in self.ROUND_POLYGON_decl.get_parameters(): if p.name in param: pv.append(param[p.name]) else: pv.append(p.default) cell = IO.layout.create_cell("ROUND_POLYGON") self.ROUND_POLYGON_decl.produce(IO.layout, [IO.layer], pv, cell) target = list(cell.each_shape(IO.layer))[0].dpolygon cell.delete() return pya.DPolygon([ pya.DPoint(pt.x / IO.layout.dbu, pt.y / IO.layout.dbu) for pt in target.each_point_hull() ])
def InterdigitedCapacitor(self, number, arg1=85000, arg2=45000, arg3=31000, arg4=4000, arg5=3000, arg6=3000, arg7=2000): ''' number must be odd http://www.rfwireless-world.com/calculators/interdigital-capacitor-calculator.html ''' assert (self.end_ext == 0 and self.bgn_ext == 0) if number % 2 != 1: raise RuntimeError('number must be odd') oldbrush = self.brush tr = oldbrush.DCplxTrans newwidin = arg5 * 2 + (arg4 + arg7) * number + arg7 newwidout = newwidin + arg3 * 2 outPolygon = pya.DPolygon([ pya.DPoint(arg2, newwidout / 2), pya.DPoint(arg2, -newwidout / 2), pya.DPoint(arg2 + arg1, -newwidout / 2), pya.DPoint(arg2 + arg1, newwidout / 2) ]).transformed(tr) inPolygons = [] xx = arg1 - arg6 yy = arg4 ly = arg4 + arg7 for ii in range(1 + number >> 1): dx = 0 if ii % 2 == 0 else arg6 inPolygons.append( pya.DPolygon([ pya.DPoint(arg2 + dx, yy / 2 + ii * ly), pya.DPoint(arg2 + dx, -yy / 2 + ii * ly), pya.DPoint(arg2 + dx + xx, -yy / 2 + ii * ly), pya.DPoint(arg2 + dx + xx, yy / 2 + ii * ly) ]).transformed(tr)) if ii == 0: continue inPolygons.append( pya.DPolygon([ pya.DPoint(arg2 + dx, yy / 2 - ii * ly), pya.DPoint(arg2 + dx, -yy / 2 - ii * ly), pya.DPoint(arg2 + dx + xx, -yy / 2 - ii * ly), pya.DPoint(arg2 + dx + xx, yy / 2 - ii * ly) ]).transformed(tr)) self.Narrow(newwidout, newwidin, arg2) self.regionlistout.append(outPolygon) self.regionlistin.extend(inPolygons) self.Narrow(newwidout, newwidin, arg1) self.regionlistout.pop() self.regionlistin.pop() self.Narrow(oldbrush.widout, oldbrush.widin, arg2)
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 DrawBorder(self,wed=50000,leng=3050000,siz=3050000): pts=[pya.DPoint(-siz,-siz),pya.DPoint(-siz+leng,-siz),pya.DPoint(-siz+leng,-siz+wed)] pts.extend([pya.DPoint(-siz+wed,-siz+wed),pya.DPoint(-siz+wed,-siz+leng),pya.DPoint(-siz,-siz+leng)]) self.outputlist.append(pya.DPolygon(pts)) for i in pts: i.x=-i.x self.outputlist.append(pya.DPolygon(pts)) for i in pts: i.y=-i.y self.outputlist.append(pya.DPolygon(pts)) for i in pts: i.x=-i.x self.outputlist.append(pya.DPolygon(pts))
def resize(self, dx, dbu): """ Resizes the polygon by a positive or negative quantity dx. Args: dbu: typically 0.001 """ dpoly = pya.DPolygon(self) dpoly.size(dx, 5) dpoly = pya.EdgeProcessor().simple_merge_p2p([dpoly.to_itype(dbu)], False, False, 1) dpoly = dpoly[0].to_dtype(dbu) # pya.DPolygon def norm(p): return sqrt(p.x**2 + p.y**2) # Filter edges if they are too small points = list(dpoly.each_point_hull()) new_points = list([points[0]]) for i in range(0, len(points)): delta = points[i] - new_points[-1] if norm(delta) > min(10 * dbu, abs(dx)): new_points.append(points[i]) sdpoly = DSimplePolygon(new_points) # convert to SimplePolygon self.assign(sdpoly) return self
def layout_taper(cell, layer, trans, w1, w2, length, insert=True): """ Lays out a taper Args: trans: pya.Trans: location and rotation w1: width of waveguide, float for DPoint type (microns); int for Point type (nm) w2: width of waveguide, float for DPoint type (microns); int for Point type (nm) length: length, float insert: flag to insert drawn waveguide or return shape, boolean """ import pya if type(w1) == type(float()): pts = [ pya.DPoint(0, -w1 / 2), pya.DPoint(0, w1 / 2), pya.DPoint(length, w2 / 2), pya.DPoint(length, -w2 / 2) ] shape_taper = pya.DPolygon(pts).transformed(trans) else: pts = [ pya.Point(0, -w1 / 2), pya.Point(0, w1 / 2), pya.Point(length, w2 / 2), pya.Point(length, -w2 / 2) ] shape_taper = pya.Polygon(pts).transformed(trans) if insert == True: cell.shapes(layer).insert(shape_taper) else: return shape_taper
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 layout_disk(cell, layer, center, r): """ function to produce the layout of a disk cell: layout cell to place the layout layer: which layer to use center: origin DPoint r: radius units in microns """ # outer arc # optimal sampling radius = r assert radius > 0 arc_function = lambda t: np.array([radius * np.cos(t), radius * np.sin(t)]) t, coords = sample_function(arc_function, [0, 2 * pi], tol=0.002 / radius) # create original waveguide poligon prior to clipping and rotation points_hull = [center + pya.DPoint(x, y) for x, y in zip(*coords)] del points_hull[-1] dpoly = pya.DPolygon(points_hull) insert_shape(cell, layer, dpoly) return dpoly
def DrawElectrode(): pts = [] pts.append(pya.DPoint(-501000, -225000)) pts.append(pya.DPoint(-621000, -8000)) pts.append(pya.DPoint(-625000, -8000)) pts.append(pya.DPoint(-625000, -4000)) pts.append(pya.DPoint(-621000, -4000)) pts.append(pya.DPoint(-501000, -125000)) pts.append(pya.DPoint(-251000, -125000)) pts.append(pya.DPoint(-251000, 125000)) pts.append(pya.DPoint(-501000, 125000)) pts.append(pya.DPoint(-621000, 4000)) pts.append(pya.DPoint(-625000, 4000)) pts.append(pya.DPoint(-625000, 8000)) pts.append(pya.DPoint(-621000, 8000)) pts.append(pya.DPoint(-501000, 225000)) pts.append(pya.DPoint(-186000, 225000)) pts.append(pya.DPoint(-186000, 5000)) pts.append(pya.DPoint(0, 5000)) pts.append(pya.DPoint(0, -5000)) pts.append(pya.DPoint(-186000, -5000)) pts.append(pya.DPoint(-186000, -225000)) return pya.DPolygon(pts), [ pya.DPoint(-625000, 8000), pya.DPoint(-625000, 4000), pya.DPoint(-625000, -4000), pya.DPoint(-625000, -8000) ]
def Drawxxx(self): pts = [] pts.append(pya.DPoint(-501000, -225000)) pts.append(pya.DPoint(-621000, -8000)) pts.append(pya.DPoint(-625000, -8000)) pts.append(pya.DPoint(-625000, -4000)) pts.append(pya.DPoint(-621000, -4000)) pts.append(pya.DPoint(-501000, -125000)) pts.append(pya.DPoint(-251000, -125000)) pts.append(pya.DPoint(-251000, 125000)) pts.append(pya.DPoint(-501000, 125000)) pts.append(pya.DPoint(-621000, 4000)) pts.append(pya.DPoint(-625000, 4000)) pts.append(pya.DPoint(-625000, 8000)) pts.append(pya.DPoint(-621000, 8000)) pts.append(pya.DPoint(-501000, 225000)) pts.append(pya.DPoint(-186000, 225000)) pts.append(pya.DPoint(-186000, 5000)) pts.append(pya.DPoint(0, 5000)) pts.append(pya.DPoint(0, -5000)) pts.append(pya.DPoint(-186000, -5000)) pts.append(pya.DPoint(-186000, -225000)) self.outputlist.append(pya.DPolygon(pts)) return [ pya.DPoint(-625000, 8000), pya.DPoint(-625000, 4000), pya.DPoint(-625000, -4000), pya.DPoint(-625000, -8000) ]
def trans(dpolygon,angle): pts=[] c=cos(angle/180*pi) s=sin(angle/180*pi) for pt in dpolygon.each_point_hull(): pts.append(pya.DPoint(c*pt.x+s*pt.y,-s*pt.x+c*pt.y)) return pya.DPolygon(pts)
def test_2_DPolygon(self): pts = [pya.DPoint(0, 0)] p = pya.DPolygon(pts, True) self.assertEqual(str(p), "(0,0)") arr = [] for e in p.each_edge(): arr.append(str(e)) self.assertEqual(arr, ["(0,0;0,0)"]) p = pya.DPolygon(pya.DBox(0, 0, 100, 100)) p.insert_hole([pya.DPoint(0, 0), pya.DPoint(10, 0)], True) self.assertEqual(str(p), "(0,0;0,100;100,100;100,0/0,0;10,0)") p.assign_hole(0, [pya.DPoint(0, 0), pya.DPoint(10, 0)]) self.assertEqual(str(p), "(0,0;0,100;100,100;100,0/0,0;10,0)") p.assign_hole(0, [pya.DPoint(0, 0), pya.DPoint(10, 0)], True) self.assertEqual(str(p), "(0,0;0,100;100,100;100,0/0,0;10,0)") pts = [pya.DPoint(0, 0), pya.DPoint(10, 0)] p = pya.DPolygon(pts, True) self.assertEqual(str(p), "(0,0;10,0)") self.assertEqual(str(pya.Polygon(p)), "(0,0;10,0)") p.hull = [] self.assertEqual(str(p), "()") p.hull = [pya.DPoint(0, 0), pya.DPoint(10, 0)] self.assertEqual(str(p), "(0,0;10,0)") p.assign_hull([pya.DPoint(0, 0), pya.DPoint(10, 0)], True) self.assertEqual(str(p), "(0,0;10,0)") arr = [] for e in p.each_edge(): arr.append(str(e)) self.assertEqual(arr, ["(0,0;10,0)", "(10,0;0,0)"]) self.assertEqual(str(p.moved(1, 2)), "(1,2;11,2)") self.assertEqual(str(p.sized(2)), "(0,-2;0,2;10,2;10,-2)") self.assertEqual(str(p * 2), "(0,0;20,0)") self.assertEqual(str(p.transformed(pya.DTrans(pya.DTrans.R90))), "(0,0;0,10)") pp = p.dup() pp.transform(pya.DTrans(pya.DTrans.R90)) self.assertEqual(str(pp), "(0,0;0,10)")
def thickarc(point0, rr, rl, n, angle0, angle1): thickarcpointlist = [] thickarcpointlist.extend( BasicPainter.arc(point0, rr, n, angle0, angle1)) thickarcpointlist.extend( BasicPainter.arc(point0, rl, n, angle1, angle0)) thickarc1 = pya.DPolygon(thickarcpointlist) return thickarc1, thickarcpointlist[n - 1], thickarcpointlist[n]
def box_dpolygon(point1, point3, ex=None): # position point2 to the right of point1 if ex is None: ex = pya.DPoint(1, 0) ey = rotate90(ex) point2 = point1 * ex * ex + point3 * ey * ey point4 = point3 * ex * ex + point1 * ey * ey return pya.DPolygon([point1, point2, point3, point4])
def conflict(self, other): if isinstance(other, Collision): return self.region.interacting(other.region) if isinstance(other, pya.DPoint): region = pya.Region( pya.DPolygon( BasicPainter.arc(other, self.pointRadius, 8, 0, 360))) return self.region.interacting(region) raise TypeError('Invalid input')
def Narrow(self, widout, widin, length=6000): super().Narrow(widout, widin, length) ex = self.Getexinfo() self.regionlistex.append( pya.DPolygon([ self.painterex.pointl, self.painterex.pointr, ex['p4'], ex['p3'] ])) self.painterex.Setpoint(ex['p3'], ex['p4']) return length
def test_touches(self): p1 = pya.Polygon(pya.Box(10, 20, 30, 40)) self.assertEqual(p1.touches(pya.Polygon(pya.Box(30, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.Polygon(pya.Box(31, 20, 40, 50))), False) self.assertEqual(p1.touches(pya.Polygon(pya.Box(29, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.SimplePolygon(pya.Box(30, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.SimplePolygon(pya.Box(31, 20, 40, 50))), False) self.assertEqual(p1.touches(pya.SimplePolygon(pya.Box(29, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.Box(30, 20, 40, 50)), True) self.assertEqual(p1.touches(pya.Box(31, 20, 40, 50)), False) self.assertEqual(p1.touches(pya.Box(29, 20, 40, 50)), True) self.assertEqual(p1.touches(pya.Edge(30, 20, 40, 50)), True) self.assertEqual(p1.touches(pya.Edge(31, 20, 40, 50)), False) self.assertEqual(p1.touches(pya.Edge(29, 20, 40, 50)), True) p1 = pya.SimplePolygon(pya.Box(10, 20, 30, 40)) self.assertEqual(p1.touches(pya.Polygon(pya.Box(30, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.Polygon(pya.Box(31, 20, 40, 50))), False) self.assertEqual(p1.touches(pya.Polygon(pya.Box(29, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.SimplePolygon(pya.Box(30, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.SimplePolygon(pya.Box(31, 20, 40, 50))), False) self.assertEqual(p1.touches(pya.SimplePolygon(pya.Box(29, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.Box(30, 20, 40, 50)), True) self.assertEqual(p1.touches(pya.Box(31, 20, 40, 50)), False) self.assertEqual(p1.touches(pya.Box(29, 20, 40, 50)), True) self.assertEqual(p1.touches(pya.Edge(30, 20, 40, 50)), True) self.assertEqual(p1.touches(pya.Edge(31, 20, 40, 50)), False) self.assertEqual(p1.touches(pya.Edge(29, 20, 40, 50)), True) p1 = pya.DPolygon(pya.DBox(10, 20, 30, 40)) self.assertEqual(p1.touches(pya.DPolygon(pya.DBox(30, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.DPolygon(pya.DBox(31, 20, 40, 50))), False) self.assertEqual(p1.touches(pya.DPolygon(pya.DBox(29, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.DSimplePolygon(pya.DBox(30, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.DSimplePolygon(pya.DBox(31, 20, 40, 50))), False) self.assertEqual(p1.touches(pya.DSimplePolygon(pya.DBox(29, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.DBox(30, 20, 40, 50)), True) self.assertEqual(p1.touches(pya.DBox(31, 20, 40, 50)), False) self.assertEqual(p1.touches(pya.DBox(29, 20, 40, 50)), True) self.assertEqual(p1.touches(pya.DEdge(30, 20, 40, 50)), True) self.assertEqual(p1.touches(pya.DEdge(31, 20, 40, 50)), False) self.assertEqual(p1.touches(pya.DEdge(29, 20, 40, 50)), True) p1 = pya.DSimplePolygon(pya.DBox(10, 20, 30, 40)) self.assertEqual(p1.touches(pya.DPolygon(pya.DBox(30, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.DPolygon(pya.DBox(31, 20, 40, 50))), False) self.assertEqual(p1.touches(pya.DPolygon(pya.DBox(29, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.DSimplePolygon(pya.DBox(30, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.DSimplePolygon(pya.DBox(31, 20, 40, 50))), False) self.assertEqual(p1.touches(pya.DSimplePolygon(pya.DBox(29, 20, 40, 50))), True) self.assertEqual(p1.touches(pya.DBox(30, 20, 40, 50)), True) self.assertEqual(p1.touches(pya.DBox(31, 20, 40, 50)), False) self.assertEqual(p1.touches(pya.DBox(29, 20, 40, 50)), True) self.assertEqual(p1.touches(pya.DEdge(30, 20, 40, 50)), True) self.assertEqual(p1.touches(pya.DEdge(31, 20, 40, 50)), False) self.assertEqual(p1.touches(pya.DEdge(29, 20, 40, 50)), True)
def Narrow(self, widout, widin, length=6000): assert (self.end_ext == 0) tr = self.brush.DCplxTrans 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.p2, edgeout.p1 ])) self.regionlistin.append( pya.DPolygon([ self.painterin.pointl, self.painterin.pointr, edgein.p2, edgein.p1 ])) self.painterout.Setpoint(edgeout.p1, edgeout.p2) self.painterin.Setpoint(edgein.p1, edgein.p2) return length
def rectangle(pointr,pointl,length): #给定矩形的右下pointr左下pointl画出指定长度矩形 #pointr,pointl,pointl2,pointr2 #x1,y1,x2,y2,length,path delta=pointr.distance(pointl) xx=length/delta*(pointl.y-pointr.y) yy=length/delta*(pointr.x-pointl.x) pointl2=pya.DPoint(pointl.x+xx,pointl.y+yy) pointr2=pya.DPoint(pointr.x+xx,pointr.y+yy) rectangle1=pya.DPolygon([pointr,pointl,pointl2,pointr2]) return rectangle1,pointr2,pointl2
def generateSolution(): with open(workDir + '/ab.json') as fid: g.ab = json.load(fid) with open(workDir + '/progress.json') as fid: g.progress = json.load(fid) for smark, slist in [['errorp', g.errorlist], ['infop', g.infolist]]: for index, pv in g.progress.items(): if pv.get('class') == smark: ab = g.ab[int(index)] slist.append([ab, pv, index]) layer_error = layout.layer(2, 2) layer_warn = layout.layer(1, 1) for slayer, slist in [[layer_error, g.errorlist], [layer_warn, g.infolist]]: for ab, pv, index in slist: # this is a temp change v # draw a rectangle instead of circle # need to be change able in gui signwh = [[1, 1], [-1, 1], [-1, -1], [1, -1]] cx = ab['x'] cy = ab['y'] angle = ab['angle'] wx = width * 0.6 * cos(angle - pi / 2) wy = width * 0.6 * sin(angle - pi / 2) hx = height * 1.1 * cos(angle) hy = height * 1.1 * sin(angle) pts = [ pya.DPoint(cx + wx * ws + hx * hs, cy + wy * ws + hy * hs) for ws, hs in signwh ] # radius = sqrt(width**2+height**2) # pts=paintlib.BasicPainter.arc(pya.DPoint(ab['x'],ab['y']),radius,3*4+1,0,360) # this is temp change ^ hole = pya.DPolygon(pts) paintlib.BasicPainter.Draw(top, slayer, hole) if noguitest: paintlib.IO.Write(workDir + '/solution.gds') # 输出到文件中 else: paintlib.IO.Show() # 输出到屏幕上 print(f''' {len(g.ab)} AB total {len(g.progress.keys())} AB checked {len(g.errorlist)} error, {len(g.infolist)} comment: ''') for ab, pv, index in g.errorlist: print(ab) for ab, pv, index in g.infolist: print(pv['comment'], '\n ', ab)
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 layout_waveguide_sbend_bezier(cell, layer, trans, w=0.5, wo=None, h=2.0, length=15.0, insert=True): """ Creates a waveguide s-bend using a bezier curve Author: Lukas Chrostowski Args: trans: pya.Trans: location and rotation w: width of input waveguide, float for DPoint type (microns); int for Point type (nm) wo (optional): width of output waveguide, float h: height length: length insert: flag to insert drawn waveguide or return shape, boolean Usage: from SiEPIC.utils import get_layout_variables TECHNOLOGY, lv, ly, cell = get_layout_variables() layer = cell.layout().layer(TECHNOLOGY['Waveguide']) layout_waveguide_sbend_bezier(cell, layer, pya.Trans(), w=0.5, h=2.0, length=15.0, insert = True) """ if wo == None: wo = w from SiEPIC.utils.geometry import bezier_parallel, translate_from_normal2 from pya import DPoint, DPolygon, Point, Polygon if type(w) == type(int()): dbu = cell.layout().dbu w = w * dbu wo = wo * dbu h = h * dbu length = length * dbu trans = trans.to_dtype(dbu) p = bezier_parallel(DPoint(0, 0), DPoint(length, h), 0) pt1 = translate_from_normal2(p, w / 2, wo / 2) pt2 = translate_from_normal2(p, -w / 2, -wo / 2) pt = pt1 + pt2[::-1] poly = pya.DPolygon(pt) print(poly) poly_t = poly.transformed(trans) if insert == True: cell.shapes(layer).insert(poly_t) return poly_t.area() / ((w + wo) / 2) else: return poly_t
def test_extractRad(self): ex = pya.SimplePolygon().extract_rad() self.assertEqual(repr(ex), "[]") sp = pya.SimplePolygon.from_s("(0,0;0,200000;300000,200000;300000,100000;100000,100000;100000,0)") sp = sp.round_corners(10000, 5000, 200) ex = sp.extract_rad() self.assertEqual(ex, [pya.SimplePolygon.from_s("(0,0;0,200000;300000,200000;300000,100000;100000,100000;100000,0)"), 10000.0, 5000.0, 200]) ex = pya.Polygon().extract_rad() self.assertEqual(ex, []) sp = pya.Polygon.from_s("(0,0;0,300000;300000,300000;300000,0/100000,100000;200000,100000;200000,200000;100000,200000)") sp = sp.round_corners(10000, 5000, 200) ex = sp.extract_rad() self.assertEqual(ex, [pya.Polygon.from_s("(0,0;0,300000;300000,300000;300000,0/100000,100000;200000,100000;200000,200000;100000,200000)"), 10000.0, 5000.0, 200]) # double coords too ... ex = pya.DSimplePolygon().extract_rad() self.assertEqual(ex, []) sp = pya.DSimplePolygon.from_s("(0,0;0,200000;300000,200000;300000,100000;100000,100000;100000,0)") sp = sp.round_corners(10000, 5000, 200) ex = sp.extract_rad() # round to integers for better comparison ex[0] = pya.SimplePolygon(ex[0]) self.assertEqual(ex, [pya.SimplePolygon.from_s("(0,0;0,200000;300000,200000;300000,100000;100000,100000;100000,0)"), 10000.0, 5000.0, 200]) ex = pya.DPolygon().extract_rad() self.assertEqual(ex, []) sp = pya.DPolygon.from_s("(0,0;0,300000;300000,300000;300000,0/100000,100000;200000,100000;200000,200000;100000,200000)") sp = sp.round_corners(10000, 5000, 200) ex = sp.extract_rad() # round to integers for better comparison ex[0] = pya.Polygon(ex[0]) self.assertEqual(ex, [pya.Polygon.from_s("(0,0;0,300000;300000,300000;300000,0/100000,100000;200000,100000;200000,200000;100000,200000)"), 10000.0, 5000.0, 200])
def create_polygon(self, points: 'list or pya.DPolygon', layer: int): """Creates a Polygon and adjusts from microns to database units. Format: [[x1,y1],[x2,y2],...] in microns :param points: Points defining the corners of the polygon. :param layer: layer_index of the target layer :return: reference to polygon object """ if isinstance(points, pya.DPolygon) or isinstance(points, pya.Polygon): self.cell.shapes(self.layout.find_layer(layer)).insert(points) else: pts = [] for p in points: pts.append(pya.DPoint(p[0], p[1])) return self.cell.shapes(self.layout.find_layer(layer)).insert( pya.DPolygon(pts))
def arc_NewtonInterpolation(n,r1,r2): thetax=0.53977; thetay=-thetax*tan(pi/180*67.5) X=[-1,-1,-1,-thetax,0,thetax,1,1,1] Y=[-1,-1,-1,thetay,-sqrt(2),thetay,-1,-1,-1] high=[-1,-1,1,1, 0,0] f=BasicPainter.NewtonInterpolation(X,Y,high) pts1=[] pts2=[] for i in range(n): x=-1.0+2.0/(n-1)*i pts1.append(pya.DPoint(x/sqrt(2)*r1,f(x)/sqrt(2)*r1)) pts2.append(pya.DPoint(x/sqrt(2)*r2,f(x)/sqrt(2)*r2)) pts1.extend(reversed(pts2)) return pya.DPolygon(pts1)
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 square_dpolygon(center, width, ex=None): # returns the polygon of a square centered at center, # aligned with ex, with width in microns if ex is None: ex = pya.DPoint(1, 0) ey = rotate90(ex) quadrant = (width / 2) * (ex + ey) point1 = center + quadrant quadrant = rotate90(quadrant) point2 = center + quadrant quadrant = rotate90(quadrant) point3 = center + quadrant quadrant = rotate90(quadrant) point4 = center + quadrant return pya.DPolygon([point1, point2, point3, point4])
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 layout_circle(cell, layer, center, r): # function to produce the layout of a filled circle # cell: layout cell to place the layout # layer: which layer to use # center: origin DPoint # r: radius # w: waveguide width # theta_start, theta_end: angle in radians # units in microns # optimal sampling arc_function = lambda t: np.array([center.x + r * np.cos(t), center.y + r * np.sin(t)]) t, coords = sample_function(arc_function, [0, 2 * np.pi - 0.001], tol=0.002 / r) dbu = cell.layout().dbu dpoly = pya.DPolygon([pya.DPoint(x, y) for x, y in zip(*coords)]) cell.shapes(layer).insert(dpoly.to_itype(dbu))
def DPathPolygon(pts, width, start, end, giveupsomepoints=False): region1 = pya.Region([ pya.Polygon.from_dpoly( pya.DPath(pts, width, start, end).polygon()) ]) region2 = pya.Region([ pya.Polygon.from_dpoly( pya.DPath(pts, width + 2000, start, end).polygon()) ]) polygon = list((region1 & region2).each_merged())[0] if giveupsomepoints: pts = [] sourcepts = list(polygon.each_point_hull()) for i, pt in enumerate(sourcepts): if i == 0 or pt.distance(pts[-1]) >= min( 1000, max(100, rounded)): pts.append(pt) return pya.DPolygon(pts) return polygon