예제 #1
0
 def test_intersectConvexHull(self, data):
     p1 = Polygon(numpy.array(data["p1"]))
     p2 = Polygon(numpy.array(data["p2"]))
     result = p1.intersectionConvexHulls(p2)
     assert len(result.getPoints()) == len(
         data["answer"])  #Same amount of vertices.
     isCorrect = False
     for rotation in range(
             0, len(result.getPoints())
     ):  #The order of vertices doesn't matter, so rotate the result around and if any check succeeds, the answer is correct.
         thisCorrect = True  #Is this rotation correct?
         for vertex in range(0, len(result.getPoints())):
             for dimension in range(0, len(result.getPoints()[vertex])):
                 if not Float.fuzzyCompare(
                         result.getPoints()[vertex][dimension],
                         data["answer"][vertex][dimension]):
                     thisCorrect = False
                     break  #Break out of two loops.
             if not thisCorrect:
                 break
         if thisCorrect:  #All vertices checked and it's still correct.
             isCorrect = True
             break
         result.setPoints(
             numpy.roll(result.getPoints(), 1,
                        axis=0))  #Perform the rotation for the next check.
     assert isCorrect
예제 #2
0
    def _getHeadAndFans(self) -> Polygon:
        if not self._global_stack:
            return Polygon()

        polygon = Polygon(numpy.array(self._global_stack.getHeadAndFansCoordinates(), numpy.float32))
        offset_x = self._getSettingProperty("machine_nozzle_offset_x", "value")
        offset_y = self._getSettingProperty("machine_nozzle_offset_y", "value")
        return polygon.translate(-offset_x, -offset_y)
예제 #3
0
    def test_translate(self):
        polygon = Polygon(
            numpy.array([[0.0, 0.0], [2.0, 0.0], [1.0, 2.0]], numpy.float32))
        translated_poly = polygon.translate(2, 3)

        result = Polygon(
            numpy.array([[2.0, 3.0], [4.0, 3.0], [3.0, 5.0]], numpy.float32))
        assert result == translated_poly
예제 #4
0
    def run(self):
        if not self._node:
            return
        ## If the scene node is a group, use the hull of the children to calculate its hull.
        if self._node.callDecoration("isGroup"):
            hull = Polygon(numpy.zeros((0, 2), dtype=numpy.int32))
            for child in self._node.getChildren():
                child_hull = child.callDecoration("getConvexHull") 
                if child_hull:
                    hull.setPoints(numpy.append(hull.getPoints(), child_hull.getPoints(), axis = 0))

                if hull.getPoints().size < 3:
                    self._node.callDecoration("setConvexHull", None)
                    self._node.callDecoration("setConvexHullJob", None)
                    return

                Job.yieldThread()

        else: 
            if not self._node.getMeshData():
                return
            mesh = self._node.getMeshData()
            vertex_data = mesh.getTransformed(self._node.getWorldTransformation()).getVertices()
            # Don't use data below 0. TODO; We need a better check for this as this gives poor results for meshes with long edges.
            vertex_data = vertex_data[vertex_data[:,1]>0]
            hull = Polygon(numpy.rint(vertex_data[:, [0, 2]]).astype(int))

        # First, calculate the normal convex hull around the points
        hull = hull.getConvexHull()

        # Then, do a Minkowski hull with a simple 1x1 quad to outset and round the normal convex hull.
        # This is done because of rounding errors.
        hull = hull.getMinkowskiHull(Polygon(numpy.array([[-1, -1], [-1, 1], [1, 1], [1, -1]], numpy.float32)))

        profile = Application.getInstance().getMachineManager().getActiveProfile()
        if profile:
            if profile.getSettingValue("print_sequence") == "one_at_a_time" and not self._node.getParent().callDecoration("isGroup"):
                # Printing one at a time and it's not an object in a group
                self._node.callDecoration("setConvexHullBoundary", copy.deepcopy(hull))
                head_hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_with_fans_polygon"),numpy.float32)))
                self._node.callDecoration("setConvexHullHead", head_hull)
                hull = hull.getMinkowskiHull(Polygon(numpy.array(profile.getSettingValue("machine_head_polygon"),numpy.float32)))
            else:
                self._node.callDecoration("setConvexHullHead", None)
        hull_node = ConvexHullNode.ConvexHullNode(self._node, hull, Application.getInstance().getController().getScene().getRoot())
        self._node.callDecoration("setConvexHullNode", hull_node)
        self._node.callDecoration("setConvexHull", hull)
        self._node.callDecoration("setConvexHullJob", None)

        if self._node.getParent().callDecoration("isGroup"):
            job = self._node.getParent().callDecoration("getConvexHullJob")
            if job:
                job.cancel()
            self._node.getParent().callDecoration("setConvexHull", None)
            hull_node = self._node.getParent().callDecoration("getConvexHullNode")
            if hull_node:
                hull_node.setParent(None)
