# The Database API

The basic object of the database is the object. A Layout object represents a layout file or a layout generated. Basically, a layout is a collection of cells and geometrical shapes. The shapes are organised in layers and the cells can be instantiated in other cells creating a hierarchy of cells. Hence, the basic objects of the database are Layout, Cell, Shapes and the geometrical primitives like Box, Path, Polygon, Text and Edge.

## The Layout class

The object is the basic container for a layout. Multiple layouts can live within KLayout. Some are stored inside the application and are created when a layout is loaded for example. However, layout objects can also be created as standalone objects for manipulation by Ruby scripts. Such a layout can be an isolated entity without connection to a view.

### A basic sample

This is a sample how to create a layout in a layout view with one cell ("TOP"), one layer (layer 10, datatype 0) and one shape (a 1x2 micron box). This sample also shows how to set up the layout view properly:

    # create a new view (mode 1) with an empty layout
    main_window = RBA::Application::instance.main_window
    layout = main_window.create_layout(1).layout
    layout_view = main_window.current_view

    # set the database unit (shown as an example, the default is 0.001)
    layout.dbu = 0.001

    # create a cell
    cell = layout.create_cell("TOP")

    # create a layer
    layer_index = layout.insert_layer(RBA::LayerInfo::new(10, 0))

    # add a shape
    cell.shapes(layer_index).insert(RBA::Box::new(0, 0, 1000, 2000))

    # select the top cell in the view, set up the view's layer list and
    # fit the viewport to the extensions of our layout
    layout_view.select_cell(cell.cell_index, 0)
    layout_view.add_missing_layers
    layout_view.zoom_fit

It is also possible to create a standalone layout. Here is an example how to create the layout without a connection to a view and save that layout to a file:

    # create the layout
    layout = RBA::Layout::new

    # set the database unit (shown as an example, the default is 0.001)
    layout.dbu = 0.001

    # create a cell
    cell = layout.create_cell("TOP")

    # create a layer
    layer_index = layout.insert_layer(RBA::LayerInfo::new(10, 0))

    # add a shape
    cell.shapes(layer_index).insert(RBA::Box::new(0, 0, 1000, 2000))

    # save the layout
    layout.write("my_layout.gds")

### Overview over the Layout object

The basic building blocks of layouts are layers and cells. Layers are not individual objects. Instead, a layer is rather an index and the various methods allow to address shapes inside layers by using that index. However, the layout object stores the layer properties, i.e. the layer and datatype number.

Cells are represented by objects which are described later. Cells are often referred to by a cell index which is basically an ID which allows identification of a cell without having to keep a reference. The Layout object allows converting of a cell index to a cell reference with the method. Cells can be instantiated inside other cells. Instances are described by objects.

Another important property of the layout object is the database unit. In the layout, all geometrical coordinates are stored as integer values for efficiency. The database unit specifies the length of one unit in micrometers. The database unit can be accessed with the attribute. Changing the database unit effectively scales a layout. Often the database unit is a fixed value and compatibility between different layouts in a flow often demands use of a specific database unit. Hence, changing the value of the database unit is possible but requires some careful consideration.

The Layout object keeps shapes (texts, polygons, boxes, paths etc.) on "layers". A layer is a collection of shapes. A layout features a set of layers and each cell provides space for each layer. The shapes are stored inside the cells while the layers are managed by the layout. For doing so, the Layout object keeps layers as a table of objects. The LayerInfo object carries information about the description of a layer, for example layer and datatype number and/or the layer name. A layer is basically just an index in that table. Layers can be created using the method. Each layer is present in every cell and inside a cell, a shape storage for each layer is provided.

Inside the layout object, shapes are kept with integer coordinates. The physical units can be obtained by multiplying the integer coordinates with the database unit. The integer type objects are , etc. Most objects also support floating-point coordinate objects (, etc.). These objects are then given in micrometer units - i.e. already multiplied by the database unit. If using these objects, keep in mind that internally they are still integer-type objects. This means, rounding to the database will happen and if you change the database unit, the objects will effectively scale.

A Layout object provides some basic layout manipulation and query methods. For example, it provides a method to retrieve shapes touching or overlapping a certain rectangular region of a cell. It also provides a clip method which extracts a rectangular region from a layout (, , , ). It provides methods to delete cells and cell trees and (, , , , ). There are also methods to manipulate layers (, , , ).

Some convenience functions are provide to read and write a layout from or to a file. The method reads a layout from a file. It basically merges the contents of the file with the layout so it's possible to combine multiple files by using read more than once. The method comes in two flavors: a simple one and one that allows specification of reader options with a object. There is also a method which writes the layout to a file. The simple form writes the layout to a file and the file type is determined by the file extension. A full-featured version exists which allows to specify the format and many more options with a object.

Layouts can also import cells from Libraries (). Such imported cells are basically cells linked to another cell inside the library. Library cells are imported using the method. This method creates a "proxy" cell which is a copy of the library cell but is linked to the library. As long as the library is present in the system, this link is maintained and stored in the layout files. If the link is lost because the library is removed, the proxy cell becomes a normal cell. Such proxy cells basically behave like normal cells but should not be manipulated.

