From 78a4f2867c4fc541c7472af3edf1b9ddf068d0a9 Mon Sep 17 00:00:00 2001 From: Kris Austin Date: Sun, 4 Oct 2026 10:36:54 -0500 Subject: [PATCH] build: update OCCT to 8.0.1 (faster STEP and Design tab, Windows STEP crash fix) (#16089) --- .gitattributes | 3 + CMakeLists.txt | 3 +- deps/OCCT/0001-OCCT-fix.patch | 264 ---- deps/OCCT/OCCT.cmake | 36 +- docs/HLSD/design-tab.md | 17 +- scripts/flatpak/com.orcaslicer.OrcaSlicer.yml | 6 +- src/libslic3r/CAD/CadDocument.cpp | 63 +- src/libslic3r/CAD/GeometryEngine.cpp | 25 +- src/libslic3r/CAD/SketchEngine.cpp | 56 +- src/libslic3r/CAD/SketchEngine.hpp | 3 + src/libslic3r/CMakeLists.txt | 29 +- src/libslic3r/Format/STEP.cpp | 33 +- src/libslic3r/Format/STEP.hpp | 4 +- src/libslic3r/Format/svg.cpp | 12 +- src/libslic3r/Shape/TextShape.cpp | 40 +- src/slic3r/GUI/CAD/DesignPanel.cpp | 30 +- src/slic3r/GUI/CAD/McpControl.cpp | 14 +- src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 2 +- tests/data/cad_brep_occt76.brep | 1288 +++++++++++++++++ tests/data/security_classification.step | 61 + tests/libslic3r/test_caddocument.cpp | 136 +- tests/libslic3r/test_step.cpp | 16 + 22 files changed, 1665 insertions(+), 476 deletions(-) delete mode 100644 deps/OCCT/0001-OCCT-fix.patch create mode 100644 tests/data/cad_brep_occt76.brep create mode 100644 tests/data/security_classification.step diff --git a/.gitattributes b/.gitattributes index 472a0b2d1f..f1b81bf615 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10,3 +10,6 @@ # resume after `call :label`. With LF endings that offset can land wrong and the # label lookup fails, so keep these CRLF whatever the platform. *.bat text eol=crlf + +# OCCT BRep fixtures, kept byte for byte as OCCT wrote them. +*.brep -text diff --git a/CMakeLists.txt b/CMakeLists.txt index c431bff558..2bfb01a657 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1131,7 +1131,8 @@ function(orcaslicer_copy_dlls target config postfix output_dlls) if (NOT OCCT_LIBS) message(FATAL_ERROR "OCCT_LIBS is not set; libslic3r must be configured first.") endif () - set(_occt_bin "${CMAKE_PREFIX_PATH}/bin/occt") + string(TOUPPER "${config}" _config_upper) + set(_occt_bin "${OCCT_BIN_DIR_${_config_upper}}") set(_occt_dlls "") set(_occt_staged "") set(_missing_occt "") diff --git a/deps/OCCT/0001-OCCT-fix.patch b/deps/OCCT/0001-OCCT-fix.patch deleted file mode 100644 index d251cc7ab6..0000000000 --- a/deps/OCCT/0001-OCCT-fix.patch +++ /dev/null @@ -1,264 +0,0 @@ -diff --git a/adm/cmake/occt_defs_flags.cmake b/adm/cmake/occt_defs_flags.cmake -index 00000000..00000001 100644 ---- a/adm/cmake/occt_defs_flags.cmake -+++ b/adm/cmake/occt_defs_flags.cmake -@@ -134,7 +134,11 @@ - set (CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}") - endif() - # Optimize size of binaries -- set (CMAKE_SHARED_LINKER_FLAGS "-Wl,-s ${CMAKE_SHARED_LINKER_FLAGS}") -+ # clang-cl reports the Clang compiler ID, and OCCT builds shared on Windows, -+ # where the MSVC-style linker gets this flag as an argument it does not know. -+ if (NOT WIN32) -+ set (CMAKE_SHARED_LINKER_FLAGS "-Wl,-s ${CMAKE_SHARED_LINKER_FLAGS}") -+ endif() - elseif(MINGW) - add_definitions(-D_WIN32_WINNT=0x0601) - # _WIN32_WINNT=0x0601 (use Windows 7 SDK) -diff --git a/CMakeLists.txt b/CMakeLists.txt -index d98acc0f..28eb8eb4 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -225,7 +225,7 @@ if (NOT DEFINED INSTALL_DIR_BIN) - if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") - set (INSTALL_DIR_BIN "bin" CACHE PATH "${INSTALL_DIR_BIN_DESCR}") - else() -- set (INSTALL_DIR_BIN "${OS_WITH_BIT}/${COMPILER}/bin" CACHE PATH "${INSTALL_DIR_BIN_DESCR}") -+ set (INSTALL_DIR_BIN "bin/occt" CACHE PATH "${INSTALL_DIR_BIN_DESCR}") - endif() - endif() - -@@ -243,11 +243,11 @@ if (NOT DEFINED INSTALL_DIR_LIB) - if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") - set (INSTALL_DIR_LIB "lib" CACHE PATH "${INSTALL_DIR_LIB_DESCR}") - else() -- set (INSTALL_DIR_LIB "${OS_WITH_BIT}/${COMPILER}/lib" CACHE PATH "${INSTALL_DIR_LIB_DESCR}") -+ set (INSTALL_DIR_LIB "lib/occt" CACHE PATH "${INSTALL_DIR_LIB_DESCR}") - endif() - endif() - --# OCCT headers: /inc for windows, -+# OCCT headers: /include for windows, - # /include/opencascade-7.0.0 for unix - if (NOT DEFINED INSTALL_DIR_INCLUDE) - if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") -@@ -256,7 +256,7 @@ if (NOT DEFINED INSTALL_DIR_INCLUDE) - set (INSTALL_DIR_INCLUDE "include/opencascade-${OCC_VERSION_STRING_EXT}" CACHE PATH "${INSTALL_DIR_INCLUDE_DESCR}" FORCE) - endif() - else() -- set (INSTALL_DIR_INCLUDE "inc" CACHE PATH "${INSTALL_DIR_INCLUDE_DESCR}") -+ set (INSTALL_DIR_INCLUDE "include/occt" CACHE PATH "${INSTALL_DIR_INCLUDE_DESCR}") - endif() - endif() - -@@ -330,7 +330,7 @@ if (NOT DEFINED INSTALL_DIR_CMAKE) - set (INSTALL_DIR_CMAKE "lib/cmake/opencascade" CACHE PATH "${INSTALL_DIR_CMAKE_DESCR}") - endif() - else() -- set (INSTALL_DIR_CMAKE "cmake" CACHE PATH "${INSTALL_DIR_CMAKE_DESCR}") -+ set (INSTALL_DIR_CMAKE "lib/cmake/occt" CACHE PATH "${INSTALL_DIR_CMAKE_DESCR}") - endif() - endif() - -@@ -338,13 +338,13 @@ endif() - OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/occt_resources") - - # install LICENSE_LGPL_21.txt and OCCT_LGPL_EXCEPTION.txt files --if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") -- OCCT_INSTALL_FILE_OR_DIR ("LICENSE_LGPL_21.txt" "${INSTALL_DIR_DOC}") -- OCCT_INSTALL_FILE_OR_DIR ("OCCT_LGPL_EXCEPTION.txt" "${INSTALL_DIR_DOC}") --else() -- OCCT_INSTALL_FILE_OR_DIR ("LICENSE_LGPL_21.txt" ".") -- OCCT_INSTALL_FILE_OR_DIR ("OCCT_LGPL_EXCEPTION.txt" ".") --endif() -+#if ("${INSTALL_DIR_LAYOUT}" STREQUAL "Unix") -+# OCCT_INSTALL_FILE_OR_DIR ("LICENSE_LGPL_21.txt" "${INSTALL_DIR_DOC}") -+# OCCT_INSTALL_FILE_OR_DIR ("OCCT_LGPL_EXCEPTION.txt" "${INSTALL_DIR_DOC}") -+#else() -+# OCCT_INSTALL_FILE_OR_DIR ("LICENSE_LGPL_21.txt" ".") -+# OCCT_INSTALL_FILE_OR_DIR ("OCCT_LGPL_EXCEPTION.txt" ".") -+#endif() - - if(APPLE) - set (INSTALL_NAME_DIR "" CACHE STRING "install_name library suffix on OS X (e.g. @executable_path/../Frameworks)") -@@ -850,34 +850,34 @@ endif() - - # build directories - if (SINGLE_GENERATOR) -- set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/lib${BIN_LETTER}") -- set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin${BIN_LETTER}") -- set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/lib${BIN_LETTER}") -+ set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/occt") -+ set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/occt") -+ set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/occt") - if (WIN32) -- set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin${BIN_LETTER}") -+ set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/occt") - endif() - endif() - --set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/lib") --set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin") --set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/lib") -+set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/lib/occt") -+set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/bin/occt") -+set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/lib/occt") - --set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/libi") --set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bini") --set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/libi") -+set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/lib/occt/RelWithDebInfo") -+set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/bin/occt/RelWithDebInfo") -+set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/lib/occt/RelWithDebInfo") - --set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/libd") --set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bind") --set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/libd") -+set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/lib/occt/Debug") -+set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin/occt/Debug") -+set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/lib/occt/Debug") - - if (WIN32) -- set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin") -- set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bini") -- set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bind") -+ set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/bin/occt") -+ set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/bin/occt/RelWithDebInfo") -+ set (CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin/occt/Debug") - endif() - - string(TIMESTAMP CURRENT_TIME "%H:%M:%S") --message (STATUS "\nInfo: \(${CURRENT_TIME}\) Start collecting all OCCT header files into ${CMAKE_BINARY_DIR}/inc ...") -+message (STATUS "\nInfo: \(${CURRENT_TIME}\) Start collecting all OCCT header files into ${CMAKE_BINARY_DIR}/include/occt ...") - - # collect all the headers to /inc folder - COLLECT_AND_INSTALL_OCCT_HEADER_FILES ("${CMAKE_BINARY_DIR}" "${BUILD_TOOLKITS}" "${CMAKE_SOURCE_DIR}/src" "${INSTALL_DIR_INCLUDE}") -@@ -984,9 +984,9 @@ if (EXISTS "${INSTALL_DIR}/${INSTALL_DIR_SCRIPT}/custom.${SCRIPT_EXT}") - - set (CUSTOM_CONTENT "${CUSTOM_CONTENT} ${ADDITIONAL_CUSTOM_CONTENT}") - -- file (WRITE "${INSTALL_DIR}/${INSTALL_DIR_SCRIPT}/custom.${SCRIPT_EXT}" "${CUSTOM_CONTENT}") -+ #file (WRITE "${INSTALL_DIR}/${INSTALL_DIR_SCRIPT}/custom.${SCRIPT_EXT}" "${CUSTOM_CONTENT}") - else() -- OCCT_CONFIGURE_AND_INSTALL ("adm/templates/custom.${SCRIPT_EXT}.main" "custom.${SCRIPT_EXT}" "custom.${SCRIPT_EXT}" "${INSTALL_DIR_SCRIPT}") -+ #OCCT_CONFIGURE_AND_INSTALL ("adm/templates/custom.${SCRIPT_EXT}.main" "custom.${SCRIPT_EXT}" "custom.${SCRIPT_EXT}" "${INSTALL_DIR_SCRIPT}") - endif() - - if (WIN32) -@@ -1007,7 +1007,7 @@ endforeach() - - # write current custom.bat/sh (for install directory) - set (SUB_CUSTOM_BUILD_NAME "custom_${COMPILER}_${COMPILER_BITNESS}.install.${SCRIPT_EXT}") --OCCT_CONFIGURE_AND_INSTALL ("adm/templates/custom.install.${SCRIPT_EXT}.in" "${SUB_CUSTOM_BUILD_NAME}" "${SUB_CUSTOM_NAME}" "${INSTALL_DIR_SCRIPT}") -+#OCCT_CONFIGURE_AND_INSTALL ("adm/templates/custom.install.${SCRIPT_EXT}.in" "${SUB_CUSTOM_BUILD_NAME}" "${SUB_CUSTOM_NAME}" "${INSTALL_DIR_SCRIPT}") - - # write current custom.bat/sh (for build directory) - OCCT_CONFIGURE ("adm/templates/custom.build.${SCRIPT_EXT}.in" "${SUB_CUSTOM_NAME}") -@@ -1019,9 +1019,9 @@ endif() - - if (WIN32) - # env script for draw in building environment -- OCCT_CONFIGURE ("adm/templates/env.${SCRIPT_EXT}.in" "env.${SCRIPT_EXT}") -+ #OCCT_CONFIGURE ("adm/templates/env.${SCRIPT_EXT}.in" "env.${SCRIPT_EXT}") - # install env script -- install (FILES "${CMAKE_BINARY_DIR}/env.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SCRIPT}") -+ #install (FILES "${CMAKE_BINARY_DIR}/env.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SCRIPT}") - # copy build.bat and install.bat scripts to CMake binary folder - OCCT_COPY_FILE_OR_DIR ("adm/templates/build.bat" "${CMAKE_BINARY_DIR}") - OCCT_COPY_FILE_OR_DIR ("adm/templates/install.bat" "${CMAKE_BINARY_DIR}") -@@ -1043,12 +1043,12 @@ endif() - FILE_TO_LIST ("adm/RESOURCES" RESOURCES) - foreach(RESOURCE ${RESOURCES}) - get_filename_component(RESOURCE_FOLDER ${RESOURCE} DIRECTORY) -- if(NOT "${RESOURCE_FOLDER}" STREQUAL "") -- get_filename_component(RESOURCE_FOLDER ${RESOURCE_FOLDER} NAME) -- OCCT_INSTALL_FILE_OR_DIR ("src/${RESOURCE}" "${INSTALL_DIR_RESOURCE}/${RESOURCE_FOLDER}") -- else() -- OCCT_INSTALL_FILE_OR_DIR ("src/${RESOURCE}" "${INSTALL_DIR_RESOURCE}") -- endif() -+ #if(NOT "${RESOURCE_FOLDER}" STREQUAL "") -+ # get_filename_component(RESOURCE_FOLDER ${RESOURCE_FOLDER} NAME) -+ # OCCT_INSTALL_FILE_OR_DIR ("src/${RESOURCE}" "${INSTALL_DIR_RESOURCE}/${RESOURCE_FOLDER}") -+ #else() -+ # OCCT_INSTALL_FILE_OR_DIR ("src/${RESOURCE}" "${INSTALL_DIR_RESOURCE}") -+ #endif() - endforeach() - - if (BUILD_SAMPLES_QT) -diff --git a/adm/cmake/occt_macros.cmake b/adm/cmake/occt_macros.cmake -index 224c96b1..8c94a1c5 100644 ---- a/adm/cmake/occt_macros.cmake -+++ b/adm/cmake/occt_macros.cmake -@@ -608,7 +608,7 @@ macro (OCCT_INSERT_CODE_FOR_TARGET) - install(CODE "if (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Rr][Ee][Ll][Ee][Aa][Ss][Ee])$\") - set (OCCT_INSTALL_BIN_LETTER \"\") - elseif (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Rr][Ee][Ll][Ww][Ii][Tt][Hh][Dd][Ee][Bb][Ii][Nn][Ff][Oo])$\") -- set (OCCT_INSTALL_BIN_LETTER \"i\") -+ set (OCCT_INSTALL_BIN_LETTER \"\") - elseif (\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Dd][Ee][Bb][Uu][Gg])$\") - set (OCCT_INSTALL_BIN_LETTER \"d\") - endif()") -diff --git a/adm/cmake/occt_toolkit.cmake b/adm/cmake/occt_toolkit.cmake -index 550e0e2f..7ac1a3b8 100644 ---- a/adm/cmake/occt_toolkit.cmake -+++ b/adm/cmake/occt_toolkit.cmake -@@ -241,7 +241,7 @@ - else() - set (aReleasePdbConf) - endif() -- install (FILES ${CMAKE_BINARY_DIR}/${OS_WITH_BIT}/${COMPILER}/bin\${OCCT_INSTALL_BIN_LETTER}/${PROJECT_NAME}.pdb -+ install (FILES $ - CONFIGURATIONS Debug ${aReleasePdbConf} RelWithDebInfo - DESTINATION "${INSTALL_DIR_BIN}\${OCCT_INSTALL_BIN_LETTER}") - endif() -diff --git a/src/Font/Font_FTFont.cxx b/src/Font/Font_FTFont.cxx -index 5ae9899f..0a17372b 100644 ---- a/src/Font/Font_FTFont.cxx -+++ b/src/Font/Font_FTFont.cxx -@@ -103,9 +103,11 @@ bool Font_FTFont::Init (const Handle(NCollection_Buffer)& theData, - { - throw Standard_ProgramError ("Font_FTFont, Light and Normal hinting styles are mutually exclusive"); - } -+#ifdef HAVE_FREETYPE - setLoadFlag (FT_LOAD_TARGET_LIGHT, (theParams.FontHinting & Font_Hinting_Light) != 0); - setLoadFlag (FT_LOAD_NO_HINTING, (theParams.FontHinting & Font_Hinting_Normal) == 0 - && (theParams.FontHinting & Font_Hinting_Light) == 0); -+#endif - - // manage native / autohinting - if ((theParams.FontHinting & Font_Hinting_ForceAutohint) != 0 -@@ -113,8 +115,10 @@ bool Font_FTFont::Init (const Handle(NCollection_Buffer)& theData, - { - throw Standard_ProgramError ("Font_FTFont, ForceAutohint and NoAutohint are mutually exclusive"); - } -+#ifdef HAVE_FREETYPE - setLoadFlag (FT_LOAD_FORCE_AUTOHINT, (theParams.FontHinting & Font_Hinting_ForceAutohint) != 0); - setLoadFlag (FT_LOAD_NO_AUTOHINT, (theParams.FontHinting & Font_Hinting_NoAutohint) != 0); -+#endif - - if (!myFTLib->IsValid()) - { -From 7236e83dcc1e7284e66dc61e612154617ef715d6 Mon Sep 17 00:00:00 2001 -From: dpasukhi -Date: Tue, 27 Aug 2024 11:33:29 +0100 -Subject: [PATCH] 0033808: Coding - FreeType Use unsigned point and contour - indexing in `FT_Outline` - -Changes to auto instead of specific type ---- - src/StdPrs/StdPrs_BRepFont.cxx | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/StdPrs/StdPrs_BRepFont.cxx b/src/StdPrs/StdPrs_BRepFont.cxx -index ab2d9b3c9f..cd701879b1 100644 ---- a/src/StdPrs/StdPrs_BRepFont.cxx -+++ b/src/StdPrs/StdPrs_BRepFont.cxx -@@ -457,7 +457,7 @@ Standard_Boolean StdPrs_BRepFont::renderGlyph (const Standard_Utf32Char theChar, - for (short aContour = 0, aStartIndex = 0; aContour < anOutline->n_contours; ++aContour) - { - const FT_Vector* aPntList = &anOutline->points[aStartIndex]; -- const char* aTags = &anOutline->tags[aStartIndex]; -+ const auto* aTags = &anOutline->tags[aStartIndex]; - const short anEndIndex = anOutline->contours[aContour]; - const short aPntsNb = (anEndIndex - aStartIndex) + 1; - aStartIndex = anEndIndex + 1; diff --git a/deps/OCCT/OCCT.cmake b/deps/OCCT/OCCT.cmake index e1a65beef7..4cab60ec6a 100644 --- a/deps/OCCT/OCCT.cmake +++ b/deps/OCCT/OCCT.cmake @@ -1,5 +1,5 @@ -# clang-cl cannot emit IGESAppli_GeneralModule.cxx on ARM64 -# (llvm/llvm-project#62081). cl and clang-cl share an ABI. +# clang-cl cannot emit some OCCT sources for ARM64 (llvm/llvm-project#62081). +# cl and clang-cl share an ABI. set(_occt_compiler_args "") if ("${DEPS_ARCH}" STREQUAL "arm64" AND CMAKE_CXX_COMPILER_ID STREQUAL Clang) set(_occt_compiler_args -DCMAKE_C_COMPILER:STRING=cl -DCMAKE_CXX_COMPILER:STRING=cl) @@ -15,31 +15,31 @@ endif() # (fillet/offset/loft), whose only consumer is the parametric Design/CAD tab. With it OFF # the deps prefix matches upstream exactly. # -# With it ON the delta is THREE toolkits, not two: TKFillet (7.40 MiB archive, used via -# BRepFilletAPI), TKOffset (5.38 MiB, used via BRepOffsetAPI) and TKFeat (4.42 MiB), which -# nothing here references but which the module flag builds anyway -- it is all-or-nothing -# per module. The module's other nine toolkits are built either way, because DataExchange -# (the STEP path upstream already ships) depends on them. +# With it ON OCCT also builds TKFillet (used via BRepFilletAPI), TKOffset (used via +# BRepOffsetAPI), and TKFeat, TKHelix, TKXMesh and TKExpress, which nothing here references +# but which the module flag builds anyway, since module flags are all-or-nothing. The +# module's other toolkits are built either way, because DataExchange (the STEP path) +# depends on them. # # On macOS/Linux OCCT links statically, so an unreferenced toolkit costs build time and no -# shipped bytes. The Windows figure is a real DLL cost and has NOT been measured -- an -# earlier "3.77 MiB, Windows only" note here covered only two of the three toolkits and is -# not a number to quote. See docs/HLSD/design-tab.md. - -if (IN_GIT_REPO) - set(OCCT_DIRECTORY_FLAG --directory ${BINARY_DIR_REL}/dep_OCCT-prefix/src/dep_OCCT) -endif () +# shipped bytes. Windows ships only the DLLs libslic3r links, so the tab adds the TKFillet, +# TKOffset and TKBool DLLs. See docs/HLSD/design-tab.md. orcaslicer_add_cmake_project(OCCT - URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V7_6_0.zip - URL_HASH SHA256=28334f0e98f1b1629799783e9b4d21e05349d89e695809d7e6dfa45ea43e1dbc - #PATCH_COMMAND ${PATCH_CMD} ${CMAKE_CURRENT_LIST_DIR}/0001-OCCT-fix.patch - PATCH_COMMAND git apply ${OCCT_DIRECTORY_FLAG} --verbose --ignore-space-change --whitespace=fix ${CMAKE_CURRENT_LIST_DIR}/0001-OCCT-fix.patch + URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V8_0_1.zip + URL_HASH SHA256=7c033d917ee8f040c0512d289dcc5f02c148889d5bac17c3e25639accb44f0da #DEPENDS dep_Boost DEPENDS ${FREETYPE_PKG} CMAKE_ARGS -DCMAKE_CXX_STANDARD=17 -DBUILD_LIBRARY_TYPE=${library_build_type} + # With the Unix layout, OCCT's resources and licenses go under share/ and its scripts + # into bin/occt on Windows too. libslic3r finds the CMake package in lib/cmake/occt. + -DINSTALL_DIR_LAYOUT=Unix + -DINSTALL_DIR_BIN=bin/occt + -DINSTALL_DIR_LIB=lib/occt + -DINSTALL_DIR_INCLUDE=include/occt + -DINSTALL_DIR_CMAKE=lib/cmake/occt -DUSE_TK=OFF -DUSE_TBB=OFF #-DUSE_FREETYPE=OFF diff --git a/docs/HLSD/design-tab.md b/docs/HLSD/design-tab.md index 67589be328..aa4c7265bc 100644 --- a/docs/HLSD/design-tab.md +++ b/docs/HLSD/design-tab.md @@ -51,14 +51,13 @@ widens the existing OCCT build by one module flag in `deps/OCCT/OCCT.cmake`: -DBUILD_MODULE_ModelingAlgorithms=${SLIC3R_CAD} ``` -Most of that module's twelve toolkits were already being built, because `DataExchange` — the -STEP path upstream ships — depends on them. The delta is `TKFillet` (used through -`BRepFilletAPI`), `TKOffset` (`BRepOffsetAPI`) and `TKFeat`, which nothing here references but -which the module flag builds anyway, because OCCT's module flags are all-or-nothing. On macOS -and Linux OCCT links statically, so an unreferenced toolkit costs build time and no shipped -bytes; on Windows OCCT builds shared, so the cost there is real DLL bytes. That Windows figure -has not been measured, and `OCCT.cmake` says so rather than carrying a number that was derived -from an incomplete toolkit list. +Most of that module's toolkits are built either way, because `DataExchange`, which the STEP +importer uses, depends on them. With the flag on, OCCT also builds `TKFillet` (used through +`BRepFilletAPI`), `TKOffset` (`BRepOffsetAPI`), and `TKFeat`, `TKHelix`, `TKXMesh` and +`TKExpress`, which nothing here references but which the module flag builds anyway, because +OCCT's module flags are all-or-nothing. On macOS and Linux OCCT links statically, so an +unreferenced toolkit costs build time and no shipped bytes. On Windows OCCT builds shared and +only the linked toolkits ship, so the tab adds the `TKFillet`, `TKOffset` and `TKBool` DLLs. On Windows the packaging step asserts that every linked OCCT toolkit has a shipped DLL and fails the configure with the name of any that is missing, because the alternative failure — a @@ -117,6 +116,8 @@ that keep it survivable are: `Import` features embed the imported solid as an OCCT BRep string inside the recipe rather than referencing the source file, so a project opens without the STEP or mesh it was built from. The cost is that saved projects are coupled to an OCCT BRep revision. +`tests/data/cad_brep_occt76.brep` holds a solid written by OCCT 7.6, and its test fails if the +bundled OCCT can no longer read it. ## The interaction contract diff --git a/scripts/flatpak/com.orcaslicer.OrcaSlicer.yml b/scripts/flatpak/com.orcaslicer.OrcaSlicer.yml index 25cb4fdcc5..21587a361f 100644 --- a/scripts/flatpak/com.orcaslicer.OrcaSlicer.yml +++ b/scripts/flatpak/com.orcaslicer.OrcaSlicer.yml @@ -301,10 +301,10 @@ modules: sha256: a63ae025bb0a14f119e73250f2c923f4bf89aa93b8d4fafa4a9f5353a96a765a dest: external-packages/CURL - # OCCT (OpenCASCADE) V7_6_0 + # OCCT (OpenCASCADE) V8_0_1 - type: file - url: https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V7_6_0.zip - sha256: 28334f0e98f1b1629799783e9b4d21e05349d89e695809d7e6dfa45ea43e1dbc + url: https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V8_0_1.zip + sha256: 7c033d917ee8f040c0512d289dcc5f02c148889d5bac17c3e25639accb44f0da dest: external-packages/OCCT # OpenCV 4.6.0 diff --git a/src/libslic3r/CAD/CadDocument.cpp b/src/libslic3r/CAD/CadDocument.cpp index b4a89f6a69..b077d9cdd6 100644 --- a/src/libslic3r/CAD/CadDocument.cpp +++ b/src/libslic3r/CAD/CadDocument.cpp @@ -37,10 +37,9 @@ #include #include #include -#include +#include #include #include -#include #include #include #include @@ -53,7 +52,7 @@ #include #include #include // SurfaceFill: GeomAbs_C0 -#include +#include #include #include #include @@ -105,7 +104,7 @@ static TopoDS_Wire make_helix_wire(const gp_Ax3& axis, double radius, // In the surface (u,v) parametrization u is the angle, v the axial height. gp_Pnt2d p0(0.0, 0.0); gp_Pnt2d p1(2.0 * M_PI * turns, height); - Handle(Geom2d_TrimmedCurve) seg = GCE2d_MakeSegment(p0, p1); + Handle(Geom2d_TrimmedCurve) seg = GC_MakeSegment2d(p0, p1); TopoDS_Edge e = BRepBuilderAPI_MakeEdge(seg, cyl).Edge(); BRepLib::BuildCurves3d(e); return BRepBuilderAPI_MakeWire(e).Wire(); @@ -147,14 +146,14 @@ static TopoDS_Wire make_helix_spine(const CadFeature& f, std::string& err) double u1 = f.helix_left_handed ? -2.0 * M_PI * turns : 2.0 * M_PI * turns; gp_Pnt2d p0(0.0, 0.0); gp_Pnt2d p1(u1, H); - Handle(Geom2d_TrimmedCurve) seg = GCE2d_MakeSegment(p0, p1); + Handle(Geom2d_TrimmedCurve) seg = GC_MakeSegment2d(p0, p1); e = BRepBuilderAPI_MakeEdge(seg, cone).Edge(); } else { Handle(Geom_CylindricalSurface) cyl = new Geom_CylindricalSurface(ax3, R); double u1 = f.helix_left_handed ? -2.0 * M_PI * turns : 2.0 * M_PI * turns; gp_Pnt2d p0(0.0, 0.0); gp_Pnt2d p1(u1, H); - Handle(Geom2d_TrimmedCurve) seg = GCE2d_MakeSegment(p0, p1); + Handle(Geom2d_TrimmedCurve) seg = GC_MakeSegment2d(p0, p1); e = BRepBuilderAPI_MakeEdge(seg, cyl).Edge(); } BRepLib::BuildCurves3d(e); @@ -193,7 +192,7 @@ static TopoDS_Wire make_thread_profile(const gp_Pnt& origin, const gp_Dir& xdir, gp_Pnt top (origin.XYZ() + (vx * inner).XYZ() + (vz * ( half)).XYZ()); gp_Pnt bot (origin.XYZ() + (vx * inner).XYZ() + (vz * (-half)).XYZ()); gp_Pnt apex(origin.XYZ() + (vx * crest).XYZ()); - BRepBuilderAPI_MakePolygon poly(top, bot, apex, Standard_True); + BRepBuilderAPI_MakePolygon poly(top, bot, apex, true); return poly.Wire(); // closed triangle, swept by MakePipeShell with a fixed binormal } @@ -2368,10 +2367,12 @@ void CadDocument::apply_feature(TopoDS_Shape& result, bool& have_body, TopoDS_Wire wire = build_sketch_wire(sk); if (wire.IsNull()) throw std::runtime_error("surface-extrude: empty profile"); gp_Dir nrm(sk.plane.normal.x(), sk.plane.normal.y(), sk.plane.normal.z()); - gp_Vec v(nrm.XYZ() * f.distance); - TopoDS_Shape shell = BRepPrimAPI_MakePrism(wire, v, false, true).Shape(); - if (shell.IsNull()) throw std::runtime_error("surface-extrude: prism failed"); - result = shell; have_body = true; + try { + result = SketchEngine::make_prism(wire, gp_Vec(nrm.XYZ() * f.distance)); + } catch (const std::exception& e) { + throw std::runtime_error(std::string("surface-extrude: ") + (*e.what() ? e.what() : "prism failed")); + } + have_body = true; break; } case CadFeatureType::SurfaceRevolve: { @@ -2584,7 +2585,7 @@ void CadDocument::apply_feature(TopoDS_Shape& result, bool& have_body, double h = f.rib_thickness * 0.5; Vec2d q0 = a + perp*h, q1 = b + perp*h, q2 = b - perp*h, q3 = a - perp*h; auto w3 = [&](const Vec2d& p){ Vec3d w = pl.to_world(p); return gp_Pnt(w.x(),w.y(),w.z()); }; - BRepBuilderAPI_MakePolygon poly(w3(q0), w3(q1), w3(q2), w3(q3), Standard_True); + BRepBuilderAPI_MakePolygon poly(w3(q0), w3(q1), w3(q2), w3(q3), true); if (!poly.IsDone()) throw std::runtime_error("rib: profile failed"); TopoDS_Shape wall = SketchEngine::make_extrude(poly.Wire(), pl, f.rib_depth, false, 0.0); if (wall.IsNull()) throw std::runtime_error("rib: extrude failed"); @@ -2746,7 +2747,7 @@ void CadDocument::apply_feature(TopoDS_Shape& result, bool& have_body, if (!have_body) throw std::runtime_error("shell needs a body"); // Hollow the body to a wall thickness; the picked face (if any) is removed so the // shell is open there. MakeThickSolidByJoin with a NEGATIVE offset shells inward. - TopTools_ListOfShape remove; + NCollection_List remove; if (f.shell_face >= 0) { TopoDS_Face fc = GeometryEngine::face_by_index(result, f.shell_face); if (!fc.IsNull()) remove.Append(fc); @@ -2769,7 +2770,7 @@ void CadDocument::apply_feature(TopoDS_Shape& result, bool& have_body, // ponytail: neutral plane / pull direction fixed to world up; pick-based neutral plane // deferred (same as the datum-plane pick types, dgv). Bnd_Box bb; BRepBndLib::Add(result, bb); - Standard_Real xmin, ymin, zmin, xmax, ymax, zmax; + double xmin, ymin, zmin, xmax, ymax, zmax; bb.Get(xmin, ymin, zmin, xmax, ymax, zmax); gp_Dir pull(0, 0, 1); gp_Pln neutral(gp_Pnt(0, 0, zmin), pull); @@ -2850,7 +2851,7 @@ void CadDocument::apply_boolean(std::vector& bodies, const CadFeature& const TopoDS_Shape B = bodies[tool].shape; // tool, consumed unless kept if (A.IsNull() || B.IsNull()) return; - TopTools_ListOfShape args, tools; + NCollection_List args, tools; args.Append(A); tools.Append(B); auto run = [&](BRepAlgoAPI_BooleanOperation& bop) -> TopoDS_Shape { @@ -3091,7 +3092,7 @@ void CadDocument::apply_thicken_surface(std::vector& bodies, const CadF int n_faces = 0; for (TopExp_Explorer fe(sheet, TopAbs_FACE); fe.More(); fe.Next()) ++n_faces; - TopTools_ListOfShape caps; + NCollection_List caps; if (n_faces > 1) { ShapeAnalysis_FreeBounds fb(sheet); for (TopExp_Explorer we(fb.GetClosedWires(), TopAbs_WIRE); we.More(); we.Next()) { @@ -3113,7 +3114,7 @@ void CadDocument::apply_thicken_surface(std::vector& bodies, const CadF } else { BRepBuilderAPI_Sewing sewer(1.0e-3); sewer.Add(sheet); - for (TopTools_ListIteratorOfListOfShape it(caps); it.More(); it.Next()) + for (NCollection_List::Iterator it(caps); it.More(); it.Next()) sewer.Add(it.Value()); sewer.Perform(); @@ -3674,13 +3675,8 @@ bool CadDocument::recompute() if (b.source_feature < 0) b.source_feature = int(fi); } - } catch (const Standard_Failure& e) { - // OCCT raises Standard_Failure (NOT a std::exception) — must be caught - // here or it escapes the event handler and terminates the app. - error = e.GetMessageString() ? e.GetMessageString() : "OCCT operation failed"; - return false; } catch (const std::exception& e) { - error = e.what(); + error = *e.what() ? e.what() : "OCCT operation failed"; return false; } catch (...) { error = "unknown geometry error"; @@ -3782,11 +3778,8 @@ bool CadDocument::preview(const CadFeature& candidate, TriangleMesh& out_mesh, std::vector tmp = bodies; // start from the current committed bodies try { route_feature(tmp, candidate); // candidate may append a new body or mutate one - } catch (const Standard_Failure& e) { - err = e.GetMessageString() ? e.GetMessageString() : "OCCT operation failed"; - return false; } catch (const std::exception& e) { - err = e.what(); + err = *e.what() ? e.what() : "OCCT operation failed"; return false; } catch (...) { err = "unknown geometry error"; @@ -3986,13 +3979,9 @@ bool CadDocument::deserialize_recipe(const std::string& blob) error = "saved with an older version of the Design tab (format v" + std::to_string(v) + "); this project cannot be opened by this build"; return false; - } catch (const Standard_Failure& e) { - const char* what = e.GetMessageString(); - error = std::string("CAD data could not be read") - + (what && *what ? ": " + std::string(what) : ""); - return false; } catch (const std::exception& e) { - error = std::string("CAD data could not be read: ") + e.what(); + error = std::string("CAD data could not be read") + + (*e.what() ? ": " + std::string(e.what()) : ""); return false; } catch (...) { error = "CAD data could not be read"; @@ -4034,11 +4023,8 @@ bool CadDocument::export_step(const std::string& path, err = "cannot write STEP file"; return false; } - } catch (const Standard_Failure& e) { - err = e.GetMessageString() ? e.GetMessageString() : "OCCT failed to write STEP"; - return false; } catch (const std::exception& e) { - err = e.what(); + err = *e.what() ? e.what() : "OCCT failed to write STEP"; return false; } return true; @@ -4109,8 +4095,7 @@ std::vector CadDocument::check_interference(double mi if (bodies[j].shape.IsNull() || is_sheet_shape(bodies[j].shape)) continue; double v = 0; - // A boolean that blows up on one pair must not lose the report for the others, - // and OCCT signals those as Standard_Failure, which is NOT a std::exception. + // A boolean that fails on one pair must not lose the report for the others. try { BRepAlgoAPI_Common common(bodies[i].shape, bodies[j].shape); common.Build(); diff --git a/src/libslic3r/CAD/GeometryEngine.cpp b/src/libslic3r/CAD/GeometryEngine.cpp index 1e5896e67a..d764ab5318 100644 --- a/src/libslic3r/CAD/GeometryEngine.cpp +++ b/src/libslic3r/CAD/GeometryEngine.cpp @@ -27,9 +27,10 @@ #include #include #include -#include -#include -#include +#include +#include +#include +#include #include #include #include @@ -62,6 +63,8 @@ namespace Slic3r { +using ShapeIndexMap = NCollection_IndexedMap; + // ---- STEP import (B-rep, not mesh) ---- std::vector GeometryEngine::read_step_solids(const std::string& path, std::string& err) { @@ -82,7 +85,7 @@ std::vector GeometryEngine::read_step_solids(const std::string& pa if (out.empty()) out.push_back(shape); } catch (const Standard_Failure& e) { - err = e.GetMessageString() ? e.GetMessageString() : "OCCT failed to read STEP"; + err = *e.what() ? e.what() : "OCCT failed to read STEP"; out.clear(); } return out; @@ -299,13 +302,13 @@ std::vector GeometryEngine::collect_edges(const TopoDS_Shape& solid } // Build edge-to-face map once - TopTools_IndexedDataMapOfShapeListOfShape edgeFaceMap; + NCollection_IndexedDataMap, TopTools_ShapeMapHasher> edgeFaceMap; TopExp::MapShapesAndAncestors(solid, TopAbs_EDGE, TopAbs_FACE, edgeFaceMap); for (TopExp_Explorer edgeExp(solid, TopAbs_EDGE); edgeExp.More(); edgeExp.Next()) { const TopoDS_Edge& edge = TopoDS::Edge(edgeExp.Current()); if (!edgeFaceMap.Contains(edge)) continue; - const TopTools_ListOfShape& faces = edgeFaceMap.FindFromKey(edge); + const NCollection_List& faces = edgeFaceMap.FindFromKey(edge); bool include = false; for (auto it = faces.begin(); it != faces.end(); ++it) { @@ -569,7 +572,7 @@ std::vector GeometryEngine::faces_of(const TopoDS_Shape& shape) std::vector GeometryEngine::edges_of(const TopoDS_Shape& shape) { - TopTools_IndexedMapOfShape map; + ShapeIndexMap map; TopExp::MapShapes(shape, TopAbs_EDGE, map); // same order as edge_by_index std::vector out; out.reserve(map.Extent()); @@ -581,7 +584,7 @@ std::vector GeometryEngine::edges_of(const TopoDS_Shape& shape) std::vector GeometryEngine::edges_of_face(const TopoDS_Face& face) { std::vector result; - TopTools_IndexedMapOfShape map; + ShapeIndexMap map; TopExp::MapShapes(face, TopAbs_EDGE, map); for (int i = 1; i <= map.Extent(); ++i) result.push_back(TopoDS::Edge(map(i))); @@ -704,14 +707,14 @@ bool GeometryEngine::face_plane_bounds(const TopoDS_Face& face, const Vec3d& ori int GeometryEngine::edge_count(const TopoDS_Shape& shape) { - TopTools_IndexedMapOfShape map; + ShapeIndexMap map; TopExp::MapShapes(shape, TopAbs_EDGE, map); return map.Extent(); } TopoDS_Edge GeometryEngine::edge_by_index(const TopoDS_Shape& shape, int index) { - TopTools_IndexedMapOfShape map; + ShapeIndexMap map; TopExp::MapShapes(shape, TopAbs_EDGE, map); if (index < 0 || index >= map.Extent()) return TopoDS_Edge(); @@ -720,7 +723,7 @@ TopoDS_Edge GeometryEngine::edge_by_index(const TopoDS_Shape& shape, int index) int GeometryEngine::edge_index_of(const TopoDS_Shape& shape, const TopoDS_Edge& edge) { - TopTools_IndexedMapOfShape map; + ShapeIndexMap map; TopExp::MapShapes(shape, TopAbs_EDGE, map); int idx = map.FindIndex(edge); return (idx > 0) ? (idx - 1) : -1; diff --git a/src/libslic3r/CAD/SketchEngine.cpp b/src/libslic3r/CAD/SketchEngine.cpp index ba92fa88bb..44ee45d8a4 100644 --- a/src/libslic3r/CAD/SketchEngine.cpp +++ b/src/libslic3r/CAD/SketchEngine.cpp @@ -27,9 +27,7 @@ #include #include #include -#include -#include -#include +#include #include #include #include @@ -179,21 +177,23 @@ TopoDS_Wire SketchProfile::to_occt_wire(const SketchPlane& plane) const // ---- SketchEngine ---- +TopoDS_Shape SketchEngine::make_prism(const TopoDS_Shape& base, const gp_Vec& vec) +{ + if (vec.Magnitude() < 1e-9) throw std::runtime_error("extrude depth is zero"); + BRepPrimAPI_MakePrism prism(base, vec); + if (!prism.IsDone()) throw std::runtime_error("extrude failed"); + return prism.Shape(); +} + static TopoDS_Shape extrude_face_internal(const TopoDS_Face& face, const gp_Dir& dir, double length, bool symmetric) { - gp_Vec vec = gp_Vec(dir) * length; if (symmetric) { gp_Vec halfVec = gp_Vec(dir) * (length / 2.0); - BRepPrimAPI_MakePrism pos(face, halfVec); - BRepPrimAPI_MakePrism neg(face, -halfVec); - if (!pos.IsDone() || !neg.IsDone()) throw std::runtime_error("Symmetric extrude failed"); - BRepAlgoAPI_Fuse fuse(pos.Shape(), neg.Shape()); + BRepAlgoAPI_Fuse fuse(SketchEngine::make_prism(face, halfVec), SketchEngine::make_prism(face, -halfVec)); if (!fuse.IsDone()) throw std::runtime_error("Fuse failed"); return fuse.Shape(); } - BRepPrimAPI_MakePrism prism(face, vec); - if (!prism.IsDone()) throw std::runtime_error("Extrude failed"); - return prism.Shape(); + return SketchEngine::make_prism(face, gp_Vec(dir) * length); } TopoDS_Shape SketchEngine::make_extrude(const TopoDS_Wire& wire, const SketchPlane& plane, @@ -224,12 +224,9 @@ TopoDS_Shape SketchEngine::make_extrude_two_sided(const TopoDS_Face& face, const { gp_Dir dir(plane.normal.x(), plane.normal.y(), plane.normal.z()); const double u = std::abs(up), d = std::abs(down); - if (u < 1e-9 && d < 1e-9) return TopoDS_Shape(); - if (d < 1e-9) { BRepPrimAPI_MakePrism p(face, gp_Vec(dir) * u); return p.Shape(); } - if (u < 1e-9) { BRepPrimAPI_MakePrism p(face, gp_Vec(dir) * -d); return p.Shape(); } - BRepPrimAPI_MakePrism pos(face, gp_Vec(dir) * u); - BRepPrimAPI_MakePrism neg(face, gp_Vec(dir) * -d); - BRepAlgoAPI_Fuse fuse(pos.Shape(), neg.Shape()); + if (d < 1e-9) return make_prism(face, gp_Vec(dir) * u); + if (u < 1e-9) return make_prism(face, gp_Vec(dir) * -d); + BRepAlgoAPI_Fuse fuse(make_prism(face, gp_Vec(dir) * u), make_prism(face, gp_Vec(dir) * -d)); if (!fuse.IsDone()) throw std::runtime_error("two-sided extrude fuse failed"); return fuse.Shape(); } @@ -240,8 +237,8 @@ TopoDS_Shape SketchEngine::make_extrude_taper(const TopoDS_Wire& wire, const Ske gp_Dir dir(plane.normal.x(), plane.normal.y(), plane.normal.z()); auto straight = [&]() -> TopoDS_Shape { BRepBuilderAPI_MakeFace fm(wire); - BRepPrimAPI_MakePrism prism(fm.Face(), gp_Vec(dir) * length); - return prism.Shape(); + if (!fm.IsDone()) throw std::runtime_error("Failed to make face from wire"); + return make_prism(fm.Face(), gp_Vec(dir) * length); }; if (std::abs(taper_deg) >= 89.0 || std::abs(length) < 1e-9) return straight(); const double off = length * std::tan(taper_deg * M_PI / 180.0); @@ -258,10 +255,10 @@ TopoDS_Shape SketchEngine::make_extrude_taper(const TopoDS_Wire& wire, const Ske if (topFlat.IsNull()) return straight(); // 2) lift it along the normal by `length` gp_Trsf tr; tr.SetTranslation(gp_Vec(dir) * length); - BRepBuilderAPI_Transform xf(topFlat, tr, Standard_True); + BRepBuilderAPI_Transform xf(topFlat, tr, true); TopoDS_Wire topWire = TopoDS::Wire(xf.Shape()); // 3) loft base -> top into a solid - BRepOffsetAPI_ThruSections loft(Standard_True /*solid*/, Standard_False /*ruled*/); + BRepOffsetAPI_ThruSections loft(true /*solid*/, false /*ruled*/); loft.AddWire(wire); loft.AddWire(topWire); loft.Build(); @@ -285,6 +282,9 @@ TopoDS_Shape SketchEngine::make_extrude_regions( const std::vector>>& regions, const SketchPlane& plane, double length, bool symmetric) { + // The loop below skips regions that fail, so a zero depth is rejected before it. + if (std::abs(length) < 1e-9) throw std::runtime_error("extrude depth is zero"); + // Drop consecutive coincident points and the closing duplicate. FreeType / // SVG flattening routinely emits repeated points which would build a // degenerate OCCT edge and make the wire builder throw — sanitising keeps a @@ -406,8 +406,7 @@ TopoDS_Shape SketchEngine::make_loft(const std::vector& profiles, b { if (profiles.size() < 2) throw std::runtime_error("loft needs at least 2 profiles"); - BRepOffsetAPI_ThruSections loft(Standard_True /*solid*/, - ruled ? Standard_True : Standard_False); + BRepOffsetAPI_ThruSections loft(true /*solid*/, ruled); for (const TopoDS_Wire& w : profiles) { if (w.IsNull()) throw std::runtime_error("loft: null profile wire"); loft.AddWire(w); @@ -424,8 +423,7 @@ TopoDS_Shape SketchEngine::make_loft_surface(const std::vector& pro { if (profiles.size() < 2) throw std::runtime_error("loft needs at least 2 profiles"); - BRepOffsetAPI_ThruSections loft(Standard_False /*shell, no end caps*/, - ruled ? Standard_True : Standard_False); + BRepOffsetAPI_ThruSections loft(false /*shell, no end caps*/, ruled); for (const TopoDS_Wire& w : profiles) { if (w.IsNull()) throw std::runtime_error("loft: null profile wire"); loft.AddWire(w); @@ -597,15 +595,15 @@ std::vector SketchEngine::entities_to_wires(const std::vector= 4 ? 3 : (n >= 2 ? n - 1 : 0); if (p < 1) return Handle(Geom_BSplineCurve)(); - TColgp_Array1OfPnt poles(1, n); + NCollection_Array1 poles(1, n); for (int i = 0; i < n; ++i) { Vec3d w = plane.to_world(c.ctrl[i]); poles.SetValue(i + 1, gp_Pnt(w.x(), w.y(), w.z())); } const int interior = n - p - 1; // count of single interior knots const int nknots = interior + 2; - TColStd_Array1OfReal knots(1, nknots); - TColStd_Array1OfInteger mults(1, nknots); + NCollection_Array1 knots(1, nknots); + NCollection_Array1 mults(1, nknots); knots.SetValue(1, 0.0); mults.SetValue(1, p + 1); for (int i = 1; i <= interior; ++i) { knots.SetValue(i + 1, double(i)); mults.SetValue(i + 1, 1); } knots.SetValue(nknots, double(interior + 1)); mults.SetValue(nknots, p + 1); @@ -808,7 +806,7 @@ std::vector SketchEngine::entities_to_wires(const std::vectortype == SketchEntity::Type::EllipseArc) { if (e->radius <= 1e-9 || e->rminor <= 1e-9) return {}; - GC_MakeArcOfEllipse arc_maker(make_elips(*e), e->start_angle, e->end_angle, Standard_True); + GC_MakeArcOfEllipse arc_maker(make_elips(*e), e->start_angle, e->end_angle, true); if (!arc_maker.IsDone()) return {}; wm.Add(BRepBuilderAPI_MakeEdge(arc_maker.Value(), va, vb).Edge()); } else if (e->type == SketchEntity::Type::Arc) { diff --git a/src/libslic3r/CAD/SketchEngine.hpp b/src/libslic3r/CAD/SketchEngine.hpp index f2166e96a6..62f4d03219 100644 --- a/src/libslic3r/CAD/SketchEngine.hpp +++ b/src/libslic3r/CAD/SketchEngine.hpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -227,6 +228,8 @@ struct SketchParams { class SketchEngine { public: + // Throws on a zero vector, for which OCCT returns a degenerate solid. + static TopoDS_Shape make_prism(const TopoDS_Shape& base, const gp_Vec& vec); static TopoDS_Shape make_extrude(const TopoDS_Wire& wire, const SketchPlane& plane, double length, bool symmetric = false, double taper_deg = 0.0); static TopoDS_Shape make_extrude(const TopoDS_Face& face, const SketchPlane& plane, diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index d569b1726e..8985c8c7d9 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -648,11 +648,8 @@ find_package(JPEG REQUIRED) find_package(Draco REQUIRED) set(OCCT_LIBS - TKXDESTEP - TKSTEP - TKSTEP209 - TKSTEPAttr - TKSTEPBase + TKDESTEP + TKDE TKXCAF TKXSBase TKVCAF @@ -699,6 +696,22 @@ if (SLIC3R_CAD) endif () # Published for the Windows packaging step in the top-level CMakeLists.txt. set(OCCT_LIBS "${OCCT_LIBS}" CACHE INTERNAL "OCCT toolkits linked by libslic3r") +if (WIN32) + # OCCT installs RelWithDebInfo and Debug builds to bin/occti and bin/occtd, so each build + # type's DLL directory is read from the imported target, falling back to the first installed + # build, as CMake does when linking. + get_target_property(_occt_configs TKernel IMPORTED_CONFIGURATIONS) + list(GET _occt_configs 0 _occt_fallback) + foreach (_build_config IN ITEMS DEBUG RELEASE RELWITHDEBINFO MINSIZEREL) + set(_occt_config ${_occt_fallback}) + if (_build_config IN_LIST _occt_configs) + set(_occt_config ${_build_config}) + endif () + get_target_property(_occt_dll TKernel IMPORTED_LOCATION_${_occt_config}) + get_filename_component(_occt_bin "${_occt_dll}" DIRECTORY) + set(OCCT_BIN_DIR_${_build_config} "${_occt_bin}" CACHE INTERNAL "OCCT DLL directory for ${_build_config} builds") + endforeach () +endif () target_link_libraries(libslic3r PUBLIC @@ -733,6 +746,12 @@ target_link_libraries(libslic3r ) if(NOT WIN32) + # OCCT's static targets name FreeType as a bare "freetype", which the macOS linker cannot + # find; this target maps that name to FREETYPE_LIBRARIES. + if (NOT TARGET freetype) + add_library(freetype INTERFACE IMPORTED GLOBAL) + target_link_libraries(freetype INTERFACE ${FREETYPE_LIBRARIES}) + endif () # Link freetype for OCCT dependency (CAD operations need font rendering) target_link_libraries(libslic3r PRIVATE ${FREETYPE_LIBRARIES}) if (NOT APPLE) diff --git a/src/libslic3r/Format/STEP.cpp b/src/libslic3r/Format/STEP.cpp index 71eb846b6a..1a77b53373 100644 --- a/src/libslic3r/Format/STEP.cpp +++ b/src/libslic3r/Format/STEP.cpp @@ -47,7 +47,8 @@ #include "XCAFDoc_DocumentTool.hxx" #include "XCAFDoc_ShapeTool.hxx" #include "XCAFApp_Application.hxx" -#include "TDF_LabelSequence.hxx" +#include "NCollection_Sequence.hxx" +#include "TDF_Label.hxx" #include "TopoDS_Solid.hxx" #include "TopoDS_Compound.hxx" #include "TopoDS_Builder.hxx" @@ -223,9 +224,9 @@ static void getNamedSolids(const TopLoc_Location& location, std::string fullName{name}; TopLoc_Location localLocation = location * shapeTool->GetLocation(label); - TDF_LabelSequence components; + NCollection_Sequence components; if (shapeTool->GetComponents(referredLabel, components)) { - for (Standard_Integer compIndex = 1; compIndex <= components.Length(); ++compIndex) { + for (int compIndex = 1; compIndex <= components.Length(); ++compIndex) { getNamedSolids(localLocation, fullName, id, shapeTool, components.Value(compIndex), namedSolids, isSplitCompound); } } else { @@ -233,7 +234,7 @@ static void getNamedSolids(const TopLoc_Location& location, TopExp_Explorer explorer; shapeTool->GetShape(referredLabel, shape); TopAbs_ShapeEnum shape_type = shape.ShapeType(); - BRepBuilderAPI_Transform transform(shape, localLocation, Standard_True); + BRepBuilderAPI_Transform transform(shape, localLocation, true); int i = 0; switch (shape_type) { case TopAbs_COMPOUND: @@ -503,11 +504,11 @@ Step::Step_Status Step::load() if (cb_cancel) return; progress = 6; m_shape_tool = XCAFDoc_DocumentTool::ShapeTool(m_doc->Main()); - TDF_LabelSequence topLevelShapes; + NCollection_Sequence topLevelShapes; m_shape_tool->GetFreeShapes(topLevelShapes); unsigned int id{ 1 }; - Standard_Integer topShapeLength = topLevelShapes.Length() + 1; - for (Standard_Integer iLabel = 1; iLabel < topShapeLength; ++iLabel) { + int topShapeLength = topLevelShapes.Length() + 1; + for (int iLabel = 1; iLabel < topShapeLength; ++iLabel) { if (cb_cancel) return; getNamedSolids(TopLoc_Location{}, "", id, m_shape_tool, topLevelShapes.Value(iLabel), m_name_solids); } @@ -562,12 +563,12 @@ Step::Step_Status Step::mesh(Model* model, new_object->input_file = m_path.c_str(); auto task = new boost::thread(Slic3r::create_thread([&]() -> void { - TDF_LabelSequence topLevelShapes; + NCollection_Sequence topLevelShapes; m_shape_tool->GetFreeShapes(topLevelShapes); unsigned int id{ 1 }; - Standard_Integer topShapeLength = topLevelShapes.Length() + 1; + int topShapeLength = topLevelShapes.Length() + 1; - for (Standard_Integer iLabel = 1; iLabel < topShapeLength; ++iLabel) { + for (int iLabel = 1; iLabel < topShapeLength; ++iLabel) { progress = static_cast(iLabel) / (topShapeLength-1); if (cb_cancel) { return; @@ -604,10 +605,10 @@ Step::Step_Status Step::mesh(Model* model, std::vector points; points.reserve(aNbNodes); // BBS: count faces missing triangulation - Standard_Integer aNbFacesNoTri = 0; + int aNbFacesNoTri = 0; // BBS: fill temporary triangulation - Standard_Integer aNodeOffset = 0; - Standard_Integer aTriangleOffet = 0; + int aNodeOffset = 0; + int aTriangleOffet = 0; for (TopExp_Explorer anExpSF(namedSolids[i].solid, TopAbs_FACE); anExpSF.More(); anExpSF.Next()) { const TopoDS_Shape& aFace = anExpSF.Current(); TopLoc_Location aLoc; @@ -618,15 +619,15 @@ Step::Step_Status Step::mesh(Model* model, } // BBS: copy nodes gp_Trsf aTrsf = aLoc.Transformation(); - for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) { + for (int aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) { gp_Pnt aPnt = aTriangulation->Node(aNodeIter); aPnt.Transform(aTrsf); points.emplace_back(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) { + int anId[3] = {}; + for (int aTriIter = 1; aTriIter <= aTriangulation->NbTriangles(); ++aTriIter) { Poly_Triangle aTri = aTriangulation->Triangle(aTriIter); aTri.Get(anId[0], anId[1], anId[2]); diff --git a/src/libslic3r/Format/STEP.hpp b/src/libslic3r/Format/STEP.hpp index a043412469..5d18f9e88f 100644 --- a/src/libslic3r/Format/STEP.hpp +++ b/src/libslic3r/Format/STEP.hpp @@ -84,9 +84,9 @@ class StepProgressIncdicator : public Message_ProgressIndicator public: StepProgressIncdicator(std::atomic& stop_flag) : should_stop(stop_flag){} - Standard_Boolean UserBreak() override { return should_stop.load(); } + bool UserBreak() override { return should_stop.load(); } - void Show(const Message_ProgressScope&, const Standard_Boolean) override { + void Show(const Message_ProgressScope&, const bool) override { std::cout << "Progress: " << std::fixed << std::setprecision(2) << 100.0 * GetPosition() << "%" << std::endl; } private: diff --git a/src/libslic3r/Format/svg.cpp b/src/libslic3r/Format/svg.cpp index 7521afddb9..45cc5758f5 100644 --- a/src/libslic3r/Format/svg.cpp +++ b/src/libslic3r/Format/svg.cpp @@ -339,10 +339,10 @@ bool load_svg(const char *path, Model *model, std::string &message) std::vector points; points.reserve(aNbNodes); // BBS: count faces missing triangulation - Standard_Integer aNbFacesNoTri = 0; + int aNbFacesNoTri = 0; // BBS: fill temporary triangulation - Standard_Integer aNodeOffset = 0; - Standard_Integer aTriangleOffet = 0; + int aNodeOffset = 0; + int aTriangleOffet = 0; for (TopExp_Explorer anExpSF(namedSolids[i].shape, TopAbs_FACE); anExpSF.More(); anExpSF.Next()) { const TopoDS_Shape &aFace = anExpSF.Current(); TopLoc_Location aLoc; @@ -353,15 +353,15 @@ bool load_svg(const char *path, Model *model, std::string &message) } // BBS: copy nodes gp_Trsf aTrsf = aLoc.Transformation(); - for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) { + for (int aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) { gp_Pnt aPnt = aTriangulation->Node(aNodeIter); aPnt.Transform(aTrsf); points.emplace_back(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) { + int anId[3]; + for (int aTriIter = 1; aTriIter <= aTriangulation->NbTriangles(); ++aTriIter) { Poly_Triangle aTri = aTriangulation->Triangle(aTriIter); aTri.Get(anId[0], anId[1], anId[2]); diff --git a/src/libslic3r/Shape/TextShape.cpp b/src/libslic3r/Shape/TextShape.cpp index cc7a7d555d..dd7ca3f119 100644 --- a/src/libslic3r/Shape/TextShape.cpp +++ b/src/libslic3r/Shape/TextShape.cpp @@ -50,6 +50,8 @@ #include "Font_BRepTextBuilder.hxx" #include "BRepPrimAPI_MakePrism.hxx" #include "Font_FontMgr.hxx" +#include "NCollection_Sequence.hxx" +#include "TCollection_HAsciiString.hxx" #include @@ -57,7 +59,7 @@ namespace Slic3r { static std::map g_occt_fonts_maps; //map -static const std::vector fonts_suffix{ "Bold", "Medium", "Heavy", "Italic", "Oblique", "Inclined", "Light", "Thin", +static const std::vector fonts_suffix{ "Bold", "Medium", "Heavy", "Italic", "Oblique", "Inclined", "Light", "Thin", "Semibold", "ExtraBold", "ExtraBold", "Semilight", "SemiLight", "ExtraLight", "Extralight", "Ultralight", "Condensed", "Ultra", "Extra", "Expanded", "Extended", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Al Tarikh"}; @@ -73,7 +75,7 @@ std::vector init_occt_fonts() Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance(); aFontMgr->InitFontDataBase(); - TColStd_SequenceOfHAsciiString availFontNames; + NCollection_Sequence availFontNames; aFontMgr->GetAvailableFontsNames(availFontNames); stdFontNames.reserve(availFontNames.Size()); @@ -122,16 +124,14 @@ std::vector init_occt_fonts() static bool TextToBRep(const char* text, const char* font, const float theTextHeight, Font_FontAspect& theFontAspect, TopoDS_Shape& theShape, double& text_width) { - Standard_Integer anArgIt = 1; - Standard_CString aName = "text_shape"; - Standard_CString aText = text; + const char* aText = text; Font_BRepFont aFont; //TCollection_AsciiString aFontName("Courier"); TCollection_AsciiString aFontName(font); - Standard_Real aTextHeight = theTextHeight; + double aTextHeight = theTextHeight; Font_FontAspect aFontAspect = theFontAspect; - Standard_Boolean anIsCompositeCurve = Standard_False; + bool anIsCompositeCurve = false; gp_Ax3 aPenAx3(gp::XOY()); gp_Dir aNormal(0.0, 0.0, 1.0); gp_Dir aDirection(1.0, 0.0, 0.0); @@ -156,10 +156,10 @@ static bool TextToBRep(const char* text, const char* font, const float theTextHe // get the text width text_width = 0; NCollection_String coll_str = aText; - for (NCollection_Utf8Iter anIter = coll_str.Iterator(); *anIter != 0;) { - const Standard_Utf32Char aCharThis = *anIter; - const Standard_Utf32Char aCharNext = *++anIter; - double width = aFont.AdvanceX(aCharThis, aCharNext); + for (auto anIter = coll_str.Iterator(); *anIter != 0;) { + const char32_t aCharThis = *anIter; + const char32_t aCharNext = *++anIter; + double width = aFont.AdvanceX(aCharThis, aCharNext); text_width += width; } @@ -173,9 +173,9 @@ static bool Prism(const TopoDS_Shape& theBase, const float thickness, TopoDS_Sha if (theBase.IsNull()) return false; gp_Vec V(0.f, 0.f, thickness); - BRepPrimAPI_MakePrism* Prism = new BRepPrimAPI_MakePrism(theBase, V, Standard_False); + BRepPrimAPI_MakePrism prism(theBase, V, false); - theSolid = Prism->Shape(); + theSolid = prism.Shape(); return true; } @@ -205,10 +205,10 @@ static void MakeMesh(TopoDS_Shape& theSolid, TriangleMesh& theMesh) std::vector points; points.reserve(aNbNodes); //BBS: count faces missing triangulation - Standard_Integer aNbFacesNoTri = 0; + int aNbFacesNoTri = 0; //BBS: fill temporary triangulation - Standard_Integer aNodeOffset = 0; - Standard_Integer aTriangleOffet = 0; + int aNodeOffset = 0; + int aTriangleOffet = 0; for (TopExp_Explorer anExpSF(theSolid, TopAbs_FACE); anExpSF.More(); anExpSF.Next()) { const TopoDS_Shape& aFace = anExpSF.Current(); TopLoc_Location aLoc; @@ -219,21 +219,21 @@ static void MakeMesh(TopoDS_Shape& theSolid, TriangleMesh& theMesh) } //BBS: copy nodes gp_Trsf aTrsf = aLoc.Transformation(); - for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) { + for (int aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter) { gp_Pnt aPnt = aTriangulation->Node(aNodeIter); aPnt.Transform(aTrsf); points.emplace_back(Vec3f(aPnt.X(), aPnt.Y(), aPnt.Z())); } //BBS: copy triangles const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation(); - for (Standard_Integer aTriIter = 1; aTriIter <= aTriangulation->NbTriangles(); ++aTriIter) { + for (int aTriIter = 1; aTriIter <= aTriangulation->NbTriangles(); ++aTriIter) { Poly_Triangle aTri = aTriangulation->Triangle(aTriIter); - Standard_Integer anId[3]; + int anId[3]; aTri.Get(anId[0], anId[1], anId[2]); if (anOrientation == TopAbs_REVERSED) { //BBS: swap 1, 2. - Standard_Integer aTmpIdx = anId[1]; + int aTmpIdx = anId[1]; anId[1] = anId[2]; anId[2] = aTmpIdx; } diff --git a/src/slic3r/GUI/CAD/DesignPanel.cpp b/src/slic3r/GUI/CAD/DesignPanel.cpp index d61d0aa11f..3b4f9bd640 100644 --- a/src/slic3r/GUI/CAD/DesignPanel.cpp +++ b/src/slic3r/GUI/CAD/DesignPanel.cpp @@ -16,7 +16,6 @@ #include #include #include // the offer/atlas join check reports on the log -#include #include #include // offer_trace: diagnostic row dump for the offer ladder @@ -4694,7 +4693,7 @@ void DesignPanel::on_import_svg() // (parse + tessellate); running it inline froze the whole window — the compositor marked the // app unresponsive and nothing repainted. The dialog is app-modal, so the document cannot be // touched while the worker owns it. Exceptions must not escape the worker: `work` is expected -// to swallow them (OCCT throws Standard_Failure, which is not a std::exception). +// to swallow them. static void run_off_ui_thread(wxWindow* parent, const wxString& message, const std::function& work) { std::atomic done{false}; @@ -4722,10 +4721,6 @@ static void run_off_ui_thread(wxWindow* parent, const wxString& message, const s worker.join(); } -// Rebuild the document off the UI thread. Every feature op (fillet, cut, shell, boolean, ...) -// goes through recompute(), and on a heavy imported solid that is seconds of OCCT work — inline -// it freezes the window. OCCT throws Standard_Failure, which is not a std::exception and would -// terminate the process if it escaped the worker, so both are caught here. // Keep the Model's copy of the recipe in step with the document. // // This used to be written in exactly ONE place — on_commit(), as a side effect of Commit to @@ -4756,18 +4751,15 @@ void DesignPanel::sync_recipe_to_model() Slic3r::put_other_changes(); } +// Runs recompute() off the UI thread, because on a heavy imported solid it takes seconds. bool DesignPanel::recompute_guarded(const wxString& message) { bool ok = false; run_off_ui_thread(this, message, [this, &ok]() { try { ok = m_doc.recompute(); - } catch (const Standard_Failure& e) { - const char* what = e.GetMessageString(); - m_doc.error = (what != nullptr && *what != '\0') ? what : "OCCT failure"; - ok = false; } catch (const std::exception& e) { - m_doc.error = e.what(); + m_doc.error = *e.what() ? e.what() : "OCCT failure"; ok = false; } }); @@ -4792,11 +4784,8 @@ void DesignPanel::on_import_step() run_off_ui_thread(this, _L("Reading STEP…"), [&]() { try { solids = GeometryEngine::read_step_solids(path, err); - } catch (const Standard_Failure& e) { - const char* what = e.GetMessageString(); - err = (what != nullptr && *what != '\0') ? what : "OCCT failure"; } catch (const std::exception& e) { - err = e.what(); + err = *e.what() ? e.what() : "OCCT failure"; } }); if (solids.empty()) { @@ -4820,11 +4809,8 @@ void DesignPanel::on_import_step() run_off_ui_thread(this, _L("Rebuilding model…"), [&]() { try { rebuilt = m_doc.recompute(); - } catch (const Standard_Failure& e) { - const char* what = e.GetMessageString(); - m_doc.error = (what != nullptr && *what != '\0') ? what : "OCCT failure"; } catch (const std::exception& e) { - m_doc.error = e.what(); + m_doc.error = *e.what() ? e.what() : "OCCT failure"; } }); if (!rebuilt) { @@ -4901,12 +4887,8 @@ void DesignPanel::on_import_mesh() try { shape = GeometryEngine::mesh_to_brep(mesh.its, MESH_IMPORT_TOLERANCE, MESH_IMPORT_MERGE_ANGLE_DEG, stats); - } catch (const Standard_Failure& e) { // on OCCT >= 8 Standard_Failure derives from std::exception — must precede that handler - fail(_L("Mesh conversion failed: ") + wxString::FromUTF8( - e.GetMessageString() ? e.GetMessageString() : "OCCT error")); - return; } catch (const std::exception& e) { - fail(_L("Mesh conversion failed: ") + wxString::FromUTF8(e.what())); + fail(_L("Mesh conversion failed: ") + wxString::FromUTF8(*e.what() ? e.what() : "OCCT error")); return; } if (shape.IsNull()) { fail(_L("Mesh conversion produced no geometry")); return; } diff --git a/src/slic3r/GUI/CAD/McpControl.cpp b/src/slic3r/GUI/CAD/McpControl.cpp index 5ae67edbb2..9436f3d686 100644 --- a/src/slic3r/GUI/CAD/McpControl.cpp +++ b/src/slic3r/GUI/CAD/McpControl.cpp @@ -27,7 +27,7 @@ #include #include -#include // OCCT base error (not a std::exception) +#include // OCCT base error #include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/MainFrame.hpp" @@ -637,9 +637,9 @@ json slice_body(DesignPanel* panel, const json& params) : plane_name == "YZ" ? gp_Dir(1, 0, 0) : gp_Dir(0, 0, 1); gp_Pnt o(n.X() * offset, n.Y() * offset, n.Z() * offset); - BRepAlgoAPI_Section sect(shape, gp_Pln(o, n), Standard_False); - sect.ComputePCurveOn1(Standard_False); - sect.Approximation(Standard_True); + BRepAlgoAPI_Section sect(shape, gp_Pln(o, n), false); + sect.ComputePCurveOn1(false); + sect.Approximation(true); sect.Build(); if (!sect.IsDone()) throw std::runtime_error("section failed"); std::vector> segs; @@ -751,7 +751,7 @@ ShapeMetrics shape_metrics(const TopoDS_Shape& s) GProp_GProps vp; BRepGProp::VolumeProperties(s, vp); gp_Pnt c = vp.CentreOfMass(); Bnd_Box bb; BRepBndLib::Add(s, bb); - Standard_Real x0, y0, z0, x1, y1, z1; bb.Get(x0, y0, z0, x1, y1, z1); + double x0, y0, z0, x1, y1, z1; bb.Get(x0, y0, z0, x1, y1, z1); return {vp.Mass(), Vec3d(c.X(), c.Y(), c.Z()), Vec3d(x0, y0, z0), Vec3d(x1, y1, z1)}; } @@ -2095,8 +2095,8 @@ std::string handle_on_main(const std::string& method, const json& params, const if (method == "mate") return rpc_result(id, action_mate(panel, params)); if (method == "check_interference") return rpc_result(id, action_check_interference(panel, params)); return rpc_error(id, -32601, "Unknown method: " + method); - } catch (const Standard_Failure& ex) { // OCCT errors are NOT std::exception - return rpc_error(id, -32000, std::string("OCCT: ") + (ex.GetMessageString() ? ex.GetMessageString() : "failure")); + } catch (const Standard_Failure& ex) { // derives from std::exception, so it comes first + return rpc_error(id, -32000, std::string("OCCT: ") + (*ex.what() ? ex.what() : "failure")); } catch (const std::exception& ex) { return rpc_error(id, -32000, ex.what()); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 69999155af..9ad06dcdf9 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -827,7 +827,7 @@ indexed_triangle_set GLGizmoCut3D::its_make_groove_plane() float slot_mouth_outer_x = slot_neck_half_width + flap_taper_offset; // upper_x extension float slot_neck_outer_x = slot_mouth_half_width + flap_taper_offset; // lower_x extension - float slot_outer_x_max = Max(slot_neck_outer_x, slot_mouth_outer_x); // max x extension + float slot_outer_x_max = std::max(slot_neck_outer_x, slot_mouth_outer_x); // max x extension float slot_neck_inner_x = slot_neck_half_width - flap_taper_offset; // upper_x narrowing float slot_mouth_inner_x = slot_mouth_half_width - flap_taper_offset; // lower_x narrowing diff --git a/tests/data/cad_brep_occt76.brep b/tests/data/cad_brep_occt76.brep new file mode 100644 index 0000000000..fb684aa759 --- /dev/null +++ b/tests/data/cad_brep_occt76.brep @@ -0,0 +1,1288 @@ + +CASCADE Topology V3, (c) Open Cascade +Locations 0 +Curve2ds 114 +1 0 1.5707963267948966 1 0 +2 5 5 1 0 -0 1 3.5 +1 5 0 0 -1 +1 0 0 0 1 +1 5 0 0 1 +1 0 30 1 0 +1 5 0 0 1 +1 0 0 1 0 +1 5 0 0 -1 +1 30 0 0 1 +1 0 1.5707963267948966 1 0 +2 15 5 1 0 -0 1 3.5 +1 0 1.5707963267948966 1 0 +2 25 5 1 0 -0 1 3.5 +1 0 1.5707963267948966 1 0 +2 5 15 1 0 -0 1 3.5 +1 0 1.5707963267948966 1 0 +2 5 25 1 0 -0 1 3.5 +1 0 1.5707963267948966 1 0 +2 15 15 1 0 -0 1 3.5 +1 0 1.5707963267948966 1 0 +2 25 15 1 0 -0 1 3.5 +1 0 1.5707963267948966 1 0 +2 15 25 1 0 -0 1 3.5 +1 0 1.5707963267948966 1 0 +2 25 25 1 0 -0 1 3.5 +8 1.5707963267948966 3.1415926535897931 +1 6.2831853071795862 0 0 1 +8 1.5707963267948966 3.1415926535897931 +1 0 0 0 1 +1 0 3.1415926535897931 1 0 +1 0 5.5 1 0 +1 0 0 1 0 +1 0 0 1 0 +1 0 -30 1 0 +1 0 0 1 0 +1 0 0 0 -1 +1 0 0 0 1 +1 0 0 0 1 +1 0 30 1 0 +1 0 -30 1 0 +1 0 30 1 0 +1 0 0 0 1 +1 0 0 1 0 +1 0 0 1 0 +1 0 30 1 0 +1 0 0 0 -1 +1 30 0 0 1 +8 1.5707963267948966 3.1415926535897931 +1 6.2831853071795862 0 0 1 +8 1.5707963267948966 3.1415926535897931 +1 0 0 0 1 +1 0 3.1415926535897931 1 0 +1 0 5.5 1 0 +8 1.5707963267948966 3.1415926535897931 +1 6.2831853071795862 0 0 1 +8 1.5707963267948966 3.1415926535897931 +1 0 0 0 1 +1 0 3.1415926535897931 1 0 +1 0 5.5 1 0 +8 1.5707963267948966 3.1415926535897931 +1 6.2831853071795862 0 0 1 +8 1.5707963267948966 3.1415926535897931 +1 0 0 0 1 +1 0 3.1415926535897931 1 0 +1 0 5.5 1 0 +8 1.5707963267948966 3.1415926535897931 +1 6.2831853071795862 0 0 1 +8 1.5707963267948966 3.1415926535897931 +1 0 0 0 1 +1 0 3.1415926535897931 1 0 +1 0 5.5 1 0 +8 1.5707963267948966 3.1415926535897931 +1 6.2831853071795862 0 0 1 +8 1.5707963267948966 3.1415926535897931 +1 0 0 0 1 +1 0 3.1415926535897931 1 0 +1 0 5.5 1 0 +8 1.5707963267948966 3.1415926535897931 +1 6.2831853071795862 0 0 1 +8 1.5707963267948966 3.1415926535897931 +1 0 0 0 1 +1 0 3.1415926535897931 1 0 +1 0 5.5 1 0 +8 1.5707963267948966 3.1415926535897931 +1 6.2831853071795862 0 0 1 +8 1.5707963267948966 3.1415926535897931 +1 0 0 0 1 +1 0 3.1415926535897931 1 0 +1 0 5.5 1 0 +8 1.5707963267948966 3.1415926535897931 +1 6.2831853071795862 0 0 1 +8 1.5707963267948966 3.1415926535897931 +1 0 0 0 1 +1 0 3.1415926535897931 1 0 +1 0 5.5 1 0 +1 6.2831853071795862 -0 0 1 +1 0 -0 0 1 +2 5 5 1 0 -0 1 3 +1 0 1 1 0 +2 15 5 1 0 -0 1 3 +1 0 1 1 0 +2 25 5 1 0 -0 1 3 +1 0 1 1 0 +2 5 15 1 0 -0 1 3 +1 0 1 1 0 +2 5 25 1 0 -0 1 3 +1 0 1 1 0 +2 15 15 1 0 -0 1 3 +1 0 1 1 0 +2 25 15 1 0 -0 1 3 +1 0 1 1 0 +2 15 25 1 0 -0 1 3 +1 0 1 1 0 +2 25 25 1 0 -0 1 3 +1 0 1 1 0 +1 6.2831853071795862 -0 0 1 +1 0 -0 0 1 +1 6.2831853071795862 -0 0 1 +1 0 -0 0 1 +1 6.2831853071795862 -0 0 1 +1 0 -0 0 1 +1 6.2831853071795862 -0 0 1 +1 0 -0 0 1 +1 6.2831853071795862 -0 0 1 +1 0 -0 0 1 +1 6.2831853071795862 -0 0 1 +1 0 -0 0 1 +1 6.2831853071795862 -0 0 1 +1 0 -0 0 1 +1 6.2831853071795862 -0 0 1 +1 0 -0 0 1 +Curves 57 +2 5 5 5 0 0 1 1 0 -0 -0 1 0 3.5 +1 0 0 5 -0 1 0 +1 0 30 5 1 0 -0 +1 0 0 5 1 0 -0 +1 30 0 5 -0 1 0 +2 15 5 5 0 0 1 1 0 -0 -0 1 0 3.5 +2 25 5 5 0 0 1 1 0 -0 -0 1 0 3.5 +2 5 15 5 0 0 1 1 0 -0 -0 1 0 3.5 +2 5 25 5 0 0 1 1 0 -0 -0 1 0 3.5 +2 15 15 5 0 0 1 1 0 -0 -0 1 0 3.5 +2 25 15 5 0 0 1 1 0 -0 -0 1 0 3.5 +2 15 25 5 0 0 1 1 0 -0 -0 1 0 3.5 +2 25 25 5 0 0 1 1 0 -0 -0 1 0 3.5 +2 8.5 5 4.5 0 -1 0 1 0 0 -0 0 1 0.5 +2 5 5 4.5 0 0 1 1 0 -0 -0 1 0 3 +1 0 0 0 0 0 1 +1 0 30 0 0 0 1 +1 0 0 0 -0 1 0 +1 0 30 0 1 0 -0 +1 30 30 0 0 0 1 +1 0 0 0 1 0 -0 +1 30 0 0 0 0 1 +1 30 0 0 -0 1 0 +2 18.5 5 4.5 0 -1 0 1 0 0 -0 0 1 0.5 +2 15 5 4.5 0 0 1 1 0 -0 -0 1 0 3 +2 28.5 5 4.5 0 -1 0 1 0 0 -0 0 1 0.5 +2 25 5 4.5 0 0 1 1 0 -0 -0 1 0 3 +2 8.5 15 4.5 0 -1 0 1 0 0 -0 0 1 0.5 +2 5 15 4.5 0 0 1 1 0 -0 -0 1 0 3 +2 8.5 25 4.5 0 -1 0 1 0 0 -0 0 1 0.5 +2 5 25 4.5 0 0 1 1 0 -0 -0 1 0 3 +2 18.5 15 4.5 0 -1 0 1 0 0 -0 0 1 0.5 +2 15 15 4.5 0 0 1 1 0 -0 -0 1 0 3 +2 28.5 15 4.5 0 -1 0 1 0 0 -0 0 1 0.5 +2 25 15 4.5 0 0 1 1 0 -0 -0 1 0 3 +2 18.5 25 4.5 0 -1 0 1 0 0 -0 0 1 0.5 +2 15 25 4.5 0 0 1 1 0 -0 -0 1 0 3 +2 28.5 25 4.5 0 -1 0 1 0 0 -0 0 1 0.5 +2 25 25 4.5 0 0 1 1 0 -0 -0 1 0 3 +1 8 4.9999999999999991 -1 0 0 1 +2 5 5 0 0 0 1 1 0 -0 -0 1 0 3 +2 15 5 0 0 0 1 1 0 -0 -0 1 0 3 +2 25 5 0 0 0 1 1 0 -0 -0 1 0 3 +2 5 15 0 0 0 1 1 0 -0 -0 1 0 3 +2 5 25 0 0 0 1 1 0 -0 -0 1 0 3 +2 15 15 0 0 0 1 1 0 -0 -0 1 0 3 +2 25 15 0 0 0 1 1 0 -0 -0 1 0 3 +2 15 25 0 0 0 1 1 0 -0 -0 1 0 3 +2 25 25 0 0 0 1 1 0 -0 -0 1 0 3 +1 18 4.9999999999999991 -1 0 0 1 +1 28 4.9999999999999991 -1 0 0 1 +1 8 15 -1 0 0 1 +1 7.9999999999999991 24.999999999999996 -1 0 0 1 +1 18 15 -1 0 0 1 +1 28 14.999999999999998 -1 0 0 1 +1 18 25 -1 0 0 1 +1 28 25 -1 0 0 1 +Polygon3D 0 +PolygonOnTriangulations 0 +Surfaces 24 +1 0 0 5 0 0 1 1 0 -0 -0 1 0 +5 5 5 4.5 0 0 1 1 0 -0 -0 1 0 3.5 0.5 +1 0 0 0 1 0 -0 0 0 1 0 -1 0 +1 0 30 0 -0 1 0 0 0 1 1 0 -0 +1 0 0 0 -0 1 0 0 0 1 1 0 -0 +1 30 0 0 1 0 -0 0 0 1 0 -1 0 +5 15 5 4.5 0 0 1 1 0 -0 -0 1 0 3.5 0.5 +5 25 5 4.5 0 0 1 1 0 -0 -0 1 0 3.5 0.5 +5 5 15 4.5 0 0 1 1 0 -0 -0 1 0 3.5 0.5 +5 5 25 4.5 0 0 1 1 0 -0 -0 1 0 3.5 0.5 +5 15 15 4.5 0 0 1 1 0 -0 -0 1 0 3.5 0.5 +5 25 15 4.5 0 0 1 1 0 -0 -0 1 0 3.5 0.5 +5 15 25 4.5 0 0 1 1 0 -0 -0 1 0 3.5 0.5 +5 25 25 4.5 0 0 1 1 0 -0 -0 1 0 3.5 0.5 +2 5 5 -1 0 0 1 1 0 -0 -0 1 0 3 +1 0 0 0 0 0 1 1 0 -0 -0 1 0 +2 15 5 -1 0 0 1 1 0 -0 -0 1 0 3 +2 25 5 -1 0 0 1 1 0 -0 -0 1 0 3 +2 5 15 -1 0 0 1 1 0 -0 -0 1 0 3 +2 5 25 -1 0 0 1 1 0 -0 -0 1 0 3 +2 15 15 -1 0 0 1 1 0 -0 -0 1 0 3 +2 25 15 -1 0 0 1 1 0 -0 -0 1 0 3 +2 15 25 -1 0 0 1 1 0 -0 -0 1 0 3 +2 25 25 -1 0 0 1 1 0 -0 -0 1 0 3 +Triangulations 0 + +TShapes 161 +Ve +1e-07 +8.5 5 5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 1 0 0 6.28318530717959 +2 1 2 0 0 6.28318530717959 +2 2 1 0 0 6.28318530717959 +4 G1 2 0 1 0 +0 + +0101000 ++161 0 -161 0 * +Wi + +0101100 +-160 0 * +Ve +1e-07 +0 30 5 +0 0 + +0101101 +* +Ve +1e-07 +0 0 5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 2 0 0 30 +2 3 3 0 0 30 +2 4 1 0 0 30 +0 + +0101000 +-158 0 +157 0 * +Ve +1e-07 +30 30 5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 3 0 0 30 +2 5 4 0 0 30 +2 6 1 0 0 30 +0 + +0101000 +-155 0 +158 0 * +Ve +1e-07 +30 0 5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 4 0 0 30 +2 7 5 0 0 30 +2 8 1 0 0 30 +0 + +0101000 +-153 0 +157 0 * +Ed + 1e-07 1 1 0 +1 5 0 0 30 +2 9 6 0 0 30 +2 10 1 0 0 30 +0 + +0101000 +-155 0 +153 0 * +Wi + +0101100 +-156 0 -154 0 +152 0 +151 0 * +Ve +1e-07 +18.5 5 5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 6 0 0 6.28318530717959 +2 11 7 0 0 6.28318530717959 +2 12 1 0 0 6.28318530717959 +4 G1 7 0 1 0 +0 + +0101000 ++149 0 -149 0 * +Wi + +0101100 +-148 0 * +Ve +1e-07 +28.5 5 5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 7 0 0 6.28318530717959 +2 13 8 0 0 6.28318530717959 +2 14 1 0 0 6.28318530717959 +4 G1 8 0 1 0 +0 + +0101000 ++146 0 -146 0 * +Wi + +0101100 +-145 0 * +Ve +1e-07 +8.5 15 5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 8 0 0 6.28318530717959 +2 15 9 0 0 6.28318530717959 +2 16 1 0 0 6.28318530717959 +4 G1 9 0 1 0 +0 + +0101000 ++143 0 -143 0 * +Wi + +0101100 +-142 0 * +Ve +1e-07 +8.5 25 5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 9 0 0 6.28318530717959 +2 17 10 0 0 6.28318530717959 +2 18 1 0 0 6.28318530717959 +4 G1 10 0 1 0 +0 + +0101000 ++140 0 -140 0 * +Wi + +0101100 +-139 0 * +Ve +1e-07 +18.5 15 5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 10 0 0 6.28318530717959 +2 19 11 0 0 6.28318530717959 +2 20 1 0 0 6.28318530717959 +4 G1 11 0 1 0 +0 + +0101000 ++137 0 -137 0 * +Wi + +0101100 +-136 0 * +Ve +1e-07 +28.5 15 5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 11 0 0 6.28318530717959 +2 21 12 0 0 6.28318530717959 +2 22 1 0 0 6.28318530717959 +4 G1 12 0 1 0 +0 + +0101000 ++134 0 -134 0 * +Wi + +0101100 +-133 0 * +Ve +1e-07 +18.5 25 5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 12 0 0 6.28318530717959 +2 23 13 0 0 6.28318530717959 +2 24 1 0 0 6.28318530717959 +4 G1 13 0 1 0 +0 + +0101000 ++131 0 -131 0 * +Wi + +0101100 +-130 0 * +Ve +1e-07 +28.5 25 5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 13 0 0 6.28318530717959 +2 25 14 0 0 6.28318530717959 +2 26 1 0 0 6.28318530717959 +4 G1 14 0 1 0 +0 + +0101000 ++128 0 -128 0 * +Wi + +0101100 +-127 0 * +Fa +0 1e-07 1 0 + +0101000 ++159 0 +150 0 +147 0 +144 0 +141 0 +138 0 +135 0 +132 0 +129 0 +126 0 +* +Ve +1e-07 +8 5 4.5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 14 0 1.5707963267949 3.14159265358979 +3 27 28CN 2 0 1.5707963267949 3.14159265358979 +0 + +0101000 ++161 0 -124 0 * +Ed + 1e-07 1 1 0 +1 15 0 0 6.28318530717959 +2 29 2 0 0 6.28318530717959 +2 30 15 0 0 6.28318530717959 +4 G1 2 0 15 0 +0 + +0101000 ++124 0 -124 0 * +Wi + +0101100 +-123 0 +160 0 -122 0 +123 0 * +Fa +0 0 2 0 + +0101000 ++121 0 * +Ve +1e-07 +0 0 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 16 0 0 5 +2 31 3 0 0 5 +2 32 5 0 0 5 +0 + +0101000 +-157 0 +119 0 * +Ve +1e-07 +0 30 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 17 0 0 5 +2 33 3 0 0 5 +2 34 4 0 0 5 +0 + +0101000 +-158 0 +117 0 * +Ed + 1e-07 1 1 0 +1 18 0 0 30 +2 35 3 0 0 30 +2 36 16 0 0 30 +0 + +0101000 +-117 0 +119 0 * +Wi + +0101100 +-118 0 -156 0 +116 0 +115 0 * +Fa +0 1e-07 3 0 + +0111000 ++114 0 * +Ve +1e-07 +30 30 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 19 0 0 30 +2 37 4 0 0 30 +2 38 16 0 0 30 +0 + +0101000 +-112 0 +117 0 * +Ed + 1e-07 1 1 0 +1 20 0 0 5 +2 39 6 0 0 5 +2 40 4 0 0 5 +0 + +0101000 +-155 0 +112 0 * +Wi + +0101100 +-111 0 -110 0 +154 0 +116 0 * +Fa +0 1e-07 4 0 + +0111000 ++109 0 * +Ve +1e-07 +30 0 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 21 0 0 30 +2 41 5 0 0 30 +2 42 16 0 0 30 +0 + +0101000 +-107 0 +119 0 * +Ed + 1e-07 1 1 0 +1 22 0 0 5 +2 43 6 0 0 5 +2 44 5 0 0 5 +0 + +0101000 +-153 0 +107 0 * +Wi + +0101100 +-106 0 -105 0 +152 0 +118 0 * +Fa +0 1e-07 5 0 + +0111000 ++104 0 * +Ed + 1e-07 1 1 0 +1 23 0 0 30 +2 45 6 0 0 30 +2 46 16 0 0 30 +0 + +0101000 +-112 0 +107 0 * +Wi + +0101100 +-105 0 -151 0 +110 0 +102 0 * +Fa +0 1e-07 6 0 + +0111000 ++101 0 * +Ve +1e-07 +18 5 4.5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 24 0 1.5707963267949 3.14159265358979 +3 47 48CN 7 0 1.5707963267949 3.14159265358979 +0 + +0101000 ++149 0 -99 0 * +Ed + 1e-07 1 1 0 +1 25 0 0 6.28318530717959 +2 49 7 0 0 6.28318530717959 +2 50 17 0 0 6.28318530717959 +4 G1 7 0 17 0 +0 + +0101000 ++99 0 -99 0 * +Wi + +0101100 +-98 0 +148 0 -97 0 +98 0 * +Fa +0 0 7 0 + +0101000 ++96 0 * +Ve +1e-07 +28 5 4.5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 26 0 1.5707963267949 3.14159265358979 +3 51 52CN 8 0 1.5707963267949 3.14159265358979 +0 + +0101000 ++146 0 -94 0 * +Ed + 1e-07 1 1 0 +1 27 0 0 6.28318530717959 +2 53 8 0 0 6.28318530717959 +2 54 18 0 0 6.28318530717959 +4 G1 8 0 18 0 +0 + +0101000 ++94 0 -94 0 * +Wi + +0101100 +-93 0 +145 0 -92 0 +93 0 * +Fa +0 0 8 0 + +0101000 ++91 0 * +Ve +1e-07 +8 15 4.5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 28 0 1.5707963267949 3.14159265358979 +3 55 56CN 9 0 1.5707963267949 3.14159265358979 +0 + +0101000 ++143 0 -89 0 * +Ed + 1e-07 1 1 0 +1 29 0 0 6.28318530717959 +2 57 9 0 0 6.28318530717959 +2 58 19 0 0 6.28318530717959 +4 G1 9 0 19 0 +0 + +0101000 ++89 0 -89 0 * +Wi + +0101100 +-88 0 +142 0 -87 0 +88 0 * +Fa +0 0 9 0 + +0101000 ++86 0 * +Ve +1e-07 +8 25 4.5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 30 0 1.5707963267949 3.14159265358979 +3 59 60CN 10 0 1.5707963267949 3.14159265358979 +0 + +0101000 ++140 0 -84 0 * +Ed + 1e-07 1 1 0 +1 31 0 0 6.28318530717959 +2 61 10 0 0 6.28318530717959 +2 62 20 0 0 6.28318530717959 +4 G1 10 0 20 0 +0 + +0101000 ++84 0 -84 0 * +Wi + +0101100 +-83 0 +139 0 -82 0 +83 0 * +Fa +0 0 10 0 + +0101000 ++81 0 * +Ve +1e-07 +18 15 4.5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 32 0 1.5707963267949 3.14159265358979 +3 63 64CN 11 0 1.5707963267949 3.14159265358979 +0 + +0101000 ++137 0 -79 0 * +Ed + 1e-07 1 1 0 +1 33 0 0 6.28318530717959 +2 65 11 0 0 6.28318530717959 +2 66 21 0 0 6.28318530717959 +4 G1 11 0 21 0 +0 + +0101000 ++79 0 -79 0 * +Wi + +0101100 +-78 0 +136 0 -77 0 +78 0 * +Fa +0 0 11 0 + +0101000 ++76 0 * +Ve +1e-07 +28 15 4.5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 34 0 1.5707963267949 3.14159265358979 +3 67 68CN 12 0 1.5707963267949 3.14159265358979 +0 + +0101000 ++134 0 -74 0 * +Ed + 1e-07 1 1 0 +1 35 0 0 6.28318530717959 +2 69 12 0 0 6.28318530717959 +2 70 22 0 0 6.28318530717959 +4 G1 12 0 22 0 +0 + +0101000 ++74 0 -74 0 * +Wi + +0101100 +-73 0 +133 0 -72 0 +73 0 * +Fa +0 0 12 0 + +0101000 ++71 0 * +Ve +1e-07 +18 25 4.5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 36 0 1.5707963267949 3.14159265358979 +3 71 72CN 13 0 1.5707963267949 3.14159265358979 +0 + +0101000 ++131 0 -69 0 * +Ed + 1e-07 1 1 0 +1 37 0 0 6.28318530717959 +2 73 13 0 0 6.28318530717959 +2 74 23 0 0 6.28318530717959 +4 G1 13 0 23 0 +0 + +0101000 ++69 0 -69 0 * +Wi + +0101100 +-68 0 +130 0 -67 0 +68 0 * +Fa +0 0 13 0 + +0101000 ++66 0 * +Ve +1e-07 +28 25 4.5 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 38 0 1.5707963267949 3.14159265358979 +3 75 76CN 14 0 1.5707963267949 3.14159265358979 +0 + +0101000 ++128 0 -64 0 * +Ed + 1e-07 1 1 0 +1 39 0 0 6.28318530717959 +2 77 14 0 0 6.28318530717959 +2 78 24 0 0 6.28318530717959 +4 G1 14 0 24 0 +0 + +0101000 ++64 0 -64 0 * +Wi + +0101100 +-63 0 +127 0 -62 0 +63 0 * +Fa +0 0 14 0 + +0101000 ++61 0 * +Ve +1.00000000888178e-07 +8 5 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 40 0 1 5.5 +3 79 80CN 15 0 1 5.5 +0 + +0101000 +-124 0 +59 0 * +Ed + 1e-07 1 1 0 +1 41 0 0 6.28318530717959 +2 81 16 0 0 6.28318530717959 +2 82 15 0 0 6.28318530717959 +0 + +0101000 ++59 0 -59 0 * +Wi + +0101100 ++58 0 -122 0 +57 0 -58 0 * +Fa +0 1e-07 15 0 + +0101000 ++56 0 * +Wi + +0101100 +-115 0 -111 0 +106 0 +102 0 * +Wi + +0101100 +-57 0 * +Ve +1.00000000888178e-07 +18 5 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 42 0 0 6.28318530717959 +2 83 16 0 0 6.28318530717959 +2 84 17 0 0 6.28318530717959 +0 + +0101000 ++52 0 -52 0 * +Wi + +0101100 +-51 0 * +Ve +1.00000000888178e-07 +28 5 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 43 0 0 6.28318530717959 +2 85 16 0 0 6.28318530717959 +2 86 18 0 0 6.28318530717959 +0 + +0101000 ++49 0 -49 0 * +Wi + +0101100 +-48 0 * +Ve +1e-07 +8 15 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 44 0 0 6.28318530717959 +2 87 16 0 0 6.28318530717959 +2 88 19 0 0 6.28318530717959 +0 + +0101000 ++46 0 -46 0 * +Wi + +0101100 +-45 0 * +Ve +1.00000003662053e-07 +8 25 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 45 0 0 6.28318530717959 +2 89 16 0 0 6.28318530717959 +2 90 20 0 0 6.28318530717959 +0 + +0101000 ++43 0 -43 0 * +Wi + +0101100 +-42 0 * +Ve +1e-07 +18 15 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 46 0 0 6.28318530717959 +2 91 16 0 0 6.28318530717959 +2 92 21 0 0 6.28318530717959 +0 + +0101000 ++40 0 -40 0 * +Wi + +0101100 +-39 0 * +Ve +1.00000001776357e-07 +28 15 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 47 0 0 6.28318530717959 +2 93 16 0 0 6.28318530717959 +2 94 22 0 0 6.28318530717959 +0 + +0101000 ++37 0 -37 0 * +Wi + +0101100 +-36 0 * +Ve +1e-07 +18 25 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 48 0 0 6.28318530717959 +2 95 16 0 0 6.28318530717959 +2 96 23 0 0 6.28318530717959 +0 + +0101000 ++34 0 -34 0 * +Wi + +0101100 +-33 0 * +Ve +1e-07 +28 25 0 +0 0 + +0101101 +* +Ed + 1e-07 1 1 0 +1 49 0 0 6.28318530717959 +2 97 16 0 0 6.28318530717959 +2 98 24 0 0 6.28318530717959 +0 + +0101000 ++31 0 -31 0 * +Wi + +0101100 +-30 0 * +Fa +0 1e-07 16 0 + +0101000 ++54 0 +53 0 +50 0 +47 0 +44 0 +41 0 +38 0 +35 0 +32 0 +29 0 +* +Ed + 1e-07 1 1 0 +1 50 0 1 5.5 +3 99 100CN 17 0 1 5.5 +0 + +0101000 +-99 0 +52 0 * +Wi + +0101100 ++27 0 -97 0 +51 0 -27 0 * +Fa +0 1e-07 17 0 + +0101000 ++26 0 * +Ed + 1e-07 1 1 0 +1 51 0 1 5.5 +3 101 102CN 18 0 1 5.5 +0 + +0101000 +-94 0 +49 0 * +Wi + +0101100 ++24 0 -92 0 +48 0 -24 0 * +Fa +0 1e-07 18 0 + +0101000 ++23 0 * +Ed + 1e-07 1 1 0 +1 52 0 1 5.5 +3 103 104CN 19 0 1 5.5 +0 + +0101000 +-89 0 +46 0 * +Wi + +0101100 ++21 0 -87 0 +45 0 -21 0 * +Fa +0 1e-07 19 0 + +0101000 ++20 0 * +Ed + 1e-07 1 1 0 +1 53 0 1 5.5 +3 105 106CN 20 0 1 5.5 +0 + +0101000 +-84 0 +43 0 * +Wi + +0101100 ++18 0 -82 0 +42 0 -18 0 * +Fa +0 1e-07 20 0 + +0101000 ++17 0 * +Ed + 1e-07 1 1 0 +1 54 0 1 5.5 +3 107 108CN 21 0 1 5.5 +0 + +0101000 +-79 0 +40 0 * +Wi + +0101100 ++15 0 -77 0 +39 0 -15 0 * +Fa +0 1e-07 21 0 + +0101000 ++14 0 * +Ed + 1e-07 1 1 0 +1 55 0 1 5.5 +3 109 110CN 22 0 1 5.5 +0 + +0101000 +-74 0 +37 0 * +Wi + +0101100 ++12 0 -72 0 +36 0 -12 0 * +Fa +0 1e-07 22 0 + +0101000 ++11 0 * +Ed + 1e-07 1 1 0 +1 56 0 1 5.5 +3 111 112CN 23 0 1 5.5 +0 + +0101000 +-69 0 +34 0 * +Wi + +0101100 ++9 0 -67 0 +33 0 -9 0 * +Fa +0 1e-07 23 0 + +0101000 ++8 0 * +Ed + 1e-07 1 1 0 +1 57 0 1 5.5 +3 113 114CN 24 0 1 5.5 +0 + +0101000 +-64 0 +31 0 * +Wi + +0101100 ++6 0 -62 0 +30 0 -6 0 * +Fa +0 1e-07 24 0 + +0101000 ++5 0 * +Sh + +0101100 ++125 0 +120 0 -113 0 +108 0 -103 0 +100 0 +95 0 +90 0 +85 0 +80 0 ++75 0 +70 0 +65 0 +60 0 -55 0 -28 0 -25 0 -22 0 -19 0 -16 0 +-13 0 -10 0 -7 0 -4 0 * +So + +0100000 ++3 0 * +Co + +1100000 ++2 0 * + ++1 0 \ No newline at end of file diff --git a/tests/data/security_classification.step b/tests/data/security_classification.step new file mode 100644 index 0000000000..2108697d89 --- /dev/null +++ b/tests/data/security_classification.step @@ -0,0 +1,61 @@ +ISO-10303-21; +HEADER; +FILE_DESCRIPTION((''),'2;1'); +FILE_NAME('security_classification','2026-10-01T00:00:00',(''),(''),'','',''); +FILE_SCHEMA(('AUTOMOTIVE_DESIGN { 1 0 10303 214 1 1 1 1 }')); +ENDSEC; +DATA; +#1=APPLICATION_CONTEXT('automotive design'); +#2=APPLICATION_PROTOCOL_DEFINITION('international standard','automotive_design',2000,#1); +#3=PRODUCT_CONTEXT('',#1,'mechanical'); +#4=PRODUCT('tetrahedron','tetrahedron','',(#3)); +#5=PRODUCT_DEFINITION_FORMATION('','',#4); +#6=PRODUCT_DEFINITION_CONTEXT('part definition',#1,'design'); +#7=PRODUCT_DEFINITION('design','',#5,#6); +#8=PRODUCT_DEFINITION_SHAPE('','',#7); +#9=SHAPE_DEFINITION_REPRESENTATION(#8,#20); +#10=SECURITY_CLASSIFICATION_LEVEL('unclassified'); +#11=SECURITY_CLASSIFICATION('','',#10); +#12=APPLIED_SECURITY_CLASSIFICATION_ASSIGNMENT(#11,(#5)); +#13=(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT(.MILLI.,.METRE.)); +#14=(NAMED_UNIT(*)PLANE_ANGLE_UNIT()SI_UNIT($,.RADIAN.)); +#15=(NAMED_UNIT(*)SI_UNIT($,.STERADIAN.)SOLID_ANGLE_UNIT()); +#16=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.001),#13,'distance_accuracy_value',''); +#17=(GEOMETRIC_REPRESENTATION_CONTEXT(3)GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#16))GLOBAL_UNIT_ASSIGNED_CONTEXT((#13,#14,#15))REPRESENTATION_CONTEXT('','')); +#20=FACETED_BREP_SHAPE_REPRESENTATION('',(#21,#22),#17); +#21=AXIS2_PLACEMENT_3D('',#30,#40,#41); +#22=FACETED_BREP('',#23); +#23=CLOSED_SHELL('',(#50,#51,#52,#53)); +#30=CARTESIAN_POINT('',(0.,0.,0.)); +#31=CARTESIAN_POINT('',(10.,0.,0.)); +#32=CARTESIAN_POINT('',(0.,10.,0.)); +#33=CARTESIAN_POINT('',(0.,0.,10.)); +#40=DIRECTION('',(0.,0.,1.)); +#41=DIRECTION('',(1.,0.,0.)); +#42=DIRECTION('',(0.,0.,-1.)); +#43=DIRECTION('',(0.,-1.,0.)); +#44=DIRECTION('',(-1.,0.,0.)); +#45=DIRECTION('',(0.577350269189626,0.577350269189626,0.577350269189626)); +#46=DIRECTION('',(0.,0.,1.)); +#50=FACE_SURFACE('',(#60),#70,.T.); +#51=FACE_SURFACE('',(#61),#71,.T.); +#52=FACE_SURFACE('',(#62),#72,.T.); +#53=FACE_SURFACE('',(#63),#73,.T.); +#60=FACE_OUTER_BOUND('',#80,.T.); +#61=FACE_OUTER_BOUND('',#81,.T.); +#62=FACE_OUTER_BOUND('',#82,.T.); +#63=FACE_OUTER_BOUND('',#83,.T.); +#70=PLANE('',#90); +#71=PLANE('',#91); +#72=PLANE('',#92); +#73=PLANE('',#93); +#80=POLY_LOOP('',(#30,#32,#31)); +#81=POLY_LOOP('',(#30,#31,#33)); +#82=POLY_LOOP('',(#30,#33,#32)); +#83=POLY_LOOP('',(#31,#32,#33)); +#90=AXIS2_PLACEMENT_3D('',#30,#42,#41); +#91=AXIS2_PLACEMENT_3D('',#30,#43,#41); +#92=AXIS2_PLACEMENT_3D('',#30,#44,#46); +#93=AXIS2_PLACEMENT_3D('',#31,#45,$); +ENDSEC; +END-ISO-10303-21; diff --git a/tests/libslic3r/test_caddocument.cpp b/tests/libslic3r/test_caddocument.cpp index afb4acf409..744c2e9f23 100644 --- a/tests/libslic3r/test_caddocument.cpp +++ b/tests/libslic3r/test_caddocument.cpp @@ -1719,7 +1719,7 @@ TEST_CASE("split by face round-trip serialization", "[CadDocument][cut]") std::vector> bboxes; for (const auto& b : doc.bodies) { Bnd_Box bb; BRepBndLib::Add(b.shape, bb); - Standard_Real x0, y0, z0, x1, y1, z1; + double x0, y0, z0, x1, y1, z1; bb.Get(x0, y0, z0, x1, y1, z1); bboxes.push_back({Vec3d(x0, y0, z0), Vec3d(x1, y1, z1)}); } @@ -1740,7 +1740,7 @@ TEST_CASE("split by face round-trip serialization", "[CadDocument][cut]") for (size_t i = 0; i < saved_nb; ++i) { Bnd_Box bb; BRepBndLib::Add(doc2.bodies[i].shape, bb); - Standard_Real x0, y0, z0, x1, y1, z1; + double x0, y0, z0, x1, y1, z1; bb.Get(x0, y0, z0, x1, y1, z1); REQUIRE_THAT(double(x0), WithinAbs(bboxes[i].first.x(), 1e-6)); REQUIRE_THAT(double(y0), WithinAbs(bboxes[i].first.y(), 1e-6)); @@ -2205,6 +2205,34 @@ TEST_CASE("a v5 project still opens", "[CadDocument][recipe]") REQUIRE_FALSE(doc.features.empty()); } +// OCCT 7.6 wrote cad_brep_occt76.brep, so do NOT regenerate it. It holds a 30 x 30 x 5 plate +// with a 3 x 3 grid of r3 holes, their rims filleted r0.5. +TEST_CASE("an Import solid written by OCCT 7.6 still loads", "[CadDocument][recipe]") +{ + using Catch::Matchers::WithinRel; + std::ifstream ifs(std::string(TEST_DATA_DIR) + "/cad_brep_occt76.brep", std::ios::binary); + REQUIRE(ifs.is_open()); + const std::string brep((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + + const TopoDS_Shape shape = brep_from_string(brep); + REQUIRE_FALSE(shape.IsNull()); + + int faces = 0; + for (TopExp_Explorer it(shape, TopAbs_FACE); it.More(); it.Next()) + ++faces; + CHECK(faces == 6 + 9 + 9); // box, hole walls, rim fillets + + // Each rim fillet removes the corner between a quarter circle and its square, swept around the + // hole, so its volume is that area times the path of the corner's centroid (Pappus). + const double hole_r = 3.0, fillet_r = 0.5; + const double corner_area = fillet_r * fillet_r * (1 - M_PI / 4); + const double corner_centroid = hole_r + fillet_r * (10 - 3 * M_PI) / (3 * (4 - M_PI)); + const double expected = 30.0 * 30.0 * 5.0 - 9 * M_PI * hole_r * hole_r * 5.0 - 9 * corner_area * 2 * M_PI * corner_centroid; + GProp_GProps props; + BRepGProp::VolumeProperties(shape, props); + CHECK_THAT(props.Mass(), WithinRel(expected, 1e-4)); +} + TEST_CASE("a v5 round trip is exact", "[CadDocument][recipe]") { using Catch::Matchers::WithinRel; @@ -3437,7 +3465,7 @@ TEST_CASE("thicken flip offsets against face normal", "[CadDocument]") doc2.add_thicken(0, tf2, 3.0, false, "PlateFwd"); REQUIRE(doc2.recompute()); Bnd_Box bb_fwd; BRepBndLib::Add(doc2.bodies[1].shape, bb_fwd); - Standard_Real x0, y0, z0, x1, y1, z1; + double x0, y0, z0, x1, y1, z1; bb_fwd.Get(x0, y0, z0, x1, y1, z1); // flipped: plate grows below the face plane (z < 10) @@ -3456,7 +3484,7 @@ TEST_CASE("thicken flip offsets against face normal", "[CadDocument]") doc3.add_thicken(0, tf3, 3.0, true, "PlateRev"); REQUIRE(doc3.recompute()); Bnd_Box bb_rev; BRepBndLib::Add(doc3.bodies[1].shape, bb_rev); - Standard_Real rx0, ry0, rz0, rx1, ry1, rz1; + double rx0, ry0, rz0, rx1, ry1, rz1; bb_rev.Get(rx0, ry0, rz0, rx1, ry1, rz1); // forward plate bbox z > 10 (source face at z=10, +3 offset = z in (10,13)) @@ -3564,7 +3592,7 @@ TEST_CASE("thicken round-trip serialization", "[CadDocument]") std::vector> bboxes; for (const auto& b : doc.bodies) { Bnd_Box bb; BRepBndLib::Add(b.shape, bb); - Standard_Real x0, y0, z0, x1, y1, z1; + double x0, y0, z0, x1, y1, z1; bb.Get(x0, y0, z0, x1, y1, z1); bboxes.push_back({Vec3d(x0, y0, z0), Vec3d(x1, y1, z1)}); } @@ -3584,7 +3612,7 @@ TEST_CASE("thicken round-trip serialization", "[CadDocument]") for (size_t i = 0; i < nb; ++i) { Bnd_Box bb; BRepBndLib::Add(doc2.bodies[i].shape, bb); - Standard_Real x0, y0, z0, x1, y1, z1; + double x0, y0, z0, x1, y1, z1; bb.Get(x0, y0, z0, x1, y1, z1); REQUIRE_THAT(double(x0), WithinAbs(bboxes[i].first.x(), 1e-6)); REQUIRE_THAT(double(y0), WithinAbs(bboxes[i].first.y(), 1e-6)); @@ -3750,7 +3778,7 @@ TEST_CASE("project round-trip serialization", "[CadDocument][project]") std::vector> bboxes; for (const auto& b : doc.bodies) { Bnd_Box bb; BRepBndLib::Add(b.shape, bb); - Standard_Real x0, y0, z0, x1, y1, z1; + double x0, y0, z0, x1, y1, z1; bb.Get(x0, y0, z0, x1, y1, z1); bboxes.push_back({Vec3d(x0, y0, z0), Vec3d(x1, y1, z1)}); } @@ -3770,7 +3798,7 @@ TEST_CASE("project round-trip serialization", "[CadDocument][project]") for (size_t i = 0; i < saved_nb; ++i) { Bnd_Box bb; BRepBndLib::Add(doc2.bodies[i].shape, bb); - Standard_Real x0, y0, z0, x1, y1, z1; + double x0, y0, z0, x1, y1, z1; bb.Get(x0, y0, z0, x1, y1, z1); REQUIRE_THAT(double(x0), WithinAbs(bboxes[i].first.x(), 1e-6)); REQUIRE_THAT(double(y0), WithinAbs(bboxes[i].first.y(), 1e-6)); @@ -4839,7 +4867,7 @@ TEST_CASE("delete_face round-trip serialization", "[CadDocument][deleteface]") std::vector> bboxes; for (const auto& b : doc.bodies) { Bnd_Box bb; BRepBndLib::Add(b.shape, bb); - Standard_Real x0, y0, z0, x1, y1, z1; + double x0, y0, z0, x1, y1, z1; bb.Get(x0, y0, z0, x1, y1, z1); bboxes.push_back({Vec3d(x0, y0, z0), Vec3d(x1, y1, z1)}); } @@ -4856,7 +4884,7 @@ TEST_CASE("delete_face round-trip serialization", "[CadDocument][deleteface]") for (size_t i = 0; i < bboxes.size(); ++i) { Bnd_Box bb; BRepBndLib::Add(doc2.bodies[i].shape, bb); - Standard_Real x0, y0, z0, x1, y1, z1; + double x0, y0, z0, x1, y1, z1; bb.Get(x0, y0, z0, x1, y1, z1); REQUIRE_THAT(double(x0), WithinAbs(bboxes[i].first.x(), 1e-6)); REQUIRE_THAT(double(y0), WithinAbs(bboxes[i].first.y(), 1e-6)); @@ -4961,7 +4989,7 @@ TEST_CASE("hole: round-trip preserves styled counterbore hole", "[CadDocument][h std::vector> bboxes; for (const auto& b : doc.bodies) { Bnd_Box bb; BRepBndLib::Add(b.shape, bb); - Standard_Real x0, y0, z0, x1, y1, z1; + double x0, y0, z0, x1, y1, z1; bb.Get(x0, y0, z0, x1, y1, z1); bboxes.emplace_back(Vec3d(x0, y0, z0), Vec3d(x1, y1, z1)); } @@ -4976,7 +5004,7 @@ TEST_CASE("hole: round-trip preserves styled counterbore hole", "[CadDocument][h for (size_t i = 0; i < bboxes.size(); ++i) { Bnd_Box bb; BRepBndLib::Add(doc2.bodies[i].shape, bb); - Standard_Real x0, y0, z0, x1, y1, z1; + double x0, y0, z0, x1, y1, z1; bb.Get(x0, y0, z0, x1, y1, z1); REQUIRE_THAT(double(x0), WithinAbs(bboxes[i].first.x(), 1e-6)); REQUIRE_THAT(double(y0), WithinAbs(bboxes[i].first.y(), 1e-6)); @@ -5280,9 +5308,9 @@ TEST_CASE("surface round-trip serialize/deserialize", "[CadDocument][surface]") Bnd_Box fresh_bb; BRepBndLib::Add(fresh.bodies.back().shape, fresh_bb); - Standard_Real ox0, oy0, oz0, ox1, oy1, oz1; + double ox0, oy0, oz0, ox1, oy1, oz1; orig_bb.Get(ox0, oy0, oz0, ox1, oy1, oz1); - Standard_Real fx0, fy0, fz0, fx1, fy1, fz1; + double fx0, fy0, fz0, fx1, fy1, fz1; fresh_bb.Get(fx0, fy0, fz0, fx1, fy1, fz1); REQUIRE_THAT(double(fx0), WithinAbs(double(ox0), 1e-6)); REQUIRE_THAT(double(fy0), WithinAbs(double(oy0), 1e-6)); @@ -5321,8 +5349,8 @@ TEST_CASE("thicken-surface makes a solid from a sheet", "[CadDocument][surface]" Bnd_Box thick_bb; BRepBndLib::Add(doc.bodies.back().shape, thick_bb); - Standard_Real sx0, sy0, sz0, sx1, sy1, sz1; - Standard_Real tx0, ty0, tz0, tx1, ty1, tz1; + double sx0, sy0, sz0, sx1, sy1, sz1; + double tx0, ty0, tz0, tx1, ty1, tz1; sheet_bb.Get(sx0, sy0, sz0, sx1, sy1, sz1); thick_bb.Get(tx0, ty0, tz0, tx1, ty1, tz1); REQUIRE_THAT(double(tx0), WithinAbs(double(sx0), 2.1)); @@ -5439,8 +5467,8 @@ TEST_CASE("surface-offset creates another sheet shifted outward", "[CadDocument] Bnd_Box off_bb; BRepBndLib::Add(doc.bodies.back().shape, off_bb); - Standard_Real sx0, sy0, sz0, sx1, sy1, sz1; - Standard_Real ox0, oy0, oz0, ox1, oy1, oz1; + double sx0, sy0, sz0, sx1, sy1, sz1; + double ox0, oy0, oz0, ox1, oy1, oz1; src_bb.Get(sx0, sy0, sz0, sx1, sy1, sz1); off_bb.Get(ox0, oy0, oz0, ox1, oy1, oz1); REQUIRE(std::abs(double(ox0) - double(sx0)) > 1e-3); @@ -5493,8 +5521,8 @@ TEST_CASE("thicken-surface round-trip serialize/deserialize", "[CadDocument][sur Bnd_Box fresh_bb; BRepBndLib::Add(fresh.bodies.back().shape, fresh_bb); - Standard_Real ox0, oy0, oz0, ox1, oy1, oz1; - Standard_Real fx0, fy0, fz0, fx1, fy1, fz1; + double ox0, oy0, oz0, ox1, oy1, oz1; + double fx0, fy0, fz0, fx1, fy1, fz1; orig_bb.Get(ox0, oy0, oz0, ox1, oy1, oz1); fresh_bb.Get(fx0, fy0, fz0, fx1, fy1, fz1); REQUIRE_THAT(double(fx0), WithinAbs(double(ox0), 1e-6)); @@ -5615,8 +5643,8 @@ TEST_CASE("surface-loft round-trip serialize/deserialize", "[CadDocument][surfac Bnd_Box fresh_bb; BRepBndLib::Add(fresh.bodies.back().shape, fresh_bb); - Standard_Real ox0, oy0, oz0, ox1, oy1, oz1; - Standard_Real fx0, fy0, fz0, fx1, fy1, fz1; + double ox0, oy0, oz0, ox1, oy1, oz1; + double fx0, fy0, fz0, fx1, fy1, fz1; orig_bb.Get(ox0, oy0, oz0, ox1, oy1, oz1); fresh_bb.Get(fx0, fy0, fz0, fx1, fy1, fz1); REQUIRE_THAT(double(fx0), WithinAbs(double(ox0), 1e-6)); @@ -8312,6 +8340,70 @@ TEST_CASE("A sketch-only document recomputes and round-trips", "[CadDocument]") REQUIRE_FALSE(bad.error.empty()); } +TEST_CASE("A zero-depth extrude is an error on every path", "[CadDocument]") +{ + CadDocument doc; + const int sk = doc.add_sketch(SketchShape::Rectangle, SketchPlane::XY(), 20, 20, 0, "Rect"); + REQUIRE(sk == 0); + + // nz = 1 picks the box's +z face, nz = -1 its -z face. + auto add_box_and_find_face = [&](double nz) { + doc.add_extrude(sk, 10.0, false, BooleanMode::New, "Box"); + REQUIRE(doc.recompute()); + const TopoDS_Shape& box = doc.bodies[0].shape; + for (int i = 0; i < GeometryEngine::face_count(box); ++i) + if (GeometryEngine::face_normal_world(GeometryEngine::face_by_index(box, i)).z() * nz > 0.9) + return i; + return -1; + }; + + SECTION("blind") { doc.add_extrude(sk, 0.0, false, BooleanMode::New, "ZeroDepth"); } + SECTION("tapered") + { + doc.add_extrude(sk, 0.0, false, BooleanMode::New, "ZeroDepth"); + doc.features.back().taper_deg = 8.0; + } + SECTION("symmetric") { doc.add_extrude(sk, 0.0, true, BooleanMode::New, "ZeroDepth"); } + SECTION("two-sided") + { + doc.add_extrude(sk, 0.0, false, BooleanMode::New, "ZeroDepth"); + doc.features.back().extrude_end = ExtrudeEnd::TwoSided; + } + SECTION("up to a vertex in the sketch plane") + { + doc.add_extrude(sk, 10.0, false, BooleanMode::New, "ZeroDepth"); + doc.features.back().extrude_end = ExtrudeEnd::UpToVertex; + doc.features.back().up_to_point = Vec3d(5, 5, 0); + } + SECTION("up to a face in the sketch plane") + { + const int bottom = add_box_and_find_face(-1.0); + REQUIRE(bottom >= 0); + doc.add_extrude(sk, 10.0, false, BooleanMode::Add, "ZeroDepth"); + doc.features.back().extrude_end = ExtrudeEnd::UpToFace; + doc.features.back().up_to_face = bottom; + } + SECTION("from a body face") + { + const int top = add_box_and_find_face(1.0); + REQUIRE(top >= 0); + doc.add_extrude_face(top, 0.0, false, BooleanMode::Add, "ZeroDepth"); + } + SECTION("imported text or SVG regions") + { + CadFeature art; + art.type = CadFeatureType::Sketch; + art.plane = SketchPlane::XY(); + art.imported_regions = {{ {Vec2d(0, 0), Vec2d(10, 0), Vec2d(10, 10), Vec2d(0, 10)} }}; + doc.features.push_back(art); + doc.add_extrude(int(doc.features.size()) - 1, 0.0, false, BooleanMode::New, "ZeroDepth"); + } + SECTION("surface") { doc.add_surface_extrude(sk, 0.0, "ZeroDepth"); } + + REQUIRE_FALSE(doc.recompute()); + CHECK_CONTAINS(doc.error, "zero"); +} + // A body is NOT the feature that created it. Reported 2026-08-23, in these words: "you have // renamed the feature extrusion, not the body ... this means that you consider the extrusion = // the body, which is very far from truth as a body can contain several extrusions." The rename diff --git a/tests/libslic3r/test_step.cpp b/tests/libslic3r/test_step.cpp index 3635c977dd..0bb83f5809 100644 --- a/tests/libslic3r/test_step.cpp +++ b/tests/libslic3r/test_step.cpp @@ -57,6 +57,22 @@ TEST_CASE("Part names with multi-byte UTF-8 survive import", "[Step]") CHECK(object->volumes[2]->name == "bracket"); } +TEST_CASE("A security classification assignment does not crash import", "[Step]") +{ + const std::string path = std::string(TEST_DATA_DIR) + PATH_SEPARATOR "security_classification.step"; + + Model model; + bool cancel = false; + Step step(path); + + REQUIRE(step.load() == Step::Step_Status::LOAD_SUCCESS); + REQUIRE(step.mesh(&model, cancel, false) == Step::Step_Status::MESH_SUCCESS); + + REQUIRE(model.objects.size() == 1); + REQUIRE(model.objects.front()->volumes.size() == 1); + CHECK(model.objects.front()->volumes.front()->mesh().facets_count() == 4); // a tetrahedron +} + TEST_CASE("isUtf8 recognises two, three and four byte sequences", "[Step]") { CHECK(StepPreProcessor::isUtf8("\xC3\xA9")); // U+00E9