예제 #5
0
 def verifyIntersection(self, p1, p2, required_result):
     for n in range(0, 4):
         for m in range(0, 4):
             result = p1.intersectsPolygon(p2)
             self.assertEqual(result, required_result)
             p2 = Polygon(
                 numpy.concatenate(
                     (p2.getPoints()[1:], p2.getPoints()[0:1])))
         p1 = Polygon(
             numpy.concatenate((p1.getPoints()[1:], p1.getPoints()[0:1])))
예제 #6
0
    def _add2DAdhesionMargin(self, poly):
        # Compensate for raft/skirt/brim
        # Add extra margin depending on adhesion type
        adhesion_type = self._global_stack.getProperty("adhesion_type", "value")
        extra_margin = 0
        machine_head_coords = numpy.array(
            self._global_stack.getProperty("machine_head_with_fans_polygon", "value"),
            numpy.float32)
        head_y_size = abs(machine_head_coords).min()  # safe margin to take off in all directions

        if adhesion_type == "raft":
            extra_margin = max(0, self._global_stack.getProperty("raft_margin", "value") - head_y_size)
        elif adhesion_type == "brim":
            extra_margin = max(0, self._global_stack.getProperty("brim_width", "value") - head_y_size)
        elif adhesion_type == "skirt":
            extra_margin = max(
                0, self._global_stack.getProperty("skirt_gap", "value") +
                   self._global_stack.getProperty("skirt_line_count", "value") * self._global_stack.getProperty("skirt_brim_line_width", "value") -
                   head_y_size)
        # adjust head_and_fans with extra margin
        if extra_margin > 0:
            # In Cura 2.2+, there is a function to create this circle-like polygon.
            extra_margin_polygon = Polygon(numpy.array([
                [-extra_margin, 0],
                [-extra_margin * 0.707, extra_margin * 0.707],
                [0, extra_margin],
                [extra_margin * 0.707, extra_margin * 0.707],
                [extra_margin, 0],
                [extra_margin * 0.707, -extra_margin * 0.707],
                [0, -extra_margin],
                [-extra_margin * 0.707, -extra_margin * 0.707]
            ], numpy.float32))

            poly = poly.getMinkowskiHull(extra_margin_polygon)
        return poly
예제 #7
0
    def fromNode(cls, node, min_offset, scale=1):
        transform = node._transformation
        transform_x = transform._data[0][3]
        transform_y = transform._data[2][3]

        arrange_align = Preferences.getInstance().getValue(
            "mesh/arrange_align")
        if arrange_align:
            bb = node.getBoundingBox()
            bb_points = numpy.array(
                [[bb.right, bb.back], [bb.left, bb.back], [bb.left, bb.front],
                 [bb.right, bb.front]],
                dtype=numpy.float32)
            polygon = Polygon(bb_points)
        else:
            hull_verts = node.callDecoration("getConvexHull")
            # If a model is too small then it will not contain any points
            if hull_verts is None or not hull_verts.getPoints().any():
                return None, None
                # For one_at_a_time printing you need the convex hull head.
            polygon = node.callDecoration("getConvexHullHead") or hull_verts

        offset_verts = polygon.getMinkowskiHull(
            Polygon.approximatedCircle(min_offset))
        offset_points = copy.deepcopy(offset_verts._points)  # x, y
        offset_points[:, 0] = numpy.add(offset_points[:, 0], -transform_x)
        offset_points[:, 1] = numpy.add(offset_points[:, 1], -transform_y)
        offset_shape_arr = ShapeArray.fromPolygon(offset_points, scale=scale)

        hull_points = copy.deepcopy(polygon._points)
        hull_points[:, 0] = numpy.add(hull_points[:, 0], -transform_x)
        hull_points[:, 1] = numpy.add(hull_points[:, 1], -transform_y)
        hull_shape_arr = ShapeArray.fromPolygon(hull_points, scale=scale)

        return offset_shape_arr, hull_shape_arr
