Exemple #1
0
    def initialize(self, parent: SceneNode, step=None, callback=None):
        parent.addChild(self)

        mesh_data = parent.getMeshData()

        if mesh_data:
            Logger.log(
                'd', 'Compute interactive mesh from SceneNode {}'.format(
                    parent.getName()))

            if mesh_data.getVertexCount() < 1000:
                self._interactive_mesh = makeInteractiveMesh(mesh_data)
                if step:
                    self.loadStep(step)
                    self.setOrigin()
                if callback:
                    callback()
            else:
                job = AnalyzeMeshJob(mesh_data, step, callback)
                job.finished.connect(self._process_mesh_analysis)

                self._mesh_analyzing_message = Message(
                    title=i18n_catalog.i18n("Smart Slice"),
                    text=i18n_catalog.i18n(
                        "Analyzing geometry - this may take a few moments"),
                    progress=-1,
                    dismissable=False,
                    lifetime=0,
                    use_inactivity_timer=False)
                self._mesh_analyzing_message.show()

                job.start()

        self.rootChanged.emit(self)
Exemple #2
0
    def test_removeChildren(self):
        node1 = SceneNode()
        node2 = SceneNode()
        node1.addChild(node2)
        assert node1.hasChildren()

        node1.removeAllChildren()

        assert not node1.hasChildren()
Exemple #3
0
    def test_removeChildren(self):
        node1 = SceneNode()
        node2 = SceneNode()
        node1.addChild(node2)
        assert node1.hasChildren()

        node1.removeAllChildren()

        assert not node1.hasChildren()
Exemple #4
0
    def test_enabled(self):
        node1 = SceneNode()
        node1.setEnabled(True)
        assert node1.isEnabled()

        node2 = SceneNode()
        node1.addChild(node2)
        node2.setEnabled(True)
        assert node2.isEnabled()

        node1.setEnabled(False)
        assert not node1.isEnabled()
        assert not node2.isEnabled()
Exemple #5
0
    def test_enabled(self):
        node1 = SceneNode()
        node1.setEnabled(True)
        assert node1.isEnabled()

        node2 = SceneNode()
        node1.addChild(node2)
        node2.setEnabled(True)
        assert node2.isEnabled()

        node1.setEnabled(False)
        assert not node1.isEnabled()
        assert not node2.isEnabled()
Exemple #6
0
    def test_visibility(self):
        node1 = SceneNode()
        node1.setVisible(True)
        assert node1.isVisible()

        node2 = SceneNode()
        node1.addChild(node2)
        node2.setVisible(True)
        assert node2.isVisible()

        node1.setVisible(False)
        assert not node1.isVisible()
        assert not node2.isVisible()
Exemple #7
0
    def test_visibility(self):
        node1 = SceneNode()
        node1.setVisible(True)
        assert node1.isVisible()

        node2 = SceneNode()
        node1.addChild(node2)
        node2.setVisible(True)
        assert node2.isVisible()

        node1.setVisible(False)
        assert not node1.isVisible()
        assert not node2.isVisible()
Exemple #8
0
    def test_addRemoveDouble(self):
        # Adding a child that's already a child of a node should not cause issues. Same for trying to remove one that isn't a child

        node_1 = SceneNode()
        node_2 = SceneNode()
        # Should work
        node_1.addChild(node_2)
        # Should still work!
        node_1.addChild(node_2)

        # This has already been tested somewhere else, so no problems are expected
        node_1.removeChild(node_2)
        # Doing it again shouldn't break.
        node_1.removeChild(node_2)
Exemple #9
0
    def test_getDepth(self):
        node1 = SceneNode()
        node2 = SceneNode()
        node3 = SceneNode()
        node4 = SceneNode()

        node1.addChild(node2)
        node1.addChild(node3)
        node2.addChild(node4)

        assert node1.getDepth() == 0
        assert node2.getDepth() == 1
        assert node3.getDepth() == 1
        assert node4.getDepth() == 2
Exemple #10
0
    def test_addRemoveDouble(self):
        # Adding a child that's already a child of a node should not cause issues. Same for trying to remove one that isn't a child

        node_1 = SceneNode()
        node_2 = SceneNode()
        # Should work
        node_1.addChild(node_2)
        # Should still work!
        node_1.addChild(node_2)

        # This has already been tested somewhere else, so no problems are expected
        node_1.removeChild(node_2)
        # Doing it again shouldn't break.
        node_1.removeChild(node_2)
Exemple #11
0
    def test_getDepth(self):
        node1 = SceneNode()
        node2 = SceneNode()
        node3 = SceneNode()
        node4 = SceneNode()

        node1.addChild(node2)
        node1.addChild(node3)
        node2.addChild(node4)

        assert node1.getDepth() == 0
        assert node2.getDepth() == 1
        assert node3.getDepth() == 1
        assert node4.getDepth() == 2
