Пример #1
0
 def validate(self):
     if self.point is None:
         self.point = Point(
             float(self.settings.get("x", 0)), float(self.settings.get("y", 0))
         )
     if self.matrix is None:
         self.matrix = Matrix()
Пример #2
0
    def tick(self):
        if self.last_position is None:
            return
        friction = 0.05
        attraction = 500
        vx = self.velocity[0] * (1 - friction)
        vy = self.velocity[1] * (1 - friction)
        angle = Point.angle(self.last_position, self.track_object)
        vx -= attraction * math.cos(angle)
        vy -= attraction * math.sin(angle)

        self.velocity[0] = vx
        self.velocity[1] = vy
        self.track_object[0] += vx
        self.track_object[1] += vy
        self.pos += 1
        if self.pos & 2:
            self.series.append((self.last_position[0], self.last_position[1]))
        else:
            self.series.append((self.track_object[0], self.track_object[1]))
        self.scene.request_refresh()
        if self.stop:
            return False
        return (abs(self.last_position[0] - self.track_object[0]) > 1000
                or abs(self.last_position[1] - self.track_object[1]) > 1000)
Пример #3
0
    def test_plotplanner_constant_xy_end(self):
        """
        With raster_smooth set to 1 we should smooth the x axis so that no y=0 occurs.
        @return:
        """
        for q in range(100):
            settings = {
                "power": 1000,
                "constant_move_x": bool(random.randint(0, 1)),
                "constant_move_y": bool(random.randint(0, 1)),
            }
            plan = PlotPlanner(settings)
            goal_x = None
            goal_y = None
            for i in range(10):
                goal_x = random.randint(0, 100)
                goal_y = random.randint(0, 100)
                plan.push(
                    LineCut(
                        Point(random.randint(0, 100), random.randint(0, 100)),
                        Point(goal_x, goal_y),
                        settings=settings,
                    ))
            break_list = list(plan.queue)
            last_x = None
            last_y = None
            for x, y, on in plan.gen():
                if on == 4:
                    last_x = x
                    last_y = y
                if on > 1:
                    continue
                last_x = x
                last_y = y

            if last_x != goal_x:
                print(settings.get("constant_move_x"))
                print(settings.get("constant_move_y"))
                for seg in break_list:
                    print(repr(seg))
            self.assertEqual(last_x, goal_x)
            if last_y != goal_y:
                print(settings.get("constant_move_x"))
                print(settings.get("constant_move_y"))
                for seg in break_list:
                    print(repr(seg))
            self.assertEqual(last_y, goal_y)
Пример #4
0
 def test_plotplanner_constant_move_xy(self):
     """
     With raster_smooth set to 1 we should smooth the x axis so that no y=0 occurs.
     @return:
     """
     settings = {
         "power": 1000,
         "constant_move_x": True,
         "constant_move_y": True
     }
     plan = PlotPlanner(settings)
     self.constant_move_x = True
     self.constant_move_y = True
     for i in range(100):
         plan.push(
             LineCut(
                 Point(random.randint(0, 1000), random.randint(0, 1000)),
                 Point(random.randint(0, 1000), random.randint(0, 1000)),
                 settings=settings,
             ))
     last_x = None
     last_y = None
     for x, y, on in plan.gen():
         if on == 4:
             last_x = x
             last_y = y
         if on > 1:
             continue
         cx = x
         cy = y
         if cx is None:
             continue
         if last_x is not None:
             total_dx = cx - last_x
             total_dy = cy - last_y
             dx = 1 if total_dx > 0 else 0 if total_dx == 0 else -1
             dy = 1 if total_dy > 0 else 0 if total_dy == 0 else -1
             for i in range(1, max(abs(total_dx), abs(total_dy)) + 1):
                 nx = last_x + (i * dx)
                 ny = last_y + (i * dy)
                 # print(nx, ny, on)
         # print(x, y, on)
         last_x = cx
         last_y = cy
         print(f"Moving to {x} {y}")
Пример #5
0
    def test_plotplanner_static_issue(self):
        settings = {
            "power": 1000,
            "constant_move_x": True,
            "constant_move_y": False,
        }
        plan = PlotPlanner(settings)
        plan.debug = True
        lines = (
            ((41, 45), (14, 43)),
            ((32, 67), (32, 61)),
        )
        for line in lines:
            plan.push(
                LineCut(
                    Point(line[0][0], line[0][1]),
                    Point(line[1][0], line[1][1]),
                    settings=settings,
                ))
        goal_x = lines[-1][-1][0]
        goal_y = lines[-1][-1][1]
        break_list = list(plan.queue)
        last_x = None
        last_y = None
        for x, y, on in plan.gen():
            if on == 4:
                last_x = x
                last_y = y
            if on > 1:
                continue
            last_x = x
            last_y = y

        if last_x != goal_x:
            for seg in break_list:
                print(repr(seg))
        self.assertEqual(last_x, goal_x)
        if last_y != goal_y:
            for seg in break_list:
                print(repr(seg))
        self.assertEqual(last_y, goal_y)