예제 #8
0
    def _onActiveMachineChanged(self):
        machine = self.getActiveMachine()
        if machine:
            Preferences.getInstance().setValue("cura/active_machine",
                                               machine.getName())

            self._volume.setWidth(
                machine.getSettingValueByKey("machine_width"))
            self._volume.setHeight(
                machine.getSettingValueByKey("machine_height"))
            self._volume.setDepth(
                machine.getSettingValueByKey("machine_depth"))

            disallowed_areas = machine.getSettingValueByKey(
                "machine_disallowed_areas")
            areas = []
            if disallowed_areas:
                for area in disallowed_areas:
                    areas.append(Polygon(numpy.array(area, numpy.float32)))

            self._volume.setDisallowedAreas(areas)

            self._volume.rebuild()

            offset = machine.getSettingValueByKey("machine_platform_offset")
            if offset:
                self._platform.setPosition(
                    Vector(offset[0], offset[1], offset[2]))
            else:
                self._platform.setPosition(Vector(0.0, 0.0, 0.0))
예제 #9
0
    def _add2DAdhesionMargin(self, poly: Polygon) -> Polygon:
        if not self._global_stack:
            return Polygon()
        # Compensate for raft/skirt/brim
        # Add extra margin depending on adhesion type
        adhesion_type = self._global_stack.getProperty("adhesion_type",
                                                       "value")

        if adhesion_type == "raft":
            extra_margin = max(
                0, self._getSettingProperty("raft_margin", "value"))
        elif adhesion_type == "brim":
            extra_margin = max(
                0,
                self._getSettingProperty("brim_line_count", "value") *
                self._getSettingProperty("skirt_brim_line_width", "value"))
        elif adhesion_type == "none":
            extra_margin = 0
        elif adhesion_type == "skirt":
            extra_margin = max(
                0,
                self._getSettingProperty("skirt_gap", "value") +
                self._getSettingProperty("skirt_line_count", "value") *
                self._getSettingProperty("skirt_brim_line_width", "value"))
        else:
            raise Exception(
                "Unknown bed adhesion type. Did you forget to update the convex hull calculations for your new bed adhesion type?"
            )

        # Adjust head_and_fans with extra margin
        if extra_margin > 0:
            extra_margin_polygon = Polygon.approximatedCircle(extra_margin)
            poly = poly.getMinkowskiHull(extra_margin_polygon)
        return poly
예제 #10
0
def test_compute2DConvexHullNoMeshData(convex_hull_decorator):
    node = SceneNode()
    with patch("UM.Application.Application.getInstance",
               MagicMock(return_value=mocked_application)):
        convex_hull_decorator.setNode(node)

    assert convex_hull_decorator._compute2DConvexHull() == Polygon([])
