Ejemplo n.º 1
0
def shorter_side(paths):
    vector_points = [path.point(0.5) for i, path in enumerate(paths) if i < 4]
    lines = [
        Line(start=vector_points[0], end=vector_points[2]),
        Line(start=vector_points[1], end=vector_points[3])
    ]
    return 1 if lines[0].length() > lines[1].length() else 0
Ejemplo n.º 2
0
def drawcurve(counter, pos, window):
    global cols
    if counter == 1:
        pygame.draw.circle(window, (0, 255, 0), pos[0], 5)
    if counter == 2:
        pygame.draw.line(window, (255, 0, 0), pos[0], pos[1])

    if counter == 3:
        pygame.draw.line(window, (255, 0, 0), pos[0], pos[1])
        pygame.draw.circle(window, (0, 255, 0), pos[2], 5)
    if counter == 0:
        pygame.draw.line(window, (255, 0, 0), pos[0], pos[1])
        pygame.draw.line(window, (255, 0, 0), pos[2], pos[3])
        rect_lol, kosmos1, kosmos2 = LLuk(pos).get_pygame_arc()
        pygame.draw.arc(window, (255, 255, 0), rect_lol, kosmos1, kosmos2)

        srodes.append(srumpy(pos[0]))
        stroke_widths.append(2)
        srodes.append(srumpy(pos[3]))
        stroke_widths.append(2)

        lines.append(Line(srumpy(pos[0]), srumpy(pos[1])))
        lines.append(Line(srumpy(pos[2]), srumpy(pos[3])))
        luck = LLuk(pos)
        lines.append(
            Line(srumpy(luck.additional_line[0]),
                 srumpy(luck.additional_line[1])))
        lines.append(luck.get_svg_arc())
        cols = cols + "kkkk"
def fillSvg(svg_path, svg_d, width=750, height=750):
    p = parse_path(svg_d)

    intersections = []
    for i in range(height, 0, -5):
        newline = Line(complex(0, i), complex(100000, i))
        intersect = p.intersect(newline)
        # print(intersect)
        indiv_sections = []
        if (intersect):
            for (T1, seg1, t1), (T2, seg2, t2) in intersect:
                point = p.point(T1)
                if point:
                    point_tuple = (point.real, point.imag)
                    # print(point_tuple)
                    indiv_sections.append(point_tuple)
            # p.append(newline)

            print(indiv_sections)

            pairs = list(
                zip(indiv_sections, indiv_sections[1:] + indiv_sections[:1]))

            del pairs[1::2]

            for pair in pairs:
                x0 = pair[0][0]
                x1 = pair[1][0]
                y = pair[0][1]
                # print("( "+ x0 + ", " + y + "), (" + x1 + ", " + y + ")")
                betweenLine = Line(complex(x0, y), complex(x1, y))
                p.append(betweenLine)

    disvg(p)
Ejemplo n.º 4
0
def make_continuous(path):
    # takes a discontinuous path (like a donut or a figure 8, and slices it together
    # such that it is continuous
    cont_paths = path.continuous_subpaths()
    paths = cont_paths[0][:]
    for i in range(1, len(cont_paths)):
        start_point = paths[-1].end
        previous_point = paths[0].end
        # find the index of the closest point on the inner circle
        inner_start_index = sorted([(j, abs(path.start - start_point))
                                    for j, path in enumerate(cont_paths)],
                                   key=lambda x: x[1])[0][0]
        next_start_index = sorted([(j, abs(path.start - previous_point))
                                   for j, path in enumerate(cont_paths)
                                   if j != inner_start_index],
                                  key=lambda x: x[1])[0][0]
        paths += [Line(start=start_point, end=cont_paths[i][inner_start_index].start)]
        if next_start_index > inner_start_index:
            paths += cont_paths[i][inner_start_index:] + cont_paths[0:inner_start_index]
        else:
            paths += cont_paths[i][len(
                cont_paths[i]) - inner_start_index:inner_start_index:-1] + cont_paths[
                                                                           inner_start_index::-1]
        paths += [Line(start=cont_paths[-1][inner_start_index].start, end=start_point)]
    return paths
