Exemple #1
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 ""
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)
Exemple #3
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
Exemple #4
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"
Exemple #5
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
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
 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)),
     ]
Exemple #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)
Exemple #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
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
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
Exemple #12
0
 def __init__(self, **kwargs):
     """Constructor
     """
     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._svgpathtools = Line(self._from.toRI(), self._to.toRI())
     self._freeze("byA_Line")
Exemple #13
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
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
Exemple #15
0
 def allcond(_t):
     from andysSVGpathTools import segUnitTangent
     tt = max(0, min(1, _t.real))
     lin2pt = Line(seg.point(tt), pt)
     real_cond = isclose(_t.imag, 0)
     bezier_cond = (0 < _t.real < 1 or
                    isclose(_t.real, 0) or
                    isclose(_t.real, 1))
     nondeg_cond = (not isclose(seg.derivative(tt), 0) or 
                    isclose(dot_prod(segUnitTangent(seg, tt), lin2pt.unit_tangent()), 0))
     outward_cond = dot_prod(lin2pt.unit_tangent(), -1j*segUnitTangent(seg, tt)) > 0
     
     return real_cond and bezier_cond and nondeg_cond and outward_cond
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
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)
Exemple #18
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"))
Exemple #19
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()")
Exemple #20
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
Exemple #21
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)
Exemple #22
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)
Exemple #23
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
    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()
Exemple #25
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)
Exemple #26
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
Exemple #27
0
class byA_Line(byA_FrozenClass):
    def __init__(self, **kwargs):
        """Constructor
        """
        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._svgpathtools = Line(self._from.toRI(), self._to.toRI())
        self._freeze("byA_Line")

    def toRI(self):
        """Point as a complex
        """
        return complex(self._from.toRI()), complex(self._to.toRI())

    def toSVGWrite(self, drawing, **extra):
        """to the svgwrite syntax
        """
        return drawing.path(d=self.toStr(), **extra)

    def toStr(self):
        return Path(self._svgpathtools).d()

    def reverse(self):
        return byA_Line(P1=self._to, P2=self._from)

    def rotate(self, degre, origin=None):
        self._svgpathtools = self._svgpathtools.rotated(degre, origin)
        self._from.rotate(degre, origin)
        self._to.rotate(degre, origin)

    def rotated(self, degre, origin=None):
        res = byA_Line(P1=self._from, P2=self._to)
        res.rotate(degre, origin)
        return res

    def coeffDir(self):
        assert (self._to._x != self._from._x)
        return (self._to._y - self._from._y) / (self._to._x - self._from._x)

    def equationLine(self):
        assert (self._to._x != self._from._x)
        # y = ax+b
        # src._y = a*src._x + b
        # dst._y = a*dst._x + b
        a = self.coeffDir()
        return [a, self._from._y - a * self._from._x]

    def split(self, t):
        p = self._from + t * (self._to - self._from)
        return (byA_Line(P1=self._from, P2=p), byA_Line(P1=p, P2=self._to))

    def lenght(self):
        """to the svgwrite syntax
        """
        return sqrt((self._from.toRI().real - self._to.toRI().real)**2 +
                    (self._from.toRI().imag - self._to.toRI().imag)**2)
Exemple #28
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")
    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)
