# 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.plot()


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


## Offset#

import gdsfactory as gf
from gdsfactory.generic_tech import LAYER

c = gf.components.coupler_ring()
c

polygons = c.get_polygons()[LAYER.WG]
polygons

[(-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;-4000,950;-4000,450),
(-9000,-250;-9000,250;-4000,250;-4000,-250),
(0,450;0,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),
(0,-250;0,250;5000,250;5000,-250),
(-4000,450;-4000,950;0,950;0,450),
(-4000,-250;-4000,250;0,250;0,-250),
(-12000,-250;-12000,250;-9000,250;-9000,-250),
(5000,-250;5000,250;8000,250;8000,-250)]

r = gf.kdb.Region(polygons)
r

(-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;-4000,950;-4000,450);(-9000,-250;-9000,250;-4000,250;-4000,-250);(0,450;0,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);(0,-250;0,250;5000,250;5000,-250);(-4000,450;-4000,950;0,950;0,450);(-4000,-250;-4000,250;0,250;0,-250);(-12000,-250;-12000,250;-9000,250;-9000,-250);(5000,-250;5000,250;8000,250;8000,-250)

c2 = c.copy()
r = r.sized(2000)
c2


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


## Outline#

c2 = gf.Component()

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

r_outline = r_sized - r
c2


## Round corners#

c = gf.c.triangle()
c

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

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


## 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

polygons = c.get_polygons()
r = gf.kdb.Region()

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

c2 = gf.Component()
c2


## 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()


## Copying and extracting geometry#

E = gf.Component()
D = E.extract(layers=[(1, 0)])
D.plot()

import gdsfactory as gf

X = gf.components.ellipse(layer=(2, 0))
c = X.copy()
c.plot()

c_copied_layers = gf.components.copy_layers(
gf.components.straight, layers=((1, 0), (2, 0))
)
c_copied_layers.plot()


## Import Images into GDS#

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

from gdsfactory.config import PATH
import gdsfactory as gf

c = from_image(
PATH.module / "samples" / "images" / "logo.png", nm_per_pixel=500, invert=False
)
c.plot()

c = from_image(
PATH.module / "samples" / "images" / "logo.png", nm_per_pixel=500, invert=True
)
c.plot()


## Dummy Fill / Tiling#

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

### Custom fill cell#

You can use a custom cell as a fill.

### Tiling processor#

For big layouts you can should use klayout 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()