Geometry#

gdsfactory provides you with some geometric functions

Boolean#

There are several common boolean-type operations available in the geometry library. These include typical boolean operations (and/or/not/xor), offsetting (expanding/shrinking polygons), outlining, and inverting.

The gf.boolean() function can perform AND/OR/NOT/XOR operations, and will return a new geometry with the result of that operation.

import gdsfactory as gf

E = gf.components.ellipse(radii=(10, 5), layer=(1, 0))
R = gf.components.rectangle(size=(15, 5), layer=(2, 0))
C = gf.boolean(A=E, B=R, operation="not", layer1=(1, 0), layer2=(2, 0), layer=(3, 0))
# Other operations include 'and', 'or', 'xor', or equivalently 'A-B', 'B-A', 'A+B'

# Plot the originals and the result
D = gf.Component()
D.add_ref(E)
D.add_ref(R)
D.add_ref(C).dmovex(30)
D.plot()
../_images/2cc8933826930b33fda80c931d3afed0bca5cd1cd977cc0c09b282b69a041e3b.png

To learn how booleans work you can try all the different operations not, and, or, xor

import gdsfactory as gf

operation = "not"
operation = "and"
operation = "or"
operation = "xor"

r1 = (8, 8)
r2 = (11, 4)
r1 = (80, 80)
r2 = (110, 40)

angle_resolution = 0.1

c1 = gf.components.ellipse(radii=r1, layer=(1, 0), angle_resolution=angle_resolution)
c2 = gf.components.ellipse(radii=r2, layer=(1, 0), angle_resolution=angle_resolution)
c4 = gf.boolean(c1, c2, operation=operation)
c4.plot()
../_images/1c3cf3973efe929c27d1efc977f9b9a3c5cb25709cdeaca6a212e116681b05ad.png

Offset#

import gdsfactory as gf
from gdsfactory.generic_tech import LAYER

c = gf.components.coupler_ring()
c
../_images/1f12e3627338e6b4ee769501b969a2051251183b992a564eeb685de8127f4175.png
polygons = c.get_polygons()[LAYER.WG]
polygons
[(-12000,-250;-12000,250;8000,250;8000,-250),
 (-4278,450;-4418,451;-4559,453;-4699,456;-4841,460;-4982,466;-5124,474;-5267,484;-5410,497;-5553,512;-5696,531;-5839,553;-5982,579;-6124,609;-6267,643;-6408,682;-6549,725;-6688,774;-6826,828;-6977,894;-7125,967;-7270,1047;-7411,1132;-7548,1224;-7681,1321;-7809,1425;-7933,1533;-8053,1647;-8167,1767;-8275,1891;-8379,2019;-8476,2152;-8568,2289;-8653,2430;-8733,2575;-8806,2723;-8872,2874;-8926,3012;-8975,3151;-9018,3292;-9057,3433;-9091,3576;-9121,3718;-9147,3861;-9169,4004;-9188,4147;-9203,4290;-9216,4433;-9226,4576;-9234,4718;-9240,4859;-9244,5001;-9247,5141;-9249,5282;-9250,5422;-9250,5700;-8750,5700;-8750,5424;-8749,5286;-8747,5149;-8744,5013;-8740,4877;-8735,4742;-8727,4607;-8718,4473;-8706,4340;-8691,4207;-8674,4075;-8654,3944;-8630,3814;-8603,3685;-8573,3558;-8538,3432;-8500,3308;-8457,3186;-8410,3066;-8352,2934;-8289,2806;-8220,2680;-8146,2558;-8066,2439;-7982,2324;-7892,2212;-7798,2104;-7699,2001;-7596,1902;-7488,1808;-7376,1718;-7261,1634;-7142,1554;-7020,1480;-6894,1411;-6766,1348;-6634,1290;-6514,1243;-6392,1200;-6268,1162;-6142,1127;-6015,1097;-5886,1070;-5756,1046;-5625,1026;-5493,1009;-5360,994;-5227,982;-5093,973;-4958,965;-4823,960;-4687,956;-4551,953;-4414,951;-4276,950;276,950;414,951;551,953;687,956;823,960;958,965;1093,973;1227,982;1360,994;1493,1009;1625,1026;1756,1046;1886,1070;2015,1097;2142,1127;2268,1162;2392,1200;2514,1243;2634,1290;2766,1348;2894,1411;3020,1480;3142,1554;3261,1634;3376,1718;3488,1808;3596,1902;3699,2001;3798,2104;3892,2212;3982,2324;4066,2439;4146,2558;4220,2680;4289,2806;4352,2934;4410,3066;4457,3186;4500,3308;4538,3432;4573,3558;4603,3685;4630,3814;4654,3944;4674,4075;4691,4207;4706,4340;4718,4473;4727,4607;4735,4742;4740,4877;4744,5013;4747,5149;4749,5286;4750,5424;4750,5700;5250,5700;5250,5422;5249,5282;5247,5141;5244,5001;5240,4859;5234,4718;5226,4576;5216,4433;5203,4290;5188,4147;5169,4004;5147,3861;5121,3718;5091,3576;5057,3433;5018,3292;4975,3151;4926,3012;4872,2874;4806,2723;4733,2575;4653,2430;4568,2289;4476,2152;4379,2019;4275,1891;4167,1767;4053,1647;3933,1533;3809,1425;3681,1321;3548,1224;3411,1132;3270,1047;3125,967;2977,894;2826,828;2688,774;2549,725;2408,682;2267,643;2124,609;1982,579;1839,553;1696,531;1553,512;1410,497;1267,484;1124,474;982,466;841,460;699,456;559,453;418,451;278,450)]