Exemple #12
0
    def test_deepCopy(self):
        node_1 = SceneNode()
        node_2 = SceneNode()
        node_1.translate(Vector(1, 2, 3))
        node_1.scale(Vector(1.5, 1., 1.))
        node_1.setMeshData(MeshData())
        node_1.addChild(node_2)
        node_1.addDecorator(GroupDecorator())
        copied_node = deepcopy(node_1)

        assert copied_node.getScale() == Vector(1.5, 1, 1)
        assert copied_node.getPosition() == Vector(1, 2, 3)
        assert len(copied_node.getChildren()) == 1
        # Ensure that the decorator also got copied
        assert copied_node.callDecoration("isGroup")
Exemple #13
0
    def test_deepCopy(self):
        node_1 = SceneNode()
        node_2 = SceneNode()
        node_1.translate(Vector(1, 2, 3))
        node_1.scale(Vector(1.5, 1., 1.))
        node_1.setMeshData(MeshData())
        node_1.addChild(node_2)
        node_1.addDecorator(GroupDecorator())
        copied_node = deepcopy(node_1)

        assert copied_node.getScale() == Vector(1.5, 1, 1)
        assert copied_node.getPosition() == Vector(1, 2, 3)
        assert len(copied_node.getChildren()) == 1
        # Ensure that the decorator also got copied
        assert copied_node.callDecoration("isGroup")
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]])
Exemple #15
0
    def test_setCenterPosition(self):
        node = SceneNode()
        child_node = SceneNode()
        node.addChild(child_node)
        child_node.setCenterPosition = MagicMock()

        builder = MeshBuilder()
        builder.addVertex(10, 20, 20)
        node.setMeshData(builder.build())

        node.setCenterPosition(Vector(-10, 0, 0))

        transformed_mesh = node.getMeshData()

        transformed_vertex = transformed_mesh.getVertices()[0]
        assert transformed_vertex[0] == 20
        assert transformed_vertex[1] == 20
        assert transformed_vertex[2] == 20

        child_node.setCenterPosition.assert_called_once_with(Vector(-10, 0, 0))
Exemple #16
0
class SceneTest(unittest.TestCase):
    def setUp(self):
        # Called before the first testfunction is executed
        self._scene = Scene()
        self._scene_object = SceneNode()
        self._scene_object2 = SceneNode()
        self._scene_object.addChild(self._scene_object2)
        self._scene.getRoot().addChild(self._scene_object)
        temp_matrix = Matrix()
        temp_matrix.setByTranslation(Vector(10,10,10))
        self._scene_object2.setLocalTransformation(deepcopy(temp_matrix))
        temp_matrix.setByScaleFactor(0.5)
        self._scene_object.setLocalTransformation(temp_matrix)

    def tearDown(self):
        # Called after the last testfunction was executed
        pass

    def test_checkWorldTransformation(self):
        numpy.testing.assert_array_almost_equal(self._scene_object2.getWorldTransformation().getData(), numpy.array([[0.5,0,0,5],[0,0.5,0,5],[0,0,0.5,5],[0,0,0,1]]))
Exemple #17
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]])
Exemple #18
0
class SceneTest(unittest.TestCase):
    def setUp(self):
        # Called before the first testfunction is executed
        self._scene = Scene()
        self._scene_object = SceneNode()
        self._scene_object2 = SceneNode()
        self._scene_object.addChild(self._scene_object2)
        self._scene.getRoot().addChild(self._scene_object)
        temp_matrix = Matrix()
        temp_matrix.setByTranslation(Vector(10, 10, 10))
        self._scene_object2.setLocalTransformation(deepcopy(temp_matrix))
        temp_matrix.setByScaleFactor(0.5)
        self._scene_object.setLocalTransformation(temp_matrix)

    def tearDown(self):
        # Called after the last testfunction was executed
        pass

    def test_checkWorldTransformation(self):
        numpy.testing.assert_array_almost_equal(
            self._scene_object2.getWorldTransformation().getData(),
            numpy.array([[0.5, 0, 0, 5], [0, 0.5, 0, 5], [0, 0, 0.5, 5], [0, 0, 0, 1]]),
        )
Exemple #19
0
def test_DepthFirstIterator():

    root_node = SceneNode()

    node_1 = SceneNode()
    root_node.addChild(node_1)

    node_1_child_1 = SceneNode()
    node_1_child_2 = SceneNode()

    node_1.addChild(node_1_child_1)
    node_1.addChild(node_1_child_2)

    node_2 = SceneNode()
    root_node.addChild(node_2)

    node_2_child_1 = SceneNode()
    node_2.addChild(node_2_child_1)

    assert list(DepthFirstIterator(root_node)) == [
        root_node, node_1, node_2, node_1_child_1, node_1_child_2,
        node_2_child_1
    ]
Exemple #20
0
    def test_getAllChildren(self):
        parent_node = SceneNode()
        child_node_1 = SceneNode()
        child_node_2 = SceneNode()
        parent_node.addChild(child_node_1)
        parent_node.addChild(child_node_2)

        child_1_of_child_node_1 = SceneNode()
        child_2_of_child_node_1 = SceneNode()
        child_node_1.addChild(child_1_of_child_node_1)
        child_node_1.addChild(child_2_of_child_node_1)

        child_1_of_child_node_2 = SceneNode()
        child_node_2.addChild(child_1_of_child_node_2)

        assert parent_node.getAllChildren() == [child_node_1, child_node_2, child_1_of_child_node_1, child_2_of_child_node_1, child_1_of_child_node_2]
