From a2176e65246f4cd9a167cc16965837a86ecf603e Mon Sep 17 00:00:00 2001 From: asuraven Date: Tue, 26 May 2020 14:16:46 +0300 Subject: [PATCH] 0031570: Samples - add Qt samples similar to standard MFC samples Added Qt sample OCCTOverview providing examples of use of OCCT API with relevant code and demonstration of results in the viewer. Off-topic: some unused images are removed from dox/introduction/images/ --- CMakeLists.txt | 2 + adm/SAMPLES | 2 +- adm/SAMPLES_RESOURCES | 3 +- adm/templates/env.bat.in | 5 +- adm/templates/env.samples.bat.in | 2 + adm/templates/env.samples.sh.in | 2 + adm/templates/sample.bat | 4 + adm/templates/sample.sh | 3 + dox/FILES_HTML.txt | 1 + dox/introduction/images/overview_c__ie.png | Bin 38265 -> 0 bytes dox/introduction/images/overview_mvc.png | Bin 32022 -> 0 bytes dox/introduction/images/overview_qt.png | Bin 64276 -> 0 bytes dox/introduction/images/sample_ios_uikit.png | Bin 48744 -> 0 bytes dox/introduction/images/sample_webgl.png | Bin 75733 -> 0 bytes .../images/samples_java_android_occt.jpg | Bin 13697 -> 0 bytes .../images/samples_qml_android_occt.jpg | Bin 14519 -> 0 bytes dox/samples/images/overview_overview_qt.png | Bin 165475 -> 0 bytes dox/samples/images/sample_overview_qt.png | Bin 0 -> 112795 bytes dox/samples/samples.md | 26 +- .../OCCTOverview/code/AdaptorCurve2d_AIS.cxx | 147 ++ .../OCCTOverview/code/AdaptorCurve2d_AIS.h | 77 + .../OCCTOverview/code/AdaptorCurve_AIS.cxx | 49 + samples/OCCTOverview/code/AdaptorCurve_AIS.h | 52 + .../OCCTOverview/code/AdaptorPnt2d_AIS.cxx | 38 + samples/OCCTOverview/code/AdaptorPnt2d_AIS.h | 57 + samples/OCCTOverview/code/AdaptorVec_AIS.cxx | 77 + samples/OCCTOverview/code/AdaptorVec_AIS.h | 121 + samples/OCCTOverview/code/BaseSample.cxx | 185 ++ samples/OCCTOverview/code/BaseSample.h | 87 + samples/OCCTOverview/code/DataExchange.json | 51 + .../OCCTOverview/code/DataExchangeSamples.cxx | 410 ++++ .../OCCTOverview/code/DataExchangeSamples.h | 90 + samples/OCCTOverview/code/FILES | 48 + samples/OCCTOverview/code/Geometry.json | 287 +++ samples/OCCTOverview/code/GeometrySamples.cxx | 2027 +++++++++++++++++ samples/OCCTOverview/code/GeometrySamples.h | 102 + samples/OCCTOverview/code/MakeBottle.cxx | 218 ++ samples/OCCTOverview/code/MakeBottle.h | 33 + samples/OCCTOverview/code/Ocaf.json | 53 + samples/OCCTOverview/code/OcafSamples.cxx | 624 +++++ samples/OCCTOverview/code/OcafSamples.h | 85 + samples/OCCTOverview/code/Sample2D_Face.cxx | 486 ++++ samples/OCCTOverview/code/Sample2D_Face.h | 107 + samples/OCCTOverview/code/Sample2D_Image.cxx | 88 + samples/OCCTOverview/code/Sample2D_Image.h | 86 + .../OCCTOverview/code/Sample2D_Markers.cxx | 80 + samples/OCCTOverview/code/Sample2D_Markers.h | 88 + samples/OCCTOverview/code/Samples.qrc | 11 + .../code/TOcafFunction_BoxDriver.cxx | 148 ++ .../code/TOcafFunction_BoxDriver.h | 57 + .../code/TOcafFunction_CutDriver.cxx | 152 ++ .../code/TOcafFunction_CutDriver.h | 57 + .../code/TOcafFunction_CylDriver.cxx | 147 ++ .../code/TOcafFunction_CylDriver.h | 59 + .../OCCTOverview/code/TOcaf_Application.cxx | 52 + samples/OCCTOverview/code/TOcaf_Application.h | 37 + samples/OCCTOverview/code/Topology.json | 176 ++ samples/OCCTOverview/code/TopologySamples.cxx | 1884 +++++++++++++++ samples/OCCTOverview/code/TopologySamples.h | 80 + samples/OCCTOverview/code/Triangulation.json | 10 + .../code/TriangulationSamples.cxx | 118 + .../OCCTOverview/code/TriangulationSamples.h | 49 + samples/OCCTOverview/code/Viewer2d.json | 58 + samples/OCCTOverview/code/Viewer2dSamples.cxx | 282 +++ samples/OCCTOverview/code/Viewer2dSamples.h | 76 + samples/OCCTOverview/code/Viewer3d.json | 106 + samples/OCCTOverview/code/Viewer3dSamples.cxx | 312 +++ samples/OCCTOverview/code/Viewer3dSamples.h | 78 + samples/qt/IESample/.gitignore | 7 + samples/qt/IESample/custom.bat | 4 - samples/qt/IESample/custom.bat.template | 5 + samples/qt/IESample/custom.sh | 4 - samples/qt/IESample/custom.sh.template | 5 + samples/qt/IESample/env.bat | 6 +- samples/qt/OCCTOverview/.gitignore | 7 + samples/qt/OCCTOverview/CMakeLists.txt | 8 + samples/qt/OCCTOverview/EXTERNLIB | 33 + samples/qt/OCCTOverview/FILES | 2 + samples/qt/OCCTOverview/OCCTOverview.pro | 89 + samples/qt/OCCTOverview/OCCTOverview0.pro | 5 + samples/qt/OCCTOverview/PACKAGES | 2 + samples/qt/OCCTOverview/ReadMe.md | 58 + samples/qt/OCCTOverview/custom.bat.template | 7 + samples/qt/OCCTOverview/custom.sh.template | 9 + samples/qt/OCCTOverview/env.bat | 29 + samples/qt/OCCTOverview/env.sh | 25 + samples/qt/OCCTOverview/genproj.bat | 17 + samples/qt/OCCTOverview/make.sh | 16 + samples/qt/OCCTOverview/msvc.bat | 19 + samples/qt/OCCTOverview/res/antialiasing.png | Bin 0 -> 230 bytes samples/qt/OCCTOverview/res/cursor_rotate.png | Bin 0 -> 291 bytes samples/qt/OCCTOverview/res/cursor_zoom.png | Bin 0 -> 245 bytes samples/qt/OCCTOverview/res/help.png | Bin 0 -> 214 bytes samples/qt/OCCTOverview/res/lamp.png | Bin 0 -> 1355 bytes samples/qt/OCCTOverview/res/raytracing.png | Bin 0 -> 223 bytes samples/qt/OCCTOverview/res/reflections.png | Bin 0 -> 217 bytes samples/qt/OCCTOverview/res/shadows.png | Bin 0 -> 264 bytes samples/qt/OCCTOverview/res/tool_color.png | Bin 0 -> 288 bytes samples/qt/OCCTOverview/res/tool_delete.png | Bin 0 -> 203 bytes samples/qt/OCCTOverview/res/tool_material.png | Bin 0 -> 293 bytes samples/qt/OCCTOverview/res/tool_shading.png | Bin 0 -> 256 bytes .../qt/OCCTOverview/res/tool_transparency.png | Bin 0 -> 318 bytes .../qt/OCCTOverview/res/tool_wireframe.png | Bin 0 -> 259 bytes samples/qt/OCCTOverview/res/view_axo.png | Bin 0 -> 392 bytes samples/qt/OCCTOverview/res/view_back.png | Bin 0 -> 233 bytes samples/qt/OCCTOverview/res/view_bottom.png | Bin 0 -> 233 bytes samples/qt/OCCTOverview/res/view_comp_off.png | Bin 0 -> 199 bytes samples/qt/OCCTOverview/res/view_comp_on.png | Bin 0 -> 180 bytes samples/qt/OCCTOverview/res/view_fitall.png | Bin 0 -> 231 bytes samples/qt/OCCTOverview/res/view_front.png | Bin 0 -> 238 bytes samples/qt/OCCTOverview/res/view_left.png | Bin 0 -> 231 bytes samples/qt/OCCTOverview/res/view_reset.png | Bin 0 -> 204 bytes samples/qt/OCCTOverview/res/view_right.png | Bin 0 -> 230 bytes samples/qt/OCCTOverview/res/view_top.png | Bin 0 -> 235 bytes samples/qt/OCCTOverview/run.bat | 23 + samples/qt/OCCTOverview/run.sh | 37 + .../qt/OCCTOverview/src/ApplicationCommon.cxx | 685 ++++++ .../qt/OCCTOverview/src/ApplicationCommon.h | 197 ++ samples/qt/OCCTOverview/src/CommonSample.h | 43 + .../qt/OCCTOverview/src/DocumentCommon.cxx | 108 + samples/qt/OCCTOverview/src/DocumentCommon.h | 75 + samples/qt/OCCTOverview/src/FILES | 19 + samples/qt/OCCTOverview/src/GeomWidget.cxx | 100 + samples/qt/OCCTOverview/src/GeomWidget.h | 65 + samples/qt/OCCTOverview/src/Main.cxx | 78 + samples/qt/OCCTOverview/src/OCCTOverview.qrc | 29 + .../qt/OCCTOverview/src/OcctHighlighter.cxx | 254 +++ samples/qt/OCCTOverview/src/OcctHighlighter.h | 75 + samples/qt/OCCTOverview/src/OcctWindow.cxx | 179 ++ samples/qt/OCCTOverview/src/OcctWindow.h | 111 + .../qt/OCCTOverview/src/TranslateDialog.cxx | 113 + samples/qt/OCCTOverview/src/TranslateDialog.h | 56 + samples/qt/OCCTOverview/src/Transparency.cxx | 46 + samples/qt/OCCTOverview/src/Transparency.h | 55 + samples/qt/OCCTOverview/src/View.cxx | 676 ++++++ samples/qt/OCCTOverview/src/View.h | 169 ++ samples/qt/Tutorial/.gitignore | 7 + samples/qt/Tutorial/custom.bat | 4 - samples/qt/Tutorial/custom.bat.template | 5 + samples/qt/Tutorial/custom.sh | 4 - samples/qt/Tutorial/custom.sh.template | 5 + samples/qt/Tutorial/env.bat | 6 +- 142 files changed, 13409 insertions(+), 24 deletions(-) delete mode 100644 dox/introduction/images/overview_c__ie.png delete mode 100644 dox/introduction/images/overview_mvc.png delete mode 100644 dox/introduction/images/overview_qt.png delete mode 100644 dox/introduction/images/sample_ios_uikit.png delete mode 100644 dox/introduction/images/sample_webgl.png delete mode 100644 dox/introduction/images/samples_java_android_occt.jpg delete mode 100644 dox/introduction/images/samples_qml_android_occt.jpg delete mode 100644 dox/samples/images/overview_overview_qt.png create mode 100644 dox/samples/images/sample_overview_qt.png create mode 100644 samples/OCCTOverview/code/AdaptorCurve2d_AIS.cxx create mode 100644 samples/OCCTOverview/code/AdaptorCurve2d_AIS.h create mode 100644 samples/OCCTOverview/code/AdaptorCurve_AIS.cxx create mode 100644 samples/OCCTOverview/code/AdaptorCurve_AIS.h create mode 100644 samples/OCCTOverview/code/AdaptorPnt2d_AIS.cxx create mode 100644 samples/OCCTOverview/code/AdaptorPnt2d_AIS.h create mode 100644 samples/OCCTOverview/code/AdaptorVec_AIS.cxx create mode 100644 samples/OCCTOverview/code/AdaptorVec_AIS.h create mode 100644 samples/OCCTOverview/code/BaseSample.cxx create mode 100644 samples/OCCTOverview/code/BaseSample.h create mode 100644 samples/OCCTOverview/code/DataExchange.json create mode 100644 samples/OCCTOverview/code/DataExchangeSamples.cxx create mode 100644 samples/OCCTOverview/code/DataExchangeSamples.h create mode 100644 samples/OCCTOverview/code/FILES create mode 100644 samples/OCCTOverview/code/Geometry.json create mode 100644 samples/OCCTOverview/code/GeometrySamples.cxx create mode 100644 samples/OCCTOverview/code/GeometrySamples.h create mode 100644 samples/OCCTOverview/code/MakeBottle.cxx create mode 100644 samples/OCCTOverview/code/MakeBottle.h create mode 100644 samples/OCCTOverview/code/Ocaf.json create mode 100644 samples/OCCTOverview/code/OcafSamples.cxx create mode 100644 samples/OCCTOverview/code/OcafSamples.h create mode 100644 samples/OCCTOverview/code/Sample2D_Face.cxx create mode 100644 samples/OCCTOverview/code/Sample2D_Face.h create mode 100644 samples/OCCTOverview/code/Sample2D_Image.cxx create mode 100644 samples/OCCTOverview/code/Sample2D_Image.h create mode 100644 samples/OCCTOverview/code/Sample2D_Markers.cxx create mode 100644 samples/OCCTOverview/code/Sample2D_Markers.h create mode 100644 samples/OCCTOverview/code/Samples.qrc create mode 100644 samples/OCCTOverview/code/TOcafFunction_BoxDriver.cxx create mode 100644 samples/OCCTOverview/code/TOcafFunction_BoxDriver.h create mode 100644 samples/OCCTOverview/code/TOcafFunction_CutDriver.cxx create mode 100644 samples/OCCTOverview/code/TOcafFunction_CutDriver.h create mode 100644 samples/OCCTOverview/code/TOcafFunction_CylDriver.cxx create mode 100644 samples/OCCTOverview/code/TOcafFunction_CylDriver.h create mode 100644 samples/OCCTOverview/code/TOcaf_Application.cxx create mode 100644 samples/OCCTOverview/code/TOcaf_Application.h create mode 100644 samples/OCCTOverview/code/Topology.json create mode 100644 samples/OCCTOverview/code/TopologySamples.cxx create mode 100644 samples/OCCTOverview/code/TopologySamples.h create mode 100644 samples/OCCTOverview/code/Triangulation.json create mode 100644 samples/OCCTOverview/code/TriangulationSamples.cxx create mode 100644 samples/OCCTOverview/code/TriangulationSamples.h create mode 100644 samples/OCCTOverview/code/Viewer2d.json create mode 100644 samples/OCCTOverview/code/Viewer2dSamples.cxx create mode 100644 samples/OCCTOverview/code/Viewer2dSamples.h create mode 100644 samples/OCCTOverview/code/Viewer3d.json create mode 100644 samples/OCCTOverview/code/Viewer3dSamples.cxx create mode 100644 samples/OCCTOverview/code/Viewer3dSamples.h create mode 100644 samples/qt/IESample/.gitignore delete mode 100644 samples/qt/IESample/custom.bat create mode 100644 samples/qt/IESample/custom.bat.template delete mode 100755 samples/qt/IESample/custom.sh create mode 100644 samples/qt/IESample/custom.sh.template create mode 100644 samples/qt/OCCTOverview/.gitignore create mode 100644 samples/qt/OCCTOverview/CMakeLists.txt create mode 100644 samples/qt/OCCTOverview/EXTERNLIB create mode 100644 samples/qt/OCCTOverview/FILES create mode 100644 samples/qt/OCCTOverview/OCCTOverview.pro create mode 100644 samples/qt/OCCTOverview/OCCTOverview0.pro create mode 100644 samples/qt/OCCTOverview/PACKAGES create mode 100644 samples/qt/OCCTOverview/ReadMe.md create mode 100644 samples/qt/OCCTOverview/custom.bat.template create mode 100644 samples/qt/OCCTOverview/custom.sh.template create mode 100644 samples/qt/OCCTOverview/env.bat create mode 100644 samples/qt/OCCTOverview/env.sh create mode 100644 samples/qt/OCCTOverview/genproj.bat create mode 100644 samples/qt/OCCTOverview/make.sh create mode 100644 samples/qt/OCCTOverview/msvc.bat create mode 100644 samples/qt/OCCTOverview/res/antialiasing.png create mode 100644 samples/qt/OCCTOverview/res/cursor_rotate.png create mode 100644 samples/qt/OCCTOverview/res/cursor_zoom.png create mode 100644 samples/qt/OCCTOverview/res/help.png create mode 100644 samples/qt/OCCTOverview/res/lamp.png create mode 100644 samples/qt/OCCTOverview/res/raytracing.png create mode 100644 samples/qt/OCCTOverview/res/reflections.png create mode 100644 samples/qt/OCCTOverview/res/shadows.png create mode 100644 samples/qt/OCCTOverview/res/tool_color.png create mode 100644 samples/qt/OCCTOverview/res/tool_delete.png create mode 100644 samples/qt/OCCTOverview/res/tool_material.png create mode 100644 samples/qt/OCCTOverview/res/tool_shading.png create mode 100644 samples/qt/OCCTOverview/res/tool_transparency.png create mode 100644 samples/qt/OCCTOverview/res/tool_wireframe.png create mode 100644 samples/qt/OCCTOverview/res/view_axo.png create mode 100644 samples/qt/OCCTOverview/res/view_back.png create mode 100644 samples/qt/OCCTOverview/res/view_bottom.png create mode 100644 samples/qt/OCCTOverview/res/view_comp_off.png create mode 100644 samples/qt/OCCTOverview/res/view_comp_on.png create mode 100644 samples/qt/OCCTOverview/res/view_fitall.png create mode 100644 samples/qt/OCCTOverview/res/view_front.png create mode 100644 samples/qt/OCCTOverview/res/view_left.png create mode 100644 samples/qt/OCCTOverview/res/view_reset.png create mode 100644 samples/qt/OCCTOverview/res/view_right.png create mode 100644 samples/qt/OCCTOverview/res/view_top.png create mode 100644 samples/qt/OCCTOverview/run.bat create mode 100644 samples/qt/OCCTOverview/run.sh create mode 100644 samples/qt/OCCTOverview/src/ApplicationCommon.cxx create mode 100644 samples/qt/OCCTOverview/src/ApplicationCommon.h create mode 100644 samples/qt/OCCTOverview/src/CommonSample.h create mode 100644 samples/qt/OCCTOverview/src/DocumentCommon.cxx create mode 100644 samples/qt/OCCTOverview/src/DocumentCommon.h create mode 100644 samples/qt/OCCTOverview/src/FILES create mode 100644 samples/qt/OCCTOverview/src/GeomWidget.cxx create mode 100644 samples/qt/OCCTOverview/src/GeomWidget.h create mode 100644 samples/qt/OCCTOverview/src/Main.cxx create mode 100644 samples/qt/OCCTOverview/src/OCCTOverview.qrc create mode 100644 samples/qt/OCCTOverview/src/OcctHighlighter.cxx create mode 100644 samples/qt/OCCTOverview/src/OcctHighlighter.h create mode 100644 samples/qt/OCCTOverview/src/OcctWindow.cxx create mode 100644 samples/qt/OCCTOverview/src/OcctWindow.h create mode 100644 samples/qt/OCCTOverview/src/TranslateDialog.cxx create mode 100644 samples/qt/OCCTOverview/src/TranslateDialog.h create mode 100644 samples/qt/OCCTOverview/src/Transparency.cxx create mode 100644 samples/qt/OCCTOverview/src/Transparency.h create mode 100644 samples/qt/OCCTOverview/src/View.cxx create mode 100644 samples/qt/OCCTOverview/src/View.h create mode 100644 samples/qt/Tutorial/.gitignore delete mode 100644 samples/qt/Tutorial/custom.bat create mode 100644 samples/qt/Tutorial/custom.bat.template delete mode 100755 samples/qt/Tutorial/custom.sh create mode 100644 samples/qt/Tutorial/custom.sh.template diff --git a/CMakeLists.txt b/CMakeLists.txt index 7de42d0ebe..0dccd4b7af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -849,9 +849,11 @@ if (INSTALL_SAMPLES) OCCT_INSTALL_FILE_OR_DIR ("samples/java" "${INSTALL_DIR_SAMPLES}") OCCT_INSTALL_FILE_OR_DIR ("samples/ocafsamples" "${INSTALL_DIR_SAMPLES}") OCCT_INSTALL_FILE_OR_DIR ("samples/qt" "${INSTALL_DIR_SAMPLES}") + OCCT_INSTALL_FILE_OR_DIR ("samples/OCCTOverview/code" "${INSTALL_DIR_SAMPLES}/OCCTOverview") install (FILES "${CMAKE_BINARY_DIR}/env.samples.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SAMPLES}/qt/FuncDemo" RENAME "env.${SCRIPT_EXT}") install (FILES "${CMAKE_BINARY_DIR}/env.samples.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SAMPLES}/qt/IESample" RENAME "env.${SCRIPT_EXT}") + install (FILES "${CMAKE_BINARY_DIR}/env.samples.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SAMPLES}/qt/OCCTOverview" RENAME "env.${SCRIPT_EXT}") install (FILES "${CMAKE_BINARY_DIR}/env.samples.${SCRIPT_EXT}" DESTINATION "${INSTALL_DIR_SAMPLES}/qt/Tutorial" RENAME "env.${SCRIPT_EXT}") endif() diff --git a/adm/SAMPLES b/adm/SAMPLES index d993165b31..92496b7397 100644 --- a/adm/SAMPLES +++ b/adm/SAMPLES @@ -1 +1 @@ -qt AndroidQt FuncDemo IESample Tutorial \ No newline at end of file +qt AndroidQt FuncDemo IESample Tutorial OCCTOverview \ No newline at end of file diff --git a/adm/SAMPLES_RESOURCES b/adm/SAMPLES_RESOURCES index a353f3f6e6..42b0dea440 100644 --- a/adm/SAMPLES_RESOURCES +++ b/adm/SAMPLES_RESOURCES @@ -1,2 +1,3 @@ qt/Common/res/ -qt/Tutorial/res/ \ No newline at end of file +qt/Tutorial/res/ +qt/OCCTOverview/res/ \ No newline at end of file diff --git a/adm/templates/env.bat.in b/adm/templates/env.bat.in index d695c22500..624ea48d05 100644 --- a/adm/templates/env.bat.in +++ b/adm/templates/env.bat.in @@ -140,7 +140,10 @@ if not ["%GLES2_DIR%"] == [""] set "PATH=%GLES2_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%" +if not ["%QTDIR%"] == [""] ( + set "PATH=%QTDIR%/bin;%PATH%" + set "QT_PLUGIN_PATH=%QTDIR%/plugins" +) rem ----- Set path to 3rd party and OCCT libraries ----- if not "%CSF_OCCTBinPath%" == "" ( diff --git a/adm/templates/env.samples.bat.in b/adm/templates/env.samples.bat.in index e855e61336..7cbb822ff1 100644 --- a/adm/templates/env.samples.bat.in +++ b/adm/templates/env.samples.bat.in @@ -27,3 +27,5 @@ if not "%QTDIR%" == "" ( set "PATH=%QTDIR%/bin;%PATH%" set "QT_QPA_PLATFORM_PLUGIN_PATH=%QTDIR%\plugins\platforms" ) + +set "CSF_OCCTOverviewSampleCodePath=%~dp0..\..\OCCTOverview\code" diff --git a/adm/templates/env.samples.sh.in b/adm/templates/env.samples.sh.in index d497aad35d..dddd137f21 100644 --- a/adm/templates/env.samples.sh.in +++ b/adm/templates/env.samples.sh.in @@ -20,3 +20,5 @@ export STATION=$host export RES_DIR=${aSamplePath}/${STATION}/res export PATH=${QTDIR}/bin:${PATH} + +export "CSF_OCCTOverviewSampleCodePath=${aSamplePath}/../../OCCTOverview/code" diff --git a/adm/templates/sample.bat b/adm/templates/sample.bat index e7446dda3f..63b79cc876 100644 --- a/adm/templates/sample.bat +++ b/adm/templates/sample.bat @@ -19,6 +19,7 @@ if ["%1"] == [""] ( echo AndroidQt echo FuncDemo echo IESample + echo OCCTOverview echo Tutorial PAUSE exit /B @@ -35,5 +36,8 @@ if not exist "%EXE_PATH%" ( exit /B ) +rem Set path to location where sample code is installed +set "CSF_OCCTOverviewSampleCodePath=%~dp0samples\OCCTOverview\code" + "%EXE_PATH%" diff --git a/adm/templates/sample.sh b/adm/templates/sample.sh index 44e337a0f9..1d6b75055b 100644 --- a/adm/templates/sample.sh +++ b/adm/templates/sample.sh @@ -8,6 +8,7 @@ if [ "$1" == "" ]; then echo available samples: echo FuncDemo echo IESample + echo OCCTOverview echo Tutorial fi @@ -31,5 +32,7 @@ if [ ! -f "$EXE_PATH" ]; then exit 1 fi +export CSF_OCCTOverviewSampleCodePath="${aCurrentPath}/samples/qt/OCCTOverview/code" + cd ${aCurrentPath} "$EXE_PATH" \ No newline at end of file diff --git a/dox/FILES_HTML.txt b/dox/FILES_HTML.txt index 5fbca28ed3..b71332f5a7 100644 --- a/dox/FILES_HTML.txt +++ b/dox/FILES_HTML.txt @@ -12,6 +12,7 @@ samples/samples.md ../samples/CSharp/ReadMe.md ../samples/CSharp/ReadMe_D3D.md ../samples/qt/AndroidQt/ReadMe.md +../samples/qt/OCCTOverview/ReadMe.md ../samples/java/jniviewer/ReadMe.md ../samples/ios/UIKitSample/ReadMe.md ../samples/webgl/ReadMe.md diff --git a/dox/introduction/images/overview_c__ie.png b/dox/introduction/images/overview_c__ie.png deleted file mode 100644 index 3cfc12e82c819be6008e1d3ac833232052c84f35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38265 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⁡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 UDF{oEp8x;=07*qoM6N<$g0553*Z=?k diff --git a/dox/introduction/images/sample_ios_uikit.png b/dox/introduction/images/sample_ios_uikit.png deleted file mode 100644 index 703e8e5e4fc0e84c503215de3eb5ee0f0ae83e98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48744 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 diff --git a/dox/introduction/images/sample_webgl.png b/dox/introduction/images/sample_webgl.png deleted file mode 100644 index 7d3781faad88696c45c7dd093a92002ce3e40ad7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 75733 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%0Dy^Z;~k)p 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 CusF5= diff --git a/dox/introduction/images/samples_java_android_occt.jpg b/dox/introduction/images/samples_java_android_occt.jpg deleted file mode 100644 index ecba47332b62d6ab170560b3ce28b49ac245261a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13697 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 Bi*x`0 diff --git a/dox/introduction/images/samples_qml_android_occt.jpg b/dox/introduction/images/samples_qml_android_occt.jpg deleted file mode 100644 index 3fbdbd34a3ebf4ec70b6c51338d6e9c9ac574ce5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14519 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 diff --git a/dox/samples/images/overview_overview_qt.png b/dox/samples/images/overview_overview_qt.png deleted file mode 100644 index 9ec815c13fe9fac1adfd6c9b76a5762f97714f7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 165475 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�^l<_jjMV`O*VTB%v0`WH6%xcy2lcEaSZ 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 diff --git a/dox/samples/images/sample_overview_qt.png b/dox/samples/images/sample_overview_qt.png new file mode 100644 index 0000000000000000000000000000000000000000..76850440a9055e22c51bdea0c7fb153157465b36 GIT binary patch literal 112795 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%0A6cpEz{NMo0-7E523H$w;ad=<5zswR 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

N@gZf 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 a)e{j#TW33UvyEt~c$GWqiUkVy{r?Zu9z3xC literal 0 HcmV?d00001 diff --git a/dox/samples/samples.md b/dox/samples/samples.md index 01e06ef975..943db58e57 100644 --- a/dox/samples/samples.md +++ b/dox/samples/samples.md @@ -46,7 +46,10 @@ See @subpage samples_mfc_standard "Readme" for details. Qt --- - OCCT contains three samples based on Qt application framework + OCCT includes several samples based on Qt application framework. +These samples are available on all supported desktop platforms. + +To start a sample on Windows use Open CASCADE Technology\\Samples\\Qt\\ item of the Start\\Programs menu. Import Export ------------- @@ -69,6 +72,27 @@ The combination of these resources allows creating substantial applications. **See also:** @ref occt__tutorial "OCCT Tutorial" +Overview +--------- + +The Qt application providing samples for basic usage of C++ API of various OCCT functionality. + +The samples are organized in several categories according to relevant module of OCCT: + + * Geometry + * Topology, + * Triangulation + * DataExchange + * OCAF + * Viewer 2d + * Viewer 3d + +Each sample presents geometry view, C++ code fragment and sample output window. + +@figure{/samples/images/sample_overview_qt.png} + +See \subpage samples_qt_overview "Readme" for details. + C# --- diff --git a/samples/OCCTOverview/code/AdaptorCurve2d_AIS.cxx b/samples/OCCTOverview/code/AdaptorCurve2d_AIS.cxx new file mode 100644 index 0000000000..b17d89cb09 --- /dev/null +++ b/samples/OCCTOverview/code/AdaptorCurve2d_AIS.cxx @@ -0,0 +1,147 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "AdaptorCurve2d_AIS.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +AdaptorCurve2d_AIS::AdaptorCurve2d_AIS (const Handle(Geom2d_Curve)& theGeom2dCurve, + const Aspect_TypeOfLine theTypeOfLine, + const Aspect_WidthOfLine theWidthOfLine) +: myGeom2dCurve (theGeom2dCurve), + myTypeOfLine (theTypeOfLine), + myWidthOfLine (theWidthOfLine), + myDisplayPole (Standard_True), + myDisplayCurbure (Standard_False), + myDiscretisation (20), + myradiusmax (10), + myradiusratio (1) +{ + // +} + +void AdaptorCurve2d_AIS::Compute (const Handle(PrsMgr_PresentationManager3d)&, + const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer theMode) +{ + if (theMode != 0) + { + return; + } + + Geom2dAdaptor_Curve anAdaptor(myGeom2dCurve); + GCPnts_QuasiUniformDeflection anEdgeDistrib(anAdaptor, 1.e-2); + if (anEdgeDistrib.IsDone()) + { + Handle(Graphic3d_ArrayOfPolylines) aCurve = new Graphic3d_ArrayOfPolylines(anEdgeDistrib.NbPoints()); + for (Standard_Integer i = 1; i <= anEdgeDistrib.NbPoints(); ++i) + { + aCurve->AddVertex(anEdgeDistrib.Value(i)); + } + + Handle(Graphic3d_Group) aPrsGroup = thePrs->NewGroup(); + aPrsGroup->SetGroupPrimitivesAspect(myDrawer->LineAspect()->Aspect()); + aPrsGroup->AddPrimitiveArray(aCurve); + } + + if (myDisplayPole) + { + if (anAdaptor.GetType() == GeomAbs_BezierCurve) + { + Handle(Geom2d_BezierCurve) aBezier = anAdaptor.Bezier(); + Handle(Graphic3d_ArrayOfPolylines) anArrayOfVertex = new Graphic3d_ArrayOfPolylines(aBezier->NbPoles()); + for (int i = 1; i <= aBezier->NbPoles(); i++) + { + gp_Pnt2d CurrentPoint = aBezier->Pole(i); + anArrayOfVertex->AddVertex(CurrentPoint.X(), CurrentPoint.Y(), 0.); + } + + Handle(Graphic3d_Group) aPrsGroup = thePrs->NewGroup(); + aPrsGroup->SetGroupPrimitivesAspect(myDrawer->LineAspect()->Aspect()); + aPrsGroup->AddPrimitiveArray(anArrayOfVertex); + } + + if (anAdaptor.GetType() == GeomAbs_BSplineCurve) + { + Handle(Geom2d_BSplineCurve) aBSpline = anAdaptor.BSpline(); + Handle(Graphic3d_ArrayOfPolylines) anArrayOfVertex = new Graphic3d_ArrayOfPolylines(aBSpline->NbPoles()); + for (int i = 1; i <= aBSpline->NbPoles(); i++) + { + gp_Pnt2d CurrentPoint = aBSpline->Pole(i); + anArrayOfVertex->AddVertex(CurrentPoint.X(), CurrentPoint.Y(), 0.); + } + + Handle(Graphic3d_Group) aPrsGroup = thePrs->NewGroup(); + aPrsGroup->SetGroupPrimitivesAspect(myDrawer->LineAspect()->Aspect()); + aPrsGroup->AddPrimitiveArray(anArrayOfVertex); + } + } + + if (myDisplayCurbure && (anAdaptor.GetType() != GeomAbs_Line)) + { + const Standard_Integer nbintv = anAdaptor.NbIntervals(GeomAbs_CN); + TColStd_Array1OfReal TI(1, nbintv + 1); + anAdaptor.Intervals(TI, GeomAbs_CN); + Standard_Real Resolution = 1.0e-9, Curvature; + Geom2dLProp_CLProps2d LProp(myGeom2dCurve, 2, Resolution); + gp_Pnt2d P1, P2; + + Handle(Graphic3d_Group) aPrsGroup = thePrs->NewGroup(); + aPrsGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect()); + for (Standard_Integer intrv = 1; intrv <= nbintv; intrv++) + { + Standard_Real t = TI(intrv); + Standard_Real step = (TI(intrv + 1) - t) / GetDiscretisation(); + Standard_Real LRad, ratio; + for (Standard_Integer ii = 1; ii <= myDiscretisation; ii++) + { + LProp.SetParameter(t); + if (LProp.IsTangentDefined()) + { + Curvature = Abs(LProp.Curvature()); + if (Curvature > Resolution) + { + myGeom2dCurve->D0(t, P1); + LRad = 1. / Curvature; + ratio = ((LRad > myradiusmax) ? myradiusmax / LRad : 1); + ratio *= myradiusratio; + LProp.CentreOfCurvature(P2); + gp_Vec2d V(P1, P2); + gp_Pnt2d P3 = P1.Translated(ratio*V); + Handle(Graphic3d_ArrayOfPolylines) aSegment = new Graphic3d_ArrayOfPolylines(2); + aSegment->AddVertex(P1.X(), P1.Y(), 0.); + aSegment->AddVertex(P3.X(), P3.Y(), 0.); + aPrsGroup->AddPrimitiveArray(aSegment); + } + } + t += step; + } + } + } +} diff --git a/samples/OCCTOverview/code/AdaptorCurve2d_AIS.h b/samples/OCCTOverview/code/AdaptorCurve2d_AIS.h new file mode 100644 index 0000000000..abb5723d55 --- /dev/null +++ b/samples/OCCTOverview/code/AdaptorCurve2d_AIS.h @@ -0,0 +1,77 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef ADAPTOR_CURVE2D_AIS_H +#define ADAPTOR_CURVE2D_AIS_H + +#include +#include +#include +#include + +//! AIS interactive Object for Geom2d_Curve +class AdaptorCurve2d_AIS : public AIS_InteractiveObject +{ + DEFINE_STANDARD_RTTI_INLINE(AdaptorCurve2d_AIS, AIS_InteractiveObject) +public: + AdaptorCurve2d_AIS(const Handle(Geom2d_Curve)& theGeom2dCurve, + const Aspect_TypeOfLine theTypeOfline = Aspect_TOL_SOLID, + const Aspect_WidthOfLine theWidthOfLine = Aspect_WOL_MEDIUM); + + Standard_Integer NbPossibleSelection() const { return 1; } + Aspect_TypeOfLine GetTypeOfLine() const { return myTypeOfLine; } + void SetTypeOfLine(const Aspect_TypeOfLine aNewTypeOfLine) { myTypeOfLine = aNewTypeOfLine; } + Aspect_WidthOfLine GetWidthOfLine() const { return myWidthOfLine; } + void SetWidthOfLine(const Aspect_WidthOfLine aNewWidthOfLine) { myWidthOfLine = aNewWidthOfLine; } + Standard_Boolean GetDisplayPole() const { return myDisplayPole; } + void SetDisplayPole(const Standard_Boolean aNewDisplayPole) { myDisplayPole = aNewDisplayPole; } + Standard_Boolean GetDisplayCurbure() const { return myDisplayCurbure; } + void SetDisplayCurbure(const Standard_Boolean aNewDisplayCurbure) { myDisplayCurbure = aNewDisplayCurbure; } + Standard_Real GetDiscretisation() const { return myDiscretisation; } + void SetDiscretisation(const Standard_Real aNewDiscretisation) { myDiscretisation = aNewDiscretisation; } + +private: + //! Return TRUE for supported display modes (only 0 mode is supported). + virtual Standard_Boolean AcceptDisplayMode(const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0; } + + //! Compute presentation. + virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr, + const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer theMode) Standard_OVERRIDE; + + //! Compute selection (not implemented). + virtual void ComputeSelection (const Handle(SelectMgr_Selection)&, + const Standard_Integer) Standard_OVERRIDE {} + +private: + + Handle(Geom2d_Curve) myGeom2dCurve; + Aspect_TypeOfLine myTypeOfLine; + Aspect_WidthOfLine myWidthOfLine; + Standard_Boolean myDisplayPole; + Standard_Boolean myDisplayCurbure; + Standard_Real myDiscretisation; + Standard_Real myradiusmax; + Standard_Real myradiusratio; + +}; + +#endif diff --git a/samples/OCCTOverview/code/AdaptorCurve_AIS.cxx b/samples/OCCTOverview/code/AdaptorCurve_AIS.cxx new file mode 100644 index 0000000000..21a692fc5b --- /dev/null +++ b/samples/OCCTOverview/code/AdaptorCurve_AIS.cxx @@ -0,0 +1,49 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "AdaptorCurve_AIS.h" + +#include +#include +#include +#include + +void AdaptorCurve_AIS::Compute (const Handle(PrsMgr_PresentationManager3d)&, + const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer theMode) +{ + GeomAdaptor_Curve anAdaptorCurve(myCurve); + switch (theMode) + { + case 1: + { + Handle(Prs3d_Drawer) aPoleDrawer = new Prs3d_Drawer(); + aPoleDrawer->SetLineAspect(new Prs3d_LineAspect(Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0)); + StdPrs_PoleCurve::Add(thePrs, anAdaptorCurve, aPoleDrawer); + } + Standard_FALLTHROUGH + case 0: + { + StdPrs_Curve::Add(thePrs, anAdaptorCurve, myDrawer); + break; + } + } +} diff --git a/samples/OCCTOverview/code/AdaptorCurve_AIS.h b/samples/OCCTOverview/code/AdaptorCurve_AIS.h new file mode 100644 index 0000000000..a01c99d7c7 --- /dev/null +++ b/samples/OCCTOverview/code/AdaptorCurve_AIS.h @@ -0,0 +1,52 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef ADAPTOR_CURVE_AIS_H +#define ADAPTOR_CURVE_AIS_H + +#include +#include + +//! AIS interactive Object for Geom_Curve +class AdaptorCurve_AIS : public AIS_InteractiveObject +{ + DEFINE_STANDARD_RTTI_INLINE(AdaptorCurve_AIS, AIS_InteractiveObject) +public: + AdaptorCurve_AIS (const Handle(Geom_Curve)& theCurve) : myCurve(theCurve) {} +private: + + //! Return TRUE for supported display modes (modes 0 and 1 are supported). + virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; } + + //! Compute presentation. + Standard_EXPORT virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr, + const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer theMode) Standard_OVERRIDE; + + //! Compute selection (not implemented). + virtual void ComputeSelection (const Handle(SelectMgr_Selection)&, + const Standard_Integer) Standard_OVERRIDE {} + +private: + Handle(Geom_Curve) myCurve; +}; + +#endif diff --git a/samples/OCCTOverview/code/AdaptorPnt2d_AIS.cxx b/samples/OCCTOverview/code/AdaptorPnt2d_AIS.cxx new file mode 100644 index 0000000000..80fdbf11d5 --- /dev/null +++ b/samples/OCCTOverview/code/AdaptorPnt2d_AIS.cxx @@ -0,0 +1,38 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "AdaptorPnt2d_AIS.h" + +#include +#include + +void AdaptorPnt2d_AIS::Compute (const Handle(PrsMgr_PresentationManager3d)& , + const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer theMode) +{ + if (theMode != 0) + { + return; + } + + Handle(Geom_CartesianPoint) aGeomPoint = new Geom_CartesianPoint(myPoint); + StdPrs_Point::Add (thePrs, aGeomPoint, myDrawer); +} diff --git a/samples/OCCTOverview/code/AdaptorPnt2d_AIS.h b/samples/OCCTOverview/code/AdaptorPnt2d_AIS.h new file mode 100644 index 0000000000..b34bee2b79 --- /dev/null +++ b/samples/OCCTOverview/code/AdaptorPnt2d_AIS.h @@ -0,0 +1,57 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef ADAPTOR_PNT2D_AIS_H +#define ADAPTOR_PNT2D_AIS_H + +#include +#include + +//! AIS interactive Object for Geom2d_Point +class AdaptorPnt2d_AIS : public AIS_InteractiveObject +{ + DEFINE_STANDARD_RTTI_INLINE(AdaptorPnt2d_AIS, AIS_InteractiveObject) +public: + AdaptorPnt2d_AIS (const Handle(Geom2d_Point)& thePoint, + Standard_Real theElevation = 0) + : myPoint(thePoint->X(), thePoint->Y(), theElevation) {} + +private: + + //! Return TRUE for supported display modes (only mode 0 is supported). + virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0; } + + //! Compute presentation. + virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr, + const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer theMode) Standard_OVERRIDE; + + //! Compute selection (not implemented). + virtual void ComputeSelection (const Handle(SelectMgr_Selection)&, + const Standard_Integer) Standard_OVERRIDE {} + +private: + + gp_Pnt myPoint; + +}; + +#endif // ADAPTOR_PNT2D_AIS_H diff --git a/samples/OCCTOverview/code/AdaptorVec_AIS.cxx b/samples/OCCTOverview/code/AdaptorVec_AIS.cxx new file mode 100644 index 0000000000..e344acda84 --- /dev/null +++ b/samples/OCCTOverview/code/AdaptorVec_AIS.cxx @@ -0,0 +1,77 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "AdaptorVec_AIS.h" + +#include +#include +#include +#include +#include + +AdaptorVec_AIS::AdaptorVec_AIS (const gp_Pnt2d& thePnt1, + const gp_Pnt2d& thePnt2, + Standard_Real theArrowLength) +: myPnt (gp_Pnt (thePnt1.X(), thePnt1.Y(), 0.0)), + myLength (0.0), + myArrowLength (theArrowLength) +{ + gp_Vec aVec (thePnt2.X() - thePnt1.X(), thePnt2.Y() - thePnt1.Y(), 0.0); + myDir = gp_Dir(aVec); + myLength = aVec.Magnitude(); +} + +void AdaptorVec_AIS::Compute (const Handle(PrsMgr_PresentationManager3d)& , + const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer theMode) +{ + if (theMode != 0) + { + return; + } + + // Set style for arrow + Handle(Prs3d_ArrowAspect) anArrowAspect = myDrawer->ArrowAspect(); + anArrowAspect->SetLength(myArrowLength); + + gp_Pnt aLastPoint = myPnt; + aLastPoint.Translate(myLength*gp_Vec(myDir)); + + // Draw Line + { + Handle(Graphic3d_Group) aLineGroup = thePrs->NewGroup(); + aLineGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect()); + Handle(Graphic3d_ArrayOfSegments) aPrims = new Graphic3d_ArrayOfSegments(2); + aPrims->AddVertex(myPnt); + aPrims->AddVertex(aLastPoint); + aLineGroup->AddPrimitiveArray(aPrims); + + // Draw arrow + Prs3d_Arrow::Draw (aLineGroup, aLastPoint, myDir, anArrowAspect->Angle(), anArrowAspect->Length()); + } + + // Draw text + if (!myText.IsEmpty()) + { + gp_Pnt aTextPosition = aLastPoint; + Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myText, aTextPosition); + } +} diff --git a/samples/OCCTOverview/code/AdaptorVec_AIS.h b/samples/OCCTOverview/code/AdaptorVec_AIS.h new file mode 100644 index 0000000000..25e02d7c86 --- /dev/null +++ b/samples/OCCTOverview/code/AdaptorVec_AIS.h @@ -0,0 +1,121 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef ADAPTOR_VEC_AIS_H +#define ADAPTOR_VEC_AIS_H + +#include + +//! AIS interactive Object for vector with arrow and text +class AdaptorVec_AIS : public AIS_InteractiveObject +{ + DEFINE_STANDARD_RTTI_INLINE(AdaptorVec_AIS, AIS_InteractiveObject) +public: + + AdaptorVec_AIS() + : myLength (1.0), + myArrowLength (1.0) + {} + + AdaptorVec_AIS (const gp_Pnt& thePnt, + const gp_Dir& theDir, + Standard_Real theLength = 1, + Standard_Real theArrowLength = 1) + : myPnt (thePnt), + myDir (theDir), + myLength (theLength), + myArrowLength (theArrowLength) + { + // + } + + AdaptorVec_AIS (const gp_Pnt& thePnt, + const gp_Vec& theVec, + Standard_Real theArrowLength = 1) + : myPnt (thePnt), + myDir (theVec), + myLength (theVec.Magnitude()), + myArrowLength (theArrowLength) + { + // + } + + AdaptorVec_AIS (const gp_Pnt2d& thePnt2d, + const gp_Dir2d& theDir2d, + Standard_Real theLength = 1, + Standard_Real theArrowLength = 1) + : myPnt (gp_Pnt(thePnt2d.X(), thePnt2d.Y(), 0.0)), + myDir (gp_Dir(theDir2d.X(), theDir2d.Y(), 0.0)), + myLength (theLength), + myArrowLength (theArrowLength) + { + // + } + + AdaptorVec_AIS (const gp_Pnt2d& thePnt2d, + const gp_Vec2d& theVec2d, + Standard_Real theArrowLength = 1) + : myPnt (gp_Pnt(thePnt2d.X(), thePnt2d.Y(), 0.0)), + myDir (gp_Dir(theVec2d.X(), theVec2d.Y(), 0.0)), + myLength (theVec2d.Magnitude()), + myArrowLength (theArrowLength) + { + // + } + + AdaptorVec_AIS (const gp_Pnt2d& thePnt1, + const gp_Pnt2d& thePnt2, + Standard_Real theArrowLength = 1); + + void SetText (const TCollection_AsciiString& theText) + { + myText = theText; + } + + void SetLineAspect (const Handle(Prs3d_LineAspect)& theAspect) + { + myDrawer->SetLineAspect(theAspect); + } + +private: + + //! Return TRUE for supported display modes (only mode 0 is supported). + virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0; } + + //! Compute presentation. + virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr, + const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer theMode) Standard_OVERRIDE; + + //! Compute selection (not implemented). + virtual void ComputeSelection (const Handle(SelectMgr_Selection)&, + const Standard_Integer) Standard_OVERRIDE {} + +private: + + gp_Pnt myPnt; + gp_Dir myDir; + Standard_Real myLength; + Standard_Real myArrowLength; + TCollection_AsciiString myText; +}; + +#endif // ADAPTOR_VEC2D_AIS_H diff --git a/samples/OCCTOverview/code/BaseSample.cxx b/samples/OCCTOverview/code/BaseSample.cxx new file mode 100644 index 0000000000..b0aa8d2ce5 --- /dev/null +++ b/samples/OCCTOverview/code/BaseSample.cxx @@ -0,0 +1,185 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "BaseSample.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +const TCollection_AsciiString BaseSample::FILE_EXTENSION = "cxx"; + +void BaseSample::Clear() +{ + myObject3d.Clear(); + myObject2d.Clear(); + myCode.Clear(); + myResult.str(""); +} + +TCollection_AsciiString BaseSample::GetResult() +{ + TCollection_AsciiString aResult(myResult.str().c_str()); + myResult.str(""); + return aResult; +} + +void BaseSample::AppendCube() +{ + Handle(AIS_ViewCube) aViewCube = new AIS_ViewCube(); + myObject3d.Append(aViewCube); +} + +void BaseSample::Process (const TCollection_AsciiString& theSampleName) +{ + myObject3d.Clear(); + myObject2d.Clear(); + myCode.Clear(); + myIsProcessed = Standard_False; + try + { + ExecuteSample(theSampleName); + if (!myObject3d.IsEmpty()) + { + Handle(AIS_ViewCube) aViewCube = new AIS_ViewCube(); + myObject3d.Append(aViewCube); + } + } + catch (...) + { + TraceError(TCollection_AsciiString("Error in sample: ") + theSampleName); + } +} + +void BaseSample::TraceError (const TCollection_AsciiString& theErrorMessage) +{ + Message::SendFail() << "\nERROR: " << theErrorMessage.ToCString() << std::endl; + myResult << "\nERROR: " << theErrorMessage << std::endl; +} + +void BaseSample::FindSourceCode (const TCollection_AsciiString& theSampleName) +{ + TCollection_AsciiString aClassName = DynamicType()->Name(); + char aSeparator = QDir::separator().toLatin1(); + TCollection_AsciiString aCxxFilePach = myCodePath + aSeparator + aClassName + '.' + FILE_EXTENSION; + OSD_File aCxxFile(aCxxFilePach); + try + { + const Standard_Integer aFileBufferSize = 100 * 1024; + TCollection_AsciiString aReadedText(aFileBufferSize); + aCxxFile.Open(OSD_ReadOnly, OSD_Protection()); + aCxxFile.Read(aReadedText, aFileBufferSize); + TCollection_AsciiString aRegexpTemplate = aClassName + "::" + theSampleName + "[\\n\\s]*\\([\\n\\s]*\\)[\\n\\s]*\\{"; + Standard_Integer aOpeningBracketPosition = findEndOfPhrase (aReadedText, aRegexpTemplate); + Standard_Integer aClosingBracketPosition = findClosingBracket (aReadedText, aOpeningBracketPosition, '}'); + myCode = aReadedText.SubString(aOpeningBracketPosition + 1, aClosingBracketPosition - 1); + } + catch (...) + { + TraceError(TCollection_AsciiString("Cannot open file: ") + aCxxFilePach); + } +} + +Standard_Integer BaseSample::findEndOfPhrase (const TCollection_AsciiString& theText, + const TCollection_AsciiString& theRegexpTemplate) +{ + Standard_Integer aIndexOfLastFoundSymbol = -1; + std::string aStdText = theText.ToCString(); + std::string aRegexpTemplate = theRegexpTemplate.ToCString(); + + try + { + std::regex aRegex(theRegexpTemplate.ToCString()); + + std::sregex_iterator aDetectIterator = std::sregex_iterator(aStdText.begin(), aStdText.end(), aRegex); + if (aDetectIterator != std::sregex_iterator()) + { + std::smatch aMatch = *aDetectIterator; + std::string aFoundString = aMatch.str(); + aIndexOfLastFoundSymbol = static_cast(aStdText.find(aFoundString) + aFoundString.length()); + } + else + { + TraceError(TCollection_AsciiString("No code found for template: ") + theRegexpTemplate); + } + } + catch (const std::regex_error& aRegError) + { + TraceError(TCollection_AsciiString("regex_error: ") + aRegError.what()); + } + catch (const std::exception& aEx) + { + TraceError(TCollection_AsciiString("common error: ") + aEx.what()); + } + catch (...) + { + TraceError("unknown error!"); + } + return aIndexOfLastFoundSymbol; +} + +Standard_Integer BaseSample::findClosingBracket (const TCollection_AsciiString& theText, + const Standard_Integer theOpeningBracketIndex, + Standard_Character theClosingBracketSymbol) +{ + // TODO this function not implemented at least 2 cases: + // - brackets in strings & chars + // - brackets in comments + Standard_Integer aClosingBracketIndex = -1; + Standard_Character anOpeningBracketSymbol = theText.Value(theOpeningBracketIndex); + TCollection_AsciiString aBracketsSet(theClosingBracketSymbol); + aBracketsSet += anOpeningBracketSymbol; + Standard_Integer aBracketDepth = 1; + Standard_Integer aStartFindIndex = theOpeningBracketIndex + 1; + //Standard_Character aStartFindChar = theText.Value(aStartFindIndex-1); + while (aBracketDepth) + { + aStartFindIndex = theText.FirstLocationInSet(aBracketsSet, aStartFindIndex, theText.Length()); + if (!aStartFindIndex) + { + TraceError("No closing bracket found!"); + break; + } + TCollection_AsciiString aRSubstr = theText.SubString(aStartFindIndex, theText.Length()); + if (theText.Value(aStartFindIndex) == anOpeningBracketSymbol) + aBracketDepth++; + else if (theText.Value(aStartFindIndex) == theClosingBracketSymbol) + aBracketDepth--; + if (!aBracketDepth) + { + aClosingBracketIndex = aStartFindIndex; + break; + } + aStartFindIndex++; + } + return aClosingBracketIndex; +} diff --git a/samples/OCCTOverview/code/BaseSample.h b/samples/OCCTOverview/code/BaseSample.h new file mode 100644 index 0000000000..20c2470af6 --- /dev/null +++ b/samples/OCCTOverview/code/BaseSample.h @@ -0,0 +1,87 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef BASESAMPLE_H +#define BASESAMPLE_H + +#include + +#include +#include +#include + +//! Base class for specified category classes +class BaseSample: public Standard_Transient +{ + DEFINE_STANDARD_RTTI_INLINE(BaseSample, Standard_Transient) +public: + BaseSample (const TCollection_AsciiString& theSampleSourcePath, + const Handle(AIS_InteractiveContext)& theContext) + : myCodePath (theSampleSourcePath), + myContext (theContext) + { + // + } + + void Clear(); + void AppendCube(); + + Standard_Boolean IsProcessed() const { return myIsProcessed; } + + const NCollection_Vector& Get2dObjects() const { return myObject2d; } + + const NCollection_Vector& Get3dObjects() const { return myObject3d; } + + TCollection_AsciiString GetResult(); + + TCollection_AsciiString GetCode() const { return myCode; } + + virtual void Process (const TCollection_AsciiString& theSampleName); + +protected: + virtual void ExecuteSample (const TCollection_AsciiString& theSampleName) = 0; + + void FindSourceCode (const TCollection_AsciiString& theSampleName); + void TraceError (const TCollection_AsciiString& theErrorMessage); + +protected: + + Standard_Boolean myIsProcessed; + NCollection_Vector myObject2d; + NCollection_Vector myObject3d; + + std::ostringstream myResult; + TCollection_AsciiString myCode; + TCollection_AsciiString myCodePath; + Handle(AIS_InteractiveContext) myContext; + +protected: + static const TCollection_AsciiString FILE_EXTENSION; + +private: + Standard_Integer findEndOfPhrase (const TCollection_AsciiString& theText, + const TCollection_AsciiString& theRegexpTemplate); + Standard_Integer findClosingBracket (const TCollection_AsciiString& theText, + Standard_Integer theOpeningBracketIndex, + Standard_Character theClosingBracketSymbol); +}; + +#endif //BASESAMPLE_H diff --git a/samples/OCCTOverview/code/DataExchange.json b/samples/OCCTOverview/code/DataExchange.json new file mode 100644 index 0000000000..9d7f444c8f --- /dev/null +++ b/samples/OCCTOverview/code/DataExchange.json @@ -0,0 +1,51 @@ +{ + "Data Exchange": { + "Export": [{ + "text": "BREP", + "function": "BrepExportSample", + "description": "" + }, + { + "text": "STEP", + "function": "StepExportSample", + "description": "" + }, + { + "text": "IGES", + "function": "IgesExportSample", + "description": "" + }, + { + "text": "STL", + "function": "StlExportSample", + "description": "" + }, + { + "text": "VRML", + "function": "VrmlExportSample", + "description": "" + }, + { + "text": "Image", + "function": "ImageExportSample", + "description": "" + } + ], + "Import": [{ + "text": "BREP", + "function": "BrepImportSample", + "description": "" + }, + { + "text": "STEP", + "function": "StepImportSample", + "description": "" + }, + { + "text": "IGES", + "function": "IgesImportSample", + "description": "" + } + ] + } +} \ No newline at end of file diff --git a/samples/OCCTOverview/code/DataExchangeSamples.cxx b/samples/OCCTOverview/code/DataExchangeSamples.cxx new file mode 100644 index 0000000000..e6bac7356f --- /dev/null +++ b/samples/OCCTOverview/code/DataExchangeSamples.cxx @@ -0,0 +1,410 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "DataExchangeSamples.h" + +#include "MakeBottle.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void DataExchangeSamples::Process (const TCollection_AsciiString& theSampleName) +{ + if (IsImportSample(theSampleName)) + { + myObject3d.Clear(); + } + myObject2d.Clear(); + myCode.Clear(); + myIsProcessed = Standard_False; + try + { + ExecuteSample(theSampleName); + } + catch (...) + { + TraceError(TCollection_AsciiString("Error in sample: ") + theSampleName); + } +} + +void DataExchangeSamples::AppendBottle() +{ + TopoDS_Shape aBottle = MakeBottle(50, 70, 30); + Handle(AIS_InteractiveObject) aShape = new AIS_Shape(aBottle); + myObject3d.Append(aShape); + Handle(AIS_ViewCube) aViewCube = new AIS_ViewCube(); + myObject3d.Append(aViewCube); + myResult << "A bottle shape was created." << std::endl; +} + +void DataExchangeSamples::ExecuteSample (const TCollection_AsciiString& theSampleName) +{ + Standard_Boolean anIsSamplePresent = Standard_True; + FindSourceCode(theSampleName); + if (theSampleName == "BrepExportSample") + { + BrepExportSample(); + } + else if (theSampleName == "StepExportSample") + { + StepExportSample(); + } + else if (theSampleName == "IgesExportSample") + { + IgesExportSample(); + } + else if (theSampleName == "StlExportSample") + { + StlExportSample(); + } + else if (theSampleName == "VrmlExportSample") + { + VrmlExportSample(); + } + else if (theSampleName == "ImageExportSample") + { + ImageExportSample(); + } + else if (theSampleName == "BrepImportSample") + { + BrepImportSample(); + } + else if (theSampleName == "StepImportSample") + { + StepImportSample(); + } + else if (theSampleName == "IgesImportSample") + { + IgesImportSample(); + } + else + { + myResult << "No function found: " << theSampleName; + myCode += TCollection_AsciiString("No function found: ") + theSampleName; + anIsSamplePresent = Standard_False; + } + myIsProcessed = anIsSamplePresent; +} + +void DataExchangeSamples::BrepExportSample() +{ + Standard_Boolean anIsShapeExist = Standard_False; + for (Handle(AIS_InteractiveObject) anObject : myObject3d) + { + if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anObject)) + { + anIsShapeExist = Standard_True; + if (BRepTools::Write(aShape->Shape(), myFileName.ToCString())) + { + myResult << "A shape was successfully written" << std::endl; + } + else + { + myResult << "A shape was not written" << std::endl; + } + break; // write only one shape + } + } + if (!anIsShapeExist) + { + myResult << "A shape does not exist" << std::endl; + } +} + +void DataExchangeSamples::StepExportSample() +{ + if (myStepType < 0) + { + myResult << "Unknown step type" << std::endl; + return; + } + + IFSelect_ReturnStatus aStatus; + + if (myStepType == STEPControl_FacetedBrep && !CheckFacetedBrep()) + { + myResult << "At least one shape doesn't contain facets" << std::endl; + return; + } + + STEPControl_Writer aStepWriter; + for (Handle(AIS_InteractiveObject) anObject : myObject3d) + { + if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anObject)) + { + aStatus = aStepWriter.Transfer(aShape->Shape(), myStepType); + if (aStatus != IFSelect_RetDone) + { + myResult << "A shape was not transferred successfully" << std::endl; + return; + } + } + } + aStatus = aStepWriter.Write(myFileName.ToCString()); + + switch (aStatus) + { + case IFSelect_RetError: + myResult << "Incorrect Data." << std::endl; + break; + case IFSelect_RetFail: + myResult << "Writing error" << std::endl; + break; + case IFSelect_RetVoid: + myResult << "Nothing to transfer." << std::endl; + break; + case IFSelect_RetStop: + case IFSelect_RetDone: + myResult << "A STEP file was successfully written" << std::endl; + break; + } + +} + +void DataExchangeSamples::IgesExportSample() +{ + IGESControl_Controller::Init(); + IGESControl_Writer anIgesWriter(Interface_Static::CVal("XSTEP.iges.unit"), + Interface_Static::IVal("XSTEP.iges.writebrep.mode")); + + Standard_Boolean anIsShapeExist = Standard_False; + for (Handle(AIS_InteractiveObject) anObject : myObject3d) + { + if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anObject)) + { + anIsShapeExist = Standard_True; + anIgesWriter.AddShape(aShape->Shape()); + } + } + if (anIsShapeExist) + { + anIgesWriter.ComputeModel(); + if (anIgesWriter.Write(myFileName.ToCString())) + { + myResult << "A STEP file was successfully written" << std::endl; + } + else + { + myResult << "A STEP file was not written" << std::endl; + } + } + else + { + myResult << "Shapes do not exist" << std::endl; + } +} + +void DataExchangeSamples::StlExportSample() +{ + TopoDS_Compound aTopoCompound; + BRep_Builder aBuilder; + aBuilder.MakeCompound(aTopoCompound); + + Standard_Boolean anIsShapeExist = Standard_False; + for (Handle(AIS_InteractiveObject) anObject : myObject3d) + { + if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anObject)) + { + anIsShapeExist = Standard_True; + aBuilder.Add(aTopoCompound, aShape->Shape()); + } + } + if (anIsShapeExist) + { + StlAPI_Writer aStlWriter; + if (aStlWriter.Write(aTopoCompound, myFileName.ToCString())) + { + myResult << "A STL file was successfully written" << std::endl; + } + else + { + myResult << "A STL file was not written" << std::endl; + } + } + else + { + myResult << "Shapes do not exist" << std::endl; + } +} + +void DataExchangeSamples::VrmlExportSample() +{ + TopoDS_Compound aTopoCompound; + BRep_Builder aBrepBuilder; + aBrepBuilder.MakeCompound(aTopoCompound); + + Standard_Boolean anIsShapeExist = Standard_False; + for (Handle(AIS_InteractiveObject) anObject : myObject3d) + { + if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anObject)) + { + anIsShapeExist = Standard_True; + aBrepBuilder.Add(aTopoCompound, aShape->Shape()); + } + } + if (anIsShapeExist) + { + VrmlAPI_Writer aVrmlWriter; + if (aVrmlWriter.Write(aTopoCompound, myFileName.ToCString())) + { + myResult << "A VRML file was successfully written" << std::endl; + } + else + { + myResult << "A VRML file was not written" << std::endl; + } + } + else + { + myResult << "Shapes do not exist" << std::endl; + } +} + +void DataExchangeSamples::ImageExportSample() +{ + if (myView) + { + Standard_Boolean aResult = myView->Dump(myFileName.ToCString()); + if (aResult) + { + myResult << "An image file was successfully written" << std::endl; + } + else + { + myResult << "An image file was not written" << std::endl; + } + } +} + +void DataExchangeSamples::BrepImportSample() +{ + TopoDS_Shape aTopoShape; + BRep_Builder aBuilder; + Standard_Boolean aResult = BRepTools::Read(aTopoShape, myFileName.ToCString(), aBuilder); + if (aResult) + { + Handle(AIS_Shape) anAisShape = new AIS_Shape(aTopoShape); + myObject3d.Append(anAisShape); + myResult << "A BREP file was read successfully" << std::endl; + } + else + { + myResult << "A BREP file was not read successfully" << std::endl; + } +} + +void DataExchangeSamples::StepImportSample() +{ + Handle(TopTools_HSequenceOfShape) aSequence = new TopTools_HSequenceOfShape(); + STEPControl_Reader aReader; + const IFSelect_ReturnStatus aStatus = aReader.ReadFile(myFileName.ToCString()); + if (aStatus != IFSelect_RetDone) + { + myResult << "A BREP file was not read successfully" << std::endl; + return; + } + + bool anIsFailsOnly = false; + aReader.PrintCheckLoad(anIsFailsOnly, IFSelect_ItemsByEntity); + + int aRootsNumber = aReader.NbRootsForTransfer(); + aReader.PrintCheckTransfer(anIsFailsOnly, IFSelect_ItemsByEntity); + for (Standard_Integer i = 1; i <= aRootsNumber; i++) + { + aReader.TransferRoot(i); + } + + int aShapesNumber = aReader.NbShapes(); + for (int i = 1; i <= aShapesNumber; i++) + { + TopoDS_Shape aTopoShape = aReader.Shape(i); + Handle(AIS_Shape) anAisShape = new AIS_Shape(aTopoShape); + myObject3d.Append(anAisShape); + } + myResult << "A STEP file was read successfully" << std::endl; +} + +void DataExchangeSamples::IgesImportSample() +{ + IGESControl_Reader aReader; + int status = aReader.ReadFile (myFileName.ToCString()); + if (status != IFSelect_RetDone) + { + myResult << "A IGES file was not read successfully" << std::endl; + return; + } + aReader.TransferRoots(); + TopoDS_Shape aTopoShape = aReader.OneShape(); + Handle(AIS_Shape) anAisShape = new AIS_Shape (aTopoShape); + myObject3d.Append(anAisShape); + myResult << "A IGES file was read successfully" << std::endl; +} + +Standard_Boolean DataExchangeSamples::CheckFacetedBrep() +{ + Standard_Boolean anError = Standard_False; + for (Handle(AIS_InteractiveObject) anObject : myObject3d) + { + if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anObject)) + { + const TopoDS_Shape aTopoShape = aShape->Shape(); + for (TopExp_Explorer aFaceExplorer(aTopoShape, TopAbs_FACE); aFaceExplorer.More() && !anError; aFaceExplorer.Next()) + { + Handle(Geom_Surface) aSurface = BRep_Tool::Surface(TopoDS::Face(aFaceExplorer.Current())); + if (!aSurface->IsKind(STANDARD_TYPE(Geom_Plane))) + { + anError = Standard_True; + } + } + for (TopExp_Explorer anEdgeExplorer(aTopoShape, TopAbs_EDGE); anEdgeExplorer.More() && !anError; anEdgeExplorer.Next()) + { + Standard_Real fd, ld; + Handle(Geom_Curve) curve = BRep_Tool::Curve(TopoDS::Edge(anEdgeExplorer.Current()), fd, ld); + if (!curve->IsKind(STANDARD_TYPE(Geom_Line))) + { + anError = Standard_True; + } + } + } + } + return !anError; +} diff --git a/samples/OCCTOverview/code/DataExchangeSamples.h b/samples/OCCTOverview/code/DataExchangeSamples.h new file mode 100644 index 0000000000..548cdcae35 --- /dev/null +++ b/samples/OCCTOverview/code/DataExchangeSamples.h @@ -0,0 +1,90 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef DATAEXCHANGESAMPLES_H +#define DATAEXCHANGESAMPLES_H + +#include "BaseSample.h" + +#include +#include + +//! Implements Data Exchange samples +class DataExchangeSamples : public BaseSample +{ + DEFINE_STANDARD_RTTI_INLINE(DataExchangeSamples, BaseSample) +public: + + DataExchangeSamples (const TCollection_AsciiString& theSampleSourcePath, + const Handle(V3d_View)& theView, + const Handle(AIS_InteractiveContext)& theContext) + : BaseSample (theSampleSourcePath, theContext), + myStepType (STEPControl_StepModelType::STEPControl_AsIs), + myView (theView) + { + // + } + + virtual void Process (const TCollection_AsciiString& theSampleName) Standard_OVERRIDE; + + void AppendBottle(); + void SetFileName(TCollection_AsciiString theFileName) { myFileName = theFileName; }; + void SetStepType(STEPControl_StepModelType theStepType) { myStepType = theStepType; }; + + static Standard_Boolean IsExportSample(const TCollection_AsciiString& theSampleName) { return theSampleName == "BrepExportSample" + || theSampleName == "StepExportSample" + || theSampleName == "IgesExportSample" + || theSampleName == "StlExportSample" + || theSampleName == "VrmlExportSample" + || theSampleName == "ImageExportSample"; } + static Standard_Boolean IsImportSample(const TCollection_AsciiString& theSampleName) { return theSampleName == "BrepImportSample" + || theSampleName == "StepImportSample" + || theSampleName == "IgesImportSample"; } + static Standard_Boolean IsBrepSample (const TCollection_AsciiString& theSampleName) { return theSampleName == "BrepExportSample" || theSampleName == "BrepImportSample"; } + static Standard_Boolean IsStepSample (const TCollection_AsciiString& theSampleName) { return theSampleName == "StepExportSample" || theSampleName == "StepImportSample"; } + static Standard_Boolean IsIgesSample (const TCollection_AsciiString& theSampleName) { return theSampleName == "IgesExportSample" || theSampleName == "IgesImportSample"; } + static Standard_Boolean IsStlSample (const TCollection_AsciiString& theSampleName) { return theSampleName == "StlExportSample"; } + static Standard_Boolean IsVrmlSample (const TCollection_AsciiString& theSampleName) { return theSampleName == "VrmlExportSample"; } + static Standard_Boolean IsImageSample (const TCollection_AsciiString& theSampleName) { return theSampleName == "ImageExportSample"; } + +protected: + virtual void ExecuteSample (const TCollection_AsciiString& theSampleName) Standard_OVERRIDE; + +private: + TCollection_AsciiString myFileName; + STEPControl_StepModelType myStepType; + Handle(V3d_View) myView; + +private: + Standard_Boolean CheckFacetedBrep(); + // One function for every sample + void BrepExportSample(); + void StepExportSample(); + void IgesExportSample(); + void StlExportSample(); + void VrmlExportSample(); + void ImageExportSample(); + void BrepImportSample(); + void StepImportSample(); + void IgesImportSample(); +}; + +#endif //DATAEXCHANGESAMPLES_H diff --git a/samples/OCCTOverview/code/FILES b/samples/OCCTOverview/code/FILES new file mode 100644 index 0000000000..f0f05d2184 --- /dev/null +++ b/samples/OCCTOverview/code/FILES @@ -0,0 +1,48 @@ +AdaptorCurve2d_AIS.cxx +AdaptorCurve2d_AIS.h +AdaptorCurve_AIS.cxx +AdaptorCurve_AIS.h +AdaptorPnt2d_AIS.cxx +AdaptorPnt2d_AIS.h +AdaptorVec_AIS.cxx +AdaptorVec_AIS.h +BaseSample.cxx +BaseSample.h +DataExchange.json +DataExchangeSamples.cxx +DataExchangeSamples.h +Geometry.json +GeometrySamples.cxx +GeometrySamples.h +MakeBottle.cxx +MakeBottle.h +Ocaf.json +OcafSamples.cxx +OcafSamples.h +Sample2D_Face.cxx +Sample2D_Face.h +Sample2D_Image.cxx +Sample2D_Image.h +Sample2D_Markers.cxx +Sample2D_Markers.h +Samples.qrc +TOcafFunction_BoxDriver.cxx +TOcafFunction_BoxDriver.h +TOcafFunction_CutDriver.cxx +TOcafFunction_CutDriver.h +TOcafFunction_CylDriver.cxx +TOcafFunction_CylDriver.h +TOcaf_Application.cxx +TOcaf_Application.h +Topology.json +TopologySamples.cxx +TopologySamples.h +Triangulation.json +TriangulationSamples.cxx +TriangulationSamples.h +Viewer2d.json +Viewer2dSamples.cxx +Viewer2dSamples.h +Viewer3d.json +Viewer3dSamples.cxx +Viewer3dSamples.h diff --git a/samples/OCCTOverview/code/Geometry.json b/samples/OCCTOverview/code/Geometry.json new file mode 100644 index 0000000000..1e2d6821de --- /dev/null +++ b/samples/OCCTOverview/code/Geometry.json @@ -0,0 +1,287 @@ +{ + "Non Parametric": { + "Free creating": { + "3D": [{ + "text": "Zero Dimension objects", + "function": "ZeroDimensionObjects3dSample", + "description": "" + }, + { + "text": "Vectors", + "function": "Vectors3dSample", + "description": "" + }, + { + "text": "Infinity lines", + "function": "InfinityLines3dSample", + "description": "" + }, + { + "text": "Second order curves", + "function": "SecondOrderCurves3dSample", + "description": "" + }, + { + "text": "Plane surfaces", + "function": "PlaneSurfaces3dSample", + "description": "" + }, + { + "text": "Second order surfaces", + "function": "SecondOrderSurfaces3dSample", + "description": "" + } + ], + "2D": [{ + "text": "Zero Dimension objects", + "function": "ZeroDimensionObjects2dSample", + "description": "" + }, + { + "text": "Vectors", + "function": "Vectors2dSample", + "description": "" + }, + { + "text": "Infinity lines", + "function": "InfinityLines2dSample", + "description": "" + }, + { + "text": "Second order curves", + "function": "SecondOrderCurves2dSample", + "description": "" + } + ] + } + + , + "Creating based on criteria": { + "3D": [{ + "text": "Barycenter point", + "function": "BarycenterPoint3dSample", + "description": "" + }, + { + "text": "Rotated vector", + "function": "RotatedVector3dSample", + "description": "" + }, + { + "text": "Mirrored line", + "function": "MirroredLine3dSample", + "description": "" + }, + { + "text": "Scaled Ellipse", + "function": "ScaledEllipse3dSample", + "description": "" + }, + { + "text": "Transformed cylinder", + "function": "TransformedCylinder3dSample", + "description": "" + }, + { + "text": "Translated torus", + "function": "TranslatedTorus3dSample", + "description": "" + }, + { + "text": "Conjugate objects ", + "function": "ConjugateObjects3dSample", + "description": "" + }, + { + "text": "Projection of point", + "function": "ProjectionOfPoint3dSample", + "description": "" + }, + { + "text": "Minimal distance", + "function": "MinimalDistance3dSample", + "description": "" + }, + { + "text": "Intersection", + "function": "Intersection3dSample", + "description": "" + } + ], + "2D": [{ + "text": "Translated point", + "function": "TranslatedPoint2dSample", + "description": "" + }, + { + "text": "Rotated direction", + "function": "RotatedDirection2dSample", + "description": "" + }, + { + "text": "Mirrored axis", + "function": "MirroredAxis2dSample", + "description": "" + }, + { + "text": "Transformed ellipse", + "function": "TransformedEllipse2dSample", + "description": "" + }, + { + "text": "Conjugate objects", + "function": "ConjugateObjects2dSample", + "description": "" + }, + { + "text": "Tangent to 2 cilcles", + "function": "Tangent2dSample", + "description": "" + }, + { + "text": "Projection of point", + "function": "ProjectionOfPoint2dSample", + "description": "" + }, + { + "text": "Minimal distance", + "function": "MinimalDistance2dSample", + "description": "" + }, + { + "text": "Intersection", + "function": "Intersection2dSample", + "description": "" + } + ] + }, + "Data extraction": { + "3D": [{ + "text": "Point info", + "function": "PointInfo3dSample", + "description": "" + }, + { + "text": "Ellipse info", + "function": "EllipseInfo3dSample", + "description": "" + } + ], + "2D": [{ + "text": "Point info", + "function": "PointInfo2dSample", + "description": "" + }, + { + "text": "Circle info", + "function": "CircleInfo2dSample", + "description": "" + } + ] + } + + }, + "Parametric": { + "Free creating": { + "3D": [{ + "text": "Free style curves", + "function": "FreeStyleCurves3dSample", + "description": "" + }, + { + "text": "Analytical surfaces", + "function": "AnalyticalSurfaces3dSample", + "description": "" + }, + { + "text": "Free style surfaces", + "function": "FreeStyleSurfaces3dSample", + "description": "" + } + ], + "2D": [{ + "text": "Free style curves", + "function": "FreeStyleCurves2dSample", + "description": "" + } + ] + }, + "Creating based on geometry": { + "3D": [{ + "text": "Trimmed curve", + "function": "TrimmedCurve3dSample", + "description": "" + }, + { + "text": "Offset curve", + "function": "OffsetCurve3dSample", + "description": "" + }, + { + "text": "BSpline from circle", + "function": "BSplineFromCircle3dSample", + "description": "" + }, + { + "text": "Trimmed surface", + "function": "TrimmedSurface3dSample", + "description": "" + }, + { + "text": "Offset surface", + "function": "OffsetSurface3dSample", + "description": "" + }, + { + "text": "Extrusion surface", + "function": "ExtrusionSurface3dSample", + "description": "" + }, + { + "text": "Revolution surface", + "function": "RevolutionSurface3dSample", + "description": "" + } + ], + "2D": [{ + "text": "Trimmed curve", + "function": "TrimmedCurve2dSample", + "description": "" + }, + { + "text": "Offset curve", + "function": "OffsetCurve2dSample", + "description": "" + } + ] + }, + "Extract geometry": [{ + "text": "Bounding box of surface (3D)", + "function": "BoundingBoxOfSurface3dSample", + "description": "" + }, + { + "text": "Bounding box of curves (3D)", + "function": "BoundingBoxOfCurves3dSample", + "description": "" + }, + { + "text": "Bounding box of curves (2D)", + "function": "BoundingBoxOfCurves2dSample", + "description": "" + } + ], + "Data extraction": [{ + "text": "Dump circle info", + "function": "DumpCircleInfoSample", + "description": "" + }, + { + "text": "Dump BSpline curve info", + "function": "DumpBSplineCurveInfoSample", + "description": "" + } + ] + + } +} \ No newline at end of file diff --git a/samples/OCCTOverview/code/GeometrySamples.cxx b/samples/OCCTOverview/code/GeometrySamples.cxx new file mode 100644 index 0000000000..278e5e1089 --- /dev/null +++ b/samples/OCCTOverview/code/GeometrySamples.cxx @@ -0,0 +1,2027 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "GeometrySamples.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "AdaptorPnt2d_AIS.h" +#include "AdaptorVec_AIS.h" +#include "AdaptorCurve_AIS.h" +#include "AdaptorCurve2d_AIS.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +void GeometrySamples::ExecuteSample (const TCollection_AsciiString& theSampleName) +{ + Standard_Boolean anIsSamplePresent = Standard_True; + FindSourceCode(theSampleName); + if (theSampleName == "ZeroDimensionObjects3dSample") + ZeroDimensionObjects3dSample(); + else if (theSampleName == "Vectors3dSample") + Vectors3dSample(); + else if (theSampleName == "InfinityLines3dSample") + InfinityLines3dSample(); + else if (theSampleName == "SecondOrderCurves3dSample") + SecondOrderCurves3dSample(); + else if (theSampleName == "PlaneSurfaces3dSample") + PlaneSurfaces3dSample(); + else if (theSampleName == "SecondOrderSurfaces3dSample") + SecondOrderSurfaces3dSample(); + else if (theSampleName == "ZeroDimensionObjects2dSample") + ZeroDimensionObjects2dSample(); + else if (theSampleName == "Vectors2dSample") + Vectors2dSample(); + else if (theSampleName == "InfinityLines2dSample") + InfinityLines2dSample(); + else if (theSampleName == "SecondOrderCurves2dSample") + SecondOrderCurves2dSample(); + else if (theSampleName == "BarycenterPoint3dSample") + BarycenterPoint3dSample(); + else if (theSampleName == "RotatedVector3dSample") + RotatedVector3dSample(); + else if (theSampleName == "MirroredLine3dSample") + MirroredLine3dSample(); + else if (theSampleName == "ScaledEllipse3dSample") + ScaledEllipse3dSample(); + else if (theSampleName == "TransformedCylinder3dSample") + TransformedCylinder3dSample(); + else if (theSampleName == "TranslatedTorus3dSample") + TranslatedTorus3dSample(); + else if (theSampleName == "ConjugateObjects3dSample") + ConjugateObjects3dSample(); + else if (theSampleName == "ProjectionOfPoint3dSample") + ProjectionOfPoint3dSample(); + else if (theSampleName == "MinimalDistance3dSample") + MinimalDistance3dSample(); + else if (theSampleName == "MirroredAxis2dSample") + MirroredAxis2dSample(); + else if (theSampleName == "TransformedEllipse2dSample") + TransformedEllipse2dSample(); + else if (theSampleName == "ConjugateObjects2dSample") + ConjugateObjects2dSample(); + else if (theSampleName == "Intersection3dSample") + Intersection3dSample(); + else if (theSampleName == "TranslatedPoint2dSample") + TranslatedPoint2dSample(); + else if (theSampleName == "RotatedDirection2dSample") + RotatedDirection2dSample(); + else if (theSampleName == "Tangent2dSample") + Tangent2dSample(); + else if (theSampleName == "ProjectionOfPoint2dSample") + ProjectionOfPoint2dSample(); + else if (theSampleName == "MinimalDistance2dSample") + MinimalDistance2dSample(); + else if (theSampleName == "Intersection2dSample") + Intersection2dSample(); + else if (theSampleName == "PointInfo3dSample") + PointInfo3dSample(); + else if (theSampleName == "EllipseInfo3dSample") + EllipseInfo3dSample(); + else if (theSampleName == "PointInfo2dSample") + PointInfo2dSample(); + else if (theSampleName == "CircleInfo2dSample") + CircleInfo2dSample(); + else if (theSampleName == "SecondOrderCurves3dSample") + SecondOrderCurves3dSample(); + else if (theSampleName == "FreeStyleCurves3dSample") + FreeStyleCurves3dSample(); + else if (theSampleName == "AnalyticalSurfaces3dSample") + AnalyticalSurfaces3dSample(); + else if (theSampleName == "FreeStyleSurfaces3dSample") + FreeStyleSurfaces3dSample(); + else if (theSampleName == "SecondOrderCurves2dSample") + SecondOrderCurves2dSample(); + else if (theSampleName == "FreeStyleCurves2dSample") + FreeStyleCurves2dSample(); + else if (theSampleName == "TrimmedCurve3dSample") + TrimmedCurve3dSample(); + else if (theSampleName == "OffsetCurve3dSample") + OffsetCurve3dSample(); + else if (theSampleName == "BSplineFromCircle3dSample") + BSplineFromCircle3dSample(); + else if (theSampleName == "TrimmedSurface3dSample") + TrimmedSurface3dSample(); + else if (theSampleName == "OffsetSurface3dSample") + OffsetSurface3dSample(); + else if (theSampleName == "ExtrusionSurface3dSample") + ExtrusionSurface3dSample(); + else if (theSampleName == "RevolutionSurface3dSample") + RevolutionSurface3dSample(); + else if (theSampleName == "TrimmedCurve2dSample") + TrimmedCurve2dSample(); + else if (theSampleName == "OffsetCurve2dSample") + OffsetCurve2dSample(); + else if (theSampleName == "BoundingBoxOfSurface3dSample") + BoundingBoxOfSurface3dSample(); + else if (theSampleName == "BoundingBoxOfCurves3dSample") + BoundingBoxOfCurves3dSample(); + else if (theSampleName == "BoundingBoxOfCurves2dSample") + BoundingBoxOfCurves2dSample(); + else if (theSampleName == "DumpCircleInfoSample") + DumpCircleInfoSample(); + else if (theSampleName == "DumpBSplineCurveInfoSample") + DumpBSplineCurveInfoSample(); + else + { + myResult << "No function found: " << theSampleName; + myCode += TCollection_AsciiString("No function found: ") + theSampleName; + anIsSamplePresent = Standard_False; + } + myIsProcessed = anIsSamplePresent; +} + +void GeometrySamples::DisplayPnt (const gp_Pnt2d& thePnt2d, const TCollection_AsciiString& theText, + Aspect_TypeOfMarker theMarker, Standard_Real theDistance) +{ + gp_Pnt aPnt(thePnt2d.X(), thePnt2d.Y(), 0.0); + Handle(Geom_CartesianPoint) aGeomPoint = new Geom_CartesianPoint(aPnt); + Handle(AIS_Point) anAisPoint = new AIS_Point(aGeomPoint); + anAisPoint->SetMarker(theMarker); + myObject2d.Append(anAisPoint); + Handle(AIS_TextLabel) aPntLabel = new AIS_TextLabel(); + aPntLabel->SetText(theText); + aPntLabel->SetPosition(gp_Pnt(aPnt.X(), aPnt.Y() + theDistance, aPnt.Z())); + myObject2d.Append(aPntLabel); +} +void GeometrySamples::DisplayPnt (const gp_Pnt& thePnt, const TCollection_AsciiString& theText, + Aspect_TypeOfMarker theMarker, Standard_Real theDistance) +{ + Handle(Geom_CartesianPoint) aPoint = new Geom_CartesianPoint(thePnt); + Handle(AIS_Point) anAisPoint = new AIS_Point(aPoint); + anAisPoint->SetMarker(theMarker); + myObject3d.Append(anAisPoint); + Handle(AIS_TextLabel) aPntLabel = new AIS_TextLabel(); + aPntLabel->SetText(theText); + aPntLabel->SetPosition(gp_Pnt(thePnt.X(), thePnt.Y(), thePnt.Z() + theDistance)); + myObject3d.Append(aPntLabel); +} + +void GeometrySamples::ZeroDimensionObjects3dSample() +{ + // gp_Pnt describes a point in 3D space. A Geom_CartesianPoint is defined by + // a gp_Pnt point, with its three Cartesian coordinates X, Y and Z. + gp_Pnt aCoordPnt(10.0, 20.0, 30.0); + Handle(Geom_CartesianPoint) aCoordGeomPoint = new Geom_CartesianPoint(aCoordPnt); + Handle(AIS_Point) aCoordAisPoint = new AIS_Point(aCoordGeomPoint); + myObject3d.Append(aCoordAisPoint); + + Handle(AIS_TextLabel) aPntLabel = new AIS_TextLabel(); + aPntLabel->SetText(" gp_Pnt"); + aPntLabel->SetPosition(gp_Pnt(aCoordPnt.X(), aCoordPnt.Y(), aCoordPnt.Z() + 5.0)); + myObject3d.Append(aPntLabel); + myResult << "gp_Pnt was created" << std::endl; + + // gp_XYZ class describes a Cartesian coordinate entity in 3D space (X,Y,Z). + // This entity is used for algebraic calculation. + // This entity can be transformed with a "Trsf" or a "GTrsf" from package "gp". + // It is used in vectorial computations or for holding this type of information + // in data structures. + gp_XYZ aXyz1(10.0, 20.0, 30.0); + gp_XYZ aXyz2(20.0, 10.0, 30.0); + gp_XYZ aXyzSum = aXyz1 + aXyz2; + gp_Pnt aSumPnt(aXyzSum); + Handle(Geom_CartesianPoint) aXyzGeomPoint = new Geom_CartesianPoint(aSumPnt); + Handle(AIS_Point) aSumAisPoint = new AIS_Point(aXyzGeomPoint); + myObject3d.Append(aSumAisPoint); + + Handle(AIS_TextLabel) aXyzLabel = new AIS_TextLabel(); + aXyzLabel->SetText(" gp_XYZ"); + aXyzLabel->SetPosition(gp_Pnt(aXyzSum.X(), aXyzSum.Y(), aXyzSum.Z() + 5.0)); + myObject3d.Append(aXyzLabel); + myResult << "gp_XYZ was created" << std::endl; +} + +void GeometrySamples::Vectors3dSample() +{ + gp_Pnt aPnt1(0.0, 0.0, 0.0); + gp_Pnt aPnt2(5.0, 0.0, 0.0); + + // gp_Vec defines a non-persistent vector in 3D space. + gp_Vec aVec(aPnt1, aPnt2); + Handle(AdaptorVec_AIS) aVecAIS = new AdaptorVec_AIS(aPnt1, aVec, 0.5); + aVecAIS->SetText(" gp_Vec"); + myObject3d.Append(aVecAIS); + myResult << "gp_Vec magnitude: " << aVec.Magnitude() << std::endl; + + // Describes a unit vector in 3D space. + // This unit vector is also called "Direction". + // See Also gce_MakeDir which provides functions for more complex unit vector + // constructions Geom_Direction which provides additional functions + // for constructing unit vectors and works, in particular, + // with the parametric equations of unit vectors. + gp_Dir aDir(aVec); + Handle(AdaptorVec_AIS) aDirAIS = new AdaptorVec_AIS(gp_Pnt(0.0, 0.0, 10.0), aDir, 1.0, 0.5); + aDirAIS->SetText(" gp_Dir"); + myObject3d.Append(aDirAIS); + myResult << "gp_Dir coordinates: X: " << aDir.X() << ", Y: " << aDir.Y() << ", Z: " << aDir.Z() << std::endl; +} + +void GeometrySamples::InfinityLines3dSample() +{ + gp_Pnt aBasePoint(0.0, 0.0, 0.0); + gp_Dir aX_Direction(1.0, 0.0, 0.0); + gp_Dir anY_Direction(0.0, 1.0, 0.0); + gp_Dir aZ_Direction(0.0, 0.0, 1.0); + + // Describes an axis in 3D space. + gp_Ax1 anAxis1(aBasePoint, aZ_Direction); + Handle(AdaptorVec_AIS) anAx1Ais = new AdaptorVec_AIS(anAxis1.Location(), anAxis1.Direction(), 1.0, 0.3); + anAx1Ais->SetText(" gp_Ax1"); + myObject3d.Append(anAx1Ais); + myResult << "gp_Ax1 was created" << std::endl << std::endl; + + // Describes a right - handed coordinate system in 3D space. + aBasePoint.SetCoord(0.0, 0.0, 3.0); + gp_Ax2 anAxis2(aBasePoint, aZ_Direction); + Handle(AdaptorVec_AIS) aAx2AisZ = new AdaptorVec_AIS(anAxis2.Location(), anAxis2.Direction(), 1.0, 0.3); + aAx2AisZ->SetText(" gp_Ax2 Z"); + myObject3d.Append(aAx2AisZ); + Handle(AdaptorVec_AIS) aAx2AisX = new AdaptorVec_AIS(anAxis2.Location(), anAxis2.XDirection(), 1.0, 0.3); + aAx2AisX->SetText(" gp_Ax2 X"); + myObject3d.Append(aAx2AisX); + Handle(AdaptorVec_AIS) aAx2AisY = new AdaptorVec_AIS(anAxis2.Location(), anAxis2.YDirection(), 1.0, 0.3); + aAx2AisY->SetText(" gp_Ax2 Y"); + myObject3d.Append(aAx2AisY); + myResult << "gp_Ax2 was created" << std::endl; + + // Describes a coordinate system in 3D space.Unlike a gp_Ax2 coordinate system, + // a gp_Ax3 can be right - handed("direct sense") or left - handed("indirect sense"). + gp_Ax3 anAxis3(gp_XYZ(0.0, 0.0, 6.0), aZ_Direction, aX_Direction); + anAxis3.YReverse(); + Handle(AdaptorVec_AIS) anAx3AisZ = new AdaptorVec_AIS(anAxis3.Location(), anAxis3.Direction(), 1.0, 0.3); + anAx3AisZ->SetText(" gp_Ax3 Z"); + myObject3d.Append(anAx3AisZ); + Handle(AdaptorVec_AIS) anAx3AisX = new AdaptorVec_AIS(anAxis3.Location(), anAxis3.XDirection(), 1.0, 0.3); + anAx3AisX->SetText(" gp_Ax3 X"); + myObject3d.Append(anAx3AisX); + Handle(AdaptorVec_AIS) anAx3AisY = new AdaptorVec_AIS(anAxis3.Location(), anAxis3.YDirection(), 1.0, 0.3); + anAx3AisY->SetText(" gp_Ax3 Y"); + myObject3d.Append(anAx3AisY); + + myResult << "gp_Ax3 was created" << std::endl; + const gp_Dir& anAxis3_xDir = anAxis3.XDirection(); + const gp_Dir& anAxis3_yDir = anAxis3.YDirection(); + myResult << "gp_Ax3 X direction: " << anAxis3_xDir.X() << " " << anAxis3_xDir.Y() << " " << anAxis3_xDir.Z() << std::endl; + myResult << "gp_Ax3 Y direction: " << anAxis3_yDir.X() << " " << anAxis3_yDir.Y() << " " << anAxis3_yDir.Z() << std::endl; + TCollection_AsciiString aDirectionDescription; + if (anAxis3.Direct()) + { + aDirectionDescription = "anAxis3 is a right-handed axis system"; + } + else + { + aDirectionDescription = "anAxis3 is a left-handed axis system"; + } + myResult << aDirectionDescription << std::endl << std::endl; + + // Describes a line in 3D space. A line is positioned in space with an axis + // (a gp_Ax1 object) which gives it an origin and a unit vector. + gp_Lin aLine(gp_Pnt(5.0, 0.0, 0.0), gp_Dir(0.0, 1.0, 0.0)); + Handle(AdaptorVec_AIS) anLineAis = new AdaptorVec_AIS(aLine.Location(), aLine.Direction(), 8.0); + anLineAis->SetText(" gp_Lin"); + myObject3d.Append(anLineAis); + myResult << "gp_Lin was created" << std::endl << std::endl; +} + +void GeometrySamples::SecondOrderCurves3dSample() +{ + gp_Ax2 anAxis2(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)); + gp_Circ aCirc(anAxis2, 10.0); + Handle(Geom_Circle) aGeomCircle = new Geom_Circle(aCirc); + Handle(AIS_Circle) anAisCircle = new AIS_Circle(aGeomCircle); + myObject3d.Append(anAisCircle); + + // Describes an ellipse in 3D space. An ellipse is defined by its major and minor + // radii and positioned in space with a coordinate system (a gp_Ax2 object) + gp_Elips anElips(anAxis2.Translated(gp_Vec(0.0, 0.0, 10.0)), 20.0, 10.0); + Handle(Geom_Ellipse) aGeomEllipse = new Geom_Ellipse(anElips); + Handle(AdaptorCurve_AIS) anAisEllipce = new AdaptorCurve_AIS(aGeomEllipse); + myObject3d.Append(anAisEllipce); + + // Describes a parabola in 3D space. A parabola is defined by its focal length + // (that is, the distance between its focus and apex) and positioned in space with + // a coordinate system (a gp_Ax2 object) + gp_Parab aParab(anAxis2.Translated(gp_Vec(0.0, 0.0, 20.0)), 2.0); + Handle(Geom_Parabola) aGeomParabola = new Geom_Parabola(aParab); + Handle(Geom_TrimmedCurve) aTrimmedParabola = new Geom_TrimmedCurve(aGeomParabola, 20.0, -20.0); + Handle(AdaptorCurve_AIS) anAisParabola = new AdaptorCurve_AIS(aTrimmedParabola); + myObject3d.Append(anAisParabola); + + // Describes a branch of a hyperbola in 3D space. A hyperbola is defined by its major + // and minor radii and positioned in space with a coordinate system (a gp_Ax2 object) + gp_Hypr aHypr(anAxis2.Translated(gp_Vec(0.0, 0.0, 30.0)), 20.0, 10.0); + Handle(Geom_Hyperbola) aGeomHyperbola = new Geom_Hyperbola(aHypr); + Handle(Geom_TrimmedCurve) aTrimmedHyperbola = new Geom_TrimmedCurve(aGeomHyperbola, 2.0, -2.0); + Handle(AdaptorCurve_AIS) anAisHyperbola = new AdaptorCurve_AIS(aTrimmedHyperbola); + myObject3d.Append(anAisHyperbola); +} + +void GeometrySamples::PlaneSurfaces3dSample() +{ + // Describes a plane.A plane is positioned in space with a coordinate system(a gp_Ax3 object), + // such that the plane is defined by the origin, "X Direction" and "Y Direction" of this + // coordinate system, which is the "local coordinate system" of the plane.The "main Direction" + // of the coordinate system is a vector normal to the plane. + gp_Pln aPln(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)); + Handle(Geom_Plane) aPlane = new Geom_Plane(aPln); + Handle(AIS_Plane) anAisPlane = new AIS_Plane(aPlane, aPln.Location(), + gp_Pnt(10.0, 10.0, 0.0), + gp_Pnt(-10.0, -10.0, 0.0), + Standard_False); + myObject3d.Append(anAisPlane); + + // Describes an infinite cylindrical surface.A cylinder is defined by its radius and positioned + // in space with a coordinate system(a gp_Ax3 object), the "main Axis" of which is the axis of + // the cylinder.This coordinate system is the "local coordinate system" of the cylinder. + gp_Cylinder aCylinder(gp_Ax3(gp_Pnt(0.0, 0.0, 10.0), gp_Dir(0.0, 0.0, 1.0)), 10.0); + Handle(Geom_CylindricalSurface) aCylindricalSurface = new Geom_CylindricalSurface(aCylinder); + Handle(AIS_Shape) anAisCylinder = new AIS_Shape(BRepBuilderAPI_MakeFace( + aCylindricalSurface, 0.0, 2.0*M_PI, 0.0, 10.0, Precision::Confusion()).Shape()); + myObject3d.Append(anAisCylinder); + + // Defines an infinite conical surface. A cone is defined by its half-angle (can be negative) at + // the apex and positioned in space with a coordinate system (a gp_Ax3 object) and a "reference radius" + gp_Cone aCone(gp_Ax3(gp_Pnt(0.0, 0.0, 30.0), gp_Dir(0.0, 0.0, 1.0)), 0.25*M_PI, 0.0); + Handle(Geom_ConicalSurface) aConicalSurface = new Geom_ConicalSurface(aCone); + Handle(AIS_Shape) anAisCone = new AIS_Shape(BRepBuilderAPI_MakeFace( + aConicalSurface, 0.0, 2.0*M_PI, 0.0, 20.0, Precision::Confusion()).Shape()); + myObject3d.Append(anAisCone); +} + +void GeometrySamples::SecondOrderSurfaces3dSample() +{ + gp_Sphere aSphere(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 10.0); + Handle(Geom_SphericalSurface) aSphericalSurface = new Geom_SphericalSurface(aSphere); + Handle(AIS_Shape) anAisSphere = new AIS_Shape(BRepBuilderAPI_MakeFace( + aSphericalSurface, 0.0, 2.0*M_PI, 0.0, 2.0*M_PI, Precision::Confusion()).Shape()); + myObject3d.Append(anAisSphere); + + gp_Torus aTorus(gp_Ax3(gp_Pnt(0.0, 0.0, 20.0), gp_Dir(0.0, 0.0, 1.0)), 40.0, 10.0); + Handle(Geom_ToroidalSurface) aToroidalSurface = new Geom_ToroidalSurface(aTorus); + Handle(AIS_Shape) anAisTorus = new AIS_Shape(BRepBuilderAPI_MakeFace( + aToroidalSurface, 0.0, 2.0*M_PI, 0.0, 2.0*M_PI, Precision::Confusion()).Shape()); + myObject3d.Append(anAisTorus); +} + +void GeometrySamples::ZeroDimensionObjects2dSample() +{ + // Defines a non-persistent 2D Cartesian point. + gp_Pnt2d aCoordPnt(10.0, 20.0); + Handle(Geom2d_CartesianPoint) aCoordGeomPoint = new Geom2d_CartesianPoint(aCoordPnt); + Handle(AdaptorPnt2d_AIS) aCoordAisPoint = new AdaptorPnt2d_AIS(aCoordGeomPoint); + myObject2d.Append(aCoordAisPoint); + + Handle(AIS_TextLabel) aPntLabel = new AIS_TextLabel(); + aPntLabel->SetText("gp_Pnt2d"); + aPntLabel->SetPosition(gp_Pnt(aCoordPnt.X(), aCoordPnt.Y() + 0.5, 0.0)); + myObject2d.Append(aPntLabel); + myResult << "gp_Pnt was created" << std::endl; + + // This class describes a Cartesian coordinate entity in 2D space{ X,Y }. + // This class is non persistent.This entity used for algebraic calculation. + // An XY can be transformed with a Trsf2d or a GTrsf2d from package gp. + // It is used in vectorial computations or for holding this type of information in data structures. + gp_XY aXy(20.0, 10.0); + Handle(Geom2d_CartesianPoint) aXyGeomPoint = new Geom2d_CartesianPoint(aXy); + Handle(AdaptorPnt2d_AIS) aXyAisPoint = new AdaptorPnt2d_AIS(aXyGeomPoint); + myObject2d.Append(aXyAisPoint); + + Handle(AIS_TextLabel) aXyLabel = new AIS_TextLabel(); + aXyLabel->SetText(" gp_XY"); + aXyLabel->SetPosition(gp_Pnt(aXy.X(), aXy.Y() + 0.5, 0.0)); + myObject2d.Append(aXyLabel); + myResult << "gp_XY was created" << std::endl; +} + +void GeometrySamples::Vectors2dSample() +{ + // Describes a unit vector in the plane (2D space). + // This unit vector is also called "Direction". + gp_Dir2d aDir(3.0, 4.0); + Handle(AdaptorVec_AIS) anAisDir = new AdaptorVec_AIS(gp_Pnt2d(0.0, 0.0), aDir, 1.0, 0.3); + anAisDir->SetText(" gp_Dir2d"); + myObject2d.Append(anAisDir); + myResult << "gp_Dir2d coordinates: X: " << aDir.X() << ", Y: " << aDir.Y() << std::endl; + + // Defines a non-persistent vector in 2D space. + gp_Vec2d aVec(aDir); + aVec = aVec * 2; + Handle(AdaptorVec_AIS) anAisVec = new AdaptorVec_AIS(gp_Pnt2d(0.0, 5.0), aVec, 0.3); + anAisVec->SetText(" gp_Vec2d"); + myObject2d.Append(anAisVec); + myResult << "gp_Vec2d magnitude: " << aVec.Magnitude() << std::endl; +} + +void GeometrySamples::InfinityLines2dSample() +{ + // Describes an axis in the plane (2D space) + gp_Ax2d anAx2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)); + Handle(AdaptorVec_AIS) anAisAx2d = new AdaptorVec_AIS(anAx2d.Location(), anAx2d.Direction(), 1.0, 0.3); + anAisAx2d->SetText(" gp_Ax2d"); + myObject2d.Append(anAisAx2d); + + // Describes a coordinate system in a plane (2D space). + gp_Ax22d anAx22d(gp_Pnt2d(0.0, 2.0), gp_Dir2d(1.0, 1.0), Standard_False); + Handle(AdaptorVec_AIS) anAisAx2d_X = new AdaptorVec_AIS(anAx22d.Location(), anAx22d.XDirection(), 1.0, 0.3); + anAisAx2d_X->SetText(" gp_Ax2d X"); + myObject2d.Append(anAisAx2d_X); + Handle(AdaptorVec_AIS) anAisAx2d_Y = new AdaptorVec_AIS(anAx22d.Location(), anAx22d.YDirection(), 1.0, 0.3); + anAisAx2d_Y->SetText(" gp_Ax2d Y"); + myObject2d.Append(anAisAx2d_Y); + + // Describes a line in 2D space. A line is positioned in the plane with an axis (a gp_Ax2d object) which gives + // the line its origin and unit vector. A line and an axis are similar objects, thus, + // we can convert one into the other. A line provides direct access to the majority of the edit and query + // functions available on its positioning axis. + gp_Lin2d aLin2d(gp_Pnt2d(2.0, 4.0), gp_Dir2d(0.0, -1.0)); + Handle(AdaptorVec_AIS) anAisLin = new AdaptorVec_AIS(aLin2d.Location(), aLin2d.Direction(), 1.0, 0.3); + anAisLin->SetText(" gp_Lin2d"); + myObject2d.Append(anAisLin); +} + +void GeometrySamples::SecondOrderCurves2dSample() +{ + // Describes a circle in the plane (2D space). A circle is defined by its radius + // and positioned in the plane with a coordinate system (a gp_Ax22d object) + gp_Circ2d aCirc2d; + aCirc2d.SetLocation(gp_Pnt2d(0.0, 0.0)); + aCirc2d.SetRadius(10.0); + Handle(Geom2d_Circle) aGeomCircle = new Geom2d_Circle(aCirc2d); + Handle(AdaptorCurve2d_AIS) anAisCirc = new AdaptorCurve2d_AIS(aGeomCircle, Aspect_TOL_SOLID); + myObject2d.Append(anAisCirc); + + // Describes an ellipse in the plane (2D space). An ellipse is defined by its major + // and minor radii and positioned in the plane with a coordinate system (a gp_Ax22d object) + gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 30.0), gp_Dir2d(1.0, 0.0)), 20.0, 10.0); + Handle(Geom2d_Ellipse) aGeomEllipse = new Geom2d_Ellipse(anElips); + Handle(AdaptorCurve2d_AIS) anAisEllipse = new AdaptorCurve2d_AIS(aGeomEllipse, Aspect_TOL_DASH); + myObject2d.Append(anAisEllipse); + + // Describes a parabola in the plane (2D space). A parabola is defined by its focal length + // (that is, the distance between its focus and apex) and positioned in the plane with + // a coordinate system (a gp_Ax22d object) + gp_Parab2d aParab2d(gp_Ax2d(gp_Pnt2d(20.0, 0.0), gp_Dir2d(1.0, 0.0)), 10.0); + Handle(Geom2d_Parabola) aGeomParabola = new Geom2d_Parabola(aParab2d); + Handle(Geom2d_TrimmedCurve) aTrimmedParabola = new Geom2d_TrimmedCurve(aGeomParabola, 40.0, -40.0); + Handle(AdaptorCurve2d_AIS) anAisParabola = new AdaptorCurve2d_AIS(aTrimmedParabola, Aspect_TOL_DOT); + myObject2d.Append(anAisParabola); + + // Describes a branch of a hyperbola in the plane (2D space). A hyperbola is defined by its major and + // minor radii, and positioned in the plane with a coordinate system (a gp_Ax22d object) + gp_Hypr2d aHypr2d(gp_Ax2d(gp_Pnt2d(20.0, 0.0), gp_Dir2d(1.0, 0.0)), 20.0, 10.0); + Handle(Geom2d_Hyperbola) aGeomHyperbola = new Geom2d_Hyperbola(aHypr2d); + Handle(Geom2d_TrimmedCurve) aTrimmedHyperbola = new Geom2d_TrimmedCurve(aGeomHyperbola, 2.0, -2.0); + Handle(AdaptorCurve2d_AIS) anAisHyperbola = new AdaptorCurve2d_AIS(aTrimmedHyperbola, Aspect_TOL_DOTDASH); + myObject2d.Append(anAisHyperbola); +} + +void GeometrySamples::BarycenterPoint3dSample() +{ + // Barycenter of 2 points + gp_Pnt aPnt1(11, 2, 3); + gp_Pnt aPnt2(13, 4, 5); + gp_Pnt aBarycenterPnt2 = aPnt1; + Standard_Real anAlpha = 3; + Standard_Real anBeta = 7; + // Assigns the result of the following expression to this point: + // (Alpha*this + Beta*P) / (Alpha + Beta) + aBarycenterPnt2.BaryCenter(anAlpha, aPnt2, anBeta); + DisplayPnt(aPnt1, "Pnt1", Aspect_TOM_PLUS, 0.5); + DisplayPnt(aPnt2, "Pnt2", Aspect_TOM_PLUS, 0.5); + DisplayPnt(aBarycenterPnt2, "Barycenter Pnt", Aspect_TOM_O_PLUS, 0.5); + + // BaryCenter of an array of point + gp_Pnt aP1(0, 0, 5); + gp_Pnt aP2(1, 2, 3); + gp_Pnt aP3(2, 3, -2); + gp_Pnt aP4(4, 3, 5); + gp_Pnt aP5(5, 5, 4); + TColgp_Array1OfPnt aPntArray(1, 5); + aPntArray.SetValue(1, aP1); + aPntArray.SetValue(2, aP2); + aPntArray.SetValue(3, aP3); + aPntArray.SetValue(4, aP4); + aPntArray.SetValue(5, aP5); + + Standard_Real Tolerance = 8; + GProp_PEquation aPEquation(aPntArray, Tolerance); + + gp_Pnt aBarycenterPnt5; // P declaration + bool isPoint = false; + if (aPEquation.IsPoint()) + { + isPoint = true; + aBarycenterPnt5 = aPEquation.Point(); + myResult << "GProp_PEquation is a point" << std::endl; + } + else + { + isPoint = false; + myResult << "GProp_PEquation is not a point" << std::endl; + } + + if (aPEquation.IsLinear()) + { + /*... */ + } + if (aPEquation.IsPlanar()) + { + /*... */ + } + if (aPEquation.IsSpace()) + { + /*... */ + } + + const TCollection_AsciiString aPointName("P"); + for (Standard_Integer i = aPntArray.Lower(); i <= aPntArray.Upper(); i++) + { + TCollection_AsciiString aString(i); + aString = aPointName + aString; + DisplayPnt(aPntArray(i), aString, Aspect_TOM_STAR, 0.5); + } + + DisplayPnt(aBarycenterPnt5, "Barycenter of 5 points", Aspect_TOM_O_STAR, 0.5); + myResult << " IsPoint = "; + if (isPoint) + { + myResult << "True --> " << " P ( " << aBarycenterPnt5.X() << aBarycenterPnt5.Y() << aBarycenterPnt5.Z() << " );" << std::endl; + } + else + { + myResult << "False"; + } + myResult << std::endl << " IsLinear = " << (aPEquation.IsLinear() ? "True" : "False"); + myResult << std::endl << " IsPlanar = " << (aPEquation.IsPlanar() ? "True" : "False"); + myResult << std::endl << " IsSpace = " << (aPEquation.IsSpace() ? "True" : "False"); +} + +void GeometrySamples::RotatedVector3dSample() +{ + gp_Vec aBaseVec(0.0, 0.0, 10.0); + gp_Pnt aZeroPnt(0.0, 0.0, 0.0); + gp_Vec aRotatedVec = aBaseVec.Rotated(gp_Ax1(aZeroPnt, gp_Dir(1.0, 0.0, 0.0)), M_PI_4); + + Handle(AdaptorVec_AIS) aBaseVecAIS = new AdaptorVec_AIS(aZeroPnt, aBaseVec); + aBaseVecAIS->SetText(" Base vector"); + myObject3d.Append(aBaseVecAIS); + Handle(AdaptorVec_AIS) aRotatedVecAIS = new AdaptorVec_AIS(aZeroPnt, aRotatedVec); + aRotatedVecAIS->SetText(" Rotated vector"); + myObject3d.Append(aRotatedVecAIS); + Standard_Real anAdgle = aBaseVec.Angle(aRotatedVec)*180.0 / M_PI; + myResult << "An angle between vectors = " << anAdgle << std::endl; +} + +void GeometrySamples::MirroredLine3dSample() +{ + gp_Lin aBaseLin(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 1.0, 1.0)); + gp_Ax2 aXyzAxis; + gp_Lin aMirroredLin = aBaseLin.Mirrored(aXyzAxis); + + Handle(AdaptorVec_AIS) aBaseLineAis = new AdaptorVec_AIS(aBaseLin.Location(), aBaseLin.Direction(), 8.0); + aBaseLineAis->SetText(" Base Line"); + myObject3d.Append(aBaseLineAis); + Handle(AdaptorVec_AIS) aMirroredLineAis = new AdaptorVec_AIS(aMirroredLin.Location(), aMirroredLin.Direction(), 8.0); + aMirroredLineAis->SetText(" Mirrored Line"); + myObject3d.Append(aMirroredLineAis); + Handle(AIS_Plane) anAisPlane = new AIS_Plane (new Geom_Plane(gp_Ax3(aXyzAxis)), aXyzAxis.Location(), + gp_Pnt(10.0, 10.0, 0.0), gp_Pnt(-10.0, -10.0, 0.0), Standard_False); + myObject3d.Append(anAisPlane); + Standard_Real anAdgle = aBaseLin.Angle(aMirroredLin)*180.0 / M_PI; + myResult << "An angle between lines = " << anAdgle << std::endl; +} + +void GeometrySamples::ScaledEllipse3dSample() +{ + gp_Ax2 anAxis2(gp_Pnt(), gp_Dir(0.0, 0.0, 1.0)); + gp_Elips anBaseElips(anAxis2, 20.0, 10.0); + gp_Elips anScaledElips = anBaseElips.Scaled(gp_Pnt(), 2.5); + + Handle(Geom_Ellipse) aBaseGeomEllipse = new Geom_Ellipse(anBaseElips); + Handle(AdaptorCurve_AIS) anAisBaseEllipce = new AdaptorCurve_AIS(aBaseGeomEllipse); + myObject3d.Append(anAisBaseEllipce); + + Handle(Geom_Ellipse) aScaledGeomEllipse = new Geom_Ellipse(anScaledElips); + Handle(AdaptorCurve_AIS) anAisScaledEllipce = new AdaptorCurve_AIS(aScaledGeomEllipse); + myObject3d.Append(anAisScaledEllipce); +} + +void GeometrySamples::TransformedCylinder3dSample() +{ + gp_Cylinder aBaseCylinder(gp_Ax3(), 10.0); + gp_Trsf aRotTrsf; + aRotTrsf.SetRotation(gp_Ax1(gp_Pnt(), gp_Dir(1.0, 0.0, 0.0)), M_PI_2); + gp_Trsf aScaleTrsf; + aScaleTrsf.SetScale(gp_Pnt(), 1.5); + gp_Trsf aTranslTrsf; + aTranslTrsf.SetTranslation(gp_Vec(30.0, 0.0, 0.0)); + gp_Trsf aComplexTrsf = aRotTrsf * aScaleTrsf * aTranslTrsf; + gp_Cylinder aTransfCylinder = aBaseCylinder.Transformed(aComplexTrsf); + + Handle(Geom_CylindricalSurface) aBaseCylinderSurface = new Geom_CylindricalSurface(aBaseCylinder); + Handle(AIS_Shape) anAisBaseCylinder = new AIS_Shape(BRepBuilderAPI_MakeFace( + aBaseCylinderSurface, 0.0, 2.0*M_PI, 0.0, 2.0*M_PI, Precision::Confusion()).Shape()); + myObject3d.Append(anAisBaseCylinder); + Handle(Geom_CylindricalSurface) aTransfCylinderSurface = new Geom_CylindricalSurface(aTransfCylinder); + Handle(AIS_Shape) anAisTransfCylinder = new AIS_Shape(BRepBuilderAPI_MakeFace( + aTransfCylinderSurface, 0.0, 2.0*M_PI, 0.0, 2.0*M_PI, Precision::Confusion()).Shape()); + myObject3d.Append(anAisTransfCylinder); +} + +void GeometrySamples::TranslatedTorus3dSample() +{ + gp_Torus aBaseTorus(gp_Ax3(gp_Pnt(), gp_Dir(0.0, 0.0, 1.0)), 40.0, 10.0); + gp_Torus aTranslatedTorus = aBaseTorus.Translated(gp_Vec(70.0, 70.0, 70.0)); + + Handle(Geom_ToroidalSurface) aBaseSurface = new Geom_ToroidalSurface(aBaseTorus); + Handle(AIS_Shape) anAisBaseShape = new AIS_Shape(BRepBuilderAPI_MakeFace( + aBaseSurface, 0.0, 2.0*M_PI, 0.0, 2.0*M_PI, Precision::Confusion()).Shape()); + myObject3d.Append(anAisBaseShape); + Handle(Geom_ToroidalSurface) aTranslSurface = new Geom_ToroidalSurface(aTranslatedTorus); + Handle(AIS_Shape) anAisTranslShape = new AIS_Shape(BRepBuilderAPI_MakeFace( + aTranslSurface, 0.0, 2.0*M_PI, 0.0, 2.0*M_PI, Precision::Confusion()).Shape()); + myObject3d.Append(anAisTranslShape); +} + +void GeometrySamples::ConjugateObjects3dSample() +{ + gp_Hypr aHypr(gp_Ax2(), 20.0, 10.0); + gp_Ax1 anAsymptote1 = aHypr.Asymptote1(); + gp_Ax1 anAsymptote2 = aHypr.Asymptote2(); + gp_Ax1 aDirectrix1 = aHypr.Directrix1(); + gp_Ax1 aDirectrix2 = aHypr.Directrix2(); + gp_Pnt aFocus1 = aHypr.Focus1(); + gp_Pnt aFocus2 = aHypr.Focus2(); + gp_Pnt aLocation = aHypr.Location(); + + Handle(AdaptorVec_AIS) anAsy1AIS = new AdaptorVec_AIS(anAsymptote1.Location(), gp_Vec(anAsymptote1.Direction())*10.0); + anAsy1AIS->SetText(" Asymptote 1"); + myObject3d.Append(anAsy1AIS); + Handle(AdaptorVec_AIS) anAsy2AIS = new AdaptorVec_AIS(anAsymptote2.Location(), gp_Vec(anAsymptote2.Direction())*10.0); + anAsy2AIS->SetText(" Asymptote 2"); + myObject3d.Append(anAsy2AIS); + Handle(AdaptorVec_AIS) anDir1AIS = new AdaptorVec_AIS(aDirectrix1.Location(), gp_Vec(aDirectrix1.Direction())*10.0); + anDir1AIS->SetText(" Directrix 1"); + myObject3d.Append(anDir1AIS); + Handle(AdaptorVec_AIS) anDir2AIS = new AdaptorVec_AIS(aDirectrix2.Location(), gp_Vec(aDirectrix2.Direction())*10.0); + anDir2AIS->SetText(" Directrix 2"); + myObject3d.Append(anDir2AIS); + + DisplayPnt(aFocus1, "Focus 1", Aspect_TOM_PLUS, 2.0); + DisplayPnt(aFocus2, "Focus 2", Aspect_TOM_PLUS, 2.0); + DisplayPnt(aLocation, "Location", Aspect_TOM_O_STAR, 2.0); + + Handle(Geom_Hyperbola) aGeomHyperbola = new Geom_Hyperbola(aHypr); + Handle(Geom_TrimmedCurve) aTrimmedHyperbola = new Geom_TrimmedCurve(aGeomHyperbola, 2.0, -2.0); + Handle(AdaptorCurve_AIS) anAisHyperbola = new AdaptorCurve_AIS(aTrimmedHyperbola); + myObject3d.Append(anAisHyperbola); +} + +void GeometrySamples::ProjectionOfPoint3dSample() +{ + gp_Sphere aSphere(gp_Ax3(), 10.0); + gp_Pnt aBasePnt(20.0, 20.0, 20.0); + // A projection point in surface coordinate + gp_Pnt2d aPrjPnt2d = ProjLib::Project(aSphere, aBasePnt); + gp_Pnt aPrjPnt = ElSLib::Value(aPrjPnt2d.X(), aPrjPnt2d.Y(), aSphere); + + DisplayPnt(aBasePnt, "Base point", Aspect_TOM_PLUS, 2.0); + DisplayPnt(aPrjPnt, "Projection point", Aspect_TOM_O_STAR, 2.0); + Handle(Geom_SphericalSurface) aSphericalSurface = new Geom_SphericalSurface(aSphere); + Handle(AIS_Shape) anAisSphere = new AIS_Shape(BRepBuilderAPI_MakeFace( + aSphericalSurface, 0.0, 2.0*M_PI, 0.0, 2.0*M_PI, Precision::Confusion()).Shape()); + myObject3d.Append(anAisSphere); +} + +void GeometrySamples::MinimalDistance3dSample() +{ + gp_Cylinder aCylinder(gp_Ax3(gp_Pnt(), gp_Dir(0.0, 0.0, 1.0)), 10.0); + gp_Lin aLine(gp_Pnt(20.0, 0.0, 5.0), gp_Dir(0.0, 1.0, 0.0)); + Extrema_ExtElCS anExtrema_ExtElCS(aLine, aCylinder); + + if (anExtrema_ExtElCS.IsDone()) + { + NCollection_Array1 aVecArray(1, anExtrema_ExtElCS.NbExt()); + NCollection_Array1 aPntArray(1, anExtrema_ExtElCS.NbExt()); + for (Standard_Integer i = 1; i <= anExtrema_ExtElCS.NbExt(); i++) + { + Extrema_POnCurv aCurvPoint; + Extrema_POnSurf aSurfPoint; + anExtrema_ExtElCS.Points(i, aCurvPoint, aSurfPoint); + gp_Pnt aCurvPnt = aCurvPoint.Value(); + gp_Pnt aSurfPnt = aSurfPoint.Value(); + + DisplayPnt(aCurvPnt, TCollection_AsciiString(i), Aspect_TOM_O_PLUS, 2.0); + DisplayPnt(aSurfPnt, TCollection_AsciiString(i), Aspect_TOM_O_STAR, 2.0); + gp_Vec aVec(aCurvPnt, aSurfPnt); + aVecArray.SetValue(i, aVec); + aPntArray.SetValue(i, aCurvPnt); + } + Standard_Integer aMinDistIndex(0); + Standard_Real aMinDistance = std::numeric_limits::max(); + for (Standard_Integer i = 1; i <= anExtrema_ExtElCS.NbExt(); i++) + { + if (aMinDistance > aVecArray(i).Magnitude()) + { + aMinDistIndex = i; + aMinDistance = aVecArray(i).Magnitude(); + } + } + Handle(AdaptorVec_AIS) anMinDistanceAis = + new AdaptorVec_AIS(aPntArray(aMinDistIndex), aVecArray(aMinDistIndex)); + anMinDistanceAis->SetText(" Min distance"); + myObject3d.Append(anMinDistanceAis); + } + Handle(Geom_CylindricalSurface) aCylindricalSurface = new Geom_CylindricalSurface(aCylinder); + Handle(AIS_Shape) anAisCylinder = new AIS_Shape(BRepBuilderAPI_MakeFace( + aCylindricalSurface, 0.0, 2.0*M_PI, 0.0, 10.0, Precision::Confusion()).Shape()); + myObject3d.Append(anAisCylinder); + Handle(AdaptorVec_AIS) anLineAis = new AdaptorVec_AIS(aLine.Location(), aLine.Direction(), 8.0); + anLineAis->SetText(" gp_Lin"); + myObject3d.Append(anLineAis); +} + +void GeometrySamples::Intersection3dSample() +{ + gp_Lin aLine(gp_Pnt(0.0, 0.0, 10.0), gp_Dir(0.0, 1.0, 0.0)); + gp_Cone aCone(gp_Ax3(gp_Pnt(), gp_Dir(0.0, 0.0, 1.0)), 0.25*M_PI, 0.0); + IntAna_Quadric anIntAna_Quadric(aCone); + IntAna_IntConicQuad anIntAna_IntConicQuad(aLine, anIntAna_Quadric); + if (anIntAna_IntConicQuad.IsDone()) + { + for (int i = 1; i <= anIntAna_IntConicQuad.NbPoints(); i++) + { + const gp_Pnt& aIntersectionPnt = anIntAna_IntConicQuad.Point(i); + DisplayPnt(aIntersectionPnt, TCollection_AsciiString(i)); + } + } + Handle(AdaptorVec_AIS) aLineVecAIS = new AdaptorVec_AIS(aLine.Location(), gp_Vec(aLine.Direction())*5.0); + aLineVecAIS->SetText(" Base vector"); + myObject3d.Append(aLineVecAIS); + Handle(Geom_ConicalSurface) aConicalSurface = new Geom_ConicalSurface(aCone); + Handle(AIS_Shape) anAisCone = new AIS_Shape(BRepBuilderAPI_MakeFace( + aConicalSurface, 0.0, 2.0*M_PI, 0.0, 20.0, Precision::Confusion()).Shape()); + myObject3d.Append(anAisCone); +} + +void GeometrySamples::TranslatedPoint2dSample() +{ + gp_Pnt2d aPnt1; + gp_Pnt2d aPnt2 = aPnt1.Translated(gp_Vec2d(10.0, 10.0)); + DisplayPnt(aPnt1, "1", Aspect_TOM_PLUS, 1.0); + DisplayPnt(aPnt2, "2", Aspect_TOM_PLUS, 1.0); + gp_Vec2d aTranslationVec(aPnt1, aPnt2); + Handle(AdaptorVec_AIS) aVecAIS = new AdaptorVec_AIS(aPnt1, aTranslationVec); + aVecAIS->SetText(" Translation"); + myObject2d.Append(aVecAIS); +} + +void GeometrySamples::RotatedDirection2dSample() +{ + gp_Dir2d aBaseDir(1.0, 1.0); + gp_Dir2d aRotatedDir = aBaseDir.Rotated(M_PI_4); + + myResult << "An angle between directions: " << aBaseDir.Angle(aRotatedDir)*180.0 / M_PI << " grad"; + Handle(AdaptorVec_AIS) aBaseAIS = new AdaptorVec_AIS(gp_Pnt2d(), aBaseDir, 5.0); + aBaseAIS->SetText(" Base"); + myObject2d.Append(aBaseAIS); + Handle(AdaptorVec_AIS) aRotatedAIS = new AdaptorVec_AIS(gp_Pnt2d(), aRotatedDir, 5.0); + aRotatedAIS->SetText(" Rotated"); + myObject2d.Append(aRotatedAIS); +} + +void GeometrySamples::MirroredAxis2dSample() +{ + gp_Ax22d aBaseAx(gp_Pnt2d(10.0, 0.0), gp_Dir2d(1.0, 0.0), Standard_True); + gp_Ax22d aMirrorAx = aBaseAx.Mirrored(gp_Pnt2d()); + + DisplayPnt(gp_Pnt2d(), "Mirror point", Aspect_TOM_PLUS, 1.0); + Handle(AdaptorVec_AIS) aBaseX_AIS = new AdaptorVec_AIS(aBaseAx.Location(), aBaseAx.XDirection(), 5.0); + aBaseX_AIS->SetText(" X (Base)"); + myObject2d.Append(aBaseX_AIS); + Handle(AdaptorVec_AIS) aBaseY_AIS = new AdaptorVec_AIS(aBaseAx.Location(), aBaseAx.YDirection(), 5.0); + aBaseY_AIS->SetText("Y (Base)"); + myObject2d.Append(aBaseY_AIS); + Handle(AdaptorVec_AIS) aMirrorX_AIS = new AdaptorVec_AIS(aMirrorAx.Location(), aMirrorAx.XDirection(), 5.0); + aMirrorX_AIS->SetText("X (Mirror)"); + myObject2d.Append(aMirrorX_AIS); + Handle(AdaptorVec_AIS) aMirrorY_AIS = new AdaptorVec_AIS(aMirrorAx.Location(), aMirrorAx.YDirection(), 5.0); + aMirrorY_AIS->SetText(" Y (Mirror)"); + myObject2d.Append(aMirrorY_AIS); +} + +void GeometrySamples::TransformedEllipse2dSample() +{ + // Creates an ellipse with the major axis, the major and the minor radius. + // The location of the MajorAxis is the center of the ellipse.The sense of + // parametrization is given by Sense.Warnings : It is possible to create + // an ellipse with MajorRadius = MinorRadius.Raises + // ConstructionError if MajorRadius < MinorRadius or MinorRadius < 0.0. + gp_Elips2d aBaseEllips(gp_Ax2d(gp_Pnt2d(), gp_Dir2d(1.0, 0.0)), 20.0, 10.0); + gp_Trsf2d aRotTrsf; + aRotTrsf.SetRotation(gp_Pnt2d(), M_PI_4); + gp_Trsf2d aScaleTrsf; + aScaleTrsf.SetScale(gp_Pnt2d(), 1.5); + gp_Trsf2d aTranslTrsf; + aTranslTrsf.SetTranslation(gp_Vec2d(30.0, 0.0)); + gp_Trsf2d aComplexTrsf = aRotTrsf * aScaleTrsf * aTranslTrsf; + gp_Elips2d aTransfEllips = aBaseEllips.Transformed(aComplexTrsf); + + Handle(Geom2d_Ellipse) aBaseEllipse = new Geom2d_Ellipse(aBaseEllips); + Handle(AdaptorCurve2d_AIS) anAisBaseEllipse = new AdaptorCurve2d_AIS(aBaseEllipse, Aspect_TOL_DASH); + myObject2d.Append(anAisBaseEllipse); + Handle(Geom2d_Ellipse) aTransfEllipse = new Geom2d_Ellipse(aTransfEllips); + Handle(AdaptorCurve2d_AIS) anAisTransfEllipse = new AdaptorCurve2d_AIS(aTransfEllipse, Aspect_TOL_DASH); + myObject2d.Append(anAisTransfEllipse); +} + +void GeometrySamples::ConjugateObjects2dSample() +{ + gp_Parab2d aParab(gp_Ax2d(), 20.0); + gp_Ax2d aDirectrix = aParab.Directrix(); + gp_Pnt2d aFocus = aParab.Focus(); + gp_Pnt2d aLocation = aParab.Location(); + gp_Ax2d aMirror = aParab.MirrorAxis(); + + Handle(AdaptorVec_AIS) aDirectAIS = new AdaptorVec_AIS(aDirectrix.Location(), gp_Vec2d(aDirectrix.Direction())*10.0); + aDirectAIS->SetText(" Directrix"); + myObject2d.Append(aDirectAIS); + Handle(AdaptorVec_AIS) aMirrorAIS = new AdaptorVec_AIS(aMirror.Location(), gp_Vec2d(aMirror.Direction())*10.0); + aMirrorAIS->SetText(" Mirror Axis"); + myObject2d.Append(aMirrorAIS); + + DisplayPnt(aFocus, "Focus", Aspect_TOM_PLUS, -3.0); + DisplayPnt(aLocation, " Location", Aspect_TOM_O_STAR, 3.0); + Handle(Geom2d_Parabola) aGeomParabola = new Geom2d_Parabola(aParab); + Handle(Geom2d_TrimmedCurve) aTrimmedParabola = new Geom2d_TrimmedCurve(aGeomParabola, 40.0, -40.0); + Handle(AdaptorCurve2d_AIS) anAisParabola = new AdaptorCurve2d_AIS(aTrimmedParabola, Aspect_TOL_DOT); + myObject2d.Append(anAisParabola); +} + +void GeometrySamples::Tangent2dSample() +{ + gp_Circ2d aCirc1(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Vec2d(1.0, 0.0)), 10.0); + gp_Circ2d aCirc2 = aCirc1.Translated(gp_Vec2d(50.0, 0.0)); + aCirc2.SetRadius(20.0); + + GccEnt_QualifiedCirc aQaCirc1(aCirc1, GccEnt_outside); + GccEnt_QualifiedCirc aQaCirc2(aCirc2, GccEnt_outside); + + GccAna_Lin2d2Tan aLin2d2Tan(aQaCirc1, aQaCirc2, 1E-6); + if (aLin2d2Tan.IsDone()) + { + for (int i = 1; i <= aLin2d2Tan.NbSolutions(); i++) + { + const gp_Lin2d& aTangentLin = aLin2d2Tan.ThisSolution(i); + Handle(AdaptorVec_AIS) anAisLin = new AdaptorVec_AIS(aTangentLin.Location(), aTangentLin.Direction(), 20.0); + myObject2d.Append(anAisLin); + } + } + + Handle(Geom2d_Circle) aCircle1 = new Geom2d_Circle(aCirc1); + Handle(AdaptorCurve2d_AIS) anAisCirc1 = new AdaptorCurve2d_AIS(aCircle1, Aspect_TOL_SOLID); + myObject2d.Append(anAisCirc1); + Handle(Geom2d_Circle) aCircle2 = new Geom2d_Circle(aCirc2); + Handle(AdaptorCurve2d_AIS) anAisCirc2 = new AdaptorCurve2d_AIS(aCircle2, Aspect_TOL_SOLID); + myObject2d.Append(anAisCirc2); +} + +void GeometrySamples::ProjectionOfPoint2dSample() +{ + gp_Pnt2d aPntToProject(40.0, 40.0); + gp_Circ2d aCirc(gp_Ax2d(), 20.0); + Handle(Geom2d_Circle) aGeom_Circle = new Geom2d_Circle(aCirc); + Geom2dAPI_ProjectPointOnCurve aProjector(aPntToProject, aGeom_Circle); + gp_Pnt2d aProjectionPnt = aProjector.NearestPoint(); + + Handle(AdaptorCurve2d_AIS) anAisCirc = new AdaptorCurve2d_AIS(aGeom_Circle, Aspect_TOL_SOLID); + myObject2d.Append(anAisCirc); + DisplayPnt(aPntToProject, "Pnt to project"); + DisplayPnt(aProjectionPnt, "Projection Pnt", Aspect_TOM_O_STAR); +} + +void GeometrySamples::MinimalDistance2dSample() +{ + gp_Lin2d aLin(gp_Pnt2d(-40.0, 0.0), gp_Dir2d(1.0, 1.0)); + Handle(Geom2d_Line) aGeom_Line = new Geom2d_Line(aLin); + gp_Circ2d aCirc(gp_Ax2d(), 20.0); + Handle(Geom2d_Circle) aGeom_Circle = new Geom2d_Circle(aCirc); + + Geom2dAPI_ExtremaCurveCurve anExtremaFinder(aGeom_Line, aGeom_Circle, + std::numeric_limits::min(), + std::numeric_limits::max(), 0.0, M_PI*2.0); + if (anExtremaFinder.NbExtrema()) + { + gp_Pnt2d aPnt1, aPnt2; + anExtremaFinder.NearestPoints(aPnt1, aPnt2); + myResult << "Extrema found: " << anExtremaFinder.NbExtrema() << std::endl; + myResult << "Minimal distance: " << anExtremaFinder.LowerDistance() << std::endl; + DisplayPnt(aPnt1, "1"); + DisplayPnt(aPnt2, "2"); + } + else + { + myResult << "No Extrema found" << std::endl; + } + + Handle(AdaptorCurve2d_AIS) anAisCirc = new AdaptorCurve2d_AIS(aGeom_Circle, Aspect_TOL_SOLID); + myObject2d.Append(anAisCirc); + Handle(AdaptorVec_AIS) anAisLin = new AdaptorVec_AIS(aLin.Location(), aLin.Direction(), 60.0); + anAisLin->SetText(" gp_Lin2d"); + myObject2d.Append(anAisLin); +} + +void GeometrySamples::Intersection2dSample() +{ + gp_Lin2d aLin(gp_Pnt2d(-20.0, 20.0), gp_Dir2d(1.0, -1.5)); + Handle(Geom2d_Line) aGeom_Line = new Geom2d_Line(aLin); + gp_Parab2d aParab(gp_Ax2d(), 20.0); + Handle(Geom2d_Parabola) aGeom_Parabola = new Geom2d_Parabola(aParab); + + Geom2dAPI_InterCurveCurve anIntersectFinder(aGeom_Line, aGeom_Parabola); + for (Standard_Integer i = 1; i <= anIntersectFinder.NbPoints(); i++) + { + gp_Pnt2d aPnt = anIntersectFinder.Point(i); + DisplayPnt(aPnt, i); + } + + myResult << "Number of intersections : " << anIntersectFinder.NbPoints() << std::endl; + + Handle(Geom2d_Parabola) aGeomParabola = new Geom2d_Parabola(aParab); + Handle(Geom2d_TrimmedCurve) aTrimmedParabola = new Geom2d_TrimmedCurve(aGeomParabola, 60.0, -60.0); + Handle(AdaptorCurve2d_AIS) anAisParabola = new AdaptorCurve2d_AIS(aTrimmedParabola, Aspect_TOL_DOT); + myObject2d.Append(anAisParabola); + Handle(AdaptorVec_AIS) anAisLin = new AdaptorVec_AIS(aLin.Location(), aLin.Direction(), 90.0); + anAisLin->SetText(" gp_Lin2d"); + myObject2d.Append(anAisLin); +} + +void GeometrySamples::PointInfo3dSample() +{ + gp_Pnt aPnt1; + gp_Pnt aPnt2(10.0, 10.0, 10.0); + gp_Pnt aPnt3(10.0, -10.0, 0.0); + gp_Pnt aPnt4(10.0, 10.0, 10.0); + Standard_Boolean anIsEqual2_3 = aPnt2.IsEqual(aPnt3, 1E-6); + Standard_Boolean anIsEqual2_4 = aPnt2.IsEqual(aPnt4, 1E-6); + Standard_Real aDistance1_2 = aPnt1.Distance(aPnt2); + Standard_Real aDistance2_4 = aPnt2.Distance(aPnt4); + Standard_Real aSquareDistance1_2 = aPnt1.SquareDistance(aPnt2); + Standard_Real aSquareDistance2_4 = aPnt2.SquareDistance(aPnt4); + + myResult << "A coordinate of a point 1: X: " << aPnt1.X() << " Y: " << aPnt1.Y() << " Z: " << aPnt1.Z() << std::endl; + myResult << "A coordinate of a point 2: X: " << aPnt2.X() << " Y: " << aPnt2.Y() << " Z: " << aPnt2.Z() << std::endl; + myResult << "A coordinate of a point 3: X: " << aPnt3.X() << " Y: " << aPnt3.Y() << " Z: " << aPnt3.Z() << std::endl; + myResult << "A coordinate of a point 4: X: " << aPnt4.X() << " Y: " << aPnt4.Y() << " Z: " << aPnt4.Z() << std::endl; + + if (anIsEqual2_3) + { + myResult << "A point 2 is equal to a point 3" << std::endl; + } + else + { + myResult << "A point 2 is different from a point 3" << std::endl; + } + if (anIsEqual2_4) + { + myResult << "A point 2 is equal to a point 4" << std::endl; + } + else + { + myResult << "A point 2 is different from a point 4" << std::endl; + } + myResult << "A distance from a point 1 to a point 2 is: " << aDistance1_2 << std::endl; + myResult << "A distance from a point 2 to a point 4 is: " << aDistance2_4 << std::endl; + + myResult << "A square distance from a point 1 to a point 2 is: " << aSquareDistance1_2 << std::endl; + myResult << "A square distance from a point 2 to a point 4 is: " << aSquareDistance2_4 << std::endl; + + DisplayPnt(aPnt1, "1", Aspect_TOM_PLUS, 0.5); + DisplayPnt(aPnt2, "2 & 4", Aspect_TOM_PLUS, 0.5); + DisplayPnt(aPnt3, "3", Aspect_TOM_PLUS, 0.5); + DisplayPnt(aPnt4, "", Aspect_TOM_PLUS, 0.5); +} + +void GeometrySamples::EllipseInfo3dSample() +{ + gp_Elips anElips(gp_Ax2(gp_Pnt(), gp_Dir(1.0, 0.0, 0.0)), 20.0, 10.0); + Standard_Real anArea = anElips.Area(); + // Returns the eccentricity of the ellipse between 0.0 and 1.0 + // If f is the distance between the center of the ellipse and the Focus1 then + // the eccentricity e = f / MajorRadius. Returns 0 if MajorRadius = 0. + Standard_Real anEccentricity = anElips.Eccentricity(); + // Returns the distance between the center of the ellipse and focus1 or focus2. + Standard_Real aFocal = anElips.Focal(); + // Returns p = (1 - e * e) * MajorRadius where e is the eccentricity + // of the ellipse. Returns 0 if MajorRadius = 0. + Standard_Real aParameter = anElips.Parameter(); + + myResult << "Ellipse area = " << anArea << " square units" << std::endl; + myResult << "Eccentricity = " << anEccentricity; + myResult << "Focal distance = " << aFocal; + myResult << "Ellipse parameter = " << aParameter; + + gp_Pnt aCenter = anElips.Location(); + gp_Pnt aFocus1 = anElips.Focus1(); + gp_Pnt aFocus2 = anElips.Focus2(); + DisplayPnt(aCenter, "Center", Aspect_TOM_PLUS, 2.0); + DisplayPnt(aFocus1, "focus 1", Aspect_TOM_PLUS, 2.0); + DisplayPnt(aFocus2, "focus 2", Aspect_TOM_PLUS, 2.0); + + Handle(Geom_Ellipse) aGeomEllipse = new Geom_Ellipse(anElips); + Handle(AdaptorCurve_AIS) anAisEllipce = new AdaptorCurve_AIS(aGeomEllipse); + myObject3d.Append(anAisEllipce); +} + +void GeometrySamples::PointInfo2dSample() +{ + gp_Pnt2d aPnt1; + gp_Pnt2d aPnt2(10.0, 10.0); + gp_Pnt2d aPnt3(10.0, -10.0); + gp_Pnt2d aPnt4(10.0, 10.0); + Standard_Boolean anIsEqual2_3 = aPnt2.IsEqual(aPnt3, 1E-6); + Standard_Boolean anIsEqual2_4 = aPnt2.IsEqual(aPnt4, 1E-6); + Standard_Real aDistance1_2 = aPnt1.Distance(aPnt2); + Standard_Real aDistance2_4 = aPnt2.Distance(aPnt4); + Standard_Real aSquareDistance1_2 = aPnt1.SquareDistance(aPnt2); + Standard_Real aSquareDistance2_4 = aPnt2.SquareDistance(aPnt4); + + myResult << "A coordinate of a point 1: X: " << aPnt1.X() << " Y: " << aPnt1.Y() << std::endl; + myResult << "A coordinate of a point 2: X: " << aPnt2.X() << " Y: " << aPnt2.Y() << std::endl; + myResult << "A coordinate of a point 3: X: " << aPnt3.X() << " Y: " << aPnt3.Y() << std::endl; + myResult << "A coordinate of a point 4: X: " << aPnt4.X() << " Y: " << aPnt4.Y() << std::endl; + if (anIsEqual2_3) + { + myResult << "A point 2 is equal to a point 3" << std::endl; + } + else + { + myResult << "A point 2 is different from a point 3" << std::endl; + } + if (anIsEqual2_4) + { + myResult << "A point 2 is equal to a point 4" << std::endl; + } + else + { + myResult << "A point 2 is different from a point 4" << std::endl; + } + + myResult << "A distance from a point 1 to a point 2 is: " << aDistance1_2 << std::endl; + myResult << "A distance from a point 2 to a point 4 is: " << aDistance2_4 << std::endl; + + myResult << "A square distance from a point 1 to a point 2 is: " << aSquareDistance1_2 << std::endl; + myResult << "A square distance from a point 2 to a point 4 is: " << aSquareDistance2_4 << std::endl; + + DisplayPnt(aPnt1, "1", Aspect_TOM_PLUS, 0.5); + DisplayPnt(aPnt2, "2 & 4", Aspect_TOM_PLUS, 0.5); + DisplayPnt(aPnt3, "3", Aspect_TOM_PLUS, 0.5); + DisplayPnt(aPnt4, ""); +} + +void GeometrySamples::CircleInfo2dSample() +{ + gp_Circ2d aCirc(gp_Ax22d(gp_Pnt2d(10.0, 10.0), gp_Vec2d(1.0, 0.0)), 10.0); + gp_Pnt2d aPnt1(0.0, 10.0); + gp_Pnt2d aPnt2(10.0, 0.0); + gp_Pnt2d aPnt3(20.0, 20.0); + + if (aCirc.Contains(aPnt1, 1E-6)) + { + DisplayPnt(aPnt1, "1", Aspect_TOM_STAR, 3.0); + myResult << "A circle contains a point 1" << std::endl; + } + else + { + DisplayPnt(aPnt1, "1", Aspect_TOM_PLUS, 1.0); + myResult << "A circle does contain a point 1" << std::endl; + } + if (aCirc.Contains(aPnt2, 1E-6)) + { + DisplayPnt(aPnt2, "2", Aspect_TOM_STAR, 1.0); + myResult << "A circle contains a point 2" << std::endl; + } + else + { + DisplayPnt(aPnt2, "2", Aspect_TOM_PLUS, 1.0); + myResult << "A circle does contain a point 2" << std::endl; + } + if (aCirc.Contains(aPnt3, 1E-6)) + { + DisplayPnt(aPnt3, "3", Aspect_TOM_STAR, 1.0); + myResult << "A circle contains a point 3" << std::endl; + } + else + { + DisplayPnt(aPnt3, "3", Aspect_TOM_PLUS, 1.0); + myResult << "A circle does contain a point 3" << std::endl; + } + myResult << "Circle area = " << aCirc.Area() << "square units" << std::endl; + Handle(Geom2d_Circle) aGeomCircle = new Geom2d_Circle(aCirc); + Handle(AdaptorCurve2d_AIS) anAisCirc = new AdaptorCurve2d_AIS(aGeomCircle); + myObject2d.Append(anAisCirc); +} + +void GeometrySamples::FreeStyleCurves3dSample() +{ + // Define points. + gp_Pnt aPnt1(0.0, 0.0, 0.0); + gp_Pnt aPnt2(5.0, 5.0, 0.0); + gp_Pnt aPnt3(10.0, 5.0, 0.0); + gp_Pnt aPnt4(15.0, 0.0, 0.0); + + // Add points to the curve poles array. + TColgp_Array1OfPnt aPoles(1, 4); + aPoles.SetValue(1, aPnt1); + aPoles.SetValue(2, aPnt2); + aPoles.SetValue(3, aPnt3); + aPoles.SetValue(4, aPnt4); + + // Define BSpline weights. + TColStd_Array1OfReal aBSplineWeights(1, 4); + aBSplineWeights.SetValue(1, 1.0); + aBSplineWeights.SetValue(2, 0.5); + aBSplineWeights.SetValue(3, 0.5); + aBSplineWeights.SetValue(4, 1.0); + + // Define knots. + TColStd_Array1OfReal aKnots(1, 2); + aKnots.SetValue(1, 0.0); + aKnots.SetValue(2, 1.0); + + // Define multiplicities. + TColStd_Array1OfInteger aMults(1, 2); + aMults.SetValue(1, 4); + aMults.SetValue(2, 4); + + // Define BSpline degree and periodicity. + Standard_Integer aDegree = 3; + Standard_Boolean aPeriodic = Standard_False; + + // Create a BSpline curve. + Handle(Geom_BSplineCurve) aBSplineCurve = new Geom_BSplineCurve( + aPoles, aBSplineWeights, aKnots, aMults, aDegree, aPeriodic); + myResult << "Geom_BSplineCurve was created in red" << std::endl; + + // Define Bezier weights. + TColStd_Array1OfReal aBezierWeights(1, 4); + aBezierWeights.SetValue(1, 0.5); + aBezierWeights.SetValue(2, 1.5); + aBezierWeights.SetValue(3, 1.5); + aBezierWeights.SetValue(4, 0.5); + + // Create Bezier curve. + Handle(Geom_BezierCurve) aBezierCurve = new Geom_BezierCurve(aPoles, aBezierWeights); + myResult << "Geom_BezierCurve was created in green" << std::endl; + + Handle(AIS_ColoredShape) anAisBSplineCurve = new AIS_ColoredShape( + BRepBuilderAPI_MakeEdge(aBSplineCurve).Shape()); + Handle(AIS_ColoredShape) anAisBezierCurve = new AIS_ColoredShape( + BRepBuilderAPI_MakeEdge(aBezierCurve).Shape()); + anAisBSplineCurve->SetColor(Quantity_Color(Quantity_NOC_RED)); + anAisBezierCurve->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisBSplineCurve); + myObject3d.Append(anAisBezierCurve); + myObject3d.Append(new AIS_Point(new Geom_CartesianPoint(aPnt1))); + myObject3d.Append(new AIS_Point(new Geom_CartesianPoint(aPnt2))); + myObject3d.Append(new AIS_Point(new Geom_CartesianPoint(aPnt3))); + myObject3d.Append(new AIS_Point(new Geom_CartesianPoint(aPnt4))); +} + +void GeometrySamples::AnalyticalSurfaces3dSample() +{ + // Define a XY plane. + gp_Pln aPln(gp::Origin(), gp::DZ()); + // Create plane geometry. + Handle(Geom_Plane) aPlaneSurf = new Geom_Plane(aPln); + myResult << "Geom_Plane was created in red" << std::endl; + + // Define a cylinder. + gp_Cylinder aCyl(gp::XOY(), 2.5); + // Create cylindrical surface. + Handle(Geom_CylindricalSurface) aCylSurf = new Geom_CylindricalSurface(aCyl); + myResult << "Geom_CylindricalSurface was created in green" << std::endl; + + // Define a cone. + gp_Cone aCone(gp::XOY(), M_PI_4, 2.5); + // Create conical surface. + Handle(Geom_ConicalSurface) aConeSurf = new Geom_ConicalSurface(aCone); + myResult << "Geom_ConicalSurface was created in blue" << std::endl; + + // Define a sphere. + gp_Pnt aSphereCenter(15.0, 15.0, 15.0); + gp_Sphere aSphere(gp_Ax3(aSphereCenter, gp::DZ()), 8.0); + // Create conical surface. + Handle(Geom_SphericalSurface) aSphereSurf = new Geom_SphericalSurface(aSphere); + myResult << "Geom_SphericalSurface was created in cyan" << std::endl; + + // Define a sphere. + gp_Pnt aTorusCenter(-15.0, -15.0, 25.0); + gp_Torus aTorus(gp_Ax3(aTorusCenter, gp::DZ()), 15.0, 5.0); + // Create toroidal surface. + Handle(Geom_ToroidalSurface) aTorusSurf = new Geom_ToroidalSurface(aTorus); + myResult << "Geom_ToroidalSurface was created in yellow" << std::endl; + + Handle(AIS_ColoredShape) anAisPlane = new AIS_ColoredShape(BRepBuilderAPI_MakeFace( + aPlaneSurf, 0.0, 20.0, 0.0, 20.0, Precision::Confusion()).Shape()); + Handle(AIS_ColoredShape) anAisCylinder = new AIS_ColoredShape(BRepBuilderAPI_MakeFace( + aCylSurf, 0.0, 2.0 * M_PI, 5.0, 15.0, Precision::Confusion()).Shape()); + Handle(AIS_ColoredShape) anAisCone = new AIS_ColoredShape(BRepBuilderAPI_MakeFace( + aConeSurf, 0.0, 2.0 * M_PI, 0.0, 15.0, Precision::Confusion()).Shape()); + Handle(AIS_ColoredShape) anAisSphere = new AIS_ColoredShape(BRepBuilderAPI_MakeFace( + aSphereSurf, Precision::Confusion()).Shape()); + Handle(AIS_ColoredShape) anAisTorus = new AIS_ColoredShape(BRepBuilderAPI_MakeFace( + aTorusSurf, Precision::Confusion()).Shape()); + anAisPlane->SetColor(Quantity_Color(Quantity_NOC_RED)); + anAisCylinder->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + anAisCone->SetColor(Quantity_Color(Quantity_NOC_BLUE1)); + anAisSphere->SetColor(Quantity_Color(Quantity_NOC_CYAN1)); + anAisTorus->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + myObject3d.Append(anAisPlane); + myObject3d.Append(anAisCylinder); + myObject3d.Append(anAisCone); + myObject3d.Append(anAisSphere); + myObject3d.Append(anAisTorus); +} + +void GeometrySamples::FreeStyleSurfaces3dSample() +{ + // Define a 4x4 grid of points for BSpline surface. + TColgp_Array2OfPnt aBSplinePnts(1, 4, 1, 4); + for (Standard_Integer i = 1; i <= 4; ++i) + { + gp_Pnt aPnt; + aPnt.SetX(5.0 * i); + for (Standard_Integer j = 1; j <= 4; ++j) + { + aPnt.SetY(5.0 * j); + if (1 < i && i < 4 && 1 < j && j < 4) + { + aPnt.SetZ(5.0); + } + else + { + aPnt.SetZ(0.0); + } + aBSplinePnts.SetValue(i, j, aPnt); + } + } + + // Define a 4x4 grid of points for Bezier surface. + TColgp_Array2OfPnt aBezierPnts(1, 4, 1, 4); + for (Standard_Integer i = 1; i <= 4; ++i) + { + gp_Pnt aPnt; + aPnt.SetX(20.0 + 5.0 * i); + for (Standard_Integer j = 1; j <= 4; ++j) + { + aPnt.SetY(20.0 + 5.0 * j); + if (1 < i && i < 4 && 1 < j && j < 4) + { + aPnt.SetZ(5.0); + } + else + { + aPnt.SetZ(0.0); + } + aBezierPnts.SetValue(i, j, aPnt); + } + } + + // Define BSpline weights. + TColStd_Array2OfReal aBSplineWeights(1, 4, 1, 4); + for (Standard_Integer i = 1; i <= 4; ++i) + { + for (Standard_Integer j = 1; j <= 4; ++j) + { + if (1 < i && i < 4 && 1 < j && j < 4) + { + aBSplineWeights.SetValue(i, j, 0.5); + } + else + { + aBSplineWeights.SetValue(i, j, 1.0); + } + } + } + + // Define knots. + TColStd_Array1OfReal aUKnots(1, 2), aVKnots(1, 2); + aUKnots.SetValue(1, 0.0); + aUKnots.SetValue(2, 1.0); + aVKnots.SetValue(1, 0.0); + aVKnots.SetValue(2, 1.0); + + // Define multiplicities. + TColStd_Array1OfInteger aUMults(1, 2), aVMults(1, 2); + aUMults.SetValue(1, 4); + aUMults.SetValue(2, 4); + aVMults.SetValue(1, 4); + aVMults.SetValue(2, 4); + + // Define BSpline degree and periodicity. + Standard_Integer aUDegree = 3; + Standard_Integer aVDegree = 3; + Standard_Boolean aUPeriodic = Standard_False; + Standard_Boolean aVPeriodic = Standard_False; + + // Create a BSpline surface. + Handle(Geom_BSplineSurface) aBSplineSurf = new Geom_BSplineSurface( + aBSplinePnts, aBSplineWeights, aUKnots, aVKnots, + aUMults, aVMults, aUDegree, aVDegree, aUPeriodic, aVPeriodic); + myResult << "Geom_BSplineSurface was created in red" << std::endl; + + // Define BSpline weights. + TColStd_Array2OfReal aBezierWeights(1, 4, 1, 4); + for (Standard_Integer i = 1; i <= 4; ++i) + { + for (Standard_Integer j = 1; j <= 4; ++j) + { + if (1 < i && i < 4 && 1 < j && j < 4) + { + aBezierWeights.SetValue(i, j, 1.5); + } + else + { + aBezierWeights.SetValue(i, j, 0.5); + } + } + } + + // Create a Bezier surface. + Handle(Geom_BezierSurface) aBezierSurf = new Geom_BezierSurface(aBezierPnts, aBezierWeights); + myResult << "Geom_BezierSurface was created in green" << std::endl; + + Handle(AIS_ColoredShape) anAisBSplineSurf = new AIS_ColoredShape( + BRepBuilderAPI_MakeFace(aBSplineSurf, Precision::Confusion()).Shape()); + Handle(AIS_ColoredShape) anAisBezierSurf = new AIS_ColoredShape( + BRepBuilderAPI_MakeFace(aBezierSurf, Precision::Confusion()).Shape()); + anAisBSplineSurf->SetColor(Quantity_Color(Quantity_NOC_RED)); + anAisBezierSurf->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisBSplineSurf); + myObject3d.Append(anAisBezierSurf); + for (TColgp_Array2OfPnt::Iterator anIt(aBSplinePnts); anIt.More(); anIt.Next()) + { + myObject3d.Append(new AIS_Point(new Geom_CartesianPoint(anIt.Value()))); + } + for (TColgp_Array2OfPnt::Iterator anIt(aBezierPnts); anIt.More(); anIt.Next()) + { + myObject3d.Append(new AIS_Point(new Geom_CartesianPoint(anIt.Value()))); + } +} + +void GeometrySamples::FreeStyleCurves2dSample() +{ + + // Define points. + gp_Pnt2d aPnt1(0.0, 0.0); + gp_Pnt2d aPnt2(5.0, 5.0); + gp_Pnt2d aPnt3(10.0, 5.0); + gp_Pnt2d aPnt4(15.0, 0.0); + + // Add points to the curve poles array. + TColgp_Array1OfPnt2d aBSplinePoles(1, 4); + aBSplinePoles.SetValue(1, aPnt1); + aBSplinePoles.SetValue(2, aPnt2); + aBSplinePoles.SetValue(3, aPnt3); + aBSplinePoles.SetValue(4, aPnt4); + + // Define BSpline weights. + TColStd_Array1OfReal aBSplineWeights(1, 4); + aBSplineWeights.SetValue(1, 1.0); + aBSplineWeights.SetValue(2, 0.5); + aBSplineWeights.SetValue(3, 0.5); + aBSplineWeights.SetValue(4, 1.0); + + // Define knots. + TColStd_Array1OfReal aKnots(1, 2); + aKnots.SetValue(1, 0.0); + aKnots.SetValue(2, 1.0); + + // Define multiplicities. + TColStd_Array1OfInteger aMults(1, 2); + aMults.SetValue(1, 4); + aMults.SetValue(2, 4); + + // Define BSpline degree and periodicity. + Standard_Integer aDegree = 3; + Standard_Boolean aPeriodic = Standard_False; + + // Create a BSpline curve. + Handle(Geom2d_BSplineCurve) aBSplineCurve = + new Geom2d_BSplineCurve(aBSplinePoles, aBSplineWeights, aKnots, aMults, aDegree, aPeriodic); + + + TColgp_Array1OfPnt2d aBezierPoles(1, 4); + gp_Vec2d anUp10Vec(0.0, 10.0); + aBezierPoles.SetValue(1, aPnt1.Translated(anUp10Vec)); + aBezierPoles.SetValue(2, aPnt2.Translated(anUp10Vec)); + aBezierPoles.SetValue(3, aPnt3.Translated(anUp10Vec)); + aBezierPoles.SetValue(4, aPnt4.Translated(anUp10Vec)); + + // Define Bezier weights. + TColStd_Array1OfReal aBezierWeights(1, 4); + aBezierWeights.SetValue(1, 0.5); + aBezierWeights.SetValue(2, 1.5); + aBezierWeights.SetValue(3, 1.5); + aBezierWeights.SetValue(4, 0.5); + + // Create Bezier curve. + Handle(Geom2d_BezierCurve) aBezierCurve = new Geom2d_BezierCurve(aBezierPoles, aBezierWeights); + + Handle(AdaptorCurve2d_AIS) anAisBSpline = new AdaptorCurve2d_AIS(aBSplineCurve); + myObject2d.Append(anAisBSpline); + Handle(AdaptorCurve2d_AIS) anAisBezier = new AdaptorCurve2d_AIS(aBezierCurve); + myObject2d.Append(anAisBezier); + + DisplayPnt(aPnt1, "1", Aspect_TOM_PLUS, 0.5); + DisplayPnt(aPnt2, "2", Aspect_TOM_PLUS, 0.5); + DisplayPnt(aPnt3, "3", Aspect_TOM_PLUS, 0.5); + DisplayPnt(aPnt4, "4", Aspect_TOM_PLUS, 0.5); +} + +void GeometrySamples::TrimmedCurve3dSample() +{ + // Define a circle placed in the origin of XY coordinate + // plane and with the radius equal to 5. + gp_Circ aCirc(gp::XOY(), 5.0); + // Create a closed circular curve. + Handle(Geom_Circle) aCircCurve = new Geom_Circle(aCirc); + myResult << "Geom_Circle was created in yellow" << std::endl; + + // Cut off a quarter of the circle. + Handle(Geom_TrimmedCurve) aCircQuater = new Geom_TrimmedCurve(aCircCurve, 0.0, M_PI_2); + myResult << "Geom_TrimmedCurve was created in red" << std::endl; + + Handle(AIS_ColoredShape) anAisCirc = new AIS_ColoredShape (BRepBuilderAPI_MakeEdge(aCircCurve).Shape()); + Handle(AIS_ColoredShape) anAisCircQuater = new AIS_ColoredShape (BRepBuilderAPI_MakeEdge(aCircQuater).Shape()); + anAisCirc->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisCircQuater->SetColor(Quantity_Color(Quantity_NOC_RED)); + anAisCircQuater->SetWidth(2.5); + myObject3d.Append(anAisCirc); + myObject3d.Append(anAisCircQuater); +} + +void GeometrySamples::OffsetCurve3dSample() +{ + // Define a circle placed in the origin of XY coordinate + // plane and with the radius equal to 5. + gp_Circ aCirc(gp::XOY(), 5.0); + // Create a closed circular curve. + Handle(Geom_Circle) aCircCurve = new Geom_Circle(aCirc); + myResult << "Geom_Circle was created in yellow" << std::endl; + + // An offset curve is a curve at constant distance (Offset) from + // a basis curve in a reference direction V. + // The offset curve takes its parametrization from the basis curve. + // The Offset curve is in the direction of the normal N + // defined with the cross product T^V, where the vector T + // is given by the first derivative on the basis curve with non zero length. + // The distance offset may be positive or negative to indicate the + // preferred side of the curve: + // . distance offset >0 => the curve is in the direction of N + // . distance offset <0 => the curve is in the direction of - N + // On the Offset curve: + // Value (U) = BasisCurve.Value(U) + (Offset * (T ^ V)) / ||T ^ V|| + // At any point the Offset direction V must not be parallel to the + // vector T and the vector T must not have null length else the + // offset curve is not defined. + + // Expand the circle by Offset equal to a quarter of the radius + // with direction V equal to Z. + Standard_Real anExpandOffset = +aCirc.Radius() / 4.0; + gp_Dir anExpandDir = gp::DZ(); + Handle(Geom_OffsetCurve) anExpandCircCurve = new Geom_OffsetCurve( + aCircCurve, anExpandOffset, anExpandDir); + myResult << "Geom_OffsetCurve (expanded circle) was created in red" << std::endl; + + // Collapse the circle by Offset equal to a half of the radius with direction V equal to Z. + Standard_Real anCollapseOffset = -aCirc.Radius() / 2.0; + gp_Dir anCollapseDir = gp::DZ(); + Handle(Geom_OffsetCurve) anCollapseCircCurve = new Geom_OffsetCurve (aCircCurve, anCollapseOffset, anCollapseDir); + myResult << "Geom_OffsetCurve (collapsed circle) was created in green" << std::endl; + + Handle(AIS_ColoredShape) anAisCirc = new AIS_ColoredShape (BRepBuilderAPI_MakeEdge(aCircCurve).Shape()); + Handle(AIS_ColoredShape) anAisExpandCirc = new AIS_ColoredShape (BRepBuilderAPI_MakeEdge(anExpandCircCurve).Shape()); + Handle(AIS_ColoredShape) anAisCpllapsedCirc = new AIS_ColoredShape (BRepBuilderAPI_MakeEdge(anCollapseCircCurve).Shape()); + anAisCirc->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisExpandCirc->SetColor(Quantity_Color(Quantity_NOC_RED)); + anAisCpllapsedCirc->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisCirc); + myObject3d.Append(anAisExpandCirc); + myObject3d.Append(anAisCpllapsedCirc); +} + +void GeometrySamples::BSplineFromCircle3dSample() +{ + // Define a circle placed in the origin of XY coordinate + // plane and with the radius equal to 5. + gp_Circ aCirc(gp::XOY(), 5.0); + // Create a closed circular curve. + Handle(Geom_Circle) aCircCurve = new Geom_Circle(aCirc); + myResult << "Geom_Circle was created in yellow" << std::endl; + + // Convert the circle curve to a BSpline one. + Handle(Geom_BSplineCurve) aBSplineFromCirc = GeomConvert::CurveToBSplineCurve(aCircCurve); + myResult << "Geom_BSplineCurve was created in red:" << std::endl; + myResult << "Degree: " << aBSplineFromCirc->Degree() << std::endl; + myResult << "Periodic: " << (aBSplineFromCirc->IsPeriodic() ? "Yes" : "No") << std::endl; + myResult << "Poles: [" << aBSplineFromCirc->Poles().Size() << "]" << std::endl; + for (TColgp_Array1OfPnt::Iterator anIt(aBSplineFromCirc->Poles()); anIt.More(); anIt.Next()) + { + myResult << " (" << anIt.Value().X() << ", " << anIt.Value().Y() << ", " << anIt.Value().Z() << ")" << std::endl; + } + + Handle(AIS_ColoredShape) anAisCirc = new AIS_ColoredShape (BRepBuilderAPI_MakeEdge(aCircCurve).Shape()); + Handle(AIS_ColoredShape) anAisBSpline = new AIS_ColoredShape (BRepBuilderAPI_MakeEdge(aBSplineFromCirc).Shape()); + anAisCirc->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisBSpline->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisCirc); + myObject3d.Append(anAisBSpline); +} + +void GeometrySamples::TrimmedSurface3dSample() +{ + // Define a XY plane. + gp_Pln aPln(gp::XOY()); + // Create a plane surface. + Handle(Geom_Plane) aPlaneSurf = new Geom_Plane(aPln); + myResult << "Geom_Plane was created" << std::endl; + + // Trim [0 ... 30 X 0 ... 50] rectangular range. + Standard_Real aUMin = 0.0; + Standard_Real aUMax = 30.0; + Standard_Real aVMin = 0.0; + Standard_Real aVMax = 50.0; + Handle(Geom_RectangularTrimmedSurface) aTrimmedPlaneSurf + = new Geom_RectangularTrimmedSurface(aPlaneSurf, aUMin, aUMax, aVMin, aVMax); + myResult << "Geom_RectangularTrimmedSurface was created in red" << std::endl; + + Handle(AIS_Plane) anAisPlane = new AIS_Plane(aPlaneSurf); + Handle(AIS_ColoredShape) anAisTimmedPlane = new AIS_ColoredShape (BRepBuilderAPI_MakeFace (aTrimmedPlaneSurf, 0.001).Shape()); + anAisTimmedPlane->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisPlane); + myObject3d.Append(anAisTimmedPlane); +} + +void GeometrySamples::OffsetSurface3dSample() +{ + // Define a XY plane. + gp_Pln aPln(gp::XOY()); + // Create a plane surface. + Handle(Geom_Plane) aPlaneSurf = new Geom_Plane(aPln); + myResult << "Geom_Plane was created" << std::endl; + + // An offset surface is defined by: + // - the basis surface to which it is parallel, and + // - the distance between the offset surface and its basis surface. + // A point on the offset surface is built by measuring the + // offset value along the normal vector at a point on the + // basis surface. This normal vector is given by the cross + // product D1u^D1v, where D1u and D1v are the + // vectors tangential to the basis surface in the u and v + // parametric directions at this point. The side of the + // basis surface on which the offset is measured + // depends on the sign of the offset value. + + // Offset the plane in the normal direction. + Standard_Real aPosOffset = 10.0; + Handle(Geom_OffsetSurface) aPosOffsetSurf = new Geom_OffsetSurface(aPlaneSurf, aPosOffset); + myResult << "Geom_OffsetSurface with " << aPosOffset << " was created in red" << std::endl; + + // Offset the plane in direction opposite to the normal one. + Standard_Real aNegOffset = -15.0; + Handle(Geom_OffsetSurface) aNegOffsetSurf = new Geom_OffsetSurface(aPlaneSurf, aNegOffset); + myResult << "Geom_OffsetSurface with " << aNegOffset << " was created in green" << std::endl; + + Handle(AIS_ColoredShape) anAisPlane = new AIS_ColoredShape( + BRepBuilderAPI_MakeFace(aPlaneSurf, 0.0, 10.0, 0.0, 10.0, Precision::Confusion()).Shape()); + Handle(AIS_ColoredShape) anAisPosOffsetPlane = new AIS_ColoredShape( + BRepBuilderAPI_MakeFace(aPosOffsetSurf, 0.0, 10.0, 0.0, 10.0, Precision::Confusion()).Shape()); + Handle(AIS_ColoredShape) anAisNegOffsetPlane = new AIS_ColoredShape( + BRepBuilderAPI_MakeFace(aNegOffsetSurf, 0.0, 10.0, 0.0, 10.0, Precision::Confusion()).Shape()); + anAisPosOffsetPlane->SetColor(Quantity_Color(Quantity_NOC_RED)); + anAisNegOffsetPlane->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisPlane); + myObject3d.Append(anAisPosOffsetPlane); + myObject3d.Append(anAisNegOffsetPlane); +} + +void GeometrySamples::ExtrusionSurface3dSample() +{ + // Create an ellipse curve in XY plane. + Standard_Real aMinorRadius = 10.0; + Standard_Real aMajorRadius = 20.0; + Handle(Geom_Ellipse) anEllipseCurve = new Geom_Ellipse(gp::XOY(), aMajorRadius, aMinorRadius); + myResult << "Geom_Ellipse was created in yellow" << std::endl; + + // Make a linear extrusion of the ellipse at 45 degrees to Z axis + gp_Dir aDirOfExtr = gp::DZ(); + Handle(Geom_SurfaceOfLinearExtrusion) aLinExtrSurf + = new Geom_SurfaceOfLinearExtrusion(anEllipseCurve, aDirOfExtr); + myResult << "Geom_SurfaceOfLinearExtrusion was created in red" << std::endl; + + Handle(AIS_ColoredShape) anAisEllipse = new AIS_ColoredShape( + BRepBuilderAPI_MakeEdge(anEllipseCurve).Shape()); + Handle(AIS_ColoredShape) anAisExtrSurf = new AIS_ColoredShape( + BRepBuilderAPI_MakeFace(aLinExtrSurf, 0.0, 2.0 * M_PI, 0.0, 30.0, + Precision::Confusion()).Shape()); + anAisEllipse->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisEllipse->SetWidth(2.5); + anAisExtrSurf->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisEllipse); + myObject3d.Append(anAisExtrSurf); +} + +void GeometrySamples::RevolutionSurface3dSample() +{ + // Create an ellipse curve in XY plane with + // the center at (-10, 0, 0). + Standard_Real aMinorRadius = 5.0; + Standard_Real aMajorRadius = 10.0; + gp_Pnt aCenter(-30.0, 0.0, 0.0); + Handle(Geom_Ellipse) anEllipseCurve = new Geom_Ellipse(gp_Ax2(aCenter, gp::DZ()), + aMajorRadius, aMinorRadius); + myResult << "Geom_Ellipse was created in yellow" << std::endl; + + // Make a revolution of the ellipse around Y axis + Handle(Geom_SurfaceOfRevolution) aRevolSurf = new Geom_SurfaceOfRevolution(anEllipseCurve, gp::OY()); + myResult << "Geom_SurfaceOfRevolution was created in red" << std::endl; + + Handle(AIS_ColoredShape) anAisEllipse = new AIS_ColoredShape( + BRepBuilderAPI_MakeEdge(anEllipseCurve).Shape()); + Handle(AIS_ColoredShape) anAisRevolSurf = new AIS_ColoredShape( + BRepBuilderAPI_MakeFace(aRevolSurf, Precision::Confusion()).Shape()); + anAisEllipse->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisEllipse->SetWidth(2.5); + anAisRevolSurf->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisEllipse); + myObject3d.Append(anAisRevolSurf); +} + +void GeometrySamples::TrimmedCurve2dSample() +{ + // Create a closed circular curve. + Handle(Geom2d_Circle) aGeomCircle = new Geom2d_Circle(gp_Ax2d(gp_Pnt2d(), gp_Vec2d(1.0, 0.0)), 5.0); + Handle(AdaptorCurve2d_AIS) anAisCirc = new AdaptorCurve2d_AIS(aGeomCircle); + myObject2d.Append(anAisCirc); + + // Cut off a quarter of the circle. + Handle(Geom2d_TrimmedCurve) aCircQuater = new Geom2d_TrimmedCurve(aGeomCircle, 0.0, M_PI_2); + aCircQuater->Translate(gp_Vec2d(15.0, 0.0)); + Handle(AdaptorCurve2d_AIS) anAisCircQuater = new AdaptorCurve2d_AIS(aCircQuater); + myObject2d.Append(anAisCircQuater); +} + +void GeometrySamples::OffsetCurve2dSample() +{ + Handle(Geom2d_Circle) aGeomCircle = new Geom2d_Circle(gp_Ax2d(gp_Pnt2d(), gp_Vec2d(1.0, 0.0)), 5.0); + + Standard_Real anExpandOffset = aGeomCircle->Radius() / 4.0; + Handle(Geom2d_OffsetCurve) anExpandCircCurve = new Geom2d_OffsetCurve(aGeomCircle, anExpandOffset); + + Standard_Real anCollapseOffset = -aGeomCircle->Radius() / 2.0; + Handle(Geom2d_OffsetCurve) anCollapseCircCurve = new Geom2d_OffsetCurve(aGeomCircle, anCollapseOffset); + + Handle(AdaptorCurve2d_AIS) anAisCirc = new AdaptorCurve2d_AIS(aGeomCircle); + myObject2d.Append(anAisCirc); + Handle(AdaptorCurve2d_AIS) anAisExpand = new AdaptorCurve2d_AIS(anExpandCircCurve); + myObject2d.Append(anAisExpand); + Handle(AdaptorCurve2d_AIS) anAisCollapse = new AdaptorCurve2d_AIS(anCollapseCircCurve); + myObject2d.Append(anAisCollapse); +} + +void GeometrySamples::BoundingBoxOfSurface3dSample() +{ + // Define a 4x4 grid of points for BSpline surface. + TColgp_Array2OfPnt aPoints(1, 4, 1, 4); + for (Standard_Integer i = 1; i <= 4; ++i) + { + gp_Pnt aPnt; + aPnt.SetX(5.0 * i); + for (Standard_Integer j = 1; j <= 4; ++j) + { + aPnt.SetY(5.0 * j); + if (1 < i && i < 4 && 1 < j && j < 4) + { + aPnt.SetZ(5.0); + } + else + { + aPnt.SetZ(0.0); + } + aPoints.SetValue(i, j, aPnt); + } + } + + // Make a BSpline surface from the points array. + Handle(Geom_BSplineSurface) aBSplineSurf = GeomAPI_PointsToBSplineSurface(aPoints).Surface(); + myResult << "Geom_BSplineSurface was created" << std::endl; + + // Compute BSpline surface bounding box. + Bnd_Box aBndBox; + BndLib_AddSurface::AddOptimal(GeomAdaptor_Surface(aBSplineSurf), Precision::Confusion(), aBndBox); + myResult << "Bounding box:" << std::endl; + myResult << " Min corner = [ " + << aBndBox.CornerMin().X() << ", " + << aBndBox.CornerMin().Y() << ", " + << aBndBox.CornerMin().Z() << " ]" << std::endl; + myResult << " Max corner = [ " + << aBndBox.CornerMax().X() << ", " + << aBndBox.CornerMax().Y() << ", " + << aBndBox.CornerMax().Z() << " ]" << std::endl; + + Handle(AIS_ColoredShape) anAisBSplineSurf = new AIS_ColoredShape( + BRepBuilderAPI_MakeFace(aBSplineSurf, Precision::Confusion()).Shape()); + Handle(AIS_ColoredShape) anAisBndBox = new AIS_ColoredShape( + BRepPrimAPI_MakeBox(aBndBox.CornerMin(), aBndBox.CornerMax()).Shell()); + myObject3d.Append(anAisBSplineSurf); + myObject3d.Append(anAisBndBox); + myContext->SetDisplayMode(anAisBndBox, 0, Standard_True); +} + +void GeometrySamples::BoundingBoxOfCurves3dSample() +{ + // Define points. + gp_Pnt aPnt1(0.0, 0.0, 10.0); + gp_Pnt aPnt2(5.0, 5.0, 5.0); + gp_Pnt aPnt3(10.0, 10.0, 15.0); + gp_Pnt aPnt4(15.0, 5.0, 20.0); + + // Add points to the curve poles array. + TColgp_Array1OfPnt aPoles(1, 4); + aPoles.SetValue(1, aPnt1); + aPoles.SetValue(2, aPnt2); + aPoles.SetValue(3, aPnt3); + aPoles.SetValue(4, aPnt4); + + // Make a BSpline curve from the points array. + Handle(Geom_BSplineCurve) aBSplineCurve = GeomAPI_PointsToBSpline(aPoles).Curve(); + myResult << "aBSplineCurve was created" << std::endl; + + // Compute BSpline curve bounding box. + Bnd_Box aBndBox; + BndLib_Add3dCurve::AddOptimal(GeomAdaptor_Curve(aBSplineCurve), Precision::Confusion(), aBndBox); + myResult << "Bounding box:" << std::endl; + myResult << " Min corner = [ " + << aBndBox.CornerMin().X() << ", " + << aBndBox.CornerMin().Y() << ", " + << aBndBox.CornerMin().Z() << " ]" << std::endl; + myResult << " Max corner = [ " + << aBndBox.CornerMax().X() << ", " + << aBndBox.CornerMax().Y() << ", " + << aBndBox.CornerMax().Z() << " ]" << std::endl; + + Handle(AIS_ColoredShape) anAisBSplineCurve = new AIS_ColoredShape (BRepBuilderAPI_MakeEdge(aBSplineCurve).Shape()); + Handle(AIS_ColoredShape) anAisBndBox = new AIS_ColoredShape (BRepPrimAPI_MakeBox(aBndBox.CornerMin(), aBndBox.CornerMax()).Shell()); + myObject3d.Append(anAisBSplineCurve); + myObject3d.Append(anAisBndBox); + myContext->SetDisplayMode(anAisBndBox, 0, Standard_True); +} + +void GeometrySamples::BoundingBoxOfCurves2dSample() +{ + // Define points. + gp_Pnt2d aPnt1(0.0, 0.0); + gp_Pnt2d aPnt2(5.0, 5.0); + gp_Pnt2d aPnt3(10.0, 10.0); + gp_Pnt2d aPnt4(15.0, 5.0); + + // Add points to the curve poles array. + TColgp_Array1OfPnt2d aPoles(1, 4); + aPoles.SetValue(1, aPnt1); + aPoles.SetValue(2, aPnt2); + aPoles.SetValue(3, aPnt3); + aPoles.SetValue(4, aPnt4); + + // Make a BSpline curve from the points array. + Handle(Geom2d_BSplineCurve) aBSplineCurve = Geom2dAPI_PointsToBSpline(aPoles).Curve(); + + // Compute BSpline curve bounding box. + Bnd_Box2d aBndBox; + BndLib_Add2dCurve::AddOptimal(aBSplineCurve, 0.0, 1.0, Precision::PConfusion(), aBndBox); + Standard_Real aXmin, aYmin, aXmax, aYmax; + aBndBox.Get(aXmin, aYmin, aXmax, aYmax); + + myResult << "Bounding box:" << std::endl; + myResult << " Min corner = [ " << aXmin << ", " << aYmin << " ]" << std::endl; + myResult << " Max corner = [ " << aXmax << ", " << aYmax << " ]" << std::endl; + + Handle(AdaptorCurve2d_AIS) anAisBSpline = new AdaptorCurve2d_AIS(aBSplineCurve); + + Handle(AdaptorVec_AIS) anAisVec1 = new AdaptorVec_AIS(gp_Pnt2d(aXmin, aYmin), gp_Pnt2d(aXmin, aYmax)); + Handle(AdaptorVec_AIS) anAisVec2 = new AdaptorVec_AIS(gp_Pnt2d(aXmin, aYmax), gp_Pnt2d(aXmax, aYmax)); + Handle(AdaptorVec_AIS) anAisVec3 = new AdaptorVec_AIS(gp_Pnt2d(aXmax, aYmax), gp_Pnt2d(aXmax, aYmin)); + Handle(AdaptorVec_AIS) anAisVec4 = new AdaptorVec_AIS(gp_Pnt2d(aXmax, aYmin), gp_Pnt2d(aXmin, aYmin)); + + myObject2d.Append(anAisBSpline); + myObject2d.Append(anAisVec1); + myObject2d.Append(anAisVec2); + myObject2d.Append(anAisVec3); + myObject2d.Append(anAisVec4); +} + +void GeometrySamples::DumpCircleInfoSample() +{ + // Define a circle placed in the origin of XY coordinate + // plane and with the radius equal to 0.5. + gp_Circ aCirc(gp::XOY(), 0.5); + // Create a closed circular curve. + Handle(Geom_Circle) aCircCurve = new Geom_Circle(aCirc); + myResult << "Geom_Circle was created:" << std::endl; + myResult << " Center = [ " + << aCircCurve->Position().Location().X() << ", " + << aCircCurve->Position().Location().Y() << ", " + << aCircCurve->Position().Location().Z() << " ]" + << std::endl; + myResult << " Radius = " << aCircCurve->Radius() << std::endl; + myResult << " Plane normal = [ " + << aCircCurve->Position().Direction().X() << ", " + << aCircCurve->Position().Direction().Y() << ", " + << aCircCurve->Position().Direction().Z() << " ]" + << std::endl; + + Handle(AIS_Circle) anAisCircle = new AIS_Circle(aCircCurve); + Handle(AIS_TextLabel) anAisCenterLabel = new AIS_TextLabel(); + anAisCenterLabel->SetText(" Center"); + anAisCenterLabel->SetPosition(aCircCurve->Position().Location()); + Handle(AIS_Point) anAisCenter = new AIS_Point(new Geom_CartesianPoint(aCirc.Location())); + Handle(AIS_Axis) anAisAxis = new AIS_Axis(new Geom_Axis2Placement(aCircCurve->Position()), AIS_TOAX_ZAxis); + myObject3d.Append(anAisCircle); + myObject3d.Append(anAisCenterLabel); + myObject3d.Append(anAisAxis); +} + +void GeometrySamples::DumpBSplineCurveInfoSample() +{ + // Define points. + gp_Pnt aPnt1(0.0, 0.0, 10.0); + gp_Pnt aPnt2(5.0, 5.0, 5.0); + gp_Pnt aPnt3(10.0, 10.0, 15.0); + gp_Pnt aPnt4(15.0, 5.0, 20.0); + + // Add points to the curve poles array. + TColgp_Array1OfPnt aPoles(1, 4); + aPoles.SetValue(1, aPnt1); + aPoles.SetValue(2, aPnt2); + aPoles.SetValue(3, aPnt3); + aPoles.SetValue(4, aPnt4); + + // Make a BSpline curve from the points array + Handle(Geom_BSplineCurve) aBSplineCurve = GeomAPI_PointsToBSpline(aPoles).Curve(); + myResult << "aBSplineCurve was created:" << std::endl; + myResult << " Degree = " << aBSplineCurve->Degree() << std::endl; + myResult << " Parameter range = [ " + << aBSplineCurve->FirstParameter() << ", " + << aBSplineCurve->LastParameter() << " ]" + << std::endl; + NCollection_List aParams; + aParams.Append(0.75 * aBSplineCurve->FirstParameter() + 0.25 * aBSplineCurve->LastParameter()); + aParams.Append(0.50 * aBSplineCurve->FirstParameter() + 0.50 * aBSplineCurve->LastParameter()); + aParams.Append(0.25 * aBSplineCurve->FirstParameter() + 0.75 * aBSplineCurve->LastParameter()); + myResult << " Curve info:" << std::endl; + for (NCollection_List::Iterator anIt(aParams); anIt.More(); anIt.Next()) + { + Standard_Real aParam = anIt.Value(); + gp_Pnt aPnt; + gp_Vec aVec; + aBSplineCurve->D1(aParam, aPnt, aVec); + myResult << " Param = " << aParam << std::endl; + myResult << " P = [ " << aPnt.X() << ", " << aPnt.Y() << ", " << aPnt.Z() << " ]" << std::endl; + myResult << " D = [ " << aVec.X() << ", " << aVec.Y() << ", " << aVec.Z() << " ]" << std::endl; + myObject3d.Append(new AIS_Point(new Geom_CartesianPoint(aPnt))); + Handle(AIS_TextLabel) anAisCenterLabel = new AIS_TextLabel(); + Standard_SStream aSS; + aSS << "P [" << aPnt.X() << ", " << aPnt.Y() << ", " << aPnt.Z() << "]" << std::endl; + aSS << "D [" << aVec.X() << ", " << aVec.Y() << ", " << aVec.Z() << "]" << std::endl; + anAisCenterLabel->SetText(aSS.str().c_str()); + anAisCenterLabel->SetPosition(aPnt); + myObject3d.Append(anAisCenterLabel); + Handle(AIS_Axis) anAisD = new AIS_Axis(new Geom_Axis1Placement(gp_Ax1(aPnt, aVec))); + myObject3d.Append(anAisD); + } + + Handle(AIS_ColoredShape) anAisBSplineCurve = new AIS_ColoredShape (BRepBuilderAPI_MakeEdge(aBSplineCurve).Shape()); + anAisBSplineCurve->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisBSplineCurve); +} diff --git a/samples/OCCTOverview/code/GeometrySamples.h b/samples/OCCTOverview/code/GeometrySamples.h new file mode 100644 index 0000000000..7da4ad7645 --- /dev/null +++ b/samples/OCCTOverview/code/GeometrySamples.h @@ -0,0 +1,102 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef GEOMETRYSAMPLES_H +#define GEOMETRYSAMPLES_H + +#include "BaseSample.h" + +//! Implements Geometry samples +class GeometrySamples : public BaseSample +{ + DEFINE_STANDARD_RTTI_INLINE(GeometrySamples, BaseSample) +public: + + GeometrySamples (const TCollection_AsciiString& theSampleSourcePath, + const Handle(AIS_InteractiveContext)& theContext) + : BaseSample(theSampleSourcePath, theContext) {} + +protected: + virtual void ExecuteSample (const TCollection_AsciiString& theSampleName) Standard_OVERRIDE; + +private: + void DisplayPnt (const gp_Pnt& thePnt, const TCollection_AsciiString& theText, + Aspect_TypeOfMarker theMarker = Aspect_TOM_PLUS, + Standard_Real theDistance = 5.0); + void DisplayPnt (const gp_Pnt2d& thePnt2d, const TCollection_AsciiString& theText, + Aspect_TypeOfMarker theMarker = Aspect_TOM_PLUS, + Standard_Real theDistance = 5.0); + + // One function for every sample + void ZeroDimensionObjects3dSample(); + void Vectors3dSample(); + void InfinityLines3dSample(); + void SecondOrderCurves3dSample(); + void PlaneSurfaces3dSample(); + void SecondOrderSurfaces3dSample(); + void ZeroDimensionObjects2dSample(); + void Vectors2dSample(); + void InfinityLines2dSample(); + void SecondOrderCurves2dSample(); + void BarycenterPoint3dSample(); + void RotatedVector3dSample(); + void MirroredLine3dSample(); + void ScaledEllipse3dSample(); + void TransformedCylinder3dSample(); + void TranslatedTorus3dSample(); + void ConjugateObjects3dSample(); + void ProjectionOfPoint3dSample(); + void MinimalDistance3dSample(); + void Intersection3dSample(); + void TranslatedPoint2dSample(); + void RotatedDirection2dSample(); + void MirroredAxis2dSample(); + void TransformedEllipse2dSample(); + void ConjugateObjects2dSample(); + void Tangent2dSample(); + void ProjectionOfPoint2dSample(); + void MinimalDistance2dSample(); + void Intersection2dSample(); + void PointInfo3dSample(); + void EllipseInfo3dSample(); + void PointInfo2dSample(); + void CircleInfo2dSample(); + void FreeStyleCurves3dSample(); + void AnalyticalSurfaces3dSample(); + void FreeStyleSurfaces3dSample(); + void FreeStyleCurves2dSample(); + void TrimmedCurve3dSample(); + void OffsetCurve3dSample(); + void BSplineFromCircle3dSample(); + void TrimmedSurface3dSample(); + void OffsetSurface3dSample(); + void ExtrusionSurface3dSample(); + void RevolutionSurface3dSample(); + void TrimmedCurve2dSample(); + void OffsetCurve2dSample(); + void BoundingBoxOfSurface3dSample(); + void BoundingBoxOfCurves3dSample(); + void BoundingBoxOfCurves2dSample(); + void DumpCircleInfoSample(); + void DumpBSplineCurveInfoSample(); +}; + +#endif //GEOMETRYSAMPLES_H diff --git a/samples/OCCTOverview/code/MakeBottle.cxx b/samples/OCCTOverview/code/MakeBottle.cxx new file mode 100644 index 0000000000..44307e0759 --- /dev/null +++ b/samples/OCCTOverview/code/MakeBottle.cxx @@ -0,0 +1,218 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "MakeBottle.h" + +#include + +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +TopoDS_Shape MakeBottle (const Standard_Real theWidth, + const Standard_Real theHeight, + const Standard_Real theThickness) +{ + // Profile : Define Support Points + gp_Pnt aPnt1(-theWidth / 2., 0, 0); + gp_Pnt aPnt2(-theWidth / 2., -theThickness / 4., 0); + gp_Pnt aPnt3(0, -theThickness / 2., 0); + gp_Pnt aPnt4(theWidth / 2., -theThickness / 4., 0); + gp_Pnt aPnt5(theWidth / 2., 0, 0); + + // Profile : Define the Geometry + Handle(Geom_TrimmedCurve) anArcOfCircle = GC_MakeArcOfCircle(aPnt2, aPnt3, aPnt4); + Handle(Geom_TrimmedCurve) aSegment1 = GC_MakeSegment(aPnt1, aPnt2); + Handle(Geom_TrimmedCurve) aSegment2 = GC_MakeSegment(aPnt4, aPnt5); + + // Profile : Define the Topology + TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(aSegment1); + TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(anArcOfCircle); + TopoDS_Edge anEdge3 = BRepBuilderAPI_MakeEdge(aSegment2); + TopoDS_Wire aWire = BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3); + + // Complete Profile + gp_Ax1 xAxis = gp::OX(); + gp_Trsf aTrsf; + + aTrsf.SetMirror(xAxis); + BRepBuilderAPI_Transform aBRepTrsf(aWire, aTrsf); + TopoDS_Shape aMirroredShape = aBRepTrsf.Shape(); + TopoDS_Wire aMirroredWire = TopoDS::Wire(aMirroredShape); + + BRepBuilderAPI_MakeWire mkWire; + mkWire.Add(aWire); + mkWire.Add(aMirroredWire); + TopoDS_Wire myWireProfile = mkWire.Wire(); + + // Body : Prism the Profile + TopoDS_Face myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile); + gp_Vec aPrismVec(0, 0, theHeight); + TopoDS_Shape myBody = BRepPrimAPI_MakePrism(myFaceProfile, aPrismVec); + + // Body : Apply Fillets + BRepFilletAPI_MakeFillet mkFillet(myBody); + TopExp_Explorer anEdgeExplorer(myBody, TopAbs_EDGE); + while (anEdgeExplorer.More()) + { + TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExplorer.Current()); + //Add edge to fillet algorithm + mkFillet.Add(theThickness / 12., anEdge); + anEdgeExplorer.Next(); + } + + myBody = mkFillet.Shape(); + + // Body : Add the Neck + gp_Pnt neckLocation(0, 0, theHeight); + gp_Dir neckAxis = gp::DZ(); + gp_Ax2 neckAx2(neckLocation, neckAxis); + + Standard_Real myNeckRadius = theThickness / 4.; + Standard_Real myNeckHeight = theHeight / 10.; + + BRepPrimAPI_MakeCylinder MKCylinder(neckAx2, myNeckRadius, myNeckHeight); + TopoDS_Shape myNeck = MKCylinder.Shape(); + + myBody = BRepAlgoAPI_Fuse(myBody, myNeck); + + // Body : Create a Hollowed Solid + TopoDS_Face faceToRemove; + Standard_Real zMax = -1; + + for (TopExp_Explorer aFaceExplorer(myBody, TopAbs_FACE); aFaceExplorer.More(); aFaceExplorer.Next()) + { + TopoDS_Face aFace = TopoDS::Face(aFaceExplorer.Current()); + // Check if is the top face of the bottle’s neck + Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace); + if (aSurface->DynamicType() == STANDARD_TYPE(Geom_Plane)) + { + Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aSurface); + gp_Pnt aPnt = aPlane->Location(); + Standard_Real aZ = aPnt.Z(); + if (aZ > zMax) + { + zMax = aZ; + faceToRemove = aFace; + } + } + } + + TopTools_ListOfShape facesToRemove; + facesToRemove.Append(faceToRemove); + BRepOffsetAPI_MakeThickSolid aSolidMaker; + aSolidMaker.MakeThickSolidByJoin(myBody, facesToRemove, -theThickness / 50, 1.e-3); + myBody = aSolidMaker.Shape(); + // Threading : Create Surfaces + Handle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 0.99); + Handle(Geom_CylindricalSurface) aCyl2 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 1.05); + + // Threading : Define 2D Curves + gp_Pnt2d aPnt(2. * M_PI, myNeckHeight / 2.); + gp_Dir2d aDir(2. * M_PI, myNeckHeight / 4.); + gp_Ax2d anAx2d(aPnt, aDir); + + Standard_Real aMajor = 2. * M_PI; + Standard_Real aMinor = myNeckHeight / 10; + + Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor); + Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor / 4); + Handle(Geom2d_TrimmedCurve) anArc1 = new Geom2d_TrimmedCurve(anEllipse1, 0, M_PI); + Handle(Geom2d_TrimmedCurve) anArc2 = new Geom2d_TrimmedCurve(anEllipse2, 0, M_PI); + gp_Pnt2d anEllipsePnt1 = anEllipse1->Value(0); + gp_Pnt2d anEllipsePnt2 = anEllipse1->Value(M_PI); + + Handle(Geom2d_TrimmedCurve) aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2); + // Threading : Build Edges and Wires + TopoDS_Edge anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(anArc1, aCyl1); + TopoDS_Edge anEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment, aCyl1); + TopoDS_Edge anEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(anArc2, aCyl2); + TopoDS_Edge anEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment, aCyl2); + TopoDS_Wire threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1, anEdge2OnSurf1); + TopoDS_Wire threadingWire2 = BRepBuilderAPI_MakeWire(anEdge1OnSurf2, anEdge2OnSurf2); + BRepLib::BuildCurves3d(threadingWire1); + BRepLib::BuildCurves3d(threadingWire2); + + // Create Threading + BRepOffsetAPI_ThruSections aTool(Standard_True); + aTool.AddWire(threadingWire1); + aTool.AddWire(threadingWire2); + aTool.CheckCompatibility(Standard_False); + + TopoDS_Shape myThreading = aTool.Shape(); + + // Building the Resulting Compound + TopoDS_Compound aRes; + BRep_Builder aBuilder; + aBuilder.MakeCompound(aRes); + aBuilder.Add(aRes, myBody); + aBuilder.Add(aRes, myThreading); + + return aRes; +} diff --git a/samples/OCCTOverview/code/MakeBottle.h b/samples/OCCTOverview/code/MakeBottle.h new file mode 100644 index 0000000000..ad1e783064 --- /dev/null +++ b/samples/OCCTOverview/code/MakeBottle.h @@ -0,0 +1,33 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef MAKEBOTTLE_H +#define MAKEBOTTLE_H + +#include +#include + +//! Returns sample bottle TopoDS_Shape +TopoDS_Shape MakeBottle(const Standard_Real theWidth, + const Standard_Real theyHeight, + const Standard_Real theThickness); + +#endif // MAKEBOTTLE_H diff --git a/samples/OCCTOverview/code/Ocaf.json b/samples/OCCTOverview/code/Ocaf.json new file mode 100644 index 0000000000..f84b2c5dba --- /dev/null +++ b/samples/OCCTOverview/code/Ocaf.json @@ -0,0 +1,53 @@ +{ + "OCAF": { + "1 Create": [{ + "text": "Create Box", + "function": "CreateBoxOcafSample", + "description": "" + }, + { + "text": "Create Cylinder", + "function": "CreateCylinderOcafSample", + "description": "" + } + ], + "2 Modify": [{ + "text": "Modify Box", + "function": "ModifyBoxOcafSample", + "description": "" + }, + { + "text": "Modify Cylinder", + "function": "ModifyCylinderOcafSample", + "description": "" + } + ], + "3 Action": [{ + "text": "Undo", + "function": "UndoOcafSample", + "description": "" + }, + { + "text": "Redo", + "function": "RedoOcafSample", + "description": "" + } + ], + "4 Data storage": [{ + "text": "Open OCAF", + "function": "DialogOpenOcafSample", + "description": "" + }, + { + "text": "Save binary OCAF", + "function": "DialogSaveBinOcafSample", + "description": "" + }, + { + "text": "Save XML OCAF", + "function": "DialogSaveXmlOcafSample", + "description": "" + } + ] + } +} \ No newline at end of file diff --git a/samples/OCCTOverview/code/OcafSamples.cxx b/samples/OCCTOverview/code/OcafSamples.cxx new file mode 100644 index 0000000000..940b49a758 --- /dev/null +++ b/samples/OCCTOverview/code/OcafSamples.cxx @@ -0,0 +1,624 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "OcafSamples.h" + +#include "TOcaf_Application.h" +#include "TOcafFunction_BoxDriver.h" +#include "TOcafFunction_CylDriver.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void OcafSamples::Process (const TCollection_AsciiString& theSampleName) +{ + if (IsImportSample(theSampleName)) + { + myObject3d.Clear(); + } + myObject2d.Clear(); + myCode.Clear(); + myIsProcessed = Standard_False; + try + { + ExecuteSample(theSampleName); + } + catch (...) + { + TraceError(TCollection_AsciiString("Error in sample: ") + theSampleName); + } +} + +void OcafSamples::ClearExtra() +{ + myOcafDoc = nullptr; + myContext->RemoveAll(Standard_True); +} + +void OcafSamples::ExecuteSample (const TCollection_AsciiString& theSampleName) +{ + Standard_Boolean anIsSamplePresent = Standard_True; + FindSourceCode(theSampleName); + if (theSampleName == "CreateOcafDocument") + CreateOcafDocument(); + else if (theSampleName == "CreateBoxOcafSample") + CreateBoxOcafSample(); + else if (theSampleName == "CreateCylinderOcafSample") + CreateCylinderOcafSample(); + else if (theSampleName == "ModifyBoxOcafSample") + ModifyBoxOcafSample(); + else if (theSampleName == "ModifyCylinderOcafSample") + ModifyCylinderOcafSample(); + else if (theSampleName == "UndoOcafSample") + UndoOcafSample(); + else if (theSampleName == "RedoOcafSample") + RedoOcafSample(); + else if (theSampleName == "DialogOpenOcafSample") + DialogOpenOcafSample(); + else if (theSampleName == "DialogSaveBinOcafSample") + DialogSaveBinOcafSample(); + else if (theSampleName == "DialogSaveXmlOcafSample") + DialogSaveXmlOcafSample(); + else + { + myResult << "No function found: " << theSampleName; + myCode += TCollection_AsciiString("No function found: ") + theSampleName; + anIsSamplePresent = Standard_False; + } + myIsProcessed = anIsSamplePresent; +} + +Standard_Boolean OcafSamples::IsExportSample (const TCollection_AsciiString& theSampleName) +{ + if (theSampleName == "DialogSaveBinOcafSample" || theSampleName == "DialogSaveXmlOcafSample") + { + return Standard_True; + } + else + { + return Standard_False; + } +} + +Standard_Boolean OcafSamples::IsImportSample (const TCollection_AsciiString& theSampleName) +{ + if (theSampleName == "DialogOpenOcafSample") + { + return Standard_True; + } + else + { + return Standard_False; + } +} + +Standard_Boolean OcafSamples::IsBinarySample (const TCollection_AsciiString& theSampleName) +{ + if (theSampleName == "DialogOpenOcafSample" || theSampleName == "DialogSaveBinOcafSample") + { + return Standard_True; + } + else + { + return Standard_False; + } +} + +Standard_Boolean OcafSamples::IsXmlSample (const TCollection_AsciiString& theSampleName) +{ + if (theSampleName == "DialogOpenOcafSample" || theSampleName == "DialogSaveXmlOcafSample") + { + return Standard_True; + } + else + { + return Standard_False; + } +} + +void OcafSamples::CreateOcafDocument() +{ + Handle(TOcaf_Application) anOcaf_Application = new TOcaf_Application; + anOcaf_Application->NewDocument("BinOcaf", myOcafDoc); + TPrsStd_AISViewer::New(myOcafDoc->Main(), myViewer); + + Handle(AIS_InteractiveContext) anAisContext; + TPrsStd_AISViewer::Find(myOcafDoc->Main(), anAisContext); + anAisContext->SetDisplayMode(AIS_Shaded, Standard_True); + myContext = anAisContext; + + // Set the maximum number of available "undo" actions + myOcafDoc->SetUndoLimit(10); +} + +void OcafSamples::CreateBoxOcafSample() +{ + // Open a new command (for undo) + myOcafDoc->NewCommand(); + + // A data structure for our box: + // the box itself is attached to the BoxLabel label (as his name and his function attribute) + // its arguments (dimensions: width, length and height; and position: x, y, z) + // are attached to the child labels of the box: + // 0:1 Box Label ---> Name ---> Named shape ---> Function + // 0:1:1 -- Width Label + // 0:1:2 -- Length Label + // 0:1:3 -- Height Label + // 0:1:4 -- X Label + // 0:1:5 -- Y Label + // 0:1:6 -- Z Label + + // Create a new label in the data structure for the box + TDF_Label aLabel = TDF_TagSource::NewChild(myOcafDoc->Main()); + + Standard_Real aBoxWidth(30.0), aBoxLength(20.0), aBoxHeight(10.0); + Standard_Real aBoxX(0.0), aBoxY(0.0), aBoxZ(0.0); + Standard_CString aBoxName("OcafBox"); + // Create the data structure : Set the dimensions, position and name attributes + TDataStd_Real::Set(aLabel.FindChild(1), aBoxWidth); + TDataStd_Real::Set(aLabel.FindChild(2), aBoxLength); + TDataStd_Real::Set(aLabel.FindChild(3), aBoxHeight); + TDataStd_Real::Set(aLabel.FindChild(4), aBoxX); + TDataStd_Real::Set(aLabel.FindChild(5), aBoxY); + TDataStd_Real::Set(aLabel.FindChild(6), aBoxZ); + TDataStd_Name::Set(aLabel, aBoxName); // Name + + // Instantiate a TFunction_Function attribute connected to the current box driver + // and attach it to the data structure as an attribute of the Box Label + Handle(TFunction_Function) myFunction = TFunction_Function::Set(aLabel, TOcafFunction_BoxDriver::GetID()); + + // Initialize and execute the box driver (look at the "Execute()" code) + Handle(TFunction_Logbook) aLogBook = TFunction_Logbook::Set(aLabel); + + Handle(TFunction_Driver) myBoxDriver; + // Find the TOcafFunction_BoxDriver in the TFunction_DriverTable using its GUID + if (!TFunction_DriverTable::Get()->FindDriver(TOcafFunction_BoxDriver::GetID(), myBoxDriver)) + { + myResult << "Ocaf Box driver not found" << std::endl; + } + + myBoxDriver->Init(aLabel); + if (myBoxDriver->Execute(aLogBook)) + { + myResult << "Create Box function execute failed" << std::endl; + } + + // Get the TPrsStd_AISPresentation of the new box TNaming_NamedShape + Handle(TPrsStd_AISPresentation) anAisPresentation = TPrsStd_AISPresentation::Set(aLabel, TNaming_NamedShape::GetID()); + // Display it + anAisPresentation->Display(1); + // Attach an integer attribute to aLabel to memorize it's displayed + TDataStd_Integer::Set(aLabel, 1); + myContext->UpdateCurrentViewer(); + + // Close the command (for undo) + myOcafDoc->CommitCommand(); + + myResult << "Created a box with name: " << aBoxName << std::endl; + myResult << "base coord X: " << aBoxX << " Y: " << aBoxY << " Z: " << aBoxZ << std::endl; + myResult << "width: " << aBoxWidth << " length: " << aBoxLength << " height: " << aBoxHeight << std::endl; +} + +void OcafSamples::CreateCylinderOcafSample() +{ + // Open a new command (for undo) + myOcafDoc->NewCommand(); + + // A data structure for our cylinder: + // the cylinder itself is attached to the CylinderLabel label (as his name and his function attribute) + // its arguments (dimensions: radius and height; and position: x, y, z) + // are attached to the child labels of the cylinder: + // 0:1 Cylinder Label ---> Name ---> Named shape ---> Function + // 0:1:1 -- Radius Label + // 0:1:2 -- Height Label + // 0:1:3 -- X Label + // 0:1:4 -- Y Label + // 0:1:5 -- Z Label + + // Create a new label in the data structure for the cylinder + TDF_Label aLabel = TDF_TagSource::NewChild(myOcafDoc->Main()); + + Standard_Real aCylRadius(10.0), aCylHeight(20.0); + Standard_Real aCylX(60.0), aCylY(40.0), aCylZ(0.0); + Standard_CString aCylName("OcafCylinder"); + // Create the data structure : Set the dimensions, position and name attributes + TDataStd_Real::Set(aLabel.FindChild(1), aCylRadius); + TDataStd_Real::Set(aLabel.FindChild(2), aCylHeight); + TDataStd_Real::Set(aLabel.FindChild(3), aCylX); + TDataStd_Real::Set(aLabel.FindChild(4), aCylY); + TDataStd_Real::Set(aLabel.FindChild(5), aCylZ); + TDataStd_Name::Set(aLabel, aCylName); + + // Instantiate a TFunction_Function attribute connected to the current cylinder driver + // and attach it to the data structure as an attribute of the Cylinder Label + Handle(TFunction_Function) myFunction = TFunction_Function::Set(aLabel, TOcafFunction_CylDriver::GetID()); + + // Initialize and execute the cylinder driver (look at the "Execute()" code) + Handle(TFunction_Logbook) aLogBook = TFunction_Logbook::Set(aLabel); + + Handle(TFunction_Driver) myCylDriver; + // Find the TOcafFunction_CylDriver in the TFunction_DriverTable using its GUID + if (!TFunction_DriverTable::Get()->FindDriver(TOcafFunction_CylDriver::GetID(), myCylDriver)) + { + myResult << "Ocaf Cylinder driver not found"; + } + myCylDriver->Init(aLabel); + if (myCylDriver->Execute(aLogBook)) + { + myResult << "Create Cylinder function execute failed"; + } + // Get the TPrsStd_AISPresentation of the new box TNaming_NamedShape + Handle(TPrsStd_AISPresentation) anAisPresentation = TPrsStd_AISPresentation::Set(aLabel, TNaming_NamedShape::GetID()); + // Display it + anAisPresentation->Display(1); + // Attach an integer attribute to aLabel to memorize it's displayed + TDataStd_Integer::Set(aLabel, 1); + myContext->UpdateCurrentViewer(); + + // Close the command (for undo) + myOcafDoc->CommitCommand(); + + myResult << "Created a cylinder with name: " << aCylName << std::endl; + myResult << "radius: " << aCylRadius << " height: " << aCylHeight << std::endl; + myResult << "base coord X: " << aCylX << " Y: " << aCylY << " Z: " << aCylZ << std::endl; +} + +void OcafSamples::ModifyBoxOcafSample() +{ + AIS_ListOfInteractive anAisObjectsList; + myContext->DisplayedObjects(anAisObjectsList); + Standard_Integer aBoxCount(0); + for (Handle(AIS_InteractiveObject) anAisObject : anAisObjectsList) + { + // Get the main label of the selected object + Handle(TPrsStd_AISPresentation) anAisPresentation = Handle(TPrsStd_AISPresentation)::DownCast(anAisObject->GetOwner()); + TDF_Label aLabel = anAisPresentation->Label(); + + // Get the TFunction_Function attribute of the selected object + Handle(TFunction_Function) aFunction; + if (!aLabel.FindAttribute(TFunction_Function::GetID(), aFunction)) + { + myResult << "Object cannot be modify."; + return; + } + // Get the Standard_GUID of the TFunction_FunctionDriver of the selected object TFunction_Function attribute + Standard_GUID aDriverID = aFunction->GetDriverGUID(); + + // Case of a box created with the box function driver + if (aDriverID == TOcafFunction_BoxDriver::GetID()) + { + aBoxCount++; + Standard_Real aBoxX, aBoxY, aBoxZ, aBoxWidth, aBoxLength, aBoxHeight; + + // Get the attributes values of the current box + Handle(TDataStd_Real) aCurrentReal; + aLabel.FindChild(1).FindAttribute(TDataStd_Real::GetID(), aCurrentReal); + aBoxWidth = aCurrentReal->Get(); + aLabel.FindChild(2).FindAttribute(TDataStd_Real::GetID(), aCurrentReal); + aBoxLength = aCurrentReal->Get(); + aLabel.FindChild(3).FindAttribute(TDataStd_Real::GetID(), aCurrentReal); + aBoxHeight = aCurrentReal->Get(); + aLabel.FindChild(4).FindAttribute(TDataStd_Real::GetID(), aCurrentReal); + aBoxX = aCurrentReal->Get(); + aLabel.FindChild(5).FindAttribute(TDataStd_Real::GetID(), aCurrentReal); + aBoxY = aCurrentReal->Get(); + aLabel.FindChild(6).FindAttribute(TDataStd_Real::GetID(), aCurrentReal); + aBoxZ = aCurrentReal->Get(); + Handle(TDataStd_Name) aBoxName; + aLabel.FindAttribute(TDataStd_Name::GetID(), aBoxName); + + myResult << "Current parameters of box with name: " << aBoxName->Get() << std::endl; + myResult << "width: " << aBoxWidth << " length: " << aBoxLength << " height: " << aBoxHeight << std::endl; + myResult << "base coord X: " << aBoxX << " Y: " << aBoxY << " Z: " << aBoxZ << std::endl; + + // Open a new command (for undo) + myOcafDoc->NewCommand(); + // Modify the box - 1.5 times increase + aBoxWidth *= 1.5; aBoxLength *= 1.5; aBoxHeight *= 1.5; + + TDataStd_Real::Set(aLabel.FindChild(1), aBoxWidth); + TDataStd_Real::Set(aLabel.FindChild(2), aBoxLength); + TDataStd_Real::Set(aLabel.FindChild(3), aBoxHeight); + TDataStd_Real::Set(aLabel.FindChild(4), aBoxX); + TDataStd_Real::Set(aLabel.FindChild(5), aBoxY); + TDataStd_Real::Set(aLabel.FindChild(6), aBoxZ); + + // Get the TFunction_FunctionDriver GUID used with the TFunction_Function + aDriverID = aFunction->GetDriverGUID(); + Handle(TFunction_Logbook) aLogBook = TFunction_Logbook::Set(aLabel); + Handle(TFunction_Driver) aBoxDriver; + // Find the TOcafFunction_BoxDriver in the TFunction_DriverTable using its GUID + TFunction_DriverTable::Get()->FindDriver(aDriverID, aBoxDriver); + // Execute the cut if it must be (if an attribute changes) + aBoxDriver->Init(aLabel); + + // Set the box touched, it will be useful to recompute an object which used this box as attribute + aLogBook->SetTouched(aLabel); + if (aBoxDriver->Execute(aLogBook)) + { + myResult << "Recompute failed" << std::endl; + } + + // Get the presentation of the box, display it and set it selected + anAisPresentation = TPrsStd_AISPresentation::Set(aLabel, TNaming_NamedShape::GetID()); + TDataStd_Integer::Set(aLabel, 1); + anAisPresentation->Display(1); + myContext->UpdateCurrentViewer(); + // Close the command (for undo) + myOcafDoc->CommitCommand(); + + myResult << std::endl; + myResult << "New box parameters: " << std::endl; + myResult << "base coord X: " << aBoxX << " Y: " << aBoxY << " Z: " << aBoxZ << std::endl; + myResult << "width: " << aBoxWidth << " length: " << aBoxLength << " height: " << aBoxHeight << std::endl; + } + } + if (aBoxCount) + { + myResult << "Number of modified boxes: " << aBoxCount << std::endl; + } + else + { + myResult << "No boxes to modify" << std::endl; + } +} + +void OcafSamples::ModifyCylinderOcafSample() +{ + AIS_ListOfInteractive anAisObjectsList; + myContext->DisplayedObjects(anAisObjectsList); + Standard_Integer aCylCount(0); + for (Handle(AIS_InteractiveObject) anAisObject : anAisObjectsList) + { + // Get the main label of the selected object + Handle(TPrsStd_AISPresentation) anAisPresentation = Handle(TPrsStd_AISPresentation)::DownCast(anAisObject->GetOwner()); + TDF_Label aLabel = anAisPresentation->Label(); + + // Get the TFunction_Function attribute of the selected object + Handle(TFunction_Function) aFunction; + if (!aLabel.FindAttribute(TFunction_Function::GetID(), aFunction)) + { + myResult << "Object cannot be modify."; + return; + } + // Get the Standard_GUID of the TFunction_FunctionDriver of the selected object TFunction_Function attribute + Standard_GUID aDriverID = aFunction->GetDriverGUID(); + + // Case of a box created with the box function driver + if (aDriverID == TOcafFunction_CylDriver::GetID()) + { + aCylCount++; + Standard_Real aCylRadius, aCylHeight, aCylX, aCylY, aCylZ; + + // Get the attributes values of the current box + Handle(TDataStd_Real) aCurrentReal; + aLabel.FindChild(1).FindAttribute(TDataStd_Real::GetID(), aCurrentReal); + aCylRadius = aCurrentReal->Get(); + aLabel.FindChild(2).FindAttribute(TDataStd_Real::GetID(), aCurrentReal); + aCylHeight = aCurrentReal->Get(); + aLabel.FindChild(3).FindAttribute(TDataStd_Real::GetID(), aCurrentReal); + aCylX = aCurrentReal->Get(); + aLabel.FindChild(4).FindAttribute(TDataStd_Real::GetID(), aCurrentReal); + aCylY = aCurrentReal->Get(); + aLabel.FindChild(5).FindAttribute(TDataStd_Real::GetID(), aCurrentReal); + aCylZ = aCurrentReal->Get(); + + Handle(TDataStd_Name) aCylName; + aLabel.FindAttribute(TDataStd_Name::GetID(), aCylName); + + myResult << "Current parameters of box with name: " << aCylName->Get() << std::endl; + myResult << "radius: " << aCylRadius << " height: " << aCylHeight << std::endl; + myResult << "base coord X: " << aCylX << " Y: " << aCylY << " Z: " << aCylZ << std::endl; + + // Open a new command (for undo) + myOcafDoc->NewCommand(); + // Modify the cylinder - 2x increase + aCylRadius *= 2.0; aCylHeight *= 2.0; + // and move base point in XY plane + aCylX *= 2.0; aCylY *= 2.0; + + TDataStd_Real::Set(aLabel.FindChild(1), aCylRadius); + TDataStd_Real::Set(aLabel.FindChild(2), aCylHeight); + TDataStd_Real::Set(aLabel.FindChild(3), aCylX); + TDataStd_Real::Set(aLabel.FindChild(4), aCylY); + TDataStd_Real::Set(aLabel.FindChild(5), aCylZ); + + // Get the TFunction_FunctionDriver GUID used with the TFunction_Function + aDriverID = aFunction->GetDriverGUID(); + Handle(TFunction_Logbook) aLogBook = TFunction_Logbook::Set(aLabel); + Handle(TFunction_Driver) aCylDriver; + // Find the TOcafFunction_CylDriver in the TFunction_DriverTable using its GUID + TFunction_DriverTable::Get()->FindDriver(aDriverID, aCylDriver); + // Execute the cut if it must be (if an attribute changes) + aCylDriver->Init(aLabel); + + // Set the cylinder touched, it will be useful to recompute an object which used this box as attribute + aLogBook->SetTouched(aLabel); + if (aCylDriver->Execute(aLogBook)) + { + myResult << "Recompute failed" << std::endl; + } + // Get the presentation of the box, display it and set it selected + anAisPresentation = TPrsStd_AISPresentation::Set(aLabel, TNaming_NamedShape::GetID()); + TDataStd_Integer::Set(aLabel, 1); + anAisPresentation->Display(1); + myContext->UpdateCurrentViewer(); + // Close the command (for undo) + myOcafDoc->CommitCommand(); + + myResult << std::endl; + myResult << "New cylinder parameters: " << std::endl; + myResult << "radius: " << aCylRadius << " height: " << aCylHeight << std::endl; + myResult << "base coord X: " << aCylX << " Y: " << aCylY << " Z: " << aCylZ << std::endl; + } + } + if (aCylCount) + { + myResult << "Number of modified boxes: " << aCylCount << std::endl; + } + else + { + myResult << "No boxes to modify" << std::endl; + } +} + +void OcafSamples::UndoOcafSample() +{ + if (myOcafDoc->Undo()) + { + myOcafDoc->CommitCommand(); + myContext->UpdateCurrentViewer(); + myResult << "Undo was done successfully" << std::endl; + } + else + { + myResult << "Nothing to undo" << std::endl; + } +} + +void OcafSamples::RedoOcafSample() +{ + if (myOcafDoc->Redo()) + { + myOcafDoc->CommitCommand(); + myContext->UpdateCurrentViewer(); + myResult << "Redo was done successfully" << std::endl; + } + else + { + myResult << "Nothing to redo" << std::endl; + } +} + +void OcafSamples::DialogOpenOcafSample() +{ + Handle(TOcaf_Application) anOcaf_Application = new TOcaf_Application; + // load persistence + BinDrivers::DefineFormat(anOcaf_Application); + XmlDrivers::DefineFormat(anOcaf_Application); + // Look for already opened + if (anOcaf_Application->IsInSession(myFileName)) + { + myResult << "Document: " << myFileName << " is already in session" << std::endl; + return; + } + // Open the document in the current application + PCDM_ReaderStatus aReaderStatus = anOcaf_Application->Open(myFileName, myOcafDoc); + if (aReaderStatus == PCDM_ReaderStatus::PCDM_RS_OK) + { + // Connect the document CAF (myDoc) with the AISContext (myAISContext) + TPrsStd_AISViewer::New(myOcafDoc->Main(), myViewer); + myOcafDoc->SetUndoLimit(10); + + myContext->RemoveAll(Standard_False); + Handle(AIS_InteractiveContext) aContext; + TPrsStd_AISViewer::Find(myOcafDoc->Main(), aContext); + aContext->SetDisplayMode(AIS_Shaded, Standard_True); + myContext = aContext; + + // Display the presentations (which was not stored in the document) + DisplayPresentation(); + myResult << "Open a document" << std::endl; + } + else + { + myResult << "Error! The file wasn't opened. PCDM_ReaderStatus: " << aReaderStatus << std::endl; + } +} + +void OcafSamples::DialogSaveBinOcafSample() +{ + Handle(TOcaf_Application) anOcaf_Application = new TOcaf_Application; + BinDrivers::DefineFormat(anOcaf_Application); + myOcafDoc->ChangeStorageFormat("BinOcaf"); + // Saves the document in the current application + PCDM_StoreStatus aStoreStatus = anOcaf_Application->SaveAs(myOcafDoc, myFileName); + if (aStoreStatus == PCDM_StoreStatus::PCDM_SS_OK) + { + myResult << "The file was saved successfully" << std::endl; + } + else + { + myResult << "Error! The file wasn't saved. PCDM_StoreStatus: " << aStoreStatus << std::endl; + } +} + +void OcafSamples::DialogSaveXmlOcafSample() +{ + Handle(TOcaf_Application) anOcaf_Application = new TOcaf_Application; + XmlDrivers::DefineFormat(anOcaf_Application); + myOcafDoc->ChangeStorageFormat("XmlOcaf"); + // Saves the document in the current application + PCDM_StoreStatus aStoreStatus = anOcaf_Application->SaveAs(myOcafDoc, myFileName); + if (aStoreStatus == PCDM_StoreStatus::PCDM_SS_OK) + { + myResult << "The file was saved successfully" << std::endl; + } + else + { + myResult << "Error! The file wasn't saved. PCDM_StoreStatus: " << aStoreStatus << std::endl; + } +} + +void OcafSamples::DisplayPresentation() +{ + TDF_Label aRootlabel = myOcafDoc->Main(); + + for (TDF_ChildIterator it(aRootlabel); it.More(); it.Next()) + { + TDF_Label aLabel = it.Value(); + Handle(TNaming_NamedShape) aNamedShape; + if (!aLabel.FindAttribute(TNaming_NamedShape::GetID(), aNamedShape)) + { + continue; + } + Handle(TDataStd_Integer) aDataInteger; + + // To know if the object was displayed + if (aLabel.FindAttribute(TDataStd_Integer::GetID(), aDataInteger)) + { + if (!aDataInteger->Get()) + { + continue; + } + } + Handle(TPrsStd_AISPresentation) anAisPresentation; + if (!aLabel.FindAttribute(TPrsStd_AISPresentation::GetID(), anAisPresentation)) + { + anAisPresentation = TPrsStd_AISPresentation::Set(aLabel, TNaming_NamedShape::GetID()); + } + anAisPresentation->SetColor(Quantity_NOC_ORANGE); + anAisPresentation->Display(1); + } + myContext->UpdateCurrentViewer(); +} diff --git a/samples/OCCTOverview/code/OcafSamples.h b/samples/OCCTOverview/code/OcafSamples.h new file mode 100644 index 0000000000..73bf742a34 --- /dev/null +++ b/samples/OCCTOverview/code/OcafSamples.h @@ -0,0 +1,85 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef OCAFSAMPLES_H +#define OCAFSAMPLES_H + +#include "BaseSample.h" +#include "TOcaf_Application.h" + +#include +#include +#include + +//! Implements OCAF samples +class OcafSamples : public BaseSample +{ + DEFINE_STANDARD_RTTI_INLINE(OcafSamples, BaseSample) +public: + + OcafSamples (const TCollection_AsciiString& theSampleSourcePath, + const Handle(V3d_Viewer)& theViewer, + const Handle(AIS_InteractiveContext)& theContext) + : BaseSample (theSampleSourcePath, theContext), + myViewer (theViewer) + { + // + } + + enum ExchangeType { None, Binary, Xml }; + + virtual void Process (const TCollection_AsciiString& theSampleName) Standard_OVERRIDE; + + void ClearExtra(); + void SetFileName (const TCollection_AsciiString& theFileName) { myFileName = theFileName; }; + + static Standard_Boolean IsExportSample (const TCollection_AsciiString& theSampleName); + static Standard_Boolean IsImportSample (const TCollection_AsciiString& theSampleName); + static Standard_Boolean IsBinarySample (const TCollection_AsciiString& theSampleName); + static Standard_Boolean IsXmlSample (const TCollection_AsciiString& theSampleName); + +protected: + virtual void ExecuteSample (const TCollection_AsciiString& theSampleName) Standard_OVERRIDE; + +private: + // One function for every sample + void CreateOcafDocument(); + void CreateBoxOcafSample(); + void CreateCylinderOcafSample(); + void ModifyBoxOcafSample(); + void ModifyCylinderOcafSample(); + void UndoOcafSample(); + void RedoOcafSample(); + void DialogOpenOcafSample(); + void DialogSaveBinOcafSample(); + void DialogSaveXmlOcafSample(); + void DisplayPresentation(); + +private: + + ExchangeType myExchangeType; + TCollection_AsciiString myFileName; + Handle(V3d_Viewer) myViewer; + Handle(TDocStd_Document) myOcafDoc; + +}; + +#endif //OCAFSAMPLES_H diff --git a/samples/OCCTOverview/code/Sample2D_Face.cxx b/samples/OCCTOverview/code/Sample2D_Face.cxx new file mode 100644 index 0000000000..2e09ce0990 --- /dev/null +++ b/samples/OCCTOverview/code/Sample2D_Face.cxx @@ -0,0 +1,486 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "Sample2D_Face.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +Sample2D_Face::Sample2D_Face (const TopoDS_Shape& theFace) +: myFORWARDColor (Quantity_NOC_BLUE1), + myREVERSEDColor (Quantity_NOC_YELLOW), + myINTERNALColor (Quantity_NOC_RED1), + myEXTERNALColor (Quantity_NOC_MAGENTA1), + myWidthIndex (1), + myTypeIndex (1), + // + myshape (theFace), + myForwardNum (0), + myReversedNum (0), + myInternalNum (0), + myExternalNum (0), + // + myForwardBounds (0), + myReversedBounds (0), + myInternalBounds (0), + myExternalBounds (0) +{ + SetAutoHilight(Standard_False); + FillData(Standard_True); +} + +void Sample2D_Face::DrawMarker (const Handle(Geom2d_TrimmedCurve)& theCurve, + const Handle(Prs3d_Presentation)& thePresentation) +{ + Standard_Real aCenterParam = (theCurve->FirstParameter() + theCurve->LastParameter()) / 2; + gp_Pnt2d p; + gp_Vec2d v; + theCurve->D1(aCenterParam, p, v); + if (v.Magnitude() > gp::Resolution()) + { + gp_Vec aDir(v.X(), v.Y(), 0.); + gp_Pnt aPoint(p.X(), p.Y(), 0.); + aDir.Normalize(); + aDir.Reverse(); + gp_Dir aZ(0, 0, 1); + gp_Pnt aLeft (aPoint.Translated(aDir.Rotated(gp_Ax1(aPoint, aZ), M_PI / 6) * 5)); + gp_Pnt aRight(aPoint.Translated(aDir.Rotated(gp_Ax1(aPoint, aZ), M_PI * 11 / 6) * 5)); + + Handle(Graphic3d_ArrayOfPolylines) anArrow = new Graphic3d_ArrayOfPolylines(3); + anArrow->AddVertex(aLeft); + anArrow->AddVertex(aPoint); + anArrow->AddVertex(aRight); + + thePresentation->CurrentGroup()->AddPrimitiveArray(anArrow); + } +} + +void Sample2D_Face::FillData(Standard_Boolean isSizesRecompute) +{ + if (myshape.IsNull() || myshape.ShapeType() != TopAbs_FACE) + { + return; + } + + Standard_Real f, l; + TopoDS_Face aFace = TopoDS::Face(myshape); + + // count number of vertices and bounds in primitive arrays + if (isSizesRecompute) + { + mySeq_FORWARD.Clear(); + mySeq_REVERSED.Clear(); + mySeq_INTERNAL.Clear(); + mySeq_EXTERNAL.Clear(); + + myshape.Orientation(TopAbs_FORWARD); + for (TopExp_Explorer anEdgeIter (myshape, TopAbs_EDGE); anEdgeIter.More(); anEdgeIter.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Current()); + BRepAdaptor_Curve2d aCurveOnEdge (anEdge, aFace); + GCPnts_QuasiUniformDeflection anEdgeDistrib(aCurveOnEdge, 1.e-2); + if (!anEdgeDistrib.IsDone()) + { + continue; + } + + switch (anEdge.Orientation()) + { + case TopAbs_FORWARD: + { + myForwardNum += anEdgeDistrib.NbPoints(); + myForwardBounds++; + break; + } + case TopAbs_REVERSED: + { + myReversedNum += anEdgeDistrib.NbPoints(); + myReversedBounds++; + break; + } + case TopAbs_INTERNAL: + { + myInternalNum += anEdgeDistrib.NbPoints(); + myInternalBounds++; + break; + } + case TopAbs_EXTERNAL: + { + myExternalNum += anEdgeDistrib.NbPoints(); + myExternalBounds++; + break; + } + } + } + } + + myForwardArray = new Graphic3d_ArrayOfPolylines(myForwardNum, myForwardBounds); + myReversedArray = new Graphic3d_ArrayOfPolylines(myReversedNum, myReversedBounds); + myInternalArray = new Graphic3d_ArrayOfPolylines(myInternalNum, myInternalBounds); + myExternalArray = new Graphic3d_ArrayOfPolylines(myExternalNum, myExternalBounds); + + // fill primitive arrays + for (TopExp_Explorer anEdgeIter (myshape, TopAbs_EDGE); anEdgeIter.More(); anEdgeIter.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Current()); + const Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface (anEdge, aFace, f, l); + Handle(Geom2d_TrimmedCurve) aTrimmedCurve = new Geom2d_TrimmedCurve(aCurve, f, l); + if (!aTrimmedCurve.IsNull()) + { + Handle(Geom_Curve) aCurve3d = GeomLib::To3d(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aTrimmedCurve); + BRepAdaptor_Curve2d aCurveOnEdge (anEdge, aFace); + GCPnts_QuasiUniformDeflection anEdgeDistrib (aCurveOnEdge, 1.e-2); + if (!anEdgeDistrib.IsDone()) + { + continue; + } + + switch (anEdge.Orientation()) + { + case TopAbs_FORWARD: + { + myForwardArray->AddBound(anEdgeDistrib.NbPoints()); + for (Standard_Integer i = 1; i <= anEdgeDistrib.NbPoints(); ++i) + { + myForwardArray->AddVertex(anEdgeDistrib.Value(i)); + } + if (isSizesRecompute) + { + mySeq_FORWARD.Append(aCurve3d); + } + break; + } + case TopAbs_REVERSED: + { + myReversedArray->AddBound(anEdgeDistrib.NbPoints()); + for (Standard_Integer i = 1; i <= anEdgeDistrib.NbPoints(); ++i) + { + myReversedArray->AddVertex(anEdgeDistrib.Value(i)); + } + if (isSizesRecompute) + { + mySeq_REVERSED.Append(aCurve3d); + } + break; + } + case TopAbs_INTERNAL: + { + myInternalArray->AddBound(anEdgeDistrib.NbPoints()); + for (Standard_Integer i = 1; i <= anEdgeDistrib.NbPoints(); ++i) + { + myInternalArray->AddVertex(anEdgeDistrib.Value(i)); + } + if (isSizesRecompute) + { + mySeq_INTERNAL.Append(aCurve3d); + } + break; + } + case TopAbs_EXTERNAL: + { + myExternalArray->AddBound(anEdgeDistrib.NbPoints()); + for (Standard_Integer i = 1; i <= anEdgeDistrib.NbPoints(); ++i) + { + myExternalArray->AddVertex(anEdgeDistrib.Value(i)); + } + if (isSizesRecompute) + { + mySeq_EXTERNAL.Append(aCurve3d); + } + break; + } + } + } + } +} + +void Sample2D_Face::Compute (const Handle(PrsMgr_PresentationManager3d)& , + const Handle(Prs3d_Presentation)& thePresentation, + const Standard_Integer theMode) +{ + if (theMode != 0) + { + return; + } + + thePresentation->Clear(); + myDrawer->SetWireDraw(1); + + if (myshape.IsNull() || myshape.ShapeType() != TopAbs_FACE) + { + return; + } + + Handle(Graphic3d_AspectLine3d) aLineAspect_FORWARD = new Graphic3d_AspectLine3d(myFORWARDColor, Aspect_TOL_SOLID, 1); + Handle(Graphic3d_AspectLine3d) aLineAspect_REVERSED = new Graphic3d_AspectLine3d(myREVERSEDColor, Aspect_TOL_SOLID, 1); + Handle(Graphic3d_AspectLine3d) aLineAspect_INTERNAL = new Graphic3d_AspectLine3d(myINTERNALColor, Aspect_TOL_SOLID, 1); + Handle(Graphic3d_AspectLine3d) aLineAspect_EXTERNAL = new Graphic3d_AspectLine3d(myEXTERNALColor, Aspect_TOL_SOLID, 1); + + Standard_Real f, l; + TopoDS_Face aFace = TopoDS::Face(myshape); + // estimating number of vertices in primitive arrays + for (TopExp_Explorer anEdgeIter (myshape, TopAbs_EDGE); anEdgeIter.More(); anEdgeIter.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(anEdgeIter.Current()); + const Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface (anEdge, aFace, f, l); + + Handle(Geom2d_TrimmedCurve) aTrimmedCurve = new Geom2d_TrimmedCurve(aCurve, f, l); + // make a 3D curve from 2D trimmed curve to display it + Handle(Geom_Curve) aCurve3d = GeomLib::To3d(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aTrimmedCurve); + // make distribution of points + BRepAdaptor_Curve2d aCurveOnEdge (anEdge, aFace); + GCPnts_QuasiUniformDeflection anEdgeDistrib(aCurveOnEdge, 1.e-2); + if (anEdgeDistrib.IsDone()) + { + switch (anEdge.Orientation()) + { + case TopAbs_FORWARD: + { + thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_FORWARD); + DrawMarker(aTrimmedCurve, thePresentation); + break; + } + case TopAbs_REVERSED: + { + thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_REVERSED); + DrawMarker(aTrimmedCurve, thePresentation); + break; + } + case TopAbs_INTERNAL: + { + thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_INTERNAL); + DrawMarker(aTrimmedCurve, thePresentation); + + mySeq_INTERNAL.Append(aCurve3d); + break; + } + case TopAbs_EXTERNAL: + { + thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_EXTERNAL); + DrawMarker(aTrimmedCurve, thePresentation); + break; + } + } + } + } + + // add all primitives to the presentation + thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_FORWARD); + thePresentation->CurrentGroup()->AddPrimitiveArray(myForwardArray); + + thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_REVERSED); + thePresentation->CurrentGroup()->AddPrimitiveArray(myReversedArray); + + thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_INTERNAL); + thePresentation->CurrentGroup()->AddPrimitiveArray(myInternalArray); + + thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_EXTERNAL); + thePresentation->CurrentGroup()->AddPrimitiveArray(myExternalArray); +} + +void Sample2D_Face::HilightSelected (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr, + const SelectMgr_SequenceOfOwner& theOwners) +{ + Handle(Prs3d_Presentation) aSelectionPrs = GetSelectPresentation (thePrsMgr); + + Handle(Graphic3d_AspectLine3d) aLineAspect = new Graphic3d_AspectLine3d(Quantity_NOC_ANTIQUEWHITE, Aspect_TOL_SOLID, 2); + if (HasPresentation()) + { + aSelectionPrs->SetTransformPersistence(Presentation()->TransformPersistence()); + } + + const Standard_Integer aLength = theOwners.Length(); + aSelectionPrs->Clear(); + FillData(); + + Handle(Graphic3d_Group) aSelectGroup = aSelectionPrs->NewGroup(); + + for (Standard_Integer i = 1; i <= aLength; ++i) + { + Handle(SelectMgr_EntityOwner) anOwner = theOwners.Value(i); + // check priority of owner to add primitives in one of array + // containing primitives with certain type of orientation + switch (anOwner->Priority()) + { + case 7: + { + // add to objects with forward orientation + aSelectGroup->SetGroupPrimitivesAspect(aLineAspect); + aSelectGroup->AddPrimitiveArray(myForwardArray); + break; + } + case 6: + { + // add to objects with reversed orientation + aSelectGroup->SetGroupPrimitivesAspect(aLineAspect); + aSelectGroup->AddPrimitiveArray(myReversedArray); + break; + } + case 5: + { + // add to objects with internal orientation + aSelectGroup->SetGroupPrimitivesAspect(aLineAspect); + aSelectGroup->AddPrimitiveArray(myInternalArray); + break; + } + case 4: + { + // add to objects with external orientation + aSelectGroup->SetGroupPrimitivesAspect(aLineAspect); + aSelectGroup->AddPrimitiveArray(myExternalArray); + break; + } + } + } + aSelectionPrs->Display(); +} + +void Sample2D_Face::ClearSelected() +{ + if (Handle(Prs3d_Presentation) aSelectionPrs = GetSelectPresentation(NULL)) + { + aSelectionPrs->Clear(); + } +} + +void Sample2D_Face::HilightOwnerWithColor (const Handle(PrsMgr_PresentationManager3d)& thePM, + const Handle(Prs3d_Drawer)& theStyle, + const Handle(SelectMgr_EntityOwner)& theOwner) +{ + Handle(Prs3d_Presentation) aHighlightPrs = GetHilightPresentation(thePM); + if (HasPresentation()) + { + aHighlightPrs->SetTransformPersistence(Presentation()->TransformPersistence()); + } + if (theOwner.IsNull()) + { + return; + } + + aHighlightPrs->Clear(); + FillData(); + + // Direct highlighting + aHighlightPrs->NewGroup(); + Handle(Graphic3d_Group) aHilightGroup = aHighlightPrs->CurrentGroup(); + Handle(Graphic3d_AspectLine3d) aLineAspect = new Graphic3d_AspectLine3d(theStyle->Color(), Aspect_TOL_SOLID, 2); + switch (theOwner->Priority()) + { + case 7: + { + aHilightGroup->SetGroupPrimitivesAspect(aLineAspect); + aHilightGroup->AddPrimitiveArray(myForwardArray); + break; + } + case 6: + { + aHilightGroup->SetGroupPrimitivesAspect(aLineAspect); + aHilightGroup->AddPrimitiveArray(myReversedArray); + break; + } + case 5: + { + aHilightGroup->SetGroupPrimitivesAspect(aLineAspect); + aHilightGroup->AddPrimitiveArray(myInternalArray); + break; + } + case 4: + { + aHilightGroup->SetGroupPrimitivesAspect(aLineAspect); + aHilightGroup->AddPrimitiveArray(myExternalArray); + break; + } + } + if (thePM->IsImmediateModeOn()) + { + thePM->AddToImmediateList(aHighlightPrs); + } +} + +void Sample2D_Face::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection, + const Standard_Integer theMode) +{ + if (myshape.IsNull() + || theMode != 0) + { + return; + } + + if (mySeq_FORWARD.IsEmpty() + && mySeq_REVERSED.IsEmpty() + && mySeq_INTERNAL.IsEmpty() + && mySeq_EXTERNAL.IsEmpty()) + { + return; + } + + // create entity owner for every part of the face + // set different priorities for primitives of different orientation + Handle(SelectMgr_EntityOwner) anOwner_Forward = new SelectMgr_EntityOwner(this, 7); + Handle(SelectMgr_EntityOwner) anOwner_Reversed = new SelectMgr_EntityOwner(this, 6); + Handle(SelectMgr_EntityOwner) anOwner_Internal = new SelectMgr_EntityOwner(this, 5); + Handle(SelectMgr_EntityOwner) anOwner_External = new SelectMgr_EntityOwner(this, 4); + + // create a sensitive for every part + Handle(Select3D_SensitiveGroup) aForwardGroup = new Select3D_SensitiveGroup(anOwner_Forward); + Handle(Select3D_SensitiveGroup) aReversedGroup = new Select3D_SensitiveGroup(anOwner_Reversed); + Handle(Select3D_SensitiveGroup) aInternalGroup = new Select3D_SensitiveGroup(anOwner_Internal); + Handle(Select3D_SensitiveGroup) aExternalGroup = new Select3D_SensitiveGroup(anOwner_External); + + Standard_Integer aLength = mySeq_FORWARD.Length(); + for (Standard_Integer i = 1; i <= aLength; ++i) + { + Handle(Select3D_SensitiveCurve) aSensitveCurve = new Select3D_SensitiveCurve(anOwner_Forward, mySeq_FORWARD(i)); + aForwardGroup->Add(aSensitveCurve); + } + theSelection->Add(aForwardGroup); + + aLength = mySeq_REVERSED.Length(); + for (Standard_Integer i = 1; i <= aLength; ++i) + { + Handle(Select3D_SensitiveCurve) aSensitveCurve = new Select3D_SensitiveCurve(anOwner_Reversed, mySeq_REVERSED(i)); + aReversedGroup->Add(aSensitveCurve); + } + theSelection->Add(aReversedGroup); + + aLength = mySeq_INTERNAL.Length(); + for (Standard_Integer i = 1; i <= aLength; ++i) + { + Handle(Select3D_SensitiveCurve) aSensitveCurve = new Select3D_SensitiveCurve(anOwner_Internal, mySeq_INTERNAL(i)); + aInternalGroup->Add(aSensitveCurve); + } + theSelection->Add(aInternalGroup); + + aLength = mySeq_EXTERNAL.Length(); + for (Standard_Integer i = 1; i <= aLength; ++i) + { + Handle(Select3D_SensitiveCurve) aSensitveCurve = new Select3D_SensitiveCurve(anOwner_External, mySeq_EXTERNAL(i)); + aExternalGroup->Add(aSensitveCurve); + } + theSelection->Add(aExternalGroup); +} diff --git a/samples/OCCTOverview/code/Sample2D_Face.h b/samples/OCCTOverview/code/Sample2D_Face.h new file mode 100644 index 0000000000..f88e9c2009 --- /dev/null +++ b/samples/OCCTOverview/code/Sample2D_Face.h @@ -0,0 +1,107 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef _Sample2D_Face_HeaderFile +#define _Sample2D_Face_HeaderFile + +#include +#include +#include +#include +#include + +//! AIS interactive Object for sample 2D face +class Sample2D_Face : public AIS_InteractiveObject +{ + DEFINE_STANDARD_RTTI_INLINE(Sample2D_Face, AIS_InteractiveObject) +public: + + Standard_EXPORT Sample2D_Face (const TopoDS_Shape& theFace); + +public: + + TopoDS_Shape& Shape() { return myshape; } + void SetFace (const TopoDS_Shape& theFace) { myshape = theFace; } + +public: + + Quantity_Color myFORWARDColor; + Quantity_Color myREVERSEDColor; + Quantity_Color myINTERNALColor; + Quantity_Color myEXTERNALColor; + Standard_Integer myWidthIndex; + Standard_Integer myTypeIndex; + +private: + + //! Return TRUE for supported display modes (only mode 0 is supported). + virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0; } + + //! Compute presentation. + virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr, + const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer theMode) Standard_OVERRIDE; + + //! Compute selection. + virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection, + const Standard_Integer theMode) Standard_OVERRIDE; + + virtual void ClearSelected() Standard_OVERRIDE; + + //! Method for advanced customizable selection of picked object + virtual void HilightSelected (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr, + const SelectMgr_SequenceOfOwner& theOwners) Standard_OVERRIDE; + + //! Method for advanced customizable highlighting of picked object. + virtual void HilightOwnerWithColor (const Handle(PrsMgr_PresentationManager3d)& thePM, + const Handle(Prs3d_Drawer)& theStyle, + const Handle(SelectMgr_EntityOwner)& theOwner) Standard_OVERRIDE; + + void DrawMarker (const Handle(Geom2d_TrimmedCurve)& theCurve, + const Handle(Prs3d_Presentation)& thePresentation); + + void FillData(Standard_Boolean isSizesRecomputed = Standard_False); + +private: + + TopoDS_Shape myshape; + TColGeom_SequenceOfCurve mySeq_FORWARD; + TColGeom_SequenceOfCurve mySeq_REVERSED; + TColGeom_SequenceOfCurve mySeq_INTERNAL; + TColGeom_SequenceOfCurve mySeq_EXTERNAL; + + Handle(Graphic3d_ArrayOfPolylines) myForwardArray; + Handle(Graphic3d_ArrayOfPolylines) myReversedArray; + Handle(Graphic3d_ArrayOfPolylines) myInternalArray; + Handle(Graphic3d_ArrayOfPolylines) myExternalArray; + + Standard_Integer myForwardNum; + Standard_Integer myReversedNum; + Standard_Integer myInternalNum; + Standard_Integer myExternalNum; + Standard_Integer myForwardBounds; + Standard_Integer myReversedBounds; + Standard_Integer myInternalBounds; + Standard_Integer myExternalBounds; + +}; + +#endif diff --git a/samples/OCCTOverview/code/Sample2D_Image.cxx b/samples/OCCTOverview/code/Sample2D_Image.cxx new file mode 100644 index 0000000000..3e833ee206 --- /dev/null +++ b/samples/OCCTOverview/code/Sample2D_Image.cxx @@ -0,0 +1,88 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "Sample2D_Image.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +Sample2D_Image::Sample2D_Image (const TCollection_AsciiString& theFileName, + const Standard_Real theX, + const Standard_Real theY, + const Standard_Real theScale) +: AIS_Shape (TopoDS_Shape()), + myFilename (theFileName), + myX (theX), + myY (theY), + myScale (theScale) +{ + // +} + +void Sample2D_Image::MakeShape() +{ + Standard_Real coeff = 1.0; + Handle(Image_AlienPixMap) anImage = new Image_AlienPixMap(); + if (anImage->Load (myFilename)) + { + coeff = Standard_Real(anImage->Height()) / Standard_Real(anImage->Width()) * myScale; + } + + TopoDS_Edge E1 = BRepBuilderAPI_MakeEdge (gp_Pnt(myX, myY, 0.), + gp_Pnt(100 * myScale + myX, myY, 0.)); + TopoDS_Edge E2 = BRepBuilderAPI_MakeEdge (gp_Pnt(100 * myScale + myX, myY, 0.), + gp_Pnt(100 * myScale + myX, 100 * coeff + myY, 0.)); + TopoDS_Edge E3 = BRepBuilderAPI_MakeEdge (gp_Pnt(100 * myScale + myX, 100 * coeff + myY, 0.), + gp_Pnt(myX, 100 * coeff + myY, 0.)); + TopoDS_Edge E4 = BRepBuilderAPI_MakeEdge (gp_Pnt(myX, 100 * coeff + myY, 0.), + gp_Pnt(myX, myY, 0.)); + TopoDS_Wire anImageBounds = BRepBuilderAPI_MakeWire(E1, E2, E3, E4); + myFace = BRepBuilderAPI_MakeFace(gp_Pln(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), anImageBounds); +} + +void Sample2D_Image::SetContext (const Handle(AIS_InteractiveContext)& theContext) +{ + if (theContext.IsNull() || theContext->CurrentViewer().IsNull()) + { + AIS_InteractiveObject::SetContext (theContext); + return; + } + + AIS_InteractiveObject::SetContext (theContext); + MakeShape(); + this->Set(TopoDS_Shape(myFace)); + + myDrawer->SetShadingAspect(new Prs3d_ShadingAspect()); + Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(myFilename); + aTexture->DisableModulate(); + myDrawer->ShadingAspect()->Aspect()->SetTextureMap (aTexture); + myDrawer->ShadingAspect()->Aspect()->SetTextureMapOn(); +} diff --git a/samples/OCCTOverview/code/Sample2D_Image.h b/samples/OCCTOverview/code/Sample2D_Image.h new file mode 100644 index 0000000000..c3b9a886b4 --- /dev/null +++ b/samples/OCCTOverview/code/Sample2D_Image.h @@ -0,0 +1,86 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef _Sample2D_Image_HeaderFile +#define _Sample2D_Image_HeaderFile +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//! AIS shape for sample 2D image +class Sample2D_Image : public AIS_Shape +{ + DEFINE_STANDARD_RTTI_INLINE(Sample2D_Image, AIS_Shape) +public: + + //! Constructor. + Standard_EXPORT Sample2D_Image (const TCollection_AsciiString& theFileName, + const Standard_Real theX = 0.0, + const Standard_Real theY = 0.0, + const Standard_Real theScale = 1.0); + + //! Return image coordinates. + void GetCoord (Standard_Real& theX, Standard_Real& theY) const + { + theX = myX; + theY = myY; + } + + //! Return image coordinates. + void SetCoord (const Standard_Real theX, const Standard_Real theY) + { + myX = theX; + myY = theY; + } + + //! Return image scale factor. + Standard_Real GetScale() const { return myScale; } + + //! Set image scale factor. + void SetScale(const Standard_Real theNewScale) { myScale = theNewScale; } + + //! Assign new interactive context to the object. + Standard_EXPORT virtual void SetContext (const Handle(AIS_InteractiveContext)& theContext) Standard_OVERRIDE; + +private: + + void MakeShape(); + +protected: + + TopoDS_Face myFace; + TCollection_AsciiString myFilename; + Standard_Real myX; + Standard_Real myY; + Standard_Real myScale; + +}; + +#endif diff --git a/samples/OCCTOverview/code/Sample2D_Markers.cxx b/samples/OCCTOverview/code/Sample2D_Markers.cxx new file mode 100644 index 0000000000..6b6095fecc --- /dev/null +++ b/samples/OCCTOverview/code/Sample2D_Markers.cxx @@ -0,0 +1,80 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "Sample2D_Markers.h" + +#include + +// generic marker +Sample2D_Markers::Sample2D_Markers (const Standard_Real theXPosition, + const Standard_Real theYPosition, + const Aspect_TypeOfMarker theMarkerType, + const Quantity_Color theColor, + const Standard_Real theScaleOrId) +: myArrayOfPoints (new Graphic3d_ArrayOfPoints(1)) +{ + myXPosition = theXPosition; + myYPosition = theYPosition; + myMarkerType = theMarkerType; + myColor = theColor; + myIndex = theScaleOrId; +} + +Sample2D_Markers::Sample2D_Markers (const Standard_Real theXPosition, + const Standard_Real theYPosition, + const Handle(Graphic3d_ArrayOfPoints)& theArrayOfPoints, + const Aspect_TypeOfMarker theMarkerType, + const Quantity_Color theColor, + const Standard_Real theScaleOrId) +: myArrayOfPoints (new Graphic3d_ArrayOfPoints(6)) +{ + myXPosition = theXPosition; + myYPosition = theYPosition; + myMarkerType = theMarkerType; + myColor = theColor; + myIndex = theScaleOrId; + myArrayOfPoints = theArrayOfPoints; +} + +void Sample2D_Markers::Compute (const Handle(PrsMgr_PresentationManager3d)& , + const Handle(Prs3d_Presentation)& thePrs, + const Standard_Integer theMode) +{ + if (theMode != 0) + { + return; + } + + if (myMarkerType == Aspect_TOM_USERDEFINED) + { + Handle(Graphic3d_AspectMarker3d) aMarker = new Graphic3d_AspectMarker3d(Aspect_TOM_POINT, myColor, myIndex); + thePrs->CurrentGroup()->SetGroupPrimitivesAspect(aMarker); + thePrs->CurrentGroup()->AddPrimitiveArray(myArrayOfPoints); + } + else + { + Handle(Graphic3d_AspectMarker3d) aMarker = new Graphic3d_AspectMarker3d(myMarkerType, myColor, myIndex); + thePrs->CurrentGroup()->SetPrimitivesAspect(aMarker); + Handle(Graphic3d_ArrayOfPoints) anArrayOfPoints = new Graphic3d_ArrayOfPoints(1); + anArrayOfPoints->AddVertex(myXPosition, myYPosition, 0); + thePrs->CurrentGroup()->AddPrimitiveArray(anArrayOfPoints); + } +} diff --git a/samples/OCCTOverview/code/Sample2D_Markers.h b/samples/OCCTOverview/code/Sample2D_Markers.h new file mode 100644 index 0000000000..5e77c43338 --- /dev/null +++ b/samples/OCCTOverview/code/Sample2D_Markers.h @@ -0,0 +1,88 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef _Sample2D_Markers_HeaderFile +#define _Sample2D_Markers_HeaderFile + +#include +#include + +//! AIS AIS interactive object for sample 2D marker +class Sample2D_Markers : public AIS_InteractiveObject +{ + DEFINE_STANDARD_RTTI_INLINE(Sample2D_Markers, AIS_InteractiveObject) +private: + enum Sample2D_CurrentTypeOfMarker + { + Sample2D_CTOM_Generic, + Sample2D_CTOM_Polyline, + Sample2D_CTOM_Circle, + Sample2D_CTOM_Ellips + }; + +public: + + //! Generic marker + Standard_EXPORT Sample2D_Markers (const Standard_Real theXPosition, + const Standard_Real theYPosition, + const Aspect_TypeOfMarker theMarkerType, + const Quantity_Color theColor, + const Standard_Real theScaleOrId=5.0); + + //! Polyline marker + Standard_EXPORT Sample2D_Markers (const Standard_Real theXPosition, + const Standard_Real theYPosition, + const Handle(Graphic3d_ArrayOfPoints)& theArrayOfPoints, + const Aspect_TypeOfMarker theMarkerType, + const Quantity_Color theColor, + const Standard_Real theScaleOrId=2.0); + +private: + + //! Return TRUE for supported display modes (only mode 0 is supported). + virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0; } + + //! Compute presentation. + virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& /*aPresentationManager*/, + const Handle(Prs3d_Presentation)& /*aPresentation*/, + const Standard_Integer theMode) Standard_OVERRIDE; + + //! Compute selection (not implemented). + virtual void ComputeSelection (const Handle(SelectMgr_Selection)& , + const Standard_Integer ) Standard_OVERRIDE {} + + virtual void SetContext(const Handle(AIS_InteractiveContext)& ) Standard_OVERRIDE {} + +private: + + Sample2D_CurrentTypeOfMarker myCurrentTypeOfMarker; + Standard_Real myXPosition; + Standard_Real myYPosition; + Aspect_TypeOfMarker myMarkerType; + Quantity_Color myColor; + Standard_Real myWidth; + Standard_Real myHeight; + Standard_Real myIndex; + //! specific polyline marker + Handle(Graphic3d_ArrayOfPoints) myArrayOfPoints; +}; + +#endif diff --git a/samples/OCCTOverview/code/Samples.qrc b/samples/OCCTOverview/code/Samples.qrc new file mode 100644 index 0000000000..59326e0751 --- /dev/null +++ b/samples/OCCTOverview/code/Samples.qrc @@ -0,0 +1,11 @@ + + + Geometry.json + Topology.json + Triangulation.json + DataExchange.json + Viewer3d.json + Viewer2d.json + Ocaf.json + + diff --git a/samples/OCCTOverview/code/TOcafFunction_BoxDriver.cxx b/samples/OCCTOverview/code/TOcafFunction_BoxDriver.cxx new file mode 100644 index 0000000000..6589efab1f --- /dev/null +++ b/samples/OCCTOverview/code/TOcafFunction_BoxDriver.cxx @@ -0,0 +1,148 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "TOcafFunction_BoxDriver.h" + +#include +#include +#include +#include + +//======================================================================= +//function : GetID +//purpose : +//======================================================================= +const Standard_GUID& TOcafFunction_BoxDriver::GetID() +{ + static const Standard_GUID anID("22D22E51-D69A-11d4-8F1A-0060B0EE18E8"); + return anID; +} + +//======================================================================= +//function : Validate +//purpose : +//======================================================================= +void TOcafFunction_BoxDriver::Validate(Handle(TFunction_Logbook)& log) const +{ + // We validate the object label ( Label() ), all the arguments and the results of the object: + log->SetValid(Label(), Standard_True); +} + +//======================================================================= +//function : MustExecute +//purpose : +//======================================================================= +Standard_Boolean TOcafFunction_BoxDriver::MustExecute(const Handle(TFunction_Logbook)& log) const +{ + // If the object's label is modified: + if (log->IsModified(Label())) return Standard_True; + + // Cut (in our simple case) has two arguments: The original shape, and the tool shape. + // They are on the child labels of the box's label: + // So, OriginalNShape - is attached to the first child label + // ToolNShape - is attached to the second child label. + // + // Let's check them: + if (log->IsModified(Label().FindChild(1))) + { + return Standard_True; // width. + } + if (log->IsModified(Label().FindChild(2))) + { + return Standard_True; // length, + } + if (log->IsModified(Label().FindChild(3))) + { + return Standard_True; // width. + } + if (log->IsModified(Label().FindChild(4))) + { + return Standard_True; // length, + } + if (log->IsModified(Label().FindChild(5))) + { + return Standard_True; // width. + } + if (log->IsModified(Label().FindChild(6))) + { + return Standard_True; // length, + } + // if there are no any modifications concerned the box, + // it's not necessary to recompute (to call the method Execute()): + return Standard_False; +} + +//======================================================================= +//function : Execute +//purpose : +//======================================================================= +Standard_Integer TOcafFunction_BoxDriver::Execute(Handle(TFunction_Logbook)& /*log*/) const +{ + // Get the values of dimension and position attributes + Handle(TDataStd_Real) TSR; + Standard_Real x, y, z, l, h, w; + if (!Label().FindChild(1).FindAttribute(TDataStd_Real::GetID(), TSR)) + { + return 1; + } + l = TSR->Get(); + + if (!Label().FindChild(2).FindAttribute(TDataStd_Real::GetID(), TSR)) + { + return 1; + } + h = TSR->Get(); + + if (!Label().FindChild(3).FindAttribute(TDataStd_Real::GetID(), TSR)) + { + return 1; + } + w = TSR->Get(); + + if (!Label().FindChild(4).FindAttribute(TDataStd_Real::GetID(), TSR)) + { + return 1; + } + x = TSR->Get(); + + if (!Label().FindChild(5).FindAttribute(TDataStd_Real::GetID(), TSR)) + { + return 1; + } + y = TSR->Get(); + + if (!Label().FindChild(6).FindAttribute(TDataStd_Real::GetID(), TSR)) + { + return 1; + } + z = TSR->Get(); + + // Build a box using the dimension and position attributes + BRepPrimAPI_MakeBox mkBox(gp_Pnt(x, y, z), l, h, w); + TopoDS_Shape ResultShape = mkBox.Shape(); + + // Build a TNaming_NamedShape using built box + TNaming_Builder B(Label()); + B.Generated(ResultShape); + // That's all: + // If there are no any mistakes we return 0: + return 0; +} diff --git a/samples/OCCTOverview/code/TOcafFunction_BoxDriver.h b/samples/OCCTOverview/code/TOcafFunction_BoxDriver.h new file mode 100644 index 0000000000..bbeed55506 --- /dev/null +++ b/samples/OCCTOverview/code/TOcafFunction_BoxDriver.h @@ -0,0 +1,57 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef _TOcafFunction_BoxDriver_HeaderFile +#define _TOcafFunction_BoxDriver_HeaderFile + +#include +#include + +//! Creation of an instance of the box driver. It's possible (and recommended) +//! to have only one instance of a driver for the whole session. +class TOcafFunction_BoxDriver : public TFunction_Driver +{ + DEFINE_STANDARD_RTTI_INLINE(TOcafFunction_BoxDriver, TFunction_Driver) +public: + Standard_EXPORT static const Standard_GUID& GetID(); +public: + + TOcafFunction_BoxDriver() {} + + //! Validation of the object label, its arguments and its results. + Standard_EXPORT virtual void Validate (Handle(TFunction_Logbook)& theLog) const Standard_OVERRIDE; + + //! We call this method to check if the object was modified to be invoked. + //! If the object label or an argument is modified, we must recompute the object - to call the method Execute(). + Standard_EXPORT virtual Standard_Boolean MustExecute (const Handle(TFunction_Logbook)& theLog) const Standard_OVERRIDE; + + //! We compute the object and topologically name it. + //! If during the execution we found something wrong, we return the number of the failure. + //! For example: + //! 1 - an attribute hasn't been found, + //! 2 - algorithm failed, + //! if there are no any mistakes occurred we return 0: + //! 0 - no mistakes were found. + Standard_EXPORT virtual Standard_Integer Execute (Handle(TFunction_Logbook)& theLog) const Standard_OVERRIDE; + +}; + +#endif diff --git a/samples/OCCTOverview/code/TOcafFunction_CutDriver.cxx b/samples/OCCTOverview/code/TOcafFunction_CutDriver.cxx new file mode 100644 index 0000000000..cbbaca349b --- /dev/null +++ b/samples/OCCTOverview/code/TOcafFunction_CutDriver.cxx @@ -0,0 +1,152 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "TOcafFunction_CutDriver.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +//======================================================================= +//function : GetID +//purpose : +//======================================================================= +const Standard_GUID& TOcafFunction_CutDriver::GetID() +{ + static const Standard_GUID anID("22D22E52-D69A-11d4-8F1A-0060B0EE18E8"); + return anID; +} + +//======================================================================= +//function : Validate +//purpose : +//======================================================================= +void TOcafFunction_CutDriver::Validate (Handle(TFunction_Logbook)& log) const +{ + // We validate the object label ( Label() ), all the arguments and the results of the object: + log->SetValid(Label(), Standard_True); +} + +//======================================================================= +//function : MustExecute +//purpose : +//======================================================================= +Standard_Boolean TOcafFunction_CutDriver::MustExecute(const Handle(TFunction_Logbook)& log) const +{ + // If the object's label is modified: + if (log->IsModified(Label())) return Standard_True; + + // Cut (in our simple case) has two arguments: The original shape, and the tool shape. + // They are on the child labels of the cut's label: + // So, OriginalNShape - is attached to the first child label + // ToolNShape - is attached to the second child label, + // . + // Let's check them: + Handle(TDF_Reference) OriginalRef; + //TDF_Label aLabel = Label().FindChild(1); +/* + BOOL f = Label().IsNull(); + int a = Label().NbChildren(); +*/ + TCollection_AsciiString aEntry; + TDF_Tool::Entry(Label(), aEntry); + std::cout << "Entry: " << aEntry.ToCString() << std::endl; + Label().FindChild(1).FindAttribute(TDF_Reference::GetID(), OriginalRef); + if (log->IsModified(OriginalRef->Get())) return Standard_True; // Original shape. + + Handle(TDF_Reference) ToolRef; + Label().FindChild(2).FindAttribute(TDF_Reference::GetID(), ToolRef); + if (log->IsModified(ToolRef->Get())) return Standard_True; // Tool shape. + + // if there are no any modifications concerned the cut, + // it's not necessary to recompute (to call the method Execute()): + return Standard_False; +} + +//======================================================================= +//function : Execute +//purpose : +//======================================================================= +Standard_Integer TOcafFunction_CutDriver::Execute(Handle(TFunction_Logbook)& /*log*/) const +{ + // Let's get the arguments (OriginalNShape, ToolNShape of the object): + + // First, we have to retrieve the TDF_Reference attributes to obtain + // the root labels of the OriginalNShape and the ToolNShape: + Handle(TDF_Reference) OriginalRef, ToolRef; + if (!Label().FindChild(1).FindAttribute(TDF_Reference::GetID(), OriginalRef)) + { + return 1; + } + TDF_Label OriginalLab = OriginalRef->Get(); + if (!Label().FindChild(2).FindAttribute(TDF_Reference::GetID(), ToolRef)) + { + return 1; + } + TDF_Label ToolLab = ToolRef->Get(); + + // Get the TNaming_NamedShape attributes of these labels + Handle(TNaming_NamedShape) OriginalNShape, ToolNShape; + if (!(OriginalLab.FindAttribute(TNaming_NamedShape::GetID(), OriginalNShape))) + { + throw Standard_Failure("TOcaf_Commands::CutObjects"); + } + if (!(ToolLab.FindAttribute(TNaming_NamedShape::GetID(), ToolNShape))) + { + throw Standard_Failure("TOcaf_Commands::CutObjects"); + } + + // Now, let's get the TopoDS_Shape of these TNaming_NamedShape: + TopoDS_Shape OriginalShape = OriginalNShape->Get(); + TopoDS_Shape ToolShape = ToolNShape->Get(); + + // STEP 2: + // Let's call for algorithm computing a cut operation: + BRepAlgoAPI_Cut mkCut(OriginalShape, ToolShape); + // Let's check if the Cut has been successful: + if (!mkCut.IsDone()) + { + QMessageBox::critical(qApp->activeWindow(), + QObject::tr("Cut Function Driver"), + QObject::tr("Cut not done.")); + return 2; + } + TopoDS_Shape ResultShape = mkCut.Shape(); + + // Build a TNaming_NamedShape using built cut + TNaming_Builder B(Label()); + B.Modify(OriginalShape, ResultShape); + // That's all: + // If there are no any mistakes we return 0: + return 0; +} diff --git a/samples/OCCTOverview/code/TOcafFunction_CutDriver.h b/samples/OCCTOverview/code/TOcafFunction_CutDriver.h new file mode 100644 index 0000000000..9b25cecf95 --- /dev/null +++ b/samples/OCCTOverview/code/TOcafFunction_CutDriver.h @@ -0,0 +1,57 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef _TOcafFunction_CutDriver_HeaderFile +#define _TOcafFunction_CutDriver_HeaderFile + +#include +#include + +//! Creation of an instance of the cut driver. It's possible (and recommended) +//! to have only one instance of a driver for the whole session. +class TOcafFunction_CutDriver : public TFunction_Driver +{ + DEFINE_STANDARD_RTTI_INLINE(TOcafFunction_CutDriver, TFunction_Driver) +public: + Standard_EXPORT static const Standard_GUID& GetID(); +public: + + TOcafFunction_CutDriver() {} + + //! Validation of the object label, its arguments and its results. + Standard_EXPORT virtual void Validate (Handle(TFunction_Logbook)& theLog) const Standard_OVERRIDE; + + //! We call this method to check if the object was modified to be invoked. + //! If the object label or an argument is modified, we must recompute the object - to call the method Execute(). + Standard_EXPORT virtual Standard_Boolean MustExecute (const Handle(TFunction_Logbook)& theLog) const Standard_OVERRIDE; + + //! We compute the object and topologically name it. + //! If during the execution we found something wrong, we return the number of the failure. + //! For example: + //! 1 - an attribute hasn't been found, + //! 2 - algorithm failed, + //! if there are no any mistakes occurred we return 0: + //! 0 - no mistakes were found. + Standard_EXPORT virtual Standard_Integer Execute (Handle(TFunction_Logbook)& theLog) const Standard_OVERRIDE; + +}; + +#endif diff --git a/samples/OCCTOverview/code/TOcafFunction_CylDriver.cxx b/samples/OCCTOverview/code/TOcafFunction_CylDriver.cxx new file mode 100644 index 0000000000..3b687e5172 --- /dev/null +++ b/samples/OCCTOverview/code/TOcafFunction_CylDriver.cxx @@ -0,0 +1,147 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "TOcafFunction_CylDriver.h" + +#include +#include +#include +#include +#include +#include + +//======================================================================= +//function : GetID +//purpose : +//======================================================================= +const Standard_GUID& TOcafFunction_CylDriver::GetID() +{ + static const Standard_GUID anID("22D22E53-D69A-11d4-8F1A-0060B0EE18E8"); + return anID; +} + +//======================================================================= +//function : TPartStd_CylDriver +//purpose : +//======================================================================= +TOcafFunction_CylDriver::TOcafFunction_CylDriver() +{ + // +} + +//======================================================================= +//function : Validate +//purpose : +//======================================================================= +void TOcafFunction_CylDriver::Validate (Handle(TFunction_Logbook)& log) const +{ + // We validate the object label ( Label() ), all the arguments and the results of the object: + log->SetValid(Label(), Standard_True); +} + +//======================================================================= +//function : MustExecute +//purpose : +//======================================================================= +Standard_Boolean TOcafFunction_CylDriver::MustExecute(const Handle(TFunction_Logbook)& log) const +{ + // If the object's label is modified: + if (log->IsModified(Label())) return Standard_True; + + // Cylinder (in our simple case) has 5 arguments: + // + // Let's check them: + if (log->IsModified(Label().FindChild(1))) + { + return Standard_True; // radius. + } + if (log->IsModified(Label().FindChild(2))) + { + return Standard_True; // height, + } + if (log->IsModified(Label().FindChild(3))) + { + return Standard_True; // x. + } + if (log->IsModified(Label().FindChild(4))) + { + return Standard_True; // y, + } + if (log->IsModified(Label().FindChild(5))) + { + return Standard_True; // z. + } + // if there are no any modifications concerned the Cyl, + // it's not necessary to recompute (to call the method Execute()): + return Standard_False; +} + +//======================================================================= +//function : Execute +//purpose : +//======================================================================= +Standard_Integer TOcafFunction_CylDriver::Execute(Handle(TFunction_Logbook)& /*log*/) const +{ + // Get the values of dimension and position attributes + Handle(TDataStd_Real) TSR; + Standard_Real x, y, z, r, h; + if (!Label().FindChild(1).FindAttribute(TDataStd_Real::GetID(), TSR)) + { + return 1; + } + r = TSR->Get(); + + if (!Label().FindChild(2).FindAttribute(TDataStd_Real::GetID(), TSR)) + { + return 1; + } + h = TSR->Get(); + + if (!Label().FindChild(3).FindAttribute(TDataStd_Real::GetID(), TSR)) + { + return 1; + } + x = TSR->Get(); + + if (!Label().FindChild(4).FindAttribute(TDataStd_Real::GetID(), TSR)) + { + return 1; + } + y = TSR->Get(); + + if (!Label().FindChild(5).FindAttribute(TDataStd_Real::GetID(), TSR)) + { + return 1; + } + z = TSR->Get(); + + // Build a Cyl using the dimension and position attributes + BRepPrimAPI_MakeCylinder mkCyl(gp_Ax2(gp_Pnt(x, y, z), gp_Dir(0, 0, 1)), r, h); + TopoDS_Shape ResultShape = mkCyl.Shape(); + + + // Build a TNaming_NamedShape using built Cyl + TNaming_Builder B(Label()); + B.Generated(ResultShape); + // That's all: + // If there are no any mistakes we return 0: + return 0; +} diff --git a/samples/OCCTOverview/code/TOcafFunction_CylDriver.h b/samples/OCCTOverview/code/TOcafFunction_CylDriver.h new file mode 100644 index 0000000000..e6d2534b71 --- /dev/null +++ b/samples/OCCTOverview/code/TOcafFunction_CylDriver.h @@ -0,0 +1,59 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef _TOcafFunction_CylDriver_HeaderFile +#define _TOcafFunction_CylDriver_HeaderFile + +#include +#include + +//! Creation of an instance of the cylinder driver. It's possible (and recommended) +//! to have only one instance of a driver for the whole session. +class TOcafFunction_CylDriver : public TFunction_Driver +{ + DEFINE_STANDARD_RTTI_INLINE(TOcafFunction_CylDriver, TFunction_Driver) +public: + Standard_EXPORT static const Standard_GUID& GetID(); +public: + + //! Creation of an instance of the driver. It's possible (and recommended) + //! to have only one instance of a driver for the whole session. + Standard_EXPORT TOcafFunction_CylDriver(); + + //! Validation of the object label, its arguments and its results. + Standard_EXPORT virtual void Validate (Handle(TFunction_Logbook)& theLog) const Standard_OVERRIDE; + + //! We call this method to check if the object was modified to be invoked. + //! If the object label or an argument is modified, we must recompute the object - to call the method Execute(). + Standard_EXPORT virtual Standard_Boolean MustExecute (const Handle(TFunction_Logbook)& theLog) const Standard_OVERRIDE; + + //! We compute the object and topologically name it. + //! If during the execution we found something wrong, + //! we return the number of the failure. For example: + //! 1 - an attribute hasn't been found, + //! 2 - algorithm failed, + //! if there are no any mistakes occurred we return 0: + //! 0 - no mistakes were found. + Standard_EXPORT virtual Standard_Integer Execute (Handle(TFunction_Logbook)& theLog) const Standard_OVERRIDE; + +}; + +#endif diff --git a/samples/OCCTOverview/code/TOcaf_Application.cxx b/samples/OCCTOverview/code/TOcaf_Application.cxx new file mode 100644 index 0000000000..ceea5843f0 --- /dev/null +++ b/samples/OCCTOverview/code/TOcaf_Application.cxx @@ -0,0 +1,52 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "TOcaf_Application.h" + +#include +#include +#include +#include +#include + +#include "TOcafFunction_BoxDriver.h" +#include "TOcafFunction_CylDriver.h" +#include "TOcafFunction_CutDriver.h" + +//======================================================================= +//function : TOcaf_Application +//purpose : +//======================================================================= +TOcaf_Application::TOcaf_Application() +{ + // Instantiate a TOcafFunction_BoxDriver and add it to the TFunction_DriverTable + TFunction_DriverTable::Get()->AddDriver (TOcafFunction_BoxDriver::GetID(), + new TOcafFunction_BoxDriver()); + + // Instantiate a TOcafFunction_Cyl Driver and add it to the TFunction_DriverTable + TFunction_DriverTable::Get()->AddDriver (TOcafFunction_CylDriver::GetID(), + new TOcafFunction_CylDriver()); + + // Instantiate a TOcafFunction_CutDriver and add it to the TFunction_DriverTable + Handle(TOcafFunction_CutDriver) myCutDriver = new TOcafFunction_CutDriver(); + TFunction_DriverTable::Get()->AddDriver (TOcafFunction_CutDriver::GetID(), + new TOcafFunction_CutDriver()); +} diff --git a/samples/OCCTOverview/code/TOcaf_Application.h b/samples/OCCTOverview/code/TOcaf_Application.h new file mode 100644 index 0000000000..bcaaf03a06 --- /dev/null +++ b/samples/OCCTOverview/code/TOcaf_Application.h @@ -0,0 +1,37 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef _TOcaf_Application_HeaderFile +#define _TOcaf_Application_HeaderFile + +#include +#include + +//! Sample OCAF application +class TOcaf_Application : public TDocStd_Application +{ + DEFINE_STANDARD_RTTI_INLINE(TOcaf_Application, TDocStd_Application) +public: + + Standard_EXPORT TOcaf_Application(); +}; + +#endif diff --git a/samples/OCCTOverview/code/Topology.json b/samples/OCCTOverview/code/Topology.json new file mode 100644 index 0000000000..fb96cb4c2a --- /dev/null +++ b/samples/OCCTOverview/code/Topology.json @@ -0,0 +1,176 @@ +{ + "Topology": { + "Topological Shape": [{ + "text": "Vertex", + "function": "Vertex3dSample", + "description": "" + }, + { + "text": "Edge", + "function": "Edge3dSample", + "description": "" + }, + { + "text": "Face", + "function": "Face3dSample", + "description": "" + }, + { + "text": "Wire", + "function": "Wire3dSample", + "description": "" + }, + { + "text": "Shell", + "function": "Shell3dSample", + "description": "" + }, + { + "text": "Solid", + "function": "Solid3dSample", + "description": "" + }, + { + "text": "Edge (2D)", + "function": "Edge2dSample", + "description": "" + } + ], + "BRep primitive objects": [{ + "text": "Box", + "function": "Box3dSample", + "description": "" + }, + { + "text": "Cylinder", + "function": "Cylinder3dSample", + "description": "" + }, + { + "text": "Revolution", + "function": "Revolution3dSample", + "description": "" + } + ], + "Topology access": [{ + "text": "Topology iterator", + "function": "TopologyIterator3dSample", + "description": "" + }, + { + "text": "Topology explorer", + "function": "TopologyExplorer3dSample", + "description": "" + }, + { + "text": "Assess to curve", + "function": "AssessToCurve3dSample", + "description": "" + }, + { + "text": "Assess to composite curve", + "function": "AssessToCompositeCurve3dSample", + "description": "" + }, + { + "text": "Assess to surface", + "function": "AssessToSurface3dSample", + "description": "" + } + ], + "Boolean operation": [{ + "text": "Common", + "function": "Common3dSample", + "description": "" + }, + { + "text": "Cut", + "function": "Cut3dSample", + "description": "" + }, + { + "text": "Fuse", + "function": "Fuse3dSample", + "description": "" + }, + { + "text": "Section", + "function": "Section3dSample", + "description": "" + }, + { + "text": "Splitter", + "function": "Splitter3dSample", + "description": "" + }, + { + "text": "Defeaturing", + "function": "Defeaturing3dSample", + "description": "" + } + ], + "Complex modelling": [{ + "text": "Fillet", + "function": "Fillet3dSample", + "description": "" + }, + { + "text": "Chamfer", + "function": "Chamfer3dSample", + "description": "" + }, + { + "text": "Offset", + "function": "Offset3dSample", + "description": "" + }, + { + "text": "Evolved", + "function": "Evolved3dSample", + "description": "" + } + ], + "Modification": [{ + "text": "Copy", + "function": "Copy3dSample", + "description": "" + }, + { + "text": "Transform", + "function": "Transform3dSample", + "description": "" + }, + { + "text": "Convert to NURBS", + "function": "ConvertToNurbs3dSample", + "description": "" + }, + { + "text": "Sew contiguous faces", + "function": "SewContiguousFaces3dSample", + "description": "" + } + ], + "Calculation": [{ + "text": "Check validity", + "function": "CheckValidity3dSample", + "description": "" + }, + { + "text": "Compute linear properties", + "function": "ComputeLinearProperties3dSample", + "description": "" + }, + { + "text": "Compute surface properties", + "function": "ComputeSurfaceProperties3dSample", + "description": "" + }, + { + "text": "Compute volume properties", + "function": "ComputeVolumeProperties3dSample", + "description": "" + } + ] + } +} \ No newline at end of file diff --git a/samples/OCCTOverview/code/TopologySamples.cxx b/samples/OCCTOverview/code/TopologySamples.cxx new file mode 100644 index 0000000000..17c4cc2dcc --- /dev/null +++ b/samples/OCCTOverview/code/TopologySamples.cxx @@ -0,0 +1,1884 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "TopologySamples.h" + +#include "AdaptorVec_AIS.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +void TopologySamples::ExecuteSample (const TCollection_AsciiString& theSampleName) +{ + Standard_Boolean anIsSamplePresent = Standard_True; + FindSourceCode(theSampleName); + if (theSampleName == "Vertex3dSample") + Vertex3dSample(); + else if (theSampleName == "Edge3dSample") + Edge3dSample(); + else if (theSampleName == "Face3dSample") + Face3dSample(); + else if (theSampleName == "Wire3dSample") + Wire3dSample(); + else if (theSampleName == "Shell3dSample") + Shell3dSample(); + else if (theSampleName == "Solid3dSample") + Solid3dSample(); + else if (theSampleName == "Edge2dSample") + Edge2dSample(); + else if (theSampleName == "Box3dSample") + Box3dSample(); + else if (theSampleName == "Cylinder3dSample") + Cylinder3dSample(); + else if (theSampleName == "Revolution3dSample") + Revolution3dSample(); + else if (theSampleName == "TopologyIterator3dSample") + TopologyIterator3dSample(); + else if (theSampleName == "TopologyExplorer3dSample") + TopologyExplorer3dSample(); + else if (theSampleName == "AssessToCurve3dSample") + AssessToCurve3dSample(); + else if (theSampleName == "AssessToCompositeCurve3dSample") + AssessToCompositeCurve3dSample(); + else if (theSampleName == "AssessToSurface3dSample") + AssessToSurface3dSample(); + else if (theSampleName == "Common3dSample") + Common3dSample(); + else if (theSampleName == "Cut3dSample") + Cut3dSample(); + else if (theSampleName == "Cut3dSample") + Cut3dSample(); + else if (theSampleName == "Fuse3dSample") + Fuse3dSample(); + else if (theSampleName == "Section3dSample") + Section3dSample(); + else if (theSampleName == "Splitter3dSample") + Splitter3dSample(); + else if (theSampleName == "Defeaturing3dSample") + Defeaturing3dSample(); + else if (theSampleName == "Fillet3dSample") + Fillet3dSample(); + else if (theSampleName == "Chamfer3dSample") + Chamfer3dSample(); + else if (theSampleName == "Offset3dSample") + Offset3dSample(); + else if (theSampleName == "Evolved3dSample") + Evolved3dSample(); + else if (theSampleName == "Copy3dSample") + Copy3dSample(); + else if (theSampleName == "Transform3dSample") + Transform3dSample(); + else if (theSampleName == "ConvertToNurbs3dSample") + ConvertToNurbs3dSample(); + else if (theSampleName == "SewContiguousFaces3dSample") + SewContiguousFaces3dSample(); + else if (theSampleName == "CheckValidity3dSample") + CheckValidity3dSample(); + else if (theSampleName == "ComputeLinearProperties3dSample") + ComputeLinearProperties3dSample(); + else if (theSampleName == "ComputeSurfaceProperties3dSample") + ComputeSurfaceProperties3dSample(); + else if (theSampleName == "ComputeVolumeProperties3dSample") + ComputeVolumeProperties3dSample(); + else + { + myResult << "No function found: " << theSampleName; + myCode += TCollection_AsciiString("No function found: ") + theSampleName; + anIsSamplePresent = Standard_False; + } + myIsProcessed = anIsSamplePresent; +} + +void TopologySamples::Vertex3dSample() +{ + // Make a vertex from a 3D point. + gp_Pnt aPnt(0.0, 0.0, 10.0); + TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex(aPnt); + myResult << "TopoDS_Vertex was created at [ " + << aPnt.X() << ", " << aPnt.Y() << ", " << aPnt.Z() + << " ]" << std::endl; + + Handle(AIS_Shape) aAisVertex = new AIS_Shape(aVertex); + Handle(AIS_TextLabel) anAisLabel = new AIS_TextLabel(); + Standard_SStream aSS; + aSS << "TopoDS_Vertex [" << aPnt.X() << ", " << aPnt.Y() << ", " << aPnt.Z() << "]" << std::endl; + anAisLabel->SetText(aSS.str().c_str()); + anAisLabel->SetPosition(aPnt); + myObject3d.Append(aAisVertex); + myObject3d.Append(anAisLabel); +} + +void TopologySamples::Edge3dSample() +{ + // Make an edge from two 3D points. + gp_Pnt aPnt1(0.0, 10.0, 0.0); + gp_Pnt aPnt2(10.0, 10.0, 0.0); + TopoDS_Edge anEdgeP12 = BRepBuilderAPI_MakeEdge(aPnt1, aPnt2); + myResult << "TopoDS_Edge between [ " + << aPnt1.X() << ", " << aPnt1.Y() << ", " << aPnt1.Z() + << " ] and [ " + << aPnt2.X() << ", " << aPnt2.Y() << ", " << aPnt2.Z() + << " ] was created in yellow" << std::endl + << std::endl; + + // Make an edge from a circular segment. + // Create a circle in XY plane of the radius 5.0. + gp_Circ aCirc(gp::XOY(), 5.0); + // Make a circular edge from the 1st quoter in the parametric space. + TopoDS_Edge anEdgeCirc = BRepBuilderAPI_MakeEdge(aCirc, 0.0, M_PI_2); + myResult << "TopoDS_Edge on the circle's 1st quoter" << std::endl + << "with the center at [ " + << aCirc.Location().X() << ", " << aCirc.Location().Y() << ", " << aCirc.Location().Z() + << " ] and R = " << aCirc.Radius() << " was created in red" << std::endl + << std::endl; + + // Make an edge from a 3D curve (BSpline). + // Define points. + gp_Pnt aPole1(0.0, 0.0, 10.0); + gp_Pnt aPole2(5.0, 5.0, 5.0); + gp_Pnt aPole3(10.0, 10.0, 15.0); + gp_Pnt aPole4(15.0, 5.0, 20.0); + // Add points to the curve poles array. + TColgp_Array1OfPnt aPoles(1, 4); + aPoles.SetValue(1, aPole1); + aPoles.SetValue(2, aPole2); + aPoles.SetValue(3, aPole3); + aPoles.SetValue(4, aPole4); + // Make a BSpline curve from the points array + Handle(Geom_BSplineCurve) aBSplineCurve = GeomAPI_PointsToBSpline(aPoles).Curve(); + // Make an edge between two point on the BSpline curve. + gp_Pnt aPntOnCurve1, aPntOnCurve2; + aBSplineCurve->D0 (0.75 * aBSplineCurve->FirstParameter() + + 0.25 * aBSplineCurve->LastParameter(), + aPntOnCurve1); + aBSplineCurve->D0 (0.25 * aBSplineCurve->FirstParameter() + + 0.75 * aBSplineCurve->LastParameter(), + aPntOnCurve2); + TopoDS_Edge anEdgeBSpline = BRepBuilderAPI_MakeEdge(aBSplineCurve, aPntOnCurve1, aPntOnCurve2); + myResult << "TopoDS_Edge on the BSpline curve" << std::endl + << "between [ " + << aPntOnCurve1.X() << ", " << aPntOnCurve1.Y() << ", " << aPntOnCurve1.Z() + << " ] and [ " + << aPntOnCurve2.X() << ", " << aPntOnCurve2.Y() << ", " << aPntOnCurve2.Z() + << " ]" << std::endl + << "was created in green" << std::endl; + + Handle(AIS_ColoredShape) anAisEdgeP12 = new AIS_ColoredShape(anEdgeP12); + Handle(AIS_ColoredShape) anAisEdgeCirc = new AIS_ColoredShape(anEdgeCirc); + Handle(AIS_ColoredShape) anAisEdgeBSpline = new AIS_ColoredShape(anEdgeBSpline); + anAisEdgeP12->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisEdgeCirc->SetColor(Quantity_Color(Quantity_NOC_RED)); + anAisEdgeBSpline->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisEdgeP12); + myObject3d.Append(anAisEdgeCirc); + myObject3d.Append(anAisEdgeBSpline); + Handle(AIS_TextLabel) anAisEdgeP12Label = new AIS_TextLabel(); + anAisEdgeP12Label->SetText("Edge between two points"); + anAisEdgeP12Label->SetPosition(0.5 * (aPnt1.XYZ() + aPnt2.XYZ())); + anAisEdgeP12Label->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + myObject3d.Append(anAisEdgeP12Label); + Handle(AIS_TextLabel) anAisEdgeCircLabel = new AIS_TextLabel(); + anAisEdgeCircLabel->SetText("Circular edge"); + anAisEdgeCircLabel->SetPosition(aCirc.Location()); + anAisEdgeCircLabel->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisEdgeCircLabel); + Handle(AIS_TextLabel) anAisEdgeBSplineLabel = new AIS_TextLabel(); + anAisEdgeBSplineLabel->SetText("BSpline edge"); + anAisEdgeBSplineLabel->SetPosition(aPole3); + anAisEdgeBSplineLabel->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisEdgeBSplineLabel); + TopoDS_Vertex anEdgeP12_V1, anEdgeP12_V2; + TopExp::Vertices(anEdgeP12, anEdgeP12_V1, anEdgeP12_V2); + myObject3d.Append(new AIS_Shape(anEdgeP12_V1)); + myObject3d.Append(new AIS_Shape(anEdgeP12_V2)); + TopoDS_Vertex anEdgeCirc_V1, anEdgeCirc_V2; + TopExp::Vertices(anEdgeCirc, anEdgeCirc_V1, anEdgeCirc_V2); + myObject3d.Append(new AIS_Shape(anEdgeCirc_V1)); + myObject3d.Append(new AIS_Shape(anEdgeCirc_V2)); + TopoDS_Vertex anEdgeBSpline_V1, anEdgeBSpline_V2; + TopExp::Vertices(anEdgeBSpline, anEdgeBSpline_V1, anEdgeBSpline_V2); + myObject3d.Append(new AIS_Shape(anEdgeBSpline_V1)); + myObject3d.Append(new AIS_Shape(anEdgeBSpline_V2)); +} + +void TopologySamples::Face3dSample() +{ + // Make a face from a sphere with the center + // at [0.0, 0.0, 10.0] and R = 5. + gp_Sphere aSphere(gp_Ax3(gp_Pnt(0.0, 0.0, 10.0), gp::DZ()), 5.0); + TopoDS_Face aFaceSphere = BRepBuilderAPI_MakeFace(aSphere); + myResult << "TopoDS_Face on the sphere with" << std::endl + << "the center at [ " + << aSphere.Location().X() << ", " << aSphere.Location().Y() << ", " << aSphere.Location().Z() + << " ] and R = " << aSphere.Radius() << " was created in yellow" << std::endl + << std::endl; + + // Make a flat rectangular face on XY plane. + gp_Pln aPln(gp::XOY()); + TopoDS_Face aFaceRect = BRepBuilderAPI_MakeFace(aPln, -10.0, +10.0, -20.0, +20.0); + myResult << "TopoDS_Face on the rectangle was created in red" << std::endl + << std::endl; + + // Make a face from a BSpline surface. + // Define a 4x4 grid of points for BSpline surface. + TColgp_Array2OfPnt aPoints(1, 4, 1, 4); + for (Standard_Integer i = 1; i <= 4; ++i) + { + gp_Pnt aPnt; + aPnt.SetX(5.0 * i); + for (Standard_Integer j = 1; j <= 4; ++j) + { + aPnt.SetY(5.0 * j); + if (1 < i && i < 4 && 1 < j && j < 4) + { + aPnt.SetZ(15.0); + } + else + { + aPnt.SetZ(10.0); + } + aPoints.SetValue(i, j, aPnt); + } + } + // Make a BSpline surface from the points array. + Handle(Geom_BSplineSurface) aBSplineSurf = GeomAPI_PointsToBSplineSurface(aPoints).Surface(); + Standard_Real aU1, aU2, aV1, aV2; + aBSplineSurf->Bounds(aU1, aU2, aV1, aV2); + TopoDS_Face aFaceBSpline = BRepBuilderAPI_MakeFace(aBSplineSurf, aU1, aU2, aV1, aV2, Precision::Confusion()); + myResult << "TopoDS_Face on the BSpline surface was created in green" << std::endl << std::endl; + + Handle(AIS_ColoredShape) anAisFaceSphere = new AIS_ColoredShape(aFaceSphere); + Handle(AIS_ColoredShape) anAisFaceRect = new AIS_ColoredShape(aFaceRect); + Handle(AIS_ColoredShape) anAisFaceBSpline = new AIS_ColoredShape(aFaceBSpline); + anAisFaceSphere->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisFaceRect->SetColor(Quantity_Color(Quantity_NOC_RED)); + anAisFaceBSpline->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisFaceSphere); + myObject3d.Append(anAisFaceRect); + myObject3d.Append(anAisFaceBSpline); + Handle(AIS_TextLabel) anAisFaceSphereLabel = new AIS_TextLabel(); + anAisFaceSphereLabel->SetText("Spherical face"); + anAisFaceSphereLabel->SetPosition(aSphere.Location().XYZ() + aSphere.Radius() * gp::DZ().XYZ()); + anAisFaceSphereLabel->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + myObject3d.Append(anAisFaceSphereLabel); + Handle(AIS_TextLabel) anAisFaceRectLabel = new AIS_TextLabel(); + anAisFaceRectLabel->SetText("Flat rectangular face"); + anAisFaceRectLabel->SetPosition(aPln.Location().XYZ() + 2.5 * gp::DZ().XYZ()); + anAisFaceRectLabel->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisFaceRectLabel); + Handle(AIS_TextLabel) anAisFaceBSplineLabel = new AIS_TextLabel(); + anAisFaceBSplineLabel->SetText("BSpline face"); + anAisFaceBSplineLabel->SetPosition(aPoints(4, 4)); + anAisFaceBSplineLabel->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisFaceBSplineLabel); +} + +void TopologySamples::Wire3dSample() +{ + // Make a wire from edges created on a set of points. + // Add points to the curve poles array. + TColgp_Array1OfPnt aPoints(1, 4); + aPoints.SetValue(1, gp_Pnt(0.0, 0.0, 0.0)); + aPoints.SetValue(2, gp_Pnt(20.0, 0.0, 0.0)); + aPoints.SetValue(3, gp_Pnt(20.0, 10.0, 0.0)); + aPoints.SetValue(4, gp_Pnt(0.0, 10.0, 0.0)); + // A wire maker contains an empty wire. + BRepBuilderAPI_MakeWire aMakeWire; + for (Standard_Integer i = 1; i <= 4; ++i) + { + Standard_Integer i1 = i; + Standard_Integer i2 = i1 < 4 ? i1 + 1 : 1; + const gp_Pnt& aPnt1 = aPoints.Value(i1); + const gp_Pnt& aPnt2 = aPoints.Value(i2); + TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(aPnt1, aPnt2); + // Add an edge to the wire under construction. + // The edge must be connectible to the wire under construction, and, + // unless it is the first edge of the wire, must satisfy the following + // condition: one of its vertices must be geometrically coincident + // with one of the vertices of the wire (provided that the highest + // tolerance factor is assigned to the two vertices). + // It could also be the same vertex. + // Warning + // If the edge is not connectible to the wire under construction it is not added. + // The function IsDone will return false and the function + // Wire will raise an error, until a new connectible edge is added. + aMakeWire.Add(anEdge); + Standard_ASSERT_VOID(aMakeWire.IsDone(), "Added edge isn't connectible!"); + } + // Retrieve a constructed wire. + TopoDS_Wire aWire = aMakeWire.Wire(); + myResult << "TopoDS_Wire was created. Vertices :" << std::endl; + // Retrieve wire vertices. 4 vertices are expected, because of + // edges connecting during wire constructing. + TopTools_IndexedMapOfShape aVertices; + TopExp::MapShapes(aWire, TopAbs_VERTEX, aVertices); + for (TopTools_IndexedMapOfShape::Iterator anIt(aVertices); anIt.More(); anIt.Next()) + { + TopoDS_Vertex aVertex = TopoDS::Vertex(anIt.Value()); + gp_Pnt aPnt = BRep_Tool::Pnt(aVertex); + myResult << "[ " << aPnt.X() << ", " << aPnt.Y() << ", " << aPnt.Z() << " ]" << std::endl; + Handle(AIS_Shape) anAisVertex = new AIS_Shape(aVertex); + myObject3d.Append(anAisVertex); + } + + Handle(AIS_Shape) anAisWire = new AIS_Shape(aWire); + myObject3d.Append(anAisWire); +} + +void TopologySamples::Shell3dSample() +{ + // Make a shell from a cylinder with R = 5 and directed along Z axis + gp_Cylinder aCyl(gp::XOY(), 5.0); + Handle(Geom_Surface) aCylSurf = new Geom_CylindricalSurface(aCyl); + TopoDS_Shell aCylShell = BRepBuilderAPI_MakeShell(aCylSurf, 0.0, 2.0 * M_PI, -10.0, +10.0); + myResult << "TopoDS_Shell on the cylinder R = " << aCyl.Radius() << std::endl + << "with axis [ " + << aCyl.Position().Direction().X() << ", " + << aCyl.Position().Direction().Y() << ", " + << aCyl.Position().Direction().Z() << " ]" << std::endl + << "limited in length [-10 ... +10] was created" << std::endl; + + Handle(AIS_Shape) anAisShell = new AIS_Shape(aCylShell); + myObject3d.Append(anAisShell); +} + +void TopologySamples::Solid3dSample() +{ + // Make a torus from a shell. + gp_Torus aTorus(gp::XOY(), 20.0, 7.5); + Handle(Geom_Surface) aTorusSurf = new Geom_ToroidalSurface(aTorus); + TopoDS_Shell aTorusShell = BRepBuilderAPI_MakeShell(aTorusSurf, 0.0, 2.0 * M_PI, 0.0, 2.0 * M_PI); + // Make a solid on the torus shell. + TopoDS_Solid aTorusSolid = BRepBuilderAPI_MakeSolid(aTorusShell); + myResult << "TopoDS_Solid on the torus with" << std::endl + << "R major = " << aTorus.MajorRadius() << std::endl + << "R minor = " << aTorus.MinorRadius() << std::endl + << "was created" << std::endl; + + Handle(AIS_Shape) anAisSolid = new AIS_Shape(aTorusSolid); + myObject3d.Append(anAisSolid); +} + +void TopologySamples::Edge2dSample() +{ + // Make an edge from two 2D points. + gp_Pnt2d aPnt1(0.0, 10.0); + gp_Pnt2d aPnt2(10.0, 10.0); + TopoDS_Edge anEdgeP12 = BRepBuilderAPI_MakeEdge2d(aPnt1, aPnt2); + myResult << "TopoDS_Edge between [ " + << aPnt1.X() << ", " << aPnt1.Y() << " ] and [ " + << aPnt2.X() << ", " << aPnt2.Y() << " ] was created in yellow" << std::endl + << std::endl; + + // Make an edge from a circular segment. + // Create a circle of the radius 5.0. + gp_Circ2d aCirc(gp::OX2d(), 5.0); + // Make a circular edge from the 1st quoter in the parametric space. + TopoDS_Edge anEdgeCirc = BRepBuilderAPI_MakeEdge2d(aCirc, 0.0, M_PI_2); + myResult << "TopoDS_Edge on the 2D circle's 1st quoter" << std::endl + << "with the center at [ " << aCirc.Location().X() << ", " << aCirc.Location().Y() + << " ] and R = " << aCirc.Radius() << " was created in red" << std::endl + << std::endl; + + // Make an edge from a 2D curve (BSpline). + // Define points. + gp_Pnt2d aPole1(0.0, 0.0); + gp_Pnt2d aPole2(5.0, 5.0); + gp_Pnt2d aPole3(10.0, 10.0); + gp_Pnt2d aPole4(15.0, 5.0); + // Add points to the curve poles array. + TColgp_Array1OfPnt2d aPoles(1, 4); + aPoles.SetValue(1, aPole1); + aPoles.SetValue(2, aPole2); + aPoles.SetValue(3, aPole3); + aPoles.SetValue(4, aPole4); + // Make a BSpline curve from the points array + Handle(Geom2d_BSplineCurve) aBSplineCurve = Geom2dAPI_PointsToBSpline(aPoles).Curve(); + // Make an edge between two point on the BSpline curve. + gp_Pnt2d aPntOnCurve1, aPntOnCurve2; + aBSplineCurve->D0 (0.75 * aBSplineCurve->FirstParameter() + + 0.25 * aBSplineCurve->LastParameter(), + aPntOnCurve1); + aBSplineCurve->D0 (0.25 * aBSplineCurve->FirstParameter() + + 0.75 * aBSplineCurve->LastParameter(), + aPntOnCurve2); + TopoDS_Edge anEdgeBSpline = BRepBuilderAPI_MakeEdge2d(aBSplineCurve, aPntOnCurve1, aPntOnCurve2); + myResult << "TopoDS_Edge on the 2D BSpline curve" << std::endl + << "between [ " << aPntOnCurve1.X() << ", " << aPntOnCurve1.Y() + << " ] and [ " << aPntOnCurve2.X() << ", " << aPntOnCurve2.Y() << " ]" << std::endl + << "was created in green" << std::endl; + + Handle(AIS_ColoredShape) anAisEdgeP12 = new AIS_ColoredShape(anEdgeP12); + Handle(AIS_ColoredShape) anAisEdgeCirc = new AIS_ColoredShape(anEdgeCirc); + Handle(AIS_ColoredShape) anAisEdgeBSpline = new AIS_ColoredShape(anEdgeBSpline); + anAisEdgeP12->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisEdgeCirc->SetColor(Quantity_Color(Quantity_NOC_RED)); + anAisEdgeBSpline->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject2d.Append(anAisEdgeP12); + myObject2d.Append(anAisEdgeCirc); + myObject2d.Append(anAisEdgeBSpline); + Handle(AIS_TextLabel) anAisEdgeP12Label = new AIS_TextLabel(); + anAisEdgeP12Label->SetText("Edge between two 2d points"); + anAisEdgeP12Label->SetPosition(0.5 * (gp_XYZ(aPnt1.X(), aPnt1.Y() + 0.5, 0.0) + gp_XYZ(aPnt2.X(), aPnt2.Y() + 0.5, 0.0))); + anAisEdgeP12Label->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + myObject2d.Append(anAisEdgeP12Label); + Handle(AIS_TextLabel) anAisEdgeCircLabel = new AIS_TextLabel(); + anAisEdgeCircLabel->SetText("Circular edge"); + anAisEdgeCircLabel->SetPosition(gp_XYZ(aCirc.Location().X(), aCirc.Location().Y() + 0.5, 0.0)); + anAisEdgeCircLabel->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject2d.Append(anAisEdgeCircLabel); + Handle(AIS_TextLabel) anAisEdgeBSplineLabel = new AIS_TextLabel(); + anAisEdgeBSplineLabel->SetText("BSpline edge"); + anAisEdgeBSplineLabel->SetPosition(gp_XYZ(aPole3.X(), aPole3.Y() + 0.5, 0.0)); + anAisEdgeBSplineLabel->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject2d.Append(anAisEdgeBSplineLabel); + TopoDS_Vertex anEdgeP12_V1, anEdgeP12_V2; + TopExp::Vertices(anEdgeP12, anEdgeP12_V1, anEdgeP12_V2); + myObject2d.Append(new AIS_Shape(anEdgeP12_V1)); + myObject2d.Append(new AIS_Shape(anEdgeP12_V2)); + TopoDS_Vertex anEdgeCirc_V1, anEdgeCirc_V2; + TopExp::Vertices(anEdgeCirc, anEdgeCirc_V1, anEdgeCirc_V2); + myObject2d.Append(new AIS_Shape(anEdgeCirc_V1)); + myObject2d.Append(new AIS_Shape(anEdgeCirc_V2)); + TopoDS_Vertex anEdgeBSpline_V1, anEdgeBSpline_V2; + TopExp::Vertices(anEdgeBSpline, anEdgeBSpline_V1, anEdgeBSpline_V2); + myObject2d.Append(new AIS_Shape(anEdgeBSpline_V1)); + myObject2d.Append(new AIS_Shape(anEdgeBSpline_V2)); +} + +void TopologySamples::Box3dSample() +{ + // Make a box with a corner at [0, 0, 0] and the specified sizes. + Standard_Real aSizeX = 5.0; + Standard_Real aSizeY = 10.0; + Standard_Real aSizeZ = 15.0; + TopoDS_Shape aBox1 = BRepPrimAPI_MakeBox(aSizeX, aSizeY, aSizeZ); + myResult << "Box at corner [0, 0, 0] and sizes [" + << aSizeX << ", " << aSizeY << ", " << aSizeZ + << "] was created in yellow" << std::endl; + + // Make a box by two points. + gp_Pnt aPnt1(10.0, 0.0, 0.0); + gp_Pnt aPnt2(20.0, 10.0, 15.0); + TopoDS_Shape aBox2 = BRepPrimAPI_MakeBox(aPnt1, aPnt2); + myResult << "Box with corners [" + << aPnt1.X() << ", " << aPnt1.Y() << ", " << aPnt1.Z() + << "] and [" + << aPnt2.X() << ", " << aPnt2.Y() << ", " << aPnt2.Z() + << "] was created in red" << std::endl; + + Handle(AIS_ColoredShape) anAisBox1 = new AIS_ColoredShape(aBox1); + Handle(AIS_ColoredShape) anAisBox2 = new AIS_ColoredShape(aBox2); + anAisBox1->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisBox2->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisBox1); + myObject3d.Append(anAisBox2); +} + +void TopologySamples::Cylinder3dSample() +{ + // Make a cylinder of the specified radius and length. + Standard_Real aRadius1 = 5.0; + Standard_Real aLength1 = 15.0; + TopoDS_Shape aCyl1 = BRepPrimAPI_MakeCylinder(aRadius1, aLength1); + myResult << "Cylinder with Radius = " << aRadius1 + << " and Length = " << aLength1 + << " was created in yellow" << std::endl; + + // Make a cylinder of the specified radius, length and sector angle. + Standard_Real aRadius2 = 8.0; + Standard_Real aLength2 = 25.0; + Standard_Real anAngle = M_PI_2; + TopoDS_Shape aCyl2 = BRepPrimAPI_MakeCylinder(aRadius2, aLength2, anAngle); + myResult << "Cylinder with Radius = " << aRadius2 + << " , Length = " << aLength2 + << " and Angle = " << anAngle + << " was created in red" << std::endl; + + Handle(AIS_ColoredShape) anAisCyl1 = new AIS_ColoredShape(aCyl1); + Handle(AIS_ColoredShape) anAisCyl2 = new AIS_ColoredShape(aCyl2); + anAisCyl1->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisCyl2->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisCyl1); + myObject3d.Append(anAisCyl2); +} + +void TopologySamples::Revolution3dSample() +{ + // Make a toroidal face by a series of shape revolves. + // Make a starting vertex at [-1.0, 0, 0]. + TopoDS_Shape aVertex = BRepBuilderAPI_MakeVertex(gp_Pnt(-1.0, 0.0, 0.0)); + + // Make a circular edge by revolting aVertex around + // an axis Y positioned at [-1.5, 0.0, 0.0] on 2*Pi angle + gp_Ax1 anAxis1(gp_Pnt(-1.5, 0.0, 0.0), gp::DY()); + TopoDS_Shape anEdge = BRepPrimAPI_MakeRevol(aVertex, anAxis1); + myResult << "Circular edge was created in yellow" << std::endl; + + // Make a toroidal face by revolting anEdge around + // Z axis on 2*Pi angle. + TopoDS_Shape aFace = BRepPrimAPI_MakeRevol(anEdge, gp::OZ()); + myResult << "Toroidal face was created in red" << std::endl; + + Handle(AIS_Axis) anAisAxis1 = new AIS_Axis(new Geom_Axis1Placement(anAxis1)); + Handle(AIS_Axis) anAisAxis2 = new AIS_Axis(new Geom_Axis1Placement(gp::OZ())); + Handle(AIS_Shape) anAisVertex = new AIS_Shape(aVertex); + Handle(AIS_ColoredShape) anAisEdge = new AIS_ColoredShape(anEdge); + Handle(AIS_ColoredShape) anAisFace = new AIS_ColoredShape(aFace); + anAisEdge->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + anAisEdge->SetWidth(1.5); + anAisAxis1->SetColor(Quantity_NOC_GREEN); + anAisFace->SetColor(Quantity_Color(Quantity_NOC_RED)); + anAisAxis2->SetColor(Quantity_NOC_RED); + myObject3d.Append(anAisVertex); + myObject3d.Append(anAisEdge); + myObject3d.Append(anAisFace); +} + +void TopologySamples::TopologyIterator3dSample() +{ + // Make a compound shape. + TopoDS_Compound aComp; + BRep_Builder aBuilder; + aBuilder.MakeCompound(aComp); + // Add shapes to the compound. + aBuilder.Add(aComp, BRepBuilderAPI_MakeVertex(gp::Origin())); + aBuilder.Add(aComp, BRepBuilderAPI_MakeEdge(gp_Pnt(5.0, 0.0, 0.0), gp_Pnt(10.0, 0.0, 0.0))); + aBuilder.Add(aComp, BRepBuilderAPI_MakeFace(gp_Sphere(gp::XOY(), 10.0))); + aBuilder.Add(aComp, BRepBuilderAPI_MakeWire( + BRepBuilderAPI_MakeEdge(gp_Pnt(15.0, 0.0, 0.0), gp_Pnt(20.0, 0.0, 0.0)), + BRepBuilderAPI_MakeEdge(gp_Pnt(20.0, 0.0, 0.0), gp_Pnt(25.0, 10.0, 5.0)) + )); + aBuilder.Add(aComp, BRepPrimAPI_MakeBox(5.0, 6.0, 7.0).Shell()); + aBuilder.Add(aComp, BRepPrimAPI_MakeBox(5.0, 6.0, 7.0).Solid()); + TopoDS_Compound aComp1; + aBuilder.MakeCompound(aComp1); + aBuilder.Add(aComp, aComp1); + + // Iterate over compound components. + myResult << "Compound components:" << std::endl; + Standard_Integer anI = 1; + for (TopoDS_Iterator anIt(aComp); anIt.More(); anIt.Next(), ++anI) + { + const TopoDS_Shape& aShape = anIt.Value(); + myResult << "#" << anI << " : "; + Handle(AIS_ColoredShape) anAisShape; + switch (aShape.ShapeType()) + { + case TopAbs_VERTEX: + myResult << "TopAbs_VERTEX"; + anAisShape = new AIS_ColoredShape(aShape); + anAisShape->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + break; + case TopAbs_EDGE: + anAisShape = new AIS_ColoredShape(aShape); + anAisShape->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myResult << "TopAbs_EDGE"; + break; + case TopAbs_WIRE: + myResult << "TopAbs_WIRE"; + break; + case TopAbs_FACE: + anAisShape = new AIS_ColoredShape(aShape); + anAisShape->SetColor(Quantity_Color(Quantity_NOC_RED)); + myResult << "TopAbs_FACE"; + break; + case TopAbs_SHELL: + myResult << "TopAbs_SHELL"; + break; + case TopAbs_SOLID: + myResult << "TopAbs_SOLID"; + break; + case TopAbs_COMPOUND: + myResult << "TopAbs_COMPOUND"; + break; + case TopAbs_COMPSOLID: + myResult << "TopAbs_COMPSOLID"; + break; + case TopAbs_SHAPE: + myResult << "TopAbs_SHAPE"; + break; + } + myResult << std::endl; + if (anAisShape) + { + myObject3d.Append(anAisShape); + } + } +} + +void TopologySamples::TopologyExplorer3dSample() +{ + // Make a box with a corner at [0, 0, 0] and the specified sizes. + Standard_Real aSizeX = 5.0; + Standard_Real aSizeY = 10.0; + Standard_Real aSizeZ = 15.0; + TopoDS_Shape aBox = BRepPrimAPI_MakeBox(aSizeX, aSizeY, aSizeZ); + + // Explore vertex references. + myResult << "Vertex refs. : "; + Standard_Integer nbVertices = 0; + for (TopExp_Explorer anExp(aBox, TopAbs_VERTEX); anExp.More(); anExp.Next(), ++nbVertices) + { + const TopoDS_Shape& aShape = anExp.Current(); + Handle(AIS_ColoredShape) anAisShape = new AIS_ColoredShape(aShape); + anAisShape->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + myObject3d.Append(anAisShape); + } + myResult << nbVertices << std::endl; + + // Explore edge references. + myResult << "Edge refs. : "; + Standard_Integer nbEdges = 0; + for (TopExp_Explorer anExp(aBox, TopAbs_EDGE); anExp.More(); anExp.Next(), ++nbEdges) + { + const TopoDS_Shape& aShape = anExp.Current(); + Handle(AIS_ColoredShape) anAisShape = new AIS_ColoredShape(aShape); + anAisShape->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + anAisShape->SetWidth(2.5); + myObject3d.Append(anAisShape); + } + myResult << nbEdges << std::endl; + + // Explore face references. + myResult << "Face refs. : "; + Standard_Integer nbFaces = 0; + for (TopExp_Explorer anExp(aBox, TopAbs_FACE); anExp.More(); anExp.Next(), ++nbFaces) + { + const TopoDS_Shape& aShape = anExp.Current(); + Handle(AIS_ColoredShape) anAisShape = new AIS_ColoredShape(aShape); + anAisShape->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + anAisShape->SetWidth(2.5); + myObject3d.Append(anAisShape); + } + myResult << nbFaces << std::endl; + + // Explore shell references. + myResult << "Wire refs. : "; + Standard_Integer nbWires = 0; + for (TopExp_Explorer anExp(aBox, TopAbs_WIRE); anExp.More(); anExp.Next(), ++nbWires) + { + } + myResult << nbWires << std::endl; + + // Explore shell references. + myResult << "Shell refs. : "; + Standard_Integer nbShells = 0; + for (TopExp_Explorer anExp(aBox, TopAbs_SHELL); anExp.More(); anExp.Next(), ++nbShells) + { + } + myResult << nbShells << std::endl; + + // Explore solid references. + myResult << "Solid refs. : "; + Standard_Integer nbSolids = 0; + for (TopExp_Explorer anExp(aBox, TopAbs_SOLID); anExp.More(); anExp.Next(), ++nbSolids) + { + } + myResult << nbSolids << std::endl; +} + +void TopologySamples::AssessToCurve3dSample() +{ + // Make a face from a sphere. + gp_Sphere aSphere(gp::XOY(), 1.0); + TopoDS_Face aFace = BRepBuilderAPI_MakeFace(aSphere); + myResult << "TopoDS_Face on the sphere with" << std::endl + << "the center at [ " + << aSphere.Location().X() << ", " << aSphere.Location().Y() << ", " << aSphere.Location().Z() + << " ] and R = " << aSphere.Radius() << " was created in yellow" << std::endl + << std::endl; + + Handle(AIS_ColoredShape) anAisFace = new AIS_ColoredShape(aFace); + anAisFace->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + myObject3d.Append(anAisFace); + + // Retrieve the first not degenerated edge. + TopoDS_Edge aCurveEdge; + for (TopExp_Explorer anExp(aFace, TopAbs_EDGE); anExp.More(); anExp.Next()) + { + TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current()); + if (!BRep_Tool::Degenerated(anEdge)) + { + aCurveEdge = anEdge; + break; + } + } + if (!aCurveEdge.IsNull()) + { + // Make a curve on edge adaptor. + BRepAdaptor_Curve aCurveAdaptor(aCurveEdge); + myResult << "Curve adaptor for edge was built in red" << std::endl; + + Handle(AIS_ColoredShape) anAisCurveEdge = new AIS_ColoredShape(aCurveEdge); + anAisCurveEdge->SetColor(Quantity_Color(Quantity_NOC_RED)); + anAisCurveEdge->SetWidth(1.5); + myObject3d.Append(anAisCurveEdge); + + // Use the curve adaptor for some calculations, e.g. compute + // a set of points using GCPnts_QuasiUniformDeflection algo. + Standard_Real aDeflection = 0.1; + GCPnts_QuasiUniformDeflection anAlgo(aCurveAdaptor, aDeflection); + Standard_ASSERT_VOID(anAlgo.IsDone(), "Success is expected!"); + myResult << "Distribution of point on the curve with " << aDeflection + << " deflection was performed:" << std::endl; + for (Standard_Integer i = 1; i <= anAlgo.NbPoints(); ++i) + { + gp_Pnt aPnt = anAlgo.Value(i); + myResult << "Point #" << i << " : [ " + << aPnt.X() << ", " << aPnt.Y() << ", " << aPnt.Z() << " ]" << std::endl; + Handle(AIS_Point) anAisPnt = new AIS_Point(new Geom_CartesianPoint(aPnt)); + myObject3d.Append(anAisPnt); + } + } +} + +void TopologySamples::AssessToCompositeCurve3dSample() +{ + // Make a wire containing two BSpline curves. + // Define points. + gp_Pnt aPole1(0.0, 0.0, 10.0); + gp_Pnt aPole2(5.0, 5.0, 5.0); + gp_Pnt aPole3(10.0, 10.0, 15.0); + gp_Pnt aPole4(15.0, 5.0, 20.0); + gp_Pnt aPole5(25.0, 15.0, 20.0); + gp_Pnt aPole6(35.0, 15.0, 15.0); + gp_Pnt aPole7(45.0, 25.0, 10.0); + // Add points to the curve poles array. + TColgp_Array1OfPnt aPoles1(1, 4), aPoles2(1, 4); + aPoles1.SetValue(1, aPole1); + aPoles1.SetValue(2, aPole2); + aPoles1.SetValue(3, aPole3); + aPoles1.SetValue(4, aPole4); + aPoles2.SetValue(1, aPole4); + aPoles2.SetValue(2, aPole5); + aPoles2.SetValue(3, aPole6); + aPoles2.SetValue(4, aPole7); + // Make a BSpline curves from the point arrays + Handle(Geom_BSplineCurve) aBSplineCurve1 = GeomAPI_PointsToBSpline(aPoles1).Curve(); + Handle(Geom_BSplineCurve) aBSplineCurve2 = GeomAPI_PointsToBSpline(aPoles2).Curve(); + // Make edges + TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(aBSplineCurve1); + TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(aBSplineCurve2); + // Make a wire + BRepBuilderAPI_MakeWire aMakeWire; + aMakeWire.Add(anEdge1); + aMakeWire.Add(anEdge2); + Standard_ASSERT_VOID(aMakeWire.IsDone(), "Added edge isn't connectible!"); + TopoDS_Wire aWire = aMakeWire.Wire(); + myResult << "Wire of two BSpline curves was created" << std::endl; + + Handle(AIS_ColoredShape) anAisWire = new AIS_ColoredShape(aWire); + myObject3d.Append(anAisWire); + + // Make an adaptor. + BRepAdaptor_CompCurve aCurveAdaptor(aWire); + + // Use the curve adaptor for some calculations, e.g. compute + // a set of points using GCPnts_QuasiUniformDeflection algo. + Standard_Real aDeflection = 0.5; + GCPnts_QuasiUniformDeflection anAlgo(aCurveAdaptor, aDeflection); + Standard_ASSERT_VOID(anAlgo.IsDone(), "Success is expected!"); + myResult << "Distribution of point on the curve with " << aDeflection + << " deflection was performed:" << std::endl; + for (Standard_Integer i = 1; i <= anAlgo.NbPoints(); ++i) + { + gp_Pnt aPnt = anAlgo.Value(i); + myResult << "Point #" << i << " : [ " + << aPnt.X() << ", " << aPnt.Y() << ", " << aPnt.Z() << " ]" << std::endl; + Handle(AIS_Point) anAisPnt = new AIS_Point(new Geom_CartesianPoint(aPnt)); + myObject3d.Append(anAisPnt); + } +} + +void TopologySamples::AssessToSurface3dSample() +{ + // Make a face from a sphere. + gp_Sphere aSphere(gp::XOY(), 4.0); + TopoDS_Face aFace = BRepBuilderAPI_MakeFace(aSphere); + myResult << "TopoDS_Face on the sphere with" << std::endl + << "the center at [ " + << aSphere.Location().X() << ", " << aSphere.Location().Y() << ", " << aSphere.Location().Z() + << " ] and R = " << aSphere.Radius() << " was created in yellow" << std::endl + << std::endl; + + // Make a surface adaptor. + BRepAdaptor_Surface aSurfAdaptor(aFace); + + // Use the surface adaptor for some calculations, e.g. compute + // a normal vector at a surface point. + Standard_Real anU = 0.0, aV = 0.0; + gp_Pnt aPnt; + gp_Vec aDU, aDV; + aSurfAdaptor.D1(anU, aV, aPnt, aDU, aDV); + gp_Vec aNorm = aDU.Crossed(aDV); + Standard_ASSERT_VOID(aNorm.Magnitude() > Precision::Confusion(), "Non zero vector is expected!"); + aNorm.Normalize(); + myResult << "Normal vector at ( " << anU << ", " << aV << " )" << std::endl + << " = " << aNorm.X() << ", " << aNorm.Y() << ", " << aNorm.Z() << " ] is in red" << std::endl; + + Handle(AIS_ColoredShape) anAisFace = new AIS_ColoredShape(aFace); + anAisFace->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + Handle(AIS_Point) anAisPnt = new AIS_Point(new Geom_CartesianPoint(aPnt)); + Handle(AIS_ColoredShape) anAisNorm = new AIS_ColoredShape( + BRepBuilderAPI_MakeEdge(aPnt, aPnt.XYZ() + aNorm.XYZ())); + myObject3d.Append(anAisFace); + myObject3d.Append(anAisNorm); + myObject3d.Append(anAisPnt); +} + +void TopologySamples::Common3dSample() +{ + // Make a box #1 with a corner at [0, 0, 0] and the specified sizes. + Standard_Real aSizeX = 10.0; + Standard_Real aSizeY = 15.0; + Standard_Real aSizeZ = 20.0; + TopoDS_Shape aShape1 = BRepPrimAPI_MakeBox(aSizeX, aSizeY, aSizeZ); + myResult << "Box at corner [0, 0, 0] and sizes [" + << aSizeX << ", " << aSizeY << ", " << aSizeZ + << "] was created in yellow wireframe" << std::endl; + + // Make a box #2 by two points. + gp_Pnt aPnt1(5.0, 7.5, 10.0); + gp_Pnt aPnt2(20.0, 25.0, 30.0); + TopoDS_Shape aShape2 = BRepPrimAPI_MakeBox(aPnt1, aPnt2); + myResult << "Box with corners [" + << aPnt1.X() << ", " << aPnt1.Y() << ", " << aPnt1.Z() + << "] and [" + << aPnt2.X() << ", " << aPnt2.Y() << ", " << aPnt2.Z() + << "] was created in green wirefreme" << std::endl; + + // Create a boolean algo. + BRepAlgoAPI_Common anAlgo(aShape1, aShape2); + + // Make operation. + anAlgo.Build(); + + if (!anAlgo.IsDone()) // Process errors + { + myResult << "Errors : " << std::endl; + anAlgo.DumpErrors(myResult); + } + if (anAlgo.HasWarnings()) // Process warnings + { + myResult << "Warnings : " << std::endl; + anAlgo.DumpErrors(myResult); + } + + if (anAlgo.IsDone()) + { + // Get result. + TopoDS_Shape aResultShape = anAlgo.Shape(); + myResult << "Result shape was created in red shading" << std::endl; + + Handle(AIS_ColoredShape) anAisShape1 = new AIS_ColoredShape(aShape1); + Handle(AIS_ColoredShape) anAisShape2 = new AIS_ColoredShape(aShape2); + anAisShape1->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisShape2->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + Handle(AIS_ColoredShape) anAisResult = new AIS_ColoredShape(aResultShape); + anAisResult->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisShape1); + myObject3d.Append(anAisShape2); + myObject3d.Append(anAisResult); + myContext->SetDisplayMode(anAisShape1, 0, Standard_True); + myContext->SetDisplayMode(anAisShape2, 0, Standard_True); + myContext->SetDisplayMode(anAisResult, 1, Standard_True); + } +} + +void TopologySamples::Cut3dSample() +{ + // Make a box #1 with a corner at [0, 0, 0] and the specified sizes. + Standard_Real aSizeX = 10.0; + Standard_Real aSizeY = 15.0; + Standard_Real aSizeZ = 20.0; + TopoDS_Shape aShape1 = BRepPrimAPI_MakeBox(aSizeX, aSizeY, aSizeZ); + myResult << "Box at corner [0, 0, 0] and sizes [" + << aSizeX << ", " << aSizeY << ", " << aSizeZ + << "] was created in yellow wireframe" << std::endl; + + // Make a box #2 by two points as a cutting tool. + gp_Pnt aPnt1(5.0, 7.5, 10.0); + gp_Pnt aPnt2(20.0, 25.0, 30.0); + TopoDS_Shape aShape2 = BRepPrimAPI_MakeBox(aPnt1, aPnt2); + myResult << "Box with corners [" + << aPnt1.X() << ", " << aPnt1.Y() << ", " << aPnt1.Z() + << "] and [" + << aPnt2.X() << ", " << aPnt2.Y() << ", " << aPnt2.Z() + << "] was created in green wireframe" << std::endl; + + // Create a boolean algo. + BRepAlgoAPI_Cut anAlgo(aShape1, aShape2); + + // Make operation. + anAlgo.Build(); + + if (!anAlgo.IsDone()) // Process errors + { + myResult << "Errors : " << std::endl; + anAlgo.DumpErrors(myResult); + } + if (anAlgo.HasWarnings()) // Process warnings + { + myResult << "Warnings : " << std::endl; + anAlgo.DumpErrors(myResult); + } + + if (anAlgo.IsDone()) + { + // Get result. + TopoDS_Shape aResultShape = anAlgo.Shape(); + myResult << "Result shape was created in red shading" << std::endl; + Handle(AIS_ColoredShape) anAisShape1 = new AIS_ColoredShape(aShape1); + Handle(AIS_ColoredShape) anAisShape2 = new AIS_ColoredShape(aShape2); + anAisShape1->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisShape2->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + Handle(AIS_ColoredShape) anAisResult = new AIS_ColoredShape(aResultShape); + anAisResult->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisShape1); + myObject3d.Append(anAisShape2); + myObject3d.Append(anAisResult); + myContext->SetDisplayMode(anAisShape1, 0, Standard_True); + myContext->SetDisplayMode(anAisShape2, 0, Standard_True); + myContext->SetDisplayMode(anAisResult, 1, Standard_True); + } +} + +void TopologySamples::Fuse3dSample() +{ + // Make a box #1 with a corner at [0, 0, 0] and the specified sizes. + Standard_Real aSizeX = 10.0; + Standard_Real aSizeY = 15.0; + Standard_Real aSizeZ = 20.0; + TopoDS_Shape aShape1 = BRepPrimAPI_MakeBox(aSizeX, aSizeY, aSizeZ); + myResult << "Box at corner [0, 0, 0] and sizes [" + << aSizeX << ", " << aSizeY << ", " << aSizeZ + << "] was created in yellow wireframe" << std::endl; + + // Make a box #2 by two points. + gp_Pnt aPnt1(5.0, 7.5, 10.0); + gp_Pnt aPnt2(20.0, 25.0, 30.0); + TopoDS_Shape aShape2 = BRepPrimAPI_MakeBox(aPnt1, aPnt2); + myResult << "Box with corners [" + << aPnt1.X() << ", " << aPnt1.Y() << ", " << aPnt1.Z() + << "] and [" + << aPnt2.X() << ", " << aPnt2.Y() << ", " << aPnt2.Z() + << "] was created in green wireframe" << std::endl; + + // Create a boolean algo. + BRepAlgoAPI_Fuse anAlgo(aShape1, aShape2); + + // Make operation. + anAlgo.Build(); + + if (!anAlgo.IsDone()) // Process errors + { + myResult << "Errors : " << std::endl; + anAlgo.DumpErrors(myResult); + } + if (anAlgo.HasWarnings()) // Process warnings + { + myResult << "Warnings : " << std::endl; + anAlgo.DumpErrors(myResult); + } + + if (anAlgo.IsDone()) + { + // Get result. + TopoDS_Shape aResultShape = anAlgo.Shape(); + myResult << "Result shape was created in red shading" << std::endl; + Handle(AIS_ColoredShape) anAisShape1 = new AIS_ColoredShape(aShape1); + Handle(AIS_ColoredShape) anAisShape2 = new AIS_ColoredShape(aShape2); + anAisShape1->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisShape2->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + Handle(AIS_ColoredShape) anAisResult = new AIS_ColoredShape(aResultShape); + anAisResult->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisShape1); + myObject3d.Append(anAisShape2); + myObject3d.Append(anAisResult); + myContext->SetDisplayMode(anAisShape1, 0, Standard_True); + myContext->SetDisplayMode(anAisShape2, 0, Standard_True); + myContext->SetDisplayMode(anAisResult, 1, Standard_True); + } +} + +void TopologySamples::Section3dSample() +{ + // Make a box #1 with a corner at [0, 0, 0] and the specified sizes. + Standard_Real aSizeX = 10.0; + Standard_Real aSizeY = 15.0; + Standard_Real aSizeZ = 20.0; + TopoDS_Shape aShape = BRepPrimAPI_MakeBox(aSizeX, aSizeY, aSizeZ); + myResult << "Box at corner [0, 0, 0] and sizes [" + << aSizeX << ", " << aSizeY << ", " << aSizeZ + << "] was created in yellow wireframe" << std::endl; + + // Create a boolean algo. + // Make a section by a plane. + gp_Pln aPln(gp_Pnt(aSizeX / 2.0, aSizeY / 2.0, aSizeZ / 2.0), gp::DZ()); + BRepAlgoAPI_Section anAlgo(aShape, aPln, Standard_False); + + // Make operation. + anAlgo.Build(); + + if (!anAlgo.IsDone()) // Process errors + { + myResult << "Errors : " << std::endl; + anAlgo.DumpErrors(myResult); + } + if (anAlgo.HasWarnings()) // Process warnings + { + myResult << "Warnings : " << std::endl; + anAlgo.DumpErrors(myResult); + } + + if (anAlgo.IsDone()) + { + // Get result. + TopoDS_Shape aResultShape = anAlgo.Shape(); + myResult << "Result shape was created in red" << std::endl; + Handle(AIS_ColoredShape) anAisShape = new AIS_ColoredShape(aShape); + Handle(AIS_Plane) anAisPlane = new AIS_Plane(new Geom_Plane(aPln)); + anAisShape->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + Handle(AIS_ColoredShape) anAisResult = new AIS_ColoredShape(aResultShape); + anAisResult->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisShape); + myObject3d.Append(anAisPlane); + myObject3d.Append(anAisResult); + myContext->SetDisplayMode(anAisShape, 0, Standard_True); + } +} + +void TopologySamples::Splitter3dSample() +{ + // Make a box by two points. + gp_Pnt aPnt1(-5.0, -7.5, -10.0); + gp_Pnt aPnt2(10.0, 15.0, 10.0); + TopoDS_Shape aBox = BRepPrimAPI_MakeBox(aPnt1, aPnt2); + myResult << "Box with corners [" + << aPnt1.X() << ", " << aPnt1.Y() << ", " << aPnt1.Z() + << "] and [" + << aPnt2.X() << ", " << aPnt2.Y() << ", " << aPnt2.Z() + << "] was created in yellow" << std::endl; + + // Make a splitting tool as XY plane. + TopoDS_Shape aTool = BRepBuilderAPI_MakeFace(gp_Pln(gp::XOY())); + + // Create a splitter algo. + BRepAlgoAPI_Splitter aSplitter; + + // Add shapes to be split. + TopTools_ListOfShape anArguments; + anArguments.Append(aBox); + aSplitter.SetArguments(anArguments); + + // Add tool shapes. + TopTools_ListOfShape aTools; + aTools.Append(aTool); + aSplitter.SetTools(aTools); + + // Perform splitting. + aSplitter.Build(); + + if (!aSplitter.IsDone()) // Process errors + { + myResult << "Errors : " << std::endl; + aSplitter.DumpErrors(myResult); + } + if (aSplitter.HasWarnings()) // Process warnings + { + myResult << "Warnings : " << std::endl; + aSplitter.DumpErrors(myResult); + } + + Handle(AIS_ColoredShape) anAisBox = new AIS_ColoredShape(aBox); + anAisBox->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + myObject3d.Append(anAisBox); + + if (aSplitter.IsDone()) // Process results + { + // Simplification of the result shape is performed by the means of + // ShapeUpgrade_UnifySameDomain algorithm. The result of the operation will + // be overwritten with the simplified result. + // The simplification is performed without creation of the Internal shapes, + // i.e. shapes connections will never be broken. + // Simplification is performed on the whole result shape. Thus, if the input + // shapes contained connected tangent edges or faces unmodified during the operation + // they will also be unified. + aSplitter.SimplifyResult(); + + // Get result of splitting. + TopoDS_Shape aResult = aSplitter.Shape(); + myResult << "Splitting result (shapes are moved apart for illustativeness) is in red" << std::endl; + + // In this particular sample two shapes in the result are expected. + // Lets move apart them for illustrative purposes. + TopoDS_Iterator anIt(aResult); + Standard_ASSERT_VOID(anIt.More(), "Not empty result is expected!"); + TopoDS_Shape aBox1 = anIt.Value(); anIt.Next(); + Standard_ASSERT_VOID(anIt.More(), "Two shapes in the result are expected!"); + TopoDS_Shape aBox2 = anIt.Value(); + gp_Trsf aTrsf1; aTrsf1.SetTranslation(gp_Vec(0.0, 0.0, -15.0)); + aBox1.Move(aTrsf1); + gp_Trsf aTrsf2; aTrsf2.SetTranslation(gp_Vec(0.0, 0.0, +15.0)); + aBox2.Move(aTrsf2); + + Handle(AIS_ColoredShape) anAisBox1 = new AIS_ColoredShape(aBox1); + Handle(AIS_ColoredShape) anAisBox2 = new AIS_ColoredShape(aBox2); + anAisBox1->SetColor(Quantity_Color(Quantity_NOC_RED)); + anAisBox2->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisBox1); + myObject3d.Append(anAisBox2); + } +} + +void TopologySamples::Defeaturing3dSample() +{ + // Prepare a box with a chamfer. + // Make a box with a corner at [0, 0, 0] and the specified sizes. + Standard_Real aSizeX = 8.0; + Standard_Real aSizeY = 10.0; + Standard_Real aSizeZ = 15.0; + TopoDS_Shape aBox = BRepPrimAPI_MakeBox(aSizeX, aSizeY, aSizeZ); + // Initialize chamfer algo. + BRepFilletAPI_MakeChamfer anAlgo(aBox); + // Set edge to apply a chamfer with specified distance from it. + // Select the 5th edge in the map returned by TopExp::MapShapes method. + TopTools_IndexedMapOfShape anEdges; + TopExp::MapShapes(aBox, TopAbs_EDGE, anEdges); + TopoDS_Edge anEdge = TopoDS::Edge(anEdges.FindKey(5)); + Standard_Real aDist = 4.0; + anAlgo.Add(aDist, anEdge); + // Make a chamfer. + anAlgo.Build(); + Standard_ASSERT_VOID(anAlgo.IsDone(), "Couldn't prepare a box with a chamfer!"); + // Get a box with a chamfer. + TopoDS_Shape aBoxWithChamfer = anAlgo.Shape(); + myResult << "Box with a chamfer is in yellow shading" << std::endl; + + Handle(AIS_ColoredShape) anAisBoxWithChamfer = new AIS_ColoredShape(aBoxWithChamfer); + anAisBoxWithChamfer->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + myObject3d.Append(anAisBoxWithChamfer); + myContext->SetDisplayMode(anAisBoxWithChamfer, 1, Standard_True); + + // Retrieve chamfer faces generated from the edge + const TopTools_ListOfShape& aGenShapes = anAlgo.Generated(anEdge); + Standard_ASSERT_VOID(!aGenShapes.IsEmpty(), "Chamfer face is expected!"); + for (TopTools_ListOfShape::Iterator anIt(aGenShapes); anIt.More(); anIt.Next()) + { + Handle(AIS_ColoredShape) anAisShape = new AIS_ColoredShape(anIt.Value()); + anAisShape->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + anAisShape->SetWidth(2.5); + myObject3d.Append(anAisShape); + myContext->SetDisplayMode(anAisBoxWithChamfer, 1, Standard_True); + } + myResult << "Chamfer faces : " << aGenShapes.Size() << std::endl; + myResult << "The first one is using to remove" << std::endl; + myResult << "The removed face is in green" << std::endl; + + // Initialize defeaturing algo. + BRepAlgoAPI_Defeaturing aDefeatAlgo; + aDefeatAlgo.SetShape(aBoxWithChamfer); + aDefeatAlgo.AddFaceToRemove(aGenShapes.First()); + + // Remove the chamfer. + aDefeatAlgo.Build(); + + if (aDefeatAlgo.IsDone()) + { + // Get result. + TopoDS_Shape aResult = aDefeatAlgo.Shape(); + myResult << "Defeatured box is in red wireframe" << std::endl; + + Handle(AIS_ColoredShape) anAisResult = new AIS_ColoredShape(aResult); + anAisResult->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisResult); + myContext->SetDisplayMode(anAisResult, 0, Standard_True); + } +} + +void TopologySamples::Fillet3dSample() +{ + // Make a box with a corner at [0, 0, 0] and the specified sizes. + Standard_Real aSizeX = 8.0; + Standard_Real aSizeY = 10.0; + Standard_Real aSizeZ = 15.0; + TopoDS_Shape aBox = BRepPrimAPI_MakeBox(aSizeX, aSizeY, aSizeZ); + myResult << "Box at corner [0, 0, 0] and sizes [" + << aSizeX << ", " << aSizeY << ", " << aSizeZ + << "] was created in yellow wireframe" << std::endl; + + // Initialize fillet algo. + BRepFilletAPI_MakeFillet anAlgo(aBox); + + // Set edge to apply a fillet with specified radius. + // Select the first edge in the map returned by TopExp::MapShapes method. + TopTools_IndexedMapOfShape anEdges; + TopExp::MapShapes(aBox, TopAbs_EDGE, anEdges); + TopoDS_Edge anEdge = TopoDS::Edge(anEdges.FindKey(1)); + Standard_Real aRadius = 3.0; + anAlgo.Add(aRadius, anEdge); + myResult << "Make a fillet of " << aRadius << " radius on an edge in green" << std::endl; + + Handle(AIS_ColoredShape) anAisBox = new AIS_ColoredShape(aBox); + Handle(AIS_ColoredShape) anAisEdge = new AIS_ColoredShape(anEdge); + anAisBox->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisEdge->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + anAisEdge->SetWidth(2.5); + myObject3d.Append(anAisBox); + myObject3d.Append(anAisEdge); + myContext->SetDisplayMode(anAisBox, 0, Standard_True); + + // Make a fillet. + anAlgo.Build(); + + if (anAlgo.IsDone()) + { + // Get result. + TopoDS_Shape aResult = anAlgo.Shape(); + myResult << "Fillet was built. Result shape is in red shading" << std::endl; + + Handle(AIS_ColoredShape) anAisResult = new AIS_ColoredShape(aResult); + anAisResult->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisResult); + myContext->SetDisplayMode(anAisResult, 1, Standard_True); + } +} + +void TopologySamples::Chamfer3dSample() +{ + // Make a box with a corner at [0, 0, 0] and the specified sizes. + Standard_Real aSizeX = 8.0; + Standard_Real aSizeY = 10.0; + Standard_Real aSizeZ = 15.0; + TopoDS_Shape aBox = BRepPrimAPI_MakeBox(aSizeX, aSizeY, aSizeZ); + myResult << "Box at corner [0, 0, 0] and sizes [" + << aSizeX << ", " << aSizeY << ", " << aSizeZ + << "] was created in yellow wirewrame" << std::endl; + + // Initialize chamfer algo. + BRepFilletAPI_MakeChamfer anAlgo(aBox); + + // Set edge to apply a chamfer with specified distance from it. + // Select the 5th edge in the map returned by TopExp::MapShapes method. + TopTools_IndexedMapOfShape anEdges; + TopExp::MapShapes(aBox, TopAbs_EDGE, anEdges); + TopoDS_Edge anEdge = TopoDS::Edge(anEdges.FindKey(5)); + Standard_Real aDist = 4.0; + anAlgo.Add(aDist, anEdge); + myResult << "Make a chamfer of " << aDist << " size on an edge in green" << std::endl; + + Handle(AIS_ColoredShape) anAisBox = new AIS_ColoredShape(aBox); + Handle(AIS_ColoredShape) anAisEdge = new AIS_ColoredShape(anEdge); + anAisBox->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisEdge->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + anAisEdge->SetWidth(2.5); + myObject3d.Append(anAisBox); + myObject3d.Append(anAisEdge); + myContext->SetDisplayMode(anAisBox, 0, Standard_True); + + // Make a chamfer. + anAlgo.Build(); + if (anAlgo.IsDone()) + { + // Get result. + TopoDS_Shape aResult = anAlgo.Shape(); + myResult << "Fillet was built. Result shape is in red shading" << std::endl; + + Handle(AIS_ColoredShape) anAisResult = new AIS_ColoredShape(aResult); + anAisResult->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisResult); + myContext->SetDisplayMode(anAisResult, 1, Standard_True); + + const TopTools_ListOfShape& aGenShapes = anAlgo.Generated(anEdge); + for (TopTools_ListOfShape::Iterator anIt(aGenShapes); anIt.More(); anIt.Next()) + { + Handle(AIS_ColoredShape) anAisShape = new AIS_ColoredShape(anIt.Value()); + anAisShape->SetColor(Quantity_Color(Quantity_NOC_RED)); + anAisShape->SetWidth(2.5); + myObject3d.Append(anAisShape); + } + } +} + +void TopologySamples::Offset3dSample() +{ + // Make a triangle wire. + BRepBuilderAPI_MakePolygon aTria; + TopoDS_Vertex aVertA = BRepBuilderAPI_MakeVertex(gp_Pnt(-0.5, 0.0, 0.0)); + TopoDS_Vertex aVertB = BRepBuilderAPI_MakeVertex(gp_Pnt(0.0, 0.0, +1.0)); + TopoDS_Vertex aVertC = BRepBuilderAPI_MakeVertex(gp_Pnt(+0.5, 0.0, 0.0)); + aTria.Add(aVertA); + aTria.Add(aVertB); + aTria.Add(aVertC); + aTria.Close(); + TopoDS_Wire aWire = aTria.Wire(); + myResult << "Trianglular wire was created in yellow" << std::endl; + + Handle(AIS_ColoredShape) anAisWire = new AIS_ColoredShape(aWire); + anAisWire->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + myObject3d.Append(anAisWire); + + // Initialize offset algo. + BRepOffsetAPI_MakeOffset anAlgo(aWire); + + // Perform a series of offsets with linearly increasing value and altitude. + Standard_Real anOffsetStep = 0.2; + Standard_Real anAltitudeStep = 0.1; + for (Standard_Integer i = 1; i <= 4; ++i) + { + Standard_Real anOffset = anOffsetStep * i; + Standard_Real anAltitude = anAltitudeStep * i; + anAlgo.Perform(anOffset, anAltitude); + if (anAlgo.IsDone()) + { + // Get result. + TopoDS_Shape aResult = anAlgo.Shape(); + myResult << "#" << i << " : Offest = " << anOffset << " Altitude = " << anAltitude + << ". Result is in red." << std::endl; + + Handle(AIS_ColoredShape) anAisResult = new AIS_ColoredShape(aResult); + anAisResult->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisResult); + } + } +} + +void TopologySamples::Evolved3dSample() +{ + // Make a triangle wire as a spine. + BRepBuilderAPI_MakePolygon aTria; + TopoDS_Vertex aVertA = BRepBuilderAPI_MakeVertex(gp_Pnt(-0.5, 0.0, 0.0)); + TopoDS_Vertex aVertB = BRepBuilderAPI_MakeVertex(gp_Pnt(0.0, +1.0, 0.0)); + TopoDS_Vertex aVertC = BRepBuilderAPI_MakeVertex(gp_Pnt(+0.5, 0.0, 0.0)); + aTria.Add(aVertA); + aTria.Add(aVertB); + aTria.Add(aVertC); + aTria.Close(); + TopoDS_Wire aSpine = aTria.Wire(); + myResult << "Profile wire was created in yellow" << std::endl; + + // Make a wire as a profile. + BRepBuilderAPI_MakePolygon aPoly; + TopoDS_Vertex aVert1 = BRepBuilderAPI_MakeVertex(gp_Pnt(-0.5, 0.0, 0.0)); + TopoDS_Vertex aVert2 = BRepBuilderAPI_MakeVertex(gp_Pnt(-0.5, -0.1, 0.5)); + TopoDS_Vertex aVert3 = BRepBuilderAPI_MakeVertex(gp_Pnt(-0.5, -0.2, 1.0)); + aPoly.Add(aVert1); + aPoly.Add(aVert2); + aPoly.Add(aVert3); + TopoDS_Wire aProfile = aPoly.Wire(); + myResult << "Spine wire was created in greed" << std::endl; + + Handle(AIS_ColoredShape) anAisSpine = new AIS_ColoredShape(aSpine); + Handle(AIS_ColoredShape) anAisProfile = new AIS_ColoredShape(aProfile); + anAisSpine->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisSpine->SetWidth(2.5); + anAisProfile->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + anAisProfile->SetWidth(2.5); + myObject3d.Append(anAisSpine); + myObject3d.Append(anAisProfile); + + // Initialize evolving algo. + GeomAbs_JoinType aJoinType = GeomAbs_Arc; + Standard_Boolean aIsGlobalCS = Standard_False; + Standard_Boolean aIsSolid = Standard_True; + BRepOffsetAPI_MakeEvolved anAlgo(aSpine, aProfile, aJoinType, aIsGlobalCS, aIsSolid); + + // Perform evolving. + anAlgo.Build(); + + if (anAlgo.IsDone()) + { + // Get result. + TopoDS_Shape aResult = anAlgo.Shape(); + myResult << "Evolving result is in red" << std::endl; + + Handle(AIS_ColoredShape) anAisResult = new AIS_ColoredShape(aResult); + anAisResult->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisResult); + } +} + +void TopologySamples::Copy3dSample() +{ + // Make a box with a corner at [0, 0, 0] and the specified sizes. + Standard_Real aSizeX = 10.0; + Standard_Real aSizeY = 15.0; + Standard_Real aSizeZ = 20.0; + BRepPrimAPI_MakeBox aBoxMake(aSizeX, aSizeY, aSizeZ); + TopoDS_Shape aBox = aBoxMake.Shape(); + myResult << "Box at corner [0, 0, 0] and sizes [" + << aSizeX << ", " << aSizeY << ", " << aSizeZ + << "] was created in yellow" << std::endl; + + // Make a box copy. + TopoDS_Shape aBoxCopy = BRepBuilderAPI_Copy(aBox); + myResult << "Box copy was created in red" << std::endl; + + gp_Trsf aTrsf1; aTrsf1.SetTranslation(gp_Vec(15.0, 0.0, 0.0)); + aBoxCopy.Move(aTrsf1); + myResult << "Box copy shape is moved apart for illustativeness" << std::endl; + + Handle(AIS_ColoredShape) anAisBox = new AIS_ColoredShape(aBox); + anAisBox->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisBox->SetWidth(2.5); + Handle(AIS_ColoredShape) anAisBoxCopy = new AIS_ColoredShape(aBoxCopy); + anAisBoxCopy->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisBox); + myObject3d.Append(anAisBoxCopy); +} + +void TopologySamples::Transform3dSample() +{ + // Make a box with a corner at [0, 0, 0] and the specified sizes. + Standard_Real aSizeX = 10.0; + Standard_Real aSizeY = 15.0; + Standard_Real aSizeZ = 20.0; + BRepPrimAPI_MakeBox aBoxMake(aSizeX, aSizeY, aSizeZ); + TopoDS_Shape aBox = aBoxMake.Shape(); + myResult << "Box at corner [0, 0, 0] and sizes [" + << aSizeX << ", " << aSizeY << ", " << aSizeZ + << "] was created in yellow" << std::endl; + + // Move the box. + gp_Trsf aTrMove; aTrMove.SetTranslation(gp_Vec(15.0, 20.0, 25.0)); + TopoDS_Shape aMovedBox = BRepBuilderAPI_Transform(aBox, aTrMove, Standard_True); + myResult << "Moved box in green" << std::endl; + + // Rotate the moved box + gp_Trsf aTrRot; aTrRot.SetRotation(gp_Ax1(gp_Pnt(15.0, 20.0, 25.0), gp::DZ()), 3.0*M_PI_4); + TopoDS_Shape aRotatedBox = BRepBuilderAPI_Transform(aBox, aTrRot, Standard_True); + myResult << "Rotated box in red" << std::endl; + + Handle(AIS_ColoredShape) anAisBox = new AIS_ColoredShape(aBox); + Handle(AIS_ColoredShape) anAisMovedBox = new AIS_ColoredShape(aMovedBox); + Handle(AIS_ColoredShape) anAisRotatedBox = new AIS_ColoredShape(aRotatedBox); + anAisBox->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisMovedBox->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + anAisRotatedBox->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisBox); + myObject3d.Append(anAisMovedBox); + myObject3d.Append(anAisRotatedBox); +} + +void TopologySamples::ConvertToNurbs3dSample() +{ + // Make a torus face. + gp_Torus aTorus(gp::XOY(), 20.0, 7.5); + TopoDS_Shape aTorusFace = BRepBuilderAPI_MakeFace(aTorus); + myResult << "TopoDS_Solid on the torus with" << std::endl + << "R major = " << aTorus.MajorRadius() << std::endl + << "R minor = " << aTorus.MinorRadius() << std::endl + << "was created in yellow" << std::endl; + + // Convert faces/edges from analytic to NURBS geometry. + TopoDS_Shape aNurbsFace = BRepBuilderAPI_NurbsConvert(aTorusFace); + myResult << "Converted torus in red" << std::endl; + gp_Trsf aTrsf1; aTrsf1.SetTranslation(gp_Vec(60.0, 0.0, 0.0)); + aNurbsFace.Move(aTrsf1); + myResult << "Converted torus is moved apart for illustativeness" << std::endl; + + Handle(AIS_ColoredShape) anAisTorus = new AIS_ColoredShape(aTorusFace); + Handle(AIS_ColoredShape) anAisNurbs = new AIS_ColoredShape(aNurbsFace); + anAisTorus->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisTorus->SetWidth(2.5); + anAisNurbs->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisTorus); + myObject3d.Append(anAisNurbs); +} + +void TopologySamples::SewContiguousFaces3dSample() +{ + // Make a sphere. + gp_Sphere aSphere(gp::XOY(), 1.0); + // South hemisphere. + TopoDS_Face aFace1 = BRepBuilderAPI_MakeFace(aSphere, 0.0, 2.0 * M_PI, -M_PI_2, 0.0); + // North hemisphere. + TopoDS_Face aFace2 = BRepBuilderAPI_MakeFace(aSphere, 0.0, 2.0 * M_PI, 0.0, +M_PI_2); + + // Make a default tailor. + BRepBuilderAPI_Sewing aTailor; + + // Add hemisphere faces. + aTailor.Add(aFace1); + aTailor.Add(aFace2); + + // Perform sewing. + aTailor.Perform(); + + // Get result. + const TopoDS_Shape& aSewedSphere = aTailor.SewedShape(); + myResult << "Two hemispheres were sewed : " << aTailor.NbFreeEdges() << " free edges" << std::endl; + + Handle(AIS_ColoredShape) anAisSewedSphere = new AIS_ColoredShape(aSewedSphere); + anAisSewedSphere->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisSewedSphere); +} + +void TopologySamples::CheckValidity3dSample() +{ + // Make a box with a corner at [0, 0, 0] and the specified sizes. + Standard_Real aSizeX = 10.0; + Standard_Real aSizeY = 15.0; + Standard_Real aSizeZ = 20.0; + BRepPrimAPI_MakeBox aBoxMake(aSizeX, aSizeY, aSizeZ); + TopoDS_Shape aBox = aBoxMake.Shape(); + myResult << "Box at corner [0, 0, 0] and sizes [" + << aSizeX << ", " << aSizeY << ", " << aSizeZ + << "] was created in yellow" << std::endl; + + // Analyze the box. + BRepCheck_Analyzer anAnalyzer(aBox); + myResult << "Box is " << (anAnalyzer.IsValid() ? "valid" : "invalid") << std::endl; + + // Make the box invalid manually. + Handle(BRepTools_ReShape) aReShape = new BRepTools_ReShape(); + myResult << "Remove the top face from the box (red)" << std::endl; + aReShape->Remove(aBoxMake.TopFace()); + TopoDS_Shape aBox1 = aReShape->Apply(aBox); + myResult << "The top face was removed" << std::endl; + + // Analyze the modified box. + BRepCheck_Analyzer anAnalyzer1(aBox1); + myResult << "Modified box is " << (anAnalyzer1.IsValid() ? "valid" : "invalid") << std::endl; + + Handle(AIS_ColoredShape) anAisBox = new AIS_ColoredShape(aBox); + Handle(AIS_ColoredShape) anAisTopFace = new AIS_ColoredShape(aBoxMake.TopFace()); + anAisBox->SetColor(Quantity_Color(Quantity_NOC_YELLOW)); + anAisTopFace->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject3d.Append(anAisBox); + myObject3d.Append(anAisTopFace); +} + +void TopologySamples::ComputeLinearProperties3dSample() +{ + // Make an edge from a circular segment. + // Create a circle in XY plane of the radius 1.0. + gp_Circ aCirc(gp::XOY(), 1.0); + // Make a circular edge from the 1st quoter in the parametric space. + TopoDS_Edge aShape = BRepBuilderAPI_MakeEdge(aCirc, 0.0, M_PI); + myResult << "TopoDS_Edge on the circle's 1st quoter" << std::endl + << "with the center at [ " + << aCirc.Location().X() << ", " << aCirc.Location().Y() << ", " << aCirc.Location().Z() + << " ] and R = " << aCirc.Radius() << " was created in red" << std::endl + << std::endl; + + // Retrieve linear properties from the edge. + GProp_GProps aGProps; + BRepGProp::LinearProperties(aShape, aGProps); + Standard_Real aLength = aGProps.Mass(); + gp_Pnt aCOM = aGProps.CentreOfMass(); + Standard_Real anIx, anIy, anIz; + aGProps.StaticMoments(anIx, anIy, anIz); + gp_Mat aMOI = aGProps.MatrixOfInertia(); + myResult << "Linear properties:" << std::endl + << " Length = " << aLength << std::endl + << " Center of mass = [ " << aCOM.X() << ", " << aCOM.Y() << ", " << aCOM.Z() << " ]" << std::endl + << " Static moments = [ " << anIx << ", " << anIy << ", " << anIz << " ]" << std::endl + << " Matrix of inertia = [ " + << aMOI(1, 1) << ", " << aMOI(1, 2) << ", " << aMOI(1, 3) << std::endl + << std::setw(33) << aMOI(2, 1) << ", " << aMOI(2, 2) << ", " << aMOI(2, 3) << std::endl + << std::setw(33) << aMOI(3, 1) << ", " << aMOI(3, 2) << ", " << aMOI(3, 3) << " ]" << std::endl; + GProp_PrincipalProps aPProps = aGProps.PrincipalProperties(); + Standard_Real anIxx, anIyy, anIzz; + aPProps.Moments(anIxx, anIyy, anIzz); + Standard_Real aRxx, aRyy, aRzz; + aPProps.RadiusOfGyration(aRxx, aRyy, aRzz); + myResult << "Principal properties:" << std::endl + << " Has symmetric axis : " << (aPProps.HasSymmetryAxis() ? "YES" : "NO") << std::endl + << " Has symmetric point : " << (aPProps.HasSymmetryPoint() ? "YES" : "NO") << std::endl + << " Moments of inertia = [ " << anIxx << ", " << anIyy << ", " << anIzz << " ]" << std::endl + << " Radius of gyration = [ " << aRxx << ", " << aRyy << ", " << aRzz << " ]" << std::endl; + if (!aPProps.HasSymmetryPoint()) + { + const gp_Vec& anAxis1 = aPProps.FirstAxisOfInertia(); + myResult << " 1st axis of inertia = [ " << anAxis1.X() << ", " << anAxis1.Y() << ", " << anAxis1.Z() << " ]" << std::endl; + Handle(AIS_ColoredShape) anAisAxis1 = new AIS_ColoredShape( + BRepBuilderAPI_MakeEdge(aCOM, aCOM.XYZ() + anAxis1.XYZ())); + anAisAxis1->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisAxis1); + if (!aPProps.HasSymmetryPoint()) + { + const gp_Vec& anAxis2 = aPProps.SecondAxisOfInertia(); + myResult << " 2nd axis of inertia = [ " << anAxis2.X() << ", " << anAxis2.Y() << ", " << anAxis2.Z() << " ]" << std::endl; + Handle(AIS_ColoredShape) anAisAxis2 = new AIS_ColoredShape( + BRepBuilderAPI_MakeEdge(aCOM, aCOM.XYZ() + anAxis2.XYZ())); + anAisAxis2->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisAxis2); + const gp_Vec& anAxis3 = aPProps.ThirdAxisOfInertia(); + myResult << " 3rd axis of inertia = [ " << anAxis3.X() << ", " << anAxis3.Y() << ", " << anAxis3.Z() << " ]" << std::endl; + Handle(AIS_ColoredShape) anAisAxis3 = new AIS_ColoredShape( + BRepBuilderAPI_MakeEdge(aCOM, aCOM.XYZ() + anAxis3.XYZ())); + anAisAxis3->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisAxis3); + } + } + + Handle(AIS_ColoredShape) anAisShape = new AIS_ColoredShape(aShape); + Handle(AIS_Point) anAisCOM = new AIS_Point(new Geom_CartesianPoint(aCOM)); + anAisShape->SetColor(Quantity_Color(Quantity_NOC_RED)); + Handle(AIS_TextLabel) aCOMLabel = new AIS_TextLabel(); + aCOMLabel->SetText("Center of mass"); + aCOMLabel->SetPosition(aCOM); + Handle(AIS_Axis) anAisAxisX = new AIS_Axis(new Geom_Axis2Placement(gp::YOZ()), AIS_TOAX_XAxis); + Handle(AIS_Axis) anAisAxisY = new AIS_Axis(new Geom_Axis2Placement(gp::ZOX()), AIS_TOAX_YAxis); + Handle(AIS_Axis) anAisAxisZ = new AIS_Axis(new Geom_Axis2Placement(gp::XOY()), AIS_TOAX_ZAxis); + myObject3d.Append(anAisAxisX); + myObject3d.Append(anAisAxisY); + myObject3d.Append(anAisAxisZ); + myObject3d.Append(anAisShape); + myObject3d.Append(anAisCOM); + myObject3d.Append(aCOMLabel); +} + +void TopologySamples::ComputeSurfaceProperties3dSample() +{ + // Make a face from a cylinder with R = 1 + // and directed along Z axis + gp_Cylinder aCyl(gp::XOY(), 1.0); + TopoDS_Face aShape = BRepBuilderAPI_MakeFace(aCyl, 0.0, M_PI, -1.0, +1.0).Face(); + myResult << "TopoDS_Face on the cylinder R = " << aCyl.Radius() << std::endl + << "with axis [ " << aCyl.Position().Direction().X() << ", " << aCyl.Position().Direction().Y() << ", " << aCyl.Position().Direction().Z() << " ]" << std::endl + << "limited in length [-1 ... +1] was created in red" << std::endl; + + // Retrieve surface properties from the face. + GProp_GProps aGProps; + BRepGProp::SurfaceProperties(aShape, aGProps); + Standard_Real aArea = aGProps.Mass(); + gp_Pnt aCOM = aGProps.CentreOfMass(); + Standard_Real anIx, anIy, anIz; + aGProps.StaticMoments(anIx, anIy, anIz); + gp_Mat aMOI = aGProps.MatrixOfInertia(); + myResult << "Linear properties:" << std::endl + << " Area = " << aArea << std::endl + << " Center of mass = [ " << aCOM.X() << ", " << aCOM.Y() << ", " << aCOM.Z() << " ]" << std::endl + << " Static moments = [ " << anIx << ", " << anIy << ", " << anIz << " ]" << std::endl + << " Matrix of inertia = [ " + << aMOI(1, 1) << ", " << aMOI(1, 2) << ", " << aMOI(1, 3) << std::endl + << std::setw(33) << aMOI(2, 1) << ", " << aMOI(2, 2) << ", " << aMOI(2, 3) << std::endl + << std::setw(33) << aMOI(3, 1) << ", " << aMOI(3, 2) << ", " << aMOI(3, 3) << " ]" << std::endl; + GProp_PrincipalProps aPProps = aGProps.PrincipalProperties(); + Standard_Real anIxx, anIyy, anIzz; + aPProps.Moments(anIxx, anIyy, anIzz); + Standard_Real aRxx, aRyy, aRzz; + aPProps.RadiusOfGyration(aRxx, aRyy, aRzz); + myResult << "Principal properties:" << std::endl + << " Has symmetric axis : " << (aPProps.HasSymmetryAxis() ? "YES" : "NO") << std::endl + << " Has symmetric point : " << (aPProps.HasSymmetryPoint() ? "YES" : "NO") << std::endl + << " Moments of inertia = [ " << anIxx << ", " << anIyy << ", " << anIzz << " ]" << std::endl + << " Radius of gyration = [ " << aRxx << ", " << aRyy << ", " << aRzz << " ]" << std::endl; + if (!aPProps.HasSymmetryPoint()) + { + const gp_Vec& anAxis1 = aPProps.FirstAxisOfInertia(); + myResult << " 1st axis of inertia = [ " << anAxis1.X() << ", " << anAxis1.Y() << ", " << anAxis1.Z() << " ]" << std::endl; + Handle(AIS_ColoredShape) anAisAxis1 = new AIS_ColoredShape( + BRepBuilderAPI_MakeEdge(aCOM, aCOM.XYZ() + anAxis1.XYZ())); + anAisAxis1->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisAxis1); + if (!aPProps.HasSymmetryPoint()) + { + const gp_Vec& anAxis2 = aPProps.SecondAxisOfInertia(); + myResult << " 2nd axis of inertia = [ " << anAxis2.X() << ", " << anAxis2.Y() << ", " << anAxis2.Z() << " ]" << std::endl; + Handle(AIS_ColoredShape) anAisAxis2 = new AIS_ColoredShape( + BRepBuilderAPI_MakeEdge(aCOM, aCOM.XYZ() + anAxis2.XYZ())); + anAisAxis2->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisAxis2); + const gp_Vec& anAxis3 = aPProps.ThirdAxisOfInertia(); + myResult << " 3rd axis of inertia = [ " << anAxis3.X() << ", " << anAxis3.Y() << ", " << anAxis3.Z() << " ]" << std::endl; + Handle(AIS_ColoredShape) anAisAxis3 = new AIS_ColoredShape( + BRepBuilderAPI_MakeEdge(aCOM, aCOM.XYZ() + anAxis3.XYZ())); + anAisAxis3->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisAxis3); + } + } + + Handle(AIS_ColoredShape) anAisShape = new AIS_ColoredShape(aShape); + Handle(AIS_Point) anAisCOM = new AIS_Point(new Geom_CartesianPoint(aCOM)); + anAisShape->SetColor(Quantity_Color(Quantity_NOC_RED)); + Handle(AIS_TextLabel) aCOMLabel = new AIS_TextLabel(); + aCOMLabel->SetText("Center of mass"); + aCOMLabel->SetPosition(aCOM); + Handle(AIS_Axis) anAisAxisX = new AIS_Axis(new Geom_Axis2Placement(gp::YOZ()), AIS_TOAX_XAxis); + Handle(AIS_Axis) anAisAxisY = new AIS_Axis(new Geom_Axis2Placement(gp::ZOX()), AIS_TOAX_YAxis); + Handle(AIS_Axis) anAisAxisZ = new AIS_Axis(new Geom_Axis2Placement(gp::XOY()), AIS_TOAX_ZAxis); + myObject3d.Append(anAisAxisX); + myObject3d.Append(anAisAxisY); + myObject3d.Append(anAisAxisZ); + myObject3d.Append(anAisShape); + myObject3d.Append(anAisCOM); + myObject3d.Append(aCOMLabel); +} + +void TopologySamples::ComputeVolumeProperties3dSample() +{ + // Make a box by two points. + gp_Pnt aPnt1(-0.5, -0.6, -0.7); + gp_Pnt aPnt2(+0.8, +0.9, +1.0); + TopoDS_Shape aShape = BRepPrimAPI_MakeBox(aPnt1, aPnt2); + myResult << "Box with corners [" << aPnt1.X() << ", " << aPnt1.Y() << ", " << aPnt1.Z() + << "] and [" << aPnt2.X() << ", " << aPnt2.Y() << ", " << aPnt2.Z() + << "] was created in red" << std::endl; + + // Retrieve volume properties from the face. + GProp_GProps aGProps; + BRepGProp::VolumeProperties(aShape, aGProps); + Standard_Real aVolume = aGProps.Mass(); + gp_Pnt aCOM = aGProps.CentreOfMass(); + Standard_Real anIx, anIy, anIz; + aGProps.StaticMoments(anIx, anIy, anIz); + gp_Mat aMOI = aGProps.MatrixOfInertia(); + myResult << "Linear properties:" << std::endl + << " Volume = " << aVolume << std::endl + << " Center of mass = [ " << aCOM.X() << ", " << aCOM.Y() << ", " << aCOM.Z() << " ]" << std::endl + << " Static moments = [ " << anIx << ", " << anIy << ", " << anIz << " ]" << std::endl + << " Matrix of inertia = [ " + << aMOI(1, 1) << ", " << aMOI(1, 2) << ", " << aMOI(1, 3) << std::endl + << std::setw(33) << aMOI(2, 1) << ", " << aMOI(2, 2) << ", " << aMOI(2, 3) << std::endl + << std::setw(33) << aMOI(3, 1) << ", " << aMOI(3, 2) << ", " << aMOI(3, 3) << " ]" << std::endl; + GProp_PrincipalProps aPProps = aGProps.PrincipalProperties(); + Standard_Real anIxx, anIyy, anIzz; + aPProps.Moments(anIxx, anIyy, anIzz); + Standard_Real aRxx, aRyy, aRzz; + aPProps.RadiusOfGyration(aRxx, aRyy, aRzz); + myResult << "Principal properties:" << std::endl + << " Has symmetric axis : " << (aPProps.HasSymmetryAxis() ? "YES" : "NO") << std::endl + << " Has symmetric point : " << (aPProps.HasSymmetryPoint() ? "YES" : "NO") << std::endl + << " Moments of inertia = [ " << anIxx << ", " << anIyy << ", " << anIzz << " ]" << std::endl + << " Radius of gyration = [ " << aRxx << ", " << aRyy << ", " << aRzz << " ]" << std::endl; + if (!aPProps.HasSymmetryPoint()) + { + const gp_Vec& anAxis1 = aPProps.FirstAxisOfInertia(); + myResult << " 1st axis of inertia = [ " << anAxis1.X() << ", " << anAxis1.Y() << ", " << anAxis1.Z() << " ]" << std::endl; + Handle(AIS_ColoredShape) anAisAxis1 = new AIS_ColoredShape( + BRepBuilderAPI_MakeEdge(aCOM, aCOM.XYZ() + anAxis1.XYZ())); + anAisAxis1->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisAxis1); + if (!aPProps.HasSymmetryPoint()) + { + const gp_Vec& anAxis2 = aPProps.SecondAxisOfInertia(); + myResult << " 2nd axis of inertia = [ " << anAxis2.X() << ", " << anAxis2.Y() << ", " << anAxis2.Z() << " ]" << std::endl; + Handle(AIS_ColoredShape) anAisAxis2 = new AIS_ColoredShape( + BRepBuilderAPI_MakeEdge(aCOM, aCOM.XYZ() + anAxis2.XYZ())); + anAisAxis2->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisAxis2); + const gp_Vec& anAxis3 = aPProps.ThirdAxisOfInertia(); + myResult << " 3rd axis of inertia = [ " << anAxis3.X() << ", " << anAxis3.Y() << ", " << anAxis3.Z() << " ]" << std::endl; + Handle(AIS_ColoredShape) anAisAxis3 = new AIS_ColoredShape( + BRepBuilderAPI_MakeEdge(aCOM, aCOM.XYZ() + anAxis3.XYZ())); + anAisAxis3->SetColor(Quantity_Color(Quantity_NOC_GREEN)); + myObject3d.Append(anAisAxis3); + } + } + + Handle(AIS_ColoredShape) anAisShape = new AIS_ColoredShape(aShape); + Handle(AIS_Point) anAisCOM = new AIS_Point(new Geom_CartesianPoint(aCOM)); + anAisShape->SetColor(Quantity_Color(Quantity_NOC_RED)); + Handle(AIS_TextLabel) aCOMLabel = new AIS_TextLabel(); + aCOMLabel->SetText("Center of mass"); + aCOMLabel->SetPosition(aCOM); + Handle(AIS_Axis) anAisAxisX = new AIS_Axis(new Geom_Axis2Placement(gp::YOZ()), AIS_TOAX_XAxis); + Handle(AIS_Axis) anAisAxisY = new AIS_Axis(new Geom_Axis2Placement(gp::ZOX()), AIS_TOAX_YAxis); + Handle(AIS_Axis) anAisAxisZ = new AIS_Axis(new Geom_Axis2Placement(gp::XOY()), AIS_TOAX_ZAxis); + myObject3d.Append(anAisAxisX); + myObject3d.Append(anAisAxisY); + myObject3d.Append(anAisAxisZ); + myObject3d.Append(anAisShape); + myObject3d.Append(anAisCOM); + myObject3d.Append(aCOMLabel); +} diff --git a/samples/OCCTOverview/code/TopologySamples.h b/samples/OCCTOverview/code/TopologySamples.h new file mode 100644 index 0000000000..ecb6ca51ac --- /dev/null +++ b/samples/OCCTOverview/code/TopologySamples.h @@ -0,0 +1,80 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef TOPOLOGYSAMPLES_H +#define TOPOLOGYSAMPLES_H + +#include "BaseSample.h" + +#include + +//! Implements Topology samples +class TopologySamples : public BaseSample +{ + DEFINE_STANDARD_RTTI_INLINE(TopologySamples, BaseSample) +public: + + TopologySamples (const TCollection_AsciiString& theSampleSourcePath, + const Handle(AIS_InteractiveContext)& theContext) + : BaseSample(theSampleSourcePath, theContext) + {} + +protected: + virtual void ExecuteSample (const TCollection_AsciiString& theSampleName) Standard_OVERRIDE; + +private: + // One function for every sample + void Vertex3dSample(); + void Edge3dSample(); + void Face3dSample(); + void Wire3dSample(); + void Shell3dSample(); + void Solid3dSample(); + void Edge2dSample(); + void Box3dSample(); + void Cylinder3dSample(); + void Revolution3dSample(); + void TopologyIterator3dSample(); + void TopologyExplorer3dSample(); + void AssessToCurve3dSample(); + void AssessToCompositeCurve3dSample(); + void AssessToSurface3dSample(); + void Common3dSample(); + void Cut3dSample(); + void Fuse3dSample(); + void Section3dSample(); + void Splitter3dSample(); + void Defeaturing3dSample(); + void Fillet3dSample(); + void Chamfer3dSample(); + void Offset3dSample(); + void Evolved3dSample(); + void Copy3dSample(); + void Transform3dSample(); + void ConvertToNurbs3dSample(); + void SewContiguousFaces3dSample(); + void CheckValidity3dSample(); + void ComputeLinearProperties3dSample(); + void ComputeSurfaceProperties3dSample(); + void ComputeVolumeProperties3dSample(); +}; + +#endif //TOPOLOGYSAMPLES_H diff --git a/samples/OCCTOverview/code/Triangulation.json b/samples/OCCTOverview/code/Triangulation.json new file mode 100644 index 0000000000..9c3a8c5eba --- /dev/null +++ b/samples/OCCTOverview/code/Triangulation.json @@ -0,0 +1,10 @@ +{ + "Triangulation": { + + "Create Triangulation": [{ + "text": "Triangulation on shape", + "function": "Triangulation3dSample", + "description": "" + }] + } +} diff --git a/samples/OCCTOverview/code/TriangulationSamples.cxx b/samples/OCCTOverview/code/TriangulationSamples.cxx new file mode 100644 index 0000000000..eff114e831 --- /dev/null +++ b/samples/OCCTOverview/code/TriangulationSamples.cxx @@ -0,0 +1,118 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "TriangulationSamples.h" + +#include "MakeBottle.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void TriangulationSamples::ExecuteSample (const TCollection_AsciiString& theSampleName) +{ + Standard_Boolean anIsSamplePresent = Standard_True; + FindSourceCode(theSampleName); + if (theSampleName == "Triangulation3dSample") + { + Triangulation3dSample(); + } + else + { + myResult << "No function found: " << theSampleName; + myCode += TCollection_AsciiString("No function found: ") + theSampleName; + anIsSamplePresent = Standard_False; + } + myIsProcessed = anIsSamplePresent; +} + +void TriangulationSamples::Triangulation3dSample() +{ + TopoDS_Shape aBottle = MakeBottle(50, 70, 30); + BRepMesh_IncrementalMesh(aBottle, 1); + + BRep_Builder aBuilder; + TopoDS_Compound aCompound; + aBuilder.MakeCompound(aCompound); + + Standard_Integer aNbTriangles(0); + for (TopExp_Explorer anExplorer(aBottle, TopAbs_FACE); anExplorer.More(); anExplorer.Next()) + { + TopoDS_Face aFace = TopoDS::Face(anExplorer.Current()); + TopLoc_Location aLocation; + Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(aFace, aLocation); + + TColgp_Array1OfPnt aTriangNodes(1, (aTriangulation->NbNodes())); + aTriangNodes = aTriangulation->Nodes(); + Poly_Array1OfTriangle aTriangles(1, aTriangulation->NbTriangles()); + aTriangles = aTriangulation->Triangles(); + + for (Standard_Integer i = 1; i <= (aTriangulation->NbTriangles()); i++) + { + Poly_Triangle trian = aTriangles.Value(i); + Standard_Integer index1, index2, index3, M = 0, N = 0; + trian.Get(index1, index2, index3); + + for (Standard_Integer j = 1; j <= 3; j++) + { + switch (j) + { + case 1: + M = index1; + N = index2; + break; + case 2: + N = index3; + break; + case 3: + M = index2; + } + + BRepBuilderAPI_MakeEdge anEdgeMaker(aTriangNodes.Value(M), aTriangNodes.Value(N)); + if (anEdgeMaker.IsDone()) + { + aBuilder.Add(aCompound, anEdgeMaker.Edge()); + } + } + } + Handle(AIS_Triangulation) anAisTriangulation = new AIS_Triangulation(aTriangulation); + aNbTriangles += aTriangulation->NbTriangles(); + myObject3d.Append(anAisTriangulation); + } + + Handle(AIS_Shape) anAisCompound = new AIS_Shape(aCompound); + myObject3d.Append(anAisCompound); + + Handle(AIS_Shape) AISBottle = new AIS_Shape(aBottle); + myObject3d.Append(AISBottle); + + myResult << "Compute the triangulation on a shape: " << aNbTriangles; +} diff --git a/samples/OCCTOverview/code/TriangulationSamples.h b/samples/OCCTOverview/code/TriangulationSamples.h new file mode 100644 index 0000000000..aaab1fc070 --- /dev/null +++ b/samples/OCCTOverview/code/TriangulationSamples.h @@ -0,0 +1,49 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef TRIANGULATIONSAMPLES_H +#define TRIANGULATIONSAMPLES_H + +#include "BaseSample.h" + +//! Implements Triangulation sample +class TriangulationSamples : public BaseSample +{ + DEFINE_STANDARD_RTTI_INLINE(TriangulationSamples, BaseSample) +public: + + TriangulationSamples (const TCollection_AsciiString& theSampleSourcePath, + const Handle(AIS_InteractiveContext)& theContext) + : BaseSample (theSampleSourcePath, theContext) + { + // + } + +protected: + virtual void ExecuteSample (const TCollection_AsciiString& theSampleName) Standard_OVERRIDE; + +private: + // One function for every sample + void Triangulation3dSample(); + +}; + +#endif //TRIANGULATIONSAMPLES_H diff --git a/samples/OCCTOverview/code/Viewer2d.json b/samples/OCCTOverview/code/Viewer2d.json new file mode 100644 index 0000000000..f5d3a5c3d3 --- /dev/null +++ b/samples/OCCTOverview/code/Viewer2d.json @@ -0,0 +1,58 @@ +{ + "Viewer 2D": { + "Labels": [{ + "text": "Text", + "function": "TextView2dSample", + "description": "" + }, + { + "text": "Marker", + "function": "MarkerView2dSample", + "description": "" + }, + { + "text": "Fill Area", + "function": "FillAreaView2dSample", + "description": "" + }, + { + "text": "Loop on face", + "function": "LoopOnFaceView2dSample", + "description": "" + } + ], + + "Grids": [{ + "text": "Rectagular Lines", + "function": "RectagularLineGrid2dSample", + "description": "" + }, + { + "text": "Rectagular Points", + "function": "RectagularPointGrid2dSample", + "description": "" + }, + { + "text": "Circular Lines", + "function": "CircularLineGrid2dSample", + "description": "" + }, + { + "text": "Circular Points", + "function": "CircularPointGrid2dSample", + "description": "" + }, + { + "text": "Clear", + "function": "ClearGrid2dSample", + "description": "" + } + ], + + "Image": [{ + "text": "Backgroung Image", + "function": "BackgroungImage2dSample", + "description": "" + }] + } +} \ No newline at end of file diff --git a/samples/OCCTOverview/code/Viewer2dSamples.cxx b/samples/OCCTOverview/code/Viewer2dSamples.cxx new file mode 100644 index 0000000000..ece0317601 --- /dev/null +++ b/samples/OCCTOverview/code/Viewer2dSamples.cxx @@ -0,0 +1,282 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "Viewer2dSamples.h" + +#include "Sample2D_Markers.h" +#include "Sample2D_Face.h" +#include "Sample2D_Image.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void Viewer2dSamples::ExecuteSample (const TCollection_AsciiString& theSampleName) +{ + Standard_Boolean anIsSamplePresent = Standard_True; + FindSourceCode(theSampleName); + if (theSampleName == "TextView2dSample") + TextView2dSample(); + else if (theSampleName == "MarkerView2dSample") + MarkerView2dSample(); + else if (theSampleName == "FillAreaView2dSample") + FillAreaView2dSample(); + else if (theSampleName == "LoopOnFaceView2dSample") + LoopOnFaceView2dSample(); + else if (theSampleName == "RectagularLineGrid2dSample") + RectagularLineGrid2dSample(); + else if (theSampleName == "RectagularPointGrid2dSample") + RectagularPointGrid2dSample(); + else if (theSampleName == "CircularLineGrid2dSample") + CircularLineGrid2dSample(); + else if (theSampleName == "CircularPointGrid2dSample") + CircularPointGrid2dSample(); + else if (theSampleName == "ClearGrid2dSample") + ClearGrid2dSample(); + else if (theSampleName == "BackgroungImage2dSample") + BackgroungImage2dSample(); + else { + myResult << "No function found: " << theSampleName; + myCode += TCollection_AsciiString("No function found: ") + theSampleName; + anIsSamplePresent = Standard_False; + } + myIsProcessed = anIsSamplePresent; +} + +void Viewer2dSamples::ClearExtra() +{ + myContext->RemoveAll(Standard_True); + myViewer->DeactivateGrid(); +} + +void Viewer2dSamples::TextView2dSample() +{ + Standard_Integer aColor = Quantity_NameOfColor::Quantity_NOC_MATRABLUE; + for (Standard_Integer j = 15; j <= 20; j++) + { + Handle(AIS_TextLabel) aText = new AIS_TextLabel(); + aText->SetText(TCollection_AsciiString("font 0 scale ") + (j / 20.0)); + aText->SetPosition(gp_Pnt(0.0, 15.0 * (j - 15.0), 0.0)); + aText->SetAngle(30.0 * M_PI / 180.0); + aText->SetColor(Quantity_NameOfColor(aColor++)); + aText->SetFontAspect(Font_FA_Regular); + aText->SetFont("Courier"); + aText->SetHeight(j); + aText->SetHJustification(Graphic3d_HTA_LEFT); + aText->SetVJustification(Graphic3d_VTA_BOTTOM); + aText->SetZoomable(Standard_False); + myObject2d.Append(aText); + } + + for (Standard_Real j = 10; j <= 15; j++) + { + Handle(AIS_TextLabel) aText = new AIS_TextLabel(); + aText->SetText(TCollection_AsciiString("font 1 scale ") + (j / 10.0)); + aText->SetPosition(gp_Pnt(80.0, 15.0 * (j - 10.0), 0.0)); + aText->SetAngle(0.0); + aText->SetColor(Quantity_NameOfColor(aColor++)); + aText->SetFontAspect(Font_FA_BoldItalic); + aText->SetFont("Cambria"); + aText->SetHeight(j * 2); + aText->SetHJustification(Graphic3d_HTA_LEFT); + aText->SetVJustification(Graphic3d_VTA_BOTTOM); + aText->SetZoomable(Standard_False); + myObject2d.Append(aText); + } + + aColor = Quantity_NOC_MATRABLUE; + for (Standard_Real j = 5; j <= 10; j++) + { + Handle(AIS_TextLabel) aText = new AIS_TextLabel(); + aText->SetText(TCollection_AsciiString("font 2 scale ") + (j / 10.0)); + aText->SetPosition(gp_Pnt(140.0, 15.0 * (j - 5.0), 0.0)); + aText->SetAngle(0.0); + aText->SetColor(Quantity_NameOfColor(aColor++)); + aText->SetFontAspect(Font_FA_Bold); + aText->SetFont("Arial"); + aText->SetHeight(j * 2); + aText->SetHJustification(Graphic3d_HTA_LEFT); + aText->SetVJustification(Graphic3d_VTA_BOTTOM); + aText->SetZoomable(Standard_False); + myObject2d.Append(aText); + } + for (Standard_Real j = 10; j <= 15; j++) + { + Handle(AIS_TextLabel) aText = new AIS_TextLabel(); + aText->SetText(TCollection_AsciiString("font 3 scale ") + (j / 10.0)); + aText->SetPosition(gp_Pnt(200.0, 15.0 * (j - 10.0), 0.0)); + aText->SetAngle(0.0); + aText->SetColor(Quantity_NameOfColor(aColor++)); + aText->SetFontAspect(Font_FA_Italic); + aText->SetFont("Georgia"); + aText->SetHeight(j * 2); + aText->SetHJustification(Graphic3d_HTA_LEFT); + aText->SetVJustification(Graphic3d_VTA_BOTTOM); + aText->SetZoomable(Standard_False); + myObject2d.Append(aText); + } +} + +void Viewer2dSamples::MarkerView2dSample() +{ + // generic Markers + Standard_Integer aColor = 20; + for (int i = 1; i <= 2; i++) + { + Handle(Sample2D_Markers) aMarker = new Sample2D_Markers(10 + 5, 5 * i, Aspect_TOM_POINT, Quantity_NOC_YELLOW, 2.0); + myObject2d.Append(aMarker); + } + for (int i = 1; i <= 2; i++) + { + Handle(Sample2D_Markers) aMarker = new Sample2D_Markers(10 + 10, 5 * i, Aspect_TOM_O, (Quantity_NameOfColor)(aColor++)); + myObject2d.Append(aMarker); + } + for (int i = 1; i <= 2; i++) + { + Handle(Sample2D_Markers) aMarker = new Sample2D_Markers(10 + 15, 5 * i, Aspect_TOM_O_PLUS, (Quantity_NameOfColor)(aColor++)); + myObject2d.Append(aMarker); + } + for (int i = 1; i <= 2; i++) + { + Handle(Sample2D_Markers) aMarker = new Sample2D_Markers(10 + 20, 5 * i, Aspect_TOM_RING1, (Quantity_NameOfColor)(aColor++)); + myObject2d.Append(aMarker); + } + for (int i = 1; i <= 2; i++) + { + Handle(Sample2D_Markers) aMarker = new Sample2D_Markers(10 + 25, 5 * i, Aspect_TOM_STAR, (Quantity_NameOfColor)(aColor++)); + myObject2d.Append(aMarker); + } + for (int i = 1; i <= 2; i++) + { + Handle(Sample2D_Markers) aMarker = new Sample2D_Markers(10 + 30, 5 * i, Aspect_TOM_O_X, (Quantity_NameOfColor)(aColor++)); + myObject2d.Append(aMarker); + } +} + +void Viewer2dSamples::FillAreaView2dSample() +{ + for (int i = 0; i <= 13; ++i) + { + for (int j = 0; j <= 5; ++j) + { + // set of rectangles here + TopoDS_Edge E1 = BRepBuilderAPI_MakeEdge(gp_Pnt(10 * i, 10 * j, 0.), gp_Pnt(10 * i + 7, 10 * j, 0.)); + TopoDS_Edge E2 = BRepBuilderAPI_MakeEdge(gp_Pnt(10 * i + 7, 10 * j, 0.), gp_Pnt(10 * i + 7, 10 * j + 5, 0.)); + TopoDS_Edge E3 = BRepBuilderAPI_MakeEdge(gp_Pnt(10 * i + 7, 10 * j + 5, 0.), gp_Pnt(10 * i, 10 * j + 5, 0.)); + TopoDS_Edge E4 = BRepBuilderAPI_MakeEdge(gp_Pnt(10 * i, 10 * j + 5, 0.), gp_Pnt(10 * i, 10 * j, 0.)); + TopoDS_Wire W = BRepBuilderAPI_MakeWire(E1, E2, E3, E4); + TopoDS_Face F = BRepBuilderAPI_MakeFace(W); + Handle(AIS_Shape) aRect = new AIS_Shape(F); + // set attributes of boundaries + Handle(Prs3d_Drawer) aDrawer = new Prs3d_Drawer(); + Handle(Prs3d_LineAspect) aLineAttrib = new Prs3d_LineAspect (Quantity_NOC_YELLOW, + (Aspect_TypeOfLine)(Aspect_TOL_SOLID + j), 1); + aDrawer->SetFaceBoundaryAspect(aLineAttrib); + aDrawer->SetFaceBoundaryDraw(Standard_True); + aRect->SetAttributes(aDrawer); + + myContext->SetDisplayMode(aRect, 1, Standard_False); + myContext->SetColor(aRect, (Quantity_NameOfColor)(Quantity_NOC_CADETBLUE + 2 * i), Standard_False); + myContext->SetMaterial(aRect, Graphic3d_NOM_PLASTIC, Standard_False); + myObject2d.Append(aRect); + + } + } +} + +void Viewer2dSamples::LoopOnFaceView2dSample() +{ + // Make a flat rectangular face on XY plane. + gp_Pln aPln(gp::XOY()); + TopoDS_Face aFaceRect = BRepBuilderAPI_MakeFace(aPln, -10.0, +10.0, -20.0, +20.0); + + Handle(AIS_ColoredShape) anAisFaceRect = new AIS_ColoredShape(aFaceRect); + anAisFaceRect->SetColor(Quantity_Color(Quantity_NOC_RED)); + myObject2d.Append(anAisFaceRect); + + TopoDS_Shape aFaceShape; + Handle(Sample2D_Face) anAISFace = new Sample2D_Face(aFaceRect); + myObject2d.Append(anAISFace); +} + +void Viewer2dSamples::RectagularLineGrid2dSample() +{ + Handle(Graphic3d_AspectMarker3d) aGridAspect = new Graphic3d_AspectMarker3d(Aspect_TOM_RING1, Quantity_NOC_WHITE, 2); + myViewer->SetGridEcho(aGridAspect); + Standard_Integer aWidth = 0, aHeight = 0, anOffset = 0; + myView->Window()->Size(aWidth, aHeight); + myViewer->SetRectangularGridGraphicValues(aWidth, aHeight, anOffset); + myViewer->ActivateGrid(Aspect_GT_Rectangular, Aspect_GDM_Lines); + myViewer->Redraw(); +} + +void Viewer2dSamples::RectagularPointGrid2dSample() +{ + Handle(Graphic3d_AspectMarker3d) aGridAspect = new Graphic3d_AspectMarker3d(Aspect_TOM_RING1, Quantity_NOC_WHITE, 2); + myViewer->SetGridEcho(aGridAspect); + Standard_Integer aWidth = 0, aHeight = 0, anOffset = 0; + myView->Window()->Size(aWidth, aHeight); + myViewer->SetRectangularGridGraphicValues(aWidth, aHeight, anOffset); + myViewer->ActivateGrid(Aspect_GT_Rectangular, Aspect_GDM_Points); + myViewer->Redraw(); +} + +void Viewer2dSamples::CircularLineGrid2dSample() +{ + Handle(Graphic3d_AspectMarker3d) aGridAspect = new Graphic3d_AspectMarker3d(Aspect_TOM_RING1, Quantity_NOC_WHITE, 2); + myViewer->SetGridEcho(aGridAspect); + Standard_Integer aWidth = 0, aHeight = 0, anOffset = 0; + myView->Window()->Size(aWidth, aHeight); + myViewer->SetRectangularGridGraphicValues(aWidth, aHeight, anOffset); + myViewer->ActivateGrid(Aspect_GT_Circular, Aspect_GDM_Lines); + myViewer->Redraw(); +} + +void Viewer2dSamples::CircularPointGrid2dSample() +{ + Handle(Graphic3d_AspectMarker3d) aGridAspect = new Graphic3d_AspectMarker3d(Aspect_TOM_RING1, Quantity_NOC_WHITE, 2); + myViewer->SetGridEcho(aGridAspect); + Standard_Integer aWidth = 0, aHeight = 0, anOffset = 0; + myView->Window()->Size(aWidth, aHeight); + myViewer->SetRectangularGridGraphicValues(aWidth, aHeight, anOffset); + myViewer->ActivateGrid(Aspect_GT_Circular, Aspect_GDM_Points); + myViewer->Redraw(); +} + +void Viewer2dSamples::ClearGrid2dSample() +{ + myViewer->DeactivateGrid(); + myViewer->Redraw(); +} + +void Viewer2dSamples::BackgroungImage2dSample() +{ + Handle(Sample2D_Image) anImage = new Sample2D_Image(myFileName); + anImage->SetCoord(40, 50); + anImage->SetScale(1.0); + myObject2d.Append(anImage); +} diff --git a/samples/OCCTOverview/code/Viewer2dSamples.h b/samples/OCCTOverview/code/Viewer2dSamples.h new file mode 100644 index 0000000000..66deb43b70 --- /dev/null +++ b/samples/OCCTOverview/code/Viewer2dSamples.h @@ -0,0 +1,76 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef VIEWER2DSAMPLES_H +#define VIEWER2DSAMPLES_H + +#include "BaseSample.h" + +#include +#include + +//! Implements viewer 2D samples. +class Viewer2dSamples : public BaseSample +{ + DEFINE_STANDARD_RTTI_INLINE(Viewer2dSamples, BaseSample) +public: + + Viewer2dSamples(const TCollection_AsciiString& theSampleSourcePath, + const Handle(V3d_View)& theView, + const Handle(V3d_Viewer)& theViewer, + const Handle(AIS_InteractiveContext)& theContext) + : BaseSample (theSampleSourcePath, theContext), + myView (theView), + myViewer (theViewer) + {} + + void SetFileName (const TCollection_AsciiString& theFileName) { myFileName = theFileName; } + void ClearExtra(); + + static Standard_Boolean IsFileSample (const TCollection_AsciiString& theSampleName) { return theSampleName == "BackgroungImage2dSample"; } + static Standard_Boolean IsShadedSample(const TCollection_AsciiString& theSampleName) { return theSampleName == "BackgroungImage2dSample"; } + +protected: + virtual void ExecuteSample (const TCollection_AsciiString& theSampleName) Standard_OVERRIDE; + +private: + + // One function for every sample + void TextView2dSample(); + void MarkerView2dSample(); + void FillAreaView2dSample(); + void LoopOnFaceView2dSample(); + void RectagularLineGrid2dSample(); + void RectagularPointGrid2dSample(); + void CircularLineGrid2dSample(); + void CircularPointGrid2dSample(); + void ClearGrid2dSample(); + void BackgroungImage2dSample(); + +private: + + TCollection_AsciiString myFileName; + Handle(V3d_View) myView; + Handle(V3d_Viewer) myViewer; + +}; + +#endif // VIEWER2DSAMPLES_H diff --git a/samples/OCCTOverview/code/Viewer3d.json b/samples/OCCTOverview/code/Viewer3d.json new file mode 100644 index 0000000000..19c2361b33 --- /dev/null +++ b/samples/OCCTOverview/code/Viewer3d.json @@ -0,0 +1,106 @@ +{ + "Viewer 3D": { + "Light source": [{ + "text": "Spot", + "function": "SpotLight3dSample", + "description": "" + }, + { + "text": "Positional", + "function": "PositionalLight3dSample", + "description": "" + }, + { + "text": "Directional", + "function": "DirectionalLight3dSample", + "description": "" + }, + { + "text": "Ambient", + "function": "AmbientLight3dSample", + "description": "" + }, + { + "text": "Clear", + "function": "ClearLight3dSample", + "description": "" + } + ], + + "Selection mode": [{ + "text": "Vertices", + "function": "VerticesSelect3dSample", + "description": "" + }, + { + "text": "Edges", + "function": "EdgesSelect3dSample", + "description": "" + }, + { + "text": "Faces", + "function": "FacesSelect3dSample", + "description": "" + }, + { + "text": "Neutral point", + "function": "NeutralPointSelect3dSample", + "description": "" + } + ], + + "Shape presentation": [ + { + "text": "WireFrame", + "function": "WireFramePresentation3dSample", + "description": "" + }, + { + "text": "Shading", + "function": "ShadingPresentation3dSample", + "description": "" + }, + { + "text": "Set color to red", + "function": "RedColorPresentation3dSample", + "description": "" + }, + { + "text": "Set color to gray", + "function": "GrayColorPresentation3dSample", + "description": "" + }, + { + "text": "Set plastic material", + "function": "PlasticPresentation3dSample", + "description": "" + }, + { + "text": "Set bronze material", + "function": "BronzePresentation3dSample", + "description": "" + }, + { + "text": "Set opaque", + "function": "OpaquePresentation3dSample", + "description": "" + }, + { + "text": "Set half transparency", + "function": "HalfTransparencyPresentation3dSample", + "description": "" + } + ], + "OpenGL VBO mode": [{ + "text": "Vertex Buffer Object mode ON", + "function": "VboOn3dSample", + "description": "" + }, + { + "text": "Vertex Buffer Object mode OFF", + "function": "VboOff3dSample", + "description": "" + } + ] + } +} \ No newline at end of file diff --git a/samples/OCCTOverview/code/Viewer3dSamples.cxx b/samples/OCCTOverview/code/Viewer3dSamples.cxx new file mode 100644 index 0000000000..ed67349180 --- /dev/null +++ b/samples/OCCTOverview/code/Viewer3dSamples.cxx @@ -0,0 +1,312 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "Viewer3dSamples.h" + +#include "MakeBottle.h" + +#include +#include +#include +#include +#include +#include +#include + +void Viewer3dSamples::ExecuteSample (const TCollection_AsciiString& theSampleName) +{ + Standard_Boolean anIsSamplePresent = Standard_True; + FindSourceCode(theSampleName); + if (theSampleName == "SpotLight3dSample") + SpotLight3dSample(); + else if (theSampleName == "PositionalLight3dSample") + PositionalLight3dSample(); + else if (theSampleName == "DirectionalLight3dSample") + DirectionalLight3dSample(); + else if (theSampleName == "AmbientLight3dSample") + AmbientLight3dSample(); + else if (theSampleName == "ClearLight3dSample") + ClearLight3dSample(); + else if (theSampleName == "VerticesSelect3dSample") + VerticesSelect3dSample(); + else if (theSampleName == "EdgesSelect3dSample") + EdgesSelect3dSample(); + else if (theSampleName == "FacesSelect3dSample") + FacesSelect3dSample(); + else if (theSampleName == "NeutralPointSelect3dSample") + NeutralPointSelect3dSample(); + else if (theSampleName == "WireFramePresentation3dSample") + WireFramePresentation3dSample(); + else if (theSampleName == "ShadingPresentation3dSample") + ShadingPresentation3dSample(); + else if (theSampleName == "RedColorPresentation3dSample") + RedColorPresentation3dSample(); + else if (theSampleName == "GrayColorPresentation3dSample") + GrayColorPresentation3dSample(); + else if (theSampleName == "PlasticPresentation3dSample") + PlasticPresentation3dSample(); + else if (theSampleName == "BronzePresentation3dSample") + BronzePresentation3dSample(); + else if (theSampleName == "OpaquePresentation3dSample") + OpaquePresentation3dSample(); + else if (theSampleName == "HalfTransparencyPresentation3dSample") + HalfTransparencyPresentation3dSample(); + else if (theSampleName == "VboOn3dSample") + VboOn3dSample(); + else if (theSampleName == "VboOff3dSample") + VboOff3dSample(); + else + { + myResult << "No function found: " << theSampleName; + myCode += TCollection_AsciiString("No function found: ") + theSampleName; + anIsSamplePresent = Standard_False; + } + myIsProcessed = anIsSamplePresent; +} + +void Viewer3dSamples::AppendBottle() +{ + TopoDS_Shape aBottle = MakeBottle(50, 70, 30); + Handle(AIS_InteractiveObject) aShape = new AIS_Shape(aBottle); + myObject3d.Append(aShape); + Handle(AIS_ViewCube) aViewCube = new AIS_ViewCube(); + myObject3d.Append(aViewCube); + myResult << "A bottle shape was created." << std::endl; +} + +void Viewer3dSamples::ClearExtra() +{ + NeutralPointSelect3dSample(); + VboOff3dSample(); + ClearLight3dSample(); + // Delete Lights + V3d_ListOfLight aLights; + for (V3d_ListOfLightIterator anIter = myView->Viewer()->DefinedLightIterator(); anIter.More(); anIter.Next()) + { + aLights.Append(anIter.Value()); + } + + for (V3d_ListOfLightIterator aLightIter (aLights); aLightIter.More(); aLightIter.Next()) + { + myView->Viewer()->DelLight (aLightIter.Value()); + } + myView->Viewer()->SetDefaultLights(); // Setting the default lights on + myView->Update(); + + myContext->RemoveAll (Standard_True); +} + +void Viewer3dSamples::SpotLight3dSample() +{ + // Spot light source creation + Handle(V3d_SpotLight) aSpotLight = new V3d_SpotLight(gp_Pnt(100.0, 0.0, 0.0), gp_Dir(-1.0, 0.0, 0.0), Quantity_NOC_RED); + aSpotLight->SetIntensity(5000); + myView->SetLightOn(aSpotLight); +} + +void Viewer3dSamples::PositionalLight3dSample() +{ + Handle(V3d_PositionalLight) aPositionalLight = new V3d_PositionalLight(gp_Pnt(0.0, -100.0, 5.0), Quantity_NOC_GREEN); + aPositionalLight->SetAttenuation(1, 0); + myView->SetLightOn(aPositionalLight); +} + +void Viewer3dSamples::DirectionalLight3dSample() +{ + Handle(V3d_DirectionalLight) aDirectionalLight = new V3d_DirectionalLight(gp_Dir(-1.0, 0.0, -1.0), Quantity_NOC_BLUE1); + myView->SetLightOn(aDirectionalLight); +} + +void Viewer3dSamples::AmbientLight3dSample() +{ + Handle(V3d_AmbientLight) aAmbientLight = new V3d_AmbientLight(Quantity_NOC_MAGENTA1); + myView->SetLightOn(aAmbientLight); +} + +void Viewer3dSamples::ClearLight3dSample() +{ + // Setting Off all viewer active lights + V3d_ListOfLight aLights; + for (V3d_ListOfLightIterator anIter = myView->Viewer()->ActiveLightIterator(); anIter.More(); anIter.Next()) + { + aLights.Append(anIter.Value()); + } + + for (V3d_ListOfLightIterator aLightIter (aLights); aLightIter.More(); aLightIter.Next()) + { + myView->Viewer()->SetLightOff (aLightIter.Value()); + } + // Setting Off all view active lights + aLights.Clear(); + for (V3d_ListOfLightIterator anIter = myView->ActiveLightIterator(); anIter.More(); anIter.Next()) + { + aLights.Append(anIter.Value()); + } + + for (V3d_ListOfLightIterator aLightIter (aLights); aLightIter.More(); aLightIter.Next()) + { + myView->SetLightOff (aLightIter.Value()); + } + myView->Viewer()->SetDefaultLights(); // Setting the default lights on + myView->Update(); +} + +void Viewer3dSamples::VerticesSelect3dSample() +{ + myContext->Deactivate(); + myContext->Activate(AIS_Shape::SelectionMode(TopAbs_VERTEX)); +} + +void Viewer3dSamples::EdgesSelect3dSample() +{ + myContext->Deactivate(); + myContext->Activate(AIS_Shape::SelectionMode(TopAbs_EDGE)); +} + +void Viewer3dSamples::FacesSelect3dSample() +{ + myContext->Deactivate(); + myContext->Activate(AIS_Shape::SelectionMode(TopAbs_FACE)); +} + +void Viewer3dSamples::NeutralPointSelect3dSample() +{ + myContext->Deactivate(); + myContext->Activate(0); +} + +void Viewer3dSamples::WireFramePresentation3dSample() +{ + AIS_ListOfInteractive anAisObjectsList; + myContext->DisplayedObjects(anAisObjectsList); + for (Handle(AIS_InteractiveObject) anAisObject : anAisObjectsList) + { + myContext->SetDisplayMode(anAisObject, 0, false); // set wireframe + } + myContext->UpdateCurrentViewer(); +} + +void Viewer3dSamples::ShadingPresentation3dSample() +{ + AIS_ListOfInteractive anAisObjectsList; + myContext->DisplayedObjects(anAisObjectsList); + for (Handle(AIS_InteractiveObject) anAisObject : anAisObjectsList) + { + myContext->SetDisplayMode(anAisObject, 1, false); // set shading + } + myContext->UpdateCurrentViewer(); +} + +void Viewer3dSamples::RedColorPresentation3dSample() +{ + AIS_ListOfInteractive anAisObjectsList; + myContext->DisplayedObjects(anAisObjectsList); + for (Handle(AIS_InteractiveObject) anAisObject : anAisObjectsList) + { + Quantity_Color aShapeColor; + myContext->Color(anAisObject, aShapeColor); + myResult << "A Current shape color: Red = " << aShapeColor.Red() + << " Green = " << aShapeColor.Green() << " Blue = " << aShapeColor.Blue() << std::endl; + aShapeColor.SetValues(0.8, 0.1, 0.1, Quantity_TOC_RGB); + myContext->SetColor(anAisObject, aShapeColor, Standard_False); + myResult << "A New shape color: Red = " << aShapeColor.Red() + << " Green = " << aShapeColor.Green() << " Blue = " << aShapeColor.Blue() << std::endl; + } +} + +void Viewer3dSamples::GrayColorPresentation3dSample() +{ + AIS_ListOfInteractive anAisObjectsList; + myContext->DisplayedObjects(anAisObjectsList); + for (Handle(AIS_InteractiveObject) anAisObject : anAisObjectsList) + { + Quantity_Color aShapeColor; + myContext->Color(anAisObject, aShapeColor); + myResult << "A Current shape color: Hue = " << aShapeColor.Hue() + << " Light = " << aShapeColor.Light() << " Saturation = " << aShapeColor.Saturation() << std::endl; + aShapeColor.SetValues(0.0, 0.3, 0.1, Quantity_TOC_HLS); + myContext->SetColor(anAisObject, aShapeColor, Standard_False); + myResult << "A New shape color: Hue = " << aShapeColor.Hue() + << " Light = " << aShapeColor.Light() << " Saturation = " << aShapeColor.Saturation() << std::endl; + } +} + +void Viewer3dSamples::PlasticPresentation3dSample() +{ + AIS_ListOfInteractive anAisObjectsList; + myContext->DisplayedObjects(anAisObjectsList); + Graphic3d_NameOfMaterial aMaterial = Graphic3d_NOM_PLASTIC; + for (Handle(AIS_InteractiveObject) anAisObject : anAisObjectsList) + { + myContext->SetMaterial(anAisObject, aMaterial, Standard_False); + } + myContext->UpdateCurrentViewer(); +} + +void Viewer3dSamples::BronzePresentation3dSample() +{ + AIS_ListOfInteractive anAisObjectsList; + myContext->DisplayedObjects(anAisObjectsList); + Graphic3d_NameOfMaterial aMaterial = Graphic3d_NOM_BRONZE; + for (Handle(AIS_InteractiveObject) anAisObject : anAisObjectsList) + { + myContext->SetMaterial(anAisObject, aMaterial, Standard_False); + } + myContext->UpdateCurrentViewer(); +} + +void Viewer3dSamples::OpaquePresentation3dSample() +{ + AIS_ListOfInteractive anAisObjectsList; + myContext->DisplayedObjects(anAisObjectsList); + for (Handle(AIS_InteractiveObject) anAisObject : anAisObjectsList) + { + myContext->SetTransparency(anAisObject, 0.0, Standard_False); + } + myContext->UpdateCurrentViewer(); +} + +void Viewer3dSamples::HalfTransparencyPresentation3dSample() +{ + AIS_ListOfInteractive anAisObjectsList; + myContext->DisplayedObjects(anAisObjectsList); + for (Handle(AIS_InteractiveObject) anAisObject : anAisObjectsList) + { + myContext->SetTransparency(anAisObject, 0.5, Standard_False); + } + myContext->UpdateCurrentViewer(); +} + +void Viewer3dSamples::VboOn3dSample() +{ + if (Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast(myContext->CurrentViewer()->Driver())) + { + aDriver->ChangeOptions().vboDisable = Standard_False; + } +} + +void Viewer3dSamples::VboOff3dSample() +{ + if (Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast(myContext->CurrentViewer()->Driver())) + { + aDriver->ChangeOptions().vboDisable = Standard_True; + } +} diff --git a/samples/OCCTOverview/code/Viewer3dSamples.h b/samples/OCCTOverview/code/Viewer3dSamples.h new file mode 100644 index 0000000000..1691736b30 --- /dev/null +++ b/samples/OCCTOverview/code/Viewer3dSamples.h @@ -0,0 +1,78 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef VIEWER3DSAMPLES_H +#define VIEWER3DSAMPLES_H + +#include "BaseSample.h" + +#include +#include + +//! Implements viewer 3D samples. +class Viewer3dSamples : public BaseSample +{ + DEFINE_STANDARD_RTTI_INLINE(Viewer3dSamples, BaseSample) +public: + + Viewer3dSamples (const TCollection_AsciiString& theSampleSourcePath, + const Handle(V3d_View)& theView, + const Handle(AIS_InteractiveContext)& theContext) + : BaseSample (theSampleSourcePath, theContext), + myView (theView) + {} + + void AppendBottle(); + void ClearExtra(); + +protected: + virtual void ExecuteSample (const TCollection_AsciiString& theSampleName) Standard_OVERRIDE; + +private: + + // One function for every sample + void SpotLight3dSample(); + void PositionalLight3dSample(); + void DirectionalLight3dSample(); + void AmbientLight3dSample(); + void ClearLight3dSample(); + void VerticesSelect3dSample(); + void EdgesSelect3dSample(); + void FacesSelect3dSample(); + void NeutralPointSelect3dSample(); + void WireFramePresentation3dSample(); + void ShadingPresentation3dSample(); + void RedColorPresentation3dSample(); + void GrayColorPresentation3dSample(); + void PlasticPresentation3dSample(); + void BronzePresentation3dSample(); + void OpaquePresentation3dSample(); + void HalfTransparencyPresentation3dSample(); + void VboOn3dSample(); + void VboOff3dSample(); + +private: + + Handle(V3d_View) myView; + +}; + +#endif //VIEWER3DSAMPLES_H diff --git a/samples/qt/IESample/.gitignore b/samples/qt/IESample/.gitignore new file mode 100644 index 0000000000..7ac6e6bc69 --- /dev/null +++ b/samples/qt/IESample/.gitignore @@ -0,0 +1,7 @@ +/debug +/release +*.sln +*.vcxproj* +.qmake.stash +/custom.bat +/custom.sh diff --git a/samples/qt/IESample/custom.bat b/samples/qt/IESample/custom.bat deleted file mode 100644 index b5eea5240f..0000000000 --- a/samples/qt/IESample/custom.bat +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -rem Define QTDIR variable - -set "QTDIR=" diff --git a/samples/qt/IESample/custom.bat.template b/samples/qt/IESample/custom.bat.template new file mode 100644 index 0000000000..dda84faa21 --- /dev/null +++ b/samples/qt/IESample/custom.bat.template @@ -0,0 +1,5 @@ +@echo off +rem Rename this file to custom.bat, +rem and define QTDIR variable. + +set "QTDIR=" diff --git a/samples/qt/IESample/custom.sh b/samples/qt/IESample/custom.sh deleted file mode 100755 index d9705989ff..0000000000 --- a/samples/qt/IESample/custom.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -#Define QTDIR variable - -export QTDIR="" diff --git a/samples/qt/IESample/custom.sh.template b/samples/qt/IESample/custom.sh.template new file mode 100644 index 0000000000..52571f097b --- /dev/null +++ b/samples/qt/IESample/custom.sh.template @@ -0,0 +1,5 @@ +#!/bin/bash +# Rename this file to custom.sh, +# and define QTDIR variable. + +export QTDIR="" diff --git a/samples/qt/IESample/env.bat b/samples/qt/IESample/env.bat index 3b7e3e4eb7..3e090cff49 100755 --- a/samples/qt/IESample/env.bat +++ b/samples/qt/IESample/env.bat @@ -1,8 +1,10 @@ @echo off -call "%~dp0..\..\..\env.bat" %1 %2 %3 +if exist "%~dp0custom.bat" ( + call "%~dp0custom.bat" %1 %2 %3 +) -call "custom.bat" %1 %2 %3 +call "%~dp0..\..\..\env.bat" %1 %2 %3 set "RES_DIR=%~dp0win%ARCH%\%VCVER%\res" set "CSF_ResourcesDefaults=%RES_DIR%" diff --git a/samples/qt/OCCTOverview/.gitignore b/samples/qt/OCCTOverview/.gitignore new file mode 100644 index 0000000000..7ac6e6bc69 --- /dev/null +++ b/samples/qt/OCCTOverview/.gitignore @@ -0,0 +1,7 @@ +/debug +/release +*.sln +*.vcxproj* +.qmake.stash +/custom.bat +/custom.sh diff --git a/samples/qt/OCCTOverview/CMakeLists.txt b/samples/qt/OCCTOverview/CMakeLists.txt new file mode 100644 index 0000000000..e9afaa4f65 --- /dev/null +++ b/samples/qt/OCCTOverview/CMakeLists.txt @@ -0,0 +1,8 @@ +project(OCCTOverview) + +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit_prepare_sample) +include_directories("${CMAKE_SOURCE_DIR}/${RELATIVE_DIR}/../OCCTOverview/code") +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit) +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit_prepare_sample) + +ADD_DEFINITIONS(-DNO_COMMONSAMPLE_EXPORTS -DNO_IESAMPLE_EXPORTS) diff --git a/samples/qt/OCCTOverview/EXTERNLIB b/samples/qt/OCCTOverview/EXTERNLIB new file mode 100644 index 0000000000..81f55c1328 --- /dev/null +++ b/samples/qt/OCCTOverview/EXTERNLIB @@ -0,0 +1,33 @@ +TKBRep +TKBin +TKBool +TKBO +TKCDF +TKFillet +TKG2d +TKG3d +TKGeomAlgo +TKGeomBase +TKernel +TKHLR +TKIGES +TKMath +TKMesh +TKOffset +TKOpenGl +TKPrim +TKService +TKShHealing +TKSTEP +TKSTEP209 +TKSTEPAttr +TKSTEPBase +TKSTL +TKTopAlgo +TKV3d +TKVRML +TKXSBase +TKLCAF +TKCAF +TKVCAF +TKXml diff --git a/samples/qt/OCCTOverview/FILES b/samples/qt/OCCTOverview/FILES new file mode 100644 index 0000000000..ca4f0e567b --- /dev/null +++ b/samples/qt/OCCTOverview/FILES @@ -0,0 +1,2 @@ +EXTERNLIB +PACKAGES diff --git a/samples/qt/OCCTOverview/OCCTOverview.pro b/samples/qt/OCCTOverview/OCCTOverview.pro new file mode 100644 index 0000000000..850d82476a --- /dev/null +++ b/samples/qt/OCCTOverview/OCCTOverview.pro @@ -0,0 +1,89 @@ +TEMPLATE = app +CONFIG += debug_and_release qt +CONFIG += lrelease +CONFIG += embed_translations +QT += widgets + +TARGET = OCCTOverview + +SAMPLESROOT = $$quote($$(CSF_OCCTSamplesPath)/qt) + +FREEIMAGE_DIR = $$quote($$(FREEIMAGE_DIR)) +TBB_DIR = $$quote($$(TBB_DIR)) + +HEADERS = ./src/*.h \ + $${SAMPLESROOT}/../OCCTOverview/code/*.h + +SOURCES = ./src/*.cxx \ + $${SAMPLESROOT}/../OCCTOverview/code/*.cxx + +RESOURCES += $${SAMPLESROOT}/../OCCTOverview/code/Samples.qrc +RESOURCES += ./src/OCCTOverview.qrc + +RES_DIR = $$quote($$(RES_DIR)) + +INCLUDEPATH += $$quote($$(CSF_SampleSources)) +INCLUDEPATH += $$quote($$(CSF_OCCTIncludePath)) \ + $${SAMPLESROOT}/../OCCTOverview/code + + +OCCT_DEFINES = $$(CSF_DEFINES) + +DEFINES = $$split(OCCT_DEFINES, ;) + +unix { + UNAME = $$system(uname -s) + LIBLIST = $$(LD_LIBRARY_PATH) + LIBPATHS = $$split(LIBLIST,":") + for(lib, LIBPATHS):LIBS += -L$${lib} + + CONFIG(debug, debug|release) { + DESTDIR = ./$$UNAME/bind + OBJECTS_DIR = ./$$UNAME/objd + MOC_DIR = ./$$UNAME/mocd + } else { + DESTDIR = ./$$UNAME/bin + OBJECTS_DIR = ./$$UNAME/obj + MOC_DIR = ./$$UNAME/moc + } + + MACOSX_USE_GLX = $$(MACOSX_USE_GLX) + + !macx | equals(MACOSX_USE_GLX, true): INCLUDEPATH += $$QMAKE_INCDIR_X11 $$QMAKE_INCDIR_OPENGL $$QMAKE_INCDIR_THREAD + equals(MACOSX_USE_GLX, true): DEFINES += MACOSX_USE_GLX + DEFINES += OCC_CONVERT_SIGNALS QT_NO_STL + !macx | equals(MACOSX_USE_GLX, true): LIBS += -L$$QMAKE_LIBDIR_X11 $$QMAKE_LIBS_X11 -L$$QMAKE_LIBDIR_OPENGL $$QMAKE_LIBS_OPENGL $$QMAKE_LIBS_THREAD + + QMAKE_CXXFLAGS += -std=gnu++11 +} + +win32 { + CONFIG(debug, debug|release) { + DEFINES += _DEBUG + DESTDIR = ./win$$(ARCH)/$$(VCVER)/bind + OBJECTS_DIR = ./win$$(ARCH)/$$(VCVER)/objd + MOC_DIR = ./win$$(ARCH)/$$(VCVER)/mocd + } else { + DEFINES += NDEBUG + DESTDIR = ./win$$(ARCH)/$$(VCVER)/bin + OBJECTS_DIR = ./win$$(ARCH)/$$(VCVER)/obj + MOC_DIR = ./win$$(ARCH)/$$(VCVER)/moc + } + LIBS = -L$$(QTDIR)/lib;$$(CSF_OCCTLibPath) + DEFINES += NO_COMMONSAMPLE_EXPORTS NO_IESAMPLE_EXPORTS +} + +LIBS += -lTKernel -lTKMath -lTKService -lTKV3d -lTKOpenGl \ + -lTKBRep -lTKIGES -lTKSTL -lTKVRML -lTKSTEP -lTKSTEPAttr -lTKSTEP209 \ + -lTKSTEPBase -lTKGeomBase -lTKGeomAlgo -lTKG3d -lTKG2d \ + -lTKXSBase -lTKShHealing -lTKHLR -lTKTopAlgo -lTKMesh -lTKPrim \ + -lTKCDF -lTKBool -lTKBO -lTKFillet -lTKOffset -lTKLCAF -lTKCAF -lTKVCAF \ + -lTKBin -lTKXml + +!exists($${RES_DIR}) { + win32 { + system(mkdir $${RES_DIR}) + } else { + system(mkdir -p $${RES_DIR}) + } +} diff --git a/samples/qt/OCCTOverview/OCCTOverview0.pro b/samples/qt/OCCTOverview/OCCTOverview0.pro new file mode 100644 index 0000000000..ec2948b973 --- /dev/null +++ b/samples/qt/OCCTOverview/OCCTOverview0.pro @@ -0,0 +1,5 @@ +TEMPLATE=subdirs + +SUBDIRS=OCCTOverview0 + +OCCTOverview0.file=OCCTOverview.pro diff --git a/samples/qt/OCCTOverview/PACKAGES b/samples/qt/OCCTOverview/PACKAGES new file mode 100644 index 0000000000..0d40a31f87 --- /dev/null +++ b/samples/qt/OCCTOverview/PACKAGES @@ -0,0 +1,2 @@ +OCCTOverview/src +/../OCCTOverview/code diff --git a/samples/qt/OCCTOverview/ReadMe.md b/samples/qt/OCCTOverview/ReadMe.md new file mode 100644 index 0000000000..99fae6050b --- /dev/null +++ b/samples/qt/OCCTOverview/ReadMe.md @@ -0,0 +1,58 @@ +Qt OCCT Overview samples {#samples_qt_overview} +========== + +1. Contents +----------------------- + +The directory samples/qt/OCCTOverview contains the folders and files of the Qt OCCT Overview application: + +* Files **OCCTOverview.pro** and **OCCTOverview0.pro** are Qt project files. +* File **genproj.bat** to denerate MS Visual Studio project. +* File **msvc.bat** to run MS Visual Studio project. +* File **make.sh** to build of the application on Linux. +* Files **run.bat** and **run.sh** to runn the application. +* Files **env.bat** and **custom.bat** are called from *genproj.bat*, *msvc.bat*, *run.bat*. + File *custom.bat* should be defined by user to provide paths to QT directory and OCCT installation directory (see *custom.bat.template*). +* **src** and **res** directories provide source and resources files. + +The directory samples/OCCTOverview/code contains the source code of samples. + +2. How to build Qt OCCT Overview application +--------------------------------- + +* Edit custom.bat file. It is necessary to define following variables: + * **QTDIR** path to where Qt is installed + * **CASROOT** path to where Open CASCADE binaries are installed. + +* Build the application: + + * On Windows: + * Generate project files: `> genproj.bat vc141 win64 Debug` + * Launch MS Visual Studio: `> msvc.bat vc141 win64 Debug` + * Build the application using MS Visual Studio. + + * On Linux: Launch building of the application by make.sh script + +3. Running the application +-------------------------- + +* On Windows: +~~~~ + > run.bat vc141 win64 Debug +~~~~ + +* On Linux: +~~~~ + > run.sh +~~~~ + +4. How to use the OCCT Overview application: +--------------------------------- + +* To select a samples categogy use the *Category* menu. +* To run concrete sample using the menu to the right of the category menu. +* See on a souce code in the *Sample code* window. Сopy the code if needed. +* See on a sample output in the *Output* window if it exist. +* Zoom, pan and rotate a geometry in the mail window using the mouse. + +See hints how to use the mouse in down hints panel. diff --git a/samples/qt/OCCTOverview/custom.bat.template b/samples/qt/OCCTOverview/custom.bat.template new file mode 100644 index 0000000000..49dccac5e8 --- /dev/null +++ b/samples/qt/OCCTOverview/custom.bat.template @@ -0,0 +1,7 @@ +@echo off +rem Rename this file to custom.bat, +rem define QTDIR variable - path to Qt directory +rem and CASROOT variable - path to Open CASCADE installation directory. + +set "CASROOT=%~dp0../../.." +set "QTDIR=" diff --git a/samples/qt/OCCTOverview/custom.sh.template b/samples/qt/OCCTOverview/custom.sh.template new file mode 100644 index 0000000000..756d3dda9d --- /dev/null +++ b/samples/qt/OCCTOverview/custom.sh.template @@ -0,0 +1,9 @@ +#!/bin/bash +# Rename this file to custom.sh, +# define QTDIR variable - path to QT directory +# and CASROOT variable - path to CasCade installation directory. + +aScriptPath=${BASH_SOURCE%/*} + +export CASROOT=${aScriptPath}/../../.. +export QTDIR= diff --git a/samples/qt/OCCTOverview/env.bat b/samples/qt/OCCTOverview/env.bat new file mode 100644 index 0000000000..008277ad0d --- /dev/null +++ b/samples/qt/OCCTOverview/env.bat @@ -0,0 +1,29 @@ +@echo off + +if exist "%~dp0custom.bat" ( + call "%~dp0custom.bat" %1 %2 %3 +) + +call "%CASROOT%\env.bat" %1 %2 %3 + +if /I ["%1"] == ["vc141"] set "VCVER=vc141" +set "BIN_DIR=win%ARCH%\%VCVER%\bind" +set "LIB_DIR=win%ARCH%\%VCVER%\libd" + +if ["%CASDEB%"] == [""] ( + set "BIN_DIR=win%ARCH%\%VCVER%\bin" + set "LIB_DIR=win%ARCH%\%VCVER%\lib" +) + +set "PATH=%~dp0%BIN_DIR%;%PATH%" + +if not "%QTDIR%" == "" ( + set "RES_DIR=%~dp0win%ARCH%\%VCVER%\res" + + set "CSF_ResourcesDefaults=!RES_DIR!" + set "CSF_TutorialResourcesDefaults=!RES_DIR!" + set "CSF_IEResourcesDefaults=!RES_DIR!" + + set "PATH=%QTDIR%/bin;%PATH%" + set "QT_QPA_PLATFORM_PLUGIN_PATH=%QTDIR%\plugins\platforms" +) diff --git a/samples/qt/OCCTOverview/env.sh b/samples/qt/OCCTOverview/env.sh new file mode 100644 index 0000000000..c161ee025b --- /dev/null +++ b/samples/qt/OCCTOverview/env.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +export aSamplePath="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +if [ -e "custom.sh" ]; then + source "custom.sh" $*; +fi + +source ${CASROOT}/bin/env.sh $* + +if [ "${QTDIR}" != "" ]; then + export PATH=${QTDIR}/bin:${PATH} +else + aQMakePath=`which qmake` + echo "Environment variable \"QTDIR\" not defined.. Define it in \"custom.sh\" script." + if [ -x "$aQMakePath" ]; then + echo "qmake from PATH will be used instead." + else + exit 1 + fi +fi + +host=`uname -s` +export STATION=$host +export RES_DIR=${aSamplePath}/${STATION}/res diff --git a/samples/qt/OCCTOverview/genproj.bat b/samples/qt/OCCTOverview/genproj.bat new file mode 100644 index 0000000000..f3670f3eae --- /dev/null +++ b/samples/qt/OCCTOverview/genproj.bat @@ -0,0 +1,17 @@ +@echo off +REM Generation of vcproj files with qmake utilite +REM Variable QTDIR and PATH to qmake executable must be defined without fail + +REM Use first argument to specify version of Visual Studio (vc10, vc11, vc12 or vc14), +REM second argument specifies architecture) (win32 or win64) +REM third argument specifies Debug or Release mode + +call "%~dp0env.bat" %1 %2 %3 + +if ["%VCARCH%"] == [""] set "VCARCH=%ARCH%" +if ["%VCARCH%"] == ["64"] set "VCARCH=amd64" +if ["%VCARCH%"] == ["32"] set "VCARCH=x86" + +call "%VCVARS%" %VCARCH% + +qmake -tp vc -r -o OCCTOverview.sln OCCTOverview0.pro diff --git a/samples/qt/OCCTOverview/make.sh b/samples/qt/OCCTOverview/make.sh new file mode 100644 index 0000000000..421dc19817 --- /dev/null +++ b/samples/qt/OCCTOverview/make.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +export aSamplePath="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +if [ -e "${aSamplePath}/env.sh" ]; then source "${aSamplePath}/env.sh" $*; fi + +cd $aSamplePath +qmake OCCTOverview.pro +if [ "$(uname -s)" != "Darwin" ] || [ "$MACOSX_USE_GLX" == "true" ]; then + aNbJobs="$(getconf _NPROCESSORS_ONLN)" + if [ "${CASDEB}" == "d" ]; then + make -j $aNbJobs debug + else + make -j $aNbJobs release + fi +fi diff --git a/samples/qt/OCCTOverview/msvc.bat b/samples/qt/OCCTOverview/msvc.bat new file mode 100644 index 0000000000..6164118ece --- /dev/null +++ b/samples/qt/OCCTOverview/msvc.bat @@ -0,0 +1,19 @@ +@echo off + +Setlocal EnableDelayedExpansion + +rem Setup environment +call "%~dp0env.bat" %1 %2 %3 + +rem Define path to project file +set "PRJFILE=%~dp0OCCTOverview.sln" + +rem Launch Visual Studio - either professional (devenv) or Express, as available +if exist "%DevEnvDir%\devenv.exe" ( + start "" "%DevEnvDir%\devenv.exe" "%PRJFILE%" +) else if exist "%DevEnvDir%\%VisualStudioExpressName%.exe" ( + start "" "%DevEnvDir%\%VisualStudioExpressName%.exe" "%PRJFILE%" +) else ( + echo Error: Could not find MS Visual Studio ^(%VCVER%^) + echo Check relevant environment variable ^(e.g. VS100COMNTOOLS for vc10^) +) diff --git a/samples/qt/OCCTOverview/res/antialiasing.png b/samples/qt/OCCTOverview/res/antialiasing.png new file mode 100644 index 0000000000000000000000000000000000000000..da8e5047a4ff2c2738718a56cfd47c1d19d24d1e GIT binary patch literal 230 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6;>1s;*b z3=DjSK$uZf!>a)(C{^MbQ4*Y=R#Ki=l*$m0n3-3i=jR%tP-d)Ws%L2E{@KYKs4B_R z#WBRfKl#W1|MtwP5^E$m99X#OzQ2<_94$HZzXDHEaxn8XZexZe9J0#N4SMWG6BaPu z;A!pTHDdl?DLP-qhNpm4Oy@}sOGTn}2R UAKHp91KP&m>FVdQ&MBb@07Pj*oB#j- literal 0 HcmV?d00001 diff --git a/samples/qt/OCCTOverview/res/cursor_rotate.png b/samples/qt/OCCTOverview/res/cursor_rotate.png new file mode 100644 index 0000000000000000000000000000000000000000..a3cb0c1ecc31ed66595b4387c55dd2731809a5e1 GIT binary patch literal 291 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH%)r1{DZJ<-ki!|^6XJT{zyToh|NsBJ3q{m` zEXI-`zhDN3XE)M7oFs2|7lsa2Sq~sbti&~FS$q5M)5)u*~FeEXuNpvI#I2A}-X}F}rqr=I=%gfWlk;uj_@bD7j z6|DtF4jh=G!12UL&ENr>PlD1KMh`VE4Ti0yjJ+8Jj78ER4MKcUJUm)LTnfPsZpKOG zEV4cgmtt0nIY{(yPjhvQn8U-#ZQ{ry%Esx*uHnq2v$d(wm(@i-H9286!$zGf)iWM5 e)|F^Z8<^g0e zmIV0)GdMiEkp|?5mAFQf1m~xflqVLYGNfmw85QKED;Vh+=o#9^?aKhFU`h9MOJ`zW zkPLd4!Up7Lc)B=-RLn_EP!KOz+h7#dX4;UsjI)PRK$4w})1Y}W<0Lc-a$k!M*zN28VxpF`U#yCAY@F9!>Q{yu)SmYHks0PSS(boFyt=akR{08E}qwEzGB literal 0 HcmV?d00001 diff --git a/samples/qt/OCCTOverview/res/help.png b/samples/qt/OCCTOverview/res/help.png new file mode 100644 index 0000000000000000000000000000000000000000..e57336285ea67f393322fd6f19a64d9d1de42e53 GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!9%)r1XI!iqT$l(m|32{Ae;K2X?Kn}y={c$Bg zim@cfFPOpM*^M+1C&}C0g(;1@2Bci9#5JNMI6tkVJh3R1Aw4tAs30$0!AQ?Q&(Jn* zUj|TxkEe@cNX4AwgoJ(PcjV()C>w#3=B*S3``o9LZ`&mG989ZJ6T-G@yGywpz CnKtYI literal 0 HcmV?d00001 diff --git a/samples/qt/OCCTOverview/res/lamp.png b/samples/qt/OCCTOverview/res/lamp.png new file mode 100644 index 0000000000000000000000000000000000000000..a5a6775c33f5655a31ef8152b0fa94fcaa73abf3 GIT binary patch literal 1355 zcmd^7i%XMH6hGglY)YE@mdni4rBLY*sVE7}O{Z?9Q&P-u!OCnICac6xjOt62ED8#G zTV`Zg2|ehcV$dp*UZzAy#gd9_84Ol4A0@4Gt{Oq~7j)pL)q+D}fNWcF8TBSX#DVWbcMABR%wvq6 zOe?HhV$RPqnX_{B%gwoKHrYyx&0C7MLMe)I8OC&Yiaz8gt9A+#DIszqR^lKJXN!gf zdPCEk%tJX`YNz1#Qvgeh$Seqj{!0-t;V7pgQ$0lrr$BvDEr;CzDwvB_oFRhL;;~vQ zt8s%S7-X=Q178M%`5VuK#w;tlE3po7iW0tj7{MBq5RF#SiErxA;I9Q{KpK;zi04j$tPAP#rd;Vs?mU!8tK9N|$Dx_y|RY@hW(Jp^Ii z6AG6Q8^jqTsEgQBIj02eoM4Q`!Ar!~Eo%{MXrn#@3!TC^Ha@dRj6a>d1gJy&`dl~b zS&qLNf*9=-G0l~7pa^mrHc|!NIp{+)xtkBW#&@&7E|vM{H*U949px)bxwNyi_5Uk* zYOD`&RNswyU0&r$*P*-oy?D9)Xj$!`cV|IlR`YAU>+XzG1L0Nii3M_n$M{YX_x6dn z);3?F4bQbNmF=sw=%BYr?Y+5Y8dtt3p~3IQG3mMHn%K1A*+2KE?CWj&tlqJ?WdCr? zeAliAZyNLakKB>uuh#Ww1}>L8c^vGoRk|%xyOoAbRmtrax_VPpZcWPZ1JCalT&r4M z-EtwdpbW2l$bb}#O0PmqO1O?{N1)#yf4VfS~p9CTG=r+0j)KWl~4LFX61<28v_ zxCS4M(6Oyowk1n_>S6`g(mm(apj6wQ)aq#MpLI2<;A`iqkJiGSgWUp`9O&TGNzus~ RS6?!1j4{omzno&J{srsJK~Vqz literal 0 HcmV?d00001 diff --git a/samples/qt/OCCTOverview/res/raytracing.png b/samples/qt/OCCTOverview/res/raytracing.png new file mode 100644 index 0000000000000000000000000000000000000000..211e697237314addce4eeaf9399e49c448101e9d GIT binary patch literal 223 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qucL8%hgh?3y^w370~qEv=}#LT=BJwMkFg)(D3 zQ$0gN_s>q|KvjO8E{-7<{%3m}xfm394*&VTe7T%iyUT`G2b~vqpYEC&+Ze>Sl*y}A zFzU>X!lvI6;>1s;*b z3=DjSL74G){)!Z!pj3%#L`iUdT1k0gQ7S_~VrE{6o}X)oLYc9ish**s`)4O}psG+$ z7sn6_|KuP4|JyUGO01jN*!a+1QzA{Xi}C$B(?9BL%{o%+*aAd4p17%6h`oCK`v2r+ z$0|)P7Y()vub6sD7>pkLoy_Z!IN_FK7K7%)hKH<0ml+wBY8~9U`j0vf&;kZeS3j3^ HP6!lvI6;>1s;*b z3=DjSL74G){)!Z!pj3%#L`iUdT1k0gQ7S_~VrE{6o}X)oLYc9ish**s`)4O}psE&6 z7sn6_|F@Gbavo3+aL)g7?je`o10`AKi}|X#e1A4{guY6*mus4%IAcx+M;fDo|GVu> z^>XVA-feF9E~j#=W6tJXkwpn>SqsmtJh7?4kgY|j+))78&qol`;+0OTi5IRF3v literal 0 HcmV?d00001 diff --git a/samples/qt/OCCTOverview/res/tool_delete.png b/samples/qt/OCCTOverview/res/tool_delete.png new file mode 100644 index 0000000000000000000000000000000000000000..3886af51d843d2599fdb390ba81a5da47333e5c4 GIT binary patch literal 203 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~q!VDzkV}oRXltF+`h%1n80OJNQ)d1u*G#of^ zprN7RKT!NX!+$UZq=76T@E2C|1d4}wx;TbZ%uzkHQSg8P2eU)e`iE^ww=W);D_x$^ zV&FZkyC?Lo=OnEK5}GdF4{nRAN?QMQW`1X>V#~o(d3T;Duj$c7-=yoA6^dG+Uk^QN hEjX;OV#k6GdE?J!s@uX>g#vA0@O1TaS?83{1ONg@Ml}Ec literal 0 HcmV?d00001 diff --git a/samples/qt/OCCTOverview/res/tool_material.png b/samples/qt/OCCTOverview/res/tool_material.png new file mode 100644 index 0000000000000000000000000000000000000000..f846a56371c43ec6a49f0414e444a52372e66929 GIT binary patch literal 293 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~q!3HGX7W?Z1DVB6cUq=RpjeRx011AId3dtTp zz6=aistgPb%?u1b{{!h43=E|P3=FRl7#OUkGcbtfPhUCn3Q+9^PZ!6KiaAMt{{OdU zR%K9Vi1^@b{K(+1y>bt$fI|fjL#CU?5mj~p2cIR`Z95qrSv4>mN@O@AaA+Mfhk}p3 z0h8+g!#M{MIXtvO*c2Kzv@_liSmDG3GUq_o$D2+E1c2&=*^V$aFeEkp5WktWqPyb@ zlLJE{KXZh_qb_!pW=1BC%MJfKERM|-`=@+}SE1oU3u7TCr$R%4M8g}d9EOP#7??Qx i;|`>A94cjCWMk;*Fw)(Yz}5+LJA7wL~P(RGc!vv-MVkzJi%BVg$4-+J%?kwyu2@*3V0?ui?VPiEHZs;#G=qJ!(i_H zhRgeJJYitsQ095{TDm~0$(K)|VFR0zhvG({Q3iV)v=}%Px_EIBlZ_l043kdxE=f^q cU|?oAQNC34y-L7&ptBe}UHx3vIVCg!0Cd_&#sB~S literal 0 HcmV?d00001 diff --git a/samples/qt/OCCTOverview/res/tool_transparency.png b/samples/qt/OCCTOverview/res/tool_transparency.png new file mode 100644 index 0000000000000000000000000000000000000000..786803a5cf0deba83f1107153186a098c9eab7cc GIT binary patch literal 318 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~q!3HGX7W?Z1DVB6cUq=RpjeRx011AId3dtTp zz6=aistgPb%?u1b{{!h43=E|P3=FRl7#OUkGcbtfPhUCn3Q+AyPZ!6KiaAMt{{OdU zR%K9Vh}ghsW@eUTx^>^ad4jP#3JnqtdJe~Ud3giWIvkcN7Oi;2$kdT>)*$so8v~1g z@UqX+4JyhPxc^ID%7wL~P(Teq`{~UU?UX14E)A!xG70MLo*~h9spp<1?%))-iJ^sQI|=n8UxF!Ied! zVM7JuWw8*;5Mc%;4tIq|pV_n+I23f^6nGg}1dg)72~JLhh7+D18cGa|El0UogoV0* trW+;(I%p^^oWUUA@I*yLgh3#Iq3NTFdbspE4WP>yJYD@<);T3K0RX6BL^A*Y literal 0 HcmV?d00001 diff --git a/samples/qt/OCCTOverview/res/view_axo.png b/samples/qt/OCCTOverview/res/view_axo.png new file mode 100644 index 0000000000000000000000000000000000000000..4801ab45921b9e94e59e7d21f649cd9fddce3187 GIT binary patch literal 392 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VOS+@4BLl<6zM9{GlYxANWRD>fq_xj)5S5QVouVZ|Nrfo zO&J{+3yVfB}5L~FmRsu zG=V{(p+Kr5Pr~RxI#4F@tI@`Xt-K5@0_O}^Zg%OPDfkIg@S#m{*L8^nnPTw;K$%I6 z3cfc)6{TBp1kD%(9DFzqPso&*Ex6?K|9Xw~#*P?P0fzwQM6*S=cuX1@a|F&T3@}r6 zQ4G7x$iz{;$$k6pkaB59_eSi+7sPC=(S1m`g@wmft4IC7wgD_-S6S7rl4 zl8f%X4NEOOs#+v{G?p(-?sK#ov=Pl)S*0|);9XJ`O&|Nn1j z0MS=oah(NHj3q&S!3+-1Zlr-YN#5=*tUvN!9tU#7N?apKg7ec#$`gxH8PYS;j0*D7 z6^!%@^bBp|_GJK7gn7C+hE&W6?YYR?;K1RmeVws@Ic1XZ&cErC7-<7ih3=n&$O8-AbydZPvd1h4VK1=GLcmtkzf;be3Jl Wo1>Y@*B}>Y1B0ilpUXO@geCy{=uV9Q literal 0 HcmV?d00001 diff --git a/samples/qt/OCCTOverview/res/view_bottom.png b/samples/qt/OCCTOverview/res/view_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..c7cfdc208aa04cd5f0109df2d262083e1b71de62 GIT binary patch literal 233 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!7%)r1n>(-?sK#ov=Pl)S*0|);9XJ`O&|Nn1j z0MS=oah(NHj3q&S!3+-1Zlr-YN#5=*tUvN!9tU#7N?apKg7ec#$`gxH8PYS;j0*D7 z6^!%@^bBp|_GJK7gn7C+hE&Xn?QP_22;gv;|CC|t!Q-4Vj)(rHd+Bmmx%k`qi+IeD z-PX$H6H&Nc^d3{mM+M_uz3yL^dS~TaGn&aPA8*1PC>Le_LomDNXXT9>-6wu$yyBJO WlFzshE?T;J_^FaAHf7qhq6^A*XP{?j8@De5 zs6yA%#WAE}PI7_+Gj~Hk-$7Om#{+!_dmA}TmWih@O1TaS?83{1OT?)Gj{+0 literal 0 HcmV?d00001 diff --git a/samples/qt/OCCTOverview/res/view_fitall.png b/samples/qt/OCCTOverview/res/view_fitall.png new file mode 100644 index 0000000000000000000000000000000000000000..21d2f423ef4acbf4380ff497084e7fb206037100 GIT binary patch literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!7%)r1n>(-?sKn{O^Pl)S*0|y!!82HV0oYtJyeg`d=T#E!A>Kj7jX5<^IG- zWuF9VJ&8BQ4WU+a-=k0smdMUac*xWgB?+c&Q#}%=uzu8aq Wv#}d9=CuH=VDNPHb6Mw<&;$Ud^G!kk literal 0 HcmV?d00001 diff --git a/samples/qt/OCCTOverview/res/view_front.png b/samples/qt/OCCTOverview/res/view_front.png new file mode 100644 index 0000000000000000000000000000000000000000..a9e99c59b697ddef7e013bb5c5957b9a6c45be01 GIT binary patch literal 238 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!7%)r1n>(-?sK#ov=Pl)S*0|);9XJ`O&|Nn1j z0MS=oah(NHj3q&S!3+-1Zlr-YN#5=*tUvN!9tU#7N?apKg7ec#$`gxH8PYS;j0*D7 z6^!%@^bBp|_GJK7M0>h8hE&Y)?Y+p`V8G#W{uX0^xI;;UT4_UF$^V%)8`Sn5cq+Jq zp@l1~sw^j`_to4Oq35mB&KQVrKY8Z9pY!dPr+HnTJ1Z0(rJdsMJpbXK8uODC*PR9K c-3$J~n&8hKB9R!|3bcm7)78&qol`;+0Em)S00000 literal 0 HcmV?d00001 diff --git a/samples/qt/OCCTOverview/res/view_left.png b/samples/qt/OCCTOverview/res/view_left.png new file mode 100644 index 0000000000000000000000000000000000000000..7d25b6ab2f8b8f778ac779da4db96d5a8d9f5756 GIT binary patch literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!7%)r1n>(-?sK#ov=Pl)S*0|);9XJ`O&|Nn1j z0MS=oah(NHj3q&S!3+-1Zlr-YN#5=*tUvN!9tU#7N?apKg7ec#$`gxH8PYS;j0*D7 z6^!%@^bBp|_GJK7gm}6*hE&W6?P=s}FyLW1e}U1fkipS>1+&PRf5tyE1->er|LiHZ z;y{;Yx0;W4{yUvx9tUeDi0HN)&s`XLvSi!D`1rIJ6XmlyZmoKff1`T;x$oZ|vZ?K7 V-?`&Y+ialu44$rjF6*2UngIO(RG`Pkan1T+sEd~k@tDPaMF snn^>8P{+}&O^zxI9?hI#>?@QQ)XuT#9Aufl8)zDXr>mdKI;Vst02TW;XaE2J literal 0 HcmV?d00001 diff --git a/samples/qt/OCCTOverview/res/view_right.png b/samples/qt/OCCTOverview/res/view_right.png new file mode 100644 index 0000000000000000000000000000000000000000..5540220cfa7e1f7a8b5258efe3bef0d1a70b2263 GIT binary patch literal 230 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!7%)r1n>(-?sK#ov=Pl)S*0|);9XJ`O&|Nn1j z0MS=oah(NHj3q&S!3+-1Zlr-YN#5=*tUvN!9tU#7N?apKg7ec#$`gxH8PYS;j0*D7 z6^!%@^bBp|_GJK71bezThE&Y)^>yTGFyP^y&A-8Z#Xbj#d#<1Vo3GuNEOkrZQVY`# z29aKu1Fr5mFF&zOeB9T{BDbmdKI;Vst0DV4DIRF3v literal 0 HcmV?d00001 diff --git a/samples/qt/OCCTOverview/res/view_top.png b/samples/qt/OCCTOverview/res/view_top.png new file mode 100644 index 0000000000000000000000000000000000000000..b788de36fb11bef11761670ac5ceda6892d5e7d0 GIT binary patch literal 235 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!7%)r1n>(-?sK#ov=Pl)S*0|);9XJ`O&|Nn1j z0MS=oah(NHj3q&S!3+-1Zlr-YN#5=*tUvN!9tU#7N?apKg7ec#$`gxH8PYS;j0*D7 z6^!%@^bBp|_GJK7M0mP5hE&YS^*tzfz<}e>3kF}c6PAweHZ}CWvk$(wZ2u<#Kaqw* zO=d5SIXXNJJ!_lGEFv=@=395$hf}p|ocC{7PrbT)j?VkVM$aAz>n2M+iq9xBK9$$> ahr!_{$FWT{v)h1nFnGH9xvX +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +ApplicationCommonWindow::ApplicationCommonWindow (ApplicationType theCategory) +: QMainWindow (nullptr), + myStdToolBar (nullptr), + myViewBar (nullptr), + myCasCadeBar (nullptr), + myFilePopup (nullptr), + myCategoryPopup (nullptr) +{ + myAppType = theCategory; + mySampleMapper = new QSignalMapper(this); + myExchangeMapper = new QSignalMapper(this); + myOcafMapper = new QSignalMapper(this); + myViewer3dMapper = new QSignalMapper(this); + myViewer2dMapper = new QSignalMapper(this); + + myCategoryMapper = new QSignalMapper(this); + + connect(mySampleMapper, static_cast(&QSignalMapper::mapped), + this, &ApplicationCommonWindow::onProcessSample); + connect(myExchangeMapper, static_cast(&QSignalMapper::mapped), + this, &ApplicationCommonWindow::onProcessExchange); + connect(myOcafMapper, static_cast(&QSignalMapper::mapped), + this, &ApplicationCommonWindow::onProcessOcaf); + connect(myViewer3dMapper, static_cast(&QSignalMapper::mapped), + this, &ApplicationCommonWindow::onProcessViewer3d); + connect(myViewer2dMapper, static_cast(&QSignalMapper::mapped), + this, &ApplicationCommonWindow::onProcessViewer2d); + + connect(myCategoryMapper, static_cast(&QSignalMapper::mapped), + this, &ApplicationCommonWindow::onChangeCategory); + + setFocusPolicy(Qt::StrongFocus); + + QFont aCodeViewFont; + aCodeViewFont.setFamily("Courier"); + aCodeViewFont.setFixedPitch(true); + aCodeViewFont.setPointSize(10); + + QGroupBox* aCodeFrame = new QGroupBox(tr("Sample code")); + QVBoxLayout* aCodeLayout = new QVBoxLayout(aCodeFrame); + aCodeLayout->setContentsMargins(3, 3, 3, 3); + myCodeView = new QTextEdit(aCodeFrame); + aCodeLayout->addWidget(myCodeView); + myCodeView->setDocumentTitle("Code"); + myCodeView->setLineWrapMode(QTextEdit::NoWrap); + myCodeView->setReadOnly(true); + myCodeView->setFont(aCodeViewFont); + myCodeViewHighlighter = new OcctHighlighter(myCodeView->document()); + + QGroupBox* aResultFrame = new QGroupBox(tr("Output")); + QVBoxLayout* aResultLayout = new QVBoxLayout(aResultFrame); + aResultLayout->setContentsMargins(3, 3, 3, 3); + myResultView = new QTextEdit(aResultFrame); + aResultLayout->addWidget(myResultView); + myResultView->setDocumentTitle("Output"); + myResultView->setReadOnly(true); + myResultView->setFont(aCodeViewFont); + + QSplitter* aCodeResultSplitter = new QSplitter(Qt::Vertical); + aCodeResultSplitter->addWidget(aCodeFrame); + aCodeResultSplitter->addWidget(aResultFrame); + + myDocument3d = createNewDocument(); + myDocument2d = createNewDocument(); + + QFrame* aViewFrame = new QFrame; + aViewFrame->setFrameStyle(QFrame::Panel | QFrame::Sunken); + aViewFrame->setLineWidth(3); + QVBoxLayout* aViewLayout = new QVBoxLayout(aViewFrame); + aViewLayout->setContentsMargins(0, 0, 0, 0); + myGeomWidget = new GeomWidget(myDocument3d, myDocument2d, this); + aViewLayout->addWidget(myGeomWidget); + //myGeomWidget->setContentsMargins(0, 0, 0, 0); + QSplitter* aGeomTextSplitter = new QSplitter(Qt::Horizontal); + + aGeomTextSplitter->addWidget(aViewFrame); + aGeomTextSplitter->addWidget(aCodeResultSplitter); + aGeomTextSplitter->setStretchFactor(0, 1); + aGeomTextSplitter->setStretchFactor(1, 1); + QList aSizeList{ 640, 640 }; + aGeomTextSplitter->setSizes(aSizeList); + setCentralWidget(aGeomTextSplitter); + + Q_INIT_RESOURCE(Samples); + + TCollection_AsciiString aSampleSourcePach = getSampleSourceDir(); + myGeometrySamples = new GeometrySamples(aSampleSourcePach, + myDocument3d->getContext()); + myTopologySamples = new TopologySamples(aSampleSourcePach, + myDocument3d->getContext()); + myTriangulationSamples = new TriangulationSamples(aSampleSourcePach, + myDocument3d->getContext()); + myDataExchangeSamples = new DataExchangeSamples(aSampleSourcePach, + myGeomWidget->Get3dView(), + myDocument3d->getContext()); + myOcafSamples = new OcafSamples(aSampleSourcePach, + myDocument3d->getViewer(), + myDocument3d->getContext()); + myViewer3dSamples = new Viewer3dSamples(aSampleSourcePach, + myGeomWidget->Get3dView(), + myDocument3d->getContext()); + myViewer2dSamples = new Viewer2dSamples(aSampleSourcePach, + myGeomWidget->Get2dView(), + myDocument2d->getViewer(), + myDocument2d->getContext()); + + MenuFormJson(":/menus/Geometry.json", mySampleMapper, myGeometryMenus); + MenuFormJson(":/menus/Topology.json", mySampleMapper, myTopologyMenus); + MenuFormJson(":/menus/Triangulation.json", mySampleMapper, myTriangulationMenus); + MenuFormJson(":/menus/DataExchange.json", myExchangeMapper, myDataExchangeMenus); + MenuFormJson(":/menus/Ocaf.json", myOcafMapper, myOcafMenus); + MenuFormJson(":/menus/Viewer3d.json", myViewer3dMapper, myViewer3dMenus); + MenuFormJson(":/menus/Viewer2d.json", myViewer2dMapper, myViewer2dMenus); + + onChangeCategory(ALL_CATEGORIES[myAppType]); + + resize(1280, 560); +} + +void ApplicationCommonWindow::RebuildMenu() +{ + menuBar()->clear(); + + myStdActions[FileQuit] = CreateAction(&ApplicationCommonWindow::onCloseAllWindows, "Quit", "CTRL+Q"); + myStdActions[HelpAbout] = CreateAction(&ApplicationCommonWindow::onAbout, "About", "F1", ":/icons/help.png"); + + // populate a menu with all actions + myFilePopup = new QMenu(this); + myFilePopup = menuBar()->addMenu(tr("&File")); + myFilePopup->addAction(myStdActions[FileQuit]); + + myCategoryPopup = new QMenu(this); + myCategoryPopup = menuBar()->addMenu(tr("&Category")); + + for (ApplicationType aCategory: ALL_CATEGORIES.keys()) + { + QString aCategoryName = ALL_CATEGORIES.value(aCategory); + QAction* anAction = myCategoryPopup->addAction(aCategoryName); + anAction->setText(aCategoryName); + myCategoryMapper->setMapping(anAction, aCategoryName); + connect(anAction, &QAction::triggered, myCategoryMapper, static_cast(&QSignalMapper::map)); + myCategoryPopup->addAction(anAction); + myCategoryActions.insert(aCategory, anAction); + } + + for (QMenu* aSampleMenu : GetCurrentMenus()) + { + menuBar()->addMenu(aSampleMenu); + } + + // add a help menu + QMenu* aHelp = new QMenu(this); + menuBar()->addSeparator(); + aHelp = menuBar()->addMenu(tr("&Help")); + aHelp->addAction(myStdActions[HelpAbout]); +} + +Handle(BaseSample) ApplicationCommonWindow::GetCurrentSamples() +{ + switch (myAppType) + { + case Geometry: return myGeometrySamples; + case Topology: return myTopologySamples; + case Triangulation: return myTriangulationSamples; + case DataExchange: return myDataExchangeSamples; + case Ocaf: return myOcafSamples; + case Viewer2d: return myViewer2dSamples; + case Viewer3d: return myViewer3dSamples; + case Unknown: + break; + } + throw QString("Unknown Application type"); +} + +const QList& ApplicationCommonWindow::GetCurrentMenus() +{ + switch (myAppType) + { + case Geometry: return myGeometryMenus; + case Topology: return myTopologyMenus; + case Triangulation: return myTriangulationMenus; + case DataExchange: return myDataExchangeMenus; + case Ocaf: return myOcafMenus; + case Viewer2d: return myViewer2dMenus; + case Viewer3d: return myViewer3dMenus; + case Unknown: + break; + } + throw QString("Unknown Application type"); +} + +DocumentCommon* ApplicationCommonWindow::createNewDocument() +{ + return new DocumentCommon(this); +} + +void ApplicationCommonWindow::onChangeCategory(const QString& theCategory) +{ + myAppType = ALL_CATEGORIES.key(theCategory); + setWindowTitle(ALL_CATEGORIES[myAppType]); + + myOcafSamples->ClearExtra(); + myViewer3dSamples->ClearExtra(); + myViewer2dSamples->ClearExtra(); + + GetCurrentSamples()->Clear(); + myDocument3d->Clear(); + myDocument2d->Clear(); + + myCodeView->setPlainText(""); + myResultView->setPlainText(""); + GetCurrentSamples()->AppendCube(); + myDocument3d->SetObjects(GetCurrentSamples()->Get3dObjects()); + myGeomWidget->FitAll(); + + RebuildMenu(); + + switch (myAppType) + { + case DataExchange: + { + myDataExchangeSamples->AppendBottle(); + myDocument3d->SetObjects(GetCurrentSamples()->Get3dObjects()); + myGeomWidget->Show3d(); + break; + } + case Ocaf: + { + onProcessOcaf("CreateOcafDocument"); + myGeomWidget->Show3d(); + break; + } + case Viewer2d: + { + myGeomWidget->Show2d(); + break; + } + case Viewer3d: + { + myViewer3dSamples->AppendBottle(); + myDocument3d->SetObjects(GetCurrentSamples()->Get3dObjects()); + myGeomWidget->Show3d(); + break; + } + case Geometry: + case Topology: + case Triangulation: + case Unknown: + { + break; + } + } +} + +void ApplicationCommonWindow::onAbout() +{ + QMessageBox::information(this, tr("OCCT Overview"), + tr("Qt based application to study OpenCASCADE Technology"), + tr("Ok"), QString::null, QString::null, 0, 0); +} + +TCollection_AsciiString ApplicationCommonWindow::getSampleSourceDir() +{ + TCollection_AsciiString aSampleSourceDir = OSD_Environment("CSF_OCCTOverviewSampleCodePath").Value(); + if (aSampleSourceDir.IsEmpty()) + { + TCollection_AsciiString aCasRoot = OSD_Environment("CASROOT").Value(); + if (!aCasRoot.IsEmpty()) + { + aSampleSourceDir = aCasRoot + "/samples/OCCTOverview/code"; + } + } + return aSampleSourceDir; +} + +template +QAction* ApplicationCommonWindow::CreateAction (PointerToMemberFunction theHandlerMethod, + const QString& theActionName, + const QString& theShortcut, + const QString& theIconName) +{ + QAction* aAction(NULL); + if (theIconName.isEmpty()) + { + aAction = new QAction(theActionName, this); + } + else + { + QPixmap aIcon = QPixmap(theIconName); + aAction = new QAction(aIcon, theActionName, this); + } + aAction->setToolTip(theActionName); + aAction->setStatusTip(theActionName); + aAction->setShortcut(theShortcut); + connect(aAction, &QAction::triggered, this, theHandlerMethod); + return aAction; +} + +template +QAction* ApplicationCommonWindow::CreateSample (PointerToMemberFunction theHandlerMethod, + const char* theActionName) +{ + QAction* aAction = new QAction(QObject::tr(theActionName), this); + connect(aAction, &QAction::triggered, this, theHandlerMethod); + return aAction; +} + +void ApplicationCommonWindow::resizeEvent(QResizeEvent* e) +{ + QMainWindow::resizeEvent(e); + statusBar()->setSizeGripEnabled(!isMaximized()); +} + +void ApplicationCommonWindow::onProcessSample(const QString& theSampleName) +{ + QApplication::setOverrideCursor(Qt::WaitCursor); + setWindowTitle(ALL_CATEGORIES[myAppType] + " - " + theSampleName); + GetCurrentSamples()->Process(theSampleName.toUtf8().data()); + myDocument3d->SetObjects(GetCurrentSamples()->Get3dObjects()); + myDocument2d->SetObjects(GetCurrentSamples()->Get2dObjects()); + myCodeView->setPlainText(GetCurrentSamples()->GetCode().ToCString()); + myResultView->setPlainText(GetCurrentSamples()->GetResult().ToCString()); + myGeomWidget->FitAll(); + QApplication::restoreOverrideCursor(); +} + +void ApplicationCommonWindow::onProcessExchange(const QString& theSampleName) +{ + setWindowTitle(ALL_CATEGORIES[myAppType] + " - " + theSampleName); + int aMode = 0; + QString aFileName = selectFileName(theSampleName, getDataExchangeDialog(theSampleName), aMode); + if (aFileName.isEmpty()) + { + return; + } + + QApplication::setOverrideCursor(Qt::WaitCursor); + myDataExchangeSamples->SetFileName(aFileName.toUtf8().data()); + myDataExchangeSamples->SetStepType(static_cast(aMode)); + myDataExchangeSamples->Process(theSampleName.toUtf8().data()); + myDocument3d->SetObjects(myDataExchangeSamples->Get3dObjects()); + myDocument2d->SetObjects(myDataExchangeSamples->Get2dObjects()); + myCodeView->setPlainText(myDataExchangeSamples->GetCode().ToCString()); + myResultView->setPlainText(myDataExchangeSamples->GetResult().ToCString()); + myGeomWidget->FitAll(); + QApplication::restoreOverrideCursor(); +} + +void ApplicationCommonWindow::onProcessOcaf(const QString& theSampleName) +{ + setWindowTitle(ALL_CATEGORIES[myAppType] + " - " + theSampleName); + + if (theSampleName.indexOf("Dialog") == 0) + { + int aMode = 0; // not used + QString aFileName = selectFileName(theSampleName, getOcafDialog(theSampleName), aMode); + if (aFileName.isEmpty()) + { + return; + } + myOcafSamples->SetFileName(aFileName.toUtf8().data()); + } + QApplication::setOverrideCursor(Qt::WaitCursor); + myOcafSamples->Process(theSampleName.toUtf8().data()); + myDocument2d->SetObjects(myOcafSamples->Get2dObjects()); + myCodeView->setPlainText(myOcafSamples->GetCode().ToCString()); + myResultView->setPlainText(myOcafSamples->GetResult().ToCString()); + QApplication::restoreOverrideCursor(); +} + +void ApplicationCommonWindow::onProcessViewer3d(const QString& theSampleName) +{ + setWindowTitle(ALL_CATEGORIES[myAppType] + " - " + theSampleName); + + QApplication::setOverrideCursor(Qt::WaitCursor); + myViewer3dSamples->Process(theSampleName.toUtf8().data()); + myCodeView->setPlainText(myViewer3dSamples->GetCode().ToCString()); + myResultView->setPlainText(myViewer3dSamples->GetResult().ToCString()); + myGeomWidget->FitAll(); + QApplication::restoreOverrideCursor(); +} + +void ApplicationCommonWindow::onProcessViewer2d(const QString& theSampleName) +{ + setWindowTitle(ALL_CATEGORIES[myAppType] + " - " + theSampleName); + + Standard_Boolean anIsFileSample = Viewer2dSamples::IsFileSample(theSampleName.toUtf8().data()); + QString aFileName; + if (anIsFileSample) + { + int aMode = 0; // not used + aFileName = selectFileName(theSampleName, getOcafDialog(theSampleName), aMode); + if (aFileName.isEmpty()) + { + return; + } + + myViewer2dSamples->SetFileName(aFileName.toUtf8().data()); + } + if (!anIsFileSample || (anIsFileSample && !aFileName.isEmpty())) + { + QApplication::setOverrideCursor(Qt::WaitCursor); + myViewer2dSamples->Process(theSampleName.toUtf8().data()); + if (!Viewer2dSamples::IsShadedSample(theSampleName.toUtf8().data())) + { + myDocument2d->SetObjects(myViewer2dSamples->Get2dObjects(), Standard_False); + } + else + { + myDocument2d->SetObjects(myViewer2dSamples->Get2dObjects(), Standard_True); + } + myCodeView->setPlainText(myViewer2dSamples->GetCode().ToCString()); + myResultView->setPlainText(myViewer2dSamples->GetResult().ToCString()); + myGeomWidget->Show2d(); + QApplication::restoreOverrideCursor(); + } + else + { + myResultView->setPlainText("No file selected!"); + } +} + +QString ApplicationCommonWindow::selectFileName(const QString& theSampleName, + TranslateDialog* theDialog, int& theMode) +{ + Q_UNUSED(theSampleName) + + std::shared_ptr aDialog(theDialog); + + int ret = aDialog->exec(); + theMode = aDialog->getMode(); + + qApp->processEvents(); + + QString aFilename; + QStringList aFileNameList; + if (ret != QDialog::Accepted) + { + return aFilename; + } + aFileNameList = aDialog->selectedFiles(); + if (!aFileNameList.isEmpty()) + { + aFilename = aFileNameList[0]; + } + + if (!QFileInfo(aFilename).completeSuffix().length()) + { + QString selFilter = aDialog->selectedNameFilter(); + int idx = selFilter.indexOf("(*."); + if (idx != -1) + { + QString tail = selFilter.mid(idx + 3); + idx = tail.indexOf(" "); + if (idx == -1) + { + idx = tail.indexOf(")"); + } + QString ext = tail.left(idx); + if (ext.length()) + { + aFilename += QString(".") + ext; + } + } + } + + return aFilename; +} + +TranslateDialog* ApplicationCommonWindow::getDataExchangeDialog(const QString& theSampleName) +{ + TranslateDialog* aTranslateDialog = new TranslateDialog(this, 0, true); + TCollection_AsciiString aSampleName(theSampleName.toUtf8().data()); + + if (DataExchangeSamples::IsExportSample(aSampleName)) + { + aTranslateDialog->setWindowTitle("Export file"); + aTranslateDialog->setFileMode(QFileDialog::AnyFile); + aTranslateDialog->setAcceptMode(QFileDialog::AcceptSave); + } + else if (DataExchangeSamples::IsImportSample(aSampleName)) + { + aTranslateDialog->setWindowTitle("Import file"); + aTranslateDialog->setFileMode(QFileDialog::ExistingFile); + aTranslateDialog->setAcceptMode(QFileDialog::AcceptOpen); + } + QString aFormatFilter; + if (DataExchangeSamples::IsBrepSample(aSampleName)) + { + aFormatFilter = "BREP Files(*.brep *.rle)"; + } + else if (DataExchangeSamples::IsStepSample(aSampleName)) + { + aFormatFilter = "STEP Files (*.stp *.step)"; + aTranslateDialog->addMode(STEPControl_ManifoldSolidBrep, "Manifold Solid Brep"); + aTranslateDialog->addMode(STEPControl_FacetedBrep, "Faceted Brep"); + aTranslateDialog->addMode(STEPControl_ShellBasedSurfaceModel, "Shell Based Surface Model"); + aTranslateDialog->addMode(STEPControl_GeometricCurveSet, "Geometric Curve Set"); + } + else if (DataExchangeSamples::IsIgesSample(aSampleName)) + { + aFormatFilter = "IGES Files (*.igs *.iges)"; + } + else if (DataExchangeSamples::IsStlSample(aSampleName)) + { + aFormatFilter = "STL Files (*.stl)"; + } + else if (DataExchangeSamples::IsVrmlSample(aSampleName)) + { + aFormatFilter = "VRML Files (*.vrml)"; + } + else if (DataExchangeSamples::IsImageSample(aSampleName)) + { + aFormatFilter = "All Image Files (*.bmp *.gif *.jpg *.jpeg *.png *.tga)"; + } + QStringList aFilters; + aFilters.append(aFormatFilter); + aFilters.append("All Files(*.*)"); + + aTranslateDialog->setNameFilters(aFilters); + aTranslateDialog->clear(); + return aTranslateDialog; +} + +TranslateDialog* ApplicationCommonWindow::getOcafDialog(const QString& theSampleName) +{ + TranslateDialog* aTranslateDialog = new TranslateDialog(this, 0, true); + TCollection_AsciiString aSampleName(theSampleName.toUtf8().data()); + + if (OcafSamples::IsExportSample(aSampleName)) + { + aTranslateDialog->setWindowTitle("Export file"); + aTranslateDialog->setFileMode(QFileDialog::AnyFile); + aTranslateDialog->setAcceptMode(QFileDialog::AcceptSave); + } + else if (OcafSamples::IsImportSample(aSampleName)) + { + aTranslateDialog->setWindowTitle("Import file"); + aTranslateDialog->setFileMode(QFileDialog::ExistingFile); + aTranslateDialog->setAcceptMode(QFileDialog::AcceptOpen); + } + QStringList aFilters; + if (OcafSamples::IsBinarySample(aSampleName)) + { + aFilters.append("Binary OCAF Sample (*.cbf)"); + } + if (OcafSamples::IsXmlSample(aSampleName)) + { + aFilters.append("XML OCAF Sample (*.xml)"); + } + aFilters.append("All Files(*.*)"); + + aTranslateDialog->setNameFilters(aFilters); + aTranslateDialog->clear(); + return aTranslateDialog; +} + +QMenu* ApplicationCommonWindow::MenuFromJsonObject (const QJsonValue& theJsonValue, + const QString& theKey, + QWidget* theParent, + QSignalMapper* theMapper) +{ + QMenu* aMenu = new QMenu(theKey, theParent); + if (theJsonValue.isObject()) + { + QJsonObject aBranchObject = theJsonValue.toObject(); + for (const QString& aBranchKey : aBranchObject.keys()) + { + aMenu->addMenu(MenuFromJsonObject(aBranchObject.value(aBranchKey), aBranchKey, aMenu, theMapper)); + } + } + else if (theJsonValue.isArray()) + { + QJsonArray aDataArray = theJsonValue.toArray(); + for (const QJsonValue& aDataValue : aDataArray) + { + if (aDataValue.isObject()) + { + QJsonObject aDataObject = aDataValue.toObject(); + QString aSampleName = aDataObject["function"].toString(); + QAction* anAction = aMenu->addAction(aSampleName); + anAction->setText(aDataObject["text"].toString()); + + theMapper->setMapping(anAction, aSampleName); + connect(anAction, &QAction::triggered, theMapper, + static_cast(&QSignalMapper::map)); + } + } + } + return aMenu; +} + +void ApplicationCommonWindow::MenuFormJson (const QString& thePath, + QSignalMapper* theMapper, + QList& theMunusList) +{ + theMunusList.clear(); + QFile aJsonFile(thePath); + QString anErrorMessage; + if (aJsonFile.error() != QFile::NoError) + { + anErrorMessage = aJsonFile.errorString(); + Message::SendFail() << "QFile creating error: " << anErrorMessage.toUtf8().constData(); + return; + } + if (!aJsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) + { + Message::SendFail() << "File " << thePath.toUtf8().constData() << " could not open"; + if (aJsonFile.error() != QFile::NoError) + { + anErrorMessage = aJsonFile.errorString(); + Message::SendFail() << "QFile opening error: " << anErrorMessage.toUtf8().constData(); + } + return; + } + QString aJsonString = aJsonFile.readAll(); + aJsonFile.close(); + + QJsonDocument aJsonDoc = QJsonDocument::fromJson(aJsonString.toUtf8()); + if (aJsonDoc.isObject()) + { + QJsonObject aJsonObj = aJsonDoc.object(); + for (const QString& aKey : aJsonObj.keys()) + { + QJsonValue aJsonValue = aJsonObj.value(aKey); + if (aJsonValue.isObject()) + { + theMunusList.push_back(MenuFromJsonObject(aJsonValue.toObject(), aKey, this, theMapper)); + } + } + } +} diff --git a/samples/qt/OCCTOverview/src/ApplicationCommon.h b/samples/qt/OCCTOverview/src/ApplicationCommon.h new file mode 100644 index 0000000000..4adcab05cc --- /dev/null +++ b/samples/qt/OCCTOverview/src/ApplicationCommon.h @@ -0,0 +1,197 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef APPLICATION_COMMON_OVERVIEW_H +#define APPLICATION_COMMON_OVERVIEW_H + +#include "BaseSample.h" +#include "CommonSample.h" +#include "DataExchangeSamples.h" +#include "DocumentCommon.h" +#include "GeometrySamples.h" +#include "GeomWidget.h" +#include "OcafSamples.h" +#include "OcctHighlighter.h" +#include "TopologySamples.h" +#include "TranslateDialog.h" +#include "TriangulationSamples.h" +#include "View.h" +#include "Viewer2dSamples.h" +#include "Viewer3dSamples.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum StdActions +{ + FileNew, FilePrefUseVBO, FileClose, FilePreferences, FileQuit, ViewTool, ViewStatus, HelpAbout +}; + +enum ToolActions +{ + ToolWireframe, ToolShading, ToolColor, ToolMaterial, ToolTransparency, ToolDelete +}; + +enum ApplicationType +{ + Geometry, + Topology, + Triangulation, + DataExchange, + Ocaf, + Viewer2d, + Viewer3d, + Unknown +}; + +const QMap ALL_CATEGORIES = +{ + { ApplicationType::Geometry,"Geometry"}, + { ApplicationType::Topology, "Topology"}, + { ApplicationType::Triangulation, "Triangulation"}, + { ApplicationType::DataExchange, "DataExchange"}, + { ApplicationType::Ocaf, "OCAF"}, + { ApplicationType::Viewer3d, "3D viewer"}, + { ApplicationType::Viewer2d, "2D Viewer"} +}; + +//! Main application window +class COMMONSAMPLE_EXPORT ApplicationCommonWindow: public QMainWindow +{ + Q_OBJECT + +public: + ApplicationCommonWindow(ApplicationType theCategory); + + ApplicationType GetApplicationType() const { return myAppType; } + void SetApplicationType(ApplicationType theApplicationType) { myAppType = theApplicationType; } + + static TCollection_AsciiString getSampleSourceDir(); + +protected: + virtual DocumentCommon* createNewDocument(); + +public slots: + virtual void onAbout(); + virtual void onChangeCategory(const QString& theCategory); + +protected: + template + QAction* CreateAction(PointerToMemberFunction theHandlerMethod, + const QString& theActionName, + const QString& theShortcut = "", + const QString& theIconName = ""); + + template + QAction* CreateSample(PointerToMemberFunction theHandlerMethod, + const char* theActionName); + + virtual void resizeEvent( QResizeEvent* ); + QMenu* getFilePopup() { return myFilePopup; } + QToolBar* getCasCadeBar() { return myCasCadeBar; } + + QMenu* MenuFromJsonObject (const QJsonValue& theJsonValue, + const QString& theKey, + QWidget* theParent, + QSignalMapper* theMapper); + void MenuFormJson (const QString& thePath, + QSignalMapper* theMapper, + QList& theMunusList); + +private slots: + void onCloseAllWindows() { qApp->closeAllWindows(); } + + void onProcessSample(const QString& theSampleName); + void onProcessExchange(const QString& theSampleName); + void onProcessOcaf(const QString& theSampleName); + void onProcessViewer3d(const QString& theSampleName); + void onProcessViewer2d(const QString& theSampleName); + +private: + + void RebuildMenu(); + Handle(BaseSample) GetCurrentSamples(); + const QList& GetCurrentMenus(); + + QString selectFileName(const QString& theSampleName, TranslateDialog* theDialog, int& theMode); + TranslateDialog* getDataExchangeDialog(const QString& theSampleName); + TranslateDialog* getOcafDialog(const QString& theSampleName); + +private: + ApplicationType myAppType; + + Handle(GeometrySamples) myGeometrySamples; + Handle(TopologySamples) myTopologySamples; + Handle(TriangulationSamples) myTriangulationSamples; + Handle(DataExchangeSamples) myDataExchangeSamples; + Handle(OcafSamples) myOcafSamples; + Handle(Viewer3dSamples) myViewer3dSamples; + Handle(Viewer2dSamples) myViewer2dSamples; + + QMap myStdActions; + QMap myCategoryActions; + QMap myToolActions; + QMap myMaterialActions; + + QToolBar* myStdToolBar; + QToolBar* myViewBar; + QToolBar* myCasCadeBar; + QMenu* myFilePopup; + QMenu* myCategoryPopup; + +// QList mySamplePopups; + QList myGeometryMenus; + QList myTopologyMenus; + QList myTriangulationMenus; + QList myDataExchangeMenus; + QList myOcafMenus; + QList myViewer3dMenus; + QList myViewer2dMenus; + + QSignalMapper* mySampleMapper; + QSignalMapper* myExchangeMapper; + QSignalMapper* myOcafMapper; + QSignalMapper* myViewer3dMapper; + QSignalMapper* myViewer2dMapper; + + QSignalMapper* myCategoryMapper; + + QTextEdit* myCodeView; + QTextEdit* myResultView; + OcctHighlighter* myCodeViewHighlighter; + + GeomWidget* myGeomWidget; + + DocumentCommon* myDocument3d; + DocumentCommon* myDocument2d; +}; + +#endif diff --git a/samples/qt/OCCTOverview/src/CommonSample.h b/samples/qt/OCCTOverview/src/CommonSample.h new file mode 100644 index 0000000000..0bb38acba6 --- /dev/null +++ b/samples/qt/OCCTOverview/src/CommonSample.h @@ -0,0 +1,43 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef COMMONSAMPLE_H +#define COMMONSAMPLE_H + +#ifndef NO_COMMONSAMPLE_EXPORTS +#ifdef COMMONSAMPLE_EXPORTS +#ifdef _WIN32 +#define COMMONSAMPLE_EXPORT __declspec( dllexport ) +#else +#define COMMONSAMPLE_EXPORT +#endif +#else +#ifdef _WIN32 +#define COMMONSAMPLE_EXPORT __declspec( dllimport ) +#else +#define COMMONSAMPLE_EXPORT +#endif +#endif +#else +#define COMMONSAMPLE_EXPORT +#endif + +#endif diff --git a/samples/qt/OCCTOverview/src/DocumentCommon.cxx b/samples/qt/OCCTOverview/src/DocumentCommon.cxx new file mode 100644 index 0000000000..1eb018aba5 --- /dev/null +++ b/samples/qt/OCCTOverview/src/DocumentCommon.cxx @@ -0,0 +1,108 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "DocumentCommon.h" + +#include "ApplicationCommon.h" +#include "Transparency.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +// ======================================================================= +// function : Viewer +// purpose : +// ======================================================================= +Handle(V3d_Viewer) DocumentCommon::Viewer(const Standard_ExtString, + const Standard_CString, + const Standard_Real theViewSize, + const V3d_TypeOfOrientation theViewProj, + const Standard_Boolean theComputedMode, + const Standard_Boolean theDefaultComputedMode) +{ + static Handle(OpenGl_GraphicDriver) aGraphicDriver; + if (aGraphicDriver.IsNull()) + { + Handle(Aspect_DisplayConnection) aDisplayConnection; +#if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) + aDisplayConnection = new Aspect_DisplayConnection(OSD_Environment("DISPLAY").Value()); +#endif + aGraphicDriver = new OpenGl_GraphicDriver(aDisplayConnection); + } + + Handle(V3d_Viewer) aViewer = new V3d_Viewer(aGraphicDriver); + aViewer->SetDefaultViewSize(theViewSize); + aViewer->SetDefaultViewProj(theViewProj); + aViewer->SetComputedMode(theComputedMode); + aViewer->SetDefaultComputedMode(theDefaultComputedMode); + return aViewer; +} + +DocumentCommon::DocumentCommon(ApplicationCommonWindow* theApp) +: QObject (theApp), + myContextIsEmpty(true) +{ + TCollection_ExtendedString a3DName("Visu3D"); + + myViewer = Viewer(a3DName.ToExtString(), "", 1000.0, V3d_XposYnegZpos, Standard_True, Standard_True); + + myViewer->SetDefaultLights(); + myViewer->SetLightOn(); + + myContext = new AIS_InteractiveContext(myViewer); +} + +void DocumentCommon::SetObjects (const NCollection_Vector& theObjects, + Standard_Boolean theDisplayShaded) +{ + myContext->RemoveAll(Standard_False); + myContextIsEmpty = theObjects.IsEmpty(); + for (const Handle(AIS_InteractiveObject) anObject : theObjects) + { + if (!theDisplayShaded) + { + myContext->Display(anObject, Standard_False); + } + else + { + myContext->Display(anObject, AIS_Shaded, 0, Standard_False); + } + } + myViewer->Redraw(); +} + +void DocumentCommon::Clear() +{ + myContext->RemoveAll(Standard_True); + myContextIsEmpty = true; +} diff --git a/samples/qt/OCCTOverview/src/DocumentCommon.h b/samples/qt/OCCTOverview/src/DocumentCommon.h new file mode 100644 index 0000000000..b9c0fd312f --- /dev/null +++ b/samples/qt/OCCTOverview/src/DocumentCommon.h @@ -0,0 +1,75 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef DOCUMENT_COMMON_OVERVIEW_H +#define DOCUMENT_COMMON_OVERVIEW_H + +#include "CommonSample.h" + +#include +#include +#include +#include + +#include +#include + +class ApplicationCommonWindow; + +//! Implements visualization of samples content +class COMMONSAMPLE_EXPORT DocumentCommon : public QObject +{ + Q_OBJECT +public: + + DocumentCommon(ApplicationCommonWindow* ); + ~DocumentCommon() { } + + const Handle(AIS_InteractiveContext)& getContext() { return myContext; } + + const Handle(V3d_Viewer)& getViewer() { return myViewer; } + + void setViewer (const Handle(V3d_Viewer)& theViewer) { myViewer = theViewer; } + + void SetObjects(const NCollection_Vector& theObjects, + Standard_Boolean theDisplayShaded = Standard_False); + void Clear(); + bool IsEmpty() const { return myContextIsEmpty; } + +signals: + void selectionChanged(); + void sendCloseDocument( DocumentCommon* ); + +private: + Handle(V3d_Viewer) Viewer (const Standard_ExtString theName, + const Standard_CString theDomain, + const Standard_Real theViewSize, + const V3d_TypeOfOrientation theViewProj, + const Standard_Boolean theComputedMode, + const Standard_Boolean theDefaultComputedMode ); + +private: + Handle(V3d_Viewer) myViewer; + Handle(AIS_InteractiveContext) myContext; + bool myContextIsEmpty; +}; + +#endif diff --git a/samples/qt/OCCTOverview/src/FILES b/samples/qt/OCCTOverview/src/FILES new file mode 100644 index 0000000000..64a1f81afc --- /dev/null +++ b/samples/qt/OCCTOverview/src/FILES @@ -0,0 +1,19 @@ +ApplicationCommon.cxx +ApplicationCommon.h +CommonSample.h +DocumentCommon.cxx +DocumentCommon.h +GeomWidget.cxx +GeomWidget.h +Main.cxx +OcctHighlighter.cxx +OcctHighlighter.h +OcctWindow.cxx +OcctWindow.h +OCCTOverview.qrc +TranslateDialog.h +TranslateDialog.cxx +Transparency.cxx +Transparency.h +View.cxx +View.h diff --git a/samples/qt/OCCTOverview/src/GeomWidget.cxx b/samples/qt/OCCTOverview/src/GeomWidget.cxx new file mode 100644 index 0000000000..a1c0438726 --- /dev/null +++ b/samples/qt/OCCTOverview/src/GeomWidget.cxx @@ -0,0 +1,100 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "GeomWidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +GeomWidget::GeomWidget (DocumentCommon* theDocument3d, + DocumentCommon* theDocument2d, + QWidget* theParent) +: QWidget (theParent), + myDocument3d(theDocument3d), + myDocument2d(theDocument2d) +{ + QVBoxLayout* aMainLayout = new QVBoxLayout(this); + aMainLayout->setContentsMargins(0, 0, 0, 0); + + my2dVidget = new QWidget; + QVBoxLayout* a2dLayout = new QVBoxLayout(my2dVidget); + a2dLayout->setContentsMargins(0, 0, 0, 0); + a2dLayout->setSpacing(0); + myView2d = new View(myDocument2d->getContext(), false, this); + QToolBar* aToolBar2d = new QToolBar; + aToolBar2d->addActions(myView2d->getViewActions()); + a2dLayout->addWidget(aToolBar2d); + a2dLayout->addWidget(myView2d); + + my3dVidget = new QWidget; + QVBoxLayout* a3dLayout = new QVBoxLayout(my3dVidget); + a3dLayout->setContentsMargins(0, 0, 0, 0); + a3dLayout->setSpacing(0); + myView3d = new View(myDocument3d->getContext(), true, this); + QToolBar* aToolBar3d = new QToolBar; + aToolBar3d->addActions(myView3d->getViewActions()); + aToolBar3d->addSeparator(); + aToolBar3d->addActions(myView3d->getRaytraceActions()); + a3dLayout->addWidget(aToolBar3d); + a3dLayout->addWidget(myView3d); + + myStackWidget = new QStackedWidget(this); + aMainLayout->addWidget(myStackWidget); + myStackWidget->addWidget(my2dVidget); + myStackWidget->addWidget(my3dVidget); + + FitAll(); +} + +void GeomWidget::FitAll() +{ + if (myDocument2d->IsEmpty()) + Show3d(); + else + Show2d(); +} + +void GeomWidget::Show3d() +{ + myView3d->axo(); + myView3d->fitAll(); + QAction* aShadingAction = myView3d->getViewAction(ViewAction::Shading); + aShadingAction->trigger(); + aShadingAction->setChecked(true); + QAction* aHlrOffAction = myView3d->getViewAction(ViewAction::HlrOff); + aHlrOffAction->trigger(); + aHlrOffAction->setChecked(true); + myStackWidget->setCurrentWidget(my3dVidget); + setStatusTip("Mouse buttons: Right-Zoom, Middle-Pan, Left-Rotate"); +} + +void GeomWidget::Show2d() +{ + myView2d->fitAll(); + myStackWidget->setCurrentWidget(my2dVidget); + setStatusTip("Mouse buttons: Right-Zoom, Middle-Pan"); +} diff --git a/samples/qt/OCCTOverview/src/GeomWidget.h b/samples/qt/OCCTOverview/src/GeomWidget.h new file mode 100644 index 0000000000..77165c6c89 --- /dev/null +++ b/samples/qt/OCCTOverview/src/GeomWidget.h @@ -0,0 +1,65 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef GEOMWIDGET_H +#define GEOMWIDGET_H + +#include "View.h" +#include "DocumentCommon.h" + +#include +#include +#include + +class ApplicationCommon; +class QStackedWidget; + +//! Qt widget for organize 3D & 2D documents +class GeomWidget : public QWidget +{ + Q_OBJECT +public: + GeomWidget(DocumentCommon* theDocument3d, + DocumentCommon* theDocument2d, + QWidget* theParent = nullptr); + + void FitAll(); + + Handle(V3d_View) Get3dView() { return myView3d->getView(); } + + Handle(V3d_View) Get2dView() { return myView2d->getView(); } + + void Show3d(); + void Show2d(); + +private: + View* myView3d; + View* myView2d; + + QWidget* my3dVidget; + QWidget* my2dVidget; + QStackedWidget* myStackWidget; + + DocumentCommon* myDocument3d; + DocumentCommon* myDocument2d; +}; + +#endif //GEOMWIDGET_H diff --git a/samples/qt/OCCTOverview/src/Main.cxx b/samples/qt/OCCTOverview/src/Main.cxx new file mode 100644 index 0000000000..675d5646b7 --- /dev/null +++ b/samples/qt/OCCTOverview/src/Main.cxx @@ -0,0 +1,78 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "ApplicationCommon.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +int main ( int argc, char* argv[] ) +{ + Q_INIT_RESOURCE(OCCTOverview); + + QApplication aQApp( argc, argv ); + + QSettings settings("OCCTOverview.conf", QSettings::IniFormat); + settings.beginGroup("ApplicationSetting"); + ApplicationType aCategory = static_cast(settings.value("ApplicationType", "").toInt()); + settings.endGroup(); + + ApplicationCommonWindow* aWindow = new ApplicationCommonWindow(aCategory); + QString aResName(":/icons/lamp.png"); + aWindow->setWindowIcon(QPixmap(aResName)); + + settings.beginGroup("WindowPosition"); + int x = settings.value("x", -1).toInt(); + int y = settings.value("y", -1).toInt(); + int width = settings.value("width", -1).toInt(); + int height = settings.value("height", -1).toInt(); + settings.endGroup(); + + if (x > 0 && y > 0 && width > 0 && height > 0) + { + aWindow->setGeometry(x, y, width, height); + } + aWindow->SetApplicationType(aCategory); + + aWindow->show(); + int aResult = aQApp.exec(); + + settings.beginGroup("WindowPosition"); + settings.setValue("x", aWindow->x()); + settings.setValue("y", aWindow->y()); + settings.setValue("width", aWindow->width()); + settings.setValue("height", aWindow->height()); + settings.endGroup(); + + settings.beginGroup("ApplicationSetting"); + settings.setValue("ApplicationType", aWindow->GetApplicationType()); + settings.endGroup(); + + return aResult; +} diff --git a/samples/qt/OCCTOverview/src/OCCTOverview.qrc b/samples/qt/OCCTOverview/src/OCCTOverview.qrc new file mode 100644 index 0000000000..8516659917 --- /dev/null +++ b/samples/qt/OCCTOverview/src/OCCTOverview.qrc @@ -0,0 +1,29 @@ + + + ../res/lamp.png + ../res/view_axo.png + ../res/view_back.png + ../res/view_bottom.png + ../res/view_comp_off.png + ../res/view_comp_on.png + ../res/view_fitall.png + ../res/view_front.png + ../res/view_left.png + ../res/view_reset.png + ../res/view_top.png + ../res/antialiasing.png + ../res/raytracing.png + ../res/reflections.png + ../res/shadows.png + ../res/view_right.png + ../res/tool_material.png + ../res/tool_color.png + ../res/tool_delete.png + ../res/tool_shading.png + ../res/tool_transparency.png + ../res/tool_wireframe.png + ../res/help.png + ../res/cursor_rotate.png + ../res/cursor_zoom.png + + diff --git a/samples/qt/OCCTOverview/src/OcctHighlighter.cxx b/samples/qt/OCCTOverview/src/OcctHighlighter.cxx new file mode 100644 index 0000000000..d9d00122f4 --- /dev/null +++ b/samples/qt/OCCTOverview/src/OcctHighlighter.cxx @@ -0,0 +1,254 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "OcctHighlighter.h" + +#include +#include +#include + +static const QString anOcctPatterns[] = +{ + QStringLiteral("gp_Pnt"), QStringLiteral("gp_XYZ"), QStringLiteral("gp_Vec"), + QStringLiteral("gp_Dir"), QStringLiteral("gp_Ax1"), QStringLiteral("gp_Ax2"), + QStringLiteral("gp_Ax3"), QStringLiteral("gp_Lin"), QStringLiteral("gp_Circ"), + QStringLiteral("gp_Elips"), QStringLiteral("gp_Parab"), QStringLiteral("gp_Hypr"), + QStringLiteral("gp_Cylinder"), QStringLiteral("gp_Cone"), QStringLiteral("gp_Sphere"), + QStringLiteral("gp_Torus"), QStringLiteral("gp_Pnt2d"), QStringLiteral("gp_XY"), + QStringLiteral("gp_Ax2d"), QStringLiteral("gp_Ax22d"), QStringLiteral("gp_Lin2d"), + QStringLiteral("gp_Circ2d."), QStringLiteral("gp_Elips2d"), QStringLiteral("gp_Parab2d"), + QStringLiteral("gp_Hypr2d"), QStringLiteral("Geom2d_BSplineCurve"), QStringLiteral("Geom2d_BezierCurve"), + QStringLiteral("Geom2d_OffsetCurve"), QStringLiteral("ProjLib"), QStringLiteral("ElSLib"), + QStringLiteral("Extrema_ExtElCS"), QStringLiteral("Extrema_POnCurv"), QStringLiteral("IntAna_Quadric"), + QStringLiteral("IntAna_IntConicQuad"), QStringLiteral("GccAna_Lin2d2Tan"), QStringLiteral("GccEnt_QualifiedCirc"), + QStringLiteral("Geom2dAPI_ProjectPointOnCurve"), QStringLiteral("Geom2dAPI_ExtremaCurveCurve"), + QStringLiteral("Geom2dAPI_InterCurveCurve"), QStringLiteral("Geom2dAPI_PointsToBSpline"), + QStringLiteral("Geom_CartesianPoint"), QStringLiteral("Geom_VectorWithMagnitude"), QStringLiteral("Geom_Axis1Placement"), + QStringLiteral("Geom_Axis2Placement"), QStringLiteral("Geom_Line"), QStringLiteral("Geom_Circle"), + QStringLiteral("Geom_Ellipse"), QStringLiteral("Geom_Parabola"), QStringLiteral("Geom_Hyperbola"), + QStringLiteral("Geom_BSplineCurve"), QStringLiteral("Geom_BezierCurve"), QStringLiteral("Geom_TrimmedCurve"), + QStringLiteral("Geom_OffsetCurve"), QStringLiteral("Geom_BSplineSurface"), QStringLiteral("Geom_BezierSurface"), + QStringLiteral("Geom_Plane"), QStringLiteral("Geom_CylindricalSurface"), QStringLiteral("Geom_ConicalSurface"), + QStringLiteral("Geom_SphericalSurface"), QStringLiteral("Geom_ToroidalSurface"), QStringLiteral("Geom_RectangularTrimmedSurface"), + QStringLiteral("Geom_OffsetSurface"), QStringLiteral("Geom_SurfaceOfLinearExtrusion"), QStringLiteral("Geom_SurfaceOfRevolution"), + QStringLiteral("BndLib_Add3dCurve"), QStringLiteral("BndLib_AddSurface"), QStringLiteral("GeomAdaptor_Curve"), + QStringLiteral("GeomAdaptor_Surface"), QStringLiteral("GeomAPI_PointsToBSpline"), QStringLiteral("GeomAPI_PointsToBSplineSurface"), + QStringLiteral("GeomConvert"), QStringLiteral("Geom2d_CartesianPoint"), QStringLiteral("Geom2d_VectorWithMagnitude"), + QStringLiteral("Geom2d_Line"), QStringLiteral("Geom2d_Circle"), QStringLiteral("Geom2d_Ellipse"), + QStringLiteral("Geom2d_Parabola"), QStringLiteral("Geom2d_Hyperbola"), QStringLiteral("Geom2d_TrimmedCurve"), + QStringLiteral("Geom2dAdaptor_Curve"), QStringLiteral("Bnd_Box2d"), QStringLiteral("BndLib_Add2dCurve"), + QStringLiteral("Adaptor2d_Curve2d"), QStringLiteral("BRepBuilderAPI_MakeEdge"), QStringLiteral("BRepBuilderAPI_MakeFace"), + QStringLiteral("BRepPrimAPI_MakeBox"), QStringLiteral("AIS_Point"), QStringLiteral("AIS_TextLabel"), QStringLiteral("AIS_Axis"), + QStringLiteral("AIS_Circle"), QStringLiteral("AIS_Plane"), QStringLiteral("AIS_Shape"), QStringLiteral("AIS_ColoredShape"), + QStringLiteral("GProp_PEquation"), QStringLiteral("Extrema_ExtCS"), QStringLiteral("GCPnts_QuasiUniformDeflection"), + QStringLiteral("GProp_GProps"), QStringLiteral("GProp_PrincipalProps"), QStringLiteral("TopoDS"), + QStringLiteral("TopoDS_Iterator"), QStringLiteral("TopoDS_Compound"), QStringLiteral("TopoDS_Edge"), QStringLiteral("TopoDS_Face"), + QStringLiteral("TopoDS_Shell"), QStringLiteral("TopoDS_Solid"), QStringLiteral("TopoDS_Vertex"), + QStringLiteral("TopoDS_Wire"), QStringLiteral("TopExp"), QStringLiteral("TopExp_Explorer"), + QStringLiteral("TColgp_Array2OfPnt"), QStringLiteral("BRep_Builder"), QStringLiteral("BRepGProp"), QStringLiteral("BRep_Tool"), + QStringLiteral("BRepTools"), QStringLiteral("BRepTools_ReShape"), QStringLiteral("BRepAdaptor_Curve"), + QStringLiteral("BRepAdaptor_CompCurve"), QStringLiteral("BRepAdaptor_Surface"), QStringLiteral("BRepAlgoAPI_Common"), + QStringLiteral("BRepAlgoAPI_Cut"), QStringLiteral("BRepAlgoAPI_Fuse"), QStringLiteral("BRepAlgoAPI_Section"), + QStringLiteral("BRepAlgoAPI_Splitter"), QStringLiteral("BRepAlgoAPI_Defeaturing"), QStringLiteral("BRepBuilderAPI_Copy"), + QStringLiteral("BRepBuilderAPI_MakeVertex"), QStringLiteral("BRepBuilderAPI_MakeEdge"), QStringLiteral("BRepBuilderAPI_MakeFace"), + QStringLiteral("BRepBuilderAPI_MakePolygon"), QStringLiteral("BRepBuilderAPI_MakeShell"), QStringLiteral("BRepBuilderAPI_MakeSolid"), + QStringLiteral("BRepBuilderAPI_MakeWire"), QStringLiteral("BRepBuilderAPI_NurbsConvert"), QStringLiteral("BRepBuilderAPI_Sewing"), + QStringLiteral("BRepBuilderAPI_Transform"), QStringLiteral("BRepCheck_Analyzer"), QStringLiteral("BRepPrimAPI_MakeBox"), + QStringLiteral("BRepPrimAPI_MakeCylinder"), QStringLiteral("BRepPrimAPI_MakeRevol"), QStringLiteral("BRepFilletAPI_MakeChamfer"), + QStringLiteral("BRepFilletAPI_MakeFillet"), QStringLiteral("BRepOffsetAPI_MakeOffset"), QStringLiteral("BRepOffsetAPI_MakeEvolved.hxx"), + QStringLiteral("Standard_Integer"), QStringLiteral("Standard_Real"), QStringLiteral("Standard_Boolean"), QStringLiteral("Standard_ShortReal"), + QStringLiteral("Standard_Character"), QStringLiteral("Standard_Byte"), QStringLiteral("Standard_Address"), QStringLiteral("Standard_Size"), + QStringLiteral("Standard_Time"), QStringLiteral("Standard_Utf8Char"), QStringLiteral("Standard_Utf8UChar"), + QStringLiteral("Standard_ExtCharacter"), QStringLiteral("Standard_Utf16Char"), QStringLiteral("Standard_Utf32Char"), + QStringLiteral("Standard_WideChar"), QStringLiteral("Standard_CString"), QStringLiteral("Standard_ExtString"), + QStringLiteral("NCollection_Vector"), QStringLiteral("TCollection_AsciiString"), QStringLiteral("TCollection_BaseSequence"), + QStringLiteral("TCollection_BasicMap"), QStringLiteral("TCollection_BasicMapIterator"), QStringLiteral("TCollection_ExtendedString"), + QStringLiteral("TCollection_HAsciiString"), QStringLiteral("TCollection_HExtendedString"), QStringLiteral("TCollection_MapNode"), + QStringLiteral("TCollection_MapNodePtr"), QStringLiteral("TCollection_SeqNode"), QStringLiteral("TCollection_SeqNodePtr"), + QStringLiteral("TCollection_Side"), QStringLiteral("Standard_False"), QStringLiteral("Standard_True"), + QStringLiteral("TCollection"), QStringLiteral("NCollection"), QStringLiteral("gp_Trsf"), QStringLiteral("Handle"), + QStringLiteral("Aspect_TOL_DASH"), QStringLiteral("Aspect_TOM_O_STAR"), QStringLiteral("Aspect_TOL_SOLID"), + QStringLiteral("Aspect_TOM_O_STAR"), QStringLiteral("AIS_InteractiveObject"), QStringLiteral("AIS_ListOfInteractive"), + QStringLiteral("Aspect_GDM_Lines"), QStringLiteral("Aspect_GDM_Points"), QStringLiteral("Aspect_TOM_POINT"), + QStringLiteral("Aspect_TOM_RING1"), QStringLiteral("Aspect_TOM_O"),QStringLiteral("BinDrivers"), + QStringLiteral("DefineFormat"), QStringLiteral("Font_FA_Bold"), QStringLiteral("Font_FA_BoldItalic"), + QStringLiteral("Font_FA_Italic"), QStringLiteral("Font_FA_Regular"), QStringLiteral("DownCast"), + QStringLiteral("gp_Pln"), QStringLiteral("Graphic3d_AspectMarker3d"), QStringLiteral("Graphic3d_HTA_LEFT"), + QStringLiteral("Graphic3d_NameOfMaterial"), QStringLiteral("Graphic3d_NOM_BRONZE"), QStringLiteral("Graphic3d_NOM_PLASTIC"), + QStringLiteral("Graphic3d_VTA_BOTTOM"), QStringLiteral("OpenGl_GraphicDriver"), QStringLiteral("PCDM_RS_OK"), + QStringLiteral("PCDM_SS_OK"), QStringLiteral("PCDM_ReaderStatus"), QStringLiteral("PCDM_StoreStatus"), + QStringLiteral("Prs3d_Drawer"), QStringLiteral("TPrsStd_AISPresentation"), QStringLiteral("Quantity_Color"), + QStringLiteral("Quantity_NameOfColor"), QStringLiteral("Quantity_NOC_BLUE1"), QStringLiteral("Quantity_NOC_CADETBLUE"), + QStringLiteral("Quantity_NOC_GREEN"), QStringLiteral("Quantity_NOC_MAGENTA1"), QStringLiteral("Quantity_NOC_RED"), + QStringLiteral("Quantity_NOC_YELLOW"), QStringLiteral("Quantity_NOC_WHITE"), QStringLiteral("Quantity_NOC_MATRABLUE"), + QStringLiteral("Quantity_TOC_RGB"), QStringLiteral("Quantity_TOC_HLS"), QStringLiteral("Standard_GUID"), + QStringLiteral("TColStd_ListIteratorOfListOfTransient"), QStringLiteral("TColStd_ListOfTransient"), QStringLiteral("TDataStd_Integer"), + QStringLiteral("TDataStd_Name"), QStringLiteral("TDataStd_Real"), QStringLiteral("TFunction_Driver"), + QStringLiteral("TFunction_DriverTable"), QStringLiteral("TFunction_Function"), QStringLiteral("TFunction_Logbook"), + QStringLiteral("TDF_Label"), QStringLiteral("TDF_TagSource"), QStringLiteral("TNaming_NamedShape"), + QStringLiteral("TopAbs_EDGE"), QStringLiteral("TopAbs_FACE"), QStringLiteral("TopAbs_VERTEX"), + QStringLiteral("TPrsStd_AISPresentation"), QStringLiteral("TPrsStd_AISViewer"), QStringLiteral("V3d_AmbientLight"), + QStringLiteral("V3d_DirectionalLight"), QStringLiteral("V3d_PositionalLight"), QStringLiteral("V3d_SpotLight"), + QStringLiteral("XmlDrivers") +}; + +static const QString aHelperPatterns[] = +{ + QStringLiteral("AdaptorCurve_AIS"), QStringLiteral("AdaptorVec_AIS"), QStringLiteral("AdaptorCurve2d_AIS"), + QStringLiteral("AdaptorPnt2d_AIS"), QStringLiteral("Sample2D_Image"), QStringLiteral("Sample2D_Markers"), + QStringLiteral("Sample2D_Face"), QStringLiteral("TOcafFunction_BoxDriver"), QStringLiteral("TOcafFunction_CylDriver"), + QStringLiteral("DisplayPresentation") +}; + +static const QString aKeywordPatterns[] = +{ + QStringLiteral("\\balignas\\b"), QStringLiteral("\\balignof\\b"), QStringLiteral("\\band\\b"), + QStringLiteral("\\band_eq\\b"), QStringLiteral("\\basm\\b"), QStringLiteral("\\bauto\\b"), + QStringLiteral("\\bbitand\\b"), QStringLiteral("\\bbitor\\b"), QStringLiteral("\\bbool\\b"), + QStringLiteral("\\bbreak\\b"), QStringLiteral("\\bcase\\b"), QStringLiteral("\\bcatch\\b"), + QStringLiteral("\\bchar\\b"), QStringLiteral("\\bchar16_t\\b"), QStringLiteral("\\bchar32_t\\b"), + QStringLiteral("\\bclass\\b"), QStringLiteral("\\bcompl\\b"), QStringLiteral("\\bconst\\b"), + QStringLiteral("\\bconstexpr\\b"), QStringLiteral("\\bconst_cast\\b"), QStringLiteral("\\bcontinue\\b"), + QStringLiteral("\\bdecltype\\b"), QStringLiteral("\\bdefault\\b"), QStringLiteral("\\bdelete\\b"), + QStringLiteral("\\bdo\\b"), QStringLiteral("\\bdouble\\b"), QStringLiteral("\\bdynamic_cast\\b"), + QStringLiteral("\\belse\\b"), QStringLiteral("\\benum\\b"), QStringLiteral("\\bexplicit\\b"), + QStringLiteral("\\bexport\\b"), QStringLiteral("\\bextern\\b"), QStringLiteral("\\bfalse\\b"), + QStringLiteral("\\bfloat\\b"), QStringLiteral("\\bfor\\b"), QStringLiteral("\\bfriend\\b"), + QStringLiteral("\\bgoto\\b"), QStringLiteral("\\bif\\b"), QStringLiteral("\\binline\\b"), + QStringLiteral("\\bint\\b"), QStringLiteral("\\blong\\b"), QStringLiteral("\\bmutable\\b"), + QStringLiteral("\\bnamespace\\b"), QStringLiteral("\\bnew\\b"), QStringLiteral("\\bnoexcept\\b"), + QStringLiteral("\\bnot\\b"), QStringLiteral("\\bnot_eq\\b"), QStringLiteral("\\bnullptr\\b"), + QStringLiteral("\\boperator\\b"), QStringLiteral("\\bor\\b"), QStringLiteral("\\bor_eq\\b"), + QStringLiteral("\\bprivate\\b"), QStringLiteral("\\bprotected\\b"), QStringLiteral("\\bpublic\\b"), + QStringLiteral("\\bregister\\b"), QStringLiteral("\\breinterpret_cast\\b"), QStringLiteral("\\breturn\\b"), + QStringLiteral("\\bshort\\b"), QStringLiteral("\\bsigned\\b"), QStringLiteral("\\bsizeof\\b"), + QStringLiteral("\\bstatic\\b"), QStringLiteral("\\bstatic_assert\\b"), QStringLiteral("\\bstatic_cast\\b"), + QStringLiteral("\\bstruct\\b"),QStringLiteral("\\bswitch\\b"), QStringLiteral("\\btemplate\\b"), + QStringLiteral("\\bthis\\b"), QStringLiteral("\\bthread_local\\b"), QStringLiteral("\\bthrow\\b"), + QStringLiteral("\\btrue\\b"), QStringLiteral("\\btry\\b"), QStringLiteral("\\btypedef\\b"), + QStringLiteral("\\btypeid\\b"), QStringLiteral("\\btypename\\b"),QStringLiteral("\\bunion\\b"), + QStringLiteral("\\bunsigned\\b"), QStringLiteral("\\busing\\b"), QStringLiteral("\\bvirtual\\b"), + QStringLiteral("\\bvoid\\b"), QStringLiteral("\\bvolatile\\b"), QStringLiteral("\\bwchar_t\\b"), + QStringLiteral("\\bwhile\\b"), QStringLiteral("\\bxor\\b"), QStringLiteral("\\bxor_eq\\b"), + QStringLiteral("\\boverride\\b"), QStringLiteral("\\bfinal\\b") +}; + +OcctHighlighter::OcctHighlighter(QTextDocument* theParent) +: QSyntaxHighlighter (theParent) +{ + HighlightingRule aRule; + + myOcctFormat.setForeground(Qt::darkCyan); + + for (const QString& aPattern : anOcctPatterns) + { + aRule.myPattern = QRegularExpression(aPattern); + aRule.myFormat = myOcctFormat; + myHighlightingRules.append(aRule); + } + + myHelperFormat.setForeground(Qt::red); + for (const QString& aPattern : aHelperPatterns) + { + aRule.myPattern = QRegularExpression(aPattern); + aRule.myFormat = myHelperFormat; + myHighlightingRules.append(aRule); + } + + + myKeywordFormat.setForeground(Qt::darkBlue); + myKeywordFormat.setFontWeight(QFont::Bold); + for (const QString& aPattern : aKeywordPatterns) + { + aRule.myPattern = QRegularExpression(aPattern); + aRule.myFormat = myKeywordFormat; + myHighlightingRules.append(aRule); + } + + myMemberFormat.setFontWeight(QFont::Bold); + aRule.myPattern = QRegularExpression(QStringLiteral("\\bmy[0-9A-Za-z]+\\b")); + aRule.myFormat = myMemberFormat; + myHighlightingRules.append(aRule); + + myLocalFormat.setForeground(Qt::darkMagenta); + aRule.myPattern = QRegularExpression(QStringLiteral("\\ba[0-9A-Za-z]+\\b")); + aRule.myFormat = myLocalFormat; + myHighlightingRules.append(aRule); + + myQuotationFormat.setForeground(Qt::darkRed); + aRule.myPattern = QRegularExpression(QStringLiteral("\".*\"")); + aRule.myFormat = myQuotationFormat; + myHighlightingRules.append(aRule); + + myFunctionFormat.setFontItalic(true); + myFunctionFormat.setForeground(Qt::blue); + aRule.myPattern = QRegularExpression(QStringLiteral("\\b[A-Za-z0-9_]+(?=\\()")); + aRule.myFormat = myFunctionFormat; + myHighlightingRules.append(aRule); + + mySingleLineCommentFormat.setForeground(Qt::darkGreen); + aRule.myPattern = QRegularExpression(QStringLiteral("//[^\n]*")); + aRule.myFormat = mySingleLineCommentFormat; + myHighlightingRules.append(aRule); + + myMultiLineCommentFormat.setForeground(Qt::darkGreen); + + myCommentStartExpression = QRegularExpression(QStringLiteral("/\\*")); + myCommentEndExpression = QRegularExpression(QStringLiteral("\\*/")); +} + +void OcctHighlighter::highlightBlock (const QString& theText) +{ + for (const HighlightingRule& rule : qAsConst(myHighlightingRules)) + { + QRegularExpressionMatchIterator matchIterator = rule.myPattern.globalMatch(theText); + while (matchIterator.hasNext()) + { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(match.capturedStart(), match.capturedLength(), rule.myFormat); + } + } + + setCurrentBlockState(0); + + int startIndex = 0; + if (previousBlockState() != 1) + startIndex = theText.indexOf(myCommentStartExpression); + + while (startIndex >= 0) + { + QRegularExpressionMatch match = myCommentEndExpression.match(theText, startIndex); + int endIndex = match.capturedStart(); + int commentLength = 0; + if (endIndex == -1) + { + setCurrentBlockState(1); + commentLength = theText.length() - startIndex; + } + else + { + commentLength = endIndex - startIndex + + match.capturedLength(); + } + setFormat(startIndex, commentLength, myMultiLineCommentFormat); + startIndex = theText.indexOf(myCommentStartExpression, startIndex + commentLength); + } +} diff --git a/samples/qt/OCCTOverview/src/OcctHighlighter.h b/samples/qt/OCCTOverview/src/OcctHighlighter.h new file mode 100644 index 0000000000..0f74282f0b --- /dev/null +++ b/samples/qt/OCCTOverview/src/OcctHighlighter.h @@ -0,0 +1,75 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef OCCTHIGHLIGHTER_H +#define OCCTHIGHLIGHTER_H + +#include + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QTextDocument; +QT_END_NAMESPACE + +//! Implements C++ and OCCT objects syntax +//! highlighting for sample code window +class OcctHighlighter: public QSyntaxHighlighter +{ + Q_OBJECT +public: + + OcctHighlighter(QTextDocument* theParent = 0); + +protected: + void highlightBlock(const QString& theText) Standard_OVERRIDE; + +private: + struct HighlightingRule + { + QRegularExpression myPattern; + QTextCharFormat myFormat; + }; + +private: + QVector myHighlightingRules; + + QRegularExpression myCommentStartExpression; + QRegularExpression myCommentEndExpression; + + QTextCharFormat myKeywordFormat; + QTextCharFormat mySingleLineCommentFormat; + QTextCharFormat myMultiLineCommentFormat; + QTextCharFormat myQuotationFormat; + QTextCharFormat myFunctionFormat; + QTextCharFormat myOcctFormat; + QTextCharFormat myMemberFormat; + QTextCharFormat myLocalFormat; + QTextCharFormat myHelperFormat; +}; + +#endif diff --git a/samples/qt/OCCTOverview/src/OcctWindow.cxx b/samples/qt/OCCTOverview/src/OcctWindow.cxx new file mode 100644 index 0000000000..64705deea6 --- /dev/null +++ b/samples/qt/OCCTOverview/src/OcctWindow.cxx @@ -0,0 +1,179 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "OcctWindow.h" + +IMPLEMENT_STANDARD_RTTIEXT(OcctWindow, Aspect_Window) + +// ======================================================================= +// function : OcctWindow +// purpose : +// ======================================================================= +OcctWindow::OcctWindow(QWidget* theWidget, const Quantity_NameOfColor theBackColor) +: myWidget (theWidget) +{ + SetBackground(theBackColor); + myXLeft = myWidget->rect().left(); + myYTop = myWidget->rect().top(); + myXRight = myWidget->rect().right(); + myYBottom = myWidget->rect().bottom(); +} + +// ======================================================================= +// function : NativeParentHandle +// purpose : +// ======================================================================= +Aspect_Drawable OcctWindow::NativeParentHandle() const +{ + QWidget* aParentWidget = myWidget->parentWidget(); + if (aParentWidget != NULL) + { + return (Aspect_Drawable)aParentWidget->winId(); + } + else + { + return 0; + } +} + +// ======================================================================= +// function : Map +// purpose : +// ======================================================================= +void OcctWindow::Map() const +{ + myWidget->show(); + myWidget->update(); +} + +// ======================================================================= +// function : Unmap +// purpose : +// ======================================================================= +void OcctWindow::Unmap() const +{ + myWidget->hide(); + myWidget->update(); +} + +// ======================================================================= +// function : DoResize +// purpose : +// ======================================================================= +Aspect_TypeOfResize OcctWindow::DoResize() +{ + int aMask = 0; + Aspect_TypeOfResize aMode = Aspect_TOR_UNKNOWN; + + if (!myWidget->isMinimized()) + { + if (Abs(myWidget->rect().left() - myXLeft) > 2) + { + aMask |= 1; + } + if (Abs(myWidget->rect().right() - myXRight) > 2) + { + aMask |= 2; + } + if (Abs(myWidget->rect().top() - myYTop) > 2) + { + aMask |= 4; + } + if (Abs(myWidget->rect().bottom() - myYBottom) > 2) + { + aMask |= 8; + } + + switch (aMask) + { + case 0: + aMode = Aspect_TOR_NO_BORDER; + break; + case 1: + aMode = Aspect_TOR_LEFT_BORDER; + break; + case 2: + aMode = Aspect_TOR_RIGHT_BORDER; + break; + case 4: + aMode = Aspect_TOR_TOP_BORDER; + break; + case 5: + aMode = Aspect_TOR_LEFT_AND_TOP_BORDER; + break; + case 6: + aMode = Aspect_TOR_TOP_AND_RIGHT_BORDER; + break; + case 8: + aMode = Aspect_TOR_BOTTOM_BORDER; + break; + case 9: + aMode = Aspect_TOR_BOTTOM_AND_LEFT_BORDER; + break; + case 10: + aMode = Aspect_TOR_RIGHT_AND_BOTTOM_BORDER; + break; + default: + break; + } // end switch + + *((Standard_Integer*)&myXLeft) = myWidget->rect().left(); + *((Standard_Integer*)&myXRight) = myWidget->rect().right(); + *((Standard_Integer*)&myYTop) = myWidget->rect().top(); + *((Standard_Integer*)&myYBottom) = myWidget->rect().bottom(); + } + + return aMode; +} + +// ======================================================================= +// function : Ratio +// purpose : +// ======================================================================= +Standard_Real OcctWindow::Ratio() const +{ + QRect aRect = myWidget->rect(); + return Standard_Real(aRect.right() - aRect.left()) / Standard_Real(aRect.bottom() - aRect.top()); +} + +// ======================================================================= +// function : Size +// purpose : +// ======================================================================= +void OcctWindow::Size(Standard_Integer& theWidth, Standard_Integer& theHeight) const +{ + QRect aRect = myWidget->rect(); + theWidth = aRect.width(); + theHeight = aRect.height(); +} + +// ======================================================================= +// function : Position +// purpose : +// ======================================================================= +void OcctWindow::Position(Standard_Integer& theX1, Standard_Integer& theY1, + Standard_Integer& theX2, Standard_Integer& theY2) const +{ + theX1 = myWidget->rect().left(); + theX2 = myWidget->rect().right(); + theY1 = myWidget->rect().top(); + theY2 = myWidget->rect().bottom(); +} diff --git a/samples/qt/OCCTOverview/src/OcctWindow.h b/samples/qt/OCCTOverview/src/OcctWindow.h new file mode 100644 index 0000000000..73ae4cb618 --- /dev/null +++ b/samples/qt/OCCTOverview/src/OcctWindow.h @@ -0,0 +1,111 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef OcctWindow_H +#define OcctWindow_H + +#include + +#include +#include +#include + +//! OcctWindow class implements Aspect_Window interface using Qt API +//! as a platform-independent source of window geometry information. +//! A similar class should be used instead of platform-specific OCCT +//! classes (WNT_Window, Xw_Window) in any Qt 5 application using OCCT +//! 3D visualization. +//! +//! With Qt 5, the requirement for a Qt-based application to rely fully +//! on Qt public API and stop using platform-specific APIs looks mandatory. +//! An example of this is changed QWidget event sequence: when a widget is +//! first shown on the screen, a resize event is generated before the +//! underlying native window is resized correctly, however the QWidget instance +//! already holds correct size information at that moment. The OCCT classes +//! acting as a source of window geometry for V3d_View class (WNT_Window, Xw_Window) +//! are no longer compatible with changed Qt behavior because they rely on +//! platform-specific API that cannot return correct window geometry information +//! in some cases. A reasonable solution is to provide a Qt-based implementation +//! of Aspect_Window interface at application level. +class OcctWindow : public Aspect_Window +{ + DEFINE_STANDARD_RTTIEXT(OcctWindow,Aspect_Window) +public: + + //! Constructor + OcctWindow( QWidget* theWidget, const Quantity_NameOfColor theBackColor = Quantity_NOC_MATRAGRAY ); + + //! Destructor + virtual ~OcctWindow() + { + myWidget = NULL; + } + + //! Returns native Window handle + virtual Aspect_Drawable NativeHandle() const Standard_OVERRIDE + { + return (Aspect_Drawable)myWidget->winId(); + } + + //! Returns parent of native Window handle. + virtual Aspect_Drawable NativeParentHandle() const Standard_OVERRIDE; + + //! Applies the resizing to the window + virtual Aspect_TypeOfResize DoResize() Standard_OVERRIDE; + + //! Returns True if the window is opened + //! and False if the window is closed. + virtual Standard_Boolean IsMapped() const Standard_OVERRIDE + { + return !(myWidget->isMinimized() || myWidget->isHidden()); + } + + //! Apply the mapping change to the window + //! and returns TRUE if the window is mapped at screen. + virtual Standard_Boolean DoMapping() const Standard_OVERRIDE { return Standard_True; } + + //! Opens the window . + virtual void Map() const Standard_OVERRIDE; + + //! Closes the window . + virtual void Unmap() const Standard_OVERRIDE; + + virtual void Position( Standard_Integer& theX1, Standard_Integer& theY1, + Standard_Integer& theX2, Standard_Integer& theY2 ) const Standard_OVERRIDE; + + //! Returns The Window RATIO equal to the physical + //! WIDTH/HEIGHT dimensions. + virtual Standard_Real Ratio() const Standard_OVERRIDE; + + virtual void Size( Standard_Integer& theWidth, Standard_Integer& theHeight ) const Standard_OVERRIDE; + + virtual Aspect_FBConfig NativeFBConfig() const Standard_OVERRIDE { return NULL; } + +protected: + Standard_Integer myXLeft; + Standard_Integer myYTop; + Standard_Integer myXRight; + Standard_Integer myYBottom; + QWidget* myWidget; +}; + + +#endif // OcctWindow_H \ No newline at end of file diff --git a/samples/qt/OCCTOverview/src/TranslateDialog.cxx b/samples/qt/OCCTOverview/src/TranslateDialog.cxx new file mode 100644 index 0000000000..fdf0eef594 --- /dev/null +++ b/samples/qt/OCCTOverview/src/TranslateDialog.cxx @@ -0,0 +1,113 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "TranslateDialog.h" + +#include +#include +#include + +TranslateDialog::TranslateDialog(QWidget* parent, Qt::WindowFlags flags, bool modal) +: QFileDialog(parent, flags) +{ + setOption(QFileDialog::DontUseNativeDialog); + setModal(modal); + + QGridLayout* grid = ::qobject_cast(layout()); + + if (grid) + { + QVBoxLayout *vbox = new QVBoxLayout; + + QWidget* paramGroup = new QWidget(this); + paramGroup->setLayout(vbox); + + myBox = new QComboBox(paramGroup); + vbox->addWidget(myBox); + + int row = grid->rowCount(); + grid->addWidget(paramGroup, row, 1, 1, 3); // make combobox occupy 1 row and 3 columns starting from 1 + } +} + +TranslateDialog::~TranslateDialog() +{ +} + +int TranslateDialog::getMode() const +{ + if (myBox->currentIndex() < 0 || myBox->currentIndex() > (int)myList.count() - 1) + { + return -1; + } + else + { + return myList.at(myBox->currentIndex()); + } +} + +void TranslateDialog::setMode(const int mode) +{ + int idx = myList.indexOf(mode); + if (idx >= 0) + { + myBox->setCurrentIndex(idx); + } +} + +void TranslateDialog::addMode(const int mode, const QString& name) +{ + myBox->show(); + myBox->addItem(name); + myList.append(mode); + myBox->updateGeometry(); + updateGeometry(); +} + +void TranslateDialog::clear() +{ + myList.clear(); + myBox->clear(); + myBox->hide(); + myBox->updateGeometry(); + updateGeometry(); +} + +QListView* TranslateDialog::findListView(const QObjectList & childList) +{ + QListView* listView = 0; + for (int i = 0, n = childList.count(); i < n && !listView; i++) + { + listView = qobject_cast(childList.at(i)); + if (!listView && childList.at(i)) + { + listView = findListView(childList.at(i)->children()); + } + } + return listView; +} + +void TranslateDialog::showEvent(QShowEvent* event) +{ + QFileDialog::showEvent(event); + QListView* aListView = findListView(children()); + aListView->setViewMode(QListView::ListMode); +} diff --git a/samples/qt/OCCTOverview/src/TranslateDialog.h b/samples/qt/OCCTOverview/src/TranslateDialog.h new file mode 100644 index 0000000000..df28094d96 --- /dev/null +++ b/samples/qt/OCCTOverview/src/TranslateDialog.h @@ -0,0 +1,56 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef TRANSLATEDIALOG_H +#define TRANSLATEDIALOG_H + +#include +#include +#include +#include +#include +#include +#include +#include + +//! Qt file dialog for save and restore sample files +class TranslateDialog : public QFileDialog +{ +public: + TranslateDialog(QWidget* = 0, Qt::WindowFlags flags = 0, bool = true); + ~TranslateDialog(); + int getMode() const; + void setMode(const int); + void addMode(const int, const QString&); + void clear(); + +protected: + void showEvent(QShowEvent* event); + +private: + QListView* findListView(const QObjectList&); + +private: + QComboBox* myBox; + QList myList; +}; + +#endif // TRANSLATEDIALOG_H diff --git a/samples/qt/OCCTOverview/src/Transparency.cxx b/samples/qt/OCCTOverview/src/Transparency.cxx new file mode 100644 index 0000000000..33fd02fc8e --- /dev/null +++ b/samples/qt/OCCTOverview/src/Transparency.cxx @@ -0,0 +1,46 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include "Transparency.h" + +#include +#include +#include +#include + +DialogTransparency::DialogTransparency(QWidget* parent) +: QDialog(parent, Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint) +{ + setWindowTitle(tr("Transparency")); + QHBoxLayout* base = new QHBoxLayout(this); + + base->addWidget(new QLabel("0", this)); + + mySlider = new QSlider(Qt::Horizontal, this); + mySlider->setRange(0, 10); + mySlider->setTickPosition(QSlider::TicksBelow); + mySlider->setTickInterval(1); + mySlider->setPageStep(2); + base->addWidget(mySlider); + connect(mySlider, SIGNAL(valueChanged(int)), this, SIGNAL(sendTransparencyChanged(int))); + + base->addWidget(new QLabel("10", this)); +} diff --git a/samples/qt/OCCTOverview/src/Transparency.h b/samples/qt/OCCTOverview/src/Transparency.h new file mode 100644 index 0000000000..80409e1748 --- /dev/null +++ b/samples/qt/OCCTOverview/src/Transparency.h @@ -0,0 +1,55 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#include +#include +#include +#include +#include + +#include + +class QSlider; + +//! Qt dialog with slider for change shapes transparency +class DialogTransparency : public QDialog +{ + Q_OBJECT +public: + DialogTransparency ( QWidget * parent=0 ); + ~DialogTransparency() { } + + int value() const + { + return mySlider->value(); + } + + void setValue(int theVal) const + { + mySlider->setValue(theVal); + } + +signals: + void sendTransparencyChanged(int value); + +private: + QSlider* mySlider; +}; diff --git a/samples/qt/OCCTOverview/src/View.cxx b/samples/qt/OCCTOverview/src/View.cxx new file mode 100644 index 0000000000..e3235029e4 --- /dev/null +++ b/samples/qt/OCCTOverview/src/View.cxx @@ -0,0 +1,676 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#if !defined _WIN32 +#define QT_CLEAN_NAMESPACE /* avoid definition of INT32 and INT8 */ +#endif + +#include "View.h" + +#include "ApplicationCommon.h" +#include "OcctWindow.h" +#include "Transparency.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && QT_VERSION < 0x050000 +#include +#endif + +#include +#include +#include + +namespace +{ + //! Map Qt buttons bitmask to virtual keys. + static Aspect_VKeyMouse qtMouseButtons2VKeys(Qt::MouseButtons theButtons) + { + Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE; + if ((theButtons & Qt::LeftButton) != 0) + { + aButtons |= Aspect_VKeyMouse_LeftButton; + } + if ((theButtons & Qt::MiddleButton) != 0) + { + aButtons |= Aspect_VKeyMouse_MiddleButton; + } + if ((theButtons & Qt::RightButton) != 0) + { + aButtons |= Aspect_VKeyMouse_RightButton; + } + return aButtons; + } + + //! Map Qt mouse modifiers bitmask to virtual keys. + static Aspect_VKeyFlags qtMouseModifiers2VKeys(Qt::KeyboardModifiers theModifiers) + { + Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE; + if ((theModifiers & Qt::ShiftModifier) != 0) + { + aFlags |= Aspect_VKeyFlags_SHIFT; + } + if ((theModifiers & Qt::ControlModifier) != 0) + { + aFlags |= Aspect_VKeyFlags_CTRL; + } + if ((theModifiers & Qt::AltModifier) != 0) + { + aFlags |= Aspect_VKeyFlags_ALT; + } + return aFlags; + } + + static QCursor* defCursor = NULL; + static QCursor* handCursor = NULL; + static QCursor* panCursor = NULL; + static QCursor* globPanCursor = NULL; + static QCursor* zoomCursor = NULL; + static QCursor* rotCursor = NULL; + +} + +View::View (const Handle(AIS_InteractiveContext)& theContext, bool theIs3dView, QWidget* theParent) +: QWidget(theParent), + myIsRaytracing(false), + myIsShadowsEnabled(true), + myIsReflectionsEnabled(false), + myIsAntialiasingEnabled(false), + myIs3dView (theIs3dView), + myBackMenu(NULL) +{ +#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && QT_VERSION < 0x050000 + XSynchronize(x11Info().display(), true); +#endif + myContext = theContext; + myCurZoom = 0; + + setAttribute(Qt::WA_PaintOnScreen); + setAttribute(Qt::WA_NoSystemBackground); + + myDefaultGestures = myMouseGestureMap; + myCurrentMode = CurrentAction3d::Nothing; + setMouseTracking(true); + + initViewActions(); + initCursors(); + + setBackgroundRole(QPalette::NoRole);//NoBackground ); + // set focus policy to threat QContextMenuEvent from keyboard + setFocusPolicy(Qt::StrongFocus); + setAttribute(Qt::WA_PaintOnScreen); + setAttribute(Qt::WA_NoSystemBackground); + init(); +} + +void View::init() +{ + if (myV3dView.IsNull()) + { + myV3dView = myContext->CurrentViewer()->CreateView(); + } + + Handle(OcctWindow) hWnd = new OcctWindow(this); + myV3dView->SetWindow(hWnd); + if (!hWnd->IsMapped()) + { + hWnd->Map(); + } + + if (myIs3dView) + { + myV3dView->SetBackgroundColor(Quantity_Color(0.0, 0.0, 0.3, Quantity_TOC_RGB)); + } + else + { + myV3dView->SetBackgroundColor(Quantity_Color(0.0, 0.2, 0.0, Quantity_TOC_RGB)); + myV3dView->SetProj(V3d_Zpos); + } + + myV3dView->MustBeResized(); + + if (myIsRaytracing) + { + myV3dView->ChangeRenderingParams().Method = Graphic3d_RM_RAYTRACING; + } +} + +void View::paintEvent(QPaintEvent *) +{ + myV3dView->InvalidateImmediate(); + FlushViewEvents(myContext, myV3dView, true); +} + +void View::resizeEvent(QResizeEvent *) +{ + if (!myV3dView.IsNull()) + { + myV3dView->MustBeResized(); + } +} + +void View::OnSelectionChanged(const Handle(AIS_InteractiveContext)& theCtx, + const Handle(V3d_View)& theView) +{ + Q_UNUSED(theCtx) + Q_UNUSED(theView) +} + +void View::fitAll() +{ + myV3dView->FitAll(); + myV3dView->ZFitAll(); + myV3dView->Redraw(); +} + +void View::axo() +{ + if (myIs3dView) + { + myV3dView->SetProj(V3d_XposYnegZpos); + } +} + +void View::hlrOff() +{ + QApplication::setOverrideCursor(Qt::WaitCursor); + myV3dView->SetComputedMode(Standard_False); + myV3dView->Redraw(); + QAction* aShadingAction = getViewAction(ViewAction::Shading); + aShadingAction->setEnabled(true); + QAction* aWireframeAction = getViewAction(ViewAction::Wireframe); + aWireframeAction->setEnabled(true); + QApplication::restoreOverrideCursor(); +} + +void View::hlrOn() +{ + QApplication::setOverrideCursor(Qt::WaitCursor); + myV3dView->SetComputedMode(Standard_True); + myV3dView->Redraw(); + QAction* aShadingAction = getViewAction(ViewAction::Shading); + aShadingAction->setEnabled(false); + QAction* aWireframeAction = getViewAction(ViewAction::Wireframe); + aWireframeAction->setEnabled(false); + QApplication::restoreOverrideCursor(); +} + +void View::shading() +{ + myContext->SetDisplayMode(1, Standard_True); +} + +void View::wireframe() +{ + myContext->SetDisplayMode(0, Standard_True); +} + +void View::SetRaytracedShadows(bool theState) +{ + myV3dView->ChangeRenderingParams().IsShadowEnabled = theState; + myIsShadowsEnabled = theState; + myContext->UpdateCurrentViewer(); +} + +void View::SetRaytracedReflections(bool theState) +{ + myV3dView->ChangeRenderingParams().IsReflectionEnabled = theState; + myIsReflectionsEnabled = theState; + myContext->UpdateCurrentViewer(); +} + +void View::onRaytraceAction() +{ + QAction* aSentBy = (QAction*)sender(); + + if (aSentBy == myRaytraceActions.value(RaytraceAction::ToolRaytracing)) + { + bool aState = myRaytraceActions.value(RaytraceAction::ToolRaytracing)->isChecked(); + + QApplication::setOverrideCursor(Qt::WaitCursor); + if (aState) + EnableRaytracing(); + else + DisableRaytracing(); + QApplication::restoreOverrideCursor(); + } + + if (aSentBy == myRaytraceActions.value(RaytraceAction::ToolShadows)) + { + bool aState = myRaytraceActions.value(RaytraceAction::ToolShadows)->isChecked(); + SetRaytracedShadows(aState); + } + + if (aSentBy == myRaytraceActions.value(RaytraceAction::ToolReflections)) + { + bool aState = myRaytraceActions.value(RaytraceAction::ToolReflections)->isChecked(); + SetRaytracedReflections(aState); + } + + if (aSentBy == myRaytraceActions.value(RaytraceAction::ToolAntialiasing)) + { + bool aState = myRaytraceActions.value(RaytraceAction::ToolAntialiasing)->isChecked(); + SetRaytracedAntialiasing(aState); + } +} + +void View::SetRaytracedAntialiasing(bool theState) +{ + myV3dView->ChangeRenderingParams().IsAntialiasingEnabled = theState; + myIsAntialiasingEnabled = theState; + myContext->UpdateCurrentViewer(); +} + +void View::EnableRaytracing() +{ + if (!myIsRaytracing) + { + myV3dView->ChangeRenderingParams().Method = Graphic3d_RM_RAYTRACING; + } + myIsRaytracing = true; + myContext->UpdateCurrentViewer(); +} + +void View::DisableRaytracing() +{ + if (myIsRaytracing) + { + myV3dView->ChangeRenderingParams().Method = Graphic3d_RM_RASTERIZATION; + } + myIsRaytracing = false; + myContext->UpdateCurrentViewer(); +} + +void View::updateToggled(bool isOn) +{ + QAction* sentBy = (QAction*)sender(); + if (!isOn) + { + return; + } + + for (QAction* anAction : myViewActions) + { + if (anAction && (anAction != sentBy)) + { + anAction->setCheckable(true); + anAction->setChecked(false); + } + else + { + if (sentBy == myViewActions.value(ViewAction::FitArea)) + setCursor(*handCursor); + else if (sentBy == myViewActions.value(ViewAction::Zoom)) + setCursor(*zoomCursor); + else if (sentBy == myViewActions.value(ViewAction::Pan)) + setCursor(*panCursor); + else if (sentBy == myViewActions.value(ViewAction::GlobalPan)) + setCursor(*globPanCursor); + else if (sentBy == myViewActions.value(ViewAction::Rotation)) + setCursor(*rotCursor); + else + setCursor(*defCursor); + + sentBy->setCheckable(false); + } + } +} + +void View::initCursors() +{ + if (!defCursor) + defCursor = new QCursor(Qt::ArrowCursor); + if (!handCursor) + handCursor = new QCursor(Qt::PointingHandCursor); + if (!panCursor) + panCursor = new QCursor(Qt::SizeAllCursor); + if (!globPanCursor) + globPanCursor = new QCursor(Qt::CrossCursor); + if (!zoomCursor) + zoomCursor = new QCursor(QPixmap(":/icons/cursor_zoom.png")); + if (!rotCursor) + rotCursor = new QCursor(QPixmap(":/icons/cursor_rotate.png")); +} + +QList View::getViewActions() +{ + initViewActions(); + return myViewActions.values(); +} + +QList View::getRaytraceActions() +{ + initRaytraceActions(); + return myRaytraceActions.values(); +} + +QAction* View::getViewAction(ViewAction theAction) +{ + return myViewActions.value(theAction); +} + +QAction* View::getRaytraceAction(RaytraceAction theAction) +{ + return myRaytraceActions.value(theAction); +} + +/*! + Get paint engine for the OpenGL viewer. [ virtual public ] +*/ +QPaintEngine* View::paintEngine() const +{ + return 0; +} + +QAction* View::RegisterAction(QString theIconPath, QString thePromt, void (View::*theSlot)(void)) +{ + QAction* anAction = new QAction(QPixmap(theIconPath), thePromt, this); + anAction->setToolTip(thePromt); + anAction->setStatusTip(thePromt); + connect(anAction, &QAction::triggered, this, theSlot); + return anAction; +} + +void View::initViewActions() +{ + if (!myViewActions.empty()) + return; + myViewActions[ViewAction::FitAll] = RegisterAction(":/icons/view_fitall.png", tr("Fit all"), &View::fitAll); + if (myIs3dView) + { + myViewActions[ViewAction::Axo] = RegisterAction(":/icons/view_axo.png", tr("Isometric"), &View::axo); + + QActionGroup* aShadingActionGroup = new QActionGroup(this); + QAction* aShadingAction = RegisterAction(":/icons/tool_shading.png", tr("Shading"), &View::shading); + aShadingAction->setCheckable(true); + aShadingActionGroup->addAction(aShadingAction); + myViewActions[ViewAction::Shading] = aShadingAction; + + QAction* aWireframeAction = RegisterAction(":/icons/tool_wireframe.png", tr("Wireframe"), &View::wireframe); + aWireframeAction->setCheckable(true); + aShadingActionGroup->addAction(aWireframeAction); + myViewActions[ViewAction::Wireframe] = aWireframeAction; + + QActionGroup* aHlrActionGroup = new QActionGroup(this); + QAction* aHlrOffAction = RegisterAction(":/icons/view_comp_off.png", tr("HLR off"), &View::hlrOff); + aHlrOffAction->setCheckable(true); + aHlrActionGroup->addAction(aHlrOffAction); + myViewActions[ViewAction::HlrOff] = aHlrOffAction; + + QAction* aHlrOnAction = RegisterAction(":/icons/view_comp_on.png", tr("HLR on"), &View::hlrOn); + aHlrOnAction->setCheckable(true); + aHlrActionGroup->addAction(aHlrOnAction); + myViewActions[ViewAction::HlrOn] = aHlrOnAction; + + myViewActions[ViewAction::Transparency] = RegisterAction(":/icons/tool_transparency.png", tr("Transparency"), &View::onTransparency); + } +} + +void View::initRaytraceActions() +{ + if (!myRaytraceActions.empty()) + { + return; + } + + QAction* aRayTraceAction = RegisterAction(":/icons/raytracing.png", tr("Ray-tracing"), &View::onRaytraceAction); + myRaytraceActions[RaytraceAction::ToolRaytracing] = aRayTraceAction; + aRayTraceAction->setCheckable(true); + aRayTraceAction->setChecked(false); + + QAction* aShadowAction = RegisterAction(":/icons/shadows.png", tr("Shadows"), &View::onRaytraceAction); + myRaytraceActions[RaytraceAction::ToolShadows] = aShadowAction; + aShadowAction->setCheckable(true); + aShadowAction->setChecked(true); + + QAction* aReflectAction = RegisterAction(":/icons/reflections.png", tr("Reflections"), &View::onRaytraceAction); + myRaytraceActions[RaytraceAction::ToolReflections] = aReflectAction; + aReflectAction->setCheckable(true); + aReflectAction->setChecked(false); + + QAction* anAntiAliasingAction = RegisterAction(":/icons/antialiasing.png", tr("Anti-aliasing"), &View::onRaytraceAction); + myRaytraceActions[RaytraceAction::ToolAntialiasing] = anAntiAliasingAction; + anAntiAliasingAction->setCheckable(true); + anAntiAliasingAction->setChecked(false); +} + +void View::activateCursor(const CurrentAction3d theMode) +{ + QCursor* aCursor = defCursor; + switch (theMode) + { + case CurrentAction3d::DynamicPanning: aCursor = panCursor; break; + case CurrentAction3d::DynamicZooming: aCursor = zoomCursor; break; + case CurrentAction3d::DynamicRotation: aCursor = rotCursor; break; + case CurrentAction3d::GlobalPanning: aCursor = globPanCursor; break; + case CurrentAction3d::WindowZooming: aCursor = handCursor; break; + case CurrentAction3d::Nothing: aCursor = defCursor; break; + default: + break; + } + setCursor(*aCursor); +} + +void View::mousePressEvent(QMouseEvent* theEvent) +{ + Qt::MouseButtons aMouseButtons = theEvent->buttons(); + if (!myIs3dView) + { + aMouseButtons.setFlag(Qt::LeftButton, false); + } + const Graphic3d_Vec2i aPnt(theEvent->pos().x(), theEvent->pos().y()); + const Aspect_VKeyFlags aFlags = qtMouseModifiers2VKeys(theEvent->modifiers()); + if (!myV3dView.IsNull() + && UpdateMouseButtons(aPnt, qtMouseButtons2VKeys(aMouseButtons), aFlags, false)) + { + updateView(); + } + myClickPos = aPnt; +} + +void View::mouseReleaseEvent(QMouseEvent* theEvent) +{ + Qt::MouseButtons aMouseButtons = theEvent->buttons(); + if (!myIs3dView) + { + aMouseButtons.setFlag(Qt::LeftButton, false); + } + const Graphic3d_Vec2i aPnt(theEvent->pos().x(), theEvent->pos().y()); + const Aspect_VKeyFlags aFlags = qtMouseModifiers2VKeys(theEvent->modifiers()); + if (!myV3dView.IsNull() + && UpdateMouseButtons(aPnt, qtMouseButtons2VKeys(aMouseButtons), aFlags, false)) + { + updateView(); + } + + if (myCurrentMode == CurrentAction3d::GlobalPanning) + { + myV3dView->Place(aPnt.x(), aPnt.y(), myCurZoom); + } + if (myCurrentMode != CurrentAction3d::Nothing) + { + setCurrentAction(CurrentAction3d::Nothing); + } +} + +void View::mouseMoveEvent(QMouseEvent* theEvent) +{ + Qt::MouseButtons aMouseButtons = theEvent->buttons(); + if (!myIs3dView) + { + aMouseButtons.setFlag(Qt::LeftButton, false); + } + const Graphic3d_Vec2i aNewPos(theEvent->pos().x(), theEvent->pos().y()); + if (!myV3dView.IsNull() + && UpdateMousePosition(aNewPos, qtMouseButtons2VKeys(aMouseButtons), qtMouseModifiers2VKeys(theEvent->modifiers()), false)) + { + updateView(); + } +} + +//============================================================================== +//function : wheelEvent +//purpose : +//============================================================================== +void View::wheelEvent(QWheelEvent* theEvent) +{ + const Graphic3d_Vec2i aPos(theEvent->pos().x(), theEvent->pos().y()); + if (!myV3dView.IsNull() + && UpdateZoom(Aspect_ScrollDelta(aPos, theEvent->delta() / 8))) + { + updateView(); + } +} + +// ======================================================================= +// function : updateView +// purpose : +// ======================================================================= +void View::updateView() +{ + update(); +} + +void View::defineMouseGestures() +{ + myMouseGestureMap.Clear(); + AIS_MouseGesture aRot = AIS_MouseGesture_RotateOrbit; + activateCursor(myCurrentMode); + switch (myCurrentMode) + { + case CurrentAction3d::Nothing: + { + myMouseGestureMap = myDefaultGestures; + break; + } + case CurrentAction3d::DynamicZooming: + { + myMouseGestureMap.Bind(Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_Zoom); + break; + } + case CurrentAction3d::GlobalPanning: + { + break; + } + case CurrentAction3d::WindowZooming: + { + myMouseGestureMap.Bind(Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_ZoomWindow); + break; + } + case CurrentAction3d::DynamicPanning: + { + myMouseGestureMap.Bind(Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_Pan); + break; + } + case CurrentAction3d::DynamicRotation: + { + myMouseGestureMap.Bind(Aspect_VKeyMouse_LeftButton, aRot); + break; + } + default: + { + break; + } + } +} + +void View::addItemInPopup(QMenu* theMenu) +{ + Q_UNUSED(theMenu) +} + +void View::onBackground() +{ + QColor aColor; + Standard_Real R1; + Standard_Real G1; + Standard_Real B1; + myV3dView->BackgroundColor(Quantity_TOC_RGB, R1, G1, B1); + aColor.setRgb((Standard_Integer)(R1 * 255), (Standard_Integer)(G1 * 255), (Standard_Integer)(B1 * 255)); + + QColor aRetColor = QColorDialog::getColor(aColor); + if (aRetColor.isValid()) + { + R1 = aRetColor.red() / 255.; + G1 = aRetColor.green() / 255.; + B1 = aRetColor.blue() / 255.; + myV3dView->SetBackgroundColor(Quantity_TOC_RGB, R1, G1, B1); + } + myV3dView->Redraw(); +} + +void View::onEnvironmentMap() +{ + if (myBackMenu->actions().at(1)->isChecked()) + { + QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", + tr("All Image Files (*.bmp *.gif *.jpg *.jpeg *.png *.tga)")); + + const TCollection_AsciiString anUtf8Path(fileName.toUtf8().data()); + Handle(Graphic3d_TextureEnv) aTexture = new Graphic3d_TextureEnv(anUtf8Path); + myV3dView->SetTextureEnv(aTexture); + } + else + { + myV3dView->SetTextureEnv(Handle(Graphic3d_TextureEnv)()); + } + + myV3dView->Redraw(); +} + +void View::onTransparency() +{ + AIS_ListOfInteractive anAisObjectsList; + myContext->DisplayedObjects(anAisObjectsList); + if (anAisObjectsList.Extent() == 0) + { + return; + } + + double aTranspValue = anAisObjectsList.First()->Transparency(); + DialogTransparency aDlg(this); + aDlg.setValue(int(aTranspValue * 10)); + connect(&aDlg, SIGNAL(sendTransparencyChanged(int)), SLOT(onTransparencyChanged(int))); + aDlg.exec(); +} + +void View::onTransparencyChanged(int theVal) +{ + AIS_ListOfInteractive anAisObjectsList; + myContext->DisplayedObjects(anAisObjectsList); + double aTranspValue = theVal / 10.; + for (Handle(AIS_InteractiveObject) anAisObject : anAisObjectsList) + { + myContext->SetTransparency(anAisObject, aTranspValue, Standard_False); + } + myContext->UpdateCurrentViewer(); +} diff --git a/samples/qt/OCCTOverview/src/View.h b/samples/qt/OCCTOverview/src/View.h new file mode 100644 index 0000000000..d21172358f --- /dev/null +++ b/samples/qt/OCCTOverview/src/View.h @@ -0,0 +1,169 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of the examples of the Open CASCADE Technology software library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE + +#ifndef VIEW_H +#define VIEW_H + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +class TopoDS_Shape; + +enum CurrentAction3d { Nothing, DynamicZooming, WindowZooming, + DynamicPanning, GlobalPanning, DynamicRotation, ObjectDececting }; +enum ViewAction { FitAll, FitArea, Zoom, Pan, GlobalPan, Front, Back, Top, Bottom, + Left, Right, Axo, Rotation, Reset, HlrOff, HlrOn, Shading, Wireframe, Transparency }; +enum RaytraceAction { ToolRaytracing, ToolShadows, ToolReflections, ToolAntialiasing }; + +//! Qt widget containing V3d_View and toolbar with view manipulation buttons. +//! Also use AIS_ViewController for redirecting user input (mouse, keyboard) +//! into 3D viewer events (rotation, panning, zooming) +class View: public QWidget, protected AIS_ViewController +{ + Q_OBJECT +public: + View (const Handle(AIS_InteractiveContext)& theContext, bool theIs3dView, QWidget* theParent); + + ~View() + { + delete myBackMenu; + } + + virtual void init(); + QList getViewActions(); + QAction* getViewAction(ViewAction theAction); + QList getRaytraceActions(); + QAction* getRaytraceAction(RaytraceAction theAction); + + void EnableRaytracing(); + void DisableRaytracing(); + + void SetRaytracedShadows (bool theState); + void SetRaytracedReflections (bool theState); + void SetRaytracedAntialiasing (bool theState); + + bool IsRaytracingMode() const { return myIsRaytracing; } + bool IsShadowsEnabled() const { return myIsShadowsEnabled; } + bool IsReflectionsEnabled() const { return myIsReflectionsEnabled; } + bool IsAntialiasingEnabled() const { return myIsAntialiasingEnabled; } + + static QString GetMessages(int type,TopAbs_ShapeEnum aSubShapeType, TopAbs_ShapeEnum aShapeType); + static QString GetShapeType(TopAbs_ShapeEnum aShapeType); + + Standard_EXPORT static void OnButtonuseraction(int ExerciceSTEP, Handle(AIS_InteractiveContext)& ); + Standard_EXPORT static void DoSelection(int Id, Handle(AIS_InteractiveContext)& ); + Standard_EXPORT static void OnSetSelectionMode(Handle(AIS_InteractiveContext)&, + Standard_Integer&, + TopAbs_ShapeEnum& SelectionMode, + Standard_Boolean& ); + virtual QPaintEngine* paintEngine() const; + const Handle(V3d_View)& getView() const { return myV3dView; } +signals: + void selectionChanged(); + +public slots: + void fitAll(); + void axo(); + void hlrOn(); + void hlrOff(); + void shading(); + void wireframe(); + void onTransparency(); + + void updateToggled( bool ); + void onBackground(); + void onEnvironmentMap(); + void onRaytraceAction(); + +private slots: +void onTransparencyChanged(int theVal); + +protected: + virtual void paintEvent( QPaintEvent* ) Standard_OVERRIDE; + virtual void resizeEvent( QResizeEvent* ) Standard_OVERRIDE; + virtual void mousePressEvent( QMouseEvent* ) Standard_OVERRIDE; + virtual void mouseReleaseEvent(QMouseEvent* ) Standard_OVERRIDE; + virtual void mouseMoveEvent( QMouseEvent* ) Standard_OVERRIDE; + virtual void wheelEvent(QWheelEvent*) Standard_OVERRIDE; + + virtual void addItemInPopup( QMenu* ); + + Handle(AIS_InteractiveContext)& getContext() { return myContext; } + + void activateCursor( const CurrentAction3d ); + + CurrentAction3d getCurrentMode() const { return myCurrentMode; } + +private: + void initCursors(); + void initViewActions(); + void initRaytraceActions(); + + QAction* RegisterAction(QString theIconPath, QString thePromt, void (View::*theSlot)(void)); + +private: + bool myIsRaytracing; + bool myIsShadowsEnabled; + bool myIsReflectionsEnabled; + bool myIsAntialiasingEnabled; + + bool myIs3dView; + + Handle(V3d_View) myV3dView; + Handle(AIS_InteractiveContext) myContext; + AIS_MouseGestureMap myDefaultGestures; + Graphic3d_Vec2i myClickPos; + + void updateView(); + + //! Setup mouse gestures. + void defineMouseGestures(); + + //! Set current action. + void setCurrentAction (CurrentAction3d theAction) + { + myCurrentMode = theAction; + defineMouseGestures(); + } + + //! Handle selection changed event. + void OnSelectionChanged(const Handle(AIS_InteractiveContext)& theCtx, + const Handle(V3d_View)& theView) Standard_OVERRIDE; + CurrentAction3d myCurrentMode; + Standard_Real myCurZoom; + QMap myViewActions; + QMap myRaytraceActions; + QMenu* myBackMenu; + QToolBar* myViewBar; +}; + +#endif diff --git a/samples/qt/Tutorial/.gitignore b/samples/qt/Tutorial/.gitignore new file mode 100644 index 0000000000..7ac6e6bc69 --- /dev/null +++ b/samples/qt/Tutorial/.gitignore @@ -0,0 +1,7 @@ +/debug +/release +*.sln +*.vcxproj* +.qmake.stash +/custom.bat +/custom.sh diff --git a/samples/qt/Tutorial/custom.bat b/samples/qt/Tutorial/custom.bat deleted file mode 100644 index b5eea5240f..0000000000 --- a/samples/qt/Tutorial/custom.bat +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -rem Define QTDIR variable - -set "QTDIR=" diff --git a/samples/qt/Tutorial/custom.bat.template b/samples/qt/Tutorial/custom.bat.template new file mode 100644 index 0000000000..dda84faa21 --- /dev/null +++ b/samples/qt/Tutorial/custom.bat.template @@ -0,0 +1,5 @@ +@echo off +rem Rename this file to custom.bat, +rem and define QTDIR variable. + +set "QTDIR=" diff --git a/samples/qt/Tutorial/custom.sh b/samples/qt/Tutorial/custom.sh deleted file mode 100755 index d9705989ff..0000000000 --- a/samples/qt/Tutorial/custom.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -#Define QTDIR variable - -export QTDIR="" diff --git a/samples/qt/Tutorial/custom.sh.template b/samples/qt/Tutorial/custom.sh.template new file mode 100644 index 0000000000..52571f097b --- /dev/null +++ b/samples/qt/Tutorial/custom.sh.template @@ -0,0 +1,5 @@ +#!/bin/bash +# Rename this file to custom.sh, +# and define QTDIR variable. + +export QTDIR="" diff --git a/samples/qt/Tutorial/env.bat b/samples/qt/Tutorial/env.bat index 56b7eeb0c8..f44cfeb397 100755 --- a/samples/qt/Tutorial/env.bat +++ b/samples/qt/Tutorial/env.bat @@ -1,8 +1,10 @@ @echo off -call "%~dp0..\..\..\env.bat" %1 %2 %3 +if exist "%~dp0custom.bat" ( + call "%~dp0custom.bat" %1 %2 %3 +) -call "custom.bat" %1 %2 %3 +call "%~dp0..\..\..\env.bat" %1 %2 %3 set "RES_DIR=%~dp0win%ARCH%\%VCVER%\res" set "CSF_ResourcesDefaults=%RES_DIR%"