r = gf.kdb.Region(polygons)
r
(-12000,-250;-12000,250;8000,250;8000,-250);(-4278,450;-4418,451;-4559,453;-4699,456;-4841,460;-4982,466;-5124,474;-5267,484;-5410,497;-5553,512;-5696,531;-5839,553;-5982,579;-6124,609;-6267,643;-6408,682;-6549,725;-6688,774;-6826,828;-6977,894;-7125,967;-7270,1047;-7411,1132;-7548,1224;-7681,1321;-7809,1425;-7933,1533;-8053,1647;-8167,1767;-8275,1891;-8379,2019;-8476,2152;-8568,2289;-8653,2430;-8733,2575;-8806,2723;-8872,2874;-8926,3012;-8975,3151;-9018,3292;-9057,3433;-9091,3576;-9121,3718;-9147,3861;-9169,4004;-9188,4147;-9203,4290;-9216,4433;-9226,4576;-9234,4718;-9240,4859;-9244,5001;-9247,5141;-9249,5282;-9250,5422;-9250,5700;-8750,5700;-8750,5424;-8749,5286;-8747,5149;-8744,5013;-8740,4877;-8735,4742;-8727,4607;-8718,4473;-8706,4340;-8691,4207;-8674,4075;-8654,3944;-8630,3814;-8603,3685;-8573,3558;-8538,3432;-8500,3308;-8457,3186;-8410,3066;-8352,2934;-8289,2806;-8220,2680;-8146,2558;-8066,2439;-7982,2324;-7892,2212;-7798,2104;-7699,2001;-7596,1902;-7488,1808;-7376,1718;-7261,1634;-7142,1554;-7020,1480;-6894,1411;-6766,1348;-6634,1290;-6514,1243;-6392,1200;-6268,1162;-6142,1127;-6015,1097;-5886,1070;-5756,1046;-5625,1026;-5493,1009;-5360,994;-5227,982;-5093,973;-4958,965;-4823,960;-4687,956;-4551,953;-4414,951;-4276,950;276,950;414,951;551,953;687,956;823,960;958,965;1093,973;1227,982;1360,994;1493,1009;1625,1026;1756,1046;1886,1070;2015,1097;2142,1127;2268,1162;2392,1200;2514,1243;2634,1290;2766,1348;2894,1411;3020,1480;3142,1554;3261,1634;3376,1718;3488,1808;3596,1902;3699,2001;3798,2104;3892,2212;3982,2324;4066,2439;4146,2558;4220,2680;4289,2806;4352,2934;4410,3066;4457,3186;4500,3308;4538,3432;4573,3558;4603,3685;4630,3814;4654,3944;4674,4075;4691,4207;4706,4340;4718,4473;4727,4607;4735,4742;4740,4877;4744,5013;4747,5149;4749,5286;4750,5424;4750,5700;5250,5700;5250,5422;5249,5282;5247,5141;5244,5001;5240,4859;5234,4718;5226,4576;5216,4433;5203,4290;5188,4147;5169,4004;5147,3861;5121,3718;5091,3576;5057,3433;5018,3292;4975,3151;4926,3012;4872,2874;4806,2723;4733,2575;4653,2430;4568,2289;4476,2152;4379,2019;4275,1891;4167,1767;4053,1647;3933,1533;3809,1425;3681,1321;3548,1224;3411,1132;3270,1047;3125,967;2977,894;2826,828;2688,774;2549,725;2408,682;2267,643;2124,609;1982,579;1839,553;1696,531;1553,512;1410,497;1267,484;1124,474;982,466;841,460;699,456;559,453;418,451;278,450)
c2 = c.copy()
r = r.sized(2000)
c2.add_polygon(r, layer=LAYER.SLAB90)
c2
/tmp/ipykernel_2431/1270480426.py:1: UserWarning: copy() is deprecated and will be removed in gdsfactory9. Please use dup() instead.
  c2 = c.copy()