Exemple #21
0
    def test_getAllChildren(self):
        parent_node = SceneNode()
        child_node_1 = SceneNode()
        child_node_2 = SceneNode()
        parent_node.addChild(child_node_1)
        parent_node.addChild(child_node_2)

        child_1_of_child_node_1 = SceneNode()
        child_2_of_child_node_1 = SceneNode()
        child_node_1.addChild(child_1_of_child_node_1)
        child_node_1.addChild(child_2_of_child_node_1)

        child_1_of_child_node_2 = SceneNode()
        child_node_2.addChild(child_1_of_child_node_2)

        assert parent_node.getAllChildren() == [child_node_1, child_node_2, child_1_of_child_node_1, child_2_of_child_node_1, child_1_of_child_node_2]
Exemple #22
0
    def _convertSavitarNodeToUMNode(self, savitar_node):
        um_node = SceneNode()
        transformation = self._createMatrixFromTransformationString(
            savitar_node.getTransformation())
        um_node.setTransformation(transformation)
        mesh_builder = MeshBuilder()

        data = numpy.fromstring(
            savitar_node.getMeshData().getFlatVerticesAsBytes(),
            dtype=numpy.float32)

        vertices = numpy.resize(data, (int(data.size / 3), 3))
        mesh_builder.setVertices(vertices)
        mesh_builder.calculateNormals(fast=True)
        mesh_data = mesh_builder.build()

        if len(mesh_data.getVertices()):
            um_node.setMeshData(mesh_data)

        for child in savitar_node.getChildren():
            child_node = self._convertSavitarNodeToUMNode(child)
            if child_node:
                um_node.addChild(child_node)

        if um_node.getMeshData() is None and len(um_node.getChildren()) == 0:
            return None

        settings = savitar_node.getSettings()

        # Add the setting override decorator, so we can add settings to this node.
        if settings:
            um_node.addDecorator(SettingOverrideDecorator())

            global_container_stack = Application.getInstance(
            ).getGlobalContainerStack()

            # Ensure the correct next container for the SettingOverride decorator is set.
            if global_container_stack:
                default_stack = ExtruderManager.getInstance().getExtruderStack(
                    0)

                if default_stack:
                    um_node.callDecoration("setActiveExtruder",
                                           default_stack.getId())

                # Get the definition & set it
                definition = QualityManager.getInstance(
                ).getParentMachineDefinition(
                    global_container_stack.getBottom())
                um_node.callDecoration("getStack").getTop().setDefinition(
                    definition.getId())

            setting_container = um_node.callDecoration("getStack").getTop()

            for key in settings:
                setting_value = settings[key]

                # Extruder_nr is a special case.
                if key == "extruder_nr":
                    extruder_stack = ExtruderManager.getInstance(
                    ).getExtruderStack(int(setting_value))
                    if extruder_stack:
                        um_node.callDecoration("setActiveExtruder",
                                               extruder_stack.getId())
                    else:
                        Logger.log("w",
                                   "Unable to find extruder in position %s",
                                   setting_value)
                    continue
                setting_container.setProperty(key, "value", setting_value)

        if len(um_node.getChildren()) > 0:
            group_decorator = GroupDecorator()
            um_node.addDecorator(group_decorator)
        um_node.setSelectable(True)
        if um_node.getMeshData():
            # Assuming that all nodes with mesh data are printable objects
            # affects (auto) slicing
            sliceable_decorator = SliceableObjectDecorator()
            um_node.addDecorator(sliceable_decorator)
        return um_node
