STEP: Implementation ported from BambuStudio:
CMake handling is different STEP: Removed preprocessing stage STEP: Small refactoring STEP: Bigger refactoring STEP: Changed naming on loaded object and volumes: If the STEP contains exactly one named volume, the object and its first volume will both have that name. Otherwise, filename w/o suffix is used as object name and volumes are named using names from the STEP (if there is none, untranslated "PartN" string is used). STEP: Load the libraries dynamically on Win wip
This commit is contained in:
parent
dc9e35d8ea
commit
88ba89dbbc
2
deps/CMakeLists.txt
vendored
2
deps/CMakeLists.txt
vendored
@ -189,6 +189,7 @@ endif ()
|
|||||||
include(JPEG/JPEG.cmake)
|
include(JPEG/JPEG.cmake)
|
||||||
include(TIFF/TIFF.cmake)
|
include(TIFF/TIFF.cmake)
|
||||||
include(wxWidgets/wxWidgets.cmake)
|
include(wxWidgets/wxWidgets.cmake)
|
||||||
|
include(OCCT/OCCT.cmake)
|
||||||
|
|
||||||
set(_dep_list
|
set(_dep_list
|
||||||
dep_Boost
|
dep_Boost
|
||||||
@ -200,6 +201,7 @@ set(_dep_list
|
|||||||
dep_OpenVDB
|
dep_OpenVDB
|
||||||
dep_OpenCSG
|
dep_OpenCSG
|
||||||
dep_CGAL
|
dep_CGAL
|
||||||
|
dep_OCCT
|
||||||
${PNG_PKG}
|
${PNG_PKG}
|
||||||
${ZLIB_PKG}
|
${ZLIB_PKG}
|
||||||
${EXPAT_PKG}
|
${EXPAT_PKG}
|
||||||
|
22
deps/OCCT/OCCT.cmake
vendored
Normal file
22
deps/OCCT/OCCT.cmake
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
prusaslicer_add_cmake_project(OCCT
|
||||||
|
#LMBBS: changed version to 7.6.2
|
||||||
|
URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V7_6_2.zip
|
||||||
|
URL_HASH SHA256=c696b923593e8c18d059709717dbf155b3e72fdd283c8522047a790ec3a432c5
|
||||||
|
|
||||||
|
CMAKE_ARGS
|
||||||
|
-DINSTALL_DIR_LAYOUT=Unix # LMBBS
|
||||||
|
-DBUILD_LIBRARY_TYPE=Static
|
||||||
|
-DUSE_TK=OFF
|
||||||
|
-DUSE_TBB=OFF
|
||||||
|
-DUSE_FREETYPE=OFF
|
||||||
|
-DUSE_FFMPEG=OFF
|
||||||
|
-DUSE_VTK=OFF
|
||||||
|
-DUSE_FREETYPE=OFF
|
||||||
|
-DBUILD_MODULE_ApplicationFramework=OFF
|
||||||
|
#-DBUILD_MODULE_DataExchange=OFF
|
||||||
|
-DBUILD_MODULE_Draw=OFF
|
||||||
|
-DBUILD_MODULE_FoundationClasses=OFF
|
||||||
|
-DBUILD_MODULE_ModelingAlgorithms=OFF
|
||||||
|
-DBUILD_MODULE_ModelingData=OFF
|
||||||
|
-DBUILD_MODULE_Visualization=OFF
|
||||||
|
)
|
@ -15,11 +15,9 @@ add_subdirectory(semver)
|
|||||||
add_subdirectory(libigl)
|
add_subdirectory(libigl)
|
||||||
add_subdirectory(hints)
|
add_subdirectory(hints)
|
||||||
add_subdirectory(qoi)
|
add_subdirectory(qoi)
|
||||||
|
|
||||||
# Adding libnest2d project for bin packing...
|
|
||||||
add_subdirectory(libnest2d)
|
add_subdirectory(libnest2d)
|
||||||
|
|
||||||
add_subdirectory(libslic3r)
|
add_subdirectory(libslic3r)
|
||||||
|
add_subdirectory(occt_wrapper)
|
||||||
|
|
||||||
if (SLIC3R_GUI)
|
if (SLIC3R_GUI)
|
||||||
add_subdirectory(imgui)
|
add_subdirectory(imgui)
|
||||||
@ -127,6 +125,7 @@ if (NOT WIN32 AND NOT APPLE)
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
target_link_libraries(PrusaSlicer libslic3r cereal)
|
target_link_libraries(PrusaSlicer libslic3r cereal)
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
# add_compile_options(-stdlib=libc++)
|
# add_compile_options(-stdlib=libc++)
|
||||||
# add_definitions(-DBOOST_THREAD_DONT_USE_CHRONO -DBOOST_NO_CXX11_RVALUE_REFERENCES -DBOOST_THREAD_USES_MOVE)
|
# add_definitions(-DBOOST_THREAD_DONT_USE_CHRONO -DBOOST_NO_CXX11_RVALUE_REFERENCES -DBOOST_THREAD_USES_MOVE)
|
||||||
|
@ -94,6 +94,8 @@ add_library(libslic3r STATIC
|
|||||||
Format/STL.hpp
|
Format/STL.hpp
|
||||||
Format/SL1.hpp
|
Format/SL1.hpp
|
||||||
Format/SL1.cpp
|
Format/SL1.cpp
|
||||||
|
Format/STEP.hpp
|
||||||
|
Format/STEP.cpp
|
||||||
GCode/ThumbnailData.cpp
|
GCode/ThumbnailData.cpp
|
||||||
GCode/ThumbnailData.hpp
|
GCode/ThumbnailData.hpp
|
||||||
GCode/Thumbnails.cpp
|
GCode/Thumbnails.cpp
|
||||||
|
110
src/libslic3r/Format/STEP.cpp
Normal file
110
src/libslic3r/Format/STEP.cpp
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#include "STEP.hpp"
|
||||||
|
#include "occt_wrapper/OCCTWrapper.hpp"
|
||||||
|
|
||||||
|
#include "libslic3r/Model.hpp"
|
||||||
|
#include "libslic3r/TriangleMesh.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include<windows.h>
|
||||||
|
#else
|
||||||
|
#include<occt_wrapper/OCCTWrapper.hpp>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
LoadStepFn get_load_step_fn()
|
||||||
|
{
|
||||||
|
static LoadStepFn load_step_fn = nullptr;
|
||||||
|
|
||||||
|
if (!load_step_fn) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
HMODULE module = LoadLibraryW(L"OCCTWrapper.dll");
|
||||||
|
if (module == NULL)
|
||||||
|
throw Slic3r::RuntimeError("Cannot load OCCTWrapper.dll");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const char* fn_name = "load_step_internal";
|
||||||
|
FARPROC farproc = GetProcAddress(module, fn_name);
|
||||||
|
if (! farproc) {
|
||||||
|
DWORD ec = GetLastError();
|
||||||
|
throw Slic3r::RuntimeError(std::string("Cannot load function from OCCTWrapper.dll: ") + fn_name
|
||||||
|
+ "\n\nError code: " + std::to_string(ec));
|
||||||
|
}
|
||||||
|
load_step_fn = reinterpret_cast<LoadStepFn>(farproc);
|
||||||
|
} catch (const Slic3r::RuntimeError&) {
|
||||||
|
FreeLibrary(module);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void *plugin_ptr = dlopen("OCCTWrapper.so", RTLD_NOW | RTLD_GLOBAL);
|
||||||
|
|
||||||
|
if (plugin_ptr) {
|
||||||
|
load_step_fn = reinterpret_cast<LoadStepFn>(dlsym(plugin_ptr, "load_step_internal"));
|
||||||
|
if (!load_step_fn) {
|
||||||
|
dlclose(plugin_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return load_step_fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load_step(const char *path, Model *model /*BBS:, ImportStepProgressFn proFn*/)
|
||||||
|
{
|
||||||
|
OCCTResult occt_object;
|
||||||
|
|
||||||
|
LoadStepFn load_step_fn = get_load_step_fn();
|
||||||
|
|
||||||
|
if (!load_step_fn)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
load_step_fn(path, &occt_object);
|
||||||
|
|
||||||
|
assert(! occt_object.volumes.empty());
|
||||||
|
|
||||||
|
assert(boost::algorithm::iends_with(occt_object.object_name, ".stp")
|
||||||
|
|| boost::algorithm::iends_with(occt_object.object_name, ".step"));
|
||||||
|
occt_object.object_name.erase(occt_object.object_name.find("."));
|
||||||
|
assert(! occt_object.object_name.empty());
|
||||||
|
|
||||||
|
|
||||||
|
ModelObject* new_object = model->add_object();
|
||||||
|
new_object->input_file = path;
|
||||||
|
if (new_object->volumes.size() == 1 && ! occt_object.volumes.front().volume_name.empty())
|
||||||
|
new_object->name = new_object->volumes.front()->name;
|
||||||
|
else
|
||||||
|
new_object->name = occt_object.object_name;
|
||||||
|
|
||||||
|
|
||||||
|
for (size_t i=0; i<occt_object.volumes.size(); ++i) {
|
||||||
|
indexed_triangle_set its;
|
||||||
|
for (size_t j=0; j<occt_object.volumes[i].vertices.size(); ++j)
|
||||||
|
its.vertices.emplace_back(Vec3f(occt_object.volumes[i].vertices[j][0],
|
||||||
|
occt_object.volumes[i].vertices[j][1],
|
||||||
|
occt_object.volumes[i].vertices[j][2]));
|
||||||
|
for (size_t j=0; j<occt_object.volumes[i].indices.size(); ++j)
|
||||||
|
its.indices.emplace_back(Vec3i(occt_object.volumes[i].indices[j][0],
|
||||||
|
occt_object.volumes[i].indices[j][1],
|
||||||
|
occt_object.volumes[i].indices[j][2]));
|
||||||
|
its_merge_vertices(its, true);
|
||||||
|
TriangleMesh triangle_mesh(std::move(its));
|
||||||
|
ModelVolume* new_volume = new_object->add_volume(std::move(triangle_mesh));
|
||||||
|
|
||||||
|
new_volume->name = occt_object.volumes[i].volume_name.empty()
|
||||||
|
? std::string("Part") + std::to_string(i+1)
|
||||||
|
: occt_object.volumes[i].volume_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // namespace Slic3r
|
19
src/libslic3r/Format/STEP.hpp
Normal file
19
src/libslic3r/Format/STEP.hpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Original implementation of STEP format import created by Bambulab.
|
||||||
|
// https://github.com/bambulab/BambuStudio
|
||||||
|
// Forked off commit 1555904, modified by Prusa Research.
|
||||||
|
|
||||||
|
#ifndef slic3r_Format_STEP_hpp_
|
||||||
|
#define slic3r_Format_STEP_hpp_
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
class Model;
|
||||||
|
|
||||||
|
//typedef std::function<void(int load_stage, int current, int total, bool& cancel)> ImportStepProgressFn;
|
||||||
|
|
||||||
|
// Load a step file into a provided model.
|
||||||
|
extern bool load_step(const char *path_str, Model *model /*LMBBS:, ImportStepProgressFn proFn = nullptr*/);
|
||||||
|
|
||||||
|
}; // namespace Slic3r
|
||||||
|
|
||||||
|
#endif /* slic3r_Format_STEP_hpp_ */
|
@ -13,6 +13,7 @@
|
|||||||
#include "Format/OBJ.hpp"
|
#include "Format/OBJ.hpp"
|
||||||
#include "Format/STL.hpp"
|
#include "Format/STL.hpp"
|
||||||
#include "Format/3mf.hpp"
|
#include "Format/3mf.hpp"
|
||||||
|
#include "Format/STEP.hpp"
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
@ -114,6 +115,8 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
|
|||||||
result = load_stl(input_file.c_str(), &model);
|
result = load_stl(input_file.c_str(), &model);
|
||||||
else if (boost::algorithm::iends_with(input_file, ".obj"))
|
else if (boost::algorithm::iends_with(input_file, ".obj"))
|
||||||
result = load_obj(input_file.c_str(), &model);
|
result = load_obj(input_file.c_str(), &model);
|
||||||
|
else if (boost::algorithm::iends_with(input_file, ".step") || boost::algorithm::iends_with(input_file, ".stp"))
|
||||||
|
result = load_step(input_file.c_str(), &model);
|
||||||
else if (boost::algorithm::iends_with(input_file, ".amf") || boost::algorithm::iends_with(input_file, ".amf.xml"))
|
else if (boost::algorithm::iends_with(input_file, ".amf") || boost::algorithm::iends_with(input_file, ".amf.xml"))
|
||||||
result = load_amf(input_file.c_str(), config, config_substitutions, &model, options & LoadAttribute::CheckVersion);
|
result = load_amf(input_file.c_str(), config, config_substitutions, &model, options & LoadAttribute::CheckVersion);
|
||||||
else if (boost::algorithm::iends_with(input_file, ".3mf"))
|
else if (boost::algorithm::iends_with(input_file, ".3mf"))
|
||||||
|
@ -1370,4 +1370,5 @@ bool its_write_stl_binary(const char *file, const char *label, const std::vector
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
51
src/occt_wrapper/CMakeLists.txt
Normal file
51
src/occt_wrapper/CMakeLists.txt
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
project(OCCTWrapper)
|
||||||
|
|
||||||
|
add_library(OCCTWrapper SHARED OCCTWrapper.cpp)
|
||||||
|
|
||||||
|
set_target_properties(OCCTWrapper
|
||||||
|
PROPERTIES
|
||||||
|
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/src"
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/src"
|
||||||
|
PREFIX ""
|
||||||
|
)
|
||||||
|
|
||||||
|
include(GenerateExportHeader)
|
||||||
|
|
||||||
|
generate_export_header(OCCTWrapper)
|
||||||
|
|
||||||
|
find_package(OpenCASCADE 7.6.2 REQUIRED)
|
||||||
|
|
||||||
|
set(OCCT_LIBS
|
||||||
|
TKXDESTEP
|
||||||
|
TKSTEP
|
||||||
|
TKSTEP209
|
||||||
|
TKSTEPAttr
|
||||||
|
TKSTEPBase
|
||||||
|
TKXCAF
|
||||||
|
TKXSBase
|
||||||
|
TKVCAF
|
||||||
|
TKCAF
|
||||||
|
TKLCAF
|
||||||
|
TKCDF
|
||||||
|
TKV3d
|
||||||
|
TKService
|
||||||
|
TKMesh
|
||||||
|
TKBO
|
||||||
|
TKPrim
|
||||||
|
TKHLR
|
||||||
|
TKShHealing
|
||||||
|
TKTopAlgo
|
||||||
|
TKGeomAlgo
|
||||||
|
TKBRep
|
||||||
|
TKGeomBase
|
||||||
|
TKG3d
|
||||||
|
TKG2d
|
||||||
|
TKMath
|
||||||
|
TKernel
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(OCCTWrapper PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
target_include_directories(OCCTWrapper PUBLIC ${OpenCASCADE_INCLUDE_DIR})
|
||||||
|
target_link_libraries(OCCTWrapper ${OCCT_LIBS})
|
||||||
|
|
201
src/occt_wrapper/OCCTWrapper.cpp
Normal file
201
src/occt_wrapper/OCCTWrapper.cpp
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
#include "OCCTWrapper.hpp"
|
||||||
|
|
||||||
|
#include "occtwrapper_export.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define DIR_SEPARATOR '\\'
|
||||||
|
#else
|
||||||
|
#define DIR_SEPARATOR '/'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "STEPCAFControl_Reader.hxx"
|
||||||
|
#include "BRepMesh_IncrementalMesh.hxx"
|
||||||
|
#include "XCAFDoc_DocumentTool.hxx"
|
||||||
|
#include "XCAFDoc_ShapeTool.hxx"
|
||||||
|
#include "XCAFApp_Application.hxx"
|
||||||
|
#include "TopoDS_Builder.hxx"
|
||||||
|
#include "TopoDS.hxx"
|
||||||
|
#include "TDataStd_Name.hxx"
|
||||||
|
#include "BRepBuilderAPI_Transform.hxx"
|
||||||
|
#include "TopExp_Explorer.hxx"
|
||||||
|
#include "BRep_Tool.hxx"
|
||||||
|
|
||||||
|
const double STEP_TRANS_CHORD_ERROR = 0.005;
|
||||||
|
const double STEP_TRANS_ANGLE_RES = 1;
|
||||||
|
|
||||||
|
// const int LOAD_STEP_STAGE_READ_FILE = 0;
|
||||||
|
// const int LOAD_STEP_STAGE_GET_SOLID = 1;
|
||||||
|
// const int LOAD_STEP_STAGE_GET_MESH = 2;
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
struct NamedSolid {
|
||||||
|
NamedSolid(const TopoDS_Shape& s,
|
||||||
|
const std::string& n) : solid{s}, name{n} {}
|
||||||
|
const TopoDS_Shape solid;
|
||||||
|
const std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void getNamedSolids(const TopLoc_Location& location, const Handle(XCAFDoc_ShapeTool) shapeTool,
|
||||||
|
const TDF_Label label, std::vector<NamedSolid>& namedSolids)
|
||||||
|
{
|
||||||
|
TDF_Label referredLabel{label};
|
||||||
|
if (shapeTool->IsReference(label))
|
||||||
|
shapeTool->GetReferredShape(label, referredLabel);
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
Handle(TDataStd_Name) shapeName;
|
||||||
|
if (referredLabel.FindAttribute(TDataStd_Name::GetID(), shapeName))
|
||||||
|
name = TCollection_AsciiString(shapeName->Get()).ToCString();
|
||||||
|
|
||||||
|
TopLoc_Location localLocation = location * shapeTool->GetLocation(label);
|
||||||
|
TDF_LabelSequence components;
|
||||||
|
if (shapeTool->GetComponents(referredLabel, components)) {
|
||||||
|
for (Standard_Integer compIndex = 1; compIndex <= components.Length(); ++compIndex) {
|
||||||
|
getNamedSolids(localLocation, shapeTool, components.Value(compIndex), namedSolids);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TopoDS_Shape shape;
|
||||||
|
shapeTool->GetShape(referredLabel, shape);
|
||||||
|
TopAbs_ShapeEnum shape_type = shape.ShapeType();
|
||||||
|
BRepBuilderAPI_Transform transform(shape, localLocation, Standard_True);
|
||||||
|
switch (shape_type) {
|
||||||
|
case TopAbs_COMPOUND:
|
||||||
|
namedSolids.emplace_back(TopoDS::Compound(transform.Shape()), name);
|
||||||
|
break;
|
||||||
|
case TopAbs_COMPSOLID:
|
||||||
|
namedSolids.emplace_back(TopoDS::CompSolid(transform.Shape()), name);
|
||||||
|
break;
|
||||||
|
case TopAbs_SOLID:
|
||||||
|
namedSolids.emplace_back(TopoDS::Solid(transform.Shape()), name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" OCCTWRAPPER_EXPORT bool load_step_internal(const char *path, OCCTResult* res /*BBS:, ImportStepProgressFn proFn*/)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
bool cb_cancel = false;
|
||||||
|
//if (proFn) {
|
||||||
|
// proFn(LOAD_STEP_STAGE_READ_FILE, 0, 1, cb_cancel);
|
||||||
|
// if (cb_cancel)
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<NamedSolid> namedSolids;
|
||||||
|
Handle(TDocStd_Document) document;
|
||||||
|
Handle(XCAFApp_Application) application = XCAFApp_Application::GetApplication();
|
||||||
|
application->NewDocument(path, 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(path);
|
||||||
|
if (stat != IFSelect_RetDone || !reader.Transfer(document)) {
|
||||||
|
application->Close(document);
|
||||||
|
res->error_str = std::string{"Could not read '"} + path + "'";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool(document->Main());
|
||||||
|
TDF_LabelSequence topLevelShapes;
|
||||||
|
shapeTool->GetFreeShapes(topLevelShapes);
|
||||||
|
|
||||||
|
Standard_Integer topShapeLength = topLevelShapes.Length() + 1;
|
||||||
|
for (Standard_Integer iLabel = 1; iLabel < topShapeLength; ++iLabel) {
|
||||||
|
//if (proFn) {
|
||||||
|
// proFn(LOAD_STEP_STAGE_GET_SOLID, iLabel, topShapeLength, cb_cancel);
|
||||||
|
// if (cb_cancel) {
|
||||||
|
// shapeTool.reset(nullptr);
|
||||||
|
// application->Close(document);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
getNamedSolids(TopLoc_Location{}, shapeTool, topLevelShapes.Value(iLabel), namedSolids);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Now the object name. Set it to filename without suffix.
|
||||||
|
// This will later be changed if only one volume is loaded.
|
||||||
|
const char *last_slash = strrchr(path, DIR_SEPARATOR);
|
||||||
|
std::string obj_name((last_slash == nullptr) ? path : last_slash + 1);
|
||||||
|
res->object_name = obj_name;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < namedSolids.size(); ++i) {
|
||||||
|
//BBS:if (proFn) {
|
||||||
|
// proFn(LOAD_STEP_STAGE_GET_MESH, i, namedSolids.size(), cb_cancel);
|
||||||
|
// if (cb_cancel) {
|
||||||
|
// model->delete_object(new_object);
|
||||||
|
// shapeTool.reset(nullptr);
|
||||||
|
// application->Close(document);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
res->volumes.emplace_back();
|
||||||
|
auto& vertices = res->volumes.back().vertices;
|
||||||
|
auto& indices = res->volumes.back().indices;
|
||||||
|
|
||||||
|
BRepMesh_IncrementalMesh mesh(namedSolids[i].solid, STEP_TRANS_CHORD_ERROR, false, STEP_TRANS_ANGLE_RES, true);
|
||||||
|
|
||||||
|
for (TopExp_Explorer anExpSF(namedSolids[i].solid, TopAbs_FACE); anExpSF.More(); anExpSF.Next()) {
|
||||||
|
const int aNodeOffset = int(vertices.size());
|
||||||
|
const TopoDS_Shape& aFace = anExpSF.Current();
|
||||||
|
TopLoc_Location aLoc;
|
||||||
|
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(TopoDS::Face(aFace), aLoc);
|
||||||
|
if (aTriangulation.IsNull())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// First copy vertices (will create duplicates).
|
||||||
|
gp_Trsf aTrsf = aLoc.Transformation();
|
||||||
|
for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) {
|
||||||
|
gp_Pnt aPnt = aTriangulation->Node(aNodeIter);
|
||||||
|
aPnt.Transform(aTrsf);
|
||||||
|
vertices.push_back({float(aPnt.X()), float(aPnt.Y()), float(aPnt.Z())});
|
||||||
|
}
|
||||||
|
// Now the indices.
|
||||||
|
const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
|
||||||
|
for (Standard_Integer aTriIter = 1; aTriIter <= aTriangulation->NbTriangles(); ++aTriIter) {
|
||||||
|
Poly_Triangle aTri = aTriangulation->Triangle(aTriIter);
|
||||||
|
|
||||||
|
Standard_Integer anId[3];
|
||||||
|
aTri.Get(anId[0], anId[1], anId[2]);
|
||||||
|
if (anOrientation == TopAbs_REVERSED)
|
||||||
|
std::swap(anId[1], anId[2]);
|
||||||
|
|
||||||
|
// Account for the vertices we already have from previous faces.
|
||||||
|
// anId is 1-based index !
|
||||||
|
indices.push_back({anId[0] - 1 + aNodeOffset,
|
||||||
|
anId[1] - 1 + aNodeOffset,
|
||||||
|
anId[2] - 1 + aNodeOffset});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res->volumes.back().volume_name = namedSolids[i].name;
|
||||||
|
|
||||||
|
if (vertices.empty())
|
||||||
|
res->volumes.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
shapeTool.reset(nullptr);
|
||||||
|
application->Close(document);
|
||||||
|
|
||||||
|
if (res->volumes.empty())
|
||||||
|
return false;
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
res->error_str = ex.what();
|
||||||
|
return false;
|
||||||
|
} catch (...) {
|
||||||
|
res->error_str = "An exception was thrown in load_step_internal.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // namespace Slic3r
|
27
src/occt_wrapper/OCCTWrapper.hpp
Normal file
27
src/occt_wrapper/OCCTWrapper.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
#ifndef occtwrapper_OCCTWrapper_hpp_
|
||||||
|
#define occtwrapper_OCCTWrapper_hpp_
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
struct OCCTVolume {
|
||||||
|
std::string volume_name;
|
||||||
|
std::vector<std::array<float, 3>> vertices;
|
||||||
|
std::vector<std::array<int, 3>> indices;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OCCTResult {
|
||||||
|
std::string error_str;
|
||||||
|
std::string object_name;
|
||||||
|
std::vector<OCCTVolume> volumes;
|
||||||
|
};
|
||||||
|
|
||||||
|
using LoadStepFn = bool (*)(const char *path, OCCTResult* occt_result);
|
||||||
|
|
||||||
|
}; // namespace Slic3r
|
||||||
|
|
||||||
|
#endif // occtwrapper_OCCTWrapper_hpp_
|
@ -482,10 +482,11 @@ struct FileWildcards {
|
|||||||
static const FileWildcards file_wildcards_by_type[FT_SIZE] = {
|
static const FileWildcards file_wildcards_by_type[FT_SIZE] = {
|
||||||
/* FT_STL */ { "STL files"sv, { ".stl"sv } },
|
/* FT_STL */ { "STL files"sv, { ".stl"sv } },
|
||||||
/* FT_OBJ */ { "OBJ files"sv, { ".obj"sv } },
|
/* FT_OBJ */ { "OBJ files"sv, { ".obj"sv } },
|
||||||
|
/* FT_STEP */ { "STEP files"sv, { ".stp"sv, ".step"sv } },
|
||||||
/* FT_AMF */ { "AMF files"sv, { ".amf"sv, ".zip.amf"sv, ".xml"sv } },
|
/* FT_AMF */ { "AMF files"sv, { ".amf"sv, ".zip.amf"sv, ".xml"sv } },
|
||||||
/* FT_3MF */ { "3MF files"sv, { ".3mf"sv } },
|
/* FT_3MF */ { "3MF files"sv, { ".3mf"sv } },
|
||||||
/* FT_GCODE */ { "G-code files"sv, { ".gcode"sv, ".gco"sv, ".g"sv, ".ngc"sv } },
|
/* FT_GCODE */ { "G-code files"sv, { ".gcode"sv, ".gco"sv, ".g"sv, ".ngc"sv } },
|
||||||
/* FT_MODEL */ { "Known files"sv, { ".stl"sv, ".obj"sv, ".3mf"sv, ".amf"sv, ".zip.amf"sv, ".xml"sv } },
|
/* FT_MODEL */ { "Known files"sv, { ".stl"sv, ".obj"sv, ".3mf"sv, ".amf"sv, ".zip.amf"sv, ".xml"sv, ".step"sv, ".stp"sv } },
|
||||||
/* FT_PROJECT */ { "Project files"sv, { ".3mf"sv, ".amf"sv, ".zip.amf"sv } },
|
/* FT_PROJECT */ { "Project files"sv, { ".3mf"sv, ".amf"sv, ".zip.amf"sv } },
|
||||||
/* FT_GALLERY */ { "Known files"sv, { ".stl"sv, ".obj"sv } },
|
/* FT_GALLERY */ { "Known files"sv, { ".stl"sv, ".obj"sv } },
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ enum FileType
|
|||||||
{
|
{
|
||||||
FT_STL,
|
FT_STL,
|
||||||
FT_OBJ,
|
FT_OBJ,
|
||||||
|
FT_STEP,
|
||||||
FT_AMF,
|
FT_AMF,
|
||||||
FT_3MF,
|
FT_3MF,
|
||||||
FT_GCODE,
|
FT_GCODE,
|
||||||
|
Loading…
Reference in New Issue
Block a user