Exemple #30
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
Exemple #31
0
def displaySVGPaths_transects(ring_list, data_transects, transect_angles, skipped_angle_indices, fn=None):
    if not fn:
        filename = opt.output_directory + ring_list[0].svgname
    else:
        filename = fn

    transectPaths = []
    for tran_index in range(len(data_transects)):
        tran_path = Path()
        for seg_index in range(len(data_transects[tran_index]) - 1):
            start_pt = data_transects[tran_index][seg_index]
            end_pt = data_transects[tran_index][seg_index + 1]
            tran_path.append(Line(start_pt,end_pt))
        transectPaths.append(tran_path)

    ringPaths = [r.path for r in ring_list]
    ringColors = [r.color for r in ring_list]
    pathList = ringPaths + transectPaths
    colors = ringColors + ['black']*len(transectPaths)
    transect_nodes = [item for sublist in data_transects for item in sublist] # flatten data_transects
    nodes = transect_nodes + [ring_list[0].center]
    node_colors = ['purple']*len(transect_nodes) + ['blue']
    text = ['%.3f' % theta for idx, theta in enumerate(transect_angles)
            if idx not in skipped_angle_indices]
    text += ['skipped %.3f' % transect_angles[idx]
             for idx in skipped_angle_indices]
    text_path = []
    for tr in data_transects:
        end = tr[-1]
        last_seg = Line(tr[-2], tr[-1])
        u = last_seg.unit_tangent(1)
        text_path.append(Path(Line(end + 10*u, end + 100*u)))

    # handle skipped transects
    bdry_ring = max(ring_list, key=lambda ring: ring.maxR)
    bdry_length = bdry_ring.path.length()
    for idx in skipped_angle_indices:
        s = bdry_length * transect_angles[idx]
        T = inv_arclength(bdry_ring.path,  s)
        u = bdry_ring.path.normal(T)
        end = bdry_ring.path.point(T)
        text_path.append(Line(end + 10*u, end + 100*u))

    wsvg(pathList, colors, nodes=nodes, node_colors=node_colors, text=text,
         text_path=text_path, filename=filename+'_transects.svg')
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
Exemple #33
0
def generate_unsorted_transects(ring_list, center):
    from options4rings import basic_output_on, warnings_output_on, N_transects, unsorted_transect_debug_output_folder, unsorted_transect_debug_on, colordict
    from misc4rings import transect_from_angle, normalLineAt_t_toInnerSeg_intersects_withOuter
    from andysSVGpathTools import pathlistXlineIntersections
    from andysmod import Timer
    import operator
    from random import uniform

    #Find outer boundary ring
    for r in ring_list:
        if r.color == colordict['boundary']:
            boundary_ring = r
            break
    else:
        warnings_output_on.dprint("[Warning:] Having trouble finding outer boundary - it should be color %s.  Will now search for a ring of a similar color and if one is found, will use that.\n"%colordict['boundary'])
        from misc4rings import closestColor
        for r in ring_list:
            if colordict['boundary'] == closestColor(r.color,colordict):
                boundary_ring = r
                basic_output_on.dprint("Found a ring of color %s, using that one."%r.color)
                break
        else:
            warnings_output_on.dprint("[Warning:] Outer boundary could not be found by color (or similar color).  This is possibly caused by the outer boundary ring not being closed - in this case you'd be able to see a (possibly quite small) gap between it's startpoint and endpoint. Using the ring of greatest maximum radius as the boundary ring (and hoping if there is a gap none of the transects hit it).\n")
            keyfcn = lambda x: x.maxR
            boundary_ring = max(ring_list,key=keyfcn)

    #Find transects
    from time import time as current_time
    from andysmod import format_time
    tr_gen_start_time = current_time()
    data = []
    data_indices = []
    angles = []
    for dummy_index in range(N_transects): #dummy_index only used to create loop
        #estimate time remaining
        if dummy_index != 0:
            total_elapsed_time = current_time() - tr_gen_start_time
            estimated_time_remaining = (N_transects - dummy_index)*total_elapsed_time/dummy_index
            timer_str = 'Transect %s of %s || Est. Remaining Time = %s || Elapsed Time = %s'%(dummy_index+1,N_transects,format_time(estimated_time_remaining),format_time(total_elapsed_time))
            overwrite_progress = True
        else:
            timer_str = 'transect %s of %s'%(dummy_index+1,N_transects)
            overwrite_progress = False
            print('')

        #generate current transect
        with Timer(timer_str, overwrite=overwrite_progress):
            if unsorted_transect_debug_on:
                print('')
            test_angle = uniform(0, 1)
