Пример #1
0
    def _createEraserMesh(self, parent: CuraSceneNode, position: Vector):
        node = CuraSceneNode()

        node.setName("Eraser")
        node.setSelectable(True)
        mesh = MeshBuilder()
        mesh.addCube(10,10,10)
        node.setMeshData(mesh.build())

        active_build_plate = Application.getInstance().getMultiBuildPlateModel().activeBuildPlate
        node.addDecorator(BuildPlateDecorator(active_build_plate))
        node.addDecorator(SliceableObjectDecorator())

        stack = node.callDecoration("getStack") # created by SettingOverrideDecorator that is automatically added to CuraSceneNode
        settings = stack.getTop()

        definition = stack.getSettingDefinition("anti_overhang_mesh")
        new_instance = SettingInstance(definition, settings)
        new_instance.setProperty("value", True)
        new_instance.resetState()  # Ensure that the state is not seen as a user state.
        settings.addInstance(new_instance)

        op = GroupedOperation()
        # First add node to the scene at the correct position/scale, before parenting, so the eraser mesh does not get scaled with the parent
        op.addOperation(AddSceneNodeOperation(node, self._controller.getScene().getRoot()))
        op.addOperation(SetParentOperation(node, parent))
        op.push()
        node.setPosition(position, CuraSceneNode.TransformSpace.World)

        Application.getInstance().getController().getScene().sceneChanged.emit(node)
Пример #2
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]])
Пример #3
0
def test_getExtents():
    # Create a cube mesh at position 0,0,0
    builder = MeshBuilder()
    builder.addCube(20, 20, 20)
    mesh_data = builder.build()

    extents = mesh_data.getExtents()
    assert extents.width == 20
    assert extents.height == 20
    assert extents.depth == 20

    assert extents.maximum == Vector(10, 10, 10)
    assert extents.minimum == Vector(-10, -10, -10)
Пример #4
0
def test_getExtents():
    # Create a cube mesh at position 0,0,0
    builder = MeshBuilder()
    builder.addCube(20, 20, 20)
    mesh_data = builder.build()

    extents = mesh_data.getExtents()
    assert extents.width == 20
    assert extents.height == 20
    assert extents.depth == 20

    assert extents.maximum == Vector(10, 10, 10)
    assert extents.minimum == Vector(-10, -10, -10)
Пример #5
0
    def read(self, file_name):
        #Here you would typically open the file, read its contents, parse it, etc.
        #For this example we will just always create a cube and return that.

        builder = MeshBuilder() #To construct your own mesh, look at the methods provided by MeshBuilder.
        builder.addCube(10, 10, 10, Vector(0, 0, 0)) #Cube of 10 by 10 by 10.
        builder.calculateNormals()

        #Put the mesh inside a scene node.
        result_node = SceneNode()
        result_node.setMeshData(builder.build())
        result_node.setName(file_name) #Typically the file name that the mesh originated from is a good name for the node.

        return result_node
Пример #6
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]])
Пример #7
0
def test_getExtentsTransposed():
    # Create a cube mesh at position 0,0,0
    builder = MeshBuilder()
    builder.addCube(20, 20, 20)
    mesh_data = builder.build()

    transformation_matrix = Matrix()
    transformation_matrix.setByTranslation(Vector(10, 10, 10))

    extents = mesh_data.getExtents(transformation_matrix)
    assert extents.width == 20
    assert extents.height == 20
    assert extents.depth == 20

    assert extents.maximum == Vector(20, 20, 20)
    assert extents.minimum == Vector(0, 0, 0)
Пример #8
0
def test_getExtentsTransposed():
    # Create a cube mesh at position 0,0,0
    builder = MeshBuilder()
    builder.addCube(20, 20, 20)
    mesh_data = builder.build()

    transformation_matrix = Matrix()
    transformation_matrix.setByTranslation(Vector(10, 10, 10))

    extents = mesh_data.getExtents(transformation_matrix)
    assert extents.width == 20
    assert extents.height == 20
    assert extents.depth == 20

    assert extents.maximum == Vector(20, 20, 20)
    assert extents.minimum == Vector(0, 0, 0)
Пример #9
0
def test_compute2DConvexHullMeshDataGrouped(convex_hull_decorator):
    parent_node = SceneNode()
    parent_node.addDecorator(GroupDecorator())
    node = SceneNode()
    parent_node.addChild(node)

    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(parent_node)
        with patch("cura.Settings.ExtruderManager.ExtruderManager.getInstance"):
            copied_decorator = copy.deepcopy(convex_hull_decorator)
            copied_decorator._getSettingProperty = MagicMock(return_value=0)
        node.addDecorator(copied_decorator)
    assert convex_hull_decorator._compute2DConvexHull() == Polygon([[-5.0,5.0], [5.0,5.0], [5.0,-5.0], [-5.0,-5.0]])
Пример #10
0
    def _createEraserMesh(self):
        node = CuraSceneNode()

        node.setName("Eraser")
        node.setSelectable(True)
        mesh = MeshBuilder()
        mesh.addCube(10, 10, 10)
        node.setMeshData(mesh.build())
        # Place the cube in the platform. Do it manually so it works if the "automatic drop models" is OFF
        move_vector = Vector(0, 5, 0)
        node.setPosition(move_vector)

        active_build_plate = Application.getInstance().getMultiBuildPlateModel(
        ).activeBuildPlate

        node.addDecorator(SettingOverrideDecorator())
        node.addDecorator(BuildPlateDecorator(active_build_plate))
        node.addDecorator(SliceableObjectDecorator())

        stack = node.callDecoration(
            "getStack"
        )  #Don't try to get the active extruder since it may be None anyway.
        if not stack:
            node.addDecorator(SettingOverrideDecorator())
            stack = node.callDecoration("getStack")

        settings = stack.getTop()

        if not (settings.getInstance("anti_overhang_mesh")
                and settings.getProperty("anti_overhang_mesh", "value")):
            definition = stack.getSettingDefinition("anti_overhang_mesh")
            new_instance = SettingInstance(definition, settings)
            new_instance.setProperty("value", True)
            new_instance.resetState(
            )  # Ensure that the state is not seen as a user state.
            settings.addInstance(new_instance)

        scene = self._controller.getScene()
        op = AddSceneNodeOperation(node, scene.getRoot())
        op.push()
        Application.getInstance().getController().getScene().sceneChanged.emit(
            node)
Пример #11
0
def test_compute2DConvexHullMeshDataGrouped(convex_hull_decorator):
    parent_node = SceneNode()
    parent_node.addDecorator(GroupDecorator())
    node = SceneNode()
    parent_node.addChild(node)

    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(parent_node)
        with patch(
                "cura.Settings.ExtruderManager.ExtruderManager.getInstance"):
            copied_decorator = copy.deepcopy(convex_hull_decorator)
            copied_decorator._getSettingProperty = MagicMock(return_value=0)
        node.addDecorator(copied_decorator)
    assert convex_hull_decorator._compute2DConvexHull() == Polygon(
        [[-5.0, 5.0], [5.0, 5.0], [5.0, -5.0], [-5.0, -5.0]])
Пример #12
0
    def _onGlobalContainerStackChanged(self):
        if self._global_container_stack:
            self.setMeshData(None)

        self._global_container_stack = Application.getInstance().getGlobalContainerStack()
        if self._global_container_stack:
            container = self._global_container_stack.findContainer({ "platform": "*" })
            if container:
                mesh_file = container.getMetaDataEntry("platform")
                try:
                    path = Resources.getPath(Resources.Meshes, mesh_file)
                except FileNotFoundError:
                    Logger.log("w", "Unable to find the platform mesh %s", mesh_file)
                    path = ""

                if self._load_platform_job:
                    # This prevents a previous load job from triggering texture loads.
                    self._load_platform_job.finished.disconnect(self._onPlatformLoaded)

                # Perform platform mesh loading in the background
                self._load_platform_job = _LoadPlatformJob(path)
                self._load_platform_job.finished.connect(self._onPlatformLoaded)
                self._load_platform_job.start()

                self._has_bed = True

                offset = container.getMetaDataEntry("platform_offset")
                if offset:
                    if len(offset) == 3:
                        self.setPosition(Vector(offset[0], offset[1], offset[2]))
                    else:
                        Logger.log("w", "Platform offset is invalid: %s", str(offset))
                        self.setPosition(Vector(0.0, 0.0, 0.0))
                else:
                    self.setPosition(Vector(0.0, 0.0, 0.0))
            else:
                settings = Application.getInstance().getGlobalContainerStack()
                machine_width = settings.getProperty("machine_width", "value")
                machine_depth = settings.getProperty("machine_depth", "value")
                line_len = 25
                line_wid = 1
                handle_size = 3
                mb = MeshBuilder()

                mb.addCube(line_wid, line_len, line_wid, Vector(-machine_width/2, line_len/2, machine_depth/2), ToolHandle.YAxisSelectionColor)
                mb.addPyramid(handle_size, handle_size, handle_size, center=Vector(-machine_width/2, line_len, machine_depth/2), color=ToolHandle.YAxisSelectionColor)

                mb.addCube(line_len, line_wid, line_wid, Vector(line_len/2-machine_width/2, 0, machine_depth/2), ToolHandle.XAxisSelectionColor)
                mb.addPyramid(handle_size, handle_size, handle_size, center=Vector(line_len-machine_width/2, 0, machine_depth/2), color=ToolHandle.XAxisSelectionColor, axis = Vector.Unit_Z, angle = 90)

                mb.addCube(line_wid, line_wid, line_len, Vector(-machine_width/2, 0, -line_len/2+machine_depth/2), ToolHandle.ZAxisSelectionColor)
                mb.addPyramid(handle_size, handle_size, handle_size, center=Vector(-machine_width/2, 0, -line_len+machine_depth/2), color=ToolHandle.ZAxisSelectionColor, axis = Vector.Unit_X, angle = 90)

                self.setMeshData(mb.build())
                self.setPosition(Vector(0.0, 0.0, 0.0))
                self._has_bed = False
Пример #13
0
 def _getAxisMesh(self, node):
     mb = MeshBuilder()
     mb.addCube(width=self.axis_width,
                height=self.axis_height,
                depth=self.axis_width,
                color=self.YAxisColor,
                center=Vector(0, self.axis_height / 2, 0))
     mb.addCube(width=self.axis_width,
                height=self.axis_width,
                depth=self.axis_height,
                color=self.ZAxisColor,
                center=Vector(0, 0, self.axis_height / 2))
     mb.addCube(width=self.axis_height,
                height=self.axis_width,
                depth=self.axis_width,
                color=self.XAxisColor,
                center=Vector(self.axis_height / 2, 0, 0))
     return mb.build().getTransformed(node.getWorldTransformation())
Пример #14
0
    def buildMesh(self):
        mb = MeshBuilder()

        #SOLIDMESH -> LINES
        if self.YAxis in self._enabled_axis:
            mb.addCube(
                width = self._line_width,
                height = self._line_length,
                depth = self._line_width,
                center = Vector(0, self._handle_position/2, 0),
                color = self._y_axis_color
            )
        if self.XAxis in self._enabled_axis:
            mb.addCube(
                width = self._line_length,
                height = self._line_width,
                depth = self._line_width,
                center = Vector(self._handle_position/2, 0, 0),
                color = self._x_axis_color
            )

        if self.ZAxis in self._enabled_axis:
            mb.addCube(
                width = self._line_width,
                height = self._line_width,
                depth = self._line_length,
                center = Vector(0, 0, self._handle_position/2),
                color = self._z_axis_color
            )

        #SOLIDMESH -> HANDLES
        if self.YAxis in self._enabled_axis:
            mb.addPyramid(
                width = self._handle_width,
                height = self._handle_height,
                depth = self._handle_width,
                center = Vector(0, self._handle_position, 0),
                color = self._y_axis_color
            )

        if self.XAxis in self._enabled_axis:
            mb.addPyramid(
                width = self._handle_width,
                height = self._handle_height,
                depth = self._handle_width,
                center = Vector(self._handle_position, 0, 0),
                color = self._x_axis_color,
                axis = Vector.Unit_Z,
                angle = 90
            )

        if self.ZAxis in self._enabled_axis:
            mb.addPyramid(
                width = self._handle_width,
                height = self._handle_height,
                depth = self._handle_width,
                center = Vector(0, 0, self._handle_position),
                color = self._z_axis_color,
                axis = Vector.Unit_X,
                angle = -90
            )

        self.setSolidMesh(mb.build())

        mb = MeshBuilder()
        #SELECTIONMESH -> LINES
        if self.YAxis in self._enabled_axis:
            mb.addCube(
                width = self._active_line_width,
                height = self._active_line_length,
                depth = self._active_line_width,
                center = Vector(0, self._active_handle_position/2, 0),
                color = self._y_axis_color
            )
        if self.XAxis in self._enabled_axis:
            mb.addCube(
                width = self._active_line_length,
                height = self._active_line_width,
                depth = self._active_line_width,
                center = Vector(self._active_handle_position/2, 0, 0),
                color = self._x_axis_color
            )

        if self.ZAxis in self._enabled_axis:
            mb.addCube(
                width = self._active_line_width,
                height = self._active_line_width,
                depth = self._active_line_length,
                center = Vector(0, 0, self._active_handle_position/2),
                color = self._z_axis_color
            )

        #SELECTIONMESH -> HANDLES
        mb.addCube(
            width = self._active_handle_width,
            height = self._active_handle_width,
            depth = self._active_handle_width,
            center = Vector(0, 0, 0),
            color = ToolHandle.AllAxisSelectionColor
        )

        mb.addCube(
            width = self._active_handle_width,
            height = self._active_handle_width,
            depth = self._active_handle_width,
            center = Vector(0, self._active_handle_position, 0),
            color = ToolHandle.YAxisSelectionColor
        )

        mb.addCube(
            width = self._active_handle_width,
            height = self._active_handle_width,
            depth = self._active_handle_width,
            center = Vector(self._active_handle_position, 0, 0),
            color = ToolHandle.XAxisSelectionColor
        )

        mb.addCube(
            width = self._active_handle_width,
            height = self._active_handle_width,
            depth = self._active_handle_width,
            center = Vector(0, 0, self._active_handle_position),
            color = ToolHandle.ZAxisSelectionColor
        )
        self.setSelectionMesh(mb.build())
