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


相关推荐

  1. 如何在three.js中3D圆弧及半圆弧组成圆

    2023-12-09 00:16:02       33 阅读
  2. Lumerical ------ 直仿真及技巧

    2023-12-09 00:16:02       57 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-09 00:16:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-09 00:16:02       101 阅读
  3. 在Django里面运行非项目文件

    2023-12-09 00:16:02       82 阅读
  4. Python语言-面向对象

    2023-12-09 00:16:02       91 阅读

热门阅读

  1. 顺序查找(数据结构实训)

    2023-12-09 00:16:02       56 阅读
  2. 第56天:django学习(五)

    2023-12-09 00:16:02       55 阅读
  3. using meta-SQL 使用元SQL 六

    2023-12-09 00:16:02       44 阅读
  4. 鸿蒙(HarmonyOS)应用开发——管理组件状态

    2023-12-09 00:16:02       61 阅读
  5. TensorRT-LLM保姆级教程(一)-快速入门

    2023-12-09 00:16:02       63 阅读
  6. 计算机网络之网络层

    2023-12-09 00:16:02       65 阅读
  7. Halcon Dict相关算子(一)

    2023-12-09 00:16:02       56 阅读
  8. 12月07日,每日信息差

    2023-12-09 00:16:02       52 阅读