From 8982664551d9364f70ac219dde42bbd96fce46d5 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 5 Feb 2019 20:23:24 +0100 Subject: [PATCH] Improved stability (fixed crashes) of the Cut by plane function by replacing the cut triangulation with freeglu tesselator. Added performance tracing output of the Cut by plane function. Added wait cursor to split to parts / objects, object cut, save to AMF/3MF. --- src/libslic3r/Model.cpp | 4 +++ src/libslic3r/TriangleMesh.cpp | 54 ++++++++++--------------------- src/slic3r/GUI/GUI_ObjectList.cpp | 2 ++ src/slic3r/GUI/Plater.cpp | 4 +++ 4 files changed, 27 insertions(+), 37 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 08eb8df81..2f1e8c275 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1120,6 +1120,8 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b { if (!keep_upper && !keep_lower) { return {}; } + BOOST_LOG_TRIVIAL(trace) << "ModelObject::cut - start"; + // Clone the object to duplicate instances, materials etc. ModelObject* upper = keep_upper ? ModelObject::new_clone(*this) : nullptr; ModelObject* lower = keep_lower ? ModelObject::new_clone(*this) : nullptr; @@ -1254,6 +1256,8 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b res.push_back(lower); } + BOOST_LOG_TRIVIAL(trace) << "ModelObject::cut - end"; + return res; } diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 8b69a9e5c..b93ce12b5 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -1,6 +1,7 @@ #include "TriangleMesh.hpp" #include "ClipperUtils.hpp" #include "Geometry.hpp" +#include "Tesselate.hpp" #include "qhull/src/libqhullcpp/Qhull.h" #include "qhull/src/libqhullcpp/QhullFacetList.h" #include "qhull/src/libqhullcpp/QhullVertexSet.h" @@ -1686,6 +1687,7 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower) { IntersectionLines upper_lines, lower_lines; + BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::cut - slicing object"; float scaled_z = scale_(z); for (int facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx) { stl_facet* facet = &this->mesh->stl.facet_start[facet_idx]; @@ -1775,57 +1777,35 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower) } } - // triangulate holes of upper mesh if (upper != NULL) { - // compute shape of section + BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::cut - triangulating upper part"; ExPolygons section; this->make_expolygons_simple(upper_lines, §ion); - - // triangulate section - Polygons triangles; - for (ExPolygons::const_iterator expolygon = section.begin(); expolygon != section.end(); ++expolygon) - expolygon->triangulate_p2t(&triangles); - - // convert triangles to facets and append them to mesh - for (Polygons::const_iterator polygon = triangles.begin(); polygon != triangles.end(); ++polygon) { - Polygon p = *polygon; - p.reverse(); - stl_facet facet; - facet.normal = stl_normal(0, 0, -1.f); - for (size_t i = 0; i <= 2; ++i) { - facet.vertex[i](0) = unscale(p.points[i](0)); - facet.vertex[i](1) = unscale(p.points[i](1)); - facet.vertex[i](2) = z; - } + Pointf3s triangles = triangulate_expolygons_3df(section, z, true); + stl_facet facet; + facet.normal = stl_normal(0, 0, -1.f); + for (size_t i = 0; i < triangles.size(); ) { + for (size_t j = 0; j < 3; ++ j) + facet.vertex[j] = triangles[i ++].cast(); stl_add_facet(&upper->stl, &facet); } } - // triangulate holes of lower mesh if (lower != NULL) { - // compute shape of section + BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::cut - triangulating lower part"; ExPolygons section; this->make_expolygons_simple(lower_lines, §ion); - - // triangulate section - Polygons triangles; - for (ExPolygons::const_iterator expolygon = section.begin(); expolygon != section.end(); ++expolygon) - expolygon->triangulate_p2t(&triangles); - - // convert triangles to facets and append them to mesh - for (Polygons::const_iterator polygon = triangles.begin(); polygon != triangles.end(); ++polygon) { - stl_facet facet; - facet.normal = stl_normal(0, 0, 1.f); - for (size_t i = 0; i <= 2; ++i) { - facet.vertex[i](0) = unscale(polygon->points[i](0)); - facet.vertex[i](1) = unscale(polygon->points[i](1)); - facet.vertex[i](2) = z; - } + Pointf3s triangles = triangulate_expolygons_3df(section, z, false); + stl_facet facet; + facet.normal = stl_normal(0, 0, -1.f); + for (size_t i = 0; i < triangles.size(); ) { + for (size_t j = 0; j < 3; ++ j) + facet.vertex[j] = triangles[i ++].cast(); stl_add_facet(&lower->stl, &facet); } } - // Update the bounding box / sphere of the new meshes. + BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::cut - updating object sizes"; stl_get_size(&upper->stl); stl_get_size(&lower->stl); } diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 9a789633f..f243143da 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1347,6 +1347,8 @@ void ObjectList::split() return; } + wxBusyCursor wait; + auto model_object = (*m_objects)[obj_idx]; auto parent = m_objects_model->GetTopParent(item); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e96e74492..1968dad69 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1886,6 +1886,7 @@ void Plater::priv::split_object() return; } + wxBusyCursor wait; ModelObjectPtrs new_objects; current_model_object->split(&new_objects); if (new_objects.size() == 1) @@ -2824,6 +2825,7 @@ void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_uppe return; } + wxBusyCursor wait; const auto new_objects = object->cut(instance_idx, z, keep_upper, keep_lower, rotate_lower); remove(obj_idx); @@ -2907,6 +2909,7 @@ void Plater::export_amf() const std::string path_u8 = into_u8(path); DynamicPrintConfig cfg = wxGetApp().preset_bundle->full_config_secure(); + wxBusyCursor wait; if (Slic3r::store_amf(path_u8.c_str(), &p->model, dialog->get_checkbox_value() ? &cfg : nullptr)) { // Success p->statusbar()->set_status_text(wxString::Format(_(L("AMF file exported to %s")), path)); @@ -2937,6 +2940,7 @@ void Plater::export_3mf(const boost::filesystem::path& output_path) DynamicPrintConfig cfg = wxGetApp().preset_bundle->full_config_secure(); const std::string path_u8 = into_u8(path); + wxBusyCursor wait; if (Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr)) { // Success p->statusbar()->set_status_text(wxString::Format(_(L("3MF file exported to %s")), path));