Пример #15
0
    def rebuild(self):
        if not self._width or not self._height or not self._depth:
            return

        min_w = -self._width / 2
        max_w = self._width / 2
        min_h = 0.0
        max_h = self._height
        min_d = -self._depth / 2
        max_d = self._depth / 2

        mb = MeshBuilder()

        # Outline 'cube' of the build volume
        mb.addLine(Vector(min_w, min_h, min_d),
                   Vector(max_w, min_h, min_d),
                   color=self.VolumeOutlineColor)
        mb.addLine(Vector(min_w, min_h, min_d),
                   Vector(min_w, max_h, min_d),
                   color=self.VolumeOutlineColor)
        mb.addLine(Vector(min_w, max_h, min_d),
                   Vector(max_w, max_h, min_d),
                   color=self.VolumeOutlineColor)
        mb.addLine(Vector(max_w, min_h, min_d),
                   Vector(max_w, max_h, min_d),
                   color=self.VolumeOutlineColor)

        mb.addLine(Vector(min_w, min_h, max_d),
                   Vector(max_w, min_h, max_d),
                   color=self.VolumeOutlineColor)
        mb.addLine(Vector(min_w, min_h, max_d),
                   Vector(min_w, max_h, max_d),
                   color=self.VolumeOutlineColor)
        mb.addLine(Vector(min_w, max_h, max_d),
                   Vector(max_w, max_h, max_d),
                   color=self.VolumeOutlineColor)
        mb.addLine(Vector(max_w, min_h, max_d),
                   Vector(max_w, max_h, max_d),
                   color=self.VolumeOutlineColor)

        mb.addLine(Vector(min_w, min_h, min_d),
                   Vector(min_w, min_h, max_d),
                   color=self.VolumeOutlineColor)
        mb.addLine(Vector(max_w, min_h, min_d),
                   Vector(max_w, min_h, max_d),
                   color=self.VolumeOutlineColor)
        mb.addLine(Vector(min_w, max_h, min_d),
                   Vector(min_w, max_h, max_d),
                   color=self.VolumeOutlineColor)
        mb.addLine(Vector(max_w, max_h, min_d),
                   Vector(max_w, max_h, max_d),
                   color=self.VolumeOutlineColor)

        self.setMeshData(mb.build())

        mb = MeshBuilder()

        # Indication of the machine origin
        if self._global_container_stack.getProperty("machine_center_is_zero",
                                                    "value"):
            origin = (Vector(min_w, min_h, min_d) +
                      Vector(max_w, min_h, max_d)) / 2
        else:
            origin = Vector(min_w, min_h, max_d)

        mb.addCube(width=self._origin_line_length,
                   height=self._origin_line_width,
                   depth=self._origin_line_width,
                   center=origin + Vector(self._origin_line_length / 2, 0, 0),
                   color=self.XAxisColor)
        mb.addCube(width=self._origin_line_width,
                   height=self._origin_line_length,
                   depth=self._origin_line_width,
                   center=origin + Vector(0, self._origin_line_length / 2, 0),
                   color=self.YAxisColor)
        mb.addCube(width=self._origin_line_width,
                   height=self._origin_line_width,
                   depth=self._origin_line_length,
                   center=origin - Vector(0, 0, self._origin_line_length / 2),
                   color=self.ZAxisColor)
        self._origin_mesh = mb.build()

        mb = MeshBuilder()
        mb.addQuad(Vector(min_w, min_h - 0.2, min_d),
                   Vector(max_w, min_h - 0.2, min_d),
                   Vector(max_w, min_h - 0.2, max_d),
                   Vector(min_w, min_h - 0.2, max_d))

        for n in range(0, 6):
            v = mb.getVertex(n)
            mb.setVertexUVCoordinates(n, v[0], v[2])
        self._grid_mesh = mb.build()

        disallowed_area_height = 0.1
        disallowed_area_size = 0
        if self._disallowed_areas:
            mb = MeshBuilder()
            color = Color(0.0, 0.0, 0.0, 0.15)
            for polygon in self._disallowed_areas:
                points = polygon.getPoints()
                first = Vector(self._clamp(points[0][0], min_w, max_w),
                               disallowed_area_height,
                               self._clamp(points[0][1], min_d, max_d))
                previous_point = Vector(
                    self._clamp(points[0][0], min_w, max_w),
                    disallowed_area_height,
                    self._clamp(points[0][1], min_d, max_d))
                for point in points:
                    new_point = Vector(self._clamp(point[0], min_w, max_w),
                                       disallowed_area_height,
                                       self._clamp(point[1], min_d, max_d))
                    mb.addFace(first, previous_point, new_point, color=color)
                    previous_point = new_point

                # Find the largest disallowed area to exclude it from the maximum scale bounds.
                # This is a very nasty hack. This pretty much only works for UM machines.
                # This disallowed area_size needs a -lot- of rework at some point in the future: TODO
                if numpy.min(
                        points[:, 1]
                ) >= 0:  # This filters out all areas that have points to the left of the centre. This is done to filter the skirt area.
                    size = abs(
                        numpy.max(points[:, 1]) - numpy.min(points[:, 1]))
                else:
                    size = 0
                disallowed_area_size = max(size, disallowed_area_size)

            self._disallowed_area_mesh = mb.build()
        else:
            self._disallowed_area_mesh = None

        if self._error_areas:
            mb = MeshBuilder()
            for error_area in self._error_areas:
                color = Color(1.0, 0.0, 0.0, 0.5)
                points = error_area.getPoints()
                first = Vector(self._clamp(points[0][0], min_w, max_w),
                               disallowed_area_height,
                               self._clamp(points[0][1], min_d, max_d))
                previous_point = Vector(
                    self._clamp(points[0][0], min_w, max_w),
                    disallowed_area_height,
                    self._clamp(points[0][1], min_d, max_d))
                for point in points:
                    new_point = Vector(self._clamp(point[0], min_w, max_w),
                                       disallowed_area_height,
                                       self._clamp(point[1], min_d, max_d))
                    mb.addFace(first, previous_point, new_point, color=color)
                    previous_point = new_point
            self._error_mesh = mb.build()
        else:
            self._error_mesh = None

        self._volume_aabb = AxisAlignedBox(
            minimum=Vector(min_w, min_h - 1.0, min_d),
            maximum=Vector(max_w, max_h - self._raft_thickness, max_d))

        bed_adhesion_size = self._getEdgeDisallowedSize()

        # As this works better for UM machines, we only add the disallowed_area_size for the z direction.
        # This is probably wrong in all other cases. TODO!
        # The +1 and -1 is added as there is always a bit of extra room required to work properly.
        scale_to_max_bounds = AxisAlignedBox(
            minimum=Vector(
                min_w + bed_adhesion_size + 1, min_h,
                min_d + disallowed_area_size - bed_adhesion_size + 1),
            maximum=Vector(
                max_w - bed_adhesion_size - 1, max_h - self._raft_thickness,
                max_d - disallowed_area_size + bed_adhesion_size - 1))

        Application.getInstance().getController().getScene(
        )._maximum_bounds = scale_to_max_bounds
Пример #16
0
    def buildMesh(self):
        #SOLIDMESH -> LINES
        mb = MeshBuilder()

        mb.addCube(width=self._line_width,
                   height=self._line_length,
                   depth=self._line_width,
                   center=Vector(0, self._handle_position / 2, 0),
                   color=self._y_axis_color)
        mb.addCube(width=self._line_length,
                   height=self._line_width,
                   depth=self._line_width,
                   center=Vector(self._handle_position / 2, 0, 0),
                   color=self._x_axis_color)

        mb.addCube(width=self._line_width,
                   height=self._line_width,
                   depth=self._line_length,
                   center=Vector(0, 0, self._handle_position / 2),
                   color=self._z_axis_color)

        #SOLIDMESH -> HANDLES
        mb.addCube(width=self._handle_width,
                   height=self._handle_width,
                   depth=self._handle_width,
                   center=Vector(0, 0, 0),
                   color=self._all_axis_color)

        mb.addCube(width=self._handle_width,
                   height=self._handle_width,
                   depth=self._handle_width,
                   center=Vector(0, self._handle_position, 0),
                   color=self._y_axis_color)

        mb.addCube(width=self._handle_width,
                   height=self._handle_width,
                   depth=self._handle_width,
                   center=Vector(self._handle_position, 0, 0),
                   color=self._x_axis_color)

        mb.addCube(width=self._handle_width,
                   height=self._handle_width,
                   depth=self._handle_width,
                   center=Vector(0, 0, self._handle_position),
                   color=self._z_axis_color)
        self.setSolidMesh(mb.build())

        #SELECTIONMESH -> LINES
        mb = MeshBuilder()
        mb.addCube(width=self._active_line_width,
                   height=self._active_line_length,
                   depth=self._active_line_width,
                   center=Vector(0, self._active_handle_position / 2, 0),
                   color=ToolHandle.YAxisSelectionColor)

        mb.addCube(width=self._active_line_length,
                   height=self._active_line_width,
                   depth=self._active_line_width,
                   center=Vector(self._active_handle_position / 2, 0, 0),
                   color=ToolHandle.XAxisSelectionColor)

        mb.addCube(width=self._active_line_width,
                   height=self._active_line_width,
                   depth=self._active_line_length,
                   center=Vector(0, 0, self._active_handle_position / 2),
                   color=ToolHandle.ZAxisSelectionColor)

        #SELECTIONMESH -> HANDLES
        mb.addCube(width=self._active_handle_width,
                   height=self._active_handle_width,
                   depth=self._active_handle_width,
                   center=Vector(0, 0, 0),
                   color=ToolHandle.AllAxisSelectionColor)

        mb.addCube(width=self._active_handle_width,
                   height=self._active_handle_width,
                   depth=self._active_handle_width,
                   center=Vector(0, self._active_handle_position, 0),
                   color=ToolHandle.YAxisSelectionColor)

        mb.addCube(width=self._active_handle_width,
                   height=self._active_handle_width,
                   depth=self._active_handle_width,
                   center=Vector(self._active_handle_position, 0, 0),
                   color=ToolHandle.XAxisSelectionColor)

        mb.addCube(width=self._active_handle_width,
                   height=self._active_handle_width,
                   depth=self._active_handle_width,
                   center=Vector(0, 0, self._active_handle_position),
                   color=ToolHandle.ZAxisSelectionColor)

        self.setSelectionMesh(mb.build())