Exemple #23
0
    def read(self, file_name):
        result = SceneNode()
        # The base object of 3mf is a zipped archive.
        archive = zipfile.ZipFile(file_name, "r")
        try:
            root = ET.parse(archive.open("3D/3dmodel.model"))

            # There can be multiple objects, try to load all of them.
            objects = root.findall("./3mf:resources/3mf:object", self._namespaces)
            if len(objects) == 0:
                Logger.log("w", "No objects found in 3MF file %s, either the file is corrupt or you are using an outdated format", file_name)
                return None

            for entry in objects:
                mesh_builder = MeshBuilder()
                node = SceneNode()
                vertex_list = []
                #for vertex in entry.mesh.vertices.vertex:
                for vertex in entry.findall(".//3mf:vertex", self._namespaces):
                    vertex_list.append([vertex.get("x"), vertex.get("y"), vertex.get("z")])
                    Job.yieldThread()

                triangles = entry.findall(".//3mf:triangle", self._namespaces)
                mesh_builder.reserveFaceCount(len(triangles))

                #for triangle in object.mesh.triangles.triangle:
                for triangle in triangles:
                    v1 = int(triangle.get("v1"))
                    v2 = int(triangle.get("v2"))
                    v3 = int(triangle.get("v3"))

                    mesh_builder.addFaceByPoints(vertex_list[v1][0], vertex_list[v1][1], vertex_list[v1][2],
                                                 vertex_list[v2][0], vertex_list[v2][1], vertex_list[v2][2],
                                                 vertex_list[v3][0], vertex_list[v3][1], vertex_list[v3][2])

                    Job.yieldThread()

                # Rotate the model; We use a different coordinate frame.
                rotation = Matrix()
                rotation.setByRotationAxis(-0.5 * math.pi, Vector(1,0,0))

                #TODO: We currently do not check for normals and simply recalculate them.
                mesh_builder.calculateNormals()

                node.setMeshData(mesh_builder.build().getTransformed(rotation))
                node.setSelectable(True)

                transformations = root.findall("./3mf:build/3mf:item[@objectid='{0}']".format(entry.get("id")), self._namespaces)
                transformation = transformations[0] if transformations else None
                if transformation is not None and transformation.get("transform"):
                    splitted_transformation = transformation.get("transform").split()
                    ## Transformation is saved as:
                    ## M00 M01 M02 0.0
                    ## M10 M11 M12 0.0
                    ## M20 M21 M22 0.0
                    ## M30 M31 M32 1.0
                    ## We switch the row & cols as that is how everyone else uses matrices!
                    temp_mat = Matrix()
                    # Rotation & Scale
                    temp_mat._data[0,0] = splitted_transformation[0]
                    temp_mat._data[1,0] = splitted_transformation[1]
                    temp_mat._data[2,0] = splitted_transformation[2]
                    temp_mat._data[0,1] = splitted_transformation[3]
                    temp_mat._data[1,1] = splitted_transformation[4]
                    temp_mat._data[2,1] = splitted_transformation[5]
                    temp_mat._data[0,2] = splitted_transformation[6]
                    temp_mat._data[1,2] = splitted_transformation[7]
                    temp_mat._data[2,2] = splitted_transformation[8]

                    # Translation
                    temp_mat._data[0,3] = splitted_transformation[9]
                    temp_mat._data[1,3] = splitted_transformation[10]
                    temp_mat._data[2,3] = splitted_transformation[11]

                    node.setTransformation(temp_mat)

                result.addChild(node)

                Job.yieldThread()

            #If there is more then one object, group them.
            if len(objects) > 1:
                group_decorator = GroupDecorator()
                result.addDecorator(group_decorator)
        except Exception as e:
            Logger.log("e" ,"exception occured in 3mf reader: %s" , e)

        return result  
Exemple #24
0
    def _createNodeFromObject(self, object, name=""):
        node = SceneNode()
        node.setName(name)
        mesh_builder = MeshBuilder()
        vertex_list = []

        components = object.find(".//3mf:components", self._namespaces)
        if components:
            for component in components:
                id = component.get("objectid")
                new_object = self._root.find(
                    "./3mf:resources/3mf:object[@id='{0}']".format(id),
                    self._namespaces)
                new_node = self._createNodeFromObject(
                    new_object, self._base_name + "_" + str(id))
                node.addChild(new_node)
                transform = component.get("transform")
                if transform is not None:
                    new_node.setTransformation(
                        self._createMatrixFromTransformationString(transform))

        # for vertex in entry.mesh.vertices.vertex:
        for vertex in object.findall(".//3mf:vertex", self._namespaces):
            vertex_list.append(
                [vertex.get("x"),
                 vertex.get("y"),
                 vertex.get("z")])
            Job.yieldThread()

        xml_settings = list(object.findall(".//cura:setting",
                                           self._namespaces))

        # Add the setting override decorator, so we can add settings to this node.
        if xml_settings:
            node.addDecorator(SettingOverrideDecorator())

            global_container_stack = Application.getInstance(
            ).getGlobalContainerStack()
            # Ensure the correct next container for the SettingOverride decorator is set.
            if global_container_stack:
                multi_extrusion = global_container_stack.getProperty(
                    "machine_extruder_count", "value") > 1
                # Ensure that all extruder data is reset
                if not multi_extrusion:
                    default_stack_id = global_container_stack.getId()
                else:
                    default_stack = ExtruderManager.getInstance(
                    ).getExtruderStack(0)
                    if default_stack:
                        default_stack_id = default_stack.getId()
                    else:
                        default_stack_id = global_container_stack.getId()
                node.callDecoration("setActiveExtruder", default_stack_id)

                # Get the definition & set it
                definition = QualityManager.getInstance(
                ).getParentMachineDefinition(
                    global_container_stack.getBottom())
                node.callDecoration("getStack").getTop().setDefinition(
                    definition)

            setting_container = node.callDecoration("getStack").getTop()
            for setting in xml_settings:
                setting_key = setting.get("key")
                setting_value = setting.text

                # Extruder_nr is a special case.
                if setting_key == "extruder_nr":
                    extruder_stack = ExtruderManager.getInstance(
                    ).getExtruderStack(int(setting_value))
                    if extruder_stack:
                        node.callDecoration("setActiveExtruder",
                                            extruder_stack.getId())
                    else:
                        Logger.log("w",
                                   "Unable to find extruder in position %s",
                                   setting_value)
                    continue
                setting_container.setProperty(setting_key, "value",
                                              setting_value)

        if len(node.getChildren()) > 0:
            group_decorator = GroupDecorator()
            node.addDecorator(group_decorator)

        triangles = object.findall(".//3mf:triangle", self._namespaces)
        mesh_builder.reserveFaceCount(len(triangles))

        for triangle in triangles:
            v1 = int(triangle.get("v1"))
            v2 = int(triangle.get("v2"))
            v3 = int(triangle.get("v3"))

            mesh_builder.addFaceByPoints(
                vertex_list[v1][0], vertex_list[v1][1], vertex_list[v1][2],
                vertex_list[v2][0], vertex_list[v2][1], vertex_list[v2][2],
                vertex_list[v3][0], vertex_list[v3][1], vertex_list[v3][2])

            Job.yieldThread()

        # TODO: We currently do not check for normals and simply recalculate them.
        mesh_builder.calculateNormals(fast=True)
        mesh_builder.setFileName(name)
        mesh_data = mesh_builder.build()

        if len(mesh_data.getVertices()):
            node.setMeshData(mesh_data)

        node.setSelectable(True)
        return node