Пример #6
0
    def test_plotplanner_flush(self):
        """
        Intro test for plotplanner.

        This is needlessly complex.

        final value is "on", and provides commands.
        128 means settings were changed.
        64 indicates x_axis major
        32 indicates x_dir, y_dir
        256 indicates ended.
        1 means cut.
        0 means move.

        :return:
        """
        settings = {"power": 1000}
        plan = PlotPlanner(settings)

        for i in range(211):
            plan.push(LineCut(Point(0, 0), Point(5, 100), settings=settings))
            plan.push(LineCut(Point(100, 50), Point(0, 0), settings=settings))
            plan.push(
                LineCut(Point(50, -50),
                        Point(100, -100),
                        settings={"power": 0}))
            q = 0
            for x, y, on in plan.gen():
                # print(x, y, on)
                if q == i:
                    # for x, y, on in plan.process_plots(None):
                    # print("FLUSH!", x, y, on)
                    plan.clear()
                    break
                q += 1
Пример #7
0
    def test_cutcode(self):
        """
        Test intro to Cutcode.

        :return:
        """
        cutcode = CutCode()
        settings = dict()
        cutcode.append(LineCut(Point(0, 0), Point(100, 100), settings=settings))
        cutcode.append(LineCut(Point(100, 100), Point(0, 0), settings=settings))
        cutcode.append(LineCut(Point(50, -50), Point(100, -100), settings=settings))
        cutcode.append(
            QuadCut(Point(0, 0), Point(100, 100), Point(200, 0), settings=settings)
        )
        path = Path(*list(cutcode.as_elements()))
        self.assertEqual(
            path, "M 0,0 L 100,100 L 0,0 M 50,-50 L 100,-100 M 0,0 Q 100,100 200,0"
        )
Пример #8
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:
             point = Point(space_pos[0], space_pos[1])
         else:
             point = Point(nearest_snap[0], nearest_snap[1])
         elements = self.scene.context.elements
         node = elements.elem_branch.add(point=point,
                                         matrix=Matrix(),
                                         type="elem point")
         if self.scene.context.elements.default_stroke is not None:
             node.stroke = self.scene.context.elements.default_stroke
         if self.scene.context.elements.default_fill is not None:
             node.fill = self.scene.context.elements.default_fill
         if elements.classify_new:
             elements.classify([node])
         self.notify_created(node)
         response = RESPONSE_CONSUME
     return response
Пример #9
0
    def find_hit_chain(self, position):
        """
        Processes the hittable_elements list and find which elements are hit at a given position.

        This gives the actual hits with regard to the position of the event.
        """
        self.hit_chain.clear()
        for current_widget, current_matrix in self.hittable_elements:
            try:
                hit_point = Point(
                    current_matrix.point_in_inverse_space(position))
            except ZeroDivisionError:
                current_matrix.reset()
                # Some object is zero matrixed, reset it.
                return
            if current_widget.contains(hit_point.x, hit_point.y):
                self.hit_chain.append((current_widget, current_matrix))
Пример #10
0
 def test_plotplanner_constant_move_x_ppi(self):
     """
     With raster_smooth set to 1 we should smooth the x axis so that no y=0 occurs.
     @return:
     """
     settings = {"power": 500, "constant_move_x": True}
     plan = PlotPlanner(settings)
     plan.push(LineCut(Point(0, 0), Point(20, 2), settings=settings))
     plan.push(LineCut(Point(20, 2), Point(20, 5), settings=settings))
     plan.push(LineCut(Point(20, 5), Point(100, 10), settings=settings))
     last_x = None
     last_y = None
     last_on = None
     for x, y, on in plan.gen():
         if on == 4:
             last_x = x
             last_y = y
         if on > 1:
             continue
         if last_on is not None:
             self.assertNotEqual(last_on, on)
         last_on = on
         cx = x
         cy = y
         if cx is None:
             continue
         if last_x is not None:
             total_dx = cx - last_x
             total_dy = cy - last_y
             dx = 1 if total_dx > 0 else 0 if total_dx == 0 else -1
             dy = 1 if total_dy > 0 else 0 if total_dy == 0 else -1
             self.assertFalse(dx == 0)
             for i in range(1, max(abs(total_dx), abs(total_dy)) + 1):
                 nx = last_x + (i * dx)
                 ny = last_y + (i * dy)
                 # print(nx, ny, on)
         # print(x, y, on)
         last_x = cx
         last_y = cy