Пример #17
0
    def rebuild(self):
        if not self._width or not self._height or not self._depth:
            return

        min_w = -self._width / 2
        max_w = self._width / 2
        min_h = 0.0
        max_h = self._height
        min_d = -self._depth / 2
        max_d = self._depth / 2

        z_fight_distance = 0.2 # Distance between buildplate and disallowed area meshes to prevent z-fighting

        if self._shape != "elliptic":
            # Outline 'cube' of the build volume
            mb = MeshBuilder()
            mb.addLine(Vector(min_w, min_h, min_d), Vector(max_w, min_h, min_d), color = self.VolumeOutlineColor)
            mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, max_h, min_d), color = self.VolumeOutlineColor)
            mb.addLine(Vector(min_w, max_h, min_d), Vector(max_w, max_h, min_d), color = self.VolumeOutlineColor)
            mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, max_h, min_d), color = self.VolumeOutlineColor)

            mb.addLine(Vector(min_w, min_h, max_d), Vector(max_w, min_h, max_d), color = self.VolumeOutlineColor)
            mb.addLine(Vector(min_w, min_h, max_d), Vector(min_w, max_h, max_d), color = self.VolumeOutlineColor)
            mb.addLine(Vector(min_w, max_h, max_d), Vector(max_w, max_h, max_d), color = self.VolumeOutlineColor)
            mb.addLine(Vector(max_w, min_h, max_d), Vector(max_w, max_h, max_d), color = self.VolumeOutlineColor)

            mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, min_h, max_d), color = self.VolumeOutlineColor)
            mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, min_h, max_d), color = self.VolumeOutlineColor)
            mb.addLine(Vector(min_w, max_h, min_d), Vector(min_w, max_h, max_d), color = self.VolumeOutlineColor)
            mb.addLine(Vector(max_w, max_h, min_d), Vector(max_w, max_h, max_d), color = self.VolumeOutlineColor)

            self.setMeshData(mb.build())

            # Build plate grid mesh
            mb = MeshBuilder()
            mb.addQuad(
                Vector(min_w, min_h - z_fight_distance, min_d),
                Vector(max_w, min_h - z_fight_distance, min_d),
                Vector(max_w, min_h - z_fight_distance, max_d),
                Vector(min_w, min_h - z_fight_distance, max_d)
            )

            for n in range(0, 6):
                v = mb.getVertex(n)
                mb.setVertexUVCoordinates(n, v[0], v[2])
            self._grid_mesh = mb.build()

        else:
            # Bottom and top 'ellipse' of the build volume
            aspect = 1.0
            scale_matrix = Matrix()
            if self._width != 0:
                # Scale circular meshes by aspect ratio if width != height
                aspect = self._height / self._width
                scale_matrix.compose(scale = Vector(1, 1, aspect))
            mb = MeshBuilder()
            mb.addArc(max_w, Vector.Unit_Y, center = (0, min_h - z_fight_distance, 0), color = self.VolumeOutlineColor)
            mb.addArc(max_w, Vector.Unit_Y, center = (0, max_h, 0),  color = self.VolumeOutlineColor)
            self.setMeshData(mb.build().getTransformed(scale_matrix))

            # Build plate grid mesh
            mb = MeshBuilder()
            mb.addVertex(0, min_h - z_fight_distance, 0)
            mb.addArc(max_w, Vector.Unit_Y, center = Vector(0, min_h - z_fight_distance, 0))
            sections = mb.getVertexCount() - 1 # Center point is not an arc section
            indices = []
            for n in range(0, sections - 1):
                indices.append([0, n + 2, n + 1])
            mb.addIndices(numpy.asarray(indices, dtype = numpy.int32))
            mb.calculateNormals()

            for n in range(0, mb.getVertexCount()):
                v = mb.getVertex(n)
                mb.setVertexUVCoordinates(n, v[0], v[2] * aspect)
            self._grid_mesh = mb.build().getTransformed(scale_matrix)

        # Indication of the machine origin
        if self._global_container_stack.getProperty("machine_center_is_zero", "value"):
            origin = (Vector(min_w, min_h, min_d) + Vector(max_w, min_h, max_d)) / 2
        else:
            origin = Vector(min_w, min_h, max_d)

        mb = MeshBuilder()
        mb.addCube(
            width = self._origin_line_length,
            height = self._origin_line_width,
            depth = self._origin_line_width,
            center = origin + Vector(self._origin_line_length / 2, 0, 0),
            color = self.XAxisColor
        )
        mb.addCube(
            width = self._origin_line_width,
            height = self._origin_line_length,
            depth = self._origin_line_width,
            center = origin + Vector(0, self._origin_line_length / 2, 0),
            color = self.YAxisColor
        )
        mb.addCube(
            width = self._origin_line_width,
            height = self._origin_line_width,
            depth = self._origin_line_length,
            center = origin - Vector(0, 0, self._origin_line_length / 2),
            color = self.ZAxisColor
        )
        self._origin_mesh = mb.build()

        disallowed_area_height = 0.1
        disallowed_area_size = 0
        if self._disallowed_areas:
            mb = MeshBuilder()
            color = Color(0.0, 0.0, 0.0, 0.15)
            for polygon in self._disallowed_areas:
                points = polygon.getPoints()
                first = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._clamp(points[0][1], min_d, max_d))
                previous_point = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._clamp(points[0][1], min_d, max_d))
                for point in points:
                    new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height, self._clamp(point[1], min_d, max_d))
                    mb.addFace(first, previous_point, new_point, color = color)
                    previous_point = new_point

                # Find the largest disallowed area to exclude it from the maximum scale bounds.
                # This is a very nasty hack. This pretty much only works for UM machines.
                # This disallowed area_size needs a -lot- of rework at some point in the future: TODO
                if numpy.min(points[:, 1]) >= 0: # This filters out all areas that have points to the left of the centre. This is done to filter the skirt area.
                    size = abs(numpy.max(points[:, 1]) - numpy.min(points[:, 1]))
                else:
                    size = 0
                disallowed_area_size = max(size, disallowed_area_size)

            self._disallowed_area_mesh = mb.build()
        else:
            self._disallowed_area_mesh = None

        if self._error_areas:
            mb = MeshBuilder()
            for error_area in self._error_areas:
                color = Color(1.0, 0.0, 0.0, 0.5)
                points = error_area.getPoints()
                first = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
                               self._clamp(points[0][1], min_d, max_d))
                previous_point = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
                                        self._clamp(points[0][1], min_d, max_d))
                for point in points:
                    new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height,
                                       self._clamp(point[1], min_d, max_d))
                    mb.addFace(first, previous_point, new_point, color=color)
                    previous_point = new_point
            self._error_mesh = mb.build()
        else:
            self._error_mesh = None

        self._volume_aabb = AxisAlignedBox(
            minimum = Vector(min_w, min_h - 1.0, min_d),
            maximum = Vector(max_w, max_h - self._raft_thickness, max_d))

        bed_adhesion_size = self._getEdgeDisallowedSize()

        # As this works better for UM machines, we only add the disallowed_area_size for the z direction.
        # This is probably wrong in all other cases. TODO!
        # The +1 and -1 is added as there is always a bit of extra room required to work properly.
        scale_to_max_bounds = AxisAlignedBox(
            minimum = Vector(min_w + bed_adhesion_size + 1, min_h, min_d + disallowed_area_size - bed_adhesion_size + 1),
            maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness, max_d - disallowed_area_size + bed_adhesion_size - 1)
        )

        Application.getInstance().getController().getScene()._maximum_bounds = scale_to_max_bounds
Пример #18
0
    def __init__(self, parent = None):
        super().__init__(parent)

        self._line_width = 0.5
        self._line_length= 40
        self._handle_position = 40
        self._handle_width = 4

        self._active_line_width = 0.8
        self._active_line_length = 40
        self._active_handle_position = 40
        self._active_handle_width = 15

        #SOLIDMESH -> LINES
        mb = MeshBuilder()

        mb.addCube(
            width = self._line_width,
            height = self._line_length,
            depth = self._line_width,
            center = Vector(0, self._handle_position/2, 0),
            color = ToolHandle.YAxisColor
        )
        mb.addCube(
            width = self._line_length,
            height = self._line_width,
            depth = self._line_width,
            center = Vector(self._handle_position/2, 0, 0),
            color = ToolHandle.XAxisColor
        )

        mb.addCube(
            width = self._line_width,
            height = self._line_width,
            depth = self._line_length,
            center = Vector(0, 0, self._handle_position/2),
            color = ToolHandle.ZAxisColor
        )

        #SOLIDMESH -> HANDLES
        mb.addCube(
            width = self._handle_width,
            height = self._handle_width,
            depth = self._handle_width,
            center = Vector(0, 0, 0),
            color = ToolHandle.AllAxisColor
        )

        mb.addCube(
            width = self._handle_width,
            height = self._handle_width,
            depth = self._handle_width,
            center = Vector(0, self._handle_position, 0),
            color = ToolHandle.YAxisColor
        )

        mb.addCube(
            width = self._handle_width,
            height = self._handle_width,
            depth = self._handle_width,
            center = Vector(self._handle_position, 0, 0),
            color = ToolHandle.XAxisColor
        )

        mb.addCube(
            width = self._handle_width,
            height = self._handle_width,
            depth = self._handle_width,
            center = Vector(0, 0, self._handle_position),
            color = ToolHandle.ZAxisColor
        )
        self.setSolidMesh(mb.build())

        #SELECTIONMESH -> LINES
        mb = MeshBuilder()
        mb.addCube(
            width = self._active_line_width,
            height = self._active_line_length,
            depth = self._active_line_width,
            center = Vector(0, self._active_handle_position/2, 0),
            color = ToolHandle.YAxisColor
        )

        mb.addCube(
            width = self._active_line_length,
            height = self._active_line_width,
            depth = self._active_line_width,
            center = Vector(self._active_handle_position/2, 0, 0),
            color = ToolHandle.XAxisColor
        )

        mb.addCube(
            width = self._active_line_width,
            height = self._active_line_width,
            depth = self._active_line_length,
            center = Vector(0, 0, self._active_handle_position/2),
            color = ToolHandle.ZAxisColor
        )

        #SELECTIONMESH -> HANDLES
        mb.addCube(
            width = self._active_handle_width,
            height = self._active_handle_width,
            depth = self._active_handle_width,
            center = Vector(0, 0, 0),
            color = ToolHandle.AllAxisColor
        )

        mb.addCube(
            width = self._active_handle_width,
            height = self._active_handle_width,
            depth = self._active_handle_width,
            center = Vector(0, self._active_handle_position, 0),
            color = ToolHandle.YAxisColor
        )

        mb.addCube(
            width = self._active_handle_width,
            height = self._active_handle_width,
            depth = self._active_handle_width,
            center = Vector(self._active_handle_position, 0, 0),
            color = ToolHandle.XAxisColor
        )

        mb.addCube(
            width = self._active_handle_width,
            height = self._active_handle_width,
            depth = self._active_handle_width,
            center = Vector(0, 0, self._active_handle_position),
            color = ToolHandle.ZAxisColor
        )

        self.setSelectionMesh(mb.build())
