Source code for gdsfactory.boolean
from __future__ import annotations
from typing import TYPE_CHECKING, Literal
import kfactory as kf
from gdsfactory.component import Component, ComponentReference, boolean_operations
if TYPE_CHECKING:
from gdsfactory.typings import ComponentOrReference, LayerSpec
[docs]
def boolean(
A: ComponentOrReference,
B: ComponentOrReference,
operation: Literal["or", "|", "not", "-", "^", "xor", "&", "and", "A-B"],
layer: LayerSpec,
layer1: LayerSpec | None = None,
layer2: LayerSpec | None = None,
) -> Component:
"""Performs boolean operations between 2 Component or Instance objects.
The `operation` parameter specifies the type of boolean operation to perform.
Supported operations include {'not', 'and', 'or', 'xor', '-', '&', '|', '^'}:
- `'|'` is equivalent to `'or'`
- `'-'` is equivalent to `'not'`
- `'&'` is equivalent to `'and'`
- `'^'` is equivalent to `'xor'`
Args:
A: Component(/Reference) or list of Component(/References).
B: Component(/Reference) or list of Component(/References).
operation: {'not', 'and', 'or', 'xor', '-', '&', '|', '^'}.
layer: Specific layer to put polygon geometry on.
layer1: Specific layer to get polygons.
layer2: Specific layer to get polygons.
Returns: Component with polygon(s) of the boolean operations between
the 2 input Components performed.
.. plot::
:include-source:
import gdsfactory as gf
c = gf.Component()
c1 = c << gf.components.circle(radius=10)
c2 = c << gf.components.circle(radius=9)
c2.movex(5)
c = gf.boolean(c1, c2, operation="xor")
c.plot()
"""
from gdsfactory import get_layer
if operation not in boolean_operations:
raise ValueError(
f"Boolean operation {operation} not supported. Choose from {list(boolean_operations.keys())}"
)
c = Component()
layer1 = layer1 or layer
layer2 = layer2 or layer
layer_index1 = get_layer(layer1)
layer_index2 = get_layer(layer2)
layer_index = get_layer(layer)
if isinstance(A, kf.DKCell):
ar = kf.kdb.Region(A.begin_shapes_rec(layer_index1))
else:
ar = get_ref_shapes(A, layer_index1)
if isinstance(B, kf.DKCell):
br = kf.kdb.Region(B.begin_shapes_rec(layer_index2))
else:
br = get_ref_shapes(B, layer_index2)
c.shapes(layer_index).insert(boolean_operations[operation](ar, br))
return c
def get_ref_shapes(ref: ComponentReference, layer_index: int) -> kf.kdb.Region:
if ref.is_regular_array():
base_inst_region = kf.kdb.Region(ref.cell.begin_shapes_rec(layer_index))
br = kf.kdb.Region()
for ia in range(ref.na):
for ib in range(ref.nb):
br.insert(
base_inst_region.transformed(
ref.cplx_trans * kf.kdb.ICplxTrans(ia * ref.a + ib * ref.b)
)
)
else:
br = kf.kdb.Region(ref.cell.begin_shapes_rec(layer_index)).transformed(
ref.cplx_trans
)
return br