Ejemplo n.º 5
0
 def create_square_shape(cls, w, h):
     return [
         Line(complex(0, 0), complex(0, h)),
         Line(complex(0, h), complex(w, h)),
         Line(complex(w, h), complex(w, 0)),
         Line(complex(w, 0), complex(0, 0)),
     ]
Ejemplo n.º 6
0
def drawcurve(counter, pos, window):
    if counter == 1:
        pygame.draw.circle(window, (0, 255, 0), pos[0], 5)
    if counter == 2:
        line = shapely.geometry.LineString([pos[0], pos[1]])
        pygame.draw.line(window, (255, 0, 0), pos[0], pos[1])

    if counter == 3:
        pygame.draw.line(window, (255, 0, 0), pos[0], pos[1])
        pygame.draw.circle(window, (0, 255, 0), pos[2], 5)
    if counter == 0:
        pygame.draw.line(window, (255, 0, 0), pos[0], pos[1])
        pygame.draw.line(window, (255, 0, 0), pos[2], pos[3])
        rect_lol, kosmos1, kosmos2 = LLuk(pos).get_pygame_arc()
        pygame.draw.arc(window, (255, 255, 0), rect_lol, kosmos1, kosmos2)

        lines.append(Line(srumpy(pos[0]), srumpy(pos[1])))
        lines.append(Line(srumpy(pos[2]), srumpy(pos[3])))
        print(kosmos2 - kosmos1)
        if (is_right_to(kosmos1, kosmos2)):
            lines.append(
                Arc(srumpy(pos[1]), srumpy((intergreat_len, intergreat_len)),
                    0, False, False, srumpy(pos[2])))
        else:
            lines.append(
                Arc(srumpy(pos[1]), srumpy((intergreat_len, intergreat_len)),
                    0, False, True, srumpy(pos[2])))
        srodes.append(srumpy(pos[0]))
        stroke_widths.append(2)
        srodes.append(srumpy(pos[3]))
        stroke_widths.append(2)
        return "kcc"
    return ""
Ejemplo n.º 7
0
    def initialize(self):
        current_grid = defaultdict(dict)
        # simplify paths to lines
        poly_paths = []
        for path in self.paths:
            if path.length() > MINIMUM_STITCH_LENGTH:
                num_segments = ceil(path.length() / MINIMUM_STITCH_LENGTH)
                for seg_i in range(int(num_segments)):
                    poly_paths.append(Line(start=path.point(seg_i/num_segments), end=path.point((seg_i+1)/num_segments)))
            else:
                poly_paths.append(Line(start=path.start, end=path.end))
        bbox = overall_bbox(self.paths)
        curr_x = int(bbox[0]/MINIMUM_STITCH_LENGTH)*MINIMUM_STITCH_LENGTH
        total_tests = int(bbox[1]-bbox[0])*int(bbox[3]-bbox[2])/(MINIMUM_STITCH_LENGTH*MINIMUM_STITCH_LENGTH)
        while curr_x < bbox[1]:
            curr_y = int(bbox[2]/MINIMUM_STITCH_LENGTH)*MINIMUM_STITCH_LENGTH

            while curr_y < bbox[3]:
                test_line = Line(start=curr_x + curr_y * 1j,
                                 end=curr_x + MINIMUM_STITCH_LENGTH + (
                                                               curr_y + MINIMUM_STITCH_LENGTH) * 1j)
                start = time()
                is_contained = path1_is_contained_in_path2(test_line, Path(*poly_paths))
                end = time()
                if is_contained:
                    current_grid[curr_x][curr_y] = False
                curr_y += MINIMUM_STITCH_LENGTH
            curr_x += MINIMUM_STITCH_LENGTH
        self.current_grid = current_grid
Ejemplo n.º 8
0
def test_generate_straight_stroke():
    dig = Digitizer()
    paths = [Path(*[Line(start=0, end=100), Line(start=100, end=100 + 100j),
                    Line(start=100 + 100j, end=100j), Line(start=100j, end=0)])]
    dig.stroke_color = (0, 0, 0)
    dig.scale = 1.0
    dig.generate_straight_stroke(paths)
    assert len(dig.stitches) > len(paths)