../_images/fecd7a5980c013247b1f01ab3e05c4d0001ec19c5bebac2f52f1bc80ab9b148d.png

To avoid acute angles you can run over / under (dilation+erosion).

c2 = c.copy()

d = 800
r = gf.kdb.Region(polygons)
r = r.sized(+d + 2000)
r = r.sized(-d)
c2.add_polygon(r, layer=LAYER.SLAB90)
c2
/tmp/ipykernel_2431/2843357525.py:1: UserWarning: copy() is deprecated and will be removed in gdsfactory9. Please use dup() instead.
  c2 = c.copy()
../_images/3e134af8be8e17c840a75d002066aee82af842eb65cc846dd73799c736e14261.png

Outline#

c2 = gf.Component()

d = 800
r = gf.kdb.Region(polygons)
r_sized = r.sized(+2000)

r_outline = r_sized - r
c2.add_polygon(r_outline, layer=LAYER.SLAB90)
c2
../_images/7b013492bf3343896e273129ac2087d5aecb542b8450fbc9f6ab28d7aaf4762b.png

Round corners#

c = gf.c.triangle()
c
../_images/dc2f8cd4eb4d885529c522c2b62c1b58d6bb174e4b5304562b46d02697209812.png
c2 = gf.Component()

rinner = 1000  # 	The circle radius of inner corners (in database units).
router = 1000  # 	The circle radius of outer corners (in database units).
n = 300  # 	The number of points per full circle.

# round corners for one layer only
for p in c.get_polygons()[LAYER.WG]:
    p_round = p.round_corners(rinner, router, n)
    c2.add_polygon(p_round, layer=LAYER.WG)

c2
../_images/04f438aaaa5837b523462c28b3ef23d24d995e18a5771112b4670758c2979b9e.png
c = gf.Component()
t = c << gf.c.triangle(x=10, y=20, layer="WG")
t = c << gf.c.triangle(x=20, y=40, layer="SLAB90")

c2 = gf.Component()
rinner = 1000  # 	The circle radius of inner corners (in database units).
router = 1000  # 	The circle radius of outer corners (in database units).
n = 300  # 	The number of points per full circle.

# round corners for all layers
for layer, polygons in c.get_polygons().items():
    for p in polygons:
        p_round = p.round_corners(rinner, router, n)
        c2.add_polygon(p_round, layer=layer)

c2
../_images/3698982b2d898b49f3ee204bbb56fd8327efdb00824d5e436b9f01f143cfb6e0.png

Union#

import gdsfactory as gf

c = gf.Component()
e0 = c << gf.components.ellipse(layer=(1, 0))
e1 = c << gf.components.ellipse(layer=(2, 0))
e2 = c << gf.components.ellipse(layer=(3, 0))
e3 = c << gf.components.ellipse(layer=(4, 0))
e4 = c << gf.components.ellipse(layer=(5, 0))
e5 = c << gf.components.ellipse(layer=(6, 0))

e1.drotate(15 * 1)
e2.drotate(15 * 2)
e3.drotate(15 * 3)
e4.drotate(15 * 4)
e5.drotate(15 * 5)

c
../_images/150c61ae26527962ed6bad2c303568f42606354d1faf2a1b9ae08de8e5a91998.png
polygons = c.get_polygons()
r = gf.kdb.Region()