Пример #19
0
    def run(self):
        if self._build_plate_number is None:
            self.setResult(StartJobResult.Error)
            return

        stack = Application.getInstance().getGlobalContainerStack()
        if not stack:
            self.setResult(StartJobResult.Error)
            return

        # Don't slice if there is a setting with an error value.
        if Application.getInstance().getMachineManager().stacksHaveErrors:
            self.setResult(StartJobResult.SettingError)
            return

        if Application.getInstance().getBuildVolume().hasErrors():
            self.setResult(StartJobResult.BuildPlateError)
            return

        # Don't slice if the buildplate or the nozzle type is incompatible with the materials
        if not Application.getInstance().getMachineManager().variantBuildplateCompatible and \
                not Application.getInstance().getMachineManager().variantBuildplateUsable:
            self.setResult(StartJobResult.MaterialIncompatible)
            return

        for position, extruder_stack in stack.extruders.items():
            material = extruder_stack.findContainer({"type": "material"})
            if not extruder_stack.isEnabled:
                continue
            if material:
                if material.getMetaDataEntry("compatible") == False:
                    self.setResult(StartJobResult.MaterialIncompatible)
                    return

        # Don't slice if there is a per object setting with an error value.
        for node in DepthFirstIterator(self._scene.getRoot()):
            if not isinstance(node, CuraSceneNode) or not node.isSelectable():
                continue

            if self._checkStackForErrors(node.callDecoration("getStack")):
                self.setResult(StartJobResult.ObjectSettingError)
                return

        with self._scene.getSceneLock():
            # Remove old layer data.
            for node in DepthFirstIterator(self._scene.getRoot()):
                if node.callDecoration("getLayerData") and node.callDecoration(
                        "getBuildPlateNumber") == self._build_plate_number:
                    node.getParent().removeChild(node)
                    break

            # Get the objects in their groups to print.
            object_groups = []
            if stack.getProperty("print_sequence", "value") == "one_at_a_time":
                for node in OneAtATimeIterator(self._scene.getRoot()):
                    temp_list = []

                    # Node can't be printed, so don't bother sending it.
                    if getattr(node, "_outside_buildarea", False):
                        continue

                    # Filter on current build plate
                    build_plate_number = node.callDecoration(
                        "getBuildPlateNumber")
                    if build_plate_number is not None and build_plate_number != self._build_plate_number:
                        continue

                    children = node.getAllChildren()
                    children.append(node)
                    for child_node in children:
                        if child_node.getMeshData() and child_node.getMeshData(
                        ).getVertices() is not None:
                            temp_list.append(child_node)

                    if temp_list:
                        object_groups.append(temp_list)
                    Job.yieldThread()
                if len(object_groups) == 0:
                    Logger.log(
                        "w",
                        "No objects suitable for one at a time found, or no correct order found"
                    )
            else:
                temp_list = []
                has_printing_mesh = False
                # print convex hull nodes as "faux-raft"
                print_convex_hulls = stack.getProperty("blackbelt_raft",
                                                       "value")
                for node in DepthFirstIterator(self._scene.getRoot()):
                    slice_node = (print_convex_hulls
                                  and type(node) is ConvexHullNode
                                  ) or node.callDecoration("isSliceable")
                    if slice_node and node.getMeshData() and node.getMeshData(
                    ).getVertices() is not None:
                        per_object_stack = node.callDecoration("getStack")
                        is_non_printing_mesh = False
                        if per_object_stack:
                            is_non_printing_mesh = any(
                                per_object_stack.getProperty(key, "value")
                                for key in NON_PRINTING_MESH_SETTINGS)

                        # Find a reason not to add the node
                        if node.callDecoration(
                                "getBuildPlateNumber"
                        ) != self._build_plate_number and type(
                                node) is not ConvexHullNode:
                            # NB: ConvexHullNodes get none of the usual decorators, so skip checking for them
                            continue
                        if getattr(node, "_outside_buildarea",
                                   False) and not is_non_printing_mesh:
                            continue

                        temp_list.append(node)
                        if not is_non_printing_mesh:
                            has_printing_mesh = True

                    Job.yieldThread()

                #If the list doesn't have any model with suitable settings then clean the list
                # otherwise CuraEngine will crash
                if not has_printing_mesh:
                    temp_list.clear()

                if temp_list:
                    object_groups.append(temp_list)

            extruders_enabled = {
                position: stack.isEnabled
                for position, stack in Application.getInstance().
                getGlobalContainerStack().extruders.items()
            }
            filtered_object_groups = []
            for group in object_groups:
                stack = Application.getInstance().getGlobalContainerStack()
                skip_group = False
                for node in group:
                    # ConvexHullNodes get none of the usual decorators. If it made it here, it is meant to be printed
                    if type(
                            node
                    ) is not ConvexHullNode and not extruders_enabled[
                            node.callDecoration("getActiveExtruderPosition")]:
                        skip_group = True
                        break
                if not skip_group:
                    filtered_object_groups.append(group)

            # There are cases when there is nothing to slice. This can happen due to one at a time slicing not being
            # able to find a possible sequence or because there are no objects on the build plate (or they are outside
            # the build volume)
            if not filtered_object_groups:
                self.setResult(StartJobResult.NothingToSlice)
                return

            container_registry = ContainerRegistry.getInstance()
            stack_id = stack.getId()

            # Adapt layer_height and material_flow for a slanted gantry
            gantry_angle = self._scene.getRoot().callDecoration(
                "getGantryAngle")
            if gantry_angle:  # not 0 or None
                # Act on a copy of the stack, so these changes don't cause a reslice
                _stack = CuraContainerStack(stack_id + "_temp")
                index = 0
                for container in stack.getContainers():
                    if container_registry.isReadOnly(container.getId()):
                        _stack.replaceContainer(index, container)
                    else:
                        _stack.replaceContainer(index,
                                                copy.deepcopy(container))
                    index = index + 1
                stack = _stack

                # Make sure CuraEngine does not create any supports
                # support_enable is set in the frontend so support options are settable,
                # but CuraEngine support structures don't work for slanted gantry
                stack.setProperty("support_enable", "value", False)
                # Make sure CuraEngine does not create a raft (we create one manually)
                # Adhsion type is used in the frontend to show the raft in the viewport
                stack.setProperty("adhesion_type", "value", "none")

                for key in ["layer_height", "layer_height_0"]:
                    current_value = stack.getProperty(key, "value")
                    stack.setProperty(key, "value",
                                      current_value / math.sin(gantry_angle))

            self._buildGlobalSettingsMessage(stack)
            self._buildGlobalInheritsStackMessage(stack)

            # Build messages for extruder stacks
            for position, extruder_stack in Application.getInstance(
            ).getGlobalContainerStack().extruders.items():
                if gantry_angle:  # not 0 or None
                    # Act on a copy of the stack, so these changes don't cause a reslice
                    _extruder_stack = CuraContainerStack(
                        extruder_stack.getId() + "_temp")
                    index = 0
                    for container in extruder_stack.getContainers():
                        if container_registry.isReadOnly(container.getId()):
                            _extruder_stack.replaceContainer(index, container)
                        else:
                            _extruder_stack.replaceContainer(
                                index, copy.deepcopy(container))
                        index = index + 1
                    extruder_stack = _extruder_stack
                    extruder_stack.setNextStack(stack)
                    for key in [
                            "material_flow", "prime_tower_flow",
                            "spaghetti_flow"
                    ]:
                        if extruder_stack.hasProperty(key, "value"):
                            current_value = extruder_stack.getProperty(
                                key, "value")
                            extruder_stack.setProperty(
                                key, "value",
                                current_value * math.sin(gantry_angle))
                self._buildExtruderMessage(extruder_stack)

            bottom_cutting_meshes = []
            raft_meshes = []
            if gantry_angle:  # not 0 or None
                # Add a modifier mesh to all printable meshes touching the belt
                for group in filtered_object_groups:
                    added_meshes = []
                    for object in group:

                        is_non_printing_mesh = False
                        per_object_stack = object.callDecoration("getStack")
                        if per_object_stack:
                            is_non_printing_mesh = any(
                                per_object_stack.getProperty(key, "value")
                                for key in NON_PRINTING_MESH_SETTINGS)

                        # ConvexHullNodes get none of the usual decorators. If it made it here, it is meant to be printed
                        if type(object) is ConvexHullNode:
                            raft_thickness = stack.getProperty(
                                "blackbelt_raft_thickness", "value")
                            raft_margin = stack.getProperty(
                                "blackbelt_raft_margin", "value")

                            mb = MeshBuilder()
                            hull_polygon = object.getHull()
                            if raft_margin > 0:
                                hull_polygon = hull_polygon.getMinkowskiHull(
                                    Polygon.approximatedCircle(raft_margin))
                            mb.addConvexPolygonExtrusion(
                                hull_polygon.getPoints()[::-1], 0,
                                raft_thickness)

                            new_node = self._addMesh(mb, "raftMesh")
                            added_meshes.append(new_node)
                            raft_meshes.append(new_node.getName())

                        elif not is_non_printing_mesh:
                            extruder_stack_index = object.callDecoration(
                                "getActiveExtruderPosition")
                            if not extruder_stack_index:
                                extruder_stack_index = 0
                            extruder_stack = ExtruderManager.getInstance(
                            ).getMachineExtruders(Application.getInstance(
                            ).getGlobalContainerStack().getId())[int(
                                extruder_stack_index)]

                            aabb = object.getBoundingBox()

                            if aabb.bottom < 0:
                                # mesh extends below the belt; add a cutting mesh to cut off the part below the bottom
                                height = -aabb.bottom
                                center = Vector(aabb.center.x, -height / 2,
                                                aabb.center.z)

                                mb = MeshBuilder()
                                mb.addCube(width=aabb.width,
                                           height=height,
                                           depth=aabb.depth,
                                           center=center)

                                new_node = self._addMesh(
                                    mb, "bottomCuttingMesh")
                                added_meshes.append(new_node)
                                bottom_cutting_meshes.append(
                                    new_node.getName())

                    if added_meshes:
                        group += added_meshes

            transform_matrix = self._scene.getRoot().callDecoration(
                "getTransformMatrix")
            front_offset = None

            raft_offset = 0
            raft_speed = None
            raft_flow = 1.0

            if stack.getProperty("blackbelt_raft", "value"):
                raft_offset = stack.getProperty(
                    "blackbelt_raft_thickness", "value") + stack.getProperty(
                        "blackbelt_raft_gap", "value")
                raft_speed = stack.getProperty("blackbelt_raft_speed", "value")
                raft_flow = stack.getProperty("blackbelt_raft_flow",
                                              "value") * math.sin(gantry_angle)

            for group in filtered_object_groups:
                group_message = self._slice_message.addRepeatedMessage(
                    "object_lists")
                if group[0].getParent() is not None and group[0].getParent(
                ).callDecoration("isGroup"):
                    self._handlePerObjectSettings(group[0].getParent(),
                                                  group_message)
                for object in group:
                    if type(object) is ConvexHullNode:
                        continue

                    mesh_data = object.getMeshData()
                    rot_scale = object.getWorldTransformation().getTransposed(
                    ).getData()[0:3, 0:3]
                    translate = object.getWorldTransformation().getData()[:3,
                                                                          3]
                    # offset all non-raft objects if rafts are enabled
                    # air gap is applied here to vertically offset objects from the raft
                    if object.getName() not in raft_meshes:
                        translate[1] = translate[1] + raft_offset

                    # This effectively performs a limited form of MeshData.getTransformed that ignores normals.
                    verts = mesh_data.getVertices()
                    verts = verts.dot(rot_scale)
                    verts += translate

                    if transform_matrix:
                        verts = transformVertices(verts, transform_matrix)

                        is_non_printing_mesh = object.getName(
                        ) in bottom_cutting_meshes or object.getName(
                        ) in raft_meshes
                        if not is_non_printing_mesh:
                            per_object_stack = object.callDecoration(
                                "getStack")
                            if per_object_stack:
                                is_non_printing_mesh = any(
                                    per_object_stack.getProperty(key, "value")
                                    for key in NON_PRINTING_MESH_SETTINGS)

                        if not is_non_printing_mesh:
                            _front_offset = verts[:, 1].min()
                            if front_offset is None or _front_offset < front_offset:
                                front_offset = _front_offset

                    # Convert from Y up axes to Z up axes. Equals a 90 degree rotation.
                    verts[:, [1, 2]] = verts[:, [2, 1]]
                    verts[:, 1] *= -1

                    obj = group_message.addRepeatedMessage("objects")
                    obj.id = id(object)

                    indices = mesh_data.getIndices()
                    if indices is not None:
                        flat_verts = numpy.take(verts,
                                                indices.flatten(),
                                                axis=0)
                    else:
                        flat_verts = numpy.array(verts)

                    obj.vertices = flat_verts

                    if object.getName() in raft_meshes:
                        self._addSettingsMessage(
                            obj, {
                                "wall_line_count": 99999999,
                                "speed_wall_0": raft_speed,
                                "speed_wall_x": raft_speed,
                                "material_flow": raft_flow
                            })

                    elif object.getName() in bottom_cutting_meshes:
                        self._addSettingsMessage(
                            obj, {
                                "cutting_mesh": True,
                                "wall_line_count": 0,
                                "top_layers": 0,
                                "bottom_layers": 0,
                                "infill_line_distance": 0
                            })

                    else:
                        self._handlePerObjectSettings(object, obj)
                        Job.yieldThread()

                # Store the front-most coordinate of the scene so the scene can be moved back into place post slicing
                # TODO: this should be handled per mesh-group instead of per scene
                # One-at-a-time printing should be disabled for slanted gantry printers for now
                self._scene.getRoot().callDecoration("setSceneFrontOffset",
                                                     front_offset)

        self.setResult(StartJobResult.Finished)
Пример #20
0
    def __init__(self, parent=None):
        super().__init__(parent)

        self._line_width = 0.5
        self._line_length = 40
        self._handle_position = 40
        self._handle_width = 4

        self._active_line_width = 0.8
        self._active_line_length = 40
        self._active_handle_position = 40
        self._active_handle_width = 15

        #SOLIDMESH -> LINES
        mb = MeshBuilder()

        mb.addCube(width=self._line_width,
                   height=self._line_length,
                   depth=self._line_width,
                   center=Vector(0, self._handle_position / 2, 0),
                   color=ToolHandle.YAxisColor)
        mb.addCube(width=self._line_length,
                   height=self._line_width,
                   depth=self._line_width,
                   center=Vector(self._handle_position / 2, 0, 0),
                   color=ToolHandle.XAxisColor)

        mb.addCube(width=self._line_width,
                   height=self._line_width,
                   depth=self._line_length,
                   center=Vector(0, 0, self._handle_position / 2),
                   color=ToolHandle.ZAxisColor)

        #SOLIDMESH -> HANDLES
        mb.addCube(width=self._handle_width,
                   height=self._handle_width,
                   depth=self._handle_width,
                   center=Vector(0, 0, 0),
                   color=ToolHandle.AllAxisColor)

        mb.addCube(width=self._handle_width,
                   height=self._handle_width,
                   depth=self._handle_width,
                   center=Vector(0, self._handle_position, 0),
                   color=ToolHandle.YAxisColor)

        mb.addCube(width=self._handle_width,
                   height=self._handle_width,
                   depth=self._handle_width,
                   center=Vector(self._handle_position, 0, 0),
                   color=ToolHandle.XAxisColor)

        mb.addCube(width=self._handle_width,
                   height=self._handle_width,
                   depth=self._handle_width,
                   center=Vector(0, 0, self._handle_position),
                   color=ToolHandle.ZAxisColor)
        self.setSolidMesh(mb.getData())

        #SELECTIONMESH -> LINES
        mb = MeshBuilder()
        mb.addCube(width=self._active_line_width,
                   height=self._active_line_length,
                   depth=self._active_line_width,
                   center=Vector(0, self._active_handle_position / 2, 0),
                   color=ToolHandle.YAxisColor)

        mb.addCube(width=self._active_line_length,
                   height=self._active_line_width,
                   depth=self._active_line_width,
                   center=Vector(self._active_handle_position / 2, 0, 0),
                   color=ToolHandle.XAxisColor)

        mb.addCube(width=self._active_line_width,
                   height=self._active_line_width,
                   depth=self._active_line_length,
                   center=Vector(0, 0, self._active_handle_position / 2),
                   color=ToolHandle.ZAxisColor)

        #SELECTIONMESH -> HANDLES
        mb.addCube(width=self._active_handle_width,
                   height=self._active_handle_width,
                   depth=self._active_handle_width,
                   center=Vector(0, 0, 0),
                   color=ToolHandle.AllAxisColor)

        mb.addCube(width=self._active_handle_width,
                   height=self._active_handle_width,
                   depth=self._active_handle_width,
                   center=Vector(0, self._active_handle_position, 0),
                   color=ToolHandle.YAxisColor)

        mb.addCube(width=self._active_handle_width,
                   height=self._active_handle_width,
                   depth=self._active_handle_width,
                   center=Vector(self._active_handle_position, 0, 0),
                   color=ToolHandle.XAxisColor)

        mb.addCube(width=self._active_handle_width,
                   height=self._active_handle_width,
                   depth=self._active_handle_width,
                   center=Vector(0, 0, self._active_handle_position),
                   color=ToolHandle.ZAxisColor)

        self.setSelectionMesh(mb.getData())
Пример #21
0
    def __init__(self, parent = None):
        super().__init__(parent)

        lines = MeshData()
        lines.addVertex(0, 0, 0)
        lines.addVertex(0, 20, 0)
        lines.addVertex(0, 0, 0)
        lines.addVertex(20, 0, 0)
        lines.addVertex(0, 0, 0)
        lines.addVertex(0, 0, 20)

        lines.setVertexColor(0, ToolHandle.YAxisColor)
        lines.setVertexColor(1, ToolHandle.YAxisColor)
        lines.setVertexColor(2, ToolHandle.XAxisColor)
        lines.setVertexColor(3, ToolHandle.XAxisColor)
        lines.setVertexColor(4, ToolHandle.ZAxisColor)
        lines.setVertexColor(5, ToolHandle.ZAxisColor)

        self.setLineMesh(lines)

        mb = MeshBuilder()

        mb.addCube(
            width = 2,
            height = 2,
            depth = 2,
            center = Vector(0, 0, 0),
            color = ToolHandle.AllAxisColor
        )

        mb.addCube(
            width = 2,
            height = 2,
            depth = 2,
            center = Vector(0, 20, 0),
            color = ToolHandle.YAxisColor
        )

        mb.addCube(
            width = 2,
            height = 2,
            depth = 2,
            center = Vector(20, 0, 0),
            color = ToolHandle.XAxisColor
        )

        mb.addCube(
            width = 2,
            height = 2,
            depth = 2,
            center = Vector(0, 0, 20),
            color = ToolHandle.ZAxisColor
        )

        self.setSolidMesh(mb.getData())

        mb = MeshBuilder()

        mb.addCube(
            width = 4,
            height = 20,
            depth = 4,
            center = Vector(0, 10, 0),
            color = ToolHandle.YAxisColor
        )

        mb.addCube(
            width = 4,
            height = 4,
            depth = 4,
            center = Vector(0, 20, 0),
            color = ToolHandle.YAxisColor
        )

        mb.addCube(
            width = 20,
            height = 4,
            depth = 4,
            center = Vector(10, 0, 0),
            color = ToolHandle.XAxisColor
        )

        mb.addCube(
            width = 4,
            height = 4,
            depth = 4,
            center = Vector(20, 0, 0),
            color = ToolHandle.XAxisColor
        )

        mb.addCube(
            width = 4,
            height = 4,
            depth = 20,
            center = Vector(0, 0, 10),
            color = ToolHandle.ZAxisColor
        )

        mb.addCube(
            width = 4,
            height = 4,
            depth = 4,
            center = Vector(0, 0, 20),
            color = ToolHandle.ZAxisColor
        )

        mb.addCube(
            width = 8,
            height = 8,
            depth = 8,
            center = Vector(0, 0, 0),
            color = ToolHandle.AllAxisColor
        )

        self.setSelectionMesh(mb.getData())
