def bezier( name: None = None, width: float = 0.5, control_points: List[Tuple[float, float]] = [ (0.0, 0.0), (5.0, 0.0), (5.0, 2.0), (10.0, 2.0), ], t: ndarray = np.linspace(0, 1, 201), layer: Tuple[int, int] = LAYER.WG, **extrude_path_params ) -> Component: """ bezier bend """ def _fmt_f(x): return "{:.3f}".format(x).rstrip("0").rstrip(".") def _fmt_cp(cps): return "_".join(["({},{})".format(_fmt_f(p[0]), _fmt_f(p[1])) for p in cps]) if name is None: points_hash = hashlib.md5(_fmt_cp(control_points).encode()).hexdigest() name = "bezier_w{}_{}_{}".format(int(width * 1e3), points_hash, layer) c = pp.Component(name=name) path_points = bezier_curve(t, control_points) polygon_points = extrude_path(path_points, width, **extrude_path_params) angles = angles_deg(path_points) c.info["start_angle"] = angles[0] c.info["end_angle"] = angles[-2] a0 = angles[0] + 180 a1 = angles[-2] a0 = snap_angle(a0) a1 = snap_angle(a1) p0 = path_points[0] p1 = path_points[-1] c.add_polygon(polygon_points, layer=layer) c.add_port(name="0", midpoint=p0, width=width, orientation=a0, layer=layer) c.add_port(name="1", midpoint=p1, width=width, orientation=a1, layer=layer) c.info["length"] = path_length(path_points) curv = curvature(path_points, t) c.info["min_bend_radius"] = 1 / max(np.abs(curv)) c.info["curvature"] = curv c.info["t"] = t return c
def objective_func(p): """ We want to minimize a combination of: - max curvature - negligible mismatch with start angle and end angle """ ps = array_1d_to_cpts(p) control_points = [start_point] + ps + [end_point] path_points = bezier_curve(t, control_points) max_curv = max(np.abs(curvature(path_points, t))) angles = angles_deg(path_points) dstart_angle = abs(angles[0] - start_angle) dend_angle = abs(angles[-2] - end_angle) angle_mismatch = dstart_angle + dend_angle return angle_mismatch * alpha + max_curv
def bezier( name: None = None, width: float = 0.5, control_points: List[Tuple[float, float]] = [ (0.0, 0.0), (5.0, 0.0), (5.0, 2.0), (10.0, 2.0), ], t: ndarray = np.linspace(0, 1, 201), layer: Tuple[int, int] = LAYER.WG, with_manhattan_facing_angles: bool = True, spike_length: float = 0.0, start_angle: Optional[int] = None, end_angle: Optional[int] = None, grid: float = 0.001, ) -> Component: """Bezier bend We avoid autoname control_points and t spacing Args: width: waveguide width control_points: list of points t: 1D array of points varying between 0 and 1 layer: layer """ def format_float(x): return "{:.3f}".format(x).rstrip("0").rstrip(".") def _fmt_cp(cps): return "_".join( [f"({format_float(p[0])},{format_float(p[1])})" for p in cps]) if name is None: points_hash = hashlib.md5(_fmt_cp(control_points).encode()).hexdigest() name = f"bezier_w{int(width*1e3)}_{points_hash}_{layer[0]}_{layer[1]}" c = pp.Component(name=name) c.ignore.add("control_points") c.ignore.add("t") path_points = bezier_curve(t, control_points) polygon_points = extrude_path( path_points, width=width, with_manhattan_facing_angles=with_manhattan_facing_angles, spike_length=spike_length, start_angle=start_angle, end_angle=end_angle, grid=grid, ) angles = angles_deg(path_points) c.info["start_angle"] = pp.drc.snap_to_1nm_grid(angles[0]) c.info["end_angle"] = pp.drc.snap_to_1nm_grid(angles[-2]) a0 = angles[0] + 180 a1 = angles[-2] a0 = snap_angle(a0) a1 = snap_angle(a1) p0 = path_points[0] p1 = path_points[-1] c.add_polygon(polygon_points, layer=layer) c.add_port(name="0", midpoint=p0, width=width, orientation=a0, layer=layer) c.add_port(name="1", midpoint=p1, width=width, orientation=a1, layer=layer) curv = curvature(path_points, t) c.info["length"] = pp.drc.snap_to_1nm_grid(path_length(path_points)) c.info["min_bend_radius"] = pp.drc.snap_to_1nm_grid(1 / max(np.abs(curv))) # c.info["curvature"] = curv # c.info["t"] = t return c