"""Based on phidl.geometry."""
from __future__ import annotations
import gdstk
import gdsfactory as gf
from gdsfactory.component_layout import Polygon
from gdsfactory.typings import Component, ComponentReference, LayerSpec
[docs]
@gf.cell
def offset(
elements: Component,
distance: float = 0.1,
use_union: bool = True,
precision: float = 1e-4,
join: str = "miter",
tolerance: int = 2,
layer: LayerSpec = "WG",
) -> Component:
"""Returns new Component with polygons eroded or dilated by an offset.
Args:
elements: Component(/Reference), list of Component(/Reference), or Polygons \
to offset or Component containing polygons to offset.
distance: Distance to offset polygons. Positive values expand, negative shrink.
use_union: If True, use union of all polygons to offset. If False, offset
precision: Desired precision for rounding vertex coordinates.
join: {'miter', 'bevel', 'round'} Type of join used to create polygon offset
tolerance: For miter joints, this number must be at least 2 represents the \
maximal distance in multiples of offset between new vertices and their \
original position before beveling to avoid spikes at acute joints. For \
round joints, it indicates the curvature resolution in number of \
points per full circle.
layer: Specific layer to put polygon geometry on.
Returns:
Component containing a polygon(s) with the specified offset applied.
.. plot::
:include-source:
import gdsfactory as gf
c = gf.Component()
layer_slab = (2, 0)
c1 = gf.components.coupler_ring(
cladding_layers=[layer_slab], cladding_offsets=[0.5]
)
d = 0.8
c2 = gf.geometry.offset(c1, distance=+d, layer=layer_slab)
c3 = gf.geometry.offset(c2, distance=-d, layer=layer_slab)
_ = c << c1.extract(layers=("WG",))
_ = c << c3
c.plot_matplotlib()
"""
if not isinstance(elements, list):
elements = [elements]
polygons_to_offset = []
for e in elements:
if isinstance(e, Component | ComponentReference):
polygons_to_offset += e.get_polygons(by_spec=False)
elif isinstance(e, Polygon | gdstk.Polygon):
polygons_to_offset.append(e)
if len(polygons_to_offset) == 0:
return gf.Component("offset")
gds_layer, gds_datatype = gf.get_layer(layer)
p = gdstk.offset(
polygons_to_offset,
distance=distance,
join=join,
tolerance=tolerance,
precision=precision,
use_union=use_union,
layer=gds_layer,
datatype=gds_datatype,
)
component = gf.Component()
component.add_polygon(p, layer=layer)
return component
def test_offset() -> None:
c = gf.components.ring()
co = offset(c, distance=0.5)
assert int(co.area()) == 94
if __name__ == "__main__":
import gdsfactory as gf
# c = gf.Component()
# layer_slab = (2, 0)
# c1 = gf.components.coupler_ring(
# cladding_layers=[layer_slab], cladding_offsets=[0.5]
# )
# d = 0.8
# # d = 1
# c2 = gf.geometry.offset(c1, distance=+d, layer=layer_slab)
# c3 = gf.geometry.offset(c2, distance=-d, layer=layer_slab)
# _ = c << c1.extract(layers=("WG",))
# _ = c << c3
# c.show()
c = gf.Component("demo_dataprep")
c1 = gf.components.coupler_ring(cross_section="xs_rc2", radius=20)
c1.show()
d = 0.8
c2 = gf.geometry.offset(c1, distance=+d, layer=(3, 0))
c3 = gf.geometry.offset(c2, distance=-d, layer=(3, 0))
c << c1
c << c3
c.show()