Exemple #25
0
    def read(self, file_name):
        result = None
        extension = os.path.splitext(file_name)[1]
        if extension.lower() == self._supported_extension:
            result = SceneNode()
            # The base object of 3mf is a zipped archive.
            archive = zipfile.ZipFile(file_name, 'r')
            try:
                root = ET.parse(archive.open("3D/3dmodel.model"))

                # There can be multiple objects, try to load all of them.
                objects = root.findall("./3mf:resources/3mf:object", self._namespaces)
                for object in objects:
                    mesh = MeshData()
                    node = SceneNode()
                    vertex_list = []
                    #for vertex in object.mesh.vertices.vertex:
                    for vertex in object.findall(".//3mf:vertex", self._namespaces):
                        vertex_list.append([vertex.get("x"), vertex.get("y"), vertex.get("z")])

                    triangles = object.findall(".//3mf:triangle", self._namespaces)

                    mesh.reserveFaceCount(len(triangles))
                    
                    #for triangle in object.mesh.triangles.triangle:
                    for triangle in triangles:
                        v1 = int(triangle.get("v1"))
                        v2 = int(triangle.get("v2"))
                        v3 = int(triangle.get("v3"))
                        mesh.addFace(vertex_list[v1][0],vertex_list[v1][1],vertex_list[v1][2],vertex_list[v2][0],vertex_list[v2][1],vertex_list[v2][2],vertex_list[v3][0],vertex_list[v3][1],vertex_list[v3][2])
                    #TODO: We currently do not check for normals and simply recalculate them. 
                    mesh.calculateNormals()
                    node.setMeshData(mesh)
                    node.setSelectable(True)
                    
                    transformation = root.findall("./3mf:build/3mf:item[@objectid='{0}']".format(object.get("id")), self._namespaces)
                    if transformation:
                        transformation = transformation[0]

                    if transformation.get("transform"):
                        splitted_transformation = transformation.get("transform").split()
                        ## Transformation is saved as:
                        ## M00 M01 M02 0.0
                        ## M10 M11 M12 0.0
                        ## M20 M21 M22 0.0
                        ## M30 M31 M32 1.0
                        ## We switch the row & cols as that is how everyone else uses matrices!
                        temp_mat = Matrix()
                        # Rotation & Scale
                        temp_mat._data[0,0] = splitted_transformation[0]
                        temp_mat._data[1,0] = splitted_transformation[1]
                        temp_mat._data[2,0] = splitted_transformation[2]
                        temp_mat._data[0,1] = splitted_transformation[3]
                        temp_mat._data[1,1] = splitted_transformation[4]
                        temp_mat._data[2,1] = splitted_transformation[5]
                        temp_mat._data[0,2] = splitted_transformation[6]
                        temp_mat._data[1,2] = splitted_transformation[7]
                        temp_mat._data[2,2] = splitted_transformation[8]
                        
                        # Translation
                        temp_mat._data[0,3] = splitted_transformation[9]
                        temp_mat._data[1,3] = splitted_transformation[10]
                        temp_mat._data[2,3] = splitted_transformation[11]
                        
                        node.setPosition(Vector(temp_mat.at(0,3), temp_mat.at(1,3), temp_mat.at(2,3)))
                        
                        temp_quaternion = Quaternion()
                        temp_quaternion.setByMatrix(temp_mat)
                        node.setOrientation(temp_quaternion)
                        
                        # Magical scale extraction
                        S2 = temp_mat.getTransposed().multiply(temp_mat)
                        scale_x = math.sqrt(S2.at(0,0))
                        scale_y = math.sqrt(S2.at(1,1))
                        scale_z = math.sqrt(S2.at(2,2))
                        node.setScale(Vector(scale_x,scale_y,scale_z))
                        
                        # We use a different coordinate frame, so rotate.
                        rotation = Quaternion.fromAngleAxis(-0.5 * math.pi, Vector(1,0,0))
                        node.rotate(rotation)
                    result.addChild(node)

                #If there is more then one object, group them.
                try:
                    if len(objects) > 1:
                        group_decorator = GroupDecorator()
                        result.addDecorator(group_decorator)
                except:
                    pass
            except Exception as e:
                Logger.log("e" ,"exception occured in 3mf reader: %s" , e)      
        return result  
