Ejemplo n.º 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)

    # 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(new_points)
    P.move(points[0, :])

    return P
Ejemplo n.º 2
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