mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-05 06:41:10 +00:00
build: update OCCT to 8.0.1 (faster STEP and Design tab, Windows STEP crash fix) (#16089)
This commit is contained in:
@@ -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
|
||||
|
||||
+2
-1
@@ -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 "")
|
||||
|
||||
Vendored
-264
@@ -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: <prefix>/inc for windows,
|
||||
+# OCCT headers: <prefix>/include for windows,
|
||||
# <prefix>/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 <binary dir>/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 $<TARGET_PDB_FILE:${PROJECT_NAME}>
|
||||
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 <dpasukhi@opencascade.com>
|
||||
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;
|
||||
Vendored
+18
-18
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -37,10 +37,9 @@
|
||||
#include <cstdint>
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <TopTools_ListOfShape.hxx>
|
||||
#include <NCollection_List.hxx>
|
||||
#include <BRepPrimAPI_MakeCylinder.hxx>
|
||||
#include <BRepPrimAPI_MakeCone.hxx>
|
||||
#include <BRepPrimAPI_MakePrism.hxx>
|
||||
#include <BRepPrimAPI_MakeRevol.hxx>
|
||||
#include <BRepCheck_Analyzer.hxx>
|
||||
#include <BRepLib.hxx>
|
||||
@@ -53,7 +52,7 @@
|
||||
#include <Geom_ConicalSurface.hxx>
|
||||
#include <Geom2d_TrimmedCurve.hxx>
|
||||
#include <GeomAbs_Shape.hxx> // SurfaceFill: GeomAbs_C0
|
||||
#include <GCE2d_MakeSegment.hxx>
|
||||
#include <GC_MakeSegment2d.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopAbs.hxx>
|
||||
@@ -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<TopoDS_Shape> 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<CadBody>& 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<TopoDS_Shape> 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<CadBody>& 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<TopoDS_Shape> 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<CadBody>& 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<TopoDS_Shape>::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<CadBody> 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::Interference> 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();
|
||||
|
||||
@@ -27,9 +27,10 @@
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopTools.hxx>
|
||||
#include <TopTools_IndexedMapOfShape.hxx>
|
||||
#include <TopTools_ListOfShape.hxx>
|
||||
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
|
||||
#include <TopTools_ShapeMapHasher.hxx>
|
||||
#include <NCollection_IndexedDataMap.hxx>
|
||||
#include <NCollection_IndexedMap.hxx>
|
||||
#include <NCollection_List.hxx>
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
@@ -62,6 +63,8 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
using ShapeIndexMap = NCollection_IndexedMap<TopoDS_Shape, TopTools_ShapeMapHasher>;
|
||||
|
||||
// ---- STEP import (B-rep, not mesh) ----
|
||||
std::vector<TopoDS_Shape> GeometryEngine::read_step_solids(const std::string& path, std::string& err)
|
||||
{
|
||||
@@ -82,7 +85,7 @@ std::vector<TopoDS_Shape> 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<TopoDS_Edge> GeometryEngine::collect_edges(const TopoDS_Shape& solid
|
||||
}
|
||||
|
||||
// Build edge-to-face map once
|
||||
TopTools_IndexedDataMapOfShapeListOfShape edgeFaceMap;
|
||||
NCollection_IndexedDataMap<TopoDS_Shape, NCollection_List<TopoDS_Shape>, 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<TopoDS_Shape>& faces = edgeFaceMap.FindFromKey(edge);
|
||||
|
||||
bool include = false;
|
||||
for (auto it = faces.begin(); it != faces.end(); ++it) {
|
||||
@@ -569,7 +572,7 @@ std::vector<TopoDS_Face> GeometryEngine::faces_of(const TopoDS_Shape& shape)
|
||||
|
||||
std::vector<TopoDS_Edge> 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<TopoDS_Edge> out;
|
||||
out.reserve(map.Extent());
|
||||
@@ -581,7 +584,7 @@ std::vector<TopoDS_Edge> GeometryEngine::edges_of(const TopoDS_Shape& shape)
|
||||
std::vector<TopoDS_Edge> GeometryEngine::edges_of_face(const TopoDS_Face& face)
|
||||
{
|
||||
std::vector<TopoDS_Edge> 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;
|
||||
|
||||
@@ -27,9 +27,7 @@
|
||||
#include <GC_MakeArcOfEllipse.hxx>
|
||||
#include <Geom_TrimmedCurve.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <TColgp_Array1OfPnt.hxx>
|
||||
#include <TColStd_Array1OfReal.hxx>
|
||||
#include <TColStd_Array1OfInteger.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <gp_Circ.hxx>
|
||||
#include <gp_Elips.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
@@ -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<std::vector<std::vector<Vec2d>>>& 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<TopoDS_Wire>& 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<TopoDS_Wire>& 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<TopoDS_Wire> SketchEngine::entities_to_wires(const std::vector<Sketc
|
||||
const int n = int(c.ctrl.size());
|
||||
const int p = n >= 4 ? 3 : (n >= 2 ? n - 1 : 0);
|
||||
if (p < 1) return Handle(Geom_BSplineCurve)();
|
||||
TColgp_Array1OfPnt poles(1, n);
|
||||
NCollection_Array1<gp_Pnt> 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<double> knots(1, nknots);
|
||||
NCollection_Array1<int> 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<TopoDS_Wire> SketchEngine::entities_to_wires(const std::vector<Sketc
|
||||
wm.Add(BRepBuilderAPI_MakeEdge(va, vb).Edge());
|
||||
} else if (e->type == 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) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Ax3.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<TDF_Label> 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<TDF_Label> 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<TDF_Label> 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<double>(iLabel) / (topShapeLength-1);
|
||||
if (cb_cancel) {
|
||||
return;
|
||||
@@ -604,10 +605,10 @@ Step::Step_Status Step::mesh(Model* model,
|
||||
std::vector<Vec3f> 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]);
|
||||
|
||||
@@ -84,9 +84,9 @@ class StepProgressIncdicator : public Message_ProgressIndicator
|
||||
public:
|
||||
StepProgressIncdicator(std::atomic<bool>& 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:
|
||||
|
||||
@@ -339,10 +339,10 @@ bool load_svg(const char *path, Model *model, std::string &message)
|
||||
std::vector<Vec3f> 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]);
|
||||
|
||||
@@ -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 <boost/log/trivial.hpp>
|
||||
|
||||
@@ -57,7 +59,7 @@ namespace Slic3r {
|
||||
|
||||
static std::map<std::string, std::string> g_occt_fonts_maps; //map<font_name, font_path>
|
||||
|
||||
static const std::vector<Standard_CString> fonts_suffix{ "Bold", "Medium", "Heavy", "Italic", "Oblique", "Inclined", "Light", "Thin",
|
||||
static const std::vector<const char*> 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<std::string> init_occt_fonts()
|
||||
Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
|
||||
aFontMgr->InitFontDataBase();
|
||||
|
||||
TColStd_SequenceOfHAsciiString availFontNames;
|
||||
NCollection_Sequence<Handle(TCollection_HAsciiString)> availFontNames;
|
||||
aFontMgr->GetAvailableFontsNames(availFontNames);
|
||||
stdFontNames.reserve(availFontNames.Size());
|
||||
|
||||
@@ -122,16 +124,14 @@ std::vector<std::string> 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<Vec3f> 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;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/log/trivial.hpp> // the offer/atlas join check reports on the log
|
||||
#include <Standard_Failure.hxx>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdarg> // 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<void()>& work)
|
||||
{
|
||||
std::atomic<bool> 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; }
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <Standard_Failure.hxx> // OCCT base error (not a std::exception)
|
||||
#include <Standard_Failure.hxx> // 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<std::vector<Vec3d>> 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());
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
@@ -1719,7 +1719,7 @@ TEST_CASE("split by face round-trip serialization", "[CadDocument][cut]")
|
||||
std::vector<std::pair<Vec3d, Vec3d>> 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<char>(ifs)), std::istreambuf_iterator<char>());
|
||||
|
||||
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<std::pair<Vec3d, Vec3d>> 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<std::pair<Vec3d, Vec3d>> 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<std::pair<Vec3d, Vec3d>> 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<std::pair<Vec3d, Vec3d>> 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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user