def smooth( points = [(20,0), (40,0), (80,40), (80,10), (100,10),], radius = 4, corner_fun = euler, **kwargs ): """ Create a smooth path from a series of waypoints. Corners will be rounded using `corner_fun` and any additional key word arguments (for example, `use_eff = True` when `corner_fun = pp.euler`) Parameters ---------- points : array-like[N][2] List of waypoints for the path to follow radius : int or float Radius of curvature, this argument will be passed to `corner_fun` corner_fun : function The function that controls how the corners are rounded. Typically either `arc()` or `euler()` **kwargs : dict Extra keyword arguments that will be passed to `corner_fun` Returns ------- Path A Path object with the specified smoothed path. """ points = np.asfarray(points) normals = np.diff(points, axis = 0) normals = (normals.T/np.linalg.norm(normals, axis = 1)).T # normals_rev = normals*np.array([1,-1]) dx = np.diff(points[:,0]) dy = np.diff(points[:,1]) ds = np.sqrt(dx**2 + dy**2) theta = np.degrees(np.arctan2(dy,dx)) dtheta = np.diff(theta) dtheta = dtheta - 360*np.floor((dtheta + 180)/360) # FIXME add caching # Create arcs paths = [] radii = [] for dt in dtheta: P = corner_fun(radius = radius, angle = dt, **kwargs) chord = np.linalg.norm(P.points[-1,:] - P.points[0,:]) r = (chord/2)/np.sin(np.radians(dt/2)) r = np.abs(r) radii.append(r) paths.append(P) d = np.abs(np.array(radii)/np.tan(np.radians(180-dtheta)/2)) encroachment = np.concatenate([[0],d]) + np.concatenate([d,[0]]) if np.any(encroachment > ds): raise ValueError('[PHIDL] smooth(): Not enough distance between points to to fit curves. Try reducing the radius or spacing the points out farther') p1 = points[1:-1,:] - normals[:-1,:]*d[:,np.newaxis] # Move arcs into position new_points = [] new_points.append( [points[0,:]] ) for n,dt in enumerate(dtheta): P = paths[n] P.rotate(theta[n] - 0) P.move(p1[n]) new_points.append(P.points) new_points.append( [points[-1,:]] ) new_points = np.concatenate(new_points) P = Path() P.rotate(theta[0]) P.append(new_points) P.move(points[0,:]) return P
def connect(x2, y2, middle_e_width, chip_width, chip_height, pos, radius, length, e_e_gap, setpos): mm = 10**3 um = 1 M = Path() # Dimensions margin = 0.5 * mm to_pad_term = 0.1 * mm pad = 50 * um pitch = 100 * um side_e_width = middle_e_width * 2 rad_gap = e_e_gap + middle_e_width / 2 + side_e_width / 2 if pos == 't': Rt = radius + rad_gap * 2 elif pos == 'm': Rt = radius + rad_gap else: Rt = radius if setpos == 't': set_bias = 0.6 * mm elif setpos == 'm': set_bias = 0.3 * mm else: set_bias = 0 x1 = (chip_width - length) / 2 - Rt - set_bias y1 = margin + to_pad_term points = np.array([(x1, y1), (x1, y2), (x2, y2)]) points = rotate90(points) M = pp.smooth( points=points, radius=Rt, corner_fun=pp.arc, ) M.rotate(90) X = CrossSection() if pos == 'm': X.add(width=middle_e_width, offset=0, layer=3) else: X.add(width=side_e_width, offset=0, layer=3) L = M.extrude(X) #Left Trace if pos == 'm': # adding pads S = pg.rectangle(size=(pad, pad), layer=3) L.add_ref(S).move([x1 - pad / 2, margin]) L.add_ref(S).move([x1 - pad / 2 - pitch, margin]) L.add_ref(S).move([x1 - pad / 2 + pitch, margin]) xm1 = x1 - middle_e_width / 2 xm2 = x1 + middle_e_width / 2 xm3 = x1 + pad / 2 xm4 = x1 - pad / 2 xpts = (xm1, xm2, xm3, xm4) ypts = (y1, y1, margin + pad, margin + pad) L.add_polygon([xpts, ypts], layer=3) xt1 = xm1 + middle_e_width + e_e_gap xt2 = xt1 + side_e_width xt3 = xm3 + pitch xt4 = xm4 + pitch xpts = (xt1, xt2, xt3, xt4) ypts = (y1, y1, margin + pad, margin + pad) L.add_polygon([xpts, ypts], layer=3) xb1 = xm1 - side_e_width - e_e_gap xb2 = xm1 - e_e_gap xb3 = xm3 - pitch xb4 = xm4 - pitch xpts = (xb1, xb2, xb3, xb4) ypts = (y1, y1, margin + pad, margin + pad) L.add_polygon([xpts, ypts], layer=3) R = pg.copy(L) # Right Trace R.mirror((chip_width / 2, chip_height), (chip_width / 2, 0)) D = Device('trace') D << L D << R return D
def smooth(points=[ (20, 0), (40, 0), (80, 40), (80, 10), (100, 10), ], radius=4, corner_fun=euler, **kwargs): """ Create a smooth path from a series of waypoints. Corners will be rounded using `corner_fun` and any additional key word arguments (for example, `use_eff = True` when `corner_fun = pp.euler`) Parameters ---------- points : array-like[N][2] List of waypoints for the path to follow radius : int or float Radius of curvature, this argument will be passed to `corner_fun` corner_fun : function The function that controls how the corners are rounded. Typically either `arc()` or `euler()` **kwargs : dict Extra keyword arguments that will be passed to `corner_fun` Returns ------- Path A Path object with the specified smoothed path. """ points, normals, ds, theta, dtheta = _compute_segments(points) colinear_elements = np.concatenate([[False], np.abs(dtheta) < 1e-6, [False]]) if np.any(colinear_elements): new_points = points[~colinear_elements, :] points, normals, ds, theta, dtheta = _compute_segments(new_points) if np.any(np.abs(np.abs(dtheta) - 180) < 1e-6): raise ValueError( '[PHIDL] smooth() received points which double-back on themselves' + '--turns cannot be computed when going forwards then exactly backwards.' ) # FIXME add caching # Create arcs paths = [] radii = [] for dt in dtheta: P = corner_fun(radius=radius, angle=dt, **kwargs) chord = np.linalg.norm(P.points[-1, :] - P.points[0, :]) r = (chord / 2) / np.sin(np.radians(dt / 2)) r = np.abs(r) radii.append(r) paths.append(P) d = np.abs(np.array(radii) / np.tan(np.radians(180 - dtheta) / 2)) encroachment = np.concatenate([[0], d]) + np.concatenate([d, [0]]) if np.any(encroachment > ds): raise ValueError( '[PHIDL] smooth(): Not enough distance between points to to fit curves. Try reducing the radius or spacing the points out farther' ) p1 = points[1:-1, :] - normals[:-1, :] * d[:, np.newaxis] # Move arcs into position new_points = [] new_points.append([points[0, :]]) for n, dt in enumerate(dtheta): P = paths[n] P.rotate(theta[n] - 0) P.move(p1[n]) new_points.append(P.points) new_points.append([points[-1, :]]) new_points = np.concatenate(new_points) P = Path() P.rotate(theta[0]) P.append(new_points) P.move(points[0, :]) return P