Layout objects are also responsible for handling properties. Properties are basically arbitrary sets of data (key/value pairs) attached to shapes, cells or instances. For efficiency, the property data is not attached to every shape, cell or instance. Instead, the layout object manages different property sets and associate each distinct set with an integer ID. The shape, cell or cell instance only stores that ID. To create, query or change property sets, the layout object provides the and methods. Since that is inconvenient, shapes, cells and instances provide access to the properties by providing methods to set, get and delete properties from the set (for example , and ). Internally, these methods create a new ID if necessary and assign that ID to the shape, cell or instance.

A layout can provide and import PCells. PCells are cells that provide it's geometry through program code (for example written in Ruby) and provide parameters which can be adjusted to change the appearance of the cell. For each PCell a "declaration" must be provided which basically contains the code for the PCell and some information about the parameters provided by the PCell. PCells are stored in the layout and are referred to by a PCell ID (an integer). PCells are added to a layout using and retrieved by ID or name using . PCells are instantiated with a specific parameter set using the . This method creates a cell representing the layout generated by the PCell code for a particular set of parameters. The layout internally caches the PCell layouts so the PCell code is executed only if a new parameter set is requested. Usually PCells are provided through libraries. In that case, the library provides the PCell variant through which is imported into the target layout through . There is a overload of which combines both steps.

The following code demonstrates how to create a PCell (in that case a "TEXT" cell from the "Basic" library):

    ly = RBA::Layout.new
    top = ly.add_cell("TOP")

    # Find the lib
    lib = RBA::Library.library_by_name("Basic")
    lib || raise("Unknown lib 'Basic'")

    # Find the pcell
    pcell_decl = lib.layout.pcell_declaration("TEXT")
    pcell_decl || raise("Unknown PCell 'TEXT'")

    # Set the parameters (text string, layer to 10/0, magnification to 2.5)
    param = { "text" => "KLAYOUT RULES", "layer" => RBA::LayerInfo::new(10, 0), "mag" => 2.5 }

    # Build a param array using the param hash as a source.
    # Fill all remaining parameter with default values.
    pv = pcell_decl.get_parameters.collect do |p|
      param[p.name] || p.default
    end

    # Create a PCell variant cell
    pcell_var = ly.add_pcell_variant(lib, pcell_decl.id, pv)

    # Instantiate that cell
    t = RBA::Trans::new(RBA::Trans::r90, 0, 0)
    pcell_inst = ly.cell(top).insert(RBA::CellInstArray::new(pcell_var, t))

### Editable mode

A layout can exist in two flavors: editable and non-editable. In editable mode, some optimisations are disabled. For example, OASIS shape arrays are expanded into single shapes. This enables manipulation of the database. For example, the shape replacement, property manipulation and other operations are only possible in editable mode. On the other hand, the memory footprint of a layout may be larger in editable mode. Independent of the mode, layouts can be created and cells, instances and shapes can be added, but not manipulated.

A layout object living in the application is created in editable or non-editable mode depending on the application setting. Layout objects explicitly created by RBA code can either be in editable or non-editable mode:

    editable_layout = RBA::Layout.new
    non_editable_layout = RBA::Layout.new(false)

The method returns true, if a layout is in editable mode. Once the layout is created, the editable mode cannot be changed.

### Meta information

A layout object can keep arbitrary meta data in the form of key/value pairs. This meta data is extracted during the reading of a layout and will reflect special properties of the layout file. For example, the GDS2 library name is available as meta information with key "libname".

The layout object offers methods to retrieve that information: will iterate over the meta data (returning a object). will get the value for a given name. will add a new meta information object and will delete one.

Meta information is a different concept than properties.

### Cell related methods

Cells can be created using the method. This method expects a cell name. If a cell with that name already exists, a new name is generated by appending a suffix. The method returns the Cell object of the new cell. or can be used to change the name of a cell. The Cell object for a given name can be obtained with which returns the Cell object or nil if no cell with that name exists.

The cell name can be obtained from the cell index with the method or ). can be used to determine whether a cell with the given name exists. can be used to determine whether a given index is a valid cell index. returns the number of cells in the layout. To work with cells, the Cell object is required. It can be obtained from the cell index using the method.

The top cell of a layout can be obtained using . If multiple top cells exist, this method will raise an exception. In that case, can be used to obtain all top cells.

All cells in the layout can be iterated using the iterator. All top cells (cells which are not instantiated itself) can be iterated with the iterator. The cells can be iterated bottom-up (all child cells come before their parents) or top-down (all parents come before their children) using the or .

deletes a cell. This method will keep the child cells, which may become top cells because their parent cell is deleted. deletes multiple cells and is more efficient than deleting cell by cell. will delete a cell and all child cells (direct and indirect), irregardless whether they are used otherwise or not. does the same but is somewhat more sensitive in that respect and does not delete child cells if they are instantiated by parents not in the cell tree below the cell being deleted. as prune_cell deletes the child cells or a cell but in contrast to prune_cell does not delete the cell itself.

### Layer related methods

