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
#endif // CSGMESH_HPP

View file

@ -257,7 +257,7 @@ void perform_csgmesh_booleans_mcut(MeshBoolean::mcut::McutMeshPtr& mcutm,
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;
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);
//It ret = csgrange.end();
//for (size_t i = 0; i < csgrange.size(); ++i) {
// if (!cgalmeshes[i]) {
// auto it = csgrange.begin();
// std::advance(it, i);
// vfn(it);
It ret = csgrange.end();
for (size_t i = 0; i < csgrange.size(); ++i) {
if (!cgalmeshes[i]) {
auto it = csgrange.begin();
std::advance(it, i);
vfn(it);
// if (ret == csgrange.end())
// ret = it;
// }
//}
if (ret == csgrange.end())
ret = it;
}
}
return { fail_reason,fail_part_name };
return { fail_reason,fail_part_name, ret};
}
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)
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);
};
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.
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;
for (const ModelVolume *v : mo.volumes)
//Prusa export negative parts
std::vector<csg::CSGPart> csgmesh;
csgmesh.reserve(2 * mo.volumes.size());
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) {
TriangleMesh vols_mesh(mesh);
mesh = TriangleMesh();