#                        test_angle = 0.408
            angles.append(test_angle)
            transect = [center]
            transect_rings = ['core']
            unused_ring_indices = range(len(ring_list)) #used to keep track of which rings I've used and thus don't need to be checked in the future

            # Find first transect segment (from core/center)
            # normal line to use to find intersections (from center to boundary ring)
            nl2bdry, seg_outer, t_outer = transect_from_angle(test_angle, center, boundary_ring.path, 'debug')
            #make normal line a little longer
            nl2bdry = Line(nl2bdry.start, nl2bdry.start + 1.5*(nl2bdry.end-nl2bdry.start))
            tmp = pathlistXlineIntersections(nl2bdry, [ring_list[i].path for i in unused_ring_indices])
            (tl,path_index,seg,tp) = min(tmp, key=operator.itemgetter(0)) #(tl,path_index,seg,tp)

            transect.append(nl2bdry.point(tl))
            transect_rings.append(unused_ring_indices[path_index])
            del unused_ring_indices[path_index]

            #now for the rest of the transect
            num_rings_checked = 0
            while (ring_list[transect_rings[-1]] != boundary_ring and 
                   num_rings_checked < len(ring_list)):  # < is correct, already did first
                num_rings_checked += 1
                inner_path = ring_list[transect_rings[-1]].path
                inner_t = tp
                inner_seg = seg
                
                # normal line to use to find intersections (from center to boundary ring)
                nl2bdry, seg_outer, t_outer = normalLineAt_t_toInnerSeg_intersects_withOuter(inner_t, inner_seg, boundary_ring.path, center, 'debug') 
                # make normal line a little longer
                nl2bdry = Line(nl2bdry.start,nl2bdry.start + 1.5*(nl2bdry.end-nl2bdry.start)) 
                
                normal_line_intersections = pathlistXlineIntersections(nl2bdry, [ring_list[i].path for i in unused_ring_indices])
                try:
                    # (tl,path_index,seg,tp)
                    tl, path_index, seg, tp = min(normal_line_intersections,
                                                  key=operator.itemgetter(0))
                except ValueError:
                    raise
                if unsorted_transect_debug_on:
                    from andysmod import format001
                    inner_path_index = transect_rings[-1]
                    used_ring_paths = [r.path for i,r in enumerate(ring_list) if i not in unused_ring_indices+[inner_path_index]]
                    used_ring_colors = ['black']*len(used_ring_paths)
                    unused_ring_paths = [ring_list[i].path for i in unused_ring_indices]
                    unused_ring_colors = [ring_list[i].color for i in unused_ring_indices]
                    transect_so_far = Path(*[Line(transect[i-1],transect[i]) for i in range(1,len(transect))])
                    paths = used_ring_paths + unused_ring_paths + [transect_so_far] +[inner_path] + [nl2bdry]
                    colors = used_ring_colors + unused_ring_colors + ['green']+['blue'] + ['black']

                    nodes_so_far = transect[1:-1]
                    potential_nodes = [nl2bdry.point(tltmp) for (tltmp,path_indextmp,segtmp,tptmp) in normal_line_intersections]
                    nodes = nodes_so_far + potential_nodes
                    node_colors = ['red']*len(nodes_so_far) + ['purple']*len(potential_nodes)
                    save_name = unsorted_transect_debug_output_folder+'unsorted_transect_debug_%s.svg'%format001(3,len(transect))
                    disvg(paths,colors,nodes=nodes,node_colors=node_colors,center=center,filename=save_name,openInBrowser=False)
                    print("Done with %s out of (at most) %s transect segments"%(len(transect),len(ring_list)))
                transect.append(nl2bdry.point(tl))
                transect_rings.append(unused_ring_indices[path_index])
                del unused_ring_indices[path_index]
            data.append(transect)
            data_indices.append(transect_rings)
    return data, data_indices, angles