Exemple #26
0
    def _createNodeFromObject(self, object, name = ""):
        node = SceneNode()
        node.setName(name)
        mesh_builder = MeshBuilder()
        vertex_list = []

        components = object.find(".//3mf:components", self._namespaces)
        if components:
            for component in components:
                id = component.get("objectid")
                new_object = self._root.find("./3mf:resources/3mf:object[@id='{0}']".format(id), self._namespaces)
                new_node = self._createNodeFromObject(new_object, self._base_name + "_" + str(id))
                node.addChild(new_node)
                transform = component.get("transform")
                if transform is not None:
                    new_node.setTransformation(self._createMatrixFromTransformationString(transform))

        # for vertex in entry.mesh.vertices.vertex:
        for vertex in object.findall(".//3mf:vertex", self._namespaces):
            vertex_list.append([vertex.get("x"), vertex.get("y"), vertex.get("z")])
            Job.yieldThread()

        xml_settings = list(object.findall(".//cura:setting", self._namespaces))

        # Add the setting override decorator, so we can add settings to this node.
        if xml_settings:
            node.addDecorator(SettingOverrideDecorator())

            global_container_stack = Application.getInstance().getGlobalContainerStack()
            # Ensure the correct next container for the SettingOverride decorator is set.
            if global_container_stack:
                multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1
                # Ensure that all extruder data is reset
                if not multi_extrusion:
                    default_stack_id = global_container_stack.getId()
                else:
                    default_stack = ExtruderManager.getInstance().getExtruderStack(0)
                    if default_stack:
                        default_stack_id = default_stack.getId()
                    else:
                        default_stack_id = global_container_stack.getId()
                node.callDecoration("setActiveExtruder", default_stack_id)

                # Get the definition & set it
                definition = QualityManager.getInstance().getParentMachineDefinition(global_container_stack.getBottom())
                node.callDecoration("getStack").getTop().setDefinition(definition)

            setting_container = node.callDecoration("getStack").getTop()
            for setting in xml_settings:
                setting_key = setting.get("key")
                setting_value = setting.text

                # Extruder_nr is a special case.
                if setting_key == "extruder_nr":
                    extruder_stack = ExtruderManager.getInstance().getExtruderStack(int(setting_value))
                    if extruder_stack:
                        node.callDecoration("setActiveExtruder", extruder_stack.getId())
                    else:
                        Logger.log("w", "Unable to find extruder in position %s", setting_value)
                    continue
                setting_container.setProperty(setting_key,"value", setting_value)

        if len(node.getChildren()) > 0:
            group_decorator = GroupDecorator()
            node.addDecorator(group_decorator)

        triangles = object.findall(".//3mf:triangle", self._namespaces)
        mesh_builder.reserveFaceCount(len(triangles))

        for triangle in triangles:
            v1 = int(triangle.get("v1"))
            v2 = int(triangle.get("v2"))
            v3 = int(triangle.get("v3"))

            mesh_builder.addFaceByPoints(vertex_list[v1][0], vertex_list[v1][1], vertex_list[v1][2],
                                         vertex_list[v2][0], vertex_list[v2][1], vertex_list[v2][2],
                                         vertex_list[v3][0], vertex_list[v3][1], vertex_list[v3][2])

            Job.yieldThread()

        # TODO: We currently do not check for normals and simply recalculate them.
        mesh_builder.calculateNormals()
        mesh_builder.setFileName(name)
        mesh_data = mesh_builder.build()

        if len(mesh_data.getVertices()):
            node.setMeshData(mesh_data)

        node.setSelectable(True)
        return node
