Esempio n. 1
0
def add_keepout(
    component: Component,
    target_layers: Layers,
    keepout_layers: Layers,
    margin: float = 2.0,
) -> Component:
    """Adds keepout after Looking up all polygons in a cell.
    You can also use add_padding

    Args:
        component
        target_layers: list of layers to read
        keepout_layers: list of layers to add keepout
        margin: offset from tareget to keepout_layers
    """
    c = Component(f"{component.name}_ko")
    c << component
    for layer in target_layers:
        polygons = component.get_polygons(by_spec=layer)
        if polygons:
            for ko_layer in keepout_layers:
                ko_layer = _parse_layer(ko_layer)
                polygon_keepout = [
                    polygon_grow(polygon, margin) for polygon in polygons
                ]
                c.add_polygon(polygon_keepout, ko_layer)
    return c
Esempio n. 2
0
def to_3d(
    component: Component,
    layer_set: LayerSet,
    layer_stack: LayerStack = LAYER_STACK,
    exclude_layers: Optional[Tuple[Layer, ...]] = None,
) -> Scene:
    """Return the Component 3D trimesh Scene.

    Args:
        component:
        layer_set: layer colors from Klayout Layer Properties file
        layer_stack: contains thickness and zmin for each layer
        exclude_layers: layers to exclude

    """
    scene = Scene()
    layer_to_thickness = layer_stack.get_layer_to_thickness()
    layer_to_zmin = layer_stack.get_layer_to_zmin()
    exclude_layers = exclude_layers or []

    for layer, polygons in component.get_polygons(by_spec=True).items():
        if (layer not in exclude_layers and layer in layer_to_thickness
                and layer in layer_to_zmin):
            height = layer_to_thickness[layer]
            zmin = layer_to_zmin[layer]
            color_hex = layer_set.get_from_tuple(layer).color
            color_rgb = matplotlib.colors.to_rgb(color_hex)
            for polygon in polygons:
                p = shapely.geometry.Polygon(polygon)
                mesh = extrude_polygon(p, height=height)
                mesh.apply_translation((0, 0, zmin))
                mesh.visual.face_colors = (*color_rgb, 0.5)
                scene.add_geometry(mesh)
    return scene
Esempio n. 3
0
def union(
        component: Component,
        by_layer: bool = False,
        precision: float = 1e-4,
        join_first: bool = True,
        max_points: int = 4000,
        layer: Layer = (1, 0),
) -> Component:
    """Creates an inverted version of the input shapes with an additional
    border around the edges.

    adapted from phidl.geometry.invert

    Args:
        D: Component(/Reference), list of Component(/Reference), or Polygon
            A Component containing the polygons to perform union on.
        by_Layer: performs the union operation layer-wise so each layer can be
            individually combined.
        precision: Desired precision for rounding vertex coordinates.
        join_first: before offsetting to avoid unnecessary joins in adjacent polygon
        max_points: The maximum number of vertices within the resulting polygon.
        layer : Specific layer to put polygon geometry on.

    Returns
        Component containing the  union of the polygons
    """
    U = Component()

    if by_layer:
        all_polygons = component.get_polygons(by_spec=True)
        for layer, polygons in all_polygons.items():
            unioned_polygons = pg._union_polygons(polygons,
                                                  precision=precision,
                                                  max_points=max_points)
            U.add_polygon(unioned_polygons, layer=layer)
    else:
        all_polygons = component.get_polygons(by_spec=False)
        unioned_polygons = pg._union_polygons(all_polygons,
                                              precision=precision,
                                              max_points=max_points)
        U.add_polygon(unioned_polygons, layer=layer)
    return U
Esempio n. 4
0
def xor_polygons(A: Component, B: Component, hash_geometry: bool = True):
    """Given two devices A and B, performs a layer-by-layer XOR diff between
    A and B, and returns polygons representing the differences between A and B.
    Adapted from lytest/kdb_xor.py
    """

    # first do a geometry hash to vastly speed up if they are equal
    if hash_geometry and (A.hash_geometry() == B.hash_geometry()):
        return Component()

    D = Component()
    A_polys = A.get_polygons(by_spec=True)
    B_polys = B.get_polygons(by_spec=True)
    A_layers = A_polys.keys()
    B_layers = B_polys.keys()
    all_layers = set()
    all_layers.update(A_layers)
    all_layers.update(B_layers)
    for layer in all_layers:
        if (layer in A_layers) and (layer in B_layers):
            p = gdspy.fast_boolean(
                A_polys[layer],
                B_polys[layer],
                operation="xor",
                precision=0.001,
                max_points=4000,
                layer=layer[0],
                datatype=layer[1],
            )
        elif layer in A_layers:
            p = A_polys[layer]
        elif layer in B_layers:
            p = B_polys[layer]
        if p is not None:
            D.add_polygon(p, layer=layer)
    return D