Пример #11
0
    def test_plotplanner_constant_move_y(self):
        """
        With smooth_raster set to 2 we should never have x = 0. The x should *always* be in motion.
        @return:
        """
        settings = {"power": 1000, "constant_move_y": True}
        plan = PlotPlanner(settings)
        plan.push(LineCut(Point(0, 0), Point(2, 20), settings=settings))
        plan.push(LineCut(Point(2, 20), Point(5, 20), settings=settings))
        plan.push(LineCut(Point(5, 20), Point(10, 100), settings=settings))
        last_x = None
        last_y = None
        for x, y, on in plan.gen():
            if on == 4:
                last_x = x
                last_y = y
            if on > 1:
                continue
            cx = x
            cy = y
            if cx is None:
                continue
            if last_x is not None:
                total_dx = cx - last_x
                total_dy = cy - last_y
                dx = 1 if total_dx > 0 else 0 if total_dx == 0 else -1
                dy = 1 if total_dy > 0 else 0 if total_dy == 0 else -1
                self.assertFalse(dy == 0)
                for i in range(0, max(abs(total_dx), abs(total_dy))):
                    nx = last_x + (i * dx)
                    ny = last_y + (i * dy)
                    # print(nx, ny, on)

            last_x = cx
            last_y = cy
            print(f"Moving to {x} {y}")
Пример #12
0
 def add_point(self, point):
     if len(self.series):
         last = self.series[-1]
         if Point.distance(last, point) < self.preferred_length:
             return
     self.series.append(point)
Пример #13
0
 def __init__(self, x, y=None):
     Point.__init__(self, x, y)
     self.connections = []
     self.visited = 0
     self.value = None
Пример #14
0
    def plot_arc(arc):
        """
        Plots an arc by converting it into a series of cubic Bézier curves and plotting those instead.

        @param arc:
        @return:
        """
        # TODO: Should actually plot the arc according to the pixel-perfect standard.
        # TODO: In this case we would plot a Bernstein weighted bezier curve.
        sweep_limit = tau / 12
        arc_required = int(ceil(abs(arc.sweep) / sweep_limit))
        if arc_required == 0:
            return
        slice = arc.sweep / float(arc_required)

        theta = arc.get_rotation()
        rx = arc.rx
        ry = arc.ry
        p_start = arc.start
        current_t = arc.get_start_t()
        x0 = arc.center[0]
        y0 = arc.center[1]
        cos_theta = cos(theta)
        sin_theta = sin(theta)

        for i in range(0, arc_required):
            next_t = current_t + slice

            alpha = sin(slice) * (sqrt(4 + 3 * pow(tan(slice / 2.0), 2)) -
                                  1) / 3.0

            cos_start_t = cos(current_t)
            sin_start_t = sin(current_t)

            ePrimen1x = -rx * cos_theta * sin_start_t - ry * sin_theta * cos_start_t
            ePrimen1y = -rx * sin_theta * sin_start_t + ry * cos_theta * cos_start_t

            cos_end_t = cos(next_t)
            sin_end_t = sin(next_t)

            p2En2x = x0 + rx * cos_end_t * cos_theta - ry * sin_end_t * sin_theta
            p2En2y = y0 + rx * cos_end_t * sin_theta + ry * sin_end_t * cos_theta
            p_end = (p2En2x, p2En2y)
            if i == arc_required - 1:
                p_end = arc.end

            ePrimen2x = -rx * cos_theta * sin_end_t - ry * sin_theta * cos_end_t
            ePrimen2y = -rx * sin_theta * sin_end_t + ry * cos_theta * cos_end_t

            p_c1 = (p_start[0] + alpha * ePrimen1x,
                    p_start[1] + alpha * ePrimen1y)
            p_c2 = (p_end[0] - alpha * ePrimen2x, p_end[1] - alpha * ePrimen2y)

            for value in ZinglPlotter.plot_cubic_bezier(
                    p_start[0],
                    p_start[1],
                    p_c1[0],
                    p_c1[1],
                    p_c2[0],
                    p_c2[1],
                    p_end[0],
                    p_end[1],
            ):
                yield value
            p_start = Point(p_end)
            current_t = next_t