Пример #22
0
    def _rebuild(self):
        mb = MeshBuilder()

        #SOLIDMESH -> LINES
        if self.YAxis in self._enabled_axis:
            mb.addCube(width=self._lineWidth,
                       height=self._lineLength,
                       depth=self._lineWidth,
                       center=Vector(0, self._handlePosition / 2, 0),
                       color=ToolHandle.YAxisColor)
        if self.XAxis in self._enabled_axis:
            mb.addCube(width=self._lineLength,
                       height=self._lineWidth,
                       depth=self._lineWidth,
                       center=Vector(self._handlePosition / 2, 0, 0),
                       color=ToolHandle.XAxisColor)

        if self.ZAxis in self._enabled_axis:
            mb.addCube(width=self._lineWidth,
                       height=self._lineWidth,
                       depth=self._lineLength,
                       center=Vector(0, 0, self._handlePosition / 2),
                       color=ToolHandle.ZAxisColor)

        #SOLIDMESH -> HANDLES
        if self.YAxis in self._enabled_axis:
            mb.addPyramid(width=self._handleWidth,
                          height=self._handleHeight,
                          depth=self._handleWidth,
                          center=Vector(0, self._handlePosition, 0),
                          color=ToolHandle.YAxisColor)

        if self.XAxis in self._enabled_axis:
            mb.addPyramid(width=self._handleWidth,
                          height=self._handleHeight,
                          depth=self._handleWidth,
                          center=Vector(self._handlePosition, 0, 0),
                          color=ToolHandle.XAxisColor,
                          axis=Vector.Unit_Z,
                          angle=90)

        if self.ZAxis in self._enabled_axis:
            mb.addPyramid(width=self._handleWidth,
                          height=self._handleHeight,
                          depth=self._handleWidth,
                          center=Vector(0, 0, self._handlePosition),
                          color=ToolHandle.ZAxisColor,
                          axis=Vector.Unit_X,
                          angle=-90)

        self.setSolidMesh(mb.getData())

        mb = MeshBuilder()
        #ACTIVEMESH -> LINES
        if self.YAxis in self._enabled_axis:
            mb.addCube(width=self._activeLineWidth,
                       height=self._activeLineLength,
                       depth=self._activeLineWidth,
                       center=Vector(0, self._activeHandlePosition / 2, 0),
                       color=ToolHandle.YAxisColor)
        if self.XAxis in self._enabled_axis:
            mb.addCube(width=self._activeLineLength,
                       height=self._activeLineWidth,
                       depth=self._activeLineWidth,
                       center=Vector(self._activeHandlePosition / 2, 0, 0),
                       color=ToolHandle.XAxisColor)

        if self.ZAxis in self._enabled_axis:
            mb.addCube(width=self._activeLineWidth,
                       height=self._activeLineWidth,
                       depth=self._activeLineLength,
                       center=Vector(0, 0, self._activeHandlePosition / 2),
                       color=ToolHandle.ZAxisColor)

        #SELECTIONMESH -> HANDLES
        mb.addCube(width=self._activeHandleWidth,
                   height=self._activeHandleWidth,
                   depth=self._activeHandleWidth,
                   center=Vector(0, 0, 0),
                   color=ToolHandle.AllAxisColor)

        mb.addCube(width=self._activeHandleWidth,
                   height=self._activeHandleWidth,
                   depth=self._activeHandleWidth,
                   center=Vector(0, self._activeHandlePosition, 0),
                   color=ToolHandle.YAxisColor)

        mb.addCube(width=self._activeHandleWidth,
                   height=self._activeHandleWidth,
                   depth=self._activeHandleWidth,
                   center=Vector(self._activeHandlePosition, 0, 0),
                   color=ToolHandle.XAxisColor)

        mb.addCube(width=self._activeHandleWidth,
                   height=self._activeHandleWidth,
                   depth=self._activeHandleWidth,
                   center=Vector(0, 0, self._activeHandlePosition),
                   color=ToolHandle.ZAxisColor)
        self.setSelectionMesh(mb.getData())
Пример #23
0
    def _rebuild(self):
        if not self._build_volume._width or not self._build_volume._height or not self._build_volume._depth:
            return

        if not self._build_volume._engine_ready:
            return

        if not self._build_volume._volume_outline_color:
            theme = Application.getInstance().getTheme()
            self._build_volume._volume_outline_color = Color(
                *theme.getColor("volume_outline").getRgb())
            self._build_volume._x_axis_color = Color(
                *theme.getColor("x_axis").getRgb())
            self._build_volume._y_axis_color = Color(
                *theme.getColor("y_axis").getRgb())
            self._build_volume._z_axis_color = Color(
                *theme.getColor("z_axis").getRgb())
            self._build_volume._disallowed_area_color = Color(
                *theme.getColor("disallowed_area").getRgb())
            self._build_volume._error_area_color = Color(
                *theme.getColor("error_area").getRgb())

        ### START PATCH
        # Get a dict from the machine metadata optionally overriding the build volume
        # Note that CuraEngine is blissfully unaware of this; it is just what the user is shown in Cura
        limit_buildvolume = self._build_volume._global_container_stack.getMetaDataEntry(
            "limit_buildvolume", {})
        if not isinstance(limit_buildvolume, dict):
            limit_buildvolume = {}

        min_w = limit_buildvolume.get("width",
                                      {}).get("minimum",
                                              -self._build_volume._width / 2)
        max_w = limit_buildvolume.get("width",
                                      {}).get("maximum",
                                              self._build_volume._width / 2)
        min_h = limit_buildvolume.get("height", {}).get("minimum", 0.0)
        max_h = limit_buildvolume.get("height",
                                      {}).get("maximum",
                                              self._build_volume._height)
        min_d = limit_buildvolume.get("depth",
                                      {}).get("minimum",
                                              -self._build_volume._depth / 2)
        max_d = limit_buildvolume.get("depth",
                                      {}).get("maximum",
                                              self._build_volume._depth / 2)
        ### END PATCH

        z_fight_distance = 0.2  # Distance between buildplate and disallowed area meshes to prevent z-fighting

        if self._build_volume._shape != "elliptic":
            # Outline 'cube' of the build volume
            mb = MeshBuilder()
            mb.addLine(Vector(min_w, min_h, min_d),
                       Vector(max_w, min_h, min_d),
                       color=self._build_volume._volume_outline_color)
            mb.addLine(Vector(min_w, min_h, min_d),
                       Vector(min_w, max_h, min_d),
                       color=self._build_volume._volume_outline_color)
            mb.addLine(Vector(min_w, max_h, min_d),
                       Vector(max_w, max_h, min_d),
                       color=self._build_volume._volume_outline_color)
            mb.addLine(Vector(max_w, min_h, min_d),
                       Vector(max_w, max_h, min_d),
                       color=self._build_volume._volume_outline_color)

            mb.addLine(Vector(min_w, min_h, max_d),
                       Vector(max_w, min_h, max_d),
                       color=self._build_volume._volume_outline_color)
            mb.addLine(Vector(min_w, min_h, max_d),
                       Vector(min_w, max_h, max_d),
                       color=self._build_volume._volume_outline_color)
            mb.addLine(Vector(min_w, max_h, max_d),
                       Vector(max_w, max_h, max_d),
                       color=self._build_volume._volume_outline_color)
            mb.addLine(Vector(max_w, min_h, max_d),
                       Vector(max_w, max_h, max_d),
                       color=self._build_volume._volume_outline_color)

            mb.addLine(Vector(min_w, min_h, min_d),
                       Vector(min_w, min_h, max_d),
                       color=self._build_volume._volume_outline_color)
            mb.addLine(Vector(max_w, min_h, min_d),
                       Vector(max_w, min_h, max_d),
                       color=self._build_volume._volume_outline_color)
            mb.addLine(Vector(min_w, max_h, min_d),
                       Vector(min_w, max_h, max_d),
                       color=self._build_volume._volume_outline_color)
            mb.addLine(Vector(max_w, max_h, min_d),
                       Vector(max_w, max_h, max_d),
                       color=self._build_volume._volume_outline_color)

            self._build_volume.setMeshData(mb.build())

            # Build plate grid mesh
            mb = MeshBuilder()
            mb.addQuad(Vector(min_w, min_h - z_fight_distance, min_d),
                       Vector(max_w, min_h - z_fight_distance, min_d),
                       Vector(max_w, min_h - z_fight_distance, max_d),
                       Vector(min_w, min_h - z_fight_distance, max_d))

            for n in range(0, 6):
                v = mb.getVertex(n)
                mb.setVertexUVCoordinates(n, v[0], v[2])
            self._build_volume._grid_mesh = mb.build()

        else:
            # Bottom and top 'ellipse' of the build volume
            aspect = 1.0
            scale_matrix = Matrix()
            if self._build_volume._width != 0:
                # Scale circular meshes by aspect ratio if width != height
                aspect = self._build_volume._depth / self._build_volume._width
                scale_matrix.compose(scale=Vector(1, 1, aspect))
            mb = MeshBuilder()
            mb.addArc(max_w,
                      Vector.Unit_Y,
                      center=(0, min_h - z_fight_distance, 0),
                      color=self._build_volume._volume_outline_color)
            mb.addArc(max_w,
                      Vector.Unit_Y,
                      center=(0, max_h, 0),
                      color=self._build_volume._volume_outline_color)
            self._build_volume.setMeshData(
                mb.build().getTransformed(scale_matrix))

            # Build plate grid mesh
            mb = MeshBuilder()
            mb.addVertex(0, min_h - z_fight_distance, 0)
            mb.addArc(max_w,
                      Vector.Unit_Y,
                      center=Vector(0, min_h - z_fight_distance, 0))
            sections = mb.getVertexCount(
            ) - 1  # Center point is not an arc section
            indices = []
            for n in range(0, sections - 1):
                indices.append([0, n + 2, n + 1])
            mb.addIndices(numpy.asarray(indices, dtype=numpy.int32))
            mb.calculateNormals()

            for n in range(0, mb.getVertexCount()):
                v = mb.getVertex(n)
                mb.setVertexUVCoordinates(n, v[0], v[2] * aspect)
            self._build_volume._grid_mesh = mb.build().getTransformed(
                scale_matrix)

        # Indication of the machine origin
        if self._build_volume._global_container_stack.getProperty(
                "machine_center_is_zero", "value"):
            origin = (Vector(min_w, min_h, min_d) +
                      Vector(max_w, min_h, max_d)) / 2
        else:
            origin = Vector(min_w, min_h, max_d)

        mb = MeshBuilder()
        mb.addCube(width=self._build_volume._origin_line_length,
                   height=self._build_volume._origin_line_width,
                   depth=self._build_volume._origin_line_width,
                   center=origin +
                   Vector(self._build_volume._origin_line_length / 2, 0, 0),
                   color=self._build_volume._x_axis_color)
        mb.addCube(width=self._build_volume._origin_line_width,
                   height=self._build_volume._origin_line_length,
                   depth=self._build_volume._origin_line_width,
                   center=origin +
                   Vector(0, self._build_volume._origin_line_length / 2, 0),
                   color=self._build_volume._y_axis_color)
        mb.addCube(width=self._build_volume._origin_line_width,
                   height=self._build_volume._origin_line_width,
                   depth=self._build_volume._origin_line_length,
                   center=origin -
                   Vector(0, 0, self._build_volume._origin_line_length / 2),
                   color=self._build_volume._z_axis_color)
        self._build_volume._origin_mesh = mb.build()

        disallowed_area_height = 0.1
        disallowed_area_size = 0
        if self._build_volume._disallowed_areas:
            mb = MeshBuilder()
            color = self._build_volume._disallowed_area_color
            for polygon in self._build_volume._disallowed_areas:
                points = polygon.getPoints()
                if len(points) == 0:
                    continue

                first = Vector(
                    self._build_volume._clamp(points[0][0], min_w, max_w),
                    disallowed_area_height,
                    self._build_volume._clamp(points[0][1], min_d, max_d))
                previous_point = Vector(
                    self._build_volume._clamp(points[0][0], min_w, max_w),
                    disallowed_area_height,
                    self._build_volume._clamp(points[0][1], min_d, max_d))
                for point in points:
                    new_point = Vector(
                        self._build_volume._clamp(point[0], min_w, max_w),
                        disallowed_area_height,
                        self._build_volume._clamp(point[1], min_d, max_d))
                    mb.addFace(first, previous_point, new_point, color=color)
                    previous_point = new_point

                # Find the largest disallowed area to exclude it from the maximum scale bounds.
                # This is a very nasty hack. This pretty much only works for UM machines.
                # This disallowed area_size needs a -lot- of rework at some point in the future: TODO
                if numpy.min(
                        points[:, 1]
                ) >= 0:  # This filters out all areas that have points to the left of the centre. This is done to filter the skirt area.
                    size = abs(
                        numpy.max(points[:, 1]) - numpy.min(points[:, 1]))
                else:
                    size = 0
                disallowed_area_size = max(size, disallowed_area_size)

            self._build_volume._disallowed_area_mesh = mb.build()
        else:
            self._build_volume._disallowed_area_mesh = None

        if self._build_volume._error_areas:
            mb = MeshBuilder()
            for error_area in self._build_volume._error_areas:
                color = self._build_volume._error_area_color
                points = error_area.getPoints()
                first = Vector(
                    self._build_volume._clamp(points[0][0], min_w, max_w),
                    disallowed_area_height,
                    self._build_volume._clamp(points[0][1], min_d, max_d))
                previous_point = Vector(
                    self._build_volume._clamp(points[0][0], min_w, max_w),
                    disallowed_area_height,
                    self._build_volume._clamp(points[0][1], min_d, max_d))
                for point in points:
                    new_point = Vector(
                        self._build_volume._clamp(point[0], min_w, max_w),
                        disallowed_area_height,
                        self._build_volume._clamp(point[1], min_d, max_d))
                    mb.addFace(first, previous_point, new_point, color=color)
                    previous_point = new_point
            self._build_volume._error_mesh = mb.build()
        else:
            self._build_volume._error_mesh = None

        self._build_volume._volume_aabb = AxisAlignedBox(
            minimum=Vector(min_w, min_h - 1.0, min_d),
            maximum=Vector(
                max_w, max_h - self._build_volume._raft_thickness -
                self._build_volume._extra_z_clearance, max_d))

        bed_adhesion_size = self._build_volume.getEdgeDisallowedSize()

        # As this works better for UM machines, we only add the disallowed_area_size for the z direction.
        # This is probably wrong in all other cases. TODO!
        # The +1 and -1 is added as there is always a bit of extra room required to work properly.
        scale_to_max_bounds = AxisAlignedBox(
            minimum=Vector(
                min_w + bed_adhesion_size + 1, min_h,
                min_d + disallowed_area_size - bed_adhesion_size + 1),
            maximum=Vector(
                max_w - bed_adhesion_size - 1,
                max_h - self._build_volume._raft_thickness -
                self._build_volume._extra_z_clearance,
                max_d - disallowed_area_size + bed_adhesion_size - 1))

        Application.getInstance().getController().getScene(
        )._maximum_bounds = scale_to_max_bounds

        self._build_volume.updateNodeBoundaryCheck()