creates a new layer in the layout. The layer will be available to all cells. This method receives a object which holds the information about the layer's name, layer and datatype. It returns a layer index which can be used to address shapes in the cells. can be used to create a layer with a specific layer index, provided that index is not used yet.

can be used to determine whether a layer index is a valid index. returns a list of indexes of all layers present. returns the number of layers present.

Returns the layer index for a given layer in various flavors. finds or creates a layer if it does not exist yet. Again, the layer can be given in various flavors - for example by layer and datatype, by name or with a object.

can be used to change the LayerInfo object for a layer. returns the LayerInfo object for a layer. To modify the information, obtain the information with get_info, modify it, and set the new information with set_info:

    lv = RBA::Application::instance.main_window.current_view
    ly = lv.current_cellview.layout
    info = ly.get_info(0)
    info.layer = 100
    ly.set_info(0, info)
    lv.add_missing_layers
    lv.remove_unused_layers

The previous sample changes the layer number for layer index 0 to 100. "add_missing_layers" and "remove_unused_layers" will create new layer entries in the layer list and remove the entry for the previous layer.

For special purposes, special (temporary) layers can be created in the layout. Those layers basically behave like normal layers but don't appear in the layer list and are not saved to a file. Special layers can be created using and . returns true if a given index is a special layer.

In addition, a layout contains a special layer which is used to implement the "guiding shape" feature of PCell's. It is a special layer that serves as a container for shapes which parametrize PCells. The index of that layer can be obtained with .

A list of the indexes for all layers inside the layout can be obtained with . A corresponding list of LayerInfo objects can be obtained with .

### Recursive full or region queries

A layout provides methods to retrieve shapes recursively. That means, that the shapes are delivered from all cells instantiated below a given top cell. Cells instantiated multiple times are also visited multiple times. While the shapes are delivered, information is provided what cell instances the specific shape instance is found in.

Recursive shape retrieval is done through a iterator, the . This object delivers one shape each time. A RecursiveShapeIterator is created for example using the method. This method requires the cell index of the starting (initial) cell and a layer index. This code demonstrates how to use the RecursiveShapeIterator:

    layout = RBA::Application::instance.main_window.current_view.active_cellview.layout
    # start iterating shapes from cell "TOP", layer index 0
    si = layout.begin_shapes(layout.cell_by_name("TOP"), 0)
    while !si.at_end?
      puts si.shape.to_s + " with transformation " + si.trans.to_s
      si.next
    end

The RecursiveShapeIterator's shape method delivers a shape reference (see description of the Shape class or ) which basically points to a shape inside a cell. Since the cell may be a child cell of the initial cell the RecursiveShapeIterator was created with, in general a transformation is present that tells how the cell's content shows up in the initial cell. The generic form of that transformation is a object which is delivered by the RecursiveShapeIterator's "trans" method. This transformation renders floating-point coordinates which is precise but not a suitable representation for transforming shapes into a form compatible with the database. For that purpose, a object is provided as well through the "itrans" method. This transformation renders integer coordinates which may imply rounding effects in some cases. The RecursiveShapeIterator delivers the cell from which the current shape is taken through the "cell_index" method.

A RecursiveShapeIterator can be configured to retrieve only certain type of shapes (i.e. boxes, texts etc.). To do so, set the shape_flags attribute of the shape iterator before using it:

    layout = RBA::Application::instance.main_window.current_view.active_cellview.layout
    # start iterating shapes from cell "TOP", layer index 0
    si = layout.begin_shapes(layout.cell_by_name("TOP"), 0)
    si.shape_flags = RBA::Shapes::SBoxes
    while !si.at_end?
      puts si.shape.to_s + " with transformation " + si.trans.to_s
      si.next
    end

Also the maximum depth at which the RecursiveShapeIterator will traverse the hierarchy can be set using the "max_depth" attribute. Setting this attribute to 0 will report only shapes from the initial cell. The depth must be set before the first shape is retrieved.

The RecursiveShapeIterator can also deliver shapes from a region. The region is a rectangle specified in coordinates of the initial cell. To create a RecursiveShapeIterator that only delivers shapes inside that region use the or methods of the Layout object. These methods expect a Box object that specifies that rectangle. All shapes delivered will either touch or overlap that box when projected into the initial cell.

Shape manipulations should be avoided inside loops that iterate over shapes using a RecursiveShapeIterator. The reason is that shape manipulations may invalidate the internal state of the RecursiveShapeIterator. Instead, collect all shape references that need to be manipulated in an array and do the manipulations later.

### Properties

As stated earlier, shapes can carry an arbitrary number of user properties in form of key/value pairs. For efficiency, these properties are not stored directly but in form of a property ID which identifies a unique set of properties. Retrieving a property hence requires an indirection over the property ID:

    layout = RBA::Application::instance.main_window.current_view.active_cellview.layout
    # first shape of cell "TOP", layer index 0
    layer_index = 0
    iter = layout.begin_shapes(layout.cell("TOP").cell_index, layer_index)
    shape = iter.shape
    # create a hash from the properties of that shape
    props = Hash[*layout.properties(shape.prop_id).flatten]
    # print the value of the property with key 1
    puts props[1]