Exemple #27
0
    def read(self, file_name):
        result = None
        extension = os.path.splitext(file_name)[1]
        if extension.lower() == self._supported_extension:
            result = SceneNode()
            # The base object of 3mf is a zipped archive.
            archive = zipfile.ZipFile(file_name, "r")
            try:
                root = ET.parse(archive.open("3D/3dmodel.model"))

                # There can be multiple objects, try to load all of them.
                objects = root.findall("./3mf:resources/3mf:object",
                                       self._namespaces)
                if len(objects) == 0:
                    Logger.log(
                        "w",
                        "No objects found in 3MF file %s, either the file is corrupt or you are using an outdated format",
                        file_name)
                    return None

                for object in objects:
                    mesh = MeshData()
                    node = SceneNode()
                    vertex_list = []
                    #for vertex in object.mesh.vertices.vertex:
                    for vertex in object.findall(".//3mf:vertex",
                                                 self._namespaces):
                        vertex_list.append([
                            vertex.get("x"),
                            vertex.get("y"),
                            vertex.get("z")
                        ])
                        Job.yieldThread()

                    triangles = object.findall(".//3mf:triangle",
                                               self._namespaces)

                    mesh.reserveFaceCount(len(triangles))

                    #for triangle in object.mesh.triangles.triangle:
                    for triangle in triangles:
                        v1 = int(triangle.get("v1"))
                        v2 = int(triangle.get("v2"))
                        v3 = int(triangle.get("v3"))
                        mesh.addFace(vertex_list[v1][0], vertex_list[v1][1],
                                     vertex_list[v1][2], vertex_list[v2][0],
                                     vertex_list[v2][1], vertex_list[v2][2],
                                     vertex_list[v3][0], vertex_list[v3][1],
                                     vertex_list[v3][2])
                        Job.yieldThread()

                    #TODO: We currently do not check for normals and simply recalculate them.
                    mesh.calculateNormals()
                    node.setMeshData(mesh)
                    node.setSelectable(True)

                    transformation = root.findall(
                        "./3mf:build/3mf:item[@objectid='{0}']".format(
                            object.get("id")), self._namespaces)
                    if transformation:
                        transformation = transformation[0]

                    if transformation.get("transform"):
                        splitted_transformation = transformation.get(
                            "transform").split()
                        ## Transformation is saved as:
                        ## M00 M01 M02 0.0
                        ## M10 M11 M12 0.0
                        ## M20 M21 M22 0.0
                        ## M30 M31 M32 1.0
                        ## We switch the row & cols as that is how everyone else uses matrices!
                        temp_mat = Matrix()
                        # Rotation & Scale
                        temp_mat._data[0, 0] = splitted_transformation[0]
                        temp_mat._data[1, 0] = splitted_transformation[1]
                        temp_mat._data[2, 0] = splitted_transformation[2]
                        temp_mat._data[0, 1] = splitted_transformation[3]
                        temp_mat._data[1, 1] = splitted_transformation[4]
                        temp_mat._data[2, 1] = splitted_transformation[5]
                        temp_mat._data[0, 2] = splitted_transformation[6]
                        temp_mat._data[1, 2] = splitted_transformation[7]
                        temp_mat._data[2, 2] = splitted_transformation[8]

                        # Translation
                        temp_mat._data[0, 3] = splitted_transformation[9]
                        temp_mat._data[1, 3] = splitted_transformation[10]
                        temp_mat._data[2, 3] = splitted_transformation[11]

                        node.setPosition(
                            Vector(temp_mat.at(0, 3), temp_mat.at(1, 3),
                                   temp_mat.at(2, 3)))

                        temp_quaternion = Quaternion()
                        temp_quaternion.setByMatrix(temp_mat)
                        node.setOrientation(temp_quaternion)

                        # Magical scale extraction
                        scale = temp_mat.getTransposed().multiply(temp_mat)
                        scale_x = math.sqrt(scale.at(0, 0))
                        scale_y = math.sqrt(scale.at(1, 1))
                        scale_z = math.sqrt(scale.at(2, 2))
                        node.setScale(Vector(scale_x, scale_y, scale_z))

                        # We use a different coordinate frame, so rotate.
                        #rotation = Quaternion.fromAngleAxis(-0.5 * math.pi, Vector(1,0,0))
                        #node.rotate(rotation)
                    result.addChild(node)

                    Job.yieldThread()

                #If there is more then one object, group them.
                try:
                    if len(objects) > 1:
                        group_decorator = GroupDecorator()
                        result.addDecorator(group_decorator)
                except:
                    pass
            except Exception as e:
                Logger.log("e", "exception occured in 3mf reader: %s", e)
        return result
Exemple #28
0
    def _convertSavitarNodeToUMNode(self, savitar_node):
        um_node = SceneNode()
        transformation = self._createMatrixFromTransformationString(savitar_node.getTransformation())
        um_node.setTransformation(transformation)
        mesh_builder = MeshBuilder()

        data = numpy.fromstring(savitar_node.getMeshData().getFlatVerticesAsBytes(), dtype=numpy.float32)

        vertices = numpy.resize(data, (int(data.size / 3), 3))
        mesh_builder.setVertices(vertices)
        mesh_builder.calculateNormals(fast=True)
        mesh_data = mesh_builder.build()

        if len(mesh_data.getVertices()):
            um_node.setMeshData(mesh_data)

        for child in savitar_node.getChildren():
            child_node = self._convertSavitarNodeToUMNode(child)
            if child_node:
                um_node.addChild(child_node)

        if um_node.getMeshData() is None and len(um_node.getChildren()) == 0:
            return None

        settings = savitar_node.getSettings()

        # Add the setting override decorator, so we can add settings to this node.
        if settings:
            um_node.addDecorator(SettingOverrideDecorator())

            global_container_stack = Application.getInstance().getGlobalContainerStack()
            # Ensure the correct next container for the SettingOverride decorator is set.
            if global_container_stack:
                multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1

                # Ensure that all extruder data is reset
                if not multi_extrusion:
                    default_stack_id = global_container_stack.getId()
                else:
                    default_stack = ExtruderManager.getInstance().getExtruderStack(0)
                    if default_stack:
                        default_stack_id = default_stack.getId()
                    else:
                        default_stack_id = global_container_stack.getId()
                um_node.callDecoration("setActiveExtruder", default_stack_id)

                # Get the definition & set it
                definition = QualityManager.getInstance().getParentMachineDefinition(global_container_stack.getBottom())
                um_node.callDecoration("getStack").getTop().setDefinition(definition)

            setting_container = um_node.callDecoration("getStack").getTop()

            for key in settings:
                setting_value = settings[key]

                # Extruder_nr is a special case.
                if key == "extruder_nr":
                    extruder_stack = ExtruderManager.getInstance().getExtruderStack(int(setting_value))
                    if extruder_stack:
                        um_node.callDecoration("setActiveExtruder", extruder_stack.getId())
                    else:
                        Logger.log("w", "Unable to find extruder in position %s", setting_value)
                    continue
                setting_container.setProperty(key,"value", setting_value)

        if len(um_node.getChildren()) > 0:
            group_decorator = GroupDecorator()
            um_node.addDecorator(group_decorator)
        um_node.setSelectable(True)
        if um_node.getMeshData():
            # Assuming that all nodes with mesh data are printable objects
            # affects (auto) slicing
            sliceable_decorator = SliceableObjectDecorator()
            um_node.addDecorator(sliceable_decorator)
        return um_node
