From 5b98f1a068cdfd3b01015b6597a8928f475c97ed Mon Sep 17 00:00:00 2001
From: bubnikv <bubnikv@gmail.com>
Date: Sun, 26 Feb 2017 22:03:03 +0100
Subject: [PATCH] Some utility methods to help loading models from the disk.
 Not quite sucessfull try to fix the crahes on mesh cut.

---
 xs/src/libslic3r/Model.cpp | 68 ++++++++++++++++++++++++++++++++++++--
 xs/src/libslic3r/Model.hpp |  4 +++
 2 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp
index 920da5d36..2fe6540e7 100644
--- a/xs/src/libslic3r/Model.cpp
+++ b/xs/src/libslic3r/Model.cpp
@@ -44,6 +44,32 @@ Model::add_object()
     return new_object;
 }
 
+ModelObject*
+Model::add_object(const char *name, const char *path, const TriangleMesh &mesh)
+{
+    ModelObject* new_object = new ModelObject(this);
+    this->objects.push_back(new_object);
+    new_object->name = name;
+    new_object->input_file = path;
+    ModelVolume *new_volume = new_object->add_volume(mesh);
+    new_volume->name = name;
+    new_object->invalidate_bounding_box();
+    return new_object;
+}
+
+ModelObject*
+Model::add_object(const char *name, const char *path, TriangleMesh &&mesh)
+{
+    ModelObject* new_object = new ModelObject(this);
+    this->objects.push_back(new_object);
+    new_object->name = name;
+    new_object->input_file = path;
+    ModelVolume *new_volume = new_object->add_volume(std::move(mesh));
+    new_volume->name = name;
+    new_object->invalidate_bounding_box();
+    return new_object;
+}
+
 ModelObject*
 Model::add_object(const ModelObject &other, bool copy_volumes)
 {
@@ -396,6 +422,15 @@ ModelObject::add_volume(const TriangleMesh &mesh)
     return v;
 }
 
+ModelVolume*
+ModelObject::add_volume(TriangleMesh &&mesh)
+{
+    ModelVolume* v = new ModelVolume(this, std::move(mesh));
+    this->volumes.push_back(v);
+    this->invalidate_bounding_box();
+    return v;
+}
+
 ModelVolume*
 ModelObject::add_volume(const ModelVolume &other)
 {
@@ -672,10 +707,35 @@ ModelObject::cut(coordf_t z, Model* model) const
             upper->add_volume(*volume);
             lower->add_volume(*volume);
         } else {
-            TriangleMeshSlicer tms(&volume->mesh);
             TriangleMesh upper_mesh, lower_mesh;
             // TODO: shouldn't we use object bounding box instead of per-volume bb?
-            tms.cut(z + volume->mesh.bounding_box().min.z, &upper_mesh, &lower_mesh);
+            coordf_t cut_z = z + volume->mesh.bounding_box().min.z;
+            if (false) {
+//            if (volume->mesh.has_multiple_patches()) {
+                // Cutting algorithm does not work on intersecting meshes.
+                // As we are not sure whether the meshes don't intersect,
+                // we rather split the mesh into multiple non-intersecting pieces.
+                TriangleMeshPtrs meshptrs = volume->mesh.split();
+                for (TriangleMeshPtrs::iterator mesh = meshptrs.begin(); mesh != meshptrs.end(); ++mesh) {
+                    printf("Cutting mesh patch %d of %d\n", size_t(mesh - meshptrs.begin()));
+                    (*mesh)->repair();
+                    TriangleMeshSlicer tms(*mesh);
+                    if (mesh == meshptrs.begin()) {
+                        tms.cut(cut_z, &upper_mesh, &lower_mesh);
+                    } else {
+                        TriangleMesh upper_mesh_this, lower_mesh_this;
+                        tms.cut(cut_z, &upper_mesh_this, &lower_mesh_this);
+                        upper_mesh.merge(upper_mesh_this);
+                        lower_mesh.merge(lower_mesh_this);
+                    }
+                    delete *mesh;
+                }
+            } else {
+                printf("Cutting mesh patch\n");
+                TriangleMeshSlicer tms(&volume->mesh);
+                tms.cut(cut_z, &upper_mesh, &lower_mesh);
+            }
+
             upper_mesh.repair();
             lower_mesh.repair();
             upper_mesh.reset_repair_stats();
@@ -732,6 +792,10 @@ ModelVolume::ModelVolume(ModelObject* object, const TriangleMesh &mesh)
 :   mesh(mesh), modifier(false), object(object)
 {}
 
+ModelVolume::ModelVolume(ModelObject* object, TriangleMesh &&mesh)
+:   mesh(std::move(mesh)), modifier(false), object(object)
+{}
+
 ModelVolume::ModelVolume(ModelObject* object, const ModelVolume &other)
 :   name(other.name), mesh(other.mesh), config(other.config),
     modifier(other.modifier), object(object)
diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp
index 5e1e29cd5..9334fc8f2 100644
--- a/xs/src/libslic3r/Model.hpp
+++ b/xs/src/libslic3r/Model.hpp
@@ -48,6 +48,8 @@ public:
     void swap(Model &other);
     ~Model();
     ModelObject* add_object();
+    ModelObject* add_object(const char *name, const char *path, const TriangleMesh &mesh);
+    ModelObject* add_object(const char *name, const char *path, TriangleMesh &&mesh);
     ModelObject* add_object(const ModelObject &other, bool copy_volumes = true);
     void delete_object(size_t idx);
     void clear_objects();
@@ -135,6 +137,7 @@ public:
     Model* get_model() const { return this->model; };
     
     ModelVolume* add_volume(const TriangleMesh &mesh);
+    ModelVolume* add_volume(TriangleMesh &&mesh);
     ModelVolume* add_volume(const ModelVolume &volume);
     void delete_volume(size_t idx);
     void clear_volumes();
@@ -206,6 +209,7 @@ private:
     t_model_material_id _material_id;
     
     ModelVolume(ModelObject *object, const TriangleMesh &mesh);
+    ModelVolume(ModelObject *object, TriangleMesh &&mesh);
     ModelVolume(ModelObject *object, const ModelVolume &other);
 };