Regions
For original class documentation see Region class reference.
Regions are basically collections of polygons. A simple application is to create a region object and insert polygons. Region objects support many geometrical operations such as sizing (enlargement, biasing), boolean operations (AND, NOT, XOR), merging (removing overlaps).
However, Region objects are much more powerful. They can be fed from a hierarchical layer. This enables operations on layouts. Regions support a hierarchical mode (“deep mode”) that allows preserving the hierarchy of the original layout as far as possible.
With this ability, Region objects are also the basis of KLayout’s DRC (design rule check) feature. All features available in DRC decks are mapped to Region methods.
I will discuss only the basic features here. The original documentation is the entry point for further explanations.
Region Creation
Region objects can be filled with integer-unit polygons. When inserting other graphic objects they are converted to polygons (note that we are using the default database unit of 1 nm here):
import klayout.db as db
r = db.Region()
r.insert(db.Box(0, 3000, 1000, 4000))
points = [
db.Point(0, 1000), db.Point(3000, 1000), db.Point(3000, 4000)
]
r.insert(db.Path(points, 2000))
Gives:
Note that there are not micrometer-unit regions currently. A trick to convert micrometer-units into integer-unit objects is a apply a complex transformation:
import klayout.db as db
dbu = 0.001
t = db.CplxTrans(dbu).inverted()
r = db.Region()
r.insert(t * db.DBox(0.0, 3.0, 1.0, 4.0))
points = [
db.DPoint(0.0, 1.0), db.DPoint(3.0, 1.0), db.DPoint(3.0, 4.0)
]
r.insert(t * db.DPath(points, 2.0))
Gives:
Region Operations
“Sizing” (also called “biasing”) is an operation that shifts the polygon edges by a certain distance. Positive values will shift outside, negative values inside. Before the edges are shifted, the polygons are merged:
import klayout.db as db
region = db.Region()
region.insert(db.Box(0, 0, 3000, 4000))
region.insert(db.Box(2000, 0, 6000, 2000))
sized_region = region.sized(1000)
Gives (the original polygons are white):
Sizing can be anisotropic - in this case, the horizontal shift can be different from the vertical shift:
import klayout.db as db
region = db.Region()
region.insert(db.Box(0, 0, 3000, 4000))
region.insert(db.Box(2000, 0, 6000, 2000))
# "2" is the default cutoff mode. It is mandatory for
# anisotropic sizing.
sized_region = region.sized(0, 2000, 2)
Gives (the original polygons are white):
The boolean “NOT” operation subtracts the second
region from the first. This operation is implemented
by the -
operator:
import klayout.db as db
r1 = db.Region()
r1.insert(db.Box(0, 0, 3000, 4000))
r2 = db.Region()
r2.insert(db.Box(1000, 1000, 6000, 2000))
result = r1 - r2
Gives (the result is white):
The boolean “AND” computes the intersection of two regions.
This operation is implemented by the &
operator:
import klayout.db as db
r1 = db.Region()
r1.insert(db.Box(0, 0, 3000, 4000))
r2 = db.Region()
r2.insert(db.Box(1000, 1000, 6000, 2000))
result = r1 & r2
Gives (the result is white):
The boolean “XOR” computes the intersection of two regions.
This operation is implemented by the ^
operator:
import klayout.db as db
r1 = db.Region()
r1.insert(db.Box(0, 0, 3000, 4000))
r2 = db.Region()
r2.insert(db.Box(1000, 1000, 6000, 2000))
result = r1 ^ r2
Gives (the result is white):
The +
operator joins two collections. merge
(in place) or merged
merges the polygons of
a region, i.e. it computes the envelopes or boolean “OR” of the polygons:
import klayout.db as db
r1 = db.Region()
r1.insert(db.Box(0, 0, 3000, 4000))
r2 = db.Region()
r2.insert(db.Box(1000, 1000, 6000, 2000))
result = (r1 + r2).merged()
Gives (the result is white):
Regions from Layout Layers
You can pull polygons from a layout layer hierarchically and perform operations on it
(Download my_layout.gds
):
import klayout.db as db
ly_file = db.Layout()
ly_file.read("my_layout.gds")
l1 = ly_file.layer(1, 0)
r1 = db.Region(ly_file.top_cell().begin_shapes_rec(l1))
l2 = ly_file.layer(2, 0)
r2 = db.Region(ly_file.top_cell().begin_shapes_rec(l2))
# Note: the database unit is 1 nm, so 300 corresponds to 0.3 µm
result = r1.sized(300) + r2.sized(-300)
Gives (the result are the white features):