Exemple #29
0
    def read(self, file_name):
        result = SceneNode()
        # The base object of 3mf is a zipped archive.
        archive = zipfile.ZipFile(file_name, "r")
        try:
            root = ET.parse(archive.open("3D/3dmodel.model"))

            # There can be multiple objects, try to load all of them.
            objects = root.findall("./3mf:resources/3mf:object",
                                   self._namespaces)
            if len(objects) == 0:
                Logger.log(
                    "w",
                    "No objects found in 3MF file %s, either the file is corrupt or you are using an outdated format",
                    file_name)
                return None

            for entry in objects:
                mesh_builder = MeshBuilder()
                node = SceneNode()
                vertex_list = []
                #for vertex in entry.mesh.vertices.vertex:
                for vertex in entry.findall(".//3mf:vertex", self._namespaces):
                    vertex_list.append(
                        [vertex.get("x"),
                         vertex.get("y"),
                         vertex.get("z")])
                    Job.yieldThread()

                triangles = entry.findall(".//3mf:triangle", self._namespaces)
                mesh_builder.reserveFaceCount(len(triangles))

                for triangle in triangles:
                    v1 = int(triangle.get("v1"))
                    v2 = int(triangle.get("v2"))
                    v3 = int(triangle.get("v3"))

                    mesh_builder.addFaceByPoints(
                        vertex_list[v1][0], vertex_list[v1][1],
                        vertex_list[v1][2], vertex_list[v2][0],
                        vertex_list[v2][1], vertex_list[v2][2],
                        vertex_list[v3][0], vertex_list[v3][1],
                        vertex_list[v3][2])

                    Job.yieldThread()

                # Rotate the model; We use a different coordinate frame.
                rotation = Matrix()
                rotation.setByRotationAxis(-0.5 * math.pi, Vector(1, 0, 0))

                # TODO: We currently do not check for normals and simply recalculate them.
                mesh_builder.calculateNormals()
                mesh_builder.setFileName(file_name)
                node.setMeshData(mesh_builder.build().getTransformed(rotation))
                node.setSelectable(True)

                transformations = root.findall(
                    "./3mf:build/3mf:item[@objectid='{0}']".format(
                        entry.get("id")), self._namespaces)
                transformation = transformations[0] if transformations else None
                if transformation is not None and transformation.get(
                        "transform"):
                    splitted_transformation = transformation.get(
                        "transform").split()
                    ## Transformation is saved as:
                    ## M00 M01 M02 0.0
                    ## M10 M11 M12 0.0
                    ## M20 M21 M22 0.0
                    ## M30 M31 M32 1.0
                    ## We switch the row & cols as that is how everyone else uses matrices!
                    temp_mat = Matrix()
                    # Rotation & Scale
                    temp_mat._data[0, 0] = splitted_transformation[0]
                    temp_mat._data[1, 0] = splitted_transformation[1]
                    temp_mat._data[2, 0] = splitted_transformation[2]
                    temp_mat._data[0, 1] = splitted_transformation[3]
                    temp_mat._data[1, 1] = splitted_transformation[4]
                    temp_mat._data[2, 1] = splitted_transformation[5]
                    temp_mat._data[0, 2] = splitted_transformation[6]
                    temp_mat._data[1, 2] = splitted_transformation[7]
                    temp_mat._data[2, 2] = splitted_transformation[8]

                    # Translation
                    temp_mat._data[0, 3] = splitted_transformation[9]
                    temp_mat._data[1, 3] = splitted_transformation[10]
                    temp_mat._data[2, 3] = splitted_transformation[11]

                    node.setTransformation(temp_mat)

                result.addChild(node)

                Job.yieldThread()

            # If there is more then one object, group them.
            if len(objects) > 1:
                group_decorator = GroupDecorator()
                result.addDecorator(group_decorator)
            elif len(objects) == 1:
                result = result.getChildren()[
                    0]  # Only one object found, return that.
        except Exception as e:
            Logger.log("e", "exception occured in 3mf reader: %s", e)

        try:  # Selftest - There might be more functions that should fail
            boundingBox = result.getBoundingBox()
            boundingBox.isValid()
        except:
            return None

        return result