def test_polygon_with_hole(self): r = Region() r.insert(Box(0, 0, 1000, 1000)) r -= Region(Box(250, 250, 700, 700)) fragments = frag.Fragments(r[0], 300) self.assertEqual( repr(fragments), "(0,0;0,350),(0,350;0,650),(0,650;0,1000),(0,1000;350,1000),(350,1000;650,1000),(650,1000;1000,1000),(1000,1000;1000,650),(1000,650;1000,350),(1000,350;1000,0),(1000,0;650,0),(650,0;350,0),(350,0;0,0);(250,250;700,250),(700,250;700,700),(700,700;250,700),(250,700;250,250)" ) poly = fragments.to_polygon() self.assertEqual(str(poly), str(r[0])) # apply alternating shifts s = 10 for ff in fragments.fragments(): for f in ff: f.move(s) s = -s poly = fragments.to_polygon() self.assertEqual( str(poly), "(350,-10;350,10;-10,10;-10,350;10,350;10,650;-10,650;-10,990;350,990;350,1010;650,1010;650,990;1010,990;1010,650;990,650;990,350;1010,350;1010,10;650,10;650,-10/240,260;710,260;710,690;240,690)" )
def init_regions(self): origin = DPoint(0, 0) hor_box = DBox(origin - DPoint(self.l / 2, self.t / 2), DPoint(self.l / 2, self.t / 2)) vert_box = DBox(origin - DPoint(self.t / 2, self.l / 2), DPoint(self.t / 2, self.l / 2)) cross = (Region(hor_box) + Region(vert_box)).merge() if self.inverse: self.empty_region.insert(cross) else: self.metal_region.insert(cross)
def __init__(self, origin, trans_in=None, inverse=False): ## MUST BE IMPLEMENTED ## self.connections = [] # DPoint list with possible connection points self.connection_edges = [ ] # indexes of edges that are intended to connect to other polygons # indexes in "self.connection_edges" where Sonnet ports # should be placed self.sonnet_port_connections = [] self.angle_connections = [] #list with angle of connecting elements ## MUST BE IMLPEMENTED END ## self.connection_ptrs = [ ] # pointers to connected structures represented by their class instances self.origin = origin self.inverse = inverse self.metal_region = Region() self.empty_region = Region() self.metal_regions = {} self.empty_regions = {} self.metal_regions["default"] = self.metal_region self.empty_regions["default"] = self.empty_region self.metal_region.merged_semantics = True self.empty_region.merged_semantics = True self.DCplxTrans_init = None self.ICplxTrans_init = None if (trans_in is not None): # if( isinstance( trans_in, ICplxTrans ) ): <==== FORBIDDEN if (isinstance(trans_in, DCplxTrans)): self.DCplxTrans_init = trans_in self.ICplxTrans_init = ICplxTrans().from_dtrans(trans_in) elif (isinstance(trans_in, CplxTrans)): self.DCplxTrans_init = DCplxTrans().from_itrans(trans_in) self.ICplxTrans_init = ICplxTrans().from_trans(trans_in) elif (isinstance(trans_in, DTrans)): self.DCplxTrans_init = DCplxTrans(trans_in, 1) self.ICplxTrans_init = ICplxTrans( Trans().from_dtrans(trans_in), 1) elif (isinstance(trans_in, Trans)): self.DCplxTrans_init = DCplxTrans( DTrans().from_itrans(trans_in), 1) self.ICplxTrans_init = ICplxTrans(trans_in, 1) self._init_regions_trans()
def __init__(self, cell_name): # getting main references of the application app = klayout.db.Application.instance() mw = app.main_window() self.lv = mw.current_view() self.cv = None self.cell = None self.region_ph = Region() self.region_el = Region() #this insures that lv and cv are valid objects if (self.lv == None): self.cv = mw.create_layout(1) self.lv = mw.current_view() else: self.cv = self.lv.active_cellview() # find or create the desired by programmer cell and layer layout = self.cv.layout() layout.dbu = 0.001 if (layout.has_cell(cell_name)): self.cell = layout.cell(cell_name) else: self.cell = layout.create_cell(cell_name) info = klayout.db.LayerInfo(1, 0) info2 = klayout.db.LayerInfo(2, 0) self.layer_ph = layout.layer(info) # photoresist layer self.layer_el = layout.layer(info2) # e-beam lithography layer # clear this cell and layer self.cell.clear() # setting layout view self.lv.select_cell(self.cell.cell_index(), 0) self.lv.add_missing_layers() # design parameters that were passed to the last # self.draw(...) call are stored here as ordered dict self.design_pars = OrderedDict()
def test_lshaped_polygon(self): r = Region() r.insert(Box(0, 0, 1000, 500)) r.insert(Box(0, 0, 500, 1000)) r.merge() fragments = frag.Fragments(r[0], 300) self.assertEqual( repr(fragments), "(0,0;0,350),(0,350;0,650),(0,650;0,1000),(0,1000;500,1000),(500,1000;500,500),(500,500;1000,500),(1000,500;1000,0),(1000,0;650,0),(650,0;350,0),(350,0;0,0)" ) poly = fragments.to_polygon() self.assertEqual(str(poly), str(r[0])) # apply alternating shifts s = 10 for ff in fragments.fragments(): for f in ff: f.move(s) s = -s poly = fragments.to_polygon() self.assertEqual( str(poly), "(350,-10;350,10;-10,10;-10,350;10,350;10,650;-10,650;-10,990;510,990;510,490;1010,490;1010,10;650,10;650,-10)" )
def place(self, dest, layer_i=-1, region_name=None): if (layer_i != -1): r_cell = Region(dest.begin_shapes_rec(layer_i)) for primitive in self.primitives.values(): primitive.place(r_cell, region_name=region_name) temp_i = dest.layout().layer( klayout.db.LayerInfo(PROGRAM.LAYER1_NUM, 0)) dest.shapes(temp_i).insert(r_cell) dest.layout().clear_layer(layer_i) dest.layout().move_layer(temp_i, layer_i) dest.layout().delete_layer(temp_i) else: for primitive in self.primitives.values(): primitive.place(dest, region_name=region_name)
def init_regions(self): origin = DPoint(0, 0) Rin = self.r - self.t Rout = self.r dpts_arr_Rout = [ DPoint(Rout * cos(2 * pi * i / self.n_pts), Rout * sin(2 * pi * i / self.n_pts)) for i in range(0, self.n_pts) ] dpts_arr_Rin = [ DPoint(Rin * cos(2 * pi * i / self.n_pts), Rin * sin(2 * pi * i / self.n_pts)) for i in range(0, self.n_pts) ] outer_circle = Region(SimplePolygon().from_dpoly( DSimplePolygon(dpts_arr_Rout))) inner_circle = Region(SimplePolygon().from_dpoly( DSimplePolygon(dpts_arr_Rin))) ring = outer_circle - inner_circle #self.metal_region.insert(ring) if self.inverse: self.empty_region = ring else: self.metal_region = ring
def init_regions(self): w_pad, g_pad = self._pad_cpw_params["w"], self._pad_cpw_params["g"] w_feed, g_feed = self._feedline_cpw_params[ "w"], self._feedline_cpw_params["g"] x, y = self._ground_connector_width + self._back_gap, 0 metal_points = [ DPoint(x, y + w_pad / 2), DPoint(x + self._pad_length, y + w_pad / 2), DPoint(x + self._pad_length + self._transition_length, y + w_feed / 2), DPoint(x + self._pad_length + self._transition_length, y - w_feed / 2), DPoint(x + self._pad_length, y - w_pad / 2), DPoint(x, y - w_pad / 2) ] metal_poly = DSimplePolygon(metal_points) self.metal_region.insert(metal_poly) protect_points = [ DPoint(x - self._back_gap, y + w_pad / 2 + g_pad), DPoint(x + self._pad_length, y + w_pad / 2 + g_pad), DPoint(x + self._pad_length + self._transition_length, y + w_feed / 2 + g_feed), DPoint(x + self._pad_length + self._transition_length, y - w_feed / 2 - g_feed), DPoint(x + self._pad_length, y - w_pad / 2 - g_pad), DPoint(x - self._back_gap, y - w_pad / 2 - g_pad) ] protect_poly = DSimplePolygon(protect_points) protect_region = Region(protect_poly) empty_region = protect_region - self.metal_region self.empty_region.insert(empty_region) self.connections = [ DPoint(0, 0), DPoint(x + self._pad_length + self._transition_length, 0) ] self.angle_connections = [pi, 0]
def init_regions(self): origin = DPoint(0, 0) w = self.out_a / 2 - self.in_a / 2 rec1 = Rectangle(origin, w, w) p2 = origin + DPoint(self.in_a + w, 0) rec2 = Rectangle(p2, w, w) p3 = origin + DPoint(self.in_a + w, self.in_a + w) rec3 = Rectangle(p3, w, w) p4 = origin + DPoint(0, self.in_a + w) rec4 = Rectangle(p4, w, w) tmp_reg = Region() rec1.place(tmp_reg) rec2.place(tmp_reg) rec3.place(tmp_reg) rec4.place(tmp_reg) rec = Rectangle(origin, self.out_a, self.out_a) rec.place(self.metal_region) self.empty_region = tmp_reg self.connections = [self.center]
def place(self, dest, layer_i=-1, region_name=None, merge=False): r_cell = None metal_region = None empty_region = None if (region_name == None): metal_region = self.metal_region empty_region = self.empty_region else: if (region_name in self.metal_regions): metal_region = self.metal_regions[region_name] else: metal_region = Region() if (region_name in self.empty_regions): empty_region = self.empty_regions[region_name] else: empty_region = Region() if (layer_i != -1): r_cell = Region(dest.begin_shapes_rec(layer_i)) temp_i = dest.layout().layer( klayout.db.LayerInfo(PROGRAM.LAYER1_NUM, 0)) r_cell += metal_region r_cell -= empty_region if (merge is True): r_cell.merge() dest.shapes(temp_i).insert(r_cell) dest.layout().clear_layer(layer_i) dest.layout().move_layer(temp_i, layer_i) dest.layout().delete_layer(temp_i) if (layer_i == -1 ): # dest is interpreted as instance of Region() class dest += metal_region dest -= empty_region if (merge is True): dest.merge()
class Element_Base(): ''' @brief: base class for simple single-layer or multi-layer elements and objects that are consisting of several polygons. metal_region polygons will be added to the design empty_region polygons will be erased from the background with metal region polygons already added. ''' def __init__(self, origin, trans_in=None, inverse=False): ## MUST BE IMPLEMENTED ## self.connections = [] # DPoint list with possible connection points self.connection_edges = [ ] # indexes of edges that are intended to connect to other polygons # indexes in "self.connection_edges" where Sonnet ports # should be placed self.sonnet_port_connections = [] self.angle_connections = [] #list with angle of connecting elements ## MUST BE IMLPEMENTED END ## self.connection_ptrs = [ ] # pointers to connected structures represented by their class instances self.origin = origin self.inverse = inverse self.metal_region = Region() self.empty_region = Region() self.metal_regions = {} self.empty_regions = {} self.metal_regions["default"] = self.metal_region self.empty_regions["default"] = self.empty_region self.metal_region.merged_semantics = True self.empty_region.merged_semantics = True self.DCplxTrans_init = None self.ICplxTrans_init = None if (trans_in is not None): # if( isinstance( trans_in, ICplxTrans ) ): <==== FORBIDDEN if (isinstance(trans_in, DCplxTrans)): self.DCplxTrans_init = trans_in self.ICplxTrans_init = ICplxTrans().from_dtrans(trans_in) elif (isinstance(trans_in, CplxTrans)): self.DCplxTrans_init = DCplxTrans().from_itrans(trans_in) self.ICplxTrans_init = ICplxTrans().from_trans(trans_in) elif (isinstance(trans_in, DTrans)): self.DCplxTrans_init = DCplxTrans(trans_in, 1) self.ICplxTrans_init = ICplxTrans( Trans().from_dtrans(trans_in), 1) elif (isinstance(trans_in, Trans)): self.DCplxTrans_init = DCplxTrans( DTrans().from_itrans(trans_in), 1) self.ICplxTrans_init = ICplxTrans(trans_in, 1) self._init_regions_trans() def init_regions(self): raise NotImplementedError # first it makes trans_init displacement # then the rest of the trans_init # then displacement of the current state to the origin # after all, origin should be updated def _init_regions_trans(self): self.init_regions() # must be implemented in every subclass dr_origin = DSimplePolygon([DPoint(0, 0)]) if (self.DCplxTrans_init is not None): # constructor trans displacement dCplxTrans_temp = DCplxTrans(1, 0, False, self.DCplxTrans_init.disp) self.make_trans(dCplxTrans_temp) dr_origin.transform(dCplxTrans_temp) # rest of the constructor trans functions dCplxTrans_temp = self.DCplxTrans_init.dup() dCplxTrans_temp.disp = DPoint(0, 0) self.make_trans(dCplxTrans_temp) dr_origin.transform(dCplxTrans_temp) # translation to the old origin (self.connections are already contain proper values) self.make_trans(DCplxTrans(1, 0, False, self.origin)) # move to the origin self.origin += dr_origin.point(0) def make_trans(self, dCplxTrans): if (dCplxTrans is not None): iCplxTrans = ICplxTrans().from_dtrans(dCplxTrans) self.metal_region.transform(iCplxTrans) self.empty_region.transform(iCplxTrans) self._update_connections(dCplxTrans) self._update_alpha(dCplxTrans) def _update_connections(self, dCplxTrans): if (dCplxTrans is not None): # the problem is, if i construct polygon with multiple points # their order in poly_temp.each_point() doesn't coinside with the # order of the list that was passed to the polygon constructor # so, when i perform transformation and try to read new values through poly_temp.each_point() # they values are rearranged # solution is: i need to create polygon for each point personally, and the initial order presists for i, pt in enumerate(self.connections): poly_temp = DSimplePolygon([pt]) poly_temp.transform(dCplxTrans) self.connections[i] = poly_temp.point(0) def _update_alpha(self, dCplxTrans): if (dCplxTrans is not None): dCplxTrans_temp = dCplxTrans.dup() dCplxTrans_temp.disp = DPoint(0, 0) for i, alpha in enumerate(self.angle_connections): poly_temp = DSimplePolygon([DPoint(cos(alpha), sin(alpha))]) poly_temp.transform(dCplxTrans_temp) pt = poly_temp.point(0) self.angle_connections[i] = atan2(pt.y, pt.x) def _update_origin(self, dCplxTrans): if (dCplxTrans is not None): poly_temp = DSimplePolygon([self.origin]) poly_temp.transform(dCplxTrans) self.origin = poly_temp.point(0) def place(self, dest, layer_i=-1, region_name=None, merge=False): r_cell = None metal_region = None empty_region = None if (region_name == None): metal_region = self.metal_region empty_region = self.empty_region else: if (region_name in self.metal_regions): metal_region = self.metal_regions[region_name] else: metal_region = Region() if (region_name in self.empty_regions): empty_region = self.empty_regions[region_name] else: empty_region = Region() if (layer_i != -1): r_cell = Region(dest.begin_shapes_rec(layer_i)) temp_i = dest.layout().layer( klayout.db.LayerInfo(PROGRAM.LAYER1_NUM, 0)) r_cell += metal_region r_cell -= empty_region if (merge is True): r_cell.merge() dest.shapes(temp_i).insert(r_cell) dest.layout().clear_layer(layer_i) dest.layout().move_layer(temp_i, layer_i) dest.layout().delete_layer(temp_i) if (layer_i == -1 ): # dest is interpreted as instance of Region() class dest += metal_region dest -= empty_region if (merge is True): dest.merge() def add_sonnet_port(self, connection_idx): ''' @brief: sets internal marker that during export to Sonnet the port should be placed at the connection edge with an index 'connection_idx' ''' print(self.connections) self.sonnet_port_connections.append(self.connections[connection_idx])
def __erase_in_layer(self, layer, box): reg_l = self._reg_from_layer(layer) box_reg = Region(box) reg_l &= box_reg