Пример #24
0
    def rebuild(self):
        if not self._width or not self._height or not self._depth:
            return

        min_w = -self._width / 2
        max_w = self._width / 2
        min_h = 0.0
        max_h = self._height
        min_d = -self._depth / 2
        max_d = self._depth / 2

        mb = MeshBuilder()

        # Outline 'cube' of the build volume
        mb.addLine(Vector(min_w, min_h, min_d), Vector(max_w, min_h, min_d), color = self.VolumeOutlineColor)
        mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, max_h, min_d), color = self.VolumeOutlineColor)
        mb.addLine(Vector(min_w, max_h, min_d), Vector(max_w, max_h, min_d), color = self.VolumeOutlineColor)
        mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, max_h, min_d), color = self.VolumeOutlineColor)

        mb.addLine(Vector(min_w, min_h, max_d), Vector(max_w, min_h, max_d), color = self.VolumeOutlineColor)
        mb.addLine(Vector(min_w, min_h, max_d), Vector(min_w, max_h, max_d), color = self.VolumeOutlineColor)
        mb.addLine(Vector(min_w, max_h, max_d), Vector(max_w, max_h, max_d), color = self.VolumeOutlineColor)
        mb.addLine(Vector(max_w, min_h, max_d), Vector(max_w, max_h, max_d), color = self.VolumeOutlineColor)

        mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, min_h, max_d), color = self.VolumeOutlineColor)
        mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, min_h, max_d), color = self.VolumeOutlineColor)
        mb.addLine(Vector(min_w, max_h, min_d), Vector(min_w, max_h, max_d), color = self.VolumeOutlineColor)
        mb.addLine(Vector(max_w, max_h, min_d), Vector(max_w, max_h, max_d), color = self.VolumeOutlineColor)

        self.setMeshData(mb.build())

        mb = MeshBuilder()

        # Indication of the machine origin
        if self._global_container_stack.getProperty("machine_center_is_zero", "value"):
            origin = (Vector(min_w, min_h, min_d) + Vector(max_w, min_h, max_d)) / 2
        else:
            origin = Vector(min_w, min_h, max_d)

        mb.addCube(
            width = self._origin_line_length,
            height = self._origin_line_width,
            depth = self._origin_line_width,
            center = origin + Vector(self._origin_line_length / 2, 0, 0),
            color = self.XAxisColor
        )
        mb.addCube(
            width = self._origin_line_width,
            height = self._origin_line_length,
            depth = self._origin_line_width,
            center = origin + Vector(0, self._origin_line_length / 2, 0),
            color = self.YAxisColor
        )
        mb.addCube(
            width = self._origin_line_width,
            height = self._origin_line_width,
            depth = self._origin_line_length,
            center = origin - Vector(0, 0, self._origin_line_length / 2),
            color = self.ZAxisColor
        )
        self._origin_mesh = mb.build()

        mb = MeshBuilder()
        mb.addQuad(
            Vector(min_w, min_h - 0.2, min_d),
            Vector(max_w, min_h - 0.2, min_d),
            Vector(max_w, min_h - 0.2, max_d),
            Vector(min_w, min_h - 0.2, max_d)
        )

        for n in range(0, 6):
            v = mb.getVertex(n)
            mb.setVertexUVCoordinates(n, v[0], v[2])
        self._grid_mesh = mb.build()

        disallowed_area_height = 0.1
        disallowed_area_size = 0
        if self._disallowed_areas:
            mb = MeshBuilder()
            color = Color(0.0, 0.0, 0.0, 0.15)
            for polygon in self._disallowed_areas:
                points = polygon.getPoints()
                first = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._clamp(points[0][1], min_d, max_d))
                previous_point = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._clamp(points[0][1], min_d, max_d))
                for point in points:
                    new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height, self._clamp(point[1], min_d, max_d))
                    mb.addFace(first, previous_point, new_point, color = color)
                    previous_point = new_point

                # Find the largest disallowed area to exclude it from the maximum scale bounds.
                # This is a very nasty hack. This pretty much only works for UM machines.
                # This disallowed area_size needs a -lot- of rework at some point in the future: TODO
                if numpy.min(points[:, 1]) >= 0: # This filters out all areas that have points to the left of the centre. This is done to filter the skirt area.
                    size = abs(numpy.max(points[:, 1]) - numpy.min(points[:, 1]))
                else:
                    size = 0
                disallowed_area_size = max(size, disallowed_area_size)

            self._disallowed_area_mesh = mb.build()
        else:
            self._disallowed_area_mesh = None

        if self._error_areas:
            mb = MeshBuilder()
            for error_area in self._error_areas:
                color = Color(1.0, 0.0, 0.0, 0.5)
                points = error_area.getPoints()
                first = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
                               self._clamp(points[0][1], min_d, max_d))
                previous_point = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height,
                                        self._clamp(points[0][1], min_d, max_d))
                for point in points:
                    new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height,
                                       self._clamp(point[1], min_d, max_d))
                    mb.addFace(first, previous_point, new_point, color=color)
                    previous_point = new_point
            self._error_mesh = mb.build()
        else:
            self._error_mesh = None

        self._volume_aabb = AxisAlignedBox(
            minimum = Vector(min_w, min_h - 1.0, min_d),
            maximum = Vector(max_w, max_h - self._raft_thickness, max_d))

        bed_adhesion_size = self._getEdgeDisallowedSize()

        # As this works better for UM machines, we only add the disallowed_area_size for the z direction.
        # This is probably wrong in all other cases. TODO!
        # The +1 and -1 is added as there is always a bit of extra room required to work properly.
        scale_to_max_bounds = AxisAlignedBox(
            minimum = Vector(min_w + bed_adhesion_size + 1, min_h, min_d + disallowed_area_size - bed_adhesion_size + 1),
            maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness, max_d - disallowed_area_size + bed_adhesion_size - 1)
        )

        Application.getInstance().getController().getScene()._maximum_bounds = scale_to_max_bounds
Пример #25
0
    def _rebuild(self):
        mb = MeshBuilder()

        #SOLIDMESH -> LINES
        if self.YAxis in self._enabled_axis:
            mb.addCube(
                width = self._lineWidth,
                height = self._lineLength,
                depth = self._lineWidth,
                center = Vector(0, self._handlePosition/2, 0),
                color = ToolHandle.YAxisColor
            )
        if self.XAxis in self._enabled_axis:
            mb.addCube(
                width = self._lineLength,
                height = self._lineWidth,
                depth = self._lineWidth,
                center = Vector(self._handlePosition/2, 0, 0),
                color = ToolHandle.XAxisColor
            )

        if self.ZAxis in self._enabled_axis:
            mb.addCube(
                width = self._lineWidth,
                height = self._lineWidth,
                depth = self._lineLength,
                center = Vector(0, 0, self._handlePosition/2),
                color = ToolHandle.ZAxisColor
            )

        #SOLIDMESH -> HANDLES
        if self.YAxis in self._enabled_axis:
            mb.addPyramid(
                width = self._handleWidth,
                height = self._handleHeight,
                depth = self._handleWidth,
                center = Vector(0, self._handlePosition, 0),
                color = ToolHandle.YAxisColor
            )

        if self.XAxis in self._enabled_axis:
            mb.addPyramid(
                width = self._handleWidth,
                height = self._handleHeight,
                depth = self._handleWidth,
                center = Vector(self._handlePosition, 0, 0),
                color = ToolHandle.XAxisColor,
                axis = Vector.Unit_Z,
                angle = 90
            )

        if self.ZAxis in self._enabled_axis:
            mb.addPyramid(
                width = self._handleWidth,
                height = self._handleHeight,
                depth = self._handleWidth,
                center = Vector(0, 0, self._handlePosition),
                color = ToolHandle.ZAxisColor,
                axis = Vector.Unit_X,
                angle = -90
            )

        self.setSolidMesh(mb.getData())

        mb = MeshBuilder()
        #ACTIVEMESH -> LINES
        if self.YAxis in self._enabled_axis:
            mb.addCube(
                width = self._activeLineWidth,
                height = self._activeLineLength,
                depth = self._activeLineWidth,
                center = Vector(0, self._activeHandlePosition/2, 0),
                color = ToolHandle.YAxisColor
            )
        if self.XAxis in self._enabled_axis:
            mb.addCube(
                width = self._activeLineLength,
                height = self._activeLineWidth,
                depth = self._activeLineWidth,
                center = Vector(self._activeHandlePosition/2, 0, 0),
                color = ToolHandle.XAxisColor
            )

        if self.ZAxis in self._enabled_axis:
            mb.addCube(
                width = self._activeLineWidth,
                height = self._activeLineWidth,
                depth = self._activeLineLength,
                center = Vector(0, 0, self._activeHandlePosition/2),
                color = ToolHandle.ZAxisColor
            )

        #SELECTIONMESH -> HANDLES
        mb.addCube(
            width = self._activeHandleWidth,
            height = self._activeHandleWidth,
            depth = self._activeHandleWidth,
            center = Vector(0, 0, 0),
            color = ToolHandle.AllAxisColor
        )

        mb.addCube(
            width = self._activeHandleWidth,
            height = self._activeHandleWidth,
            depth = self._activeHandleWidth,
            center = Vector(0, self._activeHandlePosition, 0),
            color = ToolHandle.YAxisColor
        )

        mb.addCube(
            width = self._activeHandleWidth,
            height = self._activeHandleWidth,
            depth = self._activeHandleWidth,
            center = Vector(self._activeHandlePosition, 0, 0),
            color = ToolHandle.XAxisColor
        )

        mb.addCube(
            width = self._activeHandleWidth,
            height = self._activeHandleWidth,
            depth = self._activeHandleWidth,
            center = Vector(0, 0, self._activeHandlePosition),
            color = ToolHandle.ZAxisColor
        )
        self.setSelectionMesh(mb.getData())
Пример #26
0
    def beginRendering(self):
        # Convenience setup
        scene = self.getController().getScene()
        renderer = self.getRenderer()

        if not self._shader:
            self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "color.shader"))
            self._shader.setUniformValue("u_color", Color(32, 32, 32, 170))

        for node in DepthFirstIterator(scene.getRoot()):
            if not node.render(renderer):
                # For now we only render nodes that indicate that they need rendering.
                if node.getMeshData():
                    # Render origin of this node.
                    renderer.queueNode(scene.getRoot(), mesh = self._getAxisMesh(node), transparent = True)

                    # Render transparent MeshData
                    renderer.queueNode(node, shader = self._shader, transparent = True)

                    billboard_node = self._ensureNodeHasBillboard(node)

                    # Update the displayed data on the billboard.
                    data = self._matrixToHtml(node.getLocalTransformation())
                    billboard_node.setDisplayData({"name": node.getName(), "matrix": data, "depth": node.getDepth(), "parent_name": node.getParent().getName(), "has_mesh": "True"})

                # Handle group nodes
                if node.callDecoration("isGroup"):
                    # Render origin of this node.
                    renderer.queueNode(scene.getRoot(), mesh=self._getAxisMesh(node), transparent = True)
                    # Render bounding box of this node
                    renderer.queueNode(scene.getRoot(), mesh=node.getBoundingBoxMesh(), mode=Renderer.RenderLines)

                    billboard_node = self._ensureNodeHasBillboard(node)

                    # Update the displayed data on the billboard.
                    data = self._matrixToHtml(node.getLocalTransformation())
                    billboard_node.setDisplayData({"name": node.getName(), "matrix": data, "depth": node.getDepth(), "parent_name": node.getParent().getName(), "has_mesh": node.getMeshData() is not None})

                # We sometimes have nodes that are not groups, but have children. Also draw them
                elif not node.getMeshData() and len(node.getChildren()) != 0:
                    # Render origin of this node.
                    renderer.queueNode(scene.getRoot(), mesh=self._getAxisMesh(node), transparent = True)

                    billboard_node = self._ensureNodeHasBillboard(node)

                    # Update the displayed data on the billboard.
                    data = self._matrixToHtml(node.getLocalTransformation())
                    parent_name = node.getParent().getName() if node.getParent() else ""
                    billboard_node.setDisplayData({"name": node.getName(), "matrix": data, "depth": node.getDepth(), "parent_name": parent_name, "has_mesh": "False"})
                    bounding_box = node.getBoundingBox()
                    if bounding_box:
                        mesh_builder = MeshBuilder()
                        mesh_builder.addCube(
                            width=bounding_box.width,
                            height=bounding_box.height,
                            depth=bounding_box.depth,
                            center=bounding_box.center,
                            color=Color(0.0, 0.0, 1.0, 1.0)
                        )
                        mesh = mesh_builder.build()
                        renderer.queueNode(scene.getRoot(), mesh=mesh, mode=Renderer.RenderLines)