Ejemplo n.º 9
0
def test_fill_scan():
    dig = Digitizer()
    dig.fill_color = (0, 0, 0)
    paths = Path(*[Line(start=0, end=100), Line(start=100, end=100+100j),
                   Line(start=100+100j, end=100j), Line(start=100j, end=0)])
    dig.scale = 1.0
    dig.fill = True
    dig.fill_scan(paths)
    assert len(dig.stitches) > 0
Ejemplo n.º 10
0
def test_scan_lines():
    paths = Path(*[
        Line(start=0, end=100),
        Line(start=100, end=100 + 100j),
        Line(start=100 + 100j, end=100j),
        Line(start=100j, end=0)
    ])
    lines = scan_lines(paths)
    assert len(lines) > 0
Ejemplo n.º 11
0
def remove_close_paths(input_paths):
    if len(input_paths) == 1:
        if input_paths[0].length() < MINIMUM_STITCH_LENGTH:
            return []
        else:
            return input_paths

    def snap_angle(p):
        hyp = p.length()
        y_diff = (p.start - p.end).imag
        if hyp == 0.0:
            return pi * sign(y_diff) / 2.0
        elif y_diff / hyp > 1.0:
            return pi / 2.0
        elif y_diff / hyp < -1.0:
            return pi / 2.0
        else:
            return asin(y_diff / hyp)

    paths = [
        path for path in input_paths if path.length() >= MINIMUM_STITCH_LENGTH
    ]
    # remove any paths that are less than the minimum stitch
    while len([True for line in paths if line.length() < MINIMUM_STITCH_LENGTH]) > 0 \
            or len([paths[i] for i in range(1, len(paths)) if
                    paths[i].start != paths[i - 1].end]) > 0:
        paths = [
            path for path in paths if path.length() >= MINIMUM_STITCH_LENGTH
        ]
        paths = [
            Line(start=paths[i].start, end=paths[(i + 1) % len(paths)].start)
            for i in range(0, len(paths))
        ]

        angles = [snap_angle(p) for p in paths]
        straight_lines = []
        current_angle = None
        current_start = None
        j = 0
        while j < len(angles):
            if current_angle is None:
                current_angle = angles[0]
                current_start = paths[j].start
            while abs(current_angle - angles[j % len(paths)]) < 0.01:
                j += 1
            straight_lines.append(
                Line(start=current_start, end=paths[j % len(paths)].start))
            current_angle = angles[j % len(angles)]
            current_start = paths[j % len(paths)].start
        paths = straight_lines
    assert len([
        i for i in range(1, len(paths)) if paths[i].start != paths[i - 1].end
    ]) == 0
    assert len(
        [True for line in paths if line.length() < MINIMUM_STITCH_LENGTH]) == 0
    return paths
Ejemplo n.º 12
0
def test_generate_pattern(fill):
    dig = Digitizer()
    dig.all_paths = [Path(*[Line(start=0, end=100), Line(start=100, end=100+100j),
                            Line(start=100+100j, end=100j), Line(start=100j, end=0)])]
    dig.attributes = [{"fill": "black"}]
    dig.scale = 1.0
    dig.fill = fill
    dig.generate_pattern()
    assert len(dig.pattern.blocks) > 0
    assert len(dig.pattern.blocks[0].stitches) > 0