예제 #11
0
    def _computeDisallowedAreasPrinted(self, used_extruders):
        result = {}
        for extruder in used_extruders:
            result[extruder.getId()] = []

        #Currently, the only normally printed object is the prime tower.
        if ExtruderManager.getInstance().getResolveOrValue("prime_tower_enable") == True:
            prime_tower_size = self._global_container_stack.getProperty("prime_tower_size", "value")
            machine_width = self._global_container_stack.getProperty("machine_width", "value")
            machine_depth = self._global_container_stack.getProperty("machine_depth", "value")
            prime_tower_x = self._global_container_stack.getProperty("prime_tower_position_x", "value")
            prime_tower_y = - self._global_container_stack.getProperty("prime_tower_position_y", "value")
            if not self._global_container_stack.getProperty("machine_center_is_zero", "value"):
                prime_tower_x = prime_tower_x - machine_width / 2 #Offset by half machine_width and _depth to put the origin in the front-left.
                prime_tower_y = prime_tower_y + machine_depth / 2

            prime_tower_area = Polygon([
                [prime_tower_x - prime_tower_size, prime_tower_y - prime_tower_size],
                [prime_tower_x, prime_tower_y - prime_tower_size],
                [prime_tower_x, prime_tower_y],
                [prime_tower_x - prime_tower_size, prime_tower_y],
            ])
            prime_tower_area = prime_tower_area.getMinkowskiHull(Polygon.approximatedCircle(0))
            for extruder in used_extruders:
                result[extruder.getId()].append(prime_tower_area) #The prime tower location is the same for each extruder, regardless of offset.

        return result
예제 #12
0
    def _offsetHull(self, convex_hull: Polygon) -> Polygon:
        """Offset the convex hull with settings that influence the collision area.

        :param convex_hull: Polygon of the original convex hull.
        :return: New Polygon instance that is offset with everything that
        influences the collision area.
        """

        horizontal_expansion = max(
            self._getSettingProperty("xy_offset", "value"),
            self._getSettingProperty("xy_offset_layer_0", "value"))

        mold_width = 0
        if self._getSettingProperty("mold_enabled", "value"):
            mold_width = self._getSettingProperty("mold_width", "value")
        hull_offset = horizontal_expansion + mold_width
        if hull_offset > 0:  #TODO: Implement Minkowski subtraction for if the offset < 0.
            expansion_polygon = Polygon(
                numpy.array(
                    [[-hull_offset, -hull_offset], [-hull_offset, hull_offset],
                     [hull_offset, hull_offset], [hull_offset, -hull_offset]],
                    numpy.float32))
            return convex_hull.getMinkowskiHull(expansion_polygon)
        else:
            return convex_hull
예제 #13
0
    def getConvexHull(self):
        if self._node is None:
            return None

        if getattr(self._node, "_non_printing_mesh", False):
            # infill_mesh, cutting_mesh and anti_overhang_mesh do not need a convex hull
            # node._non_printing_mesh is set in SettingOverrideDecorator
            return None

        hull = self._compute2DConvexHull()

        if self._global_stack and self._node:
            # Parent can be None if node is just loaded.
            if self._global_stack.getProperty(
                    "print_sequence", "value") == "one_at_a_time" and (
                        self._node.getParent() is None or
                        not self._node.getParent().callDecoration("isGroup")):
                hull = hull.getMinkowskiHull(
                    Polygon(
                        numpy.array(
                            self._global_stack.getProperty(
                                "machine_head_polygon", "value"),
                            numpy.float32)))
                hull = self._add2DAdhesionMargin(hull)
        return hull
예제 #14
0
    def test_intersectsPolygon(self):
        p1 = Polygon(
            numpy.array([[0, 0], [10, 0], [10, 10], [0, 10]], numpy.float32))

        p2 = Polygon(
            numpy.array([[5, 0], [15, 0], [15, 10], [5, 10]], numpy.float32))
        self.verifyIntersection(p1, p2, (-5.0, 0.0))

        p2 = Polygon(
            numpy.array([[-5, 0], [5, 0], [5, 10], [-5, 10]], numpy.float32))
        self.verifyIntersection(p1, p2, (5.0, 0.0))

        p2 = Polygon(
            numpy.array([[0, 5], [10, 5], [10, 15], [0, 15]], numpy.float32))
        self.verifyIntersection(p1, p2, (0.0, -5.0))

        p2 = Polygon(
            numpy.array([[0, -5], [10, -5], [10, 5], [0, 5]], numpy.float32))
        self.verifyIntersection(p1, p2, (0.0, 5.0))

        p2 = Polygon(
            numpy.array([[5, 5], [15, -5], [30, 5], [15, 15]], numpy.float32))
        self.verifyIntersection(p1, p2, (-5.0, 0.0))

        p2 = Polygon(
            numpy.array([[15, 0], [25, 0], [25, 10], [15, 10]], numpy.float32))
        self.verifyIntersection(p1, p2, None)