Пример #27
0
    def run(self) -> None:
        if self._build_plate_number is None:
            self.setResult(StartJobResult.Error)
            return

        stack = CuraApplication.getInstance().getGlobalContainerStack()
        if not stack:
            self.setResult(StartJobResult.Error)
            return

        # Don't slice if there is a setting with an error value.
        if CuraApplication.getInstance().getMachineManager().stacksHaveErrors:
            self.setResult(StartJobResult.SettingError)
            return

        if CuraApplication.getInstance().getBuildVolume().hasErrors():
            self.setResult(StartJobResult.BuildPlateError)
            return

        # Don't slice if the buildplate or the nozzle type is incompatible with the materials
        if not CuraApplication.getInstance().getMachineManager().variantBuildplateCompatible and \
                not CuraApplication.getInstance().getMachineManager().variantBuildplateUsable:
            self.setResult(StartJobResult.MaterialIncompatible)
            return

        for position, extruder_stack in stack.extruders.items():
            material = extruder_stack.findContainer({"type": "material"})
            if not extruder_stack.isEnabled:
                continue
            if material:
                if material.getMetaDataEntry("compatible") == False:
                    self.setResult(StartJobResult.MaterialIncompatible)
                    return

        # Don't slice if there is a per object setting with an error value.
        for node in DepthFirstIterator(
                self._scene.getRoot()
        ):  #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
            if not isinstance(node, CuraSceneNode) or not node.isSelectable():
                continue

            if self._checkStackForErrors(node.callDecoration("getStack")):
                self.setResult(StartJobResult.ObjectSettingError)
                return

        with self._scene.getSceneLock():
            # Remove old layer data.
            for node in DepthFirstIterator(
                    self._scene.getRoot()
            ):  #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
                if node.callDecoration("getLayerData") and node.callDecoration(
                        "getBuildPlateNumber") == self._build_plate_number:
                    node.getParent().removeChild(node)
                    break

            global_enable_support = stack.getProperty("support_enable",
                                                      "value")

            # Get the objects in their groups to print.
            object_groups = []
            if stack.getProperty("print_sequence", "value") == "one_at_a_time":
                # note that one_at_a_time printing is disabled on belt printers due to collission risk
                for node in OneAtATimeIterator(
                        self._scene.getRoot()
                ):  #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
                    temp_list = []

                    # Node can't be printed, so don't bother sending it.
                    if getattr(node, "_outside_buildarea", False):
                        continue

                    # Filter on current build plate
                    build_plate_number = node.callDecoration(
                        "getBuildPlateNumber")
                    if build_plate_number is not None and build_plate_number != self._build_plate_number:
                        continue

                    children = node.getAllChildren()
                    children.append(node)
                    for child_node in children:
                        if child_node.getMeshData() and child_node.getMeshData(
                        ).getVertices() is not None:
                            temp_list.append(child_node)

                    if temp_list:
                        object_groups.append(temp_list)
                    Job.yieldThread()
                if len(object_groups) == 0:
                    Logger.log(
                        "w",
                        "No objects suitable for one at a time found, or no correct order found"
                    )
            else:
                temp_list = []
                has_printing_mesh = False
                # print convex hull nodes as "faux-raft"
                print_convex_hulls = self._preferences.getValue(
                    "BeltPlugin/raft")
                for node in DepthFirstIterator(
                        self._scene.getRoot()
                ):  #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
                    slice_node = (print_convex_hulls
                                  and type(node) is ConvexHullNode
                                  ) or node.callDecoration("isSliceable")
                    if slice_node and node.getMeshData() and node.getMeshData(
                    ).getVertices() is not None:
                        per_object_stack = node.callDecoration("getStack")
                        is_non_printing_mesh = False
                        if per_object_stack:
                            is_non_printing_mesh = any(
                                per_object_stack.getProperty(key, "value")
                                for key in NON_PRINTING_MESH_SETTINGS)

                        # Find a reason not to add the node
                        if node.callDecoration(
                                "getBuildPlateNumber"
                        ) != self._build_plate_number and type(
                                node) is not ConvexHullNode:
                            # NB: ConvexHullNodes get none of the usual decorators, so skip checking for them
                            continue
                        if getattr(node, "_outside_buildarea",
                                   False) and not is_non_printing_mesh:
                            continue

                        temp_list.append(node)
                        if not is_non_printing_mesh:
                            has_printing_mesh = True

                    Job.yieldThread()

                #If the list doesn't have any model with suitable settings then clean the list
                # otherwise CuraEngine will crash
                if not has_printing_mesh:
                    temp_list.clear()

                if temp_list:
                    object_groups.append(temp_list)

            global_stack = CuraApplication.getInstance(
            ).getGlobalContainerStack()
            if not global_stack:
                return
            extruders_enabled = {
                position: stack.isEnabled
                for position, stack in global_stack.extruders.items()
            }
            filtered_object_groups = []
            has_model_with_disabled_extruders = False
            associated_disabled_extruders = set()
            for group in object_groups:
                stack = global_stack
                skip_group = False
                for node in group:
                    # Only check if the printing extruder is enabled for printing meshes
                    is_non_printing_mesh = node.callDecoration(
                        "evaluateIsNonPrintingMesh")
                    extruder_position = node.callDecoration(
                        "getActiveExtruderPosition")
                    if extruder_position is None:  # raft meshes may not have an extruder position (yet)
                        extruder_position = "0"
                    if not is_non_printing_mesh and not extruders_enabled[
                            extruder_position]:
                        skip_group = True
                        has_model_with_disabled_extruders = True
                        associated_disabled_extruders.add(extruder_position)
                if not skip_group:
                    filtered_object_groups.append(group)

            if has_model_with_disabled_extruders:
                self.setResult(StartJobResult.ObjectsWithDisabledExtruder)
                associated_disabled_extruders = {
                    str(c)
                    for c in sorted(
                        [int(p) + 1 for p in associated_disabled_extruders])
                }
                self.setMessage(", ".join(associated_disabled_extruders))
                return

            # There are cases when there is nothing to slice. This can happen due to one at a time slicing not being
            # able to find a possible sequence or because there are no objects on the build plate (or they are outside
            # the build volume)
            if not filtered_object_groups:
                self.setResult(StartJobResult.NothingToSlice)
                return

            container_registry = ContainerRegistry.getInstance()
            stack_id = stack.getId()

            # Adapt layer_height and material_flow for a slanted gantry
            gantry_angle = self._scene.getRoot().callDecoration(
                "getGantryAngle")
            #gantry_angle = float(self._preferences.getValue("BeltPlugin/gantry_angle"))
            if gantry_angle:  # not 0 or None
                # Act on a copy of the stack, so these changes don't cause a reslice
                _stack = CuraContainerStack(stack_id + "_temp")
                for index, container in enumerate(stack.getContainers()):
                    if container_registry.isReadOnly(container.getId()):
                        _stack.replaceContainer(index, container)
                    else:
                        _stack.replaceContainer(index,
                                                copy.deepcopy(container))
                stack = _stack

                # Make sure CuraEngine does not create any supports
                # support_enable is set in the frontend so support options are settable,
                # but CuraEngine support structures don't work for slanted gantry
                stack.setProperty("support_enable", "value", False)
                # Make sure CuraEngine does not create a raft (we create one manually)
                # Adhesion type is used in the frontend to show the raft in the viewport
                stack.setProperty("adhesion_type", "value", "none")

                for key in ["layer_height", "layer_height_0"]:
                    current_value = stack.getProperty(key, "value")
                    stack.setProperty(key, "value",
                                      current_value / math.sin(gantry_angle))

            self._buildGlobalSettingsMessage(stack)
            self._buildGlobalInheritsStackMessage(stack)

            # Build messages for extruder stacks
            # Send the extruder settings in the order of extruder positions. Somehow, if you send e.g. extruder 3 first,
            # then CuraEngine can slice with the wrong settings. This I think should be fixed in CuraEngine as well.
            extruder_stack_list = sorted(list(global_stack.extruders.items()),
                                         key=lambda item: int(item[0]))
            for _, extruder_stack in extruder_stack_list:
                if gantry_angle:  # not 0 or None
                    # Act on a copy of the stack, so these changes don't cause a reslice
                    _extruder_stack = CuraContainerStack(
                        extruder_stack.getId() + "_temp")
                    for index, container in enumerate(
                            extruder_stack.getContainers()):
                        if container_registry.isReadOnly(container.getId()):
                            _extruder_stack.replaceContainer(index, container)
                        else:
                            _extruder_stack.replaceContainer(
                                index, copy.deepcopy(container))
                    extruder_stack = _extruder_stack
                    extruder_stack.setNextStack(stack)
                    for key in [
                            "material_flow", "prime_tower_flow",
                            "spaghetti_flow"
                    ]:
                        if extruder_stack.hasProperty(key, "value"):
                            current_value = extruder_stack.getProperty(
                                key, "value")
                            extruder_stack.setProperty(
                                key, "value",
                                current_value * math.sin(gantry_angle))
                self._buildExtruderMessage(extruder_stack)

            bottom_cutting_meshes = []
            raft_meshes = []
            support_meshes = []
            if gantry_angle:  # not 0 or None
                for group in filtered_object_groups:
                    added_meshes = []
                    for object in group:

                        is_non_printing_mesh = False
                        per_object_stack = object.callDecoration("getStack")

                        # ConvexHullNodes get none of the usual decorators. If it made it here, it is meant to be printed
                        if type(object) is ConvexHullNode:
                            raft_thickness = self._preferences.getValue(
                                "BeltPlugin/raft_thickness")
                            raft_margin = self._preferences.getValue(
                                "BeltPlugin/raft_margin")

                            mb = MeshBuilder()
                            hull_polygon = object.getHull()
                            if raft_margin > 0:
                                hull_polygon = hull_polygon.getMinkowskiHull(
                                    Polygon.approximatedCircle(raft_margin))
                            mb.addConvexPolygonExtrusion(
                                hull_polygon.getPoints()[::-1], 0,
                                raft_thickness)

                            new_node = self._addMeshFromBuilder(mb, "raftMesh")
                            added_meshes.append(new_node)
                            raft_meshes.append(new_node.getName())

                        elif not is_non_printing_mesh:
                            # add support mesh if needed
                            belt_support_gantry_angle_bias = None
                            belt_support_minimum_island_area = None
                            if per_object_stack:
                                is_non_printing_mesh = any(
                                    per_object_stack.getProperty(key, "value")
                                    for key in NON_PRINTING_MESH_SETTINGS)

                                node_enable_support = per_object_stack.getProperty(
                                    "support_enable", "value")
                                if per_object_stack.getProperty(
                                        "support_mesh", "value"):
                                    node_enable_support = node_enable_support or per_object_stack.getProperty(
                                        "support_mesh_drop_down", "value")
                                add_support_mesh = node_enable_support if node_enable_support is not None else global_enable_support

                                belt_support_gantry_angle_bias = self._preferences.getValue(
                                    "BeltPlugin/support_gantry_angle_bias")
                                belt_support_minimum_island_area = self._preferences.getValue(
                                    "BeltPlugin/support_minimum_island_area")
                            else:
                                add_support_mesh = global_enable_support

                            if add_support_mesh:
                                #preferences = Application.getInstance().getPreferences()
                                if belt_support_gantry_angle_bias is None:
                                    belt_support_gantry_angle_bias = self._preferences.getValue(
                                        "BeltPlugin/support_gantry_angle_bias")
                                biased_down_angle = math.radians(
                                    belt_support_gantry_angle_bias)
                                if belt_support_minimum_island_area is None:
                                    belt_support_minimum_island_area = self._preferences.getValue(
                                        "BeltPlugin/support_minimum_island_area"
                                    )
                                support_mesh_data = SupportMeshCreator(
                                    down_vector=numpy.array([
                                        0, -math.cos(
                                            math.radians(biased_down_angle)),
                                        -math.sin(biased_down_angle)
                                    ]),
                                    bottom_cut_off=stack.getProperty(
                                        "wall_line_width_0", "value") / 2,
                                    minimum_island_area=
                                    belt_support_minimum_island_area
                                ).createSupportMeshForNode(object)
                                if support_mesh_data:
                                    new_node = self._addMeshFromData(
                                        support_mesh_data,
                                        "generatedSupportMesh")
                                    added_meshes.append(new_node)
                                    support_meshes.append(new_node.getName())

                            # check if the bottom needs to be cut off
                            aabb = object.getBoundingBox()

                            if aabb.bottom < 0:
                                # mesh extends below the belt; add a cutting mesh to cut off the part below the bottom
                                height = -aabb.bottom
                                center = Vector(aabb.center.x, -height / 2,
                                                aabb.center.z)

                                mb = MeshBuilder()
                                mb.addCube(width=aabb.width,
                                           height=height,
                                           depth=aabb.depth,
                                           center=center)

                                new_node = self._addMeshFromBuilder(
                                    mb, "bottomCuttingMesh")
                                added_meshes.append(new_node)
                                bottom_cutting_meshes.append(
                                    new_node.getName())

                    if added_meshes:
                        group += added_meshes

            transform_matrix = self._scene.getRoot().callDecoration(
                "getTransformMatrix")
            front_offset = None

            raft_offset = 0
            raft_speed = None
            raft_flow = 1.0

            if self._preferences.getValue("BeltPlugin/raft"):
                raft_offset = self._preferences.getValue(
                    "BeltPlugin/raft_thickness")
                raft_speed = self._preferences.getValue(
                    "BeltPlugin/raft_speed")
                raft_flow = self._preferences.getValue(
                    "BeltPlugin/raft_flow") * math.sin(gantry_angle)

            adhesion_extruder_nr = stack.getProperty("adhesion_extruder_nr",
                                                     "value")
            support_extruder_nr = stack.getProperty("support_extruder_nr",
                                                    "value")

            for group in filtered_object_groups:
                group_message = self._slice_message.addRepeatedMessage(
                    "object_lists")
                if group[0].getParent() is not None and group[0].getParent(
                ).callDecoration("isGroup"):
                    self._handlePerObjectSettings(group[0].getParent(),
                                                  group_message)

                if transform_matrix:
                    scene_front = None
                    for object in group:
                        if type(object) is ConvexHullNode:
                            continue

                        is_non_printing_mesh = object.getName(
                        ) in bottom_cutting_meshes or object.getName(
                        ) in raft_meshes
                        if not is_non_printing_mesh:
                            per_object_stack = object.callDecoration(
                                "getStack")
                            if per_object_stack:
                                is_non_printing_mesh = any(
                                    per_object_stack.getProperty(key, "value")
                                    for key in NON_PRINTING_MESH_SETTINGS)

                        if not is_non_printing_mesh:
                            _front = object.getBoundingBox().back
                            if scene_front is None or _front < scene_front:
                                scene_front = _front

                    if scene_front is not None:
                        front_offset = transformVertices(
                            numpy.array([[0, 0, scene_front]]),
                            transform_matrix)[0][1]

                for object in group:
                    if type(object) is ConvexHullNode:
                        continue

                    mesh_data = object.getMeshData()
                    rot_scale = object.getWorldTransformation().getTransposed(
                    ).getData()[0:3, 0:3]
                    translate = object.getWorldTransformation().getData()[:3,
                                                                          3]
                    # offset all non-raft objects if rafts are enabled
                    # air gap is applied here to vertically offset objects from the raft
                    if object.getName() not in raft_meshes:
                        translate[1] += raft_offset
                    if front_offset:
                        translate[2] -= front_offset

                    # This effectively performs a limited form of MeshData.getTransformed that ignores normals.
                    verts = mesh_data.getVertices()
                    verts = verts.dot(rot_scale)
                    verts += translate

                    if transform_matrix:
                        verts = transformVertices(verts, transform_matrix)

                    # Convert from Y up axes to Z up axes. Equals a 90 degree rotation.
                    verts[:, [1, 2]] = verts[:, [2, 1]]
                    verts[:, 1] *= -1

                    obj = group_message.addRepeatedMessage("objects")
                    obj.id = id(object)

                    obj.name = object.getName()
                    indices = mesh_data.getIndices()
                    if indices is not None:
                        flat_verts = numpy.take(verts,
                                                indices.flatten(),
                                                axis=0)
                    else:
                        flat_verts = numpy.array(verts)

                    obj.vertices = flat_verts

                    if object.getName() in raft_meshes:
                        self._addSettingsMessage(
                            obj, {
                                "wall_line_count": 99999999,
                                "speed_wall_0": raft_speed,
                                "speed_wall_x": raft_speed,
                                "material_flow": raft_flow,
                                "extruder_nr": adhesion_extruder_nr
                            })

                    elif object.getName() in support_meshes:
                        self._addSettingsMessage(
                            obj, {
                                "support_mesh": "True",
                                "support_mesh_drop_down": "False",
                                "extruder_nr": support_extruder_nr
                            })

                    elif object.getName() in bottom_cutting_meshes:
                        self._addSettingsMessage(
                            obj, {
                                "cutting_mesh": True,
                                "wall_line_count": 0,
                                "top_layers": 0,
                                "bottom_layers": 0,
                                "infill_line_distance": 0,
                                "extruder_nr": 0
                            })

                    else:
                        self._handlePerObjectSettings(object, obj)
                    Job.yieldThread()

                # Store the front-most coordinate of the scene so the scene can be moved back into place post slicing
                # TODO: this should be handled per mesh-group instead of per scene
                # One-at-a-time printing should be disabled for slanted gantry printers for now

                self._scene.getRoot().callDecoration("setSceneFrontOffset",
                                                     front_offset)

        self.setResult(StartJobResult.Finished)