Ejemplo n.º 13
0
def trace_image(filecontents):
    output = StringIO()
    output.write(filecontents)
    _image = Image.open(output)
    pixels = posturize(_image)
    output_paths = []
    attributes = []
    for color in pixels:
        data = zeros(_image.size, uint32)
        for pixel in pixels[color]:
            data[pixel[0], pixel[1]] = 1
        # Create a bitmap from the array
        bmp = potrace.Bitmap(data)
        # Trace the bitmap to a path
        path = bmp.trace()
        # Iterate over path curves
        for curve in path:
            svg_paths = []
            start_point = curve.start_point
            true_start = curve.start_point
            for segment in curve:
                if true_start is None:
                    true_start = segment.start_point
                if start_point is None:
                    start_point = segment.start_point
                if isinstance(segment, BezierSegment):
                    svg_paths.append(
                        CubicBezier(
                            start=start_point[1] + 1j * start_point[0],
                            control1=segment.c1[1] + segment.c1[0] * 1j,
                            control2=segment.c2[1] + segment.c2[0] * 1j,
                            end=segment.end_point[1] +
                            1j * segment.end_point[0]))
                elif isinstance(segment, CornerSegment):
                    svg_paths.append(
                        Line(start=start_point[1] + 1j * start_point[0],
                             end=segment.c[1] + segment.c[0] * 1j))
                    svg_paths.append(
                        Line(start=segment.c[1] + segment.c[0] * 1j,
                             end=segment.end_point[1] +
                             1j * segment.end_point[0]))
                else:
                    print("not sure what to do with: ", segment)
                start_point = segment.end_point
                # is the path closed?
                if true_start == start_point:
                    output_paths.append(Path(*svg_paths))
                    color = pixel[2]
                    rgb = "#%02x%02x%02x" % (color[0], color[1], color[2])
                    fill = rgb
                    attributes.append({"fill": fill, "stroke": rgb})
                    true_start = None
                    start_point = None
                    svg_paths = []
    return output_paths, attributes
Ejemplo n.º 14
0
def test_stack_paths2():
    blo = Path(*[
        Line(start=0, end=100),
        Line(start=100, end=100 + 100j),
        Line(start=100 + 100j, end=100j),
        Line(start=100j, end=0)
    ])
    all_paths = [blo, blo.translated(110)]
    attributes = [{"fill": "black"}, {"fill": "black"}]

    all_paths_new, attributes_new = stack_paths(all_paths, attributes)
    assert all_paths == all_paths_new
    assert attributes_new == attributes
Ejemplo n.º 15
0
def test_stack_paths():
    all_paths = [
        Path(*[
            Line(start=0, end=100),
            Line(start=100, end=100 + 100j),
            Line(start=100 + 100j, end=100j),
            Line(start=100j, end=0)
        ])
    ]
    attributes = [{"fill": "black"}]

    all_paths_new, attributes_new = stack_paths(all_paths, attributes)
    assert len(all_paths) == len(all_paths_new)
    assert len(attributes_new) == len(attributes)
Ejemplo n.º 16
0
 def closePath(self):
     if self._contour[0].start != self._contour[-1].end:
         self._contour.append(
             Line(self._contour[-1].end, self._contour[0].start))
     self._outline.append(self._contour)
     self._contour = SVGPathContour()
     self.logger.debug("closePath()")
Ejemplo n.º 17
0
def pattern_to_svg(pattern, filename):
    if isinstance(filename, str) or isinstance(filename, unicode):
        output_file = open(filename, "wb")
    else:
        output_file = filename
    paths = []
    colors = []
    scale_factor = 0.1  # scale from cm to mm from pes
    for block in pattern.blocks:
        block_paths = []
        last_stitch = None
        for stitch in block.stitches:
            if "JUMP" in stitch.tags:
                last_stitch = stitch
                continue
            if last_stitch is None:
                last_stitch = stitch
                continue
            block_paths.append(
                Line(start=last_stitch.complex * scale_factor,
                     end=stitch.complex * scale_factor))
            last_stitch = stitch
        if len(block_paths) > 0:
            colors.append(block.tuple_color)
            paths.append(Path(*block_paths))
    dims = overall_bbox(paths)
    mindim = max(dims[1] - dims[0], dims[3] - dims[2])
    print("in pattern to svg, overallbbox", overall_bbox(paths))
    if len(paths) == 0:
        print("warning: pattern did not generate stitches")
        return
    wsvg(paths, colors, filename=output_file, mindim=mindim)