예제 #15
0
 def _offsetHull(self, convex_hull):
     horizontal_expansion = max(0.5, self._getSettingProperty("xy_offset", "value"))
     expansion_polygon = Polygon(numpy.array([
         [-horizontal_expansion, -horizontal_expansion],
         [-horizontal_expansion, horizontal_expansion],
         [horizontal_expansion, horizontal_expansion],
         [horizontal_expansion, -horizontal_expansion]
     ], numpy.float32))
     return convex_hull.getMinkowskiHull(expansion_polygon)
예제 #16
0
    def run(self):
        if not self._node or not self._node.getMeshData():
            return

        mesh = self._node.getMeshData()
        vertexData = mesh.getTransformed(self._node.getWorldTransformation()).getVertices()

        hull = Polygon(numpy.rint(vertexData[:, [0, 2]]).astype(int))

        # First, calculate the normal convex hull around the points
        hull = hull.getConvexHull()
        # Then, do a Minkowski hull with a simple 1x1 quad to outset and round the normal convex hull.
        hull = hull.getMinkowskiHull(Polygon(numpy.array([[-1, -1], [-1, 1], [1, 1], [1, -1]], numpy.float32)))

        hull_node = ConvexHullNode.ConvexHullNode(self._node, hull, Application.getInstance().getController().getScene().getRoot())

        self._node._convex_hull = hull
        delattr(self._node, "_convex_hull_job")
예제 #17
0
 def test_mirror(self, data):
     polygon = Polygon(numpy.array(data["points"], numpy.float32)) #Create a polygon with the specified points.
     polygon.mirror(data["axis_point"], data["axis_direction"]) #Mirror over the specified axis.
     points = polygon.getPoints()
     assert len(points) == len(data["points"]) #Must have the same amount of vertices.
     for point_index in range(len(points)):
         assert len(points[point_index]) == len(data["answer"][point_index]) #Same dimensionality (2).
         for dimension in range(len(points[point_index])):
             assert Float.fuzzyCompare(points[point_index][dimension], data["answer"][point_index][dimension]) #All points must be equal.
예제 #18
0
    def fromNode(
        cls,
        node: "SceneNode",
        min_offset: float,
        scale: float = 0.5,
        include_children: bool = False
    ) -> Tuple[Optional["ShapeArray"], Optional["ShapeArray"]]:
        """Instantiate an offset and hull ShapeArray from a scene node.

        :param node: source node where the convex hull must be present
        :param min_offset: offset for the offset ShapeArray
        :param scale: scale the coordinates
        :return: A tuple containing an offset and hull shape array
        """

        transform = node._transformation
        transform_x = transform._data[0][3]
        transform_y = transform._data[2][3]
        hull_verts = node.callDecoration("getConvexHull")
        # If a model is too small then it will not contain any points
        if hull_verts is None or not hull_verts.getPoints().any():
            return None, None
        # For one_at_a_time printing you need the convex hull head.
        hull_head_verts = node.callDecoration(
            "getConvexHullHead") or hull_verts
        if hull_head_verts is None:
            hull_head_verts = Polygon()

        # If the child-nodes are included, adjust convex hulls as well:
        if include_children:
            children = node.getAllChildren()
            if not children is None:
                for child in children:
                    # 'Inefficient' combination of convex hulls through known code rather than mess it up:
                    child_hull = child.callDecoration("getConvexHull")
                    if not child_hull is None:
                        hull_verts = hull_verts.unionConvexHulls(child_hull)
                    child_hull_head = child.callDecoration(
                        "getConvexHullHead") or child_hull
                    if not child_hull_head is None:
                        hull_head_verts = hull_head_verts.unionConvexHulls(
                            child_hull_head)

        offset_verts = hull_head_verts.getMinkowskiHull(
            Polygon.approximatedCircle(min_offset))
        offset_points = copy.deepcopy(offset_verts._points)  # x, y
        offset_points[:, 0] = numpy.add(offset_points[:, 0], -transform_x)
        offset_points[:, 1] = numpy.add(offset_points[:, 1], -transform_y)
        offset_shape_arr = ShapeArray.fromPolygon(offset_points, scale=scale)

        hull_points = copy.deepcopy(hull_verts._points)
        hull_points[:, 0] = numpy.add(hull_points[:, 0], -transform_x)
        hull_points[:, 1] = numpy.add(hull_points[:, 1], -transform_y)
        hull_shape_arr = ShapeArray.fromPolygon(hull_points,
                                                scale=scale)  # x, y

        return offset_shape_arr, hull_shape_arr