Esempio n. 5
0
def to_stl(
    component: Component,
    filepath: str,
    layer_set: LayerSet,
    layer_stack: LayerStack = LAYER_STACK,
    exclude_layers: Optional[Tuple[Layer, ...]] = None,
) -> None:
    """Exports a Component into STL.

    Args:
        component:
        filepath:
        layer_set: layer colors from Klayout Layer Properties file
        layer_stack: contains thickness and zmin for each layer
        exclude_layers: layers to exclude

    """
    from trimesh.creation import extrude_polygon

    layer_to_thickness = layer_stack.get_layer_to_thickness()
    layer_to_zmin = layer_stack.get_layer_to_zmin()
    filepath = pathlib.Path(filepath)
    exclude_layers = exclude_layers or []

    for layer, polygons in component.get_polygons(by_spec=True).items():
        if (
            layer not in exclude_layers
            and layer in layer_to_thickness
            and layer in layer_to_zmin
        ):
            height = layer_to_thickness[layer]
            zmin = layer_to_zmin[layer]
            color_hex = layer_set.get_from_tuple(layer).color
            color_rgb = matplotlib.colors.to_rgb(color_hex)
            filepath_layer = (
                filepath.parent
                / f"{filepath.stem}_{layer[0]}_{layer[1]}{filepath.suffix}"
            )
            print(filepath_layer)

            for polygon in polygons:
                p = shapely.geometry.Polygon(polygon)
                mesh = extrude_polygon(p, height=height)
                mesh.apply_translation((0, 0, zmin))
                mesh.visual.face_colors = (*color_rgb, 0.5)
                mesh.export(filepath_layer)
Esempio n. 6
0
def compute_area(c: Component, target_layer: Tuple[int, int]) -> float64:
    """Returns Computed area of the component for a given layer."""
    # _print("Computing area ", c.name)
    c.flatten()
    # return c.area(by_spec=True)[layer]
    polys_by_spec = c.get_polygons(by_spec=True)
    _area = 0
    for (layer, polys) in polys_by_spec.items():
        # _print(layer)
        if layer == target_layer:
            joined_polys = gp.boolean(polys, None, operation="or")
            _print(joined_polys)
            try:
                _area += sum([abs(area(p)) for p in joined_polys.polygons])
            except BaseException:
                print(
                    f"Warning, {c.name} joinedpoly {joined_polys} could not be added"
                )
    return _area
Esempio n. 7
0
def to_np(
    component: Component,
    nm_per_pixel: int = 20,
    layers: Layers = ((1, 0), ),
    values: Optional[Floats] = None,
    pad_width: int = 1,
) -> np.ndarray:
    """Returns a pixelated numpy array from Component polygons.

    Args:
        component: Component
        nm_per_pixel: you can go from 20 (coarse) to 4 (fine)
        layers: to convert. Order matters (latter overwrite former)
        values: associated to each layer (defaults to 1)
        pad_width: padding pixels around the image

    """
    pixels_per_um = (1 / nm_per_pixel) * 1e3
    xmin, ymin = component.bbox[0]
    xmax, ymax = component.bbox[1]
    shape = (
        int(np.ceil(xmax - xmin) * pixels_per_um),
        int(np.ceil(ymax - ymin) * pixels_per_um),
    )
    img = np.zeros(shape, dtype=float)
    layer_to_polygons = component.get_polygons(by_spec=True, depth=None)

    values = values or [1] * len(layers)

    for layer, value in zip(layers, values):
        if layer in layer_to_polygons:
            polygons = layer_to_polygons[layer]
            for polygon in polygons:
                r = polygon[:, 0] - xmin
                c = polygon[:, 1] - ymin
                rr, cc = skdraw.polygon(r * pixels_per_um,
                                        c * pixels_per_um,
                                        shape=shape)
                img[rr, cc] = value

    img_with_padding = np.pad(img, pad_width=pad_width)
    return img_with_padding