Ejemplo n.º 18
0
def flip_path(upside_down_path):
    path = []
    _, _, min_y, max_y = upside_down_path.bbox()
    offset = max_y + min_y
    for segment in upside_down_path._segments:
        if type(segment) is Line:
            path.append(
                Line(complex(segment.start.real, -segment.start.imag + offset),
                     complex(segment.end.real, -segment.end.imag + offset)))
        elif type(segment) is Arc:
            path.append(
                Arc(complex(segment.start.real,
                            -segment.start.imag + offset), segment.radius,
                    abs(180 - segment.rotation), segment.large_arc,
                    not segment.sweep,
                    complex(segment.end.real, -segment.end.imag + offset)))
        elif type(segment) is QuadraticBezier:
            path.append(
                QuadraticBezier(
                    complex(segment.start.real, -segment.start.imag + offset),
                    complex(segment.control.real,
                            -segment.control.imag + offset),
                    complex(segment.end.real, -segment.end.imag + offset)))
        else:
            raise ValueError(f"Unknown type: {type(segment)}")

    return Path(*path)
Ejemplo n.º 19
0
def shape_to_path(shape):
    new_path = []
    if shape.area > 0.0:
        points = shape.exterior.coords
        # close the path
        new_path.append(Line(start=points[-1][0] + points[-1][1] * 1j,
                             end=points[0][0] + points[0][1] * 1j))
    elif shape.length > 0.0:
        points = shape.coords
    else:
        return []
    for i in range(len(points) - 1):
        new_path.append(Line(start=points[i - 1][0] + points[i - 1][1] * 1j,
                             end=points[i][0] + points[i][1] * 1j))

    return Path(*new_path)
Ejemplo n.º 20
0
def path_union(path1, path2):
    # trace around the outside of two paths to make a union
    # todo: this is pretty tricky to implement and at the moment, this is incomplete
    output_segments = []
    paths = [path1, path2]
    if path1_is_contained_in_path2(path1, path2):
        return path2
    elif path1_is_contained_in_path2(path2, path1):
        return path1
    indexes = [0, 0]
    current_path = 0
    # first, check whether the first segment is within the second path so that we can
    # find the start location. If it is, keep going until you find the first segment that
    #  isn't within the other path
    while path1_is_contained_in_path2(paths[current_path][indexes[current_path]], paths[not current_path]) and indexes[current_path] < len(paths[current_path]):
        indexes[current_path] += 1
    # does the current path intersect the other path?
    intersections = paths[not current_path].intersect(paths[current_path][indexes[current_path]]);
    if len(intersections) > 0:
        # we need to find out whether the start point is within shape 2
        test_line = Line(start=paths[current_path][indexes[current_path]].start, end=paths[current_path][indexes[current_path]].end)
        if path1_is_contained_in_path2(test_line, paths[not current_path]):
            start_point = None
        start_point = None
    else:
        start_point = paths[current_path][indexes[current_path]].start

    return output_segments
Ejemplo n.º 21
0
    def cross_stitch_to_pattern(self, _image):
        # this doesn't work well for images with more than 2-3 colors
        max_dimension = max(_image.size)
        pixel_ratio = int(max_dimension * MINIMUM_STITCH_LENGTH / (4 * 25.4))
        if pixel_ratio != 0:
            _image = _image.resize(
                (_image.size[0] / pixel_ratio, _image.size[1] / pixel_ratio))
        pixels = posturize(_image)

        paths = []
        attrs = []

        for color in pixels:
            for pixel in pixels[color]:
                rgb = "#%02x%02x%02x" % (pixel[2][0], pixel[2][1], pixel[2][2])
                x = pixel[0]
                y = pixel[1]
                attrs.append({"fill": "none", "stroke": rgb})
                paths.append(
                    Path(
                        Line(start=x + 1j * y,
                             end=x + 0.5 * MINIMUM_STITCH_LENGTH + 1j *
                             (y + MINIMUM_STITCH_LENGTH))))
        debug_paths = [[path, attrs[i]["fill"], attrs[i]["stroke"]]
                       for i, path in enumerate(paths)]
        write_debug("png", debug_paths)
        self.all_paths = paths
        self.attributes = attrs
        self.scale = 1.0
        self.generate_pattern()