예제 #19
0
def test_parts_of_fromNode2():
    from UM.Math.Polygon import Polygon
    p = Polygon(numpy.array([[-2, -2], [2, -2], [2, 2], [-2, 2]], dtype=numpy.int32) * 2)  # 4x4
    offset = 13.3
    scale = 0.5
    p_offset = p.getMinkowskiHull(Polygon.approximatedCircle(offset))
    shape_arr1 = ShapeArray.fromPolygon(p._points, scale = scale)
    shape_arr2 = ShapeArray.fromPolygon(p_offset._points, scale = scale)
    assert shape_arr1.arr.shape[0] >= (4 * scale) - 1  # -1 is to account for rounding errors
    assert shape_arr2.arr.shape[0] >= (2 * offset + 4) * scale - 1
예제 #20
0
    def getConvexHull(self):
        if self._node is None:
            return None

        hull = self._compute2DConvexHull()

        if self._global_stack and self._node:
            if self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time" and not self._node.getParent().callDecoration("isGroup"):
                hull = hull.getMinkowskiHull(Polygon(numpy.array(self._global_stack.getProperty("machine_head_polygon", "value"), numpy.float32)))
        return hull
예제 #21
0
def test_parts_of_fromNode():
    from UM.Math.Polygon import Polygon
    p = Polygon(
        numpy.array([[-2, -2], [2, -2], [2, 2], [-2, 2]], dtype=numpy.int32))
    offset = 1
    p_offset = p.getMinkowskiHull(Polygon.approximatedCircle(offset))
    assert len(numpy.where(p_offset._points[:, 0] >= 2.9)) > 0
    assert len(numpy.where(p_offset._points[:, 0] <= -2.9)) > 0
    assert len(numpy.where(p_offset._points[:, 1] >= 2.9)) > 0
    assert len(numpy.where(p_offset._points[:, 1] <= -2.9)) > 0
예제 #22
0
 def test_project(self, data):
     p = Polygon(numpy.array([
         [0.0, 1.0],
         [1.0, 1.0],
         [1.0, 2.0],
         [0.0, 2.0]
     ], numpy.float32))
     result = p.project(data["normal"]) #Project the polygon onto the specified normal vector.
     assert len(result) == len(data["answer"]) #Same dimensionality (2).
     for dimension in range(len(result)):
         assert Float.fuzzyCompare(result[dimension], data["answer"][dimension])
예제 #23
0
    def getConvexHull(self):
        if self._node is None:
            return None

        hull = self._compute2DConvexHull()

        if self._global_stack and self._node:
            # Parent can be None if node is just loaded.
            if self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time" and (self._node.getParent() is None or not self._node.getParent().callDecoration("isGroup")):
                hull = hull.getMinkowskiHull(Polygon(numpy.array(self._global_stack.getProperty("machine_head_polygon", "value"), numpy.float32)))
                hull = self._add2DAdhesionMargin(hull)
        return hull
예제 #24
0
def test_parts_of_fromNode():
    """Just adding some stuff to ensure fromNode works as expected. Some parts should actually be in UM"""

    from UM.Math.Polygon import Polygon
    p = Polygon(
        numpy.array([[-2, -2], [2, -2], [2, 2], [-2, 2]], dtype=numpy.int32))
    offset = 1
    p_offset = p.getMinkowskiHull(Polygon.approximatedCircle(offset))
    assert len(numpy.where(p_offset._points[:, 0] >= 2.9)) > 0
    assert len(numpy.where(p_offset._points[:, 0] <= -2.9)) > 0
    assert len(numpy.where(p_offset._points[:, 1] >= 2.9)) > 0
    assert len(numpy.where(p_offset._points[:, 1] <= -2.9)) > 0