Exemple #34
0
def generate_sorted_transects(ring_list, center, angles2use=None):
    from options4rings import basic_output_on, N_transects
    from misc4rings import transect_from_angle, normalLineAt_t_toInnerSeg_intersects_withOuter
    from andysSVGpathTools import pathlistXlineIntersections
    from andysmod import Timer, format_time
    from svgpathtools import Line
    from random import uniform
    from time import time as current_time
    from operator import itemgetter

    tmp = sorted(enumerate(ring_list), key = lambda tup: tup[1].sort_index)
    ring_sorting, sorted_ring_list = zip(*tmp)
    unsorted_index = lambda idx: ring_sorting[idx]

    #Find transects

    tr_gen_start_time = current_time()
    data = []
    data_indices = []
    angles = []
    for dummy_index in range(N_transects):
        #estimate time remaining
        if dummy_index != 0:
            total_elapsed_time = current_time() - tr_gen_start_time
            estimated_time_remaining = (N_transects - dummy_index)*total_elapsed_time/dummy_index
            timer_str = 'Transect %s of %s || Est. Remaining Time = %s || Elapsed Time = %s'%(dummy_index+1,N_transects,format_time(estimated_time_remaining),format_time(total_elapsed_time))
            overwrite_progress = True
        else:
            timer_str = 'transect %s of %s'%(dummy_index+1,N_transects)
            overwrite_progress = False
            print('')

        #generate current transect
        with Timer(timer_str,overwrite=overwrite_progress):
#            sorted_closed_rings = (r for r in sorted_ring_list if r.isClosed())
            if angles2use:
                test_angle = angles2use[dummy_index]
            else:
                test_angle = uniform(0,1)
#                        test_angle = 0.408
            angles.append(test_angle)
            transect = [center]
            transect_rings = ['core']
            
            # find first (innermost) closed ring
#            next_closed_ring = sorted_closed_rings.next()
            next_closed_ring = next(r for r in sorted_ring_list if r.isClosed())
            next_closed_ring_sidx = next_closed_ring.sort_index

            #Find first transect segment (from core/center)
            # Start by finding line that leaves center at angle and goes to 
            # the first closed ring
            nl2bdry, seg_outer, t_outer = transect_from_angle(test_angle, center, next_closed_ring.path, 'debug') 
            # Make normal line a little longer
            end2use = nl2bdry.start + 1.5*(nl2bdry.end - nl2bdry.start)
            nl2bdry = Line(nl2bdry.start, end2use) 
            pot_paths = [r.path for r in sorted_ring_list[0:next_closed_ring_sidx + 1]]
                
            #Note: intersections returned as (tl, path_index, seg, tp)
            pot_path_inters = pathlistXlineIntersections(nl2bdry, pot_paths) 
            tl, path_index, seg, tp = min(pot_path_inters, key=itemgetter(0))

            #updates
            transect.append(nl2bdry.point(tl))
            transect_rings.append(unsorted_index(path_index))
            cur_pos_si = path_index
            next_closed_ring = next(r for r in sorted_ring_list 
                                       if (r.sort_index > cur_pos_si and 
                                           r.isClosed()))
#            next_closed_ring = sorted_closed_rings.next()
            next_closed_ring_sidx = next_closed_ring.sort_index

            #now for the rest of the transects
            num_rings_checked = 0
            while (cur_pos_si < len(ring_list) - 1 and 
                   num_rings_checked < len(ring_list)):  # < is correct, already did first
                num_rings_checked += 1
                inner_t = tp
                inner_seg = seg
                
                # Find outwards normal line from current position to the next 
                # closed ring
                nl2bdry, seg_outer, t_outer = normalLineAt_t_toInnerSeg_intersects_withOuter(inner_t, inner_seg, next_closed_ring.path, center, 'debug') 
                # Make the normal line a bit longer to avoid numerical error
                end2use = nl2bdry.start + 1.5*(nl2bdry.end - nl2bdry.start)
                nl2bdry = Line(nl2bdry.start, end2use)

                pot_paths = [r.path for r in sorted_ring_list[cur_pos_si+1:next_closed_ring_sidx+1]]
                tl, path_index, seg, tp = min(pathlistXlineIntersections(nl2bdry,pot_paths), key=itemgetter(0))

                #updates
                transect.append(nl2bdry.point(tl))
                cur_pos_si += path_index + 1
                transect_rings.append(unsorted_index(cur_pos_si))
                if cur_pos_si < len(ring_list)-1:
#                    next_closed_ring = sorted_closed_rings.next()
                    next_closed_ring = next(r for r in sorted_ring_list 
                                               if (r.sort_index > cur_pos_si and 
                                                   r.isClosed()))
                    next_closed_ring_sidx = next_closed_ring.sort_index

            data.append(transect)
            data_indices.append(transect_rings)
    return data, data_indices, angles