コード例 #1
0
    def transform_layer(self, layer_i, trans, trans_ports=False):
        """
        Performs transofmation of the layer desired.

        Parameters
        ----------
        layer_i : int
            layer index, >0
        trans : Union[DcplxTrans, DTrans]
            transformation to perform
        trans_ports : bool
            If `True` also performs transform of `self.sonnet_ports`
            as they are vectors.

        Returns
        -------
        None
        """
        r_cell = Region(self.cell.begin_shapes_rec(layer_i))

        r_cell.transform(trans)

        temp_i = self.cell.layout().layer(pya.LayerInfo(PROGRAM.LAYER1_NUM, 0))
        self.cell.shapes(temp_i).insert(r_cell)
        self.cell.layout().clear_layer(layer_i)
        self.cell.layout().move_layer(temp_i, layer_i)
        self.cell.layout().delete_layer(temp_i)

        if trans_ports:
            self.sonnet_ports = list(
                DSimplePolygon(
                    self.sonnet_ports).transform(trans).each_point())
コード例 #2
0
ファイル: region bbox.py プロジェクト: yursa97/KLayout-python
class Element_Base():
    def __init__(self, origin, trans_in=None):
        ## MUST BE IMPLEMENTED ##
        self.connections = []  # DPoint list with possible connection points
        self.angle_connections = []  #list with angle of connecting elements
        self.connection_ptrs = [
        ]  # pointers to connected structures represented by their class instances
        ## MUST BE IMLPEMENTED END ##
        self.origin = origin
        self.metal_region = Region()
        self.empty_region = Region()
        self.metal_region.merged_semantics = False
        self.empty_region.merged_semantics = False
        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 alredy 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):
        r_cell = None
        if (layer_i != -1):
            r_cell = Region(dest.begin_shapes_rec(layer_i))

        # how to interpret destination
        if (layer_i == -1):
            dest += self.metal_region
            dest -= self.empty_region
        else:
            temp_i = dest.layout().layer(pya.LayerInfo(PROGRAM.LAYER1_NUM, 0))
            dest.shapes(temp_i).insert(r_cell + self.metal_region -
                                       self.empty_region)
            dest.layout().clear_layer(layer_i)
            dest.layout().move_layer(temp_i, layer_i)
            dest.layout().delete_layer(temp_i)
コード例 #3
0
ファイル: BaseClasses.py プロジェクト: yursa97/KLayout-python
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(pya.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])
コード例 #4
0
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._geometry_parameters = OrderedDict()
        self._init_regions_trans()

    def get_geometry_params_dict(self, prefix="", postfix=""):
        """
        Function return geometry parameters in format:
        dict[prefix + key + postfix, value]

        Parameters
        ----------
        prefix : str
        postfix : str

        Returns
        -------
        dict
        """
        if hasattr(self, "_geometry_parameters"):
            tmp_dict = {}
            for key, item in self._geometry_parameters.items():
                tmp_dict[prefix + key + postfix] = item
            return tmp_dict
        else:
            print("Geometry parameters for ", self.__class__,
                  " does not implemented")
            return None

    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)
        self._refresh_named_connections()

    def _refresh_named_connections(self):
        """
            if there is connections in `self.connections` that
        have specific class attribute e.g. `self.end` is assumed
        to coincide with `self.connections[1]`, then this function
        is used to update this correspondance after connections
        are changed due to call of `self.make_trans`.
            See ClassLib.Coplanars.CPW class for example.
        """
        # can be implemented in child class
        # see ClassLib.Coplanars.CPW for example
        pass

    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)
            self._refresh_named_angles()

    def _refresh_named_angles(self):
        """
            If there is angles in `self.angle_connections` that
        have specific class attribute e.g. `self.end_angle` is assumed
        to coincide with `self.angle_connections[1]`, then this function
        is used to update this correspondance after connections
        are changed due to call of `self.make_trans`.
            See ClassLib.Coplanars.CPW class for example.
        """
        pass

    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(pya.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()