def test_2_Trans(self): a = pya.Trans() b = pya.Trans(pya.Trans.M135, pya.Point(17, 5)) ma = pya.CplxTrans(a, 0.5) mb = pya.CplxTrans(b, 2.0) u = pya.CplxTrans(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) self.assertEqual(str(mb.inverted()), "m135 *0.5 2.5,8.5") i = mb.dup() i.invert() self.assertEqual(str(i), "m135 *0.5 2.5,8.5") self.assertEqual(i * mb == u, True) self.assertEqual(mb * i == u, True) self.assertEqual(str(mb.trans(pya.Point(1, 0))), "17,3") self.assertEqual(str(mb.ctrans(2)), "4.0") self.assertEqual(str(i.ctrans(2)), "1.0")
def DrawAirbridge(self, cell, centerlinelist, newcellname="Airbige"): IO.layout.read(self.filename) for icell in IO.layout.top_cells(): if (icell.name == self.insertcellname): icell.name = newcellname for cpts in centerlinelist: distance = 0 if not hasattr(self.airbridgedistance, '__call__'): distance = self.airbridgedistance * 0.25 dt_int = 0 for i, pt in enumerate(cpts[1:-1], 1): distance = distance + pt.distance(cpts[i - 1]) if hasattr(self.airbridgedistance, '__call__'): calt_int = self.airbridgedistance(distance) else: calt_int = distance // self.airbridgedistance if calt_int != dt_int: dx = cpts[i + 1].x - cpts[i - 1].x dy = cpts[i + 1].y - cpts[i - 1].y tr = pya.CplxTrans(1, atan2(dy, dx) / pi * 180, False, pt.x, pt.y) new_instance = pya.CellInstArray( icell.cell_index(), tr) cell.insert(new_instance) dt_int = dt_int + 1 for icell in IO.layout.top_cells(): if (icell.name == self.insertcellname): icell.flatten(True) icell.delete()
def create_port(self, x: float, y: float, rot: int = 0, length: int = 0, name: str = None): """Creates a Port at the specified coordinates. This function will be used when a port is created through the PortCreation tuple. :param x: x Coordinate in microns :param y: y Coordinate in microns :param rot: Rotation in degrees :param length: length of the port in microns """ # Append a serialized transformation to the code. if self.portlist != "": self.portlist += ";" trans = pya.CplxTrans(1, int(rot), False, int(x / self.layout.dbu), int(y / self.layout.dbu)) self.portlist += trans.to_s() self.portlist += ":" self.portlist += str(int(length / self.layout.dbu)) if name: self.portlist += f":name={name}" else: ori = 'E' if 45 <= rot < 135: ori = 'N' elif 125 <= rot < 225: ori = 'W' elif 215 <= rot < 315: ori = 'S' self.portlist += f":name={ori}{{n}}"
def print_image_definitions(filename, cv, reticle_id, dbu): # Scale for Mask, e.g. 4x scale = 4 #Calculate location of instances for inst in cv.cell.each_inst(): itrans = pya.ICplxTrans.from_trans(pya.CplxTrans()) box = inst.bbox().transformed(itrans) width = box.width()*dbu*scale/1000 height = box.height()*dbu*scale/1000 x = box.center().x*dbu*scale/1000. y = box.center().y*dbu*scale/1000. job_file_text = "START_SECTION IMAGE_DEFINITION\n" job_file_text += "\tIMAGE_ID \"{}\"\n".format(inst.cell.basic_name()) job_file_text += "\tRETICLE_ID \"{}\"\n".format(reticle_id) job_file_text += "\tIMAGE_SIZE {:.06f} {:.06f}\n".format(width, height) job_file_text += "\tIMAGE_SHIFT {:.06f} {:.06f}\n".format(x, y) job_file_text += "\tMASK_SIZE {:.06f} {:.06f}\n".format(width, height) job_file_text += "\tMASK_SHIFT {:.06f} {:.06f}\n".format(x, y) job_file_text += "\tVARIANT_ID \"\"\n" job_file_text += "END_SECTION\n\n" print(job_file_text) filename.write(job_file_text)
def write_distribution(job_file, cv, dbu): #For cellinstarray in wafer #Loop through various layouts on wafer #For cellinst in cellinstarray #Loop through all dies in particular layout, (cell selection) #For images in cellinst #Loop through images in die, writing entry for each image for inst in cv.cell.each_inst(): subcell = inst.cell # Determine indexes for cell selection if copysign(1, inst.a.x) == 1: start_index_x = 0 else: start_index_x = 1 if copysign(1, inst.b.y) == 1: start_index_y = 0 else: start_index_y = 1 x_index = arange(copysign(start_index_x, inst.a.x), copysign(inst.na, inst.a.x) + copysign(start_index_x, inst.a.x), copysign(1, inst.a.x)) y_index = arange(copysign(start_index_y, inst.b.y), copysign(inst.nb, inst.b.y) + copysign(start_index_y, inst.b.y), copysign(1, inst.b.y)) # Write each die type print("\nPrinting {} dies containing {}".format(inst.na*inst.nb, subcell.basic_name())) for i in x_index: for j in y_index: print("\tPrinting die at {:.0f}, {:.0f}".format(i, j)) for image in subcell.each_inst(): #Get position itrans = pya.ICplxTrans.from_trans(pya.CplxTrans()) box = image.bbox().transformed(itrans) x = box.center().x*dbu/1000. y = box.center().y*dbu/1000. #Write definition text = 'START_SECTION IMAGE_DISTRIBUTION\n' text += '\tIMAGE_ID "{}"\n'.format(image.cell.basic_name()) text += '\tINSTANCE_ID "{}"\n'.format("<Default>") text += '\tCELL_SELECTION "{:.0f}" "{:.0f}"\n'.format(i, j) text += '\tDISTRIBUTION_ACTION "I"\n' text += '\tOPTIMIZE_ROUTE "N"\n' text += '\tIMAGE_CELL_SHIFT {:.06f} {:.06f}\n'.format(x, y) text += 'END_SECTION\n\n' print(text) job_file.write(text) #for image in subcell.each_inst(): #print(image.cell.basic_name()) '''text = 'START_SECTION IMAGE_DISTRIBUTION\n'
def testKLayout(): #This performs a simple test of the class and draws the result on the active layout in KLayout filename = pya.FileDialog.ask_save_file_name("Save As SVG", "", "SVG (*.svg)") #Gets a reference to the active cell view cv = pya.CellView().active() lv = cv.view() #Gets a reference to the active layout layout = cv.layout() #Gets a reference to the active cell cell = cv.cell #Gets the database unit dbu = layout.dbu #Gets the binding box of the active cell bbox = cell.bbox() #Create a transform for KLayout coordinates to SVG coordinate tc = pya.CplxTrans(1.0, 0.0, True, -bbox.left, bbox.top) #Initialize an SVG object and specify its dimension s = svg(bbox.width() * dbu, bbox.height() * dbu) #Get all the layers in the layer view layerIterator = lv.each_layer() #For each layer for layer in layerIterator: #If the layer is not visible, then skip if not layer.visible: continue #Get all the shapes from this layer shapeIterator = cell.begin_shapes_rec(layer.layer_index()) #If there are no shapes, then skip if shapeIterator.at_end(): continue #Start an svg group s.startGroup(layer) while not shapeIterator.at_end(): shape = shapeIterator.shape() if shape.is_box(): #Insert a box shape with all the transformations and scaling s.insertBox( shape.box.transformed(tc * shapeIterator.trans()) * dbu) elif shape.is_polygon(): #Insert a polygon shape with all the transformations and scaling s.insertPolygon( shape.polygon.transformed(tc * shapeIterator.trans()) * dbu) #Go to the next shape in the iterator shapeIterator.next() #End an svg group s.endGroup() #Write the file s.write(filename)
def test_3_Trans(self): c = pya.CplxTrans(5, -7) self.assertEqual(str(c), "r0 *1 5,-7") self.assertEqual(str(pya.CplxTrans.from_s(str(c))), str(c)) c = pya.CplxTrans(pya.CplxTrans.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.CplxTrans.M135.rot()) self.assertEqual(str(c.s_trans()), "m135 0,0") self.assertAlmostEqual(c.angle, 270) c = pya.CplxTrans.from_dtrans(pya.DCplxTrans.M135) self.assertEqual(str(c), "m135 *1 0,0") c = pya.CplxTrans(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.CplxTrans.R0.rot()) self.assertEqual(str(c.s_trans()), "r0 0,0") self.assertAlmostEqual(c.angle, 0) c = pya.CplxTrans(0.75, 45, True, 2.5, -12.5) self.assertEqual(str(c), "m22.5 *0.75 2.5,-12.5") self.assertEqual(str(pya.CplxTrans.from_s(str(c))), str(c)) c = pya.CplxTrans(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.CplxTrans.M0.rot()) self.assertEqual(str(c.s_trans()), "m0 3,-13") self.assertAlmostEqual(c.angle, 45) self.assertEqual(str(c.ctrans(5)), "3.75") self.assertEqual(str(c.trans(pya.Point(12, 16))), "17.3492424049,-14.6213203436") self.assertEqual(str(pya.CplxTrans()), "r0 *1 0,0") self.assertEqual(pya.CplxTrans().is_unity(), True) self.assertEqual((c.inverted() * c).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")
def trans_cell(in_cell, angle=0, mirror=0, x=0, y=0, scale=1): bbx = in_cell.bbox() x_0 = bbx.left y_0 = bbx.bottom # print x_0,y_0 #x= x-x_0 #y= y-y_0 # print scale, angle, mirror, x, y trans = pya.CplxTrans(scale, angle, mirror, x, y) tmp_inst = pya.CellInstArray(in_cell.cell_index(), trans) return tmp_inst
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 make_layer_cells(): #Load View app = pya.Application.instance() mw = app.main_window() lv = mw.current_view() ly = lv.active_cellview().layout() dbu = ly.dbu if lv == None: raise Exception("No view selected") cv = lv.cellview(lv.active_cellview_index()) #Loop through layers for layer in [1, 2, 3]: new_cell = ly.create_cell(cv.cell.display_title() + "L" + str(layer)) # Loop through instances for inst in cv.cell.each_inst(): #Calculate location of instances itrans = pya.ICplxTrans.from_trans(pya.CplxTrans()) box = inst.bbox().transformed(itrans) x = box.center().x y = box.center().y #Create new cell to represent given layer new_subcell = ly.create_cell(inst.cell.display_title() + "L" + str(layer)) #Map Bounding box and shape layers to new layer lm = pya.LayerMapping() lm.map(ly.layer(1, 3), ly.layer(1, 3)) lm.map(ly.layer(layer, 0), ly.layer(layer, 0)) lm.map(ly.layer(layer, 1), ly.layer(layer, 0)) #Create Instance Array to place into cell array = pya.CellInstArray() #Copy shapes, place, and insert array.cell_index = new_subcell.cell_index() new_subcell.copy_shapes(inst.cell, lm) array.trans = pya.Trans(pya.Point(x, y)) new_cell.insert(array)
def create_port(self, x: float, y: float, rot: int = 0, length: int = 0): """Creates a Port at the specified coordinates. This function will be used when a port is created through the PortCreation tuple. :param x: x Coordinate in microns :param y: y Coordinate in microns :param rot: Rotation in degrees :param length: length of the port in microns """ # Append a serialized transformation to the code. if self.portlist != "": self.portlist += ";" trans = pya.CplxTrans(1, rot, False, x / self.layout.dbu, y / self.layout.dbu) self.portlist += trans.to_s() self.portlist += ":" self.portlist += str(int(length / self.layout.dbu))
def DrawAirbridge(self, cell, centerlinelist, newcellname="Airbige"): #CavityPainter生成的centerline未测试 for cpts in centerlinelist: IO.layout.read(self.filename) #每个腔用一个不同的cell装airbridge原型 for icell in IO.layout.top_cells(): if (icell.name == self.insertcellname): icell.name = newcellname distance = self.airbridgedistance // 2 dt_int = 0 for i, pt in enumerate(cpts[1:-1], 1): distance = distance + pt.distance(cpts[i - 1]) if distance // self.airbridgedistance != dt_int: dx = cpts[i + 1].x - cpts[i - 1].x dy = cpts[i + 1].y - cpts[i - 1].y tr = pya.CplxTrans(1, atan2(dy, dx) / pi * 180, False, pt.x, pt.y) new_instance = pya.CellInstArray( icell.cell_index(), tr) cell.insert(new_instance) dt_int = dt_int + 1
def test_6_Layout_props(self): ly = pya.Layout() pv = [[17, "a"], ["b", [1, 5, 7]]] pid = ly.properties_id(pv) ci1 = ly.add_cell("c1") ci2 = ly.add_cell("c2") linfo = pya.LayerInfo() linfo.layer = 16 linfo.datatype = 1 lindex = ly.insert_layer(linfo) linfo = pya.LayerInfo() linfo.layer = 16 linfo.datatype = 2 ldummy = ly.insert_layer(linfo) c1 = ly.cell(ci1) c2 = ly.cell(ci2) c1.shapes(lindex).insert(pya.Box(10, -10, 50, 40), pid) self.assertEqual(c1.bbox().to_s(), "(10,-10;50,40)") tr = pya.Trans(pya.Trans.R90, pya.Point(100, -50)) inst = pya.CellInstArray(c1.cell_index(), tr) self.assertEqual( inst.bbox(ly).to_s(), c1.bbox().transformed(tr).to_s()) self.assertEqual( inst.bbox_per_layer(ly, lindex).to_s(), c1.bbox().transformed(tr).to_s()) self.assertEqual(inst.bbox_per_layer(ly, ldummy).to_s(), "()") self.assertEqual(inst.size(), 1) self.assertEqual(inst.is_complex(), False) c2.insert(inst, pid) self.assertEqual(c2.bbox().to_s(), c1.bbox().transformed(tr).to_s()) c2.clear_insts() tr = pya.CplxTrans(1.5, 90.0, True, pya.DPoint(100, -50)) inst = pya.CellInstArray(c1.cell_index(), tr) inst2 = inst.dup() self.assertEqual( inst.bbox(ly).to_s(), c1.bbox().transformed(tr).to_s()) self.assertEqual(inst.size(), 1) self.assertEqual(inst.is_complex(), True) self.assertEqual(inst.is_regular_array(), False) c2.insert(inst, pid) self.assertEqual(c2.bbox().to_s(), c1.bbox().transformed(tr).to_s()) c2.clear_insts() self.assertEqual(c2.bbox().to_s(), "()") tr = pya.Trans(pya.Trans.R90, pya.Point(100, -50)) inst = pya.CellInstArray(c1.cell_index(), tr, pya.Point(100, 0), pya.Point(0, 100), 10, 20) self.assertEqual(inst == inst2, False) self.assertEqual(inst != inst2, True) inst2 = inst.dup() self.assertEqual(inst == inst2, True) self.assertEqual(inst != inst2, False) self.assertEqual(inst.bbox(ly).to_s(), "(60,-40;1010,1900)") self.assertEqual(inst.trans.to_s(), "r90 100,-50") self.assertEqual(inst.cplx_trans.to_s(), "r90 *1 100,-50") self.assertEqual(inst.size(), 200) self.assertEqual(inst.is_complex(), False) self.assertEqual(inst.is_regular_array(), True) self.assertEqual(inst.a.to_s(), "100,0") self.assertEqual(inst.b.to_s(), "0,100") self.assertEqual(inst.na, 10) self.assertEqual(inst.nb, 20) self.assertEqual(inst.cell_index, c1.cell_index()) c2.insert(inst, pid) self.assertEqual(c2.bbox().to_s(), "(60,-40;1010,1900)") inst.invert() self.assertEqual(inst == inst2, False) self.assertEqual(inst != inst2, True) self.assertEqual(inst.bbox(ly).to_s(), "(-1860,50;90,990)") self.assertEqual(inst.size(), 200) self.assertEqual(inst.is_complex(), False) self.assertEqual(inst.is_regular_array(), True) self.assertEqual(inst.a.to_s(), "0,100") self.assertEqual(inst.b.to_s(), "-100,0") self.assertEqual(inst.na, 10) self.assertEqual(inst.nb, 20) self.assertEqual(inst.cell_index, c1.cell_index()) if ly.is_editable(): for inst in c2.each_inst(): c2.erase(inst) self.assertEqual(c2.bbox().to_s(), "()") else: c2.clear_insts() self.assertEqual(c2.bbox().to_s(), "()") tr = pya.CplxTrans(1.5, 90.0, True, pya.DPoint(100, -50)) inst = pya.CellInstArray(c1.cell_index(), tr, pya.Point(100, 0), pya.Point(0, 100), 10, 20) self.assertEqual(inst.bbox(ly).to_s(), "(85,-35;1060,1925)") self.assertEqual(inst.size(), 200) self.assertEqual(inst.is_complex(), True) self.assertEqual(inst.cplx_trans.to_s(), "m45 *1.5 100,-50") inst_ret = c2.insert(inst, pid) self.assertEqual(c2.bbox().to_s(), "(85,-35;1060,1925)") self.assertEqual(inst == inst_ret.cell_inst, True) self.assertEqual(inst_ret.has_prop_id(), True) self.assertEqual(inst_ret.prop_id, pid) child_insts = [] for i in c2.each_inst(): child_insts.append(i) self.assertEqual(inst == child_insts[0].cell_inst, True) self.assertEqual(child_insts[0].has_prop_id(), True) self.assertEqual(child_insts[0].prop_id, pid) self.assertEqual(c2.child_instances(), 1) arr = [] for i in c2.each_inst(): arr.append(i) self.assertEqual(len(arr), 1) self.assertEqual(arr[0].cell_inst == inst, True) self.assertEqual(arr[0].prop_id == pid, True) arr = [] for i in c2.each_parent_inst(): arr.append(i) self.assertEqual(len(arr), 0) arr = [] for i in c1.each_inst(): arr.append(i) self.assertEqual(len(arr), 0) arr = [] for i in c1.each_parent_inst(): arr.append(i) self.assertEqual(len(arr), 1) self.assertEqual(arr[0].parent_cell_index(), c2.cell_index()) self.assertEqual(arr[0].child_inst().cell_index, c1.cell_index()) self.assertEqual(arr[0].inst().cell_index, c2.cell_index()) self.assertEqual(arr[0].inst().cplx_trans.to_s(), "m45 *0.666666667 33,-67") self.assertEqual(arr[0].child_inst().prop_id, pid) arr = [] for i in c2.each_overlapping_inst(pya.Box(100, 0, 110, 10)): arr.append(i) self.assertEqual(len(arr), 1) self.assertEqual(arr[0].cell_inst == inst, True) self.assertEqual(arr[0].prop_id == pid, True) arr = [] for i in c2.each_overlapping_inst(pya.Box(-100, 0, -90, 10)): arr.append(i) self.assertEqual(len(arr), 0) arr = [] for i in c2.each_touching_inst(pya.Box(100, 0, 110, 10)): arr.append(i) self.assertEqual(len(arr), 1) self.assertEqual(arr[0].cell_inst == inst, True) self.assertEqual(arr[0].prop_id == pid, True) arr = [] for i in c2.each_touching_inst(pya.Box(-100, 0, -90, 10)): arr.append(i) self.assertEqual(len(arr), 0) arr = [] for c in c2.each_child_cell(): arr.append(ly.cell_name(c)) self.assertEqual(arr, ["c1"]) arr = [] for c in c2.each_parent_cell(): arr.append(ly.cell_name(c)) self.assertEqual(arr, []) self.assertEqual(c2.child_cells(), 1) self.assertEqual(c2.parent_cells(), 0) self.assertEqual(c2.hierarchy_levels(), 1) arr = [] for c in c1.each_child_cell(): arr.append(ly.cell_name(c)) self.assertEqual(arr, []) arr = [] for c in c1.each_parent_cell(): arr.append(ly.cell_name(c)) self.assertEqual(arr, ["c2"]) self.assertEqual(c1.child_cells(), 0) self.assertEqual(c1.parent_cells(), 1) self.assertEqual(c1.hierarchy_levels(), 0)
def test_1_Polygon(self): a = pya.Polygon() self.assertEqual( str(a), "()" ) self.assertEqual( str(pya.Polygon.from_s(str(a))), str(a) ) self.assertEqual( a.is_box(), False ) b = a.dup() a = pya.Polygon( [ pya.Point( 0, 1 ), pya.Point( 1, 5 ), pya.Point( 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.Polygon.from_s(str(a))), str(a) ) 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.Polygon( pya.Box( 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.DPolygon(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.Point( 10, 0 ) ), True ) self.assertEqual( a.inside( pya.Point( 5, 0 ) ), True ) self.assertEqual( a.inside( pya.Point( 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.Point( 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.Point( 1, 0 ) ) self.assertEqual( str(a), "(6,-10;6,15;21,15;21,-10)" ) b = b.transformed( pya.Trans( pya.Trans.R0, pya.Point( 1, 0 )) ) self.assertEqual( str(b), "(6,-10;6,15;21,15;21,-10)" ) m = pya.CplxTrans( pya.Trans(), 1.5 ) self.assertEqual( str(a.transformed(m)), "(9,-15;9,22.5;31.5,22.5;31.5,-15)" ) self.assertEqual( str(a.transformed(pya.ICplxTrans(m))), "(9,-15;9,23;32,23;32,-15)" ) a.hull = [ pya.Point( 0, 1 ), pya.Point( 1, 1 ), pya.Point( 1, 5 ) ] self.assertEqual( str(a.bbox()), "(0,1;1,5)" ) self.assertEqual( a.holes(), 0 ) a.insert_hole( [ pya.Point( 1, 2 ), pya.Point( 2, 2 ), pya.Point( 2, 6 ) ] ) self.assertEqual( str(a), "(0,1;1,5;1,1/1,2;2,2;2,6)" ) self.assertEqual( str(pya.Polygon.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.Box( 10, 20, 20, 60 )) self.assertEqual( str(b), "(0,1;1,5;1,1/10,20;20,20;20,60;10,60)" ) self.assertEqual( b.is_box(), False ) b.insert_hole(pya.Box( 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)" ) b = a.dup() b.assign_hole(0, [ pya.Point( 10, 20 ), pya.Point( 20, 20 ), pya.Point( 20, 60 ) ]) self.assertEqual( str(b), "(0,1;1,5;1,1/10,20;20,20;20,60)" ) b.assign_hole(1, [ pya.Point( 15, 25 ), pya.Point( 25, 25 ), pya.Point( 25, 65 ) ]) self.assertEqual( str(b), "(0,1;1,5;1,1/10,20;20,20;20,60)" ) b.insert_hole( [ pya.Point( 1, 2 ), pya.Point( 2, 2 ), pya.Point( 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.Point( 15, 25 ), pya.Point( 25, 25 ), pya.Point( 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)"] ) a = pya.Polygon( [ pya.Point( 0, 1 ), pya.Point( 1, 5 ), pya.Point( 5, 5 ) ] ) self.assertEqual( str(a), "(0,1;1,5;5,5)" ) self.assertEqual( str(a.sized(2)), "(0,-2;-2,0;-1,7;7,7;8,5)" ) self.assertEqual( str(a.sized(2, 2)), "(0,-2;-2,0;-1,7;7,7;8,5)" ) aa = a.dup() a.size(2, 2) self.assertEqual( str(a), "(0,-2;-2,0;-1,7;7,7;8,5)" ) a = aa.dup() a.size(2) self.assertEqual( str(a), "(0,-2;-2,0;-1,7;7,7;8,5)" ) a = pya.Polygon( [ pya.Point( 0, 1 ), pya.Point( 1, 5 ), pya.Point( 5, 5 ) ] ) self.assertEqual( str(a), "(0,1;1,5;5,5)" ) self.assertEqual( str(a.sized(2, 0, 2)), "(-2,1;-1,5;7,5;2,1)" ) a.size(2, 0, 2); self.assertEqual( str(a), "(-2,1;-1,5;7,5;2,1)" ) a = pya.Polygon() self.assertEqual( str(a), "()" ) # corner rounding a = pya.Polygon( [ pya.Point(0, 0), pya.Point(0, 2000), pya.Point(4000, 2000), pya.Point(4000, 1000), pya.Point(2000, 1000), pya.Point(2000, 0) ] ) ar = a.round_corners(100, 200, 8) self.assertEqual( str(ar), "(117,0;0,117;0,1883;117,2000;3883,2000;4000,1883;4000,1117;3883,1000;2059,1000;2000,941;2000,117;1883,0)" ) ar = a.round_corners(200, 100, 32) self.assertEqual( str(ar), "(90,0;71,4;53,11;36,22;22,36;11,53;4,71;0,90;0,1910;4,1929;11,1947;22,1964;36,1978;53,1989;71,1996;90,2000;3910,2000;3929,1996;3947,1989;3964,1978;3978,1964;3989,1947;3996,1929;4000,1910;4000,1090;3996,1071;3989,1053;3978,1036;3964,1022;3947,1011;3929,1004;3910,1000;2180,1000;2142,992;2105,977;2073,955;2045,927;2023,895;2008,858;2000,820;2000,90;1996,71;1989,53;1978,36;1964,22;1947,11;1929,4;1910,0)" ) # Minkowsky sums p = pya.Polygon( [ pya.Point.new(0, -100), pya.Point.new(0, -50), pya.Point.new(-100, -75), pya.Point.new(0, 100), pya.Point.new(50, 50), pya.Point.new(100, 75), pya.Point.new(100, 0), pya.Point.new(100, -50) ] ) self.assertEqual(str(p.minkowsky_sum(pya.Edge.new(pya.Point.new(10, 10), pya.Point.new(210, 110)), True)), "(10,-90;10,-40;-90,-65;10,110;210,210;260,160;310,185;310,60)") self.assertEqual(str(p.minkowsky_sum([pya.Point.new(10, 10), pya.Point.new(10, 310), pya.Point.new(510, 310), pya.Point.new(510, 10), pya.Point.new(10, 10) ], False)), "(10,-90;10,-65;-90,-65;-90,235;10,410;510,410;535,385;610,385;610,-40;510,-90/110,110;410,110;410,210;110,210)") self.assertEqual(str(p.minkowsky_sum([pya.Point.new(10, 10), pya.Point.new(10, 310), pya.Point.new(510, 310), pya.Point.new(510, 10), pya.Point.new(10, 10) ], True)), "(10,-90;10,-65;-90,-65;-90,210;110,210;110,110;410,110;410,210;-90,210;-90,235;10,410;510,410;535,385;610,385;610,-40;510,-90)") self.assertEqual(str(p.minkowsky_sum(pya.Box.new(pya.Point.new(10, 10), pya.Point.new(210, 110)), True)), "(10,-90;10,-65;-90,-65;-90,35;10,210;210,210;235,185;310,185;310,-40;210,-90)") self.assertEqual(str(p.minkowsky_sum(pya.Box.new(pya.Point.new(10, 10), pya.Point.new(210, 10)), True)), "(10,-90;10,-65;-90,-65;10,110;210,110;235,85;310,85;310,-40;210,-90)") self.assertEqual(str(p.minkowsky_sum(pya.Polygon.new(pya.Box.new(pya.Point.new(10, 10), pya.Point.new(210, 110))), True)), "(10,-90;10,-65;-90,-65;-90,35;10,210;210,210;235,185;310,185;310,-40;210,-90)") # Smoothing p = pya.Polygon( [ pya.Point.new(0, 0), pya.Point.new(10, 50), pya.Point.new(0, 100), pya.Point.new(200, 100), pya.Point.new(200, 0) ]) self.assertEqual(str(p.smooth(5)), "(0,0;10,50;0,100;200,100;200,0)") self.assertEqual(str(p.smooth(15)), "(0,0;0,100;200,100;200,0)") # Ellipse constructor p = pya.Polygon.ellipse( pya.Box(-10000, -20000, 30000, 40000), 200 ) self.assertEqual(p.num_points(), 200) self.assertEqual(str(p.bbox()), "(-10000,-20000;30000,40000)") self.assertEqual(p.area(), 1884651158) # roughly box.area*PI/4 p = pya.Polygon.ellipse( pya.Box(-10000, -20000, 30000, 40000), 4 ) self.assertEqual(str(p), "(10000,-20000;-10000,10000;10000,40000;30000,10000)")
# -*- coding: utf-8 -*- #测试pcell import pya layout = pya.Layout() cell = layout.create_cell("Cell") child_cell = layout.create_cell("Child_Cell") cell.insert(pya.CellInstArray(child_cell.cell_index(), pya.Trans())) cell.insert( pya.CellInstArray(child_cell.cell_index(), pya.CplxTrans(1, 0, False, 100000, 100000))) layer1 = layout.layer(10, 10) pts = [ pya.Point(0, 0), pya.Point(50000, 0), pya.Point(50000, 50000), pya.Point(40000, 60000), pya.Point(0, 50000) ] polygon1 = pya.Polygon(pts) pts2 = [ pya.Point(20000, 0), pya.Point(60000, 0), pya.Point(60000, 50000), pya.Point(50000, 60000), pya.Point(20000, 50000) ] polygon2 = pya.Polygon(pts2)
def DrawAirbridge(self, cell, centerlinelist, newcellname="Airbige", collision={}): ''' collision = {} 表示不做检查 或者是 { 'region': pya.Region, 'regionInsert': pya.Region, 'push': int, 'extend': int, } 进行碰撞检测 ''' IO.layout.read(self.filename) for icell in IO.layout.top_cells(): if (icell.name == self.insertcellname): icell.name = newcellname break counts = [] distancesList = [] for cpts, brush in centerlinelist: distance = dp = 0 # distance 是实际距离,dp 用来计算是否放置airbridge distances = [] if not hasattr(self.airbridgedistance, '__call__'): distance = dp = self.airbridgedistance*0.25 dt_int = 0 pushlength = 0 # 下一个airbridge要额外推迟的距离 pushstatus = 'none' # none push extend for i, pt in enumerate(cpts[1:-1], 1): dis = pt.distance(cpts[i-1]) distance += dis if pushlength > 0: pushlength -= dis if pushlength > 0: continue else: dis = -pushlength pushlength = 0 dp += dis if hasattr(self.airbridgedistance, '__call__'): calt_int = self.airbridgedistance(dp) else: calt_int = dp//self.airbridgedistance if calt_int != dt_int: dx = cpts[i+1].x-cpts[i-1].x dy = cpts[i+1].y-cpts[i-1].y tr = pya.CplxTrans( 1, atan2(dy, dx)/pi*180, False, pt.x, pt.y) draw_ = True if collision: region_ = collision['regionInsert'].transformed( pya.ICplxTrans.from_trans(tr)) noconflict=(region_ & collision['region']).is_empty() if noconflict and pushstatus in ['none','extend']: collision['region'] = collision['region']+region_ collision['region'].merge() pushstatus='none' elif noconflict and pushstatus=='push': draw_ = False pushlength = collision['extend'] pushstatus='extend' else: # noconflict==False draw_ = False pushlength = collision['push'] pushstatus='push' if draw_: new_instance = pya.CellInstArray( icell.cell_index(), tr) cell.insert(new_instance) dt_int = dt_int+1 distances.append(distance) counts.append(dt_int) distancesList.append(distances) for icell in IO.layout.top_cells(): if (icell.name == self.insertcellname): icell.flatten(True) icell.delete() return counts, distancesList
def produce_impl(self): # Cross parameters cWidth = 10 cLength = 100 cGap = 0 cBorder = 10 cPos = pya.Point(0,0) # Vernier parameters vWidth = 4 vLength = 40 vPitch = 8 vGap = 0 vPosL = pya.Point(-120000,cPos.y) vPosB = pya.Point(cPos.x,-120000) # Mask number parameters mLineWidth = 4 mPos = pya.Point(140000,140000) # Border border = 10 # Create references to the active cell cv = pya.CellView().active() layout = cv.layout() dbu = self.layout.dbu # Position of the Alignment Marks posLeftMark = pya.Point(-self.pos*1000/dbu,0) posRightMark = pya.Point(self.pos*1000/dbu,0) s = shape() #Creates a cross if (self.cross == 0): #Solid Cross if (self.type == 0): #Wafer Type #Creates an inverted cross cross = s.cross((cWidth+2*cGap)/dbu, (cLength + 2*cGap)/dbu) cross = s.invert(cross, cBorder/dbu) cross.transform(pya.Trans(cPos)) else: cross = s.cross(cWidth/dbu, cLength/dbu) cross.transform(pya.Trans(cPos)) else: #Dashed Cross if (self.type == 0): #Wafer Type cross = s.cross(cWidth/dbu, cLength/dbu,1) cross = s.invert(cross, cBorder/dbu) cross.transform(pya.Trans(cPos)) else: cross = s.cross(cWidth/dbu, cLength/dbu,2) cross.transform(pya.Trans(cPos)) if (self.type == 0): #Wafer Type #Create Vernier Patterns vLeft = s.vernier(vWidth/dbu, vLength/dbu, vPitch/dbu) vLeft.transform(pya.Trans(vPosL)) vBot = vLeft.dup() vBot.transform(pya.Trans(1,0,0,0)) vRight = vLeft.dup() vRight.transform(pya.Trans(2,0,0,0)) vTop = vLeft.dup() vTop.transform(pya.Trans(3,0,0,0)) #Create Mask Number tt = pya.CplxTrans(mLineWidth, 0, False, -mPos.x, mPos.y) mNumLeft = s.text(self.num).transform(tt) mNumRight = mNumLeft.dup() mNumRight.transform(pya.Trans(2,True,0,0)) else: #Create Vernier Left 2 vLeft = s.vernier(vWidth/dbu, vLength/dbu, vPitch/dbu+self.res/dbu) vLeft.transform(pya.Trans(2, False, vPosL.x-vLength/dbu-vGap/dbu, vPosL.y)) vBot = vLeft.dup() vBot.transform(pya.Trans(1,0,0,0)) vRight = vLeft.dup() vRight.transform(pya.Trans(2,0,0,0)) vTop = vLeft.dup() vTop.transform(pya.Trans(3,0,0,0)) #Create Mask Number tt = pya.CplxTrans(mLineWidth, 0, False, -mPos.x, -mPos.y) mNumLeft = s.text(self.num).transform(tt) mNumRight = mNumLeft.dup() mNumRight.transform(pya.Trans(2,True,0,0)) #Create Shapes for Left Mark and Right Mark leftMarkCross = cross.dup() leftMarkCross.transform(pya.Trans(posLeftMark)) leftMarkVernierLeft = vLeft.dup() leftMarkVernierLeft.transform(pya.Trans(posLeftMark)) leftMarkVernierBot = vBot.dup() leftMarkVernierBot.transform(pya.Trans(posLeftMark)) leftMarkVernierRight = vRight.dup() leftMarkVernierRight.transform(pya.Trans(posLeftMark)) leftMarkVernierTop = vTop.dup() leftMarkVernierTop.transform(pya.Trans(posLeftMark)) leftMarkMNumLeft = mNumLeft.dup() leftMarkMNumLeft.transform(pya.Trans(posLeftMark)) leftMarkMNumRight = mNumRight.dup() leftMarkMNumRight.transform(pya.Trans(posLeftMark)) rightMarkCross = cross.dup() rightMarkCross.transform(pya.Trans(posRightMark)) rightMarkVernierLeft = vLeft.dup() rightMarkVernierLeft.transform(pya.Trans(posRightMark)) rightMarkVernierBot = vBot.dup() rightMarkVernierBot.transform(pya.Trans(posRightMark)) rightMarkVernierRight = vRight.dup() rightMarkVernierRight.transform(pya.Trans(posRightMark)) rightMarkVernierTop = vTop.dup() rightMarkVernierTop.transform(pya.Trans(posRightMark)) rightMarkMNumLeft = mNumLeft.dup() rightMarkMNumLeft.transform(pya.Trans(posRightMark)) rightMarkMNumRight = mNumRight.dup() rightMarkMNumRight.transform(pya.Trans(posRightMark)) #Creates the Wafer Alignment MarkCross regionLeft = pya.Region() regionLeft.insert(leftMarkCross) regionLeft.insert(leftMarkVernierLeft) regionLeft.insert(leftMarkVernierBot) regionLeft.insert(leftMarkVernierRight) regionLeft.insert(leftMarkVernierTop) regionLeft.insert(leftMarkMNumLeft) regionLeft.insert(leftMarkMNumRight) regionRight = pya.Region() regionRight.insert(rightMarkCross) regionRight.insert(rightMarkVernierLeft) regionRight.insert(rightMarkVernierBot) regionRight.insert(rightMarkVernierRight) regionRight.insert(rightMarkVernierTop) regionRight.insert(rightMarkMNumLeft) regionRight.insert(rightMarkMNumRight) if (self.type == 1) and (self.mask == 0): regionLeft = s.invert(regionLeft,border/dbu) regionRight = s.invert(regionRight,border/dbu) self.cell.shapes(self.layer_layer).insert(regionLeft) self.cell.shapes(self.layer_layer).insert(regionRight)
def produce_impl(self): # Cross parameters cWidth = 10 cLength = 100 cGap = 0 cBorder = 10 cPos = pya.Point(0, 0) # Vernier parameters vWidth = 4 vLength = 40 vPitch = 8 vGap = 0 vPosL = pya.Point(-120000, cPos.y) vPosB = pya.Point(cPos.x, -120000) # Mask number parameters mLineWidth = 4 mPosL = pya.Point(-40000, 90000) mPosR = pya.Point(40000, 90000) # Border border = 10 # Create references to the active cell cv = pya.CellView().active() layout = cv.layout() dbu = self.layout.dbu s = shape() #Creates a cross if (self.cross == 0): #Solid Cross if (self.type == 0): #Wafer Type #Creates an inverted cross cross = s.cross((cWidth + 2 * cGap) / dbu, (cLength + 2 * cGap) / dbu) cross = s.invert(cross, cBorder / dbu) cross.transform(pya.Trans(cPos)) else: cross = s.cross(cWidth / dbu, cLength / dbu) cross.transform(pya.Trans(cPos)) else: #Dashed Cross if (self.type == 0): #Wafer Type cross = s.cross(cWidth / dbu, cLength / dbu, 1) cross = s.invert(cross, cBorder / dbu) cross.transform(pya.Trans(cPos)) else: cross = s.cross(cWidth / dbu, cLength / dbu, 2) cross.transform(pya.Trans(cPos)) if (self.type == 0): #Wafer Type #Create Vernier Left 1 vLeft = s.vernier(vWidth / dbu, vLength / dbu, vPitch / dbu) vLeft.transform(pya.Trans(vPosL)) #Create Vernier Bottom 1 vBot = s.vernier(vWidth / dbu, vLength / dbu, vPitch / dbu) vBot.transform(pya.Trans(1, False, vPosB.x, vPosB.y)) #Create Mask Number tt = pya.CplxTrans(mLineWidth, 0, False, mPosL.x, mPosL.y) mNum = s.text(self.num).transform(tt) else: #Create Vernier Left 2 vLeft = s.vernier(vWidth / dbu, vLength / dbu, vPitch / dbu + self.res / dbu) vLeft.transform( pya.Trans(2, False, vPosL.x - vLength / dbu - vGap / dbu, vPosL.y)) #Create Vernier Bottom 2 vBot = s.vernier(vWidth / dbu, vLength / dbu, vPitch / dbu + self.res / dbu) vBot.transform( pya.Trans(3, False, vPosB.x, vPosB.y - vLength / dbu - vGap / dbu)) #Create Mask Number tt = pya.CplxTrans(mLineWidth, 0, False, mPosR.x, mPosR.y) mNum = s.text(self.num).transform(tt) #Creates the Wafer Alignment Mark region = pya.Region() region.insert(cross) region.insert(vLeft) region.insert(vBot) region.insert(mNum) if (self.type == 1) and (self.mask == 0): region = s.invert(region, border / dbu) self.cell.shapes(self.layer_layer).insert(region)
def _get_region_cell_port(region,brush,layerlist,boxx,boxy,offsetx=0,offsety=0,deltaangle=0,absx=None,absy=None,portbrushs=None,transmissionlines=None,crossoverLayerList=False):#added crossoverLayerList '''先把图像逆时针转deltaangle角度后沿着平直截取''' # if deltaangle>46 or deltaangle<-46:raise RuntimeError('deltaangle more than 45 degree') if absx==None or absy==None: _pb=[region.bbox()] if type(brush)!=type(None): painter=CavityPainter(brush) painter.Run(lambda painter:painter._Straight(10)+painter._Straight(-10)) _pb.append(painter.Output_Region().bbox()) _pbr=pya.Region() for ii in _pb:_pbr.insert(ii) pc=_pbr.bbox().center() else: pc=pya.DPoint(absx,absy) pc=pya.DPoint(pc.x+offsetx,pc.y+offsety) 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 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 box=tr_to(pya.Box(-boxx/2,-boxy/2,boxx/2,boxy/2),itr=True) # _,inregion=Interactive.cut(layerlist=layerlist,layermod='in',box=box,mergeanddraw=False) inregion=tr_back(inregion,itr=True) outregion=pya.Region(pya.Box(-boxx/2,-boxy/2,boxx/2,boxy/2)) if type(brush)!=type(None): painter=CavityPainter(tr_back(brush)) painter.Run(lambda painter:painter._Straight(-boxx-boxy)) painter.Run(lambda painter:painter.Straight(2*boxx+2*boxy)) inregion=inregion+painter.Output_Region() #计算端口 ports=[] edges=[ #左,上,右,下 pya.DEdge(-boxx/2,-boxy/2,-boxx/2,+boxy/2), pya.DEdge(-boxx/2,+boxy/2,+boxx/2,+boxy/2), pya.DEdge(+boxx/2,+boxy/2,+boxx/2,-boxy/2), pya.DEdge(+boxx/2,-boxy/2,-boxx/2,-boxy/2) ] # if type(brush)!=type(None): br=painter.brush pt=pya.DPoint(br.centerx,br.centery) angle=br.angle edge=pya.DEdge(pt.x,pt.y,pt.x-(2*boxx+2*boxy)*cos(angle/180*pi),pt.y-(2*boxx+2*boxy)*sin(angle/180*pi)) ports.extend([ee.crossing_point(edge) for ee in edges if ee.crossed_by(edge)]) if transmissionlines!=None: for transmissionline in transmissionlines: for info in transmissionline: cpts=info[0] pt0=cpts[0] for pt in cpts[1:]: edge=tr_back(pya.DEdge(pt0,pt)) pt0=pt ports.extend([ee.crossing_point(edge) for ee in edges if ee.crossed_by(edge)]) if portbrushs!=None: portbrushs=[tr_back(brush) for brush in portbrushs] ports.extend([pya.DPoint(brush.centerx,brush.centery) for brush in portbrushs]) ports=[[pt.x,pt.y] for pt in ports if abs(pt.x)<boxx/2+10 and abs(pt.y)<boxy/2+10] final_region,cell=Interactive._merge_and_draw(outregion,inregion,pya.CplxTrans(1,-deltaangle,False,pc.x,pc.y)) if crossoverLayerList!=False: final_region,cell=Interactive._merge_and_draw(outregion,inregion,pya.CplxTrans(1,-deltaangle,False,pc.x,pc.y),False) ######################added crossover_region_list########### # crossover_region_list=[] # if crossoverLayerList!=False: #for layerlist in crossoverLayerList: # _,crossover_inregion=Interactive.cut(layerlist=layerlist,layermod='in',box=box,mergeanddraw=False)#[1] #crossover_region_list.append(Interactive._merge_and_draw(outregion,crossover_inregion,None,False)[0]) # final_region,cell=Interactive._merge_and_draw(outregion,crossover_inregion,None,False) #if crossoverLayerList!=False: # final_region=[] # final_region=crossover_region return final_region,cell,ports
def test_6_EditableLayout(self): ly = pya.Layout(True) self.assertEqual(ly.is_editable(), True) ci1 = ly.add_cell("c1") ci2 = ly.add_cell("c2") c1 = ly.cell(ci1) c2 = ly.cell(ci2) tr = pya.CplxTrans(1.5, 90.0, True, pya.DPoint(100, -50)) inst = pya.CellInstArray(c1.cell_index(), tr) inst_ret = c2.insert(inst) self.assertEqual(inst_ret.trans.to_s(), "m45 100,-50") inst = pya.CellInstArray(c1.cell_index(), pya.CplxTrans()) inst_ret.cell_inst = inst self.assertEqual(inst_ret.trans.to_s(), "r0 0,0") manager = pya.Manager() ly = pya.Layout(True, manager) self.assertEqual(ly.is_editable(), True) ci1 = ly.add_cell("c1") ci2 = ly.add_cell("c2") c1 = ly.cell(ci1) c2 = ly.cell(ci2) tr = pya.CplxTrans(1.5, 90.0, True, pya.DPoint(100, -50)) inst = pya.CellInstArray(c1.cell_index(), tr) inst_ret = c2.insert(inst) self.assertEqual(inst_ret.trans.to_s(), "m45 100,-50") manager.transaction("trans") inst = pya.CellInstArray(c1.cell_index(), pya.CplxTrans()) inst_ret.cell_inst = inst self.assertEqual(inst_ret.trans.to_s(), "r0 0,0") manager.commit() manager.undo() c2 = ly.cell(ci2) for i in c2.each_inst(): inst_ret = i break self.assertEqual(inst_ret.trans.to_s(), "m45 100,-50") manager = None ly = pya.Layout(False) self.assertEqual(ly.is_editable(), False) ci1 = ly.add_cell("c1") ci2 = ly.add_cell("c2") c1 = ly.cell(ci1) c2 = ly.cell(ci2) tr = pya.CplxTrans(1.5, 90.0, True, pya.DPoint(100, -50)) inst = pya.CellInstArray(c1.cell_index(), tr) inst_ret = c2.insert(inst) self.assertEqual(inst_ret.trans.to_s(), "m45 100,-50") inst = pya.CellInstArray(c1.cell_index(), pya.CplxTrans()) error = True try: # should raise an error - non-editable layout does not support replacement of instances inst_ret.cell_inst = inst error = False except: pass self.assertEqual(error, True)