Export negative parts.

This commit is contained in:
vovodroid 2024-10-05 21:48:16 +03:00
parent 9245a87293
commit 9d37d1a084
3 changed files with 78 additions and 21 deletions

View file

@ -82,6 +82,40 @@ struct CSGPart {
{} {}
}; };
//Prusa
// Check if there are only positive parts (Union) within the collection.
template<class Cont> bool is_all_positive(const Cont &csgmesh)
{
bool is_all_pos =
std::all_of(csgmesh.begin(),
csgmesh.end(),
[](auto &part) {
return csg::get_operation(part) == csg::CSGType::Union;
});
return is_all_pos;
}
//Prusa
// Merge all the positive parts of the collection into a single triangle mesh without performing
// any booleans.
template<class Cont>
indexed_triangle_set csgmesh_merge_positive_parts(const Cont &csgmesh)
{
indexed_triangle_set m;
for (auto &csgpart : csgmesh) {
auto op = csg::get_operation(csgpart);
const indexed_triangle_set * pmesh = csg::get_mesh(csgpart);
if (pmesh && op == csg::CSGType::Union) {
indexed_triangle_set mcpy = *pmesh;
its_transform(mcpy, csg::get_transform(csgpart), true);
its_merge(m, mcpy);
}
}
return m;
}
}} // namespace Slic3r::csg }} // namespace Slic3r::csg
#endif // CSGMESH_HPP #endif // CSGMESH_HPP

View file

@ -257,7 +257,7 @@ void perform_csgmesh_booleans_mcut(MeshBoolean::mcut::McutMeshPtr& mcutm,
template<class It, class Visitor> template<class It, class Visitor>
std::tuple<BooleanFailReason,std::string> check_csgmesh_booleans(const Range<It> &csgrange, Visitor &&vfn) std::tuple<BooleanFailReason,std::string, It> check_csgmesh_booleans(const Range<It> &csgrange, Visitor &&vfn)
{ {
using namespace detail_cgal; using namespace detail_cgal;
BooleanFailReason fail_reason = BooleanFailReason::OK; BooleanFailReason fail_reason = BooleanFailReason::OK;
@ -304,23 +304,23 @@ std::tuple<BooleanFailReason,std::string> check_csgmesh_booleans(const Range<It>
}; };
execution::for_each(ex_tbb, size_t(0), csgrange.size(), check_part); execution::for_each(ex_tbb, size_t(0), csgrange.size(), check_part);
//It ret = csgrange.end(); It ret = csgrange.end();
//for (size_t i = 0; i < csgrange.size(); ++i) { for (size_t i = 0; i < csgrange.size(); ++i) {
// if (!cgalmeshes[i]) { if (!cgalmeshes[i]) {
// auto it = csgrange.begin(); auto it = csgrange.begin();
// std::advance(it, i); std::advance(it, i);
// vfn(it); vfn(it);
// if (ret == csgrange.end()) if (ret == csgrange.end())
// ret = it; ret = it;
// } }
//} }
return { fail_reason,fail_part_name }; return { fail_reason,fail_part_name, ret};
} }
template<class It> template<class It>
std::tuple<BooleanFailReason, std::string> check_csgmesh_booleans(const Range<It> &csgrange, bool use_mcut=false) std::tuple<BooleanFailReason, std::string, It> check_csgmesh_booleans(const Range<It> &csgrange, bool use_mcut=false)
{ {
if(!use_mcut) if(!use_mcut)
return check_csgmesh_booleans(csgrange, [](auto &) {}); return check_csgmesh_booleans(csgrange, [](auto &) {});
@ -354,7 +354,7 @@ std::tuple<BooleanFailReason, std::string> check_csgmesh_booleans(const Range<It
McutMeshes[i] = std::move(m); McutMeshes[i] = std::move(m);
}; };
execution::for_each(ex_tbb, size_t(0), csgrange.size(), check_part); execution::for_each(ex_tbb, size_t(0), csgrange.size(), check_part);
return { fail_reason,fail_part_name }; return { fail_reason,fail_part_name, csgrange.end() };
} }
} }

View file

@ -11686,14 +11686,37 @@ void Plater::export_stl(bool extended, bool selection_only, bool multi_stls)
} }
// Following lambda generates a combined mesh for export with normals pointing outwards. // Following lambda generates a combined mesh for export with normals pointing outwards.
auto mesh_to_export_fff_no_boolean = [](const ModelObject &mo, int instance_id) { auto mesh_to_export_fff_no_boolean = [this](const ModelObject &mo, int instance_id) {
TriangleMesh mesh; TriangleMesh mesh;
for (const ModelVolume *v : mo.volumes)
if (v->is_model_part()) { //Prusa export negative parts
TriangleMesh vol_mesh(v->mesh()); std::vector<csg::CSGPart> csgmesh;
vol_mesh.transform(v->get_matrix(), true); csgmesh.reserve(2 * mo.volumes.size());
mesh.merge(vol_mesh); csg::model_to_csgmesh(mo, Transform3d::Identity(), std::back_inserter(csgmesh),
} csg::mpartsPositive | csg::mpartsNegative | csg::mpartsDoSplits);
auto csgrange = range(csgmesh);
if (csg::is_all_positive(csgrange)) {
mesh = TriangleMesh{csg::csgmesh_merge_positive_parts(csgrange)};
} else if (std::get<2>(csg::check_csgmesh_booleans(csgrange)) == csgrange.end()) {
try {
auto cgalm = csg::perform_csgmesh_booleans(csgrange);
mesh = MeshBoolean::cgal::cgal_to_triangle_mesh(*cgalm);
} catch (...) {}
}
if (mesh.empty()) {
get_notification_manager()->push_plater_error_notification(
_u8L("Unable to perform boolean operation on model meshes. "
"Only positive parts will be exported."));
for (const ModelVolume* v : mo.volumes)
if (v->is_model_part()) {
TriangleMesh vol_mesh(v->mesh());
vol_mesh.transform(v->get_matrix(), true);
mesh.merge(vol_mesh);
}
}
if (instance_id == -1) { if (instance_id == -1) {
TriangleMesh vols_mesh(mesh); TriangleMesh vols_mesh(mesh);
mesh = TriangleMesh(); mesh = TriangleMesh();