Since that scheme is somewhat tedious to use, a nice shortcut exists by using the "properties" method on the shape reference. This method implicitly modifies the property set and assigns a new property ID:

    layout = RBA::Application::instance.main_window.current_view.active_cellview.layout
    # first shape of cell "TOP", layer index 0
    layer_index = 0
    iter = layout.begin_shapes(layout.cell("TOP").cell_index, layer_index)
    shape = iter.shape
    # print the value of the property with key 1
    puts shape.properties(1)

Changing a property requires to obtain a new property ID for the changed set:

    layout = RBA::Application::instance.main_window.current_view.active_cellview.layout
    # first shape of cell "TOP", layer index 0
    layer_index = 0
    iter = layout.begin_shapes(layout.cell("TOP").cell_index, layer_index)
    shape = iter.shape
    cell = layout.cell(iter.cell_index)
    # create a hash from the properties of that shape
    props = Hash[*layout.properties(shape.prop_id).flatten]
    # change or add a property with key 1
    props[1] = "NewValue"
    # store the new properties
    shape.prop_id = layout.properties_id(props.to_a)

For that problem also a shortcut exists. Use the "set_properties" method on the shape reference. This method implicitly modifies the property set and assigns a new property ID:

    layout = RBA::Application::instance.main_window.current_view.active_cellview.layout
    # first shape of cell "TOP", layer index 0
    layer_index = 0
    iter = layout.begin_shapes(layout.cell("TOP").cell_index, layer_index)
    shape = iter.shape
    # change or add a property with key 1 and value "NewValue"
    shape.set_property(1, "NewValue")

A property ID of 0 in general indicates that no properties are attached. Please note that replacing a property ID and modifying the properties also invalidates any iterators and should not be done in a loop over shapes.

Cell instances and cells also carry a properties ID which can be used to assign user properties to cell instances. The cell instance properties ID is used like the shape properties ID. The shortcut methods "property", "set_property" and "delete_property" also are provided for cells and cell instances ( and ).

## The LayerInfo class

The object encapsulates the layer's naming properties. In GDS, a layer is described by a layer number and datatype number. In OASIS, a text name can be added to that description. In other formats like DXF, a layer has just a text name.

The LayerInfo object thus has a twofold identity: a numeric identity (layer and datatype number) and a text layer name. Both properties can be specified. In that case, the numeric identity has precendence over the text name.

When a layout is loaded, LayerInfo objects are used to represent a layer's naming properties in the Layout object. The LayerInfo object associated with a layer can be retrieved using the Layout's "get_info" method. It can be set using the "set_info" method. In general, the LayerInfo property is detached from the layer index, so it can be assigned and manipulated freely.

The default constructor of LayerInfo will create a nameless object. Nameless layers are not saved to any file and can be used for internal purposes such as temporary or intermediate layers.

The attribute allows read and write access to the layer number. is the attribute for the datatype number. gives access to the text name. returns true, if the LayerInfo object represents a named layer (no layer or datatype number are specified). compares two LayerInfo objects and returns true, if both denote the same layer. This is not exact equivalence but follows the logical precendence: two layers are equivalent if layer or datatype number match (in that case the text name is ignored) or, if no layer and datatype number are specified, the name matches exactly.

LayerInfo objects supply a hash value () and can therefore be used as keys in Ruby hashes.

## The Cell class

After the Layout object, the object is the most fundamental object in KLayout's database API. It represents a cell, which itself is a collection of shapes per layer and instances of other cells. The methods provided by the Cell class deal with either the shape or the instance aspect. A cell is also responsible for handling parts of the PCell scheme, either for the cell itself (if it is an incarnation of a PCell) or instances of PCell's.

A cell has a name which can be retrieved using the method and which can be set using the method. Setting the name is equivalent to using the Layout's "rename_cell" method. delivers the PCell or library cell name for cells imported from a library or PCell variants. "name" will deliver an internal unique name in that case. is a string that encodes library name and PCell parameters as well and can be used as a descriptive title for the cell in user interfaces.

If the cell is a library cell (a "proxy"), it will have a database name (something like "TEXT$1") and a qualified name which states the library and the cell name separated with a dot (i.e. "Basic.TEXT"). The qualified name is not neccessarily unique. The qualified name of the cell can be obtained with .

A cell that represents a cell imported from a library or a PCell variant (or both) is called a proxy cell. For such cells, returns true. Such cells should not be manipulated since they may be refreshed when required and the original state is restored. and deliver a more detailed information about the nature of the proxy cell.

The layout that the cell lives in can be retrieved with the method. If the cell is created standalone (without layout), this method returns nil. In that case, a cell is not named either.

A cell can be a "ghost cell". A ghost cell is an empty cell which is not written to a layout write and created when a layout file is read with an unsatisfied reference. Unsatisfied references are present in some GDS files which represent partial layouts. By simple merging of two GDS files, such references can be made true instances, when another file contributes the cell for that reference. KLayout supports such unsatisfied references by providing the "ghost cells" which serve as a instance target but are not written. Ghost cells are simply cells where the attribute is true. An empty cell can be made a ghost cell by setting the property.

