1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

Compare commits

..

2 Commits

Author SHA1 Message Date
agv
a16fd3862a 0028569: Improve the performance of 2d classifier (CSLib_Class2d)
Previous implementation of this algorithm used plain iteration through a given array of points therefore the complexity was O(n). The performance is significatly improved by storing sqrt(n) bounding boxes each containing sqrt(n) points; the expected complexity is now O(sqrt(n)).
2017-07-30 14:50:54 +03:00
agv
f58535d13c 0028569: Improve the performance of 2d classifier (CSLib_Class2d)
changes: CSLib_Class2d (header and source file)
2017-07-30 14:50:52 +03:00
81 changed files with 2934 additions and 2648 deletions

View File

@@ -561,27 +561,6 @@ else()
OCCT_CHECK_AND_UNSET ("INSTALL_FREEIMAGE")
endif()
# FFmpeg
# search for CSF_FFmpeg variable in EXTERNLIB of each being used toolkit
OCCT_IS_PRODUCT_REQUIRED (CSF_FFmpeg CAN_USE_FFMPEG)
if (CAN_USE_FFMPEG)
set (USE_FFMPEG OFF CACHE BOOL "${USE_FFMPEG_DESCR}")
if (USE_FFMPEG)
add_definitions (-DHAVE_FFMPEG)
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/ffmpeg")
else()
OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_FFMPEG")
OCCT_CHECK_AND_UNSET ("INSTALL_FFMPEG")
endif()
else()
OCCT_CHECK_AND_UNSET ("USE_FFMPEG")
OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_FFMPEG")
OCCT_CHECK_AND_UNSET ("INSTALL_FFMPEG")
endif()
# OpenGL ES 2.0
if (WIN32 AND CAN_USE_GLES2)
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsStore")

View File

@@ -347,6 +347,8 @@ n StepToGeom
n StepToTopoDS
n StepVisual
n StlAPI
n StlMesh
n StlTransfer
n TopoDSToStep
n Transfer
n TransferBRep

View File

@@ -1,228 +0,0 @@
# FFmpeg
if (NOT DEFINED INSTALL_FFMPEG)
set (INSTALL_FFMPEG OFF CACHE BOOL "${INSTALL_FFMPEG_DESCR}")
endif()
if (NOT DEFINED 3RDPARTY_FFMPEG_DIR)
set (3RDPARTY_FFMPEG_DIR "" CACHE PATH "The directory containing FFmpeg")
endif()
# include occt macros. compiler_bitness, os_wiht_bit, compiler
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/occt_macros")
# specify FFMPEG folder in connection with 3RDPARTY_DIR
if (3RDPARTY_DIR AND EXISTS "${3RDPARTY_DIR}")
if (NOT 3RDPARTY_FFMPEG_DIR OR NOT EXISTS "${3RDPARTY_FFMPEG_DIR}")
FIND_PRODUCT_DIR ("${3RDPARTY_DIR}" FFMPEG FFMPEG_DIR_NAME)
if (FFMPEG_DIR_NAME)
set (3RDPARTY_FFMPEG_DIR "${3RDPARTY_DIR}/${FFMPEG_DIR_NAME}" CACHE PATH "The directory containing FFmpeg" FORCE)
endif()
endif()
else()
endif()
# define required FFMPEG variables
if (NOT DEFINED 3RDPARTY_FFMPEG_INCLUDE_DIR)
set (3RDPARTY_FFMPEG_INCLUDE_DIR "" CACHE PATH "the path of headers directory")
endif()
if (NOT DEFINED 3RDPARTY_FFMPEG_LIBRARY OR NOT 3RDPARTY_FFMPEG_LIBRARY_DIR OR NOT EXISTS "${3RDPARTY_FFMPEG_LIBRARY_DIR}")
set (3RDPARTY_FFMPEG_LIBRARY "" CACHE FILEPATH "FFmpeg framework" FORCE)
endif()
if (NOT DEFINED 3RDPARTY_FFMPEG_LIBRARY_DIR)
set (3RDPARTY_FFMPEG_LIBRARY_DIR "" CACHE PATH "The directory containing FFmpeg framework")
endif()
if (WIN32)
if (NOT DEFINED 3RDPARTY_FFMPEG_DLL OR NOT 3RDPARTY_FFMPEG_DLL_DIR OR NOT EXISTS "${3RDPARTY_FFMPEG_DLL_DIR}")
set (3RDPARTY_FFMPEG_DLL "" CACHE FILEPATH "FFmpeg shared libraries" FORCE)
endif()
endif()
if (WIN32)
if (NOT DEFINED 3RDPARTY_FFMPEG_DLL_DIR)
set (3RDPARTY_FFMPEG_DLL_DIR "" CACHE PATH "The directory containing FFmpeg shared libraries")
endif()
endif()
# check 3RDPARTY_${PRODUCT_NAME}_ paths for consistency with specified 3RDPARTY_${PRODUCT_NAME}_DIR
if (3RDPARTY_FFMPEG_DIR AND EXISTS "${3RDPARTY_FFMPEG_DIR}")
CHECK_PATH_FOR_CONSISTENCY (3RDPARTY_FFMPEG_DIR 3RDPARTY_FFMPEG_INCLUDE_DIR PATH "the path to FFmpeg")
CHECK_PATH_FOR_CONSISTENCY (3RDPARTY_FFMPEG_DIR 3RDPARTY_FFMPEG_LIBRARY FILEPATH "the path to FFmpeg framework")
if (3RDPARTY_FFMPEG_LIBRARY AND EXISTS "${3RDPARTY_FFMPEG_LIBRARY}")
get_filename_component (3RDPARTY_FFMPEG_LIBRARY_DIR "${3RDPARTY_FFMPEG_LIBRARY}" PATH)
set (3RDPARTY_FFMPEG_LIBRARY_DIR "${3RDPARTY_FFMPEG_LIBRARY_DIR}" CACHE PATH "The directory containing FFmpeg libraries" FORCE)
else()
CHECK_PATH_FOR_CONSISTENCY (3RDPARTY_FFMPEG_DIR 3RDPARTY_FFMPEG_LIBRARY_DIR PATH "The directory containing FFmpeg libraries")
endif()
if (WIN32)
CHECK_PATH_FOR_CONSISTENCY (3RDPARTY_FFMPEG_DIR 3RDPARTY_FFMPEG_DLL FILEPATH "the path to FFmpeg shared libraries")
if (3RDPARTY_FFMPEG_DLL AND EXISTS "${3RDPARTY_FFMPEG_DLL}")
get_filename_component (3RDPARTY_FFMPEG_DLL_DIR "${3RDPARTY_FFMPEG_DLL}" PATH)
set (3RDPARTY_FFMPEG_DLL_DIR "${3RDPARTY_FFMPEG_DLL_DIR}" CACHE PATH "The directory containing FFmpeg shared libraries" FORCE)
else()
CHECK_PATH_FOR_CONSISTENCY (3RDPARTY_FFMPEG_DIR 3RDPARTY_FFMPEG_DLL_DIR PATH "The directory containing FFmpeg shared libraries")
endif()
endif()
endif()
# header
if (NOT 3RDPARTY_FFMPEG_INCLUDE_DIR OR NOT EXISTS "${3RDPARTY_FFMPEG_INCLUDE_DIR}")
set (HEADER_NAMES avutil.h libavutil/avutil.h)
# set 3RDPARTY_FFMPEG_INCLUDE_DIR as notfound, otherwise find_library can't assign a new value to 3RDPARTY_FFMPEG_INCLUDE_DIR
set (3RDPARTY_FFMPEG_INCLUDE_DIR "3RDPARTY_FFMPEG_INCLUDE_DIR-NOTFOUND" CACHE FILEPATH "the path to header directory" FORCE)
if (3RDPARTY_FFMPEG_DIR AND EXISTS "${3RDPARTY_FFMPEG_DIR}")
find_path (3RDPARTY_FFMPEG_INCLUDE_DIR NAMES ${HEADER_NAMES}
PATHS ${3RDPARTY_FFMPEG_DIR}
PATH_SUFFIXES include
CMAKE_FIND_ROOT_PATH_BOTH
NO_DEFAULT_PATH)
else()
find_path (3RDPARTY_FFMPEG_INCLUDE_DIR NAMES ${HEADER_NAMES}
PATH_SUFFIXES include
CMAKE_FIND_ROOT_PATH_BOTH)
endif()
endif()
if (3RDPARTY_FFMPEG_INCLUDE_DIR AND EXISTS "${3RDPARTY_FFMPEG_INCLUDE_DIR}")
list (APPEND 3RDPARTY_INCLUDE_DIRS "${3RDPARTY_FFMPEG_INCLUDE_DIR}")
else()
list (APPEND 3RDPARTY_NOT_INCLUDED 3RDPARTY_FFMPEG_INCLUDE_DIR)
set (3RDPARTY_FFMPEG_INCLUDE_DIR "" CACHE FILEPATH "the path to avutil.h" FORCE)
endif()
# library
if (NOT 3RDPARTY_FFMPEG_LIBRARY OR NOT EXISTS "${3RDPARTY_FFMPEG_LIBRARY}")
set (CMAKE_FIND_LIBRARY_SUFFIXES .lib .so .dylib .a)
set (FFMPEG_PATH_SUFFIXES lib)
if (ANDROID)
set (FFMPEG_PATH_SUFFIXES ${FFMPEG_PATH_SUFFIXES} libs/${ANDROID_ABI})
elseif(APPLE)
set (FFMPEG_PATH_SUFFIXES ${FFMPEG_PATH_SUFFIXES} Frameworks)
endif()
# set 3RDPARTY_FFMPEG_LIBRARY as notfound, otherwise find_library can't assign a new value to 3RDPARTY_FFMPEG_LIBRARY
set (3RDPARTY_FFMPEG_LIBRARY "3RDPARTY_FFMPEG_LIBRARY-NOTFOUND" CACHE FILEPATH "The path to FFmpeg library" FORCE)
if (3RDPARTY_FFMPEG_DIR AND EXISTS "${3RDPARTY_FFMPEG_DIR}")
find_library (3RDPARTY_FFMPEG_LIBRARY NAMES avutil
PATHS "${3RDPARTY_FFMPEG_LIBRARY_DIR}" "${3RDPARTY_FFMPEG_DIR}"
PATH_SUFFIXES ${FFMPEG_PATH_SUFFIXES}
CMAKE_FIND_ROOT_PATH_BOTH
NO_DEFAULT_PATH)
else()
find_library (3RDPARTY_FFMPEG_LIBRARY NAMES avutil
PATH_SUFFIXES ${FFMPEG_PATH_SUFFIXES}
CMAKE_FIND_ROOT_PATH_BOTH)
endif()
if (3RDPARTY_FFMPEG_LIBRARY AND EXISTS "${3RDPARTY_FFMPEG_LIBRARY}")
get_filename_component (3RDPARTY_FFMPEG_LIBRARY_DIR "${3RDPARTY_FFMPEG_LIBRARY}" PATH)
set (3RDPARTY_FFMPEG_LIBRARY_DIR "${3RDPARTY_FFMPEG_LIBRARY_DIR}" CACHE PATH "The directory containing FFmpeg library" FORCE)
else()
set (3RDPARTY_FFMPEG_LIBRARY_DIR "" CACHE PATH "The directory containing FFmpeg library" FORCE)
endif()
endif()
if (3RDPARTY_FFMPEG_LIBRARY_DIR AND EXISTS "${3RDPARTY_FFMPEG_LIBRARY_DIR}")
list (APPEND 3RDPARTY_LIBRARY_DIRS "${3RDPARTY_FFMPEG_LIBRARY_DIR}")
else()
list (APPEND 3RDPARTY_NOT_INCLUDED 3RDPARTY_FFMPEG_LIBRARY_DIR)
set (3RDPARTY_FFMPEG_LIBRARY "" CACHE FILEPATH "The path to FFmpeg library" FORCE)
endif()
# shared library
if (WIN32)
if (NOT 3RDPARTY_FFMPEG_DLL OR NOT EXISTS "${3RDPARTY_FFMPEG_DLL}")
set (CMAKE_FIND_LIBRARY_SUFFIXES .dll)
set (3RDPARTY_FFMPEG_DLL "3RDPARTY_FFMPEG_DLL-NOTFOUND" CACHE FILEPATH "The path to FFmpeg shared library" FORCE)
# find FFmpeg shared library
file (GLOB 3RDPARTY_FFMPEG_DLL "${3RDPARTY_FFMPEG_DIR}/bin/avutil[-][0-9]*")
if (3RDPARTY_FFMPEG_DLL AND EXISTS "${3RDPARTY_FFMPEG_DLL}")
set (3RDPARTY_FFMPEG_DLL "${3RDPARTY_FFMPEG_DLL}" CACHE FILEPATH "FFmpeg shared library" FORCE)
get_filename_component (3RDPARTY_FFMPEG_DLL_DIR "${3RDPARTY_FFMPEG_DLL}" PATH)
set (3RDPARTY_FFMPEG_DLL_DIR "${3RDPARTY_FFMPEG_DLL_DIR}" CACHE PATH "The directory containing FFmpeg library" FORCE)
else()
set (3RDPARTY_FFMPEG_DLL_DIR "" CACHE PATH "The directory containing FFmpeg shared library" FORCE)
endif()
endif()
if (3RDPARTY_FFMPEG_DLL_DIR OR EXISTS "${3RDPARTY_FFMPEG_DLL_DIR}")
list (APPEND 3RDPARTY_DLL_DIRS "${3RDPARTY_FFMPEG_DLL_DIR}")
else()
list (APPEND 3RDPARTY_NOT_INCLUDED 3RDPARTY_FFMPEG_DLL_DIR)
endif()
endif()
# install instructions
if (INSTALL_FFMPEG)
OCCT_MAKE_OS_WITH_BITNESS()
OCCT_MAKE_COMPILER_SHORT_NAME()
if (WIN32)
if (DEFINED INSTALL_BIN_DIR)
install (FILES "${3RDPARTY_FFMPEG_DLL}" DESTINATION "${INSTALL_BIN_DIR}")
else()
install (FILES "${3RDPARTY_FFMPEG_DLL}"
CONFIGURATIONS Release
DESTINATION "${INSTALL_DIR}/${OS_WITH_BIT}/${COMPILER}/bin")
install (FILES "${3RDPARTY_FFMPEG_DLL}"
CONFIGURATIONS RelWithDebInfo
DESTINATION "${INSTALL_DIR}/${OS_WITH_BIT}/${COMPILER}/bini")
install (FILES "${3RDPARTY_FFMPEG_DLL}"
CONFIGURATIONS Debug
DESTINATION "${INSTALL_DIR}/${OS_WITH_BIT}/${COMPILER}/bind")
endif()
else()
get_filename_component(3RDPARTY_FFMPEG_LIBRARY_ABS ${3RDPARTY_FFMPEG_LIBRARY} REALPATH)
get_filename_component(3RDPARTY_FFMPEG_LIBRARY_NAME ${3RDPARTY_FFMPEG_LIBRARY} NAME)
if (DEFINED INSTALL_LIB_DIR)
install (FILES "${3RDPARTY_FFMPEG_LIBRARY_ABS}"
DESTINATION "${INSTALL_LIB_DIR}"
RENAME ${3RDPARTY_FFMPEG_LIBRARY_NAME}.6)
else()
install (FILES "${3RDPARTY_FFMPEG_LIBRARY_ABS}"
CONFIGURATIONS Release
DESTINATION "${INSTALL_DIR}/${OS_WITH_BIT}/${COMPILER}/lib"
RENAME ${3RDPARTY_FFMPEG_LIBRARY_NAME}.6)
install (FILES "${3RDPARTY_FFMPEG_LIBRARY_ABS}"
CONFIGURATIONS RelWithDebInfo
DESTINATION "${INSTALL_DIR}/${OS_WITH_BIT}/${COMPILER}/libi"
RENAME ${3RDPARTY_FFMPEG_LIBRARY_NAME}.6)
install (FILES "${3RDPARTY_FFMPEG_LIBRARY_ABS}"
CONFIGURATIONS Debug
DESTINATION "${INSTALL_DIR}/${OS_WITH_BIT}/${COMPILER}/libd"
RENAME ${3RDPARTY_FFMPEG_LIBRARY_NAME}.6)
endif()
endif()
set (USED_3RDPARTY_FFMPEG_DIR "")
else()
# the library directory for using by the executable
if (WIN32)
set (USED_3RDPARTY_FFMPEG_DIR ${3RDPARTY_FFMPEG_DLL_DIR})
else()
set (USED_3RDPARTY_FFMPEG_DIR ${3RDPARTY_FFMPEG_LIBRARY_DIR})
endif()
endif()
# unset all redundant variables
OCCT_CHECK_AND_UNSET (FFMPEG_INCLUDE_DIRS)
OCCT_CHECK_AND_UNSET (FFMPEG_LIBRARY_DIRS)
OCCT_CHECK_AND_UNSET (FFMPEG_DIR)
mark_as_advanced (3RDPARTY_FFMPEG_LIBRARY 3RDPARTY_FFMPEG_DLL)

View File

@@ -24,13 +24,6 @@ else()
set (CSF_FREETYPE)
endif()
# FFmpeg
if (USE_FFMPEG)
set (CSF_FFmpeg "avcodec avformat swscale avutil")
else()
set (CSF_FFmpeg)
endif()
# FREEIMAGE
if (USE_FREEIMAGE)
set (CSF_FreeImagePlus "freeimage")

View File

@@ -316,7 +316,6 @@ if (BUILD_USE_PCH)
# workaround for old gcc
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
add_definitions("-D__STDC_CONSTANT_MACROS")
add_definitions("-D__STDC_FORMAT_MACROS")
endif()

View File

