Exemplo n.º 1
0
 def event(self,
           window_pos=None,
           space_pos=None,
           event_type=None,
           nearest_snap=None):
     response = RESPONSE_CHAIN
     if event_type == "leftclick":
         if nearest_snap is None:
             self.point_series.append((space_pos[0], space_pos[1]))
         else:
             self.point_series.append((nearest_snap[0], nearest_snap[1]))
         self.scene.tool_active = True
         response = RESPONSE_CONSUME
     elif event_type == "rightdown":
         self.scene.tool_active = False
         self.point_series = []
         self.mouse_position = None
         self.scene.request_refresh()
         response = RESPONSE_ABORT
     elif event_type == "leftdown":
         self.scene.tool_active = True
         if nearest_snap is None:
             self.mouse_position = space_pos[0], space_pos[1]
         else:
             self.mouse_position = nearest_snap[0], nearest_snap[1]
         if self.point_series:
             self.scene.request_refresh()
         response = RESPONSE_CONSUME
     elif event_type in ("leftup", "move", "hover"):
         if nearest_snap is None:
             self.mouse_position = space_pos[0], space_pos[1]
         else:
             self.mouse_position = nearest_snap[0], nearest_snap[1]
         if self.point_series:
             self.scene.request_refresh()
             response = RESPONSE_CONSUME
     elif event_type == "doubleclick":
         polyline = Polygon(*self.point_series,
                            stroke="blue",
                            stroke_width=1000)
         elements = self.scene.context.elements
         node = elements.elem_branch.add(shape=polyline,
                                         type="elem polyline")
         if not self.scene.context.elements.default_stroke is None:
             node.stroke = self.scene.context.elements.default_stroke
         if not self.scene.context.elements.default_fill is None:
             node.fill = self.scene.context.elements.default_fill
         if elements.classify_new:
             elements.classify([node])
         self.scene.tool_active = False
         self.point_series = []
         self.mouse_position = None
         self.notify_created(node)
         response = RESPONSE_CONSUME
     elif event_type == "lost":
         self.scene.tool_active = False
         self.point_series = []
         self.mouse_position = None
     return response
Exemplo n.º 2
0
 def as_path(self):
     image_width, image_height = self.active_image.size
     matrix = self.active_matrix
     x0, y0 = matrix.point_in_matrix_space((0, 0))
     x1, y1 = matrix.point_in_matrix_space((0, image_height))
     x2, y2 = matrix.point_in_matrix_space((image_width, image_height))
     x3, y3 = matrix.point_in_matrix_space((image_width, 0))
     return abs(Path(Polygon((x0,y0), (x1,y1), (x2,y2), (x3,y3), (x0,y0))))
Exemplo n.º 3
0
 def vectrace(data, **kwargs):
     elements = kernel.root.elements
     path = Path(fill="black", stroke="blue")
     paths = []
     for node in data:
         matrix = node.matrix
         image = node.image
         width, height = node.image.size
         if image.mode != "L":
             image = image.convert("L")
         image = image.point(lambda e: int(e > 127) * 255)
         for points in _vectrace(image.load(), width, height):
             path += Polygon(*points)
         paths.append(
             elements.elem_branch.add(path=path,
                                      matrix=Matrix(matrix),
                                      type="elem path"))
     return "elements", paths
Exemplo n.º 4
0
 def as_cutobjects(self, closed_distance=15, passes=1):
     """Generator of cutobjects for a particular operation."""
     settings = self.derive()
     for node in self.children:
         if node.type == "reference":
             node = node.node
         if node.type == "elem image":
             object_path = node.image
             box = object_path.bbox()
             path = Path(
                 Polygon(
                     (box[0], box[1]),
                     (box[0], box[3]),
                     (box[2], box[3]),
                     (box[2], box[1]),
                 ))
         elif node.type == "elem path":
             path = abs(node.path)
             path.approximate_arcs_with_cubics()
         else:
             path = abs(Path(node.shape))
             path.approximate_arcs_with_cubics()
         settings["line_color"] = path.stroke
         for subpath in path.as_subpaths():
             sp = Path(subpath)
             if len(sp) == 0:
                 continue
             closed = (
                 isinstance(sp[-1], Close)
                 or abs(sp.z_point - sp.current_point) <= closed_distance)
             group = CutGroup(
                 None,
                 closed=closed,
                 settings=settings,
                 passes=passes,
             )
             group.path = Path(subpath)
             group.original_op = self.type
             for seg in subpath:
                 if isinstance(seg, Move):
                     pass  # Move operations are ignored.
                 elif isinstance(seg, Close):
                     if seg.start != seg.end:
                         group.append(
                             LineCut(
                                 seg.start,
                                 seg.end,
                                 settings=settings,
                                 passes=passes,
                                 parent=group,
                             ))
                 elif isinstance(seg, Line):
                     if seg.start != seg.end:
                         group.append(
                             LineCut(
                                 seg.start,
                                 seg.end,
                                 settings=settings,
                                 passes=passes,
                                 parent=group,
                             ))
                 elif isinstance(seg, QuadraticBezier):
                     group.append(
                         QuadCut(
                             seg.start,
                             seg.control,
                             seg.end,
                             settings=settings,
                             passes=passes,
                             parent=group,
                         ))
                 elif isinstance(seg, CubicBezier):
                     group.append(
                         CubicCut(
                             seg.start,
                             seg.control1,
                             seg.control2,
                             seg.end,
                             settings=settings,
                             passes=passes,
                             parent=group,
                         ))
             if len(group) > 0:
                 group[0].first = True
             for i, cut_obj in enumerate(group):
                 cut_obj.closed = closed
                 try:
                     cut_obj.next = group[i + 1]
                 except IndexError:
                     cut_obj.last = True
                     cut_obj.next = group[0]
                 cut_obj.previous = group[i - 1]
             yield group