A cell has a bounding box which includes child cells as well. KLayout keeps a per-layer bounding box, so it's very simple to tell whether a cell is empty in a certain layer (including the hierarchy below). In that case the per-layer bounding box is an empty box. The overall bounding box can be derived with the method. The per-layer bounding box can be derived with the method.

Cells can be marked as "ghost cells" using the . Ghost cells are not saved into GDS files (but their references are). Also, ghost cells act as "placeholders" for cells - for example if a cell is pasted into a layout, it will replace any ghost cell with the same name. If a normal cell with the same name exists, a copy will be created instead. A cell can be asked whether it is a ghost cell using .

Starting with version 0.23, cells can have properties as well, but writing cell properties to layout files is subject to some restrictions. Properties are only written to GDS if a special option is enabled because a potentially incompatible extension of GDS is used to store the properties. OASIS files support cell properties without restrictions.

### Cells and shapes

A cell carries a set of geometrical shapes, organised in layers. A layer is specified by a layer index. The layer index is managed by the Layout object. It is basically an integer that identifies the layer in the layout. The shapes are stored in containers of the class. Given a layer index, the shapes object can be obtained from the cell through the method:

    shapes = cell.shapes(layer_index)
    shapes.each do |shape|
      puts shape.to_s
    end

The same can be achieved by directly iterating over the shapes in the cell:

    cell.each_shape(layer_index) do |shape|
      puts shape.to_s
    end

That iterator also allows specification of a filter so it delivers only a certain subset, i.e. only text objects. See and for more details.

There are iterators that deliver shapes within a rectangular region, either overlapping or touching that region (, ). They basically work like the "each_shape" iterator. Please note that these iterators are not recursive, i.e. they don't deliver shapes from child cells. Recursive iteration can be performed using Layout's "begin_shapes" method and the RecursiveShapeIterator object.

All shapes in a cell can be cleared using . A single layer can be cleared using the method with the layer index to clear. Both methods are not recursive, i.e. they only clear the shapes on the given cell, not on the child cells.

Layers can be copied using the method. The shapes of a layer can be moved to another layer using the method. In both cases, the target layer is not overwritten, but the shapes from the source layer are added to the target layer. will swap the shapes of two layers. In all these cases, the operation is local on the cell, i.e. child cells are not affected.

Shapes within a cell are represented as objects. A shape object is a generic object which represents either a polygon, a box, a path, a text or an edge object. Shapes provide some generic methods such as to retrieve the bounding box or . Shapes act as "pointers" to geometrical objects inside the database. Manipulating a shape will also manipulate the database object.

To work with specific kind of shapes, the working classes such as are provided. Shapes can be converted into these working objects. The working objects are not related to the layout object and not having a connection to the layout makes them lightweight objects. A usual way of manipulating a shape is to translate it to a working object, modify that and assign the working object back to the shape.

Interfaces to floating-point working classes such as are provided too. By convention such objects represent shapes in micrometer units. If such an object is requested from the shapes container it is converted from an integer-type object in database units to a floating-point type object in micrometer units by multiplying with the database unit. When sending such an object to the Shapes container the same happens in reverse. Internally, the integer type is used.

### Cells and hierarchy

The direct children of a cell can be iterated with . That iterator delivers the cell index of each child cell of the cell. Similar, there is a iterator. It delivers the cell indexes of all cells calling that cells. For a top cell that iterator delivers nothing. returns true, if the cell does not have child cells. returns true, if the cell is top cell.

Cells and their children form a directed acyclic cell graph. That means, no cell may instantiate a cell which itself calls the cell whether directly or indirectly. There is a set of cells called by a given cell, either directly or indirectly through children of the cell. That set is the "called" cell set. That cell set can be obtained with the method in form of an array of cell indexes.

Similar, there is a set of cells calling a cell, either directly or indirectly. That set of cells can be obtained with the method. For a top cell that set is empty.

The number of hierarchy levels can be obtained with . This method delivers the length of the longest path to a leaf cell. A leaf cell has a hierarchy level count of 0.

A cell can be flattened using . Child cells can be removed using . The cell can be removed with or . The latter will also remove any child cells which are not used otherwise.

### Copying information between cells

Instances can be copied from one cell to another using . Shapes can be copied using . The latter method supports layer conversions by employing a object to specify input and output layers. In addition, shapes can be copied to another layout which automatically performs database unit conversion if necessary.

A full cell tree can be copied using . This method will create a new hierarchy below the target cell matching the source cell's hierarchy and copy all shapes from source to target using that new hierarchy. Source and target cell may reside in different layouts and database unit conversion is done automatically.

The content of a cell can be copied to another cell hierarchically using , provided a cell mapping exists. A cell mapping specifies, how child cells of the source cell are identified in the target, which can be a different layout. For the cell mapping a object is employed. In addition, a object can be used to specify layer mapping to the target. If no cell mapping is provided, shapes are flattened into the next possible parent, which provides a way to creating flat copies of cells. "copy_tree" is a convenience method and is a special case of "copy_tree_shapes".

