예제 #1
0
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
예제 #2
0
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
예제 #3
0
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