Ejemplo n.º 22
0
    def transform_side(sides, targets, angle_offset=0):
        def angle(point1, point2):
            diff = point1 - point2
            if diff.real == 0:
                return 90.0
            return atan(diff.imag / diff.real) * 180.0 / pi

        # change this so that it has two targets
        transformed_side = Path(*sides)
        source_angle = angle(transformed_side.end, transformed_side.start) - \
                       angle(targets[0], targets[1])
        transformed_side = transformed_side.rotated(-source_angle +
                                                    angle_offset)
        source = transformed_side.end if angle_offset == 0 else transformed_side.start
        diff = targets[1] - source
        transformed_side = transformed_side.translated(diff)
        draw_marker(targets[0], rgb(0, 200, 200))
        draw_marker(targets[1], rgb(0, 255, 255))
        transformed_diff = abs(transformed_side.start - transformed_side.end)
        targets_diff = abs(targets[0] - targets[1])
        if transformed_diff < targets_diff:
            transformed_side.insert(
                0, Line(start=targets[0], end=transformed_side.start))
        elif transformed_diff > targets_diff:
            # pop elements off until the transformed diff is smaller
            while transformed_diff > targets_diff:
                transformed_side.pop(0)
                transformed_diff = abs(transformed_side.start -
                                       transformed_side.end)
            print("path", transformed_side)
            print("path is longer", transformed_diff - targets_diff)
        return transformed_side
Ejemplo n.º 23
0
def test_jump_reduction():
    paths = []
    rect_width = 100
    rect_height = rect_width / 2
    for i in range(3):
        y_offset = rect_width*i*1j
        corners = [rect_height, rect_width+rect_height,
                   rect_width+rect_height + rect_height*1j,
                   rect_height*1j+ rect_height]
        corners = [c+y_offset for c in corners]
        lines = [Line(start=corners[j], end=corners[(j+1) % len(corners)])
                 for j in range(len(corners))]
        _path = Path(*lines)
        _path = _path.rotated(i*20)
        paths += list(_path)

    max_y = max([p.start.imag for p in paths]+[p.end.imag for p in paths])
    max_x = max([p.start.real for p in paths]+[p.end.real for p in paths])
    filename = "test_jump_reduction.svg"
    viewbox = [0, -rect_height, max_x+2*rect_height, max_y+2*rect_height]
    dwg = Drawing(filename, width="10cm",
                  viewBox=" ".join([str(b) for b in viewbox]))
    dwg.add(dwg.path(d=Path(*paths).d()))
    dwg.save()
    dig = Digitizer()
    dig.filecontents = open(filename, "r").read()
    dig.svg_to_pattern()
    pattern_to_svg(dig.pattern, join(filename + ".svg"))
Ejemplo n.º 24
0
    def snap(self, tree, threshold):
        def process(points):
            for i, p in enumerate(points):
                best, _, dist = tree.nearest_neighbor([p.real, p.imag])

                if dist < threshold:
                    points[i] = complex(best[0], best[1])
            return points

        path = parse_path(self['d'])
        newPath = Path()
        for seg in path:
            points = process([seg.start, seg.end])

            if isinstance(seg, Line):
                newSeg = Line(*points)
                newPath.append(newSeg)

            elif isinstance(seg, CubicBezier):
                newSeg = CubicBezier(points[0], seg.control1, seg.control2,
                                     points[1])
                newPath.append(newSeg)

        self['d'] = newPath.d()
        return self
Ejemplo n.º 25
0
def getIntersectionPathFromBox(infLine, left, right, top, bottom):
    # Intersect the line with all the sides of the box and
    #  take the two points inside the box.
    # This will always be on the top and bottom
    # or on the left and right sides.
    p1 = complex(left, infLine.y_for_x(left))
    p2 = complex(right, infLine.y_for_x(right))
    l1 = Line(start=p1, end=p2)

    p3 = complex(infLine.x_for_y(top), top)
    p4 = complex(infLine.x_for_y(bottom), bottom)
    l2 = Line(start=p3, end=p4)

    if l1.length() < l2.length():
        return l2
    else:
        return l1
