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 produce_impl(self): dbu = self.layout.dbu # resolve path info = pya.QFileInfo(self.path) if info.isRelative(): view = pya.Application.instance().main_window().current_view() designfile = view.active_cellview().filename() if designfile == "": self.error = "Error: In order to use relative file path, design must be saved first" return designdir = pya.QFileInfo(designfile).dir() path = designdir.absoluteFilePath(self.path) else: path = self.path # open image image = pya.QImage(path) if image.isNull(): self.error = "Error opening image" return image = image.convertToFormat(pya.QImage.Format_Grayscale8) width = image.width() height = image.height() tilesx = math.ceil(width / self.t) tilesy = math.ceil(height / self.t) for tiley in range(tilesy): for tilex in range(tilesx): tile = image.copy(tilex * self.t, tiley * self.t, self.t, self.t) polygons = [] # generate pixels rangex = rangey = self.t if self.t * (tilex + 1) > width: rangex = width % self.t if self.t * (tiley + 1) > height: rangey = height % self.t for y in range(rangey): for x in range(rangex): color = pya.QColor(tile.pixel(x, y)) color = (color.red + color.green + color.blue) / 3 if (color > self.th and not self.inv) or (color <= self.th and self.inv): x1 = (tilex * self.t + x) * self.px / dbu y1 = -(tiley * self.t + y) * self.px / dbu x2 = (tilex * self.t + x + 1) * self.px / dbu y2 = -(tiley * self.t + y + 1) * self.px / dbu polygons.append( pya.Polygon( pya.Box( pya.Point.from_dpoint( pya.DPoint(x1, y1)), pya.Point.from_dpoint( pya.DPoint(x2, y2))))) # merge processor = pya.EdgeProcessor() merged = processor.simple_merge_p2p(polygons, False, False) for polygon in merged: self.cell.shapes(self.l_layer).insert(polygon) self.error = None
def extend_photo_overetching(self): tmp_reg = Region() ep = pya.EdgeProcessor() for poly in self.region_ph.each(): tmp_reg.insert( ep.simple_merge_p2p([ poly.sized(FABRICATION.OVERETCHING, FABRICATION.OVERETCHING, 2) ], False, False, 1)) self.region_ph = tmp_reg
def extended_region(reg, extension=0): """ extends region in outer direction by `extension` value. extension is orthogonal to region`s polygons edges. Parameters ---------- reg : Region pya.Region instance extension : float extension in nm Returns ------- Region extended version of region """ tmp_reg = Region() ep = pya.EdgeProcessor() for poly in reg.each(): tmp_reg.insert( ep.simple_merge_p2p([poly.sized(extension, extension, 2)], False, False, 1)) return tmp_reg
from math import sin, cos, pi, sqrt, atan2 from load_params import * import pya # Create layout and top cell layout = pya.Layout() top = layout.create_cell("TOP") # Rotation transformation def rotate(theta=360 / n_sides): return pya.ICplxTrans(1, theta, False, 0, 0) # Edge processor ep = pya.EdgeProcessor() # Create layers nemanc = layout.layer(1, 0) nemchan = layout.layer(2, 0) nemcont = layout.layer(3, 0) nembody = layout.layer(4, 0) nemholes = layout.layer(5, 0) nemsub = layout.layer(6, 0) nemsubg = layout.layer(7, 0) nemland = layout.layer(8, 0) # Create anchors ancloc = L_plate / 2 + W_cant + L_anc / 2 ancloc = pya.Point(ancloc, ancloc) anchor = pya.Box(-L_via / 2, -L_via / 2, L_via / 2, L_via / 2).move(ancloc)
def make_cpw(): #Load View app = pya.Application.instance() mw = app.main_window() lv = mw.current_view() ly = lv.active_cellview().layout() dbu = ly.dbu center_radius = 100.0 / dbu #Curve radius center_width = 10. / dbu #Center conductor width s_width = 7. / dbu #Center - Outer conductor spacing keepout_width = center_width * 0.4 #Keepout spacing ri = center_radius - .5 * center_width #Inner radius ro = center_radius + .5 * center_width # Outer radius n = 10 / dbu #Number of points per curve cpw_layer = ly.layer(1, 0) keepout_layer = ly.layer(1, 6) if lv == None: raise Exception("No view selected") lv.transaction("Make CPW") selected_objects = lv.each_object_selected() print("x") for obj in selected_objects: if obj.shape.is_path() and not obj.is_cell_inst(): inner = pya.Path() outer = pya.Path() keepout = pya.Path() print(obj.shape.path) inner = obj.shape.path outer = obj.shape.path keepout = obj.shape.path #Adjust widths inner.width = center_width outer.width = inner.width + 2 * s_width keepout.width = outer.width + 2 * keepout_width #Round Corners inner = [inner.polygon().round_corners(ri, ro, n)] outer = [ outer.polygon().round_corners(ri - s_width, ro + s_width, n) ] keepout = keepout.polygon().round_corners( ri - s_width - keepout_width, ro + s_width + keepout_width, n) #Subtract inner from outer ep = pya.EdgeProcessor() outer_minus_inner = ep.boolean_p2p(outer, inner, pya.EdgeProcessor().ModeANotB, True, False) for p in outer_minus_inner: lv.active_cellview().cell.shapes(cpw_layer).insert(p) # lv.active_cellview().cell.shapes(cpw_layer).insert(outer_minus_inner[0]) lv.active_cellview().cell.shapes(keepout_layer).insert(keepout) lv.commit()