For all methods, "move" flavors are available (, , and ), which not only copy the information but also remove the respective objects in the source cell. That somewhat reduces the memory required for such operations.

### Cells and instances

A cell also plays a role as container for the instances. An instance describes a cell that is placed into another cell. Technically an instance is a combination of a cell reference and a transformation. Raw instances are represented by objects. Instances inside a cell are referred to by objects. An Instance object is basically a pointer into a CellInstArray stored inside a cell and associates properties with raw instances for example.

Instances can be created by using the various methods of Cell. Instances can have properties, so a property ID can be provided (see Layout class for a discussion about property ID's). Instances can be deleted using the method. All instances of a cell can be deleted using the method.

An instance can be replaced by another CellInstArray object using the method. The properties ID can be changed using the method. It is easier however to use the Instance object's "cell_inst=" or "prop_id=" method.

Instances can be iterated with . and delivers all instances overlapping or touching a given rectangular region. That means, the instance's overall bounding box overlaps or touches the search rectangle.

delivers all parent instances. Parent instances are basically reverse instances represented by the object. A parent instance identifies are parent cell and the instance of the given cell in that parent cell. This iterator allows deriving all instances of the given cell in other cells.

Instances can be transformed with a given transformation (either a orthogonal or a general complex transformation) using the method. This method invalidates the Instance pointer given as the argument and returns a new Instance pointer to the new cell instance.

A floating-point integer class exists too (). By convention this object represent an instance in micrometer units. If such an object is requested from the cell it is converted from an integer-type object in database units to a floating-point type object in micrometer units by multiplying with the database unit. When sending such an object to the cell the same happens in reverse. Internally, the integer type is used.

### Cells, libraries and PCells

If a cell is a cell imported from a library, will return true and it is possible to derive the Library object from which this cell is imported using the method. will return the cell index of the cell in the library's local layout.

If a cell is a PCell variant, either directly from the layout or from a library, returns true. This method can also be called on an Instance object in which case it delivers true if the instance is an instance of a PCell. returns the PCell declaration ID if the cell is a PCell variant. will return the PCell declaration object. There is also a overload of "pcell_declaration" that determines the PCell declaration object for an Instance if it is a PCell instance. delivers the PCell parameters for a cell (if it is a PCell variant) or an instance (if it is a PCell instance). The PCell parameters are an array of object and the interpretation is dependent on the PCell implementation. The object which can be obtained through "pcell_declaration" gives the necessary information about the interpretation of the parameters.

Finally, allows refreshing the layout of a proxy cell, i.e. transfer the current state of a library cell into this cell or recompute the PCell layout. Usually this method needs not to be called. When PCell parameters change for example, the layout is automatically recomputed.

### Cells and PCell instances

A cell can be a PCell variant as we've seen above. In addition, a cell can hold PCell instances. The parameters of PCell instances can be modified from the cell using for individual parameters given by name or for all parameters. For changing all parameters it is required to know the parameter's order and meaning. The order can be obtained from the PCell declaration class which itself can be retrieved from a PCell instance with (with the instance as the first argument).

The PCell parameters of a PCell instance can be obtained with (with the instance as the first argument). To get a specific parameter, use the PCell declaration object which lists the parameters on the order they are delivered by the "pcell_parameters" method.

## The CellInstArray class

Despite it's name, a object holds a cell reference which is not only an array, but also a single instances. The object represents a raw instance, in contrast to the Instance object which is basically a pointer to an instance inside the database. CellInstArray objects as raw instances can be created, copied, modified and stored in the usual containers, but once they are stored inside the Cell object, they can be addressed by the Instance object.

The CellInstArray object represents either single instances or array instances. Array instances correspond to GDS AREF records and are regular, two-dimensional (not necessarily orthogonal) arrays of instances. A single instance consist of a cell index, denoting the cell that is instantiated and a single transformation, which can be either a simple, orthogonal affine transformation without a magnification (a Trans object, see ) or a general affine transformation (a CplxTrans object, see ). A cell instance array in addition specifies two dimensions (na, nb) and shift vectors (a, b). For each individual instance of the array, an additional displacement is added to the transformation which is computed by the following formula:

    d=i*a+j*b   (i=0..na-1, j=0..nb-1)

A CellInstArray object that represents an array will return true on . In that case, the and attributes are the basic vectors of the array and and are the dimensions of the array. is the number of instances in the array.

A CellInstArray with a simple transformation will return false on and the attributes gives the basic transformation of the instance. If the transformation is complex, i.e. has a rotation angle which is not a multiple of 90 degree or a magnification, will return true and should be used instead of . In any case, gives the correct transformation.

The attribute gets or sets the cell index. The and methods deliver the total bounding box of the instance including all instances for an array. gives the bounding box for a single layer. Since the instance only knows the cell index, these methods require a Layout object in order to derive the actual cell's bounding box.

A CellInstArray object can be inverted using the method. This method returns an array which represents the ways the parent cell is seen from the child cell. A CellInstArray object can also be transformed by a given transformation. The method will (like ) transform the object in-place, i.e. modify the object. will do the same, but leave the object it is called on and return a modified copy (out-of-place). Various variants of the and methods exist taking different forms of transformations (simple, complex).

The floating-point variant () behaves the same way, except that by convention the unit of coordinates is micrometers.

## The Instance class

As stated earlier, the object represents a cell instance in the database and basically acts as a reference or pointer to a CellInstArray object inside the database. In addition, it provides access to properties attached to the instance. Instance objects play an important role in the Cell class to identify a certain instance, for example to delete an instance.

The Instance class provides a couple of methods that give read access to the underlying CellInstArray object (, , , , , , , , , or ). The whole CellInstArray object can be read with the method. It is possible to copy (dup) and modify that object and replace the current CellInstArray with the new one using . Please note, that this operation may invalidate iterators and should not be done inside a loop using "Cell::each_inst" for example.

The cell the Instance object lives in can be obtained with . basically renders the same information, but in form of a cell index. The layout the instance lives in can be obtained with .

User properties can be accessed through the attribute or, more convenient, through the , or methods. Please note that changing the property ID or the property values may invalidate iterators as well.

An instance has an equality operator. That operator returns true, if the Instance objects point to the same cell instance.

## The Shapes class

The object is the basic container for geometrical shapes. It stores geometrical primitives (Boxes, Polygons, Paths, Texts and Edges) either directly or in compressed form to achieve a low memory usage. For example, OASIS shape arrays are stored as compact arrays when KLayout is used in viewer mode. The Shapes container provides a simplified view through the Shape object which is basically a pointer to an individual instance of a geometrical primitive. The Shapes container provides access to the primitives through Shape objects.

In editable mode (i.e. if a Shapes container lives in an editable Layout object), the shapes can be modified or deleted after they have been inserted. In the opposite mode (viewer mode), shapes can be added, but not modified nor deleted.

A Shapes container is usually obtained from a cell with a given layer index and is filled with geometrical primitives using one of the methods. Please note that the shapes are specified in integer coordinates when you use the integer type objects and micrometer units when using the floating-point type objects (whose classes start with "D"):

    # cell = a Cell object
    # layer_index = the index of a the layer
    shapes = cell.shapes(layer_index)
    shapes.insert(RBA::Box::new(0, 0, 1000, 2000))

With floating-point objects:

    # cell = a Cell object
    # layer_index = the index of a the layer
    shapes = cell.shapes(layer_index)
    shapes.insert(RBA::DBox::new(0.0, 0.0, 1.0, 2.0))

A Shapes object can also be created without a cell:

    shapes = RBA::Shapes::new
    shapes.insert(RBA::Box::new(0, 0, 1000, 2000))

Standalone Shapes objects can be useful when the methods of the Shapes object are required (for example, region queries through "each_overlapping"). There are are variety of "insert" methods available, some of which copy shapes from other Shapes containers using a Shape object as the reference for the source object. Some of these variants allow to specify a transformation which is applied before the shape is inserted. There are also variants for all geometrical primitives with or without a properties ID.

If a Shapes container is empty, will return true. The content of another Shapes container can be assigned to a Shapes object with the method. The number of geometrical primitives inside the Shapes container can be obtained with the method. All shapes in the Shapes container can be deleted with the method.

The content of the Shapes container can be iterated with the iterator. If will deliver Shape objects pointing to the current geometrical primitive. The and methods deliver only those primitives whose bounding box overlaps or touches the given rectangle. All iterators allow to specify flags which confine the kind of shape delivered. The flags are a combination of the "S..." constants. For example:

    # delivers all primitives:
    shapes.each(RBA::Shapes::SAll) { |s| ... }
    # delivers all primitives which have user properties attached:
    shapes.each(RBA::Shapes::SAllWithProperties) { |s| ... }
    # delivers only texts:
    shapes.each(RBA::Shapes::STexts) { |s| ... }
    # delivers only polygons and boxes:
    shapes.each(RBA::Shapes::SBoxes | RBA::Shapes::SPolygons) { |s| ... }

A geometrical primitive inside the container can be erased using the method. It is safe to erase shapes inside an iterator loop for editable containers.

Shapes can be replaced by other primitives using one of the replace methods. Please note that using "replace" inside an iterator loop may lead to unexpected behavior of the iterator, so modifying a shape inside an iterator loop should be avoided. Here is an example:

    # DON'T:
    # (replace polygons by their bounding boxes)
    shapes.each do |shape|
      if shape.is_polygon?
        shapes.replace(shape, shape.bbox)
      end
    end

    # DO
    # (replace polygons by their bounding boxes)
    shapes_to_modify = []
    shapes.each do |shape|
      if shape.is_polygon?
        shapes_to_modify.push(shape)
      end
    end
    shapes_to_modify.each do |shape|
      shapes.replace(shape, shape.bbox)
    end

The latter solution requires some more memory but is in general safer. It is safe however to replace an object by the same kind of object inside a loop.

Shapes can be transformed by using one of the methods provided by the Shapes object. Variants for simple and complex transformations exist. Please note that using a arbitrary-angle transformation on a box (i.e. a CplxTrans object with a rotation angle of 45 degree) will not render a rotated box since a box is by definition parallel to the axes. Instead this operation will render the bounding box of the rotated box. Transforming shapes is safe inside an iterator loop.

The Shapes container also manages user properties by employing properties ID's. Properties can be modified by obtaining a new ID from the layout object and replacing the property ID using the method. However it's much more convenient to use the , or methods of the Shape object. In both cases however, modifying the properties should be avoided inside an iterator loop.

All shapes inside a shape container can be transformed using .

With version 0.23, new collection objects entered the stage: , and which basically provide a way to store polygons, edges or egde pair objects independently from the shapes container. They are mainly used to implement bulk operations, specifically for the DRC functionality. The cooperate with the shapes container in the sense that they can be inserted into a shapes container which will produce polygons or edges in the layout database (edge pairs are converted to single egdes or polygons. These classes are discussed in .

## The Shape class

The object provides a unified view to a geometrical primitive inside a Shapes container. It also plays an important role for addressing geometrical primitives inside a Shapes container. A Shape object has general methods and specific methods that apply depending on it's identity.

### General methods

The method delivers the bounding box of the geometrical primitive addressed by the Shape object. Please note that the bounding box of a text only contains the single point of the text's origin, not the text drawing itself.

delivers the Cell object that shape lives in. The same way, delivers the Layout object and the Shapes object.

, and allow to modify the user properties of the geometrical primitive. The same can be achieved somewhat less conveniently using a properties ID with the attributes' write accessor (). Please note the comments in the description of the Shapes object regarding the interaction of these modifying operations with iterators. returns true, if the shape has user properties attached.

returns the type code of the shape addressed by the Shape object. This is a detailed code which distinguishes between different internal representations. It's more convenient to use one of the is_...? methods. For example returns true, if the geometrical primitive is a box. A note about and : usually it is not required to distinguish between both. "is_polygon?" will also return true for simple polygons, so it is likely to be sufficient to just ask for "is_polygon?". returns true, if the primitive is a custom object. Such objects are rarely used and not supported by the Ruby API currently.

delivers the area of the shape. The area is zero for a text object. delivers the perimeter of the shape. The perimeter is zero for a text object. The Shape object provides an equality operator which delivers true if two Shape objects point to the same primitive.

It is possible to replace a primitive by another one by using the shape assignment methods, i.e. , , , , and . Using these methods is equivalent to the using "replace" on the containing Shapes objects. Please see the notes on using "replace" inside iterators there.

Floating-point objects are supported too. For example, is equivalent to , but delivers the object in micrometer units. receives a micrometer-unit object. is equivalent to , but gets the first point of the box in micrometer units.

The layer index a shape is on can be obtained with . A shape can be moved to a different layer by assigning a different layer index with . In that context, layers can also be addressed by layer/datatype or name using a object. The respective methods to address a shape's layer then are and .

A shape can be transformed using one of the flavors.

### Methods applying for box shapes

A Shape object represents a box if it returns true on . The only specific methods that are provided for box type shapes are the getter and setter. , , , , and get or modify individual aspects of the box.

For the floating-point equivalents in micrometer units see the .

### Methods applying for polygon and simple polygon shapes

A Shape object represents a polygon or simple polygon if it returns true on . If the object is a simple polygon, it will also return true on . A simple polygon is just a polygon that cannot have holes.

In every case, the iterator will deliver all edges (connections between points of the polygon). will deliver every point of the polygon, including that of the holes. will only deliver the points of the outer (hull) contour and will deliver the points of a specific hole contour. will deliver the number of holes. A simple polygon does not have holes.

The getter delivers a object. The same way delivers a object. A polygon with holes is converted in that case to a simple polygon by introducing cut lines to connect the holes with the outer contour.

The and setters will replace the current object by the given new one.

For the floating-point equivalents in micrometer units see the .

### Methods applying for path shapes

A Shape object represents a path if it returns true on . The path's width can be obtained through the method. The extensions of the path ends can be obtained with and for the start and end extensions. The object can be obtained with the getter. For the path width and extensions setters are also provided (, and ).

The path length can be obtained with and includes the begin and end extensions. The round-ended path flag can be obtained with flag and set with .

The points of the path's spine can be iterated with . can be used to obtain the path's contour.

For the floating-point equivalents in micrometer units see the .

### Methods applying for text shapes

A Shape object represents a text object if it returns true on . The text's text string can be obtained with . The text's origin and orientation is encoded in a transformation (a Trans object, see ) which can be obtained with the method. The font code, text size and alignment flags can be obtained with the , , and methods. See the description of the object for details about these attributes.

The text representation attributes can be set with , , and . will modify the text's transformation.

will deliver the Text geometrical primitive and allows replacing the shape with the given Text object.

For the floating-point equivalents in micrometer units see the .

### Methods applying for edge shapes

A Shape object represents an edge if it returns true on . Edge objects in general are not well supported in KLayout currently. They can be created and manipulated by scripts, but cannot be drawn or modified on the user interface. In GDS files, edges are represented by zero-width paths which is sometimes breaking the conventions of other tools.

The only specific methods that are provided for edge type shapes are the getter and setter.

For the floating-point equivalents in micrometer units see the .