예제 #25
0
    def test_intersectsPolygon(self, data):
        p1 = Polygon(numpy.array([ #The base polygon to intersect with.
            [ 0,  0],
            [10,  0],
            [10, 10],
            [ 0, 10]
        ], numpy.float32))
        p2 = Polygon(numpy.array(data["polygon"])) #The parametrised polygon to intersect with.

        #Shift the order of vertices in both polygons around. The outcome should be independent of what the first vertex is.
        for n in range(0, len(p1.getPoints())):
            for m in range(0, len(data["polygon"])):
                result = p1.intersectsPolygon(p2)
                if not data["answer"]: #Result should be None.
                    assert result == None
                else:
                    assert result != None
                    for i in range(0, len(data["answer"])):
                        assert Float.fuzzyCompare(result[i], data["answer"][i])
                p2.setPoints(numpy.roll(p2.getPoints(), 1, axis = 0)) #Shift p2.
            p1.setPoints(numpy.roll(p1.getPoints(), 1, axis = 0)) #Shift p1.
예제 #26
0
    def test_computeDisalowedAreasStaticSingleExtruder(self, build_volume: BuildVolume):
        mocked_stack = MagicMock()
        mocked_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)

        mocked_extruder = MagicMock()
        mocked_extruder.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
        mocked_extruder.getId = MagicMock(return_value = "zomg")

        build_volume._global_container_stack = mocked_stack
        with patch("cura.Settings.ExtruderManager.ExtruderManager.getInstance"):
            result = build_volume._computeDisallowedAreasStatic(0, [mocked_extruder])
            assert result == {"zomg": [Polygon([[-84.0, 102.5], [-115.0, 102.5], [-200.0, 112.5], [-82.0, 112.5]])]}
예제 #27
0
    def _updateDisallowedAreas(self):
        if not self._active_container_stack:
            return

        disallowed_areas = self._active_container_stack.getProperty("machine_disallowed_areas", "value")
        areas = []

        skirt_size = self._getSkirtSize(self._active_container_stack)

        if disallowed_areas:
            # Extend every area already in the disallowed_areas with the skirt size.
            for area in disallowed_areas:
                poly = Polygon(numpy.array(area, numpy.float32))
                poly = poly.getMinkowskiHull(Polygon(numpy.array([
                    [-skirt_size, 0],
                    [-skirt_size * 0.707, skirt_size * 0.707],
                    [0, skirt_size],
                    [skirt_size * 0.707, skirt_size * 0.707],
                    [skirt_size, 0],
                    [skirt_size * 0.707, -skirt_size * 0.707],
                    [0, -skirt_size],
                    [-skirt_size * 0.707, -skirt_size * 0.707]
                ], numpy.float32)))

                areas.append(poly)

        # Add the skirt areas around the borders of the build plate.
        if skirt_size > 0:
            half_machine_width = self._active_container_stack.getProperty("machine_width", "value") / 2
            half_machine_depth = self._active_container_stack.getProperty("machine_depth", "value") / 2

            areas.append(Polygon(numpy.array([
                [-half_machine_width, -half_machine_depth],
                [-half_machine_width, half_machine_depth],
                [-half_machine_width + skirt_size, half_machine_depth - skirt_size],
                [-half_machine_width + skirt_size, -half_machine_depth + skirt_size]
            ], numpy.float32)))

            areas.append(Polygon(numpy.array([
                [half_machine_width, half_machine_depth],
                [half_machine_width, -half_machine_depth],
                [half_machine_width - skirt_size, -half_machine_depth + skirt_size],
                [half_machine_width - skirt_size, half_machine_depth - skirt_size]
            ], numpy.float32)))

            areas.append(Polygon(numpy.array([
                [-half_machine_width, half_machine_depth],
                [half_machine_width, half_machine_depth],
                [half_machine_width - skirt_size, half_machine_depth - skirt_size],
                [-half_machine_width + skirt_size, half_machine_depth - skirt_size]
            ], numpy.float32)))

            areas.append(Polygon(numpy.array([
                [half_machine_width, -half_machine_depth],
                [-half_machine_width, -half_machine_depth],
                [-half_machine_width + skirt_size, -half_machine_depth + skirt_size],
                [half_machine_width - skirt_size, -half_machine_depth + skirt_size]
            ], numpy.float32)))

        self._disallowed_areas = areas