Exemplo n.º 5
0
        def cag(command, channel, _, data=None, **kwargs):
            import numpy as np

            if len(data) < 2:
                channel(
                    _("Not enough items selected to apply constructive geometric function"
                      ))
                return "elements", []

            if command == "intersection":
                ct = ClipType.Intersection
            elif command == "xor":
                ct = ClipType.Xor
            elif command == "union":
                ct = ClipType.Union
            else:  # difference
                ct = ClipType.Difference
            solution_path = Path(stroke=context.elements.default_stroke,
                                 fill=context.elements.default_fill,
                                 stroke_width=1000)
            last_polygon = None
            node = None
            for i in range(len(data)):
                node = data[i]
                try:
                    path = node.as_path()
                except AttributeError:
                    return "elements", data

                current_polygon = []
                for subpath in path.as_subpaths():
                    subj = Path(subpath).npoint(np.linspace(0, 1, 1000))
                    subj.reshape((2, 1000))
                    s = list(map(Point, subj))
                    current_polygon.append(s)

                if last_polygon is not None:
                    pc = Clipper()
                    solution = []
                    pc.AddPolygons(last_polygon, PolyType.Subject)
                    pc.AddPolygons(current_polygon, PolyType.Clip)
                    result = pc.Execute(ct, solution, PolyFillType.EvenOdd,
                                        PolyFillType.EvenOdd)
                    current_polygon = solution
                last_polygon = current_polygon

            for se in last_polygon:
                r = Polygon(*se)
                if solution_path is None:
                    solution_path = Path(r)
                else:
                    solution_path += Path(r)
            if solution_path:
                if node is None:
                    new_node = context.elements.elem_branch.add(
                        path=solution_path,
                        type="elem path",
                    )
                else:
                    new_node = context.elements.elem_branch.add(
                        path=solution_path,
                        type="elem path",
                        stroke=node.stroke if node is not None else None,
                        fill=node.fill if node is not None else None,
                        stroke_width=node.stroke_width
                        if node is not None else None,
                    )
                context.signal("refresh_scene", "Scene")
                context.elements.classify([new_node])
                return "elements", [node]
            else:
                return "elements", []
