Beispiel #1
0
def test_line_collection_extend_two_lines(lines):
    lc = LineCollection([(3, 3j)])
    lc.extend(lines)
    assert len(lc) == 3
    assert np.all(lc[0] == np.array([3, 3j]))
    assert np.all(lc[1] == np.array([0, 1 + 1j]))
    assert np.all(lc[2] == np.array([2 + 2j, 3 + 3j, 4 + 4j]))
Beispiel #2
0
def test_extend_same_as_init(lines):
    lc1 = LineCollection(lines)
    lc2 = LineCollection()
    lc2.extend(lines)

    assert len(lc1) == len(lc2)
    for l1, l2 in zip(lc1, lc2):
        assert np.all(l1 == l2)
Beispiel #3
0
def lcopy(document, sources, dest, prob: Optional[float]):
    """Copy the content of one or more layer(s) to another layer.

    SOURCES can be a single layer ID, the string 'all' (to copy all non-empty layers,
    or a coma-separated, whitespace-free list of layer IDs.

    DEST can be a layer ID or the string 'new', in which case a new layer with the
    lowest available ID will be created.

    If a layer is both in the source and destination, its content is not duplicated.

    The `--prob` option controls the probability with which each path is copied. With a value
    lower than 1.0, some paths will not be copied to DEST, which may be used to achieve random
    coloring effects.

    Examples:

        Copy layer 1 to a new layer:

            vpype [...] lcopy 1 new [...]  # duplicate layer 1

        Make a new layer with a merged copy of layer 1 and 2:

            vpype [...] lcopy 1,2 new [...]  # make new layer with merged copy of layer 1 and 2

        Add a merged copy of all layers to layer 1. If layer 1 previously had content, this \
content is not duplicated:

            vpype [...] lcopy all 1 [...]
    """

    src_lids = multiple_to_layer_ids(sources, document)
    dest_lid = single_to_layer_id(dest, document)

    if dest_lid in src_lids:
        src_lids.remove(dest_lid)

    lc = LineCollection()
    for lid in src_lids:
        if prob is not None:
            for line in document[lid]:
                if random.random() < prob:
                    lc.append(line)
        else:
            lc.extend(document[lid])

    if len(lc) > 0:
        document.add(lc, dest_lid)

    return document
Beispiel #4
0
def splitall(lines: LineCollection) -> LineCollection:
    """
    Split all paths into their constituent segments.

    This command may be used together with `linemerge` for cases such as densely-connected
    meshes where the latter cannot optimize well enough by itself.

    Note that since some paths (especially curved ones) can be made of a large number of
    segments, this command may significantly increase the processing time of the pipeline.
    """

    new_lines = LineCollection()
    for line in lines:
        new_lines.extend([line[i:i + 2] for i in range(len(line) - 1)])
    return new_lines
Beispiel #5
0
def lcopy(vector_data, sources, dest):
    """Copy the content of one or more layer(s) to another layer.

    SOURCES can be a single layer ID, the string 'all' (to copy all non-empty layers,
    or a coma-separated, whitespace-free list of layer IDs.

    DEST can be a layer ID or the string 'new', in which case a new layer with the
    lowest available ID will be created.

    If a layer is both in the source and destination, its content is not duplicated.

    Examples:

        Copy layer 1 to a new layer:

            vpype [...] lcopy 1 new [...]  # duplicate layer 1

        Make a new layer with a merged copy of layer 1 and 2:

            vpype [...] lcopy 1,2 new [...]  # make new layer with merged copy of layer 1 and 2

        Add a merged copy of all layers to layer 1. If layer 1 previously had content, this
content is not duplicated:

            vpype [...] lcopy all 1 [...]
    """

    src_lids = multiple_to_layer_ids(sources, vector_data)
    dest_lid = single_to_layer_id(dest, vector_data)

    if dest_lid in src_lids:
        src_lids.remove(dest_lid)

    lc = LineCollection()
    for lid in src_lids:
        lc.extend(vector_data[lid])
    vector_data.add(lc, dest_lid)

    return vector_data
def variablewidth(
    filename,
    scale,
    pitch,
    pen_width,
    black_level,
    white_level,
    delete_white,
    outline_alpha,
    invert,
):
    """Documentation todo"""

    # load grayscale image data
    logging.info("variablewidth: loading image")
    orig_img = cv2.imread(filename, cv2.IMREAD_UNCHANGED) / 255.0
    gray_img = np.average(orig_img[:, :, 0:3], axis=2)
    img = cv2.resize(np.array(gray_img, dtype=float), None, fx=scale, fy=scale)
    if invert:
        img = 1.0 - img
    logging.info(
        f"variablewidth: final image size: {img.shape[0]}x{img.shape[1]}")

    # load alpha layer if requested
    alpha_img = None
    if outline_alpha > 0:
        if orig_img.shape[2] == 4:
            alpha_img = orig_img[:, :, 3]
        else:
            logging.warning(
                "variablewidth: outline alpha requested but input image has no alpha layer"
            )

    # create base line work into a MultiLineString
    logging.info("variablewidth: creating line work")
    mls_arr = []
    for j in range(img.shape[0]):
        pixel_line = img[j]
        poly = translate(
            create_hatch_polygon(
                pixel_line,
                pitch=pitch,
                pen_width=pen_width,
                black_level=black_level,
                white_level=white_level,
            ),
            yoff=j * pitch,
        )
        if not poly.is_empty:
            mls_arr.append(fill_polygon(poly, pen_width))
    base_mls = unary_union(mls_arr)

    # deal with white
    if delete_white:
        logging.info("variablewidth: deleting white")
        white_cnt = [
            c * pitch for c in measure.find_contours(img, white_level)
        ]
        white_mask = build_mask(white_cnt)
        base_mls = base_mls.difference(white_mask)

    # generate outline
    additional_mls = []
    if alpha_img is not None:
        logging.info("variablewidth: outlining alpha")
        cnt = [
            c * pitch * scale for c in measure.find_contours(alpha_img, 0.5)
            if len(c) >= 4
        ]
        mask = build_mask(cnt)

        base_mls = base_mls.intersection(mask)

        # we want all boundaries, including possible holes
        bounds_mls = unary_union([mask.boundary] +
                                 [lr for lr in mask.interiors]).simplify(
                                     tolerance=pen_width / 2)
        additional_mls.append(bounds_mls)

        # if multiple
        additional_mls.extend(
            bounds_mls.parallel_offset((i + 1) * pen_width, side)
            for side in ("left", "right") for i in range(outline_alpha - 1))

    lc = LineCollection(base_mls)
    for mls in additional_mls:
        lc.extend(mls)
    return lc
Beispiel #7
0
def _add_to_line_collection(geom: Any, lc: vp.LineCollection) -> None:
    if hasattr(geom, "exterior"):
        lc.append(geom.exterior)
        lc.extend(geom.interiors)
    else:
        lc.append(geom)