예제 #28
0
    def _updateDisallowedAreas(self):
        if not self._active_instance or not self._active_profile:
            return

        disallowed_areas = self._active_instance.getMachineSettingValue("machine_disallowed_areas")
        areas = []

        skirt_size = 0.0
        if self._active_profile:
            skirt_size = self._getSkirtSize(self._active_profile)

        if disallowed_areas:
            for area in disallowed_areas:
                poly = Polygon(numpy.array(area, numpy.float32))
                poly = poly.getMinkowskiHull(Polygon(numpy.array([
                    [-skirt_size, 0],
                    [-skirt_size * 0.707, skirt_size * 0.707],
                    [0, skirt_size],
                    [skirt_size * 0.707, skirt_size * 0.707],
                    [skirt_size, 0],
                    [skirt_size * 0.707, -skirt_size * 0.707],
                    [0, -skirt_size],
                    [-skirt_size * 0.707, -skirt_size * 0.707]
                ], numpy.float32)))

                areas.append(poly)

        if skirt_size > 0:
            half_machine_width = self._active_instance.getMachineSettingValue("machine_width") / 2
            half_machine_depth = self._active_instance.getMachineSettingValue("machine_depth") / 2

            areas.append(Polygon(numpy.array([
                [-half_machine_width, -half_machine_depth],
                [-half_machine_width, half_machine_depth],
                [-half_machine_width + skirt_size, half_machine_depth - skirt_size],
                [-half_machine_width + skirt_size, -half_machine_depth + skirt_size]
            ], numpy.float32)))

            areas.append(Polygon(numpy.array([
                [half_machine_width, half_machine_depth],
                [half_machine_width, -half_machine_depth],
                [half_machine_width - skirt_size, -half_machine_depth + skirt_size],
                [half_machine_width - skirt_size, half_machine_depth - skirt_size]
            ], numpy.float32)))

            areas.append(Polygon(numpy.array([
                [-half_machine_width, half_machine_depth],
                [half_machine_width, half_machine_depth],
                [half_machine_width - skirt_size, half_machine_depth - skirt_size],
                [-half_machine_width + skirt_size, half_machine_depth - skirt_size]
            ], numpy.float32)))

            areas.append(Polygon(numpy.array([
                [half_machine_width, -half_machine_depth],
                [-half_machine_width, -half_machine_depth],
                [-half_machine_width + skirt_size, -half_machine_depth + skirt_size],
                [half_machine_width - skirt_size, -half_machine_depth + skirt_size]
            ], numpy.float32)))

        self._disallowed_areas = areas
예제 #29
0
    def getConvexHull(self) -> Optional[Polygon]:
        if self._node is None:
            return None
        if self._node.callDecoration("isNonPrintingMesh"):
            return None
        hull = self._compute2DConvexHull()

        if self._global_stack and self._node is not None and hull is not None:
            # Parent can be None if node is just loaded.
            if self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time" and not self.hasGroupAsParent(self._node):
                hull = hull.getMinkowskiHull(Polygon(numpy.array(self._global_stack.getProperty("machine_head_polygon", "value"), numpy.float32)))
                hull = self._add2DAdhesionMargin(hull)
        return hull
예제 #30
0
def test_compute2DConvexHullMeshData(convex_hull_decorator):
    node = SceneNode()
    mb = MeshBuilder()
    mb.addCube(10, 10, 10)
    node.setMeshData(mb.build())

    convex_hull_decorator._getSettingProperty = MagicMock(return_value=0)

    with patch("UM.Application.Application.getInstance",
               MagicMock(return_value=mocked_application)):
        convex_hull_decorator.setNode(node)

    assert convex_hull_decorator._compute2DConvexHull() == Polygon(
        [[5.0, -5.0], [-5.0, -5.0], [-5.0, 5.0], [5.0, 5.0]])