Пример #28
0
    def _rebuild(self):
        lines = MeshData()

        offset = 0
        if self.YAxis in self._enabled_axis:
            lines.addVertex(0, 0, 0)
            lines.addVertex(0, 20, 0)
            lines.setVertexColor(offset, ToolHandle.YAxisColor)
            lines.setVertexColor(offset + 1, ToolHandle.YAxisColor)
            offset += 2

        if self.XAxis in self._enabled_axis:
            lines.addVertex(0, 0, 0)
            lines.addVertex(20, 0, 0)
            lines.setVertexColor(offset, ToolHandle.XAxisColor)
            lines.setVertexColor(offset + 1, ToolHandle.XAxisColor)
            offset += 2

        if self.ZAxis in self._enabled_axis:
            lines.addVertex(0, 0, 0)
            lines.addVertex(0, 0, 20)
            lines.setVertexColor(offset, ToolHandle.ZAxisColor)
            lines.setVertexColor(offset + 1, ToolHandle.ZAxisColor)
            offset += 2

        self.setLineMesh(lines)

        mb = MeshBuilder()

        if self.YAxis in self._enabled_axis:
            mb.addPyramid(
                width = 2,
                height = 4,
                depth = 2,
                center = Vector(0, 20, 0),
                color = ToolHandle.YAxisColor
            )

        if self.XAxis in self._enabled_axis:
            mb.addPyramid(
                width = 2,
                height = 4,
                depth = 2,
                center = Vector(20, 0, 0),
                color = ToolHandle.XAxisColor,
                axis = Vector.Unit_Z,
                angle = 90
            )

        if self.ZAxis in self._enabled_axis:
            mb.addPyramid(
                width = 2,
                height = 4,
                depth = 2,
                center = Vector(0, 0, 20),
                color = ToolHandle.ZAxisColor,
                axis = Vector.Unit_X,
                angle = -90
            )

        self.setSolidMesh(mb.getData())

        mb = MeshBuilder()

        if self.YAxis in self._enabled_axis:
            mb.addCube(
                width = 4,
                height = 20,
                depth = 4,
                center = Vector(0, 10, 0),
                color = ToolHandle.YAxisColor
            )

            mb.addPyramid(
                width = 4,
                height = 8,
                depth = 4,
                center = Vector(0, 20, 0),
                color = ToolHandle.YAxisColor
            )

        if self.XAxis in self._enabled_axis:
            mb.addCube(
                width = 20,
                height = 4,
                depth = 4,
                center = Vector(10, 0, 0),
                color = ToolHandle.XAxisColor
            )

            mb.addPyramid(
                width = 4,
                height = 8,
                depth = 4,
                center = Vector(20, 0, 0),
                color = ToolHandle.XAxisColor,
                axis = Vector.Unit_Z,
                angle = 90
            )

        if self.ZAxis in self._enabled_axis:
            mb.addCube(
                width = 4,
                height = 4,
                depth = 20,
                center = Vector(0, 0, 10),
                color = ToolHandle.ZAxisColor
            )

            mb.addPyramid(
                width = 4,
                height = 8,
                depth = 4,
                center = Vector(0, 0, 20),
                color = ToolHandle.ZAxisColor,
                axis = Vector.Unit_X,
                angle = -90
            )

        self.setSelectionMesh(mb.getData())
Пример #29
0
    def buildMesh(self):
        mb = MeshBuilder()

        #SOLIDMESH -> LINES
        if self.YAxis in self._enabled_axis:
            mb.addCube(width=self._line_width,
                       height=self._line_length,
                       depth=self._line_width,
                       center=Vector(0, self._handle_position / 2, 0),
                       color=self._y_axis_color)
        if self.XAxis in self._enabled_axis:
            mb.addCube(width=self._line_length,
                       height=self._line_width,
                       depth=self._line_width,
                       center=Vector(self._handle_position / 2, 0, 0),
                       color=self._x_axis_color)

        if self.ZAxis in self._enabled_axis:
            mb.addCube(width=self._line_width,
                       height=self._line_width,
                       depth=self._line_length,
                       center=Vector(0, 0, self._handle_position / 2),
                       color=self._z_axis_color)

        #SOLIDMESH -> HANDLES
        if self.YAxis in self._enabled_axis:
            mb.addPyramid(width=self._handle_width,
                          height=self._handle_height,
                          depth=self._handle_width,
                          center=Vector(0, self._handle_position, 0),
                          color=self._y_axis_color)

        if self.XAxis in self._enabled_axis:
            mb.addPyramid(width=self._handle_width,
                          height=self._handle_height,
                          depth=self._handle_width,
                          center=Vector(self._handle_position, 0, 0),
                          color=self._x_axis_color,
                          axis=Vector.Unit_Z,
                          angle=90)

        if self.ZAxis in self._enabled_axis:
            mb.addPyramid(width=self._handle_width,
                          height=self._handle_height,
                          depth=self._handle_width,
                          center=Vector(0, 0, self._handle_position),
                          color=self._z_axis_color,
                          axis=Vector.Unit_X,
                          angle=-90)

        self.setSolidMesh(mb.build())

        mb = MeshBuilder()
        #SELECTIONMESH -> LINES
        if self.YAxis in self._enabled_axis:
            mb.addCube(width=self._active_line_width,
                       height=self._active_line_length,
                       depth=self._active_line_width,
                       center=Vector(0, self._active_handle_position / 2, 0),
                       color=self._y_axis_color)
        if self.XAxis in self._enabled_axis:
            mb.addCube(width=self._active_line_length,
                       height=self._active_line_width,
                       depth=self._active_line_width,
                       center=Vector(self._active_handle_position / 2, 0, 0),
                       color=self._x_axis_color)

        if self.ZAxis in self._enabled_axis:
            mb.addCube(width=self._active_line_width,
                       height=self._active_line_width,
                       depth=self._active_line_length,
                       center=Vector(0, 0, self._active_handle_position / 2),
                       color=self._z_axis_color)

        #SELECTIONMESH -> HANDLES
        mb.addCube(width=self._active_handle_width,
                   height=self._active_handle_width,
                   depth=self._active_handle_width,
                   center=Vector(0, 0, 0),
                   color=ToolHandle.AllAxisSelectionColor)

        mb.addCube(width=self._active_handle_width,
                   height=self._active_handle_width,
                   depth=self._active_handle_width,
                   center=Vector(0, self._active_handle_position, 0),
                   color=ToolHandle.YAxisSelectionColor)

        mb.addCube(width=self._active_handle_width,
                   height=self._active_handle_width,
                   depth=self._active_handle_width,
                   center=Vector(self._active_handle_position, 0, 0),
                   color=ToolHandle.XAxisSelectionColor)

        mb.addCube(width=self._active_handle_width,
                   height=self._active_handle_width,
                   depth=self._active_handle_width,
                   center=Vector(0, 0, self._active_handle_position),
                   color=ToolHandle.ZAxisSelectionColor)
        self.setSelectionMesh(mb.build())
Пример #30
0
    def buildMesh(self):
        #SOLIDMESH -> LINES
        mb = MeshBuilder()

        mb.addCube(
            width = self._line_width,
            height = self._line_length,
            depth = self._line_width,
            center = Vector(0, self._handle_position/2, 0),
            color = self._y_axis_color
        )
        mb.addCube(
            width = self._line_length,
            height = self._line_width,
            depth = self._line_width,
            center = Vector(self._handle_position/2, 0, 0),
            color = self._x_axis_color
        )

        mb.addCube(
            width = self._line_width,
            height = self._line_width,
            depth = self._line_length,
            center = Vector(0, 0, self._handle_position/2),
            color = self._z_axis_color
        )

        #SOLIDMESH -> HANDLES
        mb.addCube(
            width = self._handle_width,
            height = self._handle_width,
            depth = self._handle_width,
            center = Vector(0, 0, 0),
            color = self._all_axis_color
        )

        mb.addCube(
            width = self._handle_width,
            height = self._handle_width,
            depth = self._handle_width,
            center = Vector(0, self._handle_position, 0),
            color = self._y_axis_color
        )

        mb.addCube(
            width = self._handle_width,
            height = self._handle_width,
            depth = self._handle_width,
            center = Vector(self._handle_position, 0, 0),
            color = self._x_axis_color
        )

        mb.addCube(
            width = self._handle_width,
            height = self._handle_width,
            depth = self._handle_width,
            center = Vector(0, 0, self._handle_position),
            color = self._z_axis_color
        )
        self.setSolidMesh(mb.build())

        #SELECTIONMESH -> LINES
        mb = MeshBuilder()
        mb.addCube(
            width = self._active_line_width,
            height = self._active_line_length,
            depth = self._active_line_width,
            center = Vector(0, self._active_handle_position/2, 0),
            color = ToolHandle.YAxisSelectionColor
        )

        mb.addCube(
            width = self._active_line_length,
            height = self._active_line_width,
            depth = self._active_line_width,
            center = Vector(self._active_handle_position/2, 0, 0),
            color = ToolHandle.XAxisSelectionColor
        )

        mb.addCube(
            width = self._active_line_width,
            height = self._active_line_width,
            depth = self._active_line_length,
            center = Vector(0, 0, self._active_handle_position/2),
            color = ToolHandle.ZAxisSelectionColor
        )

        #SELECTIONMESH -> HANDLES
        mb.addCube(
            width = self._active_handle_width,
            height = self._active_handle_width,
            depth = self._active_handle_width,
            center = Vector(0, 0, 0),
            color = ToolHandle.AllAxisSelectionColor
        )

        mb.addCube(
            width = self._active_handle_width,
            height = self._active_handle_width,
            depth = self._active_handle_width,
            center = Vector(0, self._active_handle_position, 0),
            color = ToolHandle.YAxisSelectionColor
        )

        mb.addCube(
            width = self._active_handle_width,
            height = self._active_handle_width,
            depth = self._active_handle_width,
            center = Vector(self._active_handle_position, 0, 0),
            color = ToolHandle.XAxisSelectionColor
        )

        mb.addCube(
            width = self._active_handle_width,
            height = self._active_handle_width,
            depth = self._active_handle_width,
            center = Vector(0, 0, self._active_handle_position),
            color = ToolHandle.ZAxisSelectionColor
        )

        self.setSelectionMesh(mb.build())