ENH:loading the step in boost thread
github: #6079 Change-Id: I0a289fc9730e7d091a71137cf11a711dfee5392f (cherry picked from commit b454e7d8bb91b62b3be6121c567f7aee291eff50)
This commit is contained in:
parent
cf63988a45
commit
b7ffba39e4
|
@ -1,6 +1,7 @@
|
|||
#include "../libslic3r.h"
|
||||
#include "../Model.hpp"
|
||||
#include "../TriangleMesh.hpp"
|
||||
#include "libslic3r/Thread.hpp"
|
||||
|
||||
#include "STEP.hpp"
|
||||
|
||||
|
@ -225,189 +226,189 @@ static void getNamedSolids(const TopLoc_Location& location,
|
|||
}
|
||||
}
|
||||
|
||||
bool load_step(const char *path, Model *model, bool& is_cancel,
|
||||
double linear_defletion/*=0.003*/,
|
||||
double angle_defletion/*= 0.5*/,
|
||||
bool isSplitCompound,
|
||||
ImportStepProgressFn stepFn, StepIsUtf8Fn isUtf8Fn, long& mesh_face_num)
|
||||
{
|
||||
bool cb_cancel = false;
|
||||
if (stepFn) {
|
||||
stepFn(LOAD_STEP_STAGE_READ_FILE, 0, 1, cb_cancel);
|
||||
is_cancel = cb_cancel;
|
||||
if (cb_cancel) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!StepPreProcessor::isUtf8File(path) && isUtf8Fn)
|
||||
isUtf8Fn(false);
|
||||
std::string file_after_preprocess = std::string(path);
|
||||
|
||||
std::vector<NamedSolid> namedSolids;
|
||||
Handle(TDocStd_Document) document;
|
||||
Handle(XCAFApp_Application) application = XCAFApp_Application::GetApplication();
|
||||
application->NewDocument(file_after_preprocess.c_str(), document);
|
||||
STEPCAFControl_Reader reader;
|
||||
reader.SetNameMode(true);
|
||||
//BBS: Todo, read file is slow which cause the progress_bar no update and gui no response
|
||||
IFSelect_ReturnStatus stat = reader.ReadFile(file_after_preprocess.c_str());
|
||||
if (stat != IFSelect_RetDone || !reader.Transfer(document)) {
|
||||
application->Close(document);
|
||||
throw std::logic_error{ std::string{"Could not read '"} + path + "'" };
|
||||
return false;
|
||||
}
|
||||
Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool(document->Main());
|
||||
TDF_LabelSequence topLevelShapes;
|
||||
shapeTool->GetFreeShapes(topLevelShapes);
|
||||
|
||||
unsigned int id{1};
|
||||
Standard_Integer topShapeLength = topLevelShapes.Length() + 1;
|
||||
auto stage_unit2 = topShapeLength / LOAD_STEP_STAGE_UNIT_NUM + 1;
|
||||
|
||||
for (Standard_Integer iLabel = 1; iLabel < topShapeLength; ++iLabel) {
|
||||
if (stepFn) {
|
||||
if ((iLabel % stage_unit2) == 0) {
|
||||
stepFn(LOAD_STEP_STAGE_GET_SOLID, iLabel, topShapeLength, cb_cancel);
|
||||
is_cancel = cb_cancel;
|
||||
}
|
||||
if (cb_cancel) {
|
||||
shapeTool.reset(nullptr);
|
||||
application->Close(document);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
getNamedSolids(TopLoc_Location{}, "", id, shapeTool, topLevelShapes.Value(iLabel), namedSolids, isSplitCompound);
|
||||
}
|
||||
|
||||
std::vector<stl_file> stl;
|
||||
stl.resize(namedSolids.size());
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, namedSolids.size()), [&](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t i = range.begin(); i < range.end(); i++) {
|
||||
BRepMesh_IncrementalMesh mesh(namedSolids[i].solid, linear_defletion, false, angle_defletion, true);
|
||||
// BBS: calculate total number of the nodes and triangles
|
||||
int aNbNodes = 0;
|
||||
int aNbTriangles = 0;
|
||||
for (TopExp_Explorer anExpSF(namedSolids[i].solid, TopAbs_FACE); anExpSF.More(); anExpSF.Next()) {
|
||||
TopLoc_Location aLoc;
|
||||
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(TopoDS::Face(anExpSF.Current()), aLoc);
|
||||
if (!aTriangulation.IsNull()) {
|
||||
aNbNodes += aTriangulation->NbNodes();
|
||||
aNbTriangles += aTriangulation->NbTriangles();
|
||||
}
|
||||
}
|
||||
|
||||
if (aNbTriangles == 0 || aNbNodes == 0)
|
||||
// BBS: No triangulation on the shape.
|
||||
continue;
|
||||
|
||||
stl[i].stats.type = inmemory;
|
||||
stl[i].stats.number_of_facets = (uint32_t) aNbTriangles;
|
||||
stl[i].stats.original_num_facets = stl[i].stats.number_of_facets;
|
||||
stl_allocate(&stl[i]);
|
||||
|
||||
std::vector<Vec3f> points;
|
||||
points.reserve(aNbNodes);
|
||||
// BBS: count faces missing triangulation
|
||||
Standard_Integer aNbFacesNoTri = 0;
|
||||
// BBS: fill temporary triangulation
|
||||
Standard_Integer aNodeOffset = 0;
|
||||
Standard_Integer aTriangleOffet = 0;
|
||||
for (TopExp_Explorer anExpSF(namedSolids[i].solid, TopAbs_FACE); anExpSF.More(); anExpSF.Next()) {
|
||||
const TopoDS_Shape &aFace = anExpSF.Current();
|
||||
TopLoc_Location aLoc;
|
||||
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(TopoDS::Face(aFace), aLoc);
|
||||
if (aTriangulation.IsNull()) {
|
||||
++aNbFacesNoTri;
|
||||
continue;
|
||||
}
|
||||
// BBS: copy nodes
|
||||
gp_Trsf aTrsf = aLoc.Transformation();
|
||||
for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) {
|
||||
gp_Pnt aPnt = aTriangulation->Node(aNodeIter);
|
||||
aPnt.Transform(aTrsf);
|
||||
points.emplace_back(std::move(Vec3f(aPnt.X(), aPnt.Y(), aPnt.Z())));
|
||||
}
|
||||
// BBS: copy triangles
|
||||
const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
|
||||
Standard_Integer anId[3] = {};
|
||||
for (Standard_Integer aTriIter = 1; aTriIter <= aTriangulation->NbTriangles(); ++aTriIter) {
|
||||
Poly_Triangle aTri = aTriangulation->Triangle(aTriIter);
|
||||
|
||||
aTri.Get(anId[0], anId[1], anId[2]);
|
||||
if (anOrientation == TopAbs_REVERSED)
|
||||
std::swap(anId[1], anId[2]);
|
||||
// BBS: save triangles facets
|
||||
stl_facet facet;
|
||||
facet.vertex[0] = points[anId[0] + aNodeOffset - 1].cast<float>();
|
||||
facet.vertex[1] = points[anId[1] + aNodeOffset - 1].cast<float>();
|
||||
facet.vertex[2] = points[anId[2] + aNodeOffset - 1].cast<float>();
|
||||
facet.extra[0] = 0;
|
||||
facet.extra[1] = 0;
|
||||
stl_normal normal;
|
||||
stl_calculate_normal(normal, &facet);
|
||||
stl_normalize_vector(normal);
|
||||
facet.normal = normal;
|
||||
stl[i].facet_start[aTriangleOffet + aTriIter - 1] = facet;
|
||||
}
|
||||
|
||||
aNodeOffset += aTriangulation->NbNodes();
|
||||
aTriangleOffet += aTriangulation->NbTriangles();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (mesh_face_num != -1) {
|
||||
for (size_t i = 0; i < stl.size(); i++) {
|
||||
// Test for overflow
|
||||
mesh_face_num += stl[i].stats.number_of_facets;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ModelObject *new_object = model->add_object();
|
||||
const char * last_slash = strrchr(path, DIR_SEPARATOR);
|
||||
new_object->name.assign((last_slash == nullptr) ? path : last_slash + 1);
|
||||
new_object->input_file = path;
|
||||
|
||||
auto stage_unit3 = stl.size() / LOAD_STEP_STAGE_UNIT_NUM + 1;
|
||||
for (size_t i = 0; i < stl.size(); i++) {
|
||||
if (stepFn) {
|
||||
if ((i % stage_unit3) == 0) {
|
||||
stepFn(LOAD_STEP_STAGE_GET_MESH, i, stl.size(), cb_cancel);
|
||||
is_cancel = cb_cancel;
|
||||
}
|
||||
if (cb_cancel) {
|
||||
model->delete_object(new_object);
|
||||
shapeTool.reset(nullptr);
|
||||
application->Close(document);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//BBS: maybe mesh is empty from step file. Don't add
|
||||
if (stl[i].stats.number_of_facets > 0) {
|
||||
TriangleMesh triangle_mesh;
|
||||
triangle_mesh.from_stl(stl[i]);
|
||||
ModelVolume* new_volume = new_object->add_volume(std::move(triangle_mesh));
|
||||
new_volume->name = namedSolids[i].name;
|
||||
new_volume->source.input_file = path;
|
||||
new_volume->source.object_idx = (int)model->objects.size() - 1;
|
||||
new_volume->source.volume_idx = (int)new_object->volumes.size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
shapeTool.reset(nullptr);
|
||||
application->Close(document);
|
||||
|
||||
//BBS: no valid shape from the step, delete the new object as well
|
||||
if (new_object->volumes.size() == 0) {
|
||||
model->delete_object(new_object);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//bool load_step(const char *path, Model *model, bool& is_cancel,
|
||||
// double linear_defletion/*=0.003*/,
|
||||
// double angle_defletion/*= 0.5*/,
|
||||
// bool isSplitCompound,
|
||||
// ImportStepProgressFn stepFn, StepIsUtf8Fn isUtf8Fn, long& mesh_face_num)
|
||||
//{
|
||||
// bool cb_cancel = false;
|
||||
// if (stepFn) {
|
||||
// stepFn(LOAD_STEP_STAGE_READ_FILE, 0, 1, cb_cancel);
|
||||
// is_cancel = cb_cancel;
|
||||
// if (cb_cancel) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!StepPreProcessor::isUtf8File(path) && isUtf8Fn)
|
||||
// isUtf8Fn(false);
|
||||
// std::string file_after_preprocess = std::string(path);
|
||||
//
|
||||
// std::vector<NamedSolid> namedSolids;
|
||||
// Handle(TDocStd_Document) document;
|
||||
// Handle(XCAFApp_Application) application = XCAFApp_Application::GetApplication();
|
||||
// application->NewDocument(file_after_preprocess.c_str(), document);
|
||||
// STEPCAFControl_Reader reader;
|
||||
// reader.SetNameMode(true);
|
||||
// //BBS: Todo, read file is slow which cause the progress_bar no update and gui no response
|
||||
// IFSelect_ReturnStatus stat = reader.ReadFile(file_after_preprocess.c_str());
|
||||
// if (stat != IFSelect_RetDone || !reader.Transfer(document)) {
|
||||
// application->Close(document);
|
||||
// throw std::logic_error{ std::string{"Could not read '"} + path + "'" };
|
||||
// return false;
|
||||
// }
|
||||
// Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool(document->Main());
|
||||
// TDF_LabelSequence topLevelShapes;
|
||||
// shapeTool->GetFreeShapes(topLevelShapes);
|
||||
//
|
||||
// unsigned int id{1};
|
||||
// Standard_Integer topShapeLength = topLevelShapes.Length() + 1;
|
||||
// auto stage_unit2 = topShapeLength / LOAD_STEP_STAGE_UNIT_NUM + 1;
|
||||
//
|
||||
// for (Standard_Integer iLabel = 1; iLabel < topShapeLength; ++iLabel) {
|
||||
// if (stepFn) {
|
||||
// if ((iLabel % stage_unit2) == 0) {
|
||||
// stepFn(LOAD_STEP_STAGE_GET_SOLID, iLabel, topShapeLength, cb_cancel);
|
||||
// is_cancel = cb_cancel;
|
||||
// }
|
||||
// if (cb_cancel) {
|
||||
// shapeTool.reset(nullptr);
|
||||
// application->Close(document);
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// getNamedSolids(TopLoc_Location{}, "", id, shapeTool, topLevelShapes.Value(iLabel), namedSolids, isSplitCompound);
|
||||
// }
|
||||
//
|
||||
// std::vector<stl_file> stl;
|
||||
// stl.resize(namedSolids.size());
|
||||
// tbb::parallel_for(tbb::blocked_range<size_t>(0, namedSolids.size()), [&](const tbb::blocked_range<size_t> &range) {
|
||||
// for (size_t i = range.begin(); i < range.end(); i++) {
|
||||
// BRepMesh_IncrementalMesh mesh(namedSolids[i].solid, linear_defletion, false, angle_defletion, true);
|
||||
// // BBS: calculate total number of the nodes and triangles
|
||||
// int aNbNodes = 0;
|
||||
// int aNbTriangles = 0;
|
||||
// for (TopExp_Explorer anExpSF(namedSolids[i].solid, TopAbs_FACE); anExpSF.More(); anExpSF.Next()) {
|
||||
// TopLoc_Location aLoc;
|
||||
// Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(TopoDS::Face(anExpSF.Current()), aLoc);
|
||||
// if (!aTriangulation.IsNull()) {
|
||||
// aNbNodes += aTriangulation->NbNodes();
|
||||
// aNbTriangles += aTriangulation->NbTriangles();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (aNbTriangles == 0 || aNbNodes == 0)
|
||||
// // BBS: No triangulation on the shape.
|
||||
// continue;
|
||||
//
|
||||
// stl[i].stats.type = inmemory;
|
||||
// stl[i].stats.number_of_facets = (uint32_t) aNbTriangles;
|
||||
// stl[i].stats.original_num_facets = stl[i].stats.number_of_facets;
|
||||
// stl_allocate(&stl[i]);
|
||||
//
|
||||
// std::vector<Vec3f> points;
|
||||
// points.reserve(aNbNodes);
|
||||
// // BBS: count faces missing triangulation
|
||||
// Standard_Integer aNbFacesNoTri = 0;
|
||||
// // BBS: fill temporary triangulation
|
||||
// Standard_Integer aNodeOffset = 0;
|
||||
// Standard_Integer aTriangleOffet = 0;
|
||||
// for (TopExp_Explorer anExpSF(namedSolids[i].solid, TopAbs_FACE); anExpSF.More(); anExpSF.Next()) {
|
||||
// const TopoDS_Shape &aFace = anExpSF.Current();
|
||||
// TopLoc_Location aLoc;
|
||||
// Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(TopoDS::Face(aFace), aLoc);
|
||||
// if (aTriangulation.IsNull()) {
|
||||
// ++aNbFacesNoTri;
|
||||
// continue;
|
||||
// }
|
||||
// // BBS: copy nodes
|
||||
// gp_Trsf aTrsf = aLoc.Transformation();
|
||||
// for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) {
|
||||
// gp_Pnt aPnt = aTriangulation->Node(aNodeIter);
|
||||
// aPnt.Transform(aTrsf);
|
||||
// points.emplace_back(std::move(Vec3f(aPnt.X(), aPnt.Y(), aPnt.Z())));
|
||||
// }
|
||||
// // BBS: copy triangles
|
||||
// const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
|
||||
// Standard_Integer anId[3] = {};
|
||||
// for (Standard_Integer aTriIter = 1; aTriIter <= aTriangulation->NbTriangles(); ++aTriIter) {
|
||||
// Poly_Triangle aTri = aTriangulation->Triangle(aTriIter);
|
||||
//
|
||||
// aTri.Get(anId[0], anId[1], anId[2]);
|
||||
// if (anOrientation == TopAbs_REVERSED)
|
||||
// std::swap(anId[1], anId[2]);
|
||||
// // BBS: save triangles facets
|
||||
// stl_facet facet;
|
||||
// facet.vertex[0] = points[anId[0] + aNodeOffset - 1].cast<float>();
|
||||
// facet.vertex[1] = points[anId[1] + aNodeOffset - 1].cast<float>();
|
||||
// facet.vertex[2] = points[anId[2] + aNodeOffset - 1].cast<float>();
|
||||
// facet.extra[0] = 0;
|
||||
// facet.extra[1] = 0;
|
||||
// stl_normal normal;
|
||||
// stl_calculate_normal(normal, &facet);
|
||||
// stl_normalize_vector(normal);
|
||||
// facet.normal = normal;
|
||||
// stl[i].facet_start[aTriangleOffet + aTriIter - 1] = facet;
|
||||
// }
|
||||
//
|
||||
// aNodeOffset += aTriangulation->NbNodes();
|
||||
// aTriangleOffet += aTriangulation->NbTriangles();
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// if (mesh_face_num != -1) {
|
||||
// for (size_t i = 0; i < stl.size(); i++) {
|
||||
// // Test for overflow
|
||||
// mesh_face_num += stl[i].stats.number_of_facets;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// ModelObject *new_object = model->add_object();
|
||||
// const char * last_slash = strrchr(path, DIR_SEPARATOR);
|
||||
// new_object->name.assign((last_slash == nullptr) ? path : last_slash + 1);
|
||||
// new_object->input_file = path;
|
||||
//
|
||||
// auto stage_unit3 = stl.size() / LOAD_STEP_STAGE_UNIT_NUM + 1;
|
||||
// for (size_t i = 0; i < stl.size(); i++) {
|
||||
// if (stepFn) {
|
||||
// if ((i % stage_unit3) == 0) {
|
||||
// stepFn(LOAD_STEP_STAGE_GET_MESH, i, stl.size(), cb_cancel);
|
||||
// is_cancel = cb_cancel;
|
||||
// }
|
||||
// if (cb_cancel) {
|
||||
// model->delete_object(new_object);
|
||||
// shapeTool.reset(nullptr);
|
||||
// application->Close(document);
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// //BBS: maybe mesh is empty from step file. Don't add
|
||||
// if (stl[i].stats.number_of_facets > 0) {
|
||||
// TriangleMesh triangle_mesh;
|
||||
// triangle_mesh.from_stl(stl[i]);
|
||||
// ModelVolume* new_volume = new_object->add_volume(std::move(triangle_mesh));
|
||||
// new_volume->name = namedSolids[i].name;
|
||||
// new_volume->source.input_file = path;
|
||||
// new_volume->source.object_idx = (int)model->objects.size() - 1;
|
||||
// new_volume->source.volume_idx = (int)new_object->volumes.size() - 1;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// shapeTool.reset(nullptr);
|
||||
// application->Close(document);
|
||||
//
|
||||
// //BBS: no valid shape from the step, delete the new object as well
|
||||
// if (new_object->volumes.size() == 0) {
|
||||
// model->delete_object(new_object);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// return true;
|
||||
//}
|
||||
|
||||
Step::Step(fs::path path, ImportStepProgressFn stepFn, StepIsUtf8Fn isUtf8Fn):
|
||||
m_stepFn(stepFn),
|
||||
|
@ -425,30 +426,257 @@ Step::Step(std::string path, ImportStepProgressFn stepFn, StepIsUtf8Fn isUtf8Fn)
|
|||
m_app->NewDocument(TCollection_ExtendedString("BinXCAF"), m_doc);
|
||||
}
|
||||
|
||||
bool Step::load()
|
||||
Step::~Step()
|
||||
{
|
||||
m_app->Close(m_doc);
|
||||
}
|
||||
|
||||
void Step::update_process(int load_stage, int current, int total, bool& cancel)
|
||||
{
|
||||
if (m_stepFn) {
|
||||
m_stepFn(load_stage, current, total, cancel);
|
||||
}
|
||||
}
|
||||
|
||||
Step::Step_Status Step::load()
|
||||
{
|
||||
if (!StepPreProcessor::isUtf8File(m_path.c_str()) && m_utf8Fn) {
|
||||
m_utf8Fn(false);
|
||||
return false;
|
||||
return Step_Status::LOAD_ERROR;
|
||||
}
|
||||
std::atomic<bool> stop_load_flag = false;
|
||||
Handle(StepProgressIncdicator) incdicator = new StepProgressIncdicator(stop_load_flag);
|
||||
bool task_result = false;
|
||||
bool cb_cancel = false;
|
||||
int progress = 0;
|
||||
bool load_result = false;
|
||||
auto task = new boost::thread(Slic3r::create_thread([&]() -> void {
|
||||
|
||||
STEPCAFControl_Reader reader;
|
||||
reader.SetNameMode(true);
|
||||
IFSelect_ReturnStatus stat = reader.ReadFile(m_path.c_str());
|
||||
if (cb_cancel) return;
|
||||
progress = 3;
|
||||
if (stat != IFSelect_RetDone || !reader.Transfer(m_doc, incdicator->Start())) {
|
||||
load_result = false;
|
||||
task_result = true;
|
||||
return;
|
||||
}
|
||||
if (cb_cancel) return;
|
||||
progress = 6;
|
||||
m_shape_tool = XCAFDoc_DocumentTool::ShapeTool(m_doc->Main());
|
||||
TDF_LabelSequence topLevelShapes;
|
||||
m_shape_tool->GetFreeShapes(topLevelShapes);
|
||||
unsigned int id{ 1 };
|
||||
Standard_Integer topShapeLength = topLevelShapes.Length() + 1;
|
||||
for (Standard_Integer iLabel = 1; iLabel < topShapeLength; ++iLabel) {
|
||||
if (cb_cancel) return;
|
||||
getNamedSolids(TopLoc_Location{}, "", id, m_shape_tool, topLevelShapes.Value(iLabel), m_name_solids);
|
||||
}
|
||||
progress = 10;
|
||||
load_result = true;
|
||||
task_result = true;
|
||||
}));
|
||||
while (!task_result) {
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
|
||||
update_process(LOAD_STEP_STAGE_READ_FILE, progress, 10, cb_cancel);
|
||||
if (cb_cancel) {
|
||||
stop_load_flag.store(true);
|
||||
if (task) {
|
||||
if (task->joinable()) {
|
||||
task->join();
|
||||
delete task;
|
||||
}
|
||||
}
|
||||
return Step_Status::CANCEL;
|
||||
}
|
||||
}
|
||||
if (task){
|
||||
if (task->joinable()) {
|
||||
task->join();
|
||||
delete task;
|
||||
}
|
||||
}
|
||||
if (load_result) {
|
||||
return Step_Status::LOAD_SUCCESS;
|
||||
}else {
|
||||
return Step_Status::LOAD_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Step::Step_Status Step::mesh(Model* model,
|
||||
bool& is_cancel,
|
||||
bool isSplitCompound,
|
||||
double linear_defletion/*=0.003*/,
|
||||
double angle_defletion/*= 0.5*/)
|
||||
|
||||
{
|
||||
bool task_result = false;
|
||||
bool cb_cancel = false;
|
||||
float progress = .0;
|
||||
std::atomic<int> meshed_solid_num = 0;
|
||||
std::vector<NamedSolid> namedSolids;
|
||||
float progress_2 = .0;
|
||||
ModelObject* new_object = model->add_object();
|
||||
const char* last_slash = strrchr(m_path.c_str(), DIR_SEPARATOR);
|
||||
new_object->name.assign((last_slash == nullptr) ? m_path.c_str() : last_slash + 1);
|
||||
new_object->input_file = m_path.c_str();
|
||||
|
||||
auto task = new boost::thread(Slic3r::create_thread([&]() -> void {
|
||||
TDF_LabelSequence topLevelShapes;
|
||||
m_shape_tool->GetFreeShapes(topLevelShapes);
|
||||
unsigned int id{ 1 };
|
||||
Standard_Integer topShapeLength = topLevelShapes.Length() + 1;
|
||||
|
||||
for (Standard_Integer iLabel = 1; iLabel < topShapeLength; ++iLabel) {
|
||||
progress = static_cast<double>(iLabel) / (topShapeLength-1);
|
||||
if (cb_cancel) {
|
||||
return;
|
||||
}
|
||||
getNamedSolids(TopLoc_Location{}, "", id, m_shape_tool, topLevelShapes.Value(iLabel), namedSolids, isSplitCompound);
|
||||
}
|
||||
|
||||
std::vector<stl_file> stl;
|
||||
stl.resize(namedSolids.size());
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, namedSolids.size()), [&](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t i = range.begin(); i < range.end(); i++) {
|
||||
BRepMesh_IncrementalMesh mesh(namedSolids[i].solid, linear_defletion, false, angle_defletion, true);
|
||||
// BBS: calculate total number of the nodes and triangles
|
||||
int aNbNodes = 0;
|
||||
int aNbTriangles = 0;
|
||||
for (TopExp_Explorer anExpSF(namedSolids[i].solid, TopAbs_FACE); anExpSF.More(); anExpSF.Next()) {
|
||||
TopLoc_Location aLoc;
|
||||
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(TopoDS::Face(anExpSF.Current()), aLoc);
|
||||
if (!aTriangulation.IsNull()) {
|
||||
aNbNodes += aTriangulation->NbNodes();
|
||||
aNbTriangles += aTriangulation->NbTriangles();
|
||||
}
|
||||
}
|
||||
|
||||
if (aNbTriangles == 0 || aNbNodes == 0)
|
||||
// BBS: No triangulation on the shape.
|
||||
continue;
|
||||
|
||||
stl[i].stats.type = inmemory;
|
||||
stl[i].stats.number_of_facets = (uint32_t)aNbTriangles;
|
||||
stl[i].stats.original_num_facets = stl[i].stats.number_of_facets;
|
||||
stl_allocate(&stl[i]);
|
||||
|
||||
std::vector<Vec3f> points;
|
||||
points.reserve(aNbNodes);
|
||||
// BBS: count faces missing triangulation
|
||||
Standard_Integer aNbFacesNoTri = 0;
|
||||
// BBS: fill temporary triangulation
|
||||
Standard_Integer aNodeOffset = 0;
|
||||
Standard_Integer aTriangleOffet = 0;
|
||||
for (TopExp_Explorer anExpSF(namedSolids[i].solid, TopAbs_FACE); anExpSF.More(); anExpSF.Next()) {
|
||||
const TopoDS_Shape& aFace = anExpSF.Current();
|
||||
TopLoc_Location aLoc;
|
||||
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(TopoDS::Face(aFace), aLoc);
|
||||
if (aTriangulation.IsNull()) {
|
||||
++aNbFacesNoTri;
|
||||
continue;
|
||||
}
|
||||
// BBS: copy nodes
|
||||
gp_Trsf aTrsf = aLoc.Transformation();
|
||||
for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) {
|
||||
gp_Pnt aPnt = aTriangulation->Node(aNodeIter);
|
||||
aPnt.Transform(aTrsf);
|
||||
points.emplace_back(std::move(Vec3f(aPnt.X(), aPnt.Y(), aPnt.Z())));
|
||||
}
|
||||
// BBS: copy triangles
|
||||
const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
|
||||
Standard_Integer anId[3] = {};
|
||||
for (Standard_Integer aTriIter = 1; aTriIter <= aTriangulation->NbTriangles(); ++aTriIter) {
|
||||
Poly_Triangle aTri = aTriangulation->Triangle(aTriIter);
|
||||
|
||||
aTri.Get(anId[0], anId[1], anId[2]);
|
||||
if (anOrientation == TopAbs_REVERSED)
|
||||
std::swap(anId[1], anId[2]);
|
||||
// BBS: save triangles facets
|
||||
stl_facet facet;
|
||||
facet.vertex[0] = points[anId[0] + aNodeOffset - 1].cast<float>();
|
||||
facet.vertex[1] = points[anId[1] + aNodeOffset - 1].cast<float>();
|
||||
facet.vertex[2] = points[anId[2] + aNodeOffset - 1].cast<float>();
|
||||
facet.extra[0] = 0;
|
||||
facet.extra[1] = 0;
|
||||
stl_normal normal;
|
||||
stl_calculate_normal(normal, &facet);
|
||||
stl_normalize_vector(normal);
|
||||
facet.normal = normal;
|
||||
stl[i].facet_start[aTriangleOffet + aTriIter - 1] = facet;
|
||||
}
|
||||
|
||||
aNodeOffset += aTriangulation->NbNodes();
|
||||
aTriangleOffet += aTriangulation->NbTriangles();
|
||||
}
|
||||
meshed_solid_num.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
for (size_t i = 0; i < stl.size(); i++) {
|
||||
progress_2 = static_cast<float>(i) / stl.size();
|
||||
if (cb_cancel)
|
||||
return;
|
||||
|
||||
//BBS: maybe mesh is empty from step file. Don't add
|
||||
if (stl[i].stats.number_of_facets > 0) {
|
||||
TriangleMesh triangle_mesh;
|
||||
triangle_mesh.from_stl(stl[i]);
|
||||
ModelVolume* new_volume = new_object->add_volume(std::move(triangle_mesh));
|
||||
new_volume->name = namedSolids[i].name;
|
||||
new_volume->source.input_file = m_path.c_str();
|
||||
new_volume->source.object_idx = (int)model->objects.size() - 1;
|
||||
new_volume->source.volume_idx = (int)new_object->volumes.size() - 1;
|
||||
}
|
||||
}
|
||||
task_result = true;
|
||||
}));
|
||||
|
||||
while (!task_result) {
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(300));
|
||||
if (progress_2 > 0) {
|
||||
// third progress
|
||||
update_process(LOAD_STEP_STAGE_GET_MESH, static_cast<int>(progress_2 * 100), 100, cb_cancel);
|
||||
}else {
|
||||
if (meshed_solid_num.load()) {
|
||||
// second progress
|
||||
int meshed_solid = meshed_solid_num.load();
|
||||
update_process(LOAD_STEP_STAGE_GET_SOLID, static_cast<int>((float)meshed_solid / namedSolids.size() * 10) + 10, 20, cb_cancel);
|
||||
} else {
|
||||
if (progress > 0) {
|
||||
// first progress
|
||||
update_process(LOAD_STEP_STAGE_GET_SOLID, static_cast<int>(progress * 10), 20, cb_cancel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (cb_cancel) {
|
||||
if (task) {
|
||||
if (task->joinable()) {
|
||||
task->join();
|
||||
delete task;
|
||||
}
|
||||
}
|
||||
return Step_Status::CANCEL;
|
||||
}
|
||||
}
|
||||
if (task) {
|
||||
if (task->joinable()) {
|
||||
task->join();
|
||||
delete task;
|
||||
}
|
||||
}
|
||||
|
||||
STEPCAFControl_Reader reader;
|
||||
reader.SetNameMode(true);
|
||||
IFSelect_ReturnStatus stat = reader.ReadFile(m_path.c_str());
|
||||
if (stat != IFSelect_RetDone || !reader.Transfer(m_doc)) {
|
||||
m_app->Close(m_doc);
|
||||
return false;
|
||||
//BBS: no valid shape from the step, delete the new object as well
|
||||
if (new_object->volumes.size() == 0) {
|
||||
model->delete_object(new_object);
|
||||
return Step_Status::MESH_ERROR;
|
||||
}
|
||||
m_shape_tool = XCAFDoc_DocumentTool::ShapeTool(m_doc->Main());
|
||||
TDF_LabelSequence topLevelShapes;
|
||||
m_shape_tool->GetFreeShapes(topLevelShapes);
|
||||
unsigned int id{ 1 };
|
||||
Standard_Integer topShapeLength = topLevelShapes.Length() + 1;
|
||||
for (Standard_Integer iLabel = 1; iLabel < topShapeLength; ++iLabel) {
|
||||
getNamedSolids(TopLoc_Location{}, "", id, m_shape_tool, topLevelShapes.Value(iLabel), m_name_solids);
|
||||
}
|
||||
|
||||
return true;
|
||||
return Step_Status::MESH_SUCCESS;
|
||||
}
|
||||
|
||||
void Step::clean_mesh_data()
|
||||
|
|
|
@ -88,14 +88,28 @@ private:
|
|||
class Step
|
||||
{
|
||||
public:
|
||||
enum class Step_Status {
|
||||
LOAD_SUCCESS,
|
||||
LOAD_ERROR,
|
||||
CANCEL,
|
||||
MESH_SUCCESS,
|
||||
MESH_ERROR
|
||||
};
|
||||
Step(fs::path path, ImportStepProgressFn stepFn = nullptr, StepIsUtf8Fn isUtf8Fn = nullptr);
|
||||
Step(std::string path, ImportStepProgressFn stepFn = nullptr, StepIsUtf8Fn isUtf8Fn = nullptr);
|
||||
bool load();
|
||||
~Step();
|
||||
Step_Status load();
|
||||
unsigned int get_triangle_num(double linear_defletion, double angle_defletion);
|
||||
unsigned int get_triangle_num_tbb(double linear_defletion, double angle_defletion);
|
||||
void clean_mesh_data();
|
||||
Step_Status mesh(Model* model,
|
||||
bool& is_cancel,
|
||||
bool isSplitCompound,
|
||||
double linear_defletion = 0.003,
|
||||
double angle_defletion = 0.5);
|
||||
|
||||
std::atomic<bool> m_stop_mesh;
|
||||
void update_process(int load_stage, int current, int total, bool& cancel);
|
||||
private:
|
||||
std::string m_path;
|
||||
ImportStepProgressFn m_stepFn;
|
||||
|
|
|
@ -197,26 +197,34 @@ Model Model::read_from_step(const std::string&
|
|||
Model model;
|
||||
bool result = false;
|
||||
bool is_cb_cancel = false;
|
||||
std::string message;
|
||||
Step step_file(input_file);
|
||||
step_file.load();
|
||||
Step::Step_Status status;
|
||||
Step step_file(input_file, stepFn);
|
||||
status = step_file.load();
|
||||
if(status != Step::Step_Status::LOAD_SUCCESS) {
|
||||
goto _finished;
|
||||
}
|
||||
if (step_mesh_fn) {
|
||||
if (step_mesh_fn(step_file, linear_defletion, angle_defletion, is_split_compound) == -1) {
|
||||
status = Step::Step_Status::CANCEL;
|
||||
goto _finished;
|
||||
}
|
||||
}
|
||||
|
||||
status = step_file.mesh(&model, is_cb_cancel, is_split_compound, linear_defletion, angle_defletion);
|
||||
|
||||
_finished:
|
||||
|
||||
switch (status){
|
||||
case Step::Step_Status::CANCEL: {
|
||||
Model empty_model;
|
||||
return empty_model;
|
||||
}
|
||||
}
|
||||
result = load_step(input_file.c_str(), &model, is_cb_cancel, linear_defletion, angle_defletion, is_split_compound, stepFn, stepIsUtf8Fn);
|
||||
if (is_cb_cancel) {
|
||||
Model empty_model;
|
||||
return empty_model;
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
if (message.empty())
|
||||
case Step::Step_Status::LOAD_ERROR:
|
||||
throw Slic3r::RuntimeError(_L("Loading of a model file failed."));
|
||||
else
|
||||
throw Slic3r::RuntimeError(message);
|
||||
case Step::Step_Status::MESH_ERROR:
|
||||
throw Slic3r::RuntimeError(_L("Meshing of a model file failed or no valid shape."));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (model.objects.empty())
|
||||
|
|
Loading…
Reference in New Issue