@@ -82,7 +82,6 @@ endmacro()
INSTALL_MESSAGE (INSTALL_SAMPLES "OCCT samples")
INSTALL_MESSAGE (INSTALL_TEST_CASES "non-regression OCCT test scripts")
INSTALL_MESSAGE (INSTALL_DOC_Overview "OCCT overview documentation (HTML format)")
INSTALL_MESSAGE (INSTALL_FFMPEG "FFmpeg binaries")
INSTALL_MESSAGE (INSTALL_FREEIMAGE "FreeImage binaries")
INSTALL_MESSAGE (INSTALL_EGL "EGL binaries")
INSTALL_MESSAGE (INSTALL_GLES2 "OpenGL ES 2.0 binaries")
@@ -137,10 +136,6 @@ set (3RDPARTY_DIR_DESCR
third-party product have been found - corresponding CMake variables will be specified
(VTK: 3RDPARTY_VTK_DIR, 3RDPARTY_VTK_INCLUDE_DIR, 3RDPARTY_VTK_LIBRARY_DIR)")
set (USE_FFMPEG_DESCR
"Indicates whether FFmpeg framework is used or not. FFmpeg stands for
multimedia data handling, open-source software libraries used for video encoding and decoding.")
set (USE_FREEIMAGE_DESCR
"Indicates whether Freeimage product should be used in OCCT visualization
module for support of popular graphics image formats (PNG, BMP etc)")

View File

@@ -119,21 +119,6 @@ proc wokdep:SearchHeader {theHeader} {
if { [file exists "$aPath"] } {
return "$aPath"
}
if { "$::tcl_platform(os)" == "Linux" } {
if { "$::ARCH" == "64" } {
set aPath "/usr/include/x86_64-linux-gnu/${theHeader}"
if { [file exists "$aPath"] } {
return "$aPath"
}
} else {
set aPath "/usr/include/i386-linux-gnu/${theHeader}"
if { [file exists "$aPath"] } {
return "$aPath"
}
}
}
return ""
}

View File

@@ -61,7 +61,6 @@ set (OpenCASCADE_WITH_FREEIMAGE @USE_FREEIMAGE@)
set (OpenCASCADE_WITH_GL2PS @USE_GL2PS@)
set (OpenCASCADE_WITH_TBB @USE_TBB@)
set (OpenCASCADE_WITH_VTK @USE_VTK@)
set (OpenCASCADE_WITH_FFMPEG @USE_FFMPEG@)
set (OpenCASCADE_WITH_GLES2 @USE_GLES2@)
@SET_OpenCASCADE_WITH_D3D@
@SET_OpenCASCADE_WITH_GLX@

View File

@@ -14,7 +14,6 @@ if /I "%VCVER%" == "@COMPILER@" (
set "GL2PS_DIR=@3RDPARTY_GL2PS_DLL_DIRS@"
set "TBB_DIR=@3RDPARTY_TBB_DLL_DIR@"
set "VTK_DIR=@3RDPARTY_VTK_DLL_DIR@"
set "FFMPEG_DIR=@3RDPARTY_FFMPEG_DLL_DIR@"
if not "@3RDPARTY_QT_DIR@" == "" (
set "QTDIR=@3RDPARTY_QT_DIR@"

View File

@@ -12,7 +12,6 @@ if [ "$1" == "@BIN_LETTER@" ]; then
export GL2PS_DIR="@3RDPARTY_GL2PS_LIBRARY_DIRS@"
export TBB_DIR="@3RDPARTY_TBB_LIBRARY_DIR@"
export VTK_DIR="@3RDPARTY_VTK_LIBRARY_DIR@"
export FFMPEG_DIR="@3RDPARTY_FFMPEG_LIBRARY_DIR@"
if [ "x@3RDPARTY_QT_DIR" != "x" ]; then
export QTDIR="@3RDPARTY_QT_DIR@"

View File

@@ -16,7 +16,6 @@ if /I "%VCVER%" == "@COMPILER@" (
set "GL2PS_DIR=@USED_3RDPARTY_GL2PS_DIRS@"
set "TBB_DIR=@USED_3RDPARTY_TBB_DIR@"
set "VTK_DIR=@USED_3RDPARTY_VTK_DIR@"
set "FFMPEG_DIR=@USED_3RDPARTY_FFMPEG_DIR@"
if not "@USED_3RDPARTY_QT_DIR@" == "" (
set "QTDIR=@USED_3RDPARTY_QT_DIR@"

View File

@@ -12,7 +12,6 @@ if [ "$1" == "@BIN_LETTER@" ]; then
export GL2PS_DIR="@USED_3RDPARTY_GL2PS_DIRS@"
export TBB_DIR="@USED_3RDPARTY_TBB_DIR@"
export VTK_DIR="@USED_3RDPARTY_VTK_DIR@"
export FFMPEG_DIR="@USED_3RDPARTY_FFMPEG_DIR@"
if [ "x@USED_3RDPARTY_QT_DIR@" != "x" ]; then
export QTDIR="@USED_3RDPARTY_QT_DIR@"

View File

@@ -115,7 +115,6 @@ if not ["%GLES2_DIR%"] == [""] set "PATH=%GLES2_DIR%;%PATH%"
if not ["%GL2PS_DIR%"] == [""] set "PATH=%GL2PS_DIR%;%PATH%"
if not ["%TBB_DIR%"] == [""] set "PATH=%TBB_DIR%;%PATH%"
if not ["%VTK_DIR%"] == [""] set "PATH=%VTK_DIR%;%PATH%"
if not ["%FFMPEG_DIR%"] == [""] set "PATH=%FFMPEG_DIR%;%PATH%"
if not ["%QTDIR%"] == [""] set "PATH=%QTDIR%/bin;%PATH%"
rem ----- Set path to 3rd party and OCCT libraries -----

View File

@@ -66,10 +66,6 @@ if [ "$VTK_DIR" != "" ]; then
THRDPARTY_PATH="${VTK_DIR}:${THRDPARTY_PATH}"
fi
if [ "$FFMPEG_DIR" != "" ]; then
THRDPARTY_PATH="${FFMPEG_DIR}:${THRDPARTY_PATH}"
fi
if [ "$QTDIR" != "" ]; then
THRDPARTY_PATH="${QTDIR}/lib:${THRDPARTY_PATH}"
fi

View File

@@ -110,7 +110,6 @@
<ProgramDatabaseFile>.\..\..\..\win32\__VCVER__\bin\__XQTNAM__.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<ImportLibrary>..\..\..\win32\__VCVER__\lib\__XQTNAM__.lib</ImportLibrary>
<AdditionalOptions>/LARGEADDRESSAWARE %(AdditionalOptions)</AdditionalOptions>
__VCLNKREL__
</Link>
</ItemDefinitionGroup>
@@ -156,7 +155,6 @@
<ProgramDatabaseFile>..\..\..\win32\__VCVER__\bind\__XQTNAM__.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<ImportLibrary>..\..\..\win32\__VCVER__\libd\__XQTNAM__.lib</ImportLibrary>
<AdditionalOptions>/LARGEADDRESSAWARE %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

View File

@@ -1406,7 +1406,3 @@ In previous versions, *IsPeriodic()* always returned false if *IsClosed()* retur
The history of the changing of the initial shape was corrected:
* all shapes created by the algorithm are considered as modified shapes instead of generated ones;
* method Generated was removed and its calls should be replaced by calls of method History()->Modified.
@subsection upgrade_720_Change_In_RWStl Changes in STL Reader / Writer
Class RWStl now uses class Poly_Triangulation for storing triangular mesh instead of StlMesh data classes; the latter have been removed.

View File

@@ -135,9 +135,6 @@ by fully automating techniques as precompiled header usage and single compilatio
Cotire is included in OCCT repository and used optionally by OCCT CMake scripts to accelerate builds by use of precompiled headers.
Cotire is licensed under the MIT license (https://github.com/sakra/cotire/blob/master/license).
**FFmpeg** is an Open Source framework supporting various image, video and audio codecs.
FFmpeg is optionally used by OCCT for video recording, on LGPL conditions (https://www.ffmpeg.org/legal.html).
**MikTEX** is up-to-date implementation of TeX/LaTeX and related programs for Windows. It is used
for generation of User and Developer Guides in PDF format. See https://miktex.org for information
on this tool.
@@ -213,7 +210,6 @@ for which OCCT is certified to work.
| TCL (for testing tools) | Tcl/Tk 8.6.3+ http://www.tcl.tk/software/tcltk/download.html <br> or ActiveTcl 8.6 http://www.activestate.com/activetcl/downloads (for Windows)|
| Freetype (for text rendering) | FreeType 2.4.11-2.5.5 http://sourceforge.net/projects/freetype/files/ |
| FreeImage (optional, for support of common 2D graphic formats) | FreeImage 3.17.0+ http://sourceforge.net/projects/freeimage/files |
| FFmpeg (optional, for video recording) | FFmpeg 3.1+ https://www.ffmpeg.org |
| gl2ps (optional, for export contents of OCCT viewer to vector formats) | gl2ps-1.3.8+ http://geuz.org/gl2ps/ |
| Intel TBB (optional, for multithreaded algorithms) | TBB 4.x or 5.x http://www.threadingbuildingblocks.org/ |
| VTK (for VTK Integration Services | VTK 6.1+ http://www.vtk.org/VTK/resources/software.html |

View File

@@ -1508,8 +1508,8 @@ Such an object, for example, can be used for displaying the object and stored in
~~~~~
// read the data and create a data source
Handle(Poly_Triangulation) aSTLMesh = RWStl::ReadFile (aFileName);
Handle(XSDRAWSTLVRML_DataSource) aDataSource = new XSDRAWSTLVRML_DataSource (aSTLMesh);
Handle (StlMesh_Mesh) aSTLMesh = RWStl::ReadFile (aFileName);
Handle (XSDRAWSTLVRML_DataSource) aDataSource = new XSDRAWSTLVRML_DataSource (aSTLMesh);
// create mesh
Handle (MeshVS_Mesh) aMesh = new MeshVS();

View File

@@ -6,10 +6,8 @@
# initialize environment
aScriptPath=${BASH_SOURCE%/*}; if [ -d "${aScriptPath}" ]; then cd "$aScriptPath"; fi; aScriptPath="$PWD";
if [ ! -e "${aScriptPath}/env.sh" ]; then
cat ${aScriptPath}/adm/templates/env.sh | sed -e '/__CASROOT__/d' > ${aScriptPath}/env.sh
cat ${aScriptPath}/adm/templates/env.sh | sed -e '/__CASROOT__/d' > ${aScriptPath}/env.sh
fi
if [ -e "${aScriptPath}/custom.sh" ]; then source "${aScriptPath}/custom.sh"; fi
# run GUI tool
tclsh "${aScriptPath}/adm/genconf.tcl"

View File

@@ -331,8 +331,10 @@ Standard_Boolean MainPage::SaveSTEP(const wchar_t* theFilePath, const TopoDS_Sha
return Standard_False;
}
const TCollection_AsciiString aFilePath (theFilePath);
switch (aWriter.Write (aFilePath.ToCString()))
char theFilePathA[MAX_PATH];
WideCharToMultiByte(CP_UTF8, 0, theFilePath, -1, theFilePathA, sizeof(theFilePathA), NULL, NULL);
switch (aWriter.Write(theFilePathA))
{
case IFSelect_RetError:
Output_TextBlock->Text += L"Error: Incorrect Data\n";
@@ -356,8 +358,11 @@ Standard_Boolean MainPage::SaveSTEP(const wchar_t* theFilePath, const TopoDS_Sha
Standard_Boolean MainPage::SaveSTL(const wchar_t* theFilePath, const TopoDS_Shape& theShape)
{
StlAPI_Writer myStlWriter;
const TCollection_AsciiString aFilePath (theFilePath);
return myStlWriter.Write (theShape, aFilePath.ToCString());
char theFilePathA[MAX_PATH];
WideCharToMultiByte(CP_UTF8, 0, theFilePath, -1, theFilePathA, sizeof(theFilePathA), NULL, NULL);
return myStlWriter.Write(theShape, theFilePathA) == StlAPI_StatusOK;
}
//=======================================================================
@@ -367,8 +372,12 @@ Standard_Boolean MainPage::SaveSTL(const wchar_t* theFilePath, const TopoDS_Shap
Standard_Boolean MainPage::SaveVRML(const wchar_t* theFilePath, const TopoDS_Shape& theShape)
{
VrmlAPI_Writer aWriter;
const TCollection_AsciiString aFilePath (theFilePath);
aWriter.Write (theShape, aFilePath.ToCString());
char theFilePathA[MAX_PATH];
WideCharToMultiByte(CP_UTF8, 0, theFilePath, -1, theFilePathA, sizeof(theFilePathA), NULL, NULL);
aWriter.Write(theShape, theFilePathA);
return Standard_True;
}
@@ -381,8 +390,11 @@ Standard_Boolean MainPage::ReadBREP(const wchar_t* theFilePath, TopoDS_Shape& th
theShape.Nullify();
BRep_Builder aBuilder;
const TCollection_AsciiString aFilePath (theFilePath);
if (!BRepTools::Read(theShape, aFilePath.ToCString(), aBuilder))
char theFilePathA[MAX_PATH];
WideCharToMultiByte(CP_UTF8, 0, theFilePath, -1, theFilePathA, sizeof(theFilePathA), NULL, NULL);
if (!BRepTools::Read(theShape, theFilePathA, aBuilder))
return Standard_False;
return !theShape.IsNull() && BRepAlgo::IsValid(theShape);
@@ -398,8 +410,10 @@ Standard_Boolean MainPage::ReadIGES(const wchar_t* theFilePath, TopoDS_Shape& th
IGESControl_Reader Reader;
const TCollection_AsciiString aFilePath (theFilePath);
if (Reader.ReadFile (aFilePath.ToCString()) != IFSelect_RetDone)
char theFilePathA[MAX_PATH];
WideCharToMultiByte(CP_UTF8, 0, theFilePath, -1, theFilePathA, sizeof(theFilePathA), NULL, NULL);
if (Reader.ReadFile(theFilePathA) != IFSelect_RetDone)
return Standard_False;
Reader.TransferRoots();
@@ -417,8 +431,11 @@ Standard_Boolean MainPage::ReadSTEP(const wchar_t* theFilePath, TopoDS_Shape& th
theShape.Nullify();
STEPControl_Reader aReader;
const TCollection_AsciiString aFilePath (theFilePath);
switch (aReader.ReadFile (aFilePath.ToCString()))
char theFilePathA[MAX_PATH];
WideCharToMultiByte(CP_UTF8, 0, theFilePath, -1, theFilePathA, sizeof(theFilePathA), NULL, NULL);
switch (aReader.ReadFile(theFilePathA))
{
case IFSelect_RetError:
Output_TextBlock->Text += L"Error: Not a valid Step file\n";

View File

@@ -20,6 +20,15 @@
#include <gp_Pnt2d.hxx>
#include <Standard_ConstructionError.hxx>
#ifdef _WIN32
#if _MSC_VER < 1800
inline double log2 (const double arg)
{
return log(arg) / log(2.);
}
#endif
#endif
static inline
Standard_Real Transform2d(const Standard_Real u,
const Standard_Real umin,
@@ -27,50 +36,102 @@ static inline
//=======================================================================
//function : CSLib_Class2d
//purpose :
//purpose : Constructor
//CR28569 : When the number of points is big enough (now 64 or more) then
// the internal array of 1D Y-boxes myBoxes1d is initialized. It
// cointains approx. sqrt(N) boxes with equal number of points in
// them (mySizeBox is a degree of 2). In each box two double
// numbers define min Y and max Y of the referred points.
//=======================================================================
CSLib_Class2d::CSLib_Class2d(const TColgp_Array1OfPnt2d& TP2d,
const Standard_Real aTolu,
const Standard_Real aTolv,
const Standard_Real theTolu,
const Standard_Real theTolv,
const Standard_Real umin,
const Standard_Real vmin,
const Standard_Real umax,
const Standard_Real vmax)
: MyPnts2d (NULL),
MyBoxes1d (NULL),
mySizeBox (0),
myNBoxes (0),
N (0)
{
Umin=umin;
Vmin=vmin;
Umax=umax;
Vmax=vmax;
//
if(umax<=umin || vmax<=vmin) {
MyPnts2dX=NULL;
MyPnts2dY=NULL;
N=0;
}
//
else {
if(umax > umin && vmax > vmin)
{
Standard_Integer i, iLower;
Standard_Real du,dv,*Pnts2dX,*Pnts2dY, aPrc;
Standard_Real du,dv,*Pnts2dX,*Pnts2dY, aPrc;
Umin=umin;
Vmin=vmin;
Umax=umax;
Vmax=vmax;
//
aPrc=1.e-10;
N = TP2d.Length();
Tolu = aTolu;
Tolv = aTolv;
MyPnts2dX = new Standard_Real [N+1];
MyPnts2dY = new Standard_Real [N+1];
Tolu = theTolu;
Tolv = theTolv;
MyPnts2d = new Standard_Real [2*N+2];
MyBoxes1d = NULL;
Pnts2dX = MyPnts2d;
Pnts2dY = Pnts2dX + 1;
du=umax-umin;
dv=vmax-vmin;
Pnts2dX = (Standard_Real *)MyPnts2dX;
Pnts2dY = (Standard_Real *)MyPnts2dY;
//
iLower=TP2d.Lower();
for(i = 0; i<N; ++i) {
const gp_Pnt2d& aP2D=TP2d(i+iLower);
Pnts2dX[i] = Transform2d(aP2D.X(), umin, du);
Pnts2dY[i] = Transform2d(aP2D.Y(), vmin, dv);
if (N > 63) {
// large polygon, here 1D Y-boxes are created and filled with data.
const Standard_Integer aDegBox = static_cast<Standard_Integer>
(0.5 * log2(static_cast<Standard_Real>(N-1)));
mySizeBox = 1 << aDegBox;
myNBoxes = (N + mySizeBox - 1) / mySizeBox;
MyBoxes1d = new Standard_Real[2 * myNBoxes];
Standard_Integer iBox(0), maskBox(mySizeBox-1);
const gp_Pnt2d& aP0 = TP2d(iLower);
Pnts2dX[0] = Transform2d(aP0.X(), umin, du);
Pnts2dY[0] = Transform2d(aP0.Y(), vmin, dv);
MyBoxes1d[0] = Pnts2dY[0];
MyBoxes1d[1] = Pnts2dY[0];
for (i = 1; i<N; ++i) {
const gp_Pnt2d& aP2D=TP2d(i+iLower);
Pnts2dX[2*i] = Transform2d(aP2D.X(), umin, du);
const Standard_Real anY = Transform2d(aP2D.Y(), vmin, dv);
Pnts2dY[2*i] = anY;
if ((i & maskBox) == 0) {
if (anY < MyBoxes1d[iBox])
MyBoxes1d[iBox] = anY;
if (anY > MyBoxes1d[iBox+1])
MyBoxes1d[iBox+1] = anY;
iBox+=2;
MyBoxes1d[iBox] = anY;
MyBoxes1d[iBox+1] = anY;
}
else if (anY < MyBoxes1d[iBox])
MyBoxes1d[iBox] = anY;
else if (anY > MyBoxes1d[iBox+1])
MyBoxes1d[iBox+1] = anY;
}
Pnts2dX[2*N]=Pnts2dX[0];
Pnts2dY[2*N]=Pnts2dY[0];
// now iBox must be equal to 2*myNBoxes-2
if (Pnts2dY[0] < MyBoxes1d[iBox])
MyBoxes1d[iBox] = Pnts2dY[0];
if (Pnts2dY[0] > MyBoxes1d[iBox+1])
MyBoxes1d[iBox+1] = Pnts2dY[0];
}
else {
// small polygon, simply fill the array of points.
for(i = 0; i<N; ++i) {
const gp_Pnt2d& aP2D=TP2d(i+iLower);
Pnts2dX[2*i] = Transform2d(aP2D.X(), umin, du);
Pnts2dY[2*i] = Transform2d(aP2D.Y(), vmin, dv);
}
Pnts2dX[2*N]=Pnts2dX[0];
Pnts2dY[2*N]=Pnts2dY[0];
}
Pnts2dX[N]=Pnts2dX[0];
Pnts2dY[N]=Pnts2dY[0];
//
if(du>aPrc) {
Tolu/=du;
@@ -85,13 +146,13 @@ CSLib_Class2d::CSLib_Class2d(const TColgp_Array1OfPnt2d& TP2d,
//purpose :
//=======================================================================
void CSLib_Class2d::Destroy() {
if(MyPnts2dX) {
delete [] (Standard_Real *)MyPnts2dX;
MyPnts2dX=NULL;
if(MyPnts2d) {
delete [] MyPnts2d;
MyPnts2d=NULL;
}
if(MyPnts2dY) {
delete [] (Standard_Real *)MyPnts2dY;
MyPnts2dY=NULL;
if(MyBoxes1d) {
delete [] MyBoxes1d;
MyBoxes1d=NULL;
}
}
@@ -186,41 +247,73 @@ Standard_Integer CSLib_Class2d::SiDans_OnMode(const gp_Pnt2d& P,
Standard_Integer CSLib_Class2d::InternalSiDans(const Standard_Real Px,
const Standard_Real Py) const
{
Standard_Integer nbc, i, ip1, SH, NH;
Standard_Integer nbc, i, SH, NH;
Standard_Real *Pnts2dX, *Pnts2dY;
Standard_Real x, y, nx, ny;
//
nbc = 0;
i = 0;
ip1 = 1;
Pnts2dX = (Standard_Real *)MyPnts2dX;
Pnts2dY = (Standard_Real *)MyPnts2dY;
x = (Pnts2dX[i]-Px);
y = (Pnts2dY[i]-Py);
SH = (y<0.)? -1 : 1;
//
for(i=0; i<N ; i++,ip1++) {
nx = Pnts2dX[ip1] - Px;
ny = Pnts2dY[ip1] - Py;
Pnts2dX = MyPnts2d;
Pnts2dY = Pnts2dX + 1;
if (MyBoxes1d == NULL)
{
x = (Pnts2dX[0]-Px);
y = (Pnts2dY[0]-Py);
SH = (y<0.)? -1 : 1;
//
for(i=0; i<N ; i++) {
nx = Pnts2dX[2*(i+1)] - Px;
ny = Pnts2dY[2*(i+1)] - Py;
NH = (ny<0.)? -1 : 1;
if(NH!=SH) {
if(x>0. && nx>0.) {
nbc++;
NH = (ny<0.)? -1 : 1;
if(NH!=SH) {
if(x>0. && nx>0.) {
nbc++;
}
else {
if(x>0.0 || nx>0.) {
if((x-y*(nx-x)/(ny-y))>0.) {
nbc++;
}
}
}
SH = NH;
}
x = nx; y = ny;
}
}
else
{
// Find Y-boxes that include Py. Box with index iBox refers the range of
// points starting from iBox*sizeBox.
for (Standard_Integer iBox = 0; iBox < myNBoxes; iBox++) {
if ((MyBoxes1d[2*iBox] - Tolv - Py) * (MyBoxes1d[2*iBox+1] + Tolv - Py) < 0.)
{
Standard_Integer lastBox = (iBox + 1) * mySizeBox;
if (lastBox > N)
lastBox = N;
x = (Pnts2dX[2*iBox*mySizeBox]-Px);
y = (Pnts2dY[2*iBox*mySizeBox]-Py);
for (i = iBox*mySizeBox; i < lastBox; i++)
{
nx = Pnts2dX[2*(i+1)] - Px;
ny = Pnts2dY[2*(i+1)] - Py;
if (ny * y < 0.) {
if (x > 0. && nx > 0.)
nbc++;
else if (x > 0.0 || nx > 0.) {
if ((x - y*(nx-x)/(ny-y)) > 0.)
nbc++;
}
}
x = nx; y = ny;
}
}
else {
if(x>0.0 || nx>0.) {
if((x-y*(nx-x)/(ny-y))>0.) {
nbc++;
}
}
}
SH = NH;
}
x = nx; y = ny;
}
return(nbc&1);
}
//modified by NIZNHY-PKV Fri Jan 15 09:03:48 2010f
//=======================================================================
//function : InternalSiDansOuOn
@@ -229,71 +322,117 @@ Standard_Integer CSLib_Class2d::InternalSiDans(const Standard_Real Px,
Standard_Integer CSLib_Class2d::InternalSiDansOuOn(const Standard_Real Px,
const Standard_Real Py) const
{
Standard_Integer nbc, i, ip1, SH, NH, iRet;
Standard_Integer nbc, i, ip1, SH, NH, iRet = 0;
Standard_Real *Pnts2dX, *Pnts2dY;
Standard_Real x, y, nx, ny, aX;
Standard_Real aYmin;
//
nbc = 0;
i = 0;
ip1 = 1;
Pnts2dX = (Standard_Real *)MyPnts2dX;
Pnts2dY = (Standard_Real *)MyPnts2dY;
x = (Pnts2dX[i]-Px);
y = (Pnts2dY[i]-Py);
aYmin=y;
SH = (y<0.)? -1 : 1;
for(i=0; i<N ; i++, ip1++) {
nx = Pnts2dX[ip1] - Px;
ny = Pnts2dY[ip1] - Py;
//-- le 14 oct 97
if(nx<Tolu && nx>-Tolu && ny<Tolv && ny>-Tolv) {
iRet=-1;
return iRet;
}
//find Y coordinate of polyline for current X gka
//in order to detect possible status ON
Standard_Real aDx = (Pnts2dX[ip1] - Pnts2dX[ip1-1]);
if( (Pnts2dX[ip1-1] - Px) * nx < 0.)
{
Standard_Real aCurPY = Pnts2dY[ip1] - (Pnts2dY[ip1] - Pnts2dY[ip1-1])/aDx *nx;
Standard_Real aDeltaY = aCurPY - Py;
if(aDeltaY >= -Tolv && aDeltaY <= Tolv)
Pnts2dX = MyPnts2d;
Pnts2dY = Pnts2dX + 1;
if (MyBoxes1d == NULL)
{
x = (Pnts2dX[0]-Px);
y = (Pnts2dY[0]-Py);
SH = (y<0.)? -1 : 1;
for(i=0; i<N ; i++, ip1++)
{
nx = Pnts2dX[2*ip1] - Px;
ny = Pnts2dY[2*ip1] - Py;
//-- le 14 oct 97
if(nx<Tolu && nx>-Tolu && ny<Tolv && ny>-Tolv) {
iRet=-1;
return iRet;
}
//find Y coordinate of polyline for current X gka
//in order to detect possible status ON
Standard_Real aDx = (Pnts2dX[2*ip1] - Pnts2dX[2*(ip1-1)]);
if( (Pnts2dX[2*(ip1-1)] - Px) * nx < 0.)
{
iRet=-1;
return iRet;
Standard_Real aCurPY =
Pnts2dY[2*ip1] - (Pnts2dY[2*ip1] - Pnts2dY[2*(ip1-1)])/aDx *nx;
Standard_Real aDeltaY = aCurPY - Py;
if(aDeltaY >= -Tolv && aDeltaY <= Tolv)
{
iRet=-1;
return iRet;
}
}
}
//
//
NH = (ny<0.)? -1 : 1;
if(NH!=SH) {
if(x>0. && nx>0.) {
nbc++;
NH = (ny<0.)? -1 : 1;
if(NH!=SH) {
if(x>0. && nx>0.) {
nbc++;
}
else {
if(x>0. || nx>0.) {
aX=x-y*(nx-x)/(ny-y);
if(aX>0.){
nbc++;
}
}
}
SH = NH;
}
else {
if(x>0. || nx>0.) {
aX=x-y*(nx-x)/(ny-y);
if(aX>0.){
nbc++;
}
}
x = nx; y = ny;
}// for(i=0; i<N ; i++,ip1++) {
}
else
{
const Standard_Real aTolu2(Tolu * Tolu);
const Standard_Real aTolv2(Tolv * Tolv);
// Find Y-boxes that include Py. Box with index iBox refers the range of
// points starting from iBox*sizeBox.
for (Standard_Integer iBox = 0; iBox < myNBoxes; iBox++) {
if ((MyBoxes1d[2*iBox] - Tolv - Py) * (MyBoxes1d[2*iBox+1] + Tolv - Py) < 0.)
{
Standard_Integer lastBox = (iBox + 1) * mySizeBox;
if (lastBox > N)
lastBox = N;
x = (Pnts2dX[2*iBox*mySizeBox]-Px);
y = (Pnts2dY[2*iBox*mySizeBox]-Py);
for (i = iBox*mySizeBox; i < lastBox; i++)
{
nx = Pnts2dX[2*(i+1)] - Px;
ny = Pnts2dY[2*(i+1)] - Py;
if (nx * nx < aTolu2 && ny * ny < aTolv2) {
iRet = -1;
break;
}
//find Y coordinate of polyline for current X gka
//in order to detect possible status ON
if (x /*(Pnts2dX[2*(ip1-1)] - Px)*/ * nx < 0.)
{
const Standard_Real aDeltaY = ny - (ny - y)/(nx - x) * nx;
if (aDeltaY*aDeltaY <= aTolv2) {
iRet = -1;
break;
}
}
if (ny * y < 0.) {
if (x > 0. && nx > 0.)
nbc++;
else if (x > 0. || nx > 0.) {
if ((x - y*(nx-x)/(ny-y)) > 0.)
nbc++;
}
}
x = nx; y = ny;
} // for(.. i ..)
if (iRet < 0)
break;
}
SH = NH;
}
else {// y has same sign as ny
if (ny<aYmin) {
aYmin=ny;
}
}
x = nx; y = ny;
}// for(i=0; i<N ; i++,ip1++) {
iRet=nbc&1;
} // for(.. iBox ..)
}
if (iRet == 0)
iRet = nbc&1;
return iRet;
}
//modified by NIZNHY-PKV Fri Jan 15 09:03:55 2010t
//=======================================================================
//function : Copy

View File

@@ -73,8 +73,10 @@ private:
Standard_Address MyPnts2dX;
Standard_Address MyPnts2dY;
Standard_Real * MyPnts2d;
Standard_Real * MyBoxes1d;
Standard_Integer mySizeBox;
Standard_Integer myNBoxes;
Standard_Real Tolu;
Standard_Real Tolv;
Standard_Integer N;

View File

@@ -350,11 +350,6 @@ static Standard_Integer dversion(Draw_Interpretor& di, Standard_Integer, const c
#else
di << "FreeImage disabled\n";
#endif
#ifdef HAVE_FFMPEG
di << "FFmpeg enabled (HAVE_FFMPEG)\n";
#else
di << "FFmpeg disabled\n";
#endif
#ifdef HAVE_GLES2
di << "OpenGL: ES2\n";
#else

View File

@@ -576,12 +576,13 @@ void GCPnts_TangentialDeflection::PerformCurve (const TheCurve& C)
//-- if(Nbp < MinNb) { cout<<"\n*"; } else { cout<<"\n."; }
while(Nbp < MinNb) {
//-- cout<<" \nGCPnts TangentialDeflection : Ajout de Points ("<<Nbp<<" "<<minNbPnts<<" )"<<endl;
for (i = 2; i <= Nbp; i += 2) {
for(i=2; i<=Nbp; i++) {
MiddleU = (parameters.Value(i-1)+parameters.Value(i))*0.5;
D0 (C, MiddleU, MiddlePoint);
parameters.InsertBefore(i,MiddleU);
points.InsertBefore(i,MiddlePoint);
Nbp++;
i++;
}
}
//Additional check for intervals

View File

@@ -7,5 +7,3 @@ Image_Format.hxx
Image_PixMap.cxx
Image_PixMap.hxx
Image_PixMapData.hxx
Image_VideoRecorder.cxx
Image_VideoRecorder.hxx

View File

@@ -1,509 +0,0 @@
// Created on: 2016-04-01
// Created by: Anastasia BORISOVA
// Copyright (c) 2016 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
// activate some C99 macros like UINT64_C in "stdint.h" which used by FFmpeg
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif
#include <Image_VideoRecorder.hxx>
#include <Message.hxx>
#include <Message_Messenger.hxx>
#ifdef HAVE_FFMPEG
// Suppress deprecation warnings - it is difficult to provide compatibility with old and new API at once
// since new APIs are introduced too often.
// Should be disabled from time to time to clean up usage of old APIs.
#if (defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
#else
Standard_DISABLE_DEPRECATION_WARNINGS
#endif
extern "C"
{
#ifdef _MSC_VER
// suppress some common warnings in FFmpeg headers
#pragma warning(disable : 4244)
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#ifdef _MSC_VER
#pragma warning(default : 4244)
#endif
};
#endif
IMPLEMENT_STANDARD_RTTIEXT(Image_VideoRecorder, Standard_Transient)
//=============================================================================
//function : Constructor
//purpose :
//=============================================================================
Image_VideoRecorder::Image_VideoRecorder()
: myAVContext (NULL),
myVideoStream (NULL),
myVideoCodec (NULL),
myFrame (NULL),
myScaleCtx (NULL),
myFrameCount (0)
{
myFrameRate.num = 1;
myFrameRate.den = 30;
#ifdef HAVE_FFMPEG
// initialize libavcodec, and register all codecs and formats, should be done once
av_register_all();
#endif
}
//=============================================================================
//function : ~Image_VideoRecorder
//purpose :
//=============================================================================
Image_VideoRecorder::~Image_VideoRecorder()
{
Close();
}
//=============================================================================
//function : formatAvError
//purpose :
//=============================================================================
TCollection_AsciiString Image_VideoRecorder::formatAvError (const int theError) const
{
#ifdef HAVE_FFMPEG
char anErrBuf[AV_ERROR_MAX_STRING_SIZE] = {};
av_strerror (theError, anErrBuf, AV_ERROR_MAX_STRING_SIZE);
return anErrBuf;
#else
return TCollection_AsciiString(theError);
#endif
}
//=============================================================================
//function : Close
//purpose :
//=============================================================================
void Image_VideoRecorder::Close()
{
#ifdef HAVE_FFMPEG
if (myScaleCtx != NULL)
{
sws_freeContext (myScaleCtx);
myScaleCtx = NULL;
}
if (myAVContext == NULL)
{
myFrameCount = 0;
return;
}
// Write the trailer, if any. The trailer must be written before you close the CodecContexts open when you wrote the header;
// otherwise av_write_trailer() may try to use memory that was freed on av_codec_close().
if (myFrameCount != 0)
{
av_write_trailer (myAVContext);
myFrameCount = 0;
}
// close each codec
if (myVideoStream != NULL)
{
avcodec_close (myVideoStream->codec);
myVideoStream = NULL;
}
if (myFrame != NULL)
{
av_free (myFrame->data[0]);
av_frame_free (&myFrame);
myFrame = NULL;
}
if (!(myAVContext->oformat->flags & AVFMT_NOFILE))
{
// close the output file
avio_close (myAVContext->pb);
}
// free the stream
avformat_free_context (myAVContext);
myAVContext = NULL;
#endif
}
//=============================================================================
//function : Open
//purpose :
//=============================================================================
Standard_Boolean Image_VideoRecorder::Open (const char* theFileName,
const Image_VideoParams& theParams)
{
#ifdef HAVE_FFMPEG
Close();
if (theParams.Width <= 0
|| theParams.Height <= 0)
{
return Standard_False;
}
// allocate the output media context
avformat_alloc_output_context2 (&myAVContext, NULL, theParams.Format.IsEmpty() ? NULL : theParams.Format.ToCString(), theFileName);
if (myAVContext == NULL)
{
::Message::DefaultMessenger()->Send ("ViewerTest_VideoRecorder, could not deduce output format from file extension", Message_Fail);
return Standard_False;
}
// add the audio stream using the default format codecs and initialize the codecs
if (!addVideoStream (theParams, myAVContext->oformat->video_codec))
{
Close();
return Standard_False;
}
// open video codec and allocate the necessary encode buffers
if (!openVideoCodec (theParams))
{
Close();
return Standard_False;
}
#ifdef OCCT_DEBUG
av_dump_format (myAVContext, 0, theFileName, 1);
#endif
// open the output file, if needed
if ((myAVContext->oformat->flags & AVFMT_NOFILE) == 0)
{
const int aResAv = avio_open (&myAVContext->pb, theFileName, AVIO_FLAG_WRITE);
if (aResAv < 0)
{
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: could not open '") + theFileName + "', " + formatAvError (aResAv);
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
Close();
return Standard_False;
}
}
// write the stream header, if any
const int aResAv = avformat_write_header (myAVContext, NULL);
if (aResAv < 0)
{
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not open output file '") + theFileName + "', " + formatAvError (aResAv);
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
Close();
return Standard_False;
}
#else
(void )theFileName;
(void )theParams;
#endif
return Standard_True;
}
//=============================================================================
//function : addVideoStream
//purpose :
//=============================================================================
Standard_Boolean Image_VideoRecorder::addVideoStream (const Image_VideoParams& theParams,
const Standard_Integer theDefCodecId)
{
myFrameRate.num = theParams.FpsNum;
myFrameRate.den = theParams.FpsDen;
#ifdef HAVE_FFMPEG
// find the encoder
TCollection_AsciiString aCodecName;
if (!theParams.VideoCodec.IsEmpty())
{
myVideoCodec = avcodec_find_encoder_by_name (theParams.VideoCodec.ToCString());
aCodecName = theParams.VideoCodec;
}
else
{
myVideoCodec = avcodec_find_encoder ((AVCodecID )theDefCodecId);
aCodecName = avcodec_get_name ((AVCodecID )theDefCodecId);
}
if (myVideoCodec == NULL)
{
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not find encoder for ") + aCodecName;
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
return Standard_False;
}
const AVCodecID aCodecId = myVideoCodec->id;
myVideoStream = avformat_new_stream (myAVContext, myVideoCodec);
if (myVideoStream == NULL)
{
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not allocate stream!");
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
return Standard_False;
}
myVideoStream->id = myAVContext->nb_streams - 1;
AVCodecContext* aCodecCtx = myVideoStream->codec;
aCodecCtx->codec_id = aCodecId;
// resolution must be a multiple of two
aCodecCtx->width = theParams.Width;
aCodecCtx->height = theParams.Height;
// Timebase is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
// For fixed-fps content, timebase should be 1/framerate and timestamp increments should be identical to 1.
aCodecCtx->time_base.den = myFrameRate.num;
aCodecCtx->time_base.num = myFrameRate.den;
aCodecCtx->gop_size = 12; // emit one intra frame every twelve frames at most
// some formats want stream headers to be separate
if (myAVContext->oformat->flags & AVFMT_GLOBALHEADER)
{
aCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
return Standard_True;
#else
(void )theParams;
(void )theDefCodecId;
return Standard_False;
#endif
}
//=============================================================================
//function : openVideoCodec
//purpose :
//=============================================================================
Standard_Boolean Image_VideoRecorder::openVideoCodec (const Image_VideoParams& theParams)
{
#ifdef HAVE_FFMPEG
AVDictionary* anOptions = NULL;
AVCodecContext* aCodecCtx = myVideoStream->codec;
// setup default values
aCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
//av_dict_set (&anOptions, "threads", "auto", 0);
if (aCodecCtx->codec == avcodec_find_encoder_by_name ("mpeg2video"))
{
// just for testing, we also add B frames
aCodecCtx->max_b_frames = 2;
aCodecCtx->bit_rate = 6000000;
}
else if (aCodecCtx->codec == avcodec_find_encoder_by_name ("mpeg4"))
{
//
}
else if (aCodecCtx->codec == avcodec_find_encoder_by_name ("mjpeg"))
{
aCodecCtx->pix_fmt = AV_PIX_FMT_YUVJ420P;
aCodecCtx->qmin = aCodecCtx->qmax = 5;
}
else if (aCodecCtx->codec == avcodec_find_encoder_by_name ("huffyuv"))
{
aCodecCtx->pix_fmt = AV_PIX_FMT_RGB24;
}
else if (aCodecCtx->codec == avcodec_find_encoder_by_name ("png"))
{
aCodecCtx->pix_fmt = AV_PIX_FMT_RGB24;
aCodecCtx->compression_level = 9; // 0..9
}
else if (aCodecCtx->codec == avcodec_find_encoder_by_name ("h264")
|| aCodecCtx->codec == avcodec_find_encoder_by_name ("libx264"))
{
// use CRF (Constant Rate Factor) as best single-pass compressing method
av_dict_set (&anOptions, "crf", "20", 0); // quality 18-28, 23 is default (normal), 18 is almost lossless
av_dict_set (&anOptions, "preset", "slow", 0); // good compression (see also "veryslow", "ultrafast")
// live-capturing
//av_dict_set (&anOptions, "qp", "0", 0); // instead of crf
//av_dict_set (&anOptions, "preset", "ultrafast", 0);
// compatibility with devices
//av_dict_set (&anOptions, "profile", "baseline", 0);
//av_dict_set (&anOptions, "level", "3.0", 0);
}
else if (aCodecCtx->codec == avcodec_find_encoder_by_name ("vp8")
|| aCodecCtx->codec == avcodec_find_encoder_by_name ("vp9"))
{
av_dict_set (&anOptions, "crf", "20", 0); // quality 4<>63, 10 is normal
}
// override defaults with specified options
if (!theParams.PixelFormat.IsEmpty())
{
const AVPixelFormat aPixFormat = av_get_pix_fmt (theParams.PixelFormat.ToCString());
if (aPixFormat == AV_PIX_FMT_NONE)
{
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: unknown pixel format has been specified '") + theParams.PixelFormat + "'";
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
return Standard_False;
}
aCodecCtx->pix_fmt = aPixFormat;
for (Resource_DataMapOfAsciiStringAsciiString::Iterator aParamIter (theParams.VideoCodecParams);
aParamIter.More(); aParamIter.Next())
{
av_dict_set (&anOptions, aParamIter.Key().ToCString(), aParamIter.Value().ToCString(), 0);
}
}
// open codec
int aResAv = avcodec_open2 (aCodecCtx, myVideoCodec, &anOptions);
if (anOptions != NULL)
{
av_dict_free (&anOptions);
}
if (aResAv < 0)
{
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not open video codec, ") + formatAvError (aResAv);
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
return Standard_False;
}
// allocate and init a re-usable frame
myFrame = av_frame_alloc();
if (myFrame == NULL)
{
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not allocate video frame!");
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
return Standard_False;
}
// allocate the encoded raw picture
aResAv = av_image_alloc (myFrame->data, myFrame->linesize,
aCodecCtx->width, aCodecCtx->height, aCodecCtx->pix_fmt, 1);
if (aResAv < 0)
{
memset (myFrame->data, 0, sizeof(myFrame->data));
memset (myFrame->linesize, 0, sizeof(myFrame->linesize));
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not allocate picture ")
+ aCodecCtx->width+ "x" + aCodecCtx->height + ", " + formatAvError (aResAv);
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
return Standard_False;
}
// copy data and linesize picture pointers to frame
myFrame->format = aCodecCtx->pix_fmt;
myFrame->width = aCodecCtx->width;
myFrame->height = aCodecCtx->height;
const Standard_Size aStride = aCodecCtx->width + 16 - (aCodecCtx->width % 16);
if (!myImgSrcRgba.InitZero (Image_PixMap::ImgRGBA, aCodecCtx->width, aCodecCtx->height, aStride))
{
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not allocate RGBA32 picture ")
+ aCodecCtx->width+ "x" + aCodecCtx->height;
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
return Standard_False;
}
myScaleCtx = sws_getContext (aCodecCtx->width, aCodecCtx->height, AV_PIX_FMT_RGBA,
aCodecCtx->width, aCodecCtx->height, aCodecCtx->pix_fmt,
SWS_BICUBIC, NULL, NULL, NULL);
if (myScaleCtx == NULL)
{
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not initialize the conversion context!");
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
return Standard_False;
}
return Standard_True;
#else
(void )theParams;
return Standard_False;
#endif
}
//=============================================================================
//function : writeVideoFrame
//purpose :
//=============================================================================
Standard_Boolean Image_VideoRecorder::writeVideoFrame (const Standard_Boolean theToFlush)
{
#ifdef HAVE_FFMPEG
int aResAv = 0;
AVCodecContext* aCodecCtx = myVideoStream->codec;
if (!theToFlush)
{
uint8_t* aSrcData[4] = { (uint8_t*)myImgSrcRgba.ChangeData(), NULL, NULL, NULL };
int aSrcLinesize[4] = { (int )myImgSrcRgba.SizeRowBytes(), 0, 0, 0 };
sws_scale (myScaleCtx,
aSrcData, aSrcLinesize,
0, aCodecCtx->height,
myFrame->data, myFrame->linesize);
}
AVPacket aPacket;
memset (&aPacket, 0, sizeof(aPacket));
av_init_packet (&aPacket);
if ((myAVContext->oformat->flags & AVFMT_RAWPICTURE) != 0
&& !theToFlush)
{
// raw video case - directly store the picture in the packet
aPacket.flags |= AV_PKT_FLAG_KEY;
aPacket.stream_index = myVideoStream->index;
aPacket.data = myFrame->data[0];
aPacket.size = sizeof(AVPicture);
aResAv = av_interleaved_write_frame (myAVContext, &aPacket);
}
else
{
// encode the image
myFrame->pts = myFrameCount;
int isGotPacket = 0;
aResAv = avcodec_encode_video2 (aCodecCtx, &aPacket, theToFlush ? NULL : myFrame, &isGotPacket);
if (aResAv < 0)
{
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not encode video frame, ") + formatAvError (aResAv);
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
return Standard_False;
}
// if size is zero, it means the image was buffered
if (isGotPacket)
{
const AVRational& aTimeBase = aCodecCtx->time_base;
// rescale output packet timestamp values from codec to stream timebase
aPacket.pts = av_rescale_q_rnd (aPacket.pts, aTimeBase, myVideoStream->time_base, AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
aPacket.dts = av_rescale_q_rnd (aPacket.dts, aTimeBase, myVideoStream->time_base, AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
aPacket.duration = av_rescale_q (aPacket.duration, aTimeBase, myVideoStream->time_base);
aPacket.stream_index = myVideoStream->index;
// write the compressed frame to the media file
aResAv = av_interleaved_write_frame (myAVContext, &aPacket);
}
else
{
aResAv = 0;
}
}
if (aResAv < 0)
{
const TCollection_AsciiString aMsg = TCollection_AsciiString ("Error: can not write video frame, ") + formatAvError (aResAv);
::Message::DefaultMessenger()->Send (aMsg, Message_Fail);
return Standard_False;
}
++myFrameCount;
return Standard_True;
#else
(void)theToFlush;
return Standard_False;
#endif
}

View File

@@ -1,141 +0,0 @@
// Created on: 2016-04-01
// Created by: Anastasia BORISOVA
// Copyright (c) 2016 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef Image_VideoRecorder_HeaderFile_
#define Image_VideoRecorder_HeaderFile_
#include <Image_PixMap.hxx>
#include <Resource_DataMapOfAsciiStringAsciiString.hxx>
#include <Standard_Transient.hxx>
#include <TCollection_AsciiString.hxx>
// forward declarations
struct AVFormatContext;
struct AVStream;
struct AVCodec;
struct AVFrame;
struct SwsContext;
//! Auxiliary structure defining video parameters.
//! Please refer to FFmpeg documentation for defining text values.
struct Image_VideoParams
{
TCollection_AsciiString Format; //!< [optional] video format (container), if empty - will be determined from the file name
TCollection_AsciiString VideoCodec; //!< [optional] codec identifier, if empty - default codec from file format will be used
TCollection_AsciiString PixelFormat; //!< [optional] pixel format, if empty - default codec pixel format will be used
Standard_Integer Width; //!< [mandatory] video frame width
Standard_Integer Height; //!< [mandatory] video frame height
Standard_Integer FpsNum; //!< [mandatory] framerate numerator
Standard_Integer FpsDen; //!< [mandatory] framerate denumerator
Resource_DataMapOfAsciiStringAsciiString
VideoCodecParams; //!< map of advanced video codec parameters
//! Empty constructor.
Image_VideoParams() : Width (0), Height (0), FpsNum (0), FpsDen (1) {}
//! Setup playback FPS.
void SetFramerate (const Standard_Integer theNumerator,
const Standard_Integer theDenominator)
{
FpsNum = theNumerator;
FpsDen = theDenominator;
}
//! Setup playback FPS.
//! For fixed-fps content, timebase should be 1/framerate and timestamp increments should be identical to 1.
void SetFramerate (const Standard_Integer theValue)
{
FpsNum = theValue;
FpsDen = 1;
}
};
//! Video recording tool based on FFmpeg framework.
class Image_VideoRecorder : public Standard_Transient
{
DEFINE_STANDARD_RTTIEXT(Image_VideoRecorder, Standard_Transient)
public:
//! Empty constructor.
Standard_EXPORT Image_VideoRecorder();
//! Destructor.
Standard_EXPORT virtual ~Image_VideoRecorder();
//! Close the stream - stop recorder.
Standard_EXPORT void Close();
//! Open output stream - initialize recorder.
//! @param theFileName [in] video filename
//! @param theParams [in] video parameters
Standard_EXPORT Standard_Boolean Open (const char* theFileName,
const Image_VideoParams& theParams);
//! Access RGBA frame, should NOT be re-initialized outside.
//! Note that image is expected to have upper-left origin.
Image_PixMap& ChangeFrame() { return myImgSrcRgba; }
//! Return current frame index.
int64_t FrameCount() const { return myFrameCount; }
//! Push new frame, should be called after Open().
Standard_Boolean PushFrame()
{
return writeVideoFrame (Standard_False);
}
protected:
//! Wrapper for av_strerror().
Standard_EXPORT TCollection_AsciiString formatAvError (const int theError) const;
//! Append video stream.
//! theParams [in] video parameters
//! theDefCodecId [in] identifier of codec managed by FFmpeg library (AVCodecID enum)
Standard_EXPORT Standard_Boolean addVideoStream (const Image_VideoParams& theParams,
const Standard_Integer theDefCodecId);
//! Open video codec.
Standard_EXPORT Standard_Boolean openVideoCodec (const Image_VideoParams& theParams);
//! Write new video frame.
Standard_EXPORT Standard_Boolean writeVideoFrame (const Standard_Boolean theToFlush);
protected:
//! AVRational alias.
struct VideoRational
{
int num; //!< numerator
int den; //!< denominator
};
protected:
AVFormatContext* myAVContext; //!< video context
AVStream* myVideoStream; //!< video stream
AVCodec* myVideoCodec; //!< video codec
AVFrame* myFrame; //!< frame to record
SwsContext* myScaleCtx; //!< scale context for conversion from RGBA to YUV
Image_PixMap myImgSrcRgba; //!< input RGBA image
VideoRational myFrameRate; //!< video framerate
int64_t myFrameCount; //!< current frame index
};
DEFINE_STANDARD_HANDLE(Image_VideoRecorder, Standard_Transient)
#endif // Image_VideoRecorder_HeaderFile_

View File

@@ -128,9 +128,33 @@ static Standard_Integer OCC527(Draw_Interpretor& di, Standard_Integer argc, cons
return 0;
}
#include <StlMesh_Mesh.hxx>
#include <StlTransfer.hxx>
//=======================================================================
//function : OCC1048
//purpose :
//=======================================================================
static Standard_Integer OCC1048 (Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
{
// Verify amount of arguments of the command
if (argc < 2) { di << "Usage : " << argv[0] <<" shape"; return 1;}
TopoDS_Shape aShape = DBRep::Get(argv[1]);
Standard_Real theDeflection = 0.006;
Handle(StlMesh_Mesh) theStlMesh = new StlMesh_Mesh;
BRepMesh_IncrementalMesh aMesh(aShape, theDeflection);
StlTransfer::RetrieveMesh(aShape, theStlMesh);
Standard_Integer NBTRIANGLES = theStlMesh->NbTriangles();
di<<"Info: Number of triangles = "<<NBTRIANGLES<<"\n";
return 0;
}
void QABugs::Commands_2(Draw_Interpretor& theCommands) {
const char *group = "QABugs";
theCommands.Add("OCC527", "OCC527 shape", __FILE__, OCC527, group);
theCommands.Add("OCC1048", "OCC1048 shape", __FILE__, OCC1048, group);
return;
}

View File

@@ -1,4 +1,2 @@
RWStl.cxx
RWStl.hxx
RWStl_Reader.cxx
RWStl_Reader.hxx

View File

@@ -1,6 +1,7 @@
// Created on: 2017-06-13
// Created by: Alexander MALYSHEV
// Copyright (c) 2017 OPEN CASCADE SAS
// Created on: 1994-10-13
// Created by: Marc LEGAY
// Copyright (c) 1994-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
@@ -13,289 +14,272 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <RWStl.hxx>
#include <BRepBuilderAPI_CellFilter.hxx>
#include <BRepBuilderAPI_VertexInspector.hxx>
#include <gp.hxx>
#include <gp_Vec.hxx>
#include <gp_XYZ.hxx>
#include <Message.hxx>
#include <Message_Messenger.hxx>
#include <Message_ProgressIndicator.hxx>
#include <Message_ProgressSentry.hxx>
#include <NCollection_Vector.hxx>
#include <OSD.hxx>
#include <OSD_File.hxx>
#include <OSD_Host.hxx>
#include <OSD_OpenFile.hxx>
#include <RWStl_Reader.hxx>
#include <OSD_Path.hxx>
#include <OSD_Protection.hxx>
#include <Precision.hxx>
#include <RWStl.hxx>
#include <Standard_NoMoreObject.hxx>
#include <Standard_TypeMismatch.hxx>
#include <StlMesh_Mesh.hxx>
#include <StlMesh_MeshExplorer.hxx>
#include <TCollection_AsciiString.hxx>
namespace
#include <stdio.h>
// A static method adding nodes to a mesh and keeping coincident (sharing) nodes.
static Standard_Integer AddVertex(Handle(StlMesh_Mesh)& mesh,
BRepBuilderAPI_CellFilter& filter,
BRepBuilderAPI_VertexInspector& inspector,
const gp_XYZ& p)
{
static const Standard_Integer THE_STL_SIZEOF_FACET = 50;
static const Standard_Integer IND_THRESHOLD = 1000; // increment the indicator every 1k triangles
//! Writing a Little Endian 32 bits integer
inline static void convertInteger (const Standard_Integer theValue,
Standard_Character* theResult)
Standard_Integer index;
inspector.SetCurrent(p);
gp_XYZ minp = inspector.Shift(p, -Precision::Confusion());
gp_XYZ maxp = inspector.Shift(p, +Precision::Confusion());
filter.Inspect(minp, maxp, inspector);
const TColStd_ListOfInteger& indices = inspector.ResInd();
if (indices.IsEmpty() == Standard_False)
{
union
{
Standard_Integer i;
Standard_Character c[4];
} anUnion;
anUnion.i = theValue;
theResult[0] = anUnion.c[0];
theResult[1] = anUnion.c[1];
theResult[2] = anUnion.c[2];
theResult[3] = anUnion.c[3];
index = indices.First(); // it should be only one
inspector.ClearResList();
}
//! Writing a Little Endian 32 bits float
inline static void convertDouble (const Standard_Real theValue,
Standard_Character* theResult)
else
{
union
{
Standard_ShortReal i;
Standard_Character c[4];
} anUnion;
anUnion.i = (Standard_ShortReal)theValue;
theResult[0] = anUnion.c[0];
theResult[1] = anUnion.c[1];
theResult[2] = anUnion.c[2];
theResult[3] = anUnion.c[3];
index = mesh->AddVertex(p.X(), p.Y(), p.Z());
filter.Add(index, p);
inspector.Add(p);
}
class Reader : public RWStl_Reader
{
public:
//! Add new node
virtual Standard_Integer AddNode (const gp_XYZ& thePnt) Standard_OVERRIDE
{
myNodes.Append (thePnt);
return myNodes.Size();
}
//! Add new triangle
virtual void AddTriangle (Standard_Integer theNode1, Standard_Integer theNode2, Standard_Integer theNode3) Standard_OVERRIDE
{
myTriangles.Append (Poly_Triangle (theNode1, theNode2, theNode3));
}
//! Creates Poly_Triangulation from collected data
Handle(Poly_Triangulation) GetTriangulation()
{
Handle(Poly_Triangulation) aPoly = new Poly_Triangulation (myNodes.Length(), myTriangles.Length(), Standard_False);
for (Standard_Integer aNodeIter = 0; aNodeIter < myNodes.Size(); ++aNodeIter)
{
aPoly->ChangeNode (aNodeIter + 1) = myNodes (aNodeIter);
}
for (Standard_Integer aTriIter = 0; aTriIter < myTriangles.Size(); ++aTriIter)
{
aPoly->ChangeTriangle (aTriIter + 1) = myTriangles (aTriIter);
}
return aPoly;
}
private:
NCollection_Vector<gp_XYZ> myNodes;
NCollection_Vector<Poly_Triangle> myTriangles;
};
return index;
}
//=============================================================================
//function : Read
//purpose :
//=============================================================================
Handle(Poly_Triangulation) RWStl::ReadFile (const Standard_CString theFile,
const Handle(Message_ProgressIndicator)& theProgress)
// constants
static const size_t HEADER_SIZE = 84;
static const size_t SIZEOF_STL_FACET = 50;
static const size_t ASCII_LINES_PER_FACET = 7;
static const int IND_THRESHOLD = 1000; // increment the indicator every 1k triangles
//=======================================================================
//function : WriteInteger
//purpose : writing a Little Endian 32 bits integer
//=======================================================================
inline static void WriteInteger(OSD_File& ofile,const Standard_Integer value)
{
Reader aReader;
if (!aReader.Read (theFile, theProgress))
{
return Handle(Poly_Triangulation)();
}
return aReader.GetTriangulation();
union {
Standard_Integer i;// don't be afraid, this is just an unsigned int
char c[4];
} bidargum;
bidargum.i = value;
Standard_Integer entier;
entier = bidargum.c[0] & 0xFF;
entier |= (bidargum.c[1] & 0xFF) << 0x08;
entier |= (bidargum.c[2] & 0xFF) << 0x10;
entier |= (bidargum.c[3] & 0xFF) << 0x18;
ofile.Write((char *)&entier,sizeof(bidargum.c));
}
//=============================================================================
//function : ReadFile
//purpose :
//=============================================================================
Handle(Poly_Triangulation) RWStl::ReadFile (const OSD_Path& theFile,
const Handle(Message_ProgressIndicator)& theProgress)
{
OSD_File aFile(theFile);
if (!aFile.Exists())
{
return Handle(Poly_Triangulation)();
}
//=======================================================================
//function : WriteDouble2Float
//purpose : writing a Little Endian 32 bits float
//=======================================================================
TCollection_AsciiString aPath;
theFile.SystemName (aPath);
return ReadFile (aPath.ToCString(), theProgress);
inline static void WriteDouble2Float(OSD_File& ofile,Standard_Real value)
{
union {
Standard_ShortReal f;
char c[4];
} bidargum;
bidargum.f = (Standard_ShortReal)value;
Standard_Integer entier;
entier = bidargum.c[0] & 0xFF;
entier |= (bidargum.c[1] & 0xFF) << 0x08;
entier |= (bidargum.c[2] & 0xFF) << 0x10;
entier |= (bidargum.c[3] & 0xFF) << 0x18;
ofile.Write((char *)&entier,sizeof(bidargum.c));
}
//=============================================================================
//function : ReadBinary
//purpose :
//=============================================================================
Handle(Poly_Triangulation) RWStl::ReadBinary (const OSD_Path& theFile,
const Handle(Message_ProgressIndicator)& theProgress)
//=======================================================================
//function : readFloat2Double
//purpose : reading a Little Endian 32 bits float
//=======================================================================
inline static Standard_Real ReadFloat2Double(OSD_File &aFile)
{
OSD_File aFile(theFile);
if (!aFile.Exists())
{
return Handle(Poly_Triangulation)();
}
union {
uint32_t i;
float f;
}bidargum;
TCollection_AsciiString aPath;
theFile.SystemName (aPath);
char c[4];
Standard_Address adr;
adr = (Standard_Address)c;
Standard_Integer lread;
aFile.Read(adr,4,lread);
bidargum.i = c[0] & 0xFF;
bidargum.i |= (c[1] & 0xFF) << 0x08;
bidargum.i |= (c[2] & 0xFF) << 0x10;
bidargum.i |= (c[3] & 0xFF) << 0x18;
std::filebuf aBuf;
OSD_OpenStream (aBuf, aPath, std::ios::in | std::ios::binary);
if (!aBuf.is_open())
{
return Handle(Poly_Triangulation)();
}
Standard_IStream aStream (&aBuf);
Reader aReader;
if (!aReader.ReadBinary (aStream, theProgress))
{
return Handle(Poly_Triangulation)();
}
return aReader.GetTriangulation();
return (Standard_Real)(bidargum.f);
}
//=============================================================================
//function : ReadAscii
//purpose :
//=============================================================================
Handle(Poly_Triangulation) RWStl::ReadAscii (const OSD_Path& theFile,
const Handle(Message_ProgressIndicator)& theProgress)
{
OSD_File aFile (theFile);
if (!aFile.Exists())
{
return Handle(Poly_Triangulation)();
}
TCollection_AsciiString aPath;
theFile.SystemName (aPath);
std::filebuf aBuf;
OSD_OpenStream (aBuf, aPath, std::ios::in | std::ios::binary);
if (!aBuf.is_open())
{
return Handle(Poly_Triangulation)();
}
Standard_IStream aStream (&aBuf);
//=======================================================================
//function : WriteBinary
//purpose : write a binary STL file in Little Endian format
//=======================================================================
// get length of file to feed progress indicator
aStream.seekg (0, aStream.end);
std::streampos theEnd = aStream.tellg();
aStream.seekg (0, aStream.beg);
Reader aReader;
if (!aReader.ReadAscii (aStream, theEnd, theProgress))
{
return Handle(Poly_Triangulation)();
}
return aReader.GetTriangulation();
}
//=============================================================================
//function : Write
//purpose :
//=============================================================================
Standard_Boolean RWStl::WriteBinary (const Handle(Poly_Triangulation)& aMesh,
Standard_Boolean RWStl::WriteBinary (const Handle(StlMesh_Mesh)& theMesh,
const OSD_Path& thePath,
const Handle(Message_ProgressIndicator)& theProgInd)
{
TCollection_AsciiString aPath;
thePath.SystemName (aPath);
OSD_File aFile (thePath);
aFile.Build (OSD_WriteOnly, OSD_Protection());
FILE* aFile = OSD_OpenFile (aPath, "wb");
if (aFile == NULL)
Standard_Real x1, y1, z1;
Standard_Real x2, y2, z2;
Standard_Real x3, y3, z3;
// writing 80 bytes of the trash?
char sval[80];
aFile.Write ((Standard_Address)sval,80);
WriteInteger (aFile, theMesh->NbTriangles());
int dum=0;
StlMesh_MeshExplorer aMexp (theMesh);
// create progress sentry for domains
Standard_Integer aNbDomains = theMesh->NbDomains();
Message_ProgressSentry aDPS (theProgInd, "Mesh domains", 0, aNbDomains, 1);
for (Standard_Integer nbd = 1; nbd <= aNbDomains && aDPS.More(); nbd++, aDPS.Next())
{
return Standard_False;
// create progress sentry for triangles in domain
Message_ProgressSentry aTPS (theProgInd, "Triangles", 0,
theMesh->NbTriangles (nbd), IND_THRESHOLD);
Standard_Integer aTriangleInd = 0;
for (aMexp.InitTriangle (nbd); aMexp.MoreTriangle(); aMexp.NextTriangle())
{
aMexp.TriangleVertices (x1,y1,z1,x2,y2,z2,x3,y3,z3);
//pgo aMexp.TriangleOrientation (x,y,z);
gp_XYZ Vect12 ((x2-x1), (y2-y1), (z2-z1));
gp_XYZ Vect13 ((x3-x1), (y3-y1), (z3-z1));
gp_XYZ Vnorm = Vect12 ^ Vect13;
Standard_Real Vmodul = Vnorm.Modulus ();
if (Vmodul > gp::Resolution())
{
Vnorm.Divide(Vmodul);
}
else
{
// si Vnorm est quasi-nul, on le charge a 0 explicitement
Vnorm.SetCoord (0., 0., 0.);
}
WriteDouble2Float (aFile, Vnorm.X());
WriteDouble2Float (aFile, Vnorm.Y());
WriteDouble2Float (aFile, Vnorm.Z());
WriteDouble2Float (aFile, x1);
WriteDouble2Float (aFile, y1);
WriteDouble2Float (aFile, z1);
WriteDouble2Float (aFile, x2);
WriteDouble2Float (aFile, y2);
WriteDouble2Float (aFile, z2);
WriteDouble2Float (aFile, x3);
WriteDouble2Float (aFile, y3);
WriteDouble2Float (aFile, z3);
aFile.Write (&dum, 2);
// update progress only per 1k triangles
if (++aTriangleInd % IND_THRESHOLD == 0)
{
if (!aTPS.More())
break;
aTPS.Next();
}
}
}
Standard_Boolean isOK = writeBinary (aMesh, aFile, theProgInd);
fclose (aFile);
return isOK;
aFile.Close();
Standard_Boolean isInterrupted = !aDPS.More();
return !isInterrupted;
}
//=======================================================================
//function : WriteAscii
//purpose : write an ASCII STL file
//=======================================================================
//=============================================================================
//function : Write
//purpose :
//=============================================================================
Standard_Boolean RWStl::WriteAscii (const Handle(Poly_Triangulation)& theMesh,
Standard_Boolean RWStl::WriteAscii (const Handle(StlMesh_Mesh)& theMesh,
const OSD_Path& thePath,
const Handle(Message_ProgressIndicator)& theProgInd)
{
TCollection_AsciiString aPath;
thePath.SystemName (aPath);
OSD_File theFile (thePath);
theFile.Build(OSD_WriteOnly,OSD_Protection());
TCollection_AsciiString buf ("solid\n");
theFile.Write (buf,buf.Length());buf.Clear();
FILE* aFile = OSD_OpenFile (aPath, "w");
if (aFile == NULL)
Standard_Real x1, y1, z1;
Standard_Real x2, y2, z2;
Standard_Real x3, y3, z3;
char sval[512];
// create progress sentry for domains
Standard_Integer aNbDomains = theMesh->NbDomains();
Message_ProgressSentry aDPS (theProgInd, "Mesh domains", 0, aNbDomains, 1);
StlMesh_MeshExplorer aMexp (theMesh);
for (Standard_Integer nbd = 1; nbd <= aNbDomains && aDPS.More(); nbd++, aDPS.Next())
{
return Standard_False;
}
Standard_Boolean isOK = writeASCII (theMesh, aFile, theProgInd);
fclose (aFile);
return isOK;
}
//=============================================================================
//function : writeASCII
//purpose :
//=============================================================================
Standard_Boolean RWStl::writeASCII (const Handle(Poly_Triangulation)& theMesh,
FILE* theFile,
const Handle(Message_ProgressIndicator)& theProgInd)
{
// note that space after 'solid' is necessary for many systems
if (fwrite ("solid \n", 1, 7, theFile) != 7)
{
return Standard_False;
}
char aBuffer[512];
memset (aBuffer, 0, sizeof(aBuffer));
Message_ProgressSentry aPS (theProgInd, "Triangles", 0,
theMesh->NbTriangles(), IND_THRESHOLD);
const TColgp_Array1OfPnt& aNodes = theMesh->Nodes();
const Poly_Array1OfTriangle& aTriangles = theMesh->Triangles();
const Standard_Integer NBTriangles = theMesh->NbTriangles();
Standard_Integer anElem[3] = {0, 0, 0};
for (Standard_Integer aTriIter = 1; aTriIter <= NBTriangles; ++aTriIter)
{
const Poly_Triangle& aTriangle = aTriangles (aTriIter);
aTriangle.Get (anElem[0], anElem[1], anElem[2]);
const gp_Pnt aP1 = aNodes (anElem[0]);
const gp_Pnt aP2 = aNodes (anElem[1]);
const gp_Pnt aP3 = aNodes (anElem[2]);
const gp_Vec aVec1 (aP1, aP2);
const gp_Vec aVec2 (aP1, aP3);
gp_Vec aVNorm = aVec1.Crossed (aVec2);
if (aVNorm.SquareMagnitude() > gp::Resolution())
// create progress sentry for triangles in domain
Message_ProgressSentry aTPS (theProgInd, "Triangles", 0,
theMesh->NbTriangles (nbd), IND_THRESHOLD);
Standard_Integer aTriangleInd = 0;
for (aMexp.InitTriangle (nbd); aMexp.MoreTriangle(); aMexp.NextTriangle())
{
aVNorm.Normalize();
}
else
{
aVNorm.SetCoord (0.0, 0.0, 0.0);
}
aMexp.TriangleVertices (x1,y1,z1,x2,y2,z2,x3,y3,z3);
Sprintf (aBuffer,
// Standard_Real x, y, z;
// aMexp.TriangleOrientation (x,y,z);
gp_XYZ Vect12 ((x2-x1), (y2-y1), (z2-z1));
gp_XYZ Vect23 ((x3-x2), (y3-y2), (z3-z2));
gp_XYZ Vnorm = Vect12 ^ Vect23;
Standard_Real Vmodul = Vnorm.Modulus ();
if (Vmodul > gp::Resolution())
{
Vnorm.Divide (Vmodul);
}
else
{
// si Vnorm est quasi-nul, on le charge a 0 explicitement
Vnorm.SetCoord (0., 0., 0.);
}
Sprintf (sval,
" facet normal % 12e % 12e % 12e\n"
" outer loop\n"
" vertex % 12e % 12e % 12e\n"
@@ -303,132 +287,270 @@ Standard_Boolean RWStl::writeASCII (const Handle(Poly_Triangulation)& theMesh,
" vertex % 12e % 12e % 12e\n"
" endloop\n"
" endfacet\n",
aVNorm.X(), aVNorm.Y(), aVNorm.Z(),
aP1.X(), aP1.Y(), aP1.Z(),
aP2.X(), aP2.Y(), aP2.Z(),
aP3.X(), aP3.Y(), aP3.Z());
Vnorm.X(), Vnorm.Y(), Vnorm.Z(),
x1, y1, z1,
x2, y2, z2,
x3, y3, z3);
buf += sval;
theFile.Write (buf, buf.Length()); buf.Clear();
if (fprintf (theFile, "%s", aBuffer) < 0)
{
return Standard_False;
}
// update progress only per 1k triangles
if ((aTriIter % IND_THRESHOLD) == 0)
{
aPS.Next();
// update progress only per 1k triangles
if (++aTriangleInd % IND_THRESHOLD == 0)
{
if (!aTPS.More())
break;
aTPS.Next();
}
}
}
if (fwrite ("endsolid\n", 1, 9, theFile) != 9)
{
return Standard_False;
}
return Standard_True;
buf += "endsolid\n";
theFile.Write (buf, buf.Length()); buf.Clear();
theFile.Close();
Standard_Boolean isInterrupted = !aDPS.More();
return !isInterrupted;
}
//=======================================================================
//function : ReadFile
//Design :
//Warning :
//=======================================================================
//=============================================================================
//function : writeBinary
//purpose :
//=============================================================================
Standard_Boolean RWStl::writeBinary (const Handle(Poly_Triangulation)& theMesh,
FILE* theFile,
Handle(StlMesh_Mesh) RWStl::ReadFile (const OSD_Path& thePath,
const Handle(Message_ProgressIndicator)& theProgInd)
{
char aHeader[80] = "STL Exported by OpenCASCADE [www.opencascade.com]";
if (fwrite (aHeader, 1, 80, theFile) != 80)
OSD_File file (thePath);
file.Open(OSD_ReadOnly,OSD_Protection(OSD_RWD,OSD_RWD,OSD_RWD,OSD_RWD));
Standard_Boolean IsAscii;
unsigned char str[128];
Standard_Integer lread,i;
Standard_Address ach;
ach = (Standard_Address)str;
// we skip the header which is in Ascii for both modes
file.Read(ach,HEADER_SIZE,lread);
// we read 128 characters to detect if we have a non-ascii char
file.Read(ach,sizeof(str),lread);
IsAscii = Standard_True;
for (i = 0; i< lread && IsAscii; ++i) {
if (str[i] > '~') {
IsAscii = Standard_False;
}
}
#ifdef OCCT_DEBUG
cout << (IsAscii ? "ascii\n" : "binary\n");
#endif
file.Close();
return IsAscii ? RWStl::ReadAscii (thePath, theProgInd)
: RWStl::ReadBinary (thePath, theProgInd);
}
//=======================================================================
//function : ReadBinary
//Design :
//Warning :
//=======================================================================
Handle(StlMesh_Mesh) RWStl::ReadBinary (const OSD_Path& thePath,
const Handle(Message_ProgressIndicator)& /*theProgInd*/)
{
Standard_Integer ifacet;
Standard_Real fx,fy,fz,fx1,fy1,fz1,fx2,fy2,fz2,fx3,fy3,fz3;
Standard_Integer i1,i2,i3,lread;
char buftest[5];
Standard_Address adr;
adr = (Standard_Address)buftest;
// Open the file
OSD_File theFile (thePath);
theFile.Open(OSD_ReadOnly,OSD_Protection(OSD_RWD,OSD_RWD,OSD_RWD,OSD_RWD));
// the size of the file (minus the header size)
// must be a multiple of SIZEOF_STL_FACET
// compute file size
Standard_Size filesize = theFile.Size();
// don't trust the number of triangles which is coded in the file sometimes it is wrong
Standard_Integer NBFACET = (Standard_Integer)((filesize - HEADER_SIZE) / SIZEOF_STL_FACET);
if (NBFACET < 1)
{
return Standard_False;
throw Standard_NoMoreObject("RWStl::ReadBinary (wrong file size)");
}
Message_ProgressSentry aPS (theProgInd, "Triangles", 0,
theMesh->NbTriangles(), IND_THRESHOLD);
const Standard_Size aNbChunkTriangles = 4096;
const Standard_Size aChunkSize = aNbChunkTriangles * THE_STL_SIZEOF_FACET;
NCollection_Array1<Standard_Character> aData (1, aChunkSize);
Standard_Character* aDataChunk = &aData.ChangeFirst();
const TColgp_Array1OfPnt& aNodes = theMesh->Nodes();
const Poly_Array1OfTriangle& aTriangles = theMesh->Triangles();
const Standard_Integer aNBTriangles = theMesh->NbTriangles();
Standard_Character aConv[4];
convertInteger (aNBTriangles, aConv);
if (fwrite (aConv, 1, 4, theFile) != 4)
theFile.Seek (80, OSD_FromBeginning);
theFile.Read (adr, 4, lread);
Standard_Integer aNbTrisInHeader = (((char* )buftest)[3] << 24) | (((Standard_Byte* )buftest)[2] << 16)
| (((Standard_Byte* )buftest)[1] << 8 ) | (((Standard_Byte* )buftest)[0] << 0 );
if (NBFACET < aNbTrisInHeader)
{
return Standard_False;
Message::DefaultMessenger()->Send (TCollection_AsciiString ("RWStl - Binary STL file defines more triangles (") + aNbTrisInHeader
+ ") that can be read (" + NBFACET + ") - probably corrupted file",
Message_Warning);
}
else if (NBFACET > aNbTrisInHeader)
{
Message::DefaultMessenger()->Send (TCollection_AsciiString ("RWStl - Binary STL file defines less triangles (") + aNbTrisInHeader
+ ") that can be read (" + NBFACET + ") - probably corrupted file",
Message_Warning);
}
else if ((filesize - HEADER_SIZE) % SIZEOF_STL_FACET != 0)
{
Message::DefaultMessenger()->Send (TCollection_AsciiString ("RWStl - Binary STL file has unidentified tail"),
Message_Warning);
}
Standard_Size aByteCount = 0;
for (Standard_Integer aTriIter = 1; aTriIter <= aNBTriangles; ++aTriIter)
// skip the header
theFile.Seek(HEADER_SIZE,OSD_FromBeginning);
// create the StlMesh_Mesh object
Handle(StlMesh_Mesh) ReadMesh = new StlMesh_Mesh ();
ReadMesh->AddDomain ();
// Filter unique vertices to share the nodes of the mesh.
BRepBuilderAPI_CellFilter uniqueVertices(Precision::Confusion());
BRepBuilderAPI_VertexInspector inspector(Precision::Confusion());
for (ifacet=1; ifacet<=NBFACET; ++ifacet) {
// read normal coordinates
fx = ReadFloat2Double(theFile);
fy = ReadFloat2Double(theFile);
fz = ReadFloat2Double(theFile);
// read vertex 1
fx1 = ReadFloat2Double(theFile);
fy1 = ReadFloat2Double(theFile);
fz1 = ReadFloat2Double(theFile);
// read vertex 2
fx2 = ReadFloat2Double(theFile);
fy2 = ReadFloat2Double(theFile);
fz2 = ReadFloat2Double(theFile);
// read vertex 3
fx3 = ReadFloat2Double(theFile);
fy3 = ReadFloat2Double(theFile);
fz3 = ReadFloat2Double(theFile);
// Add vertices.
i1 = AddVertex(ReadMesh, uniqueVertices, inspector, gp_XYZ(fx1, fy1, fz1));
i2 = AddVertex(ReadMesh, uniqueVertices, inspector, gp_XYZ(fx2, fy2, fz2));
i3 = AddVertex(ReadMesh, uniqueVertices, inspector, gp_XYZ(fx3, fy3, fz3));
// Add triangle.
ReadMesh->AddTriangle (i1,i2,i3,fx,fy,fz);
// skip extra bytes
theFile.Read(adr,2,lread);
}
theFile.Close ();
return ReadMesh;
}
//=======================================================================
//function : ReadAscii
//Design :
//Warning :
//=======================================================================
Handle(StlMesh_Mesh) RWStl::ReadAscii (const OSD_Path& thePath,
const Handle(Message_ProgressIndicator)& theProgInd)
{
TCollection_AsciiString filename;
long ipos;
Standard_Integer nbLines = 0;
Standard_Integer nbTris = 0;
Standard_Integer iTri;
Standard_Integer i1,i2,i3;
Handle(StlMesh_Mesh) ReadMesh;
thePath.SystemName (filename);
// Open the file
FILE* file = OSD_OpenFile(filename.ToCString(),"r");
fseek(file,0L,SEEK_END);
long filesize = ftell(file);
rewind(file);
// count the number of lines
for (ipos = 0; ipos < filesize; ++ipos) {
if (getc(file) == '\n')
nbLines++;
}
// compute number of triangles
nbTris = (nbLines / ASCII_LINES_PER_FACET);
// go back to the beginning of the file
rewind(file);
// skip header
while (getc(file) != '\n');
#ifdef OCCT_DEBUG
cout << "start mesh\n";
#endif
ReadMesh = new StlMesh_Mesh();
ReadMesh->AddDomain();
// Filter unique vertices to share the nodes of the mesh.
BRepBuilderAPI_CellFilter uniqueVertices(Precision::Confusion());
BRepBuilderAPI_VertexInspector inspector(Precision::Confusion());
// main reading
Message_ProgressSentry aPS (theProgInd, "Triangles", 0, (nbTris - 1) * 1.0 / IND_THRESHOLD, 1);
for (iTri = 0; iTri < nbTris && aPS.More();)
{
Standard_Integer id[3];
const Poly_Triangle& aTriangle = aTriangles (aTriIter);
aTriangle.Get (id[0], id[1], id[2]);
char x[256]="", y[256]="", z[256]="";
const gp_Pnt aP1 = aNodes (id[0]);
const gp_Pnt aP2 = aNodes (id[1]);
const gp_Pnt aP3 = aNodes (id[2]);
// reading the facet normal
if (3 != fscanf(file,"%*s %*s %80s %80s %80s\n", x, y, z))
break; // error should be properly reported
gp_XYZ aN (Atof(x), Atof(y), Atof(z));
gp_Vec aVec1 (aP1, aP2);
gp_Vec aVec2 (aP1, aP3);
gp_Vec aVNorm = aVec1.Crossed(aVec2);
if (aVNorm.SquareMagnitude() > gp::Resolution())
{
aVNorm.Normalize();
}
else
{
aVNorm.SetCoord (0.0, 0.0, 0.0);
}
// skip the keywords "outer loop"
if (fscanf(file,"%*s %*s") < 0)
break;
convertDouble (aVNorm.X(), &aDataChunk[aByteCount]); aByteCount += 4;
convertDouble (aVNorm.Y(), &aDataChunk[aByteCount]); aByteCount += 4;
convertDouble (aVNorm.Z(), &aDataChunk[aByteCount]); aByteCount += 4;
// reading vertex
if (3 != fscanf(file,"%*s %80s %80s %80s\n", x, y, z))
break; // error should be properly reported
gp_XYZ aV1 (Atof(x), Atof(y), Atof(z));
if (3 != fscanf(file,"%*s %80s %80s %80s\n", x, y, z))
break; // error should be properly reported
gp_XYZ aV2 (Atof(x), Atof(y), Atof(z));
if (3 != fscanf(file,"%*s %80s %80s %80s\n", x, y, z))
break; // error should be properly reported
gp_XYZ aV3 (Atof(x), Atof(y), Atof(z));
convertDouble (aP1.X(), &aDataChunk[aByteCount]); aByteCount += 4;
convertDouble (aP1.Y(), &aDataChunk[aByteCount]); aByteCount += 4;
convertDouble (aP1.Z(), &aDataChunk[aByteCount]); aByteCount += 4;
// here the facet must be built and put in the mesh datastructure
convertDouble (aP2.X(), &aDataChunk[aByteCount]); aByteCount += 4;
convertDouble (aP2.Y(), &aDataChunk[aByteCount]); aByteCount += 4;
convertDouble (aP2.Z(), &aDataChunk[aByteCount]); aByteCount += 4;
i1 = AddVertex(ReadMesh, uniqueVertices, inspector, aV1);
i2 = AddVertex(ReadMesh, uniqueVertices, inspector, aV2);
i3 = AddVertex(ReadMesh, uniqueVertices, inspector, aV3);
ReadMesh->AddTriangle (i1, i2, i3, aN.X(), aN.Y(), aN.Z());
convertDouble (aP3.X(), &aDataChunk[aByteCount]); aByteCount += 4;
convertDouble (aP3.Y(), &aDataChunk[aByteCount]); aByteCount += 4;
convertDouble (aP3.Z(), &aDataChunk[aByteCount]); aByteCount += 4;
// skip the keywords "endloop"
if (fscanf(file,"%*s") < 0)
break;
aDataChunk[aByteCount] = 0; aByteCount += 1;
aDataChunk[aByteCount] = 0; aByteCount += 1;
// Chunk is filled. Dump it to the file.
if (aByteCount == aChunkSize)
{
if (fwrite (aDataChunk, 1, aChunkSize, theFile) != aChunkSize)
{
return Standard_False;
}
aByteCount = 0;
}
// skip the keywords "endfacet"
if (fscanf(file,"%*s") < 0)
break;
// update progress only per 1k triangles
if ((aTriIter % IND_THRESHOLD) == 0)
{
if (++iTri % IND_THRESHOLD == 0)
aPS.Next();
}
}
// Write last part if necessary.
if (aByteCount != aChunkSize)
{
if (fwrite (aDataChunk, 1, aByteCount, theFile) != aByteCount)
{
return Standard_False;
}
}
return Standard_True;
#ifdef OCCT_DEBUG
cout << "end mesh\n";
#endif
fclose(file);
return ReadMesh;
}

View File

@@ -1,6 +1,7 @@
// Created on: 2017-06-13
// Created by: Alexander MALYSHEV
// Copyright (c) 2017 OPEN CASCADE SAS
// Created on: 1994-10-13
// Created by: Marc LEGAY
// Copyright (c) 1994-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
@@ -16,61 +17,85 @@
#ifndef _RWStl_HeaderFile
#define _RWStl_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <Message_ProgressIndicator.hxx>
#include <OSD_Path.hxx>
#include <Poly_Triangulation.hxx>
#include <Standard_Macro.hxx>
//! This class provides methods to read and write triangulation from / to the STL files.
class RWStl
class StlMesh_Mesh;
class OSD_Path;
//! This package contains the methods to be used in
//! the Stereo Lithograpy Application. The main
//! features of this application are ,starting from a
//! Shape :
//! - mesh this shape with a maximun tolerance,
//! - display the meshing,
//! - write the meshing in a file (binary or ascii),
//! - read of file (binary or ascii) and display it,
//! - translate a binary file to an ascii file,
//! - translate an ascii file to an binary file.
class RWStl
{
public:
//! Write triangulation to binary STL file.
DEFINE_STANDARD_ALLOC
//! write the meshing in a file following the
//! binary format of an STL file.
//! Returns false if the cannot be opened;
Standard_EXPORT static Standard_Boolean WriteBinary (const Handle(Poly_Triangulation)& theMesh,
const OSD_Path& thePath,
const Handle(Message_ProgressIndicator)& theProgInd = Handle(Message_ProgressIndicator)());
Standard_EXPORT static Standard_Boolean WriteBinary (const Handle(StlMesh_Mesh)& aMesh, const OSD_Path& aPath, const Handle(Message_ProgressIndicator)& aProgInd = NULL);
//! write the meshing in a file following the
//! Ascii format of an STL file.
//! Returns false if the cannot be opened;
Standard_EXPORT static Standard_Boolean WriteAscii (const Handle(Poly_Triangulation)& theMesh,
const OSD_Path& thePath,
const Handle(Message_ProgressIndicator)& theProgInd = Handle(Message_ProgressIndicator)());
Standard_EXPORT static Standard_Boolean WriteAscii (const Handle(StlMesh_Mesh)& aMesh, const OSD_Path& aPath, const Handle(Message_ProgressIndicator)& aProgInd = NULL);
//! Read specified STL file and returns its content as triangulation.
//! In case of error, returns Null handle.
Standard_EXPORT static Handle(Poly_Triangulation) ReadFile (const OSD_Path& theFile,
const Handle(Message_ProgressIndicator)& aProgInd = Handle(Message_ProgressIndicator)());
//! Read specified STL file and returns its content as triangulation.
//! In case of error, returns Null handle.
Standard_EXPORT static Handle(Poly_Triangulation) ReadFile (const Standard_CString theFile,
const Handle(Message_ProgressIndicator)& aProgInd = Handle(Message_ProgressIndicator)());
//! Read triangulation from a binary STL file
//! In case of error, returns Null handle.
Standard_EXPORT static Handle(Poly_Triangulation) ReadBinary (const OSD_Path& thePath,
const Handle(Message_ProgressIndicator)& theProgInd = Handle(Message_ProgressIndicator)());
//! This method will chwck if the file is a binary
//! file or an AsciiFile testing the 5 first
//! characters of the file wich are :"solid" in an
//! ascii file. If we do not find that word we assume
//! that it is a binary file.
Standard_EXPORT static Handle(StlMesh_Mesh) ReadFile (const OSD_Path& aPath, const Handle(Message_ProgressIndicator)& aProgInd = NULL);
//! Read triangulation from an Ascii STL file
//! In case of error, returns Null handle.
Standard_EXPORT static Handle(Poly_Triangulation) ReadAscii (const OSD_Path& thePath,
const Handle(Message_ProgressIndicator)& theProgInd = Handle(Message_ProgressIndicator)());
//! Read a meshing from a binary file
//! Raises NoMoreObject from Standard if a statement
//! does not contain the right number of tokens
//! Raises TypeMisMatch if a token has not the good
//! type (often real)
Standard_EXPORT static Handle(StlMesh_Mesh) ReadBinary (const OSD_Path& aPath, const Handle(Message_ProgressIndicator)& aProgInd = NULL);
//! Read a meshing from a binary file
//! Raises NoMoreObject from Standard if a statement
//! does not contain the right number of tokens
//! Raises TypeMisMatch if a token has not the good
//! type (often real)
//! Raises MoMoreObject if a file is finished before
//! having found the word endsolid;
Standard_EXPORT static Handle(StlMesh_Mesh) ReadAscii (const OSD_Path& aPath, const Handle(Message_ProgressIndicator)& aProgInd = NULL);
protected:
private:
//! Write ASCII version.
static Standard_Boolean writeASCII (const Handle(Poly_Triangulation)& theMesh,
FILE *theFile,
const Handle(Message_ProgressIndicator)& theProgInd);
//! Write binary version.
static Standard_Boolean writeBinary (const Handle(Poly_Triangulation)& theMesh,
FILE *theFile,
const Handle(Message_ProgressIndicator)& theProgInd);
};
#endif
#endif // _RWStl_HeaderFile

View File

@@ -1,420 +0,0 @@
// Created: 2016-05-01
// Author: Andrey Betenev
// Copyright: Open CASCADE 2016
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <RWStl_Reader.hxx>
#include <gp_XY.hxx>
#include <Message.hxx>
#include <Message_Messenger.hxx>
#include <Message_ProgressSentry.hxx>
#include <NCollection_DataMap.hxx>
#include <NCollection_IncAllocator.hxx>
#include <FSD_BinaryFile.hxx>
#include <OSD_OpenFile.hxx>
#include <OSD_Timer.hxx>
#include <Precision.hxx>
#include <Standard_CLocaleSentry.hxx>
#include <algorithm>
#include <limits>
IMPLEMENT_STANDARD_RTTIEXT(RWStl_Reader, Standard_Transient)
namespace
{
// Binary STL sizes
static const size_t THE_STL_HEADER_SIZE = 84;
static const size_t THE_STL_SIZEOF_FACET = 50;
static const size_t THE_STL_MIN_FILE_SIZE = THE_STL_HEADER_SIZE + THE_STL_SIZEOF_FACET;
//! Auxiliary tool for merging nodes during STL reading.
class MergeNodeTool
{
public:
//! Constructor
MergeNodeTool (RWStl_Reader* theReader)
: myReader (theReader),
myMap (1024, new NCollection_IncAllocator (1024 * 1024))
{
}
//! Add new triangle
int AddNode (double theX, double theY, double theZ)
{
// use existing node if found at the same point
gp_XYZ aPnt (theX, theY, theZ);
Standard_Integer anIndex = -1;
if (myMap.Find (aPnt, anIndex))
{
return anIndex;
}
anIndex = myReader->AddNode (aPnt);
myMap.Bind (aPnt, anIndex);
return anIndex;
}
public:
static Standard_Boolean IsEqual (const gp_XYZ& thePnt1, const gp_XYZ& thePnt2)
{
return (thePnt1 - thePnt2).SquareModulus() < Precision::SquareConfusion();
}
static Standard_Integer HashCode (const gp_XYZ& thePnt, Standard_Integer theUpper)
{
return ::HashCode (thePnt.X() * M_LN10 + thePnt.Y() * M_PI + thePnt.Z() * M_E, theUpper);
}
private:
RWStl_Reader* myReader;
NCollection_DataMap<gp_XYZ, Standard_Integer, MergeNodeTool> myMap;
};
//! Read a Little Endian 32 bits float
inline static float readStlFloat (const char* theData)
{
#if OCCT_BINARY_FILE_DO_INVERSE
// on big-endian platform, map values byte-per-byte
union
{
uint32_t i;
float f;
} bidargum;
bidargum.i = theData[0] & 0xFF;
bidargum.i |= (theData[1] & 0xFF) << 0x08;
bidargum.i |= (theData[2] & 0xFF) << 0x10;
bidargum.i |= (theData[3] & 0xFF) << 0x18;
return bidargum.f;
#else
// on little-endian platform, use plain cast
return *reinterpret_cast<const float*>(theData);
#endif
}
//! Read a Little Endian 32 bits float
inline static gp_XYZ readStlFloatVec3 (const char* theData)
{
return gp_XYZ (readStlFloat (theData),
readStlFloat (theData + sizeof(float)),
readStlFloat (theData + sizeof(float) * 2));
}
}
//==============================================================================
//function : Read
//purpose :
//==============================================================================
Standard_Boolean RWStl_Reader::Read (const char* theFile,
const Handle(Message_ProgressIndicator)& theProgress)
{
std::filebuf aBuf;
OSD_OpenStream (aBuf, theFile, std::ios::in | std::ios::binary);
if (!aBuf.is_open())
{
return Standard_False;
}
Standard_IStream aStream (&aBuf);
// get length of file to feed progress indicator in Ascii mode
aStream.seekg (0, aStream.end);
std::streampos theEnd = aStream.tellg();
aStream.seekg (0, aStream.beg);
while (!aStream.eof() && !aStream.bad())
{
if (IsAscii (aStream))
{
if (!ReadAscii (aStream, theEnd, theProgress))
{
break;
}
}
else
{
if (!ReadBinary (aStream, theProgress))
{
break;
}
}
aStream >> std::ws; // skip any white spaces
}
return !aStream.bad();
}
//==============================================================================
//function : IsAscii
//purpose :
//==============================================================================
Standard_Boolean RWStl_Reader::IsAscii (Standard_IStream& theStream)
{
// read first 134 bytes to detect file format
char aBuffer[THE_STL_MIN_FILE_SIZE];
std::streamsize aNbRead = theStream.read (aBuffer, THE_STL_MIN_FILE_SIZE).gcount();
if (!theStream)
{
Message::DefaultMessenger()->Send ("Error: Cannot read file", Message_Fail);
return false;
}
// put back the read symbols
for (std::streamsize aByteIter = aNbRead; aByteIter > 0; --aByteIter)
{
theStream.unget();
}
// if file is shorter than size of binary file with 1 facet, it must be ascii
if (aNbRead < std::streamsize(THE_STL_MIN_FILE_SIZE))
{
return true;
}
// otherwise, detect binary format by presence of non-ascii symbols in first 128 bytes
// (note that binary STL file may start with the same bytes "solid " as Ascii one)
for (Standard_Integer aByteIter = 0; aByteIter < aNbRead; ++aByteIter)
{
if ((unsigned char )aBuffer[aByteIter] > (unsigned char )'~')
{
return false;
}
}
return true;
}
// adapted from Standard_CString.cxx
#ifdef __APPLE__
// There are a lot of *_l functions availalbe on Mac OS X - we use them
#define SAVE_TL()
#elif defined(_MSC_VER)
// MSVCRT has equivalents with slightly different syntax
#define SAVE_TL()
#define sscanf_l(theBuffer, theLocale, theFormat, ...) _sscanf_s_l(theBuffer, theFormat, theLocale, __VA_ARGS__)
#else
// glibc provides only limited xlocale implementation:
// strtod_l/strtol_l/strtoll_l functions with explicitly specified locale
// and newlocale/uselocale/freelocale to switch locale within current thread only.
// So we switch to C locale temporarily
#define SAVE_TL() Standard_CLocaleSentry aLocaleSentry;
#define sscanf_l(theBuffer, theLocale, theFormat, ...) sscanf(theBuffer, theFormat, __VA_ARGS__)
#endif
// Macro to get 64-bit position of the file from streampos
#if defined(_MSC_VER)
#define GETPOS(aPos) aPos.seekpos()
#else
#define GETPOS(aPos) ((int64_t)aPos)
#endif
static inline bool str_starts_with (const char* theStr, const char* theWord, int theN)
{
while (isspace (*theStr) && *theStr != '\0') theStr++;
return !strncmp (theStr, theWord, theN);
}
//==============================================================================
//function : ReadAscii
//purpose :
//==============================================================================
Standard_Boolean RWStl_Reader::ReadAscii (Standard_IStream& theStream,
const std::streampos theUntilPos,
const Handle(Message_ProgressIndicator)& theProgress)
{
// use method seekpos() to get true 64-bit offset to enable
// handling of large files (VS 2010 64-bit)
const int64_t aStartPos = GETPOS(theStream.tellg());
const int64_t aEndPos = (theUntilPos > 0 ? GETPOS(theUntilPos) : std::numeric_limits<int64_t>::max());
// skip header "solid ..."
theStream.ignore (aEndPos - aStartPos, '\n');
if (!theStream)
{
Message::DefaultMessenger()->Send ("Error: premature end of file", Message_Fail);
return false;
}
MergeNodeTool aMergeTool (this);
Standard_CLocaleSentry::clocale_t aLocale = Standard_CLocaleSentry::GetCLocale();
(void)aLocale; // to avoid warning on GCC where it is actually not used
SAVE_TL() // for GCC only, set C locale globally
// report progress every 1 MiB of read data
const int aStepB = 1024 * 1024;
const Standard_Integer aNbSteps = 1 + Standard_Integer((theUntilPos - aStartPos) / aStepB);
Message_ProgressSentry aPSentry (theProgress, "Reading text STL file", 0, aNbSteps, 1);
int64_t aProgressPos = aStartPos + aStepB;
const int64_t LINELEN = 1024;
int aNbLine = 1;
char aLine1[LINELEN], aLine2[LINELEN], aLine3[LINELEN];
while (aPSentry.More())
{
if (GETPOS(theStream.tellg()) > aProgressPos)
{
aPSentry.Next();
aProgressPos += aStepB;
}
char facet[LINELEN], outer[LINELEN];
theStream.getline (facet, std::min (LINELEN, aEndPos - GETPOS(theStream.tellg()))); // "facet normal nx ny nz"
if (str_starts_with (facet, "endsolid", 8))
{
// end of STL code
break;
}
theStream.getline (outer, std::min (LINELEN, aEndPos - GETPOS(theStream.tellg()))); // "outer loop"
if (!str_starts_with (facet, "facet", 5) || !str_starts_with (outer, "outer", 5))
{
TCollection_AsciiString aStr ("Error: unexpected format of facet at line ");
aStr += aNbLine + 1;
Message::DefaultMessenger()->Send (aStr, Message_Fail);
return false;
}
theStream.getline (aLine1, std::min (LINELEN, aEndPos - GETPOS(theStream.tellg())));
theStream.getline (aLine2, std::min (LINELEN, aEndPos - GETPOS(theStream.tellg())));
theStream.getline (aLine3, std::min (LINELEN, aEndPos - GETPOS(theStream.tellg())));
// stop reading if end of file is reached;
// note that well-formatted file never ends by the vertex line
if (theStream.eof() || GETPOS(theStream.tellg()) >= aEndPos)
{
break;
}
if (!theStream)
{
Message::DefaultMessenger()->Send ("Error: premature end of file", Message_Fail);
return false;
}
aNbLine += 5;
Standard_Real x1, y1, z1, x2, y2, z2, x3, y3, z3;
Standard_Integer aReadCount = // read 3 lines "vertex x y z"
sscanf_l (aLine1, aLocale, "%*s %lf %lf %lf", &x1, &y1, &z1) +
sscanf_l (aLine2, aLocale, "%*s %lf %lf %lf", &x2, &y2, &z2) +
sscanf_l (aLine3, aLocale, "%*s %lf %lf %lf", &x3, &y3, &z3);
if (aReadCount != 9)
{
TCollection_AsciiString aStr ("Error: cannot read vertex co-ordinates at line ");
aStr += aNbLine;
Message::DefaultMessenger()->Send(aStr, Message_Fail);
return false;
}
// add triangle
int n1 = aMergeTool.AddNode (x1, y1, z1);
int n2 = aMergeTool.AddNode (x2, y2, z2);
int n3 = aMergeTool.AddNode (x3, y3, z3);
if (n1 != n2 && n2 != n3 && n3 != n1)
{
AddTriangle (n1, n2, n3);
}
theStream.ignore (aEndPos - GETPOS(theStream.tellg()), '\n'); // skip "endloop"
theStream.ignore (aEndPos - GETPOS(theStream.tellg()), '\n'); // skip "endfacet"
aNbLine += 2;
}
return aPSentry.More();
}
//==============================================================================
//function : readStlBinary
//purpose :
//==============================================================================
Standard_Boolean RWStl_Reader::ReadBinary (Standard_IStream& theStream,
const Handle(Message_ProgressIndicator)& theProgress)
{
/*
// the size of the file (minus the header size)
// must be a multiple of SIZEOF_STL_FACET
if ((theFileLen - THE_STL_HEADER_SIZE) % THE_STL_SIZEOF_FACET != 0
|| (theFileLen < THE_STL_MIN_FILE_SIZE))
{
Message::DefaultMessenger()->Send ("Error: Corrupted binary STL file (inconsistent file size)!", Message_Fail);
return Standard_False;
}
const Standard_Integer aNbFacets = Standard_Integer((theFileLen - THE_STL_HEADER_SIZE) / THE_STL_SIZEOF_FACET);
*/
// read file header at first
char aHeader[THE_STL_HEADER_SIZE + 1];
if (theStream.read (aHeader, THE_STL_HEADER_SIZE).gcount() != std::streamsize(THE_STL_HEADER_SIZE))
{
Message::DefaultMessenger()->Send ("Error: Corrupted binary STL file!", Message_Fail);
return false;
}
// number of facets is stored as 32-bit integer at position 80
const Standard_Integer aNbFacets = *(int32_t*)(aHeader + 80);
MergeNodeTool aMergeTool (this);
// don't trust the number of triangles which is coded in the file
// sometimes it is wrong, and with this technique we don't need to swap endians for integer
Message_ProgressSentry aPSentry (theProgress, "Reading binary STL file", 0, aNbFacets, 1);
Standard_Integer aNbRead = 0;
// allocate buffer for 80 triangles
const int THE_CHUNK_NBFACETS = 80;
char aBuffer[THE_STL_SIZEOF_FACET * THE_CHUNK_NBFACETS];
// normal + 3 nodes + 2 extra bytes
const size_t aVec3Size = sizeof(float) * 3;
const size_t aFaceDataLen = aVec3Size * 4 + 2;
const char* aBufferPtr = aBuffer;
Standard_Integer aNbFacesInBuffer = 0;
for (Standard_Integer aNbFacetRead = 0; aNbFacetRead < aNbFacets && aPSentry.More();
++aNbFacetRead, ++aNbRead, --aNbFacesInBuffer, aBufferPtr += aFaceDataLen, aPSentry.Next())
{
// read more data
if (aNbFacesInBuffer <= 0)
{
aNbFacesInBuffer = Min (THE_CHUNK_NBFACETS, aNbFacets - aNbFacetRead);
const std::streamsize aDataToRead = aNbFacesInBuffer * aFaceDataLen;
if (theStream.read (aBuffer, aDataToRead).gcount() != aDataToRead)
{
Message::DefaultMessenger()->Send ("Error: read filed", Message_Fail);
return false;
}
aBufferPtr = aBuffer;
}
// get points from buffer
// readStlFloatVec3 (aBufferPtr); // skip normal
gp_XYZ aP1 = readStlFloatVec3 (aBufferPtr + aVec3Size);
gp_XYZ aP2 = readStlFloatVec3 (aBufferPtr + aVec3Size * 2);
gp_XYZ aP3 = readStlFloatVec3 (aBufferPtr + aVec3Size * 3);
// add triangle
int n1 = aMergeTool.AddNode (aP1.X(), aP1.Y(), aP1.Z());
int n2 = aMergeTool.AddNode (aP2.X(), aP2.Y(), aP2.Z());
int n3 = aMergeTool.AddNode (aP3.X(), aP3.Y(), aP3.Z());
if (n1 != n2 && n2 != n3 && n3 != n1)
{
AddTriangle (n1, n2, n3);
}
}
return true;
}

View File

@@ -1,79 +0,0 @@
// Created: 2016-05-01
// Author: Andrey Betenev
// Copyright: Open CASCADE 2016
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _RWStl_Reader_HeaderFile
#define _RWStl_Reader_HeaderFile
#include <Message_ProgressIndicator.hxx>
#include <gp_XYZ.hxx>
//! An abstract class implementing procedure to read STL file.
//!
//! This class is not bound to particular data structure and can be used to read the file directly into arbitrary data model.
//! To use it, create descendant class and implement methods addNode() and addTriangle().
//!
//! Call method Read() to read the file. In the process of reading, the tool will call methods addNode() and addTriangle() to fill the mesh data structure.
//!
//! The nodes with equal coordinates are merged automatically on the fly.
class RWStl_Reader : public Standard_Transient
{
DEFINE_STANDARD_RTTIEXT(RWStl_Reader, Standard_Transient)
public:
//! Reads data from STL file (either binary or Ascii).
//! This function supports reading multi-domain STL files formed by concatenation of several "plain" files.
//! The mesh nodes are not merged between domains.
//! Unicode paths can be given in UTF-8 encoding.
//! Format is recognized automatically by analysis of the file header.
//! Returns true if success, false on error or user break.
Standard_EXPORT Standard_Boolean Read (const char* theFile,
const Handle(Message_ProgressIndicator)& theProgress);
//! Guess whether the stream is an Ascii STL file, by analysis of the first bytes (~200).
//! The function attempts to put back the read symbols to the stream which thus must support ungetc().
//! Returns true if the stream seems to contain Ascii STL.
Standard_EXPORT Standard_Boolean IsAscii (Standard_IStream& theStream);
//! Reads STL data from binary stream.
//! The stream must be opened in binary mode.
//! Stops after reading the number of triangles recorded in the file header.
//! Returns true if success, false on error or user break.
Standard_EXPORT Standard_Boolean ReadBinary (Standard_IStream& theStream,
const Handle(Message_ProgressIndicator)& theProgress);
//! Reads data from the stream assumed to contain Ascii STL data.
//! The stream can be opened either in binary or in Ascii mode.
//! Reading stops at the position specified by theUntilPos,
//! or end of file is reached, or when keyword "endsolid" is found.
//! Empty lines are not supported and will read to reading failure.
//! If theUntilPos is non-zero, reads not more than until that position.
//! Returns true if success, false on error or user break.
Standard_EXPORT Standard_Boolean ReadAscii (Standard_IStream& theStream,
const std::streampos theUntilPos,
const Handle(Message_ProgressIndicator)& theProgress);
public:
//! Callback function to be implemented in descendant.
//! Should create new node with specified coordinates in the target model, and return its ID as integer.
virtual Standard_Integer AddNode (const gp_XYZ& thePnt) = 0;
//! Callback function to be implemented in descendant.
//! Should create new triangle built on specified nodes in the target model.
virtual void AddTriangle (Standard_Integer theN1, Standard_Integer theN2, Standard_Integer theN3) = 0;
};
#endif

View File

@@ -34,20 +34,20 @@
// Primary definitions
#define OCC_VERSION_MAJOR 7
#define OCC_VERSION_MINOR 2
#define OCC_VERSION_MAINTENANCE 0
#define OCC_VERSION_MINOR 1
#define OCC_VERSION_MAINTENANCE 1
//! This macro must be commented in official release, and set to non-empty
//! string in other situations, to identify specifics of the version, e.g.:
//! - "dev" for official (certified) version (master branch) between releases
//! - "beta..." or "rc..." for beta releases or release candidates
//! - "project..." for version containing project-specific fixes
#define OCC_VERSION_DEVELOPMENT "beta"
#define OCC_VERSION_DEVELOPMENT "dev"
// Derived (manually): version as real and string (major.minor)
#define OCC_VERSION 7.2
#define OCC_VERSION_STRING "7.2"
#define OCC_VERSION_COMPLETE "7.2.0"
#define OCC_VERSION 7.1
#define OCC_VERSION_STRING "7.1"
#define OCC_VERSION_COMPLETE "7.1.1"
//! Derived: extended version as string ("major.minor.maintenance.dev")
#ifdef OCC_VERSION_DEVELOPMENT

View File

@@ -1,5 +1,6 @@
StlAPI.cxx
StlAPI.hxx
StlAPI_ErrorStatus.hxx
StlAPI_Reader.cxx
StlAPI_Reader.hxx
StlAPI_Writer.cxx

View File

@@ -11,32 +11,24 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <StlAPI.hxx>
#include <StlAPI.hxx>
#include <StlAPI_Reader.hxx>
#include <StlAPI_Writer.hxx>
#include <TopoDS_Shape.hxx>
//=============================================================================
//function : Write
//purpose :
//=============================================================================
Standard_Boolean StlAPI::Write (const TopoDS_Shape& theShape,
const Standard_CString theFile,
const Standard_Boolean theAsciiMode)
StlAPI_ErrorStatus StlAPI::Write(const TopoDS_Shape& aShape,
const Standard_CString aFile,
const Standard_Boolean aAsciiMode)
{
StlAPI_Writer aWriter;
aWriter.ASCIIMode() = theAsciiMode;
return aWriter.Write (theShape, theFile);
StlAPI_Writer writer;
writer.ASCIIMode() = aAsciiMode;
return writer.Write (aShape, aFile);
}
//=============================================================================
//function : Read
//purpose :
//=============================================================================
Standard_Boolean StlAPI::Read (TopoDS_Shape& theShape,
const Standard_CString theFile)
void StlAPI::Read(TopoDS_Shape& aShape,const Standard_CString aFile)
{
StlAPI_Reader aReader;
return aReader.Read(theShape, theFile);
StlAPI_Reader reader;
reader.Read (aShape, aFile);
}

View File

@@ -17,37 +17,57 @@
#ifndef _StlAPI_HeaderFile
#define _StlAPI_HeaderFile
#include <Poly_Triangulation.hxx>
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <StlAPI_ErrorStatus.hxx>
#include <Standard_CString.hxx>
#include <Standard_Boolean.hxx>
class TopoDS_Shape;
class StlAPI_Writer;
class StlAPI_Reader;
//! Offers the API for STL data manipulation.
class StlAPI
class StlAPI
{
public:
DEFINE_STANDARD_ALLOC
//! Convert and write shape to STL format.
//! File is written in binary if aAsciiMode is False otherwise it is written in Ascii (by default).
Standard_EXPORT static Standard_Boolean Write (const TopoDS_Shape& theShape,
const Standard_CString theFile,
const Standard_Boolean theAsciiMode = Standard_True);
//! file is written in binary if aAsciiMode is False
//! otherwise it is written in Ascii (by default)
Standard_EXPORT static StlAPI_ErrorStatus Write (const TopoDS_Shape& aShape, const Standard_CString aFile, const Standard_Boolean aAsciiMode = Standard_True);
//! Create a shape from a STL format.
Standard_EXPORT static void Read (TopoDS_Shape& aShape, const Standard_CString aFile);
//! Legacy interface.
//! Read STL file and create a shape composed of triangular faces, one per facet.
//! This approach is very inefficient, especially for large files.
//! Consider reading STL file to Poly_Triangulation object instead (see class RWStl).
Standard_DEPRECATED("This method is very inefficient; see RWStl class for better alternative")
Standard_EXPORT static Standard_Boolean Read (TopoDS_Shape& theShape,
const Standard_CString aFile);
protected:
private:
friend class StlAPI_Writer;
friend class StlAPI_Reader;
};
#endif // _StlAPI_HeaderFile

View File

@@ -0,0 +1,30 @@
// Created on: 1997-05-13
// Created by: Fabien REUTER
// Copyright (c) 1997-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _StlAPI_ErrorStatus_HeaderFile
#define _StlAPI_ErrorStatus_HeaderFile
//! Set of statuses to indicate a type of the error
//! occurred during data retrieving and writing operations.
enum StlAPI_ErrorStatus
{
StlAPI_StatusOK,
StlAPI_MeshIsEmpty,
StlAPI_CannotOpenFile,
StlAPI_WriteError
};
#endif // _StlAPI_ErrorStatus_HeaderFile

View File

@@ -11,7 +11,6 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <StlAPI_Reader.hxx>
#include <BRep_Builder.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
@@ -21,6 +20,9 @@
#include <gp_Pnt.hxx>
#include <OSD_Path.hxx>
#include <RWStl.hxx>
#include <StlAPI_Reader.hxx>
#include <StlMesh_Mesh.hxx>
#include <StlMesh_MeshExplorer.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
@@ -29,68 +31,64 @@
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Wire.hxx>
//=============================================================================
//function : Read
//purpose :
//=============================================================================
Standard_Boolean StlAPI_Reader::Read (TopoDS_Shape& theShape,
const Standard_CString theFileName)
StlAPI_Reader::StlAPI_Reader() {}
void StlAPI_Reader::Read(TopoDS_Shape& aShape, const Standard_CString aFileName)
{
Handle(Poly_Triangulation) aMesh = RWStl::ReadFile (theFileName);
if (aMesh.IsNull())
{
return Standard_False;
}
TopoDS_Vertex aTriVertexes[3];
TopoDS_Face aFace;
TopoDS_Wire aWire;
OSD_Path aFile(aFileName);
Handle(StlMesh_Mesh) aSTLMesh = RWStl::ReadFile(aFile);
Standard_Integer NumberDomains = aSTLMesh->NbDomains();
Standard_Integer iND;
gp_XYZ p1, p2, p3;
TopoDS_Vertex Vertex1, Vertex2, Vertex3;
TopoDS_Face AktFace;
TopoDS_Wire AktWire;
BRepBuilderAPI_Sewing aSewingTool;
aSewingTool.Init (1.0e-06, Standard_True);
Standard_Real x1, y1, z1;
Standard_Real x2, y2, z2;
Standard_Real x3, y3, z3;
aSewingTool.Init(1.0e-06,Standard_True);
TopoDS_Compound aComp;
BRep_Builder BuildTool;
BuildTool.MakeCompound (aComp);
BuildTool.MakeCompound( aComp );
const TColgp_Array1OfPnt& aNodes = aMesh->Nodes();
const Poly_Array1OfTriangle& aTriangles = aMesh->Triangles();
for (Standard_Integer aTriIdx = aTriangles.Lower();
aTriIdx <= aTriangles.Upper();
++aTriIdx)
StlMesh_MeshExplorer aMExp (aSTLMesh);
for (iND=1;iND<=NumberDomains;iND++)
{
const Poly_Triangle& aTriangle = aTriangles(aTriIdx);
Standard_Integer anId[3];
aTriangle.Get(anId[0], anId[1], anId[2]);
const gp_Pnt& aPnt1 = aNodes (anId[0]);
const gp_Pnt& aPnt2 = aNodes (anId[1]);
const gp_Pnt& aPnt3 = aNodes (anId[2]);
if ((!(aPnt1.IsEqual (aPnt2, 0.0)))
&& (!(aPnt1.IsEqual (aPnt3, 0.0))))
for (aMExp.InitTriangle (iND); aMExp.MoreTriangle (); aMExp.NextTriangle ())
{
aTriVertexes[0] = BRepBuilderAPI_MakeVertex (aPnt1);
aTriVertexes[1] = BRepBuilderAPI_MakeVertex (aPnt2);
aTriVertexes[2] = BRepBuilderAPI_MakeVertex (aPnt3);
aWire = BRepBuilderAPI_MakePolygon (aTriVertexes[0], aTriVertexes[1], aTriVertexes[2], Standard_True);
if (!aWire.IsNull())
aMExp.TriangleVertices (x1,y1,z1,x2,y2,z2,x3,y3,z3);
p1.SetCoord(x1,y1,z1);
p2.SetCoord(x2,y2,z2);
p3.SetCoord(x3,y3,z3);
if ((!(p1.IsEqual(p2,0.0))) && (!(p1.IsEqual(p3,0.0))))
{
aFace = BRepBuilderAPI_MakeFace (aWire);
if (!aFace.IsNull())
Vertex1 = BRepBuilderAPI_MakeVertex(p1);
Vertex2 = BRepBuilderAPI_MakeVertex(p2);
Vertex3 = BRepBuilderAPI_MakeVertex(p3);
AktWire = BRepBuilderAPI_MakePolygon( Vertex1, Vertex2, Vertex3, Standard_True);
if( !AktWire.IsNull())
{
BuildTool.Add (aComp, aFace);
AktFace = BRepBuilderAPI_MakeFace( AktWire);
if(!AktFace.IsNull())
BuildTool.Add( aComp, AktFace );
}
}
}
}
aSTLMesh->Clear();
aSewingTool.Load (aComp);
aSewingTool.Load( aComp );
aSewingTool.Perform();
theShape = aSewingTool.SewedShape();
if (theShape.IsNull())
{
theShape = aComp;
}
return Standard_True;
aShape = aSewingTool.SewedShape();
if ( aShape.IsNull() )
aShape = aComp;
}

View File

@@ -19,20 +19,44 @@
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <Standard_CString.hxx>
#include <Standard_CString.hxx>
class TopoDS_Shape;
//! Reading from stereolithography format.
class StlAPI_Reader
class StlAPI_Reader
{
public:
//! Reads STL file to the TopoDS_Shape (each triangle is converted to the face).
//! @return True if reading is successful
Standard_EXPORT Standard_Boolean Read (TopoDS_Shape& theShape,
const Standard_CString theFileName);
DEFINE_STANDARD_ALLOC
Standard_EXPORT StlAPI_Reader();
Standard_EXPORT void Read (TopoDS_Shape& aShape, const Standard_CString aFileName);
protected:
private:
};
#endif // _StlAPI_Reader_HeaderFile

View File

@@ -11,102 +11,198 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <StlAPI_Writer.hxx>
#include <Bnd_Box.hxx>
#include <BRepBndLib.hxx>
#include <OSD_Path.hxx>
#include <OSD_OpenFile.hxx>
#include <RWStl.hxx>
#include <StlAPI_Writer.hxx>
#include <StlMesh_Mesh.hxx>
#include <StlTransfer.hxx>
#include <BRep_Tool.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopExp_Explorer.hxx>
#include <Poly_Triangulation.hxx>
//=============================================================================
//function : StlAPI_Writer
//purpose :
//=============================================================================
StlAPI_Writer::StlAPI_Writer()
: myASCIIMode (Standard_True)
{
//
theStlMesh = new StlMesh_Mesh;
theASCIIMode = Standard_True;
}
//=============================================================================
//function : Write
//purpose :
//=============================================================================
Standard_Boolean StlAPI_Writer::Write (const TopoDS_Shape& theShape,
const Standard_CString theFileName)
Standard_Boolean& StlAPI_Writer::ASCIIMode()
{
Standard_Integer aNbNodes = 0;
Standard_Integer aNbTriangles = 0;
return theASCIIMode;
}
// calculate total number of the nodes and triangles
for (TopExp_Explorer anExpSF (theShape, TopAbs_FACE); anExpSF.More(); anExpSF.Next())
// Auxiliary tools
namespace
{
// Tool to get triangles from triangulation taking into account face
// orientation and location
class TriangleAccessor
{
TopLoc_Location aLoc;
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (anExpSF.Current()), aLoc);
aNbNodes += aTriangulation->NbNodes();
aNbTriangles += aTriangulation->NbTriangles();
}
// create temporary triangulation
Handle(Poly_Triangulation) aMesh = new Poly_Triangulation (aNbNodes, aNbTriangles, Standard_False);
// fill temporary triangulation
Standard_Integer aNodeOffset = 0;
Standard_Integer aTriangleOffet = 0;
for (TopExp_Explorer anExpSF (theShape, TopAbs_FACE); anExpSF.More(); anExpSF.Next())
{
TopLoc_Location aLoc;
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (anExpSF.Current()), aLoc);
const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes();
const Poly_Array1OfTriangle& aTriangles = aTriangulation->Triangles();
// copy nodes
gp_Trsf aTrsf = aLoc.Transformation();
for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
public:
TriangleAccessor (const TopoDS_Face& aFace)
{
gp_Pnt aPnt = aNodes (aNodeIter);
aPnt.Transform (aTrsf);
aMesh->ChangeNode (aNodeIter + aNodeOffset) = aPnt;
TopLoc_Location aLoc;
myPoly = BRep_Tool::Triangulation (aFace, aLoc);
myTrsf = aLoc.Transformation();
myNbTriangles = (myPoly.IsNull() ? 0 : myPoly->Triangles().Length());
myInvert = (aFace.Orientation() == TopAbs_REVERSED);
if (myTrsf.IsNegative())
myInvert = ! myInvert;
}
// copy triangles
const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
for (Standard_Integer aTriIter = aTriangles.Lower(); aTriIter <= aTriangles.Upper(); ++aTriIter)
{
Poly_Triangle aTri = aTriangles (aTriIter);
int NbTriangles () const { return myNbTriangles; }
Standard_Integer anId[3];
aTri.Get (anId[0], anId[1], anId[2]);
if (anOrientation == TopAbs_REVERSED)
// get i-th triangle and outward normal
void GetTriangle (int iTri, gp_Vec &theNormal, gp_Pnt &thePnt1, gp_Pnt &thePnt2, gp_Pnt &thePnt3)
{
// get positions of nodes
int iNode1, iNode2, iNode3;
myPoly->Triangles()(iTri).Get (iNode1, iNode2, iNode3);
thePnt1 = myPoly->Nodes()(iNode1);
thePnt2 = myPoly->Nodes()(myInvert ? iNode3 : iNode2);
thePnt3 = myPoly->Nodes()(myInvert ? iNode2 : iNode3);
// apply transormation if not identity
if (myTrsf.Form() != gp_Identity)
{
// Swap 1, 2.
Standard_Integer aTmpIdx = anId[1];
anId[1] = anId[2];
anId[2] = aTmpIdx;
thePnt1.Transform (myTrsf);
thePnt2.Transform (myTrsf);
thePnt3.Transform (myTrsf);
}
// Update nodes according to the offset.
anId[0] += aNodeOffset;
anId[1] += aNodeOffset;
anId[2] += aNodeOffset;
aTri.Set (anId[0], anId[1], anId[2]);
aMesh->ChangeTriangle (aTriIter + aTriangleOffet) = aTri;
// calculate normal
theNormal = (thePnt2.XYZ() - thePnt1.XYZ()) ^ (thePnt3.XYZ() - thePnt1.XYZ());
Standard_Real aNorm = theNormal.Magnitude();
if (aNorm > gp::Resolution())
theNormal /= aNorm;
}
aNodeOffset += aNodes.Size();
aTriangleOffet += aTriangles.Size();
private:
Handle(Poly_Triangulation) myPoly;
gp_Trsf myTrsf;
int myNbTriangles;
bool myInvert;
};
// convert to float and, on big-endian platform, to little-endian representation
inline float convertFloat (Standard_Real aValue)
{
#ifdef OCCT_BINARY_FILE_DO_INVERSE
return OSD_BinaryFile::InverseShortReal ((float)aValue);
#else
return (float)aValue;
#endif
}
}
StlAPI_ErrorStatus StlAPI_Writer::Write(const TopoDS_Shape& theShape, const Standard_CString theFileName)
{
// open file
FILE* aFile = OSD_OpenFile (theFileName, "wb");
if (!aFile)
return StlAPI_CannotOpenFile;
// write
if (theASCIIMode)
{
// header
Fprintf (aFile, "solid shape, STL ascii file, created with Open CASCADE Technology\n");
// facets
for (TopExp_Explorer exp (theShape, TopAbs_FACE); exp.More(); exp.Next())
{
TriangleAccessor aTool (TopoDS::Face (exp.Current()));
for (int iTri = 1; iTri <= aTool.NbTriangles(); iTri++)
{
gp_Vec aNorm;
gp_Pnt aPnt1, aPnt2, aPnt3;
aTool.GetTriangle (iTri, aNorm, aPnt1, aPnt2, aPnt3);
Fprintf (aFile,
" facet normal %12e %12e %12e\n"
" outer loop\n"
" vertex %12e %12e %12e\n"
" vertex %12e %12e %12e\n"
" vertex %12e %12e %12e\n"
" endloop\n"
" endfacet\n",
aNorm.X(), aNorm.Y(), aNorm.Z(),
aPnt1.X(), aPnt1.Y(), aPnt1.Z(),
aPnt2.X(), aPnt2.Y(), aPnt2.Z(),
aPnt3.X(), aPnt3.Y(), aPnt3.Z());
}
}
// footer
Fprintf (aFile, "endsolid shape\n");
}
else
{
// header block (meaningless 80 bytes)
Fprintf (aFile, "%-80.80s", "STL binary file, created with Open CASCADE Technology");
// number of facets
int32_t aNbTri = 0;
for (TopExp_Explorer exp (theShape, TopAbs_FACE); exp.More(); exp.Next())
{
TopLoc_Location aLoc;
Handle(Poly_Triangulation) aPoly =
BRep_Tool::Triangulation (TopoDS::Face (exp.Current()), aLoc);
if (! aPoly.IsNull())
aNbTri += aPoly->NbTriangles();
}
// suppose that number of triangles must be little endian...
#ifdef OCCT_BINARY_FILE_DO_INVERSE
aNbTri = OSD_BinaryFile::InverseInteger (aNbTri);
#endif
fwrite (&aNbTri, sizeof(int32_t), 1, aFile);
// facets
struct Facet {
float nx, ny, nz;
float x1, y1, z1;
float x2, y2, z2;
float x3, y3, z3;
uint16_t dummy;
} f;
f.dummy = 0;
for (TopExp_Explorer exp (theShape, TopAbs_FACE); exp.More(); exp.Next())
{
TriangleAccessor aTool (TopoDS::Face (exp.Current()));
for (int iTri = 1; iTri <= aTool.NbTriangles(); iTri++)
{
gp_Vec aNorm;
gp_Pnt aPnt1, aPnt2, aPnt3;
aTool.GetTriangle (iTri, aNorm, aPnt1, aPnt2, aPnt3);
f.nx = convertFloat (aNorm.X());
f.ny = convertFloat (aNorm.Y());
f.nz = convertFloat (aNorm.Z());
f.x1 = convertFloat (aPnt1.X());
f.y1 = convertFloat (aPnt1.Y());
f.z1 = convertFloat (aPnt1.Z());
f.x2 = convertFloat (aPnt2.X());
f.y2 = convertFloat (aPnt2.Y());
f.z2 = convertFloat (aPnt2.Z());
f.x3 = convertFloat (aPnt3.X());
f.y3 = convertFloat (aPnt3.Y());
f.z3 = convertFloat (aPnt3.Z());
fwrite (&f, 50 /* 50 bytes per facet */, 1, aFile);
}
}
}
OSD_Path aPath (theFileName);
return myASCIIMode
? RWStl::WriteAscii (aMesh, aPath)
: RWStl::WriteBinary (aMesh, aPath);
fclose (aFile);
return ferror(aFile) ? StlAPI_WriteError : StlAPI_StatusOK;
}

View File

@@ -16,39 +16,66 @@
#ifndef _StlAPI_Writer_HeaderFile
#define _StlAPI_Writer_HeaderFile
#include <Poly_Triangulation.hxx>
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <Standard_Boolean.hxx>
#include <Standard_CString.hxx>
#include <Standard_Boolean.hxx>
#include <StlAPI_ErrorStatus.hxx>
#include <Standard_CString.hxx>
class StlMesh_Mesh;
class TopoDS_Shape;
//! This class creates and writes
//! STL files from Open CASCADE shapes. An STL file can be written to an existing STL file or to a new one.
class StlAPI_Writer
//! STL files from Open CASCADE shapes. An STL file can be
//! written to an existing STL file or to a new one..
class StlAPI_Writer
{
public:
DEFINE_STANDARD_ALLOC
//! Creates a writer object with default parameters: ASCIIMode.
//! Creates a writer object with
//! default parameters: ASCIIMode.
Standard_EXPORT StlAPI_Writer();
//! Returns the address to the flag defining the mode for writing the file.
//! This address may be used to either read or change the flag.
//! If the mode returns True (default value) the generated file is an ASCII file.
//! If the mode returns False, the generated file is a binary file.
Standard_Boolean& ASCIIMode() { return myASCIIMode; }
//! Returns the address to the
//! flag defining the mode for writing the file. This address
//! may be used to either read or change the flag.
//! If the mode returns True (default value) the generated
//! file is an ASCII file. If the mode returns False, the
//! generated file is a binary file.
Standard_EXPORT Standard_Boolean& ASCIIMode();
//! Converts a given shape to STL format and writes it to file with a given filename.
//! \return the error state.
Standard_EXPORT Standard_Boolean Write (const TopoDS_Shape& theShape,
const Standard_CString theFileName);
Standard_EXPORT StlAPI_ErrorStatus Write (const TopoDS_Shape& aShape, const Standard_CString aFileName);
protected:
private:
Standard_Boolean myASCIIMode;
Standard_Boolean theASCIIMode;
Handle(StlMesh_Mesh) theStlMesh;
};
#endif // _StlAPI_Writer_HeaderFile

16
src/StlMesh/FILES Normal file
View File

@@ -0,0 +1,16 @@
StlMesh.cxx
StlMesh.hxx
StlMesh_Mesh.cxx
StlMesh_Mesh.hxx
StlMesh_Mesh.lxx
StlMesh_MeshDomain.cxx
StlMesh_MeshDomain.hxx
StlMesh_MeshDomain.lxx
StlMesh_MeshExplorer.cxx
StlMesh_MeshExplorer.hxx
StlMesh_MeshExplorer.lxx
StlMesh_MeshTriangle.cxx
StlMesh_MeshTriangle.hxx
StlMesh_SequenceOfMesh.hxx
StlMesh_SequenceOfMeshDomain.hxx
StlMesh_SequenceOfMeshTriangle.hxx

78
src/StlMesh/StlMesh.cxx Normal file
View File

@@ -0,0 +1,78 @@
// Created on: 1996-06-21
// Created by: Bruno TACCI
// Copyright (c) 1996-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <StlMesh.hxx>
#include <StlMesh_Mesh.hxx>
#include <StlMesh_MeshTriangle.hxx>
#include <StlMesh_SequenceOfMeshTriangle.hxx>
#include <TColgp_SequenceOfXYZ.hxx>
//=======================================================================
//function : Merge
//purpose :
//=======================================================================
Handle(StlMesh_Mesh) StlMesh::Merge(const Handle(StlMesh_Mesh)& mesh1, const Handle(StlMesh_Mesh)& mesh2)
{
Handle(StlMesh_Mesh) mergeMesh = new StlMesh_Mesh;
StlMesh_SequenceOfMeshTriangle aSeqOfTriangle;
TColgp_SequenceOfXYZ aSeqOfVertex;
Standard_Real xn,yn,zn;
Standard_Integer v1,v2,v3;
// Chargement de mesh1 dans mergeMesh
// Boucle sur les domaines puis sur les triangles
Standard_Integer idom;
for (idom = 1; idom <= mesh1->NbDomains(); idom++) {
aSeqOfTriangle = mesh1->Triangles(idom);
aSeqOfVertex = mesh1->Vertices(idom);
mergeMesh->AddDomain(mesh1->Deflection(idom));
for (Standard_Integer itri = 1; itri <= mesh1->NbTriangles(idom); itri++) {
const Handle(StlMesh_MeshTriangle) aTrian = aSeqOfTriangle.Value(itri);
aTrian->GetVertexAndOrientation(v1,v2,v3,xn,yn,zn);
mergeMesh->AddTriangle(v1,v2,v3,xn,yn,zn);
}
for (Standard_Integer iver = 1; iver <= mesh1->NbVertices(idom); iver++) {
mergeMesh->AddVertex(aSeqOfVertex.Value(iver).X(),
aSeqOfVertex.Value(iver).Y(),
aSeqOfVertex.Value(iver).Z());
}
}
// Idem avec mesh2
for (idom = 1; idom <= mesh2->NbDomains(); idom++) {
aSeqOfTriangle = mesh2->Triangles(idom);
aSeqOfVertex = mesh2->Vertices(idom);
mergeMesh->AddDomain(mesh2->Deflection(idom));
for (Standard_Integer itri = 1; itri <= mesh2->NbTriangles(idom); itri++) {
const Handle(StlMesh_MeshTriangle) aTrian = aSeqOfTriangle.Value(itri);
aTrian->GetVertexAndOrientation(v1,v2,v3,xn,yn,zn);
mergeMesh->AddTriangle(v1,v2,v3,xn,yn,zn);
}
for (Standard_Integer iver = 1; iver <= mesh2->NbVertices(idom); iver++) {
mergeMesh->AddVertex(aSeqOfVertex.Value(iver).X(),
aSeqOfVertex.Value(iver).Y(),
aSeqOfVertex.Value(iver).Z());
}
}
return mergeMesh;
}

73
src/StlMesh/StlMesh.hxx Normal file
View File

@@ -0,0 +1,73 @@
// Created on: 1995-09-21
// Created by: Philippe GIRODENGO
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _StlMesh_HeaderFile
#define _StlMesh_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
class StlMesh_Mesh;
class StlMesh_Mesh;
class StlMesh_MeshExplorer;
class StlMesh_MeshDomain;
class StlMesh_MeshTriangle;
//! Implements a basic mesh data-structure for the
//! needs of the application fast prototyping.
class StlMesh
{
public:
DEFINE_STANDARD_ALLOC
//! Sequence of meshes
//! Make a merge of two Mesh and returns a new Mesh.
//! Very useful if you want to merge partMesh and CheckSurfaceMesh
//! for example
Standard_EXPORT static Handle(StlMesh_Mesh) Merge (const Handle(StlMesh_Mesh)& mesh1, const Handle(StlMesh_Mesh)& mesh2);
protected:
private:
friend class StlMesh_Mesh;
friend class StlMesh_MeshExplorer;
friend class StlMesh_MeshDomain;
friend class StlMesh_MeshTriangle;
};
#endif // _StlMesh_HeaderFile

View File

@@ -0,0 +1,181 @@
// Created on: 1995-09-25
// Created by: Philippe GIRODENGO
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
//=======================================================================
#include <gp_XYZ.hxx>
#include <Precision.hxx>
#include <Standard_NegativeValue.hxx>
#include <Standard_NoSuchObject.hxx>
#include <Standard_NullValue.hxx>
#include <Standard_Type.hxx>
#include <StlMesh_Mesh.hxx>
#include <StlMesh_MeshDomain.hxx>
IMPLEMENT_STANDARD_RTTIEXT(StlMesh_Mesh,Standard_Transient)
//=======================================================================
//function : StlMesh_Mesh
//design :
//warning :
//=======================================================================
StlMesh_Mesh::StlMesh_Mesh()
: nbTriangles (0), nbVertices (0), xyzmax (-(Precision::Infinite()), -(Precision::Infinite()), -(Precision::Infinite())), xyzmin (Precision::Infinite(), Precision::Infinite(), Precision::Infinite())
{ }
//=======================================================================
//function : AddDomain
//design :
//warning :
//=======================================================================
void StlMesh_Mesh::AddDomain()
{
Handle(StlMesh_MeshDomain) MD = new StlMesh_MeshDomain;
domains.Append (MD);
}
//=======================================================================
//function : AddDomain
//design :
//warning :
//=======================================================================
void StlMesh_Mesh::AddDomain(const Standard_Real Deflection)
{
Handle(StlMesh_MeshDomain) MD = new StlMesh_MeshDomain (Deflection);
domains.Append (MD);
}
//=======================================================================
//function : AddTriangle
//design :
//warning :
//=======================================================================
Standard_Integer StlMesh_Mesh::AddTriangle(const Standard_Integer V1, const Standard_Integer V2,
const Standard_Integer V3, const Standard_Real Xn,
const Standard_Real Yn, const Standard_Real Zn)
{
nbTriangles++;
return (domains.Last())->AddTriangle (V1, V2, V3, Xn, Yn, Zn);
}
//=======================================================================
//function : AddVertex
//design :
//warning :
//=======================================================================
Standard_Integer StlMesh_Mesh::AddVertex(const Standard_Real X, const Standard_Real Y, const Standard_Real Z)
{
nbVertices++;
if (X > xyzmax.X()) xyzmax.SetX (X);
if (Y > xyzmax.Y()) xyzmax.SetY (Y);
if (Z > xyzmax.Z()) xyzmax.SetZ (Z);
if (X < xyzmin.X()) xyzmin.SetX (X);
if (Y < xyzmin.Y()) xyzmin.SetY (Y);
if (Z < xyzmin.Z()) xyzmin.SetZ (Z);
return (domains.Last())->AddVertex (X, Y, Z);
}
//=======================================================================
//function : AddOnlyNewVertex
//design :
//warning :
//=======================================================================
Standard_Integer StlMesh_Mesh::AddOnlyNewVertex(const Standard_Real X, const Standard_Real Y, const Standard_Real Z)
{
Standard_Boolean IsNew = Standard_True;
Standard_Integer VIndex = (domains.Last())->AddOnlyNewVertex (X, Y, Z, IsNew);
if (IsNew) nbVertices++;
return VIndex;
}
//=======================================================================
//function : Bounds
//design :
//warning :
//=======================================================================
void StlMesh_Mesh::Bounds(gp_XYZ& XYZmax, gp_XYZ& XYZmin) const
{
XYZmax = xyzmax;
XYZmin = xyzmin;
}
//=======================================================================
//function : Clear
//design :
//warning :
//=======================================================================
void StlMesh_Mesh::Clear()
{
nbTriangles = 0;
nbVertices = 0;
xyzmax.SetCoord(-(Precision::Infinite()),-(Precision::Infinite()),-(Precision::Infinite()));
xyzmin.SetCoord(Precision::Infinite(),Precision::Infinite(),Precision::Infinite());
domains.Clear ();
}
//=======================================================================
//function : Deflection
//design :
//warning :
//=======================================================================
Standard_Real StlMesh_Mesh::Deflection(const Standard_Integer DomainIndex) const
{return (domains.Value (DomainIndex))->Deflection ();}
//=======================================================================
//function : NbTriangles
//design :
//warning :
//=======================================================================
Standard_Integer StlMesh_Mesh::NbTriangles(const Standard_Integer DomainIndex) const
{ return (domains.Value(DomainIndex))->NbTriangles ();}
//=======================================================================
//function : NbVertices
//design :
//warning :
//=======================================================================
Standard_Integer StlMesh_Mesh::NbVertices(const Standard_Integer DomainIndex) const
{ return (domains.Value(DomainIndex))->NbVertices ();}
//=======================================================================
//function : Triangles
//design :
//warning :
//=======================================================================
const StlMesh_SequenceOfMeshTriangle& StlMesh_Mesh::Triangles(const Standard_Integer DomainIndex) const
{ return (domains.Value (DomainIndex))->Triangles ();}
//=======================================================================
//function : Vertices
//design :
//warning :
//=======================================================================
const TColgp_SequenceOfXYZ& StlMesh_Mesh::Vertices(const Standard_Integer DomainIndex) const
{ return (domains.Value (DomainIndex))->Vertices ();}

View File

@@ -0,0 +1,160 @@
// Created on: 1995-09-21
// Created by: Philippe GIRODENGO
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _StlMesh_Mesh_HeaderFile
#define _StlMesh_Mesh_HeaderFile
#include <Standard.hxx>
#include <Standard_Type.hxx>
#include <Standard_Integer.hxx>
#include <StlMesh_SequenceOfMeshDomain.hxx>
#include <gp_XYZ.hxx>
#include <Standard_Transient.hxx>
#include <Standard_Real.hxx>
#include <Standard_Boolean.hxx>
#include <StlMesh_SequenceOfMeshTriangle.hxx>
#include <TColgp_SequenceOfXYZ.hxx>
class Standard_NegativeValue;
class Standard_NullValue;
class Standard_NoSuchObject;
class gp_XYZ;
class StlMesh_Mesh;
DEFINE_STANDARD_HANDLE(StlMesh_Mesh, Standard_Transient)
//! Mesh definition. The mesh contains one or several
//! domains. Each mesh domain contains a set of
//! triangles. Each domain can have its own deflection
//! value.
class StlMesh_Mesh : public Standard_Transient
{
public:
//! Creates an empty mesh.
Standard_EXPORT StlMesh_Mesh();
//! Adds a new mesh domain. The mesh deflection is
//! defaulted to Confusion from package Precision.
Standard_EXPORT virtual void AddDomain();
//! Adds a new mesh domain.
//! Raised if the deflection is lower than zero
//! Raised if the deflection is lower than Confusion
//! from package Precision
Standard_EXPORT virtual void AddDomain (const Standard_Real Deflection);
//! Build a triangle with the triplet of vertices (V1,
//! V2, V3). This triplet defines the indexes of the
//! vertex in the current domain The coordinates Xn,
//! Yn, Zn defines the normal direction to the
//! triangle. Returns the range of the triangle in
//! the current domain.
Standard_EXPORT virtual Standard_Integer AddTriangle (const Standard_Integer V1, const Standard_Integer V2, const Standard_Integer V3, const Standard_Real Xn, const Standard_Real Yn, const Standard_Real Zn);
//! Returns the range of the vertex in the current
//! domain.
Standard_EXPORT virtual Standard_Integer AddVertex (const Standard_Real X, const Standard_Real Y, const Standard_Real Z);
//! Returns the range of the vertex in the current
//! domain. The current vertex is not inserted in the
//! mesh if it already exist.
Standard_EXPORT virtual Standard_Integer AddOnlyNewVertex (const Standard_Real X, const Standard_Real Y, const Standard_Real Z);
//! Each vertex of the mesh verifies the following
//! relations :
//! XYZMin.X() <= X <= XYZMax.X()
//! XYZMin.Y() <= Y <= XYZMax.y()
//! XYZMin.Z() <= Z <= XYZMax.Z()
Standard_EXPORT virtual void Bounds (gp_XYZ& XYZmax, gp_XYZ& XYZmin) const;
Standard_EXPORT virtual void Clear();
//! Returns the deflection of the mesh of the domain
//! of range <DomainIndex>.
//! Raised if <DomainIndex> is lower than 1 or greater
//! than the number of domains.
Standard_EXPORT virtual Standard_Real Deflection (const Standard_Integer DomainIndex) const;
virtual Standard_Boolean IsEmpty() const;
//! Number of domains in the mesh.
virtual Standard_Integer NbDomains() const;
//! Cumulative Number of triangles in the mesh.
Standard_Integer NbTriangles() const;
//! Number of triangles in the domain of range
//! <DomainIndex>.
//! Raised if <DomainIndex> is lower than 1 or greater
//! than the number of domains.
Standard_EXPORT virtual Standard_Integer NbTriangles (const Standard_Integer DomainIndex) const;
//! Cumulative Number of vertices in the mesh.
virtual Standard_Integer NbVertices() const;
//! Number of vertices in the domain of range
//! <DomainIndex>.
//! Raised if <DomainIndex> is lower than 1 or greater
//! than the number of domains.
Standard_EXPORT virtual Standard_Integer NbVertices (const Standard_Integer DomainIndex) const;
//! Returns the set of triangle of the mesh domain of range
//! <DomainIndex>.
//! Raised if <DomainIndex> is lower than 1 or greater
//! than the number of domains.
Standard_EXPORT virtual const StlMesh_SequenceOfMeshTriangle& Triangles (const Standard_Integer DomainIndex = 1) const;
//! Returns the coordinates of the vertices of the
//! mesh domain of range <DomainIndex>. {XV1, YV1,
//! ZV1, XV2, YV2, ZV2, XV3,.....}
//! Raised if <DomainIndex> is lower than 1 or greater
//! than the number of domains.
Standard_EXPORT virtual const TColgp_SequenceOfXYZ& Vertices (const Standard_Integer DomainIndex = 1) const;
DEFINE_STANDARD_RTTIEXT(StlMesh_Mesh,Standard_Transient)
protected:
Standard_Integer nbTriangles;
Standard_Integer nbVertices;
StlMesh_SequenceOfMeshDomain domains;
gp_XYZ xyzmax;
gp_XYZ xyzmin;
private:
};
#include <StlMesh_Mesh.lxx>
#endif // _StlMesh_Mesh_HeaderFile

View File

@@ -0,0 +1,61 @@
// Created on: 1995-09-25
// Created by: Philippe GIRODENGO
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
//=======================================================================
//=======================================================================
//function : IsEmpty
//design :
//warning :
//=======================================================================
inline Standard_Boolean StlMesh_Mesh::IsEmpty() const
{return domains.IsEmpty ();}
//=======================================================================
//function : NbDomains
//design :
//warning :
//=======================================================================
inline Standard_Integer StlMesh_Mesh::NbDomains() const
{ return domains.Length ();}
//=======================================================================
//function : NbTriangles
//design :
//warning :
//=======================================================================
inline Standard_Integer StlMesh_Mesh::NbTriangles() const
{return nbTriangles;}
//=======================================================================
//function : NbVertices
//design :
//warning :
//=======================================================================
inline Standard_Integer StlMesh_Mesh::NbVertices() const
{return nbVertices;}

View File

@@ -0,0 +1,101 @@
// Created on: 1995-09-25
// Created by: Philippe GIRODENGO
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
//=======================================================================
#include <gp_XYZ.hxx>
#include <Precision.hxx>
#include <Standard_NegativeValue.hxx>
#include <Standard_NullValue.hxx>
#include <Standard_Type.hxx>
#include <StlMesh_MeshDomain.hxx>
#include <StlMesh_MeshTriangle.hxx>
IMPLEMENT_STANDARD_RTTIEXT(StlMesh_MeshDomain,Standard_Transient)
//=======================================================================
//function : StlMesh_MeshDomain
//design :
//warning :
//=======================================================================
StlMesh_MeshDomain::StlMesh_MeshDomain() : deflection (Precision::Confusion ()), nbVertices (0), nbTriangles (0)
{
}
//=======================================================================
//function : StlMesh_MeshDomain
//design :
//warning :
//=======================================================================
StlMesh_MeshDomain::StlMesh_MeshDomain(const Standard_Real Deflection)
: deflection (Deflection), nbVertices (0), nbTriangles (0) { }
//=======================================================================
//function : AddTriangle
//design :
//warning :
//=======================================================================
Standard_Integer StlMesh_MeshDomain::AddTriangle(const Standard_Integer V1,
const Standard_Integer V2, const Standard_Integer V3,
const Standard_Real Xn, const Standard_Real Yn,
const Standard_Real Zn)
{
const Handle (StlMesh_MeshTriangle) tri = new StlMesh_MeshTriangle (V1, V2, V3, Xn, Yn, Zn);
trianglesVertex.Append (tri);
nbTriangles++;
return nbTriangles;
}
//=======================================================================
//function : AddVertex
//design :
//warning :
//=======================================================================
Standard_Integer StlMesh_MeshDomain::AddVertex(const Standard_Real X, const Standard_Real Y, const Standard_Real Z)
{
gp_XYZ Vx (X, Y, Z);
vertexCoords.Append (Vx);
nbVertices++;
return nbVertices;
}
//=======================================================================
//function : AddOnlyNewVertex
//design : Adds the vertex only if X and Y and Z doesn`t already exists.
//=======================================================================
Standard_Integer StlMesh_MeshDomain::AddOnlyNewVertex(const Standard_Real X,
const Standard_Real Y,
const Standard_Real Z,
Standard_Boolean& IsNew)
{
gp_XYZ Vx (X, Y, Z);
IsNew = Standard_True;
vertexCoords.Append (Vx);
nbVertices++;
return nbVertices;
}

View File

@@ -0,0 +1,117 @@
// Created on: 1995-09-21
// Created by: Philippe GIRODENGO
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _StlMesh_MeshDomain_HeaderFile
#define _StlMesh_MeshDomain_HeaderFile
#include <Standard.hxx>
#include <Standard_Type.hxx>
#include <Standard_Real.hxx>
#include <Standard_Integer.hxx>
#include <TColgp_SequenceOfXYZ.hxx>
#include <StlMesh_SequenceOfMeshTriangle.hxx>
#include <Standard_Transient.hxx>
#include <Standard_Boolean.hxx>
class Standard_NegativeValue;
class Standard_NullValue;
class StlMesh_MeshDomain;
DEFINE_STANDARD_HANDLE(StlMesh_MeshDomain, Standard_Transient)
//! A mesh domain is a set of triangles defined with
//! three geometric vertices and a given orientation.
//! The mesh domain has its own deflection.
//! Internal class used to classify the triangles of each domain.
class StlMesh_MeshDomain : public Standard_Transient
{
public:
//! The mesh deflection is defaulted to Confusion from
//! package Precision.
Standard_EXPORT StlMesh_MeshDomain();
//! Raised if the deflection is lower than zero
//! Raised if the deflection is lower than Confusion
//! from package Precision
Standard_EXPORT StlMesh_MeshDomain(const Standard_Real Deflection);
//! Build a triangle with the triplet of vertices (V1,
//! V2, V3). This triplet defines the indexes of the
//! vertex in the current domain The coordinates Xn,
//! Yn, Zn defines the normal direction to the
//! triangle. Returns the range of the triangle in
//! the current domain.
Standard_EXPORT virtual Standard_Integer AddTriangle (const Standard_Integer V1, const Standard_Integer V2, const Standard_Integer V3, const Standard_Real Xn, const Standard_Real Yn, const Standard_Real Zn);
//! Returns the range of the vertex in the current
//! domain.
Standard_EXPORT virtual Standard_Integer AddVertex (const Standard_Real X, const Standard_Real Y, const Standard_Real Z);
//! Returns the range of the vertex in the current
//! domain. The current vertex is not inserted in the
//! mesh if it already exist.
Standard_EXPORT virtual Standard_Integer AddOnlyNewVertex (const Standard_Real X, const Standard_Real Y, const Standard_Real Z, Standard_Boolean& IsNew);
virtual Standard_Real Deflection() const;
//! Number of triangles in the mesh.
virtual Standard_Integer NbTriangles() const;
//! Number of vertices in the mesh.
virtual Standard_Integer NbVertices() const;
//! Returns the set of triangles of the current mesh domain
virtual const StlMesh_SequenceOfMeshTriangle& Triangles() const;
//! Returns the coordinates of the vertices of the
//! mesh domain of range <DomainIndex>. {XV1, YV1,
//! ZV1, XV2, YV2, ZV2, XV3,.....}
virtual const TColgp_SequenceOfXYZ& Vertices() const;
DEFINE_STANDARD_RTTIEXT(StlMesh_MeshDomain,Standard_Transient)
protected:
private:
Standard_Real deflection;
Standard_Integer nbVertices;
Standard_Integer nbTriangles;
TColgp_SequenceOfXYZ vertexCoords;
StlMesh_SequenceOfMeshTriangle trianglesVertex;
};
#include <StlMesh_MeshDomain.lxx>
#endif // _StlMesh_MeshDomain_HeaderFile

View File

@@ -0,0 +1,63 @@
// Created on: 1995-09-25
// Created by: Philippe GIRODENGO
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
//=======================================================================
//=======================================================================
//function : Deflection
//design :
//warning :
//=======================================================================
inline Standard_Real StlMesh_MeshDomain::Deflection() const
{ return deflection; }
//=======================================================================
//function : NbTriangles
//design :
//warning :
//=======================================================================
inline Standard_Integer StlMesh_MeshDomain::NbTriangles() const
{ return nbTriangles; }
//=======================================================================
//function : NbVertices
//design :
//warning :
//=======================================================================
inline Standard_Integer StlMesh_MeshDomain::NbVertices() const
{ return nbVertices; }
//=======================================================================
//function : Triangles
//design :
//warning :
//=======================================================================
inline const StlMesh_SequenceOfMeshTriangle& StlMesh_MeshDomain::Triangles() const
{ return trianglesVertex; }
//=======================================================================
//function : Vertices
//design :
//warning :
//=======================================================================
inline const TColgp_SequenceOfXYZ& StlMesh_MeshDomain::Vertices() const
{ return vertexCoords; }

View File

@@ -0,0 +1,121 @@
// Created on: 1995-09-25
// Created by: Philippe GIRODENGO
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
//=======================================================================
#include <Standard_NoMoreObject.hxx>
#include <Standard_NoSuchObject.hxx>
#include <Standard_OutOfRange.hxx>
#include <StlMesh_Mesh.hxx>
#include <StlMesh_MeshExplorer.hxx>
#include <StlMesh_MeshTriangle.hxx>
//=======================================================================
//function : StlMesh_MeshExplorer
//design :
//warning :
//=======================================================================
StlMesh_MeshExplorer::StlMesh_MeshExplorer(const Handle(StlMesh_Mesh)& M)
: domainIndex (0), nbTriangles (0) ,triangleIndex (0) { mesh = M;}
//=======================================================================
//function : Deflection
//design :
//warning :
//=======================================================================
Standard_Real StlMesh_MeshExplorer::Deflection() const
{ return mesh->Deflection (domainIndex);}
//=======================================================================
//function : InitTriangle
//design :
//warning :
//=======================================================================
void StlMesh_MeshExplorer::InitTriangle(const Standard_Integer DomainIndex)
{
triangleIndex = 1;
domainIndex = DomainIndex;
nbTriangles = mesh->NbTriangles (domainIndex);
if (nbTriangles > 0) {
trianglesdef.Assign (mesh->Triangles (DomainIndex));
trianglesVertex.Assign (mesh->Vertices (DomainIndex));
const Handle (StlMesh_MeshTriangle) trian = trianglesdef.First();
trian->GetVertexAndOrientation (v1,v2,v3,xn,yn,zn);
}
}
//=======================================================================
//function : NextTriangle
//design :
//warning :
//=======================================================================
void StlMesh_MeshExplorer::NextTriangle()
{
triangleIndex++;
if (triangleIndex <= nbTriangles) {
const Handle (StlMesh_MeshTriangle) trian = trianglesdef.Value (triangleIndex);
trian->GetVertexAndOrientation (v1,v2,v3,xn,yn,zn);
}
}
//=======================================================================
//function : TriangleVertices
//design :
//warning :
//=======================================================================
void StlMesh_MeshExplorer::TriangleVertices(Standard_Real& X1, Standard_Real& Y1,
Standard_Real& Z1, Standard_Real& X2,
Standard_Real& Y2, Standard_Real& Z2,
Standard_Real& X3, Standard_Real& Y3,
Standard_Real& Z3) const
{
Standard_NoSuchObject_Raise_if (triangleIndex > nbTriangles, " StlMesh_MeshExplorer::TriangleVertices");
X1 = (trianglesVertex.Value(v1)).X();
Y1 = (trianglesVertex.Value(v1)).Y();
Z1 = (trianglesVertex.Value(v1)).Z();
X2 = (trianglesVertex.Value(v2)).X();
Y2 = (trianglesVertex.Value(v2)).Y();
Z2 = (trianglesVertex.Value(v2)).Z();
X3 = (trianglesVertex.Value(v3)).X();
Y3 = (trianglesVertex.Value(v3)).Y();
Z3 = (trianglesVertex.Value(v3)).Z();
}
//=======================================================================
//function : TriangleDirection
//design :
//warning :
//=======================================================================
void StlMesh_MeshExplorer::TriangleOrientation(Standard_Real& Xn, Standard_Real& Yn, Standard_Real& Zn) const
{
Xn = xn;
Yn = yn;
Zn = zn;
}

View File

@@ -0,0 +1,105 @@
// Created on: 1995-09-21
// Created by: Philippe GIRODENGO
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _StlMesh_MeshExplorer_HeaderFile
#define _StlMesh_MeshExplorer_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <Standard_Real.hxx>
#include <Standard_Integer.hxx>
#include <TColgp_SequenceOfXYZ.hxx>
#include <StlMesh_SequenceOfMeshTriangle.hxx>
#include <Standard_Boolean.hxx>
class StlMesh_Mesh;
class Standard_OutOfRange;
class Standard_NoMoreObject;
class Standard_NoSuchObject;
//! Provides facilities to explore the triangles of
//! each mesh domain.
class StlMesh_MeshExplorer
{
public:
DEFINE_STANDARD_ALLOC
Standard_EXPORT StlMesh_MeshExplorer(const Handle(StlMesh_Mesh)& M);
//! Returns the mesh deflection of the current domain.
Standard_EXPORT Standard_Real Deflection() const;
//! Initializes the exploration of the triangles of
//! the mesh domain of range <DomainIndex>.
//! Raised if <DomainIndex> is lower than 1 or greater
//! than the number of domains.
Standard_EXPORT void InitTriangle (const Standard_Integer DomainIndex = 1);
Standard_Boolean MoreTriangle() const;
//! Raised if there is no more triangle in the current
//! domain.
Standard_EXPORT void NextTriangle();
//! Raised if there is no more triangle in the current
//! domain.
Standard_EXPORT void TriangleVertices (Standard_Real& X1, Standard_Real& Y1, Standard_Real& Z1, Standard_Real& X2, Standard_Real& Y2, Standard_Real& Z2, Standard_Real& X3, Standard_Real& Y3, Standard_Real& Z3) const;
//! Raised if there is no more triangle in the current
//! domain.
Standard_EXPORT void TriangleOrientation (Standard_Real& Xn, Standard_Real& Yn, Standard_Real& Zn) const;
protected:
private:
Handle(StlMesh_Mesh) mesh;
Standard_Real xn;
Standard_Real yn;
Standard_Real zn;
Standard_Integer v1;
Standard_Integer v2;
Standard_Integer v3;
Standard_Integer domainIndex;
Standard_Integer nbTriangles;
Standard_Integer triangleIndex;
TColgp_SequenceOfXYZ trianglesVertex;
StlMesh_SequenceOfMeshTriangle trianglesdef;
};
#include <StlMesh_MeshExplorer.lxx>
#endif // _StlMesh_MeshExplorer_HeaderFile

View File

@@ -0,0 +1,27 @@
// Created on: 1995-09-25
// Created by: Philippe GIRODENGO
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
//=======================================================================
//=======================================================================
//function : MoreTriangle
//design :
//warning :
//=======================================================================
inline Standard_Boolean StlMesh_MeshExplorer::MoreTriangle() const
{ return triangleIndex <= nbTriangles; }

View File

@@ -0,0 +1,117 @@
// Created on: 1995-09-25
// Created by: Philippe GIRODENGO
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
//=======================================================================
#include <gp_XYZ.hxx>
#include <Precision.hxx>
#include <Standard_NegativeValue.hxx>
#include <Standard_Type.hxx>
#include <StlMesh_MeshTriangle.hxx>
IMPLEMENT_STANDARD_RTTIEXT(StlMesh_MeshTriangle,Standard_Transient)
//=======================================================================
//function : StlMesh_MeshTriangle
//design :
//warning :
//=======================================================================
StlMesh_MeshTriangle::StlMesh_MeshTriangle()
: MyV1 (0), MyV2 (0), MyV3 (0), MyXn (0.0), MyYn (0.0), MyZn (0.0) { }
//=======================================================================
//function : StlMesh_MeshTriangle
//design :
//warning :
//=======================================================================
StlMesh_MeshTriangle::StlMesh_MeshTriangle(const Standard_Integer V1,
const Standard_Integer V2,
const Standard_Integer V3,
const Standard_Real Xn,
const Standard_Real Yn,
const Standard_Real Zn)
: MyV1 (V1), MyV2 (V2), MyV3 (V3), MyXn (Xn), MyYn (Yn), MyZn (Zn) { }
//=======================================================================
//function : GetVertexAndOrientation
//design :
//warning :
//=======================================================================
void StlMesh_MeshTriangle::GetVertexAndOrientation(Standard_Integer& V1,
Standard_Integer& V2,
Standard_Integer& V3,
Standard_Real& Xn,
Standard_Real& Yn,
Standard_Real& Zn) const
{
V1 = MyV1;
V2 = MyV2;
V3 = MyV3;
Xn = MyXn;
Yn = MyYn;
Zn = MyZn;
}
//=======================================================================
//function : SetVertexAndOrientation
//design :
//warning :
//=======================================================================
void StlMesh_MeshTriangle::SetVertexAndOrientation(const Standard_Integer V1, const Standard_Integer V2,
const Standard_Integer V3, const Standard_Real Xn,
const Standard_Real Yn, const Standard_Real Zn)
{
MyV1 = V1;
MyV2 = V2;
MyV3 = V3;
MyXn = Xn;
MyYn = Yn;
MyZn = Zn;
}
//=======================================================================
//function : GetVertex
//design :
//warning :
//=======================================================================
void StlMesh_MeshTriangle::GetVertex(Standard_Integer& V1, Standard_Integer& V2, Standard_Integer& V3) const
{
V1 = MyV1;
V2 = MyV2;
V3 = MyV3;
}
//=======================================================================
//function : SetVertex
//design :
//warning :
//=======================================================================
void StlMesh_MeshTriangle::SetVertex(const Standard_Integer V1, const Standard_Integer V2, const Standard_Integer V3)
{
MyV1 = V1;
MyV2 = V2;
MyV3 = V3;
}

View File

@@ -0,0 +1,91 @@
// Created on: 1995-09-21
// Created by: Philippe GIRODENGO
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _StlMesh_MeshTriangle_HeaderFile
#define _StlMesh_MeshTriangle_HeaderFile
#include <Standard.hxx>
#include <Standard_Type.hxx>
#include <Standard_Integer.hxx>
#include <Standard_Real.hxx>
#include <Standard_Transient.hxx>
class Standard_NegativeValue;
class StlMesh_MeshTriangle;
DEFINE_STANDARD_HANDLE(StlMesh_MeshTriangle, Standard_Transient)
//! A mesh triangle is defined with
//! three geometric vertices and an orientation
class StlMesh_MeshTriangle : public Standard_Transient
{
public:
//! empty constructor
Standard_EXPORT StlMesh_MeshTriangle();
//! create a triangle defined with the indexes of its three vertices
//! and its orientation
//! Raised if V1, V2 or V3 is lower than zero
Standard_EXPORT StlMesh_MeshTriangle(const Standard_Integer V1, const Standard_Integer V2, const Standard_Integer V3, const Standard_Real Xn, const Standard_Real Yn, const Standard_Real Zn);
//! get indexes of the three vertices (V1,V2,V3) and the orientation
Standard_EXPORT void GetVertexAndOrientation (Standard_Integer& V1, Standard_Integer& V2, Standard_Integer& V3, Standard_Real& Xn, Standard_Real& Yn, Standard_Real& Zn) const;
//! set indexes of the three vertices (V1,V2,V3) and the orientation
//! Raised if V1, V2 or V3 is lower than zero
Standard_EXPORT void SetVertexAndOrientation (const Standard_Integer V1, const Standard_Integer V2, const Standard_Integer V3, const Standard_Real Xn, const Standard_Real Yn, const Standard_Real Zn);
//! get indexes of the three vertices (V1,V2,V3)
Standard_EXPORT void GetVertex (Standard_Integer& V1, Standard_Integer& V2, Standard_Integer& V3) const;
//! set indexes of the three vertices (V1,V2,V3)
//! Raised if V1, V2 or V3 is lower than zero
Standard_EXPORT void SetVertex (const Standard_Integer V1, const Standard_Integer V2, const Standard_Integer V3);
DEFINE_STANDARD_RTTIEXT(StlMesh_MeshTriangle,Standard_Transient)
protected:
private:
Standard_Integer MyV1;
Standard_Integer MyV2;
Standard_Integer MyV3;
Standard_Real MyXn;
Standard_Real MyYn;
Standard_Real MyZn;
};
#endif // _StlMesh_MeshTriangle_HeaderFile

View File

@@ -0,0 +1,26 @@
// Created on: 1995-09-21
// Created by: Philippe GIRODENGO
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef StlMesh_SequenceOfMesh_HeaderFile
#define StlMesh_SequenceOfMesh_HeaderFile
#include <StlMesh_Mesh.hxx>
#include <NCollection_Sequence.hxx>
typedef NCollection_Sequence<Handle(StlMesh_Mesh)> StlMesh_SequenceOfMesh;
#endif

View File

@@ -0,0 +1,26 @@
// Created on: 1995-09-21
// Created by: Philippe GIRODENGO
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef StlMesh_SequenceOfMeshDomain_HeaderFile
#define StlMesh_SequenceOfMeshDomain_HeaderFile
#include <StlMesh_MeshDomain.hxx>
#include <NCollection_Sequence.hxx>
typedef NCollection_Sequence<Handle(StlMesh_MeshDomain)> StlMesh_SequenceOfMeshDomain;
#endif

View File

@@ -0,0 +1,26 @@
// Created on: 1995-09-21
// Created by: Philippe GIRODENGO
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef StlMesh_SequenceOfMeshTriangle_HeaderFile
#define StlMesh_SequenceOfMeshTriangle_HeaderFile
#include <StlMesh_MeshTriangle.hxx>
#include <NCollection_Sequence.hxx>
typedef NCollection_Sequence<Handle(StlMesh_MeshTriangle)> StlMesh_SequenceOfMeshTriangle;
#endif

2
src/StlTransfer/FILES Normal file
View File

@@ -0,0 +1,2 @@
StlTransfer.cxx
StlTransfer.hxx

View File

@@ -0,0 +1,187 @@
// Created on: 2000-06-23
// Created by: Sergey MOZOKHIN
// Copyright (c) 2000-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
//=======================================================================
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <CSLib.hxx>
#include <Geom_Surface.hxx>
#include <gp_Dir.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <gp_XYZ.hxx>
#include <Poly_Connect.hxx>
#include <Poly_Triangulation.hxx>
#include <Precision.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>
#include <StlMesh_Mesh.hxx>
#include <StlTransfer.hxx>
#include <TColgp_Array1OfDir.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TColgp_SequenceOfXYZ.hxx>
#include <TopAbs.hxx>
#include <TopExp_Explorer.hxx>
#include <TopLoc_Location.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
//function computes normals for surface
static void Normal(const TopoDS_Face& aFace,
Poly_Connect& pc,
TColgp_Array1OfDir& Nor)
{
const Handle(Poly_Triangulation)& T = pc.Triangulation();
BRepAdaptor_Surface S;
Standard_Boolean hasUV = T->HasUVNodes();
Standard_Integer i;
TopLoc_Location l;
Handle(Geom_Surface) GS = BRep_Tool::Surface(aFace, l);
if (hasUV && !GS.IsNull()) {
Standard_Boolean OK = Standard_True;
gp_Vec D1U,D1V;
gp_Vec D2U,D2V,D2UV;
gp_Pnt P;
Standard_Real U, V;
CSLib_DerivativeStatus aStatus;
CSLib_NormalStatus NStat;
S.Initialize(aFace, Standard_False);
const TColgp_Array1OfPnt2d& UVNodes = T->UVNodes();
if (S.GetType() != GeomAbs_Plane) {
for (i = UVNodes.Lower(); i <= UVNodes.Upper(); i++) {
U = UVNodes(i).X();
V = UVNodes(i).Y();
S.D1(U,V,P,D1U,D1V);
CSLib::Normal (D1U, D1V, Precision::Angular(), aStatus, Nor (i));
if (aStatus != CSLib_Done) {
S.D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
CSLib::Normal(D1U,D1V,D2U,D2V,D2UV,Precision::Angular(),OK,NStat,Nor(i));
}
if (aFace.Orientation() == TopAbs_REVERSED) (Nor(i)).Reverse();
}
}
else {
gp_Dir NPlane;
U = UVNodes(UVNodes.Lower()).X();
V = UVNodes(UVNodes.Lower()).Y();
S.D1(U,V,P,D1U,D1V);
CSLib::Normal (D1U, D1V, Precision::Angular(), aStatus, NPlane);
if (aStatus != CSLib_Done) {
S.D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
CSLib::Normal(D1U,D1V,D2U,D2V,D2UV,Precision::Angular(),OK,NStat,NPlane);
}
if (aFace.Orientation() == TopAbs_REVERSED) NPlane.Reverse();
Nor.Init(NPlane);
}
}
else {
const TColgp_Array1OfPnt& Nodes = T->Nodes();
Standard_Integer n[3];
const Poly_Array1OfTriangle& triangles = T->Triangles();
for (i = Nodes.Lower(); i <= Nodes.Upper(); i++) {
gp_XYZ eqPlan(0, 0, 0);
for (pc.Initialize(i); pc.More(); pc.Next()) {
triangles(pc.Value()).Get(n[0], n[1], n[2]);
gp_XYZ v1(Nodes(n[1]).Coord()-Nodes(n[0]).Coord());
gp_XYZ v2(Nodes(n[2]).Coord()-Nodes(n[1]).Coord());
eqPlan += (v1^v2).Normalized();
}
Nor(i) = gp_Dir(eqPlan);
if (aFace.Orientation() == TopAbs_REVERSED) (Nor(i)).Reverse();
}
}
}
void StlTransfer::RetrieveMesh (const TopoDS_Shape& Shape,
const Handle(StlMesh_Mesh)& Mesh)
{
for (TopExp_Explorer itf(Shape,TopAbs_FACE); itf.More(); itf.Next()) {
TopoDS_Face face = TopoDS::Face(itf.Current());
TopLoc_Location Loc, loc;
Handle(Poly_Triangulation) theTriangulation = BRep_Tool::Triangulation(face, Loc);
if (theTriangulation.IsNull()) continue; //Meshing was not done for this face!
Poly_Array1OfTriangle theTriangles(1,theTriangulation->NbTriangles());
theTriangles.Assign(theTriangulation->Triangles());
Mesh->AddDomain (theTriangulation->Deflection());
TColgp_Array1OfPnt thePoints(1, theTriangulation->NbNodes());
thePoints.Assign(theTriangulation->Nodes());
//compute normal of face
const TColgp_Array1OfPnt& Nodes = theTriangulation->Nodes();
TColgp_Array1OfDir NORMAL(Nodes.Lower(), Nodes.Upper());
Poly_Connect pc(theTriangulation);
Normal(face, pc, NORMAL);
Standard_Integer i;
for(i=1;i<=thePoints.Length();i++) {
Standard_Real X1, Y1, Z1;
gp_Pnt p = thePoints.Value(i);
p.Transform(Loc.Transformation());
p.Coord (X1, Y1, Z1);
Mesh->AddVertex (X1, Y1, Z1);
}
try {
OCC_CATCH_SIGNALS
for (i=1;i<=theTriangles.Length();i++) {
Standard_Integer V1, V2, V3;
Poly_Triangle triangle = theTriangles.Value(i);
triangle.Get(V1, V2, V3);
gp_Pnt P1, P2, P3;
P1 = Mesh->Vertices(Mesh->NbDomains()).Value(V1);
P2 = Mesh->Vertices(Mesh->NbDomains()).Value(V2);
P3 = Mesh->Vertices(Mesh->NbDomains()).Value(V3);
gp_Vec average = NORMAL(V1);;
//check angle between vectors
gp_Vec V1V2(P1, P2), V2V3(P2, P3);
Standard_Integer A,B,C;
gp_Vec vec = V1V2^V2V3;
Standard_Real modul1, modul2;
modul1 = average.XYZ().Modulus();
modul2 = vec.XYZ().Modulus();
if (modul2>Precision::Confusion ()) vec.Divide(modul2);
A=V1;B=V2;C=V3;
// vec.Transform(loc);
if (modul1>Precision::Confusion () && modul2>Precision::Confusion ()) {
Standard_Real an = vec.Angle(average);
if ( an > M_PI/2) {
A = V3;B=V2;C=V1;
}
else {
A=V1;B=V2;C=V3;
}
}
Mesh->AddTriangle (A, B, C, average.X(), average.Y(), average.Z());
}
}
catch(Standard_Failure)
{
#ifdef OCCT_DEBUG
cout << "Fail in StlTransfer::BuildIncrementalMesh" << endl;
#endif
}
}
}

View File

@@ -0,0 +1,66 @@
// Created on: 1994-11-14
// Created by: Jean Claude VAUTHIER
// Copyright (c) 1994-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _StlTransfer_HeaderFile
#define _StlTransfer_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
class TopoDS_Shape;
class StlMesh_Mesh;
//! The package Algorithm for Meshing implements
//! facilities to retrieve the Mesh data-structure from a shape of package
//! TopoDS. The triangulation should be computed before.
//! The result is stored in the mesh
//! data-structure Mesh from package StlMesh.
class StlTransfer
{
public:
DEFINE_STANDARD_ALLOC
//! Retrieve a Mesh data-structure from the Shape, convert and store it into the Mesh.
Standard_EXPORT static void RetrieveMesh (const TopoDS_Shape& Shape, const Handle(StlMesh_Mesh)& Mesh);
protected:
private:
};
#endif // _StlTransfer_HeaderFile

View File

@@ -1,2 +1,4 @@
StlMesh
StlAPI
StlTransfer
RWStl

View File

@@ -16,4 +16,3 @@ CSF_Appkit
CSF_IOKit
CSF_FreeImagePlus
CSF_FREETYPE
CSF_FFmpeg

View File

@@ -27,7 +27,6 @@
#include <AIS_ListOfInteractive.hxx>
#include <AIS_ListIteratorOfListOfInteractive.hxx>
#include <DBRep.hxx>
#include <Draw_ProgressIndicator.hxx>
#include <Graphic3d_ArrayOfPolylines.hxx>
#include <Graphic3d_AspectMarker3d.hxx>
#include <Graphic3d_ExportFormat.hxx>
@@ -47,7 +46,6 @@
#include <V3d_DirectionalLight.hxx>
#include <V3d_PositionalLight.hxx>
#include <V3d_SpotLight.hxx>
#include <Message_ProgressSentry.hxx>
#include <NCollection_DoubleMap.hxx>
#include <NCollection_List.hxx>
#include <NCollection_Vector.hxx>
@@ -56,7 +54,6 @@
#include <Draw.hxx>
#include <Draw_Appli.hxx>
#include <Image_AlienPixMap.hxx>
#include <Image_VideoRecorder.hxx>
#include <OpenGl_GraphicDriver.hxx>
#include <OSD_Timer.hxx>
#include <TColStd_HSequenceOfAsciiString.hxx>
@@ -6265,48 +6262,6 @@ namespace
return Standard_True;
}
//! Auxiliary class for flipping image upside-down.
class ImageFlipper
{
public:
//! Empty constructor.
ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
//! Perform flipping.
Standard_Boolean FlipY (Image_PixMap& theImage)
{
if (theImage.IsEmpty()
|| theImage.SizeX() == 0
|| theImage.SizeY() == 0)
{
return Standard_False;
}
const Standard_Size aRowSize = theImage.SizeRowBytes();
if (myTmp.Size() < aRowSize
&& !myTmp.Allocate (aRowSize))
{
return Standard_False;
}
// for odd height middle row should be left as is
Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
{
Standard_Byte* aTop = theImage.ChangeRow (aRowT);
Standard_Byte* aBot = theImage.ChangeRow (aRowB);
memcpy (myTmp.ChangeData(), aTop, aRowSize);
memcpy (aTop, aBot, aRowSize);
memcpy (aBot, myTmp.Data(), aRowSize);
}
return Standard_True;
}
private:
NCollection_Buffer myTmp;
};
}
//=================================================================================================
@@ -6635,13 +6590,10 @@ static Standard_Integer VAnimation (Draw_Interpretor& theDI,
Standard_Real aPlaySpeed = 1.0;
Standard_Real aPlayStartTime = anAnimation->StartPts();
Standard_Real aPlayDuration = anAnimation->Duration();
Standard_Integer aFpsNum = 0;
Standard_Integer aFpsDen = 1;
Standard_Boolean isFreeCamera = Standard_False;
Standard_Boolean isLockLoop = Standard_False;
// video recording parameters
TCollection_AsciiString aRecFile;
Image_VideoParams aRecParams;
Handle(V3d_View) aView = ViewerTest::CurrentView();
for (; anArgIter < theArgNb; ++anArgIter)
{
@@ -6727,37 +6679,6 @@ static Standard_Integer VAnimation (Draw_Interpretor& theDI,
{
isFreeCamera = Standard_True;
}
// video recodring options
else if (anArg == "-rec"
|| anArg == "-record")
{
if (++anArgIter >= theArgNb)
{
std::cout << "Syntax error at " << anArg << ".\n";
return 1;
}
aRecFile = theArgVec[anArgIter];
if (aRecParams.FpsNum <= 0)
{
aRecParams.FpsNum = 24;
}
if (anArgIter + 2 < theArgNb
&& *theArgVec[anArgIter + 1] != '-'
&& *theArgVec[anArgIter + 2] != '-')
{
TCollection_AsciiString aWidthArg (theArgVec[anArgIter + 1]);
TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
if (aWidthArg .IsIntegerValue()
&& aHeightArg.IsIntegerValue())
{
aRecParams.Width = aWidthArg .IntegerValue();
aRecParams.Height = aHeightArg.IntegerValue();
anArgIter += 2;
}
}
}
else if (anArg == "-fps")
{
if (++anArgIter >= theArgNb)
@@ -6770,66 +6691,22 @@ static Standard_Integer VAnimation (Draw_Interpretor& theDI,
Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
if (aSplitIndex == 0)
{
aRecParams.FpsNum = aFpsArg.IntegerValue();
aFpsNum = aFpsArg.IntegerValue();
}
else
{
const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
aFpsArg.Split (aFpsArg.Length() - 1);
const TCollection_AsciiString aNumStr = aFpsArg;
aRecParams.FpsNum = aNumStr.IntegerValue();
aRecParams.FpsDen = aDenStr.IntegerValue();
if (aRecParams.FpsDen < 1)
aFpsNum = aNumStr.IntegerValue();
aFpsDen = aDenStr.IntegerValue();
if (aFpsDen < 1)
{
std::cout << "Syntax error at " << anArg << ".\n";
return 1;
}
}
}
else if (anArg == "-format")
{
if (++anArgIter >= theArgNb)
{
std::cout << "Syntax error at " << anArg << ".\n";
return 1;
}
aRecParams.Format = theArgVec[anArgIter];
}
else if (anArg == "-pix_fmt"
|| anArg == "-pixfmt"
|| anArg == "-pixelformat")
{
if (++anArgIter >= theArgNb)
{
std::cout << "Syntax error at " << anArg << ".\n";
return 1;
}
aRecParams.PixelFormat = theArgVec[anArgIter];
}
else if (anArg == "-codec"
|| anArg == "-vcodec"
|| anArg == "-videocodec")
{
if (++anArgIter >= theArgNb)
{
std::cout << "Syntax error at " << anArg << ".\n";
return 1;
}
aRecParams.VideoCodec = theArgVec[anArgIter];
}
else if (anArg == "-crf"
|| anArg == "-preset"
|| anArg == "-qp")
{
const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
if (++anArgIter >= theArgNb)
{
std::cout << "Syntax error at " << anArg << ".\n";
return 1;
}
aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
}
// animation definition options
else if (anArg == "-start"
|| anArg == "-starttime"
@@ -7081,7 +6958,7 @@ static Standard_Integer VAnimation (Draw_Interpretor& theDI,
}
}
if (!toPlay && aRecFile.IsEmpty())
if (!toPlay)
{
return 0;
}
@@ -7097,7 +6974,7 @@ static Standard_Integer VAnimation (Draw_Interpretor& theDI,
}
const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
if (aRecParams.FpsNum <= 0)
if (aFpsNum <= 0)
{
while (!anAnimation->IsStopped())
{
@@ -7151,35 +7028,12 @@ static Standard_Integer VAnimation (Draw_Interpretor& theDI,
OSD_Timer aPerfTimer;
aPerfTimer.Start();
Handle(Image_VideoRecorder) aRecorder;
ImageFlipper aFlipper;
Handle(Draw_ProgressIndicator) aProgress;
if (!aRecFile.IsEmpty())
{
if (aRecParams.Width <= 0
|| aRecParams.Height <= 0)
{
aView->Window()->Size (aRecParams.Width, aRecParams.Height);
}
aRecorder = new Image_VideoRecorder();
if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
{
std::cout << "Error: failed to open video file for recording\n";
return 0;
}
aProgress = new Draw_ProgressIndicator (theDI, 1);
}
// Manage frame-rated animation here
Standard_Real aPts = aPlayStartTime;
int64_t aNbFrames = 0;
Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
Standard_Integer aSecondsProgress = 0;
for (; aPts <= anUpperPts && aPSentry.More();)
for (; aPts <= anUpperPts;)
{
const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aFpsDen) / Standard_Real(aFpsNum)) * Standard_Real(aNbFrames));
aPts = aPlayStartTime + aRecPts;
++aNbFrames;
if (!anAnimation->Update (aPts))
@@ -7187,35 +7041,7 @@ static Standard_Integer VAnimation (Draw_Interpretor& theDI,
break;
}
if (!aRecorder.IsNull())
{
V3d_ImageDumpOptions aDumpParams;
aDumpParams.Width = aRecParams.Width;
aDumpParams.Height = aRecParams.Height;
aDumpParams.BufferType = Graphic3d_BT_RGBA;
aDumpParams.StereoOptions = V3d_SDO_MONO;
aDumpParams.ToAdjustAspect = Standard_True;
if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
{
std::cout << "Error: view dump is failed!\n";
return 0;
}
aFlipper.FlipY (aRecorder->ChangeFrame());
if (!aRecorder->PushFrame())
{
return 0;
}
}
else
{
aView->Redraw();
}
while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
{
aPSentry.Next();
++aSecondsProgress;
}
aView->Redraw();
}
aPerfTimer.Stop();
@@ -11346,17 +11172,6 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
"\n\t\t: %Pts overall animation presentation timestamp"
"\n\t\t: %LocalPts local animation timestamp"
"\n\t\t: %Normalized local animation normalized value in range 0..1"
"\n\t\t:"
"\n\t\t: Video recording:"
"\n\t\t: vanim name -record FileName [Width Height] [-fps FrameRate=24]"
"\n\t\t: [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
"\n\t\t: [-crf Value] [-preset Preset]"
"\n\t\t: -fps video framerate"
"\n\t\t: -format file format, container (matroska, etc.)"
"\n\t\t: -vcodec video codec identifier (ffv1, mjpeg, etc.)"
"\n\t\t: -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
"\n\t\t: -crf constant rate factor (specific to codec)"
"\n\t\t: -preset codec parameters preset (specific to codec)"
__FILE__, VAnimation, group);
theCommands.Add("vchangeselected",

View File

@@ -17,7 +17,6 @@
#include <AIS_InteractiveContext.hxx>
#include <Aspect_TypeOfMarker.hxx>
#include <Bnd_Box.hxx>
#include <BRep_Builder.hxx>
#include <DBRep.hxx>
#include <Draw.hxx>
#include <Draw_Interpretor.hxx>
@@ -46,12 +45,13 @@
#include <StdSelect_ViewerSelector3d.hxx>
#include <StlAPI.hxx>
#include <StlAPI_Writer.hxx>
#include <StlMesh_Mesh.hxx>
#include <StlMesh_SequenceOfMeshTriangle.hxx>
#include <TColgp_SequenceOfXYZ.hxx>
#include <TCollection_AsciiString.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_HPackedMapOfInteger.hxx>
#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <V3d_View.hxx>
#include <ViewerTest.hxx>
@@ -90,50 +90,27 @@ static Standard_Integer writestl
}
StlAPI_Writer aWriter;
aWriter.ASCIIMode() = isASCIIMode;
Standard_Boolean isOK = aWriter.Write (aShape, argv[2]);
if (!isOK)
di << "** Error **: Mesh writing has been failed.\n";
StlAPI_ErrorStatus aStatus = aWriter.Write (aShape, argv[2]);
switch (aStatus)
{
case StlAPI_MeshIsEmpty: di << "** Error **: Mesh is empty. Please, compute triangulation before."; break;
case StlAPI_CannotOpenFile: di << "** Error **: Cannot create/open a file with the passed name."; break;
case StlAPI_StatusOK: default: break;
}
}
return 0;
}
//=============================================================================
//function : readstl
//purpose : Reads stl file
//=============================================================================
static Standard_Integer readstl(Draw_Interpretor& theDI,
Standard_Integer theArgc,
const char** theArgv)
static Standard_Integer readstl
(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
{
if (theArgc < 3)
{
theDI << "wrong number of parameters" << "\n";
return 1;
if (argc<3) di << "wrong number of parameters" << "\n";
else {
TopoDS_Shape aShape ;
StlAPI::Read(aShape,argv[2]);
DBRep::Set(argv[1],aShape);
}
else
{
if (theArgc == 4 &&
strcmp("triangulation", theArgv[3]) == 0)
{
// Read STL file to the triangulation.
Handle(Poly_Triangulation) aTriangulation = RWStl::ReadFile (theArgv[2]);
TopoDS_Face aFace;
BRep_Builder aB;
aB.MakeFace(aFace);
aB.UpdateFace(aFace, aTriangulation);
DBRep::Set(theArgv[1], aFace);
}
else
{
TopoDS_Shape aShape;
Standard_DISABLE_DEPRECATION_WARNINGS
StlAPI::Read(aShape, theArgv[2]);
Standard_ENABLE_DEPRECATION_WARNINGS
DBRep::Set(theArgv[1], aShape);
}
}
return 0;
}
@@ -283,7 +260,7 @@ static Standard_Integer createmesh
// Progress indicator
OSD_Path aFile( argv[2] );
Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (di, 1);
Handle(Poly_Triangulation) aSTLMesh = RWStl::ReadFile (aFile, aProgress);
Handle(StlMesh_Mesh) aSTLMesh = RWStl::ReadFile (aFile, aProgress);
di << "Reading OK...\n";
Handle( XSDRAWSTLVRML_DataSource ) aDS = new XSDRAWSTLVRML_DataSource( aSTLMesh );
@@ -298,7 +275,7 @@ static Standard_Integer createmesh
// Hide all nodes by default
Handle(TColStd_HPackedMapOfInteger) aNodes = new TColStd_HPackedMapOfInteger();
Standard_Integer aLen = aSTLMesh->Nodes().Length();
Standard_Integer aLen = aSTLMesh->Vertices().Length();
for ( Standard_Integer anIndex = 1; anIndex <= aLen; anIndex++ )
aNodes->ChangeMap().Add( anIndex );
aMesh->SetHiddenNodes( aNodes );
@@ -1246,7 +1223,7 @@ void XSDRAWSTLVRML::InitCommands (Draw_Interpretor& theCommands)
theCommands.Add ("writevrml", "shape file [version VRML#1.0/VRML#2.0 (1/2): 2 by default] [representation shaded/wireframe/both (0/1/2): 1 by default]",__FILE__,writevrml,g);
theCommands.Add ("writestl", "shape file [ascii/binary (0/1) : 1 by default] [InParallel (0/1) : 0 by default]",__FILE__,writestl,g);
theCommands.Add ("readstl", "shape file [triangulation: no by default]",__FILE__,readstl,g);
theCommands.Add ("readstl", "shape file",__FILE__,readstl,g);
theCommands.Add ("loadvrml" , "shape file",__FILE__,loadvrml,g);
theCommands.Add ("meshfromstl", "creates MeshVS_Mesh from STL file", __FILE__, createmesh, g );

View File

@@ -13,13 +13,15 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <XSDRAWSTLVRML_DataSource.hxx>
#include <Precision.hxx>
#include <Standard_Type.hxx>
#include <StlMesh_Mesh.hxx>
#include <StlMesh_MeshTriangle.hxx>
#include <StlMesh_SequenceOfMeshTriangle.hxx>
#include <TColgp_SequenceOfXYZ.hxx>
#include <TColStd_DataMapOfIntegerInteger.hxx>
#include <TColStd_DataMapOfIntegerReal.hxx>
#include <XSDRAWSTLVRML_DataSource.hxx>
IMPLEMENT_STANDARD_RTTIEXT(XSDRAWSTLVRML_DataSource,MeshVS_DataSource)
@@ -27,13 +29,13 @@ IMPLEMENT_STANDARD_RTTIEXT(XSDRAWSTLVRML_DataSource,MeshVS_DataSource)
// Function : Constructor
// Purpose :
//================================================================
XSDRAWSTLVRML_DataSource::XSDRAWSTLVRML_DataSource (const Handle(Poly_Triangulation)& aMesh)
XSDRAWSTLVRML_DataSource::XSDRAWSTLVRML_DataSource( const Handle( StlMesh_Mesh )& aMesh )
{
myMesh = aMesh;
if( !myMesh.IsNull() )
{
const TColgp_Array1OfPnt& aCoords = myMesh->Nodes();
const TColgp_SequenceOfXYZ& aCoords = myMesh->Vertices();
Standard_Integer len = aCoords.Length(), i, j;
myNodeCoords = new TColStd_HArray2OfReal(1, len, 1, 3);
cout << "Nodes : " << len << endl;
@@ -43,14 +45,14 @@ XSDRAWSTLVRML_DataSource::XSDRAWSTLVRML_DataSource (const Handle(Poly_Triangulat
for( i = 1; i <= len; i++ )
{
myNodes.Add( i );
xyz = aCoords(i).XYZ();
xyz = aCoords(i);
myNodeCoords->SetValue(i, 1, xyz.X());
myNodeCoords->SetValue(i, 2, xyz.Y());
myNodeCoords->SetValue(i, 3, xyz.Z());
}
const Poly_Array1OfTriangle& aSeq = myMesh->Triangles();
const StlMesh_SequenceOfMeshTriangle& aSeq = myMesh->Triangles();
len = aSeq.Length();
myElemNormals = new TColStd_HArray2OfReal(1, len, 1, 3);
myElemNodes = new TColStd_HArray2OfInteger(1, len, 1, 3);
@@ -60,33 +62,19 @@ XSDRAWSTLVRML_DataSource::XSDRAWSTLVRML_DataSource (const Handle(Poly_Triangulat
for( i = 1; i <= len; i++ )
{
myElements.Add( i );
Handle( StlMesh_MeshTriangle ) aTriangle = aSeq.Value( i );
Standard_Integer V[3]; Standard_Real nx, ny, nz;
const Poly_Triangle& aTri = aSeq(i);
Standard_Integer V[3];
aTri.Get (V[0], V[1], V[2]);
const gp_Pnt aP1 = aCoords (V[0]);
const gp_Pnt aP2 = aCoords (V[1]);
const gp_Pnt aP3 = aCoords (V[2]);
gp_Vec aV1(aP1, aP2);
gp_Vec aV2(aP2, aP3);
gp_Vec aN = aV1.Crossed(aV2);
if (aN.SquareMagnitude() > Precision::SquareConfusion())
aN.Normalize();
else
aN.SetCoord(0.0, 0.0, 0.0);
aTriangle->GetVertexAndOrientation( V[0], V[1], V[2], nx, ny, nz );
for( j = 0; j < 3; j++ )
{
myElemNodes->SetValue(i, j+1, V[j]);
}
myElemNormals->SetValue (i, 1, aN.X());
myElemNormals->SetValue (i, 2, aN.Y());
myElemNormals->SetValue (i, 3, aN.Z());
myElemNormals->SetValue(i, 1, nx);
myElemNormals->SetValue(i, 2, ny);
myElemNormals->SetValue(i, 3, nz);
}
}
cout << "Construction is finished" << endl;

View File

@@ -30,7 +30,7 @@
#include <Standard_Address.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <Standard_Real.hxx>
#include <Poly_Triangulation.hxx>
class StlMesh_Mesh;
class XSDRAWSTLVRML_DataSource;
@@ -44,7 +44,7 @@ public:
//! Constructor
Standard_EXPORT XSDRAWSTLVRML_DataSource(const Handle(Poly_Triangulation)& aMesh);
Standard_EXPORT XSDRAWSTLVRML_DataSource(const Handle(StlMesh_Mesh)& aMesh);
//! Returns geometry information about node ( if IsElement is False ) or element ( IsElement is True )
//! by co-ordinates. For element this method must return all its nodes co-ordinates in the strict order: X, Y, Z and
@@ -85,7 +85,7 @@ protected:
private:
Handle(Poly_Triangulation) myMesh;
Handle(StlMesh_Mesh) myMesh;
TColStd_PackedMapOfInteger myNodes;
TColStd_PackedMapOfInteger myElements;
Handle(TColStd_HArray2OfInteger) myElemNodes;

View File

@@ -15,6 +15,8 @@
#include <Standard_Type.hxx>
#include <StlMesh_MeshTriangle.hxx>
#include <StlMesh_SequenceOfMeshTriangle.hxx>
#include <TColgp_SequenceOfXYZ.hxx>
#include <TColStd_DataMapOfIntegerInteger.hxx>
#include <TColStd_DataMapOfIntegerReal.hxx>

View File

@@ -1,28 +0,0 @@
puts "TODO OCC24909 ALL: Tcl Exception: Buildsweep : Not Done"
puts "TODO OCC24909 ALL: An exception was caught"
puts "TODO OCC24909 ALL: \\*\\* Exception \\*\\*.*"
puts "TODO OCC24909 ALL: TEST INCOMPLETE"
puts "========"
puts "OCC24909"
puts "========"
puts ""
##################################
# 0024909: SIGSEGV in buildsweep
##################################
restore [locate_data_file bug24909_sweep3-draw-Sweep-0-spine.brep] Sweep-0-spine
mksweep Sweep-0-spine
setsweep -CF
restore [locate_data_file bug24909_sweep3-draw-Sweep-0-section-00-Sketch.brep] Sweep-0-section-00-Sketch
addsweep Sweep-0-section-00-Sketch
restore [locate_data_file bug24909_sweep3-draw-Sweep-0-section-01-Sketch001.brep] Sweep-0-section-01-Sketch001
addsweep Sweep-0-section-01-Sketch001
buildsweep Sweep

View File

@@ -1,31 +0,0 @@
puts "TODO OCC24909 ALL: Tcl Exception: Buildsweep : Not Done"
puts "TODO OCC24909 ALL: An exception was caught"
puts "TODO OCC24909 ALL: \\*\\* Exception \\*\\*.*"
puts "TODO OCC24909 ALL: TEST INCOMPLETE"
puts "========"
puts "OCC24909"
puts "========"
puts ""
##################################
# 0024909: SIGSEGV in buildsweep
##################################
circle c1 0 0 0 40
mkedge e1 c1
wire w1 e1
tcopy w1 Sketch002
tcopy w1 Sketch001
renamevar w1 Sketch
trotate Sketch 0 0 0 0. 1. 0. 90
ttranslate Sketch 0. 0. 75.
trotate Sketch001 0 0 0 0. 1. 0. 90
ttranslate Sketch001 0. 0. -75.
ttranslate Sketch002 50. 0. 0.
mksweep Sketch002
setsweep -CF
addsweep Sketch001
addsweep Sketch
buildsweep Sweep

View File

@@ -1,32 +0,0 @@
puts "TODO OCC24909 ALL: Tcl Exception: Buildsweep : Not Done"
puts "TODO OCC24909 ALL: TEST INCOMPLETE"
puts "========"
puts "OCC24909"
puts "========"
puts ""
##################################
# 0024909: SIGSEGV in buildsweep
##################################
restore [locate_data_file bug24909_minihyd-draw-BezCurve.brep] BezCurve
ttranslate BezCurve 0 -8 0
explode BezCurve E
wire Sweep001-0-spine BezCurve_1
mksweep Sweep001-0-spine
setsweep -CF
circle Circle-curve 0 0 0 18
mkedge Circle-edge Circle-curve 0 0
wire Circle Circle-edge
trotate Circle 0 0 0 0.577350269189625731 0.577350269189625731 0.577350269189625731 120
ttranslate Circle 0 -71 203.5
addsweep Circle
circle Circle001-curve 0 0 0 16
mkedge Circle001-edge Circle001-curve 0 0
wire Circle001 Circle001-edge
trotate Circle001 0 0 0 0.577350269189625731 0.577350269189625731 0.577350269189625731 120
ttranslate Circle001 0 -71 203.5
addsweep Circle001
buildsweep Sweep001 -C -S

View File

@@ -1,15 +0,0 @@
puts "TODO OCC24997 ALL: An exception was caught"
puts "TODO OCC24997 ALL: \\*\\* Exception \\*\\*.*"
puts "TODO OCC24997 ALL: TEST INCOMPLETE"
puts "========"
puts "OCC24997"
puts "========"
puts ""
#########################################
# SIGSEGV in BRepOffsetAPI_ThruSections
#########################################
restore [locate_data_file bug24997_loft3-draw-Loft-00-section.brep] Loft-00-section
restore [locate_data_file bug24997_loft3-draw-Loft-01-section.brep] Loft-01-section
thrusections Loft 0 0 Loft-00-section Loft-01-section

View File

@@ -1,22 +0,0 @@
puts "TODO OCC25081 ALL: TEST INCOMPLETE"
puts "TODO OCC25081 ALL: Process killed by CPU limit"
puts "========"
puts "OCC25081"
puts "========"
puts ""
############################
# bopcheck does not return
############################
cpulimit 1200
restore [locate_data_file bug25081_v1-sweep-draw-Sweep-0-spine.brep] Sweep-0-spine
restore [locate_data_file bug25081_v1-sweep-draw-Sweep-0-section-00-Wire.brep] Sweep-0-section-00-Wire
mksweep Sweep-0-spine
setsweep -FR
addsweep Sweep-0-section-00-Wire
buildsweep Sweep -C -S
bopcheck Sweep

View File

@@ -1,20 +0,0 @@
puts "TODO OCC25110 ALL: An exception was caught"
puts "TODO OCC25110 ALL: \\*\\* Exception \\*\\*.*"
puts "TODO OCC25110 ALL: TEST INCOMPLETE"
puts "========"
puts "OCC25110"
puts "========"
puts ""
########################################################################################
# TCollection_IndexedDataMap::FindFromKey error when sweeping circle along BezierCurve
########################################################################################
restore [locate_data_file bug25110_unsweepable1-draw-Sweep-0-spine.brep] Sweep-0-spine
restore [locate_data_file bug25110_unsweepable1-draw-Sweep-0-section-00-Circle.brep] Sweep-0-section-00-Circle
mksweep Sweep-0-spine
setsweep -CF
addsweep Sweep-0-section-00-Circle
buildsweep Sweep -C -S

View File

@@ -1,21 +0,0 @@
puts "TODO OCC26030 ALL: An exception was caught"
puts "TODO OCC26030 ALL: \\*\\* Exception \\*\\*.*"
puts "TODO OCC26030 ALL: TEST INCOMPLETE"
puts "========"
puts "OCC26030"
puts "========"
puts ""
#################################################
# Offset of a lofted body fails after long time
#################################################
restore [locate_data_file bug26030_thickness-crash1-tcl-Loft001-00-section.brep] Loft001-00-section
restore [locate_data_file bug26030_thickness-crash1-tcl-Loft001-01-section.brep] Loft001-01-section
thrusections Loft001 1 0 Loft001-00-section Loft001-01-section
explode Loft001 F
offsetparameter 1e-7 p i
offsetload Loft001 1
offsetperform Offset

View File

@@ -1,16 +0,0 @@
puts "TODO OCC26088 ALL: An exception was caught"
puts "TODO OCC26088 ALL: \\*\\* Exception \\*\\*.*"
puts "TODO OCC26088 ALL: TEST INCOMPLETE"
puts "========"
puts "OCC26088"
puts "========"
puts ""
###############################
# Exception in pipe algorithm
###############################
restore [locate_data_file bug26088_path0.brep] p
restore [locate_data_file bug26088_profile0.brep] pr
pipe result p pr

23
tests/bugs/moddata_1/bug1048 Executable file
View File

@@ -0,0 +1,23 @@
puts "================"
puts "OCC1048"
puts "================"
puts ""
pload QAcommands
restore [locate_data_file OCC1048.brep] result
set list [OCC1048 result]
set NBTRIANGLES 0
regexp {Info: +Number +of +triangles += +([-0-9.+eE]+)} $list full NBTRIANGLES
if { ${NBTRIANGLES} > 0 } {
puts "OCC1048: OK"
} else {
puts "OCC1048: Error"
}
checkview -display result -2d -path ${imagedir}/${test_image}.png

View File

@@ -1,17 +0,0 @@
puts "TODO OCC24621 ALL: An exception was caught"
puts "TODO OCC24621 ALL: \\*\\* Exception \\*\\*.*"
puts "TODO OCC24621 ALL: TEST INCOMPLETE"
puts "========"
puts "OCC24621"
puts "========"
puts ""
##################################################
# Failed to build Geom_OffsetSurface on B-Spline
##################################################
restore [locate_data_file bug24621_bs.draw] bs
offset obs bs -2
setunotperiodic bs
offset obs bs -2

View File

@@ -1,8 +0,0 @@
readstl m [locate_data_file bug28680_sample01b.stl] triangulation
# Number of triangles check
checktrinfo m -tri 62075 -nod 31879
# Visual check
checkview -display m -3d -vdispmode 0 -path ${imagedir}/${test_image}_edges.png
checkview -display m -3d -vdispmode 1 -path ${imagedir}/${test_image}_shading.png

View File

@@ -1,17 +0,0 @@
puts "================"
puts "OCC25382"
puts "================"
puts ""
puts "==============================================================="
puts "Visualization, TKOpenGl - improved video recording capability"
puts "==============================================================="
set aFile ${imagedir}/propeller.mkv
file delete -force ${aFile}
source $env(CSF_OCCTTestsPath)/v3d/anim/propeller
vraytrace 1
vrenderparams -msaa 8
vrenderparams -fsaa 1
XProgress +g
vanimation anim -play -record ${aFile} 1920 1080 -vcodec ffv1 -fps 30 -speed 0.5