luceda ipkiss教程 43:画渐变圆弧型波导

案例分享:
在这里插入图片描述

from si_fab import all as pdk
import ipkiss3.all as i3
from ipcore.properties.restrictions import RestrictTuple
from ipkiss.geometry.shapes.modifiers import __ShapePathBase__
import numpy as np
from math import atan2

class ShapePathTaperExtended(__ShapePathBase__):
    """ Tapered path with extended ends based on a shape. """
    extension = i3.Tuple2Property(
        restriction=RestrictTuple((float)),
        doc="extension of the path shape at start and end: (start, end)"
    )
    end_path_width = i3.PositiveNumberProperty(doc="end width of path")
    start_path_width = i3.PositiveNumberProperty(doc="start width of path")

    def _default_end_path_width(self):
        return self.path_width

    def _default_path_width(self):
        return self.start_path_width

    def _default_extension(self):
        return 0., 0.

    def __init__(self, original_shape, start_path_width, end_path_width, **kwargs):
        super(ShapePathTaperExtended, self).__init__(
            original_shape=original_shape,
            start_path_width=start_path_width,
            end_path_width=end_path_width,
            **kwargs)

    def define_points(self, pts):
        # TODO: include start_face_angle and end_face_angle in the calculations
        start_ext, end_ext = self.extension
        west_coords = i3.Shape()
        east_coords = i3.Shape()
        orig_shp = i3.Shape(self.__get_original_shape_without_straight_angles__())
        start_angle, end_angle = orig_shp.get_face_angles()
        if len(orig_shp) == 0 or np.isclose(orig_shp.length(), 0.):
            return pts
        # begin
        orig_shp[0] = orig_shp[0].move_polar(-start_ext, start_angle)
        # end
        orig_shp[-1] = orig_shp[-1].move_polar(end_ext, end_angle)
        dist = [i3.distance(orig_shp[_], orig_shp[_ + 1]) for _ in range(len(orig_shp) - 1)]
        widths = [(self.end_path_width - self.path_width) * np.sum(dist[:_]) / np.sum(dist) + self.path_width for _ in
                  range(len(orig_shp))]
        coords = orig_shp.points
        n_points = len(coords)
        start_angle, end_angle = orig_shp.get_face_angles()
        # middle
        for i in range(n_points):
            x = coords[i][0]
            y = coords[i][1]
            if i == 0:
                angle1 = i3.DEG2RAD * start_angle
                angle2 = atan2(coords[i + 1][1] - y, coords[i + 1][0] - x)
            elif i == n_points - 1:
                angle1 = atan2(y - coords[i - 1][1], x - coords[i - 1][0])
                angle2 = i3.DEG2RAD * end_angle
            else:
                angle1 = atan2(y - coords[i - 1][1], x - coords[i - 1][0])
                angle2 = atan2(coords[i + 1][1] - y, coords[i + 1][0] - x)
            angle = angle1 + 0.5 * (angle2 - angle1 + np.pi) % (np.pi) - 0.5 * np.pi
            turn = (angle2 - angle1) % (2 * np.pi)
            ca = np.cos(angle)
            sa = np.sin(angle)
            if turn == np.pi and i not in [0, n_points - 1]:
                i3.LOG.error("Path to Boundary conversion is not possible with paths that turn 180 degree at a node")
                raise SystemExit
            w = 0.5 * widths[i] / np.abs(np.cos(0.5 * turn))
            c_west = (x - w * sa, y + w * ca)
            c_east = (x + w * sa, y - w * ca)
            west_coords.append(c_west)
            east_coords.append(c_east)
        east_coords.reverse()
        pts.extend(west_coords)
        pts.extend(east_coords)
        pts.append(west_coords[0])
        return pts


class gradient_arc(i3.PCell):
    class Layout(i3.LayoutView):
        radius = i3.PositiveNumberProperty(doc="Radius of the central bends", default=100.0)
        def _generate_elements(self, elems):
            shape_wg1 = [
                (0.0, 0.0),
                (self.radius, 0),
                (self.radius, self.radius),
                (self.radius, 2 * self.radius),
                (0, 2 * self.radius),
            ]
            shape_wg1_path = i3.ShapeRound(original_shape=shape_wg1, radius=self.radius)
            elems += i3.Boundary(layer=i3.TECH.PPLAYER.SI,
                                 shape=ShapePathTaperExtended(
                                     original_shape=shape_wg1_path,
                                     start_path_width=10,
                                     end_path_width=1,
                                 ))
            return elems


if __name__ == '__main__':
    gradient_arc().Layout().visualize()


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值