Exemplo n.º 6
0
    def as_cutobjects(self, closed_distance=15, passes=1):
        """
        Generator of cutobjects for a raster operation. This takes any image node children
        and converts them into rastercut objects. These objects should have already been converted
        from vector shapes.

        The preference for raster shapes is to use the settings set on this operation rather than on the image-node.
        """
        settings = self.derive()

        # Set overscan
        overscan = self.overscan
        if not isinstance(overscan, float):
            overscan = float(Length(overscan))
        settings["overscan"] = overscan

        # Set steps
        step_x = self.raster_step_x
        step_y = self.raster_step_y
        assert step_x != 0
        assert step_y != 0
        settings["raster_step_x"] = step_x
        settings["raster_step_x"] = step_y

        # Set variables by direction
        direction = self.raster_direction
        horizontal = False
        start_on_left = False
        start_on_top = False
        if direction == 0 or direction == 4:
            horizontal = True
            start_on_top = True
        elif direction == 1:
            horizontal = True
            start_on_top = False
        elif direction == 2:
            horizontal = False
            start_on_left = False
        elif direction == 3:
            horizontal = False
            start_on_left = True
        bidirectional = bool(self.raster_swing)

        for image_node in self.children:
            # Process each child. Some core settings are the same for each child.

            if image_node.type != "elem image":
                continue

            # Perform correct actualization
            image_node.step_x = step_x
            image_node.step_y = step_y
            image_node.process_image()

            # Set variables
            matrix = image_node.matrix
            pil_image = image_node.image
            offset_x = matrix.value_trans_x()
            offset_y = matrix.value_trans_y()

            # Establish path
            min_x = offset_x
            min_y = offset_y
            max_x = offset_x + pil_image.width * step_x
            max_y = offset_y + pil_image.height * step_y
            path = Path(
                Polygon(
                    (min_x, min_y),
                    (min_x, max_y),
                    (max_x, max_y),
                    (max_x, min_y),
                ))

            # Create Cut Object
            cut = RasterCut(
                image=pil_image,
                offset_x=offset_x,
                offset_y=offset_y,
                step_x=step_x,
                step_y=step_y,
                inverted=False,
                bidirectional=bidirectional,
                horizontal=horizontal,
                start_on_top=start_on_top,
                start_on_left=start_on_left,
                overscan=overscan,
                settings=settings,
                passes=passes,
            )
            cut.path = path
            cut.original_op = self.type
            yield cut
            if direction == 4:
                # Create optional crosshatch cut
                horizontal = False
                start_on_left = False
                cut = RasterCut(
                    image=pil_image,
                    offset_x=offset_x,
                    offset_y=offset_y,
                    step_x=step_x,
                    step_y=step_y,
                    inverted=False,
                    bidirectional=bidirectional,
                    horizontal=horizontal,
                    start_on_top=start_on_top,
                    start_on_left=start_on_left,
                    overscan=overscan,
                    settings=settings,
                    passes=passes,
                )
                cut.path = path
                cut.original_op = self.type
                yield cut
Exemplo n.º 7
0
    def as_cutobjects(self, closed_distance=15, passes=1):
        """
        Generator of cutobjects for the image operation. This takes any image node children
        and converts them into rastercut cutobjects.
        """
        for image_node in self.children:
            # Process each child. All settings are different for each child.

            if image_node.type != "elem image":
                continue
            settings = self.derive()

            # Set overscan
            overscan = self.overscan
            if not isinstance(overscan, float):
                overscan = float(Length(overscan))

            # Set variables by direction
            if image_node.direction is not None:
                direction = image_node.direction
            else:
                direction = self.raster_direction
            horizontal = False
            start_on_left = False
            start_on_top = False
            if direction == 0 or direction == 4:
                horizontal = True
                start_on_top = True
            elif direction == 1:
                horizontal = True
                start_on_top = False
            elif direction == 2:
                horizontal = False
                start_on_left = False
            elif direction == 3:
                horizontal = False
                start_on_left = True
            bidirectional = bool(self.raster_swing)

            # Get steps from individual images
            step_x = image_node.step_x
            step_y = image_node.step_y

            settings["raster_step_x"] = step_x
            settings["raster_step_x"] = step_y

            # Set variables
            matrix = image_node.active_matrix
            pil_image = image_node.active_image
            offset_x = matrix.value_trans_x()
            offset_y = matrix.value_trans_y()

            # Establish path
            min_x = offset_x
            min_y = offset_y
            max_x = offset_x + pil_image.width * step_x
            max_y = offset_y + pil_image.height * step_y
            path = Path(
                Polygon(
                    (min_x, min_y),
                    (min_x, max_y),
                    (max_x, max_y),
                    (max_x, min_y),
                )
            )

            # Create Cut Object
            cut = RasterCut(
                image=pil_image,
                offset_x=offset_x,
                offset_y=offset_y,
                step_x=step_x,
                step_y=step_y,
                inverted=False,
                bidirectional=bidirectional,
                horizontal=horizontal,
                start_on_top=start_on_top,
                start_on_left=start_on_left,
                overscan=overscan,
                settings=settings,
                passes=passes,
            )
            cut.path = path
            cut.original_op = self.type
            yield cut
            if direction == 4:
                # Create optional crosshatch cut
                horizontal = False
                start_on_left = False
                cut = RasterCut(
                    image=pil_image,
                    offset_x=offset_x,
                    offset_y=offset_y,
                    step_x=step_x,
                    step_y=step_y,
                    inverted=False,
                    bidirectional=bidirectional,
                    horizontal=horizontal,
                    start_on_top=start_on_top,
                    start_on_left=start_on_left,
                    overscan=overscan,
                    settings=settings,
                    passes=passes,
                )
                cut.path = path
                cut.original_op = self.type
                yield cut