Ejemplo n.º 26
0
 def __init__(self, **kwargs):
     byA_FrozenClass.__init__(self)
     self._from = kwargs.get('P1')
     self._to = kwargs.get('P2')
     assert isinstance(self._from, byA_Point)
     assert isinstance(self._to, byA_Point)
     self._svgline = Line(self._from.toRI(), self._to.toRI())
     self._freeze("byA_Line")
Ejemplo n.º 27
0
    def connect_pins(self, c1, p1, c2, p2, **kwargs):
        start_pin = self.board_component_pin_location(c1, p1)
        end_pin = self.board_component_pin_location(c2, p2)

        self.add_route([
            Line(complex(start_pin[0], start_pin[1]),
                 complex(end_pin[0], end_pin[1]))
        ], **kwargs)
Ejemplo n.º 28
0
def generateInBetweens(poseA, poseB, steps):
    inv = Inventory()

    # make pairs
    pairs = []
    for key in ORDER:
        if key in poseA.inv and key in poseB.inv:
            partA = poseA.inv[key]
            partB = poseB.inv[key]

            if len(partA) != 1 or len(partB) != 1:
                print('Too many parts {0} - A: {1} B: {2}'.format(
                    key, partA.keys(), partB.keys()))
                continue

            pairs.append((key, partA.values()[0], partB.values()[0]))

    # If there are 3 steps, there are 4 gaps between start and finish
    # |------1------2------3------|
    gaps = steps + 1

    # process pairs
    for key, a, b in pairs:
        pathA = parse_path(a['d'])
        pathB = parse_path(b['d'])

        if len(pathA) != len(pathB):
            print('Unmatched segments {0} - A: {1} B: {2}'.format(
                key, pathA, pathB))
            continue

        for step in range(1, gaps):
            newPath = Path()
            for i in range(len(pathA)):
                segA = pathA[i]
                segB = pathB[i]

                if isinstance(segA, Line):
                    points = _deltaPoints([segA.start, segA.end],
                                          [segB.start, segB.end], step, gaps)
                    newPath.append(Line(*points))

                elif isinstance(segA, CubicBezier):
                    points = _deltaPoints(
                        [segA.start, segA.control1, segA.control2, segA.end],
                        [segB.start, segB.control1, segB.control2, segB.end],
                        step, gaps)
                    newPath.append(CubicBezier(*points))

            newPart = Part(newPath.d())
            newPart['x'] = int(_delta(a['x'], b['x'], step, gaps))
            newPart['y'] = int(_delta(a['y'], b['y'], step, gaps))
            newPart['z'] = int(_delta(a['z'], b['z'], step, gaps))

            inv.addPart(key, newPart)
            print(key, step, newPart)

    return inv
Ejemplo n.º 29
0
def offset_curve(path, offset_distance, steps=1000):
    """Takes in a Path object, `path`, and a distance,
    `offset_distance`, and outputs an piecewise-linear approximation
    of the 'parallel' offset curve."""
    nls = []
    for seg in path:
        for k in range(steps):
            t = k / float(steps)
            offset_vector = offset_distance * seg.normal(t)
            nl = Line(seg.point(t), seg.point(t) + offset_vector)
            nls.append(nl)
    connect_the_dots = [
        Line(nls[k].end, nls[k + 1].end) for k in range(len(nls) - 1)
    ]
    if path.isclosed():
        connect_the_dots.append(Line(nls[-1].end, nls[0].end))
    offset_path = Path(*connect_the_dots)
    return offset_path
Ejemplo n.º 30
0
 def lineTo(self, pt):
     # an old bug in fontTools.ttLib.tables._g_l_y_f.Glyph.draw()
     # can cause this to be called w/ a zero-length line.
     if pt != self._lastOnCurve:
         self._contour.append(
             Line(self.convertPoint(self._lastOnCurve),
                  self.convertPoint(pt)))
         self.logger.debug(f"lineTo({pt})")
         self._lastOnCurve = pt