Merge branch lm_tm_step_sq into master_250
This commit is contained in:
commit
ea0a68a073
17 changed files with 488 additions and 9 deletions
|
@ -33,6 +33,7 @@ option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1)
|
|||
option(SLIC3R_MSVC_PDB "Generate PDB files on MSVC in Release mode" 1)
|
||||
option(SLIC3R_PERL_XS "Compile XS Perl module and enable Perl unit and integration tests" 0)
|
||||
option(SLIC3R_ASAN "Enable ASan on Clang and GCC" 0)
|
||||
option(SLIC3R_ENABLE_FORMAT_STEP "Enable compilation of STEP file support" 1)
|
||||
# If SLIC3R_FHS is 1 -> SLIC3R_DESKTOP_INTEGRATION is always 0, othrewise variable.
|
||||
CMAKE_DEPENDENT_OPTION(SLIC3R_DESKTOP_INTEGRATION "Allow perfoming desktop integration during runtime" 1 "NOT SLIC3R_FHS" 0)
|
||||
|
||||
|
|
5
deps/CMakeLists.txt
vendored
5
deps/CMakeLists.txt
vendored
|
@ -75,6 +75,9 @@ function(prusaslicer_add_cmake_project projectname)
|
|||
if (MSVC)
|
||||
set(_gen CMAKE_GENERATOR "${DEP_MSVC_GEN}" CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}")
|
||||
set(_build_j "/m")
|
||||
if (${projectname} STREQUAL "OCCT")
|
||||
set(_build_j "/m:1")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
ExternalProject_Add(
|
||||
|
@ -189,6 +192,7 @@ endif ()
|
|||
include(JPEG/JPEG.cmake)
|
||||
include(TIFF/TIFF.cmake)
|
||||
include(wxWidgets/wxWidgets.cmake)
|
||||
include(OCCT/OCCT.cmake)
|
||||
|
||||
set(_dep_list
|
||||
dep_Boost
|
||||
|
@ -200,6 +204,7 @@ set(_dep_list
|
|||
dep_OpenVDB
|
||||
dep_OpenCSG
|
||||
dep_CGAL
|
||||
dep_OCCT
|
||||
${PNG_PKG}
|
||||
${ZLIB_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,12 +15,13 @@ add_subdirectory(semver)
|
|||
add_subdirectory(libigl)
|
||||
add_subdirectory(hints)
|
||||
add_subdirectory(qoi)
|
||||
|
||||
# Adding libnest2d project for bin packing...
|
||||
add_subdirectory(libnest2d)
|
||||
|
||||
add_subdirectory(libslic3r)
|
||||
|
||||
if (SLIC3R_ENABLE_FORMAT_STEP)
|
||||
add_subdirectory(occt_wrapper)
|
||||
endif ()
|
||||
|
||||
if (SLIC3R_GUI)
|
||||
add_subdirectory(imgui)
|
||||
add_subdirectory(hidapi)
|
||||
|
@ -127,6 +128,7 @@ if (NOT WIN32 AND NOT APPLE)
|
|||
endif ()
|
||||
|
||||
target_link_libraries(PrusaSlicer libslic3r cereal)
|
||||
|
||||
if (APPLE)
|
||||
# add_compile_options(-stdlib=libc++)
|
||||
# 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/SL1.hpp
|
||||
Format/SL1.cpp
|
||||
Format/STEP.hpp
|
||||
Format/STEP.cpp
|
||||
GCode/ThumbnailData.cpp
|
||||
GCode/ThumbnailData.hpp
|
||||
GCode/Thumbnails.cpp
|
||||
|
@ -412,6 +414,11 @@ target_link_libraries(libslic3r
|
|||
qoi
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
# TODO: we need to fix notarization with the separate shared library
|
||||
target_link_libraries(libslic3r OCCTWrapper)
|
||||
endif ()
|
||||
|
||||
if (TARGET OpenVDB::openvdb)
|
||||
target_link_libraries(libslic3r OpenVDB::openvdb)
|
||||
endif()
|
||||
|
|
129
src/libslic3r/Format/STEP.cpp
Normal file
129
src/libslic3r/Format/STEP.cpp
Normal file
|
@ -0,0 +1,129 @@
|
|||
#include "STEP.hpp"
|
||||
#include "occt_wrapper/OCCTWrapper.hpp"
|
||||
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/dll/runtime_symbol_info.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include<windows.h>
|
||||
#else
|
||||
#include<occt_wrapper/OCCTWrapper.hpp>
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
#if __APPLE__
|
||||
extern "C" bool load_step_internal(const char *path, OCCTResult* res);
|
||||
#endif
|
||||
|
||||
LoadStepFn get_load_step_fn()
|
||||
{
|
||||
static LoadStepFn load_step_fn = nullptr;
|
||||
|
||||
constexpr const char* fn_name = "load_step_internal";
|
||||
|
||||
if (!load_step_fn) {
|
||||
auto libpath = boost::dll::program_location().parent_path();
|
||||
#ifdef _WIN32
|
||||
libpath /= "OCCTWrapper.dll";
|
||||
HMODULE module = LoadLibraryW(libpath.wstring().c_str());
|
||||
if (module == NULL)
|
||||
throw Slic3r::RuntimeError("Cannot load OCCTWrapper.dll");
|
||||
|
||||
try {
|
||||
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;
|
||||
}
|
||||
#elif __APPLE__
|
||||
load_step_fn = &load_step_internal;
|
||||
#else
|
||||
libpath /= "OCCTWrapper.so";
|
||||
void *plugin_ptr = dlopen(libpath.c_str(), RTLD_NOW | RTLD_GLOBAL);
|
||||
|
||||
if (plugin_ptr) {
|
||||
load_step_fn = reinterpret_cast<LoadStepFn>(dlsym(plugin_ptr, fn_name));
|
||||
if (!load_step_fn) {
|
||||
dlclose(plugin_ptr);
|
||||
throw Slic3r::RuntimeError(std::string("Cannot load function from OCCTWrapper.dll: ") + fn_name
|
||||
+ "\n\n" + dlerror());
|
||||
}
|
||||
} else {
|
||||
throw Slic3r::RuntimeError(std::string("Cannot load OCCTWrapper.dll:\n\n") + dlerror());
|
||||
}
|
||||
#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/STL.hpp"
|
||||
#include "Format/3mf.hpp"
|
||||
#include "Format/STEP.hpp"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
|
@ -114,13 +115,15 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
|
|||
result = load_stl(input_file.c_str(), &model);
|
||||
else if (boost::algorithm::iends_with(input_file, ".obj"))
|
||||
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"))
|
||||
result = load_amf(input_file.c_str(), config, config_substitutions, &model, options & LoadAttribute::CheckVersion);
|
||||
else if (boost::algorithm::iends_with(input_file, ".3mf"))
|
||||
//FIXME options & LoadAttribute::CheckVersion ?
|
||||
result = load_3mf(input_file.c_str(), *config, *config_substitutions, &model, false);
|
||||
else
|
||||
throw Slic3r::RuntimeError("Unknown file format. Input file must have .stl, .obj, .amf(.xml) or .prusa extension.");
|
||||
throw Slic3r::RuntimeError("Unknown file format. Input file must have .stl, .obj, .amf(.xml), .prusa or .step/.stp extension.");
|
||||
|
||||
if (! result)
|
||||
throw Slic3r::RuntimeError("Loading of a model file failed.");
|
||||
|
|
|
@ -1370,4 +1370,5 @@ bool its_write_stl_binary(const char *file, const char *label, const std::vector
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
60
src/occt_wrapper/CMakeLists.txt
Normal file
60
src/occt_wrapper/CMakeLists.txt
Normal file
|
@ -0,0 +1,60 @@
|
|||
cmake_minimum_required(VERSION 3.13)
|
||||
project(OCCTWrapper)
|
||||
|
||||
if (APPLE)
|
||||
# TODO: we need to fix notarization with the separate shared library
|
||||
add_library(OCCTWrapper STATIC OCCTWrapper.cpp)
|
||||
else ()
|
||||
add_library(OCCTWrapper MODULE OCCTWrapper.cpp)
|
||||
endif ()
|
||||
|
||||
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})
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
install(TARGETS OCCTWrapper DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
|
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] = {
|
||||
/* FT_STL */ { "STL files"sv, { ".stl"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_3MF */ { "3MF files"sv, { ".3mf"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_GALLERY */ { "Known files"sv, { ".stl"sv, ".obj"sv } },
|
||||
|
||||
|
@ -1867,7 +1868,7 @@ void GUI_App::import_model(wxWindow *parent, wxArrayString& input_files) const
|
|||
{
|
||||
input_files.Clear();
|
||||
wxFileDialog dialog(parent ? parent : GetTopWindow(),
|
||||
_L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"),
|
||||
_L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA/STEP):"),
|
||||
from_u8(app_config->get_last_dir()), "",
|
||||
file_wildcards(FT_MODEL), wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ enum FileType
|
|||
{
|
||||
FT_STL,
|
||||
FT_OBJ,
|
||||
FT_STEP,
|
||||
FT_AMF,
|
||||
FT_3MF,
|
||||
FT_GCODE,
|
||||
|
|
|
@ -80,7 +80,7 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||
{ ctrl + alt + "S", L("Save project as (3mf)") },
|
||||
{ ctrl + "R", L("(Re)slice") },
|
||||
// File>Import
|
||||
{ ctrl + "I", L("Import STL/OBJ/AMF/3MF without config, keep plater") },
|
||||
{ ctrl + "I", L("Import STL/OBJ/AMF/3MF/STEP without config, keep plater") },
|
||||
{ ctrl + "L", L("Import Config from ini/amf/3mf/gcode") },
|
||||
{ ctrl + alt + "L", L("Load Config from ini/amf/3mf/gcode and merge") },
|
||||
// File>Export
|
||||
|
|
|
@ -1205,7 +1205,7 @@ void MainFrame::init_menubar_as_editor()
|
|||
fileMenu->AppendSeparator();
|
||||
|
||||
wxMenu* import_menu = new wxMenu();
|
||||
append_menu_item(import_menu, wxID_ANY, _L("Import STL/OBJ/AM&F/3MF") + dots + "\tCtrl+I", _L("Load a model"),
|
||||
append_menu_item(import_menu, wxID_ANY, _L("Import STL/OBJ/AM&F/3MF/STEP") + dots + "\tCtrl+I", _L("Load a model"),
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->add_model(); }, "import_plater", nullptr,
|
||||
[this](){return m_plater != nullptr; }, this);
|
||||
|
||||
|
|
|
@ -5340,7 +5340,7 @@ void ProjectDropDialog::on_dpi_changed(const wxRect& suggested_rect)
|
|||
|
||||
bool Plater::load_files(const wxArrayString& filenames)
|
||||
{
|
||||
const std::regex pattern_drop(".*[.](stl|obj|amf|3mf|prusa)", std::regex::icase);
|
||||
const std::regex pattern_drop(".*[.](stl|obj|amf|3mf|prusa|step|stp)", std::regex::icase);
|
||||
const std::regex pattern_gcode_drop(".*[.](gcode|g)", std::regex::icase);
|
||||
|
||||
std::vector<fs::path> paths;
|
||||
|
|
Loading…
Reference in a new issue