for polys in polygons.values():
    r = r + gf.kdb.Region(polys)

c2 = gf.Component()
c2.add_polygon(r, layer=(1, 0))
c2
../_images/5de662ef7e0066fecb5c228da0b813100d22b6936e6220a1453f9ccd3c27cb66.png

Importing GDS files#

gf.import_gds() allows you to easily import external GDSII files. It imports a single cell from the external GDS file and converts it into a gdsfactory component.

D = gf.components.ellipse()
D.write_gds("myoutput.gds")
D2 = gf.import_gds(gdspath="myoutput.gds")
D2.plot()
../_images/2c9dad8cbe8f161752225235ba8f59429e4120d68c2bb1a1d7bda172fa2ba21f.png

Copying and extracting geometry#

E = gf.Component()
E.add_ref(gf.components.ellipse(layer=(1, 0)))
D = E.extract(layers=[(1, 0)])
D.plot()
../_images/2c9dad8cbe8f161752225235ba8f59429e4120d68c2bb1a1d7bda172fa2ba21f.png
import gdsfactory as gf

X = gf.components.ellipse(layer=(2, 0))
c = X.copy()
c.plot()
/tmp/ipykernel_2431/2728904800.py:4: UserWarning: copy() is deprecated and will be removed in gdsfactory9. Please use dup() instead.
  c = X.copy()
../_images/30798bc021c8897af532aba0bfedb052c50d8753ce6740a46d84031eeb1623c2.png
c_copied_layers = gf.components.copy_layers(
    gf.components.straight, layers=((1, 0), (2, 0))
)
c_copied_layers.plot()
../_images/fada3fba9dfee8417e23cb4961bb08aeaa7338e1466bf644c9dc56d3622a9afb.png

Import Images into GDS#

You can import your logo into GDS using the conversion from numpy arrays.

from gdsfactory.config import PATH
from gdsfactory.read.from_np import from_image
import gdsfactory as gf

c = from_image(
    PATH.module / "samples" / "images" / "logo.png", nm_per_pixel=500, invert=False
)
c.plot()
../_images/2c00481315775e6a8379a2256ec41bbb2e82c088d9f9a14223c1d7c69caa305f.png
c = from_image(
    PATH.module / "samples" / "images" / "logo.png", nm_per_pixel=500, invert=True
)
c.plot()
../_images/3a5cc9c91a58774a447906e2f41eeca20eb48d33353c8d31f540168eb4b11586.png

Dummy Fill / Tiling#

To keep constant density in some layers you can add dummy fill shapes.

For big layouts you should use tiling processor.

import kfactory as kf

import gdsfactory as gf
from kfactory.utils.fill import fill_tiled

c = kf.KCell("ToFill")
c.shapes(kf.kcl.layer(1, 0)).insert(
    kf.kdb.DPolygon.ellipse(kf.kdb.DBox(5000, 3000), 512)
)
c.shapes(kf.kcl.layer(10, 0)).insert(
    kf.kdb.DPolygon(
        [kf.kdb.DPoint(0, 0), kf.kdb.DPoint(5000, 0), kf.kdb.DPoint(5000, 3000)]
    )
)

fc = kf.KCell()
fc.shapes(fc.kcl.layer(2, 0)).insert(kf.kdb.DBox(20, 40))
fc.shapes(fc.kcl.layer(3, 0)).insert(kf.kdb.DBox(30, 15))

# fill.fill_tiled(c, fc, [(kf.kcl.layer(1,0), 0)], exclude_layers = [(kf.kcl.layer(10,0), 100), (kf.kcl.layer(2,0), 0), (kf.kcl.layer(3,0),0)], x_space=5, y_space=5)
fill_tiled(
    c,
    fc,
    [(kf.kcl.layer(1, 0), 0)],
    exclude_layers=[
        (kf.kcl.layer(10, 0), 100),
        (kf.kcl.layer(2, 0), 0),
        (kf.kcl.layer(3, 0), 0),
    ],
    x_space=5,
    y_space=5,
)

gdspath = "mzi_fill.gds"
c.write(gdspath)
c = gf.import_gds(gdspath, cellname="ToFill")
c.plot()
../_images/1f1aafc9d1181dbfc9698b7ee7875f6c54d52c56c3c051049e877ff8196cc84e.png