mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 01:07:57 -06:00
Export negative parts.
This commit is contained in:
parent
9245a87293
commit
9d37d1a084
3 changed files with 78 additions and 21 deletions
|
@ -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
|
||||||
|
|
|
@ -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() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue