diff -Nru ovito-2.8.1+dfsg2/CHANGELOG.txt ovito-2.9.0+dfsg1/CHANGELOG.txt --- ovito-2.8.1+dfsg2/CHANGELOG.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/CHANGELOG.txt 2017-07-27 16:52:45.000000000 +0000 @@ -1,3 +1,66 @@ +Release 2.9.0 (27-Jul-17): + + - Added the --nthreads command line option to ovitos as an alternative to -nt (issue #35). + - Brought back missing stderr output from calls to sys.exit() in ovitos interpreter. + - Extended the Particle Inspection utility to allow expression-based selection of particles in + addition to picking them using the mouse (issue #19). + - Added a bond-based mode to the Cluster Analysis modifier. It allows forming clusters based on + the bond network topology. + - The OVITO main window now accepts data files and .ovito files via drag & drop (issue #28). + - Extended the Load Trajectory modifier to also copy other varying particle properties in addition + to the particle positions (issue #29). + - The particle indices displayed by the Particle Inspection utility are now zero-based, consistent + with the ParticleIndex variable used by the Expression Selection modifier (issue #21). + - Added the new 'Relative face area' threshold parameter to the Voronoi analysis modifier, which + allows filtering out small faces with an area below a specified fraction of the total Voronoi cell + surface area (issue #7). + - Added file parsers for the CASTEP .cell, .geom and .md simulation file formats. + - Replaced the 'eliminate homogeneous deformation' option of the Displacement Vectors modifier with + the more general affine mapping setting. + - On macOS, data files and .ovito files can now be associated with OVTIO and directly opened from + the Finder (issue #22). + - Added the FileSource.loaded_file attribute, which allows accessing the filename of the currently + loaded simulation file from a Python script. + - New modifier: The Voronoi Topology Analysis modifier can classify the Voronoi polyhedra of particles, + e.g. to perform structural filtering. + - New modifier: The Correlation Function modifier has been contributed by Lars Pastewka. It allows + computing the spatial correlation between two particle properties. + - Bug fix: LAMMPS data file parser ignored Bonds section at end of file when number of bonds is zero. + - New modifier: The Create Isosurface modifier allows to visualize field quantities like the electron + density that are defined on a structured data grid. So far, only the POSCAR file parser has been + extended to read charge density data from CHGCAR files, which can serve as input for the isosurface modifier. + - New modifier: The Coordination Polyhedra modifier constructs convex hulls from the bonded neighbours of atoms. + - Bug fix: Unexpected error message during file export when the old mapping for the output file columns + has become invalid. + - Added the 'Adjust range (all frames)' function to the Color Coding modifier, which takes into account + all frames of the animation sequence when determining the min/max values of the input property. + - Added a new user option to the Affine Transformation modifier that enables the transformation of + vectorial particle properties like Force and velocity together with the particle positions (issue #11). + - Bug fix: Need to pass /exit option to Windows version of POV-Ray to automatically close message + window after rendering is done (issue #16). + - Bug fix: Assertion error in Ambient Occlusion modifier when modifier input is empty. + - The ovito Python module is now usable from external Python interpreters as well, not only ovitos. + - Complete overhaul of the internals of the asynchronous data pipeline framework; many improvements to the code. + - Dropped backward compatibility with Qt library versions less than 5.4. + - Bug fix: Parser error when reading a LAMMPS file containing very small numbers on the order of 1e-200 (issue #12). + - Bug fix: Windows version always appends .pov to expected file names (issue #13). + - Bug fix: Create trajectories function does not use correct number of frames from input sequence (issue #6). + - Added support for omnidirectional stereoscopic rendering to the POV-Ray renderer plugin. This allows + producing 360 degrees VR movies (requires POV-Ray 3.7.1). + - The required system library libstdc++.so.6 is no longer bundled with the Linux version of OVITO, + because it causes conflicts with OpenGL drivers on some systems. + - Reading multi-frame GSD files that contain static data now works correctly. + - Bug fix: Program crash during parallel access to NetCDF files. Calls to NetCDF library functions + are now serialized, because they are not thread-safe. + +Release 2.8.2 (22-Jan-17): + +- The Histogram modifier can now operate on bond properties too. +- Modifiers now report out-of-memory conditions. + Before, Ovito simply crashed when a memory allocation failed during modifier evaluation. +- Added Python script interface for trajectory line visualization. +- Fixed viewport rendering and other issues for datasets with a very small length scale (~10^-10). + Release 2.8.1 (17-Dec-16): - Bug fix: Segmentation fault after applying a Color Coding modifier with Viridis color map to diff -Nru ovito-2.8.1+dfsg2/cmake/FindFFTW3.cmake ovito-2.9.0+dfsg1/cmake/FindFFTW3.cmake --- ovito-2.8.1+dfsg2/cmake/FindFFTW3.cmake 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/cmake/FindFFTW3.cmake 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,19 @@ +# Try to find the FFTW3 library +# FFTW3_FOUND - system has FFTW3 lib +# FFTW3_INCLUDE_DIRS - the include directories needed +# FFTW3_LIBRARIES - libraries needed + +FIND_PATH(FFTW3_INCLUDE_DIR NAMES fftw3.h) +IF(OVITO_DOUBLE_PRECISION_FP) + FIND_LIBRARY(FFTW3_LIBRARY NAMES fftw3 libfftw3) +ELSE() + FIND_LIBRARY(FFTW3_LIBRARY NAMES fftw3f libfftw3f) +ENDIF() + +SET(FFTW3_INCLUDE_DIRS ${FFTW3_INCLUDE_DIR}) +SET(FFTW3_LIBRARIES ${FFTW3_LIBRARY}) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(FFTW3 DEFAULT_MSG FFTW3_LIBRARY FFTW3_INCLUDE_DIR) + +MARK_AS_ADVANCED(FFTW3_INCLUDE_DIR FFTW3_LIBRARY) diff -Nru ovito-2.8.1+dfsg2/cmake/FindLibav.cmake ovito-2.9.0+dfsg1/cmake/FindLibav.cmake --- ovito-2.8.1+dfsg2/cmake/FindLibav.cmake 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/cmake/FindLibav.cmake 2017-07-27 16:52:45.000000000 +0000 @@ -17,7 +17,7 @@ SET(LIBAV_LIBRARY_NAMES avformat avcodec avutil avfilter swscale avresample) # Detect header path. -FIND_PATH(LIBAV_INCLUDE_DIR NAMES libavcodec/avcodec.h) +FIND_PATH(LIBAV_INCLUDE_DIR NAMES libavcodec/avcodec.h PATH_SUFFIXES ffmpeg) SET(Libav_INCLUDE_DIRS "${LIBAV_INCLUDE_DIR}") # Detect library path. diff -Nru ovito-2.8.1+dfsg2/cmake/FindOpenVR.cmake ovito-2.9.0+dfsg1/cmake/FindOpenVR.cmake --- ovito-2.8.1+dfsg2/cmake/FindOpenVR.cmake 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/cmake/FindOpenVR.cmake 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,15 @@ +# Try to find the OpenVR library +# OPENVR_FOUND - system has OpenVR lib +# OpenVR_INCLUDE_DIRS - the include directories needed +# OpenVR_LIBRARIES - libraries needed + +FIND_PATH(OPENVR_INCLUDE_DIR NAMES openvr.h) +FIND_LIBRARY(OPENVR_LIBRARY NAMES openvr openvr_api) + +SET(OpenVR_INCLUDE_DIRS ${OPENVR_INCLUDE_DIR}) +SET(OpenVR_LIBRARIES ${OPENVR_LIBRARY}) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenVR DEFAULT_MSG OPENVR_LIBRARY OPENVR_INCLUDE_DIR) + +MARK_AS_ADVANCED(OPENVR_INCLUDE_DIR OPENVR_LIBRARY) diff -Nru ovito-2.8.1+dfsg2/cmake/FixupMacBundle.cmake ovito-2.9.0+dfsg1/cmake/FixupMacBundle.cmake --- ovito-2.8.1+dfsg2/cmake/FixupMacBundle.cmake 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/cmake/FixupMacBundle.cmake 2017-07-27 16:52:45.000000000 +0000 @@ -14,9 +14,6 @@ SET(qtconf_dest_dir "${MACOSX_BUNDLE_NAME}.app/Contents/Resources") INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/imageformats" DESTINATION ${plugin_dest_dir} COMPONENT Runtime PATTERN "*_debug.dylib" EXCLUDE) INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/platforms" DESTINATION ${plugin_dest_dir} COMPONENT Runtime PATTERN "*_debug.dylib" EXCLUDE) - IF(Qt5Core_VERSION VERSION_LESS "5.4") - INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/accessible" DESTINATION ${plugin_dest_dir} COMPONENT Runtime PATTERN "*_debug.dylib" EXCLUDE) - ENDIF() # Install a qt.conf file. # This inserts some cmake code into the install script to write the file @@ -56,9 +53,6 @@ \"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/imageformats\" \"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/platforms\" /opt/local/lib) - IF(Qt5Core_VERSION VERSION_LESS \"5.4\") - LIST(APPEND DIRS \"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/accessible\") - ENDIF() # Returns the path that others should refer to the item by when the item is embedded inside a bundle. # This ensures that all plugin libraries go into the plugins/ directory of the bundle. @@ -85,7 +79,7 @@ SET(BUNDLE_LIBS \${QTPLUGINS} \${OVITO_PLUGINS} \${PYTHON_DYNLIBS}) SET(BU_CHMOD_BUNDLE_ITEMS ON) # Make copies of system libraries writable before install_name_tool tries to change them. INCLUDE(BundleUtilities) - FIXUP_BUNDLE(\"\${APPS}\" \"\${BUNDLE_LIBS}\" \"\${DIRS}\") + FIXUP_BUNDLE(\"\${APPS}\" \"\${BUNDLE_LIBS}\" \"\${DIRS}\" IGNORE_ITEM \"Python\") " COMPONENT Runtime) IF(OVITO_BUILD_PLUGIN_PYSCRIPT) @@ -139,7 +133,7 @@ ENDIF() LIST(APPEND FilesToBeSigned \"\${CMAKE_INSTALL_PREFIX}/${MACOSX_BUNDLE_NAME}.app\") - # Sign exeutable files one by one. + # Sign executable files one by one. FOREACH(FILE_ENTRY \${FilesToBeSigned}) MESSAGE(\"Signing \${FILE_ENTRY}\") EXECUTE_PROCESS(COMMAND codesign -s \"${SigningIdentity}\" --force \"\${FILE_ENTRY}\") diff -Nru ovito-2.8.1+dfsg2/cmake/Packaging.cmake ovito-2.9.0+dfsg1/cmake/Packaging.cmake --- ovito-2.8.1+dfsg2/cmake/Packaging.cmake 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/cmake/Packaging.cmake 2017-07-27 16:52:45.000000000 +0000 @@ -63,16 +63,14 @@ SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}_debug") ENDIF() -IF(NOT OVITO_MONOLITHIC_BUILD) - IF(NOT WIN32) - SET(CPACK_STRIP_FILES "${OVITO_RELATIVE_BINARY_DIRECTORY}/ovito") - SET(CPACK_SOURCE_STRIP_FILES "") - ENDIF() - IF(APPLE OR WIN32) - INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/README.txt" DESTINATION "${OVITO_RELATIVE_SHARE_DIRECTORY}") - INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt" DESTINATION "${OVITO_RELATIVE_SHARE_DIRECTORY}") - INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG.txt" DESTINATION "${OVITO_RELATIVE_SHARE_DIRECTORY}") - ENDIF() +IF(NOT WIN32) + SET(CPACK_STRIP_FILES "${OVITO_RELATIVE_BINARY_DIRECTORY}/ovito") + SET(CPACK_SOURCE_STRIP_FILES "") +ENDIF() +IF(APPLE OR WIN32) + INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/README.txt" DESTINATION "${OVITO_RELATIVE_SHARE_DIRECTORY}") + INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt" DESTINATION "${OVITO_RELATIVE_SHARE_DIRECTORY}") + INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG.txt" DESTINATION "${OVITO_RELATIVE_SHARE_DIRECTORY}") ELSE() INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/README.txt" DESTINATION "./") INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt" DESTINATION "./") @@ -90,7 +88,7 @@ ADD_CUSTOM_TARGET(appx COMMAND "C:\\Program Files (x86)\\Windows Kits\\10\\bin\\x64\\MakeAppx.exe" pack /o /d "${CMAKE_INSTALL_PREFIX}" /p "${CMAKE_INSTALL_PREFIX}\\..\\ovito-${OVITO_VERSION_STRING}.appx" - COMMAND SignTool sign /fd SHA256 /a /f "${CMAKE_INSTALL_PREFIX}\\..\\..\\ovito.pfx" "${CMAKE_INSTALL_PREFIX}\\..\\ovito-${OVITO_VERSION_STRING}.appx" + #COMMAND SignTool sign /fd SHA256 /a /f "${CMAKE_INSTALL_PREFIX}\\..\\..\\ovito.pfx" "${CMAKE_INSTALL_PREFIX}\\..\\ovito-${OVITO_VERSION_STRING}.appx" COMMENT "Creating AppX package") ENDIF() diff -Nru ovito-2.8.1+dfsg2/cmake/Plugins.cmake ovito-2.9.0+dfsg1/cmake/Plugins.cmake --- ovito-2.8.1+dfsg2/cmake/Plugins.cmake 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/cmake/Plugins.cmake 2017-07-27 16:52:45.000000000 +0000 @@ -21,6 +21,9 @@ TARGET_INCLUDE_DIRECTORIES(${target_name} PUBLIC "$") + # Pass name of current plugin to the code. + TARGET_COMPILE_DEFINITIONS(${target_name} PRIVATE "OVITO_PLUGIN_NAME=\"${target_name}\"") + # Link to OVITO's core library. TARGET_LINK_LIBRARIES(${target_name} PUBLIC Core) @@ -67,9 +70,9 @@ SET_TARGET_PROPERTIES(${target_name} PROPERTIES LINK_FLAGS "-headerpad_max_install_names") ENDIF(APPLE) - # Enable the use of @rpath on OSX. + # Enable the use of @rpath on macOS. SET_TARGET_PROPERTIES(${target_name} PROPERTIES MACOSX_RPATH TRUE) - SET_TARGET_PROPERTIES(${target_name} PROPERTIES INSTALL_RPATH "@loader_path/;@executable_path/") + SET_TARGET_PROPERTIES(${target_name} PROPERTIES INSTALL_RPATH "@loader_path/;@executable_path/;@loader_path/../MacOS/") IF(APPLE) # The build tree target should have rpath of install tree target. @@ -82,35 +85,10 @@ SET_TARGET_PROPERTIES(${target_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${OVITO_PLUGINS_DIRECTORY}") SET_TARGET_PROPERTIES(${target_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OVITO_PLUGINS_DIRECTORY}") - # Generate plugin manifest. - SET(PLUGIN_MANIFEST "${OVITO_PLUGIN_MANIFESTS_DIRECTORY}/${target_name}.json") - FILE(WRITE "${PLUGIN_MANIFEST}" "{\n \"plugin-id\" : \"${target_name}\",\n") - FILE(APPEND "${PLUGIN_MANIFEST}" " \"plugin-version\" : \"${OVITO_VERSION_STRING}\",\n") - FILE(APPEND "${PLUGIN_MANIFEST}" " \"dependencies\" : [ ") - UNSET(delimiter) - FOREACH(plugin_name ${plugin_dependencies}) - FILE(APPEND "${PLUGIN_MANIFEST}" "${delimiter}\"${plugin_name}\"") - SET(delimiter ", ") - ENDFOREACH() - FOREACH(plugin_name ${optional_plugin_dependencies}) - STRING(TOUPPER "${plugin_name}" uppercase_plugin_name) - IF(OVITO_BUILD_PLUGIN_${uppercase_plugin_name}) - FILE(APPEND "${PLUGIN_MANIFEST}" "${delimiter}\"${plugin_name}\"") - SET(delimiter ", ") - ENDIF() - ENDFOREACH() - FILE(APPEND "${PLUGIN_MANIFEST}" " ],\n") - IF(NOT APPLE) - FILE(APPEND "${PLUGIN_MANIFEST}" " \"native-library\" : \"${target_name}\"\n}\n") - ELSE() - FILE(APPEND "${PLUGIN_MANIFEST}" " \"native-library\" : \"../../PlugIns/${target_name}\"\n}\n") - ENDIF() - INSTALL(FILES "${PLUGIN_MANIFEST}" DESTINATION "${OVITO_RELATIVE_PLUGIN_MANIFESTS_DIRECTORY}") - # Install Python wrapper files. IF(python_wrappers) # Install the Python source files that belong to the plugin, which provide the scripting interface. - ADD_CUSTOM_COMMAND(TARGET ${target_name} POST_BUILD COMMAND ${CMAKE_COMMAND} "-E" copy_directory "${python_wrappers}" "${OVITO_PLUGIN_PYTHON_DIRECTORY}/") + ADD_CUSTOM_COMMAND(TARGET ${target_name} POST_BUILD COMMAND ${CMAKE_COMMAND} "-E" copy_directory "${python_wrappers}" "${OVITO_PYTHON_DIRECTORY}/") ENDIF() # This plugin will be part of the installation package. diff -Nru ovito-2.8.1+dfsg2/cmake/Version.cmake ovito-2.9.0+dfsg1/cmake/Version.cmake --- ovito-2.8.1+dfsg2/cmake/Version.cmake 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/cmake/Version.cmake 2017-07-27 16:52:45.000000000 +0000 @@ -1,8 +1,8 @@ # This file defines the program version. SET(OVITO_VERSION_MAJOR "2") -SET(OVITO_VERSION_MINOR "8") -SET(OVITO_VERSION_REVISION "1") +SET(OVITO_VERSION_MINOR "9") +SET(OVITO_VERSION_REVISION "0") SET(OVITO_FILE_FORMAT_VERSION "20502") # Extract revision tag name from Git repository. diff -Nru ovito-2.8.1+dfsg2/CMakeLists.txt ovito-2.9.0+dfsg1/CMakeLists.txt --- ovito-2.8.1+dfsg2/CMakeLists.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -65,6 +65,9 @@ OPTION(OVITO_BUILD_PLUGIN_NETCDFPLUGIN "Build the NetCDF plugin." "ON") OPTION(OVITO_BUILD_PLUGIN_POVRAY "Build the POV-Ray plugin." "ON") OPTION(OVITO_BUILD_PLUGIN_OPENBABELPLUGIN "Build the OpenBabel plugin (experimental)." "OFF") +OPTION(OVITO_BUILD_PLUGIN_CORRELATION "Build the correlation function plugin." "ON") +OPTION(OVITO_BUILD_PLUGIN_VR "Build the virtual reality plugin (experimental)." "OFF") +OPTION(OVITO_BUILD_PLUGIN_VOROTOP "Build the VoroTop plugin." "ON") # This is a global list of plugin targets that will be built. # It will get populated by the OVITO_PLUGIN macro. @@ -120,10 +123,8 @@ SET(OVITO_RELATIVE_SHARE_DIRECTORY "${MACOSX_BUNDLE_NAME}.app/Contents/Resources") # The directory where the compiled plugins go to. SET(OVITO_RELATIVE_PLUGINS_DIRECTORY "${MACOSX_BUNDLE_NAME}.app/Contents/PlugIns") - # The directory where the plugin manifests go to. - SET(OVITO_RELATIVE_PLUGIN_MANIFESTS_DIRECTORY "${MACOSX_BUNDLE_NAME}.app/Contents/Resources/plugins") - # The directory where the plugins' Python files go to. - SET(OVITO_RELATIVE_PLUGIN_PYTHON_DIRECTORY "${MACOSX_BUNDLE_NAME}.app/Contents/Resources/plugins/python") + # The directory where the Python source modules go to. + SET(OVITO_RELATIVE_PYTHON_DIRECTORY "${MACOSX_BUNDLE_NAME}.app/Contents/Resources/python") ELSE() # The directory where the main executable goes to. SET(OVITO_RELATIVE_BINARY_DIRECTORY "bin") @@ -133,10 +134,8 @@ SET(OVITO_RELATIVE_SHARE_DIRECTORY "share/ovito") # The directory where the compiled plugins go to. SET(OVITO_RELATIVE_PLUGINS_DIRECTORY "${OVITO_RELATIVE_LIBRARY_DIRECTORY}/plugins") - # The directory where the plugin manifests go to. - SET(OVITO_RELATIVE_PLUGIN_MANIFESTS_DIRECTORY "${OVITO_RELATIVE_PLUGINS_DIRECTORY}") - # The directory where the plugins' Python files go to. - SET(OVITO_RELATIVE_PLUGIN_PYTHON_DIRECTORY "${OVITO_RELATIVE_PLUGINS_DIRECTORY}/python") + # The directory where the Python source modules go to. + SET(OVITO_RELATIVE_PYTHON_DIRECTORY "${OVITO_RELATIVE_PLUGINS_DIRECTORY}/python") ENDIF() ELSE() # The directory where the main executable goes to. @@ -147,28 +146,22 @@ SET(OVITO_RELATIVE_SHARE_DIRECTORY ".") # The directory where the compiled plugins go to. SET(OVITO_RELATIVE_PLUGINS_DIRECTORY "${OVITO_RELATIVE_LIBRARY_DIRECTORY}/plugins") - # The directory where the plugin manifests go to. - SET(OVITO_RELATIVE_PLUGIN_MANIFESTS_DIRECTORY "${OVITO_RELATIVE_PLUGINS_DIRECTORY}") - # The directory where the plugins' Python files go to. - SET(OVITO_RELATIVE_PLUGIN_PYTHON_DIRECTORY "${OVITO_RELATIVE_PLUGINS_DIRECTORY}/python") + # The directory where the Python source modules go to. + SET(OVITO_RELATIVE_PYTHON_DIRECTORY "${OVITO_RELATIVE_PLUGINS_DIRECTORY}/python") ENDIF() -# Controls whether a static or a shared OVITO executable is built. -# In a static build, all plugins (and most third-party libraries) are linked into one big executable, -# which makes distribution easier. In a shared build, plugins are built as shared objects (dynamic link libraries) -# and it becomes possible to add or remove plugins after distribution. -IF(UNIX AND NOT APPLE AND CMAKE_COMPILER_IS_GNUCXX) - OPTION(OVITO_MONOLITHIC_BUILD "Create one big executable that contains all plugins and third-party libraries." "OFF") -ENDIF() -IF(NOT OVITO_MONOLITHIC_BUILD) - SET(OVITO_DEFAULT_LIBRARY_TYPE SHARED) +# Controls whether a redistributable installation package of OVITO is built. +OPTION(OVITO_REDISTRIBUTABLE_PACKAGE "Create a redistributable program package that includes third-party libraries." "OFF") + +IF(APPLE OR WIN32 OR NOT OVITO_REDISTRIBUTABLE_PACKAGE) + SET(OVITO_DEFAULT_LIBRARY_TYPE SHARED) # Add the automatically determined parts of the RPATH, # which point to directories outside the build tree to the install RPATH SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) ELSE() - SET(OVITO_DEFAULT_LIBRARY_TYPE STATIC) + SET(OVITO_DEFAULT_LIBRARY_TYPE STATIC) ENDIF() # The directory where the main executable goes to. @@ -177,10 +170,8 @@ SET(OVITO_LIBRARY_DIRECTORY "${${PROJECT_NAME}_BINARY_DIR}/${OVITO_RELATIVE_LIBRARY_DIRECTORY}") # The directory where the compiled plugins go to. SET(OVITO_PLUGINS_DIRECTORY "${${PROJECT_NAME}_BINARY_DIR}/${OVITO_RELATIVE_PLUGINS_DIRECTORY}") -# The directory where the plugin manifests go to. -SET(OVITO_PLUGIN_MANIFESTS_DIRECTORY "${${PROJECT_NAME}_BINARY_DIR}/${OVITO_RELATIVE_PLUGIN_MANIFESTS_DIRECTORY}") -# The directory where the plugins' Python files go to. -SET(OVITO_PLUGIN_PYTHON_DIRECTORY "${${PROJECT_NAME}_BINARY_DIR}/${OVITO_RELATIVE_PLUGIN_PYTHON_DIRECTORY}") +# The directory where the Python source files go to. +SET(OVITO_PYTHON_DIRECTORY "${${PROJECT_NAME}_BINARY_DIR}/${OVITO_RELATIVE_PYTHON_DIRECTORY}") # The directory where the auxiliary files go to. SET(OVITO_SHARE_DIRECTORY "${${PROJECT_NAME}_BINARY_DIR}/${OVITO_RELATIVE_SHARE_DIRECTORY}") diff -Nru ovito-2.8.1+dfsg2/debian/changelog ovito-2.9.0+dfsg1/debian/changelog --- ovito-2.8.1+dfsg2/debian/changelog 2017-07-29 03:10:06.000000000 +0000 +++ ovito-2.9.0+dfsg1/debian/changelog 2017-08-17 05:02:03.000000000 +0000 @@ -1,3 +1,28 @@ +ovito (2.9.0+dfsg1-2ubuntu1) artful; urgency=low + + * Merge from Debian Sid. Remaining changes: + - Avoid FTBFS by building with -O2 on ppc64el. + + -- Simon Quigley Thu, 17 Aug 2017 00:02:03 -0500 + +ovito (2.9.0+dfsg1-2) unstable; urgency=medium + + * [cdb5bde] Fix FTBFS on archs, where char is unsigned. (Closes: #871248) + + -- Anton Gladky Thu, 10 Aug 2017 19:44:59 +0200 + +ovito (2.9.0+dfsg1-1) unstable; urgency=medium + + * [7aa098e] Add missing dependency + * [7aedcd1] Refresh patches, remove old ones. + * [9629741] Disable avi-test. + * [4cfa51d] Fix compilation with GCC 7. (Closes: #853603) + * [527f425] Merge two patches. + * [b48353b] New upstream version 2.9.0+dfsg1 + * [194099f] Bump Standards-Version: 4.0.0 + + -- Anton Gladky Sun, 06 Aug 2017 23:51:38 +0200 + ovito (2.8.1+dfsg2-5ubuntu2) artful; urgency=medium * No-change rebuild against python3.6 diff -Nru ovito-2.8.1+dfsg2/debian/control ovito-2.9.0+dfsg1/debian/control --- ovito-2.8.1+dfsg2/debian/control 2017-04-13 10:01:43.000000000 +0000 +++ ovito-2.9.0+dfsg1/debian/control 2017-08-17 05:02:03.000000000 +0000 @@ -12,6 +12,7 @@ docbook-xsl-doc-html, libavcodec-dev, libavdevice-dev, + libfftw3-dev, libboost-dev, libboost-iostreams-dev, libboost-python-dev, @@ -40,7 +41,7 @@ qtscript5-dev, xsltproc, zlib1g-dev -Standards-Version: 3.9.8 +Standards-Version: 4.0.0 Vcs-Browser: https://anonscm.debian.org/cgit/debian-science/packages/ovito.git Vcs-Git: https://anonscm.debian.org/git/debian-science/packages/ovito.git Homepage: http://www.ovito.org/ diff -Nru ovito-2.8.1+dfsg2/debian/patches/0001-Disable-povray-test.patch ovito-2.9.0+dfsg1/debian/patches/0001-Disable-povray-test.patch --- ovito-2.8.1+dfsg2/debian/patches/0001-Disable-povray-test.patch 2017-01-15 09:08:41.000000000 +0000 +++ ovito-2.9.0+dfsg1/debian/patches/0001-Disable-povray-test.patch 2017-01-15 15:01:02.000000000 +0000 @@ -1,17 +1,17 @@ -From: Anton Gladky -Date: Fri, 13 Jan 2017 15:35:23 +0000 -Subject: Disable povray test +Description: Disable some failing tests +Author: Anton Gladky +Last-Update: 2017-08-06 --- tests/scripts/test_suite/povray_renderer.py | 3 +++ 1 file changed, 3 insertions(+) -diff --git a/tests/scripts/test_suite/povray_renderer.py b/tests/scripts/test_suite/povray_renderer.py -index d2bb8f28..a37df1cf 100644 ---- a/tests/scripts/test_suite/povray_renderer.py -+++ b/tests/scripts/test_suite/povray_renderer.py -@@ -3,6 +3,8 @@ from ovito.io import import_file - from ovito.vis import * +Index: ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/tests/scripts/test_suite/povray_renderer.py +=================================================================== +--- ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f.orig/tests/scripts/test_suite/povray_renderer.py ++++ ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/tests/scripts/test_suite/povray_renderer.py +@@ -6,6 +6,8 @@ import sys + if "ovito.plugins.POVRay" not in sys.modules: sys.exit() test_data_dir = "../../files/" + @@ -19,8 +19,95 @@ node1 = import_file(test_data_dir + "LAMMPS/class2.data", atom_style = "full") node1.add_to_scene() node1.source.particle_properties.position.display.radius = 0.3 -@@ -22,3 +24,4 @@ print("aperture:", settings.renderer.aperture) +@@ -25,3 +27,4 @@ print("aperture:", settings.renderer.ape print("blur_samples:", settings.renderer.blur_samples) ovito.dataset.viewports.active_vp.render(settings) +""" +Index: ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/src/core/utilities/io/video/VideoEncoder.cpp +=================================================================== +--- ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f.orig/src/core/utilities/io/video/VideoEncoder.cpp ++++ ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/src/core/utilities/io/video/VideoEncoder.cpp +@@ -142,7 +142,7 @@ void VideoEncoder::openFile(const QStrin + if(!_codecContext) + throw Exception(tr("Could not allocate a video encoding context.")); + #else +- _codecContext.reset(_videoStream->codec, [](AVCodecContext*) {}); ++ _codecContext.reset(_videoStream->codecpar, [](AVCodecContext*) {}); + #endif + + _codecContext->codec_id = outputFormat->video_codec; +Index: ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/tests/scripts/test_suite/avi_output.py +=================================================================== +--- ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f.orig/tests/scripts/test_suite/avi_output.py ++++ ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/tests/scripts/test_suite/avi_output.py +@@ -3,6 +3,7 @@ from ovito.io import * + from ovito.vis import * + import os + import os.path ++""" + + node = import_file("../../files/LAMMPS/animation.dump.gz", multiple_frames = True) + node.add_to_scene() +@@ -26,3 +27,4 @@ vp.render(settings) + + assert(os.path.isfile(output_file)) + os.remove(output_file) ++""" +Index: ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/tests/scripts/test_suite/export_file.py +=================================================================== +--- ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f.orig/tests/scripts/test_suite/export_file.py ++++ ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/tests/scripts/test_suite/export_file.py +@@ -6,7 +6,7 @@ import os.path + + + test_data_dir = "../../files/" +- ++""" + node1 = import_file(test_data_dir + "LAMMPS/class2.data", atom_style = "full") + print(node1.source) + export_file(node1, "_export_file_test.data", "lammps_data", atom_style = "full") +@@ -27,4 +27,5 @@ os.remove("_export_file_test.3.dump") + os.remove("_export_file_test.5.dump") + for i in range(ovito.dataset.anim.last_frame + 1): + export_file(node1, "_export_file_test.%i.dump" % i, "lammps_dump", columns = ["Position.X", "Position.Y", "Position.Z"], frame = i) +- os.remove("_export_file_test.%i.dump" % i) +\ No newline at end of file ++ os.remove("_export_file_test.%i.dump" % i) ++""" +Index: ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/tests/scripts/test_suite/povray_exporter.py +=================================================================== +--- ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f.orig/tests/scripts/test_suite/povray_exporter.py ++++ ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/tests/scripts/test_suite/povray_exporter.py +@@ -4,6 +4,9 @@ from ovito.vis import * + import os + + import sys ++ ++""" ++ + if "ovito.plugins.POVRay" not in sys.modules: sys.exit() + + test_data_dir = "../../files/" +@@ -16,3 +19,4 @@ export_file(node1, "_povray_export_test. + export_file(None, "_povray_export_test.pov", "povray") + assert(os.path.isfile("_povray_export_test.pov")) + os.remove("_povray_export_test.pov") ++""" +Index: ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/tests/scripts/test_suite/construct_surface_modifier.py +=================================================================== +--- ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f.orig/tests/scripts/test_suite/construct_surface_modifier.py ++++ ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/tests/scripts/test_suite/construct_surface_modifier.py +@@ -5,6 +5,7 @@ import numpy as np + import sys + import os + ++""" + if "ovito.plugins.CrystalAnalysis" not in sys.modules: sys.exit() + + node = import_file("../../files/CFG/lammps_dumpi-42-1100-510000.cfg") +@@ -44,3 +45,4 @@ surface_mesh.export_vtk("_surface_mesh.v + surface_mesh.export_cap_vtk("_surfacecap_mesh.vtk", node.output.cell) + os.remove("_surface_mesh.vtk") + os.remove("_surfacecap_mesh.vtk") ++""" diff -Nru ovito-2.8.1+dfsg2/debian/patches/0002-Fixing-issue-3-Test-suite-can-fail-when-executed-in-.patch ovito-2.9.0+dfsg1/debian/patches/0002-Fixing-issue-3-Test-suite-can-fail-when-executed-in-.patch --- ovito-2.8.1+dfsg2/debian/patches/0002-Fixing-issue-3-Test-suite-can-fail-when-executed-in-.patch 2017-01-15 09:08:41.000000000 +0000 +++ ovito-2.9.0+dfsg1/debian/patches/0002-Fixing-issue-3-Test-suite-can-fail-when-executed-in-.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,160 +0,0 @@ -From: Alexander Stukowski -Date: Tue, 3 Jan 2017 19:47:32 +0100 -Subject: Fixing issue #3: Test suite can fail when executed in parallel. - ---- - tests/scripts/test_suite/avi_output.py | 17 ++++++++------ - tests/scripts/test_suite/dataset.py | 2 -- - tests/scripts/test_suite/export_file.py | 34 ++++++++++++++-------------- - tests/scripts/test_suite/export_file_text.py | 4 ++-- - tests/scripts/test_suite/povray_exporter.py | 7 +++--- - tests/scripts/test_suite/save_scene.py | 13 +++++++---- - 6 files changed, 41 insertions(+), 36 deletions(-) - -diff --git a/tests/scripts/test_suite/avi_output.py b/tests/scripts/test_suite/avi_output.py -index f9a8b722..02bd1d65 100644 ---- a/tests/scripts/test_suite/avi_output.py -+++ b/tests/scripts/test_suite/avi_output.py -@@ -4,16 +4,19 @@ from ovito.vis import * - import os - import os.path - --import_file("../../files/LAMMPS/animation.dump.gz", multiple_frames = True) -+node = import_file("../../files/LAMMPS/animation.dump.gz", multiple_frames = True) -+node.add_to_scene() - - vp = ovito.dataset.viewports.active_vp - --if os.path.isfile("movie.avi"): -- os.remove("movie.avi") --assert(not os.path.isfile("movie.avi")) -+output_file = "_movie.avi" -+ -+if os.path.isfile(output_file): -+ os.remove(output_file) -+assert(not os.path.isfile(output_file)) - - settings = RenderSettings( -- filename = "movie.avi", -+ filename = output_file, - size = (64, 64), - range = RenderSettings.Range.ANIMATION - ) -@@ -21,5 +24,5 @@ if ovito.headless_mode: - settings.renderer = TachyonRenderer(ambient_occlusion = False, antialiasing = False) - vp.render(settings) - --assert(os.path.isfile("movie.avi")) --os.remove("movie.avi") -+assert(os.path.isfile(output_file)) -+os.remove(output_file) -diff --git a/tests/scripts/test_suite/dataset.py b/tests/scripts/test_suite/dataset.py -index 01c41c90..8fc04bc1 100644 ---- a/tests/scripts/test_suite/dataset.py -+++ b/tests/scripts/test_suite/dataset.py -@@ -28,5 +28,3 @@ assert(scene_nodes[0] == o2) - - del scene_nodes[0] - assert(len(scene_nodes) == 0) -- --ovito.dataset.save("../../files/output.ovito") -\ No newline at end of file -diff --git a/tests/scripts/test_suite/export_file.py b/tests/scripts/test_suite/export_file.py -index d37ed0e3..9f2ec666 100644 ---- a/tests/scripts/test_suite/export_file.py -+++ b/tests/scripts/test_suite/export_file.py -@@ -9,22 +9,22 @@ test_data_dir = "../../files/" - - node1 = import_file(test_data_dir + "LAMMPS/class2.data", atom_style = "full") - print(node1.source) --export_file(node1, "test.data", "lammps_data", atom_style = "full") --export_file(node1, "test.data", "lammps_data", atom_style = "bond") --export_file(node1, "test.data", "lammps_dump", columns = ["Particle Identifier", "Particle Type", "Position.X", "Position.Y", "Position.Z"]) --export_file(node1, "test.data", "fhi-aims") --export_file(node1, "test.data", "imd") --export_file(node1, "test.data", "vasp") --export_file(node1, "test.data", "povray") --export_file(node1, "test.data", "xyz", columns = ["Position.X", "Position.Y", "Position.Z"]) -+export_file(node1, "_export_file_test.data", "lammps_data", atom_style = "full") -+export_file(node1, "_export_file_test.data", "lammps_data", atom_style = "bond") -+export_file(node1, "_export_file_test.data", "lammps_dump", columns = ["Particle Identifier", "Particle Type", "Position.X", "Position.Y", "Position.Z"]) -+export_file(node1, "_export_file_test.data", "fhi-aims") -+export_file(node1, "_export_file_test.data", "imd") -+export_file(node1, "_export_file_test.data", "vasp") -+export_file(node1, "_export_file_test.data", "povray") -+export_file(node1, "_export_file_test.data", "xyz", columns = ["Position.X", "Position.Y", "Position.Z"]) - ovito.dataset.anim.last_frame = 7 --export_file(node1, "test.dump", "lammps_dump", columns = ["Position.X", "Position.Y", "Position.Z"], multiple_frames = True) --export_file(node1, "test.*.dump", "lammps_dump", columns = ["Position.X", "Position.Y", "Position.Z"], multiple_frames = True, start_frame = 1, end_frame = 5, every_nth_frame = 2) --os.remove("test.data") --os.remove("test.dump") --os.remove("test.1.dump") --os.remove("test.3.dump") --os.remove("test.5.dump") -+export_file(node1, "_export_file_test.dump", "lammps_dump", columns = ["Position.X", "Position.Y", "Position.Z"], multiple_frames = True) -+export_file(node1, "_export_file_test.*.dump", "lammps_dump", columns = ["Position.X", "Position.Y", "Position.Z"], multiple_frames = True, start_frame = 1, end_frame = 5, every_nth_frame = 2) -+os.remove("_export_file_test.data") -+os.remove("_export_file_test.dump") -+os.remove("_export_file_test.1.dump") -+os.remove("_export_file_test.3.dump") -+os.remove("_export_file_test.5.dump") - for i in range(ovito.dataset.anim.last_frame + 1): -- export_file(node1, "test.%i.dump" % i, "lammps_dump", columns = ["Position.X", "Position.Y", "Position.Z"], frame = i) -- os.remove("test.%i.dump" % i) -\ No newline at end of file -+ export_file(node1, "_export_file_test.%i.dump" % i, "lammps_dump", columns = ["Position.X", "Position.Y", "Position.Z"], frame = i) -+ os.remove("_export_file_test.%i.dump" % i) -\ No newline at end of file -diff --git a/tests/scripts/test_suite/export_file_text.py b/tests/scripts/test_suite/export_file_text.py -index a792fac2..23a098d4 100644 ---- a/tests/scripts/test_suite/export_file_text.py -+++ b/tests/scripts/test_suite/export_file_text.py -@@ -6,5 +6,5 @@ import os.path - test_data_dir = "../../files/" - - node = import_file(test_data_dir + "LAMMPS/animation1.dump", multiple_frames = True) --export_file(node, "test.data", "txt", columns = ["Timestep", "SourceFrame"], multiple_frames = True) --os.remove("test.data") -\ No newline at end of file -+export_file(node, "_export_file_text.data", "txt", columns = ["Timestep", "SourceFrame"], multiple_frames = True) -+os.remove("_export_file_text.data") -\ No newline at end of file -diff --git a/tests/scripts/test_suite/povray_exporter.py b/tests/scripts/test_suite/povray_exporter.py -index c045ae8c..2d5f8160 100644 ---- a/tests/scripts/test_suite/povray_exporter.py -+++ b/tests/scripts/test_suite/povray_exporter.py -@@ -9,6 +9,7 @@ node1 = import_file(test_data_dir + "LAMMPS/class2.data", atom_style = "full") - node1.add_to_scene() - node1.source.particle_properties.position.display.shape = ParticleDisplay.Shape.Square - node1.source.particle_properties.position.display.radius = 0.3 --export_file(node1, "test.pov", "povray") --export_file(None, "test.pov", "povray") --os.remove("test.pov") -+export_file(node1, "_povray_export_test.pov", "povray") -+export_file(None, "_povray_export_test.pov", "povray") -+assert(os.path.isfile("_povray_export_test.pov")) -+os.remove("_povray_export_test.pov") -diff --git a/tests/scripts/test_suite/save_scene.py b/tests/scripts/test_suite/save_scene.py -index e02231d0..2950bb2b 100644 ---- a/tests/scripts/test_suite/save_scene.py -+++ b/tests/scripts/test_suite/save_scene.py -@@ -3,11 +3,14 @@ from ovito.io import * - import os - import os.path - --import_file("../../files/LAMMPS/animation.dump.gz") -+node = import_file("../../files/LAMMPS/animation.dump.gz") -+node.add_to_scene() - --if os.path.isfile("scene.ovito"): os.remove("scene.ovito") -+output_test_file = "_save_scene.ovito" - --ovito.dataset.save("scene.ovito") --assert(os.path.isfile("scene.ovito")) -+if os.path.isfile(output_test_file): os.remove(output_test_file) - --os.remove("scene.ovito") -+ovito.dataset.save(output_test_file) -+assert(os.path.isfile(output_test_file)) -+ -+os.remove(output_test_file) diff -Nru ovito-2.8.1+dfsg2/debian/patches/0003-Fixing-issue-4-Tests-that-depend-on-the-CrystalAnaly.patch ovito-2.9.0+dfsg1/debian/patches/0003-Fixing-issue-4-Tests-that-depend-on-the-CrystalAnaly.patch --- ovito-2.8.1+dfsg2/debian/patches/0003-Fixing-issue-4-Tests-that-depend-on-the-CrystalAnaly.patch 2017-01-15 09:08:41.000000000 +0000 +++ ovito-2.9.0+dfsg1/debian/patches/0003-Fixing-issue-4-Tests-that-depend-on-the-CrystalAnaly.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,226 +0,0 @@ -From: Alexander Stukowski -Date: Mon, 9 Jan 2017 21:42:28 +0100 -Subject: Fixing issue #4: Tests that depend on the CrystalAnalysis module - fail when the module was disabled in the build. - ---- - .../example_snippets/construct_surface_modifier.py | 3 ++ - .../dislocation_analysis_modifier.py | 3 ++ - doc/python/example_snippets/surface_mesh.py | 3 ++ - src/plugins/CMakeLists.txt | 33 +++++++++++----------- - .../crystalanalysis/scripting/PythonInterface.cpp | 9 ++++-- - .../particles/scripting/PythonInterface.cpp | 3 +- - src/plugins/pyscript/python/ovito/__init__.py | 1 + - .../test_suite/construct_surface_modifier.py | 3 ++ - .../test_suite/dislocation_analysis_modifier.py | 3 ++ - .../elastic_strain_calculation_modifier.py | 3 ++ - 10 files changed, 44 insertions(+), 20 deletions(-) - -diff --git a/doc/python/example_snippets/construct_surface_modifier.py b/doc/python/example_snippets/construct_surface_modifier.py -index 67ceeba5..f51e45dd 100644 ---- a/doc/python/example_snippets/construct_surface_modifier.py -+++ b/doc/python/example_snippets/construct_surface_modifier.py -@@ -1,3 +1,6 @@ -+import sys -+if "ovito.modifiers.crystalanalysis" not in sys.modules: sys.exit() -+ - from ovito.io import import_file - from ovito.modifiers import ConstructSurfaceModifier - -diff --git a/doc/python/example_snippets/dislocation_analysis_modifier.py b/doc/python/example_snippets/dislocation_analysis_modifier.py -index 8affc158..b9d98164 100644 ---- a/doc/python/example_snippets/dislocation_analysis_modifier.py -+++ b/doc/python/example_snippets/dislocation_analysis_modifier.py -@@ -1,3 +1,6 @@ -+import sys -+if "ovito.modifiers.crystalanalysis" not in sys.modules: sys.exit() -+ - from ovito.io import import_file, export_file - from ovito.modifiers import DislocationAnalysisModifier - -diff --git a/doc/python/example_snippets/surface_mesh.py b/doc/python/example_snippets/surface_mesh.py -index e5934c86..26ccdc47 100644 ---- a/doc/python/example_snippets/surface_mesh.py -+++ b/doc/python/example_snippets/surface_mesh.py -@@ -1,3 +1,6 @@ -+import sys -+if "ovito.modifiers.crystalanalysis" not in sys.modules: sys.exit() -+ - from ovito.io import import_file - from ovito.modifiers import ConstructSurfaceModifier - -diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt -index dd9a8cc5..7bf9af27 100755 ---- a/src/plugins/CMakeLists.txt -+++ b/src/plugins/CMakeLists.txt -@@ -19,62 +19,63 @@ - # - ############################################################################### - --# Create the plugins directory. --FILE(MAKE_DIRECTORY ${OVITO_PLUGINS_DIRECTORY}) -+# Create the plugins library and manifest directories. -+FILE(MAKE_DIRECTORY "${OVITO_PLUGINS_DIRECTORY}") -+FILE(MAKE_DIRECTORY "${OVITO_PLUGIN_MANIFESTS_DIRECTORY}") - - IF(OVITO_BUILD_PLUGIN_PYSCRIPT) - ADD_SUBDIRECTORY(pyscript) - SET(OVITOS_EXECUTABLE ${OVITOS_EXECUTABLE} PARENT_SCOPE) - ELSE() -- FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/PyScript.json) -- FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/PyScriptGui.json) -+ FILE(REMOVE ${OVITO_PLUGIN_MANIFESTS_DIRECTORY}/PyScript.json) -+ FILE(REMOVE ${OVITO_PLUGIN_MANIFESTS_DIRECTORY}/PyScriptGui.json) - ENDIF() - - IF(OVITO_BUILD_PLUGIN_PARTICLES) - ADD_SUBDIRECTORY(particles) - ELSE() -- FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/Particles.json) -- FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/ParticlesGui.json) -+ FILE(REMOVE ${OVITO_PLUGIN_MANIFESTS_DIRECTORY}/Particles.json) -+ FILE(REMOVE ${OVITO_PLUGIN_MANIFESTS_DIRECTORY}/ParticlesGui.json) - ENDIF() - - IF(OVITO_BUILD_PLUGIN_TACHYON) - ADD_SUBDIRECTORY(tachyon) - ELSE() -- FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/Tachyon.json) -- FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/TachyonGui.json) -+ FILE(REMOVE ${OVITO_PLUGIN_MANIFESTS_DIRECTORY}/Tachyon.json) -+ FILE(REMOVE ${OVITO_PLUGIN_MANIFESTS_DIRECTORY}/TachyonGui.json) - ENDIF() - - IF(OVITO_BUILD_PLUGIN_MESH) - ADD_SUBDIRECTORY(mesh) - ELSE() -- FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/Mesh.json) -+ FILE(REMOVE ${OVITO_PLUGIN_MANIFESTS_DIRECTORY}/Mesh.json) - ENDIF() - - IF(OVITO_BUILD_PLUGIN_CRYSTALANALYSIS) - ADD_SUBDIRECTORY(crystalanalysis) - ELSE() -- FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/CrystalAnalysis.json) -- FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/CrystalAnalysisGui.json) -+ FILE(REMOVE ${OVITO_PLUGIN_MANIFESTS_DIRECTORY}/CrystalAnalysis.json) -+ FILE(REMOVE ${OVITO_PLUGIN_MANIFESTS_DIRECTORY}/CrystalAnalysisGui.json) - ENDIF() - - IF(OVITO_BUILD_PLUGIN_NETCDFPLUGIN) - ADD_SUBDIRECTORY(netcdf) - ELSE() -- FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/NetCDFPlugin.json) -- FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/NetCDFPluginGui.json) -+ FILE(REMOVE ${OVITO_PLUGIN_MANIFESTS_DIRECTORY}/NetCDFPlugin.json) -+ FILE(REMOVE ${OVITO_PLUGIN_MANIFESTS_DIRECTORY}/NetCDFPluginGui.json) - ENDIF() - - IF(OVITO_BUILD_PLUGIN_POVRAY) - ADD_SUBDIRECTORY(povray) - ELSE() -- FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/POVRay.json) -- FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/POVRayGui.json) -+ FILE(REMOVE ${OVITO_PLUGIN_MANIFESTS_DIRECTORY}/POVRay.json) -+ FILE(REMOVE ${OVITO_PLUGIN_MANIFESTS_DIRECTORY}/POVRayGui.json) - ENDIF() - - IF(OVITO_BUILD_PLUGIN_OPENBABELPLUGIN) - ADD_SUBDIRECTORY(openbabel) - ELSE() -- FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/OpenBabelPlugin.json) -+ FILE(REMOVE ${OVITO_PLUGIN_MANIFESTS_DIRECTORY}/OpenBabelPlugin.json) - ENDIF() - - # Propagate list of plugins to parent scope. -diff --git a/src/plugins/crystalanalysis/scripting/PythonInterface.cpp b/src/plugins/crystalanalysis/scripting/PythonInterface.cpp -index ab27d960..eb310ed2 100755 ---- a/src/plugins/crystalanalysis/scripting/PythonInterface.cpp -+++ b/src/plugins/crystalanalysis/scripting/PythonInterface.cpp -@@ -74,7 +74,8 @@ PYBIND11_PLUGIN(CrystalAnalysis) - " The volume of the solid region bounded by the surface mesh.\n" - "\n\n" - "Example:\n\n" -- ".. literalinclude:: ../example_snippets/construct_surface_modifier.py" -+ ".. literalinclude:: ../example_snippets/construct_surface_modifier.py\n" -+ " :lines: 4-\n" - ) - .def_property("radius", &ConstructSurfaceModifier::probeSphereRadius, &ConstructSurfaceModifier::setProbeSphereRadius, - "The radius of the probe sphere used in the surface construction algorithm." -@@ -142,7 +143,8 @@ PYBIND11_PLUGIN(CrystalAnalysis) - " The number of particles with local hexagonal diamond structure.\n" - "\n\n" - "Example:\n\n" -- ".. literalinclude:: ../example_snippets/dislocation_analysis_modifier.py" -+ ".. literalinclude:: ../example_snippets/dislocation_analysis_modifier.py\n" -+ " :lines: 4-\n" - ) - .def_property("trial_circuit_length", &DislocationAnalysisModifier::maxTrialCircuitSize, &DislocationAnalysisModifier::setMaxTrialCircuitSize, - "The maximum length of trial Burgers circuits constructed by the DXA to discover dislocations. " -@@ -377,7 +379,8 @@ PYBIND11_PLUGIN(CrystalAnalysis) - "the :py:attr:`~DataObject.display` attribute of the :py:class:`~DataObject` base class." - "\n\n" - "Example:\n\n" -- ".. literalinclude:: ../example_snippets/dislocation_analysis_modifier.py", -+ ".. literalinclude:: ../example_snippets/dislocation_analysis_modifier.py\n" -+ " :lines: 4-\n", - // Python class name: - "DislocationNetwork") - -diff --git a/src/plugins/particles/scripting/PythonInterface.cpp b/src/plugins/particles/scripting/PythonInterface.cpp -index 231dbf8e..530659c4 100755 ---- a/src/plugins/particles/scripting/PythonInterface.cpp -+++ b/src/plugins/particles/scripting/PythonInterface.cpp -@@ -669,7 +669,8 @@ PYBIND11_PLUGIN(Particles) - "of the :py:class:`~ovito.modifiers.ConstructSurfaceModifier` that created the surface mesh." - "\n\n" - "Example:\n\n" -- ".. literalinclude:: ../example_snippets/surface_mesh.py" -+ ".. literalinclude:: ../example_snippets/surface_mesh.py\n" -+ " :lines: 4-\n" - ) - .def_property("is_completely_solid", &SurfaceMesh::isCompletelySolid, &SurfaceMesh::setCompletelySolid) - .def("export_vtk", [](SurfaceMesh& mesh, const QString& filename, SimulationCellObject* simCellObj) { -diff --git a/src/plugins/pyscript/python/ovito/__init__.py b/src/plugins/pyscript/python/ovito/__init__.py -index dbc9b9f1..c7b889df 100644 ---- a/src/plugins/pyscript/python/ovito/__init__.py -+++ b/src/plugins/pyscript/python/ovito/__init__.py -@@ -1,4 +1,5 @@ - import os.path -+import sys - try: - # Python 3.x - import collections.abc as collections -diff --git a/tests/scripts/test_suite/construct_surface_modifier.py b/tests/scripts/test_suite/construct_surface_modifier.py -index 7cda4a8f..ad57023d 100644 ---- a/tests/scripts/test_suite/construct_surface_modifier.py -+++ b/tests/scripts/test_suite/construct_surface_modifier.py -@@ -1,3 +1,6 @@ -+import sys -+if "ovito.modifiers.crystalanalysis" not in sys.modules: sys.exit() -+ - from ovito import * - from ovito.io import * - from ovito.modifiers import * -diff --git a/tests/scripts/test_suite/dislocation_analysis_modifier.py b/tests/scripts/test_suite/dislocation_analysis_modifier.py -index 033b5f73..6b246559 100644 ---- a/tests/scripts/test_suite/dislocation_analysis_modifier.py -+++ b/tests/scripts/test_suite/dislocation_analysis_modifier.py -@@ -1,3 +1,6 @@ -+import sys -+if "ovito.modifiers.crystalanalysis" not in sys.modules: sys.exit() -+ - from ovito import * - from ovito.io import * - from ovito.modifiers import * -diff --git a/tests/scripts/test_suite/elastic_strain_calculation_modifier.py b/tests/scripts/test_suite/elastic_strain_calculation_modifier.py -index b3047cee..a44741e3 100644 ---- a/tests/scripts/test_suite/elastic_strain_calculation_modifier.py -+++ b/tests/scripts/test_suite/elastic_strain_calculation_modifier.py -@@ -1,3 +1,6 @@ -+import sys -+if "ovito.modifiers.crystalanalysis" not in sys.modules: sys.exit() -+ - from ovito import * - from ovito.io import * - from ovito.data import * diff -Nru ovito-2.8.1+dfsg2/debian/patches/0004-Use-system-pybind11.patch ovito-2.9.0+dfsg1/debian/patches/0004-Use-system-pybind11.patch --- ovito-2.8.1+dfsg2/debian/patches/0004-Use-system-pybind11.patch 2017-01-15 09:08:41.000000000 +0000 +++ ovito-2.9.0+dfsg1/debian/patches/0004-Use-system-pybind11.patch 2017-01-15 15:01:02.000000000 +0000 @@ -6,10 +6,10 @@ src/plugins/pyscript/PyScript.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) -diff --git a/src/plugins/pyscript/PyScript.h b/src/plugins/pyscript/PyScript.h -index 7bc647bb..fd0ba267 100644 ---- a/src/plugins/pyscript/PyScript.h -+++ b/src/plugins/pyscript/PyScript.h +Index: ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/src/plugins/pyscript/PyScript.h +=================================================================== +--- ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f.orig/src/plugins/pyscript/PyScript.h ++++ ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/src/plugins/pyscript/PyScript.h @@ -33,12 +33,12 @@ #endif diff -Nru ovito-2.8.1+dfsg2/debian/patches/0005-Updated-to-latest-pybind11-version.-Also-fixing-issu.patch ovito-2.9.0+dfsg1/debian/patches/0005-Updated-to-latest-pybind11-version.-Also-fixing-issu.patch --- ovito-2.8.1+dfsg2/debian/patches/0005-Updated-to-latest-pybind11-version.-Also-fixing-issu.patch 2017-01-15 09:08:41.000000000 +0000 +++ ovito-2.9.0+dfsg1/debian/patches/0005-Updated-to-latest-pybind11-version.-Also-fixing-issu.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -From: Alexander Stukowski -Date: Mon, 9 Jan 2017 22:57:42 +0100 -Subject: Updated to latest pybind11 version. Also fixing issue #5. - ---- - src/plugins/pyscript/binding/AnimationBinding.cpp | 11 ++++++----- - src/plugins/pyscript/binding/FileIOBinding.cpp | 5 +++-- - src/plugins/pyscript/python/ovito/anim/__init__.py | 3 --- - 3 files changed, 9 insertions(+), 10 deletions(-) - -diff --git a/src/plugins/pyscript/binding/AnimationBinding.cpp b/src/plugins/pyscript/binding/AnimationBinding.cpp -index 28c987a1..110bfe8d 100644 ---- a/src/plugins/pyscript/binding/AnimationBinding.cpp -+++ b/src/plugins/pyscript/binding/AnimationBinding.cpp -@@ -42,7 +42,7 @@ PYBIND11_PLUGIN(PyScriptAnimation) - - py::module m("PyScriptAnimation"); - -- py::object TimeInterval_py = py::class_(m, "TimeInterval") -+ py::class_(m, "TimeInterval", py::metaclass()) - .def(py::init<>()) - .def(py::init()) - .def(py::init()) -@@ -58,13 +58,14 @@ PYBIND11_PLUGIN(PyScriptAnimation) - .def("intersect", &TimeInterval::intersect) - .def_static("time_to_seconds", &TimeToSeconds) - .def_static("seconds_to_time", &TimeFromSeconds) -- .def_property_readonly_static("infinite", &TimeInterval::infinite) -- .def_property_readonly_static("empty", &TimeInterval::empty) -+ .def_property_readonly_static("infinite", [](py::object /*self*/) { return TimeInterval::infinite(); }) -+ .def_property_readonly_static("empty", [](py::object /*self*/) { return TimeInterval::empty(); }) -+ .def_property_readonly_static("TimeNegativeInfinity", [](py::object /*self*/) { return TimeNegativeInfinity(); }) -+ .def_property_readonly_static("TimePositiveInfinity", [](py::object /*self*/) { return TimePositiveInfinity(); }) -+ .def("__str__", [](TimeInterval& iv) { return py::str("({},{})").format(iv.start(), iv.end()); }) - .def(py::self == TimeInterval()) - .def(py::self != TimeInterval()) - ; -- py::setattr(TimeInterval_py, "TimeNegativeInfinity", py::cast(TimeNegativeInfinity())); -- py::setattr(TimeInterval_py, "TimePositiveInfinity", py::cast(TimePositiveInfinity())); - - ovito_class(m, - "Stores animation-related settings of the current :py:attr:`~ovito.DataSet`. You can access " -diff --git a/src/plugins/pyscript/binding/FileIOBinding.cpp b/src/plugins/pyscript/binding/FileIOBinding.cpp -index 3ebf7321..a19dd391 100644 ---- a/src/plugins/pyscript/binding/FileIOBinding.cpp -+++ b/src/plugins/pyscript/binding/FileIOBinding.cpp -@@ -57,8 +57,9 @@ PYBIND11_PLUGIN(PyScriptFileIO) - .value("ResetScene", FileImporter::ResetScene) - ; - -- py::class_(m, "FileManager") -- .def_property_readonly_static("instance", py::cpp_function(&FileManager::instance, py::return_value_policy::reference)) -+ py::class_(m, "FileManager", py::metaclass()) -+ .def_property_readonly_static("instance", py::cpp_function( -+ [](py::object /*self*/) { return &FileManager::instance(); }, py::return_value_policy::reference)) - //.def("removeFromCache", &FileManager::removeFromCache) - //.def("urlFromUserInput", &FileManager::urlFromUserInput) - ; -diff --git a/src/plugins/pyscript/python/ovito/anim/__init__.py b/src/plugins/pyscript/python/ovito/anim/__init__.py -index bc25378f..465426bf 100644 ---- a/src/plugins/pyscript/python/ovito/anim/__init__.py -+++ b/src/plugins/pyscript/python/ovito/anim/__init__.py -@@ -1,5 +1,2 @@ - # Load the native module. - from PyScriptAnimation import * -- --# Add __str__ method to TimeInterval class: --TimeInterval.__str__ = lambda self: str((self.start,self.end)) -\ No newline at end of file diff -Nru ovito-2.8.1+dfsg2/debian/patches/0006-Code-change-required-by-latest-pybind11-version.-Fix.patch ovito-2.9.0+dfsg1/debian/patches/0006-Code-change-required-by-latest-pybind11-version.-Fix.patch --- ovito-2.8.1+dfsg2/debian/patches/0006-Code-change-required-by-latest-pybind11-version.-Fix.patch 2017-01-15 09:08:41.000000000 +0000 +++ ovito-2.9.0+dfsg1/debian/patches/0006-Code-change-required-by-latest-pybind11-version.-Fix.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -From: Alexander Stukowski -Date: Mon, 9 Jan 2017 23:53:04 +0100 -Subject: Code change required by latest pybind11 version. Fixing issue #5. - ---- - src/plugins/particles/resources/python/ovito/data/particles/__init__.py | 2 +- - src/plugins/pyscript/binding/PythonBinding.h | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/plugins/particles/resources/python/ovito/data/particles/__init__.py b/src/plugins/particles/resources/python/ovito/data/particles/__init__.py -index c02b314a..c1dcdcda 100644 ---- a/src/plugins/particles/resources/python/ovito/data/particles/__init__.py -+++ b/src/plugins/particles/resources/python/ovito/data/particles/__init__.py -@@ -380,7 +380,7 @@ class CutoffNeighborFinder(Particles.CutoffNeighborFinder): - - def __init__(self, cutoff, data_collection): - """ This is the constructor. """ -- super(self.__class__, self).__init__() -+ super(self.__class__, self).__init__() - if not hasattr(data_collection, 'position'): - raise KeyError("Data collection does not contain any particles.") - if not hasattr(data_collection, 'cell'): -diff --git a/src/plugins/pyscript/binding/PythonBinding.h b/src/plugins/pyscript/binding/PythonBinding.h -index 0f8095e2..4f2cb497 100644 ---- a/src/plugins/pyscript/binding/PythonBinding.h -+++ b/src/plugins/pyscript/binding/PythonBinding.h -@@ -26,7 +26,7 @@ - #include - #include - --PYBIND11_DECLARE_HOLDER_TYPE(T, Ovito::OORef); -+PYBIND11_DECLARE_HOLDER_TYPE(T, Ovito::OORef, true); - - namespace pybind11 { namespace detail { - diff -Nru ovito-2.8.1+dfsg2/debian/patches/06_fix_gcc7_compiation.patch ovito-2.9.0+dfsg1/debian/patches/06_fix_gcc7_compiation.patch --- ovito-2.8.1+dfsg2/debian/patches/06_fix_gcc7_compiation.patch 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/debian/patches/06_fix_gcc7_compiation.patch 2017-01-15 15:01:02.000000000 +0000 @@ -0,0 +1,30 @@ +Description: Fix compilation with GCC 7. +Author: Anton Gladky +Bug-Debian: https://bugs.debian.org/853603 +Last-Update: 2017-08-06 + +Index: ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/src/core/reference/PropertyField.h +=================================================================== +--- ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f.orig/src/core/reference/PropertyField.h ++++ ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/src/core/reference/PropertyField.h +@@ -159,7 +159,7 @@ private: + // This undo class records a change to the property value. + class PropertyChangeOperation : public UndoableOperation { + public: +- PropertyChangeOperation(PropertyField& field) : _field(field), _owner(field.owner() != field.owner()->dataset() ? field.owner() : nullptr) { ++ PropertyChangeOperation(PropertyField& field) : _field(field), _owner(field.owner() != static_cast(field.owner()->dataset()) ? field.owner() : nullptr) { + // Make a copy of the current property value. + _oldValue = field; + } +Index: ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/src/core/Core.h +=================================================================== +--- ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f.orig/src/core/Core.h ++++ ovito-v2.9.0-d0745a5f3db3a0423c85f3f1754f2111ca43e60f/src/core/Core.h +@@ -50,6 +50,7 @@ + #include + #include + #include ++#include + + /****************************************************************************** + * QT Library diff -Nru ovito-2.8.1+dfsg2/debian/patches/10_fix_ftbfs_on_some_archs.patch ovito-2.9.0+dfsg1/debian/patches/10_fix_ftbfs_on_some_archs.patch --- ovito-2.8.1+dfsg2/debian/patches/10_fix_ftbfs_on_some_archs.patch 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/debian/patches/10_fix_ftbfs_on_some_archs.patch 2017-08-10 17:44:20.000000000 +0000 @@ -0,0 +1,70 @@ +Description: Fix FTBFS on archs, where char is unsigned +Author: Anton Gladky +Bug-Debian: https://bugs.debian.org/871248 +Last-Update: 2017-08-10 + +--- ovito-2.9.0+dfsg1.orig/src/plugins/particles/modifier/fields/MarchingCubesLookupTable.h ++++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/fields/MarchingCubesLookupTable.h +@@ -41,7 +41,7 @@ + * 0 1 0 1 + */ + //----------------------------------------------------------------------------- +-static const char cases[256][2] = { ++static const signed char cases[256][2] = { + /* 0: */ { 0, -1 }, + /* 1: 0, */ { 1, 0 }, + /* 2: 1, */ { 1, 1 }, +@@ -388,7 +388,7 @@ static const char tiling2[24][6] = { + * A minus sign means to invert the result of the test. + */ + //----------------------------------------------------------------------------- +-static const char test3[24] = { ++static const signed char test3[24] = { + /* 5: 0, 2, */ 5, + /* 33: 0, 5, */ 1, + /* 129: 0, 7, */ 4, +@@ -509,7 +509,7 @@ static const char tiling3_2[24][12] = { + * A minus sign means to invert the result of the test. + */ + //----------------------------------------------------------------------------- +-static const char test4[8] = { ++static const signed char test4[8] = { + /* 65: 0, 6, */ 7, + /* 130: 1, 7, */ 7, + /* 20: 2, 4, */ 7, +@@ -648,7 +648,7 @@ static const char tiling5[48][9] = { + * A minus sign means to invert the result of the test. + */ + //----------------------------------------------------------------------------- +-static const char test6[48][3] = { ++static const signed char test6[48][3] = { + /* 67: 0, 1, 6, */ { 2, 7, 10 }, + /* 131: 0, 1, 7, */ { 4, 7, 11 }, + /* 21: 0, 2, 4, */ { 5, 7, 1 }, +@@ -912,7 +912,7 @@ static const char tiling6_2[48][15] = { + * A minus sign means to invert the result of the test. + */ + //----------------------------------------------------------------------------- +-static const char test7[16][5] = { ++static const signed char test7[16][5] = { + /* 37: 0, 2, 5, */ { 1, 2, 5, 7, 1 }, + /* 133: 0, 2, 7, */ { 3, 4, 5, 7, 3 }, + /* 161: 0, 5, 7, */ { 4, 1, 6, 7, 4 }, +@@ -1689,7 +1689,7 @@ static const char test13[2][7] = { + */ + //----------------------------------------------------------------------------- + /* 13: sub configs */ +-static const char subconfig13[64] = { ++static const signed char subconfig13[64] = { + /* 0: 0,0,0,0,0,0 */ 0, + /* 1: 1,0,0,0,0,0 */ 1, + /* 2: 0,1,0,0,0,0 */ 2, +@@ -2057,7 +2057,7 @@ static const char tiling14[12][12] = { + * the cube is not. + */ + //----------------------------------------------------------------------------- +-static const char casesClassic[256][16] = { ++static const signed char casesClassic[256][16] = { + /* 0: */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + /* 1: 0, */ { 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + /* 2: 1, */ { 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, diff -Nru ovito-2.8.1+dfsg2/debian/patches/series ovito-2.9.0+dfsg1/debian/patches/series --- ovito-2.8.1+dfsg2/debian/patches/series 2017-01-15 09:08:41.000000000 +0000 +++ ovito-2.9.0+dfsg1/debian/patches/series 2017-08-10 17:43:36.000000000 +0000 @@ -1,6 +1,4 @@ 0001-Disable-povray-test.patch -0002-Fixing-issue-3-Test-suite-can-fail-when-executed-in-.patch -0003-Fixing-issue-4-Tests-that-depend-on-the-CrystalAnaly.patch 0004-Use-system-pybind11.patch -0005-Updated-to-latest-pybind11-version.-Also-fixing-issu.patch -0006-Code-change-required-by-latest-pybind11-version.-Fix.patch +06_fix_gcc7_compiation.patch +10_fix_ftbfs_on_some_archs.patch diff -Nru ovito-2.8.1+dfsg2/doc/develop/build_linux_howto.txt ovito-2.9.0+dfsg1/doc/develop/build_linux_howto.txt --- ovito-2.8.1+dfsg2/doc/develop/build_linux_howto.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/develop/build_linux_howto.txt 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,8 @@ ncurses-dev \ libssl-dev \ libreadline-dev \ - povray + povray \ + libfftw3-dev ************************************************************************** Install GNU g++ 5 compiler on Ubuntu 10.04 @@ -260,10 +261,11 @@ -DOVITO_BUILD_DOCUMENTATION=ON \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=../release_install \ - -DOVITO_MONOLITHIC_BUILD=ON \ + -DOVITO_REDISTRIBUTABLE_PACKAGE=ON \ -DBOOST_ROOT=$HOME/progs/boost \ -DHDF5_DIR=$HOME/progs/hdf5/share/cmake \ -DnetCDF_DIR=$HOME/progs/netcdf/lib/cmake/netCDF \ + -DPYTHON_EXECUTABLE=$HOME/progs/python/bin/python3 \ -DPYTHON_LIBRARY=$HOME/progs/python/lib/libpython3.5m.so.1.0 \ -DPYTHON_INCLUDE_DIR=$HOME/progs/python/include/python3.5m \ -DSPHINX_PROCESSOR_PATH=$HOME/progs/python/bin \ diff -Nru ovito-2.8.1+dfsg2/doc/develop/build_macosx_howto.txt ovito-2.9.0+dfsg1/doc/develop/build_macosx_howto.txt --- ovito-2.8.1+dfsg2/doc/develop/build_macosx_howto.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/develop/build_macosx_howto.txt 2017-07-27 16:52:45.000000000 +0000 @@ -3,6 +3,7 @@ ************************************************************************** export MACOSX_DEPLOYMENT_TARGET=10.8 sudo port install cmake docbook-xml doxygen libxslt boost yasm povray +sudo port install -s fftw-3-single ************************************************************************** Install Qt libraries, version 5.7 @@ -104,21 +105,12 @@ install_name_tool -id $PWD/libnetcdf.dylib libnetcdf.dylib ************************************************************************** -Remove unused Python.app bundle from Python framework, because -CMake's fixup_bundle() macro cannot fix it. -************************************************************************** -sudo mv /Library/Frameworks/Python.framework/Versions/3.5/Resources/Python.app /Library/Frameworks/Python.framework/Versions/ - -# To undo this change: -# sudo mv /Library/Frameworks/Python.framework/Versions/Python.app /Library/Frameworks/Python.framework/Versions/3.5/Resources/ - - -************************************************************************** Build OVITO: ************************************************************************** export MACOSX_DEPLOYMENT_TARGET=10.8 cmake -DOVITO_BUILD_DOCUMENTATION=ON \ -DCMAKE_BUILD_TYPE=Release \ + -DOVITO_REDISTRIBUTABLE_PACKAGE=ON \ -DCMAKE_INSTALL_PREFIX=../release_install \ -DCMAKE_PREFIX_PATH=$HOME/progs/Qt/5.7/clang_64/ \ -DPYTHON_INCLUDE_DIR=/Library/Frameworks/Python.framework/Versions/3.5/include/python3.5m \ diff -Nru ovito-2.8.1+dfsg2/doc/develop/build_windows_howto.txt ovito-2.9.0+dfsg1/doc/develop/build_windows_howto.txt --- ovito-2.8.1+dfsg2/doc/develop/build_windows_howto.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/develop/build_windows_howto.txt 2017-07-27 16:52:45.000000000 +0000 @@ -148,6 +148,11 @@ make install ************************************************************************** +OpenVR +************************************************************************** +git clone https://github.com/ValveSoftware/openvr.git + +************************************************************************** Create an app package signing certificate: ************************************************************************** MakeCert /n "CN=ovito.org, O=ovito.org, L=Darmstadt, C=Germany" /r /h 0 /eku "1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.10.3.13" /e 12/31/2017 /sv ovito.pvk ovito.cer @@ -163,6 +168,7 @@ cmake -G "NMake Makefiles" ^ -DCMAKE_BUILD_TYPE=Release ^ -DCMAKE_INSTALL_PREFIX=../ovito_release_install ^ + -DOVITO_REDISTRIBUTABLE_PACKAGE=ON ^ -DZLIB_INCLUDE_DIR=%cd:\=/%/../zlib_install/include ^ -DZLIB_LIBRARY=%cd:\=/%/../zlib_install/lib/zlib.lib ^ -Dnetcdf_DIR=%cd:\=/%/../netcdf_install/lib/cmake/netCDF ^ @@ -172,16 +178,50 @@ -DQSCINTILLA_LIBRARY=%cd:\=/%/../qscintilla/release/qscintilla2.lib ^ -DPYTHON_LIBRARY=%cd:\=/%/../Python/libs/python34.lib ^ -DPYTHON_INCLUDE_DIR=%cd:\=/%/../Python/include ^ + -DPYTHON_EXECUTABLE=%cd:\=/%/../Python/bin/python.exe ^ -DXSLT_PROCESSOR=../../libxslt-1.1.26.win32/bin/xsltproc.exe ^ -DSPHINX_PROCESSOR_PATH=%cd:\=/%/../Python/Scripts ^ -DLIBAV_INCLUDE_DIR=%cd:\=/%/../libav_install/include ^ -DLIBAV_LIBRARY_DIR=%cd:\=/%/../libav_install/bin ^ -DOVITO_BUILD_DOCUMENTATION=ON ^ + -DOVITO_BUILD_PLUGIN_VR=OFF ^ + -DOPENVR_INCLUDE_DIR=%cd:\=/%/../openvr/headers ^ + -DOPENVR_LIBRARY=%cd:\=/%/../openvr/lib/win64/openvr_api.lib ^ + -DFFTW3_INCLUDE_DIR=%cd:\=/%/../fftw ^ + -DFFTW3_LIBRARY=%cd:\=/%/../fftw/libfftw3f-3.lib ^ ../../source - + nmake install ---- Copy missing DLLs into installation dir of 32-bit version ---- C:\Program Files (x86)\CMake 2.8\bin\libeay32.dll -C:\Program Files (x86)\CMake 2.8\bin\ssleay32.dll \ No newline at end of file +C:\Program Files (x86)\CMake 2.8\bin\ssleay32.dll + +************************************************************************** +Debug version: +************************************************************************** +mkdir ovito_debug +cd ovito_debug +cmake -G "NMake Makefiles" ^ + -DCMAKE_BUILD_TYPE=Debug ^ + -DCMAKE_INSTALL_PREFIX=../ovito_debug_install ^ + -DOVITO_REDISTRIBUTABLE_PACKAGE=ON ^ + -DZLIB_INCLUDE_DIR=%cd:\=/%/../zlib_install/include ^ + -DZLIB_LIBRARY=%cd:\=/%/../zlib_install/lib/zlib.lib ^ + -Dnetcdf_DIR=%cd:\=/%/../netcdf_install/lib/cmake/netCDF ^ + -DHDF5_DIR=%cd:\=/%/../hdf5_install/cmake ^ + -DBOOST_INCLUDEDIR=%cd:\=/%/../../boost_1_62_0 ^ + -DQSCINTILLA_INCLUDE_DIR=%cd:\=/%/../../QScintilla_gpl-2.9.3\Qt4Qt5 ^ + -DQSCINTILLA_LIBRARY=%cd:\=/%/../qscintilla/debug/qscintilla2.lib ^ + -DPYTHON_LIBRARY=%cd:\=/%/../Python/libs/python34.lib ^ + -DPYTHON_INCLUDE_DIR=%cd:\=/%/../Python/include ^ + -DPYTHON_EXECUTABLE=%cd:\=/%/../Python/bin/python.exe ^ + -DXSLT_PROCESSOR=../../libxslt-1.1.26.win32/bin/xsltproc.exe ^ + -DSPHINX_PROCESSOR_PATH=%cd:\=/%/../Python/Scripts ^ + -DLIBAV_INCLUDE_DIR=%cd:\=/%/../libav_install/include ^ + -DLIBAV_LIBRARY_DIR=%cd:\=/%/../libav_install/bin ^ + -DOVITO_BUILD_DOCUMENTATION=ON ^ + -DFFTW3_INCLUDE_DIR=%cd:\=/%/../fftw ^ + -DFFTW3_LIBRARY=%cd:\=/%/../fftw/libfftw3f-3.lib ^ + ../../source \ No newline at end of file diff -Nru ovito-2.8.1+dfsg2/doc/develop/conda_recipe/build.sh ovito-2.9.0+dfsg1/doc/develop/conda_recipe/build.sh --- ovito-2.8.1+dfsg2/doc/develop/conda_recipe/build.sh 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/develop/conda_recipe/build.sh 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,30 @@ +#!/bin/bash + +if [ ! -d build ]; then + mkdir build +fi +cd build + +PY_LIB="libpython${PY_VER}m${SHLIB_EXT}" +MACOSX_DEPLOYMENT_TARGET=10.8 + +cmake \ + -G "${CMAKE_GENERATOR}" \ + -DCMAKE_INSTALL_PREFIX="${PREFIX}" \ + -DOVITO_BUILD_GUI=OFF \ + -DOVITO_BUILD_DOCUMENTATION=OFF \ + -DCMAKE_BUILD_TYPE=Release \ + -DPYTHON_EXECUTABLE=${PYTHON} \ + -DPYTHON_INCLUDE_DIR=${PREFIX}/include/python${PY_VER}m \ + -DPYTHON_LIBRARY=${PREFIX}/lib/${PY_LIB} \ + ${SRC_DIR} + +make -j${CPU_COUNT} +make install + +if [ `uname` == Darwin ]; then + echo "${PREFIX}/Ovito.app/Contents/Resources/python" > ${SP_DIR}/${PKG_NAME}.pth +else + echo "${PREFIX}/lib/ovito/plugins/python" > ${SP_DIR}/${PKG_NAME}.pth +fi +echo "SP_DIR=${SP_DIR}" diff -Nru ovito-2.8.1+dfsg2/doc/develop/conda_recipe/meta.yaml ovito-2.9.0+dfsg1/doc/develop/conda_recipe/meta.yaml --- ovito-2.8.1+dfsg2/doc/develop/conda_recipe/meta.yaml 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/develop/conda_recipe/meta.yaml 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,40 @@ +package: + name: ovito + version: "2.8.2" + +source: + path: ../../../ +# git_url: https://gitlab.com/stuko/ovito.git + +requirements: + build: + - cmake + - boost + - git + - netcdf4 + - hdf5 + - qt + - zlib + - python + - numpy + - pyqt + - setuptools + + run: + - netcdf4 + - hdf5 + - qt + - zlib + - python + - numpy + - pyqt + +test: + imports: + - ovito + +about: + home: http://www.ovito.org + license: GPLv3 + license_file: LICENSE.txt + summary: "A scientific data visualization and analysis software for atomistic and other particle-based simulation models" \ No newline at end of file diff -Nru ovito-2.8.1+dfsg2/doc/develop/feature_requests.txt ovito-2.9.0+dfsg1/doc/develop/feature_requests.txt --- ovito-2.8.1+dfsg2/doc/develop/feature_requests.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/develop/feature_requests.txt 2017-07-27 16:52:45.000000000 +0000 @@ -8,6 +8,8 @@ - List of most recently accessed files - Histogram plot export (SaeeD PourasaD ). - Spherical and cylindral slices (Enrique Martinez) +- Warn about NaN/infinite values in the input of modifiers +- Add positibility to export custom modifier presets to a file so that they can be transferred to other computers (requested in Ovito forum). Work-flow improvements: @@ -15,7 +17,7 @@ New visualization features: -- Visualize polyhedra (like Vesta). +- Visualization of coordination polyhedra: Improve behavior at periodic boundaries - Particle text labels (joy5142@psu.edu) and bond text labels (mickaeltrochet@yahoo.fr) - More particle representations (e.g. open circles). - Test OpenGL rendering support for more than 12 million particles. @@ -23,6 +25,8 @@ - Stereoscopic display (Erik Bitzek) - Wireframe mesh rendering (robin.gibaud@simap.grenoble-inp.fr) - Double bonds (SP2) (Jejoon Yeon ) +- Visualization of Voronoi polyhedra. +- Add modifiers to select and delete bonds. Unresolved OpenGL problems: @@ -53,8 +57,10 @@ Workaround is to explicitly turn off the use point sprites. - High-quality particle rendering does not work properly (spheres are cut in half), Ovito 2.6.1 Linux, Mesa DRI Intel(R) Sandybridge Mobile, 3.3 (Core Profile) Mesa 11.1.2 (morten.nagel@helsinki.fi) -- Crash when opnening any simulation file, +- Crash when opening any simulation file, Ovito 2.6.0 Windows, Intel(R) HD Graphics 4400, 3.2.0 - Build 9.18.10.3186 (ashishvineet07@gmail.com) +- Main window turns to be black + Ovito 2.8.1, Windows 64-bit, Intel(R) HD Graphics Family, 3.0.0 - Build 8.15.10.2342 - Program crashes when setting particle radius to an extremely large value: Linux, Intel Graphics, Message: "Matrix4 cannot be inverted: determinant is zero." @@ -74,15 +80,24 @@ - Particle trajectory creation doesn't work if new particles are created over time. - WebM video export not working on Windows & Linux (stefan.parviainen@iki.fi). +- On Windows: Program crash at File->Load File when previous accessed path does not exist anymore. + Changing the file selection dialog to the alternative solves the problem. + After changing back to the normal file selection dialog, this one also works for me but opening the selection box takes about 10 seconds, + while the programm does not receive any feedback ('Keine Rückmeldung'). + After changing the preferred file path to a local path in the registry, the selection box opens immediately. + Changing the preferred file path back to the non existing server, I can reproduce the 10 seconds of no response, + but without any crash. + New analysis features: -- Create Bonds modifier: Add 'lower bound' parameter such that, when using the mothod todifier several times, bonds with different lengths can be assigned different colors (jerome.dequeker@ed.univ-lille1.fr). +- Create Bonds modifier: Add 'lower bound' parameter such that, when using the modifier several times, bonds with different lengths can be assigned different colors (jerome.dequeker@ed.univ-lille1.fr). - Plotting the value of a certain property of a certain particle versus simulation time. To make this work, all simulation frames need to be kept in memory (requested by Taojun & Mathieu Marciante). -- Calculation of type-specific (partial) RDF (requested by Jordan R Keith ). Also demonstrate how to average RDF over time using a script. +- Calculation of type-specific (partial) RDF (requested by Jordan R Keith , lindeye0716@163.com). Also demonstrate how to average RDF over time using a script. - Identification of binary phases and defects (see Christoph Begau's work) - Glass ring analysis (see ISAACS, RINGS, Sudheer @ FAU) - Crystal orientation map - Extend Create Bonds modifier to make it possible to create different bond types depending on atom pair types (Yan CHEN <1358179191@qq.com>). +- Implement coarsening of surface meshes as a postprocessing step to reduce number of triangles. New I/O functions: @@ -98,7 +113,4 @@ Scripting features: - Display script output when running a script via the GUI menu. - -Documentation: - -- Application settings dialog +- Make "ovito" module usable from normal Python interpreter (n.hamilton@unsw.onmicrosoft.com) diff -Nru ovito-2.8.1+dfsg2/doc/manual/Chapter_Credits.docbook ovito-2.9.0+dfsg1/doc/manual/Chapter_Credits.docbook --- ovito-2.8.1+dfsg2/doc/manual/Chapter_Credits.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/Chapter_Credits.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -51,6 +51,7 @@ (license). Matplotlib (license). + FFTW (GNU General Public License). diff -Nru ovito-2.8.1+dfsg2/doc/manual/Chapter_Installation.docbook ovito-2.9.0+dfsg1/doc/manual/Chapter_Installation.docbook --- ovito-2.8.1+dfsg2/doc/manual/Chapter_Installation.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/Chapter_Installation.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -18,7 +18,7 @@ Linux - Extract the downloaded .tar.gz archive using the tar command, e.g.: tar xzf ovito-2.8.1-x86_64.tar.gz. + Extract the downloaded .tar.gz archive using the tar command, e.g.: tar xzf ovito-2.9.0-x86_64.tar.gz. This will create a new subdirectory containing the program package. Change into the new directory and start OVITO by running the executable ./bin/ovito. diff -Nru ovito-2.8.1+dfsg2/doc/manual/Chapter_Introduction.docbook ovito-2.9.0+dfsg1/doc/manual/Chapter_Introduction.docbook --- ovito-2.8.1+dfsg2/doc/manual/Chapter_Introduction.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/Chapter_Introduction.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -17,7 +17,7 @@ OVITO is a scientific data visualization and analysis software for atomistic simulation models in materials science and related disciplines. OVITO is freely available for - Windows, Linux, and Mac OS X under an open-source license. It is being developed by Dr. Alexander + Windows, Linux, and macOS under an open-source license. It is being developed by Dr. Alexander Stukowski at the Materials Science Department of Darmstadt University of Technology, Germany. @@ -25,7 +25,7 @@ The first version of OVITO was released in December 2009 and its initial feature set was described in a journal article about OVITO in 2010. - Today OVITO has more than active 50,000 users from the computational physics, materials science, and chemistry fields. + Today OVITO has more than active 100,000 users from the computational physics, materials science, and chemistry fields. @@ -38,7 +38,7 @@ Input and output of various file formats used by - MD simulation codes, including LAMMPS, XYZ, CFG, IMD, POSCAR, NetCDF, PDB, FHI-aims, and GSD/HOOMD. + MD simulation codes, including LAMMPS, XYZ, CFG, IMD, POSCAR, NetCDF, PDB, FHI-aims, CASTEP, and GSD/HOOMD. @@ -125,6 +125,10 @@ + Spatial correlation function + + + Automated dislocation line identification (DXA) @@ -135,6 +139,10 @@ Atomic strain tensor calculation + + + Local elastic strain calculation + Histogram and scatter plot functions @@ -144,11 +152,11 @@ Reconstruction of geometric surfaces from atomistic models - + Voronoi cell analysis - + Identification of point defects using Wigner-Seitz cell method diff -Nru ovito-2.8.1+dfsg2/doc/manual/Chapter_Reference.docbook ovito-2.9.0+dfsg1/doc/manual/Chapter_Reference.docbook --- ovito-2.8.1+dfsg2/doc/manual/Chapter_Reference.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/Chapter_Reference.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -25,6 +25,7 @@ +
Renderering diff -Nru ovito-2.8.1+dfsg2/doc/manual/development/build_linux.docbook ovito-2.9.0+dfsg1/doc/manual/development/build_linux.docbook --- ovito-2.8.1+dfsg2/doc/manual/development/build_linux.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/development/build_linux.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -17,20 +17,58 @@ Installing dependencies - First install the required build tools and third-party libraries - by running + First install the required build tools and third-party libraries: + + + + + Distribution + Command + + + + + Ubuntu + sudo apt-get install build-essential git cmake-curses-gui qt5-default libboost-dev libqt5scintilla2-dev \ libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev libavresample-dev \ libavutil-dev libswscale-dev libnetcdf-dev libhdf5-dev libhdf5-serial-dev \ libbotan1.10-dev libmuparser-dev libqwt-qt5-dev python3-dev \ python3-sphinx python3-numpy python3-matplotlib python3-pyqt5 \ - xsltproc docbook-xml + libfftw3-dev xsltproc docbook-xml + + + + openSUSE + +sudo zypper install git docbook_5 libxslt-tools cmake gcc-c++ \ + libQt5Concurrent-devel libQt5Core-devel libQt5Gui-devel libQt5Network-devel libQt5DBus-devel \ + libQt5OpenGL-devel libQt5PrintSupport-devel libQt5Widgets-devel libQt5Xml-devel \ + libavutil-devel libavresample-devel libavfilter-devel libavcodec-devel libavdevice-devel \ + netcdf-devel libbotan-devel muparser-devel python3-devel python3-numpy python3-matplotlib \ + python3-Sphinx python3-qt5 boost-devel hdf5-devel libswscale-devel libqscintilla-qt5-devel \ + fftw3-devel + + + + + centOS + + sudo yum install epel-release + sudo yum install git gcc gcc-c++ cmake qt5-qtbase-devel qt5-qtsvg-devel qt5-qttools-devel \ + muParser-devel boost-devel netcdf-devel hdf5-devel botan-devel + These packages allow building only a basic version of OVITO without Python scripting and video encoding support and documentation. + In order to build a more complete version, other dependencies must be installed manually. + + + + - Downloading the source code + Getting the source code Then download OVITO's source code into a new subdirectory named ovito/: git clone https://gitlab.com/stuko/ovito.git ovito @@ -47,6 +85,7 @@ cd build cmake -DOVITO_BUILD_DOCUMENTATION=ON \ -DCMAKE_BUILD_TYPE=Release \ + -DPYTHON_EXECUTABLE=/usr/bin/python3 \ -DPYTHON_INCLUDE_DIR=/usr/include/python3.5m \ -DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython3.5m.so \ .. @@ -55,8 +94,8 @@ If this step fails, or if you want to disable certain components of OVITO, you can now run "ccmake ." to open the CMake configuration program. - Changin the PYTHON_INCLUDE_DIR and PYTHON_LIBRARY settings may be needed to - build OVITO against a different Python version. + Changing the PYTHON_INCLUDE_DIR and PYTHON_LIBRARY settings may be needed to + build OVITO against a different Python version. Finally, compile OVITO: @@ -67,3 +106,4 @@
+ diff -Nru ovito-2.8.1+dfsg2/doc/manual/development/build_windows.docbook ovito-2.9.0+dfsg1/doc/manual/development/build_windows.docbook --- ovito-2.8.1+dfsg2/doc/manual/development/build_windows.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/development/build_windows.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -28,7 +28,7 @@ To download OVITO's source code into a new subdirectory named ovito, install Git and run: git clone https://gitlab.com/stuko/ovito.git ovito - from the command line or go to https://sourceforge.net/p/ovito/git/ci/master/tree/ + from the command line or go to https://gitlab.com/stuko/ovito
diff -Nru ovito-2.8.1+dfsg2/doc/manual/development/Chapter_Development.docbook ovito-2.9.0+dfsg1/doc/manual/development/Chapter_Development.docbook --- ovito-2.8.1+dfsg2/doc/manual/development/Chapter_Development.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/development/Chapter_Development.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -54,7 +54,7 @@ LibraryRequirementNotes Qt5required - Used for OVITO's graphical user interface (version 5.2 or newer) + Used for OVITO's graphical user interface (version 5.4 or newer) zlibrequired Required for reading and writing compressed files. Boostrequired @@ -65,6 +65,8 @@ Audio and video processing libraries used by OVITO to write movie files. libnetcdfoptional Required by the NetCDF plugin to read NetCDF files + FFTWoptional + Required to build the Correlation Function plugin. QScintilla2optional Text editing widget required by the PyScript plugin. muparserincluded diff -Nru ovito-2.8.1+dfsg2/doc/manual/html-customization-layer.xsl ovito-2.9.0+dfsg1/doc/manual/html-customization-layer.xsl --- ovito-2.8.1+dfsg2/doc/manual/html-customization-layer.xsl 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/html-customization-layer.xsl 2017-07-27 16:52:45.000000000 +0000 @@ -179,7 +179,7 @@ - + Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/display_objects/surface_mesh_panel.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/display_objects/surface_mesh_panel.png differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/affine_transformation_panel.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/affine_transformation_panel.png differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/cluster_analysis_panel.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/cluster_analysis_panel.png differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/color_coding_panel.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/color_coding_panel.png differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/coordination_polyhedra_example.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/coordination_polyhedra_example.png differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/correlation_function_panel.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/correlation_function_panel.png differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/create_isosurface_example.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/create_isosurface_example.png differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/create_isosurface_panel.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/create_isosurface_panel.png differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/displacement_vectors_mapping.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/displacement_vectors_mapping.png differ diff -Nru ovito-2.8.1+dfsg2/doc/manual/images/modifiers/displacement_vectors_mapping.svg ovito-2.9.0+dfsg1/doc/manual/images/modifiers/displacement_vectors_mapping.svg --- ovito-2.8.1+dfsg2/doc/manual/images/modifiers/displacement_vectors_mapping.svg 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/images/modifiers/displacement_vectors_mapping.svg 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,525 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + Reference configuration + Currentconfiguration + Computeddisplacement + Setting"Assume unwrapped" + "Off" + "On" + + + + + + + + + + + + + + + Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/displacement_vectors_panel.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/displacement_vectors_panel.png differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/displacement_vectors_unwrapped.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/displacement_vectors_unwrapped.png differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/histogram_panel.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/histogram_panel.png differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/voronoi_analysis_panel.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/voronoi_analysis_panel.png differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/vorotop_analyis_panel.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/vorotop_analyis_panel.png differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/wigner_seitz_analysis_panel.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/wigner_seitz_analysis_panel.png differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/wigner_seitz_method.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/wigner_seitz_method.png differ diff -Nru ovito-2.8.1+dfsg2/doc/manual/images/modifiers/wigner_seitz_method.svg ovito-2.9.0+dfsg1/doc/manual/images/modifiers/wigner_seitz_method.svg --- ovito-2.8.1+dfsg2/doc/manual/images/modifiers/wigner_seitz_method.svg 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/images/modifiers/wigner_seitz_method.svg 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,2496 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 2 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + Reference configuration + Displacedconfiguration + Binning of atoms in cells + Computedoccupancy numbers + + + + + + + + + + + + Displaced config + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Reference config + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + 2 + + 1 + + 1 + 1 + 0 + 1 + 1 + 1 + 1 + Occupancy property + + WS analysis modifier + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + 2 + + 1 + + 1 + 1 + 0 + 1 + 1 + 1 + 1 + Particle selection + + Expression Selectmodifier:"Occupancy==1" + + + + + + + + + + + + + + + + + + + + + + + 2 + 0 + Point defects + + Delete SelectedParticles modifier + + Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/modifiers/wigner_seitz_pipeline_example.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/modifiers/wigner_seitz_pipeline_example.png differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/doc/manual/images/utilities/particle_inspection_panel.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/doc/manual/images/utilities/particle_inspection_panel.png differ diff -Nru ovito-2.8.1+dfsg2/doc/manual/Manual.docbook ovito-2.9.0+dfsg1/doc/manual/Manual.docbook --- ovito-2.8.1+dfsg2/doc/manual/Manual.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/Manual.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -11,7 +11,7 @@ OVITO User Manual - 2013-2016 + 2017 Alexander Stukowski diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/display_objects/surface_mesh.docbook ovito-2.9.0+dfsg1/doc/manual/reference/display_objects/surface_mesh.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/display_objects/surface_mesh.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/display_objects/surface_mesh.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -11,13 +11,21 @@ Surface mesh display - - + - This display object is responsible for rendering the polyhedral mesh that is - produced by a Construct surface mesh modifier. + This display object controls the rendering of triangulated surface meshes (two-dimensional manifolds) + as produced by, for example, the Construct surface mesh, + Create isosurface, + or Dislocation analysis modifiers. + + + + Surfaces meshes in OVITO typically represent closed two-dimensional manifolds that may be periodic + if periodic boundary conditions are active. For visualization purposes, a periodic mesh is first converted to a non-periodic + representation by cutting it at the simulation cell boundaries. OVITO can generate so called + 'cap polygons' to fill the holes that occur at the intersection of the closed surface with the periodic boundary. @@ -27,7 +35,7 @@ Surface color - The rendering color of the surface. + The rendering color for the surface. @@ -46,8 +54,8 @@ Cap polygons - OVITO computes the intersection of the surface with the periodic boundaries of the simulation cell. - Cap polygons are created to close the cut mesh again. This option enables or disables the display of the cap polygons. + This option enables the display of the cap polygons at the intersection of a closed surface + with periodic boundaries. diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/modifiers.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/modifiers.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/modifiers.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/modifiers.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -49,6 +49,10 @@ Constructs a polyhedral mesh representing the surface of an atomistic solid. + Correlation function + Calculates the spatial cross-correlation function between two particle properties. + + Dislocation analysis (DXA) Detects dislocation lines in a crystal. @@ -97,6 +101,10 @@ Computes the coordination number, atomic volume, and Voronoi index of particles from their Voronoi polyhedra. + VoroTop analysis + Identifies local structure of particles using the topology of their Voronoi polyhedra. + + Wigner-Seitz defect analysis Identifies point defects (vacancies and interstitials) in a crystal lattice. @@ -118,6 +126,15 @@ Colors particles or bonds based on a property. + + + Fields + + + Create isosurface + Constructs isosurfaces from scalar field data. + + Modification @@ -143,6 +160,10 @@ Computes a new property for each particle based a user-defined formula. + Coordination polyhedra + Shows coordination polyhedra + + Delete selected particles Deletes all selected particles. @@ -236,8 +257,14 @@ + + + + + + @@ -276,6 +303,8 @@ + + diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/affine_transformation.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/affine_transformation.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/affine_transformation.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/affine_transformation.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -12,16 +12,16 @@ - + - Applies an affine transformation to the particle positions and/or - the simulation cell. The transformation is either specified as a 3x3 - matrix and an additional translation vector or by prescribing a - target simulation cell to which the particles are mapped. + Applies an affine transformation to the dataset. This can be used to translate, scale, rotate, or shear + the particles, the simulation cell, and/or surface meshes. + The transformation can either be specified directly as a 3 x 3 + matrix plus a translation vector, or by prescribing a target simulation cell to which the old cell and its content are mapped. - Given the 3x3 transformation matrix M + Given the 3 x 3 linear transformation matrix M and the translation vector t, the new position x' of a particle at the old position x @@ -31,8 +31,8 @@ - The Enter rotation button opens a utility that lets you enter a rotation - axis and an angle. It computes the corresponding transformation matrix for you. + The Enter rotation button opens a dialog box that lets you enter an + axis and a rotation angle. OVITO computes the corresponding transformation matrix for you. @@ -43,35 +43,44 @@ Transform simulation cell - Selects whether the transformation is applied to the simulation cell. + Controls whether the simulation cell is transformed. - Transform particles + Transform particle positions - Selects whether the transformation is applied to the - particle coordinates. You can select which particles are affected by the - modifier: All particles or only the selected ones. + Controls whether the transformation is applied to the + particle coordinates. You can select which particles should be affected by the + modifier: All particles or only the currently selected ones. - Transform surface mesh + Transform vector properties - Selects whether the transformation is applied to the surface mesh (if one exists). - Surface meshes are typically created with the Construct surface mesh modifier. + Controls whether certain vectorial properties of particles are transformed too. + If selected, the values of the following vector properties will be transformed by the linear part of the transformation: + Velocity, Force, Displacement. + + + Transform surface mesh + + Controls whether the transformation is applied to the surface mesh (if one exists). + Surface meshes are typically created by the Construct surface mesh modifier. + + Transformation matrix - Rotate/Scale/Shear - The 3x3 matrix specifying the affine transformation. + The 3x3 matrix specifying the linear part of the affine transformation. @@ -79,7 +88,7 @@ Transformation matrix - Translation - The translation that is added after multiplying a particle position with the matrix. + The translation that is added after multiplying positions with the linear transformation matrix. @@ -87,9 +96,9 @@ Transform to target box - The three vectors that define the target simulation cell. The - modifier will automatically calculate the transformation matrix based on this target cell shape and - the input simulation cell. + Three vectors defining the target simulation cell. The + modifier will dynamically calculate the transformation based on this target cell shape and + the current input simulation cell. diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/cluster_analysis.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/cluster_analysis.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/cluster_analysis.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/cluster_analysis.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -41,23 +41,29 @@ - This modifier decomposes a particle system into disconnected sets of particles (clusters) based on a distance criterion. + This modifier decomposes a particle system into disconnected sets of particles (clusters) based on a local neighboring criterion. + The neighboring criterion can either be based on the distance between particles (i.e. a cutoff) or on the bond topology. - A cluster is defined as a set of connected particles, each of which is within the cutoff distance of one or more + A cluster is defined as a set of connected particles, each of which is within the range of one or more other particles from the same cluster. Thus, any two particles from the same cluster are connected by a - continuous path consisting only of steps which are shorter than the given cutoff distance. + continuous path consisting only of steps fulfilling the selected neighboring criterion. Conversely, two particles will not belong to the same cluster if there is no continuous path on the neighbor network leading from one particle to the other. - If a particle possesses no neighbors within the cutoff distance, then it will form a 1-particle cluster. + You can choose between the distance-based neighbor criterion, in which case two particles are considered + neighbors if they are within a specified range of each other, or the bond-based criterion, in which case + two particles are considered neighbors if they are connected by a bond. + + + Note that a particle which possesses no neighbors forms a 1-particle cluster. The modifier outputs its results to the Cluster particle property, which stores the - cluster each particle has been assigned to. Cluster IDs range from 1 to N, where N + cluster each particle has been assigned to. Cluster IDs generated by the modifier range from 1 to N, where N is the number of clusters found by the modifier. @@ -65,9 +71,16 @@ Parameters + Neighbor mode + + Selects the criterion which is used to determine whether two particles are neighbors or not. + + + + Cutoff distance - The distance threshold up to which two particles are considered direct neighbors and assigned to the same cluster. + The range up to which two particles are considered neighbors when the distance-based criterion is selected. @@ -119,28 +132,28 @@ Computing and exporting the size of each cluster (i.e. the number of particles) requires a simple Python script. The following example script can be executed using the ScriptingRun Script File menu function after manually applying the Cluster Analysis modifier: - from ovito import * + import ovito import numpy output_filepath = "cluster_sizes.txt" -output = dataset.selected_node.compute() +output = ovito.dataset.selected_node.compute() cluster_sizes = numpy.bincount(output.particle_properties['Cluster'].array) numpy.savetxt(output_filepath, cluster_sizes) - Please copy/paste the above script to a text editor and save it as .py file. Don't forget to adjust the output file path as needed. The script makes use + Please copy/paste the above script to a text editor and save it as .py file. Don't forget to adjust the output file path as needed. The script makes use of the bincount() Numpy function to count the number of particles belonging to each cluster. Note that the array returned by this function includes cluster ID 0, which is not assigned by the modifier and therefore typically has size zero. For more information on OVITO's scripting interface, see this page. It is possible to perform the file export for every frame in a simulation sequence by adding a for-loop to the script: -from ovito import * +import ovito import numpy -for frame in range(dataset.anim.last_frame + 1): +for frame in range(ovito.dataset.anim.last_frame + 1): output_filepath = "cluster_sizes.%i.txt" % frame - output = dataset.selected_node.compute(frame) + output = ovito.dataset.selected_node.compute(frame) cluster_sizes = numpy.bincount(output.particle_properties['Cluster'].array) numpy.savetxt(output_filepath, cluster_sizes) diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/color_coding.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/color_coding.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/color_coding.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/color_coding.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -12,25 +12,27 @@ - + - This modifier colors particles, bonds, or vector arrows based on one of their properties. It can be used to visualize - per-particle or per-bond scalar quantities. + This modifier assigns colors to particles, bonds, or arrows based on one of their properties. + It thus provides a simple method to visualize scalar per-particle or per-bond quantities. - The input property values are first mapped and clamped to the unit interval [0,1] according to the + The values of the selected input property are first mapped and clamped to the unit interval [0,1] according to the Start value and End value - parameters of the modifier. The normalized values are then mapped to a corresponding color using the selected - color gradient map and assigned to the particles or bonds. + parameters of the modifier. The normalized values are then mapped to a color using the selected + color gradient map and finally assigned to the particles or bonds. The Adjust range button resets the Start value and - End value parameters to the minimum and maximum values - of the selected input property. This ensures that no clamping occurs - when values are mapped to a color. The Reverse range button + End value parameters to the minimum and maximum value + of the selected input property, respectively. This ensures that no clamping occurs when property values are mapped to colors. + The Adjust range (all frames) button does the same but considers every frame + of the animation sequence when determining the range of values, not just the currently loaded frame. + The Reverse range button swaps the Start value and End value parameters to effectively reverse the color scale. @@ -77,29 +79,29 @@ Property - The input particle or bond property to be used for color mapping. + The input particle property or bond property to be used for color mapping. Color gradient - The type of color map to use. + Selects the color gradient for mapping scalar values to colors. Start & end value - Controls the source range for the linear mapping of property values to the [0,1] unit interval. + Controls the value range for the linear mapping of input values to the [0,1] interval. Color only selected particles/bonds - This option restricts the assignment of colors to selected particles or bonds. - The existing colors of unselected particles or bonds will be preserved. + This option restricts the assignment of colors to currently selected particles or bonds. + The colors of unselected particles or bonds will remain unchanged. @@ -107,9 +109,9 @@ Keep selection OVITO uses a red color by default to highlight selected particles in the interactive viewports. - Since this highlighting would mask the actual color assigned by this + Since this highlighting would mask the actual colors assigned by this modifier, the modifier clears the current selection by default. - If you need to preserve the current selection for further use down the pipeline, activate this option. + If you want to preserve the selection, because you want to use it further down the data pipeline, activate this option. diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/combine_particle_sets.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/combine_particle_sets.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/combine_particle_sets.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/combine_particle_sets.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -33,8 +33,8 @@ - The IDs of particles loaded from the second file are overwritten by the modifier to make sure they - do not conflict with any of the IDs in the current dataset. + The IDs of particles loaded from the second file are newly assigned by the modifier to ensure that they + do not conflict with the existing particle IDs in the current dataset. diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/compute_property.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/compute_property.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/compute_property.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/compute_property.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -88,11 +88,11 @@ - The first term, F(i), is the first user-defined function, which is evaluated once for the central particle. - The second term consists of contributions from all neighbors within the cutoff radius Rc. Each contribution is determined by a second user-defined - function, G(j), which is evaluated for every neighbor particle j. The function G(j) - must be entered into the input field Neighbor expression, and it may only depend on properties - of the current neighbor and on global parameters. In addition it may depend on the distance of the neighbor from the central particle. + The first term, F(i), is the first user-defined function, which gets evaluated once for the central particle. + The second term consists of contributions from all neighbors within the cutoff radius Rc. The contributions are given by a second + function, G(j), which is evaluated for every neighbor particle j. The user-defined function G(j) + is entered into the input field Neighbor expression, and it may only depend on properties + of the current neighbor, its distance from the central particle, and on global parameters. This allows you to perform advanced computions that take into account the local neighborhood of particles. For example, we can diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/coordination_analysis.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/coordination_analysis.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/coordination_analysis.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/coordination_analysis.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -23,14 +23,15 @@ In addition, the modifier also computes the radial pair distribution function (RDF) of the particle system. - The pair distribution function is normalized by the number density of particles (i.e. total number of - particles divided by the simulation cell volume). + The RDF g(r) measures the probability of finding a particle at distance r given that there is a particle at position 0; + it is essentially a histogram of inter-particle distances. The pair distribution function is normalized by the number + density of particles (i.e. total number of particles divided by the simulation cell volume). - The current program version cannot compute partial pair distribution functions, which take into account - the type of particles. If this is a program feature you are interested in, please let the developer - of OVITO know. + The current version of the modifier can only calculate the global RDF ignoring the types + of particles. As explained in this forum post, you can also compute the partial RDFs for a system + containing more than one particle species using a different approach. diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/coordination_polyhedra.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/coordination_polyhedra.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/coordination_polyhedra.docbook 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/coordination_polyhedra.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,30 @@ + +
+ Coordination polyhedra + + + + + + This modifier creates coordination polyhedra around selected atoms/particles for visualization purposes. + A coordination polyhedron is the convex hull spanned by the bonded neighbors of a central particle. + + + Note: The modifier creates coordination polyhedra only for currently selected particles. So you should select some + particles first, e.g. using the Select particle type modifier. + + + The modifier requires bonds to determine the neighbors of a particles. Thus, you should create + some bonds first using the Create bonds modifier + (unless they are already provided in the input file). + + +
diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/correlation_function.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/correlation_function.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/correlation_function.docbook 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/correlation_function.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,98 @@ + +
+ Correlation function + + + + + + + + This modifier calculates the spatial correlation function between two particle properties. + + OVITO uses the FFT to compute the convolution. It then computes a radial average in reciprocal and real space. This gives the correlation function up to half of the cell size. The modifier can additionally compute the short-ranged part of the correlation function from a direct summation over neighbors. + + For example, when both particle properties are constant and unity, the modifier returns the pair correlation function. The reciprocal space representation is then the structure factor. + + + Parameters + + + + First property + + First particle property for which to compute the correlation, P1. + + + + + Second property + + Second particle property for which to compute the correlation, P2. If both particle properties are identical, the modifier computes the autocorrelation. + + + + + FFT grid spacing + + This property sets the approximate size of the FFT grid cell. The actual size is determined by the distance of the cell faces which must contain an integer number of grid cells. + + + + + Apply window function to nonperiodic directions + + This property controls whether nonperiodic direction have a Hann window applied to them. Applying a window function is necessary to remove spurios oscillations and power-law scaling of the (implicit) rectangular window of the nonperiodic domain. + + + + + Direct summation + + If enabled, the real-space correlation plot will show the result of a direct calculation of the correlation function, obtaining by summing over neighbors. This short-ranged part of the correlation function is displayed as a red line. + + + + + Neighbor cutoff radius + + This property determines the cutoff of the direct calculation of the real-space correlation function. + + + + + Number of neighbor bins + + This property sets the number of bins for the direct calculation of the real-space correlation function. + + + + + Normalize correlation function + + If set to "by covariance" for the real-space correlation, the correlation function is normalized to approach unity at small distances and zero at large distances, i.e. the plot shows (C(r)-〈P1〉〈P2〉)/(〈P1P2〉-〈P1〉〈P2〉) rather than the unnormalized C(r). + If set to "by RDF" for the real-space correlation, the correlation function is divided by the radial distribution function. + If activated for the reciprocal-space correlation function, the plot shows C(q)/〈P1P2 rather than the unnormalized C(q). + + + + + + + + + Acknowledgment + + This modifier has been contributed by Lars Pastewka. + + + +
diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/create_isosurface.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/create_isosurface.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/create_isosurface.docbook 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/create_isosurface.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,47 @@ + +
+ Create isosurface + + + + + + + + + + + + + Example: Two isosurfaces of charge density: + + + + + + + + + + + + + + This modifier computes an isosurface for a field quantity defined on a structured data grid. + Note that the modifier is available only if a field quantity has been loaded. In the current program version, + the only file parser that provides such data is the POSCAR reader, which can load charge densities + computed by the VASP DFT code from CHGCAR files. + + + Note: The modifier may be applied several times to create multiple surfaces at different iso-levels. + + +
diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/displacement_vectors.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/displacement_vectors.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/displacement_vectors.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/displacement_vectors.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -57,31 +57,50 @@ - Eliminate homogeneous cell deformation + Affine mapping - This option lets the modifier first rescale the current - simulation cell including all particle coordinates to match the - cell shape in the reference configuration before calculating the displacement vectors. - This effectively eliminates any macroscopic, homogeneous deformation of the simulation cell, and the - calculated vectors will reflect only the internal, microscopic displacements of particles. + This option applies an affine transformation to the simulation cell and all particle positions prior + to calculating the displacement vectors. This can be used to effectively eliminate contributions to the displacements from the macroscopic deformation + of the simulation cell and retain only the internal (non-affine) motion of the particles. + + + The following table shows the effect of the mapping option on the calculated displacement vector of a particle. When mapping is turned off (first row), + the vector is simply calculated from the new and old absolute particle positions irrespective of the changing cell shape. + The second option, "To reference", applies an affine transformation to the particle positions of the deformed configuration such that + they are first mapped to the reference cell before calculating the displacement vectors. Note that this transformation + is applied only virtually during the displacement vector calculation. + The last option, "To current", does the opposite of the second option: it maps the reference particle positions + to the deformed cell before calculating the displacements. + + + + + Note: The "To reference" setting corresponds to the eliminate homogeneous cell deformation option + found in older program versions. + Assume unwrapped coordinates - This only affects the treatment of simulation cells with - periodic boundary conditions. If activated, the particle coordinates - in the reference and the current configuration are taken as is. If - this option is not checked, the minimum image convention is used to - deal with particles that have crossed a periodic boundary. + This option only affects simulations cells with periodic boundary conditions. If activated, the particle coordinates + in the reference and the current configuration are always taken as is and the displacement vectors are directly calculated + from the coordinate differences, even for particles that crossed a periodic boundary. + If this option is not checked, which is the default, the minimum image convention is used to deal with particles that have + crossed a periodic boundary as indicated in the figure below. + + + + Note: For directions without periodic boundary conditions, assume unwrapped coordinates is the standard behavior. + - Fixed reference configuration + Constant reference configuration - If this option is active, the selected animation frame from the reference simulation sequence is used + If this option is active, the specified animation frame from the reference simulation sequence is used as a fixed reference to calculate the displacement vectors. This is the default mode. @@ -89,9 +108,9 @@ Relative to current frame - If this option is active, then a changing reference configuration is used to calculate the displacement vectors. + If this option is active, then a varying reference configuration is used to calculate the displacement vectors. This allows computing incremental displacement vectors (similar to discrete velocity vectors). - The frame offset controls the distance between reference and current frame and can be negative or positive. If it is negative, then the reference frame + The frame offset paremeter controls the temporal distance between reference and current frame and can be negative or positive. If it is negative, then the reference frame precedes the current frame in the simulation sequence. Note that the displacement vectors will not be computed for simulation frames for which the resulting reference frame is negative or out of range. diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/expression_select.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/expression_select.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/expression_select.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/expression_select.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -17,7 +17,7 @@ This modifier allows you to select particles based on a user-defined criterion. - You enter an arbitrary complex Boolean expression, which is evaluated by the modifier for every particle + You enter an Boolean expression, which is evaluated by the modifier for every particle in the system. Those particles for which the expression yields a non-zero value ("true") will be selected; all other particles, for which the expression evaluates to zero ("false"), are deselected. diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/histogram.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/histogram.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/histogram.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/histogram.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -16,22 +16,30 @@ - This modifier computes and displays a histogram of a particle property. + This modifier computes a histogram of the values of a particle or bond property.
- Optionally, the modifier can be used to select particles whose property value - is within a certain interval. + Additionally, the modifier allows to select all particles or bonds whose property values + lie within a certain interval. Parameters + + + Input + + Selects whether input property values should be taken from particles or bonds. + + + Property - The particle property the histogram should be computed for. + The particle or bond property the histogram should be computed for. @@ -43,17 +51,16 @@ - Use only selected particles + Use only selected particles/bonds - Restricts the histogram calculation to the subset of particles that are currently selected. + Restricts the histogram calculation to the subset of particles or bonds that are currently selected. - Select particles in range + Select value range - If this option is active, the modifier selects all particles whose property value falls - into the specified range. + Lets the modifier select all particles or bonds whose property value lies in the specified range. diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/load_trajectory.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/load_trajectory.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/load_trajectory.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/load_trajectory.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -16,14 +16,15 @@ - This modifier is used to load time-dependent atomic positions from a separate molecular dynamics trajectory file. + This modifier loads time-dependent atomic positions and other properties from a separate molecular dynamics trajectory file + and combines them with static topology data (e.g. bonds and atom type information) from another file. Some MD codes work with separate topology and a trajectory files. The former contain the initial atomic positions and other definitions like atom types, bonds, etc. - which are constant throughout the simulation and which are read in by the MD simulation code. + which are constant throughout the simulation and which are read in by the MD code at the beginning of the simulation. The MD code writes the computed trajectories to a separate file containing just the time-dependent - coordinates (but no other static information like the bonds). + coordinates and perhaps other varying properties like atomic energies (but no static information like the bonds). One typical example is the code LAMMPS, which relies on the data input file format @@ -32,10 +33,11 @@ - To load such a pair of topology/trajectory files in OVITO, first import the topology file. - Then apply the Load Trajectory modifier to the loaded dataset and select the trajectory file on disk. The modifier - will replace the initial atomic positions loaded from the topology file with the time-dependent positions - loaded from the trajectory file. The same is done for the simulation cell geometry. + To load such a pair of topology/trajectory files in OVITO, first import the topology file as usual. + Then apply the Load Trajectory modifier to the dataset and select the corresponding trajectory file. The modifier + will replace the initial atomic positions from the topology file with the time-dependent positions + loaded from the trajectory file. The same is done for the simulation cell geometry and also any other particle property + that is present in the trajectory file. @@ -46,4 +48,12 @@ of the simulation box size. + + If particles in the topology and the trajectory file possess IDs, then the modifier + uses them to determine the correct one-to-one mapping when the storage order of particles + changes during the course of a simulation. If no particle IDs are available, + then the modifier assumes that the storage order of particles in the topology and the trajectory file + is the same. + + diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/polyhedral_template_matching.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/polyhedral_template_matching.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/polyhedral_template_matching.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/polyhedral_template_matching.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -18,10 +18,10 @@ This modifier classifies the local structural environment of particles using the Polyhedral Template Matching (PTM) method [P.M. Larsen et al., Modelling Simul. Mater. Sci. Eng. 24, 055007] + xlink:href="https://dx.doi.org/10.1088/0965-0393/24/5/055007">P.M. Larsen et al., Modelling Simul. Mater. Sci. Eng. 24, 055007] (preprint available) and allows identifying the local crystalline structure of simple condensed phases (FCC, BCC, etc.) formed by atoms. - + The PTM approach promises greater reliability than e.g. Common Neighbor Analysis (CNA) in the @@ -104,9 +104,9 @@ Local lattice orientation The PTM modifier can calculate the local lattice orientation for atoms that match one of the structural types. The computed orientation is stored - as a quaternion in the Orientation particle property. + as a quaternion in the Orientation particle property. You can switch the particle display shape to Cube/Box to visualize the computed - per-particle orientations. + per-particle orientations or apply this custom Python modifier to color particles according to their local lattice orientation. Lattice orientations are calculated such that they lie in the fundamental zone of the symmetry group for each structural type. This means that two atoms with very similar orientations can have large misorientations if they lie close to the boundaries of the fundamental zone. For atoms that do not match any of the known structure types, no local lattice orientation can be computed. They are assigned the diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/voronoi_analysis.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/voronoi_analysis.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/voronoi_analysis.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/voronoi_analysis.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -18,50 +18,87 @@ This analysis modifier calculates the Voronoi tessellation of the simulation box, taking the particle positions as Voronoi cell centers. By default two quantities are output by the analysis modifier for each particle: - The volume of the particle's Voronoi cell and the number of faces the Voronoi cell has. Since the face count - is equal to the number of nearest neighbors of the particle, this quantity is also called the coordination number. + The volume of the particle's Voronoi cell and the number of faces the Voronoi cell has. Since the face count + is equal to the number of nearest neighbors of a particle, this quantity is also called the coordination number. + The modifier outputs both quantities as new particle properties, which allows them to be referenced in subsequent + analysis or filtering steps. + + Voronoi indices + - In addition the modifier can compute the Voronoi index of each cell, + In addition to these basic quantities, the modifier can compute the index of each Voronoi cell, which is a vector of integers constituting a histogram of the number of edges on the faces of the Voronoi cell. - This index vector can be considered a characteristic signature of a particle's coordination structure. + This index vector can be considered a characteristic signature of a particle's coordination structure and the topology of the Voronoi polyhedron. For instance, an icosahedral coordination structure corresponds to the Voronoi index vector (0,0,0,0,12,0,...). - In other words, these indices describe a polyhdron with exactly 12 faces with 5 edges each. - To select all atoms having this kind of icosahedral coordination structure we can use the + In other words, this index vector denotes a polyhdron with exactly 12 faces with 5 edges each. + To select all atoms having this kind of icosahedral coordination structure, we can use the Expression select modifier with the Boolean expression: VoronoiIndex.3==0 && VoronoiIndex.4==0 && VoronoiIndex.5==12 && VoronoiIndex.6==0 - (VoronoiIndex.1 and VoronoiIndex.2 are always zero because faces with less than three edges do not exist.) + Note that we don't need to include the first two indices in the selection expression, since faces with less than three edges + do not exist. + + + Due to limitation in OVITO's data model, which can only store per-particle Voronoi index vectors of uniform length, + the vectors are truncated at a certain maximum face order, which is given by the maximum edge count + parameter. Faces with more edges will be ignored and don't show up in the truncated index vector. + OVITO warns if it encounters any such higher order faces and will recommend to increase the vector length to avoid truncation. + - - If you are interested in the Voronoi indices computed by the analysis modifier for a particular atom, you can use the - Particle Inspection utility to select the atom - in the viewports and display its properties (including the assigned Voronoi indices). - + + How to analyze the computation results - If you want to know what is the Voronoi index vector that occurs most frequently in your atomistic system, - you can perform a statistical analysis of the computed Voronoi indices using a custom Python script. + If you are interested in the indices computed by the modifier for a particular particle, you can use OVITO's + Particle Inspection utility to select the particle + in the viewports. It lists all properties of the particle, including the computed Voronoi indices. + If you would like to perform a statistical analysis of the Voronoi polyhedra, e.g. to determine the Voronoi index vector that + occurs most frequently in your system, then you can use OVITO's Python scripting interface to access the computed per-particle indices. You can find an example script in the OVITO scripting manual. + + Note: Currently, OVITO doesn't provide an option to visualize the Voronoi cells. If this is something + you would like to do for illustrative purposes, you have to use other tools. + + + + + Face area and edge length thresholds + + + Voronoi polyhedra are known to be unstable with regard to small pertubations of the particle positions in + many cases. To address this issue, at least partially, the modifier provides threshold parameters for the + area of Voronoi faces and the length of face edges to filter out very small, + almost degenerate faces and edges. + + + If an edge of a Voronoi face is shorter than the specified edge length threshold, then this edge is not counted toward + the order of the Voronoi face. Furthermore, if the face's area is below the area threshold, then the face is + not included in the computed Voronoi index and it also not counted toward the coordination number of the central particle. + The threshold face area can either be specified as an absolute value or relative to the total surface area of the Voronoi polyhedron. + The purpose of these thresholds is to exclude very small faces/edges, which occur sporadically + in the presence of pertubations, from the analysis and the counting. Also see this paper on the topic. + + - Potential issues in non-periodic domains + Potential issues with non-periodic boundaries - Note that the modifier calculates the Voronoi tessellation of the volume enclosed by the simulation cell only (and not - entire space). Thus, Voronoi cells will be truncated at the simulation box boundaries (unless periodic boundary conditions are used). - No computation will be performed for particles located outside the (non-periodic) simulation box boundaries - (but they will still be taken into account when calculating the Voronoi cells of particles inside the box). + The algorithm calculates the Voronoi tessellation of the finite volume enclosed by the simulation cell (not + infinite space!). Thus, Voronoi cells get truncated at the simulation box boundaries (unless periodic boundary conditions are active). + Accordingly, no computation will be performed for particles located outside the finite simulation box + (but they still affect the Voronoi cells of particles inside the box). - Particles that are located exactly on the simulation box boundaries (along non-periodic directions) also pose a problem. - The Voronoi cell of such particles is singular and the analysis may stop with the error message "Could not compute Voronoi cell for some particles". - The solution to this problem is to increase the size of the simulation box to fully include all particles. - This can be archieved, for example, by applying the Affine Transformation modifier to scale the box size. + Particles located exactly on the simulation box boundaries (in a non-periodic direction) pose a problem. + The Voronoi cell of such particles is singular and the construction algorithm may stop with the error message "Could not compute Voronoi cell for some particles". + The solution to this type of problem is to slightly enlarge the simulation box to fully include all particles. + This can be done, for example, by using the Affine Transformation modifier to scale the box size by a factor greater than 1. @@ -72,11 +109,26 @@ - Face area threshold + Absolute face area threshold + + + Specifies a minimum area for the individual faces of a Voronoi cell. The modifier will ignore any Voronoi cell face whose area is smaller than this + threshold area when computing the coordination number and the Voronoi index of a particle. + The threshold is an absolute value in units of length squared (in whatever units of length your input data is given). + + + + + + Relative face area threshold - Specifies a minimum area for faces of a Voronoi cell. The modifier will ignore any Voronoi cell faces with an area smaller than this - threshold when computing the coordination number and the Voronoi index of particles. + Specifies a minimum area for the individual faces of a Voronoi cell in terms of a fraction of the total surface area of a Voronoi polyhedron. + The modifier will ignore any Voronoi cell face whose area is smaller than this + threshold when computing the coordination number and the Voronoi index of a particle. + The relative threshold is specified as a fraction of the total surface area of the Voronoi polyhedron the faces belong to. + For example, you can use this threshold to exclude those faces from the analysis with an area less than 1% of the total area of the polyhedron surface, + like it was done in this paper. @@ -85,10 +137,10 @@ Compute Voronoi indices - Lets the modifier calculate the Voronoi indices of particles. The modifier stores the computed indices in a vector particle property - named Voronoi Index. The i-th component of this property will contain the number of faces of the - Voronoi cell that have i edges. Thus, the first two components of the per-particle vector will always be zero, because the minimum - number of edges a polygon can have is three. + Activates the calculation of Voronoi indices. The modifier stores the computed indices in a vector particle property + named Voronoi Index. The i-th component of this vector will contain the number of faces of the + Voronoi cell having i edges. This implies that the leading two components of the per-particle + vector are always zero, because the minimum number of edges a polygon can have is three. @@ -106,8 +158,9 @@ Edge length threshold - Specifies the minimum length an edge must have to be considered in the Voronoi index calculation. Edges that are shorter + Specifies the minimum length a face edge must have to be considered in the Voronoi index calculation. Edges that are shorter than this threshold will be ignored when counting the number of edges of a Voronoi face. + The threshold value is given in absolute units of length (depending on your input data). @@ -116,15 +169,14 @@ Generate neighbor bonds - If this option is enabled, the modifier outputs the bonds between pairs of - neighboring particles. A bond is generated for every Voronoi face whose - area is larger than the specified face area threshold, and which has at least three edges + If this option is enabled, the modifier generates bonds between neighboring particles that share a Voronoi face. + A bond is generated for every Voronoi face whose area is larger than the face area threshold and which has at least three edges longer than the specified edge length threshold. Note that bonds in periodic simulation cells are computed using the minimum image convention, which requires that the cell is at least twice as large in each periodic direction as the - longest neighbor bond. In cases where the cell is shorter, the computed bonds might be incorrect. + longest neighbor bond. In cases where the cell is shorter, the computed bonds may be incorrect. diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/vorotop_analysis.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/vorotop_analysis.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/vorotop_analysis.docbook 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/vorotop_analysis.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,57 @@ + +
+ Voronoi topology analysis + + + + + + This modifier uses the Voronoi cell topology of a particle + to characterize its local environment [Lazar, Han, Srolovitz, PNAS 112:43 + (2015)]. + + + The Voronoi cell of a particle is the region of space closer to it than to any other particle. + The topology of the Voronoi cell is the manner in which its faces are connected, and describes + the manner in which a particle's neighbors are arranged. The topology of a Voronoi cell can be + completely described in a vector of integers called a Weinberg vector [Weinberg, IEEE Trans. Circuit Theory 13:2 (1966)]. + + + + This modifier requires loading a filter, which specifies structure types and associated + Weinberg vectors. Filters for several common structures can be obtained from the VoroTop + website. The modifier calculates the Voronoi cell topology of each particle, uses the provided + filter to determine the structure type, and stores the results in the + Structure Type particle property. This allows the user to subsequently select particles + of a certain structural type, e.g. by using the Select Particle Type modifier. This + modifier requires access to the complete set of input particles to perform the analysis, and + should therefore be placed at the beginning of the processing pipeline, preceding any modifiers + that delete particles. + + + + This method is well-suited for analyzing finite-temperature systems, including those heated to + their bulk melting temperatures. This robust behavior relieves the need to quench a sample + (such as by energy minimization) prior to analysis. + + + + Further information about the Voronoi topology approach for local structure analysis, as well + as additional filters, can be found on the + VoroTop webpage. + + +
+ diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/wigner_seitz_analysis.docbook ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/wigner_seitz_analysis.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/modifiers/particles/wigner_seitz_analysis.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/modifiers/particles/wigner_seitz_analysis.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -16,34 +16,44 @@ - This analysis modifier identifies point defects and counts vacancies and interstitials in a crystal - using the so-called Wigner-Seitz cell method. + This analysis modifier identifies point defects in crystalline structures using the so-called Wigner-Seitz cell method. It can be used to count vacancies and interstitials, + for example, or track their motion through the lattice.
+ + How the Wigner-Seitz cell method works - The Wigner-Seitz cell method works as follows: We assume that there exist two configurations of - the atomistic system. One is the reference state, which is defect-free (typically a perfect crystal lattice). - The other is the displaced configuration, which represents the defective state of the crystal to be analyzed. - Here, some atoms have been displaced from their original sites. - - - Each atomic site in the reference configuration defines the center of a Wigner-Seitz cell (also called Voronoi cell), - which is the spatial region that belongs to that site. Any atom (from the displaced configuration) that is located within the Wigner-Seitz cell - of a reference site is said to occupy that site. The analysis modifier basically counts the number of - atoms from the displaced configuration that occupy each site from the reference configuration. Typically, - sites are occupied by exactly one atom each. However, some sites may by occupied by zero atoms (then we call it a vacancy) - or by more than one atom (then we call the excess atoms interstitials). + The Wigner-Seitz cell method works as follows: It is presumed that two configurations of + the atomistic system exist: the reference state, which is defect-free (typically the perfect crystal lattice), + and the displaced configuration, which represents the defective state of the crystal to be analyzed. + In the latter, some atoms have been displaced or completely removed from their original sites. + + + + + + Each atomic site in the reference configuration defines the center of a Wigner-Seitz cell (also called a Voronoi cell), + which is the spatial region belonging to that site. Any atom that is located within the Wigner-Seitz cell + of a reference site is said to occupy that site. In other words, the WS anlysis algorithm simply counts the number of + atoms (from the displaced configuration) that occupy each site (of the reference configuration). Typically, + sites are occupied by exactly one atom each, because most of the crystal remains intact and atoms do not leave their original positions. + However, some sites may be occupied by zero atoms (we call these sites vacancies) + or by more than one atom (then we call the excess atoms interstitials). + + + + Generated output - The modifier outputs the number of atoms sitting on each site as a new particle property named Occupancy. - This property allows to subsequently filter out normal sites and show only defective sites (e.g. by using the Expression Select modifier). + The modifier outputs the number of atoms sitting on each site as a particle property named Occupancy. + This integer property allows to subsequently filter out normal sites and show only defective sites (e.g. by using the Expression Select modifier). Furthermore, the modifier reports two global quantities: Number of vacancies This is the total number of sites in the reference configuration which are not occupied by any atom - in the displaced configuration (sites with occupancy=0). + of the displaced configuration (sites with occupancy=0). @@ -55,48 +65,67 @@
+
+ + + Workflow - The number of atoms in the reference configuration and in the displaced configuration do not have to be the same. - However, if the two configurations do contain the same number of atoms, then the number of vacancies and the number of interstitials + Note that the numbers of atoms in the reference configuration and in the displaced configuration do not have to be the same. + However, if the two configurations do contain exactly the same number of atoms, then the number of vacancies and the number of interstitials reported by the modifier will be equal. That is because, in this case, the sum over all occupancy numbers is equal to the number of sites in the reference configuration. - The modifier loads the reference configuration from a separate input file. + The currently loaded dataset, which the modifier has been applied to, is considered as the displaced configuration by the modifier. + The reference configuration is loaded by the modifier from a separate input file. Use the "Reference: External file" panel to pick the - file containing the reference particle positions, which define the defect-free state of the crystal. - The displaced configuration is given by the particle dataset to which the Wigner-Seitz modifier is being applied. + file containing the reference particle positions, which define the defect-free state of the crystal. - IMPORTANT NOTE: - After performing the analysis this modifier throws away the displaced configuration and completely replaces it with the - reference configuration loaded from the external file. Thus, as an effect of applying the Wigner-Seitz modifier you will - now see the reference configuration (defect-free crystal) instead of the displaced configuration (defective crystal) which you applied it to. - This makes sense because the computed occupancy numbers apply to the atomic sites of the reference configuration, - not to the atoms of the defective crystal. Keep in mind that the modifier only computes the number of atoms that occupy each - site. It does not tell you which atom from the defective configuration occupies which site. + IMPORTANT NOTE: + The figure above shows that the occupancy numbers computed by the modifier are values associated with the reference + sites, not with the atoms of the displaced configuration. As the modifier's output data + relates to the reference configuration, the modifier throws away the displaced configuration after performing the WS analysis and completely replaces + it with the reference configuration loaded from the secondary file. Thus, as an effect of applying the Wigner-Seitz modifier you will + now see the atoms as they were in the reference configuration (defect-free crystal) instead of the displaced configuration (defective crystal) which you applied the modifier to. + Keep in mind that the modifier only computes the number of atoms that occupy each site. It does not tell you which atom from the defective + configuration occupies what site. + + + After the WS modifier has performed its computation, each atomic site will be associated with a new integer property named Occupancy. + You can subsequently use the Expression Select modifier to select certain sites that + correspond to certain types of point defects. For example, the selection expression "Occupancy==0" would select all empty sites (vacancies) + while the expression "Occupancy>1" would select all sites containing at least one interstitial atom. Typically, you want + to visualize just the defective sites and hide all other sites, which are occupied by exactly one atom. This can be achieved with the following modification pipeline setup: + + + + + + + Systems with more than one atomic species - However, if more specific information is needed, the modifier provides the - Output per-type occupancies option. If actived, the modifer breaks down the - occupancy number of each site into per-type counts. Thus, if your displaced configuration contains + To identify antisites and other defects in multi-component systems, more specific information about the atom(s) that occupy a site is required. + For this, the modifier provides the Output per-type occupancies option. If actived, the modifer breaks down the + occupancy number of each site into type-specific counts. Thus, if your displaced configuration contains atoms of different types, then this allows you to determine how many atoms of each type occupy each - site in the ideal reference crystal. The per-type occupancy numbers are output as + site in the reference crystal. The per-type occupancy numbers are output as vector components of the Occupancy particle property. For example, the property component Occupancy.1 contains the number of atoms of type 1 that occupy a site. - This allows you to identify specific types of point defects, e.g. vacancies or antisites. OVITO's particle selection tools, in particular the Expression Select modifier, can be used to select the sites that meet specific criteria, for example - A-sites that are occupied by a B-atom. You can find a detailed example of how to also accomplish this selection using - the Python Script modifier in the + A-sites that are occupied by a B-atom (antisite). Another way of selecting this type of defect sites + is using OVITO's scripting interface or OVITO's Python Script modifier. You can find a detailed example in the scripting documentation of the Wigner-Seitz modifier. + Parameters @@ -118,25 +147,6 @@ If this option is active, the modifier outputs per-type occupancy numbers as explained above. - - - - Fixed reference configuration - - If this option is active, the selected animation frame from the reference simulation sequence is used - as a fixed reference to perform the analysis. This is the default mode. - - - - - Relative to current frame - - If this option is active, then a changing reference configuration is used for the analysis. - The frame offset controls the distance between reference and current frame and can be negative or positive. If it is negative, then the reference frame - precedes the current frame in the simulation sequence. - Note that the analysis will not be performed for frames for which the reference frame is negative or out of range. - -
diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/rendering/povray_renderer.docbook ovito-2.9.0+dfsg1/doc/manual/reference/rendering/povray_renderer.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/rendering/povray_renderer.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/rendering/povray_renderer.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -28,4 +28,8 @@ a .pov file using OVITO's file export function. This allows you to render the exported scene through POV-Ray at a later time or on a different machine. + + The omni­directional stereo projection option, which requires POV-Ray 3.7.1 or newer, + allows to create stereoscopic 360-degree VR videos. + diff -Nru ovito-2.8.1+dfsg2/doc/manual/reference/utilities/particle_inspection_utility.docbook ovito-2.9.0+dfsg1/doc/manual/reference/utilities/particle_inspection_utility.docbook --- ovito-2.8.1+dfsg2/doc/manual/reference/utilities/particle_inspection_utility.docbook 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/reference/utilities/particle_inspection_utility.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,40 @@ + +
+ Particle inspection utility + + + + + + + This utility applet allows you to inspect the property values associated with individual particles + and to measure distances and angles between pairs and triplets of particles. + The utility is invoked from "Utilities" tab of OVITO's command panel shown on the right. + + + After opening the utility, you can pick individual particles in the viewports using the mouse. + The current values of their properties are displayed in the utility's text panel. + It is possible to select multiple particles at once, in which case the pair-wise distances + between all selected particles and angles formed by all triplets are computed by OVITO. + + + The expression text box allows you to enter an expression to select certain particles based on their properties + instead of picking them using the mouse. The syntax of the Boolean expression must follow + the same rules as for the Expression Select modifier. + Note that, for performance reasons, the utility only displays the properties of the first ten particles that match the expression. + + + Note that particle indices reported by the utility are zero-based and always refer to the set of + of particles currently visible. Thus, if you delete some particles, the indices of the remaining + ones are shifted (this is in contrast to particle identifiers, which stick). + + +
diff -Nru ovito-2.8.1+dfsg2/doc/manual/usage/import_particles.docbook ovito-2.9.0+dfsg1/doc/manual/usage/import_particles.docbook --- ovito-2.8.1+dfsg2/doc/manual/usage/import_particles.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/usage/import_particles.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -156,8 +156,9 @@ - POSCAR / XDATCAR - File formats used by the ab initio simulation package VASP. + POSCAR / XDATCAR / CHGCAR + File formats used by the ab initio simulation package VASP. + OVITO can read and visualize charge density data from CHGCAR files. IMD @@ -187,6 +188,10 @@ GSD/HOOMD Binary format for molecular dynamics data used by the HOOMD-blue code. See GSD (General Simulation Data) format. + + CASTEP + File format used by the CASTEP ab initio code. OVITO can read the .cell, .md and .geom formats. +
diff -Nru ovito-2.8.1+dfsg2/doc/manual/usage/miscellaneous.docbook ovito-2.9.0+dfsg1/doc/manual/usage/miscellaneous.docbook --- ovito-2.8.1+dfsg2/doc/manual/usage/miscellaneous.docbook 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/manual/usage/miscellaneous.docbook 2017-07-27 16:52:45.000000000 +0000 @@ -53,9 +53,9 @@ Particle inspection utility - The "Utilities" tab in OVITO's command panel, which is shown in the screenshoft on the right, provides a tool for - inspecting the properties of individual particles. It also allows you to measure distances between pairs of selected particles and - angles formed by triplets. + The "Utilities" tab of OVITO's command panel, which is shown in the screenshoft on the right, contains the + Particle Inspection utility for + displaying the properties of individual particles. The tool also allows you to measure distances between pairs of particles. There is also a utility on the same command panel tab that lets you visualize diff -Nru ovito-2.8.1+dfsg2/doc/python/conf.py ovito-2.9.0+dfsg1/doc/python/conf.py --- ovito-2.8.1+dfsg2/doc/python/conf.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/python/conf.py 2017-07-27 16:52:45.000000000 +0000 @@ -46,7 +46,7 @@ # General information about the project. project = 'OVITO' -copyright = '2016, Alexander Stukowski' +copyright = '2017, Alexander Stukowski' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -231,7 +231,7 @@ def process_signature(app, what, name, obj, options, signature, return_annotation): # Look for keyword "SIGNATURE:" in the docstring. - # TIt allows the C++ code to specify a custom function signature string for the Python documentation. + # This allows the C++ code to specify a custom function signature string for the Python documentation. if obj.__doc__: for line in obj.__doc__.splitlines(): if line.strip().startswith("SIGNATURE:"): diff -Nru ovito-2.8.1+dfsg2/doc/python/example_snippets/construct_surface_modifier.py ovito-2.9.0+dfsg1/doc/python/example_snippets/construct_surface_modifier.py --- ovito-2.8.1+dfsg2/doc/python/example_snippets/construct_surface_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/python/example_snippets/construct_surface_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,3 +1,6 @@ +import sys +if "ovito.modifiers.crystalanalysis" not in sys.modules: sys.exit() + from ovito.io import import_file from ovito.modifiers import ConstructSurfaceModifier diff -Nru ovito-2.8.1+dfsg2/doc/python/example_snippets/dislocation_analysis_modifier.py ovito-2.9.0+dfsg1/doc/python/example_snippets/dislocation_analysis_modifier.py --- ovito-2.8.1+dfsg2/doc/python/example_snippets/dislocation_analysis_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/python/example_snippets/dislocation_analysis_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,3 +1,6 @@ +import sys +if "ovito.modifiers.crystalanalysis" not in sys.modules: sys.exit() + from ovito.io import import_file, export_file from ovito.modifiers import DislocationAnalysisModifier diff -Nru ovito-2.8.1+dfsg2/doc/python/example_snippets/freeze_property_modifier.py ovito-2.9.0+dfsg1/doc/python/example_snippets/freeze_property_modifier.py --- ovito-2.8.1+dfsg2/doc/python/example_snippets/freeze_property_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/python/example_snippets/freeze_property_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * diff -Nru ovito-2.8.1+dfsg2/doc/python/example_snippets/quaternions_to_colors.py ovito-2.9.0+dfsg1/doc/python/example_snippets/quaternions_to_colors.py --- ovito-2.8.1+dfsg2/doc/python/example_snippets/quaternions_to_colors.py 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/python/example_snippets/quaternions_to_colors.py 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,61 @@ +from ovito.data import * +import math +import numpy as np + +def quaternions_to_colors(qs): + """ Takes a list of quaternions (Nx4 array) and returns a list of + corresponding RGB colors (Nx3 array) """ + + if len(qs.shape) != 2: + raise RuntimeError("qs must be a 2-dimensional array") + + if qs.shape[1] != 4: + raise RuntimeError("qs must be a n x 4 dimensional array") + + # Project quaternions into Rodrigues space: rs = (qs.X/qs.W, qs.Y/qs.W, qs.Z/qs.W) + # Note that the qs.W may be zero for particles for which no lattice orientation + # could be computed by the PTM modifier. + rs = np.zeros_like(qs[:,:3]) + np.divide(qs[:,0], qs[:,3], out=rs[:,0], where=qs[:,3] != 0) + np.divide(qs[:,1], qs[:,3], out=rs[:,1], where=qs[:,3] != 0) + np.divide(qs[:,2], qs[:,3], out=rs[:,2], where=qs[:,3] != 0) + + # Compute vector lengths rr = norm(rs) + rr = np.linalg.norm(rs, axis=1) + rr = np.maximum(rr, 1e-9) # hack + + # Normalize Rodrigues vectors. + rs[:,0] /= rr + rs[:,1] /= rr + rs[:,2] /= rr + + theta = 2 * np.arctan(rr) + rs[:,0] *= theta + rs[:,1] *= theta + rs[:,2] *= theta + + # Normalize values. + rs += math.radians(62.8) + rs[:,0] /= 2*math.radians(62.8) + rs[:,1] /= 2*math.radians(62.8) + rs[:,2] /= 2*math.radians(62.8) + + return rs + +def modify(frame, input, output): + """ The custom modifier function """ + + # The input: + orientation_property = input.particle_properties.orientation.array + + # The output: + color_property = output.create_particle_property(ParticleProperty.Type.Color) + color_property.marray[:] = quaternions_to_colors(orientation_property ) + +# This part is for automated testing. +from ovito.io import import_file +from ovito.modifiers import PythonScriptModifier, PolyhedralTemplateMatchingModifier +node = import_file("simulation.dump") +node.modifiers.append(PolyhedralTemplateMatchingModifier(output_orientation = True)) +node.modifiers.append(PythonScriptModifier(function = modify)) +node.compute() diff -Nru ovito-2.8.1+dfsg2/doc/python/example_snippets/render_to_image.py ovito-2.9.0+dfsg1/doc/python/example_snippets/render_to_image.py --- ovito-2.8.1+dfsg2/doc/python/example_snippets/render_to_image.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/python/example_snippets/render_to_image.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,9 +1,9 @@ -from ovito import * +import ovito from ovito.vis import * from PyQt5.QtGui import QPainter # Let OVITO render an image of the active viewport. -vp = dataset.viewports.active_vp +vp = ovito.dataset.viewports.active_vp rs = RenderSettings(size = (320,240), renderer = TachyonRenderer()) image = vp.render(rs) diff -Nru ovito-2.8.1+dfsg2/doc/python/example_snippets/surface_mesh.py ovito-2.9.0+dfsg1/doc/python/example_snippets/surface_mesh.py --- ovito-2.8.1+dfsg2/doc/python/example_snippets/surface_mesh.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/python/example_snippets/surface_mesh.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,3 +1,6 @@ +import sys +if "ovito.modifiers.crystalanalysis" not in sys.modules: sys.exit() + from ovito.io import import_file from ovito.modifiers import ConstructSurfaceModifier diff -Nru ovito-2.8.1+dfsg2/doc/python/example_snippets/trajectory_lines.py ovito-2.9.0+dfsg1/doc/python/example_snippets/trajectory_lines.py --- ovito-2.8.1+dfsg2/doc/python/example_snippets/trajectory_lines.py 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/python/example_snippets/trajectory_lines.py 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,27 @@ +from ovito import ObjectNode +from ovito.io import import_file +from ovito.data import TrajectoryLineGenerator +from ovito.vis import TrajectoryLineDisplay + +# Load a particle simulation sequence: +particle_node = import_file('simulation.*.dump') +particle_node.add_to_scene() + +# Create a second scene node for the trajectory lines: +traj_node = ObjectNode() +traj_node.add_to_scene() + +# Create data source and assign it to the new scene node: +traj_node.source = TrajectoryLineGenerator( + source_node = particle_node, + only_selected = False +) + +# Generate the trajectory lines by sampling the +# particle positions over the entire animation interval. +traj_node.source.generate() + +# Adjust trajectory display settings: +traj_node.source.display.width = 0.4 +traj_node.source.display.color = (1,0,0) +traj_node.source.display.shading = TrajectoryLineDisplay.Shading.Flat diff -Nru ovito-2.8.1+dfsg2/doc/python/introduction/examples.rst ovito-2.9.0+dfsg1/doc/python/introduction/examples.rst --- ovito-2.8.1+dfsg2/doc/python/introduction/examples.rst 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/python/introduction/examples.rst 2017-07-27 16:52:45.000000000 +0000 @@ -9,6 +9,7 @@ * :ref:`example_msd_calculation` * :ref:`example_order_parameter_calculation` * :ref:`example_creating_particles_programmatically` + * :ref:`example_visualize_local_lattice_orientation` .. _example_compute_voronoi_indices: @@ -111,13 +112,13 @@ Implementing an advanced analysis modifier -------------------------------------------------- -In the paper `[Phys. Rev. Lett. 86, 5530] `_ an order parameter has been specified as a means +In the paper `[Phys. Rev. Lett. 86, 5530] `_ an order parameter is specified as a means of labeling an atom in the simulation as belonging to either the liquid or solid fcc crystal phase. In the following we will develop a custom analysis modifier for OVITO, which calculates this per-atom order parameter. The order parameter is defined as follows (see the paper for details): For any of the 12 nearest neighbors of a given atom one can compute the distance the neighbor -makes from the ideal fcc positions of the crystal in the given orientation (denoted by vector **r**\ :sub:`fcc`). The sum of the distances over the 12 neighbors, -phi = 1/12*sum(| **r**\ :sub:`i` - **r**\ :sub:`fcc` |), acts as an "order parameter" for the central atom. +makes from the ideal fcc positions of the crystal in the given orientation (denoted by vector :strong:`r`:sub:`fcc`). The sum of the distances over the 12 neighbors, +phi = 1/12*sum(\| :strong:`r`:sub:`i` - :strong:`r`:sub:`fcc` \|), acts as an "order parameter" for the central atom. Calculating this parameter involves finding the 12 nearest neighbors of each atom and, for each of these neighbors, determining the closest ideal lattice vector. To find the neighbors, OVITO provides the :py:class:`~ovito.data.NearestNeighborFinder` utility class. @@ -153,3 +154,20 @@ .. literalinclude:: ../../../tests/scripts/test_suite/create_new_particle_property.py +.. _example_visualize_local_lattice_orientation: + +--------------------------------------------------------------- +Visualizing local lattice orientations using particle coloring +--------------------------------------------------------------- + +The `Polyhedredral Template Matching (PTM) <../../particles.modifiers.polyhedral_template_matching.html>`_ function of OVITO allows +computing the local lattice orientation for each atom in a (poly)crystal. The computed local orientations +are stored by the modifier as quaternions, i.e. as rotations within the fundamental zone, in the particle property named ``Orientation``. +Each per-particle quaternion can be translated into an RGB color to visualize the local lattice orientation. +This can be achieved by inserting a :ref:`custom Python modifier ` into the pipeline which translates the output of the PTM modifier +into RGB values and stores them in the ``Color`` particle property. + +In the graphical OVITO version, simply insert a new Python modifier and copy/paste the following script into the source code window: + +.. literalinclude:: ../example_snippets/quaternions_to_colors.py + :lines: 1-52 \ No newline at end of file diff -Nru ovito-2.8.1+dfsg2/doc/python/introduction/file_io.rst ovito-2.9.0+dfsg1/doc/python/introduction/file_io.rst --- ovito-2.8.1+dfsg2/doc/python/introduction/file_io.rst 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/python/introduction/file_io.rst 2017-07-27 16:52:45.000000000 +0000 @@ -4,113 +4,155 @@ File I/O =================================== -This section describes how to load simulation data from external files and how to export -modified particle data or other results computed by OVITO to a file. +This section describes how to load simulation data from external files and how to :ref:`export data ` +computed by OVITO to a file again. ------------------------------------ -File input +Data import ------------------------------------ -The primary way of loading an external data file is the :py:func:`~ovito.io.import_file` function:: +The standard way of loading external data is calling the global :py:func:`~ovito.io.import_file` function:: >>> from ovito.io import import_file >>> node = import_file("simulation.dump") -This high-level function works like the `Load File` menu function in OVITO's graphical user interface. +This high-level function works similar to the `Load File` function in OVITO's graphical user interface. It creates and returns an :py:class:`~ovito.ObjectNode`, whose :py:class:`~ovito.io.FileSource` is set up to point -to the specified file, and which is reponsible for loading the actual data from the file. +to the specified file and loads it. -In case you already have an existing object node, for example after a first call to :py:func:`~ovito.io.import_file`, -you can subsequently load a different simulation file with the :py:meth:`~ovito.io.FileSource.load` method +In case you already have an existing :py:class:`~ovito.ObjectNode`, for example after a first call to :py:func:`~ovito.io.import_file`, +you can subsequently load different simulation files by calling the :py:meth:`~ovito.io.FileSource.load` method of the :py:class:`~ovito.io.FileSource` owned by the node:: - >>> node.source.load("other_simulation.dump") + >>> node.source.load("next_simulation.dump") -This method takes the same parameters as the :py:func:`~ovito.io.import_file` function, but it doesn't create a new -object node. Any existing modification pipeline of the object node is preserved. +This method takes the same parameters as the :py:func:`~ovito.io.import_file` global function, but it doesn't create a new +object node. Any existing modifiers assigned to the object node are preserved, only the input data is replaced. -Note that the :py:meth:`~ovito.io.FileSource.load` method is also used to -load reference configurations for modifiers that require reference particle coordinates, e.g.:: +Note that the same :py:meth:`~ovito.io.FileSource.load` method is also used when +loading reference configurations for analysis modifiers that require reference particle coordinates, e.g.:: >>> modifier = CalculateDisplacementsModifier() >>> modifier.reference.load("reference.dump") Here the :py:attr:`~ovito.modifiers.CalculateDisplacementsModifier.reference` attribute refers to a second :py:class:`~ovito.io.FileSource`, which is owned by the :py:class:`~ovito.modifiers.CalculateDisplacementsModifier` and which is responsible -for loading the reference particle positions required by the modifier. +for loading the reference particle positions required for the displacement vector calculation. -**Column mapping** +**Specifying the column-to-property mapping** -Both the global :py:func:`~ovito.io.import_file` function and the :py:meth:`FileSource.load() ` method -accept format-specific keyword arguments in addition to the filename. For instance, when loading XYZ +OVITO automatically detects the format of input files, but both the global :py:func:`~ovito.io.import_file` function and the +:py:meth:`FileSource.load() ` method accept format-specific keyword arguments that further control the import process. +For instance, when loading XYZ files, the mapping of input file columns to OVITO's particle properties needs to be specified using the ``columns`` keyword:: >>> node = import_file("simulation.xyz", columns = - ... ["Particle Type", "Position.X", "Position.Y", "Position.Z", "My Property"]) + ... ["Particle Type", "Position.X", "Position.Y", "Position.Z", "My Property"]) -The number of entries in the ``columns`` list must match the number of data columns in the input file. +The number of entries in the ``columns`` list must match the number of data columns present in the XYZ input file. See the documentation of the :py:func:`~ovito.io.import_file` function for more information on this. **Simulation sequences** -So far we have only considered loading a single simulation snapshot. As you know from the graphical program version, OVITO is also able to -load a sequence of simulation snapshots (a trajectory), which can be played back as an animation. -There are two possible scenarios: +So far we only considered loading single simulation snapshots. As you know from the graphical program, OVITO is also able to +load sequences of simulation snapshots (trajectories), which can be played back as animations. +There are two scenarios: -1. To load a file that stores multiple simulation frames, use the ``multiple_frames`` keyword:: +1. To load a file containing multiple simulation frames, use the ``multiple_frames`` keyword:: >>> node = import_file("sequence.dump", multiple_frames = True) - OVITO will scan the entire file and discover all contained simulation frames. This works for LAMMPS dump files and XYZ files. + OVITO will scan the entire file and discover all contained simulation frames. This works for LAMMPS dump files and XYZ files, for example. 2. To load a series of simulation files from a directory, following a naming pattern like :file:`frame.0.dump`, :file:`frame.1000.dump`, :file:`frame.2000.dump`, etc., pass a wildcard pattern to the :py:func:`~ovito.io.import_file` function:: >>> node = import_file("frame.*.dump") - OVITO will automatically find all files in the directory belonging to the the simulation trajectory. + OVITO will automatically find all files in the directory belonging to the simulation trajectory. -In both cases you can check how many animation frames were found by querying the :py:attr:`~ovito.io.FileSource.num_frames` property -of the :py:class:`~ovito.io.FileSource`:: +In both cases you can check how many frames were found by querying the :py:attr:`~ovito.io.FileSource.num_frames` property +of the :py:class:`~ovito.io.FileSource`, e.g.:: >>> node.source.num_frames - 100 + 85 .. note:: - To save memory and time, OVITO never loads all frames from a trjectory at once. It only scans the directory (or the multi-frame file) + To save memory and time, OVITO never loads all frames of a trajectory at once. It only scans the directory (or the multi-frame file) to discover all frames belonging to the sequence and adjusts the internal animation length to match the number of input frames found. - The actual simulation data will only be loaded by the :py:class:`~ovito.io.FileSource` on demand, e.g., when + The actual simulation data of a frame will only be loaded by the :py:class:`~ovito.io.FileSource` on demand, e.g., when jumping to a specific frame in the animation or when rendering a movie. -You can iterate over the frames of a loaded animation sequence in a script loop:: +You can loop over the frames of a loaded animation sequence:: - # Load a sequence of simulation files 'frame.0.dump', 'frame.1000.dump', etc. - node = import_file("simulation.*.dump") + # Load a sequence of simulation files 'frame0.dump', 'frame1000.dump', etc. + node = import_file("simulation*.dump") + + # Set up data pipeline, apply modifiers as needed, e.g. + node.modifiers.append(CoordinationNumberModifier(cutoff=3.2)) for frame in range(node.source.num_frames): - # Load the input data and apply the modifiers to current frame: - node.compute(frame) - # ... access computation results for current animation frame. + + # This loads the input data for the current frame and + # evaluates the applied modifiers: + output = node.compute(frame) + + # Work with the computation results + ... .. _file_output_overview: - + ------------------------------------ -File output +Data export ------------------------------------ -Exporting particles and other computation results to a file typically done using the :py:func:`ovito.io.export_file` function. -For example, to export the particles that leave the modification pipeline and their properties to a LAMMPS dump file, one would +Exporting particles and other computation results to a file is typically done using the global :py:func:`ovito.io.export_file` function. +For example, to export the particles that leave the modification pipeline of an :py:class:`~ovito.ObjectNode` to a LAMMPS dump file, one would write:: >>> export_file(node, "outputfile.dump", "lammps_dump", ... columns = ["Position.X", "Position.Y", "Position.Z", "My Property"]) -OVITO will automatically evaluate the node's modification pipeline before writing the computation results to the file. -If the node's modification pipeline contains no modifiers, then the original, unmodified data is exported. +OVITO automatically evaluates the node's modification pipeline to obtain the computation results and writes them to the file. +Of course, if the node's modification pipeline contains no modifiers, then the original data loaded via :py:func:`~ovito.io.import_file` is exported. The second function parameter specifies the output filename, and the third parameter selects the output format. For a list of supported file formats, see the :py:func:`~ovito.io.export_file` documentation. -Depending on the selected output format, additional keyword arguments must be specified. For instance, -in the example above the ``columns`` parameter specifies the particle properties to be exported. +Depending on the selected output format, additional keyword arguments may need to be specified. For instance, +in the example above the ``columns`` parameter specifies the list of particle properties to be exported. + +In addition to particles, :py:func:`~ovito.io.export_file` can also export other types of data computed by OVITO. +One example are global attributes, which are data values generated by modifiers during the pipeline evaluation. +In other words, unlike particle properties, attributes are computation results that are associated with a particle dataset as a whole. +For example, the :py:class:`~ovito.modifiers.SelectExpressionModifier` outputs an attribute with the name ``SelectExpression.num_selected`` +to report the number of particles that matched the given selection criterion. + +You can export the value of this computed attribute to a text file, typically for all frames of a simulation as a table, +to graphically plot the time evolution using an external program. For this purpose the :py:func:`~ovito.io.export_file` function +supports the ``txt`` output format:: + + node = import_file("simulation*.dump") + + node.modifiers.append(SelectExpressionModifier(expression="PotentialEnergy<-3.9")) + + export_file(node, "potenergy.txt", "txt", multiple_frames=True, + columns = ["Frame", "SelectExpression.num_selected"]) + +This produces a text file :file:`potenergy.txt` containing one line per simulation frame and two columns:: + + 0 531 + 1 540 + 2 522 + 3 502 + ... + +The first column is the animation frame number (starting at 0) and the second +column contains the value of the ``SelectExpression.num_selected`` attribute output by the :py:class:`~ovito.modifiers.SelectExpressionModifier`. + +Typically, attributes are generated by modifiers in the pipeline, but some may also be defined +during file import. For example, an attributed named ``Timestep`` is set by OVITO when importing a LAMMPS dump file, +which specifies the simulation timestep number of the loaded snapshots. This makes it possible, for example, +to replace the animation frame number in the first column above (corresponding to the predefined attribute ``Frame``) +with the actual timestep number from the simulation. See :py:attr:`ovito.data.DataCollection.attributes` for more information. diff -Nru ovito-2.8.1+dfsg2/doc/python/introduction/overview.rst ovito-2.9.0+dfsg1/doc/python/introduction/overview.rst --- ovito-2.8.1+dfsg2/doc/python/introduction/overview.rst 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/python/introduction/overview.rst 2017-07-27 16:52:45.000000000 +0000 @@ -2,19 +2,18 @@ Overview ================================== -OVITO scripting interface provides full access to most of OVITO's program features. Using Python scripts, you can +OVITO's scripting interface provides access to most of program features. Using Python scripting, you can do many things that are already familiar from the graphical user interface (and even a few more): * :ref:`Import data from external files ` * :ref:`Apply modifiers to a dataset and configure them ` - * Set up a camera and render pictures or movies of the scene - * Control the visual appearance of particles and other objects - * Access per-particle properties and other analysis results computed by OVITO - * :ref:`Implement new types of modifiers ` * :ref:`Export data to a file ` + * :ref:`Set up a camera and render pictures or movies of the scene ` + * :ref:`Control the visual appearance of particles and other objects ` + * :ref:`Access per-particle properties and other analysis results computed by OVITO ` + * :ref:`Implement new types of modifiers ` -The following sections will introduce the essential concepts and walk you through different parts of OVITO's -scripting framework. +But first let's take a look at some essential concepts of OVITO's data model and the scripting framework. ------------------------------------ OVITO's data pipeline architecture @@ -27,19 +26,19 @@ To access this capability from a script, we first need to understand the basics of OVITO's underlying data model. In general, there are two different groups of objects that participate in the described system: -Objects that constitute the modification pipeline (the modifiers and the data source) and *data objects*, which -carry the data that is being processed by the modifier. The data objects enter the modification pipeline, -get modified by a modifier, or are newly produced (e.g. computed particle properties). -We start by discussing the objects that consitute a modification pipeline. +Objects that constitute the modification pipeline (i.e. the modifiers and a data source) and *data objects*, which +carry the data that is being processed by the modifiers. The data objects enter the modification pipeline, +get modified by one or more modifiers, or are newly produced (e.g. as a result of a computation). +We first discuss the objects that constitute the modification pipeline. ------------------------------------ Data sources, modifiers, and more ------------------------------------ -A modification pipeline is fed by a *data source*, which is an object +A modification pipeline is always fed by some *data source*, which is an object that provides or generates the input data entering a modification pipeline. OVITO currently knows two types of data sources: :py:class:`~ovito.io.FileSource` and :py:class:`~ovito.data.DataCollection`. -The :py:class:`~ovito.io.FileSource` class is the data source typically used. It is responsible for loading data +The :py:class:`~ovito.io.FileSource` class is the data source type commonly used. It is responsible for loading data from an external file and passing it on to the modification pipeline. The data source and the modification pipeline together form an :py:class:`~ovito.ObjectNode`. This class @@ -66,32 +65,32 @@ Loading data and applying modifiers ------------------------------------ -An :py:class:`~ovito.ObjectNode` is automatically created when you import a data file into OVITO +A new instance of the :py:class:`~ovito.ObjectNode` class is automatically created whenever you import a file using the :py:func:`ovito.io.import_file` function:: >>> from ovito.io import * >>> node = import_file("simulation.dump") This high-level function creates an :py:class:`~ovito.ObjectNode` with an empty modification pipeline -and sets up a :py:class:`~ovito.io.FileSource` (which will subsequently load the data +and sets up a :py:class:`~ovito.io.FileSource` (which will subsequently load the actual data from the given file) and assigns it to the :py:attr:`ObjectNode.source ` property. We can now start populating the node's modification pipeline with some modifiers by appending them to the :py:attr:`ObjectNode.modifiers ` list:: >>> from ovito.modifiers import * - >>> node.modifiers.append(SelectExpressionModifier(expression="PotentialEnergy < -3.9")) + >>> node.modifiers.append(SelectExpressionModifier(expression="PotentialEnergy<-3.9")) >>> node.modifiers.append(DeleteSelectedParticlesModifier()) -Modifiers are constructed by calling the constructor of the corresponding classes, which are -all found in the :py:mod:`ovito.modifiers` module. Note how a modifier's parameters can be initialized in two ways: +A modifier is constructed by calling the constructor of one of the modifier classes, which are +all found in the :py:mod:`ovito.modifiers` module. Note how a modifier's parameters can be initialized in two different ways: .. note:: - When constructing a new object (such as a modifier, but also most other OVITO objects) it is possible to directly initialize its + When constructing a new object (e.g. a modifier, but also most other OVITO objects) it is possible to directly initialize its properties by passing keyword arguments to the constructor function. Thus :: - node.modifiers.append(CommonNeighborAnalysisModifier(cutoff = 3.2, only_selected = True)) + node.modifiers.append(CommonNeighborAnalysisModifier(cutoff=3.2, only_selected=True)) is equivalent to setting the properties one by one after constructing the object:: @@ -99,25 +98,31 @@ modifier.cutoff = 3.2 modifier.only_selected = True node.modifiers.append(modifier) - -After the modification pipeline has been populated with modifiers, we can do three different things: -(i) write the results to a file, (ii) render an image of the data, (iii) or directly work with the pipeline -data and read out particle properties and other results. Keep reading. + + Obviously the first way of initializing the object's parameters is more convenient and should be used + whenever the parameter values are known at construction time. + + +After the input data has been loaded and the modification pipeline is populated with some modifiers, +we can basically do three different things: (i) export the computation results to a file, +(ii) render an image of the data, (iii) or directly access the pipeline output from the script. +Keep reading, we'll now give a quick overview on these tasks and go into details in the later sections. ------------------------------------ Exporting data to a file ------------------------------------ -Exporting the data that has left the modification pipeline to a file is simple; -we use the :py:func:`ovito.io.export_file` function for this:: +Exporting the data to a file that is produced by the modification pipeline is simple; +we call the :py:func:`ovito.io.export_file` function for this:: >>> export_file(node, "outputdata.dump", "lammps_dump", ... columns = ["Position.X", "Position.Y", "Position.Z", "Structure Type"]) -The first argument of this high-level function is the node whose pipeline results should be exported. -It is followed by the name of the output file and the desired output format. -Depending on the selected file format, additional keyword arguments such as the list of particle properties to -be exported must be provided. See the documentation of the :py:func:`~ovito.io.export_file` function for more information. +The first argument of this high-level function is the :py:class:`~ovito.ObjectNode` whose pipeline results are to be exported. +It is followed by the output filename and the desired output format. +Depending on the selected format, additional keyword arguments such as the list of particle properties to +export must be provided. See the documentation of the :py:func:`~ovito.io.export_file` function and :ref:`this section ` +of the manual for more information on the supported output formats and additional options. ------------------------------------ Rendering images diff -Nru ovito-2.8.1+dfsg2/doc/python/introduction/particle_properties.rst ovito-2.9.0+dfsg1/doc/python/introduction/particle_properties.rst --- ovito-2.8.1+dfsg2/doc/python/introduction/particle_properties.rst 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/python/introduction/particle_properties.rst 2017-07-27 16:52:45.000000000 +0000 @@ -1,3 +1,5 @@ +.. _particle_properties_intro: + =================================== Particle properties =================================== diff -Nru ovito-2.8.1+dfsg2/doc/python/introduction/rendering.rst ovito-2.9.0+dfsg1/doc/python/introduction/rendering.rst --- ovito-2.8.1+dfsg2/doc/python/introduction/rendering.rst 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/python/introduction/rendering.rst 2017-07-27 16:52:45.000000000 +0000 @@ -2,6 +2,8 @@ Rendering =================================== +.. _rendering_display_objects: + ----------------------------------- Display objects ----------------------------------- @@ -68,6 +70,8 @@ Similarly, the :py:class:`~ovito.modifiers.CreateBondsModifier` attached a :py:class:`~ovito.vis.BondsDisplay` to the :py:class:`~ovito.data.Bonds` data object it computes. +.. _rendering_viewports: + ----------------------------------- Viewports ----------------------------------- diff -Nru ovito-2.8.1+dfsg2/doc/python/introduction/running.rst ovito-2.9.0+dfsg1/doc/python/introduction/running.rst --- ovito-2.8.1+dfsg2/doc/python/introduction/running.rst 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/doc/python/introduction/running.rst 2017-07-27 16:52:45.000000000 +0000 @@ -2,48 +2,48 @@ Running scripts ================================== -OVITO's scripting interface serves two main purposes: It allows you to automate tasks (i.e. programmatically execute program functions) and to extend the -program (e.g. adding new analysis functions). How you write a script and how you execute it depends on the intended purpose. -The following list gives an overview of the various ways scripts are being used within OVITO: - - 1. **Programmatically execute program functions**: Scripts can invoke program actions like the human user does using the graphical interface. - This requires writing a Python script file containing the commands using an external text editor. The script file is executed by choosing - *Run Script File* from the *Scripting* menu of OVITO. The script can automatically add modifiers to the current dataset and configure them, for example. - Or it may access the results of the current modification pipeline and write the data to an output file in a custom format. +OVITO's scripting interface serves two main purposes: It enables you to automate visualization and analysis tasks and to extend the +program (e.g. by adding your own data modification or analysis functions). The way you write a script and run it depend on the intended purpose. +The following list gives an overview of the different ways scripts are being used within OVITO: + + 1. **Programmatically execute program functions**: Scripts can invoke program actions like a human user does in the graphical interface. + You typically write a Python script file containing the commands using an external text editor. The script file is executed by choosing + *Run Script File* from the *Scripting* menu of OVITO. The script can automatically insert modifiers and configure them, for example. + Or it may access the result of the current data pipeline and write it to an output file in a custom format. - 2. **Batch-processing**: Batch-processing scripts also contain instructions to invoke program functions. However, they are meant to be run from the command line - without any user interaction. A batch-processing script is therefore responsible for performing all necessary actions: loading the simulation data first, - optionally processing it using OVITO's modifier framework, - and finally exporting or rendering the results. Batch scripts are run using the :program:`ovitos` script interpreter, which will be introduced + 2. **Batch-processing**: Batch-processing scripts also contain instructions that invoke program functions. However, they are meant to be run from the command line + without any user interaction. A batch-processing script is therefore responsible for all actions from beginning to end: importing the simulation data first, + optionally modifying it using OVITO's modifier system, + and finally exporting or rendering the results. Batch scripts are typically executed using the :program:`ovitos` script interpreter, which will be introduced in the next section. This allows you to leverage OVITO's file I/O and data analysis functions in a fully automated manner, for example to process - a large number of simulation files on a remote computing cluster and perform complex analyses. + a large number of simulation files on a remote computing cluster and perform complex analysis tasks. 3. **User-defined data modifiers**: OVITO's scripting framework also gives you the possibility to develop new types of modifiers, which can manipulate - or analyze simulation data in ways that are not covered by any of the built-in standard modifiers provided by the program. So-called *Python script modifiers* + or analyze simulation data in ways not covered by any of the built-in standard modifiers provided by the program. So-called *Python script modifiers* (see :ref:`writing_custom_modifiers` section) participate in the data pipeline system of OVITO and behave like the built-in modifiers. A *Python script modifier* essentially consists of a single Python script function named ``modify()``, which you define. It is executed automatically by the system whenever the data pipeline is evaluated. - This is in contrast to the command scripts described above, which are executed only once and explicitly by the user. + This is in contrast to the command scripts described above, which are executed explicitly by the user. 4. **User-defined viewport overlays**: A `Python script overlay <../../viewport_overlays.python_script.html>`_ is a user-defined script function that gets called by OVITO every time a viewport is repainted or an image is rendered. This allows you to amend or enrich images or movies rendered by OVITO with custom graphics or text, e.g., to include additional information like a scale bar. -Note that a *Python script modifiers* is meant to be used from within the graphical user interface, but under certain circumstances it may also make sense -to define one from within a non-interactive script (see :py:class:`~ovito.modifiers.PythonScriptModifier` class). +Note that *Python script modifiers* are meant to be used from within the graphical user interface, but under certain circumstances it may also make sense +to define them in non-interactive scripts (see :py:class:`~ovito.modifiers.PythonScriptModifier` class). OVITO's Python interpreter ---------------------------------- -OVITO includes a built-in script interpreter, which can execute programs written in the Python language. +OVITO comes with an embedded script interpreter, which can execute programs written in the Python language. The current version of OVITO is compatible with the `Python 3.4 `_ language standard. -You typically execute a Python script from the terminal using the :program:`ovitos` script launcher that comes with OVITO: +You typically execute batch Python scripts from the terminal of your operating system using the :program:`ovitos` script interpreter that is installed with OVITO: .. code-block:: shell-session ovitos [-o file] [-g] [script.py] [args...] The :program:`ovitos` program is located in the :file:`bin/` subdirectory of OVITO for Linux, in the -:file:`Ovito.app/Contents/MacOS/` directory of OVITO for MacOS, and in the main application directory +:file:`Ovito.app/Contents/MacOS/` directory of OVITO for macOS, and in the main application directory on Windows systems. It should not be confused with :program:`ovito`, the main program which provides the graphical user interface. @@ -52,62 +52,75 @@ import ovito print("Hello, this is OVITO %i.%i.%i" % ovito.version) -We can execute the script from a Linux terminal as follows: +We can then execute the script from a Linux terminal as follows: .. code-block:: shell-session - me@linux:~/ovito-2.7.1-x86_64/bin$ ./ovitos hello.py - Hello, this is OVITO 2.7.1 + me@linux:~/ovito-2.9.0-x86_64/bin$ ./ovitos hello.py + Hello, this is OVITO 2.9.0 -By default, the :program:`ovitos` script launcher invokes OVITO in console mode, which is a non-graphical mode -where the main window isn't shown. This allows running OVITO scripts on remote machines or -computing clusters that don't possess a graphics display. In OVITO's console mode, scripts can read from and write -to the terminal as if they were executed by a standard Python interpreter. Any command line arguments following the -script's name are passed to the script via the ``sys.argv`` variable. Furthermore, it is possible to start OVITO's -interpreter in interactive scripting mode by running :program:`ovitos` without any arguments. +By default, the :program:`ovitos` script interpreter displays only console output and no graphical output. +This allows running OVITO scripts on remote machines or computing clusters that don't possess a graphics display. +The :program:`ovitos` program behaves like a standard Python interpreter. Any command line arguments following the +script's name are passed to the script via the ``sys.argv`` variable. Furthermore, it is possible to start +an interactive interpreter session by running :program:`ovitos` without any arguments. Preloading program state ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The :command:`-o` command line option loads an OVITO state file before executing the -script. This allows you to preload and use an existing visualization setup that has -been manually prepared using the graphical version of OVITO and saved to a :file:`.ovito` file. This can save you programming -work, because modifiers, parameters, and the camera setup already get loaded from the OVITO file and +The :command:`-o` command line option lets :program:`ovitos` load an :file:`.ovito` state file before executing the +script. This allows you to preload an existing visualization setup that your have +previously prepared using the graphical version of OVITO and which was saved to a :file:`.ovito` file. This can save you programming +work, because modifiers, parameters and the camera setup get already loaded from the state file and don't need to be set up programatically in the script anymore. Running scripts in graphical mode ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The :command:`-g` command line option switches from console mode to graphical mode. This displays OVITO's main window -and you can follow your script's actions as they are being executed. This is useful, for instance, if you want to visually +The :command:`-g` command line option activates the graphical mode. Then OVITO's main window is shown +and you can follow your script's actions as they are being executed in the user interface. This is useful, for instance, if you want to visually inspect the results of your script during the development phase. -Using third-party Python modules from OVITO scripts +Number of parallel threads ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Scripts that make use of the :py:mod:`ovito` Python module, cannot be run with a standard Python interpreter (usually named :program:`python`). -They must be executed with the launcher :program:`ovitos`, which takes care of setting up the program environment. However, this Python interpreter shipping with OVITO -includes `NumPy `_ and `matplotlib `_ as the only non-standard extension modules. - -If you want to use other third-party Python modules from your OVITO scripts, it may be possible to install them in the -:program:`ovitos` interpreter using the normal *pip* or *setuptools* mechanisms -(e.g., run :command:`ovitos -m pip install ` to install a module via *pip*). - -Installing Python extension that include native code (e.g. `Scipy `_) in the interpreter shipping with OVITO is currently not possible. -In this case it is recommended to build OVITO from source on your system. OVITO will then use the system's standard Python interpreter instead of its own. -This will make all modules that are installed in the system Python interpreter accessible within OVITO as well. (Note that you still need -to execute OVITO scripts with the :program:`ovitos` launcher.) How to build OVITO from source is described `on this page `_. +OVITO uses all available processor cores by default to perform computations. To restrict OVITO +to a certain number of parallel threads, use the :command:`--nthreads` command line parameter, e.g. :command:`ovitos --nthreads 1 myscript.py`. -Number of parallel threads +Third-party Python modules ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -OVITO uses all available processor cores on a machine to perform computations by default. To restrict OVITO -to a certain number of parallel threads, use the :command:`-nt` command line parameter, e.g. :command:`ovitos -nt 1 myscript.py`. - -Further uses of Python scripts within OVITO -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The embedded script interpreter of OVITO is a preconfigured version of the standard `CPython `_ interpreter with an integrated +:py:mod:`ovito` Python package. This makes it possible to run scripts both within the graphical program OVITO as well as through the :program:`ovitos` +command line interpreter. However, the embedded interpreter shipping with OVITO includes only the `NumPy `_, `matplotlib `_, +and `PyQt5 `_ packages as preinstalled extensions. + +If you want to call other third-party Python modules from your OVITO scripts, it may be possible to install them in the +:program:`ovitos` interpreter using the normal *pip* or *setuptools* mechanisms +(e.g., run :command:`ovitos -m pip install ` to install a module via *pip*). -In addition to non-interactive scripts that execute program commands and automate tasks, OVITO provides two more uses of the built-in script interpreter: -You can :ref:`write your own modifier function ` using Python, which can then also be used within the graphical program like the -standard modifiers. Or you can write a `custom viewport overlay <../../viewport_overlays.python_script.html>`_, which is a script function -that can draw arbitrary graphical content into an image or movie rendered by OVITO. +Installing Python extensions that include native code (e.g. `Scipy `_) in the embedded interpreter +will likely fail however. In this case it is recommended to build OVITO from source on your local system. +The graphical program and :program:`ovitos` will then both make use of your system's standard Python interpreter instead of the built-in interpreter. +This makes all modules that are installed in your Python interpreter accessible within OVITO and :program:`ovitos` as well. +How to build OVITO from source is described `on this page `_. + +Using the ovito package from other Python interpreters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The :py:mod:`ovito` Python package can also be imported by standard Python scripts running in an external Python interpreter. +However, because this module contains native extensions, it must be compiled specifically for the Python interpreter being used. +Since there is a chance that the precompiled version of the module shipping with the binary OVITO installation is not compatible +with your Python interpreter, it might thus be necessary to `build OVITO from source `_. +Make sure you link against the Python interpreter which you are going to run your scripts with. + +Once the graphical program and the :py:mod:`ovito` Python extension module have been built, you can make the module loadable from your +Python interpreter by adding the following directory to the `PYTHONPATH `_: + +=============== =========================================================== +Platform: Location of ovito package relative to build path: +=============== =========================================================== +Windows :file:`plugins/python/` +Linux :file:`lib/ovito/plugins/python/` +macOS :file:`Ovito.app/Contents/Resources/python/` +=============== =========================================================== diff -Nru ovito-2.8.1+dfsg2/examples/scripts/ase-interface.py ovito-2.9.0+dfsg1/examples/scripts/ase-interface.py --- ovito-2.8.1+dfsg2/examples/scripts/ase-interface.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/examples/scripts/ase-interface.py 2017-07-27 16:52:45.000000000 +0000 @@ -2,7 +2,7 @@ import numpy as np -from ovito import * +import ovito from ovito.data import * from ovito.modifiers import * @@ -29,13 +29,13 @@ # Create a node and insert it into the scene node = ObjectNode() node.source = data -dataset.scene_nodes.append(node) +ovito.dataset.scene_nodes.append(node) new_data = node.compute() # Select the new node and adjust viewport cameras to show everything. -dataset.selected_node = node -for vp in dataset.viewports: +ovito.dataset.selected_node = node +for vp in ovito.dataset.viewports: vp.zoom_all() # Do the reverse conversion, after pipeline has been applied diff -Nru ovito-2.8.1+dfsg2/examples/scripts/demo1.py ovito-2.9.0+dfsg1/examples/scripts/demo1.py --- ovito-2.8.1+dfsg2/examples/scripts/demo1.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/examples/scripts/demo1.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -# Import OVITO modules. -from ovito import * -from ovito.io import * -from ovito.modifiers import * -from ovito.vis import * -from ovito.data import * - -# Import modules from standard Python library. -import math -import numpy as np - -# Query program version. -print("This is Ovito version", version) - -# Import a data file. -node = import_file("../data/NanocrystallinePd.dump.gz") - -# Apply a modifier to the dataset. -node.modifiers.append(ColorCodingModifier( - property = ParticleProperty.Type.PotentialEnergy, - gradient = ColorCodingModifier.Hot() -)) - -# Set up view, looking along the [2,3,-3] direction from camera position (-100, -150, 150). -vp = Viewport() -vp.type = Viewport.Type.PERSPECTIVE -vp.camera_pos = (-100, -150, 150) -vp.camera_dir = (2, 3, -3) -vp.fov = math.radians(60.0) - -settings = RenderSettings( - filename = "rendered_image.png", - size = (220,220) -) - -# Render a picture of the dataset. -vp.render(settings) - -# Apply two more modifiers to delete some particles. -node.modifiers.append(SelectExpressionModifier(expression = "PotentialEnergy < -3.9")) -node.modifiers.append(DeleteSelectedParticlesModifier()) - -# Print the modification pipeline of the selected node to the console. -print("Modification pipeline:") -print(node.modifiers) - -# Perform some analysis. -cna = CommonNeighborAnalysisModifier() -node.modifiers.append(cna) - -# Block execution of the script until the node's modification pipeline is ready, that is, until -# the results of all modifiers have been computed. -node.compute() -for c in enumerate(cna.counts): - print("Type %i: %i particles" % c) -print(node.output['Position'].array) -for t in node.output.particle_properties.structure_type.type_list: - print(t.id, t.name, t.color) - -# Read out analysis results. -print("Number of FCC atoms:", cna.counts[CommonNeighborAnalysisModifier.Type.FCC]) - -# Write processed atoms back to an output file. -export_file(node, "exported_data.dump", "lammps_dump", - columns = ["Position.X", "Position.Y", "Position.Z", "Structure Type"] -) diff -Nru ovito-2.8.1+dfsg2/examples/scripts/export_bond_count.py ovito-2.9.0+dfsg1/examples/scripts/export_bond_count.py --- ovito-2.8.1+dfsg2/examples/scripts/export_bond_count.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/examples/scripts/export_bond_count.py 2017-07-27 16:52:45.000000000 +0000 @@ -4,15 +4,14 @@ You should run this script from within the graphical user interface using the Scripting->Run Script File menu option. """ -from ovito import * +import ovito from ovito.data import * # Open output file for writing: fout = open("outputfile.txt", "w") -for frame in range(dataset.anim.first_frame, dataset.anim.last_frame+1): - dataset.anim.current_frame = frame - data = dataset.selected_node.compute() +for frame in range(ovito.dataset.anim.first_frame, dataset.anim.last_frame+1): + data = dataset.selected_node.compute(frame) num_bonds = len(data.bonds.array) // 2 # Divide by 2 because each bond is represented by two half-bonds. print(frame, num_bonds, file = fout) diff -Nru ovito-2.8.1+dfsg2/examples/scripts/export_dislocations.py ovito-2.9.0+dfsg1/examples/scripts/export_dislocations.py --- ovito-2.8.1+dfsg2/examples/scripts/export_dislocations.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/examples/scripts/export_dislocations.py 2017-07-27 16:52:45.000000000 +0000 @@ -5,7 +5,7 @@ You should run this script from within the graphical user interface using the Scripting->Run Script File menu option. """ -from ovito import * +import ovito from ovito.data import * def export_dislocations(disloc_network): @@ -18,8 +18,8 @@ # Loop over all objects in the scene and # find one that contains dislocation data. # Then call export_dislocations(). -for i in range(len(dataset.scene_nodes)): - node = dataset.scene_nodes[i] +for i in range(len(ovito.dataset.scene_nodes)): + node = ovito.dataset.scene_nodes[i] data = node.compute() if hasattr(data, 'dislocations'): export_dislocations(data.dislocations) diff -Nru ovito-2.8.1+dfsg2/examples/scripts/export_point_defect_counts.py ovito-2.9.0+dfsg1/examples/scripts/export_point_defect_counts.py --- ovito-2.8.1+dfsg2/examples/scripts/export_point_defect_counts.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/examples/scripts/export_point_defect_counts.py 2017-07-27 16:52:45.000000000 +0000 @@ -5,13 +5,13 @@ You should run this script from within the graphical user interface using the Scripting->Run Script File menu option. """ -from ovito import * +import ovito from ovito.data import * from ovito.modifiers import * # Find the WS modifier in the pipeline: ws_mod = None -for modifier in dataset.selected_node.modifiers: +for modifier in ovito.dataset.selected_node.modifiers: if isinstance(modifier, WignerSeitzAnalysisModifier): ws_mod = modifier if ws_mod is None: @@ -20,9 +20,8 @@ # Open output file for writing: fout = open("outputfile.txt", "w") -for frame in range(dataset.anim.first_frame, dataset.anim.last_frame+1): - dataset.anim.current_frame = frame - dataset.selected_node.compute() +for frame in range(ovito.dataset.anim.first_frame, ovito.dataset.anim.last_frame+1): + ovito.dataset.selected_node.compute(frame) num_vacancies = ws_mod.vacancy_count num_interstitials = ws_mod.interstitial_count print(frame, num_vacancies, num_interstitials, file = fout) diff -Nru ovito-2.8.1+dfsg2/examples/scripts/export_to_idtf.py ovito-2.9.0+dfsg1/examples/scripts/export_to_idtf.py --- ovito-2.8.1+dfsg2/examples/scripts/export_to_idtf.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/examples/scripts/export_to_idtf.py 2017-07-27 16:52:45.000000000 +0000 @@ -9,7 +9,7 @@ """ import sys -from ovito import * +import ovito from ovito.data import * from ovito.vis import * @@ -117,8 +117,8 @@ export_simulation_cell(group_name, data.cell) # Loop over scene nodes. -for i in range(len(dataset.scene_nodes)): - export_node(dataset.scene_nodes[i]) +for i in range(len(ovito.dataset.scene_nodes)): + export_node(ovito.dataset.scene_nodes[i]) # Write node resources. diff -Nru ovito-2.8.1+dfsg2/.gitlab-ci.yml ovito-2.9.0+dfsg1/.gitlab-ci.yml --- ovito-2.8.1+dfsg2/.gitlab-ci.yml 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/.gitlab-ci.yml 2017-07-27 16:52:45.000000000 +0000 @@ -16,6 +16,7 @@ libavutil-dev libswscale-dev libnetcdf-dev + libfftw3-dev libhdf5-dev libhdf5-serial-dev libbotan1.10-dev @@ -27,11 +28,18 @@ python3-sip python3-pyqt5 python3-matplotlib + python-dev + python-sphinx + python-numpy + python-sip + python-pyqt5 + python-matplotlib xsltproc docbook-xml povray + linkchecker -build_linux: +build_linux_python3: stage: build tags: - linux @@ -41,9 +49,34 @@ - cmake -DCMAKE_BUILD_TYPE=Debug -DOVITO_BUILD_DOCUMENTATION=ON + -DPYTHON_EXECUTABLE=/usr/bin/python3.5 -DPYTHON_INCLUDE_DIR=/usr/include/python3.5m -DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython3.5m.so -DCMAKE_INSTALL_PREFIX=../install .. - - make -j2 install - - ctest --output-on-failure \ No newline at end of file + - make -j4 install + - ctest --output-on-failure + - linkchecker --check-extern ../install/share/ovito/doc/manual/html/index.html + --ignore-url=https://dx.doi.org/10.1088/0965-0393/24/5/055007 + --ignore-url=http://stacks.iop.org/0965-0393/18/015012 + --ignore-url=http://dx.doi.org/10.1088/0965-0393/20/3/035012 + --ignore-url=http://dx.doi.org/10.1088/0965-0393/20/4/045021 + --ignore-url=http://dx.doi.org/10.1038/nature04421 + +build_linux_python2: + stage: build + tags: + - linux + script: + - mkdir build + - cd build + - cmake + -DCMAKE_BUILD_TYPE=Debug + -DOVITO_BUILD_DOCUMENTATION=ON + -DPYTHON_EXECUTABLE=/usr/bin/python2.7 + -DPYTHON_INCLUDE_DIR=/usr/include/python2.7 + -DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython2.7.so + -DCMAKE_INSTALL_PREFIX=../install + .. + - make -j4 install + - ctest --output-on-failure diff -Nru ovito-2.8.1+dfsg2/src/3rdparty/qssh/CMakeLists.txt ovito-2.9.0+dfsg1/src/3rdparty/qssh/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/3rdparty/qssh/CMakeLists.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/3rdparty/qssh/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -61,13 +61,13 @@ TARGET_INCLUDE_DIRECTORIES(QSsh PUBLIC "$") # Make this library part of the installation package. -IF(NOT OVITO_MONOLITHIC_BUILD) +IF(OVITO_DEFAULT_LIBRARY_TYPE STREQUAL SHARED) INSTALL(TARGETS QSsh EXPORT OVITO RUNTIME DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}" LIBRARY DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}") ENDIF() -SET_TARGET_PROPERTIES(QSsh PROPERTIES MACOSX_RPATH TRUE) +SET_TARGET_PROPERTIES(QSsh PROPERTIES MACOSX_RPATH TRUE) # Export target to make it accessible for external plugins. IF(CMAKE_VERSION VERSION_LESS "3") Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/src/3rdparty/tachyon/.DS_Store and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/src/3rdparty/tachyon/.DS_Store differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/src/3rdparty/tachyon/tachyon/.DS_Store and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/src/3rdparty/tachyon/tachyon/.DS_Store differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/src/3rdparty/tachyon/unix/.DS_Store and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/src/3rdparty/tachyon/unix/.DS_Store differ diff -Nru ovito-2.8.1+dfsg2/src/CMakeLists.txt ovito-2.9.0+dfsg1/src/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/CMakeLists.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -52,7 +52,9 @@ ################### Main executable ####################### -ADD_SUBDIRECTORY(main) +IF(OVITO_BUILD_GUI) + ADD_SUBDIRECTORY(main) +ENDIF() # Propagate list of plugins to parent scope. SET(OVITO_PLUGIN_LIST ${OVITO_PLUGIN_LIST} PARENT_SCOPE) diff -Nru ovito-2.8.1+dfsg2/src/core/animation/AnimationSettings.cpp ovito-2.9.0+dfsg1/src/core/animation/AnimationSettings.cpp --- ovito-2.8.1+dfsg2/src/core/animation/AnimationSettings.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/AnimationSettings.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,26 +26,26 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Anim) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, AnimationSettings, RefTarget); -DEFINE_FLAGS_PROPERTY_FIELD(AnimationSettings, _time, "Time", PROPERTY_FIELD_NO_UNDO); -DEFINE_PROPERTY_FIELD(AnimationSettings, _animationInterval, "AnimationInterval"); -DEFINE_PROPERTY_FIELD(AnimationSettings, _ticksPerFrame, "TicksPerFrame"); -DEFINE_PROPERTY_FIELD(AnimationSettings, _playbackSpeed, "PlaybackSpeed"); -DEFINE_PROPERTY_FIELD(AnimationSettings, _loopPlayback, "LoopPlayback"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(AnimationSettings, RefTarget); +DEFINE_FLAGS_PROPERTY_FIELD(AnimationSettings, time, "Time", PROPERTY_FIELD_NO_UNDO); +DEFINE_PROPERTY_FIELD(AnimationSettings, animationInterval, "AnimationInterval"); +DEFINE_PROPERTY_FIELD(AnimationSettings, ticksPerFrame, "TicksPerFrame"); +DEFINE_PROPERTY_FIELD(AnimationSettings, playbackSpeed, "PlaybackSpeed"); +DEFINE_PROPERTY_FIELD(AnimationSettings, loopPlayback, "LoopPlayback"); /****************************************************************************** * Constructor. ******************************************************************************/ AnimationSettings::AnimationSettings(DataSet* dataset) : RefTarget(dataset), _ticksPerFrame(TICKS_PER_SECOND/10), _playbackSpeed(1), - _animationInterval(0, 0), _time(0), _animSuspendCount(0), _autoKeyMode(false), _timeIsChanging(0), - _isPlaybackActive(false), _loopPlayback(true) + _animationInterval(0, 0), _time(0), + _loopPlayback(true) { - INIT_PROPERTY_FIELD(AnimationSettings::_time); - INIT_PROPERTY_FIELD(AnimationSettings::_animationInterval); - INIT_PROPERTY_FIELD(AnimationSettings::_ticksPerFrame); - INIT_PROPERTY_FIELD(AnimationSettings::_playbackSpeed); - INIT_PROPERTY_FIELD(AnimationSettings::_loopPlayback); + INIT_PROPERTY_FIELD(time); + INIT_PROPERTY_FIELD(animationInterval); + INIT_PROPERTY_FIELD(ticksPerFrame); + INIT_PROPERTY_FIELD(playbackSpeed); + INIT_PROPERTY_FIELD(loopPlayback); // Call our own listener when the current animation time changes. connect(this, &AnimationSettings::timeChanged, this, &AnimationSettings::onTimeChanged); @@ -56,11 +56,11 @@ ******************************************************************************/ void AnimationSettings::propertyChanged(const PropertyFieldDescriptor& field) { - if(field == PROPERTY_FIELD(AnimationSettings::_time)) + if(field == PROPERTY_FIELD(time)) Q_EMIT timeChanged(time()); - else if(field == PROPERTY_FIELD(AnimationSettings::_animationInterval)) + else if(field == PROPERTY_FIELD(animationInterval)) Q_EMIT intervalChanged(animationInterval()); - else if(field == PROPERTY_FIELD(AnimationSettings::_ticksPerFrame)) + else if(field == PROPERTY_FIELD(ticksPerFrame)) Q_EMIT speedChanged(ticksPerFrame()); } @@ -105,11 +105,20 @@ ******************************************************************************/ void AnimationSettings::onTimeChanged(TimePoint newTime) { - _timeIsChanging++; - dataset()->runWhenSceneIsReady([this] () { - _timeIsChanging--; + if(_isTimeChanging) { + dataset()->makeSceneReady(); + return; + } + _isTimeChanging = true; + + // Wait until scene is complete, then generate a timeChangeComplete event. + PromiseWatcher* watcher = new PromiseWatcher(this); + connect(watcher, &PromiseWatcher::finished, this, [this] { + _isTimeChanging = false; Q_EMIT timeChangeComplete(); }); + connect(watcher, &PromiseWatcher::finished, watcher, &QObject::deleteLater); // Self-destruct watcher object when it's no longer needed. + watcher->setFuture(dataset()->makeSceneReady()); } /****************************************************************************** @@ -193,7 +202,7 @@ ******************************************************************************/ void AnimationSettings::startAnimationPlayback() { - if(!_isPlaybackActive) { + if(!isPlaybackActive()) { _isPlaybackActive = true; Q_EMIT playbackChanged(_isPlaybackActive); @@ -201,21 +210,35 @@ scheduleNextAnimationFrame(); } else { - setTime(animationInterval().start()); - dataset()->runWhenSceneIsReady([this]() { - if(_isPlaybackActive) { - scheduleNextAnimationFrame(); - } - }); + continuePlaybackAtTime(animationInterval().start()); } } } /****************************************************************************** +* Jumps to the given animation time, then schedules the next frame as soon as +* the scene was completely shown. +******************************************************************************/ +void AnimationSettings::continuePlaybackAtTime(TimePoint time) +{ + setTime(time); + + if(isPlaybackActive()) { + PromiseWatcher* watcher = new PromiseWatcher(this); + connect(watcher, &PromiseWatcher::finished, this, &AnimationSettings::scheduleNextAnimationFrame); + connect(watcher, &PromiseWatcher::canceled, this, &AnimationSettings::stopAnimationPlayback); + connect(watcher, &PromiseWatcher::finished, watcher, &QObject::deleteLater); // Self-destruct watcher object when it's no longer needed. + watcher->setFuture(dataset()->makeSceneReady()); + } +} + +/****************************************************************************** * Starts a timer to show the next animation frame. ******************************************************************************/ void AnimationSettings::scheduleNextAnimationFrame() { + if(!isPlaybackActive()) return; + int timerSpeed = 1000; if(playbackSpeed() > 1) timerSpeed /= playbackSpeed(); else if(playbackSpeed() < -1) timerSpeed *= -playbackSpeed(); @@ -227,7 +250,7 @@ ******************************************************************************/ void AnimationSettings::stopAnimationPlayback() { - if(_isPlaybackActive) { + if(isPlaybackActive()) { _isPlaybackActive = false; Q_EMIT playbackChanged(_isPlaybackActive); } @@ -239,7 +262,7 @@ void AnimationSettings::onPlaybackTimer() { // Check if the animation playback has been deactivated in the meantime. - if(!_isPlaybackActive) + if(!isPlaybackActive()) return; // Add one frame to current time @@ -257,17 +280,8 @@ } } - // Set new time. - setTime(newTime); - - // Wait until the scene is ready. Then jump to the next frame. - if(_isPlaybackActive) { - dataset()->runWhenSceneIsReady([this]() { - if(_isPlaybackActive) { - scheduleNextAnimationFrame(); - } - }); - } + // Set new time and continue playing. + continuePlaybackAtTime(newTime); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/core/animation/AnimationSettings.h ovito-2.9.0+dfsg1/src/core/animation/AnimationSettings.h --- ovito-2.8.1+dfsg2/src/core/animation/AnimationSettings.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/AnimationSettings.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ANIMATION_SETTINGS_H -#define __OVITO_ANIMATION_SETTINGS_H +#pragma once + #include #include @@ -63,32 +63,6 @@ /// \brief Constructor that initializes the object with default values. /// \param dataset The context dataset. Q_INVOKABLE AnimationSettings(DataSet* dataset); - - /// \brief Gets the current animation time. - /// \return The current time. - /// - /// The state of the scene at this time is shown in the viewports. - /// \sa setTime() - TimePoint time() const { return _time; } - - /// \brief Sets the current animation time. - /// \param time The new animation time. - /// - /// The state of the scene at the given time will be shown in the viewports. - /// \undoable - /// \sa time() - void setTime(TimePoint time) { _time = time; } - - /// \brief Gets the animation interval. - /// \return The time interval of the animation. - /// \sa setAnimationInterval() - const TimeInterval& animationInterval() const { return _animationInterval; } - - /// \brief Sets the animation interval. - /// \param interval The new animation interval for the scene. - /// \undoable - /// \sa animationInterval() - void setAnimationInterval(const TimeInterval& interval) { _animationInterval = interval; } /// \brief Returns the number of frames per second. /// \return The number of frames per second. @@ -96,7 +70,7 @@ /// This setting controls the playback speed of the animation. /// /// \sa setFramesPerSecond() - int framesPerSecond() const { return TICKS_PER_SECOND / _ticksPerFrame; } + int framesPerSecond() const { return TICKS_PER_SECOND / ticksPerFrame(); } /// \brief Sets the number of frames per second. /// \param fps The number of frames per second. Please note that not all @@ -110,23 +84,6 @@ /// \sa setTicksPerFrame() void setFramesPerSecond(int fps) { setTicksPerFrame(TICKS_PER_SECOND / fps); } - /// \brief Returns the number of time ticks per frame. - /// \return The number of time ticks per animation frame. One tick is 1/4800 of a second. - /// - /// This setting controls the playback speed of the animation. - /// - /// \sa setTicksPerFrame() - int ticksPerFrame() const { return _ticksPerFrame; } - - /// \brief Sets the number of time ticks per frame. - /// \param ticksPerFrame The number of time tick units per animation frame. - /// This must be a positive value. - /// \undoable - /// - /// This setting controls the playback speed of the animation. - /// \sa ticksPerFrame() - void setTicksPerFrame(int ticksPerFrame) { _ticksPerFrame = ticksPerFrame; } - /// \brief Gets the current animation frame. /// \return The current frame. int currentFrame() const { return timeToFrame(time()); } @@ -162,19 +119,6 @@ TimePoint snapTime(TimePoint time) const { return frameToTime(timeToFrame(time + ticksPerFrame()/(time >= 0 ? 2 : -2))); } - - /// \brief Returns the playback speed factor that is used for animation playback in the viewports. - /// \return The playback speed factor. A value greater than 1 means that the animation is played at a speed higher - /// than realtime whereas a value smaller than -1 means that the animation is played at a speed lower than realtime. - /// \sa setPlaybackSpeed() - int playbackSpeed() const { return _playbackSpeed; } - - /// \brief Sets the playback speed factor that is used for animation playback in the viewport. - /// \param factor A value greater than 1 means that the animation is played at a speed higher - /// than realtime. A value smaller than -1 that the animation is played at a speed lower than realtime. - /// \undoable - /// \sa playbackSpeed() - void setPlaybackSpeed(int factor) { _playbackSpeed = factor; } /// \brief Returns the list of names assigned to animation frames. const QMap& namedFrames() const { return _namedFrames; } @@ -230,10 +174,7 @@ /// \brief Indicates that the animation time has recently been changed via setTime(), and the scene /// is still being prepared for displaying the new frame. - bool isTimeChanging() const { return _timeIsChanging != 0; } - - /// Returns whether the animation is played back in a loop in the interactive viewports. - bool loopPlayback() const { return _loopPlayback; } + bool isTimeChanging() const { return _isTimeChanging; } /// Returns whether the animation is currently being played back in the viewports. bool isPlaybackActive() const { return _isPlaybackActive; } @@ -305,6 +246,9 @@ /// \brief Timer callback used during animation playback. void onPlaybackTimer(); + /// Starts a timer to show the next animation frame. + void scheduleNextAnimationFrame(); + protected: /// \brief Is called when the value of a non-animatable property field of this RefMaker has changed. @@ -319,55 +263,47 @@ /// \brief Creates a copy of this object. virtual OORef clone(bool deepCopy, CloneHelper& cloneHelper) override; - /// Starts a timer to show the next animation frame. - void scheduleNextAnimationFrame(); + /// Jumps to the given animation time, then schedules the next frame as soon as the scene was completely shown. + void continuePlaybackAtTime(TimePoint time); private: /// The current animation time. - PropertyField _time; + DECLARE_MODIFIABLE_PROPERTY_FIELD(TimePoint, time, setTime); /// The start and end times of the animation. - PropertyField _animationInterval; + DECLARE_MODIFIABLE_PROPERTY_FIELD(TimeInterval, animationInterval, setAnimationInterval); /// The number of time ticks per frame. /// This controls the animation speed. - PropertyField _ticksPerFrame; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, ticksPerFrame, setTicksPerFrame); /// The playback speed factor that is used for animation playback in the viewport. /// A value greater than 1 means that the animation is played at a speed higher /// than realtime. /// A value smaller than -1 that the animation is played at a speed lower than realtime. - PropertyField _playbackSpeed; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, playbackSpeed, setPlaybackSpeed); /// List of names assigned to animation frames. QMap _namedFrames; /// Counts the number of times the animation modes has been suspended. - int _animSuspendCount; + int _animSuspendCount = 0; /// Indicates whether animation recording mode is active. - bool _autoKeyMode; + bool _autoKeyMode = false; /// Indicates that the animation has been changed, and the scene is still being prepared for display of the new frame. - int _timeIsChanging; + bool _isTimeChanging = false; /// Indicates that the animation is currently being played back in the viewports. - bool _isPlaybackActive; + bool _isPlaybackActive = false; /// Controls whether the animation is played back in a loop in the interactive viewports. - PropertyField _loopPlayback; - -private: + DECLARE_PROPERTY_FIELD(bool, loopPlayback); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_time); - DECLARE_PROPERTY_FIELD(_animationInterval); - DECLARE_PROPERTY_FIELD(_ticksPerFrame); - DECLARE_PROPERTY_FIELD(_playbackSpeed); - DECLARE_PROPERTY_FIELD(_loopPlayback); }; /** @@ -405,4 +341,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ANIMATION_SETTINGS_H + diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/AnimationKeys.cpp ovito-2.9.0+dfsg1/src/core/animation/controller/AnimationKeys.cpp --- ovito-2.8.1+dfsg2/src/core/animation/controller/AnimationKeys.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/AnimationKeys.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,34 +24,34 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Anim) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, AnimationKey, RefTarget); -DEFINE_PROPERTY_FIELD(AnimationKey, _time, "Time"); -SET_PROPERTY_FIELD_LABEL(AnimationKey, _time, "Time"); -SET_PROPERTY_FIELD_UNITS(AnimationKey, _time, TimeParameterUnit); - -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, FloatAnimationKey, AnimationKey); -DEFINE_PROPERTY_FIELD(FloatAnimationKey, _value, "Value"); -SET_PROPERTY_FIELD_LABEL(FloatAnimationKey, _value, "Value"); - -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, IntegerAnimationKey, AnimationKey); -DEFINE_PROPERTY_FIELD(IntegerAnimationKey, _value, "Value"); -SET_PROPERTY_FIELD_LABEL(IntegerAnimationKey, _value, "Value"); - -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, Vector3AnimationKey, AnimationKey); -DEFINE_PROPERTY_FIELD(Vector3AnimationKey, _value, "Value"); -SET_PROPERTY_FIELD_LABEL(Vector3AnimationKey, _value, "Value"); - -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, PositionAnimationKey, AnimationKey); -DEFINE_PROPERTY_FIELD(PositionAnimationKey, _value, "Value"); -SET_PROPERTY_FIELD_LABEL(PositionAnimationKey, _value, "Value"); - -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, RotationAnimationKey, AnimationKey); -DEFINE_PROPERTY_FIELD(RotationAnimationKey, _value, "Value"); -SET_PROPERTY_FIELD_LABEL(RotationAnimationKey, _value, "Value"); - -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, ScalingAnimationKey, AnimationKey); -DEFINE_PROPERTY_FIELD(ScalingAnimationKey, _value, "Value"); -SET_PROPERTY_FIELD_LABEL(ScalingAnimationKey, _value, "Value"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(AnimationKey, RefTarget); +DEFINE_PROPERTY_FIELD(AnimationKey, time, "Time"); +SET_PROPERTY_FIELD_LABEL(AnimationKey, time, "Time"); +SET_PROPERTY_FIELD_UNITS(AnimationKey, time, TimeParameterUnit); + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(FloatAnimationKey, AnimationKey); +DEFINE_PROPERTY_FIELD(FloatAnimationKey, value, "Value"); +SET_PROPERTY_FIELD_LABEL(FloatAnimationKey, value, "Value"); + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(IntegerAnimationKey, AnimationKey); +DEFINE_PROPERTY_FIELD(IntegerAnimationKey, value, "Value"); +SET_PROPERTY_FIELD_LABEL(IntegerAnimationKey, value, "Value"); + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Vector3AnimationKey, AnimationKey); +DEFINE_PROPERTY_FIELD(Vector3AnimationKey, value, "Value"); +SET_PROPERTY_FIELD_LABEL(Vector3AnimationKey, value, "Value"); + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(PositionAnimationKey, AnimationKey); +DEFINE_PROPERTY_FIELD(PositionAnimationKey, value, "Value"); +SET_PROPERTY_FIELD_LABEL(PositionAnimationKey, value, "Value"); + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(RotationAnimationKey, AnimationKey); +DEFINE_PROPERTY_FIELD(RotationAnimationKey, value, "Value"); +SET_PROPERTY_FIELD_LABEL(RotationAnimationKey, value, "Value"); + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ScalingAnimationKey, AnimationKey); +DEFINE_PROPERTY_FIELD(ScalingAnimationKey, value, "Value"); +SET_PROPERTY_FIELD_LABEL(ScalingAnimationKey, value, "Value"); OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/AnimationKeys.h ovito-2.9.0+dfsg1/src/core/animation/controller/AnimationKeys.h --- ovito-2.8.1+dfsg2/src/core/animation/controller/AnimationKeys.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/AnimationKeys.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,7 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ANIMATION_KEYS_H -#define __OVITO_ANIMATION_KEYS_H +#pragma once #include #include @@ -37,12 +36,9 @@ /// Constructor. AnimationKey(DataSet* dataset, TimePoint time = 0) : RefTarget(dataset), _time(time) { - INIT_PROPERTY_FIELD(AnimationKey::_time); + INIT_PROPERTY_FIELD(time); } - /// Returns the animation time at which the key is set. - TimePoint time() const { return _time; } - /// Returns the value of this animation key as a QVariant. virtual QVariant valueQVariant() const = 0; @@ -51,47 +47,32 @@ private: - /// Changes the key's time position. - void setTime(TimePoint newTime) { _time = newTime; } - /// The animation time at which the key is positioned. - PropertyField _time; + DECLARE_MODIFIABLE_PROPERTY_FIELD(TimePoint, time, setTime); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_time); - - friend class KeyframeController; }; /** - * \brief Base template class for animation keys. + * \brief Animation key class for float controllers. */ -template -class TypedAnimationKey : public AnimationKey +class OVITO_CORE_EXPORT FloatAnimationKey : public AnimationKey { public: /// The type of value stored by this animation key. - typedef ValueType value_type; + using value_type = FloatType; /// The type used to initialize default values of this key. - typedef NullValue nullvalue_type; + using nullvalue_type = FloatType; /// The type used for derivatives/tangents. - typedef TangentType tangent_type; + using tangent_type = FloatType; /// Constructor. - TypedAnimationKey(DataSet* dataset, TimePoint time = 0, const value_type& value = nullvalue_type()) : AnimationKey(dataset, time), _value(value) {} - - /// Returns the value of this animation key. - const value_type& value() const { return _value; } - - /// Changes the key's value. - bool setValue(const value_type& newValue) { - _value = newValue; - return true; + Q_INVOKABLE FloatAnimationKey(DataSet* dataset, TimePoint time = 0, FloatType value = 0) : AnimationKey(dataset, time), _value(value) { + INIT_PROPERTY_FIELD(value); } /// Returns the value of this animation key as a QVariant. @@ -102,28 +83,8 @@ /// Sets the value of the key. virtual bool setValueQVariant(const QVariant& v) override { if(!v.canConvert()) return false; - return setValue(v.value()); - } - -protected: - - /// The key's value. - PropertyField _value; - - friend class KeyframeController; -}; - - -/** - * \brief Animation key class for float controllers. - */ -class OVITO_CORE_EXPORT FloatAnimationKey : public TypedAnimationKey -{ -public: - - /// Constructor. - Q_INVOKABLE FloatAnimationKey(DataSet* dataset, TimePoint time = 0, FloatType value = 0) : TypedAnimationKey(dataset, time, value) { - INIT_PROPERTY_FIELD(FloatAnimationKey::_value); + setValue(v.value()); + return true; } private: @@ -131,19 +92,41 @@ Q_OBJECT OVITO_OBJECT - DECLARE_PROPERTY_FIELD(_value); + /// Stores the value of the key. + DECLARE_MODIFIABLE_PROPERTY_FIELD(value_type, value, setValue); }; /** * \brief Animation key class for integer controllers. */ -class OVITO_CORE_EXPORT IntegerAnimationKey : public TypedAnimationKey +class OVITO_CORE_EXPORT IntegerAnimationKey : public AnimationKey { public: + /// The type of value stored by this animation key. + using value_type = int; + + /// The type used to initialize default values of this key. + using nullvalue_type = int; + + /// The type used for derivatives/tangents. + using tangent_type = int; + /// Constructor. - Q_INVOKABLE IntegerAnimationKey(DataSet* dataset, TimePoint time = 0, int value = 0) : TypedAnimationKey(dataset, time, value) { - INIT_PROPERTY_FIELD(IntegerAnimationKey::_value); + Q_INVOKABLE IntegerAnimationKey(DataSet* dataset, TimePoint time = 0, int value = 0) : AnimationKey(dataset, time), _value(value) { + INIT_PROPERTY_FIELD(value); + } + + /// Returns the value of this animation key as a QVariant. + virtual QVariant valueQVariant() const override { + return QVariant::fromValue(value()); + } + + /// Sets the value of the key. + virtual bool setValueQVariant(const QVariant& v) override { + if(!v.canConvert()) return false; + setValue(v.value()); + return true; } private: @@ -151,19 +134,41 @@ Q_OBJECT OVITO_OBJECT - DECLARE_PROPERTY_FIELD(_value); + /// Stores the value of the key. + DECLARE_MODIFIABLE_PROPERTY_FIELD(value_type, value, setValue); }; /** * \brief Animation key class for Vector3 controllers. */ -class OVITO_CORE_EXPORT Vector3AnimationKey : public TypedAnimationKey +class OVITO_CORE_EXPORT Vector3AnimationKey : public AnimationKey { public: + /// The type of value stored by this animation key. + using value_type = Vector3; + + /// The type used to initialize default values of this key. + using nullvalue_type = Vector3::Zero; + + /// The type used for derivatives/tangents. + using tangent_type = Vector3; + /// Constructor. - Q_INVOKABLE Vector3AnimationKey(DataSet* dataset, TimePoint time = 0, const Vector3& value = Vector3::Zero()) : TypedAnimationKey(dataset, time, value) { - INIT_PROPERTY_FIELD(Vector3AnimationKey::_value); + Q_INVOKABLE Vector3AnimationKey(DataSet* dataset, TimePoint time = 0, const Vector3& value = Vector3::Zero()) : AnimationKey(dataset, time), _value(value) { + INIT_PROPERTY_FIELD(value); + } + + /// Returns the value of this animation key as a QVariant. + virtual QVariant valueQVariant() const override { + return QVariant::fromValue(value()); + } + + /// Sets the value of the key. + virtual bool setValueQVariant(const QVariant& v) override { + if(!v.canConvert()) return false; + setValue(v.value()); + return true; } private: @@ -171,67 +176,134 @@ Q_OBJECT OVITO_OBJECT - DECLARE_PROPERTY_FIELD(_value); + /// Stores the value of the key. + DECLARE_MODIFIABLE_PROPERTY_FIELD(value_type, value, setValue); }; /** * \brief Animation key class for position controllers. */ -class OVITO_CORE_EXPORT PositionAnimationKey : public TypedAnimationKey +class OVITO_CORE_EXPORT PositionAnimationKey : public AnimationKey { public: + /// The type of value stored by this animation key. + using value_type = Vector3; + + /// The type used to initialize default values of this key. + using nullvalue_type = Vector3::Zero; + + /// The type used for derivatives/tangents. + using tangent_type = Vector3; + /// Constructor. - Q_INVOKABLE PositionAnimationKey(DataSet* dataset, TimePoint time = 0, const Vector3& value = Vector3::Zero()) : TypedAnimationKey(dataset, time, value) { - INIT_PROPERTY_FIELD(PositionAnimationKey::_value); + Q_INVOKABLE PositionAnimationKey(DataSet* dataset, TimePoint time = 0, const Vector3& value = Vector3::Zero()) : AnimationKey(dataset, time), _value(value) { + INIT_PROPERTY_FIELD(value); } + /// Returns the value of this animation key as a QVariant. + virtual QVariant valueQVariant() const override { + return QVariant::fromValue(value()); + } + + /// Sets the value of the key. + virtual bool setValueQVariant(const QVariant& v) override { + if(!v.canConvert()) return false; + setValue(v.value()); + return true; + } + private: Q_OBJECT OVITO_OBJECT - DECLARE_PROPERTY_FIELD(_value); + /// Stores the value of the key. + DECLARE_MODIFIABLE_PROPERTY_FIELD(value_type, value, setValue); }; /** * \brief Animation key class for rotation controllers. */ -class OVITO_CORE_EXPORT RotationAnimationKey : public TypedAnimationKey +class OVITO_CORE_EXPORT RotationAnimationKey : public AnimationKey { public: + /// The type of value stored by this animation key. + using value_type = Rotation; + + /// The type used to initialize default values of this key. + using nullvalue_type = Rotation::Identity; + + /// The type used for derivatives/tangents. + using tangent_type = Rotation; + /// Constructor. - Q_INVOKABLE RotationAnimationKey(DataSet* dataset, TimePoint time = 0, const Rotation& value = Rotation::Identity()) : TypedAnimationKey(dataset, time, value) { - INIT_PROPERTY_FIELD(RotationAnimationKey::_value); + Q_INVOKABLE RotationAnimationKey(DataSet* dataset, TimePoint time = 0, const Rotation& value = Rotation::Identity()) : AnimationKey(dataset, time), _value(value) { + INIT_PROPERTY_FIELD(value); } + /// Returns the value of this animation key as a QVariant. + virtual QVariant valueQVariant() const override { + return QVariant::fromValue(value()); + } + + /// Sets the value of the key. + virtual bool setValueQVariant(const QVariant& v) override { + if(!v.canConvert()) return false; + setValue(v.value()); + return true; + } + private: Q_OBJECT OVITO_OBJECT - DECLARE_PROPERTY_FIELD(_value); + /// Stores the value of the key. + DECLARE_MODIFIABLE_PROPERTY_FIELD(value_type, value, setValue); }; /** * \brief Animation key class for scaling controllers. */ -class OVITO_CORE_EXPORT ScalingAnimationKey : public TypedAnimationKey +class OVITO_CORE_EXPORT ScalingAnimationKey : public AnimationKey { public: + /// The type of value stored by this animation key. + using value_type = Scaling; + + /// The type used to initialize default values of this key. + using nullvalue_type = Scaling::Identity; + + /// The type used for derivatives/tangents. + using tangent_type = Scaling; + /// Constructor. - Q_INVOKABLE ScalingAnimationKey(DataSet* dataset, TimePoint time = 0, const Scaling& value = Scaling::Identity()) : TypedAnimationKey(dataset, time, value) { - INIT_PROPERTY_FIELD(ScalingAnimationKey::_value); + Q_INVOKABLE ScalingAnimationKey(DataSet* dataset, TimePoint time = 0, const Scaling& value = Scaling::Identity()) : AnimationKey(dataset, time), _value(value) { + INIT_PROPERTY_FIELD(value); + } + + /// Returns the value of this animation key as a QVariant. + virtual QVariant valueQVariant() const override { + return QVariant::fromValue(value()); } + /// Sets the value of the key. + virtual bool setValueQVariant(const QVariant& v) override { + if(!v.canConvert()) return false; + setValue(v.value()); + return true; + } + private: Q_OBJECT OVITO_OBJECT - DECLARE_PROPERTY_FIELD(_value); + /// Stores the value of the key. + DECLARE_MODIFIABLE_PROPERTY_FIELD(value_type, value, setValue); }; /** @@ -415,5 +487,3 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace - -#endif // __OVITO_KEYED_CONTROLLERS_H diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/ConstantControllers.cpp ovito-2.9.0+dfsg1/src/core/animation/controller/ConstantControllers.cpp --- ovito-2.8.1+dfsg2/src/core/animation/controller/ConstantControllers.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/ConstantControllers.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,18 +24,18 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Anim) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, ConstFloatController, Controller); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, ConstIntegerController, Controller); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, ConstVectorController, Controller); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, ConstPositionController, Controller); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, ConstRotationController, Controller); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, ConstScalingController, Controller); -DEFINE_PROPERTY_FIELD(ConstFloatController, _value, "Value"); -DEFINE_PROPERTY_FIELD(ConstIntegerController, _value, "Value"); -DEFINE_PROPERTY_FIELD(ConstVectorController, _value, "Value"); -DEFINE_PROPERTY_FIELD(ConstPositionController, _value, "Value"); -DEFINE_PROPERTY_FIELD(ConstRotationController, _value, "Value"); -DEFINE_PROPERTY_FIELD(ConstScalingController, _value, "Value"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ConstFloatController, Controller); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ConstIntegerController, Controller); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ConstVectorController, Controller); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ConstPositionController, Controller); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ConstRotationController, Controller); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ConstScalingController, Controller); +DEFINE_PROPERTY_FIELD(ConstFloatController, value, "Value"); +DEFINE_PROPERTY_FIELD(ConstIntegerController, value, "Value"); +DEFINE_PROPERTY_FIELD(ConstVectorController, value, "Value"); +DEFINE_PROPERTY_FIELD(ConstPositionController, value, "Value"); +DEFINE_PROPERTY_FIELD(ConstRotationController, value, "Value"); +DEFINE_PROPERTY_FIELD(ConstScalingController, value, "Value"); OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/ConstantControllers.h ovito-2.9.0+dfsg1/src/core/animation/controller/ConstantControllers.h --- ovito-2.8.1+dfsg2/src/core/animation/controller/ConstantControllers.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/ConstantControllers.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CONSTANT_CONTROLLERS_H -#define __OVITO_CONSTANT_CONTROLLERS_H +#pragma once + #include #include "Controller.h" @@ -36,7 +36,7 @@ /// Constructor. Q_INVOKABLE ConstFloatController(DataSet* dataset) : Controller(dataset), _value(0) { - INIT_PROPERTY_FIELD(ConstFloatController::_value); + INIT_PROPERTY_FIELD(value); } /// \brief Returns the value type of the controller. @@ -57,12 +57,10 @@ private: /// Stores the constant value of the controller. - PropertyField _value; + DECLARE_PROPERTY_FIELD(FloatType, value); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_value); }; /** @@ -74,7 +72,7 @@ /// Constructor. Q_INVOKABLE ConstIntegerController(DataSet* dataset) : Controller(dataset), _value(0) { - INIT_PROPERTY_FIELD(ConstIntegerController::_value); + INIT_PROPERTY_FIELD(value); } /// \brief Returns the value type of the controller. @@ -95,12 +93,10 @@ private: /// Stores the constant value of the controller. - PropertyField _value; + DECLARE_PROPERTY_FIELD(int, value); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_value); }; /** @@ -112,7 +108,7 @@ /// Constructor. Q_INVOKABLE ConstVectorController(DataSet* dataset) : Controller(dataset), _value(Vector3::Zero()) { - INIT_PROPERTY_FIELD(ConstVectorController::_value); + INIT_PROPERTY_FIELD(value); } /// \brief Returns the value type of the controller. @@ -133,12 +129,10 @@ private: /// Stores the constant value of the controller. - PropertyField _value; + DECLARE_PROPERTY_FIELD(Vector3, value); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_value); }; /** @@ -150,7 +144,7 @@ /// Constructor. Q_INVOKABLE ConstPositionController(DataSet* dataset) : Controller(dataset), _value(Vector3::Zero()) { - INIT_PROPERTY_FIELD(ConstPositionController::_value); + INIT_PROPERTY_FIELD(value); } /// \brief Returns the value type of the controller. @@ -174,12 +168,10 @@ private: /// Stores the constant value of the controller. - PropertyField _value; + DECLARE_PROPERTY_FIELD(Vector3, value); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_value); }; /** @@ -191,7 +183,7 @@ /// Constructor. Q_INVOKABLE ConstRotationController(DataSet* dataset) : Controller(dataset), _value(Rotation::Identity()) { - INIT_PROPERTY_FIELD(ConstRotationController::_value); + INIT_PROPERTY_FIELD(value); } /// \brief Returns the value type of the controller. @@ -215,12 +207,10 @@ private: /// Stores the constant value of the controller. - PropertyField _value; + DECLARE_PROPERTY_FIELD(Rotation, value); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_value); }; /** @@ -232,7 +222,7 @@ /// Constructor. Q_INVOKABLE ConstScalingController(DataSet* dataset) : Controller(dataset), _value(Scaling::Identity()) { - INIT_PROPERTY_FIELD(ConstScalingController::_value); + INIT_PROPERTY_FIELD(value); } /// \brief Returns the value type of the controller. @@ -256,15 +246,11 @@ private: /// Stores the constant value of the controller. - PropertyField _value; + DECLARE_PROPERTY_FIELD(Scaling, value); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_value); }; OVITO_END_INLINE_NAMESPACE } // End of namespace - -#endif // __OVITO_CONSTANT_CONTROLLERS_H diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/Controller.cpp ovito-2.9.0+dfsg1/src/core/animation/controller/Controller.cpp --- ovito-2.8.1+dfsg2/src/core/animation/controller/Controller.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/Controller.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -31,10 +31,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Anim) -/// The singleton instance of the manager class. -ControllerManager* ControllerManager::_instance = nullptr; - -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, Controller, RefTarget); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Controller, RefTarget); /****************************************************************************** * Returns the float controller's value at the current animation time. @@ -89,14 +86,6 @@ } /****************************************************************************** -* Initializes the controller manager. -******************************************************************************/ -ControllerManager::ControllerManager() -{ - OVITO_ASSERT_MSG(!_instance, "ControllerManager constructor", "Multiple instances of this singleton class have been created."); -} - -/****************************************************************************** * Creates a new float controller. ******************************************************************************/ OORef ControllerManager::createFloatController(DataSet* dataset) diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/Controller.h ovito-2.9.0+dfsg1/src/core/animation/controller/Controller.h --- ovito-2.8.1+dfsg2/src/core/animation/controller/Controller.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/Controller.h 2017-07-27 16:52:45.000000000 +0000 @@ -25,8 +25,8 @@ * and the Ovito::ControllerManager class. */ -#ifndef __OVITO_CONTROLLER_H -#define __OVITO_CONTROLLER_H +#pragma once + #include #include @@ -305,56 +305,32 @@ { public: - /// \brief Returns the one and only instance of this class. - /// \return The predefined instance of the ControllerManager singleton class. - inline static ControllerManager& instance() { - OVITO_ASSERT_MSG(_instance != nullptr, "ControllerManager::instance", "Singleton object is not initialized yet."); - return *_instance; - } - /// \brief Creates a new float controller. - OORef createFloatController(DataSet* dataset); + static OORef createFloatController(DataSet* dataset); /// \brief Creates a new integer controller. - OORef createIntController(DataSet* dataset); + static OORef createIntController(DataSet* dataset); /// \brief Creates a new Vector3 controller. - OORef createVector3Controller(DataSet* dataset); + static OORef createVector3Controller(DataSet* dataset); /// \brief Creates a new Color controller. - OORef createColorController(DataSet* dataset) { return createVector3Controller(dataset); } + static OORef createColorController(DataSet* dataset) { return createVector3Controller(dataset); } /// \brief Creates a new position controller. - OORef createPositionController(DataSet* dataset); + static OORef createPositionController(DataSet* dataset); /// \brief Creates a new rotation controller. - OORef createRotationController(DataSet* dataset); + static OORef createRotationController(DataSet* dataset); /// \brief Creates a new scaling controller. - OORef createScalingController(DataSet* dataset); + static OORef createScalingController(DataSet* dataset); /// \brief Creates a new transformation controller. - OORef createTransformationController(DataSet* dataset); - -private: - - /// Private constructor. - /// This is a singleton class; no public instances are allowed. - ControllerManager(); - - /// Create the singleton instance of this class. - static void initialize() { _instance = new ControllerManager(); } - - /// Deletes the singleton instance of this class. - static void shutdown() { delete _instance; _instance = nullptr; } - - /// The singleton instance of this class. - static ControllerManager* _instance; - - friend class Application; + static OORef createTransformationController(DataSet* dataset); }; OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_CONTROLLER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/KeyframeController.cpp ovito-2.9.0+dfsg1/src/core/animation/controller/KeyframeController.cpp --- ovito-2.8.1+dfsg2/src/core/animation/controller/KeyframeController.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/KeyframeController.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,9 +24,9 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Anim) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, KeyframeController, Controller); -DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(KeyframeController, _keys, "Keys", AnimationKey, PROPERTY_FIELD_ALWAYS_CLONE | PROPERTY_FIELD_NO_SUB_ANIM); -SET_PROPERTY_FIELD_LABEL(KeyframeController, _keys, "Keys"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(KeyframeController, Controller); +DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(KeyframeController, keys, "Keys", AnimationKey, PROPERTY_FIELD_ALWAYS_CLONE | PROPERTY_FIELD_NO_SUB_ANIM); +SET_PROPERTY_FIELD_LABEL(KeyframeController, keys, "Keys"); /****************************************************************************** * Maps all keys from the old animation interval to the new interval. diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/KeyframeController.h ovito-2.9.0+dfsg1/src/core/animation/controller/KeyframeController.h --- ovito-2.8.1+dfsg2/src/core/animation/controller/KeyframeController.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/KeyframeController.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_KEYFRAME_CONTROLLER_H -#define __OVITO_KEYFRAME_CONTROLLER_H +#pragma once + #include #include @@ -39,15 +39,12 @@ /// Constructor. KeyframeController(DataSet* dataset) : Controller(dataset) { - INIT_PROPERTY_FIELD(KeyframeController::_keys); + INIT_PROPERTY_FIELD(keys); } /// \brief Returns whether the value of this controller is changing over time. virtual bool isAnimated() const override { return keys().size() >= 2; } - /// Returns the controller's list of animation keys. - const QVector& keys() const { return _keys; } - /// Maps all keys from the old animation interval to the new interval. virtual void rescaleTime(const TimeInterval& oldAnimationInterval, const TimeInterval& newAnimationInterval) override; @@ -83,12 +80,10 @@ private: /// Stores the list of animation keys. - VectorReferenceField _keys; + DECLARE_VECTOR_REFERENCE_FIELD(AnimationKey, keys); Q_OBJECT OVITO_OBJECT - - DECLARE_VECTOR_REFERENCE_FIELD(_keys); }; /** @@ -294,4 +289,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_KEYFRAME_CONTROLLER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/LinearInterpolationControllers.cpp ovito-2.9.0+dfsg1/src/core/animation/controller/LinearInterpolationControllers.cpp --- ovito-2.8.1+dfsg2/src/core/animation/controller/LinearInterpolationControllers.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/LinearInterpolationControllers.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,12 +24,12 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Anim) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, LinearFloatController, KeyframeController); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, LinearIntegerController, KeyframeController); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, LinearVectorController, KeyframeController); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, LinearPositionController, KeyframeController); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, LinearRotationController, KeyframeController); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, LinearScalingController, KeyframeController); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(LinearFloatController, KeyframeController); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(LinearIntegerController, KeyframeController); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(LinearVectorController, KeyframeController); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(LinearPositionController, KeyframeController); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(LinearRotationController, KeyframeController); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(LinearScalingController, KeyframeController); OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/LinearInterpolationControllers.h ovito-2.9.0+dfsg1/src/core/animation/controller/LinearInterpolationControllers.h --- ovito-2.8.1+dfsg2/src/core/animation/controller/LinearInterpolationControllers.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/LinearInterpolationControllers.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_LINEAR_INTERPOLATION_CONTROLLERS_H -#define __OVITO_LINEAR_INTERPOLATION_CONTROLLERS_H +#pragma once + #include #include "KeyframeController.h" @@ -237,5 +237,3 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace - -#endif // __OVITO_LINEAR_INTERPOLATION_CONTROLLERS_H diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/LookAtController.cpp ovito-2.9.0+dfsg1/src/core/animation/controller/LookAtController.cpp --- ovito-2.8.1+dfsg2/src/core/animation/controller/LookAtController.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/LookAtController.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,23 +26,23 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Anim) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, LookAtController, Controller); -DEFINE_REFERENCE_FIELD(LookAtController, _rollCtrl, "Roll", Controller); -DEFINE_FLAGS_REFERENCE_FIELD(LookAtController, _targetNode, "Target", SceneNode, PROPERTY_FIELD_NEVER_CLONE_TARGET | PROPERTY_FIELD_NO_SUB_ANIM); -SET_PROPERTY_FIELD_LABEL(LookAtController, _rollCtrl, "Roll"); -SET_PROPERTY_FIELD_LABEL(LookAtController, _targetNode, "Target"); -SET_PROPERTY_FIELD_UNITS(LookAtController, _rollCtrl, AngleParameterUnit); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(LookAtController, Controller); +DEFINE_REFERENCE_FIELD(LookAtController, rollController, "Roll", Controller); +DEFINE_FLAGS_REFERENCE_FIELD(LookAtController, targetNode, "Target", SceneNode, PROPERTY_FIELD_NEVER_CLONE_TARGET | PROPERTY_FIELD_NO_SUB_ANIM); +SET_PROPERTY_FIELD_LABEL(LookAtController, rollController, "Roll"); +SET_PROPERTY_FIELD_LABEL(LookAtController, targetNode, "Target"); +SET_PROPERTY_FIELD_UNITS(LookAtController, rollController, AngleParameterUnit); /****************************************************************************** * Constructor. ******************************************************************************/ LookAtController::LookAtController(DataSet* dataset) : Controller(dataset) { - INIT_PROPERTY_FIELD(LookAtController::_rollCtrl); - INIT_PROPERTY_FIELD(LookAtController::_targetNode); + INIT_PROPERTY_FIELD(rollController); + INIT_PROPERTY_FIELD(targetNode); // Create sub-controller. - _rollCtrl = ControllerManager::instance().createFloatController(dataset); + setRollController(ControllerManager::createFloatController(dataset)); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/LookAtController.h ovito-2.9.0+dfsg1/src/core/animation/controller/LookAtController.h --- ovito-2.8.1+dfsg2/src/core/animation/controller/LookAtController.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/LookAtController.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::LookAtController class. */ -#ifndef __OVITO_LOOKAT_CONTROLLER_H -#define __OVITO_LOOKAT_CONTROLLER_H +#pragma once + #include #include "Controller.h" @@ -69,26 +69,6 @@ /// contextNode - The node to which this controller is assigned to virtual void changeParent(TimePoint time, const AffineTransformation& oldParentTM, const AffineTransformation& newParentTM, SceneNode* contextNode) override {} - /// \brief Returns the target node to look at. - /// \return The target this rotation controller is looking at or \c NULL if it - /// has not been set yet. - SceneNode* targetNode() const { return _targetNode; } - - /// \brief Sets the target node to look at. - /// \param target The new target this rotation controller should use for its - /// calculation of the rotation matrix. - /// \undoable - void setTargetNode(SceneNode* target) { _targetNode = target; } - - /// \brief Returns the sub-controller that controls the rolling parameter. - /// \return The sub-controller for the rolling angle. - Controller* rollController() const { return _rollCtrl; } - - /// \brief Sets the sub-controller that controls the rolling parameter. - /// \param ctrl The new roll angle controller. - /// \undoable - void setRollController(Controller* ctrl) { _rollCtrl = ctrl; } - /// \brief Returns whether the value of this controller is changing over time. virtual bool isAnimated() const override { return (rollController() && rollController()->isAnimated()) @@ -98,10 +78,10 @@ private: /// The sub-controller for rolling. - ReferenceField _rollCtrl; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, rollController, setRollController); /// The target scene node to look at. - ReferenceField _targetNode; + DECLARE_MODIFIABLE_REFERENCE_FIELD(SceneNode, targetNode, setTargetNode); /// Stores the cached position of the source node. Vector3 _sourcePos; @@ -113,12 +93,9 @@ Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_rollCtrl); - DECLARE_REFERENCE_FIELD(_targetNode); }; OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_LOOKAT_CONTROLLER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/PRSTransformationController.cpp ovito-2.9.0+dfsg1/src/core/animation/controller/PRSTransformationController.cpp --- ovito-2.8.1+dfsg2/src/core/animation/controller/PRSTransformationController.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/PRSTransformationController.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,28 +27,28 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Anim) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, PRSTransformationController, Controller); -DEFINE_REFERENCE_FIELD(PRSTransformationController, _position, "Position", Controller); -DEFINE_REFERENCE_FIELD(PRSTransformationController, _rotation, "Rotation", Controller); -DEFINE_REFERENCE_FIELD(PRSTransformationController, _scaling, "Scaling", Controller); -SET_PROPERTY_FIELD_LABEL(PRSTransformationController, _position, "Position"); -SET_PROPERTY_FIELD_LABEL(PRSTransformationController, _rotation, "Rotation"); -SET_PROPERTY_FIELD_LABEL(PRSTransformationController, _scaling, "Scaling"); -SET_PROPERTY_FIELD_UNITS(PRSTransformationController, _position, WorldParameterUnit); -SET_PROPERTY_FIELD_UNITS(PRSTransformationController, _rotation, AngleParameterUnit); -SET_PROPERTY_FIELD_UNITS(PRSTransformationController, _scaling, PercentParameterUnit); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(PRSTransformationController, Controller); +DEFINE_REFERENCE_FIELD(PRSTransformationController, positionController, "Position", Controller); +DEFINE_REFERENCE_FIELD(PRSTransformationController, rotationController, "Rotation", Controller); +DEFINE_REFERENCE_FIELD(PRSTransformationController, scalingController, "Scaling", Controller); +SET_PROPERTY_FIELD_LABEL(PRSTransformationController, positionController, "Position"); +SET_PROPERTY_FIELD_LABEL(PRSTransformationController, rotationController, "Rotation"); +SET_PROPERTY_FIELD_LABEL(PRSTransformationController, scalingController, "Scaling"); +SET_PROPERTY_FIELD_UNITS(PRSTransformationController, positionController, WorldParameterUnit); +SET_PROPERTY_FIELD_UNITS(PRSTransformationController, rotationController, AngleParameterUnit); +SET_PROPERTY_FIELD_UNITS(PRSTransformationController, scalingController, PercentParameterUnit); /****************************************************************************** * Default constructor. ******************************************************************************/ PRSTransformationController::PRSTransformationController(DataSet* dataset) : Controller(dataset) { - INIT_PROPERTY_FIELD(PRSTransformationController::_position); - INIT_PROPERTY_FIELD(PRSTransformationController::_rotation); - INIT_PROPERTY_FIELD(PRSTransformationController::_scaling); - _position = ControllerManager::instance().createPositionController(dataset); - _rotation = ControllerManager::instance().createRotationController(dataset); - _scaling = ControllerManager::instance().createScalingController(dataset); + INIT_PROPERTY_FIELD(positionController); + INIT_PROPERTY_FIELD(rotationController); + INIT_PROPERTY_FIELD(scalingController); + setPositionController(ControllerManager::createPositionController(dataset)); + setRotationController(ControllerManager::createRotationController(dataset)); + setScalingController(ControllerManager::createScalingController(dataset)); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/PRSTransformationController.h ovito-2.9.0+dfsg1/src/core/animation/controller/PRSTransformationController.h --- ovito-2.8.1+dfsg2/src/core/animation/controller/PRSTransformationController.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/PRSTransformationController.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::PRSTransformationController class. */ -#ifndef __OVITO_PRS_TRANSFORMATION_CONTROLLER_H -#define __OVITO_PRS_TRANSFORMATION_CONTROLLER_H +#pragma once + #include #include "Controller.h" @@ -106,39 +106,6 @@ /// controller's value does not change. virtual TimeInterval validityInterval(TimePoint time) override; - /// \brief Returns the position sub-controller. - /// \return The sub-controller that controls the translational part of the transformation. - Controller* positionController() const { return _position; } - - /// \brief Returns the rotation sub-controller. - /// \return The sub-controller that controls the rotational part of the transformation. - Controller* rotationController() const { return _rotation; } - - /// \brief Returns the scaling sub-controller. - /// \return The sub-controller that controls the scaling part of the transformation. - Controller* scalingController() const { return _scaling; } - - /// \brief Assigns a new sub-controller for the translational component of the transformation. - /// \param position The new controller. - void setPositionController(Controller* position) { - OVITO_CHECK_OBJECT_POINTER(position); - this->_position = position; - } - - /// \brief Assigns a new sub-controller for the rotational component of the transformation. - /// \param rotation The new controller. - void setRotationController(Controller* rotation) { - OVITO_CHECK_OBJECT_POINTER(rotation); - this->_rotation = rotation; - } - - /// \brief Assigns a new sub-controller for the scaling component of the transformation. - /// \param scaling The new controller. - void setScalingController(Controller* scaling) { - OVITO_CHECK_OBJECT_POINTER(scaling); - this->_scaling = scaling; - } - /// \brief Adds a translation to the transformation. /// \param time The animation at which the translation should be applied to the transformation. /// \param translation The translation vector to add to the transformation. This is specified in the coordinate system given by \a axisSystem. @@ -179,23 +146,19 @@ private: /// The sub-controller for translation. - ReferenceField _position; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, positionController, setPositionController); /// The sub-controller for rotation. - ReferenceField _rotation; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, rotationController, setRotationController); /// The sub-controller for scaling. - ReferenceField _scaling; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, scalingController, setScalingController); Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_position); - DECLARE_REFERENCE_FIELD(_rotation); - DECLARE_REFERENCE_FIELD(_scaling); }; OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_PRS_TRANSFORMATION_CONTROLLER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/SplineInterpolationControllers.cpp ovito-2.9.0+dfsg1/src/core/animation/controller/SplineInterpolationControllers.cpp --- ovito-2.8.1+dfsg2/src/core/animation/controller/SplineInterpolationControllers.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/SplineInterpolationControllers.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,19 +24,19 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Anim) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, FloatSplineAnimationKey, FloatAnimationKey); -DEFINE_PROPERTY_FIELD(FloatSplineAnimationKey, _inTangent, "InTangent"); -DEFINE_PROPERTY_FIELD(FloatSplineAnimationKey, _outTangent, "OutTangent"); -SET_PROPERTY_FIELD_LABEL(FloatSplineAnimationKey, _inTangent, "In Tangent"); -SET_PROPERTY_FIELD_LABEL(FloatSplineAnimationKey, _outTangent, "Out Tangent"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(FloatSplineAnimationKey, FloatAnimationKey); +DEFINE_PROPERTY_FIELD(FloatSplineAnimationKey, inTangent, "InTangent"); +DEFINE_PROPERTY_FIELD(FloatSplineAnimationKey, outTangent, "OutTangent"); +SET_PROPERTY_FIELD_LABEL(FloatSplineAnimationKey, inTangent, "In Tangent"); +SET_PROPERTY_FIELD_LABEL(FloatSplineAnimationKey, outTangent, "Out Tangent"); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, PositionSplineAnimationKey, PositionAnimationKey); -DEFINE_PROPERTY_FIELD(PositionSplineAnimationKey, _inTangent, "InTangent"); -DEFINE_PROPERTY_FIELD(PositionSplineAnimationKey, _outTangent, "OutTangent"); -SET_PROPERTY_FIELD_LABEL(PositionSplineAnimationKey, _inTangent, "In Tangent"); -SET_PROPERTY_FIELD_LABEL(PositionSplineAnimationKey, _outTangent, "Out Tangent"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(PositionSplineAnimationKey, PositionAnimationKey); +DEFINE_PROPERTY_FIELD(PositionSplineAnimationKey, inTangent, "InTangent"); +DEFINE_PROPERTY_FIELD(PositionSplineAnimationKey, outTangent, "OutTangent"); +SET_PROPERTY_FIELD_LABEL(PositionSplineAnimationKey, inTangent, "In Tangent"); +SET_PROPERTY_FIELD_LABEL(PositionSplineAnimationKey, outTangent, "Out Tangent"); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, SplinePositionController, KeyframeController); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SplinePositionController, KeyframeController); OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/SplineInterpolationControllers.h ovito-2.9.0+dfsg1/src/core/animation/controller/SplineInterpolationControllers.h --- ovito-2.8.1+dfsg2/src/core/animation/controller/SplineInterpolationControllers.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/SplineInterpolationControllers.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SPLINE_INTERPOLATION_CONTROLLERS_H -#define __OVITO_SPLINE_INTERPOLATION_CONTROLLERS_H +#pragma once + #include #include "KeyframeController.h" @@ -61,7 +61,7 @@ /// \brief Returns the point that defines the outgoing direction. value_type outPoint() const { return this->value() + outTangent(); } -protected: +public: /// The tangent that defines the left derivative at the key point. PropertyField _inTangent; @@ -80,8 +80,8 @@ /// Constructor. Q_INVOKABLE FloatSplineAnimationKey(DataSet* dataset, TimePoint time = 0, FloatType value = 0) : SplineAnimationKey(dataset, time, value) { - INIT_PROPERTY_FIELD(FloatSplineAnimationKey::_inTangent); - INIT_PROPERTY_FIELD(FloatSplineAnimationKey::_outTangent); + INIT_PROPERTY_FIELD(inTangent); + INIT_PROPERTY_FIELD(outTangent); } private: @@ -89,8 +89,8 @@ Q_OBJECT OVITO_OBJECT - DECLARE_PROPERTY_FIELD(_inTangent); - DECLARE_PROPERTY_FIELD(_outTangent); + DECLARE_PROPERTY_FIELD_DESCRIPTOR(inTangent); + DECLARE_PROPERTY_FIELD_DESCRIPTOR(outTangent); }; /** @@ -102,8 +102,8 @@ /// Constructor. Q_INVOKABLE PositionSplineAnimationKey(DataSet* dataset, TimePoint time = 0, const Vector3& value = Vector3::Zero()) : SplineAnimationKey(dataset, time, value) { - INIT_PROPERTY_FIELD(PositionSplineAnimationKey::_inTangent); - INIT_PROPERTY_FIELD(PositionSplineAnimationKey::_outTangent); + INIT_PROPERTY_FIELD(inTangent); + INIT_PROPERTY_FIELD(outTangent); } private: @@ -111,8 +111,8 @@ Q_OBJECT OVITO_OBJECT - DECLARE_PROPERTY_FIELD(_inTangent); - DECLARE_PROPERTY_FIELD(_outTangent); + DECLARE_PROPERTY_FIELD_DESCRIPTOR(inTangent); + DECLARE_PROPERTY_FIELD_DESCRIPTOR(outTangent); }; /** @@ -209,4 +209,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_SPLINE_INTERPOLATION_CONTROLLERS_H + diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/TCBInterpolationControllers.cpp ovito-2.9.0+dfsg1/src/core/animation/controller/TCBInterpolationControllers.cpp --- ovito-2.8.1+dfsg2/src/core/animation/controller/TCBInterpolationControllers.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/TCBInterpolationControllers.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,41 +24,41 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Anim) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, FloatTCBAnimationKey, FloatAnimationKey); -DEFINE_PROPERTY_FIELD(FloatTCBAnimationKey, _easeTo, "EaseTo"); -DEFINE_PROPERTY_FIELD(FloatTCBAnimationKey, _easeFrom, "EaseFrom"); -DEFINE_PROPERTY_FIELD(FloatTCBAnimationKey, _tension, "Tension"); -DEFINE_PROPERTY_FIELD(FloatTCBAnimationKey, _continuity, "Continuity"); -DEFINE_PROPERTY_FIELD(FloatTCBAnimationKey, _bias, "Bias"); -SET_PROPERTY_FIELD_LABEL(FloatTCBAnimationKey, _easeTo, "Ease to"); -SET_PROPERTY_FIELD_LABEL(FloatTCBAnimationKey, _easeFrom, "Ease from"); -SET_PROPERTY_FIELD_LABEL(FloatTCBAnimationKey, _tension, "Tension"); -SET_PROPERTY_FIELD_LABEL(FloatTCBAnimationKey, _continuity, "Continuity"); -SET_PROPERTY_FIELD_LABEL(FloatTCBAnimationKey, _bias, "Bias"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(FloatTCBAnimationKey, _easeTo, FloatParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(FloatTCBAnimationKey, _easeFrom, FloatParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(FloatTCBAnimationKey, _tension, FloatParameterUnit, -1, 1); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(FloatTCBAnimationKey, _continuity, FloatParameterUnit, -1, 1); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(FloatTCBAnimationKey, _bias, FloatParameterUnit, -1, 1); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(FloatTCBAnimationKey, FloatAnimationKey); +DEFINE_PROPERTY_FIELD(FloatTCBAnimationKey, easeTo, "EaseTo"); +DEFINE_PROPERTY_FIELD(FloatTCBAnimationKey, easeFrom, "EaseFrom"); +DEFINE_PROPERTY_FIELD(FloatTCBAnimationKey, tension, "Tension"); +DEFINE_PROPERTY_FIELD(FloatTCBAnimationKey, continuity, "Continuity"); +DEFINE_PROPERTY_FIELD(FloatTCBAnimationKey, bias, "Bias"); +SET_PROPERTY_FIELD_LABEL(FloatTCBAnimationKey, easeTo, "Ease to"); +SET_PROPERTY_FIELD_LABEL(FloatTCBAnimationKey, easeFrom, "Ease from"); +SET_PROPERTY_FIELD_LABEL(FloatTCBAnimationKey, tension, "Tension"); +SET_PROPERTY_FIELD_LABEL(FloatTCBAnimationKey, continuity, "Continuity"); +SET_PROPERTY_FIELD_LABEL(FloatTCBAnimationKey, bias, "Bias"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(FloatTCBAnimationKey, easeTo, FloatParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(FloatTCBAnimationKey, easeFrom, FloatParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(FloatTCBAnimationKey, tension, FloatParameterUnit, -1, 1); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(FloatTCBAnimationKey, continuity, FloatParameterUnit, -1, 1); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(FloatTCBAnimationKey, bias, FloatParameterUnit, -1, 1); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, PositionTCBAnimationKey, PositionAnimationKey); -DEFINE_PROPERTY_FIELD(PositionTCBAnimationKey, _easeTo, "EaseTo"); -DEFINE_PROPERTY_FIELD(PositionTCBAnimationKey, _easeFrom, "EaseFrom"); -DEFINE_PROPERTY_FIELD(PositionTCBAnimationKey, _tension, "Tension"); -DEFINE_PROPERTY_FIELD(PositionTCBAnimationKey, _continuity, "Continuity"); -DEFINE_PROPERTY_FIELD(PositionTCBAnimationKey, _bias, "Bias"); -SET_PROPERTY_FIELD_LABEL(PositionTCBAnimationKey, _easeTo, "Ease to"); -SET_PROPERTY_FIELD_LABEL(PositionTCBAnimationKey, _easeFrom, "Ease from"); -SET_PROPERTY_FIELD_LABEL(PositionTCBAnimationKey, _tension, "Tension"); -SET_PROPERTY_FIELD_LABEL(PositionTCBAnimationKey, _continuity, "Continuity"); -SET_PROPERTY_FIELD_LABEL(PositionTCBAnimationKey, _bias, "Bias"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(PositionTCBAnimationKey, _easeTo, FloatParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(PositionTCBAnimationKey, _easeFrom, FloatParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(PositionTCBAnimationKey, _tension, FloatParameterUnit, -1, 1); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(PositionTCBAnimationKey, _continuity, FloatParameterUnit, -1, 1); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(PositionTCBAnimationKey, _bias, FloatParameterUnit, -1, 1); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(PositionTCBAnimationKey, PositionAnimationKey); +DEFINE_PROPERTY_FIELD(PositionTCBAnimationKey, easeTo, "EaseTo"); +DEFINE_PROPERTY_FIELD(PositionTCBAnimationKey, easeFrom, "EaseFrom"); +DEFINE_PROPERTY_FIELD(PositionTCBAnimationKey, tension, "Tension"); +DEFINE_PROPERTY_FIELD(PositionTCBAnimationKey, continuity, "Continuity"); +DEFINE_PROPERTY_FIELD(PositionTCBAnimationKey, bias, "Bias"); +SET_PROPERTY_FIELD_LABEL(PositionTCBAnimationKey, easeTo, "Ease to"); +SET_PROPERTY_FIELD_LABEL(PositionTCBAnimationKey, easeFrom, "Ease from"); +SET_PROPERTY_FIELD_LABEL(PositionTCBAnimationKey, tension, "Tension"); +SET_PROPERTY_FIELD_LABEL(PositionTCBAnimationKey, continuity, "Continuity"); +SET_PROPERTY_FIELD_LABEL(PositionTCBAnimationKey, bias, "Bias"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(PositionTCBAnimationKey, easeTo, FloatParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(PositionTCBAnimationKey, easeFrom, FloatParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(PositionTCBAnimationKey, tension, FloatParameterUnit, -1, 1); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(PositionTCBAnimationKey, continuity, FloatParameterUnit, -1, 1); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(PositionTCBAnimationKey, bias, FloatParameterUnit, -1, 1); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, TCBPositionController, KeyframeController); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(TCBPositionController, KeyframeController); OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/animation/controller/TCBInterpolationControllers.h ovito-2.9.0+dfsg1/src/core/animation/controller/TCBInterpolationControllers.h --- ovito-2.8.1+dfsg2/src/core/animation/controller/TCBInterpolationControllers.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/controller/TCBInterpolationControllers.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TCB_INTERPOLATION_CONTROLLERS_H -#define __OVITO_TCB_INTERPOLATION_CONTROLLERS_H +#pragma once + #include #include "KeyframeController.h" @@ -56,7 +56,7 @@ /// Returns the 'bias' parameter, which controls where the animation curve occurs with respect to the key. FloatType bias() const { return _bias; } -protected: +public: /// Slows the velocity of the animation curve as it approaches the key. PropertyField _easeTo; @@ -84,11 +84,11 @@ /// Constructor. Q_INVOKABLE FloatTCBAnimationKey(DataSet* dataset, TimePoint time = 0, FloatType value = 0) : TCBAnimationKey(dataset, time, value) { - INIT_PROPERTY_FIELD(FloatTCBAnimationKey::_easeTo); - INIT_PROPERTY_FIELD(FloatTCBAnimationKey::_easeFrom); - INIT_PROPERTY_FIELD(FloatTCBAnimationKey::_tension); - INIT_PROPERTY_FIELD(FloatTCBAnimationKey::_continuity); - INIT_PROPERTY_FIELD(FloatTCBAnimationKey::_bias); + INIT_PROPERTY_FIELD(easeTo); + INIT_PROPERTY_FIELD(easeFrom); + INIT_PROPERTY_FIELD(tension); + INIT_PROPERTY_FIELD(continuity); + INIT_PROPERTY_FIELD(bias); } private: @@ -96,11 +96,11 @@ Q_OBJECT OVITO_OBJECT - DECLARE_PROPERTY_FIELD(_easeTo); - DECLARE_PROPERTY_FIELD(_easeFrom); - DECLARE_PROPERTY_FIELD(_tension); - DECLARE_PROPERTY_FIELD(_continuity); - DECLARE_PROPERTY_FIELD(_bias); + DECLARE_PROPERTY_FIELD_DESCRIPTOR(easeTo); + DECLARE_PROPERTY_FIELD_DESCRIPTOR(easeFrom); + DECLARE_PROPERTY_FIELD_DESCRIPTOR(tension); + DECLARE_PROPERTY_FIELD_DESCRIPTOR(continuity); + DECLARE_PROPERTY_FIELD_DESCRIPTOR(bias); }; /** @@ -112,11 +112,11 @@ /// Constructor. Q_INVOKABLE PositionTCBAnimationKey(DataSet* dataset, TimePoint time = 0, const Vector3& value = Vector3::Zero()) : TCBAnimationKey(dataset, time, value) { - INIT_PROPERTY_FIELD(PositionTCBAnimationKey::_easeTo); - INIT_PROPERTY_FIELD(PositionTCBAnimationKey::_easeFrom); - INIT_PROPERTY_FIELD(PositionTCBAnimationKey::_tension); - INIT_PROPERTY_FIELD(PositionTCBAnimationKey::_continuity); - INIT_PROPERTY_FIELD(PositionTCBAnimationKey::_bias); + INIT_PROPERTY_FIELD(easeTo); + INIT_PROPERTY_FIELD(easeFrom); + INIT_PROPERTY_FIELD(tension); + INIT_PROPERTY_FIELD(continuity); + INIT_PROPERTY_FIELD(bias); } private: @@ -124,11 +124,11 @@ Q_OBJECT OVITO_OBJECT - DECLARE_PROPERTY_FIELD(_easeTo); - DECLARE_PROPERTY_FIELD(_easeFrom); - DECLARE_PROPERTY_FIELD(_tension); - DECLARE_PROPERTY_FIELD(_continuity); - DECLARE_PROPERTY_FIELD(_bias); + DECLARE_PROPERTY_FIELD_DESCRIPTOR(easeTo); + DECLARE_PROPERTY_FIELD_DESCRIPTOR(easeFrom); + DECLARE_PROPERTY_FIELD_DESCRIPTOR(tension); + DECLARE_PROPERTY_FIELD_DESCRIPTOR(continuity); + DECLARE_PROPERTY_FIELD_DESCRIPTOR(bias); }; /** @@ -200,4 +200,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_TCB_INTERPOLATION_CONTROLLERS_H + diff -Nru ovito-2.8.1+dfsg2/src/core/animation/TimeInterval.h ovito-2.9.0+dfsg1/src/core/animation/TimeInterval.h --- ovito-2.8.1+dfsg2/src/core/animation/TimeInterval.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/animation/TimeInterval.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TIME_INTERVAL_H -#define __OVITO_TIME_INTERVAL_H +#pragma once + #include #include @@ -236,4 +236,4 @@ Q_DECLARE_METATYPE(Ovito::TimeInterval); Q_DECLARE_TYPEINFO(Ovito::TimeInterval, Q_MOVABLE_TYPE); -#endif // __OVITO_TIME_INTERVAL_H + diff -Nru ovito-2.8.1+dfsg2/src/core/app/Application.cpp ovito-2.9.0+dfsg1/src/core/app/Application.cpp --- ovito-2.8.1+dfsg2/src/core/app/Application.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/app/Application.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,8 +22,6 @@ #include #include #include -#include -#include #include #include #include "Application.h" @@ -98,36 +96,11 @@ /****************************************************************************** * This is called on program startup. ******************************************************************************/ -bool Application::initialize(int& argc, char** argv) +bool Application::initialize() { // Install custom Qt error message handler to catch fatal errors in debug mode. defaultQtMessageHandler = qInstallMessageHandler(qtMessageOutput); - // Install default exception handler. - Exception::setExceptionHandler(consoleExceptionHandler); - -#ifdef Q_OS_LINUX - // Migrate settings file from old "Alexander Stukowski" directory to new default location. - // This is for backward compatibility with OVITO version 2.4.4 and earlier. - { - QString oldConfigFile = QDir::homePath() + QStringLiteral("/.config/Alexander Stukowski/Ovito.conf"); - QString newConfigFile = QDir::homePath() + QStringLiteral("/.config/Ovito/Ovito.conf"); - if(QFile::exists(oldConfigFile) && !QFile::exists(newConfigFile)) { - QDir configPath(newConfigFile + QStringLiteral("/..")); - if(!configPath.mkpath(".")) - qDebug() << "Warning: Migrating the configuration file from" << oldConfigFile << "to" << newConfigFile << "failed. The destination directory could not be created."; - if(!QFile::copy(oldConfigFile, newConfigFile)) - qDebug() << "Warning: Migrating the configuration file from" << oldConfigFile << "to" << newConfigFile << "failed. The copy operation failed."; - } - } -#endif - - // Set the application name. - QCoreApplication::setApplicationName(tr("Ovito")); - QCoreApplication::setOrganizationName(tr("Ovito")); - QCoreApplication::setOrganizationDomain("ovito.org"); - QCoreApplication::setApplicationVersion(QStringLiteral(OVITO_VERSION_STRING)); - // Activate default "C" locale, which will be used to parse numbers in strings. std::setlocale(LC_NUMERIC, "C"); @@ -160,133 +133,13 @@ QMetaType::registerConverter(); QMetaType::registerConverter(); - // Register command line arguments. - _cmdLineParser.setApplicationDescription(tr("OVITO - Open Visualization Tool")); - registerCommandLineParameters(_cmdLineParser); - - // Parse command line arguments. - // Ignore unknown command line options for now. - QStringList arguments; - for(int i = 0; i < argc; i++) - arguments << QString::fromLocal8Bit(argv[i]); - - // Because they may collide with our own options, we should ignore script arguments though. - QStringList filteredArguments; - for(int i = 0; i < arguments.size(); i++) { - if(arguments[i] == QStringLiteral("--scriptarg")) { - i += 1; - continue; - } - filteredArguments.push_back(arguments[i]); - } - _cmdLineParser.parse(filteredArguments); - - // Output program version if requested. - if(cmdLineParser().isSet("version")) { - std::cout << qPrintable(QCoreApplication::applicationName()) << " " << qPrintable(QCoreApplication::applicationVersion()) << std::endl; - _consoleMode = true; - return true; - } - - try { - // Interpret the command line arguments. - if(!processCommandLineParameters()) { - return true; - } - } - catch(const Exception& ex) { - ex.showError(); - return false; - } - - // Always use desktop OpenGL implementation (avoid ANGLE on Windows). - QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL); - - // Create Qt application object. - createQtApplication(argc, argv); - - // Reactivate default "C" locale, which, in the meantime, might have been changed by QCoreApplication. - std::setlocale(LC_NUMERIC, "C"); + // Create global FileManager object. + _fileManager.reset(createFileManager()); - try { - // Initialize global objects in the right order. - PluginManager::initialize(); - ControllerManager::initialize(); - FileManager::initialize(createFileManager()); - - // Load auto-start objects and let them register their custom command line options. - for(const OvitoObjectType* clazz : PluginManager::instance().listClasses(AutoStartObject::OOType)) { - OORef obj = static_object_cast(clazz->createInstance(nullptr)); - _autostartObjects.push_back(obj); - obj->registerCommandLineOptions(_cmdLineParser); - } - - // Parse the command line parameters again after the plugins have registered their options. - if(!_cmdLineParser.parse(arguments)) { - std::cerr << "Error: " << qPrintable(_cmdLineParser.errorText()) << std::endl; - _consoleMode = true; - shutdown(); - return false; - } - - // Help command line option implicitly activates console mode. - if(_cmdLineParser.isSet("help")) - _consoleMode = true; - - // Handle --help command line option. Print list of command line options and quit. - if(_cmdLineParser.isSet("help")) { - std::cout << qPrintable(_cmdLineParser.helpText()) << std::endl; - return true; - } - - // Prepares application to start running. - if(!startupApplication()) - return true; - - // Invoke auto-start objects. - for(const auto& obj : autostartObjects()) - obj->applicationStarted(); - } - catch(const Exception& ex) { - ex.showError(); - shutdown(); - return false; - } return true; } -/****************************************************************************** -* Defines the program's command line parameters. -******************************************************************************/ -void Application::registerCommandLineParameters(QCommandLineParser& parser) -{ - parser.addOption(QCommandLineOption(QStringList{{"h", "help"}}, tr("Shows this list of program options and exits."))); - parser.addOption(QCommandLineOption(QStringList{{"v", "version"}}, tr("Prints the program version and exits."))); - parser.addOption(QCommandLineOption(QStringList{{"nthreads"}}, tr("Sets the number of parallel threads to use for computations."), QStringLiteral("N"))); -} - -/****************************************************************************** -* Interprets the command line parameters provided to the application. -******************************************************************************/ -bool Application::processCommandLineParameters() -{ - // Output program version if requested. - if(cmdLineParser().isSet("version")) { - std::cout << qPrintable(QCoreApplication::applicationName()) << " " << qPrintable(QCoreApplication::applicationVersion()) << std::endl; - return false; - } - - // User can overwrite the number of parallel threads to use. - if(cmdLineParser().isSet("nthreads")) { - bool ok; - int nthreads = cmdLineParser().value("nthreads").toInt(&ok); - if(!ok || nthreads <= 0) - throw Exception(tr("Invalid thread count specified on command line.")); - setIdealThreadCount(nthreads); - } - - return true; -} +void test_func() {} /****************************************************************************** * Create the global instance of the right QCoreApplication derived class. @@ -301,6 +154,8 @@ if(sepIndex != std::string::npos) applicationPath.resize(sepIndex + 1); std::string fontPath = applicationPath + "../share/ovito/fonts"; + if(!QDir(QString::fromStdString(fontPath)).exists()) + fontPath = "/usr/share/fonts"; // On Linux, use the 'minimal' QPA platform plugin instead of the standard XCB plugin when no X server is available. // Still create a Qt GUI application object, because otherwise we cannot use (offscreen) font rendering functions. @@ -309,67 +164,32 @@ qputenv("QT_DEBUG_BACKINGSTORE", "1"); qputenv("QT_QPA_FONTDIR", fontPath.c_str()); - _app.reset(new QGuiApplication(argc, argv)); + new QGuiApplication(argc, argv); +#elif defined(Q_OS_MAC) + new QGuiApplication(argc, argv); #else - _app.reset(new QCoreApplication(argc, argv)); + new QCoreApplication(argc, argv); #endif } -} - -/****************************************************************************** -* Creates the global FileManager class instance. -******************************************************************************/ -FileManager* Application::createFileManager() -{ - return new FileManager(); -} - -/****************************************************************************** -* Starts the main event loop. -******************************************************************************/ -int Application::runApplication() -{ - if(guiMode()) { - // Enter the main event loop. - return QCoreApplication::exec(); - } else { - // Deliver all events that have been posted during the initialization. - QCoreApplication::processEvents(); - // Wait for all background tasks to finish before quitting. - if(_datasetContainer) - _datasetContainer->taskManager().waitForAll(); - return _exitCode; + new QGuiApplication(argc, argv); } } /****************************************************************************** -* This is called on program shutdown. +* Returns a pointer to the main dataset container. ******************************************************************************/ -void Application::shutdown() +DataSetContainer* Application::datasetContainer() const { - // Release dataset and all contained objects. - if(datasetContainer()) - datasetContainer()->setCurrentSet(nullptr); - - // Destroy auto-start objects. - _autostartObjects.clear(); - - // Shutdown global objects in reverse order they were initialized. - FileManager::shutdown(); - ControllerManager::shutdown(); - PluginManager::shutdown(); - - // Destroy Qt application object. - _app.reset(); + return _datasetContainer; } /****************************************************************************** -* Returns a pointer to the main dataset container. +* Creates the global FileManager class instance. ******************************************************************************/ -DataSetContainer* Application::datasetContainer() const +FileManager* Application::createFileManager() { - return _datasetContainer; + return new FileManager(); } /****************************************************************************** @@ -378,18 +198,18 @@ ******************************************************************************/ void Application::processRunOnceList() { - auto copy = _runOnceList; - _runOnceList.clear(); - for(auto entry = copy.cbegin(); entry != copy.cend(); ++entry) { + QMap,std::function> listCopy; + _runOnceList.swap(listCopy); + for(auto entry = listCopy.cbegin(); entry != listCopy.cend(); ++entry) { if(entry.key()) entry.value()(); } } /****************************************************************************** -* Handler function for exceptions used in console mode. +* Handler function for exceptions. ******************************************************************************/ -void Application::consoleExceptionHandler(const Exception& exception) +void Application::reportError(const Exception& exception, bool blocking) { for(int i = exception.messages().size() - 1; i >= 0; i--) { std::cerr << "ERROR: " << qPrintable(exception.messages()[i]) << std::endl; diff -Nru ovito-2.8.1+dfsg2/src/core/app/Application.h ovito-2.9.0+dfsg1/src/core/app/Application.h --- ovito-2.8.1+dfsg2/src/core/app/Application.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/app/Application.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_APPLICATION_H -#define __OVITO_APPLICATION_H +#pragma once + #include #include @@ -33,14 +33,11 @@ class OVITO_CORE_EXPORT Application : public QObject { Q_OBJECT - + public: /// \brief Returns the one and only instance of this class. - inline static Application& instance() { - OVITO_ASSERT_MSG(_instance != nullptr, "Application::instance()", "Application object has not been created yet."); - return *_instance; - } + inline static Application* instance() { return _instance; } /// \brief Constructor. Application(); @@ -49,24 +46,9 @@ virtual ~Application(); /// \brief Initializes the application. - /// \param argc The number of command line arguments. - /// \param argv The command line arguments. /// \return \c true if the application was initialized successfully; /// \c false if an error occurred and the program should be terminated. - /// - /// This is called on program startup. The method creates all other global objects and the main window. - bool initialize(int& argc, char** argv); - - /// \brief Enters the main event loop. - /// \return The program exit code. - /// - /// If the application has been started in console mode then this method does nothing. - int runApplication(); - - /// \brief Releases everything. - /// - /// This is called before the application exits. - void shutdown(); + bool initialize(); /// \brief Handler method for Qt error messages. /// @@ -94,8 +76,8 @@ /// or the global dataset container when running in console mode. DataSetContainer* datasetContainer() const; - /// \brief Returns the command line options passed to the program. - const QCommandLineParser& cmdLineParser() const { return _cmdLineParser; } + /// Returns the global FileManager class instance. + FileManager* fileManager() const { return _fileManager.get(); } /// This registers a functor object to be called after all events in the UI event queue have been processed and /// before control returns to the event loop. For a given target object, only one functor can be registered at a @@ -127,22 +109,11 @@ /// Returns the revision version number of the application. static int applicationVersionRevision(); -protected: - - /// Defines the program's command line parameters. - virtual void registerCommandLineParameters(QCommandLineParser& parser); - - /// Interprets the command line parameters provided to the application. - virtual bool processCommandLineParameters(); - /// Create the global instance of the right QCoreApplication derived class. virtual void createQtApplication(int& argc, char** argv); - /// Prepares application to start running. - virtual bool startupApplication() = 0; - - /// Creates the global FileManager class instance. - virtual FileManager* createFileManager(); + /// Handler function for exceptions. + virtual void reportError(const Exception& exception, bool blocking); private: @@ -152,11 +123,8 @@ protected: - /// The Qt application object. - QScopedPointer _app; - - /// The parser for the command line options passed to the program. - QCommandLineParser _cmdLineParser; + /// Creates the global FileManager class instance. + virtual FileManager* createFileManager(); /// Indicates that the application is running in console mode. bool _consoleMode; @@ -179,16 +147,16 @@ /// The number of parallel threads to be used by the application when doing computations. int _idealThreadCount; + /// The global file manager instance. + std::unique_ptr _fileManager; + /// The default message handler method of Qt. static QtMessageHandler defaultQtMessageHandler; - /// Handler function for exceptions used in console mode. - static void consoleExceptionHandler(const Exception& exception); - /// The one and only instance of this class. static Application* _instance; }; } // End of namespace -#endif // __OVITO_APPLICATION_H + diff -Nru ovito-2.8.1+dfsg2/src/core/app/StandaloneApplication.cpp ovito-2.9.0+dfsg1/src/core/app/StandaloneApplication.cpp --- ovito-2.8.1+dfsg2/src/core/app/StandaloneApplication.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/app/StandaloneApplication.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,210 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "StandaloneApplication.h" + +namespace Ovito { + +/****************************************************************************** +* This is called on program startup. +******************************************************************************/ +bool StandaloneApplication::initialize(int& argc, char** argv) +{ + if(!Application::initialize()) + return false; + + // Set the application name. + QCoreApplication::setApplicationName(tr("Ovito")); + QCoreApplication::setOrganizationName(tr("Ovito")); + QCoreApplication::setOrganizationDomain("ovito.org"); + QCoreApplication::setApplicationVersion(QStringLiteral(OVITO_VERSION_STRING)); + + // Register command line arguments. + _cmdLineParser.setApplicationDescription(tr("OVITO - Open Visualization Tool")); + registerCommandLineParameters(_cmdLineParser); + + // Parse command line arguments. + // Ignore unknown command line options for now. + QStringList arguments; + for(int i = 0; i < argc; i++) + arguments << QString::fromLocal8Bit(argv[i]); + + // Because they may collide with our own options, we should ignore script arguments though. + QStringList filteredArguments; + for(int i = 0; i < arguments.size(); i++) { + if(arguments[i] == QStringLiteral("--scriptarg")) { + i += 1; + continue; + } + filteredArguments.push_back(arguments[i]); + } + _cmdLineParser.parse(filteredArguments); + + // Output program version if requested. + if(cmdLineParser().isSet("version")) { + std::cout << qPrintable(QCoreApplication::applicationName()) << " " << qPrintable(QCoreApplication::applicationVersion()) << std::endl; + _consoleMode = true; + return true; + } + + try { + // Interpret the command line arguments. + if(!processCommandLineParameters()) { + return true; + } + } + catch(const Exception& ex) { + ex.reportError(true); + return false; + } + + // Always use desktop OpenGL implementation (avoid ANGLE on Windows). + QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL); + + // Create Qt application object. + createQtApplication(argc, argv); + + // Reactivate default "C" locale, which, in the meantime, might have been changed by QCoreApplication. + std::setlocale(LC_NUMERIC, "C"); + + try { + // Load plugins. + PluginManager::initialize(); + PluginManager::instance().loadAllPlugins(); + + // Load auto-start objects and let them register their custom command line options. + for(const OvitoObjectType* clazz : PluginManager::instance().listClasses(AutoStartObject::OOType)) { + OORef obj = static_object_cast(clazz->createInstance(nullptr)); + _autostartObjects.push_back(obj); + obj->registerCommandLineOptions(_cmdLineParser); + } + + // Parse the command line parameters again after the plugins have registered their options. + if(!_cmdLineParser.parse(arguments)) { + std::cerr << "Error: " << qPrintable(_cmdLineParser.errorText()) << std::endl; + _consoleMode = true; + shutdown(); + return false; + } + + // Help command line option implicitly activates console mode. + if(_cmdLineParser.isSet("help")) + _consoleMode = true; + + // Handle --help command line option. Print list of command line options and quit. + if(_cmdLineParser.isSet("help")) { + std::cout << qPrintable(_cmdLineParser.helpText()) << std::endl; + return true; + } + + // Prepares application to start running. + if(!startupApplication()) + return true; + + // Invoke auto-start objects. + for(const auto& obj : autostartObjects()) + obj->applicationStarted(); + } + catch(const Exception& ex) { + ex.reportError(true); + shutdown(); + return false; + } + return true; +} + +/****************************************************************************** +* Defines the program's command line parameters. +******************************************************************************/ +void StandaloneApplication::registerCommandLineParameters(QCommandLineParser& parser) +{ + parser.addOption(QCommandLineOption(QStringList{{"h", "help"}}, tr("Shows this list of program options and exits."))); + parser.addOption(QCommandLineOption(QStringList{{"v", "version"}}, tr("Prints the program version and exits."))); + parser.addOption(QCommandLineOption(QStringList{{"nthreads"}}, tr("Sets the number of parallel threads to use for computations."), QStringLiteral("N"))); +} + +/****************************************************************************** +* Interprets the command line parameters provided to the application. +******************************************************************************/ +bool StandaloneApplication::processCommandLineParameters() +{ + // Output program version if requested. + if(cmdLineParser().isSet("version")) { + std::cout << qPrintable(QCoreApplication::applicationName()) << " " << qPrintable(QCoreApplication::applicationVersion()) << std::endl; + return false; + } + + // User can overwrite the number of parallel threads to use. + if(cmdLineParser().isSet("nthreads")) { + bool ok; + int nthreads = cmdLineParser().value("nthreads").toInt(&ok); + if(!ok || nthreads <= 0) + throw Exception(tr("Invalid thread count specified on command line.")); + setIdealThreadCount(nthreads); + } + + return true; +} + +/****************************************************************************** +* Starts the main event loop. +******************************************************************************/ +int StandaloneApplication::runApplication() +{ + if(guiMode()) { + // Enter the main event loop. + return QCoreApplication::exec(); + } + else { + // Deliver all events that have been posted during the initialization. + QCoreApplication::processEvents(); + // Wait for all background tasks to finish before quitting. + if(_datasetContainer) + _datasetContainer->taskManager().waitForAll(); + return _exitCode; + } +} + +/****************************************************************************** +* This is called on program shutdown. +******************************************************************************/ +void StandaloneApplication::shutdown() +{ + // Release dataset and all contained objects. + if(datasetContainer()) + datasetContainer()->setCurrentSet(nullptr); + + // Destroy auto-start objects. + _autostartObjects.clear(); + + // Unload plugins. + PluginManager::shutdown(); + + // Destroy Qt application object. + delete QCoreApplication::instance(); +} + +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/app/StandaloneApplication.h ovito-2.9.0+dfsg1/src/core/app/StandaloneApplication.h --- ovito-2.8.1+dfsg2/src/core/app/StandaloneApplication.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/app/StandaloneApplication.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,86 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include "Application.h" + +namespace Ovito { + +/** + * \brief The application object used when running as a standalone application. + */ +class OVITO_CORE_EXPORT StandaloneApplication : public Application +{ + Q_OBJECT + +public: + + /// \brief Returns the one and only instance of this class. + inline static StandaloneApplication* instance() { + return qobject_cast(Application::instance()); + } + + /// \brief Initializes the application. + /// \param argc The number of command line arguments. + /// \param argv The command line arguments. + /// \return \c true if the application was initialized successfully; + /// \c false if an error occurred and the program should be terminated. + /// + /// This is called on program startup. + bool initialize(int& argc, char** argv); + + /// \brief Enters the main event loop. + /// \return The program exit code. + /// + /// If the application has been started in console mode then this method does nothing. + int runApplication(); + + /// \brief Releases everything. + /// + /// This is called before the application exits. + void shutdown(); + + /// \brief Returns the command line options passed to the program. + const QCommandLineParser& cmdLineParser() const { return _cmdLineParser; } + +protected: + + /// Defines the program's command line parameters. + virtual void registerCommandLineParameters(QCommandLineParser& parser); + + /// Interprets the command line parameters provided to the application. + virtual bool processCommandLineParameters(); + + /// Prepares application to start running. + virtual bool startupApplication() = 0; + +protected: + + /// The parser for the command line options passed to the program. + QCommandLineParser _cmdLineParser; +}; + +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/core/CMakeLists.txt ovito-2.9.0+dfsg1/src/core/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/core/CMakeLists.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -35,10 +35,10 @@ object/OvitoObjectType.cpp object/NativeOvitoObjectType.cpp plugins/Plugin.cpp - plugins/NativePlugin.cpp plugins/PluginManager.cpp plugins/autostart/AutoStartObject.cpp app/Application.cpp + app/StandaloneApplication.cpp reference/CloneHelper.cpp reference/PropertyFieldDescriptor.cpp reference/PropertyField.cpp @@ -79,6 +79,7 @@ scene/pipeline/PipelineObject.cpp scene/pipeline/Modifier.cpp scene/pipeline/ModifierApplication.cpp + scene/pipeline/AsyncPipelineEvaluationHelper utilities/units/UnitsManager.cpp utilities/io/ObjectSaveStream.cpp utilities/io/ObjectLoadStream.cpp @@ -86,8 +87,10 @@ utilities/io/SftpJob.cpp utilities/io/CompressedTextReader.cpp utilities/io/CompressedTextWriter.cpp - utilities/concurrent/Future.cpp + utilities/concurrent/PromiseWatcher.cpp + utilities/concurrent/Promise.cpp utilities/concurrent/TaskManager.cpp + utilities/concurrent/Task.cpp utilities/mesh/TriMesh.cpp rendering/SceneRenderer.cpp rendering/noninteractive/NonInteractiveSceneRenderer.cpp @@ -121,13 +124,16 @@ # Build library ADD_LIBRARY(Core SHARED Core.cpp ${SourceFiles} ${ResourceFiles}) +# Pass name of core plugin to the code. +TARGET_COMPILE_DEFINITIONS(Core PRIVATE "OVITO_PLUGIN_NAME=\"Core\"") + # Set default include directory. TARGET_INCLUDE_DIRECTORIES(Core PUBLIC "$") # Required by built-in SSH client. TARGET_LINK_LIBRARIES(Core PRIVATE QSsh) -# Link to ZLib library. +# Link to zlib library. TARGET_LINK_LIBRARIES(Core PRIVATE ${ZLIB_LIBRARIES}) TARGET_INCLUDE_DIRECTORIES(Core PRIVATE "${ZLIB_INCLUDE_DIRS}") @@ -142,7 +148,7 @@ IF(LIBAV_FOUND) TARGET_COMPILE_DEFINITIONS(Core PUBLIC OVITO_VIDEO_OUTPUT_SUPPORT) TARGET_LINK_LIBRARIES(Core PRIVATE ${Libav_LIBRARIES}) - TARGET_INCLUDE_DIRECTORIES(Core PRIVATE ${Libav_INCLUDE_DIRS}) + TARGET_INCLUDE_DIRECTORIES(Core BEFORE PRIVATE ${Libav_INCLUDE_DIRS}) ENDIF() # Define the OVITO_DEBUG macro in debug builds. @@ -158,9 +164,9 @@ ENDIF() # Pass version information to source code. -SET_SOURCE_FILES_PROPERTIES("app/Application.cpp" PROPERTIES COMPILE_DEFINITIONS +SET_SOURCE_FILES_PROPERTIES(app/Application.cpp app/StandaloneApplication.cpp PROPERTIES COMPILE_DEFINITIONS "OVITO_VERSION_MAJOR=${OVITO_VERSION_MAJOR};OVITO_VERSION_MINOR=${OVITO_VERSION_MINOR};OVITO_VERSION_REVISION=${OVITO_VERSION_REVISION};OVITO_VERSION_STRING=\"${OVITO_VERSION_STRING}\"") -SET_SOURCE_FILES_PROPERTIES("utilities/io/SaveStream.cpp" "utilities/io/LoadStream.cpp" PROPERTIES COMPILE_DEFINITIONS +SET_SOURCE_FILES_PROPERTIES(utilities/io/SaveStream.cpp utilities/io/LoadStream.cpp PROPERTIES COMPILE_DEFINITIONS "OVITO_FILE_FORMAT_VERSION=${OVITO_FILE_FORMAT_VERSION}") # Speed up compilation by using precompiled headers. @@ -198,7 +204,7 @@ FOREACH(dll ${lib_dll}) OVITO_INSTALL_DLL("${dll}") ENDFOREACH() - ELSEIF(UNIX AND NOT APPLE AND OVITO_MONOLITHIC_BUILD) + ELSEIF(UNIX AND NOT APPLE AND OVITO_REDISTRIBUTABLE_PACKAGE) FILE(GLOB lib_versions "${lib}*") FOREACH(lib_version ${lib_versions}) INSTALL(FILES "${lib_version}" DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}/") diff -Nru ovito-2.8.1+dfsg2/src/core/Core.h ovito-2.9.0+dfsg1/src/core/Core.h --- ovito-2.8.1+dfsg2/src/core/Core.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/Core.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief This file includes STL and third-party library headers required by OVITO. It is included by all .cpp files belonging to OVITO's codebase. */ -#ifndef __OVITO_CORE_H -#define __OVITO_CORE_H +#pragma once + /****************************************************************************** * Standard Template Library (STL) @@ -52,11 +52,6 @@ #include /****************************************************************************** -* Boost Library -******************************************************************************/ -#include - -/****************************************************************************** * QT Library ******************************************************************************/ #include @@ -69,6 +64,7 @@ #include #include #include +#include #include #include #include @@ -83,10 +79,16 @@ #include #include -#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) -# error "OVITO requires at least Qt 5.2" +#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) +# error "OVITO requires Qt 5.4 or newer." #endif +/****************************************************************************** +* Boost Library +******************************************************************************/ +#include + + #ifdef Core_EXPORTS // This is defined by CMake when building the Core library. # define OVITO_CORE_EXPORT Q_DECL_EXPORT #else @@ -154,4 +156,4 @@ #include #include -#endif // __OVITO_CORE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/DataSetContainer.cpp ovito-2.9.0+dfsg1/src/core/dataset/DataSetContainer.cpp --- ovito-2.8.1+dfsg2/src/core/dataset/DataSetContainer.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/DataSetContainer.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -31,23 +31,18 @@ #include #include #include -#include - -#ifdef Q_OS_UNIX - #include -#endif namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) -IMPLEMENT_OVITO_OBJECT(Core, DataSetContainer, RefMaker); -DEFINE_FLAGS_REFERENCE_FIELD(DataSetContainer, _currentSet, "CurrentSet", DataSet, PROPERTY_FIELD_NO_UNDO | PROPERTY_FIELD_NO_CHANGE_MESSAGE); +IMPLEMENT_OVITO_OBJECT(DataSetContainer, RefMaker); +DEFINE_FLAGS_REFERENCE_FIELD(DataSetContainer, currentSet, "CurrentSet", DataSet, PROPERTY_FIELD_NO_UNDO | PROPERTY_FIELD_NO_CHANGE_MESSAGE); /****************************************************************************** * Initializes the dataset manager. ******************************************************************************/ -DataSetContainer::DataSetContainer() : RefMaker(nullptr), _taskManager() +DataSetContainer::DataSetContainer() : RefMaker(nullptr) { - INIT_PROPERTY_FIELD(DataSetContainer::_currentSet); + INIT_PROPERTY_FIELD(currentSet); } /****************************************************************************** @@ -55,7 +50,7 @@ ******************************************************************************/ void DataSetContainer::referenceReplaced(const PropertyFieldDescriptor& field, RefTarget* oldTarget, RefTarget* newTarget) { - if(field == PROPERTY_FIELD(DataSetContainer::_currentSet)) { + if(field == PROPERTY_FIELD(currentSet)) { if(oldTarget) { DataSet* oldDataSet = static_object_cast(oldTarget); @@ -141,57 +136,5 @@ } } - -/****************************************************************************** -* This function blocks execution until some operation has been completed. -******************************************************************************/ -bool DataSetContainer::waitUntil(const std::function& callback, const QString& message, AbstractProgressDisplay* progressDisplay) -{ - OVITO_ASSERT_MSG(QThread::currentThread() == QCoreApplication::instance()->thread(), "DataSetContainer::waitUntil()", "This function may only be called from the main thread."); - - // Check if operation is already completed. - if(callback()) - return true; - - // Boolean flag which is set by the POSIX signal handler when user - // presses Ctrl+C to interrupt the program. In console mode, the - // DataSetContainer::waitUntil() function breaks out of the waiting loop - // when this flag is set. - static QAtomicInt _userInterrupt; - -#ifdef Q_OS_UNIX - // Install POSIX signal handler to catch Ctrl+C key press in console mode. - auto oldSignalHandler = ::signal(SIGINT, [](int) { _userInterrupt.storeRelease(1); }); -#endif - - try { - - // Poll callback function until it returns true. -#ifdef Q_OS_UNIX - while(!callback() && !_userInterrupt.loadAcquire()) { -#else - while(!callback()) { -#endif - QCoreApplication::processEvents(); - QThread::msleep(20); - } - -#ifdef Q_OS_UNIX - ::signal(SIGINT, oldSignalHandler); -#endif - } - catch(...) { -#ifdef Q_OS_UNIX - ::signal(SIGINT, oldSignalHandler); -#endif - throw; - } - if(_userInterrupt.load()) { - taskManager().cancelAll(); - return false; - } - return true; -} - OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/DataSetContainer.h ovito-2.9.0+dfsg1/src/core/dataset/DataSetContainer.h --- ovito-2.8.1+dfsg2/src/core/dataset/DataSetContainer.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/DataSetContainer.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DATASET_CONTAINER_H -#define __OVITO_DATASET_CONTAINER_H +#pragma once + #include #include @@ -45,31 +45,12 @@ clearAllReferences(); } - /// \brief Returns the current dataset being edited by the user. - /// \return The active dataset. - DataSet* currentSet() const { return _currentSet; } - - /// \brief Sets the current dataset being edited by the user. - /// \param set The dataset that should be shown in the main window. - void setCurrentSet(DataSet* set) { _currentSet = set; } - /// \brief Returns the manager of background tasks. /// \return Reference to the task manager, which is part of this dataset manager. /// /// Use the task manager to start and control background jobs. TaskManager& taskManager() { return _taskManager; } - - /// \brief This function blocks execution until some operation has been completed. - /// The function displays a progress dialog to block access to the application main window. - /// The dialog allows the user to cancel the operation. - /// \param callback This callback function will be polled to check whether the operation has finished. - /// The callback function should return true to indicate that the operation has finished. - /// \param message The text to be shown to the user while waiting. - /// \param progressDisplay The progress display/dialog to be used for showing the message. - /// If NULL, the function will create and show its own progress dialog box. - /// \return true on success; false if the operation has been canceled by the user. - virtual bool waitUntil(const std::function& callback, const QString& message, AbstractProgressDisplay* progressDisplay = nullptr); - + Q_SIGNALS: /// Is emitted when a another dataset has become the active dataset. @@ -138,7 +119,7 @@ private: /// The current dataset being edited by the user. - ReferenceField _currentSet; + DECLARE_MODIFIABLE_REFERENCE_FIELD(DataSet, currentSet, setCurrentSet); /// The list of running compute tasks. TaskManager _taskManager; @@ -156,11 +137,9 @@ Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_currentSet); }; OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_DATASET_CONTAINER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/DataSet.cpp ovito-2.9.0+dfsg1/src/core/dataset/DataSet.cpp --- ovito-2.8.1+dfsg2/src/core/dataset/DataSet.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/DataSet.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,38 +30,41 @@ #include #include #include -#include +#include #ifdef OVITO_VIDEO_OUTPUT_SUPPORT #include #endif namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, DataSet, RefTarget); -DEFINE_FLAGS_REFERENCE_FIELD(DataSet, _viewportConfig, "ViewportConfiguration", ViewportConfiguration, PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_REFERENCE_FIELD(DataSet, _animSettings, "AnimationSettings", AnimationSettings, PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_REFERENCE_FIELD(DataSet, _sceneRoot, "SceneRoot", SceneRoot, PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_ALWAYS_DEEP_COPY); -DEFINE_FLAGS_REFERENCE_FIELD(DataSet, _selection, "CurrentSelection", SelectionSet, PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_ALWAYS_DEEP_COPY); -DEFINE_FLAGS_REFERENCE_FIELD(DataSet, _renderSettings, "RenderSettings", RenderSettings, PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(DataSet, _viewportConfig, "Viewport Configuration"); -SET_PROPERTY_FIELD_LABEL(DataSet, _animSettings, "Animation Settings"); -SET_PROPERTY_FIELD_LABEL(DataSet, _sceneRoot, "Scene"); -SET_PROPERTY_FIELD_LABEL(DataSet, _selection, "Selection"); -SET_PROPERTY_FIELD_LABEL(DataSet, _renderSettings, "Render Settings"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(DataSet, RefTarget); +DEFINE_FLAGS_REFERENCE_FIELD(DataSet, viewportConfig, "ViewportConfiguration", ViewportConfiguration, PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(DataSet, animationSettings, "AnimationSettings", AnimationSettings, PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(DataSet, sceneRoot, "SceneRoot", SceneRoot, PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_ALWAYS_DEEP_COPY); +DEFINE_FLAGS_REFERENCE_FIELD(DataSet, selection, "CurrentSelection", SelectionSet, PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_ALWAYS_DEEP_COPY); +DEFINE_FLAGS_REFERENCE_FIELD(DataSet, renderSettings, "RenderSettings", RenderSettings, PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(DataSet, globalObjects, "GlobalObjects", RefTarget, PROPERTY_FIELD_ALWAYS_CLONE|PROPERTY_FIELD_ALWAYS_DEEP_COPY); +SET_PROPERTY_FIELD_LABEL(DataSet, viewportConfig, "Viewport Configuration"); +SET_PROPERTY_FIELD_LABEL(DataSet, animationSettings, "Animation Settings"); +SET_PROPERTY_FIELD_LABEL(DataSet, sceneRoot, "Scene"); +SET_PROPERTY_FIELD_LABEL(DataSet, selection, "Selection"); +SET_PROPERTY_FIELD_LABEL(DataSet, renderSettings, "Render Settings"); +SET_PROPERTY_FIELD_LABEL(DataSet, globalObjects, "Global objects"); /****************************************************************************** * Constructor. ******************************************************************************/ DataSet::DataSet(DataSet* self) : RefTarget(this), _unitsManager(this) { - INIT_PROPERTY_FIELD(DataSet::_viewportConfig); - INIT_PROPERTY_FIELD(DataSet::_animSettings); - INIT_PROPERTY_FIELD(DataSet::_sceneRoot); - INIT_PROPERTY_FIELD(DataSet::_selection); - INIT_PROPERTY_FIELD(DataSet::_renderSettings); + INIT_PROPERTY_FIELD(viewportConfig); + INIT_PROPERTY_FIELD(animationSettings); + INIT_PROPERTY_FIELD(sceneRoot); + INIT_PROPERTY_FIELD(selection); + INIT_PROPERTY_FIELD(renderSettings); + INIT_PROPERTY_FIELD(globalObjects); _viewportConfig = createDefaultViewportConfiguration(); - _animSettings = new AnimationSettings(this); + _animationSettings = new AnimationSettings(this); _sceneRoot = new SceneRoot(this); _selection = new SelectionSet(this); _renderSettings = new RenderSettings(this); @@ -72,6 +75,11 @@ ******************************************************************************/ DataSet::~DataSet() { + if(_sceneReadyRequest) { + _sceneReadyRequest->cancel(); + _sceneReadyRequest->setFinished(); + _sceneReadyRequest.reset(); + } } /****************************************************************************** @@ -111,18 +119,28 @@ ******************************************************************************/ bool DataSet::referenceEvent(RefTarget* source, ReferenceEvent* event) { - OVITO_ASSERT_MSG(QThread::currentThread() == QCoreApplication::instance()->thread(), "DataSet::referenceEvent", "Reference events may only be processed in the main thread."); + OVITO_ASSERT_MSG(!QCoreApplication::instance() || QThread::currentThread() == QCoreApplication::instance()->thread(), "DataSet::referenceEvent", "Reference events may only be processed in the main thread."); if(event->type() == ReferenceEvent::TargetChanged || event->type() == ReferenceEvent::PendingStateChanged) { // Update the viewports whenever something has changed in the current data set. - if(source != viewportConfig() && source != animationSettings()) { + if(source == sceneRoot() || source == selection() || source == renderSettings()) { // Do not automatically update while in the process of jumping to a new animation frame. if(!animationSettings()->isTimeChanging()) viewportConfig()->updateViewports(); if(source == sceneRoot() && event->type() == ReferenceEvent::PendingStateChanged) { - notifySceneReadyListeners(); + // Serve requests waiting for scene to become ready. + if(_sceneReadyRequest) { + Application::instance()->runOnceLater(this, [this]() { + if(_sceneReadyRequest) { + if(_sceneReadyRequest->isCanceled() || isSceneReady(animationSettings()->time())) { + _sceneReadyRequest->setFinished(); + _sceneReadyRequest.reset(); + } + } + }); + } } } } @@ -134,25 +152,25 @@ ******************************************************************************/ void DataSet::referenceReplaced(const PropertyFieldDescriptor& field, RefTarget* oldTarget, RefTarget* newTarget) { - if(field == PROPERTY_FIELD(DataSet::_viewportConfig)) { + if(field == PROPERTY_FIELD(viewportConfig)) { Q_EMIT viewportConfigReplaced(viewportConfig()); } - else if(field == PROPERTY_FIELD(DataSet::_animSettings)) { + else if(field == PROPERTY_FIELD(animationSettings)) { // Stop animation playback when animation settings are being replaced. if(AnimationSettings* oldAnimSettings = static_object_cast(oldTarget)) oldAnimSettings->stopAnimationPlayback(); Q_EMIT animationSettingsReplaced(animationSettings()); } - else if(field == PROPERTY_FIELD(DataSet::_renderSettings)) { + else if(field == PROPERTY_FIELD(renderSettings)) { Q_EMIT renderSettingsReplaced(renderSettings()); } - else if(field == PROPERTY_FIELD(DataSet::_selection)) { + else if(field == PROPERTY_FIELD(selection)) { Q_EMIT selectionSetReplaced(selection()); } - // Install a signal/slot connection that updates the viewports every time the animation time changes. - if(field == PROPERTY_FIELD(DataSet::_viewportConfig) || field == PROPERTY_FIELD(DataSet::_animSettings)) { + // Install a signal/slot connection that updates the viewports every time the animation time has changed. + if(field == PROPERTY_FIELD(viewportConfig) || field == PROPERTY_FIELD(animationSettings)) { disconnect(_updateViewportOnTimeChangeConnection); if(animationSettings() && viewportConfig()) { _updateViewportOnTimeChangeConnection = connect(animationSettings(), &AnimationSettings::timeChangeComplete, viewportConfig(), &ViewportConfiguration::updateViewports); @@ -200,7 +218,7 @@ } /****************************************************************************** -* Checks all scene nodes if their geometry pipeline is fully evaluated at the +* Checks all scene nodes if their data pipeline is fully evaluated at the * given animation time. ******************************************************************************/ bool DataSet::isSceneReady(TimePoint time) const @@ -208,55 +226,57 @@ OVITO_ASSERT_MSG(QThread::currentThread() == QCoreApplication::instance()->thread(), "DataSet::isSceneReady", "This function may only be called from the main thread."); OVITO_CHECK_OBJECT_POINTER(sceneRoot()); - // Iterate over all object nodes and request an evaluation of their geometry pipeline. - bool isReady = sceneRoot()->visitObjectNodes([time](ObjectNode* node) { - return (node->evalPipeline(time).status().type() != PipelineStatus::Pending); + PipelineEvalRequest pipelineRequest(time, true); // Request display objects to be ready as well. + + // Iterate over all object nodes and make an attempt to request results from their data pipelines. + // The scene is ready if none of the results has status 'pending'. + bool isReady = sceneRoot()->visitObjectNodes([&pipelineRequest](ObjectNode* node) { + return (node->evaluatePipelineImmediately(pipelineRequest).status().type() != PipelineStatus::Pending); }); return isReady; } /****************************************************************************** -* Calls the given slot as soon as the geometry pipelines of all scene nodes has been -* completely evaluated. +* This function blocks until the scene has become ready. ******************************************************************************/ -void DataSet::runWhenSceneIsReady(const std::function& fn) +Future DataSet::makeSceneReady(const QString& message) { - OVITO_ASSERT_MSG(QThread::currentThread() == QCoreApplication::instance()->thread(), "DataSet::runWhenSceneIsReady", "This function may only be called from the main thread."); - OVITO_CHECK_OBJECT_POINTER(sceneRoot()); - - TimePoint time = animationSettings()->time(); - - // Iterate over all object nodes and request an evaluation of their geometry pipeline. - bool isReady = sceneRoot()->visitObjectNodes([time](ObjectNode* node) { - return (node->evalPipeline(time).status().type() != PipelineStatus::Pending); - }); - - if(isReady) - fn(); - else - _sceneReadyListeners.push_back(fn); -} + // Perform a first quick check if scene is already ready. + if(isSceneReady(animationSettings()->time())) { + if(!_sceneReadyRequest) + return Future::createImmediate(message); + else { + _sceneReadyRequest->setFinished(); + Future future(_sceneReadyRequest); + _sceneReadyRequest.reset(); + return future; + } + } -/****************************************************************************** -* Checks if the scene is ready and calls all registered listeners. -******************************************************************************/ -void DataSet::notifySceneReadyListeners() -{ - if(!_sceneReadyListeners.empty() && isSceneReady(animationSettings()->time())) { - auto oldListenerList = _sceneReadyListeners; - _sceneReadyListeners.clear(); - for(const auto& listener : oldListenerList) { - listener(); + // Re-use existing request. + if(_sceneReadyRequest) { + if(!_sceneReadyRequest->isCanceled()) + return Future(_sceneReadyRequest); + else { + _sceneReadyRequest->setFinished(); + _sceneReadyRequest.reset(); } } + + // If not ready yet, create a future. + Future future = Future::createWithPromise(); + _sceneReadyRequest = future.promise(); + _sceneReadyRequest->setStarted(); + _sceneReadyRequest->setProgressText(message); + return future; } /****************************************************************************** * This is the high-level rendering function, which invokes the renderer to generate one or more * output images of the scene. All rendering parameters are specified in the RenderSettings object. ******************************************************************************/ -bool DataSet::renderScene(RenderSettings* settings, Viewport* viewport, FrameBuffer* frameBuffer, AbstractProgressDisplay* progressDisplay) +bool DataSet::renderScene(RenderSettings* settings, Viewport* viewport, FrameBuffer* frameBuffer, TaskManager& taskManager) { OVITO_CHECK_OBJECT_POINTER(settings); OVITO_CHECK_OBJECT_POINTER(viewport); @@ -266,7 +286,8 @@ SceneRenderer* renderer = settings->renderer(); if(!renderer) throwException(tr("No rendering engine has been selected.")); - bool wasCanceled = false; + SynchronousTask renderTask(taskManager); + renderTask.setProgressText(tr("Initializing renderer")); try { // Resize output frame buffer. @@ -300,8 +321,9 @@ // Render a single frame. TimePoint renderTime = animationSettings()->time(); int frameNumber = animationSettings()->timeToFrame(renderTime); - if(!renderFrame(renderTime, frameNumber, settings, renderer, viewport, frameBuffer, videoEncoder, progressDisplay)) - wasCanceled = true; + renderTask.setProgressText(QString()); + if(!renderFrame(renderTime, frameNumber, settings, renderer, viewport, frameBuffer, videoEncoder, taskManager)) + renderTask.cancel(); } else if(settings->renderingRangeType() == RenderSettings::ANIMATION_INTERVAL || settings->renderingRangeType() == RenderSettings::CUSTOM_INTERVAL) { // Render an animation interval. @@ -320,20 +342,18 @@ numberOfFrames = (numberOfFrames + settings->everyNthFrame() - 1) / settings->everyNthFrame(); if(numberOfFrames < 1) throwException(tr("Invalid rendering range: Frame %1 to %2").arg(settings->customRangeStart()).arg(settings->customRangeEnd())); - if(progressDisplay) - progressDisplay->setMaximum(numberOfFrames); + renderTask.setProgressMaximum(numberOfFrames); // Render frames, one by one. for(int frameIndex = 0; frameIndex < numberOfFrames; frameIndex++) { - if(progressDisplay) - progressDisplay->setValue(frameIndex); - int frameNumber = firstFrameNumber + frameIndex * settings->everyNthFrame() + settings->fileNumberBase(); - if(!renderFrame(renderTime, frameNumber, settings, renderer, viewport, frameBuffer, videoEncoder, progressDisplay)) { - wasCanceled = true; - break; - } - if(progressDisplay && progressDisplay->wasCanceled()) + + renderTask.setProgressValue(frameIndex); + renderTask.setProgressText(tr("Rendering animation (frame %1 of %2)").arg(frameIndex+1).arg(numberOfFrames)); + + if(!renderFrame(renderTime, frameNumber, settings, renderer, viewport, frameBuffer, videoEncoder, taskManager)) + renderTask.cancel(); + if(renderTask.isCanceled()) break; // Go to next animation frame. @@ -350,9 +370,6 @@ // Shutdown renderer. renderer->endRender(); - - if(progressDisplay && progressDisplay->wasCanceled()) - wasCanceled = true; } catch(Exception& ex) { // Shutdown renderer. @@ -362,21 +379,21 @@ throw; } - return !wasCanceled; + return !renderTask.isCanceled(); } /****************************************************************************** * Renders a single frame and saves the output file. ******************************************************************************/ bool DataSet::renderFrame(TimePoint renderTime, int frameNumber, RenderSettings* settings, SceneRenderer* renderer, Viewport* viewport, - FrameBuffer* frameBuffer, VideoEncoder* videoEncoder, AbstractProgressDisplay* progressDisplay) + FrameBuffer* frameBuffer, VideoEncoder* videoEncoder, TaskManager& taskManager) { // Determine output filename for this frame. QString imageFilename; if(settings->saveToFile() && !videoEncoder) { imageFilename = settings->imageFilename(); if(imageFilename.isEmpty()) - throwException(tr("Cannot save rendered image to file. Output filename has not been specified.")); + throwException(tr("Cannot save rendered image to file, because no output filename has been specified.")); if(settings->renderingRangeType() != RenderSettings::CURRENT_FRAME) { // Append frame number to file name if rendering an animation. @@ -393,12 +410,10 @@ animationSettings()->setTime(renderTime); // Wait until the scene is ready. - if(!waitUntilSceneIsReady(tr("Preparing frame %1").arg(frameNumber), progressDisplay)) + Future sceneReadyFuture = makeSceneReady(tr("Preparing frame %1").arg(frameNumber)); + if(!taskManager.waitForTask(sceneReadyFuture)) return false; - if(progressDisplay) - progressDisplay->setStatusText(tr("Rendering frame %1").arg(frameNumber)); - // Request scene bounding box. Box3 boundingBox = renderer->sceneBoundingBox(renderTime); @@ -407,12 +422,18 @@ // Render one frame. frameBuffer->clear(); - renderer->beginFrame(renderTime, projParams, viewport); - if(!renderer->renderFrame(frameBuffer, SceneRenderer::NonStereoscopic, progressDisplay) || (progressDisplay && progressDisplay->wasCanceled())) { - renderer->endFrame(); - return false; + try { + renderer->beginFrame(renderTime, projParams, viewport); + if(!renderer->renderFrame(frameBuffer, SceneRenderer::NonStereoscopic, taskManager)) { + renderer->endFrame(false); + return false; + } + renderer->endFrame(true); + } + catch(...) { + renderer->endFrame(false); + throw; } - renderer->endFrame(); // Apply viewport overlays. for(ViewportOverlay* overlay : viewport->overlays()) { @@ -441,20 +462,6 @@ } /****************************************************************************** -* This function blocks until the scene has become ready. -******************************************************************************/ -bool DataSet::waitUntilSceneIsReady(const QString& message, AbstractProgressDisplay* progressDisplay) -{ - std::atomic_flag keepWaiting; - keepWaiting.test_and_set(); - runWhenSceneIsReady( [&keepWaiting]() { keepWaiting.clear(); } ); - - return container()->waitUntil([&keepWaiting]() { - return !keepWaiting.test_and_set(); - }, message, progressDisplay); -} - -/****************************************************************************** * Saves the dataset to the given file. ******************************************************************************/ void DataSet::saveToFile(const QString& filePath) diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/DataSet.h ovito-2.9.0+dfsg1/src/core/dataset/DataSet.h --- ovito-2.8.1+dfsg2/src/core/dataset/DataSet.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/DataSet.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,13 +19,15 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DATASET_H -#define __OVITO_DATASET_H +#pragma once + #include #include #include #include +#include +#include #include "UndoStack.h" namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) @@ -53,26 +55,6 @@ /// \brief Destructor. virtual ~DataSet(); - /// \brief Returns a reference to the viewport configuration associated with this dataset. - /// \return The internal object managing the viewports. - ViewportConfiguration* viewportConfig() const { return _viewportConfig; } - - /// \brief Returns the animation settings. - /// \return The internal object storing the animation settings of the scene. - AnimationSettings* animationSettings() { return _animSettings; } - - /// \brief Returns this dataset's root scene node. - /// \return The root node of the scene tree. - SceneRoot* sceneRoot() const { return _sceneRoot; } - - /// \brief Returns the selection set. - /// \return The current selection set storing the list of selected scene nodes. - SelectionSet* selection() const { return _selection; } - - /// \brief Returns the rendering settings for this scene. - /// \return The current rendering settings. - RenderSettings* renderSettings() const { return _renderSettings; } - /// \brief Returns the path where this dataset is stored on disk. /// \return The location where the dataset is stored or will be stored on disk. const QString& filePath() const { return _filePath; } @@ -128,21 +110,11 @@ /// sequence, the buffer will contain only the last rendered frame when the function returns. /// \return true on success; false if operation has been canceled by the user. /// \throw Exception on error. - bool renderScene(RenderSettings* settings, Viewport* viewport, FrameBuffer* frameBuffer, AbstractProgressDisplay* progressDisplay = nullptr); - - /// \brief Checks all scene nodes if their geometry pipeline is fully evaluated at the given animation time. - bool isSceneReady(TimePoint time) const; + bool renderScene(RenderSettings* settings, Viewport* viewport, FrameBuffer* frameBuffer, TaskManager& taskManager); - /// \brief Calls the given slot as soon as the geometry pipelines of all scene nodes has been - /// completely evaluated. - void runWhenSceneIsReady(const std::function& fn); - - /// \brief This function blocks until the scene has become ready. - /// \param message The text to be shown to the user while waiting. - /// \param progressDisplay The progress display/dialog to be use to show the message. - /// If NULL, the function will show its own progress dialog box. - /// \return true on success; false if the operation has been canceled by the user. - bool waitUntilSceneIsReady(const QString& message, AbstractProgressDisplay* progressDisplay = nullptr); + /// \brief This function returns a future that is triggered once all data pipelines in the scene become ready. + /// \param message An optional messge text to be shown to the user while waiting. + Future makeSceneReady(const QString& message = QString()); /// \brief Saves the dataset to the given file. /// \throw Exception on error. @@ -150,6 +122,27 @@ /// Note that this method does NOT invoke setFilePath(). void saveToFile(const QString& filePath); + /// \brief Appends an object to this dataset's list of global objects. + void addGlobalObject(RefTarget* target) { + if(!_globalObjects.contains(target)) + _globalObjects.push_back(target); + } + + /// \brief Removes an object from this dataset's list of global objects. + void removeGlobalObject(int index) { + _globalObjects.remove(index); + } + + /// \brief Looks for a global object of the given type. + template + T* findGlobalObject() const { + for(RefTarget* obj : globalObjects()) { + T* castObj = dynamic_object_cast(obj); + if(castObj) return castObj; + } + return nullptr; + } + Q_SIGNALS: /// \brief This signal is emitted whenever the current viewport configuration of this dataset @@ -187,30 +180,33 @@ /// Renders a single frame and saves the output file. This is part of the implementation of the renderScene() method. bool renderFrame(TimePoint renderTime, int frameNumber, RenderSettings* settings, SceneRenderer* renderer, - Viewport* viewport, FrameBuffer* frameBuffer, VideoEncoder* videoEncoder, AbstractProgressDisplay* progressDisplay); + Viewport* viewport, FrameBuffer* frameBuffer, VideoEncoder* videoEncoder, TaskManager& taskManager); /// Returns a viewport configuration that is used as template for new scenes. OORef createDefaultViewportConfiguration(); - /// Checks if the scene is ready and calls all registered listeners. - void notifySceneReadyListeners(); + /// \brief Checks if all scene nodes are ready and their data pipelines can provide fully computed results. + bool isSceneReady(TimePoint time) const; private: /// The configuration of the viewports. - ReferenceField _viewportConfig; + DECLARE_REFERENCE_FIELD(ViewportConfiguration, viewportConfig); /// Current animation settings. - ReferenceField _animSettings; + DECLARE_REFERENCE_FIELD(AnimationSettings, animationSettings); /// Root node of the scene node tree. - ReferenceField _sceneRoot; + DECLARE_REFERENCE_FIELD(SceneRoot, sceneRoot); /// The current node selection set. - ReferenceField _selection; + DECLARE_REFERENCE_FIELD(SelectionSet, selection); /// The settings used when rendering the scene. - ReferenceField _renderSettings; + DECLARE_REFERENCE_FIELD(RenderSettings, renderSettings); + + /// Global data managed by plugins. + DECLARE_MODIFIABLE_VECTOR_REFERENCE_FIELD(RefTarget, globalObjects, setGlobalObjects); /// The file path this DataSet has been saved to. QString _filePath; @@ -221,23 +217,17 @@ /// The manager of ParameterUnit objects. UnitsManager _unitsManager; - /// List of listener objects that want to get notified when the scene is ready. - QVector> _sceneReadyListeners; + /// Active request waiting for the scene to become ready. + PromisePtr _sceneReadyRequest; /// This signal/slot connection updates the viewports when the animation time changes. QMetaObject::Connection _updateViewportOnTimeChangeConnection; Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_viewportConfig); - DECLARE_REFERENCE_FIELD(_animSettings); - DECLARE_REFERENCE_FIELD(_sceneRoot); - DECLARE_REFERENCE_FIELD(_selection); - DECLARE_REFERENCE_FIELD(_renderSettings); }; OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_DATASET_H + diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/importexport/AttributeFileExporter.cpp ovito-2.9.0+dfsg1/src/core/dataset/importexport/AttributeFileExporter.cpp --- ovito-2.8.1+dfsg2/src/core/dataset/importexport/AttributeFileExporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/importexport/AttributeFileExporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,19 +23,20 @@ #include #include #include +#include #include "AttributeFileExporter.h" namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(DataIO) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, AttributeFileExporter, FileExporter); -DEFINE_PROPERTY_FIELD(AttributeFileExporter, _attributesToExport, "AttributesToExport"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(AttributeFileExporter, FileExporter); +DEFINE_PROPERTY_FIELD(AttributeFileExporter, attributesToExport, "AttributesToExport"); /****************************************************************************** * Constructs a new instance of the class. ******************************************************************************/ AttributeFileExporter::AttributeFileExporter(DataSet* dataset) : FileExporter(dataset) { - INIT_PROPERTY_FIELD(AttributeFileExporter::_attributesToExport); + INIT_PROPERTY_FIELD(attributesToExport); } /****************************************************************************** @@ -106,36 +107,42 @@ /****************************************************************************** * Evaluates the pipeline of an ObjectNode and returns the computed attributes. ******************************************************************************/ -QVariantMap AttributeFileExporter::getAttributes(SceneNode* sceneNode, TimePoint time) +bool AttributeFileExporter::getAttributes(SceneNode* sceneNode, TimePoint time, QVariantMap& attributes, TaskManager& taskManager) { ObjectNode* objectNode = dynamic_object_cast(sceneNode); if(!objectNode) throwException(tr("The scene node to be exported is not an object node.")); // Evaluate pipeline of object node. - const PipelineFlowState& state = objectNode->evalPipeline(time); + auto evalFuture = objectNode->evaluatePipelineAsync(PipelineEvalRequest(time, false)); + if(!taskManager.waitForTask(evalFuture)) + return false; + + const PipelineFlowState& state = evalFuture.result(); if(state.isEmpty()) throwException(tr("The object to be exported does not contain any data.")); - QVariantMap attributes = state.attributes(); + attributes = state.attributes(); attributes.insert(QStringLiteral("Frame"), sceneNode->dataset()->animationSettings()->timeToFrame(time)); - return attributes; + return true; } /****************************************************************************** * Exports a single animation frame to the current output file. *****************************************************************************/ -bool AttributeFileExporter::exportFrame(int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) +bool AttributeFileExporter::exportFrame(int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) { - if(!FileExporter::exportFrame(frameNumber, time, filePath, progressDisplay)) + if(!FileExporter::exportFrame(frameNumber, time, filePath, taskManager)) return false; // Export the first scene node from the selection set. if(outputData().empty()) throwException(tr("The selection set to be exported is empty.")); - QVariantMap attrMap = getAttributes(outputData().front(), time); + QVariantMap attrMap; + if(!getAttributes(outputData().front(), time, attrMap, taskManager)) + return false; for(const QString& attrName : attributesToExport()) { if(!attrMap.contains(attrName)) diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/importexport/AttributeFileExporter.h ovito-2.9.0+dfsg1/src/core/dataset/importexport/AttributeFileExporter.h --- ovito-2.8.1+dfsg2/src/core/dataset/importexport/AttributeFileExporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/importexport/AttributeFileExporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ATTRIBUTE_FILE_EXPORTER_H -#define __OVITO_ATTRIBUTE_FILE_EXPORTER_H +#pragma once + #include #include @@ -51,14 +51,8 @@ /// \brief Selects the natural scene nodes to be exported by this exporter under normal circumstances. virtual void selectStandardOutputData() override; - /// Returns the list of global attributes to be exported. - const QStringList& attributesToExport() const { return _attributesToExport; } - - /// Sets the list of global attributes to be exported. - void setAttributesToExport(const QStringList& attrList) { _attributesToExport = attrList; } - /// \brief Evaluates the pipeline of an ObjectNode and returns the computed attributes. - QVariantMap getAttributes(SceneNode* sceneNode, TimePoint time); + bool getAttributes(SceneNode* sceneNode, TimePoint time, QVariantMap& attributes, TaskManager& taskManager); protected: @@ -69,7 +63,7 @@ virtual void closeOutputFile(bool exportCompleted) override; /// \brief Exports a single animation frame to the current output file. - virtual bool exportFrame(int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) override; + virtual bool exportFrame(int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) override; /// Returns the current file this exporter is writing to. QFile& outputFile() { return _outputFile; } @@ -86,15 +80,13 @@ std::unique_ptr _outputStream; /// The list of global attributes to export. - PropertyField _attributesToExport; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QStringList, attributesToExport, setAttributesToExport); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_attributesToExport); }; OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ATTRIBUTE_FILE_EXPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileExporter.cpp ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileExporter.cpp --- ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileExporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileExporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -31,21 +31,21 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(DataIO) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, FileExporter, RefTarget); -DEFINE_PROPERTY_FIELD(FileExporter, _outputFilename, "OutputFile"); -DEFINE_PROPERTY_FIELD(FileExporter, _exportAnimation, "ExportAnimation"); -DEFINE_PROPERTY_FIELD(FileExporter, _useWildcardFilename, "UseWildcardFilename"); -DEFINE_PROPERTY_FIELD(FileExporter, _wildcardFilename, "WildcardFilename"); -DEFINE_PROPERTY_FIELD(FileExporter, _startFrame, "StartFrame"); -DEFINE_PROPERTY_FIELD(FileExporter, _endFrame, "EndFrame"); -DEFINE_PROPERTY_FIELD(FileExporter, _everyNthFrame, "EveryNthFrame"); -SET_PROPERTY_FIELD_LABEL(FileExporter, _outputFilename, "Output filename"); -SET_PROPERTY_FIELD_LABEL(FileExporter, _exportAnimation, "Export animation"); -SET_PROPERTY_FIELD_LABEL(FileExporter, _useWildcardFilename, "Use wildcard filename"); -SET_PROPERTY_FIELD_LABEL(FileExporter, _wildcardFilename, "Wildcard filename"); -SET_PROPERTY_FIELD_LABEL(FileExporter, _startFrame, "Start frame"); -SET_PROPERTY_FIELD_LABEL(FileExporter, _endFrame, "End frame"); -SET_PROPERTY_FIELD_LABEL(FileExporter, _everyNthFrame, "Every Nth frame"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(FileExporter, RefTarget); +DEFINE_PROPERTY_FIELD(FileExporter, outputFilename, "OutputFile"); +DEFINE_PROPERTY_FIELD(FileExporter, exportAnimation, "ExportAnimation"); +DEFINE_PROPERTY_FIELD(FileExporter, useWildcardFilename, "UseWildcardFilename"); +DEFINE_PROPERTY_FIELD(FileExporter, wildcardFilename, "WildcardFilename"); +DEFINE_PROPERTY_FIELD(FileExporter, startFrame, "StartFrame"); +DEFINE_PROPERTY_FIELD(FileExporter, endFrame, "EndFrame"); +DEFINE_PROPERTY_FIELD(FileExporter, everyNthFrame, "EveryNthFrame"); +SET_PROPERTY_FIELD_LABEL(FileExporter, outputFilename, "Output filename"); +SET_PROPERTY_FIELD_LABEL(FileExporter, exportAnimation, "Export animation"); +SET_PROPERTY_FIELD_LABEL(FileExporter, useWildcardFilename, "Use wildcard filename"); +SET_PROPERTY_FIELD_LABEL(FileExporter, wildcardFilename, "Wildcard filename"); +SET_PROPERTY_FIELD_LABEL(FileExporter, startFrame, "Start frame"); +SET_PROPERTY_FIELD_LABEL(FileExporter, endFrame, "End frame"); +SET_PROPERTY_FIELD_LABEL(FileExporter, everyNthFrame, "Every Nth frame"); /****************************************************************************** * Constructs a new instance of the class. @@ -55,13 +55,13 @@ _useWildcardFilename(false), _startFrame(0), _endFrame(-1), _everyNthFrame(1) { - INIT_PROPERTY_FIELD(FileExporter::_outputFilename); - INIT_PROPERTY_FIELD(FileExporter::_exportAnimation); - INIT_PROPERTY_FIELD(FileExporter::_useWildcardFilename); - INIT_PROPERTY_FIELD(FileExporter::_wildcardFilename); - INIT_PROPERTY_FIELD(FileExporter::_startFrame); - INIT_PROPERTY_FIELD(FileExporter::_endFrame); - INIT_PROPERTY_FIELD(FileExporter::_everyNthFrame); + INIT_PROPERTY_FIELD(outputFilename); + INIT_PROPERTY_FIELD(exportAnimation); + INIT_PROPERTY_FIELD(useWildcardFilename); + INIT_PROPERTY_FIELD(wildcardFilename); + INIT_PROPERTY_FIELD(startFrame); + INIT_PROPERTY_FIELD(endFrame); + INIT_PROPERTY_FIELD(everyNthFrame); // Use the entire animation interval as default export interval. setStartFrame(0); @@ -104,7 +104,7 @@ /****************************************************************************** * Exports the data of the scene nodes to one or more output files. *****************************************************************************/ -bool FileExporter::exportNodes(AbstractProgressDisplay* progressDisplay) +bool FileExporter::exportNodes(TaskManager& taskManager) { if(outputFilename().isEmpty()) throwException(tr("The output filename not been set for the file exporter.")); @@ -139,7 +139,9 @@ throwException(tr("Cannot write animation frames to separate files. The filename must contain the '*' wildcard character, which gets replaced by the frame number.")); } - if(progressDisplay) progressDisplay->setMaximum(numberOfFrames * 100); + SynchronousTask exportTask(taskManager); + exportTask.setProgressText(tr("Opening output file")); + QDir dir = QFileInfo(outputFilename()).dir(); QString filename = outputFilename(); @@ -152,9 +154,9 @@ try { // Export animation frames. + exportTask.setProgressMaximum(numberOfFrames); for(int frameIndex = 0; frameIndex < numberOfFrames; frameIndex++) { - if(progressDisplay) - progressDisplay->setValue(frameIndex * 100); + exportTask.setProgressValue(frameIndex); int frameNumber = firstFrameNumber + frameIndex * everyNthFrame(); @@ -167,13 +169,15 @@ return false; } - if(!exportFrame(frameNumber, exportTime, filename, progressDisplay) && progressDisplay) - progressDisplay->cancel(); + exportTask.setProgressText(tr("Exporting frame %1 to file '%2'").arg(frameNumber).arg(filename)); + + if(!exportFrame(frameNumber, exportTime, filename, taskManager)) + exportTask.cancel(); if(exportAnimation() && useWildcardFilename()) - closeOutputFile(!progressDisplay || !progressDisplay->wasCanceled()); + closeOutputFile(!exportTask.isCanceled()); - if(progressDisplay && progressDisplay->wasCanceled()) + if(exportTask.isCanceled()) break; // Go to next animation frame. @@ -187,39 +191,21 @@ // Close output file. if(!exportAnimation() || !useWildcardFilename()) { - closeOutputFile(!progressDisplay || !progressDisplay->wasCanceled()); + exportTask.setProgressText(tr("Closing output file")); + closeOutputFile(!exportTask.isCanceled()); } - return !progressDisplay || !progressDisplay->wasCanceled(); + return !exportTask.isCanceled(); } /****************************************************************************** * Exports a single animation frame to the current output file. *****************************************************************************/ -bool FileExporter::exportFrame(int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) +bool FileExporter::exportFrame(int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) { // Jump to animation time. dataset()->animationSettings()->setTime(time); - // Wait until the scene is ready. - if(!dataset()->waitUntilSceneIsReady(tr("Preparing frame %1 for export...").arg(frameNumber), progressDisplay)) - return false; - - // Also make sure nodes to be exported are ready, in case they are not part of the scene. - for(SceneNode* sceneNode : outputData()) { - try { - if(ObjectNode* objNode = dynamic_object_cast(sceneNode)) { - if(!objNode->waitUntilReady(time, tr("Preparing frame %1 for export...").arg(frameNumber), progressDisplay)) - return false; - } - } - catch(Exception& ex) { - // Provide a local context for errors that occurred during export. - if(ex.context() == nullptr) ex.setContext(dataset()); - throw; - } - } - return true; } diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileExporter.h ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileExporter.h --- ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileExporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileExporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FILE_EXPORTER_H -#define __OVITO_FILE_EXPORTER_H +#pragma once + #include #include @@ -66,57 +66,12 @@ /// \brief Sets the name of the output file that should be written by this exporter. virtual void setOutputFilename(const QString& filename); - - /// \brief Returns the path of the output file written by this exporter. - const QString& outputFilename() const { return _outputFilename; } - - /// Returns whether only the current animation frame or an entire animation interval should be exported. - bool exportAnimation() const { return _exportAnimation; } - - /// Sets whether only the current animation frame or an entire animation interval should be exported. - void setExportAnimation(bool exportAnim) { _exportAnimation = exportAnim; } - - /// \brief Controls whether the exporter should produce separate files for each exported frame. - void setUseWildcardFilename(bool enable) { _useWildcardFilename = enable; } - - /// \brief Returns whether the exporter produces separate files for each exported frame. - bool useWildcardFilename() const { return _useWildcardFilename; } - - /// \brief Sets the wildcard pattern used to generate filenames when writing - /// a separate file for each exported frame. - /// - /// The wildcard filename must contain the character '*', which will be replaced by the - /// frame number. - void setWildcardFilename(const QString& filename) { _wildcardFilename = filename; } - - /// \brief Returns the wild-card pattern used to generate filenames when writing - /// a separate file for each exported frame. - const QString& wildcardFilename() const { return _wildcardFilename; } - - /// \brief Sets the start of the animation interval that should be exported to the output file. - void setStartFrame(int frame) { _startFrame = frame; } - - /// \brief Returns the first frame of the animation interval that will be exported to the output file. - TimePoint startFrame() const { return _startFrame; } - - /// \brief Sets the end of the animation interval that should be exported to the output file. - void setEndFrame(int frame) { _endFrame = frame; } - - /// \brief Returns the last frame of the animation interval that will be exported to the output file. - TimePoint endFrame() const { return _endFrame; } - - /// \brief Returns the interval between exported frames. - int everyNthFrame() const { return _everyNthFrame; } - - /// \brief Sets the interval between exported frames. - void setEveryNthFrame(int n) { _everyNthFrame = n; } - + /// \brief Exports the scene objects to the output file(s). - /// \param progressDisplay Optional callback object which is used by the function to report progress. /// \return \c true if the output file has been successfully written; /// \c false if the export operation has been canceled by the user. /// \throws Util::Exception if the export operation has failed due to an error. - virtual bool exportNodes(AbstractProgressDisplay* progressDisplay); + virtual bool exportNodes(TaskManager& taskManager); protected: @@ -130,47 +85,39 @@ virtual void closeOutputFile(bool exportCompleted) = 0; /// \brief Exports a single animation frame to the current output file. - virtual bool exportFrame(int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay); + virtual bool exportFrame(int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager); private: /// The output file path. - PropertyField _outputFilename; + DECLARE_PROPERTY_FIELD(QString, outputFilename); /// Controls whether only the current animation frame or an entire animation interval should be exported. - PropertyField _exportAnimation; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, exportAnimation, setExportAnimation); /// Indicates that the exporter should produce a separate file for each timestep. - PropertyField _useWildcardFilename; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, useWildcardFilename, setUseWildcardFilename); /// The wildcard name that is used to generate the output filenames. - PropertyField _wildcardFilename; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, wildcardFilename, setWildcardFilename); /// The first animation frame that should be exported. - PropertyField _startFrame; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, startFrame, setStartFrame); /// The last animation frame that should be exported. - PropertyField _endFrame; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, endFrame, setEndFrame); /// Controls the interval between exported frames. - PropertyField _everyNthFrame; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, everyNthFrame, setEveryNthFrame); /// Holds the scene objects to be exported. QVector> _nodesToExport; Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_outputFilename); - DECLARE_PROPERTY_FIELD(_exportAnimation); - DECLARE_PROPERTY_FIELD(_useWildcardFilename); - DECLARE_PROPERTY_FIELD(_wildcardFilename); - DECLARE_PROPERTY_FIELD(_startFrame); - DECLARE_PROPERTY_FIELD(_endFrame); - DECLARE_PROPERTY_FIELD(_everyNthFrame); }; OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_FILE_EXPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileImporter.cpp ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileImporter.cpp --- ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,11 +25,12 @@ #include #include #include +#include #include "FileImporter.h" namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(DataIO) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, FileImporter, RefTarget); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(FileImporter, RefTarget); /****************************************************************************** * Return the list of available import services. @@ -49,6 +50,7 @@ try { DataSetContainer* container = dataset->container(); + OVITO_ASSERT(container != nullptr); // Resolve filename if it contains a wildcard. Future> framesFuture = FileSourceImporter::findWildcardMatches(url, container); @@ -59,7 +61,7 @@ dataset->throwException(tr("There are no files in the directory matching the filename pattern.")); // Download file so we can determine its format. - Future fetchFileFuture = FileManager::instance().fetchUrl(*container, frames.front().sourceFile); + Future fetchFileFuture = Application::instance()->fileManager()->fetchUrl(*container, frames.front().sourceFile); if(!container->taskManager().waitForTask(fetchFileFuture)) dataset->throwException(tr("Operation has been canceled by the user.")); diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileImporter.h ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileImporter.h --- ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FILE_IMPORTER_H -#define __OVITO_FILE_IMPORTER_H +#pragma once + #include #include @@ -103,4 +103,4 @@ Q_DECLARE_METATYPE(Ovito::FileImporter::ImportMode); Q_DECLARE_TYPEINFO(Ovito::FileImporter::ImportMode, Q_PRIMITIVE_TYPE); -#endif // __OVITO_FILE_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileSource.cpp ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileSource.cpp --- ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileSource.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileSource.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -34,21 +35,22 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(DataIO) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, FileSource, CompoundObject); -DEFINE_FLAGS_REFERENCE_FIELD(FileSource, _importer, "Importer", FileSourceImporter, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_NO_UNDO); -DEFINE_PROPERTY_FIELD(FileSource, _adjustAnimationIntervalEnabled, "AdjustAnimationIntervalEnabled"); -DEFINE_FLAGS_PROPERTY_FIELD(FileSource, _sourceUrl, "SourceUrl", PROPERTY_FIELD_NO_UNDO); -DEFINE_PROPERTY_FIELD(FileSource, _playbackSpeedNumerator, "PlaybackSpeedNumerator"); -DEFINE_PROPERTY_FIELD(FileSource, _playbackSpeedDenominator, "PlaybackSpeedDenominator"); -DEFINE_PROPERTY_FIELD(FileSource, _playbackStartTime, "PlaybackStartTime"); -SET_PROPERTY_FIELD_LABEL(FileSource, _importer, "File Importer"); -SET_PROPERTY_FIELD_LABEL(FileSource, _adjustAnimationIntervalEnabled, "Adjust animation length to time series"); -SET_PROPERTY_FIELD_LABEL(FileSource, _sourceUrl, "Source location"); -SET_PROPERTY_FIELD_LABEL(FileSource, _playbackSpeedNumerator, "Playback rate numerator"); -SET_PROPERTY_FIELD_LABEL(FileSource, _playbackSpeedDenominator, "Playback rate denominator"); -SET_PROPERTY_FIELD_LABEL(FileSource, _playbackStartTime, "Playback start time"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(FileSource, _playbackSpeedNumerator, IntegerParameterUnit, 1); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(FileSource, _playbackSpeedDenominator, IntegerParameterUnit, 1); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(FileSource, CompoundObject); +DEFINE_FLAGS_REFERENCE_FIELD(FileSource, importer, "Importer", FileSourceImporter, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_NO_UNDO); +DEFINE_PROPERTY_FIELD(FileSource, adjustAnimationIntervalEnabled, "AdjustAnimationIntervalEnabled"); +DEFINE_FLAGS_PROPERTY_FIELD(FileSource, sourceUrl, "SourceUrl", PROPERTY_FIELD_NO_UNDO); +DEFINE_PROPERTY_FIELD(FileSource, playbackSpeedNumerator, "PlaybackSpeedNumerator"); +DEFINE_PROPERTY_FIELD(FileSource, playbackSpeedDenominator, "PlaybackSpeedDenominator"); +DEFINE_PROPERTY_FIELD(FileSource, playbackStartTime, "PlaybackStartTime"); +SET_PROPERTY_FIELD_LABEL(FileSource, importer, "File Importer"); +SET_PROPERTY_FIELD_LABEL(FileSource, adjustAnimationIntervalEnabled, "Adjust animation length to time series"); +SET_PROPERTY_FIELD_LABEL(FileSource, sourceUrl, "Source location"); +SET_PROPERTY_FIELD_LABEL(FileSource, playbackSpeedNumerator, "Playback rate numerator"); +SET_PROPERTY_FIELD_LABEL(FileSource, playbackSpeedDenominator, "Playback rate denominator"); +SET_PROPERTY_FIELD_LABEL(FileSource, playbackStartTime, "Playback start time"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(FileSource, playbackSpeedNumerator, IntegerParameterUnit, 1); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(FileSource, playbackSpeedDenominator, IntegerParameterUnit, 1); +SET_PROPERTY_FIELD_CHANGE_EVENT(FileSource, sourceUrl, ReferenceEvent::TitleChanged); /****************************************************************************** * Constructs the object. @@ -57,15 +59,15 @@ _adjustAnimationIntervalEnabled(true), _loadedFrameIndex(-1), _frameBeingLoaded(-1), _playbackSpeedNumerator(1), _playbackSpeedDenominator(1), _playbackStartTime(0), _isNewFile(false) { - INIT_PROPERTY_FIELD(FileSource::_importer); - INIT_PROPERTY_FIELD(FileSource::_adjustAnimationIntervalEnabled); - INIT_PROPERTY_FIELD(FileSource::_sourceUrl); - INIT_PROPERTY_FIELD(FileSource::_playbackSpeedNumerator); - INIT_PROPERTY_FIELD(FileSource::_playbackSpeedDenominator); - INIT_PROPERTY_FIELD(FileSource::_playbackStartTime); + INIT_PROPERTY_FIELD(importer); + INIT_PROPERTY_FIELD(adjustAnimationIntervalEnabled); + INIT_PROPERTY_FIELD(sourceUrl); + INIT_PROPERTY_FIELD(playbackSpeedNumerator); + INIT_PROPERTY_FIELD(playbackSpeedDenominator); + INIT_PROPERTY_FIELD(playbackStartTime); - connect(&_frameLoaderWatcher, &FutureWatcher::finished, this, &FileSource::loadOperationFinished); - connect(&_frameDiscoveryWatcher, &FutureWatcher::finished, this, &FileSource::frameDiscoveryFinished); + connect(&_frameLoaderWatcher, &PromiseWatcher::finished, this, &FileSource::loadOperationFinished); + connect(&_frameDiscoveryWatcher, &PromiseWatcher::finished, this, &FileSource::frameDiscoveryFinished); // Do not save a copy of the linked external data in state file by default. setSaveWithScene(false); @@ -181,7 +183,7 @@ if(_frameBeingLoaded != -1) { try { // This will suppress any pending notification events. - _frameLoaderWatcher.unsetFuture(); + _frameLoaderWatcher.unsetPromise(); OVITO_ASSERT(_activeFrameLoader); _activeFrameLoader->cancel(); _activeFrameLoader->waitForFinished(); @@ -197,9 +199,9 @@ int FileSource::animationTimeToInputFrame(TimePoint time) const { int animFrame = dataset()->animationSettings()->timeToFrame(time); - return (animFrame - _playbackStartTime) * - std::max(1, (int)_playbackSpeedNumerator) / - std::max(1, (int)_playbackSpeedDenominator); + return (animFrame - playbackStartTime()) * + std::max(1, playbackSpeedNumerator()) / + std::max(1, playbackSpeedDenominator()); } /****************************************************************************** @@ -208,18 +210,18 @@ TimePoint FileSource::inputFrameToAnimationTime(int frame) const { int animFrame = frame * - std::max(1, (int)_playbackSpeedDenominator) / - std::max(1, (int)_playbackSpeedNumerator) + - _playbackStartTime; + std::max(1, playbackSpeedDenominator()) / + std::max(1, playbackSpeedNumerator()) + + playbackStartTime(); return dataset()->animationSettings()->frameToTime(animFrame); } /****************************************************************************** * Asks the object for the result of the geometry pipeline at the given time. ******************************************************************************/ -PipelineFlowState FileSource::evaluate(TimePoint time) +PipelineFlowState FileSource::evaluateImmediately(const PipelineEvalRequest& request) { - return requestFrame(animationTimeToInputFrame(time)); + return requestFrame(animationTimeToInputFrame(request.time())); } /****************************************************************************** @@ -255,7 +257,7 @@ // Cancel pending loading operation first. try { // This will suppress any pending notification events. - _frameLoaderWatcher.unsetFuture(); + _frameLoaderWatcher.unsetPromise(); OVITO_ASSERT(_activeFrameLoader); _activeFrameLoader->cancel(); _activeFrameLoader->waitForFinished(); @@ -295,7 +297,7 @@ _frameBeingLoaded = frame; _activeFrameLoader = importer()->createFrameLoader(frames()[frame], _isNewFile); _isNewFile = false; - _frameLoaderWatcher.setFutureInterface(_activeFrameLoader); + _frameLoaderWatcher.setPromise(_activeFrameLoader); dataset()->container()->taskManager().runTaskAsync(_activeFrameLoader); setStatus(PipelineStatus::Pending); if(oldLoadingTaskWasCanceled) @@ -314,42 +316,46 @@ OVITO_ASSERT(_frameBeingLoaded != -1); OVITO_ASSERT(_activeFrameLoader); bool wasCanceled = _activeFrameLoader->isCanceled(); + int loadedFrame = _frameBeingLoaded; _loadedFrameIndex = _frameBeingLoaded; _frameBeingLoaded = -1; PipelineStatus newStatus = status(); + _frameLoaderWatcher.unsetPromise(); + std::shared_ptr frameLoader = std::move(_activeFrameLoader); + OVITO_ASSERT(!_activeFrameLoader); + if(!wasCanceled) { try { // Check for exceptions thrown by the frame loader. - _activeFrameLoader->waitForFinished(); + frameLoader->waitForFinished(); // Adopt the data loaded by the frame loader. - _activeFrameLoader->handOver(this); - newStatus = _activeFrameLoader->status(); - if(frames().count() > 1) - newStatus.setText(tr("Loaded frame %1 of %2\n").arg(_loadedFrameIndex+1).arg(frames().count()) + newStatus.text()); + frameLoader->handOver(this); + newStatus = frameLoader->status(); + if(frames().count() > 1) { + newStatus.setText(tr("Loaded frame %1 of %2\n").arg(loadedFrame+1).arg(frames().count()) + newStatus.text()); + } } catch(Exception& ex) { // Provide a context for this error. ex.setContext(dataset()); // Transfer exception message to evaluation status. newStatus = PipelineStatus(PipelineStatus::Error, ex.messages().join(QChar('\n'))); - ex.showError(); + ex.reportError(); } } else { newStatus = PipelineStatus(PipelineStatus::Error, tr("Load operation has been canceled by the user.")); } - // Reset everything. - _frameLoaderWatcher.unsetFuture(); - _activeFrameLoader.reset(); - - // Set the new object status. - setStatus(newStatus); + if(_loadedFrameIndex == loadedFrame) { + // Set the new object status. + setStatus(newStatus); - // Notify dependents that the evaluation request was completed. - notifyDependents(ReferenceEvent::PendingStateChanged); - notifyDependents(ReferenceEvent::TitleChanged); + // Notify dependents that the evaluation request was completed. + notifyDependents(ReferenceEvent::PendingStateChanged); + notifyDependents(ReferenceEvent::TitleChanged); + } } /****************************************************************************** @@ -372,7 +378,7 @@ catch(Exception& ex) { // Provide a context for this error. ex.setContext(dataset()); - ex.showError(); + ex.reportError(); } // Jump to the right frame to show the originally selected file. @@ -392,11 +398,12 @@ } // Reset everything. - _frameDiscoveryWatcher.unsetFuture(); + _frameDiscoveryWatcher.unsetPromise(); _frameDiscoveryFuture.reset(); // Notify dependents that the evaluation request was completed. notifyDependents(ReferenceEvent::TargetChanged); + notifyDependents(ReferenceEvent::PendingStateChanged); } /****************************************************************************** @@ -410,7 +417,7 @@ // Remove external file from local file cache so that it will be fetched from the // remote server again. if(frameIndex >= 0 && frameIndex < frames().size()) - FileManager::instance().removeFromCache(frames()[frameIndex].sourceFile); + Application::instance()->fileManager()->removeFromCache(frames()[frameIndex].sourceFile); if(frameIndex == loadedFrameIndex() || frameIndex == -1) { _loadedFrameIndex = -1; @@ -435,7 +442,7 @@ ******************************************************************************/ void FileSource::adjustAnimationInterval(int gotoFrameIndex) { - if(!_adjustAnimationIntervalEnabled) + if(!adjustAnimationIntervalEnabled()) return; AnimationSettings* animSettings = dataset()->animationSettings(); @@ -555,14 +562,25 @@ ******************************************************************************/ void FileSource::propertyChanged(const PropertyFieldDescriptor& field) { - if(field == PROPERTY_FIELD(FileSource::_adjustAnimationIntervalEnabled) || - field == PROPERTY_FIELD(FileSource::_playbackSpeedNumerator) || - field == PROPERTY_FIELD(FileSource::_playbackSpeedDenominator) || - field == PROPERTY_FIELD(FileSource::_playbackStartTime)) { + if(field == PROPERTY_FIELD(adjustAnimationIntervalEnabled) || + field == PROPERTY_FIELD(playbackSpeedNumerator) || + field == PROPERTY_FIELD(playbackSpeedDenominator) || + field == PROPERTY_FIELD(playbackStartTime)) { adjustAnimationInterval(); } CompoundObject::propertyChanged(field); } +/****************************************************************************** +* Sends an event to all dependents of this RefTarget. +******************************************************************************/ +void FileSource::notifyDependents(ReferenceEvent& event) +{ + if(event.type() == ReferenceEvent::PendingStateChanged) + _evaluationRequestHelper.serveRequests(this); + + DataObject::notifyDependents(event); +} + OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileSource.h ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileSource.h --- ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileSource.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileSource.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,11 +19,14 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FILE_SOURCE_H -#define __OVITO_FILE_SOURCE_H +#pragma once + #include #include +#include +#include +#include #include "FileSourceImporter.h" namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(DataIO) @@ -39,12 +42,7 @@ /// Constructs an empty file source which is not referring to an external file. Q_INVOKABLE FileSource(DataSet* dataset); - - /// Returns the object that is responsible for loading data from the external file referenced by this FileSource. - /// \return The importer owned by this FileSource; or \c nullptr if this FileSource is currently not referring to an external file. - /// The importer can be replaced by calling setSource(). - FileSourceImporter* importer() const { return _importer; } - + /// \brief Sets the source location for importing data. /// \param sourceUrl The new source location. /// \param importer The importer object that will parse the input file. @@ -52,9 +50,6 @@ /// \return false if the operation has been canceled by the user. bool setSource(QUrl sourceUrl, FileSourceImporter* importer, bool autodetectFileSequences); - /// \brief Returns the source location of the data. - const QUrl& sourceUrl() const { return _sourceUrl; } - /// \brief This reloads the input data from the external file. /// \param frameIndex The animation frame to reload from the external file. Q_INVOKABLE void refreshFromSource(int frameIndex = -1); @@ -80,24 +75,39 @@ /// \brief Given an input frame index, returns the animation time at which it is shown. Q_INVOKABLE TimePoint inputFrameToAnimationTime(int frame) const; - /// \brief Returns whether the scene's animation interval is being adjusted to the number of frames reported by the file parser. - bool adjustAnimationIntervalEnabled() const { return _adjustAnimationIntervalEnabled; } - - /// \brief Controls whether the scene's animation interval should be adjusted to the number of frames reported by the file parser. - void setAdjustAnimationIntervalEnabled(bool enabled) { _adjustAnimationIntervalEnabled = enabled; } - /// \brief Adjusts the animation interval of the current data set to the number of frames in the data source. void adjustAnimationInterval(int gotoFrameIndex = -1); /// \brief Requests a frame of the input file sequence. PipelineFlowState requestFrame(int frameIndex); - /// \brief Asks the object for the result of the geometry pipeline at the given time. - virtual PipelineFlowState evaluate(TimePoint time) override; + /// \brief Asks the object for the results of the data pipeline. + virtual PipelineFlowState evaluateImmediately(const PipelineEvalRequest& request) override; + + /// Asks the object for the complete results of the data pipeline. + virtual Future evaluateAsync(const PipelineEvalRequest& request) override { + return _evaluationRequestHelper.createRequest(this, request); + } /// Returns the title of this object. virtual QString objectTitle() override; + /// Sends an event to all dependents of this RefTarget. + virtual void notifyDependents(ReferenceEvent& event) override; + + /// \brief Sends an event to all dependents of this RefTarget. + /// \param eventType The event type passed to the ReferenceEvent constructor. + inline void notifyDependents(ReferenceEvent::Type eventType) { + DataObject::notifyDependents(eventType); + } + + /// This method is called after the reference counter of this object has reached zero + /// and before the object is being deleted. + virtual void aboutToBeDeleted() override { + cancelLoadOperation(); + CompoundObject::aboutToBeDeleted(); + } + protected Q_SLOTS: /// \brief This is called when the background loading operation has finished. @@ -126,22 +136,22 @@ private: /// The associated importer object that is responsible for parsing the input file. - ReferenceField _importer; + DECLARE_REFERENCE_FIELD(FileSourceImporter, importer); /// Controls whether the scene's animation interval is adjusted to the number of frames found in the input file. - PropertyField _adjustAnimationIntervalEnabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, adjustAnimationIntervalEnabled, setAdjustAnimationIntervalEnabled); /// The source file (may include a wild-card pattern). - PropertyField _sourceUrl; + DECLARE_PROPERTY_FIELD(QUrl, sourceUrl); /// Controls the mapping of input file frames to animation frames (i.e. the numerator of the playback rate for the file sequence). - PropertyField _playbackSpeedNumerator; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, playbackSpeedNumerator, setPlaybackSpeedNumerator); /// Controls the mapping of input file frames to animation frames (i.e. the denominator of the playback rate for the file sequence). - PropertyField _playbackSpeedDenominator; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, playbackSpeedDenominator, setPlaybackSpeedDenominator); /// Specifies the starting animation frame to which the first frame of the file sequence is mapped. - PropertyField _playbackStartTime; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, playbackStartTime, setPlaybackStartTime); /// Stores the list of frames of the time series. QVector _frames; @@ -163,33 +173,27 @@ std::shared_ptr _activeFrameLoader; /// The watcher object that is used to monitor the background operation. - FutureWatcher _frameLoaderWatcher; + PromiseWatcher _frameLoaderWatcher; /// The active Future that provides the discovered input frames. Future> _frameDiscoveryFuture; /// The watcher object that is used to monitor the background operation. - FutureWatcher _frameDiscoveryWatcher; + PromiseWatcher _frameDiscoveryWatcher; /// The status returned by the parser during its last call. PipelineStatus _importStatus; -private: + /// Manages pending asynchronous pipeline requests. + AsyncPipelineEvaluationHelper _evaluationRequestHelper; Q_OBJECT OVITO_OBJECT Q_CLASSINFO("ClassNameAlias", "LinkedFileObject"); // This for backward compatibility with files written by Ovito 2.4 and older. - - DECLARE_REFERENCE_FIELD(_importer); - DECLARE_PROPERTY_FIELD(_adjustAnimationIntervalEnabled); - DECLARE_PROPERTY_FIELD(_sourceUrl); - DECLARE_PROPERTY_FIELD(_playbackSpeedNumerator); - DECLARE_PROPERTY_FIELD(_playbackSpeedDenominator); - DECLARE_PROPERTY_FIELD(_playbackStartTime); }; OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_FILE_SOURCE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileSourceImporter.cpp ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileSourceImporter.cpp --- ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileSourceImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileSourceImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,12 +28,13 @@ #include #include #include +#include #include "FileSourceImporter.h" #include "FileSource.h" namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(DataIO) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, FileSourceImporter, FileImporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(FileSourceImporter, FileImporter); /****************************************************************************** * Sends a request to the FileSource owning this importer to reload @@ -48,7 +49,7 @@ fileSource->refreshFromSource(frame); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } } @@ -83,7 +84,7 @@ fileSource->updateFrames(); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } } @@ -190,11 +191,12 @@ dataset()->selection()->setNode(node); if(importMode != ReplaceSelected) { - // Adjust views to completely show the newly imported object. - OORef ds(dataset()); - ds->runWhenSceneIsReady([ds]() { - ds->viewportConfig()->zoomToSelectionExtents(); - }); + // Adjust viewports to completely show the newly imported object. + // This needs to be done after the data has been completely loaded. + PromiseWatcher* watcher = new PromiseWatcher(this); + connect(watcher, &PromiseWatcher::finished, dataset()->viewportConfig(), &ViewportConfiguration::zoomToSelectionExtents); + connect(watcher, &PromiseWatcher::finished, watcher, &QObject::deleteLater); // Self-destruct watcher object when it's no longer needed. + watcher->setFuture(dataset()->makeSceneReady()); } transaction.commit(); @@ -242,7 +244,7 @@ try { // Retrieve list of files in remote directory. - Future fileListFuture = FileManager::instance().listDirectoryContents(directoryUrl); + Future fileListFuture = Application::instance()->fileManager()->listDirectoryContents(directoryUrl); if(!datasetContainer->taskManager().waitForTask(fileListFuture)) return Future>::createCanceled(); @@ -262,7 +264,7 @@ // A file called "abc9.xyz" must come before a file named "abc10.xyz", which is not // the default lexicographic ordering. QMap sortedFilenames; - Q_FOREACH(QString oldName, entries) { + for(const QString& oldName : entries) { // Generate a new name from the original filename that yields the correct ordering. QString newName; QString number; diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileSourceImporter.h ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileSourceImporter.h --- ovito-2.8.1+dfsg2/src/core/dataset/importexport/FileSourceImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/importexport/FileSourceImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FILE_SOURCE_IMPORTER_H -#define __OVITO_FILE_SOURCE_IMPORTER_H +#pragma once + #include #include @@ -189,4 +189,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_FILE_SOURCE_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/UndoStack.cpp ovito-2.9.0+dfsg1/src/core/dataset/UndoStack.cpp --- ovito-2.8.1+dfsg2/src/core/dataset/UndoStack.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/UndoStack.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -140,7 +140,7 @@ cop->clear(); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } _isUndoing = false; } @@ -219,7 +219,7 @@ curOp->undo(); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } _isUndoing = false; resume(); @@ -250,7 +250,7 @@ nextOp->redo(); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } _isRedoing = false; resume(); diff -Nru ovito-2.8.1+dfsg2/src/core/dataset/UndoStack.h ovito-2.9.0+dfsg1/src/core/dataset/UndoStack.h --- ovito-2.8.1+dfsg2/src/core/dataset/UndoStack.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/dataset/UndoStack.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_UNDO_STACK_H -#define __OVITO_UNDO_STACK_H +#pragma once + #include @@ -540,7 +540,7 @@ return true; } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); return false; } } @@ -555,4 +555,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_UNDO_STACK_H + diff -Nru ovito-2.8.1+dfsg2/src/core/ForwardDecl.h ovito-2.9.0+dfsg1/src/core/ForwardDecl.h --- ovito-2.8.1+dfsg2/src/core/ForwardDecl.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/ForwardDecl.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains forward declarations of OVITO's core classes and namespaces. */ -#ifndef __OVITO_CORE_FORWARD_DECL_H -#define __OVITO_CORE_FORWARD_DECL_H +#pragma once + // Sub-namespaces are only used for the documentation generated by Doxygen, // because current C++ compilers do not fully support C++11 inline namespaces yet. @@ -48,8 +48,9 @@ OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) - class AbstractProgressDisplay; - class ProgressDialogAdapter; + class TaskManager; + class AsynchronousTask; + class SynchronousTask; OVITO_END_INLINE_NAMESPACE OVITO_BEGIN_INLINE_NAMESPACE(Mesh) class TriMesh; @@ -100,6 +101,7 @@ class Modifier; class ModifierApplication; class ObjectNode; + class PipelineEvalRequest; class PipelineFlowState; class PipelineObject; class DisplayObject; @@ -156,4 +158,4 @@ #endif } -#endif // __OVITO_CORE_FORWARD_DECL_H + diff -Nru ovito-2.8.1+dfsg2/src/core/object/NativeOvitoObjectType.h ovito-2.9.0+dfsg1/src/core/object/NativeOvitoObjectType.h --- ovito-2.8.1+dfsg2/src/core/object/NativeOvitoObjectType.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/object/NativeOvitoObjectType.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_NATIVE_OVITO_OBJECT_TYPE_H -#define __OVITO_NATIVE_OVITO_OBJECT_TYPE_H +#pragma once + #include #include "OvitoObjectType.h" @@ -90,22 +90,22 @@ ///////////////////////////////////// Macros ////////////////////////////////////////// -/// This macro must be included in the class definition of a OvitoObject-derived class. +/// This macro must be included in the class definition of any OvitoObject-derived class. #define OVITO_OBJECT \ public: \ static const Ovito::NativeOvitoObjectType OOType; \ virtual const Ovito::OvitoObjectType& getOOType() const override { return OOType; } /// This macro must be included in the .cpp file for a OvitoObject-derived class. -#define IMPLEMENT_OVITO_OBJECT(plugin, name, basename) \ - const Ovito::NativeOvitoObjectType name::OOType(QStringLiteral(#name), #plugin, &basename::OOType, &name::staticMetaObject, false); +#define IMPLEMENT_OVITO_OBJECT(name, basename) \ + const Ovito::NativeOvitoObjectType name::OOType(QStringLiteral(#name), OVITO_PLUGIN_NAME, &basename::OOType, &name::staticMetaObject, false); -/// This macro must be included in the .cpp file for a OvitoObject-derived class. -#define IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(plugin, name, basename) \ - const Ovito::NativeOvitoObjectType name::OOType(QStringLiteral(#name), #plugin, &basename::OOType, &name::staticMetaObject, true); +/// This macro must be included in the .cpp file for a OvitoObject-derived class that supports serialization. +#define IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(name, basename) \ + const Ovito::NativeOvitoObjectType name::OOType(QStringLiteral(#name), OVITO_PLUGIN_NAME, &basename::OOType, &name::staticMetaObject, true); OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_NATIVE_OVITO_OBJECT_TYPE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/object/OvitoObject.h ovito-2.9.0+dfsg1/src/core/object/OvitoObject.h --- ovito-2.8.1+dfsg2/src/core/object/OvitoObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/object/OvitoObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OBJECT_H -#define __OVITO_OBJECT_H +#pragma once + #include #include "OvitoObjectReference.h" @@ -150,7 +150,7 @@ size_t _referenceCount; /// \brief Increments the reference count by one. - void incrementReferenceCount() { + void incrementReferenceCount() Q_DECL_NOTHROW { OVITO_CHECK_OBJECT_POINTER(this); ++_referenceCount; } @@ -274,4 +274,4 @@ #include #include -#endif // __OVITO_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/core/object/OvitoObjectReference.h ovito-2.9.0+dfsg1/src/core/object/OvitoObjectReference.h --- ovito-2.8.1+dfsg2/src/core/object/OvitoObjectReference.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/object/OvitoObjectReference.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OBJECT_REFERENCE_H -#define __OVITO_OBJECT_REFERENCE_H +#pragma once + #include @@ -49,18 +49,18 @@ OORef() Q_DECL_NOTHROW : px(nullptr) {} /// Initialization constructor. - OORef(T* p) : px(p) { + OORef(T* p) Q_DECL_NOTHROW : px(p) { if(px) px->incrementReferenceCount(); } /// Copy constructor. - OORef(const OORef& rhs) : px(rhs.get()) { + OORef(const OORef& rhs) Q_DECL_NOTHROW : px(rhs.get()) { if(px) px->incrementReferenceCount(); } /// Copy and conversion constructor. template - OORef(const OORef& rhs) : px(rhs.get()) { + OORef(const OORef& rhs) Q_DECL_NOTHROW : px(rhs.get()) { if(px) px->incrementReferenceCount(); } @@ -95,7 +95,7 @@ return *this; } - void reset() Q_DECL_NOTHROW { + void reset() { this_type().swap(*this); } @@ -111,12 +111,12 @@ return px; } - inline T& operator*() const { + inline T& operator*() const Q_DECL_NOTHROW { OVITO_ASSERT(px != nullptr); return *px; } - inline T* operator->() const { + inline T* operator->() const Q_DECL_NOTHROW { OVITO_ASSERT(px != nullptr); return px; } @@ -130,32 +130,32 @@ T* px; }; -template inline bool operator==(const OORef& a, const OORef& b) +template inline bool operator==(const OORef& a, const OORef& b) Q_DECL_NOTHROW { return a.get() == b.get(); } -template inline bool operator!=(const OORef& a, const OORef& b) +template inline bool operator!=(const OORef& a, const OORef& b) Q_DECL_NOTHROW { return a.get() != b.get(); } -template inline bool operator==(const OORef& a, U* b) +template inline bool operator==(const OORef& a, U* b) Q_DECL_NOTHROW { return a.get() == b; } -template inline bool operator!=(const OORef& a, U* b) +template inline bool operator!=(const OORef& a, U* b) Q_DECL_NOTHROW { return a.get() != b; } -template inline bool operator==(T* a, const OORef& b) +template inline bool operator==(T* a, const OORef& b) Q_DECL_NOTHROW { return a == b.get(); } -template inline bool operator!=(T* a, const OORef& b) +template inline bool operator!=(T* a, const OORef& b) Q_DECL_NOTHROW { return a != b.get(); } @@ -180,7 +180,7 @@ return p.get() != nullptr; } -template inline bool operator<(const OORef& a, const OORef& b) +template inline bool operator<(const OORef& a, const OORef& b) Q_DECL_NOTHROW { return std::less()(a.get(), b.get()); } @@ -190,7 +190,7 @@ lhs.swap(rhs); } -template T* get_pointer(const OORef& p) +template T* get_pointer(const OORef& p) Q_DECL_NOTHROW { return p.get(); } @@ -218,4 +218,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OBJECT_REFERENCE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/object/OvitoObjectType.cpp ovito-2.9.0+dfsg1/src/core/object/OvitoObjectType.cpp --- ovito-2.8.1+dfsg2/src/core/object/OvitoObjectType.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/object/OvitoObjectType.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -104,6 +104,11 @@ try { + // This is for backward compatibility with OVITO 2.8.2. + // The StandardSceneRenderer class has been moved from the 'Gui' plugin to the 'OpenGLRenderer' plugin. + if(className == "StandardSceneRenderer" && pluginId == "Gui") + pluginId = "OpenGLRenderer"; + // Lookup class descriptor. Plugin* plugin = PluginManager::instance().plugin(pluginId); if(!plugin) diff -Nru ovito-2.8.1+dfsg2/src/core/object/OvitoObjectType.h ovito-2.9.0+dfsg1/src/core/object/OvitoObjectType.h --- ovito-2.8.1+dfsg2/src/core/object/OvitoObjectType.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/object/OvitoObjectType.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OBJECT_TYPE_H -#define __OVITO_OBJECT_TYPE_H +#pragma once + #include #include "OvitoObjectReference.h" @@ -180,4 +180,4 @@ Q_DECLARE_METATYPE(const Ovito::OvitoObjectType*); Q_DECLARE_TYPEINFO(const Ovito::OvitoObjectType*, Q_MOVABLE_TYPE); -#endif // __OVITO_OBJECT_TYPE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/plugins/autostart/AutoStartObject.cpp ovito-2.9.0+dfsg1/src/core/plugins/autostart/AutoStartObject.cpp --- ovito-2.8.1+dfsg2/src/core/plugins/autostart/AutoStartObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/plugins/autostart/AutoStartObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(PluginSystem) -IMPLEMENT_OVITO_OBJECT(Core, AutoStartObject, OvitoObject); +IMPLEMENT_OVITO_OBJECT(AutoStartObject, OvitoObject); OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/plugins/autostart/AutoStartObject.h ovito-2.9.0+dfsg1/src/core/plugins/autostart/AutoStartObject.h --- ovito-2.8.1+dfsg2/src/core/plugins/autostart/AutoStartObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/plugins/autostart/AutoStartObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_AUTO_START_OBJECT_H -#define __OVITO_AUTO_START_OBJECT_H +#pragma once + #include @@ -55,4 +55,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_AUTO_START_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/core/plugins/NativePlugin.cpp ovito-2.9.0+dfsg1/src/core/plugins/NativePlugin.cpp --- ovito-2.8.1+dfsg2/src/core/plugins/NativePlugin.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/plugins/NativePlugin.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (2014) Alexander Stukowski -// -// This file is part of OVITO (Open Visualization Tool). -// -// OVITO is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// OVITO is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -/////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include - -#include - -namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(PluginSystem) OVITO_BEGIN_INLINE_NAMESPACE(Internal) - -/****************************************************************************** -* Constructor for the NativePlugin class. -******************************************************************************/ -NativePlugin::NativePlugin(const QString& manifestFile, bool builtinPlugin) : - Plugin(manifestFile, builtinPlugin), _library(nullptr) -{ - // Get the name of the shared library file. - QString libBasename = metadata().object().value(QStringLiteral("native-library")).toString(); - if(libBasename.isEmpty()) - throw Exception(tr("Invalid plugin manifest file %1. 'native-library' element not present.").arg(manifestFile)); - - // Resolve the filename by adding the platform specific suffix/extension - // and make the path absolute. - QDir baseDir; - if(builtinPlugin) // The core libraries are not in the plugins directory. - baseDir = QCoreApplication::applicationDirPath(); - else - baseDir = QFileInfo(manifestFile).dir(); -#if defined(Q_OS_WIN) - QFileInfo libFile(baseDir.absoluteFilePath(libBasename + ".dll")); -#else - QFileInfo libFile(baseDir.absoluteFilePath(libBasename + ".so")); -#endif - _libraryFilename = QDir::cleanPath(libFile.absoluteFilePath()); -} - -/****************************************************************************** -* Loads a native plugin's library. -******************************************************************************/ -void NativePlugin::loadPluginImpl() -{ - // Save pointer to original linked list. - NativeOvitoObjectType* linkedListBefore = NativeOvitoObjectType::_firstInfo; - - // Load dynamic library. - if(_library == nullptr || _library->isLoaded() == false) { - if(libraryFilename().isEmpty()) - throw Exception(QString("The manifest file of the native plugin %1 does not specify the library name.").arg(pluginId())); - _library = new QLibrary(libraryFilename(), this); - _library->setLoadHints(QLibrary::ExportExternalSymbolsHint); - if(!_library->load()) { - throw Exception(QString("Failed to load native plugin library.\nLibrary file: %1\nError: %2").arg(libraryFilename(), _library->errorString())); - } - } - - // New pointer to extended linked list. - NativeOvitoObjectType* linkedListAfter = NativeOvitoObjectType::_firstInfo; - - // Initialize all newly loaded classes and connect them with this plugin. - for(NativeOvitoObjectType* clazz = linkedListAfter; clazz != linkedListBefore; clazz = clazz->_next) { - if(clazz->pluginId() != pluginId()) - throw Exception(QString("Compile-time plugin ID %1 set for class %2 does not match plugin library %3 containing the class.").arg(clazz->pluginId()).arg(clazz->name()).arg(pluginId())); - OVITO_ASSERT(clazz->plugin() == nullptr); - clazz->initializeClassDescriptor(this); - registerClass(clazz); - } -} - -OVITO_END_INLINE_NAMESPACE -OVITO_END_INLINE_NAMESPACE -} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/plugins/NativePlugin.h ovito-2.9.0+dfsg1/src/core/plugins/NativePlugin.h --- ovito-2.8.1+dfsg2/src/core/plugins/NativePlugin.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/plugins/NativePlugin.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (2014) Alexander Stukowski -// -// This file is part of OVITO (Open Visualization Tool). -// -// OVITO is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// OVITO is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef __OVITO_NATIVE_PLUGIN_H -#define __OVITO_NATIVE_PLUGIN_H - -#include -#include "Plugin.h" - -#include - -namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(PluginSystem) OVITO_BEGIN_INLINE_NAMESPACE(Internal) - -/** - * \brief A plugin that is implemented as a native shared library. - */ -class OVITO_CORE_EXPORT NativePlugin : public Plugin -{ - Q_OBJECT - -public: - - /// \brief Returns the file path of the plugin's dynamic library. - /// \return The full path to the link library that contains the plugin's code. - const QString& libraryFilename() const { return _libraryFilename; } - - /// \brief Returns the plugin library after it has been loaded. - /// \return The runtime library or \c NULL if the plugin has not been loaded. - QLibrary* library() const { return _library; } - -protected: - - /// \brief Constructor that loads the given manifest file. - NativePlugin(const QString& manifestFile, bool builtinPlugin); - - /// \brief Loads the plugin's dynamic link library. - /// \throw Exception on error. - virtual void loadPluginImpl() override; - -private: - - /// The file path of the dynamic library. - QString _libraryFilename; - - /// The plugin library after it has been loaded. - QLibrary* _library; - - friend class PluginManager; -}; - -OVITO_END_INLINE_NAMESPACE -OVITO_END_INLINE_NAMESPACE -} // End of namespace - -#endif // __OVITO_NATIVE_PLUGIN_H diff -Nru ovito-2.8.1+dfsg2/src/core/plugins/Plugin.cpp ovito-2.9.0+dfsg1/src/core/plugins/Plugin.cpp --- ovito-2.8.1+dfsg2/src/core/plugins/Plugin.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/plugins/Plugin.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,39 +23,13 @@ #include #include -#include -#include -#include - namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(PluginSystem) /****************************************************************************** * Constructor for the Plugin class. ******************************************************************************/ -Plugin::Plugin(const QString& manifestFile, bool builtinPlugin) : _isLoaded(builtinPlugin) +Plugin::Plugin(const QString& pluginId) : _pluginId(pluginId) { - // Load plugin manifest. - QFile file(manifestFile); - if(!file.open(QIODevice::ReadOnly)) - throw Exception(tr("Failed to open plugin manifest file %1").arg(manifestFile)); - QJsonParseError parserError; - _metadata = QJsonDocument::fromJson(file.readAll(), &parserError); - if(parserError.error != QJsonParseError::NoError || _metadata.isNull() || !_metadata.isObject()) - throw Exception(tr("Failed to load plugin manifest file %1:\n%2").arg(manifestFile, parserError.errorString())); - - // Extract the metadata fields. - QJsonObject root = _metadata.object(); - _pluginId = root.value(QStringLiteral("plugin-id")).toString(); - _pluginVendor = root.value(QStringLiteral("plugin-vendor")).toString(); - _pluginVersion = root.value(QStringLiteral("plugin-version")).toString(); - - // Parse dependency list. - for(QJsonValue dep : root.value(QStringLiteral("dependencies")).toArray()) { - QString depPluginName = dep.toString(); - if(depPluginName.isEmpty()) - throw Exception(tr("Invalid plugin dependency in plugin manifest %1.").arg(manifestFile)); - _dependencies.push_back(depPluginName); - } } /****************************************************************************** @@ -66,47 +40,6 @@ } /****************************************************************************** -* Loads the plugin into memory. -******************************************************************************/ -void Plugin::loadPlugin() -{ - if(isLoaded()) return; // Plugin is already loaded. - - // Load other plugins this plugin depends on explicitly. - for(QVector::const_iterator depName = _dependencies.begin(); depName != _dependencies.end(); ++depName) { - Plugin* depPlugin = PluginManager::instance().plugin(*depName); - if(depPlugin == NULL) - throw Exception(QString("Cannot load plugin %1 because it depends on the plugin %2, which is not installed.").arg(pluginId(), *depName)); - _isLoaded = true; - try { - depPlugin->loadPlugin(); - _isLoaded = false; - } - catch(...) { _isLoaded = false; throw; } - } - - // Load other plugins this plugin depends on implicitly. - for(QSet::const_iterator dep = _implicitDependencies.begin(); dep != _implicitDependencies.end(); ++dep) { - _isLoaded = true; - try { - (*dep)->loadPlugin(); - _isLoaded = false; - } - catch(Exception& ex) { - _isLoaded = false; - throw ex.prependGeneralMessage(tr("Failed to load plugin %1, which is required by plugin %2.").arg((*dep)->pluginId(), pluginId())); - } - catch(...) { _isLoaded = false; throw; } - } - - // Do the plugin type specific work. - loadPluginImpl(); - - // Loading was successful. - this->_isLoaded = true; -} - -/****************************************************************************** * Finds the plugin class with the given name defined by the plugin. ******************************************************************************/ OvitoObjectType* Plugin::findClass(const QString& name) const @@ -118,20 +51,6 @@ return nullptr; } -/****************************************************************************** -* Returns all plugins this plugin directly depends on. -******************************************************************************/ -QSet Plugin::dependencies() const -{ - QSet dep = _implicitDependencies; - for(const QString& depName : _dependencies) { - Plugin* depPlugin = PluginManager::instance().plugin(depName); - if(depPlugin != NULL) - dep.insert(depPlugin); - } - return dep; -} - OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/plugins/Plugin.h ovito-2.9.0+dfsg1/src/core/plugins/Plugin.h --- ovito-2.8.1+dfsg2/src/core/plugins/Plugin.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/plugins/Plugin.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,14 +19,12 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PLUGIN_H -#define __OVITO_PLUGIN_H +#pragma once + #include #include -#include - namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(PluginSystem) /** @@ -41,18 +39,9 @@ /// \brief Destructor virtual ~Plugin(); - /// \brief Returns the plugin's metadata. - const QJsonDocument& metadata() const { return _metadata; } - /// \brief Returns the unique identifier of the plugin. const QString& pluginId() const { return _pluginId; } - /// \brief Returns the plugin's vendor string. - const QString& pluginVendor() const { return _pluginVendor; } - - /// \brief Returns the plugin's version string. - const QString& pluginVersion() const { return _pluginVersion; } - /// \brief Finds the plugin class with the given name defined by the plugin. /// \param name The class name. /// \return The descriptor for the plugin class with the given name or \c NULL @@ -62,7 +51,7 @@ /// \brief Returns whether the plugin's dynamic library has been loaded. /// \sa loadPlugin() - bool isLoaded() const { return _isLoaded; } + bool isLoaded() const { return true; } /// \brief Loads the plugin's dynamic link library into memory. /// \throw Exception if an error occurs. @@ -70,26 +59,16 @@ /// This method may load other plugins first if this plugin /// depends on them. /// \sa isLoaded() - void loadPlugin(); + void loadPlugin() {} /// \brief Returns all classes defined by the plugin. /// \sa findClass() const QVector& classes() const { return _classes; } - /// \brief Returns all other plugins this plugin (directly) depends on. - QSet dependencies() const; - protected: - /// \brief Constructor that loads the given manifest file. - /// \param manifestFile Path to the plugin's JSON manifest file. - /// \param builtinPlugin Indicates whether this plugin is statically linked into the executable. - /// \throw Exception If a parsing error occurred. - Plugin(const QString& manifestFile, bool builtinPlugin); - - /// \brief Implementation method that loads the plugin. - /// \throw Exception if an error occurred. - virtual void loadPluginImpl() = 0; + /// \brief Constructor. + Plugin(const QString& pluginId); /// \brief Adds a class to the list of plugin classes. void registerClass(OvitoObjectType* clazz) { _classes.push_back(clazz); } @@ -99,31 +78,13 @@ /// The unique identifier of the plugin. QString _pluginId; - /// The vendor of the plugin. - QString _pluginVendor; - - /// The version string of the plugin. - QString _pluginVersion; - /// The classes provided by the plugin. QVector _classes; - /// The plugins this plugin explicitly depends on. - QVector _dependencies; - - /// The plugins this plugin implicitly depends on. - QSet _implicitDependencies; - - /// The plugin's metadata. - QJsonDocument _metadata; - - /// Indicates whether the plugin dynamic library has been loaded. - bool _isLoaded; - friend class PluginManager; }; OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_PLUGIN_H + diff -Nru ovito-2.8.1+dfsg2/src/core/plugins/PluginManager.cpp ovito-2.9.0+dfsg1/src/core/plugins/PluginManager.cpp --- ovito-2.8.1+dfsg2/src/core/plugins/PluginManager.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/plugins/PluginManager.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,7 +22,8 @@ #include #include #include -#include + +#include namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(PluginSystem) @@ -58,14 +59,6 @@ if(plugin->pluginId() == pluginId) return plugin; } - - // For backward compatibility with OVITO 2.1: - // The "Viz" plugin has been renamed to "Particles". - // To support loading of old state files in newer program versions, - // use "Viz" as an alias for the Particles plugin. - if(pluginId == QStringLiteral("Viz")) - return plugin(QStringLiteral("Particles")); - return nullptr; } @@ -96,7 +89,7 @@ return { QDir(prefixDir.absolutePath() + QStringLiteral("/plugins")) }; #elif defined(Q_OS_MAC) prefixDir.cdUp(); - return { QDir(prefixDir.absolutePath() + QStringLiteral("/Resources/plugins")) }; + return { QDir(prefixDir.absolutePath() + QStringLiteral("/PlugIns")) }; #else prefixDir.cdUp(); return { QDir(prefixDir.absolutePath() + QStringLiteral("/lib/ovito/plugins")) }; @@ -104,50 +97,61 @@ } /****************************************************************************** -* Searches the plugin directories for installed plugins and -* loads their XML manifests. +* Searches the plugin directories for installed plugins and loads them. ******************************************************************************/ -void PluginManager::registerPlugins() +void PluginManager::loadAllPlugins() { - // Initialize all built-in classes. - for(NativeOvitoObjectType* clazz = NativeOvitoObjectType::_firstInfo; clazz != nullptr; clazz = clazz->_next) { - Plugin* classPlugin = this->plugin(clazz->pluginId()); - if(!classPlugin) { - classPlugin = new NativePlugin(QStringLiteral(":/%1/PluginManifest.json").arg(QString(clazz->pluginId()).toLower()), true); - registerPlugin(classPlugin); - } - OVITO_ASSERT(clazz->plugin() == nullptr); - clazz->initializeClassDescriptor(classPlugin); - classPlugin->registerClass(clazz); +#ifdef Q_OS_WIN + // Modify PATH enviroment variable so that Windows finds the plugin DLLs if + // there are dependencies between them. + QByteArray path = qgetenv("PATH"); + for(QDir pluginDir : pluginDirs()) { + path = QDir::toNativeSeparators(pluginDir.absolutePath()).toUtf8() + ";" + path; } - + qputenv("PATH", path); +#endif + // Scan the plugin directories for installed plugins. + // This only done in standalone mode. + // When OVITO is being used from an external Python interpreter, + // then plugins are loaded via explicit import statements. for(QDir pluginDir : pluginDirs()) { if(!pluginDir.exists()) throw Exception(tr("Failed to scan the plugin directory. Path %1 does not exist.").arg(pluginDir.path())); - // List all manifest files. - pluginDir.setNameFilters(QStringList("*.json")); + // List all plugin files. + pluginDir.setNameFilters(QStringList() << "*.so" << "*.dll"); pluginDir.setFilter(QDir::Files); - - // Load each manifest file in the plugin directory. for(const QString& file : pluginDir.entryList()) { - QString filePath = pluginDir.absoluteFilePath(file); - try { - Plugin* plugin = new NativePlugin(filePath, false); - registerPlugin(plugin); - } - catch(Exception& ex) { - ex.prependGeneralMessage(tr("Failed to load plugin manifest:\n\n%1").arg(filePath)); - ex.showError(); + QString filePath = pluginDir.absoluteFilePath(file); + QLibrary* library = new QLibrary(filePath, this); + library->setLoadHints(QLibrary::ExportExternalSymbolsHint); + if(!library->load()) { + Exception ex(QString("Failed to load native plugin library.\nLibrary file: %1\nError: %2").arg(filePath, library->errorString())); + ex.reportError(true); } } } - // Load all other plugins too. - for(Plugin* plugin : plugins()) { - plugin->loadPlugin(); + registerLoadedPluginClasses(); +} + +/****************************************************************************** +* Registers all classes of the already plugins. +******************************************************************************/ +void PluginManager::registerLoadedPluginClasses() +{ + for(NativeOvitoObjectType* clazz = NativeOvitoObjectType::_firstInfo; clazz != _lastRegisteredClass; clazz = clazz->_next) { + Plugin* classPlugin = this->plugin(clazz->pluginId()); + if(!classPlugin) { + classPlugin = new Plugin(clazz->pluginId()); + registerPlugin(classPlugin); + } + OVITO_ASSERT(clazz->plugin() == nullptr); + clazz->initializeClassDescriptor(classPlugin); + classPlugin->registerClass(clazz); } + _lastRegisteredClass = NativeOvitoObjectType::_firstInfo; } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/core/plugins/PluginManager.h ovito-2.9.0+dfsg1/src/core/plugins/PluginManager.h --- ovito-2.8.1+dfsg2/src/core/plugins/PluginManager.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/plugins/PluginManager.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PLUGIN_MANAGER_H -#define __OVITO_PLUGIN_MANAGER_H +#pragma once + #include #include "Plugin.h" @@ -36,6 +36,15 @@ public: + /// Create the singleton instance of this class. + static void initialize() { + _instance = new PluginManager(); + _instance->registerLoadedPluginClasses(); + } + + /// Deletes the singleton instance of this class. + static void shutdown() { delete _instance; _instance = nullptr; } + /// \brief Returns the one and only instance of this class. /// \return The predefined instance of the PluginManager singleton class. inline static PluginManager& instance() { @@ -43,6 +52,9 @@ return *_instance; } + /// Searches the plugin directories for installed plugins and loads them. + void loadAllPlugins(); + /// \brief Returns the plugin with a given identifier. /// \param pluginId The identifier of the plugin to return. /// \return The plugin with the given identifier or \c NULL if no such plugin is installed. @@ -65,6 +77,9 @@ /// delete it on application shutdown. void registerPlugin(Plugin* plugin); + /// Registers all classes of already loaded plugins. + void registerLoadedPluginClasses(); + /// \brief Returns the list of directories containing the Ovito plugins. QList pluginDirs(); @@ -78,32 +93,22 @@ /// The list of installed plugins. QVector _plugins; - /// Searches the plugin directories for installed plugins and loads their XML manifests. - void registerPlugins(); - /////////////////////////// Maintenance //////////////////////////////// /// Private constructor. /// This is a singleton class; no public instances are allowed. PluginManager(); - /// Create the singleton instance of this class. - static void initialize() { - _instance = new PluginManager(); - _instance->registerPlugins(); - } - - /// Deletes the singleton instance of this class. - static void shutdown() { delete _instance; _instance = nullptr; } + /// The position in the global linked list of native object types up to which classes have already been registered. + NativeOvitoObjectType* _lastRegisteredClass = nullptr; /// The singleton instance of this class. static PluginManager* _instance; - friend class Application; friend class Plugin; }; OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_PLUGIN_MANAGER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/reference/CloneHelper.h ovito-2.9.0+dfsg1/src/core/reference/CloneHelper.h --- ovito-2.8.1+dfsg2/src/core/reference/CloneHelper.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/reference/CloneHelper.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CLONE_HELPER_H -#define __OVITO_CLONE_HELPER_H +#pragma once + #include #include @@ -146,5 +146,5 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_CLONE_HELPER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/reference/NativePropertyFieldDescriptor.h ovito-2.9.0+dfsg1/src/core/reference/NativePropertyFieldDescriptor.h --- ovito-2.8.1+dfsg2/src/core/reference/NativePropertyFieldDescriptor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/reference/NativePropertyFieldDescriptor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_NATIVE_PROPERTY_FIELD_DESCRIPTOR_H -#define __OVITO_NATIVE_PROPERTY_FIELD_DESCRIPTOR_H +#pragma once + #include #include "PropertyFieldDescriptor.h" @@ -74,94 +74,168 @@ propfield._displayName = label; } }; + + // Internal helper class that is used to set the reference event type to generate + // for a property field every time its value changes. Do not use this class directly but use the + // SET_PROPERTY_FIELD_CHANGE_EVENT macro instead. + struct PropertyFieldChangeEventSetter { + PropertyFieldChangeEventSetter(NativePropertyFieldDescriptor& propfield, ReferenceEvent::Type eventType) { + OVITO_ASSERT(propfield._extraChangeEventType == 0); + propfield._extraChangeEventType = eventType; + } + }; }; -/***************** Macros to define reference fields in RefMaker-derived classes. ********************/ +/*** Macros to define reference and property fields in RefMaker-derived classes: ***/ +/// This macros returns a reference to the PropertyFieldDescriptor of a +/// named reference or property field. #define PROPERTY_FIELD(RefMakerClassPlusStorageFieldName) \ - RefMakerClassPlusStorageFieldName##__propFieldInstance + RefMakerClassPlusStorageFieldName##__propdescr -#define DECLARE_REFERENCE_FIELD(storageFieldName) \ - public: \ - static Ovito::SingleReferenceFieldBase& storageFieldName##__access_reffield(RefMaker* obj); \ - static Ovito::NativePropertyFieldDescriptor storageFieldName##__propFieldInstance; \ +#define DECLARE_PROPERTY_FIELD_DESCRIPTOR(name) \ + public: \ + static Ovito::NativePropertyFieldDescriptor name##__propdescr; \ private: -#define DEFINE_FLAGS_REFERENCE_FIELD(RefMakerClass, storageFieldName, UniqueFieldIdentifier, TargetClass, Flags) \ - Ovito::SingleReferenceFieldBase& RefMakerClass::storageFieldName##__access_reffield(RefMaker* obj) { \ - return static_cast(obj)->storageFieldName; \ - } \ - Ovito::NativePropertyFieldDescriptor RefMakerClass::storageFieldName##__propFieldInstance( \ - &RefMakerClass::OOType, &TargetClass::OOType, \ - UniqueFieldIdentifier, Flags, RefMakerClass::storageFieldName##__access_reffield \ - ); - -#define DEFINE_REFERENCE_FIELD(RefMakerClass, storageFieldName, UniqueFieldIdentifier, TargetClass) \ - DEFINE_FLAGS_REFERENCE_FIELD(RefMakerClass, storageFieldName, UniqueFieldIdentifier, TargetClass, PROPERTY_FIELD_NO_FLAGS) +/// Adds a reference field to a class definition. +/// The first parameter specifies the RefTarget derived class of the referenced object. +/// The second parameter determines the name of the reference field. It must be unique within the current class. +#define DECLARE_REFERENCE_FIELD(type, name) \ + public: \ + Ovito::ReferenceField _##name; \ + type* name() const { return _##name; } \ + DECLARE_PROPERTY_FIELD_DESCRIPTOR(name) \ + private: -#define DECLARE_VECTOR_REFERENCE_FIELD(storageFieldName)\ - public: \ - static Ovito::VectorReferenceFieldBase& storageFieldName##__access_reffield(RefMaker* obj); \ - static Ovito::NativePropertyFieldDescriptor storageFieldName##__propFieldInstance; \ +/// Adds a settable reference field to a class definition. +/// The first parameter specifies the RefTarget derived class of the referenced object. +/// The second parameter determines the name of the reference field. It must be unique within the current class. +/// The third parameter is the name of the setter method to be created for this reference field. +#define DECLARE_MODIFIABLE_REFERENCE_FIELD(type, name, setterName) \ + DECLARE_REFERENCE_FIELD(type, name) \ + public: \ + void setterName(type* obj) { _##name = obj; } \ private: -#define DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(RefMakerClass, storageFieldName, UniqueFieldIdentifier, TargetClass, Flags) \ - Ovito::VectorReferenceFieldBase& RefMakerClass::storageFieldName##__access_reffield(RefMaker* obj) { \ - return static_cast(obj)->storageFieldName; \ - } \ - Ovito::NativePropertyFieldDescriptor RefMakerClass::storageFieldName##__propFieldInstance( \ - &RefMakerClass::OOType, &TargetClass::OOType, \ - UniqueFieldIdentifier, Flags | PROPERTY_FIELD_VECTOR, RefMakerClass::storageFieldName##__access_reffield \ +#define DEFINE_FLAGS_REFERENCE_FIELD(RefMakerClass, name, UniqueFieldIdentifier, TargetClass, Flags) \ + static Ovito::SingleReferenceFieldBase& RefMakerClass##name##__access_reffield(RefMaker* obj) { \ + return static_cast(obj)->_##name; \ + } \ + Ovito::NativePropertyFieldDescriptor RefMakerClass::name##__propdescr( \ + &RefMakerClass::OOType, &TargetClass::OOType, \ + UniqueFieldIdentifier, Flags, &RefMakerClass##name##__access_reffield \ ); -#define DEFINE_VECTOR_REFERENCE_FIELD(RefMakerClass, storageFieldName, UniqueFieldIdentifier, TargetClass) \ - DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(RefMakerClass, storageFieldName, UniqueFieldIdentifier, TargetClass, PROPERTY_FIELD_VECTOR) - -#define INIT_PROPERTY_FIELD(RefMakerClassPlusStorageFieldName) \ - RefMakerClassPlusStorageFieldName.init(this, &PROPERTY_FIELD(RefMakerClassPlusStorageFieldName)); +#define DEFINE_REFERENCE_FIELD(RefMakerClass, name, UniqueFieldIdentifier, TargetClass) \ + DEFINE_FLAGS_REFERENCE_FIELD(RefMakerClass, name, UniqueFieldIdentifier, TargetClass, PROPERTY_FIELD_NO_FLAGS) -#define SET_PROPERTY_FIELD_UNITS(RefMakerClass, storageFieldName, ParameterUnitClass) \ - static Ovito::NativePropertyFieldDescriptor::PropertyFieldUnitsSetter __unitsSetter##RefMakerClass##storageFieldName(RefMakerClass::storageFieldName##__propFieldInstance, &ParameterUnitClass::staticMetaObject); +/// Adds a vector reference field to a class definition. +/// The first parameter specifies the RefTarget-derived class of the objects stored in the vector reference field. +/// The second parameter determines the name of the vector reference field. It must be unique within the current class. +#define DECLARE_VECTOR_REFERENCE_FIELD(type, name) \ + public: \ + Ovito::VectorReferenceField _##name; \ + const QVector& name() const { return _##name.targets(); } \ + DECLARE_PROPERTY_FIELD_DESCRIPTOR(name) \ + private: -#define SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(RefMakerClass, storageFieldName, ParameterUnitClass, minValue) \ - static Ovito::NativePropertyFieldDescriptor::PropertyFieldUnitsSetter __unitsSetter##RefMakerClass##storageFieldName(RefMakerClass::storageFieldName##__propFieldInstance, &ParameterUnitClass::staticMetaObject, minValue); +/// Adds a vector reference field to a class definition that is settable. +/// The first parameter specifies the RefTarget-derived class of the objects stored in the vector reference field. +/// The second parameter determines the name of the vector reference field. It must be unique within the current class. +/// The third parameter is the name of the setter method to be created for this reference field. +#define DECLARE_MODIFIABLE_VECTOR_REFERENCE_FIELD(type, name, setterName) \ + DECLARE_VECTOR_REFERENCE_FIELD(type, name) \ + public: \ + void setterName(const QVector& lst) { _##name = lst; } \ + private: -#define SET_PROPERTY_FIELD_UNITS_AND_RANGE(RefMakerClass, storageFieldName, ParameterUnitClass, minValue, maxValue) \ - static Ovito::NativePropertyFieldDescriptor::PropertyFieldUnitsSetter __unitsSetter##RefMakerClass##storageFieldName(RefMakerClass::storageFieldName##__propFieldInstance, &ParameterUnitClass::staticMetaObject, minValue, maxValue); +#define DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(RefMakerClass, name, UniqueFieldIdentifier, TargetClass, Flags) \ + static Ovito::VectorReferenceFieldBase& RefMakerClass##name##__access_reffield(RefMaker* obj) { \ + return static_cast(obj)->_##name; \ + } \ + Ovito::NativePropertyFieldDescriptor RefMakerClass::name##__propdescr( \ + &RefMakerClass::OOType, &TargetClass::OOType, \ + UniqueFieldIdentifier, Flags | PROPERTY_FIELD_VECTOR, &RefMakerClass##name##__access_reffield \ + ); -#define SET_PROPERTY_FIELD_LABEL(RefMakerClass, storageFieldName, labelText) \ - static Ovito::NativePropertyFieldDescriptor::PropertyFieldDisplayNameSetter __displayNameSetter##RefMakerClass##storageFieldName(RefMakerClass::storageFieldName##__propFieldInstance, labelText); +#define DEFINE_VECTOR_REFERENCE_FIELD(RefMakerClass, name, UniqueFieldIdentifier, TargetClass) \ + DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(RefMakerClass, name, UniqueFieldIdentifier, TargetClass, PROPERTY_FIELD_VECTOR) -#define DECLARE_PROPERTY_FIELD(storageFieldName) \ +/// This macro must be called for every reference or property field from the constructor +/// of the RefMaker derived class that owns the field. +#define INIT_PROPERTY_FIELD(name) \ + _##name.init(this, &PROPERTY_FIELD(name)); + +/// Assigns a unit class to an animation controller reference or numeric property field. +/// The unit class will automatically be assigned to the numeric input field for this parameter in the user interface. +#define SET_PROPERTY_FIELD_UNITS(RefMakerClass, name, ParameterUnitClass) \ + static Ovito::NativePropertyFieldDescriptor::PropertyFieldUnitsSetter __unitsSetter##RefMakerClass##name(PROPERTY_FIELD(RefMakerClass::name), &ParameterUnitClass::staticMetaObject); + +/// Assigns a unit class and a minimum value limit to an animation controller reference or numeric property field. +/// The unit class and the value limit will automatically be assigned to the numeric input field for this parameter in the user interface. +#define SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(RefMakerClass, name, ParameterUnitClass, minValue) \ + static Ovito::NativePropertyFieldDescriptor::PropertyFieldUnitsSetter __unitsSetter##RefMakerClass##name(PROPERTY_FIELD(RefMakerClass::name), &ParameterUnitClass::staticMetaObject, minValue); + +/// Assigns a unit class and a minimum and maximum value limit to an animation controller reference or numeric property field. +/// The unit class and the value limits will automatically be assigned to the numeric input field for this parameter in the user interface. +#define SET_PROPERTY_FIELD_UNITS_AND_RANGE(RefMakerClass, name, ParameterUnitClass, minValue, maxValue) \ + static Ovito::NativePropertyFieldDescriptor::PropertyFieldUnitsSetter __unitsSetter##RefMakerClass##name(PROPERTY_FIELD(RefMakerClass::name), &ParameterUnitClass::staticMetaObject, minValue, maxValue); + +/// Assigns a label string to the given reference or property field. +/// This string will be used in the user interface. +#define SET_PROPERTY_FIELD_LABEL(RefMakerClass, name, labelText) \ + static Ovito::NativePropertyFieldDescriptor::PropertyFieldDisplayNameSetter __displayNameSetter##RefMakerClass##name(PROPERTY_FIELD(RefMakerClass::name), labelText); + +/// Use this macro to let the system automatically generate an event of the +/// given type every time the given property field changes its value. +#define SET_PROPERTY_FIELD_CHANGE_EVENT(RefMakerClass, name, eventType) \ + static Ovito::NativePropertyFieldDescriptor::PropertyFieldChangeEventSetter __changeEventSetter##RefMakerClass##name(PROPERTY_FIELD(RefMakerClass::name), eventType); + +/// Adds a property field to a class definition. +/// The first parameter specifies the data type of the property field. +/// The second parameter determines the name of the property field. It must be unique within the current class. +#define DECLARE_PROPERTY_FIELD(type, name) \ public: \ - static QVariant __read_propfield_##storageFieldName(Ovito::RefMaker* obj); \ - static void __write_propfield_##storageFieldName(Ovito::RefMaker* obj, const QVariant& newValue); \ - static void __save_propfield_##storageFieldName(Ovito::RefMaker* obj, Ovito::SaveStream& stream); \ - static void __load_propfield_##storageFieldName(Ovito::RefMaker* obj, Ovito::LoadStream& stream); \ - static Ovito::NativePropertyFieldDescriptor storageFieldName##__propFieldInstance; \ + Ovito::PropertyField _##name; \ + const type& name() const { return _##name; } \ + DECLARE_PROPERTY_FIELD_DESCRIPTOR(name) \ private: -#define DEFINE_FLAGS_PROPERTY_FIELD(RefMakerClass, storageFieldName, UniqueFieldIdentifier, Flags) \ - QVariant RefMakerClass::__read_propfield_##storageFieldName(RefMaker* obj) { \ - return static_cast(obj)->storageFieldName.to_qvariant(); \ +/// Adds a settable property field to a class definition. +/// The first parameter specifies the data type of the property field. +/// The second parameter determines the name of the property field. It must be unique within the current class. +/// The third parameter is the name of the setter method to be created for this property field. +#define DECLARE_MODIFIABLE_PROPERTY_FIELD(type, name, setterName) \ + DECLARE_PROPERTY_FIELD(type, name) \ + public: \ + void setterName(const type& value) { _##name = value; } \ + private: + +#define DEFINE_FLAGS_PROPERTY_FIELD(RefMakerClass, name, UniqueFieldIdentifier, Flags) \ + static QVariant RefMakerClass##__read_propfield_##name(RefMaker* obj) { \ + return static_cast(obj)->_##name.to_qvariant(); \ } \ - void RefMakerClass::__write_propfield_##storageFieldName(RefMaker* obj, const QVariant& newValue) { \ - static_cast(obj)->storageFieldName = newValue; \ + static void RefMakerClass##__write_propfield_##name(RefMaker* obj, const QVariant& newValue) { \ + static_cast(obj)->_##name = newValue; \ } \ - void RefMakerClass::__save_propfield_##storageFieldName(RefMaker* obj, SaveStream& stream) { \ - static_cast(obj)->storageFieldName.saveToStream(stream); \ + static void RefMakerClass##__save_propfield_##name(RefMaker* obj, SaveStream& stream) { \ + static_cast(obj)->_##name.saveToStream(stream); \ } \ - void RefMakerClass::__load_propfield_##storageFieldName(RefMaker* obj, LoadStream& stream) { \ - static_cast(obj)->storageFieldName.loadFromStream(stream); \ + static void RefMakerClass##__load_propfield_##name(RefMaker* obj, LoadStream& stream) { \ + static_cast(obj)->_##name.loadFromStream(stream); \ } \ - Ovito::NativePropertyFieldDescriptor RefMakerClass::storageFieldName##__propFieldInstance( \ - &RefMakerClass::OOType, \ - UniqueFieldIdentifier, Flags, __read_propfield_##storageFieldName, __write_propfield_##storageFieldName, \ - __save_propfield_##storageFieldName, __load_propfield_##storageFieldName \ + Ovito::NativePropertyFieldDescriptor RefMakerClass::name##__propdescr( \ + &RefMakerClass::OOType, \ + UniqueFieldIdentifier, Flags, \ + &RefMakerClass##__read_propfield_##name, \ + &RefMakerClass##__write_propfield_##name, \ + &RefMakerClass##__save_propfield_##name, \ + &RefMakerClass##__load_propfield_##name \ ); -#define DEFINE_PROPERTY_FIELD(RefMakerClass, storageFieldName, UniqueFieldIdentifier) \ - DEFINE_FLAGS_PROPERTY_FIELD(RefMakerClass, storageFieldName, UniqueFieldIdentifier, PROPERTY_FIELD_NO_FLAGS) +#define DEFINE_PROPERTY_FIELD(RefMakerClass, name, UniqueFieldIdentifier) \ + DEFINE_FLAGS_PROPERTY_FIELD(RefMakerClass, name, UniqueFieldIdentifier, PROPERTY_FIELD_NO_FLAGS) OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE @@ -172,4 +246,4 @@ #include "RefMaker.h" #include "RefTarget.h" -#endif // __OVITO_NATIVE_PROPERTY_FIELD_DESCRIPTOR_H + diff -Nru ovito-2.8.1+dfsg2/src/core/reference/PropertyField.cpp ovito-2.9.0+dfsg1/src/core/reference/PropertyField.cpp --- ovito-2.8.1+dfsg2/src/core/reference/PropertyField.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/reference/PropertyField.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -107,7 +107,7 @@ // Check for cyclic references. if(inactiveTarget && refmaker->isReferencedBy(inactiveTarget.get())) { - OVITO_ASSERT(!owner()->isRefTarget() || !owner()->dataset()->undoStack().isUndoingOrRedoing()); + OVITO_ASSERT(!owner()->isRefTarget() || !owner()->dataset() || !owner()->dataset()->undoStack().isUndoingOrRedoing()); throw CyclicReferenceError(); } @@ -167,7 +167,7 @@ qPrintable(QString("PROPERTY_FIELD_NO_UNDO flag has not been set for reference field '%1' of non-RefTarget derived class '%2'.") .arg(descriptor()->identifier()).arg(descriptor()->definingClass()->name()))); - if(descriptor()->automaticUndo() && owner()->dataset()->undoStack().isRecording()) { + if(descriptor()->automaticUndo() && owner()->dataset() && owner()->dataset()->undoStack().isRecording()) { std::unique_ptr op(new SetReferenceOperation(newTarget, *this)); op->redo(); owner()->dataset()->undoStack().push(std::move(op)); @@ -228,7 +228,7 @@ generateTargetChangedEvent(); } catch(...) { - if(!owner()->isRefTarget() || !owner()->dataset()->undoStack().isUndoingOrRedoing()) + if(!owner()->isRefTarget() || !owner()->dataset() || !owner()->dataset()->undoStack().isUndoingOrRedoing()) throw; qDebug() << "Caught exception in VectorReferenceFieldBase::removeReference(). RefMaker is" << owner() << ". RefTarget is" << target; } @@ -250,7 +250,7 @@ // Check for cyclic references. if(target && refmaker->isReferencedBy(target.get())) { - OVITO_ASSERT(!owner()->isRefTarget() || !owner()->dataset()->undoStack().isUndoingOrRedoing()); + OVITO_ASSERT(!owner()->isRefTarget() || !owner()->dataset() || !owner()->dataset()->undoStack().isUndoingOrRedoing()); throw CyclicReferenceError(); } @@ -278,7 +278,7 @@ generateTargetChangedEvent(); } catch(...) { - if(!owner()->isRefTarget() || !owner()->dataset()->undoStack().isUndoingOrRedoing()) + if(!owner()->isRefTarget() || !owner()->dataset() || !owner()->dataset()->undoStack().isUndoingOrRedoing()) throw; qDebug() << "Caught exception in VectorReferenceFieldBase::addReference(). RefMaker is" << refmaker << ". RefTarget is" << target.get(); } @@ -303,7 +303,7 @@ qPrintable(QString("PROPERTY_FIELD_NO_UNDO flag has not been set for reference field '%1' of non-RefTarget derived class '%2'.") .arg(descriptor()->identifier()).arg(descriptor()->definingClass()->name()))); - if(descriptor()->automaticUndo() && owner()->dataset()->undoStack().isRecording()) { + if(descriptor()->automaticUndo() && owner()->dataset() && owner()->dataset()->undoStack().isRecording()) { std::unique_ptr op(new InsertReferenceOperation(newTarget, *this, index)); op->redo(); int index = op->insertionIndex(); @@ -328,7 +328,7 @@ qPrintable(QString("PROPERTY_FIELD_NO_UNDO flag has not been set for reference field '%1' of non-RefTarget derived class '%2'.") .arg(descriptor()->identifier()).arg(descriptor()->definingClass()->name()))); - if(descriptor()->automaticUndo() && owner()->dataset()->undoStack().isRecording()) { + if(descriptor()->automaticUndo() && owner()->dataset() && owner()->dataset()->undoStack().isRecording()) { std::unique_ptr op(new RemoveReferenceOperation(*this, i)); op->redo(); owner()->dataset()->undoStack().push(std::move(op)); diff -Nru ovito-2.8.1+dfsg2/src/core/reference/PropertyFieldDescriptor.cpp ovito-2.9.0+dfsg1/src/core/reference/PropertyFieldDescriptor.cpp --- ovito-2.8.1+dfsg2/src/core/reference/PropertyFieldDescriptor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/reference/PropertyFieldDescriptor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -48,7 +48,7 @@ settings.beginGroup(definingClass()->plugin()->pluginId()); settings.beginGroup(definingClass()->name()); QVariant v = object->getPropertyFieldValue(*this); - // Workaround for bug in Qt 5.7: QVariants of type float for not get correctly stored + // Workaround for bug in Qt 5.7.0: QVariants of type float for not get correctly stored // by QSettings (at least on macOS), because QVariant::Float is not an official type. if((QMetaType::Type)v.type() == QMetaType::Float) v = QVariant::fromValue((double)v.toFloat()); diff -Nru ovito-2.8.1+dfsg2/src/core/reference/PropertyFieldDescriptor.h ovito-2.9.0+dfsg1/src/core/reference/PropertyFieldDescriptor.h --- ovito-2.8.1+dfsg2/src/core/reference/PropertyFieldDescriptor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/reference/PropertyFieldDescriptor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PROPERTY_FIELD_DESCRIPTOR_H -#define __OVITO_PROPERTY_FIELD_DESCRIPTOR_H +#pragma once + #include #include @@ -86,7 +86,7 @@ PropertyFieldDescriptor(const NativeOvitoObjectType* definingClass, const char* identifier, PropertyFieldFlags flags, QVariant (*_propertyStorageReadFunc)(RefMaker*), void (*_propertyStorageWriteFunc)(RefMaker*, const QVariant&), void (*_propertyStorageSaveFunc)(RefMaker*, SaveStream&), void (*_propertyStorageLoadFunc)(RefMaker*, LoadStream&)) - : _definingClassDescriptor(definingClass), _targetClassDescriptor(nullptr), _identifier(identifier), _flags(flags), singleStorageAccessFunc(nullptr), vectorStorageAccessFunc(nullptr), + : _definingClassDescriptor(definingClass), _identifier(identifier), _flags(flags), propertyStorageReadFunc(_propertyStorageReadFunc), propertyStorageWriteFunc(_propertyStorageWriteFunc), propertyStorageSaveFunc(_propertyStorageSaveFunc), propertyStorageLoadFunc(_propertyStorageLoadFunc) { OVITO_ASSERT(_identifier != nullptr); @@ -101,8 +101,7 @@ /// Constructor for a property field that stores a single reference to a RefTarget. PropertyFieldDescriptor(const NativeOvitoObjectType* definingClass, const OvitoObjectType* targetClass, const char* identifier, PropertyFieldFlags flags, SingleReferenceFieldBase& (*_storageAccessFunc)(RefMaker*)) - : _definingClassDescriptor(definingClass), _targetClassDescriptor(targetClass), _identifier(identifier), _flags(flags), singleStorageAccessFunc(_storageAccessFunc), vectorStorageAccessFunc(nullptr), - propertyStorageReadFunc(nullptr), propertyStorageWriteFunc(nullptr), propertyStorageSaveFunc(nullptr), propertyStorageLoadFunc(nullptr) { + : _definingClassDescriptor(definingClass), _targetClassDescriptor(targetClass), _identifier(identifier), _flags(flags), singleStorageAccessFunc(_storageAccessFunc) { OVITO_ASSERT(_identifier != nullptr); OVITO_ASSERT(singleStorageAccessFunc != nullptr); OVITO_ASSERT(!_flags.testFlag(PROPERTY_FIELD_VECTOR)); @@ -117,8 +116,7 @@ /// Constructor for a property field that stores a vector of references to RefTarget objects. PropertyFieldDescriptor(const NativeOvitoObjectType* definingClass, const OvitoObjectType* targetClass, const char* identifier, PropertyFieldFlags flags, VectorReferenceFieldBase& (*_storageAccessFunc)(RefMaker*)) - : _definingClassDescriptor(definingClass), _targetClassDescriptor(targetClass), _identifier(identifier), _flags(flags), singleStorageAccessFunc(nullptr), vectorStorageAccessFunc(_storageAccessFunc), - propertyStorageReadFunc(nullptr), propertyStorageWriteFunc(nullptr), propertyStorageSaveFunc(nullptr), propertyStorageLoadFunc(nullptr) { + : _definingClassDescriptor(definingClass), _targetClassDescriptor(targetClass), _identifier(identifier), _flags(flags), vectorStorageAccessFunc(_storageAccessFunc) { OVITO_ASSERT(_identifier != nullptr); OVITO_ASSERT(vectorStorageAccessFunc != nullptr); OVITO_ASSERT(_flags.testFlag(PROPERTY_FIELD_VECTOR)); @@ -156,6 +154,10 @@ /// Returns true if a TargetChanged event should be generated each time the property's value changes. bool shouldGenerateChangeEvent() const { return !_flags.testFlag(PROPERTY_FIELD_NO_CHANGE_MESSAGE); } + /// Return the type of reference event to generate each time this property field's value changes + /// (in addition to the TargetChanged event, which is generated by default). + int extraChangeEventType() const { return _extraChangeEventType; } + /// Returns the human readable and localized name of the property field. /// It will be used as label text in the user interface. QString displayName() const; @@ -188,7 +190,7 @@ const char* _identifier; /// The base type of the objects stored in this field if this is a reference field. - const OvitoObjectType* _targetClassDescriptor; + const OvitoObjectType* _targetClassDescriptor = nullptr; /// The RefMaker derived class that owns the property. const OvitoObjectType* _definingClassDescriptor; @@ -200,22 +202,22 @@ PropertyFieldFlags _flags; /// Stores a pointer to the function that reads the property field's value for a certain RefMaker instance. - QVariant (*propertyStorageReadFunc)(RefMaker*); + QVariant (*propertyStorageReadFunc)(RefMaker*) = nullptr; /// Stores a pointer to the function that sets the property field's value for a certain RefMaker instance. - void (*propertyStorageWriteFunc)(RefMaker*, const QVariant&); + void (*propertyStorageWriteFunc)(RefMaker*, const QVariant&) = nullptr; /// Stores a pointer to the function that saves the property field's value to a stream. - void (*propertyStorageSaveFunc)(RefMaker*, SaveStream&); + void (*propertyStorageSaveFunc)(RefMaker*, SaveStream&) = nullptr; /// Stores a pointer to the function that loads the property field's value from a stream. - void (*propertyStorageLoadFunc)(RefMaker*, LoadStream&); + void (*propertyStorageLoadFunc)(RefMaker*, LoadStream&) = nullptr; /// Stores a pointer to the function that returns the single reference field for a certain RefMaker instance. - SingleReferenceFieldBase& (*singleStorageAccessFunc)(RefMaker*); + SingleReferenceFieldBase& (*singleStorageAccessFunc)(RefMaker*) = nullptr; /// Stores a pointer to the function that return the vector reference field for a certain RefMaker instance. - VectorReferenceFieldBase& (*vectorStorageAccessFunc)(RefMaker*); + VectorReferenceFieldBase& (*vectorStorageAccessFunc)(RefMaker*) = nullptr; /// The human-readable name of this property field. It will be used /// as label text in the user interface. @@ -224,6 +226,9 @@ /// Provides further information about numerical parameters of objects. const NumericalParameterDescriptor* _parameterInfo; + /// The type of reference event to generate each time this property field's value changes. + int _extraChangeEventType = 0; + friend class RefMaker; friend class RefTarget; }; @@ -231,4 +236,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_PROPERTY_FIELD_DESCRIPTOR_H + diff -Nru ovito-2.8.1+dfsg2/src/core/reference/PropertyField.h ovito-2.9.0+dfsg1/src/core/reference/PropertyField.h --- ovito-2.8.1+dfsg2/src/core/reference/PropertyField.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/reference/PropertyField.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PROPERTY_FIELD_H -#define __OVITO_PROPERTY_FIELD_H +#pragma once + #include #include @@ -82,12 +82,17 @@ /** * \brief Stores a non-animatable property of a RefTarget derived class. */ -template +template class PropertyField : public PropertyFieldBase { public: - typedef property_data_type property_type; - typedef qvariant_data_type qvariant_type; + using property_type = property_data_type; + + // Pick the QVariant data type used to wrap the property type. + // If the property type is an enum, then use int. + // If the property is Color, then use QColor. + using qvariant_type = typename std::conditional::value, int, + typename std::conditional::value, QColor, property_data_type>::type>::type; /// Forwarding constructor. template @@ -98,8 +103,9 @@ PropertyFieldBase::init(owner, descriptor); // For enum types, the QVariant data type must always be set to 'int'. - static_assert(!std::is_enum::value || std::is_same::value, - "When using PropertyField<> with an enum type, the QVariant data type must always be set to 'int'. For example: PropertyField"); + static_assert(!std::is_enum::value || std::is_same::value, "QVariant data type must be 'int' for enum property types."); + // For color properties, the QVariant data type must always be set to 'QColor'. + static_assert(!std::is_same::value || std::is_same::value, "QVariant data type must be 'QColor' for color property types."); } /// Cast the property field to the property value. @@ -146,8 +152,8 @@ _value = newValue; generatePropertyChangedEvent(); generateTargetChangedEvent(); - if(additionalChangeMessage != 0) - generateTargetChangedEvent((ReferenceEvent::Type)additionalChangeMessage); + if(descriptor()->extraChangeEventType() != 0) + generateTargetChangedEvent(static_cast(descriptor()->extraChangeEventType())); } // This undo class records a change to the property value. @@ -495,4 +501,4 @@ #include -#endif // __OVITO_PROPERTY_FIELD_H + diff -Nru ovito-2.8.1+dfsg2/src/core/reference/ReferenceEvent.h ovito-2.9.0+dfsg1/src/core/reference/ReferenceEvent.h --- ovito-2.8.1+dfsg2/src/core/reference/ReferenceEvent.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/reference/ReferenceEvent.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_REFERENCE_EVENT_H -#define __OVITO_REFERENCE_EVENT_H +#pragma once + #include @@ -148,4 +148,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_REFERENCE_EVENT_H + diff -Nru ovito-2.8.1+dfsg2/src/core/reference/RefMaker.cpp ovito-2.9.0+dfsg1/src/core/reference/RefMaker.cpp --- ovito-2.8.1+dfsg2/src/core/reference/RefMaker.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/reference/RefMaker.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -32,7 +32,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) // Gives the class run-time type information. -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, RefMaker, OvitoObject); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(RefMaker, OvitoObject); /****************************************************************************** * This method is called when the reference counter of this OvitoObject @@ -43,7 +43,7 @@ OVITO_CHECK_OBJECT_POINTER(this); // Make sure undo recording is not active while deleting a RefTarget. - OVITO_ASSERT_MSG(!isRefTarget() || dataset()->undoStack().isRecording() == false, "RefMaker::aboutToBeDeleted()", "Cannot delete object from memory while undo recording is active."); + OVITO_ASSERT_MSG(!isRefTarget() || !dataset() || dataset()->undoStack().isRecording() == false, "RefMaker::aboutToBeDeleted()", "Cannot delete object from memory while undo recording is active."); // Clear all references this object has to other objects. clearAllReferences(); @@ -155,7 +155,7 @@ ******************************************************************************/ void RefMaker::replaceReferencesTo(RefTarget* oldTarget, RefTarget* newTarget) { - if(oldTarget == NULL) return; + if(!oldTarget) return; OVITO_CHECK_OBJECT_POINTER(oldTarget); // Check for cyclic references first. @@ -192,7 +192,7 @@ ******************************************************************************/ void RefMaker::clearReferencesTo(RefTarget* target) { - if(target == NULL) return; + if(!target) return; OVITO_CHECK_OBJECT_POINTER(target); // Iterate over all reference fields in the class hierarchy. @@ -202,7 +202,7 @@ if(field->isVector() == false) { SingleReferenceFieldBase& singleField = field->singleStorageAccessFunc(this); if(singleField == target) - singleField.setValue(NULL); + singleField.setValue(nullptr); } else { VectorReferenceFieldBase& vectorField = field->vectorStorageAccessFunc(this); diff -Nru ovito-2.8.1+dfsg2/src/core/reference/RefMaker.h ovito-2.9.0+dfsg1/src/core/reference/RefMaker.h --- ovito-2.8.1+dfsg2/src/core/reference/RefMaker.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/reference/RefMaker.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_REFMAKER_H -#define __OVITO_REFMAKER_H +#pragma once + #include #include "ReferenceEvent.h" @@ -291,10 +291,7 @@ ///////////////////////////// DataSet access /////////////////////////////// /// \brief Returns the dataset this object belongs to. - DataSet* dataset() const { - OVITO_ASSERT_MSG(_dataset != nullptr, "RefMaker::dataset()", "Tried to access non-existing parent dataset of RefMaker."); - return _dataset; - } + DataSet* dataset() const { return _dataset; } /// \brief Changes the dataset this object belongs to. void setDataset(DataSet* dataset) { _dataset = dataset; } @@ -321,7 +318,7 @@ static void walkNode(QSet& nodes, const RefMaker* node); /// The dataset this object belongs to. - DataSet* _dataset; + QPointer _dataset; friend class RefTarget; friend class SingleReferenceFieldBase; @@ -337,4 +334,4 @@ #include "NativePropertyFieldDescriptor.h" -#endif // __OVITO_REFMAKER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/reference/RefTarget.cpp ovito-2.9.0+dfsg1/src/core/reference/RefTarget.cpp --- ovito-2.8.1+dfsg2/src/core/reference/RefTarget.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/reference/RefTarget.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) // Gives the class run-time type information. -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, RefTarget, RefMaker); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(RefTarget, RefMaker); /****************************************************************************** * This method is called when the reference counter of this OvitoObject @@ -37,10 +37,9 @@ { OVITO_CHECK_OBJECT_POINTER(this); OVITO_ASSERT(this->__isObjectAlive()); - OVITO_CHECK_OBJECT_POINTER(dataset()); // Make sure undo recording is not active while deleting the object from memory. - UndoSuspender noUndo(dataset()->undoStack()); + UndoSuspender noUndo(this); // This will remove all references to this target object. notifyDependents(ReferenceEvent::TargetDeleted); diff -Nru ovito-2.8.1+dfsg2/src/core/reference/RefTarget.h ovito-2.9.0+dfsg1/src/core/reference/RefTarget.h --- ovito-2.8.1+dfsg2/src/core/reference/RefTarget.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/reference/RefTarget.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_REFTARGET_H -#define __OVITO_REFTARGET_H +#pragma once + #include #include "RefMaker.h" @@ -301,4 +301,4 @@ // Also include the CloneHelper header because it is always needed in conjunction with the RefTarget class. #include "CloneHelper.h" -#endif // __OVITO_REFTARGET_H + diff -Nru ovito-2.8.1+dfsg2/src/core/reference/RefTargetListener.cpp ovito-2.9.0+dfsg1/src/core/reference/RefTargetListener.cpp --- ovito-2.8.1+dfsg2/src/core/reference/RefTargetListener.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/reference/RefTargetListener.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,10 +24,10 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) -IMPLEMENT_OVITO_OBJECT(Core, RefTargetListenerBase, RefMaker); -IMPLEMENT_OVITO_OBJECT(Core, VectorRefTargetListenerBase, RefMaker); -DEFINE_FLAGS_REFERENCE_FIELD(RefTargetListenerBase, _target, "Target", RefTarget, PROPERTY_FIELD_NEVER_CLONE_TARGET|PROPERTY_FIELD_NO_UNDO|PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_WEAK_REF); -DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(VectorRefTargetListenerBase, _targets, "Targets", RefTarget, PROPERTY_FIELD_NEVER_CLONE_TARGET|PROPERTY_FIELD_NO_UNDO|PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_WEAK_REF); +IMPLEMENT_OVITO_OBJECT(RefTargetListenerBase, RefMaker); +IMPLEMENT_OVITO_OBJECT(VectorRefTargetListenerBase, RefMaker); +DEFINE_FLAGS_REFERENCE_FIELD(RefTargetListenerBase, target, "Target", RefTarget, PROPERTY_FIELD_NEVER_CLONE_TARGET|PROPERTY_FIELD_NO_UNDO|PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_WEAK_REF); +DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(VectorRefTargetListenerBase, targets, "Targets", RefTarget, PROPERTY_FIELD_NEVER_CLONE_TARGET|PROPERTY_FIELD_NO_UNDO|PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_WEAK_REF); /****************************************************************************** * Is called when the RefTarget referenced by this listener has sent a message. diff -Nru ovito-2.8.1+dfsg2/src/core/reference/RefTargetListener.h ovito-2.9.0+dfsg1/src/core/reference/RefTargetListener.h --- ovito-2.8.1+dfsg2/src/core/reference/RefTargetListener.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/reference/RefTargetListener.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_REFTARGET_LISTENER_H -#define __OVITO_REFTARGET_LISTENER_H +#pragma once + #include #include "RefTarget.h" @@ -41,7 +41,7 @@ /// \brief The default constructor. RefTargetListenerBase() : RefMaker(nullptr) { - INIT_PROPERTY_FIELD(RefTargetListenerBase::_target); + INIT_PROPERTY_FIELD(target); } /// \brief Destructor. @@ -49,16 +49,6 @@ clearAllReferences(); } - /// \brief Returns the current target this listener is listening to. - /// \return The current target object or \c NULL. - /// \sa setTarget() - RefTarget* target() const { return _target; } - - /// \brief Sets the current target this listener should listen to. - /// \param newTarget The new target or \c NULL. - /// \sa target() - void setTarget(RefTarget* newTarget) { _target = newTarget; } - Q_SIGNALS: /// \brief This Qt signal is emitted by the listener each time it receives a notification @@ -79,13 +69,11 @@ private: - /// The RefTarget which is being monitored by this listener. - ReferenceField _target; - Q_OBJECT OVITO_OBJECT - DECLARE_REFERENCE_FIELD(_target); + /// The RefTarget which is being monitored by this listener. + DECLARE_MODIFIABLE_REFERENCE_FIELD(RefTarget, target, setTarget); }; /** @@ -122,7 +110,7 @@ /// \brief The default constructor. VectorRefTargetListenerBase() : RefMaker(nullptr) { - INIT_PROPERTY_FIELD(VectorRefTargetListenerBase::_targets); + INIT_PROPERTY_FIELD(targets); } /// \brief Destructor. @@ -130,16 +118,6 @@ clearAllReferences(); } - /// \brief Returns the list of targets this listener is listening to. - /// \return The current list of target objects. - /// \sa setTargets() - const QVector& targets() const { return _targets; } - - /// \brief Sets the list of targets this listener should listen to. - /// \param newTargets The new list of targets. - /// \sa targets() - void setTargets(const QVector& newTargets) { _targets = newTargets; } - /// \brief Clears the list of targets. void clear() { _targets.clear(); } @@ -183,13 +161,11 @@ private: - /// The list of RefTargets which are being monitored by this listener. - VectorReferenceField _targets; - Q_OBJECT OVITO_OBJECT - DECLARE_VECTOR_REFERENCE_FIELD(_targets); + /// The list of RefTargets which are being monitored by this listener. + DECLARE_MODIFIABLE_VECTOR_REFERENCE_FIELD(RefTarget, targets, setTargets); }; /** @@ -223,5 +199,5 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_REFTARGET_LISTENER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/ArrowPrimitive.h ovito-2.9.0+dfsg1/src/core/rendering/ArrowPrimitive.h --- ovito-2.8.1+dfsg2/src/core/rendering/ArrowPrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/ArrowPrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ARROW_PRIMITIVE_H -#define __OVITO_ARROW_PRIMITIVE_H +#pragma once + #include #include @@ -112,4 +112,4 @@ Q_DECLARE_TYPEINFO(Ovito::ArrowPrimitive::RenderingQuality, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::ArrowPrimitive::Shape, Q_PRIMITIVE_TYPE); -#endif // __OVITO_ARROW_PRIMITIVE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/FrameBuffer.h ovito-2.9.0+dfsg1/src/core/rendering/FrameBuffer.h --- ovito-2.8.1+dfsg2/src/core/rendering/FrameBuffer.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/FrameBuffer.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FRAME_BUFFER_H -#define __OVITO_FRAME_BUFFER_H +#pragma once + #include @@ -188,4 +188,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_FRAME_BUFFER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/ImagePrimitive.h ovito-2.9.0+dfsg1/src/core/rendering/ImagePrimitive.h --- ovito-2.8.1+dfsg2/src/core/rendering/ImagePrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/ImagePrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_IMAGE_PRIMITIVE_H -#define __OVITO_IMAGE_PRIMITIVE_H +#pragma once + #include #include "PrimitiveBase.h" @@ -58,4 +58,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_IMAGE_PRIMITIVE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/LinePrimitive.h ovito-2.9.0+dfsg1/src/core/rendering/LinePrimitive.h --- ovito-2.8.1+dfsg2/src/core/rendering/LinePrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/LinePrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_LINE_DISPLAY_PRIMITIVE_H -#define __OVITO_LINE_DISPLAY_PRIMITIVE_H +#pragma once + #include #include "PrimitiveBase.h" @@ -53,4 +53,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_LINE_DISPLAY_PRIMITIVE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/MarkerPrimitive.h ovito-2.9.0+dfsg1/src/core/rendering/MarkerPrimitive.h --- ovito-2.8.1+dfsg2/src/core/rendering/MarkerPrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/MarkerPrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_MARKER_PRIMITIVE_H -#define __OVITO_MARKER_PRIMITIVE_H +#pragma once + #include #include "PrimitiveBase.h" @@ -71,4 +71,4 @@ Q_DECLARE_METATYPE(Ovito::MarkerPrimitive::MarkerShape); Q_DECLARE_TYPEINFO(Ovito::MarkerPrimitive::MarkerShape, Q_PRIMITIVE_TYPE); -#endif // __OVITO_MARKER_PRIMITIVE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/MeshPrimitive.h ovito-2.9.0+dfsg1/src/core/rendering/MeshPrimitive.h --- ovito-2.8.1+dfsg2/src/core/rendering/MeshPrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/MeshPrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_MESH_PRIMITIVE_H -#define __OVITO_MESH_PRIMITIVE_H +#pragma once + #include #include "PrimitiveBase.h" @@ -66,4 +66,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_MESH_PRIMITIVE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/DefaultArrowPrimitive.h ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/DefaultArrowPrimitive.h --- ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/DefaultArrowPrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/DefaultArrowPrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DEFAULT_ARROW_GEOMETRY_BUFFER_H -#define __OVITO_DEFAULT_ARROW_GEOMETRY_BUFFER_H +#pragma once + #include #include @@ -82,4 +82,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_VIEWPORT_ARROW_GEOMETRY_BUFFER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/DefaultImagePrimitive.h ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/DefaultImagePrimitive.h --- ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/DefaultImagePrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/DefaultImagePrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DEFAULT_IMAGE_GEOMETRY_BUFFER_H -#define __OVITO_DEFAULT_IMAGE_GEOMETRY_BUFFER_H +#pragma once + #include #include @@ -51,4 +51,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_DEFAULT_IMAGE_GEOMETRY_BUFFER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/DefaultLinePrimitive.h ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/DefaultLinePrimitive.h --- ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/DefaultLinePrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/DefaultLinePrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DEFAULT_LINE_GEOMETRY_BUFFER_H -#define __OVITO_DEFAULT_LINE_GEOMETRY_BUFFER_H +#pragma once + #include #include @@ -87,4 +87,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_DEFAULT_LINE_GEOMETRY_BUFFER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/DefaultMarkerPrimitive.h ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/DefaultMarkerPrimitive.h --- ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/DefaultMarkerPrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/DefaultMarkerPrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DEFAULT_MARKER_PRIMITIVE_H -#define __OVITO_DEFAULT_MARKER_PRIMITIVE_H +#pragma once + #include #include @@ -72,4 +72,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_DEFAULT_MARKER_PRIMITIVE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/DefaultMeshPrimitive.h ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/DefaultMeshPrimitive.h --- ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/DefaultMeshPrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/DefaultMeshPrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DEFAULT_TRIMESH_GEOMETRY_BUFFER_H -#define __OVITO_DEFAULT_TRIMESH_GEOMETRY_BUFFER_H +#pragma once + #include #include @@ -72,4 +72,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_DEFAULT_TRIMESH_GEOMETRY_BUFFER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/DefaultParticlePrimitive.h ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/DefaultParticlePrimitive.h --- ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/DefaultParticlePrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/DefaultParticlePrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DEFAULT_PARTICLE_GEOMETRY_BUFFER_H -#define __OVITO_DEFAULT_PARTICLE_GEOMETRY_BUFFER_H +#pragma once + #include #include @@ -143,4 +143,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_DEFAULT_PARTICLE_GEOMETRY_BUFFER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/DefaultTextPrimitive.h ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/DefaultTextPrimitive.h --- ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/DefaultTextPrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/DefaultTextPrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DEFAULT_TEXT_GEOMETRY_BUFFER_H -#define __OVITO_DEFAULT_TEXT_GEOMETRY_BUFFER_H +#pragma once + #include #include @@ -50,4 +50,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_DEFAULT_TEXT_GEOMETRY_BUFFER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/NonInteractiveSceneRenderer.cpp ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/NonInteractiveSceneRenderer.cpp --- ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/NonInteractiveSceneRenderer.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/NonInteractiveSceneRenderer.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, NonInteractiveSceneRenderer, SceneRenderer); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(NonInteractiveSceneRenderer, SceneRenderer); /****************************************************************************** * This method is called just before renderFrame() is called. diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/NonInteractiveSceneRenderer.h ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/NonInteractiveSceneRenderer.h --- ovito-2.8.1+dfsg2/src/core/rendering/noninteractive/NonInteractiveSceneRenderer.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/noninteractive/NonInteractiveSceneRenderer.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_NON_INTERACTIVE_SCENE_RENDERER_H -#define __OVITO_NON_INTERACTIVE_SCENE_RENDERER_H +#pragma once + #include #include @@ -128,4 +128,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_NON_INTERACTIVE_SCENE_RENDERER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/ParticlePrimitive.h ovito-2.9.0+dfsg1/src/core/rendering/ParticlePrimitive.h --- ovito-2.8.1+dfsg2/src/core/rendering/ParticlePrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/ParticlePrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_PRIMITIVE_H -#define __OVITO_PARTICLE_PRIMITIVE_H +#pragma once + #include #include "PrimitiveBase.h" @@ -148,4 +148,4 @@ Q_DECLARE_TYPEINFO(Ovito::ParticlePrimitive::RenderingQuality, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::ParticlePrimitive::ParticleShape, Q_PRIMITIVE_TYPE); -#endif // __OVITO_PARTICLE_PRIMITIVE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/PrimitiveBase.h ovito-2.9.0+dfsg1/src/core/rendering/PrimitiveBase.h --- ovito-2.8.1+dfsg2/src/core/rendering/PrimitiveBase.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/PrimitiveBase.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PRIMITIVE_BASE_H -#define __OVITO_PRIMITIVE_BASE_H +#pragma once + #include @@ -46,4 +46,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_PRIMITIVE_BASE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/RenderSettings.cpp ovito-2.9.0+dfsg1/src/core/rendering/RenderSettings.cpp --- ovito-2.8.1+dfsg2/src/core/rendering/RenderSettings.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/RenderSettings.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,67 +27,65 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, RenderSettings, RefTarget); -DEFINE_FLAGS_REFERENCE_FIELD(RenderSettings, _renderer, "Renderer", SceneRenderer, PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_REFERENCE_FIELD(RenderSettings, _backgroundColor, "BackgroundColor", Controller, PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(RenderSettings, _outputImageWidth, "OutputImageWidth"); -DEFINE_PROPERTY_FIELD(RenderSettings, _outputImageHeight, "OutputImageHeight"); -DEFINE_PROPERTY_FIELD(RenderSettings, _generateAlphaChannel, "GenerateAlphaChannel"); -DEFINE_PROPERTY_FIELD(RenderSettings, _saveToFile, "SaveToFile"); -DEFINE_PROPERTY_FIELD(RenderSettings, _skipExistingImages, "SkipExistingImages"); -DEFINE_PROPERTY_FIELD(RenderSettings, _renderingRangeType, "RenderingRangeType"); -DEFINE_PROPERTY_FIELD(RenderSettings, _customRangeStart, "CustomRangeStart"); -DEFINE_PROPERTY_FIELD(RenderSettings, _customRangeEnd, "CustomRangeEnd"); -DEFINE_PROPERTY_FIELD(RenderSettings, _everyNthFrame, "EveryNthFrame"); -DEFINE_PROPERTY_FIELD(RenderSettings, _fileNumberBase, "FileNumberBase"); -SET_PROPERTY_FIELD_LABEL(RenderSettings, _renderer, "Renderer"); -SET_PROPERTY_FIELD_LABEL(RenderSettings, _backgroundColor, "Background color"); -SET_PROPERTY_FIELD_LABEL(RenderSettings, _outputImageWidth, "Width"); -SET_PROPERTY_FIELD_LABEL(RenderSettings, _outputImageHeight, "Height"); -SET_PROPERTY_FIELD_LABEL(RenderSettings, _generateAlphaChannel, "Transparent background"); -SET_PROPERTY_FIELD_LABEL(RenderSettings, _saveToFile, "Save to file"); -SET_PROPERTY_FIELD_LABEL(RenderSettings, _skipExistingImages, "Skip existing animation images"); -SET_PROPERTY_FIELD_LABEL(RenderSettings, _renderingRangeType, "Rendering range"); -SET_PROPERTY_FIELD_LABEL(RenderSettings, _customRangeStart, "Range start"); -SET_PROPERTY_FIELD_LABEL(RenderSettings, _customRangeEnd, "Range end"); -SET_PROPERTY_FIELD_LABEL(RenderSettings, _everyNthFrame, "Every Nth frame"); -SET_PROPERTY_FIELD_LABEL(RenderSettings, _fileNumberBase, "File number base"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(RenderSettings, _outputImageWidth, IntegerParameterUnit, 1); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(RenderSettings, _outputImageHeight, IntegerParameterUnit, 1); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(RenderSettings, _everyNthFrame, IntegerParameterUnit, 1); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(RenderSettings, RefTarget); +DEFINE_FLAGS_REFERENCE_FIELD(RenderSettings, renderer, "Renderer", SceneRenderer, PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(RenderSettings, backgroundColorController, "BackgroundColor", Controller, PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(RenderSettings, outputImageWidth, "OutputImageWidth"); +DEFINE_PROPERTY_FIELD(RenderSettings, outputImageHeight, "OutputImageHeight"); +DEFINE_PROPERTY_FIELD(RenderSettings, generateAlphaChannel, "GenerateAlphaChannel"); +DEFINE_PROPERTY_FIELD(RenderSettings, saveToFile, "SaveToFile"); +DEFINE_PROPERTY_FIELD(RenderSettings, skipExistingImages, "SkipExistingImages"); +DEFINE_PROPERTY_FIELD(RenderSettings, renderingRangeType, "RenderingRangeType"); +DEFINE_PROPERTY_FIELD(RenderSettings, customRangeStart, "CustomRangeStart"); +DEFINE_PROPERTY_FIELD(RenderSettings, customRangeEnd, "CustomRangeEnd"); +DEFINE_PROPERTY_FIELD(RenderSettings, everyNthFrame, "EveryNthFrame"); +DEFINE_PROPERTY_FIELD(RenderSettings, fileNumberBase, "FileNumberBase"); +SET_PROPERTY_FIELD_LABEL(RenderSettings, renderer, "Renderer"); +SET_PROPERTY_FIELD_LABEL(RenderSettings, backgroundColorController, "Background color"); +SET_PROPERTY_FIELD_LABEL(RenderSettings, outputImageWidth, "Width"); +SET_PROPERTY_FIELD_LABEL(RenderSettings, outputImageHeight, "Height"); +SET_PROPERTY_FIELD_LABEL(RenderSettings, generateAlphaChannel, "Transparent background"); +SET_PROPERTY_FIELD_LABEL(RenderSettings, saveToFile, "Save to file"); +SET_PROPERTY_FIELD_LABEL(RenderSettings, skipExistingImages, "Skip existing animation images"); +SET_PROPERTY_FIELD_LABEL(RenderSettings, renderingRangeType, "Rendering range"); +SET_PROPERTY_FIELD_LABEL(RenderSettings, customRangeStart, "Range start"); +SET_PROPERTY_FIELD_LABEL(RenderSettings, customRangeEnd, "Range end"); +SET_PROPERTY_FIELD_LABEL(RenderSettings, everyNthFrame, "Every Nth frame"); +SET_PROPERTY_FIELD_LABEL(RenderSettings, fileNumberBase, "File number base"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(RenderSettings, outputImageWidth, IntegerParameterUnit, 1); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(RenderSettings, outputImageHeight, IntegerParameterUnit, 1); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(RenderSettings, everyNthFrame, IntegerParameterUnit, 1); /****************************************************************************** * Constructor. -* Creates an instance of the default renderer class which can be -* accessed via the renderer() method. ******************************************************************************/ RenderSettings::RenderSettings(DataSet* dataset) : RefTarget(dataset), _outputImageWidth(640), _outputImageHeight(480), _generateAlphaChannel(false), _saveToFile(false), _skipExistingImages(false), _renderingRangeType(CURRENT_FRAME), _customRangeStart(0), _customRangeEnd(100), _everyNthFrame(1), _fileNumberBase(0) { - INIT_PROPERTY_FIELD(RenderSettings::_renderer); - INIT_PROPERTY_FIELD(RenderSettings::_backgroundColor); - INIT_PROPERTY_FIELD(RenderSettings::_outputImageWidth); - INIT_PROPERTY_FIELD(RenderSettings::_outputImageHeight); - INIT_PROPERTY_FIELD(RenderSettings::_generateAlphaChannel); - INIT_PROPERTY_FIELD(RenderSettings::_saveToFile); - INIT_PROPERTY_FIELD(RenderSettings::_skipExistingImages); - INIT_PROPERTY_FIELD(RenderSettings::_renderingRangeType); - INIT_PROPERTY_FIELD(RenderSettings::_customRangeStart); - INIT_PROPERTY_FIELD(RenderSettings::_customRangeEnd); - INIT_PROPERTY_FIELD(RenderSettings::_everyNthFrame); - INIT_PROPERTY_FIELD(RenderSettings::_fileNumberBase); + INIT_PROPERTY_FIELD(renderer); + INIT_PROPERTY_FIELD(backgroundColorController); + INIT_PROPERTY_FIELD(outputImageWidth); + INIT_PROPERTY_FIELD(outputImageHeight); + INIT_PROPERTY_FIELD(generateAlphaChannel); + INIT_PROPERTY_FIELD(saveToFile); + INIT_PROPERTY_FIELD(skipExistingImages); + INIT_PROPERTY_FIELD(renderingRangeType); + INIT_PROPERTY_FIELD(customRangeStart); + INIT_PROPERTY_FIELD(customRangeEnd); + INIT_PROPERTY_FIELD(everyNthFrame); + INIT_PROPERTY_FIELD(fileNumberBase); // Setup default background color. - _backgroundColor = ControllerManager::instance().createColorController(dataset); + setBackgroundColorController(ControllerManager::createColorController(dataset)); setBackgroundColor(Color(1,1,1)); // Create an instance of the default renderer class. - Plugin* guiPlugin = PluginManager::instance().plugin("Gui"); + Plugin* glrendererPlugin = PluginManager::instance().plugin("OpenGLRenderer"); OvitoObjectType* rendererClass = nullptr; - if(guiPlugin) - rendererClass = guiPlugin->findClass("StandardSceneRenderer"); + if(glrendererPlugin) + rendererClass = glrendererPlugin->findClass("StandardSceneRenderer"); if(rendererClass == nullptr) { QVector classList = PluginManager::instance().listClasses(SceneRenderer::OOType); if(classList.isEmpty() == false) rendererClass = classList.front(); diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/RenderSettings.h ovito-2.9.0+dfsg1/src/core/rendering/RenderSettings.h --- ovito-2.8.1+dfsg2/src/core/rendering/RenderSettings.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/RenderSettings.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_RENDER_SETTINGS_H -#define __OVITO_RENDER_SETTINGS_H +#pragma once + #include #include @@ -52,30 +52,15 @@ /// Constructor. /// Creates an instance of the default renderer class which can be accessed via the renderer() method. Q_INVOKABLE RenderSettings(DataSet* dataset); - - /// Returns the active renderer. - SceneRenderer* renderer() const { return _renderer; } - /// Sets the active renderer. - void setRenderer(SceneRenderer* renderer) { OVITO_ASSERT(renderer == nullptr || renderer->dataset() == this->dataset()); _renderer = renderer; } - - /// Returns whether only the current frame or the whole animation will be rendered. - RenderingRangeType renderingRangeType() const { return _renderingRangeType; } - /// Specifies whether only the current frame or the whole animation should be rendered. - void setRenderingRangeType(RenderingRangeType mode) { _renderingRangeType = mode; } - - /// Returns the width of the image to be rendered in pixels. - int outputImageWidth() const { return std::max((int)_outputImageWidth, 1); } - /// Sets the width of the image to be rendered in pixels. - void setOutputImageWidth(int width) { _outputImageWidth = width; } - - /// Returns the height of the image to be rendered in pixels. - int outputImageHeight() const { return std::max((int)_outputImageHeight, 1); } - /// Sets the height of the image to be rendered in pixels. - void setOutputImageHeight(int height) { _outputImageHeight = height; } /// Returns the aspect ratio (height/width) of the rendered image. FloatType outputImageAspectRatio() const { return (FloatType)outputImageHeight() / (FloatType)outputImageWidth(); } + /// Returns the background color of the rendered image. + Color backgroundColor() const { return backgroundColorController() ? backgroundColorController()->currentColorValue() : Color(0,0,0); } + /// Sets the background color of the rendered image. + void setBackgroundColor(const Color& color) { if(backgroundColorController()) backgroundColorController()->setCurrentColorValue(color); } + /// Returns the output filename of the rendered image. const QString& imageFilename() const { return _imageInfo.filename(); } /// Sets the output filename of the rendered image. @@ -86,50 +71,6 @@ /// Sets the output image info for the rendered image. void setImageInfo(const ImageInfo& imageInfo); - /// Returns the background color of the rendered image. - Color backgroundColor() const { return _backgroundColor ? _backgroundColor->currentColorValue() : Color(0,0,0); } - /// Sets the background color of the rendered image. - void setBackgroundColor(const Color& color) { if(_backgroundColor) _backgroundColor->setCurrentColorValue(color); } - /// Returns the controller for the background color of the rendered image. - Controller* backgroundColorController() const { return _backgroundColor; } - /// Sets the controller for the background color of the rendered image. - void setBackgroundColorController(Controller* colorController) { _backgroundColor = colorController; } - - /// Returns whether the alpha channel will be generated. - bool generateAlphaChannel() const { return _generateAlphaChannel; } - /// Sets whether the alpha channel will be generated. - void setGenerateAlphaChannel(bool enable) { _generateAlphaChannel = enable; } - - /// Returns whether the rendered image is saved to an output file. - bool saveToFile() const { return _saveToFile; } - /// Sets whether the rendered image is saved to an output file. - void setSaveToFile(bool enable) { _saveToFile = enable; } - - /// Returns whether existing animation frames are skipped during render. - bool skipExistingImages() const { return _skipExistingImages; } - /// Sets whether existing animation frames are skipped during render. - void setSkipExistingImages(bool enable) { _skipExistingImages = enable; } - - /// Returns the first frame to render when the rendering range is set to CUSTOM_INTERVAL. - int customRangeStart() const { return _customRangeStart; } - /// Sets the first frame to render when the rendering range is set to CUSTOM_INTERVAL. - void setCustomRangeStart(int frame) { _customRangeStart = frame; } - - /// Returns the last frame to render when the rendering range is set to CUSTOM_INTERVAL. - int customRangeEnd() const { return _customRangeEnd; } - /// Sets the last frame to render when the rendering range is set to CUSTOM_INTERVAL. - void setCustomRangeEnd(int frame) { _customRangeEnd = frame; } - - /// Returns the frame interval to render when rendering an animation. - int everyNthFrame() const { return _everyNthFrame; } - /// Sets the frame interval to render when rendering an animation. - void setEveryNthFrame(int n) { _everyNthFrame = n; } - - /// Returns the base number for filename generation when rendering an animation. - int fileNumberBase() const { return _fileNumberBase; } - /// Sets the base number for filename generation when rendering an animation. - void setFileNumberBase(int n) { _fileNumberBase = n; } - public: Q_PROPERTY(QString imageFilename READ imageFilename WRITE setImageFilename); @@ -149,40 +90,40 @@ ImageInfo _imageInfo; /// The instance of the plugin renderer class. - ReferenceField _renderer; + DECLARE_MODIFIABLE_REFERENCE_FIELD(SceneRenderer, renderer, setRenderer); /// Controls the background color of the rendered image. - ReferenceField _backgroundColor; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, backgroundColorController, setBackgroundColorController); /// The width of the output image in pixels. - PropertyField _outputImageWidth; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, outputImageWidth, setOutputImageWidth); /// The height of the output image in pixels. - PropertyField _outputImageHeight; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, outputImageHeight, setOutputImageHeight); /// Controls whether the alpha channel will be included in the output image. - PropertyField _generateAlphaChannel; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, generateAlphaChannel, setGenerateAlphaChannel); /// Controls whether the rendered image is saved to the output file. - PropertyField _saveToFile; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, saveToFile, setSaveToFile); /// Controls whether already rendered frames are skipped. - PropertyField _skipExistingImages; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, skipExistingImages, setSkipExistingImages); /// Specifies which part of the animation should be rendered. - PropertyField _renderingRangeType; + DECLARE_MODIFIABLE_PROPERTY_FIELD(RenderingRangeType, renderingRangeType, setRenderingRangeType); /// The first frame to render when rendering range is set to CUSTOM_INTERVAL. - PropertyField _customRangeStart; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, customRangeStart, setCustomRangeStart); /// The last frame to render when rendering range is set to CUSTOM_INTERVAL. - PropertyField _customRangeEnd; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, customRangeEnd, setCustomRangeEnd); /// Specifies the number of frames to skip when rendering an animation. - PropertyField _everyNthFrame; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, everyNthFrame, setEveryNthFrame); /// Specifies the base number for filename generation when rendering an animation. - PropertyField _fileNumberBase; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, fileNumberBase, setFileNumberBase); private: @@ -190,19 +131,6 @@ Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_renderer); - DECLARE_REFERENCE_FIELD(_backgroundColor); - DECLARE_PROPERTY_FIELD(_outputImageWidth); - DECLARE_PROPERTY_FIELD(_outputImageHeight); - DECLARE_PROPERTY_FIELD(_generateAlphaChannel); - DECLARE_PROPERTY_FIELD(_saveToFile); - DECLARE_PROPERTY_FIELD(_skipExistingImages); - DECLARE_PROPERTY_FIELD(_renderingRangeType); - DECLARE_PROPERTY_FIELD(_customRangeStart); - DECLARE_PROPERTY_FIELD(_customRangeEnd); - DECLARE_PROPERTY_FIELD(_everyNthFrame); - DECLARE_PROPERTY_FIELD(_fileNumberBase); }; OVITO_END_INLINE_NAMESPACE @@ -211,4 +139,4 @@ Q_DECLARE_METATYPE(Ovito::RenderSettings::RenderingRangeType); Q_DECLARE_TYPEINFO(Ovito::RenderSettings::RenderingRangeType, Q_PRIMITIVE_TYPE); -#endif // __OVITO_RENDER_SETTINGS_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/SceneRenderer.cpp ovito-2.9.0+dfsg1/src/core/rendering/SceneRenderer.cpp --- ovito-2.8.1+dfsg2/src/core/rendering/SceneRenderer.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/SceneRenderer.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,8 +30,8 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, SceneRenderer, RefTarget); -IMPLEMENT_OVITO_OBJECT(Core, ObjectPickInfo, OvitoObject); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SceneRenderer, RefTarget); +IMPLEMENT_OVITO_OBJECT(ObjectPickInfo, OvitoObject); /****************************************************************************** * Constructor. @@ -145,6 +145,8 @@ ******************************************************************************/ void SceneRenderer::renderNodeTrajectory(SceneNode* node) { + if(viewport()->viewNode() == node) return; + std::vector trajectory = getNodeTrajectory(node); if(!trajectory.empty()) { setWorldTransform(AffineTransformation::Identity()); diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/SceneRenderer.h ovito-2.9.0+dfsg1/src/core/rendering/SceneRenderer.h --- ovito-2.8.1+dfsg2/src/core/rendering/SceneRenderer.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/SceneRenderer.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::SceneRenderer class. */ -#ifndef __OVITO_SCENE_RENDERER_H -#define __OVITO_SCENE_RENDERER_H +#pragma once + #include #include @@ -112,7 +112,7 @@ /// Returns the viewport whose contents are currently being rendered. /// This may be NULL. - Viewport* viewport() const { OVITO_CHECK_OBJECT_POINTER(_viewport); return _viewport; } + Viewport* viewport() const { return _viewport; } /// Returns the final size of the rendered image in pixels. virtual QSize outputSize() const; @@ -134,10 +134,10 @@ /// Renders the current animation frame. /// Returns false if the operation has been canceled by the user. - virtual bool renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, AbstractProgressDisplay* progress) = 0; + virtual bool renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, TaskManager& taskManager) = 0; /// This method is called after renderFrame() has been called. - virtual void endFrame() {} + virtual void endFrame(bool renderSuccessful) {} /// Changes the current local-to-world transformation matrix. virtual void setWorldTransform(const AffineTransformation& tm) = 0; @@ -262,4 +262,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_SCENE_RENDERER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/rendering/TextPrimitive.h ovito-2.9.0+dfsg1/src/core/rendering/TextPrimitive.h --- ovito-2.8.1+dfsg2/src/core/rendering/TextPrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/rendering/TextPrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TEXT_PRIMITIVE_H -#define __OVITO_TEXT_PRIMITIVE_H +#pragma once + #include #include "PrimitiveBase.h" @@ -88,4 +88,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_TEXT_PRIMITIVE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/ObjectNode.cpp ovito-2.9.0+dfsg1/src/core/scene/ObjectNode.cpp --- ovito-2.8.1+dfsg2/src/core/scene/ObjectNode.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/ObjectNode.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -// Copyright (2013) Alexander Stukowski +// Copyright (2017) Alexander Stukowski // // This file is part of OVITO (Open Visualization Tool). // @@ -28,18 +28,18 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, ObjectNode, SceneNode); -DEFINE_REFERENCE_FIELD(ObjectNode, _dataProvider, "SceneObject", DataObject); -DEFINE_VECTOR_REFERENCE_FIELD(ObjectNode, _displayObjects, "DisplayObjects", DisplayObject); -SET_PROPERTY_FIELD_LABEL(ObjectNode, _dataProvider, "Object"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ObjectNode, SceneNode); +DEFINE_REFERENCE_FIELD(ObjectNode, dataProvider, "SceneObject", DataObject); +DEFINE_VECTOR_REFERENCE_FIELD(ObjectNode, displayObjects, "DisplayObjects", DisplayObject); +SET_PROPERTY_FIELD_LABEL(ObjectNode, dataProvider, "Object"); /****************************************************************************** * Constructor. ******************************************************************************/ ObjectNode::ObjectNode(DataSet* dataset) : SceneNode(dataset) { - INIT_PROPERTY_FIELD(ObjectNode::_dataProvider); - INIT_PROPERTY_FIELD(ObjectNode::_displayObjects); + INIT_PROPERTY_FIELD(dataProvider); + INIT_PROPERTY_FIELD(displayObjects); } /****************************************************************************** @@ -50,79 +50,108 @@ } /****************************************************************************** -* Evaluates the geometry pipeline of this scene node at the given time. +* Evaluates the data pipeline of this node. ******************************************************************************/ -const PipelineFlowState& ObjectNode::evalPipeline(TimePoint time) +const PipelineFlowState& ObjectNode::evaluatePipelineImmediately(const PipelineEvalRequest& request) { - // Check if the caches need to be updated. - if(_displayCache.stateValidity().contains(time) == false) { - if(_pipelineCache.stateValidity().contains(time) == false) { - if(dataProvider()) { - - // Avoid recording the creation of transient objects on the undo stack - // while evaluating the pipeline. - UndoSuspender suspendUndo(dataset()->undoStack()); - - // Evaluate data flow pipeline and store results in local cache. - _pipelineCache = dataProvider()->evaluate(time); - - // Update list of active display objects. - - // First discard those display objects which are no longer needed. - // (Only when we got the final pipeline results.) - if(_pipelineCache.status().type() != PipelineStatus::Pending) { - for(int i = displayObjects().size() - 1; i >= 0; i--) { - DisplayObject* displayObj = displayObjects()[i]; - // Check if the display object is still being referenced by any of the objects - // that left the pipeline. - if(std::none_of(_pipelineCache.objects().begin(), _pipelineCache.objects().end(), - [displayObj](DataObject* obj) { return obj->displayObjects().contains(displayObj); })) { - _displayObjects.remove(i); - } + // Check if the result is already in the cache. + if(_pipelineCache.stateValidity().contains(request.time()) == false) { + if(dataProvider()) { + + // Avoid recording the creation of transient objects on the undo stack + // while evaluating the pipeline. + UndoSuspender suspendUndo(dataset()->undoStack()); + + // Evaluate data flow pipeline and store results in local cache. + _pipelineCache = dataProvider()->evaluateImmediately(request); + + // Update list of active display objects. + + // First discard those display objects which are no longer needed. + // (Only when we got the final pipeline results.) + if(_pipelineCache.status().type() != PipelineStatus::Pending) { + for(int i = displayObjects().size() - 1; i >= 0; i--) { + DisplayObject* displayObj = displayObjects()[i]; + // Check if the display object is still being referenced by any of the objects + // that left the pipeline. + if(std::none_of(_pipelineCache.objects().begin(), _pipelineCache.objects().end(), + [displayObj](DataObject* obj) { return obj->displayObjects().contains(displayObj); })) { + _displayObjects.remove(i); } } + } - // Now add any new display objects. - for(const auto& dataObj : _pipelineCache.objects()) { - for(DisplayObject* displayObj : dataObj->displayObjects()) { - OVITO_CHECK_OBJECT_POINTER(displayObj); - if(displayObjects().contains(displayObj) == false) - _displayObjects.push_back(displayObj); - } + // Now add any new display objects. + for(const auto& dataObj : _pipelineCache.objects()) { + for(DisplayObject* displayObj : dataObj->displayObjects()) { + OVITO_CHECK_OBJECT_POINTER(displayObj); + if(displayObjects().contains(displayObj) == false) + _displayObjects.push_back(displayObj); } - - OVITO_ASSERT(_pipelineCache.stateValidity().contains(time)); - } - else { - // Reset cache if this node doesn't have a data source. - invalidatePipelineCache(); - // Discard any display objects as well. - _displayObjects.clear(); } + + OVITO_ASSERT(_pipelineCache.stateValidity().contains(request.time())); + } + else { + // Reset cache if this node doesn't have a data source. + invalidatePipelineCache(); + // Discard any display objects as well. + _displayObjects.clear(); } + } + // If no display objects are requested, then we are done now. + if(!request.prepareDisplayObjects()) + return _pipelineCache; + + if(!_displayCache.stateValidity().contains(request.time())) { // Let display objects prepare the data for rendering. _displayCache = _pipelineCache; for(const auto& dataObj : _displayCache.objects()) { for(DisplayObject* displayObj : dataObj->displayObjects()) { if(displayObj && displayObj->isEnabled()) { - displayObj->prepare(time, dataObj, _displayCache); + displayObj->prepare(request.time(), dataObj, _displayCache); } } } } - else { - OVITO_ASSERT(_pipelineCache.stateValidity().contains(time)); - } return _displayCache; } /****************************************************************************** -* Renders the node's data. +* Asks the object for the result of the geometry pipeline at the given time. +******************************************************************************/ +Future ObjectNode::evaluatePipelineAsync(const PipelineEvalRequest& request) +{ + // Check if there is already an active request pending for the same animation time. + for(const auto& req : _evaluationRequests) { + if(req.first == request) + return Future(req.second); + } + + // Check if we can immediately satisfy the request. + if(_evaluationRequests.empty()) { + const PipelineFlowState& state = evaluatePipelineImmediately(request); + if(state.status().type() != PipelineStatus::Pending) + return Future::createImmediate(state); + } + + // Create a new record for this evaluation request. + auto future = Future::createWithPromise(); + _evaluationRequests.emplace_back(request, future.promise()); + future.promise()->setStarted(); + return future; +} + +/****************************************************************************** +* Renders the node's data through a SceneRenderer. ******************************************************************************/ void ObjectNode::render(TimePoint time, SceneRenderer* renderer) { - const PipelineFlowState& state = evalPipeline(time); + // Get pipeline results. + const PipelineFlowState& state = evaluatePipelineImmediately(PipelineEvalRequest(time, true)); + + // Render every display object of every data object. for(const auto& dataObj : state.objects()) { for(DisplayObject* displayObj : dataObj->displayObjects()) { if(displayObj && displayObj->isEnabled()) { @@ -149,6 +178,8 @@ else if(event->type() == ReferenceEvent::TitleChanged) { notifyDependents(ReferenceEvent::TitleChanged); } + // If input object has changed, the pipeline might have become ready. + serveEvaluationRequests(); } else if(_displayObjects.contains(source)) { if(event->type() == ReferenceEvent::TargetChanged || event->type() == ReferenceEvent::PendingStateChanged) { @@ -156,6 +187,8 @@ _displayCache.clear(); // Update cached bounding box when display settings change. invalidateBoundingBox(); + // If display object status has changed, the pipeline might have become ready. + serveEvaluationRequests(); } } return SceneNode::referenceEvent(source, event); @@ -166,12 +199,13 @@ ******************************************************************************/ void ObjectNode::referenceReplaced(const PropertyFieldDescriptor& field, RefTarget* oldTarget, RefTarget* newTarget) { - if(field == PROPERTY_FIELD(ObjectNode::_dataProvider)) { + if(field == PROPERTY_FIELD(dataProvider)) { invalidatePipelineCache(); // When the data object is being replaced, the pending state of the node might change. // Even though we don't know for sure if the state has really changed, we send a notification event here. notifyDependents(ReferenceEvent::PendingStateChanged); + serveEvaluationRequests(); } SceneNode::referenceReplaced(field, oldTarget, newTarget); @@ -183,7 +217,7 @@ Box3 ObjectNode::localBoundingBox(TimePoint time) { Box3 bb; - const PipelineFlowState& state = evalPipeline(time); + const PipelineFlowState& state = evaluatePipelineImmediately(PipelineEvalRequest(time, true)); // Compute bounding boxes of data objects. for(DataObject* dataObj : state.objects()) { @@ -224,8 +258,8 @@ QString ObjectNode::objectTitle() { // If a name has been assigned to this node, return it as the node's display title. - if(!name().isEmpty()) - return name(); + if(!nodeName().isEmpty()) + return nodeName(); // Otherwise, use the title of the node's data source object. if(DataObject* sourceObj = sourceObject()) @@ -293,14 +327,37 @@ } /****************************************************************************** -* This function blocks execution until the node's modification -* pipeline has been fully evaluated. +* Checks if the data pipeline evaluation is completed. ******************************************************************************/ -bool ObjectNode::waitUntilReady(TimePoint time, const QString& message, AbstractProgressDisplay* progressDisplay) +void ObjectNode::serveEvaluationRequests() { - return dataset()->container()->waitUntil([this, time]() { - return evalPipeline(time).status().type() != PipelineStatus::Pending; - }, message, progressDisplay); + while(!_evaluationRequests.empty()) { + // Sort out canceled requests. + Promise* promise = _evaluationRequests.front().second.get(); + if(promise->isCanceled()) { + promise->setFinished(); + _evaluationRequests.erase(_evaluationRequests.begin()); + continue; + } + + // Check if we can now satisfy the oldest request. + const PipelineFlowState& state = evaluatePipelineImmediately(_evaluationRequests.front().first); + + // The call above might have led to re-entrant call to this function; detect this kind of situation. + if(_evaluationRequests.empty() || promise != _evaluationRequests.front().second.get()) + break; + + if(state.status().type() != PipelineStatus::Pending) { + promise->setResult(state); + promise->setFinished(); + OVITO_ASSERT(promise == _evaluationRequests.front().second.get()); + _evaluationRequests.erase(_evaluationRequests.begin()); + } + else { + // Check back again later. + break; + } + } } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/core/scene/ObjectNode.h ovito-2.9.0+dfsg1/src/core/scene/ObjectNode.h --- ovito-2.8.1+dfsg2/src/core/scene/ObjectNode.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/ObjectNode.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,13 +19,15 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OBJECT_NODE_H -#define __OVITO_OBJECT_NODE_H +#pragma once + #include +#include #include "SceneNode.h" #include "objects/DataObject.h" #include "objects/DisplayObject.h" +#include "pipeline/PipelineEvalRequest.h" namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) @@ -42,15 +44,6 @@ /// \brief Destructor. virtual ~ObjectNode(); - /// \brief Returns this node's data provider, i.e. the object - /// that generates the data displayed by this scene node. - DataObject* dataProvider() const { return _dataProvider; } - - /// \brief Sets the data provider object of this node. - /// \param pipeline An object that generates data, which will be displayed by this ObjectNode. - /// \undoable - void setDataProvider(DataObject* dataProvider) { _dataProvider = dataProvider; } - /// \brief Returns the data source of this node's pipeline, i.e., the object that provides the /// input data entering the pipeline. DataObject* sourceObject() const; @@ -59,29 +52,21 @@ /// input data entering the pipeline. void setSourceObject(DataObject* sourceObject); - /// \brief Evaluates the data flow pipeline of this object node at the given animation time. - /// \param time The animation time at which the pipeline of the node should be evaluated. - /// \return The output of the pipeline. - const PipelineFlowState& evalPipeline(TimePoint time); - - /// \brief This function blocks execution until the node's modification - /// pipeline has been fully evaluated. - /// \param time The animation time at which the modification pipeline should be evaluated. - /// \param message The text to be shown to the user while waiting. - /// \param progressDisplay The progress display/dialog to be used to show the message. - /// If NULL, the function will show its own progress dialog box. - /// \return true on success; false if the operation has been canceled by the user. - bool waitUntilReady(TimePoint time, const QString& message, AbstractProgressDisplay* progressDisplay = nullptr); + /// \brief Evaluates the data pipeline of this node. + /// If the pipeline results are not immediately available, the method can react by returning an incomplete state (pending status). + /// \param request An object that describes when and how the pipeline should be evaluated. + /// \return The results of the pipeline (may be status pending). + const PipelineFlowState& evaluatePipelineImmediately(const PipelineEvalRequest& request); + + /// \brief Asks the object for the result of the data pipeline. + /// \param request An object that describes when and how the pipeline should be evaluated. + Future evaluatePipelineAsync(const PipelineEvalRequest& request); /// \brief Applies a modifier by appending it to the end of the node's data pipeline. /// \param mod The modifier to be inserted into the data flow pipeline. /// \undoable Q_INVOKABLE void applyModifier(Modifier* mod); - /// \brief Returns the list of display objects that are responsible for displaying - /// the node's data in the viewports. - const QVector& displayObjects() const { return _displayObjects; } - /// \brief Returns the bounding box of the node's object in local coordinates. /// \param time The time at which the bounding box should be computed. /// \return An axis-aligned box in the node's local coordinate system that fully contains @@ -112,8 +97,15 @@ private: - /// The object which generates the data to be displayed by this ObjectNode. - ReferenceField _dataProvider; + /// Checks if the data pipeline evaluation is completed. + void serveEvaluationRequests(); + + /// The object that generates the data to be displayed by this ObjectNode. + DECLARE_MODIFIABLE_REFERENCE_FIELD(DataObject, dataProvider, setDataProvider); + + /// The list of display objects that are responsible for displaying + /// the node's data in the viewports. This is for internal caching purposes only. + DECLARE_VECTOR_REFERENCE_FIELD(DisplayObject, displayObjects); /// The cached results from the last data pipeline evaluation. PipelineFlowState _pipelineCache; @@ -121,10 +113,6 @@ /// The cached results from the display preparation stage. PipelineFlowState _displayCache; - /// The list of display objects that are responsible for displaying - /// the node's data in the viewports. - VectorReferenceField _displayObjects; - /// This method invalidates the data pipeline cache of the object node. void invalidatePipelineCache() { // Reset data caches. @@ -134,15 +122,15 @@ invalidateBoundingBox(); } + /// List active asynchronous pipeline evaluation requests. + std::vector>> _evaluationRequests; + Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_dataProvider); - DECLARE_VECTOR_REFERENCE_FIELD(_displayObjects); }; OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OBJECT_NODE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/AsynchronousDisplayObject.cpp ovito-2.9.0+dfsg1/src/core/scene/objects/AsynchronousDisplayObject.cpp --- ovito-2.8.1+dfsg2/src/core/scene/objects/AsynchronousDisplayObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/AsynchronousDisplayObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,14 +27,14 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, AsynchronousDisplayObject, DisplayObject); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(AsynchronousDisplayObject, DisplayObject); /****************************************************************************** * Constructs the display object. ******************************************************************************/ AsynchronousDisplayObject::AsynchronousDisplayObject(DataSet* dataset) : DisplayObject(dataset) { - connect(&_engineWatcher, &FutureWatcher::finished, this, &AsynchronousDisplayObject::computeEngineFinished); + connect(&_engineWatcher, &PromiseWatcher::finished, this, &AsynchronousDisplayObject::computeEngineFinished); } /****************************************************************************** @@ -56,7 +56,7 @@ return; try { - _engineWatcher.unsetFuture(); + _engineWatcher.unsetPromise(); _runningEngine->cancel(); _runningEngine->waitForFinished(); } catch(...) {} @@ -84,7 +84,7 @@ // Start new compute engine. _runningEngine = engine; dataset()->container()->taskManager().runTaskAsync(_runningEngine); - _engineWatcher.setFutureInterface(_runningEngine); + _engineWatcher.setPromise(_runningEngine); } // Mark the pipeline output as pending as long as we are preparing the data for display. @@ -124,7 +124,7 @@ } // Reset everything. - _engineWatcher.unsetFuture(); + _engineWatcher.unsetPromise(); _runningEngine.reset(); // Set the new status. diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/AsynchronousDisplayObject.h ovito-2.9.0+dfsg1/src/core/scene/objects/AsynchronousDisplayObject.h --- ovito-2.8.1+dfsg2/src/core/scene/objects/AsynchronousDisplayObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/AsynchronousDisplayObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,11 +19,12 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ASYNC_DISPLAY_OBJECT_H -#define __OVITO_ASYNC_DISPLAY_OBJECT_H +#pragma once + #include #include +#include #include "DisplayObject.h" namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) @@ -72,7 +73,7 @@ std::shared_ptr _runningEngine; /// The watcher that is used to monitor the currently running compute engine. - FutureWatcher _engineWatcher; + PromiseWatcher _engineWatcher; /// The current status of the display object. PipelineStatus _status; @@ -87,4 +88,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ASYNC_DISPLAY_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/camera/AbstractCameraObject.h ovito-2.9.0+dfsg1/src/core/scene/objects/camera/AbstractCameraObject.h --- ovito-2.8.1+dfsg2/src/core/scene/objects/camera/AbstractCameraObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/camera/AbstractCameraObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ABSTRACT_CAMERA_OBJECT_H -#define __OVITO_ABSTRACT_CAMERA_OBJECT_H +#pragma once + #include #include @@ -63,4 +63,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ABSTRACT_CAMERA_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/camera/CameraObject.cpp ovito-2.9.0+dfsg1/src/core/scene/objects/camera/CameraObject.cpp --- ovito-2.8.1+dfsg2/src/core/scene/objects/camera/CameraObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/camera/CameraObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,19 +30,19 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) OVITO_BEGIN_INLINE_NAMESPACE(StdObj) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, AbstractCameraObject, DataObject); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, CameraObject, AbstractCameraObject); -DEFINE_PROPERTY_FIELD(CameraObject, _isPerspective, "IsPerspective"); -DEFINE_REFERENCE_FIELD(CameraObject, _fov, "FOV", Controller); -DEFINE_REFERENCE_FIELD(CameraObject, _zoom, "Zoom", Controller); -SET_PROPERTY_FIELD_LABEL(CameraObject, _isPerspective, "Perspective projection"); -SET_PROPERTY_FIELD_LABEL(CameraObject, _fov, "FOV angle"); -SET_PROPERTY_FIELD_LABEL(CameraObject, _zoom, "FOV size"); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(CameraObject, _fov, AngleParameterUnit, FloatType(1e-3), FLOATTYPE_PI - FloatType(1e-2)); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CameraObject, _zoom, WorldParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(AbstractCameraObject, DataObject); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CameraObject, AbstractCameraObject); +DEFINE_PROPERTY_FIELD(CameraObject, isPerspective, "IsPerspective"); +DEFINE_REFERENCE_FIELD(CameraObject, fovController, "FOV", Controller); +DEFINE_REFERENCE_FIELD(CameraObject, zoomController, "Zoom", Controller); +SET_PROPERTY_FIELD_LABEL(CameraObject, isPerspective, "Perspective projection"); +SET_PROPERTY_FIELD_LABEL(CameraObject, fovController, "FOV angle"); +SET_PROPERTY_FIELD_LABEL(CameraObject, zoomController, "FOV size"); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(CameraObject, fovController, AngleParameterUnit, FloatType(1e-3), FLOATTYPE_PI - FloatType(1e-2)); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CameraObject, zoomController, WorldParameterUnit, 0); OVITO_BEGIN_INLINE_NAMESPACE(Internal) - IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, CameraDisplayObject, DisplayObject); + IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CameraDisplayObject, DisplayObject); OVITO_END_INLINE_NAMESPACE /****************************************************************************** @@ -50,14 +50,14 @@ ******************************************************************************/ CameraObject::CameraObject(DataSet* dataset) : AbstractCameraObject(dataset), _isPerspective(true) { - INIT_PROPERTY_FIELD(CameraObject::_isPerspective); - INIT_PROPERTY_FIELD(CameraObject::_fov); - INIT_PROPERTY_FIELD(CameraObject::_zoom); - - _fov = ControllerManager::instance().createFloatController(dataset); - _fov->setFloatValue(0, FLOATTYPE_PI/4); - _zoom = ControllerManager::instance().createFloatController(dataset); - _zoom->setFloatValue(0, 200); + INIT_PROPERTY_FIELD(isPerspective); + INIT_PROPERTY_FIELD(fovController); + INIT_PROPERTY_FIELD(zoomController); + + setFovController(ControllerManager::createFloatController(dataset)); + fovController()->setFloatValue(0, FLOATTYPE_PI/4); + setZoomController(ControllerManager::createFloatController(dataset)); + zoomController()->setFloatValue(0, 200); addDisplayObject(new CameraDisplayObject(dataset)); } @@ -68,8 +68,8 @@ TimeInterval CameraObject::objectValidity(TimePoint time) { TimeInterval interval = DataObject::objectValidity(time); - if(isPerspective() && _fov) interval.intersect(_fov->validityInterval(time)); - if(!isPerspective() && _zoom) interval.intersect(_zoom->validityInterval(time)); + if(isPerspective() && fovController()) interval.intersect(fovController()->validityInterval(time)); + if(!isPerspective() && zoomController()) interval.intersect(zoomController()->validityInterval(time)); return interval; } @@ -95,7 +95,7 @@ params.zfar = std::max(params.zfar, params.znear * FloatType(1.01)); // Get the camera angle. - params.fieldOfView = _fov->getFloatValue(time, params.validityInterval); + params.fieldOfView = fovController() ? fovController()->getFloatValue(time, params.validityInterval) : 0; if(params.fieldOfView < FLOATTYPE_EPSILON) params.fieldOfView = FLOATTYPE_EPSILON; if(params.fieldOfView > FLOATTYPE_PI - FLOATTYPE_EPSILON) params.fieldOfView = FLOATTYPE_PI - FLOATTYPE_EPSILON; @@ -112,7 +112,7 @@ } // Get the camera zoom. - params.fieldOfView = _zoom->getFloatValue(time, params.validityInterval); + params.fieldOfView = zoomController() ? zoomController()->getFloatValue(time, params.validityInterval) : 0; if(params.fieldOfView < FLOATTYPE_EPSILON) params.fieldOfView = FLOATTYPE_EPSILON; params.projectionMatrix = Matrix4::ortho(-params.fieldOfView / params.aspectRatio, params.fieldOfView / params.aspectRatio, @@ -127,9 +127,9 @@ FloatType CameraObject::fieldOfView(TimePoint time, TimeInterval& validityInterval) { if(isPerspective()) - return _fov->getFloatValue(time, validityInterval); + return fovController() ? fovController()->getFloatValue(time, validityInterval) : 0; else - return _zoom->getFloatValue(time, validityInterval); + return zoomController() ? zoomController()->getFloatValue(time, validityInterval) : 0; } /****************************************************************************** @@ -137,10 +137,12 @@ ******************************************************************************/ void CameraObject::setFieldOfView(TimePoint time, FloatType newFOV) { - if(isPerspective()) - _fov->setFloatValue(time, newFOV); - else - _zoom->setFloatValue(time, newFOV); + if(isPerspective()) { + if(fovController()) fovController()->setFloatValue(time, newFOV); + } + else { + if(zoomController()) zoomController()->setFloatValue(time, newFOV); + } } /****************************************************************************** @@ -169,7 +171,7 @@ OORef targetObj = new TargetObject(dataset()); OORef targetNode = new ObjectNode(dataset()); targetNode->setDataProvider(targetObj); - targetNode->setName(tr("%1.target").arg(node->name())); + targetNode->setNodeName(tr("%1.target").arg(node->nodeName())); parentNode->addChildNode(targetNode); // Position the new target to match the current orientation of the camera. TimeInterval iv; @@ -207,7 +209,7 @@ } // That's the fixed target distance of a free camera: - return 50.0f; + return FloatType(50); } OVITO_BEGIN_INLINE_NAMESPACE(Internal) @@ -228,7 +230,7 @@ { TimeInterval iv; Point3 cameraPos = Point3::Origin() + contextNode->getWorldTransform(time, iv).translation(); - FloatType size = 1.0f * viewport->nonScalingSize(cameraPos); + FloatType size = viewport->nonScalingSize(cameraPos); Box3 bbox(Point3::Origin(), size); // Add the camera cone to the bounding box. @@ -249,7 +251,7 @@ FloatType aspectRatio = renderSettings->outputImageAspectRatio(); FloatType coneAngle = camera->fieldOfView(time, iv); - FloatType sizeY = tan(0.5f * coneAngle) * targetDistance; + FloatType sizeY = tan(FloatType(0.5) * coneAngle) * targetDistance; FloatType sizeX = sizeY / aspectRatio; bbox.addPoint(Point3(sizeX, sizeY, -targetDistance)); bbox.addPoint(Point3(-sizeX, sizeY, -targetDistance)); @@ -380,7 +382,7 @@ targetLineVertices.push_back(Point3(0,0,-targetDistance)); } if(aspectRatio != 0 && coneAngle != 0) { - FloatType sizeY = tan(0.5f * coneAngle) * targetDistance; + FloatType sizeY = tan(FloatType(0.5) * coneAngle) * targetDistance; FloatType sizeX = sizeY / aspectRatio; targetLineVertices.push_back(Point3::Origin()); targetLineVertices.push_back(Point3(sizeX, sizeY, -targetDistance)); diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/camera/CameraObject.h ovito-2.9.0+dfsg1/src/core/scene/objects/camera/CameraObject.h --- ovito-2.8.1+dfsg2/src/core/scene/objects/camera/CameraObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/camera/CameraObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CAMERA_OBJECT_H -#define __OVITO_CAMERA_OBJECT_H +#pragma once + #include #include @@ -44,18 +44,6 @@ /// \brief Returns the title of this object. virtual QString objectTitle() override { return tr("Camera"); } - /// Returns whether this camera uses a perspective or an orthogonal projection. - bool isPerspective() const { return _isPerspective; } - - /// Sets whether this camera uses a perspective or an orthogonal projection. - void setIsPerspective(bool perspective) { _isPerspective = perspective; } - - /// Returns the controller that controls the field-of-view angle of the camera with perspective projection. - Controller* fovController() const { return _fov; } - - /// Returns the controller that controls the zoom of the camera with orthogonal projection. - Controller* zoomController() const { return _zoom; } - /// Returns whether this camera is a target camera directory at a target object. bool isTargetCamera() const; @@ -91,20 +79,16 @@ private: /// Determines if this camera uses a perspective projection. - PropertyField _isPerspective; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, isPerspective, setIsPerspective); /// This controller stores the field of view of the camera if it uses a perspective projection. - ReferenceField _fov; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, fovController, setFovController); /// This controller stores the field of view of the camera if it uses an orthogonal projection. - ReferenceField _zoom; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, zoomController, setZoomController); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_isPerspective); - DECLARE_REFERENCE_FIELD(_fov); - DECLARE_REFERENCE_FIELD(_zoom); }; OVITO_BEGIN_INLINE_NAMESPACE(Internal) @@ -146,7 +130,7 @@ /// that require updating the geometry buffer. SceneObjectCacheHelper< WeakVersionedOORef, // Camera object + revision number - Color // Display color + Color // Display color > _geometryCacheHelper; /// This helper structure is used to detect any changes in the input data @@ -172,4 +156,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_CAMERA_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/CompoundObject.cpp ovito-2.9.0+dfsg1/src/core/scene/objects/CompoundObject.cpp --- ovito-2.8.1+dfsg2/src/core/scene/objects/CompoundObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/CompoundObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,22 +24,22 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, CompoundObject, DataObject); -DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(CompoundObject, _dataObjects, "SceneObjects", DataObject, PROPERTY_FIELD_ALWAYS_DEEP_COPY); -SET_PROPERTY_FIELD_LABEL(CompoundObject, _dataObjects, "Objects"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CompoundObject, DataObject); +DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(CompoundObject, dataObjects, "SceneObjects", DataObject, PROPERTY_FIELD_ALWAYS_DEEP_COPY); +SET_PROPERTY_FIELD_LABEL(CompoundObject, dataObjects, "Objects"); /****************************************************************************** * Constructs an empty compound data object. ******************************************************************************/ CompoundObject::CompoundObject(DataSet* dataset) : DataObject(dataset) { - INIT_PROPERTY_FIELD(CompoundObject::_dataObjects); + INIT_PROPERTY_FIELD(dataObjects); } /****************************************************************************** * Asks the object for the result of the geometry pipeline at the given time. ******************************************************************************/ -PipelineFlowState CompoundObject::evaluate(TimePoint time) +PipelineFlowState CompoundObject::evaluateImmediately(const PipelineEvalRequest& request) { return PipelineFlowState(PipelineStatus::Success, dataObjects(), TimeInterval::infinite(), attributes()); } @@ -65,7 +65,7 @@ ******************************************************************************/ void CompoundObject::referenceInserted(const PropertyFieldDescriptor& field, RefTarget* newTarget, int listIndex) { - if(field == PROPERTY_FIELD(CompoundObject::_dataObjects)) + if(field == PROPERTY_FIELD(dataObjects)) notifyDependents(ReferenceEvent::SubobjectListChanged); DataObject::referenceInserted(field, newTarget, listIndex); @@ -76,7 +76,7 @@ ******************************************************************************/ void CompoundObject::referenceRemoved(const PropertyFieldDescriptor& field, RefTarget* newTarget, int listIndex) { - if(field == PROPERTY_FIELD(CompoundObject::_dataObjects)) + if(field == PROPERTY_FIELD(dataObjects)) notifyDependents(ReferenceEvent::SubobjectListChanged); DataObject::referenceRemoved(field, newTarget, listIndex); diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/CompoundObject.h ovito-2.9.0+dfsg1/src/core/scene/objects/CompoundObject.h --- ovito-2.8.1+dfsg2/src/core/scene/objects/CompoundObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/CompoundObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COMPOUND_OBJECT_H -#define __OVITO_COMPOUND_OBJECT_H +#pragma once + #include #include @@ -38,11 +38,8 @@ /// Constructs an empty compound data object. Q_INVOKABLE CompoundObject(DataSet* dataset); - /// Asks the object for the result of the modification pipeline at the given time. - virtual PipelineFlowState evaluate(TimePoint time) override; - - /// \brief Returns the list of imported data objects. - const QVector& dataObjects() const { return _dataObjects; } + /// Asks the object for the result of the data pipeline. + virtual PipelineFlowState evaluateImmediately(const PipelineEvalRequest& request) override; /// \brief Inserts a new object into the list of data objects held by this container object. void addDataObject(DataObject* obj) { @@ -132,7 +129,7 @@ private: /// Stores the data objects in the compound. - VectorReferenceField _dataObjects; + DECLARE_VECTOR_REFERENCE_FIELD(DataObject, dataObjects); /// Attributes set or loaded by the file importer which will be fed into the modification pipeline /// along with the data objects. @@ -144,12 +141,10 @@ Q_OBJECT OVITO_OBJECT - - DECLARE_VECTOR_REFERENCE_FIELD(_dataObjects); }; OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_COMPOUND_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/DataObject.cpp ovito-2.9.0+dfsg1/src/core/scene/objects/DataObject.cpp --- ovito-2.8.1+dfsg2/src/core/scene/objects/DataObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/DataObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,19 +27,35 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, DataObject, RefTarget); -DEFINE_PROPERTY_FIELD(DataObject, _saveWithScene, "SaveWithScene"); -DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(DataObject, _displayObjects, "DisplayObjects", DisplayObject, PROPERTY_FIELD_NEVER_CLONE_TARGET); -SET_PROPERTY_FIELD_LABEL(DataObject, _saveWithScene, "Save data with scene"); -SET_PROPERTY_FIELD_LABEL(DataObject, _displayObjects, "Display objects"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(DataObject, RefTarget); +DEFINE_PROPERTY_FIELD(DataObject, saveWithScene, "SaveWithScene"); +DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(DataObject, displayObjects, "DisplayObjects", DisplayObject, PROPERTY_FIELD_NEVER_CLONE_TARGET); +SET_PROPERTY_FIELD_LABEL(DataObject, saveWithScene, "Save data with scene"); +SET_PROPERTY_FIELD_LABEL(DataObject, displayObjects, "Display objects"); /****************************************************************************** * Constructor. ******************************************************************************/ DataObject::DataObject(DataSet* dataset) : RefTarget(dataset), _revisionNumber(0), _saveWithScene(true) { - INIT_PROPERTY_FIELD(DataObject::_saveWithScene); - INIT_PROPERTY_FIELD(DataObject::_displayObjects); + INIT_PROPERTY_FIELD(saveWithScene); + INIT_PROPERTY_FIELD(displayObjects); +} + +/****************************************************************************** +* Asks the object for the result of the data pipeline. +******************************************************************************/ +PipelineFlowState DataObject::evaluateImmediately(const PipelineEvalRequest& request) +{ + return PipelineFlowState(this, objectValidity(request.time())); +} + +/****************************************************************************** +* Asks the object for the result of the data pipeline. +******************************************************************************/ +Future DataObject::evaluateAsync(const PipelineEvalRequest& request) +{ + return Future::createImmediate(PipelineFlowState(this, objectValidity(request.time()))); } /****************************************************************************** @@ -135,17 +151,6 @@ return nodeList; } -/****************************************************************************** -* This function blocks execution until the object is able ready to -* provide data via its evaluate() function. -******************************************************************************/ -bool DataObject::waitUntilReady(TimePoint time, const QString& message, AbstractProgressDisplay* progressDisplay) -{ - return dataset()->container()->waitUntil([this, time]() { - return evaluate(time).status().type() != PipelineStatus::Pending; - }, message, progressDisplay); -} - OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/DataObject.h ovito-2.9.0+dfsg1/src/core/scene/objects/DataObject.h --- ovito-2.8.1+dfsg2/src/core/scene/objects/DataObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/DataObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,14 +19,15 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DATA_OBJECT_H -#define __OVITO_DATA_OBJECT_H +#pragma once + #include #include #include #include #include +#include namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) @@ -49,9 +50,9 @@ /// \return The maximum time interval that contains \a time and during which the object is valid. /// /// When computing the validity interval of the object, an implementation of this method - /// should take validity intervals of all sub-objects and sub-controller into account. + /// should take validity intervals of all sub-objects and sub-controllers into account. /// - /// The default implementation return TimeInterval::infinite(). + /// The default implementation returns TimeInterval::infinite(). virtual TimeInterval objectValidity(TimePoint time) { return TimeInterval::infinite(); } /// \brief This asks the object whether it supports the conversion to another object type. @@ -97,23 +98,19 @@ return static_object_cast(convertTo(T::OOType, time)); } - /// \brief Asks the object for the result of the geometry pipeline at the given time. - /// \param time The animation time at which the geometry pipeline is being evaluated. + /// \brief Asks the object for the result of the data pipeline. + /// If the result is not available immediately, the method can react by returning an incomplete result (pending status). + /// \param request An object that describes when and how the pipeline should be evaluated. /// \return The pipeline flow state generated by this object. /// /// The default implementation just returns the data object itself as the evaluation result. - virtual PipelineFlowState evaluate(TimePoint time) { - return PipelineFlowState(this, objectValidity(time)); - } + virtual PipelineFlowState evaluateImmediately(const PipelineEvalRequest& request); - /// \brief This function blocks execution until the object is able ready to - /// provide data via its evaluate() function. - /// \param time The animation time at which the object should be evaluated. - /// \param message The text to be shown to the user while waiting. - /// \param progressDisplay A progress display/dialog to be used for showing the message. - /// If NULL, the function will show its own progress dialog box. - /// \return true on success; false if the operation has been canceled by the user. - bool waitUntilReady(TimePoint time, const QString& message, AbstractProgressDisplay* progressDisplay = nullptr); + /// \brief Asks the object for the result of the data pipeline. + /// \param request An object that describes when and how the pipeline should be evaluated. + /// + /// The default implementation just returns the data object itself as the evaluation result. + virtual Future evaluateAsync(const PipelineEvalRequest& request); /// \brief Returns a structure that describes the current status of the object. /// @@ -123,10 +120,6 @@ /// An object should generate a ReferenceEvent::ObjectStatusChanged event when its status has changed. virtual PipelineStatus status() const { return PipelineStatus(); } - /// \brief Returns the list of attached display objects that are responsible for rendering this - /// data object. - const QVector& displayObjects() const { return _displayObjects; } - /// \brief Attaches a display object to this scene object that will be responsible for rendering the /// data object. void addDisplayObject(DisplayObject* displayObj) { @@ -139,12 +132,6 @@ _displayObjects.insert(index, displayObj); } - /// \brief Attaches one or more display objects to this scene object that will be responsible for rendering the - /// data object. - void setDisplayObjects(const QVector& displayObjs) { - _displayObjects = displayObjs; - } - /// \brief Removes a display object from this scene object. void removeDisplayObject(int index) { _displayObjects.remove(index); @@ -193,6 +180,9 @@ Q_PROPERTY(bool saveWithScene READ saveWithScene WRITE setSaveWithScene); + /// Controls whether the internal data is saved along with the scene. + PropertyField _saveWithScene; + protected: /// Handles reference events sent by reference targets of this object. @@ -213,22 +203,19 @@ /// Controls whether the internal data is saved along with the scene. /// If false, only metadata will be saved in a state file, while the actual contents will be /// recomputed or restored from an external data source. - PropertyField _saveWithScene; + DECLARE_PROPERTY_FIELD_DESCRIPTOR(saveWithScene); /// The attached display objects that are responsible for rendering this object's data. - VectorReferenceField _displayObjects; + DECLARE_MODIFIABLE_VECTOR_REFERENCE_FIELD(DisplayObject, displayObjects, setDisplayObjects); Q_OBJECT OVITO_OBJECT Q_CLASSINFO("ClassNameAlias", "SceneObject"); // This for backward compatibility with files written by Ovito 2.4 and older. - - DECLARE_PROPERTY_FIELD(_saveWithScene); - DECLARE_VECTOR_REFERENCE_FIELD(_displayObjects); }; OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_DATA_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/DataObjectWithSharedStorage.h ovito-2.9.0+dfsg1/src/core/scene/objects/DataObjectWithSharedStorage.h --- ovito-2.8.1+dfsg2/src/core/scene/objects/DataObjectWithSharedStorage.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/DataObjectWithSharedStorage.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DATA_OBJECT_WITH_SHARED_STORAGE_H -#define __OVITO_DATA_OBJECT_WITH_SHARED_STORAGE_H +#pragma once + #include #include "DataObject.h" @@ -89,4 +89,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_DATA_OBJECT_WITH_SHARED_STORAGE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/DisplayObject.cpp ovito-2.9.0+dfsg1/src/core/scene/objects/DisplayObject.cpp --- ovito-2.8.1+dfsg2/src/core/scene/objects/DisplayObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/DisplayObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,19 +24,21 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, DisplayObject, RefTarget); -DEFINE_PROPERTY_FIELD(DisplayObject, _isEnabled, "IsEnabled"); -SET_PROPERTY_FIELD_LABEL(DisplayObject, _isEnabled, "Enabled"); -DEFINE_PROPERTY_FIELD(DisplayObject, _title, "Name"); -SET_PROPERTY_FIELD_LABEL(DisplayObject, _title, "Name"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(DisplayObject, RefTarget); +DEFINE_PROPERTY_FIELD(DisplayObject, isEnabled, "IsEnabled"); +SET_PROPERTY_FIELD_LABEL(DisplayObject, isEnabled, "Enabled"); +SET_PROPERTY_FIELD_CHANGE_EVENT(DisplayObject, isEnabled, ReferenceEvent::TargetEnabledOrDisabled); +DEFINE_PROPERTY_FIELD(DisplayObject, title, "Name"); +SET_PROPERTY_FIELD_LABEL(DisplayObject, title, "Name"); +SET_PROPERTY_FIELD_CHANGE_EVENT(DisplayObject, title, ReferenceEvent::TitleChanged); /****************************************************************************** * Constructor. ******************************************************************************/ DisplayObject::DisplayObject(DataSet* dataset) : RefTarget(dataset), _isEnabled(true) { - INIT_PROPERTY_FIELD(DisplayObject::_isEnabled); - INIT_PROPERTY_FIELD(DisplayObject::_title); + INIT_PROPERTY_FIELD(isEnabled); + INIT_PROPERTY_FIELD(title); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/DisplayObject.h ovito-2.9.0+dfsg1/src/core/scene/objects/DisplayObject.h --- ovito-2.8.1+dfsg2/src/core/scene/objects/DisplayObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/DisplayObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DISPLAY_OBJECT_H -#define __OVITO_DISPLAY_OBJECT_H +#pragma once + #include #include @@ -86,39 +86,29 @@ /// The default implementation returns \c true. virtual bool showSelectionMarker() { return true; } - /// \brief Returns whether this display object is currently enabled. - bool isEnabled() const { return _isEnabled; } - - /// \brief Enables or disables this display object. - /// \undoable - void setEnabled(bool enabled) { _isEnabled = enabled; } - /// \brief Returns a structure that describes the current status of the display object. virtual PipelineStatus status() const { return PipelineStatus(); } /// \brief Returns the title of this object. virtual QString objectTitle() override { - if(_title.value().isEmpty()) return RefTarget::objectTitle(); - else return _title; + if(title().isEmpty()) return RefTarget::objectTitle(); + else return title(); } /// \brief Changes the title of this object. /// \undoable - void setObjectTitle(const QString& title) { _title = title; } + void setObjectTitle(const QString& title) { setTitle(title); } private: /// Flag that indicates whether the modifier is enabled. - PropertyField _isEnabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, isEnabled, setEnabled); /// The title of this display object. - PropertyField _title; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, title, setTitle); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_isEnabled); - DECLARE_PROPERTY_FIELD(_title); }; /** @@ -158,4 +148,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_DISPLAY_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/geometry/TriMeshDisplay.cpp ovito-2.9.0+dfsg1/src/core/scene/objects/geometry/TriMeshDisplay.cpp --- ovito-2.8.1+dfsg2/src/core/scene/objects/geometry/TriMeshDisplay.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/geometry/TriMeshDisplay.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,12 +26,12 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) OVITO_BEGIN_INLINE_NAMESPACE(StdObj) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, TriMeshDisplay, DisplayObject); -DEFINE_FLAGS_PROPERTY_FIELD(TriMeshDisplay, _color, "Color", PROPERTY_FIELD_MEMORIZE); -DEFINE_REFERENCE_FIELD(TriMeshDisplay, _transparency, "Transparency", Controller); -SET_PROPERTY_FIELD_LABEL(TriMeshDisplay, _color, "Display color"); -SET_PROPERTY_FIELD_LABEL(TriMeshDisplay, _transparency, "Transparency"); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(TriMeshDisplay, _transparency, PercentParameterUnit, 0, 1); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(TriMeshDisplay, DisplayObject); +DEFINE_FLAGS_PROPERTY_FIELD(TriMeshDisplay, color, "Color", PROPERTY_FIELD_MEMORIZE); +DEFINE_REFERENCE_FIELD(TriMeshDisplay, transparencyController, "Transparency", Controller); +SET_PROPERTY_FIELD_LABEL(TriMeshDisplay, color, "Display color"); +SET_PROPERTY_FIELD_LABEL(TriMeshDisplay, transparencyController, "Transparency"); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(TriMeshDisplay, transparencyController, PercentParameterUnit, 0, 1); /****************************************************************************** * Constructor. @@ -39,10 +39,10 @@ TriMeshDisplay::TriMeshDisplay(DataSet* dataset) : DisplayObject(dataset), _color(0.85, 0.85, 1) { - INIT_PROPERTY_FIELD(TriMeshDisplay::_color); - INIT_PROPERTY_FIELD(TriMeshDisplay::_transparency); + INIT_PROPERTY_FIELD(color); + INIT_PROPERTY_FIELD(transparencyController); - _transparency = ControllerManager::instance().createFloatController(dataset); + setTransparencyController(ControllerManager::createFloatController(dataset)); } /****************************************************************************** @@ -72,8 +72,8 @@ FloatType transp = 0; TimeInterval iv; - if(_transparency) transp = _transparency->getFloatValue(time, iv); - ColorA color_mesh(color(), 1.0f - transp); + if(transparencyController()) transp = transparencyController()->getFloatValue(time, iv); + ColorA color_mesh(color(), FloatType(1) - transp); // Do we have to update contents of the geometry buffer? bool updateContents = _geometryCacheHelper.updateState(dataObject, color_mesh) || recreateBuffer; diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/geometry/TriMeshDisplay.h ovito-2.9.0+dfsg1/src/core/scene/objects/geometry/TriMeshDisplay.h --- ovito-2.8.1+dfsg2/src/core/scene/objects/geometry/TriMeshDisplay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/geometry/TriMeshDisplay.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TRIMESH_DISPLAY_H -#define __OVITO_TRIMESH_DISPLAY_H +#pragma once + #include #include @@ -47,25 +47,19 @@ /// \brief Computes the bounding box of the object. virtual Box3 boundingBox(TimePoint time, DataObject* dataObject, ObjectNode* contextNode, const PipelineFlowState& flowState) override; - /// Returns the display color of the mesh. - const Color& color() const { return _color; } - - /// Sets the display color of the mesh. - void setColor(const Color& color) { _color = color; } - /// Returns the transparency parameter. - FloatType transparency() const { return _transparency->currentFloatValue(); } + FloatType transparency() const { return transparencyController()->currentFloatValue(); } /// Sets the transparency parameter. - void setTransparency(FloatType t) { _transparency->setCurrentFloatValue(t); } + void setTransparency(FloatType t) { transparencyController()->setCurrentFloatValue(t); } protected: /// Controls the display color of the mesh. - PropertyField _color; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, color, setColor); /// Controls the transparency of the mesh. - ReferenceField _transparency; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, transparencyController, setTransparencyController); /// The buffered geometry used to render the mesh. std::shared_ptr _buffer; @@ -92,9 +86,6 @@ OVITO_OBJECT Q_CLASSINFO("DisplayName", "Triangle mesh"); - - DECLARE_PROPERTY_FIELD(_color); - DECLARE_REFERENCE_FIELD(_transparency); }; OVITO_END_INLINE_NAMESPACE @@ -102,4 +93,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_TRIMESH_DISPLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/geometry/TriMeshObject.cpp ovito-2.9.0+dfsg1/src/core/scene/objects/geometry/TriMeshObject.cpp --- ovito-2.8.1+dfsg2/src/core/scene/objects/geometry/TriMeshObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/geometry/TriMeshObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) OVITO_BEGIN_INLINE_NAMESPACE(StdObj) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, TriMeshObject, DataObject); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(TriMeshObject, DataObject); /****************************************************************************** * Default constructor. diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/geometry/TriMeshObject.h ovito-2.9.0+dfsg1/src/core/scene/objects/geometry/TriMeshObject.h --- ovito-2.8.1+dfsg2/src/core/scene/objects/geometry/TriMeshObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/geometry/TriMeshObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TRIMESH_OBJECT_H -#define __OVITO_TRIMESH_OBJECT_H +#pragma once + #include #include @@ -81,4 +81,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_TRIMESH_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/helpers/TargetObject.cpp ovito-2.9.0+dfsg1/src/core/scene/objects/helpers/TargetObject.cpp --- ovito-2.8.1+dfsg2/src/core/scene/objects/helpers/TargetObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/helpers/TargetObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,8 +26,8 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) OVITO_BEGIN_INLINE_NAMESPACE(StdObj) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, TargetObject, DataObject); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, TargetDisplayObject, DisplayObject); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(TargetObject, DataObject); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(TargetDisplayObject, DisplayObject); /****************************************************************************** * Constructs a target object. diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/helpers/TargetObject.h ovito-2.9.0+dfsg1/src/core/scene/objects/helpers/TargetObject.h --- ovito-2.8.1+dfsg2/src/core/scene/objects/helpers/TargetObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/helpers/TargetObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TARGET_OBJECT_H -#define __OVITO_TARGET_OBJECT_H +#pragma once + #include #include @@ -97,4 +97,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_TARGET_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/VersionedObjectReference.h ovito-2.9.0+dfsg1/src/core/scene/objects/VersionedObjectReference.h --- ovito-2.8.1+dfsg2/src/core/scene/objects/VersionedObjectReference.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/VersionedObjectReference.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VERSIONED_OBJECT_REFERENCE_H -#define __OVITO_VERSIONED_OBJECT_REFERENCE_H +#pragma once + #include @@ -35,13 +35,13 @@ * * Each C++ instance of a data container class has an internal revision counter that is incremented each time * the object is being modified in some way. This allows to detect changes made to an object without - * looking at the stored data. In particular, it avoid saving a complete copy of the old data to detect changes. + * looking at the stored data. In particular, it avoids saving a complete copy of the old data to detect changes. * * This VersionedOORef smart pointer class stores an ordinary reference-counted pointer (OORef) to a data object and, * in addition, a revision number, which refers to a particular version (or state in time) of that object. * - * Two VersionedOORef instances compare equal only if both the raw C++ pointers match as well as the - * object revision numbers they refer to. + * Two VersionedOORef instances compare equal only if both their object pointers as well as their + * object revision numbers match. */ template class VersionedOORef { @@ -187,4 +187,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_VERSIONED_OBJECT_REFERENCE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/objects/WeakVersionedObjectReference.h ovito-2.9.0+dfsg1/src/core/scene/objects/WeakVersionedObjectReference.h --- ovito-2.8.1+dfsg2/src/core/scene/objects/WeakVersionedObjectReference.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/objects/WeakVersionedObjectReference.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_WEAK_VERSIONED_OBJECT_REFERENCE_H -#define __OVITO_WEAK_VERSIONED_OBJECT_REFERENCE_H +#pragma once + #include @@ -35,13 +35,13 @@ * * Each C++ instance of a data container class has an internal revision counter that is incremented each time * the object is being modified in some way. This allows to detect changes made to an object without - * looking at the stored data. In particular, it avoid saving a complete copy of the old data to detect changes. + * looking at the stored data. In particular, it avoids saving a complete copy of the old data to detect changes. * * The WeakVersionedOORef class stores an ordinary guarded pointer (QPointer) to a data object and, * in addition, a revision number, which refers to a particular version (or state in time) of that object. * - * Two WeakVersionedOORef instances compare equal only if both the raw C++ pointers match as well as the - * object revision numbers they refer to. + * Two WeakVersionedOORef instances compare equal only if both their object pointers as well as their + * object revision numbers match. */ template class WeakVersionedOORef { @@ -187,4 +187,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_WEAK_VERSIONED_OBJECT_REFERENCE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/pipeline/AsyncPipelineEvaluationHelper.cpp ovito-2.9.0+dfsg1/src/core/scene/pipeline/AsyncPipelineEvaluationHelper.cpp --- ovito-2.8.1+dfsg2/src/core/scene/pipeline/AsyncPipelineEvaluationHelper.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/pipeline/AsyncPipelineEvaluationHelper.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,103 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "AsyncPipelineEvaluationHelper.h" + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) + +/****************************************************************************** +* Creates a Future for a pipeline evaluation request. +******************************************************************************/ +Future AsyncPipelineEvaluationHelper::createRequest(DataObject* owner, const PipelineEvalRequest& request) +{ + // Check if there is already an active request pending that is identical. + for(const auto& req : _requests) { + if(req.first == request) + return Future(req.second); + } + + // Check if we can satisfy the request immediately. + if(_requests.empty()) { + const PipelineFlowState& state = owner->evaluateImmediately(request); + if(state.status().type() != PipelineStatus::Pending) + return Future::createImmediate(state); + } + + // Create a new record for this evaluation request. + auto future = Future::createWithPromise(); + _requests.emplace_back(request, future.promise()); + future.promise()->setStarted(); + return future; +} + +/****************************************************************************** +* Checks if the data pipeline evaluation is completed and pending requests +* can be served. +******************************************************************************/ +void AsyncPipelineEvaluationHelper::serveRequests(DataObject* owner) +{ + if(_requests.empty()) return; + Application::instance()->runOnceLater(owner, [this,owner]() { + serveRequestsDeferred(owner); + }); +} + +/****************************************************************************** +* Checks if the data pipeline evaluation is completed and pending requests +* can be served. +******************************************************************************/ +void AsyncPipelineEvaluationHelper::serveRequestsDeferred(DataObject* owner) +{ + while(!_requests.empty()) { + // Sort out canceled requests. + Promise* promise = _requests.front().second.get(); + if(promise->isCanceled()) { + promise->setFinished(); + _requests.erase(_requests.begin()); + continue; + } + + // Check if we can now satisfy the oldest request. + const PipelineFlowState& state = owner->evaluateImmediately(_requests.front().first); + + // The call above might have led to re-entrant call to this function; detect this kind of situation. + if(_requests.empty() || promise != _requests.front().second.get()) + break; + + if(state.status().type() != PipelineStatus::Pending) { + promise->setResult(state); + promise->setFinished(); + OVITO_ASSERT(promise == _requests.front().second.get()); + _requests.erase(_requests.begin()); + } + else { + // Check back again later. + break; + } + } +} + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/scene/pipeline/AsyncPipelineEvaluationHelper.h ovito-2.9.0+dfsg1/src/core/scene/pipeline/AsyncPipelineEvaluationHelper.h --- ovito-2.8.1+dfsg2/src/core/scene/pipeline/AsyncPipelineEvaluationHelper.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/pipeline/AsyncPipelineEvaluationHelper.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include +#include +#include +#include + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) + +/** + * \brief A helper class that manages requests for asynchronous pipeline evaluations + * and the corresponding promises issued by a DataObject. + */ +class OVITO_CORE_EXPORT AsyncPipelineEvaluationHelper +{ +public: + + /// Creates a Future/Promise for a pipeline evaluation request. + Future createRequest(DataObject* owner, const PipelineEvalRequest& request); + + /// Checks if the data pipeline evaluation is completed and pending requests can be served. + void serveRequests(DataObject* owner); + +private: + + /// Checks if the data pipeline evaluation is completed and pending requests can be served. + void serveRequestsDeferred(DataObject* owner); + + /// List of pending pipeline requests and their corresponding promises. + std::vector>> _requests; +}; + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/pipeline/ModifierApplication.cpp ovito-2.9.0+dfsg1/src/core/scene/pipeline/ModifierApplication.cpp --- ovito-2.8.1+dfsg2/src/core/scene/pipeline/ModifierApplication.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/pipeline/ModifierApplication.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,20 +26,20 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, ModifierApplication, RefTarget); -DEFINE_REFERENCE_FIELD(ModifierApplication, _modifier, "Modifier", Modifier); -DEFINE_FLAGS_REFERENCE_FIELD(ModifierApplication, _modifierData, "ModifierData", RefTarget, PROPERTY_FIELD_ALWAYS_CLONE); -SET_PROPERTY_FIELD_LABEL(ModifierApplication, _modifier, "Modifier"); -SET_PROPERTY_FIELD_LABEL(ModifierApplication, _modifierData, "Modifier data"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ModifierApplication, RefTarget); +DEFINE_REFERENCE_FIELD(ModifierApplication, modifier, "Modifier", Modifier); +DEFINE_FLAGS_REFERENCE_FIELD(ModifierApplication, modifierData, "ModifierData", RefTarget, PROPERTY_FIELD_ALWAYS_CLONE); +SET_PROPERTY_FIELD_LABEL(ModifierApplication, modifier, "Modifier"); +SET_PROPERTY_FIELD_LABEL(ModifierApplication, modifierData, "Modifier data"); /****************************************************************************** * Constructor. ******************************************************************************/ ModifierApplication::ModifierApplication(DataSet* dataset, Modifier* mod) : RefTarget(dataset) { - INIT_PROPERTY_FIELD(ModifierApplication::_modifier); - INIT_PROPERTY_FIELD(ModifierApplication::_modifierData); - _modifier = mod; + INIT_PROPERTY_FIELD(modifier); + INIT_PROPERTY_FIELD(modifierData); + setModifier(mod); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/core/scene/pipeline/ModifierApplication.h ovito-2.9.0+dfsg1/src/core/scene/pipeline/ModifierApplication.h --- ovito-2.8.1+dfsg2/src/core/scene/pipeline/ModifierApplication.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/pipeline/ModifierApplication.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_MODIFIER_APPLICATION_H -#define __OVITO_MODIFIER_APPLICATION_H +#pragma once + #include #include "Modifier.h" @@ -49,11 +49,6 @@ /// \param modifier The modifier that is going to be inserted into a modification pipeline. Q_INVOKABLE ModifierApplication(DataSet* dataset, Modifier* modifier = nullptr); - /// \brief Returns the Modifier, which is connected by this ModifierApplication to a specific - /// modification pipeline. - /// \return The modifier instance. - Modifier* modifier() const { return _modifier; } - /// \brief Returns the modification pipeline the Modifier managed by this ModifierApplication is part of. /// \return The PipelineObject this ModifierApplication is referenced by. PipelineObject* pipelineObject() const; @@ -63,16 +58,6 @@ /// ModifierApplication. QSet objectNodes() const; - /// \brief Returns the data managed by the modifier, which has been set via setModifierData(). - /// \return The data object previously set by the modifier. - RefTarget* modifierData() const { return _modifierData; } - - /// \brief Sets or replaces the data object used by the modifier. - /// \param data A subclass of RefTarget, created and managed by the Modifier. - /// - /// Modifiers can use this method to store pipeline-specific data. - void setModifierData(RefTarget* data) { _modifierData = data; } - protected: /// \brief Is called when a RefTarget referenced by this object has generated an event. @@ -86,20 +71,17 @@ private: /// The modifier that is inserted into the pipeline. - ReferenceField _modifier; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Modifier, modifier, setModifier); /// Optional data managed by the modifier. - ReferenceField _modifierData; + DECLARE_MODIFIABLE_REFERENCE_FIELD(RefTarget, modifierData, setModifierData); Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_modifier); - DECLARE_REFERENCE_FIELD(_modifierData); }; OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_MODIFIER_APPLICATION_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/pipeline/Modifier.cpp ovito-2.9.0+dfsg1/src/core/scene/pipeline/Modifier.cpp --- ovito-2.8.1+dfsg2/src/core/scene/pipeline/Modifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/pipeline/Modifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,23 +23,26 @@ #include #include #include +#include #include namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, Modifier, RefTarget); -DEFINE_PROPERTY_FIELD(Modifier, _isEnabled, "IsEnabled"); -SET_PROPERTY_FIELD_LABEL(Modifier, _isEnabled, "Enabled"); -DEFINE_PROPERTY_FIELD(Modifier, _title, "Name"); -SET_PROPERTY_FIELD_LABEL(Modifier, _title, "Name"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Modifier, RefTarget); +DEFINE_PROPERTY_FIELD(Modifier, isEnabled, "IsEnabled"); +SET_PROPERTY_FIELD_LABEL(Modifier, isEnabled, "Enabled"); +SET_PROPERTY_FIELD_CHANGE_EVENT(Modifier, isEnabled, ReferenceEvent::TargetEnabledOrDisabled); +DEFINE_PROPERTY_FIELD(Modifier, title, "Name"); +SET_PROPERTY_FIELD_LABEL(Modifier, title, "Name"); +SET_PROPERTY_FIELD_CHANGE_EVENT(Modifier, title, ReferenceEvent::TitleChanged); /****************************************************************************** * Constructor. ******************************************************************************/ Modifier::Modifier(DataSet* dataset) : RefTarget(dataset), _isEnabled(true) { - INIT_PROPERTY_FIELD(Modifier::_isEnabled); - INIT_PROPERTY_FIELD(Modifier::_title); + INIT_PROPERTY_FIELD(isEnabled); + INIT_PROPERTY_FIELD(title); } /****************************************************************************** @@ -62,15 +65,14 @@ * Note: This method might return empty result objects in some cases when the modifier stack * cannot be evaluated because of an invalid modifier. ******************************************************************************/ -QVector> Modifier::getModifierInputs() const +QVector> Modifier::getModifierInputs(TimePoint time) const { - TimePoint time = dataset()->animationSettings()->time(); QVector> results; for(RefMaker* dependent : dependents()) { ModifierApplication* modApp = dynamic_object_cast(dependent); if(modApp != nullptr && modApp->modifier() == this) { if(PipelineObject* pipelineObj = modApp->pipelineObject()) - results.push_back(qMakePair(modApp, pipelineObj->evaluatePipeline(time, modApp, false))); + results.push_back(qMakePair(modApp, pipelineObj->evaluateImmediately(PipelineEvalRequest(time, false, modApp, false)))); } } @@ -84,9 +86,10 @@ ******************************************************************************/ PipelineFlowState Modifier::getModifierInput(ModifierApplication* modApp) const { + TimePoint time = dataset()->animationSettings()->time(); if(modApp != nullptr && modApp->modifier() == this) { if(PipelineObject* pipelineObj = modApp->pipelineObject()) { - return pipelineObj->evaluatePipeline(dataset()->animationSettings()->time(), modApp, false); + return pipelineObj->evaluateImmediately(PipelineEvalRequest(time, false, modApp, false)); } } else { @@ -94,7 +97,7 @@ ModifierApplication* modApp = dynamic_object_cast(dependent); if(modApp != nullptr && modApp->modifier() == this) { if(PipelineObject* pipelineObj = modApp->pipelineObject()) { - return pipelineObj->evaluatePipeline(dataset()->animationSettings()->time(), modApp, false); + return pipelineObj->evaluateImmediately(PipelineEvalRequest(time, false, modApp, false)); } } } diff -Nru ovito-2.8.1+dfsg2/src/core/scene/pipeline/Modifier.h ovito-2.9.0+dfsg1/src/core/scene/pipeline/Modifier.h --- ovito-2.8.1+dfsg2/src/core/scene/pipeline/Modifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/pipeline/Modifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_MODIFIER_H -#define __OVITO_MODIFIER_H +#pragma once + #include #include @@ -101,15 +101,15 @@ /// \brief Returns the input object of this modifier for each application of the modifier. /// \param time The animation for which the geometry pipelines should be evaluated. - /// \return A container that contains for each application of this modifier the - /// state of the geometry pipeline evaluation up to the modifier's application. + /// \return A list of applications of this modifier and the corresponding + /// computed state of the data pipeline up to the modifier's application. /// - /// This method evaluates the geometry pipeline up this modifier. It can be used to work with + /// This method evaluates the data pipeline up this modifier. It can be used to work with /// the input objects outside of a normal call to modifyObject(). /// /// \note This method might return empty result objects in some cases when the modifier stack /// cannot be evaluated because of an invalid modifier. - QVector> getModifierInputs() const; + QVector> getModifierInputs(TimePoint time) const; /// \brief Returns the input object of the modifier assuming that it has been applied only in a single geometry pipeline. /// \return The object that comes out of the geometry pipeline when it is evaluated up the application of this modifier. @@ -121,20 +121,6 @@ /// This method can be used to work with the input object outside of a normal call to modifyObject(). PipelineFlowState getModifierInput(ModifierApplication* modApp = nullptr) const; - /// \brief Returns whether this modifier is currently enabled. - /// \return \c true if it is currently enabled, i.e. applied. - /// \c false if it is disabled and skipped in the geometry pipeline. - bool isEnabled() const { return _isEnabled; } - - /// \brief Enables or disables this modifier. - /// \param enabled Controls the state of the modifier. - /// - /// A disabled modifier is skipped in the geometry pipeline - /// and is not applied to the input object. - /// - /// \undoable - void setEnabled(bool enabled) { _isEnabled = enabled; } - /// \brief Asks the modifier whether it can be applied to the given input data. /// \param input The pipeline state at the point of the pipeline where the modifier is going to be inserted. /// \return true if the modifier can operate on the provided input data; false otherwise. @@ -144,13 +130,13 @@ /// \brief Returns the title of this modifier object. virtual QString objectTitle() override { - if(_title.value().isEmpty()) return RefTarget::objectTitle(); - else return _title; + if(title().isEmpty()) return RefTarget::objectTitle(); + else return title(); } /// \brief Changes the title of this modifier. /// \undoable - void setObjectTitle(const QString& title) { _title = title; } + void setObjectTitle(const QString& title) { setTitle(title); } protected: @@ -174,17 +160,14 @@ private: /// Flag that indicates whether the modifier is enabled. - PropertyField _isEnabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, isEnabled, setEnabled); /// The user-defined title of this modifier. - PropertyField _title; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, title, setTitle); Q_OBJECT OVITO_OBJECT - DECLARE_PROPERTY_FIELD(_isEnabled); - DECLARE_PROPERTY_FIELD(_title); - friend class PipelineObject; }; @@ -195,4 +178,4 @@ Q_DECLARE_METATYPE(Ovito::Modifier*); Q_DECLARE_TYPEINFO(Ovito::Modifier*, Q_MOVABLE_TYPE); -#endif // __OVITO_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/pipeline/PipelineEvalRequest.h ovito-2.9.0+dfsg1/src/core/scene/pipeline/PipelineEvalRequest.h --- ovito-2.8.1+dfsg2/src/core/scene/pipeline/PipelineEvalRequest.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/pipeline/PipelineEvalRequest.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,80 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) + +/** + * \brief Describes when and how the data pipeline should be evaluated. + */ +class OVITO_CORE_EXPORT PipelineEvalRequest +{ +public: + + /// \brief Constructor + explicit PipelineEvalRequest(TimePoint time, bool prepareDisplayObjects, ModifierApplication* upToThisModifier = nullptr, bool includeLastModifier = false) : + _time(time), _prepareDisplayObjects(prepareDisplayObjects), _upToThisModifier(upToThisModifier), _includeLastModifier(includeLastModifier) {} + + /// Returns the animation time at which the pipeline shoud be evaluated. + TimePoint time() const { return _time; } + + /// Indicates whether display objects should be prepared for rendering. + bool prepareDisplayObjects() const { return _prepareDisplayObjects; } + + /// Indicates whether the pipeline should be evaluated only up to a certain modifier. + ModifierApplication* upToThisModifier() const { return _upToThisModifier; } + + /// If a partial pipeline evaluation up to a certain modifier is requested, then this indicates whether + /// that modifier should be included in the results. + bool includeLastModifier() const { return _includeLastModifier; } + + /// Compares two requests for equality. + bool operator==(const PipelineEvalRequest& other) const { + return (time() == other.time() && prepareDisplayObjects() == other.prepareDisplayObjects() && + upToThisModifier() == other.upToThisModifier() && includeLastModifier() == other.includeLastModifier()); + } + +private: + + /// The animation time at which the pipeline shoud be evaluated. + TimePoint _time; + + /// Indicates whether display objects should be prepared for rendering. + bool _prepareDisplayObjects; + + /// Used to indicate that the pipeline should be evaluated only up to this modifier. + ModifierApplication* _upToThisModifier; + + /// When requesting a partial pipeline evaluation, indicates whether the last modifier + /// should be included in the result. + bool _includeLastModifier; +}; + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/pipeline/PipelineFlowState.h ovito-2.9.0+dfsg1/src/core/scene/pipeline/PipelineFlowState.h --- ovito-2.8.1+dfsg2/src/core/scene/pipeline/PipelineFlowState.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/pipeline/PipelineFlowState.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PIPELINE_FLOW_STATE_H -#define __OVITO_PIPELINE_FLOW_STATE_H +#pragma once + #include #include @@ -172,4 +172,4 @@ #include -#endif // __OVITO_PIPELINE_FLOW_STATE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/pipeline/PipelineObject.cpp ovito-2.9.0+dfsg1/src/core/scene/pipeline/PipelineObject.cpp --- ovito-2.8.1+dfsg2/src/core/scene/pipeline/PipelineObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/pipeline/PipelineObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -21,34 +21,30 @@ #include #include +#include #include namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, PipelineObject, DataObject); -DEFINE_REFERENCE_FIELD(PipelineObject, _sourceObject, "InputObject", DataObject); -DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(PipelineObject, _modApps, "ModifierApplications", ModifierApplication, PROPERTY_FIELD_ALWAYS_CLONE); -SET_PROPERTY_FIELD_LABEL(PipelineObject, _sourceObject, "Input"); -SET_PROPERTY_FIELD_LABEL(PipelineObject, _modApps, "Modifier Applications"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(PipelineObject, DataObject); +DEFINE_REFERENCE_FIELD(PipelineObject, sourceObject, "InputObject", DataObject); +DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(PipelineObject, modifierApplications, "ModifierApplications", ModifierApplication, PROPERTY_FIELD_ALWAYS_CLONE); +SET_PROPERTY_FIELD_LABEL(PipelineObject, sourceObject, "Input"); +SET_PROPERTY_FIELD_LABEL(PipelineObject, modifierApplications, "Modifier Applications"); /****************************************************************************** * Default constructor. ******************************************************************************/ PipelineObject::PipelineObject(DataSet* dataset) : DataObject(dataset), _cachedIndex(-1) { - INIT_PROPERTY_FIELD(PipelineObject::_sourceObject); - INIT_PROPERTY_FIELD(PipelineObject::_modApps); + INIT_PROPERTY_FIELD(sourceObject); + INIT_PROPERTY_FIELD(modifierApplications); } /****************************************************************************** -* Asks the object for the result of the geometry pipeline at the given time -* up to a given point in the modifier stack. -* If upToHere is NULL then the complete modifier stack will be evaluated. -* Otherwise only the modifiers in the pipeline before the given point will be -* applied to the input object. The 'include' parameter specifies whether the -* last modifier given by 'upToHere' will be applied. +* Asks the object for the results of the data pipeline. ******************************************************************************/ -PipelineFlowState PipelineObject::evaluatePipeline(TimePoint time, ModifierApplication* upToHere, bool including) +PipelineFlowState PipelineObject::evaluateImmediately(const PipelineEvalRequest& request) { // Prevent the recoding of transient operations while evaluating the pipeline. UndoSuspender undoSuspender(dataset()->undoStack()); @@ -59,15 +55,18 @@ // Determine the position in the pipeline up to which it should be evaluated. int upToHereIndex; - if(upToHere != nullptr) { - upToHereIndex = modifierApplications().indexOf(upToHere); - OVITO_ASSERT(upToHereIndex != -1); - if(including) upToHereIndex++; + if(request.upToThisModifier() != nullptr) { + upToHereIndex = modifierApplications().indexOf(request.upToThisModifier()); + if(upToHereIndex == -1) + upToHereIndex = modifierApplications().size(); + else if(request.includeLastModifier()) + upToHereIndex++; } else upToHereIndex = modifierApplications().size(); + OVITO_ASSERT(upToHereIndex >= 0 && upToHereIndex <= modifierApplications().size()); // Receive the input data from the source object. - PipelineFlowState inputState = sourceObject()->evaluate(time); + PipelineFlowState inputState = sourceObject()->evaluateImmediately(request); // Determine the modifier from which on to evaluate the pipeline. int fromHereIndex = 0; @@ -76,8 +75,8 @@ // Use the cached results if possible. // First check if the cache is filled. if(_cachedIndex >= 0 && _cachedIndex <= upToHereIndex && - _cachedState.stateValidity().contains(time) && - _lastInput.stateValidity().contains(time)) { + _cachedState.stateValidity().contains(request.time()) && + _lastInput.stateValidity().contains(request.time())) { // Check if there have been any changes in the input data // since the cache has been filled. @@ -106,7 +105,7 @@ // Flag that indicates whether the output of the pipeline is considered incomplete. bool isPending = (flowState.status().type() == PipelineStatus::Pending); - + // Apply the modifiers one by one. for(int stackIndex = fromHereIndex; stackIndex < upToHereIndex; stackIndex++) { @@ -124,16 +123,16 @@ if(mod->isEnabled() == false) continue; - // Save current flow state in cache at this point of the pipeline - // if the next modifier is changing frequently (because it is currently being edited). - if(mod->modifierValidity(time).isEmpty()) { + // Save the current flow state at this point of the pipeline in the cache + // if the next modifier is changing frequently (because of it being currently edited). + if(mod->modifierValidity(request.time()).isEmpty()) { _cachedState = flowState; _cachedState.updateRevisionNumbers(); _cachedIndex = stackIndex; } // Apply modifier. - PipelineStatus modifierStatus = mod->modifyObject(time, app, flowState); + PipelineStatus modifierStatus = mod->modifyObject(request.time(), app, flowState); if(modifierStatus.type() == PipelineStatus::Pending) isPending = true; else if(isPending) @@ -147,7 +146,7 @@ // Make sure the revision information in the output is up to date. flowState.updateRevisionNumbers(); - // Cache the pipeline output (if not already cached an intermediate state of the pipeline). + // Cache the pipeline output (if not already done for an intermediate state of the pipeline). if(_cachedIndex < 0 && flowState.isEmpty() == false) { _cachedState = flowState; _cachedIndex = upToHereIndex; @@ -177,7 +176,7 @@ { OVITO_ASSERT(index >= 0 && index <= modifierApplications().size()); OVITO_CHECK_OBJECT_POINTER(modApp); - _modApps.insert(index, modApp); + _modifierApplications.insert(index, modApp); if(modApp->modifier()) modApp->modifier()->initializeModifier(this, modApp); @@ -190,7 +189,7 @@ { OVITO_ASSERT(index >= 0 && index < modifierApplications().size()); OVITO_ASSERT(modifierApplications()[index]->pipelineObject() == this); - _modApps.remove(index); + _modifierApplications.remove(index); } /****************************************************************************** @@ -214,7 +213,7 @@ event->type() == ReferenceEvent::PendingStateChanged) { // If one of the modifiers has changed, then all subsequent // modifiers in the pipeline need to be informed (unless it's from a disabled modifier). - int index = _modApps.indexOf(source); + int index = _modifierApplications.indexOf(source); if(index != -1) { Modifier* mod = modifierApplications()[index]->modifier(); if(mod && mod->isEnabled()) @@ -224,12 +223,11 @@ else if(event->type() == ReferenceEvent::TargetEnabledOrDisabled) { // If one of the modifiers gets enabled/disabled, then all subsequent // modifiers in the pipeline need to be informed. - int index = _modApps.indexOf(source); + int index = _modifierApplications.indexOf(source); if(index != -1) { modifierChanged(index); // We also consider this a change of the modification pipeline itself. notifyDependents(ReferenceEvent::TargetChanged); - notifyDependents(ReferenceEvent::PendingStateChanged); } } } @@ -244,7 +242,7 @@ { // If a new modifier has been inserted into the pipeline, then all // following modifiers need to be informed. - if(field == PROPERTY_FIELD(PipelineObject::_modApps)) { + if(field == PROPERTY_FIELD(modifierApplications)) { // Also inform the new modifier itself that its input has changed // because it is being inserted into a pipeline. @@ -254,8 +252,6 @@ // Inform all subsequent modifiers that their input has changed. modifierChanged(listIndex); - // A change to the pipeline may potentially result in a change of the pending status. - notifyDependents(ReferenceEvent::PendingStateChanged); } DataObject::referenceInserted(field, newTarget, listIndex); } @@ -266,12 +262,10 @@ ******************************************************************************/ void PipelineObject::referenceRemoved(const PropertyFieldDescriptor& field, RefTarget* oldTarget, int listIndex) { - if(field == PROPERTY_FIELD(PipelineObject::_modApps)) { + if(field == PROPERTY_FIELD(modifierApplications)) { // If a modifier is being removed from the pipeline, then all // modifiers following it need to be informed. modifierChanged(listIndex - 1); - // A change to the pipeline may potentially result in a change of the pending status. - notifyDependents(ReferenceEvent::PendingStateChanged); } DataObject::referenceRemoved(field, oldTarget, listIndex); } @@ -281,7 +275,7 @@ ******************************************************************************/ void PipelineObject::referenceReplaced(const PropertyFieldDescriptor& field, RefTarget* oldTarget, RefTarget* newTarget) { - if(field == PROPERTY_FIELD(PipelineObject::_sourceObject)) { + if(field == PROPERTY_FIELD(sourceObject)) { // Invalidate cache if input object has been replaced. modifierChanged(-1); } @@ -315,6 +309,20 @@ if(app && app->modifier()) app->modifier()->upstreamPipelineChanged(app); } + + // A change in the pipeline may affect the status of the pipeline results. + notifyDependents(ReferenceEvent::PendingStateChanged); +} + +/****************************************************************************** +* Sends an event to all dependents of this RefTarget. +******************************************************************************/ +void PipelineObject::notifyDependents(ReferenceEvent& event) +{ + if(event.type() == ReferenceEvent::PendingStateChanged) + _evaluationRequestHelper.serveRequests(this); + + DataObject::notifyDependents(event); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/core/scene/pipeline/PipelineObject.h ovito-2.9.0+dfsg1/src/core/scene/pipeline/PipelineObject.h --- ovito-2.8.1+dfsg2/src/core/scene/pipeline/PipelineObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/pipeline/PipelineObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,11 +19,14 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PIPELINE_OBJECT_H -#define __OVITO_PIPELINE_OBJECT_H +#pragma once + #include #include +#include +#include +#include #include "ModifierApplication.h" namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) @@ -39,29 +42,6 @@ /// \brief Constructor that creates an empty pipeline. Q_INVOKABLE PipelineObject(DataSet* dataset); - /// \brief Asks the object for the result of the geometry pipeline at the given time - /// up to a given point in the modifier stack. - /// \param time The animation at which the geometry pipeline should be evaluated. - /// \param upToHere If \a upToHere is \c NULL then the complete modifier stack will be evaluated. - /// Otherwise only the modifiers in the pipeline before the given point will be applied to the - /// input object. \a upToHere must be one of the application objects returned by modifierApplications(). - /// \param including Specifies whether the last modifier given by \a upToHere will also be applied to the input object. - /// \return The result object. - PipelineFlowState evaluatePipeline(TimePoint time, ModifierApplication* upToHere, bool including); - - /// \brief Returns the object that provides the input data for this pipeline. - DataObject* sourceObject() const { return _sourceObject; } - - /// \brief Replaces the object that provides the input data for this pipeline. - /// \param sourceObject The new source object. - /// \undoable - void setSourceObject(DataObject* sourceObject) { _sourceObject = sourceObject; } - - /// \brief Returns the list of modifier applications. - /// \return The list of applications of modifiers that make up the data flow pipeline. - /// The modifiers in this list are applied to the input object in ascending order. - const QVector& modifierApplications() const { return _modApps; } - /// \brief Inserts a modifier into the data flow pipeline. /// \param modifier The modifier to be inserted. /// \param index Specifies the position in the pipeline where the modifier should be inserted. @@ -88,9 +68,21 @@ /////////////////////////////////////// from DataObject ///////////////////////////////////////// - /// Asks the object for the result of the geometry pipeline at the given time. - virtual PipelineFlowState evaluate(TimePoint time) override { - return evaluatePipeline(time, nullptr, true); + /// Asks the object for the result of the data pipeline. + virtual PipelineFlowState evaluateImmediately(const PipelineEvalRequest& request) override; + + /// Asks the object for the result of the data pipeline. + virtual Future evaluateAsync(const PipelineEvalRequest& request) override { + return _evaluationRequestHelper.createRequest(this, request); + } + + /// Sends an event to all dependents of this RefTarget. + virtual void notifyDependents(ReferenceEvent& event) override; + + /// \brief Sends an event to all dependents of this RefTarget. + /// \param eventType The event type passed to the ReferenceEvent constructor. + inline void notifyDependents(ReferenceEvent::Type eventType) { + DataObject::notifyDependents(eventType); } protected: @@ -113,34 +105,40 @@ /// Notifies all modifiers starting at the given index that their input has changed. void modifierChanged(int changedIndex); + /// Asks the object for the result of the geometry pipeline at the given time + /// up to a given point in the modifier stack. The result may be incomplete (i.e. status pending) + /// if the results are not immediately available. + PipelineFlowState evaluatePipeline(TimePoint time, int upToHereIndex); + private: /// The object providing the input data that is processed by the modifiers. - ReferenceField _sourceObject; + DECLARE_MODIFIABLE_REFERENCE_FIELD(DataObject, sourceObject, setSourceObject); /// The ordered list of modifiers that are applied to the input object. /// The modifiers are applied to the input object in the reverse order of this list. - VectorReferenceField _modApps; + DECLARE_VECTOR_REFERENCE_FIELD(ModifierApplication, modifierApplications); /// The state of the input object from the last evaluation of the pipeline. + /// This is used to detect changes in the input that require recalculation of the pipeline. PipelineFlowState _lastInput; /// The cached results from the last pipeline evaluation. PipelineFlowState _cachedState; /// Indicates which pipeline stage has been stored in the cache. - /// If the cache is empty, then this is -1. + /// If the cache is empty, then this is set to -1. int _cachedIndex; + /// Manages pending asynchronous pipeline requests. + AsyncPipelineEvaluationHelper _evaluationRequestHelper; + Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_sourceObject); - DECLARE_VECTOR_REFERENCE_FIELD(_modApps); }; OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_PIPELINE_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/pipeline/PipelineStatus.h ovito-2.9.0+dfsg1/src/core/scene/pipeline/PipelineStatus.h --- ovito-2.8.1+dfsg2/src/core/scene/pipeline/PipelineStatus.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/pipeline/PipelineStatus.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PIPELINE_STATUS_H -#define __OVITO_PIPELINE_STATUS_H +#pragma once + #include @@ -128,4 +128,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_PIPELINE_STATUS_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/SceneNode.cpp ovito-2.9.0+dfsg1/src/core/scene/SceneNode.cpp --- ovito-2.8.1+dfsg2/src/core/scene/SceneNode.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/SceneNode.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -32,17 +32,18 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, SceneNode, RefTarget); -DEFINE_FLAGS_REFERENCE_FIELD(SceneNode, _transformation, "Transform", Controller, PROPERTY_FIELD_ALWAYS_DEEP_COPY); -DEFINE_FLAGS_REFERENCE_FIELD(SceneNode, _lookatTargetNode, "TargetNode", SceneNode, PROPERTY_FIELD_ALWAYS_CLONE | PROPERTY_FIELD_NO_SUB_ANIM); -DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(SceneNode, _children, "Children", SceneNode, PROPERTY_FIELD_ALWAYS_CLONE | PROPERTY_FIELD_NO_SUB_ANIM); -DEFINE_PROPERTY_FIELD(SceneNode, _nodeName, "NodeName"); -DEFINE_PROPERTY_FIELD(SceneNode, _displayColor, "DisplayColor"); -SET_PROPERTY_FIELD_LABEL(SceneNode, _transformation, "Transformation"); -SET_PROPERTY_FIELD_LABEL(SceneNode, _lookatTargetNode, "Target"); -SET_PROPERTY_FIELD_LABEL(SceneNode, _children, "Children"); -SET_PROPERTY_FIELD_LABEL(SceneNode, _nodeName, "Name"); -SET_PROPERTY_FIELD_LABEL(SceneNode, _displayColor, "Display color"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SceneNode, RefTarget); +DEFINE_FLAGS_REFERENCE_FIELD(SceneNode, transformationController, "Transform", Controller, PROPERTY_FIELD_ALWAYS_DEEP_COPY); +DEFINE_FLAGS_REFERENCE_FIELD(SceneNode, lookatTargetNode, "TargetNode", SceneNode, PROPERTY_FIELD_ALWAYS_CLONE | PROPERTY_FIELD_NO_SUB_ANIM); +DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(SceneNode, children, "Children", SceneNode, PROPERTY_FIELD_ALWAYS_CLONE | PROPERTY_FIELD_NO_SUB_ANIM); +DEFINE_PROPERTY_FIELD(SceneNode, nodeName, "NodeName"); +DEFINE_PROPERTY_FIELD(SceneNode, displayColor, "DisplayColor"); +SET_PROPERTY_FIELD_LABEL(SceneNode, transformationController, "Transformation"); +SET_PROPERTY_FIELD_LABEL(SceneNode, lookatTargetNode, "Target"); +SET_PROPERTY_FIELD_LABEL(SceneNode, children, "Children"); +SET_PROPERTY_FIELD_LABEL(SceneNode, nodeName, "Name"); +SET_PROPERTY_FIELD_LABEL(SceneNode, displayColor, "Display color"); +SET_PROPERTY_FIELD_CHANGE_EVENT(SceneNode, nodeName, ReferenceEvent::TitleChanged); /****************************************************************************** * Default constructor. @@ -50,18 +51,18 @@ SceneNode::SceneNode(DataSet* dataset) : RefTarget(dataset), _parentNode(nullptr), _worldTransform(AffineTransformation::Identity()), _worldTransformValidity(TimeInterval::empty()), _worldBBTime(TimeNegativeInfinity()), _displayColor(0,0,0) { - INIT_PROPERTY_FIELD(SceneNode::_transformation); - INIT_PROPERTY_FIELD(SceneNode::_lookatTargetNode); - INIT_PROPERTY_FIELD(SceneNode::_children); - INIT_PROPERTY_FIELD(SceneNode::_nodeName); - INIT_PROPERTY_FIELD(SceneNode::_displayColor); + INIT_PROPERTY_FIELD(transformationController); + INIT_PROPERTY_FIELD(lookatTargetNode); + INIT_PROPERTY_FIELD(children); + INIT_PROPERTY_FIELD(nodeName); + INIT_PROPERTY_FIELD(displayColor); // Assign random color to node. static std::default_random_engine rng; - _displayColor = Color::fromHSV(std::uniform_real_distribution()(rng), 1, 1); + setDisplayColor(Color::fromHSV(std::uniform_real_distribution()(rng), 1, 1)); // Create a transformation controller for the node. - _transformation = ControllerManager::instance().createTransformationController(dataset); + setTransformationController(ControllerManager::createTransformationController(dataset)); } /****************************************************************************** @@ -169,7 +170,7 @@ prs->rotationController()->getRotationValue(time, rotation, iv); // Reset to default rotation controller. - OORef controller = ControllerManager::instance().createRotationController(dataset()); + OORef controller = ControllerManager::createRotationController(dataset()); controller->setRotationValue(time, rotation, true); prs->setRotationController(controller); } @@ -217,7 +218,7 @@ ******************************************************************************/ void SceneNode::referenceReplaced(const PropertyFieldDescriptor& field, RefTarget* oldTarget, RefTarget* newTarget) { - if(field == PROPERTY_FIELD(SceneNode::_transformation)) { + if(field == PROPERTY_FIELD(transformationController)) { // TM controller has changed -> rebuild world tm cache. invalidateWorldTransformation(); } @@ -229,7 +230,7 @@ ******************************************************************************/ void SceneNode::referenceInserted(const PropertyFieldDescriptor& field, RefTarget* newTarget, int listIndex) { - if(field == PROPERTY_FIELD(SceneNode::_children)) { + if(field == PROPERTY_FIELD(children)) { // A new child node has been added. SceneNode* child = static_object_cast(newTarget); OVITO_CHECK_OBJECT_POINTER(child); @@ -247,7 +248,7 @@ ******************************************************************************/ void SceneNode::referenceRemoved(const PropertyFieldDescriptor& field, RefTarget* oldTarget, int listIndex) { - if(field == PROPERTY_FIELD(SceneNode::_children)) { + if(field == PROPERTY_FIELD(children)) { // A child node has been removed. SceneNode* child = static_object_cast(oldTarget); OVITO_ASSERT(child->parentNode() == this); diff -Nru ovito-2.8.1+dfsg2/src/core/scene/SceneNode.h ovito-2.9.0+dfsg1/src/core/scene/SceneNode.h --- ovito-2.8.1+dfsg2/src/core/scene/SceneNode.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/SceneNode.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SCENE_NODE_H -#define __OVITO_SCENE_NODE_H +#pragma once + #include #include @@ -45,14 +45,6 @@ public: - /// \brief Returns the controller that controls this node's local transformation matrix. - /// \return The transformation controller. - Controller* transformationController() const { return _transformation; } - - /// \brief Sets the controller that controls this node's local transformation. - /// \param ctrl The new transformation controller. - void setTransformationController(Controller* ctrl) { _transformation = ctrl; } - /// \brief Returns this node's world transformation matrix. /// \param[in] time The animation for which the transformation matrix should be computed. /// \param[in,out] validityInterval The validity interval of the returned transformation matrix. @@ -72,24 +64,6 @@ /// does not contain the transformation of the parent node. AffineTransformation getLocalTransform(TimePoint time, TimeInterval& validityInterval); - /// \brief Gets the node's display name. - /// \return A string given by the user to this node. - const QString& name() const { return _nodeName; } - - /// \brief Sets the node's display name. - /// \param name The new name to be given to the node. - /// \undoable - void setName(const QString& name) { _nodeName = name; } - - /// \brief Gets the display color of the node. - /// \return This color is used to render the node in viewports. - const Color& displayColor() const { return _displayColor; } - - /// \brief Sets the display color of the node. - /// \param color The new color to be used to render the node in the viewports. - /// \undoable - void setDisplayColor(const Color& color) { _displayColor = color; } - /// \brief Returns the parent node of this node in the scene tree graph. /// \return This node's parent node or \c NULL if this is the root node. SceneNode* parentNode() const { return _parentNode; } @@ -136,11 +110,6 @@ /// \sa children(), insertChildNode(), addChildNode() void removeChildNode(int index); - /// \brief Returns the array of child nodes. - /// \return A vector that contains all children of this scene node. - /// \sa addChildNode(), removeChildNode() - const QVector& children() const { return _children; } - /// \brief Recursively visits all nodes below this parent node /// and invokes the given visitor function for every node. /// @@ -183,11 +152,6 @@ return true; } - /// \brief Returns the target node this scene node is looking at. - /// \return The target this node's rotation controller is bound to or \c NULL if this scene node - /// has not been bound to a target via a call to bindToTarget(). - SceneNode* lookatTargetNode() const { return _lookatTargetNode; } - /// \brief Binds this scene node to a target node and creates a LookAtController /// that lets this scene node look at the target. /// \param targetNode The target to look at or \c NULL to unbind the node from its old target. @@ -221,12 +185,23 @@ bool isSelected() const; /// \brief Returns whether this is the root scene node. - /// \return \c true if this is the root node of the scene, i.e. parentNode() returns \c NULL; - /// \c false if this a node with a parent. + /// \return \c true if this is the root node of the scene. /// /// \sa DataSet::sceneRoot() /// \sa parentNode() - bool isRootNode() const { return parentNode() == nullptr; } + virtual bool isRootNode() const { return false; } + + /// \brief Returns whether this node is part of a scene. + /// \return \c true if the node has a root node. + bool isInScene() const { + const SceneNode* n = this; + do { + if(n->isRootNode()) return true; + n = n->parentNode(); + } + while(n != nullptr); + return false; + } /// \brief Returns the title of this object. virtual QString objectTitle() override { return _nodeName; } @@ -268,7 +243,7 @@ SceneNode* _parentNode; /// Transformation matrix controller. - ReferenceField _transformation; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, transformationController, setTransformationController); /// This node's cached world transformation matrix. /// It contains the transformation of the parent node. @@ -279,17 +254,17 @@ TimeInterval _worldTransformValidity; /// The name of this scene node. - PropertyField _nodeName; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, nodeName, setNodeName); /// The display color of the node. - PropertyField _displayColor; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, displayColor, setDisplayColor); /// Stores the target node this scene node is bound to using a look /// at controller or null if this scene node is not bound to a target node. - ReferenceField _lookatTargetNode; + DECLARE_REFERENCE_FIELD(SceneNode, lookatTargetNode); /// Contains all child nodes. - VectorReferenceField _children; + DECLARE_VECTOR_REFERENCE_FIELD(SceneNode, children); /// The cached world bounding box of this node. Box3 _worldBB; @@ -302,12 +277,6 @@ Q_OBJECT OVITO_OBJECT - DECLARE_REFERENCE_FIELD(_transformation); - DECLARE_REFERENCE_FIELD(_lookatTargetNode); - DECLARE_VECTOR_REFERENCE_FIELD(_children); - DECLARE_PROPERTY_FIELD(_nodeName); - DECLARE_PROPERTY_FIELD(_displayColor); - friend class SceneRoot; }; @@ -315,4 +284,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_SCENE_NODE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/SceneRoot.cpp ovito-2.9.0+dfsg1/src/core/scene/SceneRoot.cpp --- ovito-2.8.1+dfsg2/src/core/scene/SceneRoot.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/SceneRoot.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,14 +24,14 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, SceneRoot, SceneNode); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SceneRoot, SceneNode); /****************************************************************************** * Default constructor. ******************************************************************************/ SceneRoot::SceneRoot(DataSet* dataset) : SceneNode(dataset) { - setName("Scene"); + setNodeName("Scene"); // The root node does not need a transformation controller. setTransformationController(nullptr); @@ -44,7 +44,7 @@ { SceneNode* result = nullptr; visitChildren([nodeName, &result](SceneNode* node) -> bool { - if(node->name() == nodeName) { + if(node->nodeName() == nodeName) { result = node; return false; } diff -Nru ovito-2.8.1+dfsg2/src/core/scene/SceneRoot.h ovito-2.9.0+dfsg1/src/core/scene/SceneRoot.h --- ovito-2.8.1+dfsg2/src/core/scene/SceneRoot.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/SceneRoot.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SCENEROOT_H -#define __OVITO_SCENEROOT_H +#pragma once + #include #include @@ -53,6 +53,9 @@ /// \return An world axis-aligned box that contains the bounding boxes of all child nodes. virtual Box3 localBoundingBox(TimePoint time) override; + /// \brief Returns whether this is the root scene node. + virtual bool isRootNode() const override { return true; } + private: Q_OBJECT @@ -63,4 +66,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_SCENEROOT_H + diff -Nru ovito-2.8.1+dfsg2/src/core/scene/SelectionSet.cpp ovito-2.9.0+dfsg1/src/core/scene/SelectionSet.cpp --- ovito-2.8.1+dfsg2/src/core/scene/SelectionSet.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/SelectionSet.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,16 +24,16 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, SelectionSet, RefTarget); -DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(SelectionSet, _selection, "SelectedNodes", SceneNode, PROPERTY_FIELD_NEVER_CLONE_TARGET); -SET_PROPERTY_FIELD_LABEL(SelectionSet, _selection, "Nodes"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SelectionSet, RefTarget); +DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(SelectionSet, selection, "SelectedNodes", SceneNode, PROPERTY_FIELD_NEVER_CLONE_TARGET); +SET_PROPERTY_FIELD_LABEL(SelectionSet, selection, "Nodes"); /****************************************************************************** * Default constructor. ******************************************************************************/ SelectionSet::SelectionSet(DataSet* dataset) : RefTarget(dataset), _selectionChangeInProgress(false) { - INIT_PROPERTY_FIELD(SelectionSet::_selection); + INIT_PROPERTY_FIELD(selection); } /****************************************************************************** @@ -120,7 +120,7 @@ ******************************************************************************/ void SelectionSet::referenceInserted(const PropertyFieldDescriptor& field, RefTarget* newTarget, int listIndex) { - if(field == PROPERTY_FIELD(SelectionSet::_selection)) { + if(field == PROPERTY_FIELD(selection)) { Q_EMIT selectionChanged(this); if(!_selectionChangeInProgress) { _selectionChangeInProgress = true; @@ -135,7 +135,7 @@ ******************************************************************************/ void SelectionSet::referenceRemoved(const PropertyFieldDescriptor& field, RefTarget* oldTarget, int listIndex) { - if(field == PROPERTY_FIELD(SelectionSet::_selection)) { + if(field == PROPERTY_FIELD(selection)) { Q_EMIT selectionChanged(this); if(!_selectionChangeInProgress) { _selectionChangeInProgress = true; diff -Nru ovito-2.8.1+dfsg2/src/core/scene/SelectionSet.h ovito-2.9.0+dfsg1/src/core/scene/SelectionSet.h --- ovito-2.8.1+dfsg2/src/core/scene/SelectionSet.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/scene/SelectionSet.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SELECTION_SET_H -#define __OVITO_SELECTION_SET_H +#pragma once + #include #include @@ -154,19 +154,17 @@ private: /// Holds the references to the selected scene nodes. - VectorReferenceField _selection; + DECLARE_VECTOR_REFERENCE_FIELD(SceneNode, selection); /// Indicates that there is a pending change event in the event queue. bool _selectionChangeInProgress; Q_OBJECT OVITO_OBJECT - - DECLARE_VECTOR_REFERENCE_FIELD(_selection); }; OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_SELECTION_SET_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/BoundedPriorityQueue.h ovito-2.9.0+dfsg1/src/core/utilities/BoundedPriorityQueue.h --- ovito-2.8.1+dfsg2/src/core/utilities/BoundedPriorityQueue.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/BoundedPriorityQueue.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::BoundedPriorityQueue class template. */ -#ifndef __OVITO_BOUNDED_PRIORITY_QUEUE_H -#define __OVITO_BOUNDED_PRIORITY_QUEUE_H +#pragma once + #include @@ -127,8 +127,8 @@ Compare _comp; }; -OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_BOUNDED_PRIORITY_QUEUE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/Color.h ovito-2.9.0+dfsg1/src/core/utilities/Color.h --- ovito-2.8.1+dfsg2/src/core/utilities/Color.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/Color.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definitions of the Ovito::ColorT and Ovito::ColorAT class templates. */ -#ifndef __OVITO_COLOR_H -#define __OVITO_COLOR_H +#pragma once + #include #include @@ -610,4 +610,4 @@ Q_DECLARE_TYPEINFO(Ovito::Color*, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::ColorA*, Q_PRIMITIVE_TYPE); -#endif // __OVITO_COLOR_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/concurrent/Future.cpp ovito-2.9.0+dfsg1/src/core/utilities/concurrent/Future.cpp --- ovito-2.8.1+dfsg2/src/core/utilities/concurrent/Future.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/concurrent/Future.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,438 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (2013) Alexander Stukowski -// -// This file is part of OVITO (Open Visualization Tool). -// -// OVITO is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// OVITO is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -/////////////////////////////////////////////////////////////////////////////// - -#include -#include "FutureWatcher.h" -#include "FutureInterface.h" -#include "Future.h" -#include "Task.h" -#include "moc_FutureWatcher.cpp" - -namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) - -enum { - MaxProgressEmitsPerSecond = 20 -}; - -FutureInterfaceBase::~FutureInterfaceBase() -{ -} - -void FutureInterfaceBase::cancel() -{ - QMutexLocker locker(&_mutex); - - if(_subTask) { - _subTask->cancel(); - } - - if(isCanceled()) { - return; - } - - _state = State(_state | Canceled); - _waitCondition.wakeAll(); - sendCallOut(FutureWatcher::CallOutEvent::Canceled); -} - -bool FutureInterfaceBase::reportStarted() -{ - QMutexLocker locker(&_mutex); - if(isStarted()) - return false; // It's already started. Don't run it again. - OVITO_ASSERT(!isFinished() || isRunning()); - _state = State(Started | Running); - sendCallOut(FutureWatcher::CallOutEvent::Started); - return true; -} - -void FutureInterfaceBase::reportFinished() -{ - QMutexLocker locker(&_mutex); - OVITO_ASSERT(isStarted()); - if(!isFinished()) { - _state = State((_state & ~Running) | Finished); - _waitCondition.wakeAll(); - sendCallOut(FutureWatcher::CallOutEvent::Finished); - } -} - -void FutureInterfaceBase::reportException() -{ - QMutexLocker locker(&_mutex); - if(isCanceled() || isFinished()) - return; - - reportException(std::current_exception()); -} - -void FutureInterfaceBase::reportException(std::exception_ptr ex) -{ - _exceptionStore = ex; - _state = State(_state | ResultSet); - _waitCondition.wakeAll(); - sendCallOut(FutureWatcher::CallOutEvent::ResultReady); -} - -void FutureInterfaceBase::reportResultReady() -{ - if(isCanceled() || isFinished()) - return; - - _state = State(_state | ResultSet); - _waitCondition.wakeAll(); - sendCallOut(FutureWatcher::CallOutEvent::ResultReady); -} - -void FutureInterfaceBase::waitForResult() -{ - throwPossibleException(); - - QMutexLocker lock(&_mutex); - if(!isRunning() && isStarted()) - return; - - lock.unlock(); - - // To avoid deadlocks and reduce the number of threads used, try to - // run the runnable in the current thread. - tryToRunImmediately(); - - lock.relock(); - if(!isRunning() && isStarted()) - return; - - while(isRunning() && isResultSet() == false) - _waitCondition.wait(&_mutex); - - throwPossibleException(); -} - -void FutureInterfaceBase::waitForFinished() -{ - QMutexLocker lock(&_mutex); - const bool alreadyFinished = !isRunning() && isStarted(); - lock.unlock(); - - if(!alreadyFinished) { - tryToRunImmediately(); - lock.relock(); - while(isRunning() || !isStarted()) - _waitCondition.wait(&_mutex); - } - - throwPossibleException(); -} - -void FutureInterfaceBase::registerWatcher(FutureWatcher* watcher) -{ - QMutexLocker locker(&_mutex); - - if(isStarted()) - watcher->postCallOutEvent(FutureWatcher::CallOutEvent::Started, this); - - if(isResultSet()) - watcher->postCallOutEvent(FutureWatcher::CallOutEvent::ResultReady, this); - - if(isCanceled()) - watcher->postCallOutEvent(FutureWatcher::CallOutEvent::Canceled, this); - - if(isFinished()) - watcher->postCallOutEvent(FutureWatcher::CallOutEvent::Finished, this); - - _watchers.push_back(watcher); -} - -void FutureInterfaceBase::unregisterWatcher(FutureWatcher* watcher) -{ - QMutexLocker locker(&_mutex); - _watchers.removeOne(watcher); -} - -bool FutureInterfaceBase::waitForSubTask(const std::shared_ptr& subTask) -{ - QMutexLocker locker(&_mutex); - if(this->isCanceled()) { - subTask->cancel(); - return false; - } - if(subTask->isCanceled()) { - locker.unlock(); - this->cancel(); - return false; - } - this->_subTask = subTask.get(); - locker.unlock(); - try { -#if 0 - subTask->waitForFinished(); -#else - QMutexLocker subtaskLock(&subTask->_mutex); - const bool subTaskAlreadyFinished = !subTask->isRunning() && subTask->isStarted(); - subtaskLock.unlock(); - - if(!subTaskAlreadyFinished) { - subTask->tryToRunImmediately(); - subtaskLock.relock(); - while(!subTask->isCanceled() && (subTask->isRunning() || !subTask->isStarted())) - subTask->_waitCondition.wait(&subTask->_mutex); - } - - subTask->throwPossibleException(); -#endif - } - catch(...) { - locker.relock(); - this->_subTask = nullptr; - throw; - } - locker.relock(); - this->_subTask = nullptr; - locker.unlock(); - if(subTask->isCanceled()) { - this->cancel(); - return false; - } - return true; -} - -void FutureInterfaceBase::setProgressRange(int maximum) -{ - QMutexLocker locker(&_mutex); - - if(maximum == _progressMaximum || isCanceled() || isFinished()) - return; - - _progressMaximum = maximum; - computeTotalProgress(); - sendCallOut(FutureWatcher::CallOutEvent::ProgressRange, maximum); -} - -bool FutureInterfaceBase::setProgressValue(int value) -{ - QMutexLocker locker(&_mutex); - _intermittentUpdateCounter = 0; - - if(value == _progressValue || isCanceled() || isFinished()) - return !isCanceled(); - - _progressValue = value; - computeTotalProgress(); - - if(!_progressTime.isValid() || _progressValue == _progressMaximum || _progressTime.elapsed() >= (1000 / MaxProgressEmitsPerSecond)) { - _progressTime.start(); - sendCallOut(FutureWatcher::CallOutEvent::ProgressValue, progressValue()); - } - - return !isCanceled(); -} - -bool FutureInterfaceBase::setProgressValueIntermittent(int progressValue, int updateEvery) -{ - if(_intermittentUpdateCounter == 0 || _intermittentUpdateCounter > updateEvery) { - setProgressValue(progressValue); - } - _intermittentUpdateCounter++; - return !isCanceled(); -} - -bool FutureInterfaceBase::incrementProgressValue(int increment) -{ - QMutexLocker locker(&_mutex); - - if(isCanceled() || isFinished()) - return !isCanceled(); - - _progressValue += increment; - computeTotalProgress(); - - if(!_progressTime.isValid() || _progressValue == _progressMaximum || _progressTime.elapsed() >= (1000 / MaxProgressEmitsPerSecond)) { - _progressTime.start(); - sendCallOut(FutureWatcher::CallOutEvent::ProgressValue, progressValue()); - } - - return !isCanceled(); -} - -void FutureInterfaceBase::computeTotalProgress() -{ - if(subStepsStack.empty()) { - _totalProgressMaximum = _progressMaximum; - _totalProgressValue = _progressValue; - } - else { - double percentage; - if(_progressMaximum > 0) - percentage = (double)_progressValue / _progressMaximum; - else - percentage = 0.0; - for(auto level = subStepsStack.crbegin(); level != subStepsStack.crend(); ++level) { - OVITO_ASSERT(level->first >= 0 && level->first < level->second.size()); - int weightSum1 = std::accumulate(level->second.cbegin(), level->second.cbegin() + level->first, 0); - int weightSum2 = std::accumulate(level->second.cbegin() + level->first, level->second.cend(), 0); - percentage = ((double)weightSum1 + percentage * level->second[level->first]) / (weightSum1 + weightSum2); - } - _totalProgressMaximum = 1000; - _totalProgressValue = int(percentage * 1000.0); - } -} - -void FutureInterfaceBase::beginProgressSubSteps(std::vector weights) -{ - QMutexLocker locker(&_mutex); - OVITO_ASSERT(std::accumulate(weights.cbegin(), weights.cend(), 0) > 0); - subStepsStack.push_back(std::make_pair(0, std::move(weights))); - _progressMaximum = 0; - _progressValue = 0; - computeTotalProgress(); -} - -void FutureInterfaceBase::nextProgressSubStep() -{ - QMutexLocker locker(&_mutex); - OVITO_ASSERT(!subStepsStack.empty()); - OVITO_ASSERT(subStepsStack.back().first < subStepsStack.back().second.size() - 1); - subStepsStack.back().first++; - _progressMaximum = 0; - _progressValue = 0; - computeTotalProgress(); -} - -void FutureInterfaceBase::endProgressSubSteps() -{ - QMutexLocker locker(&_mutex); - OVITO_ASSERT(!subStepsStack.empty()); - subStepsStack.pop_back(); - _progressMaximum = 0; - _progressValue = 0; - computeTotalProgress(); -} - -void FutureInterfaceBase::setProgressText(const QString& progressText) -{ - QMutexLocker locker(&_mutex); - - if(isCanceled() || isFinished()) - return; - - _progressText = progressText; - sendCallOut(FutureWatcher::CallOutEvent::ProgressText, progressText); -} - -void FutureWatcher::setFutureInterface(const std::shared_ptr& futureInterface, bool pendingAssignment) -{ - if(futureInterface == _futureInterface) - return; - - if(_futureInterface) { - _futureInterface->unregisterWatcher(this); - if(pendingAssignment) { - _finished = false; - QCoreApplication::removePostedEvents(this); - } - } - _futureInterface = futureInterface; - if(_futureInterface) - _futureInterface->registerWatcher(this); -} - -void FutureWatcher::customEvent(QEvent* event) -{ - if(_futureInterface) { - OVITO_ASSERT(static_cast(event)->_source == _futureInterface.get()); - if(event->type() == (QEvent::Type)CallOutEvent::Started) - Q_EMIT started(); - else if(event->type() == (QEvent::Type)CallOutEvent::Finished) { - _finished = true; - Q_EMIT finished(); - } - else if(event->type() == (QEvent::Type)CallOutEvent::Canceled) - Q_EMIT canceled(); - else if(event->type() == (QEvent::Type)CallOutEvent::ResultReady) { - if(!_futureInterface->isCanceled()) { - Q_EMIT resultReady(); - } - } - else if(event->type() == (QEvent::Type)CallOutEvent::ProgressValue) { - if(!_futureInterface->isCanceled()) - Q_EMIT progressValueChanged(static_cast(event)->_value); - } - else if(event->type() == (QEvent::Type)CallOutEvent::ProgressText) { - if(!_futureInterface->isCanceled()) - Q_EMIT progressTextChanged(static_cast(event)->_text); - } - else if(event->type() == (QEvent::Type)CallOutEvent::ProgressRange) { - Q_EMIT progressRangeChanged(static_cast(event)->_value); - } - } - QObject::customEvent(event); -} - -void FutureWatcher::cancel() -{ - if(_futureInterface) - _futureInterface->cancel(); -} - -bool FutureWatcher::isCanceled() const -{ - return _futureInterface->isCanceled(); -} - -bool FutureWatcher::isFinished() const -{ - return _finished; -} - -int FutureWatcher::progressMaximum() const -{ - return _futureInterface->progressMaximum(); -} - -int FutureWatcher::progressValue() const -{ - return _futureInterface->progressValue(); -} - -int FutureWatcher::totalProgressMaximum() const -{ - return _futureInterface->totalProgressMaximum(); -} - -int FutureWatcher::totalProgressValue() const -{ - return _futureInterface->totalProgressValue(); -} - -QString FutureWatcher::progressText() const -{ - return _futureInterface->progressText(); -} - -void FutureWatcher::waitForFinished() const -{ - if(_futureInterface) - _futureInterface->waitForFinished(); -} - -OVITO_END_INLINE_NAMESPACE -OVITO_END_INLINE_NAMESPACE -} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/concurrent/Future.h ovito-2.9.0+dfsg1/src/core/utilities/concurrent/Future.h --- ovito-2.8.1+dfsg2/src/core/utilities/concurrent/Future.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/concurrent/Future.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,118 +19,205 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FUTURE_H -#define __OVITO_FUTURE_H +#pragma once + #include -#include "FutureInterface.h" +#include "Promise.h" namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) -class FutureBase { +/****************************************************************************** +* Generic base class for futures, which implements the basic state management, +* progress reporting, and event processing. +******************************************************************************/ +class FutureBase +{ public: - bool isCanceled() const { return getinterface()->isCanceled(); } - bool isFinished() const { return getinterface()->isFinished(); } + /// Returns true if the Promise associated with this Future has been canceled. + bool isCanceled() const { return promise()->isCanceled(); } + + /// Returns true if the Promise associated with this Future has been completed. + bool isFinished() const { return promise()->isFinished(); } + + /// Cancels the Promise associated with this Future. + void cancel() { promise()->cancel(); } - void cancel() { getinterface()->cancel(); } + /// Blocks execution until the Promise associated with this future has been completed. void waitForFinished() const { - getinterface()->waitForFinished(); + promise()->waitForFinished(); } - bool isValid() const { return (bool)_interface; } - void reset() { _interface.reset(); } - int progressValue() const { return getinterface()->progressValue(); } - int progressMaximum() const { return getinterface()->progressMaximum(); } - int totalProgressValue() const { return getinterface()->totalProgressValue(); } - int totalProgressMaximum() const { return getinterface()->totalProgressMaximum(); } - QString progressText() const { return getinterface()->progressText(); } + /// Returns true if this Future is associated with a valid Promise. + bool isValid() const { return (bool)_promise; } + + /// Dissociates this Future from its Promise. + void reset() { _promise.reset(); } + + /// Returns the Promise associated with this Future. + /// Make sure it has a Promise before calling this function. + const PromiseBasePtr& promise() const { + OVITO_ASSERT(isValid()); + return _promise; + } protected: + /// Default constructor, which creates a Future with a Promise. FutureBase() {} - explicit FutureBase(const std::shared_ptr& p) : _interface(p) {} + /// Constructor that creates a Future associated with a Promise. + explicit FutureBase(const PromiseBasePtr& p) : _promise(p) {} - std::shared_ptr& getinterface() { - OVITO_ASSERT(isValid()); - return _interface; - } - const std::shared_ptr& getinterface() const { - OVITO_ASSERT(isValid()); - return _interface; - } - std::shared_ptr _interface; + /// The Promise associated with this Future. + PromiseBasePtr _promise; template friend class Task; - template friend class FutureInterface; - friend class FutureInterfaceBase; - friend class FutureWatcher; + template friend class Promise; + friend class PromiseBase; + friend class PromiseWatcher; friend class TaskManager; }; +/****************************************************************************** +* A future that provides access to the value computed by a Promise. +******************************************************************************/ template -class Future : public FutureBase { +class Future : public FutureBase +{ public: - typedef FutureInterface Interface; + typedef Promise PromiseType; + typedef PromisePtr PromisePtrType; + /// Default constructor that coonstructs an invalid Future that is not associated with any Promise. Future() {} - explicit Future(const std::shared_ptr& p) : FutureBase(p) {} + /// Constructor that constructs a Future that is associated with the given Promise. + explicit Future(const PromisePtrType& p) : FutureBase(p) {} - /// Create a Future with immediate results. - static Future createImmediate(const R& result, const QString& text = QString()) { - auto iface = std::make_shared(); - iface->reportStarted(); - if(text.isEmpty() == false) - iface->setProgressText(text); - iface->setResult(result); - iface->reportFinished(); - return Future(iface); + /// Creates a new Future and its associated Promise. The Promise is not started yet. + static Future createWithPromise() { + return Future(std::make_shared()); + } + + /// Creates an already completed Future with a result value that is immediately available. + static Future createImmediate(const R& result, const QString& statusText = QString()) { + auto promise = std::make_shared(); + promise->setStarted(); + if(statusText.isEmpty() == false) + promise->setProgressText(statusText); + promise->setResult(result); + promise->setFinished(); + return Future(promise); + } + + /// Creates an already completed Future with a result value that is immediately available. + static Future createImmediate(R&& result, const QString& statusText = QString()) { + auto promise = std::make_shared(); + promise->setStarted(); + if(statusText.isEmpty() == false) + promise->setProgressText(statusText); + promise->setResult(std::move(result)); + promise->setFinished(); + return Future(promise); } - /// Create a Future with a thrown exception. + /// Creates a completed Future that is in the 'exception' state. static Future createFailed(const Exception& ex) { - auto iface = std::make_shared(); - iface->reportStarted(); - iface->reportException(std::make_exception_ptr(ex)); - iface->reportFinished(); - return Future(iface); + auto promise = std::make_shared(); + promise->setStarted(); + promise->setException(std::make_exception_ptr(ex)); + promise->setFinished(); + return Future(promise); } - /// Create a Future without results that is in the canceled state. + /// Creates a Future without results that is in the canceled state. static Future createCanceled() { - auto iface = std::make_shared(); - iface->reportStarted(); - iface->cancel(); - iface->reportFinished(); - return Future(iface); + auto promise = std::make_shared(); + promise->setStarted(); + promise->cancel(); + promise->setFinished(); + return Future(promise); } + /// Returns the results computed by the associated Promise. + /// Blocks execution until the results become available. + /// Throws an exception if an error occurred while the promise was computing + /// the results, or if the promise has been canceled. const R& result() const { - getinterface()->waitForResult(); - return static_cast*>(getinterface().get())->_result; + promise()->waitForResult(); + return static_cast*>(promise().get())->_result; + } + + /// Returns the Promise associated with this Future. + /// Make sure it has a Promise before calling this function. + PromisePtrType promise() const { + return std::static_pointer_cast(FutureBase::promise()); } }; +/****************************************************************************** +* A future without a result. +******************************************************************************/ template<> -class Future : public FutureBase { +class Future : public FutureBase +{ public: + typedef Promise PromiseType; + typedef PromisePtr PromisePtrType; + + /// Default constructor that coonstructs an invalid Future that is not associated with any Promise. Future() {} - explicit Future(const std::shared_ptr>& p) : FutureBase(p) {} + /// Constructor that constructs a Future that is associated with the given Promise. + explicit Future(const PromisePtrType& p) : FutureBase(p) {} + + /// Creates a new Future and its associated Promise. The Promise is not started yet. + static Future createWithPromise() { + return Future(std::make_shared()); + } + + /// Creates a Future that is already complete. + static Future createImmediate(const QString& statusText = QString()) { + auto promise = std::make_shared(); + promise->setStarted(); + if(statusText.isEmpty() == false) + promise->setProgressText(statusText); + promise->setFinished(); + return Future(promise); + } + + /// Create a Future without results that is in the canceled state. + static Future createCanceled() { + auto promise = std::make_shared(); + promise->setStarted(); + promise->cancel(); + promise->setFinished(); + return Future(promise); + } + + /// Blocks execution until the Promise associated with this Future has finished. + /// Throws an exception if an error occurred while the promise was running or if the promise has been canceled. void result() const { - getinterface()->waitForResult(); + promise()->waitForResult(); + } + + /// Returns the Promise associated with this Future. + /// Make sure it has a Promise before calling this function. + PromisePtrType promise() const { + return std::static_pointer_cast(FutureBase::promise()); } }; -inline void FutureWatcher::setFuture(const FutureBase& future) +/// Part of PromiseWatcher implementation. +inline void PromiseWatcher::setFuture(const FutureBase& future) { - setFutureInterface(future.getinterface()); + setPromise(future.promise()); } OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_BACKGROUND_OPERATION_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/concurrent/FutureInterface.h ovito-2.9.0+dfsg1/src/core/utilities/concurrent/FutureInterface.h --- ovito-2.8.1+dfsg2/src/core/utilities/concurrent/FutureInterface.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/concurrent/FutureInterface.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,204 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (2013) Alexander Stukowski -// -// This file is part of OVITO (Open Visualization Tool). -// -// OVITO is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// OVITO is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef __OVITO_FUTURE_INTERFACE_H -#define __OVITO_FUTURE_INTERFACE_H - -#include -#include "FutureWatcher.h" - -#include -#include -#include -#include - -namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) - -template class Future; // Defined in Future.h - -class OVITO_CORE_EXPORT FutureInterfaceBase -{ -public: - - enum State { - NoState = 0, - Running = (1<<0), - Started = (1<<1), - Canceled = (1<<2), - Finished = (1<<3), - ResultSet = (1<<4) - }; - - virtual ~FutureInterfaceBase(); - - bool isCanceled() const { return (_state & Canceled); } - int progressMaximum() const { return _progressMaximum; } - int totalProgressMaximum() const { return _totalProgressMaximum; } - int progressValue() const { return _progressValue; } - int totalProgressValue() const { return _totalProgressValue; } - QString progressText() const { return _progressText; } - - void setProgressRange(int maximum); - bool setProgressValue(int progressValue); - bool setProgressValueIntermittent(int progressValue, int updateEvery = 2000); - bool incrementProgressValue(int increment = 1); - void setProgressText(const QString& progressText); - void beginProgressSubSteps(std::vector weights); - void beginProgressSubSteps(int numSteps) { beginProgressSubSteps(std::vector(numSteps, 1)); } - void nextProgressSubStep(); - void endProgressSubSteps(); - - template - bool waitForSubTask(Future& subFuture) { - return waitForSubTask(subFuture.getinterface()); - } - bool waitForSubTask(const std::shared_ptr& subTask); - - virtual void cancel(); - - bool reportStarted(); - - void reportFinished(); - - void reportException(); - void reportException(std::exception_ptr ex); - - void waitForFinished(); - -protected: - - FutureInterfaceBase(State initialState = NoState) : - _subTask(nullptr), _state(initialState), _progressValue(0), _progressMaximum(0), - _totalProgressValue(0), _totalProgressMaximum(0), _intermittentUpdateCounter(0) { -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - _progressTime.invalidate(); -#endif - } - - bool isRunning() const { return (_state & Running); } - bool isStarted() const { return (_state & Started); } - bool isFinished() const { return (_state & Finished); } - bool isResultSet() const { return (_state & ResultSet); } - - void reportResultReady(); - - void reportCanceled() { - cancel(); - } - - void throwPossibleException() { - if(_exceptionStore) - std::rethrow_exception(_exceptionStore); - } - - void waitForResult(); - - void sendCallOut(FutureWatcher::CallOutEvent::CallOutType type) { - Q_FOREACH(FutureWatcher* watcher, _watchers) - watcher->postCallOutEvent(type, this); - } - - void sendCallOut(FutureWatcher::CallOutEvent::CallOutType type, int value) { - Q_FOREACH(FutureWatcher* watcher, _watchers) - watcher->postCallOutEvent(type, value, this); - } - - void sendCallOut(FutureWatcher::CallOutEvent::CallOutType type, const QString& text) { - Q_FOREACH(FutureWatcher* watcher, _watchers) - watcher->postCallOutEvent(type, text, this); - } - - void registerWatcher(FutureWatcher* watcher); - void unregisterWatcher(FutureWatcher* watcher); - - void computeTotalProgress(); - - virtual void tryToRunImmediately() {} - - FutureInterfaceBase* _subTask; - QList _watchers; - QMutex _mutex; - State _state; - QWaitCondition _waitCondition; - std::exception_ptr _exceptionStore; - int _totalProgressValue; - int _totalProgressMaximum; - int _progressValue; - int _progressMaximum; - int _intermittentUpdateCounter; - QString _progressText; - QElapsedTimer _progressTime; - std::vector>> subStepsStack; - - friend class FutureWatcher; - friend class TaskManager; - friend class FutureBase; - template friend class Future; -}; - -template -class FutureInterface : public FutureInterfaceBase -{ -public: - - FutureInterface() {} - - void setResult(const R& value) { - QMutexLocker locker(&_mutex); - if(isCanceled() || isFinished()) - return; - _result = value; - _state = State(_state | ResultSet); - reportResultReady(); - } - - void setResult(R&& value) { - QMutexLocker locker(&_mutex); - if(isCanceled() || isFinished()) - return; - _result = std::move(value); - _state = State(_state | ResultSet); - reportResultReady(); - } - -private: - - R _result; - - template friend class Task; - template friend class Future; -}; - -template<> -class FutureInterface : public FutureInterfaceBase -{ -public: - FutureInterface() {} - - template friend class Task; - template friend class Future; -}; - -OVITO_END_INLINE_NAMESPACE -OVITO_END_INLINE_NAMESPACE -} // End of namespace - -#endif // __OVITO_FUTURE_INTERFACE_H diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/concurrent/FutureWatcher.h ovito-2.9.0+dfsg1/src/core/utilities/concurrent/FutureWatcher.h --- ovito-2.8.1+dfsg2/src/core/utilities/concurrent/FutureWatcher.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/concurrent/FutureWatcher.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,132 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (2013) Alexander Stukowski -// -// This file is part of OVITO (Open Visualization Tool). -// -// OVITO is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// OVITO is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef __OVITO_FUTURE_WATCHER_H -#define __OVITO_FUTURE_WATCHER_H - -#include - -namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) - -class FutureBase; -class FutureInterfaceBase; - -class OVITO_CORE_EXPORT FutureWatcher : public QObject -{ -public: - - FutureWatcher(QObject* parent = nullptr) : QObject(parent), _finished(false) {} - - virtual ~FutureWatcher() { - setFutureInterface(nullptr, false); - } - - void setFuture(const FutureBase& future); - - void setFutureInterface(const std::shared_ptr& futureInterface) { - setFutureInterface(futureInterface, true); - } - - void unsetFuture() { - setFutureInterface(nullptr, true); - } - - bool isCanceled() const; - bool isFinished() const; - int progressMaximum() const; - int progressValue() const; - int totalProgressMaximum() const; - int totalProgressValue() const; - QString progressText() const; - - void waitForFinished() const; - -protected: - - class CallOutEvent : public QEvent - { - public: - enum CallOutType { - Started = QEvent::User, - Finished, - Canceled, - ResultReady, - ProgressValue, - ProgressRange, - ProgressText, - }; - - CallOutEvent(CallOutType callOutType, FutureInterfaceBase* source) : QEvent((QEvent::Type)callOutType), _source(source) {} - CallOutEvent(CallOutType callOutType, int value, FutureInterfaceBase* source) : QEvent((QEvent::Type)callOutType), _value(value), _source(source) {} - CallOutEvent(CallOutType callOutType, const QString& text, FutureInterfaceBase* source) : QEvent((QEvent::Type)callOutType), _text(text), _source(source) {} - - int _value; - QString _text; - FutureInterfaceBase* _source; - }; - - void postCallOutEvent(CallOutEvent::CallOutType type, FutureInterfaceBase* source) { - OVITO_ASSERT(source == _futureInterface.get()); - QCoreApplication::postEvent(this, new CallOutEvent(type, _futureInterface.get())); - } - - void postCallOutEvent(CallOutEvent::CallOutType type, int value, FutureInterfaceBase* source) { - OVITO_ASSERT(source == _futureInterface.get()); - QCoreApplication::postEvent(this, new CallOutEvent(type, value, _futureInterface.get())); - } - - void postCallOutEvent(CallOutEvent::CallOutType type, const QString& text, FutureInterfaceBase* source) { - OVITO_ASSERT(source == _futureInterface.get()); - QCoreApplication::postEvent(this, new CallOutEvent(type, text, _futureInterface.get())); - } - - virtual void customEvent(QEvent* event) override; - - void setFutureInterface(const std::shared_ptr& futureInterface, bool pendingAssignment); - -Q_SIGNALS: - - void canceled(); - void finished(); - void started(); - void resultReady(); - void progressRangeChanged(int maximum); - void progressValueChanged(int progressValue); - void progressTextChanged(const QString& progressText); - -public Q_SLOTS: - - void cancel(); - -private: - - std::shared_ptr _futureInterface; - bool _finished; - - friend class FutureInterfaceBase; - Q_OBJECT -}; - -OVITO_END_INLINE_NAMESPACE -OVITO_END_INLINE_NAMESPACE -} // End of namespace - -#endif // __OVITO_FUTURE_WATCHER_H diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/concurrent/ParallelFor.h ovito-2.9.0+dfsg1/src/core/utilities/concurrent/ParallelFor.h --- ovito-2.8.1+dfsg2/src/core/utilities/concurrent/ParallelFor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/concurrent/ParallelFor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,12 +19,12 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARALLEL_FOR_H -#define __OVITO_PARALLEL_FOR_H +#pragma once + #include #include -#include "FutureInterface.h" +#include "Promise.h" #include @@ -33,22 +33,22 @@ template bool parallelFor( T loopCount, - FutureInterfaceBase& futureInterface, + PromiseBase& promise, Function kernel, T progressChunkSize = 1024) { - futureInterface.setProgressRange(loopCount / progressChunkSize); - futureInterface.setProgressValue(0); + promise.setProgressMaximum(loopCount / progressChunkSize); + promise.setProgressValue(0); std::vector> workers; - size_t num_threads = Application::instance().idealThreadCount(); + size_t num_threads = Application::instance()->idealThreadCount(); T chunkSize = loopCount / num_threads; T startIndex = 0; T endIndex = chunkSize; for(size_t t = 0; t < num_threads; t++) { if(t == num_threads - 1) endIndex += loopCount % num_threads; - workers.push_back(std::async(std::launch::async, [&futureInterface, &kernel, startIndex, endIndex, progressChunkSize]() { + workers.push_back(std::async(std::launch::async, [&promise, &kernel, startIndex, endIndex, progressChunkSize]() { for(T i = startIndex; i < endIndex;) { // Execute kernel. kernel(i); @@ -58,9 +58,9 @@ // Update progress indicator. if((i % progressChunkSize) == 0) { OVITO_ASSERT(i != 0); - futureInterface.incrementProgressValue(); + promise.incrementProgressValue(); } - if(futureInterface.isCanceled()) + if(promise.isCanceled()) return; } })); @@ -73,15 +73,15 @@ for(auto& t : workers) t.get(); - futureInterface.incrementProgressValue(loopCount % progressChunkSize); - return !futureInterface.isCanceled(); + promise.incrementProgressValue(loopCount % progressChunkSize); + return !promise.isCanceled(); } template void parallelFor(T loopCount, Function kernel) { std::vector> workers; - size_t num_threads = Application::instance().idealThreadCount(); + size_t num_threads = Application::instance()->idealThreadCount(); if(num_threads > loopCount) { if(loopCount <= 0) return; num_threads = loopCount; @@ -116,10 +116,10 @@ } template -bool parallelForChunks(size_t loopCount, FutureInterfaceBase& futureInterface, Function kernel) +bool parallelForChunks(size_t loopCount, PromiseBase& promise, Function kernel) { std::vector> workers; - size_t num_threads = Application::instance().idealThreadCount(); + size_t num_threads = Application::instance()->idealThreadCount(); if(num_threads > loopCount) { if(loopCount <= 0) return true; num_threads = loopCount; @@ -130,11 +130,11 @@ if(t == num_threads - 1) { chunkSize += loopCount % num_threads; OVITO_ASSERT(startIndex + chunkSize == loopCount); - kernel(startIndex, chunkSize, futureInterface); + kernel(startIndex, chunkSize, promise); } else { - workers.push_back(std::async(std::launch::async, [&kernel, startIndex, chunkSize, &futureInterface]() { - kernel(startIndex, chunkSize, futureInterface); + workers.push_back(std::async(std::launch::async, [&kernel, startIndex, chunkSize, &promise]() { + kernel(startIndex, chunkSize, promise); })); } startIndex += chunkSize; @@ -144,7 +144,7 @@ for(auto& t : workers) t.get(); - return !futureInterface.isCanceled(); + return !promise.isCanceled(); } @@ -152,7 +152,7 @@ void parallelForChunks(size_t loopCount, Function kernel) { std::vector> workers; - size_t num_threads = Application::instance().idealThreadCount(); + size_t num_threads = Application::instance()->idealThreadCount(); if(num_threads > loopCount) { if(loopCount <= 0) return; num_threads = loopCount; @@ -182,4 +182,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_PARALLEL_FOR_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/concurrent/ProgressDisplay.h ovito-2.9.0+dfsg1/src/core/utilities/concurrent/ProgressDisplay.h --- ovito-2.8.1+dfsg2/src/core/utilities/concurrent/ProgressDisplay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/concurrent/ProgressDisplay.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,62 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (2016) Alexander Stukowski -// -// This file is part of OVITO (Open Visualization Tool). -// -// OVITO is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// OVITO is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef __OVITO_PROGRESS_DISPLAY_H -#define __OVITO_PROGRESS_DISPLAY_H - -#include - -namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) - -class AbstractProgressDisplay -{ -public: - - /// Returns whether the operation has been canceled by the user. - virtual bool wasCanceled() = 0; - - /// Cancels the operation. - virtual void cancel() = 0; - - /// Sets the status text to be displayed. - virtual void setStatusText(const QString& text) = 0; - - /// Return the current status text. - virtual QString statusText() = 0; - - /// Returns the highest value represented by the progress bar. - virtual int maximum() = 0; - - /// Sets the highest value represented by the progress bar. - virtual void setMaximum(int max) = 0; - - /// Returns the value displayed by the progress bar. - virtual int value() = 0; - - /// Sets the value displayed by the progress bar. - virtual void setValue(int v) = 0; -}; - -OVITO_END_INLINE_NAMESPACE -OVITO_END_INLINE_NAMESPACE -} // End of namespace - -#endif // __OVITO_PROGRESS_DISPLAY_H diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/concurrent/Promise.cpp ovito-2.9.0+dfsg1/src/core/utilities/concurrent/Promise.cpp --- ovito-2.8.1+dfsg2/src/core/utilities/concurrent/Promise.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/concurrent/Promise.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,354 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2013) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include "Promise.h" +#include "Future.h" + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) + +enum { + MaxProgressEmitsPerSecond = 20 +}; + +PromiseBase::~PromiseBase() +{ +} + +void PromiseBase::cancel() +{ + QMutexLocker locker(&_mutex); + + if(_subTask) { + _subTask->cancel(); + } + + if(isCanceled()) { + return; + } + + _state = State(_state | Canceled); + _waitCondition.wakeAll(); + for(PromiseWatcher* watcher : _watchers) + QMetaObject::invokeMethod(watcher, "promiseCanceled", Qt::QueuedConnection); +} + +bool PromiseBase::setStarted() +{ + QMutexLocker locker(&_mutex); + if(isStarted()) + return false; // It's already started. Don't run it again. + OVITO_ASSERT(!isFinished() || isRunning()); + _state = State(Started | Running); + for(PromiseWatcher* watcher : _watchers) + QMetaObject::invokeMethod(watcher, "promiseStarted", Qt::QueuedConnection); + return true; +} + +void PromiseBase::setFinished() +{ + QMutexLocker locker(&_mutex); + OVITO_ASSERT(isStarted()); + if(!isFinished()) { + _state = State((_state & ~Running) | Finished); + _waitCondition.wakeAll(); + for(PromiseWatcher* watcher : _watchers) + QMetaObject::invokeMethod(watcher, "promiseFinished", Qt::QueuedConnection); + } +} + +void PromiseBase::setException() +{ + QMutexLocker locker(&_mutex); + if(isCanceled() || isFinished()) + return; + + setException(std::current_exception()); +} + +void PromiseBase::setException(std::exception_ptr ex) +{ + _exceptionStore = ex; + _state = State(_state | ResultSet); + _waitCondition.wakeAll(); + for(PromiseWatcher* watcher : _watchers) + QMetaObject::invokeMethod(watcher, "promiseResultReady", Qt::QueuedConnection); +} + +void PromiseBase::setResultReady() +{ + if(isCanceled() || isFinished()) + return; + + _state = State(_state | ResultSet); + _waitCondition.wakeAll(); + for(PromiseWatcher* watcher : _watchers) + QMetaObject::invokeMethod(watcher, "promiseResultReady", Qt::QueuedConnection); +} + +void PromiseBase::waitForResult() +{ + throwPossibleException(); + + QMutexLocker lock(&_mutex); + if(!isRunning() && isStarted()) + return; + + lock.unlock(); + + // To avoid deadlocks and reduce the number of threads used, try to + // run the runnable in the current thread. + tryToRunImmediately(); + + lock.relock(); + if(!isRunning() && isStarted()) + return; + + while(isRunning() && isResultSet() == false) + _waitCondition.wait(&_mutex); + + throwPossibleException(); + + if(isCanceled()) + throw Exception("No result available, because promise has been canceled."); + + OVITO_ASSERT(isResultSet()); +} + +void PromiseBase::waitForFinished() +{ + QMutexLocker lock(&_mutex); + const bool alreadyFinished = !isRunning() && isStarted(); + lock.unlock(); + + if(!alreadyFinished) { + tryToRunImmediately(); + lock.relock(); + while(isRunning() || !isStarted()) + _waitCondition.wait(&_mutex); + } + + throwPossibleException(); +} + +void PromiseBase::registerWatcher(PromiseWatcher* watcher) +{ + QMutexLocker locker(&_mutex); + + if(isStarted()) + QMetaObject::invokeMethod(watcher, "promiseStarted", Qt::QueuedConnection); + + if(isResultSet()) + QMetaObject::invokeMethod(watcher, "promiseResultReady", Qt::QueuedConnection); + + if(isCanceled()) + QMetaObject::invokeMethod(watcher, "promiseCanceled", Qt::QueuedConnection); + + if(isFinished()) + QMetaObject::invokeMethod(watcher, "promiseFinished", Qt::QueuedConnection); + + _watchers.push_back(watcher); +} + +void PromiseBase::unregisterWatcher(PromiseWatcher* watcher) +{ + QMutexLocker locker(&_mutex); + _watchers.removeOne(watcher); +} + +bool PromiseBase::waitForSubTask(const FutureBase& subFuture) +{ + return waitForSubTask(subFuture.promise()); +} + +bool PromiseBase::waitForSubTask(const PromiseBasePtr& subTask) +{ + QMutexLocker locker(&_mutex); + if(this->isCanceled()) { + subTask->cancel(); + return false; + } + if(subTask->isCanceled()) { + locker.unlock(); + this->cancel(); + return false; + } + this->_subTask = subTask.get(); + locker.unlock(); + try { + QMutexLocker subtaskLock(&subTask->_mutex); + const bool subTaskAlreadyFinished = !subTask->isRunning() && subTask->isStarted(); + subtaskLock.unlock(); + + if(!subTaskAlreadyFinished) { + subTask->tryToRunImmediately(); + subtaskLock.relock(); + while(!subTask->isCanceled() && (subTask->isRunning() || !subTask->isStarted())) + subTask->_waitCondition.wait(&subTask->_mutex); + } + + subTask->throwPossibleException(); + } + catch(...) { + locker.relock(); + this->_subTask = nullptr; + throw; + } + locker.relock(); + this->_subTask = nullptr; + locker.unlock(); + if(subTask->isCanceled()) { + this->cancel(); + return false; + } + return true; +} + +void PromiseBase::setProgressMaximum(int maximum) +{ + QMutexLocker locker(&_mutex); + + if(maximum == _progressMaximum || isCanceled() || isFinished()) + return; + + _progressMaximum = maximum; + computeTotalProgress(); + for(PromiseWatcher* watcher : _watchers) + QMetaObject::invokeMethod(watcher, "promiseProgressRangeChanged", Qt::QueuedConnection, Q_ARG(int, totalProgressMaximum())); +} + +bool PromiseBase::setProgressValue(int value) +{ + QMutexLocker locker(&_mutex); + _intermittentUpdateCounter = 0; + + if(value == _progressValue || isCanceled() || isFinished()) + return !isCanceled(); + + _progressValue = value; + computeTotalProgress(); + + if(!_progressTime.isValid() || _progressValue == _progressMaximum || _progressTime.elapsed() >= (1000 / MaxProgressEmitsPerSecond)) { + _progressTime.start(); + for(PromiseWatcher* watcher : _watchers) + QMetaObject::invokeMethod(watcher, "promiseProgressValueChanged", Qt::QueuedConnection, Q_ARG(int, totalProgressValue())); + } + + return !isCanceled(); +} + +bool PromiseBase::setProgressValueIntermittent(int progressValue, int updateEvery) +{ + if(_intermittentUpdateCounter == 0 || _intermittentUpdateCounter > updateEvery) { + setProgressValue(progressValue); + } + _intermittentUpdateCounter++; + return !isCanceled(); +} + +bool PromiseBase::incrementProgressValue(int increment) +{ + QMutexLocker locker(&_mutex); + + if(isCanceled() || isFinished()) + return !isCanceled(); + + _progressValue += increment; + computeTotalProgress(); + + if(!_progressTime.isValid() || _progressValue == _progressMaximum || _progressTime.elapsed() >= (1000 / MaxProgressEmitsPerSecond)) { + _progressTime.start(); + for(PromiseWatcher* watcher : _watchers) + QMetaObject::invokeMethod(watcher, "promiseProgressValueChanged", Qt::QueuedConnection, Q_ARG(int, progressValue())); + } + + return !isCanceled(); +} + +void PromiseBase::computeTotalProgress() +{ + if(subStepsStack.empty()) { + _totalProgressMaximum = _progressMaximum; + _totalProgressValue = _progressValue; + } + else { + double percentage; + if(_progressMaximum > 0) + percentage = (double)_progressValue / _progressMaximum; + else + percentage = 0.0; + for(auto level = subStepsStack.crbegin(); level != subStepsStack.crend(); ++level) { + OVITO_ASSERT(level->first >= 0 && level->first < level->second.size()); + int weightSum1 = std::accumulate(level->second.cbegin(), level->second.cbegin() + level->first, 0); + int weightSum2 = std::accumulate(level->second.cbegin() + level->first, level->second.cend(), 0); + percentage = ((double)weightSum1 + percentage * level->second[level->first]) / (weightSum1 + weightSum2); + } + _totalProgressMaximum = 1000; + _totalProgressValue = int(percentage * 1000.0); + } +} + +void PromiseBase::beginProgressSubSteps(std::vector weights) +{ + QMutexLocker locker(&_mutex); + OVITO_ASSERT(std::accumulate(weights.cbegin(), weights.cend(), 0) > 0); + subStepsStack.push_back(std::make_pair(0, std::move(weights))); + _progressMaximum = 0; + _progressValue = 0; + computeTotalProgress(); +} + +void PromiseBase::nextProgressSubStep() +{ + QMutexLocker locker(&_mutex); + OVITO_ASSERT(!subStepsStack.empty()); + OVITO_ASSERT(subStepsStack.back().first < subStepsStack.back().second.size() - 1); + subStepsStack.back().first++; + _progressMaximum = 0; + _progressValue = 0; + computeTotalProgress(); +} + +void PromiseBase::endProgressSubSteps() +{ + QMutexLocker locker(&_mutex); + OVITO_ASSERT(!subStepsStack.empty()); + subStepsStack.pop_back(); + _progressMaximum = 0; + _progressValue = 0; + computeTotalProgress(); +} + +void PromiseBase::setProgressText(const QString& progressText) +{ + QMutexLocker locker(&_mutex); + + if(isCanceled() || isFinished()) + return; + + _progressText = progressText; + for(PromiseWatcher* watcher : _watchers) + QMetaObject::invokeMethod(watcher, "promiseProgressTextChanged", Qt::QueuedConnection, Q_ARG(QString, progressText)); +} + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/concurrent/Promise.h ovito-2.9.0+dfsg1/src/core/utilities/concurrent/Promise.h --- ovito-2.8.1+dfsg2/src/core/utilities/concurrent/Promise.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/concurrent/Promise.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,262 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include "PromiseWatcher.h" + +#include +#include +#include +#include + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) + +template class Future; // Defined in Future.h + +/****************************************************************************** +* Generic base class for promises, which implements the basic state management, +* progress reporting, and event processing. +******************************************************************************/ +class OVITO_CORE_EXPORT PromiseBase +{ +public: + + /// The different states the promise can be in. + /// Note that combinations are possible. + enum State { + NoState = 0, + Running = (1<<0), + Started = (1<<1), + Canceled = (1<<2), + Finished = (1<<3), + ResultSet = (1<<4) + }; + + /// Destructor. + virtual ~PromiseBase(); + + /// Returns whether this promise has been canceled by a previous call to cancel(). + bool isCanceled() const { return (_state & Canceled); } + + /// Returns the maximum value for progress reporting. + int progressMaximum() const { return _progressMaximum; } + + /// Sets the current maximum value for progress reporting. + void setProgressMaximum(int maximum); + + /// Returns the current progress value (in the range 0 to progressMaximum()). + int progressValue() const { return _progressValue; } + + /// Sets the current progress value (must be in the range 0 to progressMaximum()). + /// Returns false if the promise has been canceled. + bool setProgressValue(int progressValue); + + /// Increments the progress value by 1. + /// Returns false if the promise has been canceled. + bool incrementProgressValue(int increment = 1); + + /// Sets the progress value of the promise but generates an update event only occasionally. + /// Returns false if the promise has been canceled. + bool setProgressValueIntermittent(int progressValue, int updateEvery = 2000); + + /// Return the current status text set for this promise. + QString progressText() const { return _progressText; } + + /// Changes the status text of this promise. + void setProgressText(const QString& progressText); + + // Progress reporting for tasks with sub-steps: + + /// Begins a sequence of sub-steps in the progress range of this promise. + /// This is used for long and complex computations, which consist of several logical sub-steps, each with + /// a separate progress range. + void beginProgressSubSteps(std::vector weights); + + /// Convenience version of the function above, which creates N substeps, all with the same weight. + void beginProgressSubSteps(int nsteps) { beginProgressSubSteps(std::vector(nsteps, 1)); } + + /// Changes to the next sub-step in the sequence started with beginProgressSubSteps(). + void nextProgressSubStep(); + + /// Must be called at the end of a sub-step sequence started with beginProgressSubSteps(). + void endProgressSubSteps(); + + /// Returns the maximum progress value that can be reached (taking into account sub-steps). + int totalProgressMaximum() const { return _totalProgressMaximum; } + + /// Returns the current progress value (taking into account sub-steps). + int totalProgressValue() const { return _totalProgressValue; } + + /// Blocks execution until the given promise is complete. + /// Returns false if either the sub-promise or this promise have been canceled. + bool waitForSubTask(const PromiseBasePtr& subTask); + + /// Blocks execution until the given future is complete. + /// Returns false if either the future or this promise have been canceled. + bool waitForSubTask(const FutureBase& subFuture); + + /// Cancels this promise. + virtual void cancel(); + + // Implementation details: + + /// This must be called after creating a promise to put it into the 'started' state. + /// Returns false if the promise is or was already in the 'started' state. + bool setStarted(); + + /// This must be called after the promise has been fulfilled (even if an exception occurred). + void setFinished(); + + /// Sets the promise into the 'exception' state to signal that an exception has occurred + /// while trying to fulfill it. This method should be called from a catch(...) exception handler. + void setException(); + + /// Sets the promise into the 'exception' state to signal that an exception has occurred + /// while trying to fulfill it. + void setException(std::exception_ptr ex); + + /// Blocks execution until this promise has been fulfilled, canceled or an exception occurred. + void waitForFinished(); + +protected: + + /// Constructor. + PromiseBase(State initialState = NoState) : _state(initialState) {} + + /// Returns true if the promise is in the 'running' state. + bool isRunning() const { return (_state & Running); } + + /// Returns true if the promise is in the 'started' state. + bool isStarted() const { return (_state & Started); } + + /// Returns true if the promise is in the 'finished' state. + bool isFinished() const { return (_state & Finished); } + + /// Returns true if a result value (or, alternatively, an exception) has been set for this promise. + bool isResultSet() const { return (_state & ResultSet); } + + /// Signals the associated future that a result value is available. + void setResultReady(); + + /// Re-throws the exception stored in this promise if an exception was previously set via setException(). + void throwPossibleException() { + if(_exceptionStore) + std::rethrow_exception(_exceptionStore); + } + + /// Blocks execution until a result value (or exception) has been set for this promise. + void waitForResult(); + + void registerWatcher(PromiseWatcher* watcher); + void unregisterWatcher(PromiseWatcher* watcher); + + void computeTotalProgress(); + + virtual void tryToRunImmediately() {} + + PromiseBase* _subTask = nullptr; + QList _watchers; + QMutex _mutex; + State _state; + QWaitCondition _waitCondition; + std::exception_ptr _exceptionStore; + int _totalProgressValue = 0; + int _totalProgressMaximum = 0; + int _progressValue = 0; + int _progressMaximum = 0; + int _intermittentUpdateCounter = 0; + QString _progressText; + QElapsedTimer _progressTime; + std::vector>> subStepsStack; + + friend class PromiseWatcher; + friend class TaskManager; + friend class FutureBase; + template friend class Future; +}; + +/****************************************************************************** +* A promise that generates a result value of a specific type. +******************************************************************************/ +template +class Promise : public PromiseBase +{ +public: + + /// Default constructor. + Promise() {} + + /// Sets the result value of this promise. A copy of the provided value is stored in the promise. + void setResult(const R& value) { + QMutexLocker locker(&_mutex); + if(isCanceled() || isFinished()) + return; + _result = value; + _state = State(_state | ResultSet); + setResultReady(); + } + + /// Sets the result value of this promise. The provided value is moved into the promise. + void setResult(R&& value) { + QMutexLocker locker(&_mutex); + if(isCanceled() || isFinished()) + return; + _result = std::move(value); + _state = State(_state | ResultSet); + setResultReady(); + } + +private: + + /// The result value stored by this promise. + R _result; + + template friend class Task; + template friend class Future; +}; + +/****************************************************************************** +* A promise that generates no result value. +******************************************************************************/ +template<> +class Promise : public PromiseBase +{ +public: + + /// Default constructor. + Promise() {} + + template friend class Task; + template friend class Future; +}; + +/// A pointer to a promise. +template +using PromisePtr = std::shared_ptr>; + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/concurrent/PromiseWatcher.cpp ovito-2.9.0+dfsg1/src/core/utilities/concurrent/PromiseWatcher.cpp --- ovito-2.8.1+dfsg2/src/core/utilities/concurrent/PromiseWatcher.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/concurrent/PromiseWatcher.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,130 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include "PromiseWatcher.h" +#include "Promise.h" +#include "Future.h" +#include "Task.h" + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) + +void PromiseWatcher::setPromise(const PromiseBasePtr& promise, bool pendingAssignment) +{ + if(promise == _promise) + return; + + if(_promise) { + _promise->unregisterWatcher(this); + if(pendingAssignment) { + _finished = false; + QCoreApplication::removePostedEvents(this); + } + } + _promise = promise; + if(_promise) + _promise->registerWatcher(this); +} + +void PromiseWatcher::promiseCanceled() +{ + if(promise()) + Q_EMIT canceled(); +} + +void PromiseWatcher::promiseFinished() +{ + if(promise()) { + _finished = true; + Q_EMIT finished(); + } +} + +void PromiseWatcher::promiseStarted() +{ + if(promise()) + Q_EMIT started(); +} + +void PromiseWatcher::promiseResultReady() +{ + if(promise() && !promise()->isCanceled()) + Q_EMIT resultReady(); +} + +void PromiseWatcher::promiseProgressRangeChanged(int maximum) +{ + if(promise() && !promise()->isCanceled()) + Q_EMIT progressRangeChanged(maximum); +} + +void PromiseWatcher::promiseProgressValueChanged(int progressValue) +{ + if(promise() && !promise()->isCanceled()) + Q_EMIT progressValueChanged(progressValue); +} + +void PromiseWatcher::promiseProgressTextChanged(QString progressText) +{ + if(promise() && !promise()->isCanceled()) + Q_EMIT progressTextChanged(progressText); +} + +void PromiseWatcher::cancel() +{ + if(promise()) + promise()->cancel(); +} + +bool PromiseWatcher::isCanceled() const +{ + return promise() ? promise()->isCanceled() : false; +} + +bool PromiseWatcher::isFinished() const +{ + return _finished; +} + +int PromiseWatcher::progressMaximum() const +{ + return promise() ? promise()->totalProgressMaximum() : 0; +} + +int PromiseWatcher::progressValue() const +{ + return promise() ? promise()->totalProgressValue() : 0; +} + +QString PromiseWatcher::progressText() const +{ + return promise() ? promise()->progressText() : QString(); +} + +void PromiseWatcher::waitForFinished() const +{ + if(promise()) + promise()->waitForFinished(); +} + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/concurrent/PromiseWatcher.h ovito-2.9.0+dfsg1/src/core/utilities/concurrent/PromiseWatcher.h --- ovito-2.8.1+dfsg2/src/core/utilities/concurrent/PromiseWatcher.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/concurrent/PromiseWatcher.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,132 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) + +class FutureBase; +class PromiseBase; + +/// A pointer to the promise base class. +using PromiseBasePtr = std::shared_ptr; + +/****************************************************************************** +* A utility class that integrates the Promise class into the Qt signal/slots +* framework. It allows to have signals generated when the state of a Promise +* changes. +******************************************************************************/ +class OVITO_CORE_EXPORT PromiseWatcher : public QObject +{ +public: + + /// Constructor that creates a watcher that is not associated with + /// a Promise yet. + PromiseWatcher(QObject* parent = nullptr) : QObject(parent) {} + + /// Destructor. + virtual ~PromiseWatcher() { + setPromise(nullptr, false); + } + + /// Associates this object with the Promise of the given Future. + void setFuture(const FutureBase& future); + + /// Associates this object with the given Promise. + void setPromise(const PromiseBasePtr& promise) { + setPromise(promise, true); + } + + /// Dissociates this object from its Promise. + void unsetPromise() { + setPromise(nullptr, true); + } + + /// Returns true if the Promise monitored by this object has been canceled. + bool isCanceled() const; + + /// Returns true if the Promise monitored by this object has reached the 'finished' state. + bool isFinished() const; + + /// Returns the maximum value for the progress of the Promise monitored by this object. + int progressMaximum() const; + + /// Returns the current value for the progress of the Promise monitored by this object. + int progressValue() const; + + /// Returns the status text of the Promise monitored by this object. + QString progressText() const; + + /// Blocks execution until the Promise monitored by this object has reached the 'finished' state. + void waitForFinished() const; + + /// Returns the Promise monitored by this object. + const PromiseBasePtr& promise() const { return _promise; } + +protected: + + void setPromise(const PromiseBasePtr& promise, bool pendingAssignment); + +Q_SIGNALS: + + void canceled(); + void finished(); + void started(); + void resultReady(); + void progressRangeChanged(int maximum); + void progressValueChanged(int progressValue); + void progressTextChanged(const QString& progressText); + +public Q_SLOTS: + + void cancel(); + +private Q_SLOTS: + + void promiseCanceled(); + void promiseFinished(); + void promiseStarted(); + void promiseResultReady(); + void promiseProgressRangeChanged(int maximum); + void promiseProgressValueChanged(int progressValue); + void promiseProgressTextChanged(QString progressText); + +private: + + /// The Promise being monitored. + PromiseBasePtr _promise; + + /// Indicates that the promise has reached the 'finished' state. + bool _finished = false; + + Q_OBJECT + + friend class PromiseBase; +}; + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/concurrent/Task.cpp ovito-2.9.0+dfsg1/src/core/utilities/concurrent/Task.cpp --- ovito-2.8.1+dfsg2/src/core/utilities/concurrent/Task.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/concurrent/Task.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,86 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2016) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) + +/****************************************************************************** +* Constructor. +******************************************************************************/ +SynchronousTask::SynchronousTask(TaskManager& taskManager) : _promise(std::make_shared>()), _taskManager(taskManager) +{ + taskManager.registerTask(_promise); + _promise->setStarted(); +} + +/****************************************************************************** +* Destructor. +******************************************************************************/ +SynchronousTask::~SynchronousTask() +{ + _promise->setFinished(); +} + +/****************************************************************************** +* Sets the status text to be displayed. +******************************************************************************/ +void SynchronousTask::setProgressText(const QString& text) +{ + _promise->setProgressText(text); + + // Yield control to the event loop to process user interface events. + // This is necessary so that the user can interrupt the running opertion. + _taskManager.processEvents(); +} + +/****************************************************************************** +* Sets the value displayed by the progress bar. +******************************************************************************/ +void SynchronousTask::setProgressValue(int v) +{ + _promise->setProgressValue(v); + + // Yield control to the event loop to process user interface events. + // This is necessary so that the user can interrupt the running opertion. + _taskManager.processEvents(); +} + +/****************************************************************************** +* Returns whether the operation has been canceled by the user. +******************************************************************************/ +bool SynchronousTask::isCanceled() const +{ + // Note: The SynchronousTask may get destroyed during event processing. Better access it first. + bool result = _promise->isCanceled(); + + // Yield control to the event loop to process user interface events. + // This is necessary so that the user can interrupt the running opertion. + _taskManager.processEvents(); + + return result; +} + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/concurrent/Task.h ovito-2.9.0+dfsg1/src/core/utilities/concurrent/Task.h --- ovito-2.8.1+dfsg2/src/core/utilities/concurrent/Task.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/concurrent/Task.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,18 +19,17 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TASK_H -#define __OVITO_TASK_H +#pragma once + #include -#include "FutureInterface.h" #include "Future.h" #include namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) -class AsynchronousTask : public FutureInterface, public QRunnable +class AsynchronousTask : public Promise, public QRunnable { public: @@ -51,20 +50,63 @@ /// Implementation of FutureInterface. virtual void tryToRunImmediately() override { - if(!this->reportStarted()) + if(!this->setStarted()) return; try { perform(); } catch(...) { - this->reportException(); + this->setException(); } - this->reportFinished(); + this->setFinished(); } }; +class OVITO_CORE_EXPORT SynchronousTask +{ +public: + + /// Constructor. + SynchronousTask(TaskManager& taskManager); + + /// Destructor. + ~SynchronousTask(); + + /// Returns whether the operation has been canceled by the user. + bool isCanceled() const; + + /// Cancels the operation. + void cancel() { _promise->cancel(); } + + /// Sets the status text to be displayed. + void setProgressText(const QString& text); + + /// Return the current status text. + QString progressText() const { return _promise->progressText(); } + + /// Returns the highest value represented by the progress bar. + int progressMaximum() const { return _promise->progressMaximum(); } + + /// Sets the highest value represented by the progress bar. + void setProgressMaximum(int max) { _promise->setProgressMaximum(max); } + + /// Returns the value displayed by the progress bar. + int progressValue() const { return _promise->progressValue(); } + + /// Sets the value displayed by the progress bar. + void setProgressValue(int v); + + /// Returns the internal promise managed by this object. + Promise& promise() const { return *_promise.get(); } + +private: + + PromisePtr _promise; + TaskManager& _taskManager; +}; + OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_TASK_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/concurrent/TaskManager.cpp ovito-2.9.0+dfsg1/src/core/utilities/concurrent/TaskManager.cpp --- ovito-2.8.1+dfsg2/src/core/utilities/concurrent/TaskManager.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/concurrent/TaskManager.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -21,6 +21,12 @@ #include #include +#include +#include + +#ifdef Q_OS_UNIX + #include +#endif namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) @@ -29,21 +35,28 @@ ******************************************************************************/ TaskManager::TaskManager() { - qRegisterMetaType>("std::shared_ptr"); + qRegisterMetaType("PromiseBasePtr"); } /****************************************************************************** -* Registers a future with the task manager. +* Registers a promise with the task manager. ******************************************************************************/ -void TaskManager::addTaskInternal(std::shared_ptr futureInterface) +PromiseWatcher* TaskManager::addTaskInternal(PromiseBasePtr promise) { - // Create a task watcher which will generate start/stop notification signals. - FutureWatcher* watcher = new FutureWatcher(this); - connect(watcher, &FutureWatcher::started, this, &TaskManager::taskStartedInternal); - connect(watcher, &FutureWatcher::finished, this, &TaskManager::taskFinishedInternal); + // Check if task is already registered. + for(PromiseWatcher* watcher : runningTasks()) { + if(watcher->promise() == promise) + return watcher; + } + + // Create a task watcher, which will generate start/stop notification signals. + PromiseWatcher* watcher = new PromiseWatcher(this); + connect(watcher, &PromiseWatcher::started, this, &TaskManager::taskStartedInternal); + connect(watcher, &PromiseWatcher::finished, this, &TaskManager::taskFinishedInternal); // Activate the watcher. - watcher->setFutureInterface(futureInterface); + watcher->setPromise(promise); + return watcher; } /****************************************************************************** @@ -51,7 +64,7 @@ ******************************************************************************/ void TaskManager::taskStartedInternal() { - FutureWatcher* watcher = static_cast(sender()); + PromiseWatcher* watcher = static_cast(sender()); _runningTaskStack.push_back(watcher); Q_EMIT taskStarted(watcher); @@ -62,7 +75,7 @@ ******************************************************************************/ void TaskManager::taskFinishedInternal() { - FutureWatcher* watcher = static_cast(sender()); + PromiseWatcher* watcher = static_cast(sender()); OVITO_ASSERT(std::find(_runningTaskStack.begin(), _runningTaskStack.end(), watcher) != _runningTaskStack.end()); _runningTaskStack.erase(std::find(_runningTaskStack.begin(), _runningTaskStack.end(), watcher)); @@ -77,8 +90,9 @@ ******************************************************************************/ void TaskManager::cancelAll() { - for(FutureWatcher* watcher : _runningTaskStack) + for(PromiseWatcher* watcher : runningTasks()) { watcher->cancel(); + } } /****************************************************************************** @@ -95,7 +109,7 @@ ******************************************************************************/ void TaskManager::waitForAll() { - for(FutureWatcher* watcher : _runningTaskStack) { + for(PromiseWatcher* watcher : runningTasks()) { try { watcher->waitForFinished(); } @@ -104,25 +118,88 @@ } /****************************************************************************** -* Waits for the given task to finish and displays a modal progress dialog -* to show the task's progress. +* This should be called whenever a local event handling loop is entered. +******************************************************************************/ +void TaskManager::startLocalEventHandling() +{ + OVITO_ASSERT_MSG(QThread::currentThread() == QCoreApplication::instance()->thread(), "TaskManager::waitForTask", "Function may only be called from the main thread."); + + _inLocalEventLoop++; + Q_EMIT localEventLoopEntered(); +} + +/****************************************************************************** +* This should be called whenever a local event handling loop is left. ******************************************************************************/ -bool TaskManager::waitForTask(const std::shared_ptr& futureInterface) +void TaskManager::stopLocalEventHandling() { - OVITO_ASSERT_MSG(QThread::currentThread() == QCoreApplication::instance()->thread(), "TaskManager::waitForTask", "Function can only be called from the main thread."); + OVITO_ASSERT_MSG(QThread::currentThread() == QCoreApplication::instance()->thread(), "TaskManager::waitForTask", "Function may only be called from the main thread."); + OVITO_ASSERT(_inLocalEventLoop > 0); + + _inLocalEventLoop--; + Q_EMIT localEventLoopExited(); +} + +/****************************************************************************** +* Waits for the given task to finish. +******************************************************************************/ +bool TaskManager::waitForTask(const PromiseBasePtr& promise) +{ + OVITO_ASSERT_MSG(QThread::currentThread() == QCoreApplication::instance()->thread(), "TaskManager::waitForTask", "Function may only be called from the main thread."); // Before entering the local event loop, check if task has already finished. - if(futureInterface->isFinished()) - return !futureInterface->isCanceled(); + if(promise->isFinished()) { + return !promise->isCanceled(); + } + + // Register the task in cases it hasn't been registered with this TaskManager yet. + PromiseWatcher* watcher = addTaskInternal(promise); - // Start a local event loop and wait for the task to generate the finished signal. - FutureWatcher watcher; + // Start a local event loop and wait for the task to generate a signal when it finishes. QEventLoop eventLoop; - watcher.setFutureInterface(futureInterface); - connect(&watcher, &FutureWatcher::finished, &eventLoop, &QEventLoop::quit); + connect(watcher, &PromiseWatcher::finished, &eventLoop, &QEventLoop::quit); + +#ifdef Q_OS_UNIX + // Boolean flag which is set by the POSIX signal handler when user + // presses Ctrl+C to interrupt the program. + static QAtomicInt userInterrupt; + userInterrupt.storeRelease(0); + + // Install POSIX signal handler to catch Ctrl+C key signal. + static QEventLoop* activeEventLoop = nullptr; + activeEventLoop = &eventLoop; + auto oldSignalHandler = ::signal(SIGINT, [](int) { + userInterrupt.storeRelease(1); + if(activeEventLoop) + QMetaObject::invokeMethod(activeEventLoop, "quit"); + }); +#endif + + startLocalEventHandling(); eventLoop.exec(); + stopLocalEventHandling(); - return !futureInterface->isCanceled(); +#ifdef Q_OS_UNIX + ::signal(SIGINT, oldSignalHandler); + activeEventLoop = nullptr; + if(userInterrupt.load()) { + cancelAll(); + return false; + } +#endif + + return !promise->isCanceled(); +} + +/****************************************************************************** +* Process events from the event queue when the tasks manager has started +* a local event loop. Otherwise does nothing and lets the main event loop +* do the processing. +******************************************************************************/ +void TaskManager::processEvents() +{ + if(_inLocalEventLoop) + QCoreApplication::processEvents(); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/concurrent/TaskManager.h ovito-2.9.0+dfsg1/src/core/utilities/concurrent/TaskManager.h --- ovito-2.8.1+dfsg2/src/core/utilities/concurrent/TaskManager.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/concurrent/TaskManager.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,12 +19,13 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TASK_MANAGER_H -#define __OVITO_TASK_MANAGER_H +#pragma once + #include #include "Future.h" #include "Task.h" +#include "PromiseWatcher.h" #include #include @@ -40,7 +41,7 @@ public: - /// Default constructor. + /// Constructor. TaskManager(); /// Shuts down the task manager after canceling and stopping all active tasks. @@ -51,18 +52,18 @@ /// \brief Returns the list of watchers of all currently running tasks. /// /// This method may only be called from the main thread. - const std::vector& runningTasks() const { return _runningTaskStack; } + const std::vector& runningTasks() const { return _runningTaskStack; } - /// \brief Asynchronously executes an C++ function in the background. + /// \brief Asynchronously executes a C++ function in the background. /// /// This function may be called from any thread. It returns immediately and schedules /// the function for execution at a later time. template - Future::type> execAsync(Function f) { + Future::type> execAsync(Function f) { auto task = std::make_shared>(f); QThreadPool::globalInstance()->start(task.get()); registerTask(task); - return Future::type>(task); + return Future::type>(task); } /// \brief Executes a function in a different thread and blocks the GUI until the function returns @@ -72,7 +73,7 @@ /// /// The function signature of \c func must be: /// - /// void func(FutureInterfaceBase& futureInterface); + /// void func(PromiseBase& promise); /// /// exec() may only be called from the main thread. In GUI mode, exec() will display /// a modal progress dialog while running the worker function, allowing the user to @@ -108,37 +109,47 @@ return true; } - /// \brief Registers a future with the progress manager, which will display the progress of the background task + /// \brief Registers a future's promise with the progress manager, which will display the progress of the background task /// in the main window. /// /// This function is thread-safe. template void registerTask(const Future& future) { - registerTask(future.getinterface()); + registerTask(future.promise()); } - /// \brief Registers a future interface with the progress manager, which will display the progress of the background task + /// \brief Registers a promise with the progress manager, which will display the progress of the background task /// in the main window. /// /// This function is thread-safe. - void registerTask(const std::shared_ptr& futureInterface) { - // Execute the function call in the GUI thread. - QMetaObject::invokeMethod(this, "addTaskInternal", Q_ARG(std::shared_ptr, futureInterface)); + void registerTask(const PromiseBasePtr& promise) { + // Execute the function call in the main thread. + QMetaObject::invokeMethod(this, "addTaskInternal", Q_ARG(PromiseBasePtr, promise)); } /// \brief Waits for the given task to finish and displays a modal progress dialog /// to show the task's progress. /// \return False if the task has been cancelled by the user. /// - /// This function must be called from the GUI thread. + /// This function must be called from the main thread. template bool waitForTask(const Future& future) { - return waitForTask(future.getinterface()); + return waitForTask(future.promise()); } - /// \brief Waits for the given task to finish and displays a modal progress dialog - /// to show the task's progress. - bool waitForTask(const std::shared_ptr& futureInterface); + /// \brief Waits for the given task to finish. + bool waitForTask(const PromiseBasePtr& futureInterface); + + /// \brief Process events from the event queue when the tasks manager has started + /// a local event loop. Otherwise does nothing and lets the main event loop + /// do the processing. + void processEvents(); + + /// \brief This should be called whenever a local event handling loop is entered. + void startLocalEventHandling(); + + /// \brief This should be called whenever a local event handling loop is left. + void stopLocalEventHandling(); public Q_SLOTS: @@ -154,20 +165,26 @@ Q_SIGNALS: /// \brief This signal is generated by the task manager whenever a new task started to run. - /// The FutureWatcher can be used to track the task's progress. - void taskStarted(FutureWatcher* taskWatcher); + /// The PromiseWatcher can be used to track the task's progress. + void taskStarted(PromiseWatcher* taskWatcher); /// \brief This signal is generated by the task manager whenever a task finished or stopped running. - void taskFinished(FutureWatcher* taskWatcher); + void taskFinished(PromiseWatcher* taskWatcher); + + /// \brief This signal is generated whenever a local event loop is entered to wait for a task to finish. + void localEventLoopEntered(); + + /// \brief This signal is generated whenever a local event loop was exited after waiting for a task to finish. + void localEventLoopExited(); private: - /// \brief Registers a future with the progress manager. - Q_INVOKABLE void addTaskInternal(std::shared_ptr futureInterface); + /// \brief Registers a promise with the progress manager. + Q_INVOKABLE PromiseWatcher* addTaskInternal(PromiseBasePtr futureInterface); /// Helper class used by asyncExec(). template - class FunctionRunner : public FutureInterface::type>, public QRunnable + class FunctionRunner : public Promise::type>, public QRunnable { Function _function; public: @@ -176,14 +193,14 @@ } virtual void run() override { tryToRunImmediately(); } virtual void tryToRunImmediately() override { - if(!this->reportStarted()) return; + if(!this->setStarted()) return; try { this->setResult(_function(*this)); } catch(...) { - this->reportException(); + this->setException(); } - this->reportFinished(); + this->setFinished(); } }; @@ -197,13 +214,17 @@ private: - std::vector _runningTaskStack; + /// The list of watchers for the active tasks. + std::vector _runningTaskStack; + + /// Indicates that waitForTask() has started a local event loop. + int _inLocalEventLoop = 0; }; OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -Q_DECLARE_METATYPE(std::shared_ptr); +Q_DECLARE_METATYPE(Ovito::PromiseBasePtr); + -#endif // __OVITO_TASK_MANAGER_H diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/Debugging.h ovito-2.9.0+dfsg1/src/core/utilities/Debugging.h --- ovito-2.8.1+dfsg2/src/core/utilities/Debugging.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/Debugging.h 2017-07-27 16:52:45.000000000 +0000 @@ -27,8 +27,8 @@ * \brief Defines several macros for debugging purposes. */ -#ifndef __OVITO_DEBUGGING_H -#define __OVITO_DEBUGGING_H +#pragma once + namespace Ovito { @@ -64,4 +64,4 @@ } // End of namespace -#endif // __OVITO_DEBUGGING_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/DeferredMethodInvocation.h ovito-2.9.0+dfsg1/src/core/utilities/DeferredMethodInvocation.h --- ovito-2.8.1+dfsg2/src/core/utilities/DeferredMethodInvocation.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/DeferredMethodInvocation.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DEFERRED_METHOD_INVOCATION_H -#define __OVITO_DEFERRED_METHOD_INVOCATION_H +#pragma once + #include @@ -80,5 +80,5 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_DEFERRED_METHOD_INVOCATION_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/Exception.cpp ovito-2.9.0+dfsg1/src/core/utilities/Exception.cpp --- ovito-2.8.1+dfsg2/src/core/utilities/Exception.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/Exception.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -20,12 +20,11 @@ /////////////////////////////////////////////////////////////////////////////// #include +#include #include "Exception.h" namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) -Exception::ExceptionHandler Exception::exceptionHandler = nullptr; - Exception::Exception(QObject* context) : _context(context) { _messages.push_back("An exception has occurred."); @@ -54,18 +53,17 @@ void Exception::logError() const { - for(int i = 0; i < _messages.size(); i++) - qCritical("%s", qPrintable(_messages[i])); + for(const QString& msg : _messages) + qCritical("%s", qPrintable(msg)); } -void Exception::showError() const +void Exception::reportError(bool blocking) const { - if(exceptionHandler == NULL) { + Application* app = Application::instance(); + if(!app) logError(); - return; - } - - exceptionHandler(*this); + else + app->reportError(*this, blocking); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/Exception.h ovito-2.9.0+dfsg1/src/core/utilities/Exception.h --- ovito-2.8.1+dfsg2/src/core/utilities/Exception.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/Exception.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::Exception class. */ -#ifndef __OVITO_EXCEPTION_H -#define __OVITO_EXCEPTION_H +#pragma once + #include @@ -39,7 +39,7 @@ * \brief The standard exception type used by OVITO. * * The Exception class carries a message string that describes the error that has occurred. - * The showError() method displays the error message to the user. A typical usage pattern is: + * The reportError() method displays the error message to the user. A typical usage pattern is: * * \code * try { @@ -48,7 +48,7 @@ * ... * } * catch(const Exception& ex) { - * ex.showError(); + * ex.reportError(); * } * \endcode * @@ -76,7 +76,7 @@ * } * catch(Exception& ex) { * ex.prependGeneralMessage("The input file has an invalid format."); - * ex.showError(); + * ex.reportError(); * } * \endcode * @@ -124,16 +124,18 @@ const QStringList& messages() const { return _messages; } /// Logs the error message(s) stored in this Exception object by printing them to the console. - /// - /// Use this method instead of showError() if the error needs to be logged for debugging purposes - /// but has no direct relevance for the user. + /// No modal dialog box is shown in GUI mode. void logError() const; /// Displays the error message(s) stored in the Exception object to the user. /// - /// In the graphical program mode, this method displays a message box. - /// In console mode, this method prints the error messages(s) to the console. - void showError() const; + /// In the graphical program mode, this method will display a modal message box. + /// In console mode, this method just prints the error messages(s) to the console. + /// + /// Note that, unless 'blocking' is true, the reporting happens asynchronously in GUI mode. + /// The method returns immediately and the error messaeg is displayed to the user at a later time, + /// as soon as control returns to the event loop. + void reportError(bool blocking = false) const; /// Returns a pointer to an object that provides the context for this exception or error. QObject* context() const { return _context; } @@ -150,15 +152,6 @@ // Creates a copy of this exception object. virtual Exception* clone() const override { return new Exception(*this); } -public: - - // Prototype for a handler function that takes care of displaying a caught exception to the user. - typedef void (*ExceptionHandler)(const Exception& exception); - - // Installs a handler for caught exceptions, which is invoked by showError(). - // \param handler The new handler routine. This handler is responsible for showing the error message to the user. - static void setExceptionHandler(ExceptionHandler handler) { exceptionHandler = handler; } - private: /// The message strings describing the exception. @@ -167,12 +160,9 @@ /// Pointer to an object that provides the context for this exception or error. QPointer _context; - - /// The current exception handler for displaying error messages. - static ExceptionHandler exceptionHandler; }; OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_EXCEPTION_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/FloatType.h ovito-2.9.0+dfsg1/src/core/utilities/FloatType.h --- ovito-2.8.1+dfsg2/src/core/utilities/FloatType.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/FloatType.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief This header file defines the default floating-point type and numeric constants used throughout the program. */ -#ifndef __OVITO_FLOATTYPE_H -#define __OVITO_FLOATTYPE_H +#pragma once + namespace Ovito { @@ -65,4 +65,4 @@ } // End of namespace -#endif // __OVITO_FLOATTYPE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/io/CompressedTextReader.h ovito-2.9.0+dfsg1/src/core/utilities/io/CompressedTextReader.h --- ovito-2.8.1+dfsg2/src/core/utilities/io/CompressedTextReader.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/io/CompressedTextReader.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COMPRESSED_TEXT_READER_H -#define __OVITO_COMPRESSED_TEXT_READER_H +#pragma once + #include #include @@ -174,4 +174,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_COMPRESSED_TEXT_READER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/io/CompressedTextWriter.h ovito-2.9.0+dfsg1/src/core/utilities/io/CompressedTextWriter.h --- ovito-2.8.1+dfsg2/src/core/utilities/io/CompressedTextWriter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/io/CompressedTextWriter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COMPRESSED_TEXT_WRITER_H -#define __OVITO_COMPRESSED_TEXT_WRITER_H +#pragma once + #include #include @@ -118,4 +118,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_COMPRESSED_TEXT_WRITER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/io/FileManager.cpp ovito-2.9.0+dfsg1/src/core/utilities/io/FileManager.cpp --- ovito-2.8.1+dfsg2/src/core/utilities/io/FileManager.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/io/FileManager.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,17 +27,6 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(IO) -/// The singleton instance of the class. -FileManager* FileManager::_instance = nullptr; - -/****************************************************************************** -* Constructor. -******************************************************************************/ -FileManager::FileManager() : _mutex(QMutex::Recursive) -{ - OVITO_ASSERT_MSG(!_instance, "FileManager constructor", "Multiple instances of this singleton class have been created."); -} - /****************************************************************************** * Makes a file available on this computer. ******************************************************************************/ @@ -71,11 +60,10 @@ } // Start the background download job. - std::shared_ptr> futureInterface = std::make_shared>(); - Future future(futureInterface); + Future future = Future::createWithPromise(); _pendingFiles.insert(normalizedUrl, future); - new SftpDownloadJob(url, futureInterface); - container.taskManager().registerTask(futureInterface); + new SftpDownloadJob(url, future.promise()); + container.taskManager().registerTask(future); return future; } else throw Exception(tr("URL scheme not supported. The program supports only the sftp:// scheme and local file paths."), &container); @@ -87,9 +75,9 @@ Future FileManager::listDirectoryContents(const QUrl& url) { if(url.scheme() == QStringLiteral("sftp")) { - std::shared_ptr> futureInterface = std::make_shared>(); - new SftpListDirectoryJob(url, futureInterface); - return Future(futureInterface); + Future future = Future::createWithPromise(); + new SftpListDirectoryJob(url, future.promise()); + return future; } else throw Exception(tr("URL scheme not supported. The program supports only the sftp:// scheme and local file paths.")); } diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/io/FileManager.h ovito-2.9.0+dfsg1/src/core/utilities/io/FileManager.h --- ovito-2.8.1+dfsg2/src/core/utilities/io/FileManager.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/io/FileManager.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FILE_MANAGER_H -#define __OVITO_FILE_MANAGER_H +#pragma once + #include #include @@ -36,13 +36,6 @@ public: - /// \brief Returns the one and only instance of this class. - /// \return The predefined instance of the UnitsManager singleton class. - inline static FileManager& instance() { - OVITO_ASSERT_MSG(_instance != nullptr, "FileManager::instance", "Singleton object is not initialized yet."); - return *_instance; - } - /// \brief Makes a file available on this computer. /// \return A QFuture that will provide the local file name of the downloaded file. Future fetchUrl(DataSetContainer& container, const QUrl& url); @@ -90,26 +83,11 @@ QMap _cachedFiles; /// The mutex to synchronize access to above data structures. - QMutex _mutex; + QMutex _mutex{QMutex::Recursive}; /// Cache of login/password information for remote machines. QMap> _credentialCache; -protected: - - /// This is a singleton class. No public instances allowed. - FileManager(); - - /// Create the singleton instance of this class. - static void initialize(FileManager* manager) { _instance = manager; } - - /// Deletes the singleton instance of this class. - static void shutdown() { delete _instance; _instance = nullptr; } - - /// The singleton instance of this class. - static FileManager* _instance; - - friend class Application; friend class SftpDownloadJob; }; @@ -117,4 +95,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_FILE_MANAGER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/io/LoadStream.h ovito-2.9.0+dfsg1/src/core/utilities/io/LoadStream.h --- ovito-2.8.1+dfsg2/src/core/utilities/io/LoadStream.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/io/LoadStream.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::IO::LoadStream class. */ -#ifndef __OVITO_LOADSTREAM_H -#define __OVITO_LOADSTREAM_H +#pragma once + #include @@ -310,4 +310,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_LOADSTREAM_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/io/NumberParsing.h ovito-2.9.0+dfsg1/src/core/utilities/io/NumberParsing.h --- ovito-2.8.1+dfsg2/src/core/utilities/io/NumberParsing.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/io/NumberParsing.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,100 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include + +#include +#include +#include +#include +#include + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(IO) + +/****************************************************************************** + * Helper function that converts a string to a floating-point number. + *****************************************************************************/ +inline bool parseFloatType(const char* s, const char* s_end, float& f) +{ + const char* s_orig = s; // Make a copy, because parse() modifies its argument. + if(!boost::spirit::qi::parse(s, s_end, boost::spirit::qi::float_, f)) { + // Fall back to Boost's lexical cast if Boost.Spirit parser fails (e.g. for very small numbers like 1e-204). +#if BOOST_VERSION >= 105600 + if(!boost::conversion::try_lexical_convert(boost::make_iterator_range(s_orig, s_end), f)) + return false; +#else + try { f = boost::lexical_cast(s_orig, s_end - s_orig); } + catch(const boost::bad_lexical_cast&) { return false; } +#endif + } + return true; +} + +/****************************************************************************** + * Helper function that converts a string to a floating-point number. + *****************************************************************************/ +inline bool parseFloatType(const char* s, const char* s_end, double& f) +{ + const char* s_orig = s; // Make a copy, because parse() modifies its argument. + if(!boost::spirit::qi::parse(s, s_end, boost::spirit::qi::double_, f)) { + // Fall back to Boost's lexical cast if Boost.Spirit parser fails (e.g. for very small numbers like 1e-204). +#if BOOST_VERSION >= 105600 + if(!boost::conversion::try_lexical_convert(boost::make_iterator_range(s_orig, s_end), f)) + return false; +#else + try { f = boost::lexical_cast(s_orig, s_end - s_orig); } + catch(const boost::bad_lexical_cast&) { return false; } +#endif + } + return true; +} + +/****************************************************************************** + * Helper function that converts a string to an integer number. + *****************************************************************************/ +inline bool parseInt(const char* s, const char* s_end, int& i) +{ + return boost::spirit::qi::parse(s, s_end, boost::spirit::qi::int_, i); +} + +/****************************************************************************** + * Helper function that converts a string repr. of a bool ('T' or 'F') to an int + *****************************************************************************/ +inline bool parseBool(const char* s, const char* s_end, int& d) +{ + if(s_end != s + 1) return false; + if(s[0] == 'T') { + d = 1; + return true; + } + else if(s[0] == 'F') { + d = 0; + return true; + } + return false; +} + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/io/ObjectLoadStream.h ovito-2.9.0+dfsg1/src/core/utilities/io/ObjectLoadStream.h --- ovito-2.8.1+dfsg2/src/core/utilities/io/ObjectLoadStream.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/io/ObjectLoadStream.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OBJECT_LOADSTREAM_H -#define __OVITO_OBJECT_LOADSTREAM_H +#pragma once + #include #include @@ -143,4 +143,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OBJECT_LOADSTREAM_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/io/ObjectSaveStream.cpp ovito-2.9.0+dfsg1/src/core/utilities/io/ObjectSaveStream.cpp --- ovito-2.8.1+dfsg2/src/core/utilities/io/ObjectSaveStream.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/io/ObjectSaveStream.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -37,8 +37,9 @@ try { close(); } - catch(const Exception& ex) { - ex.showError(); + catch(Exception& ex) { + if(!ex.context()) ex.setContext(_dataset); + ex.reportError(); } } diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/io/ObjectSaveStream.h ovito-2.9.0+dfsg1/src/core/utilities/io/ObjectSaveStream.h --- ovito-2.8.1+dfsg2/src/core/utilities/io/ObjectSaveStream.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/io/ObjectSaveStream.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OBJECT_SAVESTREAM_H -#define __OVITO_OBJECT_SAVESTREAM_H +#pragma once + #include #include "SaveStream.h" @@ -77,4 +77,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OBJECT_SAVESTREAM_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/io/SaveStream.h ovito-2.9.0+dfsg1/src/core/utilities/io/SaveStream.h --- ovito-2.8.1+dfsg2/src/core/utilities/io/SaveStream.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/io/SaveStream.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::IO::SaveStream class. */ -#ifndef __OVITO_SAVESTREAM_H -#define __OVITO_SAVESTREAM_H +#pragma once + #include @@ -228,4 +228,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_SAVESTREAM_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/io/SftpJob.cpp ovito-2.9.0+dfsg1/src/core/utilities/io/SftpJob.cpp --- ovito-2.8.1+dfsg2/src/core/utilities/io/SftpJob.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/io/SftpJob.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,6 +22,7 @@ #include #include #include +#include #include "SftpJob.h" @@ -38,8 +39,8 @@ /****************************************************************************** * Constructor. ******************************************************************************/ -SftpJob::SftpJob(const QUrl& url, const std::shared_ptr& futureInterface) : - _url(url), _connection(nullptr), _futureInterface(futureInterface), _isActive(false) +SftpJob::SftpJob(const QUrl& url, const PromiseBasePtr& promise) : + _url(url), _connection(nullptr), _promise(promise), _isActive(false) { // Run all event handlers of this class in the main thread. moveToThread(QCoreApplication::instance()->thread()); @@ -67,10 +68,10 @@ } // This background task started to run. - _futureInterface->reportStarted(); + _promise->setStarted(); // Check if process has already been canceled. - if(_futureInterface->isCanceled()) { + if(_promise->isCanceled()) { shutdown(false); return; } @@ -80,7 +81,7 @@ connectionParams.userName = _url.userName(); connectionParams.password = _url.password(); if(connectionParams.userName.isEmpty() || connectionParams.password.isEmpty()) { - QPair credentials = FileManager::instance().findCredentials(connectionParams.host); + QPair credentials = Application::instance()->fileManager()->findCredentials(connectionParams.host); if(credentials.first.isEmpty() == false) { connectionParams.userName = credentials.first; connectionParams.password = credentials.second; @@ -91,7 +92,7 @@ connectionParams.options &= ~QSsh::SshEnableStrictConformanceChecks; connectionParams.timeout = 10; - _futureInterface->setProgressText(tr("Connecting to remote server %1").arg(_url.host())); + _promise->setProgressText(tr("Connecting to remote server %1").arg(_url.host())); // Open connection _connection = QSsh::acquireConnection(connectionParams); @@ -126,7 +127,7 @@ _connection = nullptr; } - _futureInterface->reportFinished(); + _promise->setFinished(); // Update the counter of active jobs. if(_isActive) { @@ -140,12 +141,12 @@ // If there are now less jobs active simultaneously, execute one of the waiting jobs. if(_numActiveJobs < MaximumNumberOfSimulateousSftpJobs && !_queuedJobs.isEmpty()) { SftpJob* waitingJob = _queuedJobs.dequeue(); - if(waitingJob->_futureInterface->isCanceled() == false) { + if(waitingJob->_promise->isCanceled() == false) { waitingJob->start(); } else { // Skip canceled jobs. - waitingJob->_futureInterface->reportStarted(); + waitingJob->_promise->setStarted(); waitingJob->shutdown(false); } } @@ -157,9 +158,9 @@ void SftpJob::onSshConnectionError(QSsh::SshError error) { // If authentication failed, ask the user to re-enter username/password. - if(error == QSsh::SshAuthenticationError && !_futureInterface->isCanceled()) { + if(error == QSsh::SshAuthenticationError && !_promise->isCanceled()) { OVITO_ASSERT(!_sftpChannel); - if(FileManager::instance().askUserForCredentials(_url)) { + if(Application::instance()->fileManager()->askUserForCredentials(_url)) { // Start over with new login information. QObject::disconnect(_connection, 0, this, 0); QSsh::releaseConnection(_connection); @@ -168,7 +169,7 @@ return; } else { - _futureInterface->cancel(); + _promise->cancel(); } } else { @@ -177,7 +178,7 @@ arg(_connection->errorString())); } catch(Exception&) { - _futureInterface->reportException(); + _promise->setException(); } } shutdown(false); @@ -188,16 +189,16 @@ ******************************************************************************/ void SftpJob::onSshConnectionEstablished() { - if(_futureInterface->isCanceled()) { + if(_promise->isCanceled()) { shutdown(false); return; } // After successful login, store login information in cache. QSsh::SshConnectionParameters connectionParams = _connection->connectionParameters(); - FileManager::instance().cacheCredentials(connectionParams.host, connectionParams.userName, connectionParams.password); + Application::instance()->fileManager()->cacheCredentials(connectionParams.host, connectionParams.userName, connectionParams.password); - _futureInterface->setProgressText(tr("Opening SFTP file transfer channel.")); + _promise->setProgressText(tr("Opening SFTP file transfer channel")); _sftpChannel = _connection->createSftpChannel(); connect(_sftpChannel.data(), &QSsh::SftpChannel::initialized, this, &SftpJob::onSftpChannelInitialized); @@ -210,12 +211,7 @@ ******************************************************************************/ void SftpJob::onSftpChannelError(const QString& reason) { - try { - throw Exception(tr("Cannot access URL\n\n%1\n\nSFTP error: %2").arg(_url.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded)).arg(reason)); - } - catch(Exception&) { - _futureInterface->reportException(); - } + _promise->setException(std::make_exception_ptr(Exception(tr("Cannot access URL\n\n%1\n\nSFTP error: %2").arg(_url.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded)).arg(reason)))); shutdown(false); } @@ -228,13 +224,13 @@ killTimer(_timerId); if(_localFile && success) - static_cast*>(_futureInterface.get())->setResult(_localFile->fileName()); + static_cast*>(_promise.get())->setResult(_localFile->fileName()); else _localFile.reset(); SftpJob::shutdown(success); - FileManager::instance().fileFetched(_url, _localFile.take()); + Application::instance()->fileManager()->fileFetched(_url, _localFile.take()); } /****************************************************************************** @@ -242,7 +238,7 @@ ******************************************************************************/ void SftpDownloadJob::onSftpChannelInitialized() { - if(_futureInterface->isCanceled()) { + if(_promise->isCanceled()) { shutdown(false); return; } @@ -252,7 +248,7 @@ try { // Set progress text. - _futureInterface->setProgressText(tr("Fetching remote file %1").arg(_url.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded))); + _promise->setProgressText(tr("Fetching remote file %1").arg(_url.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded))); // Create temporary file. _localFile.reset(new QTemporaryFile()); @@ -272,7 +268,7 @@ _timerId = startTimer(500); } catch(Exception&) { - _futureInterface->reportException(); + _promise->setException(); shutdown(false); } } @@ -284,19 +280,14 @@ if(jobId != _downloadJob) return; - if(_futureInterface->isCanceled()) { + if(_promise->isCanceled()) { shutdown(false); return; } if(!errorMessage.isEmpty()) { - try { - throw Exception(tr("Cannot access URL\n\n%1\n\nSFTP error: %2") + _promise->setException(std::make_exception_ptr(Exception(tr("Cannot access URL\n\n%1\n\nSFTP error: %2") .arg(_url.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded)) - .arg(errorMessage)); - } - catch(Exception&) { - _futureInterface->reportException(); - } + .arg(errorMessage)))); shutdown(false); return; } @@ -310,7 +301,7 @@ { if(fileInfoList.empty() == false ) { if(fileInfoList[0].sizeValid) { - _futureInterface->setProgressRange(fileInfoList[0].size / 1000); + _promise->setProgressMaximum(fileInfoList[0].size / 1000); } } } @@ -324,10 +315,10 @@ if(_localFile) { qint64 size = _localFile->size(); - if(size >= 0 && _futureInterface->progressMaximum() > 0) { - _futureInterface->setProgressValue(size / 1000); + if(size >= 0 && _promise->progressMaximum() > 0) { + _promise->setProgressValue(size / 1000); } - if(_futureInterface->isCanceled()) + if(_promise->isCanceled()) shutdown(false); } } @@ -337,7 +328,7 @@ ******************************************************************************/ void SftpListDirectoryJob::onSftpChannelInitialized() { - if(_futureInterface->isCanceled()) { + if(_promise->isCanceled()) { shutdown(false); return; } @@ -346,7 +337,7 @@ connect(_sftpChannel.data(), &QSsh::SftpChannel::fileInfoAvailable, this, &SftpListDirectoryJob::onFileInfoAvailable); try { // Set progress text. - _futureInterface->setProgressText(tr("Listing remote directory %1").arg(_url.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded))); + _promise->setProgressText(tr("Listing remote directory %1").arg(_url.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded))); // Request file list. _listingJob = _sftpChannel->listDirectory(_url.path()); @@ -354,7 +345,7 @@ throw Exception(tr("Failed to list contents of remote directory %1.").arg(_url.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded))); } catch(Exception&) { - _futureInterface->reportException(); + _promise->setException(); shutdown(false); } } @@ -366,24 +357,19 @@ if(jobId != _listingJob) return; - if(_futureInterface->isCanceled()) { + if(_promise->isCanceled()) { shutdown(false); return; } if(!errorMessage.isEmpty()) { - try { - throw Exception(tr("Cannot access URL\n\n%1\n\nSFTP error: %2") + _promise->setException(std::make_exception_ptr(Exception(tr("Cannot access URL\n\n%1\n\nSFTP error: %2") .arg(_url.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded)) - .arg(errorMessage)); - } - catch(Exception&) { - _futureInterface->reportException(); - } + .arg(errorMessage)))); shutdown(false); return; } - static_cast*>(_futureInterface.get())->setResult(_fileList); + static_cast*>(_promise.get())->setResult(_fileList); shutdown(true); } diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/io/SftpJob.h ovito-2.9.0+dfsg1/src/core/utilities/io/SftpJob.h --- ovito-2.8.1+dfsg2/src/core/utilities/io/SftpJob.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/io/SftpJob.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SFTP_JOB_H -#define __OVITO_SFTP_JOB_H +#pragma once + #include #include @@ -45,7 +45,7 @@ public: /// Constructor. - SftpJob(const QUrl& url, const std::shared_ptr& futureInterface); + SftpJob(const QUrl& url, const PromiseBasePtr& promise); /// Destructor. virtual ~SftpJob() { @@ -93,7 +93,7 @@ QSsh::SftpChannel::Ptr _sftpChannel; /// The associated future interface of the job. - std::shared_ptr _futureInterface; + PromiseBasePtr _promise; /// Indicates whether this SFTP job is currently active. bool _isActive; @@ -115,8 +115,8 @@ public: /// Constructor. - SftpDownloadJob(const QUrl& url, const std::shared_ptr>& futureInterface) : - SftpJob(url, futureInterface), _timerId(0) {} + SftpDownloadJob(const QUrl& url, const PromisePtr& promise) : + SftpJob(url, promise), _timerId(0) {} protected: @@ -159,8 +159,8 @@ public: /// Constructor. - SftpListDirectoryJob(const QUrl& url, const std::shared_ptr>& futureInterface) : - SftpJob(url, futureInterface) {} + SftpListDirectoryJob(const QUrl& url, const PromisePtr& promise) : + SftpJob(url, promise) {} protected: @@ -189,4 +189,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_SFTP_JOB_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/io/video/VideoEncoder.cpp ovito-2.9.0+dfsg1/src/core/utilities/io/video/VideoEncoder.cpp --- ovito-2.8.1+dfsg2/src/core/utilities/io/video/VideoEncoder.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/io/video/VideoEncoder.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,10 +29,6 @@ #include }; -#if LIBAVCODEC_VERSION_MAJOR >= 55 - #define CODEC_ID_NONE AV_CODEC_ID_NONE -#endif - namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(IO) OVITO_BEGIN_INLINE_NAMESPACE(Internal) /// The list of supported video formats. @@ -52,7 +48,10 @@ void VideoEncoder::initCodecs() { static std::once_flag initFlag; - std::call_once(initFlag, []() { av_register_all(); }); + std::call_once(initFlag, []() { + av_register_all(); + avcodec_register_all(); + }); } /****************************************************************************** @@ -62,7 +61,7 @@ { char errbuf[256]; if(av_strerror(errorCode, errbuf, sizeof(errbuf)) < 0) { - return QString("Unknown FFmpeg error."); + return QString("Unknown Libav error."); } return QString::fromLocal8Bit(errbuf); } @@ -89,7 +88,7 @@ format.extensions = QString::fromLocal8Bit(fmt->extensions).split(','); format.avformat = fmt; - if(format.name != "mov" && format.name != "mp4" && format.name != "webm" && format.name != "avi" && format.name != "gif") + if(format.name != "mov" && format.name != "mp4" && format.name != "avi" && format.name != "gif") continue; _supportedFormats.push_back(format); @@ -111,7 +110,7 @@ AVOutputFormat* outputFormat; if(format == nullptr) { // Auto detect the output format from the file name. - outputFormat = av_guess_format(NULL, filename.toLocal8Bit().constData(), NULL); + outputFormat = av_guess_format(NULL, qPrintable(filename), NULL); if(!outputFormat) throw Exception(tr("Could not deduce video output format from file extension.")); } @@ -123,17 +122,29 @@ throw Exception(tr("Failed to allocate output media context.")); _formatContext->oformat = outputFormat; - qstrncpy(_formatContext->filename, filename.toLocal8Bit().constData(), sizeof(_formatContext->filename) - 1); + qstrncpy(_formatContext->filename, qPrintable(filename), sizeof(_formatContext->filename) - 1); - if(outputFormat->video_codec == CODEC_ID_NONE) + if(outputFormat->video_codec == AV_CODEC_ID_NONE) throw Exception(tr("No video codec available.")); + // Find the video encoder. + AVCodec* codec = avcodec_find_encoder(outputFormat->video_codec); + if(!codec) + throw Exception(tr("Video codec not found.")); + // Add the video stream using the default format codec and initialize the codec. - _videoStream = avformat_new_stream(_formatContext.get(), NULL); + _videoStream = avformat_new_stream(_formatContext.get(), codec); if(!_videoStream) throw Exception(tr("Failed to create video stream.")); - _codecContext = _videoStream->codec; +#if LIBAVCODEC_VERSION_MAJOR >= 57 + _codecContext.reset(avcodec_alloc_context3(codec), [](AVCodecContext* ctxt) { avcodec_free_context(&ctxt); }); + if(!_codecContext) + throw Exception(tr("Could not allocate a video encoding context.")); +#else + _codecContext.reset(_videoStream->codec, [](AVCodecContext*) {}); +#endif + _codecContext->codec_id = outputFormat->video_codec; _codecContext->codec_type = AVMEDIA_TYPE_VIDEO; _codecContext->qmin = 4; @@ -141,8 +152,8 @@ _codecContext->bit_rate = 0; _codecContext->width = width; _codecContext->height = height; - _codecContext->time_base.den = _videoStream->time_base.den = fps; _codecContext->time_base.num = _videoStream->time_base.num = 1; + _codecContext->time_base.den = _videoStream->time_base.den = fps; _codecContext->gop_size = 12; // Emit one intra frame every twelve frames at most. if(qstrcmp(outputFormat->name, "gif") != 0) _codecContext->pix_fmt = AV_PIX_FMT_YUV420P; @@ -153,15 +164,10 @@ if(_formatContext->oformat->flags & AVFMT_GLOBALHEADER) _codecContext->flags |= CODEC_FLAG_GLOBAL_HEADER; - // Find the video encoder. - AVCodec* codec = avcodec_find_encoder(_codecContext->codec_id); - if(!codec) - throw Exception(tr("Video codec not found.")); - - av_dump_format(_formatContext.get(), 0, filename.toLocal8Bit().constData(), 1); + av_dump_format(_formatContext.get(), 0, _formatContext->filename, 1); // Open the codec. - if((errCode = avcodec_open2(_codecContext, codec, NULL)) < 0) + if((errCode = avcodec_open2(_codecContext.get(), NULL, NULL)) < 0) throw Exception(tr("Could not open video codec: %1").arg(errorMessage(errCode))); // Allocate and init a YUV frame. @@ -185,12 +191,13 @@ // Open output file (if needed). if(!(outputFormat->flags & AVFMT_NOFILE)) { - if(avio_open(&_formatContext->pb, filename.toLocal8Bit().constData(), AVIO_FLAG_WRITE) < 0) + if(avio_open(&_formatContext->pb, _formatContext->filename, AVIO_FLAG_WRITE) < 0) throw Exception(tr("Failed to open output video file %1").arg(filename)); } // Write stream header, if any. - avformat_write_header(_formatContext.get(), NULL); + if((errCode = avformat_write_header(_formatContext.get(), NULL)) < 0) + throw Exception(tr("Failed to write video file header: %1").arg(errorMessage(errCode))); // Success. _isOpen = true; @@ -211,9 +218,10 @@ av_write_trailer(_formatContext.get()); // Close codec. - if(_videoStream) - avcodec_close(_videoStream->codec); + if(_codecContext) + avcodec_close(_codecContext.get()); +#if LIBAVCODEC_VERSION_MAJOR < 57 // Free streams. if(_formatContext) { for(size_t i = 0; i < _formatContext->nb_streams; i++) { @@ -221,6 +229,7 @@ av_freep(&_formatContext->streams[i]); } } +#endif // Close the output file. if(_formatContext->pb) @@ -230,7 +239,7 @@ _pictureBuf.reset(); _frame.reset(); _videoStream = nullptr; - _codecContext = nullptr; + _codecContext.reset(); _outputBuf.clear(); _formatContext.reset(); _isOpen = false; @@ -296,7 +305,7 @@ AVPacket pkt = {0}; av_init_packet(&pkt); - if(avcodec_encode_video2(_codecContext, &pkt, _frame.get(), &got_packet_ptr) < 0) + if(avcodec_encode_video2(_codecContext.get(), &pkt, _frame.get(), &got_packet_ptr) < 0) throw Exception(tr("Error while encoding video frame.")); if(got_packet_ptr && pkt.size) { diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/io/video/VideoEncoder.h ovito-2.9.0+dfsg1/src/core/utilities/io/video/VideoEncoder.h --- ovito-2.8.1+dfsg2/src/core/utilities/io/video/VideoEncoder.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/io/video/VideoEncoder.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VIDEO_ENCODER_H -#define __OVITO_VIDEO_ENCODER_H +#pragma once + #include @@ -88,7 +88,7 @@ std::vector _outputBuf; std::shared_ptr _frame; AVStream* _videoStream; - AVCodecContext* _codecContext; + std::shared_ptr _codecContext; SwsContext* _imgConvertCtx; bool _isOpen; @@ -103,4 +103,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_VIDEO_ENCODER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/AffineDecomposition.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/AffineDecomposition.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/AffineDecomposition.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/AffineDecomposition.h 2017-07-27 16:52:45.000000000 +0000 @@ -27,8 +27,8 @@ * \brief Contains the definition of the Ovito::AffineDecomposition class. */ -#ifndef __OVITO_AFFINE_DECOMP_H -#define __OVITO_AFFINE_DECOMP_H +#pragma once + #include #include "Vector3.h" @@ -83,4 +83,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_AFFINE_DECOMP_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/AffineTransformation.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/AffineTransformation.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/AffineTransformation.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/AffineTransformation.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::AffineTransformationT class template. */ -#ifndef __OVITO_AFFINE_TRANSFORMATION_H -#define __OVITO_AFFINE_TRANSFORMATION_H +#pragma once + #include #include @@ -830,4 +830,4 @@ Q_DECLARE_TYPEINFO(Ovito::AffineTransformation, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::AffineTransformation*, Q_PRIMITIVE_TYPE); -#endif // __OVITO_AFFINE_TRANSFORMATION_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/Box2.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/Box2.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/Box2.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/Box2.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::Box_2 class template. */ -#ifndef __OVITO_BOX2_H -#define __OVITO_BOX2_H +#pragma once + #include #include @@ -311,4 +311,4 @@ Q_DECLARE_TYPEINFO(Ovito::Box2*, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(Ovito::Box2I*, Q_MOVABLE_TYPE); -#endif // __OVITO_BOX2_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/Box3.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/Box3.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/Box3.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/Box3.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::Box_3 class template. */ -#ifndef __OVITO_BOX3_H -#define __OVITO_BOX3_H +#pragma once + #include #include @@ -355,4 +355,4 @@ Q_DECLARE_TYPEINFO(Ovito::Box3*, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(Ovito::Box3I*, Q_MOVABLE_TYPE); -#endif // __OVITO_BOX3_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/LinAlg.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/LinAlg.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/LinAlg.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/LinAlg.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief This high-level header file includes other headers to import the most important linear algebra classes. */ -#ifndef __OVITO_LINALG_H -#define __OVITO_LINALG_H +#pragma once + #include @@ -46,4 +46,4 @@ #include "Plane.h" #include "SymmetricTensor.h" -#endif // __OVITO_LINALG_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/Matrix3.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/Matrix3.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/Matrix3.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/Matrix3.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::Matrix_3 class template. */ -#ifndef __OVITO_MATRIX3_H -#define __OVITO_MATRIX3_H +#pragma once + #include #include @@ -768,4 +768,4 @@ Q_DECLARE_TYPEINFO(Ovito::Matrix3, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::Matrix3*, Q_PRIMITIVE_TYPE); -#endif // __OVITO_MATRIX3_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/Matrix4.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/Matrix4.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/Matrix4.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/Matrix4.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::Matrix_4 class template. */ -#ifndef __OVITO_MATRIX4_H -#define __OVITO_MATRIX4_H +#pragma once + #include #include @@ -597,4 +597,4 @@ Q_DECLARE_TYPEINFO(Ovito::Matrix4, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::Matrix4*, Q_PRIMITIVE_TYPE); -#endif // __OVITO_MATRIX4_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/Plane.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/Plane.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/Plane.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/Plane.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::Plane_3 class template. */ -#ifndef __OVITO_PLANE_H -#define __OVITO_PLANE_H +#pragma once + #include #include @@ -321,4 +321,4 @@ Q_DECLARE_TYPEINFO(Ovito::Plane3, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::Plane3*, Q_PRIMITIVE_TYPE); -#endif // __OVITO_PLANE_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/Point2.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/Point2.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/Point2.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/Point2.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::Point_2 class template. */ -#ifndef __OVITO_POINT2_H -#define __OVITO_POINT2_H +#pragma once + #include #include @@ -350,4 +350,4 @@ Q_DECLARE_TYPEINFO(Ovito::Point2*, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::Point2I*, Q_PRIMITIVE_TYPE); -#endif // __OVITO_POINT2_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/Point3.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/Point3.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/Point3.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/Point3.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::Point_3 class template. */ -#ifndef __OVITO_POINT3_H -#define __OVITO_POINT3_H +#pragma once + #include #include @@ -375,4 +375,4 @@ Q_DECLARE_TYPEINFO(Ovito::Point3*, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::Point3I*, Q_PRIMITIVE_TYPE); -#endif // __OVITO_POINT3_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/Quaternion.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/Quaternion.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/Quaternion.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/Quaternion.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::QuaternionT class template. */ -#ifndef __OVITO_QUATERNION_H -#define __OVITO_QUATERNION_H +#pragma once + #include #include @@ -490,4 +490,4 @@ Q_DECLARE_TYPEINFO(Ovito::Quaternion, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::Quaternion*, Q_PRIMITIVE_TYPE); -#endif // __OVITO_QUATERNION_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/Ray.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/Ray.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/Ray.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/Ray.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::Ray_3 class template. */ -#ifndef __OVITO_RAY_H -#define __OVITO_RAY_H +#pragma once + #include #include @@ -178,4 +178,4 @@ Q_DECLARE_TYPEINFO(Ovito::Ray3, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::Ray3*, Q_PRIMITIVE_TYPE); -#endif // __OVITO_RAY_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/Rotation.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/Rotation.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/Rotation.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/Rotation.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::RotationT class template. */ -#ifndef __OVITO_ROTATION_H -#define __OVITO_ROTATION_H +#pragma once + #include #include @@ -567,4 +567,4 @@ Q_DECLARE_TYPEINFO(Ovito::Rotation, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::Rotation*, Q_PRIMITIVE_TYPE); -#endif // __OVITO_ROTATION_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/Scaling.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/Scaling.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/Scaling.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/Scaling.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::ScalingT class template. */ -#ifndef __OVITO_SCALING_H -#define __OVITO_SCALING_H +#pragma once + #include #include @@ -240,4 +240,4 @@ Q_DECLARE_TYPEINFO(Ovito::Scaling, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::Scaling*, Q_PRIMITIVE_TYPE); -#endif // __OVITO_SCALING_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/SymmetricTensor.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/SymmetricTensor.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/SymmetricTensor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/SymmetricTensor.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::SymmetricTensor2T class template. */ -#ifndef __OVITO_SYMMETRIC_TENSOR_H -#define __OVITO_SYMMETRIC_TENSOR_H +#pragma once + #include #include @@ -330,4 +330,4 @@ Q_DECLARE_TYPEINFO(Ovito::SymmetricTensor2, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::SymmetricTensor2*, Q_PRIMITIVE_TYPE); -#endif // __OVITO_SYMMETRIC_TENSOR_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/Vector2.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/Vector2.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/Vector2.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/Vector2.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::Vector_2 class template. */ -#ifndef __OVITO_VECTOR2_H -#define __OVITO_VECTOR2_H +#pragma once + #include #include @@ -389,4 +389,4 @@ Q_DECLARE_TYPEINFO(Ovito::Vector2*, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::Vector2I*, Q_PRIMITIVE_TYPE); -#endif // __OVITO_VECTOR2_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/Vector3.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/Vector3.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/Vector3.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/Vector3.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::Vector_3 class template. */ -#ifndef __OVITO_VECTOR3_H -#define __OVITO_VECTOR3_H +#pragma once + #include #include @@ -437,4 +437,4 @@ Q_DECLARE_TYPEINFO(Ovito::Vector3*, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::Vector3I*, Q_PRIMITIVE_TYPE); -#endif // __OVITO_VECTOR3_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/linalg/Vector4.h ovito-2.9.0+dfsg1/src/core/utilities/linalg/Vector4.h --- ovito-2.8.1+dfsg2/src/core/utilities/linalg/Vector4.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/linalg/Vector4.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::Vector_4 class template. */ -#ifndef __OVITO_VECTOR4_H -#define __OVITO_VECTOR4_H +#pragma once + #include #include @@ -382,4 +382,4 @@ Q_DECLARE_TYPEINFO(Ovito::Vector4*, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::Vector4I*, Q_PRIMITIVE_TYPE); -#endif // __OVITO_VECTOR4_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/MemoryPool.h ovito-2.9.0+dfsg1/src/core/utilities/MemoryPool.h --- ovito-2.8.1+dfsg2/src/core/utilities/MemoryPool.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/MemoryPool.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::MemoryPool class template. */ -#ifndef __OVITO_MEMORY_POOL_H -#define __OVITO_MEMORY_POOL_H +#pragma once + #include @@ -121,8 +121,8 @@ std::allocator _alloc; }; -OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_MEMORY_POOL_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/mesh/HalfEdgeMesh_EdgeCollapse.h ovito-2.9.0+dfsg1/src/core/utilities/mesh/HalfEdgeMesh_EdgeCollapse.h --- ovito-2.8.1+dfsg2/src/core/utilities/mesh/HalfEdgeMesh_EdgeCollapse.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/mesh/HalfEdgeMesh_EdgeCollapse.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,681 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include "HalfEdgeMesh.h" + +#include +#include + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Mesh) + +/// Default implementation of a functor that calculates the vector between to spatial points. +struct DefaultPointPointVector +{ + Vector3 operator()(const Point3& p0, const Point3& p1) const { + return p1 - p0; + } +}; + +/// Default implementation of a functor that validates an edge vector. +struct DefaultEdgeVectorValidation +{ + bool operator()(const Vector3& v) const { + return true; + } +}; + +/****************************************************************************** +* Algorithm that reduces the number of faces/edges/vertices of a HalfEdgeMesh +* structure using an edge collapse strategy. +* +* See "Fast and Memory Efficient Polygonal Simplification" +* by Peter Lindstrom and Greg Turk. +* +* This implementation only supports closed manifold meshes made of +* triangle faces. +******************************************************************************/ +template +class EdgeCollapseMeshSimplification +{ +public: + + using Face = typename HEM::Face; + using Edge = typename HEM::Edge; + using Vertex = typename HEM::Vertex; + + /// Constructor. + EdgeCollapseMeshSimplification(HEM& mesh, PointPointVector ppvec = PointPointVector(), EdgeVectorValidation edgeValidation = EdgeVectorValidation()) : + _mesh(mesh), _ppvec(std::move(ppvec)), _edgeValidation(std::move(edgeValidation)) {} + + bool perform(FloatType minEdgeLength, PromiseBase& promise) + { + // Current implementation can only handle closed manifolds. + OVITO_ASSERT(_mesh.isClosed()); + + promise.beginProgressSubSteps(2); + + // First collect all candidate edges in a priority queue + if(!collect(promise)) + return false; + + promise.nextProgressSubStep(); + + // Then proceed to collapse each edge in turn. + if(!loop(minEdgeLength, promise)) + return false; + + promise.endProgressSubSteps(); + + return !promise.isCanceled(); + } + +private: + + /// Used to decide whether a half-edge is the primary half-edge of a pair. + bool edgeSense(const Vector3& v) const + { + if(v.x() >= FLOATTYPE_EPSILON) return true; + else if(v.x() <= -FLOATTYPE_EPSILON) return false; + if(v.y() >= FLOATTYPE_EPSILON) return true; + else if(v.y() <= -FLOATTYPE_EPSILON) return false; + return v.z() > 0; + } + + /// Collects all candidate edges. + bool collect(PromiseBase& promise) + { + promise.setProgressMaximum(_mesh.faceCount()); + + // Insert edges into priority queue. + _pqHandles.clear(); + for(Face* face : _mesh.faces()) { + Edge* edge = face->edges(); + do { + // Skip every other half-edge. + if(edge->oppositeEdge() == nullptr || edgeSense(_ppvec(edge->vertex1()->pos(), edge->vertex2()->pos()))) { + boost::optional placement = computePlacement(edge); + FloatType cost = placement ? computeCost(edge, *placement) : -1; + _pqHandles.insert(std::make_pair(edge, _pq.push({ edge, cost }))); + } + edge = edge->nextFaceEdge(); + } + while(edge != face->edges()); + + if(!promise.incrementProgressValue()) + return false; + } + + return true; + } + + /// Collapses edges in order of priority. + bool loop(FloatType minEdgeLength, PromiseBase& promise) + { + promise.setProgressMaximum(_pq.size()); + + // Pop and processe each edge from the PQ. + size_t collapsedEdges = 0; + while(!_pq.empty()) { + if(!promise.incrementProgressValue()) + return false; + + Edge* edge = _pq.top().edge; + FloatType cost = _pq.top().cost; + _pq.pop(); + _pqHandles.erase(edge); + + // Stopping criterion: + if(_ppvec(edge->vertex1()->pos(), edge->vertex2()->pos()).squaredLength() > minEdgeLength*minEdgeLength) + break; + + if(cost >= 0) { + boost::optional placement = computePlacement(edge); + if(placement && isCollapseTopologicallyValid(edge, edge->vertex2()->pos() + *placement)) { + collapse(edge, *placement); + collapsedEdges++; + } + } + } + promise.setProgressValue(promise.progressMaximum()); + + // Remove faces and vertices which were marked for deletion. + for(int f = _mesh.faceCount() - 1; f >= 0; f--) { + if(_mesh.faces()[f]->edges() == nullptr) + _mesh.removeFace(f); + } + for(int v = _mesh.vertexCount() - 1; v >= 0; v--) { + if(_mesh.vertices()[v]->numEdges() == 0) + _mesh.removeVertex(v); + } + + // Need to assigne new indices to vertices and faces after some of the have been deleted. + _mesh.reindexVerticesAndFaces(); + + return true; + } + + /// Calls a callback function on all faces which are adjacent on the two vertices of the given edge. + template + void visitAdjacentTriangles(Edge* edge, Callback callback) const + { + // Go around first vertex. + OVITO_ASSERT(edge->oppositeEdge() && edge->oppositeEdge()->nextFaceEdge()); + Edge* currentEdge = edge; + Edge* stopEdge = edge->oppositeEdge()->nextFaceEdge(); + do { + callback(currentEdge); + currentEdge = currentEdge->prevFaceEdge()->oppositeEdge(); + OVITO_ASSERT(currentEdge); + } + while(currentEdge != stopEdge); + + // Go around second vertex. + edge = edge->oppositeEdge(); + OVITO_ASSERT(edge && edge->oppositeEdge()->nextFaceEdge()); + currentEdge = edge; + stopEdge = edge->oppositeEdge()->nextFaceEdge(); + do { + callback(currentEdge); + currentEdge = currentEdge->prevFaceEdge()->oppositeEdge(); + OVITO_ASSERT(currentEdge); + } + while(currentEdge != stopEdge); + } + + /// Calls a callback function on all vertices which are adjacent on the two vertices of the given edge. + template + void visitLink(Edge* edge, Callback callback) const + { + // Go around first vertex. + OVITO_ASSERT(edge->oppositeEdge() && edge->oppositeEdge()->nextFaceEdge()); + Edge* currentEdge = edge->prevFaceEdge()->oppositeEdge(); + Edge* stopEdge = edge->oppositeEdge()->nextFaceEdge(); + do { + callback(currentEdge->vertex2()); + currentEdge = currentEdge->prevFaceEdge()->oppositeEdge(); + OVITO_ASSERT(currentEdge); + } + while(currentEdge != stopEdge); + + // Go around second vertex. + edge = edge->oppositeEdge(); + OVITO_ASSERT(edge && edge->oppositeEdge()->nextFaceEdge()); + currentEdge = edge->prevFaceEdge()->oppositeEdge(); + stopEdge = edge->oppositeEdge()->nextFaceEdge(); + do { + callback(currentEdge->vertex2()); + currentEdge = currentEdge->prevFaceEdge()->oppositeEdge(); + OVITO_ASSERT(currentEdge); + } + while(currentEdge != stopEdge); + } + + /// Each vertex constraint is an equation of the form: Ai * v = bi + /// Where 'v' is a vector representing the vertex, + /// 'Ai' is a (row) vector and 'bi' a scalar. + /// + /// The vertex is completely determined by 3 such constraints, + /// so is the solution to the following system: + /// + /// A.row(0) * v = b0 + /// A.row(1) * v = b1 + /// A.row(2) * v = b2 + /// + /// Which in matrix form is: A * v = b + /// + /// (with 'A' a 3x3 matrix and 'b' a vector) + /// + /// The member variables contain A and b. Individual constraints (Ai,bi) can be added to it. + /// Once 3 such constraints have been added, 'v' is directly solved as: + /// + /// v = inv(A) * b + /// + /// A constraint (Ai,bi) must be alpha-compatible with the previously added constraints (see paper); otherwise, it's discarded. + struct Constraints + { + int numConstraints = 0; + Matrix3 constraintsA = Matrix3::Zero(); + Vector3 constraintsB = Vector3::Zero(); + + void addConstraintIfAlphaCompatible(const Vector3& Ai, FloatType bi) + { + OVITO_ASSERT(numConstraints < 3); + FloatType slai = Ai.squaredLength(); + if(slai == 0) return; + FloatType l = std::sqrt(slai); + + Vector3 Ain = Ai / l; + FloatType bin = bi / l; + if(numConstraints == 1) { + FloatType d01 = constraintsA.column(0).dot(Ai); + FloatType sla0 = constraintsA.column(0).squaredLength(); + FloatType sd01 = d01 * d01; + FloatType max = sla0 * slai * mcMaxDihedralAngleCos2; + if(sd01 > max) + return; + } + else if(numConstraints == 2) { + Vector3 N = constraintsA.column(0).cross(constraintsA.column(1)); + FloatType dc012 = N.dot(Ai); + FloatType slc01 = N.squaredLength(); + FloatType sdc012 = dc012 * dc012; + FloatType min = slc01 * slai * mcMaxDihedralAngleSin2; + if(sdc012 <= min) + return; + } + + constraintsA.column(numConstraints) = Ain; + constraintsB[numConstraints] = bin; + ++numConstraints; + } + + void addConstraintFromGradient(const Matrix3& H, const Vector3& c) + { + OVITO_ASSERT(numConstraints >= 0 && numConstraints < 3); + switch(numConstraints) + { + case 0: + addConstraintIfAlphaCompatible(H.column(0), -c.x()); + addConstraintIfAlphaCompatible(H.column(1), -c.y()); + addConstraintIfAlphaCompatible(H.column(2), -c.z()); + break; + + case 1: + { + const Vector3& A0 = constraintsA.column(0); + OVITO_ASSERT(A0 != Vector3::Zero()); + + Vector3 AbsA0(std::abs(A0.x()), std::abs(A0.y()), std::abs(A0.z())); + + Vector3 Q0; + switch(AbsA0.maxComponent()) + { + // Since A0 is guaranteed to be non-zero, the denominators here are known to be non-zero too. + case 0: Q0 = Vector3(-A0.z()/A0.x(),0 ,1 ); break; + case 1: Q0 = Vector3(0 ,-A0.z()/A0.y(),1 ); break; + case 2: Q0 = Vector3(1 ,0 ,-A0.x()/A0.z()); break; + default: Q0.setZero(); // This should never happen! + } + Vector3 Q1 = A0.cross(Q0); + Vector3 A1 = H * Q0; + Vector3 A2 = H * Q1; + + FloatType b1 = -Q0.dot(c); + FloatType b2 = -Q1.dot(c); + + addConstraintIfAlphaCompatible(A1,b1); + addConstraintIfAlphaCompatible(A2,b2); + } + break; + + case 2: + { + Vector3 Q = constraintsA.column(0).cross(constraintsA.column(1)); + Vector3 A2 = H * Q; + FloatType b2 = -Q.dot(c); + addConstraintIfAlphaCompatible(A2,b2); + } + break; + } + } + + boost::optional solve() const + { + // It might happen that there were not enough alpha-compatible constraints. + // In that case there is simply no good vertex placement + if(numConstraints != 3) return {}; + + // If the matrix is singular it's inverse cannot be computed so an 'absent' value is returned. + Matrix3 inverseA; + if(!constraintsA.inverse(inverseA)) return {}; + + return inverseA.transposed() * constraintsB; + } + }; + + + boost::optional computePlacement(Edge* edge) const + { + Constraints constraints; + addVolumePreservationConstraints(edge, constraints); + + if(constraints.numConstraints < 3) + addBoundaryAndVolumeOptimizationConstraints(edge, constraints); + + if(constraints.numConstraints < 3) + addShapeOptimizationConstraints(edge, constraints); + + return constraints.solve(); + } + + void addVolumePreservationConstraints(Edge* edge, Constraints& constraints) const + { + Vector3 sumV = Vector3::Zero(); + FloatType sumL = 0; + const Point3& origin = edge->vertex2()->pos(); + visitAdjacentTriangles(edge, [this,&sumV,&sumL,&origin](Edge* faceEdge) { + const Point3& p0 = faceEdge->prevFaceEdge()->vertex1()->pos(); + const Point3& p1 = faceEdge->vertex1()->pos(); + const Point3& p2 = faceEdge->vertex2()->pos(); + Vector3 v01 = _ppvec(p0, p1); + Vector3 v02 = _ppvec(p0, p2); + Vector3 normalV = v01.cross(v02); + // Determinant: + FloatType normalL = _ppvec(origin, p0).cross(_ppvec(origin, p1)).dot(_ppvec(origin, p2)); + sumV += normalV; + sumL += normalL; + }); + constraints.addConstraintIfAlphaCompatible(sumV, sumL); + } + + void addBoundaryAndVolumeOptimizationConstraints(Edge* edge, Constraints& constraints) const + { + Matrix3 H = Matrix3::Zero(); + Vector3 c = Vector3::Zero(); + const Point3& origin = edge->vertex2()->pos(); + visitAdjacentTriangles(edge, [this,&H,&c,&origin](Edge* faceEdge) { + const Point3& p0 = faceEdge->prevFaceEdge()->vertex1()->pos(); + const Point3& p1 = faceEdge->vertex1()->pos(); + const Point3& p2 = faceEdge->vertex2()->pos(); + Vector3 v01 = _ppvec(p0, p1); + Vector3 v02 = _ppvec(p0, p2); + Vector3 normalV = v01.cross(v02); + // Determinant: + FloatType normalL = _ppvec(origin, p0).cross(_ppvec(origin, p1)).dot(_ppvec(origin, p2)); + H.column(0) += normalV * normalV.x(); + H.column(1) += normalV * normalV.y(); + H.column(2) += normalV * normalV.z(); + c -= normalL * normalV; + }); + constraints.addConstraintFromGradient(H,c); + } + + void addShapeOptimizationConstraints(Edge* edge, Constraints& constraints) const + { + Vector3 c = Vector3::Zero(); + int linkCount = 0; + const Point3& origin = edge->vertex2()->pos(); + visitLink(edge, [this,&c,&linkCount,&origin](Vertex* v) { + c -= _ppvec(origin, v->pos()); + linkCount++; + }); + FloatType s = linkCount; + Matrix3 H(s,0,0,0,s,0,0,0,s); + constraints.addConstraintFromGradient(H,c); + } + + /// Computes the costs associated with collapsing the given edge into a single vertex at relative position v. + FloatType computeCost(Edge* edge, const Vector3& v) const + { + const Point3& p0 = edge->vertex1()->pos(); + const Point3& p1 = edge->vertex2()->pos(); + FloatType squaredLength = _ppvec(p0, p1).squaredLength(); + FloatType volumeCost = computeVolumeCost(edge, v); + FloatType shapeCost = computeShapeCost(edge, p1 + v); + + FloatType totalCost = _volumeWeight * volumeCost + + _shapeWeight * shapeCost * squaredLength * squaredLength; + + OVITO_ASSERT(totalCost >= 0); + return std::isfinite(totalCost) ? totalCost : FloatType(-1); + } + + FloatType computeVolumeCost(Edge* edge, const Vector3& v) const + { + FloatType cost = 0; + const Point3& origin = edge->vertex2()->pos(); + visitAdjacentTriangles(edge, [this,&cost,&v,&origin](Edge* faceEdge) { + const Point3& p0 = faceEdge->prevFaceEdge()->vertex1()->pos(); + const Point3& p1 = faceEdge->vertex1()->pos(); + const Point3& p2 = faceEdge->vertex2()->pos(); + Vector3 v01 = _ppvec(p0, p1); + Vector3 v02 = _ppvec(p0, p2); + Vector3 normalV = v01.cross(v02); + // Determinant: + FloatType normalL = _ppvec(origin, p0).cross(_ppvec(origin, p1)).dot(_ppvec(origin, p2)); + FloatType f = normalV.dot(v) - normalL; + cost += f*f; + }); + return cost / 36; + } + + FloatType computeShapeCost(Edge* edge, const Point3& p) const + { + FloatType cost = 0; + visitLink(edge, [this,&p,&cost](Vertex* v) { + cost += _ppvec(p, v->pos()).squaredLength(); + }); + return cost; + } + + /// A collapse is geometrically valid if in the resulting local mesh no two adjacent triangles form an internal dihedral angle + /// greater than a fixed threshold (i.e. triangles do not "fold" into each other). + bool isCollapseTopologicallyValid(Edge* edge, const Point3& k0) const + { + // Go around first vertex. + OVITO_ASSERT(edge->nextFaceEdge()->oppositeEdge()); + OVITO_ASSERT(edge->prevFaceEdge()->oppositeEdge()); + if(!checkLinkTriangles(k0, edge->nextFaceEdge()->oppositeEdge()->prevFaceEdge(), edge->prevFaceEdge()->oppositeEdge()->nextFaceEdge())) + return false; + OVITO_ASSERT(edge->oppositeEdge() && edge->oppositeEdge()->nextFaceEdge()); + OVITO_ASSERT(edge->vertex1()->numEdges() >= 3); + Edge* currentEdge = edge->prevFaceEdge()->oppositeEdge(); + Edge* stopEdge = edge->oppositeEdge()->nextFaceEdge(); + OVITO_ASSERT(stopEdge->oppositeEdge()); + stopEdge = stopEdge->oppositeEdge()->nextFaceEdge(); + while(currentEdge != stopEdge) { + OVITO_ASSERT(currentEdge); + Edge* nextEdge = currentEdge->prevFaceEdge()->oppositeEdge(); + OVITO_ASSERT(nextEdge); + if(!checkLinkTriangles(k0, currentEdge->nextFaceEdge(), nextEdge->nextFaceEdge())) + return false; + currentEdge = nextEdge; + } + + // Go around second vertex. + edge = edge->oppositeEdge(); + OVITO_ASSERT(edge->nextFaceEdge()->oppositeEdge()); + OVITO_ASSERT(edge->prevFaceEdge()->oppositeEdge()); + if(!checkLinkTriangles(k0, edge->nextFaceEdge()->oppositeEdge()->prevFaceEdge(), edge->prevFaceEdge()->oppositeEdge()->nextFaceEdge())) + return false; + OVITO_ASSERT(edge->oppositeEdge() && edge->oppositeEdge()->nextFaceEdge()); + OVITO_ASSERT(edge->vertex1()->numEdges() >= 3); + currentEdge = edge->prevFaceEdge()->oppositeEdge(); + stopEdge = edge->oppositeEdge()->nextFaceEdge(); + OVITO_ASSERT(stopEdge->oppositeEdge()); + stopEdge = stopEdge->oppositeEdge()->nextFaceEdge(); + while(currentEdge != stopEdge) { + OVITO_ASSERT(currentEdge); + Edge* nextEdge = currentEdge->prevFaceEdge()->oppositeEdge(); + OVITO_ASSERT(nextEdge); + if(!checkLinkTriangles(k0, currentEdge->nextFaceEdge(), nextEdge->nextFaceEdge())) + return false; + currentEdge = nextEdge; + } + + return true; + } + + /// Performs the geometric validity test for two consecutive edges along the link of the collapsing edge. + bool checkLinkTriangles(const Point3& k0, Edge* e12, Edge* e23) const + { + OVITO_ASSERT(e12->vertex2() == e23->vertex1()); + + if(!areSharedTrianglesValid(k0, e12->vertex1()->pos(), e12->vertex2()->pos(), e23->vertex2()->pos())) + return false; + + if(e12->oppositeEdge()) { + OVITO_ASSERT(e12->oppositeEdge()->face()); + if(!areSharedTrianglesValid(e12->vertex1()->pos(), e12->oppositeEdge()->nextFaceEdge()->vertex2()->pos(), e12->vertex2()->pos(), k0)) + return false; + } + + return true; + } + + /// Given triangles 'p0,p1,p2' and 'p0,p2,p3', both shared along edge 'v0-v2', + /// determine if they are geometrically valid: that is, the ratio of their + /// respective areas is no greater than a max value and the internal + /// dihedral angle formed by their supporting planes is no greater than + /// a given threshold + bool areSharedTrianglesValid(const Point3& p0, const Point3& p1, const Point3& p2, const Point3& p3) const + { + Vector3 e01 = _ppvec(p0, p1); + Vector3 e02 = _ppvec(p0, p2); + Vector3 e03 = _ppvec(p0, p3); + if(!_edgeValidation(e01)) return false; + if(!_edgeValidation(e02)) return false; + if(!_edgeValidation(e03)) return false; + + Vector3 n012 = e01.cross(e02); + Vector3 n023 = e02.cross(e03); + + FloatType l012 = n012.dot(n012); + FloatType l023 = n023.dot(n023); + + FloatType larger = std::max(l012,l023); + FloatType smaller = std::min(l012,l023); + + if(larger < cMaxAreaRatio * smaller) { + FloatType l0123 = n012.dot(n023); + if(l0123 > 0) + return true; + if(l0123 * l0123 <= mcMaxDihedralAngleCos2 * l012 * l023) + return true; + } + return false; + } + + /// Removes the given edge from the mesh and updates the neighborhood. + void collapse(Edge* edge, const Vector3& placement) + { + Edge* oppositeEdge = edge->oppositeEdge(); + OVITO_ASSERT(oppositeEdge); + + // Reposition vertex. + Vertex* remainingVertex = edge->vertex2(); + remainingVertex->setPos(remainingVertex->pos() + placement); + + Edge* ep1 = edge->prevFaceEdge(); + Edge* epo1 = ep1->oppositeEdge(); + Edge* en1 = edge->nextFaceEdge(); + Edge* eno1 = en1->oppositeEdge(); + Edge* ep2 = oppositeEdge->prevFaceEdge(); + Edge* epo2 = ep2->oppositeEdge(); + Edge* en2 = oppositeEdge->nextFaceEdge(); + Edge* eno2 = en2->oppositeEdge(); + + eraseEdgeFromPQ(ep1); + eraseEdgeFromPQ(en2); + _mesh.joinFaces(ep1); + _mesh.joinFaces(en2); + _mesh.collapseEdge(edge); + + // Update priority queue and costs of all affected edges. + Edge* currentEdge = en1; + do { + OVITO_ASSERT(currentEdge->vertex1() == remainingVertex); + updateEdgeCostIfPrimary(currentEdge); + Edge* currentEdge2 = currentEdge->nextFaceEdge(); + do { + updateEdgeCostIfPrimary(currentEdge2); + currentEdge2 = currentEdge2->prevFaceEdge()->oppositeEdge(); + OVITO_ASSERT(currentEdge2); + } + while(currentEdge2 != currentEdge->nextFaceEdge()); + currentEdge = currentEdge->prevFaceEdge()->oppositeEdge(); + OVITO_ASSERT(currentEdge); + } + while(currentEdge != en1); + } + + void eraseEdgeFromPQ(Edge* edge) + { + auto handle = _pqHandles.find(edge); + if(handle == _pqHandles.end()) { + OVITO_ASSERT(edge->oppositeEdge() != nullptr); + handle = _pqHandles.find(edge->oppositeEdge()); + } + if(handle != _pqHandles.end()) { + _pq.erase(handle->second); + _pqHandles.erase(handle); + } + } + + void updateEdgeCostIfPrimary(Edge* edge) + { + auto handle = _pqHandles.find(edge); + if(handle == _pqHandles.end()) + return; + boost::optional placement = computePlacement(edge); + (*handle->second).cost = placement ? computeCost(edge, *placement) : -1; + _pq.update(handle->second); + } + +private: + + /// Data type to be stored in priority queue. + struct EdgeWithCost { + Edge* edge; + FloatType cost; + bool operator<(const EdgeWithCost& other) const { return cost > other.cost; } + }; + + /// The mutable priority queue type. + using PQ = boost::heap::fibonacci_heap>; + + /// The mesh this algorithm operates on. + HEM& _mesh; + + /// The priority queue of edges. + PQ _pq; + + /// Loopup map for handles in the priority queue. + std::unordered_map _pqHandles; + + /// Functor object that is responsible for calculating the vector between two points. + PointPointVector _ppvec; + + /// Client-provided functor object that allow to reject new edges. + EdgeVectorValidation _edgeValidation; + + // Lindstrom-Turk algorithm parameters: + FloatType _volumeWeight = FloatType(0.5); + FloatType _boundaryWeight = FloatType(0.5); + FloatType _shapeWeight = FloatType(0); + + static constexpr FloatType cMaxAreaRatio = FloatType(1e8); + static constexpr double cMaxDihedralAngleCos = 0.99984769515639123916; // =cos(1 degree) + static constexpr FloatType mcMaxDihedralAngleCos2 = FloatType(0.999695413509547865); // =cos(1 degree)^2 + static constexpr double cMaxDihedralAngleSin = 0.017452406437284; // =sin(1 degree) + static constexpr FloatType mcMaxDihedralAngleSin2 = FloatType(0.000304586490452); // =sin(1 degree)^2 +}; + + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/mesh/HalfEdgeMesh.h ovito-2.9.0+dfsg1/src/core/utilities/mesh/HalfEdgeMesh.h --- ovito-2.8.1+dfsg2/src/core/utilities/mesh/HalfEdgeMesh.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/mesh/HalfEdgeMesh.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_HALF_EDGE_MESH_H -#define __OVITO_HALF_EDGE_MESH_H +#pragma once + #include #include @@ -102,10 +102,13 @@ protected: /// Constructor. - Edge(Vertex* vertex2, Face* face) : _oppositeEdge(nullptr), _vertex2(vertex2), _face(face) {} + Edge(Vertex* vertex2, Face* face) : _vertex2(vertex2), _face(face) { + OVITO_ASSERT(vertex2 != nullptr); + OVITO_ASSERT(face != nullptr); + } /// The opposite half-edge. - Edge* _oppositeEdge; + Edge* _oppositeEdge = nullptr; /// The vertex this half-edge is pointing to. Vertex* _vertex2; @@ -180,7 +183,7 @@ protected: /// Constructor. - Vertex(const Point3& pos, int index = -1) : _pos(pos), _edges(nullptr), _numEdges(0), _index(index) {} + Vertex(const Point3& pos, int index = -1) : _pos(pos), _index(index) {} /// Adds an adjacent half-edge to this vertex. void addEdge(Edge* edge) { @@ -212,10 +215,10 @@ Point3 _pos; /// The number of faces (as well as half-edges) adjacent to this vertex. - int _numEdges; + int _numEdges = 0; /// The head of the linked-list of outgoing half-edges. - Edge* _edges; + Edge* _edges = nullptr; /// The index of the vertex in the list of vertices of the mesh. int _index; @@ -273,16 +276,16 @@ protected: /// Constructor. - Face(int index = -1) : _edges(nullptr), _index(index), _flags(0) {} + Face(int index = -1) : _index(index) {} /// The head of the linked-list of half-edges that are adjacent to this face. - Edge* _edges; + Edge* _edges = nullptr; /// The index of the face in the list of faces of the mesh. int _index; /// The bit-wise flags assigned to this face. - unsigned int _flags; + unsigned int _flags = 0; friend class HalfEdgeMesh; }; @@ -305,6 +308,9 @@ _vertexPool.clear(); _edgePool.clear(); _facePool.clear(); + _reclaimedFaces.clear(); + _reclaimedEdges.clear(); + _reclaimedVertices.clear(); } /// Returns the list of vertices in the mesh. @@ -339,7 +345,15 @@ /// Adds a new vertex to the mesh. Vertex* createVertex(const Point3& pos) { - Vertex* vert = _vertexPool.construct(pos, vertexCount()); + Vertex* vert; + if(_reclaimedVertices.empty()) { + vert = _vertexPool.construct(pos, vertexCount()); + } + else { + vert = _reclaimedVertices.back(); + _reclaimedVertices.pop_back(); + vert->setPos(pos); + } _vertices.push_back(vert); return vert; } @@ -361,19 +375,150 @@ for(v2 = begin, v1 = v2++; v2 != end; v1 = v2++) createEdge(*v1, *v2, face); createEdge(*v1, *begin, face); + + // First edge of face should start at first supplied vertex. + OVITO_ASSERT(face->edges()->vertex1() == *begin); + return face; } /// Creates a new face without edges. This is for internal use only. Face* createFace() { - Face* face = _facePool.construct(faceCount()); + Face* face; + if(_reclaimedFaces.empty()) { + face = _facePool.construct(faceCount()); + } + else { + face = _reclaimedFaces.back(); + face->_edges = nullptr; + face->_flags = 0; + _reclaimedFaces.pop_back(); + } _faces.push_back(face); return face; } + /// Deletes a halfedge from the mesh. + /// This method assumes that the edge is not connected to any part of the mesh. + void removeEdge(Edge* edge) { + OVITO_ASSERT(edge != nullptr); + OVITO_ASSERT(edge->oppositeEdge() == nullptr); + _reclaimedEdges.push_back(edge); + } + + /// Deletes a face from the mesh. + /// A hole in the mesh will be left behind. + /// The halfedges of the face are also disconnected from their respective opposite halfedges + /// and reclaimed by this method. + void removeFace(int faceIndex) { + Face* face = this->face(faceIndex); + if(Edge* e = face->edges()) { + do { + OVITO_ASSERT(e->vertex1()); + e->vertex1()->removeEdge(e); + if(e->oppositeEdge() != nullptr) + e->unlinkFromOppositeEdge(); + removeEdge(e); + e = e->nextFaceEdge(); + } + while(e != face->edges()); + } + _faces[faceIndex] = _faces.back(); + _faces.erase(_faces.end() - 1); + _reclaimedFaces.push_back(face); + } + + /// Deletes a face from the mesh. + void removeFace(Face* face) { + OVITO_ASSERT(face != nullptr); + OVITO_ASSERT(faces()[face->index()] == face); + removeFace(face->index()); + } + + /// Deletes a vertex from the mesh. + /// This method assumes that the vertex is not connected to any edges or faces of the mesh. + void removeVertex(int vertexIndex) { + Vertex* vertex = this->vertex(vertexIndex); + OVITO_ASSERT(vertex->edges() == nullptr); + OVITO_ASSERT(vertex->numEdges() == 0); + _vertices[vertexIndex] = _vertices.back(); + _vertices.erase(_vertices.end() - 1); + _reclaimedVertices.push_back(vertex); + } + + void joinFaces(Edge* edge) { + Edge* oppositeEdge = edge->oppositeEdge(); + OVITO_ASSERT(oppositeEdge); + + for(Edge* currentEdge = edge->nextFaceEdge(); currentEdge != edge; currentEdge = currentEdge->nextFaceEdge()) { + currentEdge->_face = oppositeEdge->face(); + } + oppositeEdge->face()->_edges = oppositeEdge->nextFaceEdge(); + edge->face()->_edges = nullptr; + edge->vertex1()->removeEdge(edge); + edge->vertex2()->removeEdge(oppositeEdge); + edge->unlinkFromOppositeEdge(); + edge->prevFaceEdge()->_nextFaceEdge = oppositeEdge->nextFaceEdge(); + oppositeEdge->nextFaceEdge()->_prevFaceEdge = edge->prevFaceEdge(); + oppositeEdge->prevFaceEdge()->_nextFaceEdge = edge->nextFaceEdge(); + edge->nextFaceEdge()->_prevFaceEdge = oppositeEdge->prevFaceEdge(); + removeEdge(edge); + removeEdge(oppositeEdge); + } + + void collapseEdge(Edge* edge) { + + Edge* oppositeEdge = edge->oppositeEdge(); + OVITO_ASSERT(oppositeEdge); + Edge* ep1 = edge->prevFaceEdge(); + Edge* epo1 = ep1->oppositeEdge(); + Edge* en1 = edge->nextFaceEdge(); + Edge* eno1 = en1->oppositeEdge(); + Edge* ep2 = oppositeEdge->prevFaceEdge(); + Edge* epo2 = ep2->oppositeEdge(); + Edge* en2 = oppositeEdge->nextFaceEdge(); + Edge* eno2 = en2->oppositeEdge(); + Vertex* deletedVertex = edge->vertex1(); + Vertex* remainingVertex = edge->vertex2(); + + // Go around the deleted vertex and transfer edges. + Edge* currentEdge = edge; + do { + if(currentEdge != edge) + deletedVertex->transferEdgeToVertex(currentEdge, remainingVertex); + currentEdge = currentEdge->prevFaceEdge()->oppositeEdge(); + OVITO_ASSERT(currentEdge); + } + while(currentEdge != edge); + + edge->prevFaceEdge()->_nextFaceEdge = edge->nextFaceEdge(); + edge->nextFaceEdge()->_prevFaceEdge = edge->prevFaceEdge(); + oppositeEdge->prevFaceEdge()->_nextFaceEdge = oppositeEdge->nextFaceEdge(); + oppositeEdge->nextFaceEdge()->_prevFaceEdge = oppositeEdge->prevFaceEdge(); + edge->face()->_edges = edge->nextFaceEdge(); + oppositeEdge->face()->_edges = oppositeEdge->nextFaceEdge(); + + deletedVertex->removeEdge(edge); + remainingVertex->removeEdge(oppositeEdge); + + edge->unlinkFromOppositeEdge(); + removeEdge(edge); + removeEdge(oppositeEdge); + } + /// Create a new half-edge. This is for internal use only. Edge* createEdge(Vertex* vertex1, Vertex* vertex2, Face* face) { - Edge* edge = _edgePool.construct(vertex2, face); + Edge* edge; + if(_reclaimedEdges.empty()) { + edge = _edgePool.construct(vertex2, face); + } + else { + edge = _reclaimedEdges.back(); + _reclaimedEdges.pop_back(); + edge->_vertex2 = vertex2; + edge->_face = face; + OVITO_ASSERT(!edge->oppositeEdge()); + } vertex1->addEdge(edge); if(face->_edges) { edge->_nextFaceEdge = face->_edges; @@ -492,6 +637,9 @@ _vertexPool.swap(other._vertexPool); _edgePool.swap(other._edgePool); _facePool.swap(other._facePool); + _reclaimedFaces.swap(other._reclaimedFaces); + _reclaimedEdges.swap(other._reclaimedEdges); + _reclaimedVertices.swap(other._reclaimedVertices); } /// Converts this half-edge mesh to a triangle mesh. @@ -634,6 +782,15 @@ return true; } + /// Re-assigned indices to faces and vertices of the mesh so that the indices + /// form a consecutive sequence starting at zero. + void reindexVerticesAndFaces() { + int vindex = 0; + for(Vertex* vertex : vertices()) vertex->_index = vindex++; + int findex = 0; + for(Face* face : faces()) face->_index = findex++; + } + private: /// This derived class is needed to make the protected Vertex constructor accessible. @@ -666,10 +823,22 @@ /// The faces of the mesh. std::vector _faces; MemoryPool _facePool; + + /// A list of faces that have been deleted from the mesh. + /// They can be reused when a new face is to be created. + std::vector _reclaimedFaces; + + /// A list of haldedges that have been deleted from the mesh. + /// They can be reused when a new edge is to be created. + std::vector _reclaimedEdges; + + /// A list of vertices that have been deleted from the mesh. + /// They can be reused when a new vertex is to be created. + std::vector _reclaimedVertices; }; OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_HALF_EDGE_MESH_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/mesh/TriMesh.cpp ovito-2.9.0+dfsg1/src/core/utilities/mesh/TriMesh.cpp --- ovito-2.8.1+dfsg2/src/core/utilities/mesh/TriMesh.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/mesh/TriMesh.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,7 +28,7 @@ /****************************************************************************** * Constructs an empty mesh. ******************************************************************************/ -TriMesh::TriMesh() : _hasVertexColors(false), _hasFaceColors(false) +TriMesh::TriMesh() : _hasVertexColors(false), _hasFaceColors(false), _hasNormals(false) { } @@ -44,6 +44,7 @@ _boundingBox.setEmpty(); _hasVertexColors = false; _hasFaceColors = false; + _hasNormals = false; } /****************************************************************************** @@ -64,6 +65,8 @@ _faces.resize(n); if(_hasFaceColors) _faceColors.resize(n); + if(_hasNormals) + _normals.resize(n * 3); } /****************************************************************************** @@ -72,7 +75,7 @@ ******************************************************************************/ TriMeshFace& TriMesh::addFace() { - setFaceCount(faceCount()+1); + setFaceCount(faceCount() + 1); return _faces.back(); } @@ -81,7 +84,7 @@ ******************************************************************************/ void TriMesh::saveToStream(SaveStream& stream) { - stream.beginChunk(0x02); + stream.beginChunk(0x03); // Save vertices. stream << _vertices; @@ -94,6 +97,10 @@ stream << _hasFaceColors; stream << _faceColors; + // Save face normals. + stream << _hasNormals; + stream << _normals; + // Save faces. stream << (int)faceCount(); for(auto face = faces().constBegin(); face != faces().constEnd(); ++face) { @@ -113,7 +120,7 @@ ******************************************************************************/ void TriMesh::loadFromStream(LoadStream& stream) { - int formatVersion = stream.expectChunkRange(0x00, 0x02); + int formatVersion = stream.expectChunkRange(0x00, 0x03); // Reset mesh. clear(); @@ -132,6 +139,12 @@ stream >> _faceColors; } + if(formatVersion >= 3) { + // Load normals. + stream >> _hasNormals; + stream >> _normals; + } + // Load faces. int nFaces; stream >> nFaces; @@ -157,6 +170,10 @@ face.setVertices(face.vertex(2), face.vertex(1), face.vertex(0)); face.setEdgeVisibility(face.edgeVisible(2), face.edgeVisible(1), face.edgeVisible(0)); } + if(_hasNormals) { + for(Vector3& n : _normals) + n = -n; + } invalidateFaces(); } @@ -183,13 +200,13 @@ Vector3 s = ray.base - v0; FloatType u = f * s.dot(h); - if(u < 0.0f || u > 1.0f) + if(u < FloatType(0) || u > FloatType(1)) continue; Vector3 q = s.cross(e1); FloatType v = f * ray.dir.dot(q); - if(v < 0.0f || u + v > 1.0f) + if(v < FloatType(0) || u + v > FloatType(1)) continue; FloatType tt = f * e2.dot(q); @@ -246,6 +263,24 @@ } /****************************************************************************** +* Exports the triangle mesh to a Wavefront .obj file. +******************************************************************************/ +void TriMesh::saveToOBJ(CompressedTextWriter& stream) +{ + stream << "# Wavefront OBJ file written by OVITO\n"; + stream << "# List of geometric vertices:\n"; + for(const Point3& p : vertices()) + stream << "v " << p.x() << " " << p.y() << " " << p.z() << "\n"; + stream << "# List of faces:\n"; + for(const TriMeshFace& f : faces()) { + stream << "f "; + for(size_t i = 0; i < 3; i++) + stream << " " << (f.vertex(i)+1); + stream << "\n"; + } +} + +/****************************************************************************** * Clips the mesh at the given plane. ******************************************************************************/ void TriMesh::clipAtPlane(const Plane3& plane) @@ -291,7 +326,7 @@ int next_classification; for(int v = v0; v < v0 + 3; v++, current_classification = next_classification) { next_classification = plane.classifyPoint(vertex(face.vertex((v+1)%3))); - if(next_classification <= 0 && current_classification <= 0) { + if((next_classification <= 0 && current_classification <= 0) || (next_classification == 1 && current_classification == 0)) { OVITO_ASSERT(existingVertexMapping[face.vertex(v%3)] >= 0); OVITO_ASSERT(newface_vcount <= 3); newface[newface_vcount++] = existingVertexMapping[face.vertex(v%3)]; diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/mesh/TriMesh.h ovito-2.9.0+dfsg1/src/core/utilities/mesh/TriMesh.h --- ovito-2.8.1+dfsg2/src/core/utilities/mesh/TriMesh.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/mesh/TriMesh.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TRI_MESH_H -#define __OVITO_TRI_MESH_H +#pragma once + #include @@ -159,6 +159,8 @@ _vertexColors.swap(other._vertexColors); std::swap(_hasFaceColors, other._hasFaceColors); _faceColors.swap(other._faceColors); + std::swap(_hasNormals, other._hasNormals); + _normals.swap(other._normals); } /// \brief Returns the bounding box of the mesh. @@ -412,6 +414,70 @@ vertexColor(index) = c; } + /// \brief Returns whether this mesh has normal vectors stored. + bool hasNormals() const { + return _hasNormals; + } + + /// \brief Controls whether this mesh has normal vectors (three per face). + void setHasNormals(bool enableNormals) { + _hasNormals = enableNormals; + _normals.resize(enableNormals ? (_faces.size()*3) : 0); + } + + /// \brief Allows direct access to the face vertex normals of the mesh. + /// \return A reference to the vector that stores all normal vectors (three per face). + /// \note After you have finished changing the normals, + /// you have to call invalidateFaces() to let the mesh know that it has to update its internal + /// caches based on the new normals. + QVector& normals() { + OVITO_ASSERT(_hasNormals); + OVITO_ASSERT(_normals.size() == _faces.size()*3); + return _normals; + } + + /// \brief Allows direct read-access to the normal vectors of the mesh. + /// \return A constant reference to the vector that stores all normal vectors (three per face). + const QVector& normals() const { + OVITO_ASSERT(_hasNormals); + OVITO_ASSERT(_normals.size() == _faces.size()*3); + return _normals; + } + + /// \brief Returns the normal vector stored for the given vertex of the given face. + /// \param faceIndex The index starting at 0 of the face whose normal should be returned. + /// \param vertexIndex The face vertex (0-2) for which the normal should be returned. + /// \return The stored normal vector. + const Vector3& faceVertexNormal(int faceIndex, int vertexIndex) const { + OVITO_ASSERT(faceIndex >= 0 && faceIndex < faceCount()); + OVITO_ASSERT(vertexIndex >= 0 && vertexIndex < 3); + return normals()[faceIndex*3 + vertexIndex]; + } + + /// \brief Returns a reference to the stored normal vector of the given vertex of the given face. + /// \param faceIndex The index starting at 0 of the face whose normal should be returned. + /// \param vertexIndex The face vertex (0-2) for which the normal should be returned. + /// \return A reference to the normal vector of the given face vertex. The reference can be used to alter the vector.. + /// \note After you have finished changing the normals, + /// you have to call invalidateFaces() to let the mesh know that it has + /// to update its internal caches based on the new normals. + Vector3& faceVertexNormal(int faceIndex, int vertexIndex) { + OVITO_ASSERT(faceIndex >= 0 && faceIndex < faceCount()); + OVITO_ASSERT(vertexIndex >= 0 && vertexIndex < 3); + return normals()[faceIndex*3 + vertexIndex]; + } + + /// \brief Sets the normal vectors stored for a vertex of a face. + /// \param faceIndex The index starting at 0 of the face whose normal should be set. + /// \param vertexIndex The face vertex (0-2) for which the normal should be set. + /// \param n The new normal vector. + /// \note After you have finished changing the normal vectors, + /// you have to call invalidateFaces() to let the mesh know that it has + /// to update its internal caches based on the new normals. + void setFaceVertexNormal(int faceIndex, int vertexIndex, const Vector3& n) { + faceVertexNormal(faceIndex, vertexIndex) = n; + } + /************************************* Ray intersection *************************************/ /// \brief Performs a ray intersection calculation. @@ -436,6 +502,9 @@ /// \brief Exports the triangle mesh to a VTK file. void saveToVTK(CompressedTextWriter& stream); + /// \brief Exports the triangle mesh to a Wavefront .obj file. + void saveToOBJ(CompressedTextWriter& stream); + /************************************* Clipping *************************************/ /// Clips the mesh at the given plane. @@ -463,6 +532,12 @@ /// Array of mesh faces. QVector _faces; + + /// Indicates that normal vectors are stored in this mesh. + bool _hasNormals; + + /// Array of normals (three per face). + QVector _normals; }; OVITO_END_INLINE_NAMESPACE @@ -471,4 +546,4 @@ Q_DECLARE_TYPEINFO(Ovito::TriMeshFace, Q_MOVABLE_TYPE); -#endif // __OVITO_TRI_MESH_H + diff -Nru ovito-2.8.1+dfsg2/src/core/utilities/units/UnitsManager.h ovito-2.9.0+dfsg1/src/core/utilities/units/UnitsManager.h --- ovito-2.8.1+dfsg2/src/core/utilities/units/UnitsManager.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/utilities/units/UnitsManager.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_UNITS_MANAGER_H -#define __OVITO_UNITS_MANAGER_H +#pragma once + #include @@ -154,9 +154,9 @@ int exponent; currentValue = nativeToUser(currentValue); if(currentValue != 0) { - exponent = (int)std::floor(std::log10(std::abs(currentValue))-1.0); - if(exponent < -5) exponent = -5; - else if(exponent > 5) exponent = 5; + exponent = (int)std::floor(std::log10(std::abs(currentValue)) - FloatType(1)); + if(exponent < -12) exponent = -12; + else if(exponent > 6) exponent = 6; } else exponent = 0; return userToNative(std::pow(FloatType(10), exponent)); @@ -212,7 +212,7 @@ /// \brief Given an arbitrary value, which is potentially invalid, rounds it to the closest valid value. virtual FloatType roundValue(FloatType value) override { - return floor(value + (FloatType)0.5); + return std::floor(value + FloatType(0.5)); } }; @@ -414,4 +414,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_UNITS_MANAGER_H + diff -Nru ovito-2.8.1+dfsg2/src/core/viewport/overlay/CoordinateTripodOverlay.cpp ovito-2.9.0+dfsg1/src/core/viewport/overlay/CoordinateTripodOverlay.cpp --- ovito-2.8.1+dfsg2/src/core/viewport/overlay/CoordinateTripodOverlay.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/viewport/overlay/CoordinateTripodOverlay.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,42 +26,42 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(View) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, CoordinateTripodOverlay, ViewportOverlay); -DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, _alignment, "Alignment", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, _tripodSize, "Size", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, _lineWidth, "LineWidth", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, _font, "Font", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, _fontSize, "FontSize", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, _offsetX, "OffsetX", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, _offsetY, "OffsetY", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, _axis1Enabled, "Axis1Enabled"); -DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, _axis2Enabled, "Axis2Enabled"); -DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, _axis3Enabled, "Axis3Enabled"); -DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, _axis4Enabled, "Axis4Enabled"); -DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, _axis1Label, "Axis1Label"); -DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, _axis2Label, "Axis2Label"); -DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, _axis3Label, "Axis3Label"); -DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, _axis4Label, "Axis4Label"); -DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, _axis1Dir, "Axis1Dir"); -DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, _axis2Dir, "Axis2Dir"); -DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, _axis3Dir, "Axis3Dir"); -DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, _axis4Dir, "Axis4Dir"); -DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, _axis1Color, "Axis1Color", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, _axis2Color, "Axis2Color", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, _axis3Color, "Axis3Color", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, _axis4Color, "Axis4Color", PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(CoordinateTripodOverlay, _alignment, "Position"); -SET_PROPERTY_FIELD_LABEL(CoordinateTripodOverlay, _tripodSize, "Size factor"); -SET_PROPERTY_FIELD_LABEL(CoordinateTripodOverlay, _lineWidth, "Line width"); -SET_PROPERTY_FIELD_LABEL(CoordinateTripodOverlay, _font, "Font"); -SET_PROPERTY_FIELD_LABEL(CoordinateTripodOverlay, _fontSize, "Label size"); -SET_PROPERTY_FIELD_LABEL(CoordinateTripodOverlay, _offsetX, "Offset X"); -SET_PROPERTY_FIELD_LABEL(CoordinateTripodOverlay, _offsetY, "Offset Y"); -SET_PROPERTY_FIELD_UNITS(CoordinateTripodOverlay, _offsetX, PercentParameterUnit); -SET_PROPERTY_FIELD_UNITS(CoordinateTripodOverlay, _offsetY, PercentParameterUnit); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CoordinateTripodOverlay, _tripodSize, FloatParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CoordinateTripodOverlay, _lineWidth, FloatParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CoordinateTripodOverlay, _fontSize, FloatParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CoordinateTripodOverlay, ViewportOverlay); +DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, alignment, "Alignment", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, tripodSize, "Size", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, lineWidth, "LineWidth", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, font, "Font", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, fontSize, "FontSize", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, offsetX, "OffsetX", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, offsetY, "OffsetY", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, axis1Enabled, "Axis1Enabled"); +DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, axis2Enabled, "Axis2Enabled"); +DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, axis3Enabled, "Axis3Enabled"); +DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, axis4Enabled, "Axis4Enabled"); +DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, axis1Label, "Axis1Label"); +DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, axis2Label, "Axis2Label"); +DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, axis3Label, "Axis3Label"); +DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, axis4Label, "Axis4Label"); +DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, axis1Dir, "Axis1Dir"); +DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, axis2Dir, "Axis2Dir"); +DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, axis3Dir, "Axis3Dir"); +DEFINE_PROPERTY_FIELD(CoordinateTripodOverlay, axis4Dir, "Axis4Dir"); +DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, axis1Color, "Axis1Color", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, axis2Color, "Axis2Color", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, axis3Color, "Axis3Color", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CoordinateTripodOverlay, axis4Color, "Axis4Color", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(CoordinateTripodOverlay, alignment, "Position"); +SET_PROPERTY_FIELD_LABEL(CoordinateTripodOverlay, tripodSize, "Size factor"); +SET_PROPERTY_FIELD_LABEL(CoordinateTripodOverlay, lineWidth, "Line width"); +SET_PROPERTY_FIELD_LABEL(CoordinateTripodOverlay, font, "Font"); +SET_PROPERTY_FIELD_LABEL(CoordinateTripodOverlay, fontSize, "Label size"); +SET_PROPERTY_FIELD_LABEL(CoordinateTripodOverlay, offsetX, "Offset X"); +SET_PROPERTY_FIELD_LABEL(CoordinateTripodOverlay, offsetY, "Offset Y"); +SET_PROPERTY_FIELD_UNITS(CoordinateTripodOverlay, offsetX, PercentParameterUnit); +SET_PROPERTY_FIELD_UNITS(CoordinateTripodOverlay, offsetY, PercentParameterUnit); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CoordinateTripodOverlay, tripodSize, FloatParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CoordinateTripodOverlay, lineWidth, FloatParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CoordinateTripodOverlay, fontSize, FloatParameterUnit, 0); /****************************************************************************** * Constructor. @@ -75,29 +75,29 @@ _axis1Dir(1,0,0), _axis2Dir(0,1,0), _axis3Dir(0,0,1), _axis4Dir(sqrt(0.5),sqrt(0.5),0), _axis1Color(1,0,0), _axis2Color(0,0.8,0), _axis3Color(0.2,0.2,1), _axis4Color(1,0,1) { - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_alignment); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_tripodSize); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_lineWidth); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_offsetX); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_offsetY); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_font); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_fontSize); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis1Enabled); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis2Enabled); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis3Enabled); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis4Enabled); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis1Label); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis2Label); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis3Label); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis4Label); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis1Dir); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis2Dir); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis3Dir); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis4Dir); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis1Color); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis2Color); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis3Color); - INIT_PROPERTY_FIELD(CoordinateTripodOverlay::_axis4Color); + INIT_PROPERTY_FIELD(alignment); + INIT_PROPERTY_FIELD(tripodSize); + INIT_PROPERTY_FIELD(lineWidth); + INIT_PROPERTY_FIELD(offsetX); + INIT_PROPERTY_FIELD(offsetY); + INIT_PROPERTY_FIELD(font); + INIT_PROPERTY_FIELD(fontSize); + INIT_PROPERTY_FIELD(axis1Enabled); + INIT_PROPERTY_FIELD(axis2Enabled); + INIT_PROPERTY_FIELD(axis3Enabled); + INIT_PROPERTY_FIELD(axis4Enabled); + INIT_PROPERTY_FIELD(axis1Label); + INIT_PROPERTY_FIELD(axis2Label); + INIT_PROPERTY_FIELD(axis3Label); + INIT_PROPERTY_FIELD(axis4Label); + INIT_PROPERTY_FIELD(axis1Dir); + INIT_PROPERTY_FIELD(axis2Dir); + INIT_PROPERTY_FIELD(axis3Dir); + INIT_PROPERTY_FIELD(axis4Dir); + INIT_PROPERTY_FIELD(axis1Color); + INIT_PROPERTY_FIELD(axis2Color); + INIT_PROPERTY_FIELD(axis3Color); + INIT_PROPERTY_FIELD(axis4Color); } /****************************************************************************** @@ -111,18 +111,18 @@ FloatType lineWidth = _lineWidth.value() * tripodSize; if(lineWidth <= 0) return; - FloatType arrowSize = 0.17f; + FloatType arrowSize = FloatType(0.17); QPointF origin(_offsetX.value() * renderSettings->outputImageWidth(), -_offsetY.value() * renderSettings->outputImageHeight()); FloatType margin = tripodSize + lineWidth; if(_alignment.value() & Qt::AlignLeft) origin.rx() += margin; else if(_alignment.value() & Qt::AlignRight) origin.rx() += renderSettings->outputImageWidth() - margin; - else if(_alignment.value() & Qt::AlignHCenter) origin.rx() += 0.5 * renderSettings->outputImageWidth(); + else if(_alignment.value() & Qt::AlignHCenter) origin.rx() += FloatType(0.5) * renderSettings->outputImageWidth(); if(_alignment.value() & Qt::AlignTop) origin.ry() += margin; else if(_alignment.value() & Qt::AlignBottom) origin.ry() += renderSettings->outputImageHeight() - margin; - else if(_alignment.value() & Qt::AlignVCenter) origin.ry() += 0.5 * renderSettings->outputImageHeight(); + else if(_alignment.value() & Qt::AlignVCenter) origin.ry() += FloatType(0.5) * renderSettings->outputImageHeight(); // Project axes to screen. Vector3 axisDirs[4] = { diff -Nru ovito-2.8.1+dfsg2/src/core/viewport/overlay/CoordinateTripodOverlay.h ovito-2.9.0+dfsg1/src/core/viewport/overlay/CoordinateTripodOverlay.h --- ovito-2.8.1+dfsg2/src/core/viewport/overlay/CoordinateTripodOverlay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/viewport/overlay/CoordinateTripodOverlay.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COORDINATE_TRIPOD_OVERLAY_H -#define __OVITO_COORDINATE_TRIPOD_OVERLAY_H +#pragma once + #include #include "ViewportOverlay.h" @@ -47,214 +47,76 @@ setOffsetY(offsetY() + delta.y()); } - /// Returns the corner of the viewport where the tripod is shown. - int alignment() const { return _alignment; } - - /// Sets the corner of the viewport where the tripod is shown. - void setAlignment(int align) { _alignment = align; } - - /// Returns the size of the tripod. - FloatType tripodSize() const { return _tripodSize; } - - /// Sets the size of the tripod. - void setTripodSize(FloatType size) { _tripodSize = size; } - - /// Returns the line width. - FloatType lineWidth() const { return _lineWidth; } - - /// Sets the line width. - void setLineWidth(FloatType lw) { _lineWidth = lw; } - - /// Returns the horizontal offset of the tripod's position. - FloatType offsetX() const { return _offsetX; } - - /// Sets the horizontal offset of the tripod's position. - void setOffsetX(FloatType offset) { _offsetX = offset; } - - /// Returns the vertical offset of the tripod's position. - FloatType offsetY() const { return _offsetY; } - - /// Sets the vertical offset of the tripod's position. - void setOffsetY(FloatType offset) { _offsetY = offset; } - - /// Returns the text label font. - const QFont& font() const { return _font; } - - /// Sets the text label font. - void setFont(const QFont& font) { _font = font; } - - /// Returns the text label font size. - FloatType fontSize() const { return _fontSize; } - - /// Sets the text label font size. - void setFontSize(FloatType fontSize) { _fontSize = fontSize; } - - /// Returns whether the first axis is displayed. - bool axis1Enabled() const { return _axis1Enabled; } - - /// Sets whether display is enabled for the first axis. - void setAxis1Enabled(bool enabled) { _axis1Enabled = enabled; } - - /// Returns whether the second axis is displayed. - bool axis2Enabled() const { return _axis2Enabled; } - - /// Sets whether display is enabled for the second axis. - void setAxis2Enabled(bool enabled) { _axis2Enabled = enabled; } - - /// Returns whether the third axis is displayed. - bool axis3Enabled() const { return _axis3Enabled; } - - /// Sets whether display is enabled for the third axis. - void setAxis3Enabled(bool enabled) { _axis3Enabled = enabled; } - - /// Returns whether the fourth axis is displayed. - bool axis4Enabled() const { return _axis4Enabled; } - - /// Sets whether display is enabled for the fourth axis. - void setAxis4Enabled(bool enabled) { _axis4Enabled = enabled; } - - /// Returns the text label of the first axis. - const QString& axis1Label() const { return _axis1Label; } - - /// Sets the text label of the first axis. - void setAxis1Label(const QString& label) { _axis1Label = label; } - - /// Returns the text label of the second axis. - const QString& axis2Label() const { return _axis2Label; } - - /// Sets the text label of the second axis. - void setAxis2Label(const QString& label) { _axis2Label = label; } - - /// Returns the text label of the third axis. - const QString& axis3Label() const { return _axis3Label; } - - /// Sets the text label of the third axis. - void setAxis3Label(const QString& label) { _axis3Label = label; } - - /// Returns the text label of the fourth axis. - const QString& axis4Label() const { return _axis4Label; } - - /// Sets the text label of the fourth axis. - void setAxis4Label(const QString& label) { _axis4Label = label; } - - /// Returns the direction of the first axis. - const Vector3& axis1Dir() const { return _axis1Dir; } - - /// Sets the direction of the first axis. - void setAxis1Dir(const Vector3& dir) { _axis1Dir = dir; } - - /// Returns the direction of the second axis. - const Vector3& axis2Dir() const { return _axis2Dir; } - - /// Sets the direction of the second axis. - void setAxis2Dir(const Vector3& dir) { _axis2Dir = dir; } - - /// Returns the direction of the third axis. - const Vector3& axis3Dir() const { return _axis3Dir; } - - /// Sets the direction of the third axis. - void setAxis3Dir(const Vector3& dir) { _axis3Dir = dir; } - - /// Returns the direction of the fourth axis. - const Vector3& axis4Dir() const { return _axis4Dir; } - - /// Sets the direction of the fourth axis. - void setAxis4Dir(const Vector3& dir) { _axis4Dir = dir; } - private: /// The corner of the viewport where the tripod is shown in. - PropertyField _alignment; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, alignment, setAlignment); /// Controls the size of the tripod. - PropertyField _tripodSize; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, tripodSize, setTripodSize); /// Controls the line width. - PropertyField _lineWidth; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, lineWidth, setLineWidth); /// Controls the horizontal offset of tripod position. - PropertyField _offsetX; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, offsetX, setOffsetX); /// Controls the vertical offset of tripod position. - PropertyField _offsetY; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, offsetY, setOffsetY); /// Controls the label font. - PropertyField _font; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QFont, font, setFont); /// Controls the label font size. - PropertyField _fontSize; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, fontSize, setFontSize); /// Controls the display of the first axis. - PropertyField _axis1Enabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, axis1Enabled, setAxis1Enabled); /// Controls the display of the second axis. - PropertyField _axis2Enabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, axis2Enabled, setAxis2Enabled); /// Controls the display of the third axis. - PropertyField _axis3Enabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, axis3Enabled, setAxis3Enabled); /// Controls the display of the fourth axis. - PropertyField _axis4Enabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, axis4Enabled, setAxis4Enabled); /// The label of the first axis. - PropertyField _axis1Label; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, axis1Label, setAxis1Label); /// The label of the second axis. - PropertyField _axis2Label; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, axis2Label, setAxis2Label); /// The label of the third axis. - PropertyField _axis3Label; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, axis3Label, setAxis3Label); /// The label of the fourth axis. - PropertyField _axis4Label; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, axis4Label, setAxis4Label); /// The direction of the first axis. - PropertyField _axis1Dir; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Vector3, axis1Dir, setAxis1Dir); /// The direction of the second axis. - PropertyField _axis2Dir; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Vector3, axis2Dir, setAxis2Dir); /// The direction of the third axis. - PropertyField _axis3Dir; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Vector3, axis3Dir, setAxis3Dir); /// The direction of the fourth axis. - PropertyField _axis4Dir; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Vector3, axis4Dir, setAxis4Dir); /// The display color of the first axis. - PropertyField _axis1Color; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, axis1Color, setAxis1Color); /// The display color of the second axis. - PropertyField _axis2Color; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, axis2Color, setAxis2Color); /// The display color of the third axis. - PropertyField _axis3Color; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, axis3Color, setAxis3Color); /// The display color of the fourth axis. - PropertyField _axis4Color; - - DECLARE_PROPERTY_FIELD(_alignment); - DECLARE_PROPERTY_FIELD(_font); - DECLARE_PROPERTY_FIELD(_fontSize); - DECLARE_PROPERTY_FIELD(_tripodSize); - DECLARE_PROPERTY_FIELD(_lineWidth); - DECLARE_PROPERTY_FIELD(_offsetX); - DECLARE_PROPERTY_FIELD(_offsetY); - DECLARE_PROPERTY_FIELD(_axis1Enabled); - DECLARE_PROPERTY_FIELD(_axis2Enabled); - DECLARE_PROPERTY_FIELD(_axis3Enabled); - DECLARE_PROPERTY_FIELD(_axis4Enabled); - DECLARE_PROPERTY_FIELD(_axis1Label); - DECLARE_PROPERTY_FIELD(_axis2Label); - DECLARE_PROPERTY_FIELD(_axis3Label); - DECLARE_PROPERTY_FIELD(_axis4Label); - DECLARE_PROPERTY_FIELD(_axis1Dir); - DECLARE_PROPERTY_FIELD(_axis2Dir); - DECLARE_PROPERTY_FIELD(_axis3Dir); - DECLARE_PROPERTY_FIELD(_axis4Dir); - DECLARE_PROPERTY_FIELD(_axis1Color); - DECLARE_PROPERTY_FIELD(_axis2Color); - DECLARE_PROPERTY_FIELD(_axis3Color); - DECLARE_PROPERTY_FIELD(_axis4Color); + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, axis4Color, setAxis4Color); Q_CLASSINFO("DisplayName", "Coordinate tripod"); @@ -266,4 +128,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_COORDINATE_TRIPOD_OVERLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/core/viewport/overlay/TextLabelOverlay.cpp ovito-2.9.0+dfsg1/src/core/viewport/overlay/TextLabelOverlay.cpp --- ovito-2.8.1+dfsg2/src/core/viewport/overlay/TextLabelOverlay.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/viewport/overlay/TextLabelOverlay.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,29 +27,29 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(View) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, TextLabelOverlay, ViewportOverlay); -DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, _alignment, "Alignment", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, _font, "Font", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, _fontSize, "FontSize", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, _offsetX, "OffsetX", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, _offsetY, "OffsetY", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(TextLabelOverlay, _labelText, "LabelText"); -DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, _textColor, "TextColor", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, _outlineColor, "OutlineColor", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, _outlineEnabled, "OutlineEnabled", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_REFERENCE_FIELD(TextLabelOverlay, _sourceNode, "SourceNode", ObjectNode, PROPERTY_FIELD_NO_SUB_ANIM); -SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, _alignment, "Position"); -SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, _font, "Font"); -SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, _fontSize, "Font size"); -SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, _offsetX, "Offset X"); -SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, _offsetY, "Offset Y"); -SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, _textColor, "Text color"); -SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, _outlineColor, "Outline color"); -SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, _outlineEnabled, "Enable outline"); -SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, _sourceNode, "Attributes source"); -SET_PROPERTY_FIELD_UNITS(TextLabelOverlay, _offsetX, PercentParameterUnit); -SET_PROPERTY_FIELD_UNITS(TextLabelOverlay, _offsetY, PercentParameterUnit); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(TextLabelOverlay, _fontSize, FloatParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(TextLabelOverlay, ViewportOverlay); +DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, alignment, "Alignment", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, font, "Font", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, fontSize, "FontSize", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, offsetX, "OffsetX", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, offsetY, "OffsetY", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(TextLabelOverlay, labelText, "LabelText"); +DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, textColor, "TextColor", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, outlineColor, "OutlineColor", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TextLabelOverlay, outlineEnabled, "OutlineEnabled", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(TextLabelOverlay, sourceNode, "SourceNode", ObjectNode, PROPERTY_FIELD_NO_SUB_ANIM); +SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, alignment, "Position"); +SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, font, "Font"); +SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, fontSize, "Font size"); +SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, offsetX, "Offset X"); +SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, offsetY, "Offset Y"); +SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, textColor, "Text color"); +SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, outlineColor, "Outline color"); +SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, outlineEnabled, "Enable outline"); +SET_PROPERTY_FIELD_LABEL(TextLabelOverlay, sourceNode, "Attributes source"); +SET_PROPERTY_FIELD_UNITS(TextLabelOverlay, offsetX, PercentParameterUnit); +SET_PROPERTY_FIELD_UNITS(TextLabelOverlay, offsetY, PercentParameterUnit); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(TextLabelOverlay, fontSize, FloatParameterUnit, 0); /****************************************************************************** * Constructor. @@ -63,16 +63,16 @@ _outlineColor(1,1,1), _outlineEnabled(false) { - INIT_PROPERTY_FIELD(TextLabelOverlay::_alignment); - INIT_PROPERTY_FIELD(TextLabelOverlay::_offsetX); - INIT_PROPERTY_FIELD(TextLabelOverlay::_offsetY); - INIT_PROPERTY_FIELD(TextLabelOverlay::_font); - INIT_PROPERTY_FIELD(TextLabelOverlay::_fontSize); - INIT_PROPERTY_FIELD(TextLabelOverlay::_labelText); - INIT_PROPERTY_FIELD(TextLabelOverlay::_textColor); - INIT_PROPERTY_FIELD(TextLabelOverlay::_outlineColor); - INIT_PROPERTY_FIELD(TextLabelOverlay::_outlineEnabled); - INIT_PROPERTY_FIELD(TextLabelOverlay::_sourceNode); + INIT_PROPERTY_FIELD(alignment); + INIT_PROPERTY_FIELD(offsetX); + INIT_PROPERTY_FIELD(offsetY); + INIT_PROPERTY_FIELD(font); + INIT_PROPERTY_FIELD(fontSize); + INIT_PROPERTY_FIELD(labelText); + INIT_PROPERTY_FIELD(textColor); + INIT_PROPERTY_FIELD(outlineColor); + INIT_PROPERTY_FIELD(outlineEnabled); + INIT_PROPERTY_FIELD(sourceNode); // Automatically connect to the selected object node. setSourceNode(dynamic_object_cast(dataset->selection()->front())); @@ -86,14 +86,14 @@ FloatType fontSize = this->fontSize() * renderSettings->outputImageHeight(); if(fontSize <= 0) return; - QPointF origin(_offsetX.value() * renderSettings->outputImageWidth(), -_offsetY.value() * renderSettings->outputImageHeight()); + QPointF origin(offsetX() * renderSettings->outputImageWidth(), -offsetY() * renderSettings->outputImageHeight()); FloatType margin = fontSize; QString textString = labelText(); // Resolve attributes referenced in text string. if(sourceNode()) { - const PipelineFlowState& flowState = sourceNode()->evalPipeline(dataset()->animationSettings()->time()); + const PipelineFlowState& flowState = sourceNode()->evaluatePipelineImmediately(PipelineEvalRequest(dataset()->animationSettings()->time(), false)); for(auto a = flowState.attributes().cbegin(); a != flowState.attributes().cend(); ++a) { textString.replace(QStringLiteral("[") + a.key() + QStringLiteral("]"), a.value().toString()); } @@ -112,12 +112,12 @@ textPath.addText(origin, font, textString); QRectF textBounds = textPath.boundingRect(); - if(_alignment.value() & Qt::AlignLeft) textPath.translate(textRect.left(), 0); - else if(_alignment.value() & Qt::AlignRight) textPath.translate(textRect.right() - textBounds.width(), 0); - else if(_alignment.value() & Qt::AlignHCenter) textPath.translate(textRect.left() + textRect.width()/2.0 - textBounds.width()/2.0, 0); - if(_alignment.value() & Qt::AlignTop) textPath.translate(0, textRect.top() + textBounds.height()); - else if(_alignment.value() & Qt::AlignBottom) textPath.translate(0, textRect.bottom()); - else if(_alignment.value() & Qt::AlignVCenter) textPath.translate(0, textRect.top() + textRect.height()/2.0 + textBounds.height()/2.0); + if(alignment() & Qt::AlignLeft) textPath.translate(textRect.left(), 0); + else if(alignment() & Qt::AlignRight) textPath.translate(textRect.right() - textBounds.width(), 0); + else if(alignment() & Qt::AlignHCenter) textPath.translate(textRect.left() + textRect.width()/2.0 - textBounds.width()/2.0, 0); + if(alignment() & Qt::AlignTop) textPath.translate(0, textRect.top() + textBounds.height()); + else if(alignment() & Qt::AlignBottom) textPath.translate(0, textRect.bottom()); + else if(alignment() & Qt::AlignVCenter) textPath.translate(0, textRect.top() + textRect.height()/2.0 + textBounds.height()/2.0); if(outlineEnabled()) { // Always render the outline pen 3 pixels wide, irrespective of frame buffer resolution. diff -Nru ovito-2.8.1+dfsg2/src/core/viewport/overlay/TextLabelOverlay.h ovito-2.9.0+dfsg1/src/core/viewport/overlay/TextLabelOverlay.h --- ovito-2.8.1+dfsg2/src/core/viewport/overlay/TextLabelOverlay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/viewport/overlay/TextLabelOverlay.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TEXT_LABEL_OVERLAY_H -#define __OVITO_TEXT_LABEL_OVERLAY_H +#pragma once + #include #include @@ -48,66 +48,6 @@ setOffsetY(offsetY() + delta.y()); } - /// Returns the corner of the viewport where the label is shown. - int alignment() const { return _alignment; } - - /// Sets the corner of the viewport where the label is shown. - void setAlignment(int align) { _alignment = align; } - - /// Returns the horizontal offset of the label's position. - FloatType offsetX() const { return _offsetX; } - - /// Sets the horizontal offset of the label's position. - void setOffsetX(FloatType offset) { _offsetX = offset; } - - /// Returns the vertical offset of the label's position. - FloatType offsetY() const { return _offsetY; } - - /// Sets the vertical offset of the label's position. - void setOffsetY(FloatType offset) { _offsetY = offset; } - - /// Returns the text label font. - const QFont& font() const { return _font; } - - /// Sets the text label font. - void setFont(const QFont& font) { _font = font; } - - /// Returns the text label font size. - FloatType fontSize() const { return _fontSize; } - - /// Sets the text label font size. - void setFontSize(FloatType fontSize) { _fontSize = fontSize; } - - /// Returns the user-defined text string. - const QString& labelText() const { return _labelText; } - - /// Sets the user-defined text string. - void setLabelText(const QString& text) { _labelText = text; } - - /// Returns the display color of the label. - const Color& textColor() const { return _textColor; } - - /// Sets the display color of the label. - void setTextColor(const Color& c) { _textColor = c; } - - /// Returns the outline color of the font. - const Color& outlineColor() const { return _outlineColor; } - - /// Sets the outline color of the font. - void setOutlineColor(const Color& c) { _outlineColor = c; } - - /// Returns whether a text outline is drawn. - bool outlineEnabled() const { return _outlineEnabled; } - - /// Sets whether a text outline is drawn. - void setOutlineEnabled(bool enable) { _outlineEnabled = enable; } - - /// Returns the ObjectNode providing global attributes that can be reference in the text. - ObjectNode* sourceNode() const { return _sourceNode; } - - /// Sets the ObjectNode providing global attributes that can be reference in the text. - void setSourceNode(ObjectNode* node) { _sourceNode = node; } - public: Q_PROPERTY(Ovito::ObjectNode* sourceNode READ sourceNode WRITE setSourceNode); @@ -115,45 +55,34 @@ private: /// The corner of the viewport where the label is shown in. - PropertyField _alignment; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, alignment, setAlignment); /// Controls the horizontal offset of label position. - PropertyField _offsetX; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, offsetX, setOffsetX); /// Controls the vertical offset of label position. - PropertyField _offsetY; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, offsetY, setOffsetY); /// Controls the label font. - PropertyField _font; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QFont, font, setFont); /// Controls the label font size. - PropertyField _fontSize; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, fontSize, setFontSize); /// The label's text. - PropertyField _labelText; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, labelText, setLabelText); /// The display color of the label. - PropertyField _textColor; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, textColor, setTextColor); /// The text outline color. - PropertyField _outlineColor; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, outlineColor, setOutlineColor); /// Controls the outlining of the font. - PropertyField _outlineEnabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, outlineEnabled, setOutlineEnabled); /// The ObjectNode providing global attributes that can be reference in the text. - ReferenceField _sourceNode; - - DECLARE_PROPERTY_FIELD(_alignment); - DECLARE_PROPERTY_FIELD(_font); - DECLARE_PROPERTY_FIELD(_fontSize); - DECLARE_PROPERTY_FIELD(_offsetX); - DECLARE_PROPERTY_FIELD(_offsetY); - DECLARE_PROPERTY_FIELD(_labelText); - DECLARE_PROPERTY_FIELD(_textColor); - DECLARE_PROPERTY_FIELD(_outlineColor); - DECLARE_PROPERTY_FIELD(_outlineEnabled); - DECLARE_REFERENCE_FIELD(_sourceNode); + DECLARE_MODIFIABLE_REFERENCE_FIELD(ObjectNode, sourceNode, setSourceNode); Q_CLASSINFO("DisplayName", "Text label"); @@ -165,4 +94,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_TEXT_LABEL_OVERLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/core/viewport/overlay/ViewportOverlay.cpp ovito-2.9.0+dfsg1/src/core/viewport/overlay/ViewportOverlay.cpp --- ovito-2.8.1+dfsg2/src/core/viewport/overlay/ViewportOverlay.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/viewport/overlay/ViewportOverlay.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(View) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, ViewportOverlay, RefTarget); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ViewportOverlay, RefTarget); /****************************************************************************** * Constructor. diff -Nru ovito-2.8.1+dfsg2/src/core/viewport/overlay/ViewportOverlay.h ovito-2.9.0+dfsg1/src/core/viewport/overlay/ViewportOverlay.h --- ovito-2.8.1+dfsg2/src/core/viewport/overlay/ViewportOverlay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/viewport/overlay/ViewportOverlay.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VIEWPORT_OVERLAY_H -#define __OVITO_VIEWPORT_OVERLAY_H +#pragma once + #include #include @@ -65,4 +65,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_VIEWPORT_OVERLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/core/viewport/ViewportConfiguration.cpp ovito-2.9.0+dfsg1/src/core/viewport/ViewportConfiguration.cpp --- ovito-2.8.1+dfsg2/src/core/viewport/ViewportConfiguration.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/viewport/ViewportConfiguration.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,12 +28,12 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(View) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, ViewportConfiguration, RefTarget); -DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(ViewportConfiguration, _viewports, "Viewports", Viewport, PROPERTY_FIELD_NO_UNDO|PROPERTY_FIELD_ALWAYS_CLONE); -DEFINE_FLAGS_REFERENCE_FIELD(ViewportConfiguration, _activeViewport, "ActiveViewport", Viewport, PROPERTY_FIELD_NO_UNDO); -DEFINE_FLAGS_REFERENCE_FIELD(ViewportConfiguration, _maximizedViewport, "MaximizedViewport", Viewport, PROPERTY_FIELD_NO_UNDO); -DEFINE_FLAGS_PROPERTY_FIELD(ViewportConfiguration, _orbitCenterMode, "OrbitCenterMode", PROPERTY_FIELD_NO_UNDO); -DEFINE_FLAGS_PROPERTY_FIELD(ViewportConfiguration, _userOrbitCenter, "UserOrbitCenter", PROPERTY_FIELD_NO_UNDO); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ViewportConfiguration, RefTarget); +DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(ViewportConfiguration, viewports, "Viewports", Viewport, PROPERTY_FIELD_NO_UNDO|PROPERTY_FIELD_ALWAYS_CLONE); +DEFINE_FLAGS_REFERENCE_FIELD(ViewportConfiguration, activeViewport, "ActiveViewport", Viewport, PROPERTY_FIELD_NO_UNDO); +DEFINE_FLAGS_REFERENCE_FIELD(ViewportConfiguration, maximizedViewport, "MaximizedViewport", Viewport, PROPERTY_FIELD_NO_UNDO); +DEFINE_FLAGS_PROPERTY_FIELD(ViewportConfiguration, orbitCenterMode, "OrbitCenterMode", PROPERTY_FIELD_NO_UNDO); +DEFINE_FLAGS_PROPERTY_FIELD(ViewportConfiguration, userOrbitCenter, "UserOrbitCenter", PROPERTY_FIELD_NO_UNDO); /****************************************************************************** * Constructor. @@ -41,11 +41,11 @@ ViewportConfiguration::ViewportConfiguration(DataSet* dataset) : RefTarget(dataset), _orbitCenterMode(ORBIT_SELECTION_CENTER), _userOrbitCenter(Point3::Origin()), _viewportSuspendCount(0) { - INIT_PROPERTY_FIELD(ViewportConfiguration::_viewports); - INIT_PROPERTY_FIELD(ViewportConfiguration::_activeViewport); - INIT_PROPERTY_FIELD(ViewportConfiguration::_maximizedViewport); - INIT_PROPERTY_FIELD(ViewportConfiguration::_orbitCenterMode); - INIT_PROPERTY_FIELD(ViewportConfiguration::_userOrbitCenter); + INIT_PROPERTY_FIELD(viewports); + INIT_PROPERTY_FIELD(activeViewport); + INIT_PROPERTY_FIELD(maximizedViewport); + INIT_PROPERTY_FIELD(orbitCenterMode); + INIT_PROPERTY_FIELD(userOrbitCenter); // Repaint viewports when the camera orbit center changed. connect(this, &ViewportConfiguration::cameraOrbitCenterChanged, this, &ViewportConfiguration::updateViewports); @@ -56,10 +56,10 @@ ******************************************************************************/ void ViewportConfiguration::referenceReplaced(const PropertyFieldDescriptor& field, RefTarget* oldTarget, RefTarget* newTarget) { - if(field == PROPERTY_FIELD(ViewportConfiguration::_activeViewport)) { + if(field == PROPERTY_FIELD(activeViewport)) { Q_EMIT activeViewportChanged(_activeViewport); } - else if(field == PROPERTY_FIELD(ViewportConfiguration::_maximizedViewport)) { + else if(field == PROPERTY_FIELD(maximizedViewport)) { Q_EMIT maximizedViewportChanged(_maximizedViewport); } RefTarget::referenceReplaced(field, oldTarget, newTarget); @@ -70,7 +70,7 @@ ******************************************************************************/ void ViewportConfiguration::propertyChanged(const PropertyFieldDescriptor& field) { - if(field == PROPERTY_FIELD(ViewportConfiguration::_orbitCenterMode) || field == PROPERTY_FIELD(ViewportConfiguration::_userOrbitCenter)) { + if(field == PROPERTY_FIELD(orbitCenterMode) || field == PROPERTY_FIELD(userOrbitCenter)) { Q_EMIT cameraOrbitCenterChanged(); } RefTarget::propertyChanged(field); diff -Nru ovito-2.8.1+dfsg2/src/core/viewport/ViewportConfiguration.h ovito-2.9.0+dfsg1/src/core/viewport/ViewportConfiguration.h --- ovito-2.8.1+dfsg2/src/core/viewport/ViewportConfiguration.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/viewport/ViewportConfiguration.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VIEWPORT_CONFIGURATION_H -#define __OVITO_VIEWPORT_CONFIGURATION_H +#pragma once + #include #include @@ -49,20 +49,9 @@ /// Constructor. Q_INVOKABLE ViewportConfiguration(DataSet* dataset); - /// Returns the list of viewports. - const QVector& viewports() const { return _viewports; } - /// Add a record for a new viewport. void addViewport(const OORef& vp) { _viewports.push_back(vp); } - /// \brief Returns the active viewport. - /// \return The active Viewport or \c NULL if no viewport is currently active. - Viewport* activeViewport() { return _activeViewport; } - - /// \brief Returns the maximized viewport. - /// \return The maximized viewport or \c NULL if no one is currently maximized. - Viewport* maximizedViewport() { return _maximizedViewport; } - /// \brief Immediately repaints all viewports that have been scheduled for an update using updateViewports(). /// \sa updateViewports() void processViewportUpdates(); @@ -100,12 +89,6 @@ /// Returns the current center of orbit mode. OrbitCenterMode orbitCenterMode() { return _orbitCenterMode; } - /// Sets the user-defined location around which the camera orbits. - void setUserOrbitCenter(const Point3& center) { _userOrbitCenter = center; } - - /// Returns the user-defined location around which the camera orbits. - const Point3& userOrbitCenter() const { return _userOrbitCenter; } - /// Returns the current location around which the viewport camera orbits. Point3 orbitCenter(); @@ -173,13 +156,13 @@ private: /// The list of viewports. - VectorReferenceField _viewports; + DECLARE_VECTOR_REFERENCE_FIELD(Viewport, viewports); /// The active viewport. May be NULL. - ReferenceField _activeViewport; + DECLARE_REFERENCE_FIELD(Viewport, activeViewport); /// The maximized viewport or NULL. - ReferenceField _maximizedViewport; + DECLARE_REFERENCE_FIELD(Viewport, maximizedViewport); /// This counter is for suspending the viewport updates. int _viewportSuspendCount; @@ -188,19 +171,13 @@ bool _viewportsNeedUpdate; /// Controls around which point the viewport camera should orbit. - PropertyField _orbitCenterMode; + DECLARE_PROPERTY_FIELD(OrbitCenterMode, orbitCenterMode); /// Position of the orbiting center picked by the user. - PropertyField _userOrbitCenter; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Point3, userOrbitCenter, setUserOrbitCenter); Q_OBJECT OVITO_OBJECT - - DECLARE_VECTOR_REFERENCE_FIELD(_viewports); - DECLARE_REFERENCE_FIELD(_activeViewport); - DECLARE_REFERENCE_FIELD(_maximizedViewport); - DECLARE_PROPERTY_FIELD(_orbitCenterMode); - DECLARE_PROPERTY_FIELD(_userOrbitCenter); }; @@ -230,4 +207,4 @@ Q_DECLARE_METATYPE(Ovito::ViewportConfiguration::OrbitCenterMode); Q_DECLARE_TYPEINFO(Ovito::ViewportConfiguration::OrbitCenterMode, Q_PRIMITIVE_TYPE); -#endif // __OVITO_VIEWPORT_CONFIGURATION_H + diff -Nru ovito-2.8.1+dfsg2/src/core/viewport/Viewport.cpp ovito-2.9.0+dfsg1/src/core/viewport/Viewport.cpp --- ovito-2.8.1+dfsg2/src/core/viewport/Viewport.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/viewport/Viewport.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,6 +28,7 @@ #include #include #include +#include /// The default field of view in world units used for orthogonal view types when the scene is empty. #define DEFAULT_ORTHOGONAL_FIELD_OF_VIEW FloatType(200) @@ -40,19 +41,17 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(View) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Core, Viewport, RefTarget); -DEFINE_FLAGS_REFERENCE_FIELD(Viewport, _viewNode, "ViewNode", ObjectNode, PROPERTY_FIELD_NEVER_CLONE_TARGET | PROPERTY_FIELD_NO_SUB_ANIM); -DEFINE_FLAGS_PROPERTY_FIELD(Viewport, _viewType, "ViewType", PROPERTY_FIELD_NO_UNDO); -DEFINE_FLAGS_PROPERTY_FIELD(Viewport, _gridMatrix, "GridMatrix", PROPERTY_FIELD_NO_UNDO); -DEFINE_FLAGS_PROPERTY_FIELD(Viewport, _fieldOfView, "FieldOfView", PROPERTY_FIELD_NO_UNDO); -DEFINE_FLAGS_PROPERTY_FIELD(Viewport, _cameraPosition, "CameraPosition", PROPERTY_FIELD_NO_UNDO); -DEFINE_FLAGS_PROPERTY_FIELD(Viewport, _cameraDirection, "CameraDirection", PROPERTY_FIELD_NO_UNDO); -DEFINE_FLAGS_PROPERTY_FIELD(Viewport, _renderPreviewMode, "ShowRenderFrame", PROPERTY_FIELD_NO_UNDO); -DEFINE_FLAGS_PROPERTY_FIELD(Viewport, _viewportTitle, "Title", PROPERTY_FIELD_NO_UNDO); -DEFINE_FLAGS_PROPERTY_FIELD(Viewport, _cameraTM, "CameraTransformation", PROPERTY_FIELD_NO_UNDO); -DEFINE_FLAGS_PROPERTY_FIELD(Viewport, _showGrid, "ShowGrid", PROPERTY_FIELD_NO_UNDO); -DEFINE_FLAGS_PROPERTY_FIELD(Viewport, _stereoscopicMode, "StereoscopicMode", PROPERTY_FIELD_NO_UNDO); -DEFINE_VECTOR_REFERENCE_FIELD(Viewport, _overlays, "Overlays", ViewportOverlay); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Viewport, RefTarget); +DEFINE_FLAGS_REFERENCE_FIELD(Viewport, viewNode, "ViewNode", ObjectNode, PROPERTY_FIELD_NEVER_CLONE_TARGET | PROPERTY_FIELD_NO_SUB_ANIM); +DEFINE_FLAGS_PROPERTY_FIELD(Viewport, viewType, "ViewType", PROPERTY_FIELD_NO_UNDO); +DEFINE_FLAGS_PROPERTY_FIELD(Viewport, gridMatrix, "GridMatrix", PROPERTY_FIELD_NO_UNDO); +DEFINE_FLAGS_PROPERTY_FIELD(Viewport, fieldOfView, "FieldOfView", PROPERTY_FIELD_NO_UNDO); +DEFINE_FLAGS_PROPERTY_FIELD(Viewport, renderPreviewMode, "ShowRenderFrame", PROPERTY_FIELD_NO_UNDO); +DEFINE_FLAGS_PROPERTY_FIELD(Viewport, viewportTitle, "Title", PROPERTY_FIELD_NO_UNDO); +DEFINE_FLAGS_PROPERTY_FIELD(Viewport, cameraTransformation, "CameraTransformation", PROPERTY_FIELD_NO_UNDO); +DEFINE_FLAGS_PROPERTY_FIELD(Viewport, isGridVisible, "ShowGrid", PROPERTY_FIELD_NO_UNDO); +DEFINE_FLAGS_PROPERTY_FIELD(Viewport, stereoscopicMode, "StereoscopicMode", PROPERTY_FIELD_NO_UNDO); +DEFINE_VECTOR_REFERENCE_FIELD(Viewport, overlays, "Overlays", ViewportOverlay); /****************************************************************************** * Constructor. @@ -62,25 +61,22 @@ _fieldOfView(100), _renderPreviewMode(false), _isRendering(false), - _cameraPosition(Point3::Origin()), _cameraDirection(Vector3::Zero()), - _cameraTM(AffineTransformation::Identity()), + _cameraTransformation(AffineTransformation::Identity()), _gridMatrix(AffineTransformation::Identity()), - _showGrid(false), + _isGridVisible(false), _stereoscopicMode(false), _window(nullptr) { - INIT_PROPERTY_FIELD(Viewport::_viewNode); - INIT_PROPERTY_FIELD(Viewport::_viewType); - INIT_PROPERTY_FIELD(Viewport::_gridMatrix); - INIT_PROPERTY_FIELD(Viewport::_fieldOfView); - INIT_PROPERTY_FIELD(Viewport::_cameraPosition); - INIT_PROPERTY_FIELD(Viewport::_cameraDirection); - INIT_PROPERTY_FIELD(Viewport::_renderPreviewMode); - INIT_PROPERTY_FIELD(Viewport::_viewportTitle); - INIT_PROPERTY_FIELD(Viewport::_cameraTM); - INIT_PROPERTY_FIELD(Viewport::_showGrid); - INIT_PROPERTY_FIELD(Viewport::_overlays); - INIT_PROPERTY_FIELD(Viewport::_stereoscopicMode); + INIT_PROPERTY_FIELD(viewNode); + INIT_PROPERTY_FIELD(viewType); + INIT_PROPERTY_FIELD(gridMatrix); + INIT_PROPERTY_FIELD(fieldOfView); + INIT_PROPERTY_FIELD(renderPreviewMode); + INIT_PROPERTY_FIELD(viewportTitle); + INIT_PROPERTY_FIELD(cameraTransformation); + INIT_PROPERTY_FIELD(isGridVisible); + INIT_PROPERTY_FIELD(overlays); + INIT_PROPERTY_FIELD(stereoscopicMode); connect(&ViewportSettings::getSettings(), &ViewportSettings::settingsChanged, this, &Viewport::viewportSettingsChanged); } @@ -225,7 +221,7 @@ params.inverseViewMatrix = viewNode()->getWorldTransform(time, params.validityInterval); params.viewMatrix = params.inverseViewMatrix.inverse(); - PipelineFlowState state = viewNode()->evalPipeline(time); + PipelineFlowState state = viewNode()->evaluatePipelineImmediately(PipelineEvalRequest(time, true)); if(OORef camera = state.convertObject(time)) { // Get remaining parameters from camera object. @@ -248,7 +244,7 @@ // Compute projection matrix. if(params.isPerspective) { - if(bb.minc.z() < -FLOATTYPE_EPSILON) { + if(bb.minc.z() < 0) { params.zfar = -bb.minc.z(); params.znear = std::max(-bb.maxc.z(), params.zfar * FloatType(1e-4)); } @@ -262,7 +258,9 @@ else { if(!bb.isEmpty()) { params.znear = -bb.maxc.z(); - params.zfar = std::max(-bb.minc.z(), params.znear + FloatType(1)); + params.zfar = -bb.minc.z(); + if(params.zfar <= params.znear) + params.zfar = params.znear + FloatType(1); } else { params.znear = 1; @@ -335,8 +333,8 @@ if(trans.y() < minY) minY = trans.y(); if(trans.y() > maxY) maxY = trans.y(); } - FloatType w = std::max(maxX - minX, FloatType(1e-5)); - FloatType h = std::max(maxY - minY, FloatType(1e-5)); + FloatType w = std::max(maxX - minX, FloatType(1e-12)); + FloatType h = std::max(maxY - minY, FloatType(1e-12)); if(aspectRatio > h/w) setFieldOfView(w * aspectRatio * FloatType(0.55)); else @@ -375,7 +373,7 @@ ******************************************************************************/ void Viewport::referenceReplaced(const PropertyFieldDescriptor& field, RefTarget* oldTarget, RefTarget* newTarget) { - if(field == PROPERTY_FIELD(Viewport::_viewNode)) { + if(field == PROPERTY_FIELD(viewNode)) { if(viewType() == VIEW_SCENENODE && newTarget == nullptr) { // If the camera node has been deleted, switch to Orthographic or Perspective view type. // Keep current camera orientation. @@ -398,7 +396,7 @@ ******************************************************************************/ void Viewport::referenceInserted(const PropertyFieldDescriptor& field, RefTarget* newTarget, int listIndex) { - if(field == PROPERTY_FIELD(Viewport::_overlays)) { + if(field == PROPERTY_FIELD(overlays)) { updateViewport(); } RefTarget::referenceInserted(field, newTarget, listIndex); @@ -409,40 +407,19 @@ ******************************************************************************/ void Viewport::referenceRemoved(const PropertyFieldDescriptor& field, RefTarget* oldTarget, int listIndex) { - if(field == PROPERTY_FIELD(Viewport::_overlays)) { + if(field == PROPERTY_FIELD(overlays)) { updateViewport(); } RefTarget::referenceRemoved(field, oldTarget, listIndex); } /****************************************************************************** -* Loads the class' contents from an input stream. -******************************************************************************/ -void Viewport::loadFromStream(ObjectLoadStream& stream) -{ - RefTarget::loadFromStream(stream); - - // The old OVITO versions stored the camera transformation not as a matrix but - // as a position and a direction vector. After loading an old OVITO file, we - // have to convert the position/direction representation to a matrix representation. - if(_cameraDirection.value() != Vector3::Zero()) { - setCameraPosition(_cameraPosition); - setCameraDirection(_cameraDirection); - _cameraDirection = Vector3(Vector3::Zero()); - } - - // The global viewport settings may have changed. - // Adjust camera orientation according to new settings. - setCameraDirection(cameraDirection()); -} - -/****************************************************************************** * Is called when the value of a property field of this object has changed. ******************************************************************************/ void Viewport::propertyChanged(const PropertyFieldDescriptor& field) { RefTarget::propertyChanged(field); - if(field == PROPERTY_FIELD(Viewport::_viewType)) { + if(field == PROPERTY_FIELD(viewType)) { updateViewportTitle(); } updateViewport(); @@ -453,7 +430,7 @@ ******************************************************************************/ void Viewport::viewportSettingsChanged(ViewportSettings* newSettings) { - // Update camera TM if up axis ha changed. + // Update camera TM if up axis has changed. setCameraDirection(cameraDirection()); // Redraw viewport. @@ -477,7 +454,7 @@ case VIEW_PERSPECTIVE: _viewportTitle = tr("Perspective"); break; case VIEW_SCENENODE: if(viewNode() != nullptr) - _viewportTitle = viewNode()->name(); + _viewportTitle = viewNode()->nodeName(); else _viewportTitle = tr("No view node"); break; @@ -566,8 +543,7 @@ renderer->setProjParams(projectionParams()); // Call the viewport renderer to render the scene objects. - renderer->renderFrame(nullptr, SceneRenderer::NonStereoscopic, nullptr); - + renderer->renderFrame(nullptr, SceneRenderer::NonStereoscopic, dataset()->container()->taskManager()); } else { @@ -592,7 +568,7 @@ renderer->setProjParams(params); // Render image of left eye. - renderer->renderFrame(nullptr, SceneRenderer::StereoscopicLeft, nullptr); + renderer->renderFrame(nullptr, SceneRenderer::StereoscopicLeft, dataset()->container()->taskManager()); // Setup project of right eye. left = -c * params.znear / convergence; @@ -604,7 +580,7 @@ renderer->setProjParams(params); // Render image of right eye. - renderer->renderFrame(nullptr, SceneRenderer::StereoscopicRight, nullptr); + renderer->renderFrame(nullptr, SceneRenderer::StereoscopicRight, dataset()->container()->taskManager()); } // Render viewport overlays. @@ -638,7 +614,7 @@ } // Finish rendering. - renderer->endFrame(); + renderer->endFrame(true); renderer->endRender(); _isRendering = false; @@ -728,7 +704,7 @@ if(isPerspectiveProjection()) { Point3 p = projectionParams().viewMatrix * worldPosition; - if(std::abs(p.z()) < FLOATTYPE_EPSILON) return FloatType(1); + if(p.z() == 0) return FloatType(1); Point3 p1 = projectionParams().projectionMatrix * p; Point3 p2 = projectionParams().projectionMatrix * (p + Vector3(1,0,0)); diff -Nru ovito-2.8.1+dfsg2/src/core/viewport/Viewport.h ovito-2.9.0+dfsg1/src/core/viewport/Viewport.h --- ovito-2.8.1+dfsg2/src/core/viewport/Viewport.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/viewport/Viewport.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VIEWPORT_H -#define __OVITO_VIEWPORT_H +#pragma once + #include #include @@ -129,10 +129,6 @@ /// \brief Returns whether the rendering of the viewport's contents is currently in progress. bool isRendering() const { return _isRendering; } - /// \brief Returns the view type of the viewport. - /// \return The type of view used in the viewport. - ViewType viewType() const { return _viewType; } - /// \brief Changes the view type. /// \param type The new view type. /// \param keepViewParams When setting the view type to ViewType::VIEW_ORTHO or ViewType::VIEW_PERSPECTIVE, @@ -145,31 +141,15 @@ /// returns false if it is using an orthogonal projection. bool isPerspectiveProjection() const; - /// \brief Returns the field of view value of the viewport. - /// \return Vertical camera angle in radians if the viewport uses a perspective projection or - /// the field of view in the vertical direction in world units if the viewport - /// uses an orthogonal projection. - FloatType fieldOfView() const { return _fieldOfView; } - /// \brief Sets the zoom of the viewport. /// \param fov Vertical camera angle in radians if the viewport uses a perspective projection or /// the field of view in the vertical direction in world units if the viewport /// uses an orthogonal projection. void setFieldOfView(FloatType fov) { // Clamp FOV to reasonable interval. - if(fov > 1e12f) fov = 1e12f; - else if(fov < -1e12f) fov = -1e12f; - _fieldOfView = fov; + _fieldOfView = qBound(FloatType(-1e12), fov, FloatType(1e12)); } - /// \brief Returns the orientation of the viewport's camera in space. - /// \note This is only used when viewNode() == NULL. - const AffineTransformation& cameraTransformation() const { return _cameraTM; } - - /// \brief Sets the position and orientation of the viewport's camera in space. - /// \note This only has effect when viewNode() == NULL. - void setCameraTransformation(const AffineTransformation& tm) { _cameraTM = tm; } - /// \brief Returns the viewing direction of the camera. Vector3 cameraDirection() const { if(cameraTransformation().column(2) == Vector3::Zero()) return Vector3(0,0,1); @@ -194,34 +174,6 @@ /// Return the current 3D projection used to render the contents of the viewport. const ViewProjectionParameters& projectionParams() const { return _projParams; } - /// \brief Returns whether the viewport displays a realtime preview of the rendered image. - bool renderPreviewMode() const { return _renderPreviewMode; } - - /// \brief Sets whether the viewport displays a realtime preview of the rendered image. - void setRenderPreviewMode(bool show) { _renderPreviewMode = show; } - - /// \brief Returns whether the grid is shown in the viewport. - bool isGridVisible() const { return _showGrid; } - - /// \brief Sets whether the grid is shown in the viewport. - void setGridVisible(bool showGrid) { _showGrid = showGrid; } - - /// \brief Returns whether stereoscopic rendering is enabled for this viewport. - bool stereoscopicMode() const { return _stereoscopicMode; } - - /// \brief Enables or disables stereoscopic rendering for this viewport. - void setStereoscopicMode(bool enable) { _stereoscopicMode = enable; } - - /// \brief Gets the scene node used as camera for the viewport. - /// \return The scene node or \c NULL if no scene node has been set. - ObjectNode* viewNode() const { return _viewNode; } - - /// \brief Sets the scene node used as camera for the viewport. - /// \param node The scene node to be used as view point. The scene node must be a camera object and the - /// viewport type must have been set to ViewType::VIEW_SCENENODE using setViewType() - /// to enable the camera tracking mode for this viewport. - void setViewNode(ObjectNode* node) { _viewNode = node; } - /// \brief Returns the current orbit center for this viewport. Point3 orbitCenter(); @@ -279,16 +231,6 @@ /// \brief Zooms to the extents of the given bounding box. Q_INVOKABLE void zoomToBox(const Box3& box); - /// \brief Returns the transformation matrix that defines the orientation of the viewport grid in world space. - const AffineTransformation& gridMatrix() const { return _gridMatrix; } - - /// \brief Sets the orientation of the viewport grid in world space. - void setGridMatrix(const AffineTransformation& tm) { _gridMatrix = tm; } - - /// \brief Returns the caption of the viewport. - /// \return The title of the viewport. - const QString& viewportTitle() const { return _viewportTitle; } - /// \brief Returns a color value for drawing something in the viewport. The user can configure the color for each element. /// \param which The enum constant that specifies what type of element to draw. /// \return The color that should be used for the given element type. @@ -296,9 +238,6 @@ return ViewportSettings::getSettings().viewportColor(which); } - /// Returns this viewport's list of overlays. - const QVector& overlays() const { return _overlays; } - /// \brief Inserts an overlay into this viewport's list of overlays. /// \param index The position at which to insert the overlay. /// \param overlay The overlay to insert. @@ -346,9 +285,6 @@ /// Is called when a RefTarget has been removed from a VectorReferenceField. virtual void referenceRemoved(const PropertyFieldDescriptor& field, RefTarget* oldTarget, int listIndex) override; - /// Loads the class' contents from an input stream. - virtual void loadFromStream(ObjectLoadStream& stream) override; - protected: /// Updates the title text of the viewport based on the current view type. @@ -366,39 +302,31 @@ private: /// The type of the viewport (top, left, perspective, etc.) - PropertyField _viewType; + DECLARE_PROPERTY_FIELD(ViewType, viewType); /// The orientation of the grid. - PropertyField _gridMatrix; + DECLARE_MODIFIABLE_PROPERTY_FIELD(AffineTransformation, gridMatrix, setGridMatrix); /// The zoom or field of view. - PropertyField _fieldOfView; - - /// The position of the camera in world space. - /// Note: This property field is obsolete and no longer used. We only keep it for file compatibility. - PropertyField _cameraPosition; - - /// The viewing direction of the camera in world space. - /// Note: This property field is obsolete and no longer used. We only keep it for file compatibility. - PropertyField _cameraDirection; + DECLARE_PROPERTY_FIELD(FloatType, fieldOfView); /// The orientation of the camera. - PropertyField _cameraTM; + DECLARE_MODIFIABLE_PROPERTY_FIELD(AffineTransformation, cameraTransformation, setCameraTransformation); /// Indicates whether the rendering frame is shown. - PropertyField _renderPreviewMode; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, renderPreviewMode, setRenderPreviewMode); /// Indicates whether the grid is shown. - PropertyField _showGrid; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, isGridVisible, setGridVisible); /// Enables stereoscopic rendering. - PropertyField _stereoscopicMode; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, stereoscopicMode, setStereoscopicMode); /// The scene node (camera) that has been selected as the view node. - ReferenceField _viewNode; + DECLARE_MODIFIABLE_REFERENCE_FIELD(ObjectNode, viewNode, setViewNode); /// The title of the viewport. - PropertyField _viewportTitle; + DECLARE_PROPERTY_FIELD(QString, viewportTitle); /// This flag is true during the rendering phase. bool _isRendering; @@ -407,7 +335,7 @@ ViewProjectionParameters _projParams; /// The list of overlay objects owned by this viewport. - VectorReferenceField _overlays; + DECLARE_VECTOR_REFERENCE_FIELD(ViewportOverlay, overlays); /// The GUI window associated with this viewport. ViewportWindowInterface* _window; @@ -416,20 +344,6 @@ Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_viewNode); - DECLARE_PROPERTY_FIELD(_viewType); - DECLARE_PROPERTY_FIELD(_shadingMode); - DECLARE_PROPERTY_FIELD(_gridMatrix); - DECLARE_PROPERTY_FIELD(_fieldOfView); - DECLARE_PROPERTY_FIELD(_cameraPosition); - DECLARE_PROPERTY_FIELD(_cameraDirection); - DECLARE_PROPERTY_FIELD(_renderPreviewMode); - DECLARE_PROPERTY_FIELD(_viewportTitle); - DECLARE_PROPERTY_FIELD(_cameraTM); - DECLARE_PROPERTY_FIELD(_showGrid); - DECLARE_PROPERTY_FIELD(_stereoscopicMode); - DECLARE_VECTOR_REFERENCE_FIELD(_overlays); }; OVITO_END_INLINE_NAMESPACE @@ -440,4 +354,4 @@ #include -#endif // __OVITO_VIEWPORT_H + diff -Nru ovito-2.8.1+dfsg2/src/core/viewport/ViewportSettings.cpp ovito-2.9.0+dfsg1/src/core/viewport/ViewportSettings.cpp --- ovito-2.8.1+dfsg2/src/core/viewport/ViewportSettings.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/viewport/ViewportSettings.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -167,7 +167,7 @@ QColor c = store.value(key).value(); bool ok; int index = colorEnum.keyToValue(key.toUtf8().constData(), &ok); - if(ok && index >= 0 && index < NUMBER_OF_COLORS) { + if(ok && index >= 0 && index < NUMBER_OF_COLORS && c.isValid()) { _viewportColors[index] = Color(c); } } diff -Nru ovito-2.8.1+dfsg2/src/core/viewport/ViewportSettings.h ovito-2.9.0+dfsg1/src/core/viewport/ViewportSettings.h --- ovito-2.8.1+dfsg2/src/core/viewport/ViewportSettings.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/viewport/ViewportSettings.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VIEWPORT_SETTINGS_H -#define __OVITO_VIEWPORT_SETTINGS_H +#pragma once + #include @@ -145,4 +145,4 @@ Q_DECLARE_TYPEINFO(Ovito::ViewportSettings::ViewportColor, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::ViewportSettings::UpDirection, Q_PRIMITIVE_TYPE); -#endif // __OVITO_VIEWPORT_SETTINGS_H + diff -Nru ovito-2.8.1+dfsg2/src/core/viewport/ViewportWindowInterface.h ovito-2.9.0+dfsg1/src/core/viewport/ViewportWindowInterface.h --- ovito-2.8.1+dfsg2/src/core/viewport/ViewportWindowInterface.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/core/viewport/ViewportWindowInterface.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,11 +19,13 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VIEWPORT_WINDOW_INTERFACE_H -#define __OVITO_VIEWPORT_WINDOW_INTERFACE_H +#pragma once + #include +class QOpenGLContext; // Defined in QtGui headers + namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Internal) /** @@ -56,10 +58,13 @@ /// Renders custom GUI elements in the viewport on top of the scene. virtual void renderGui() = 0; + + /// Provides access to the OpenGL context used by the viewport window for rendering. + virtual QOpenGLContext* glcontext() = 0; }; OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_VIEWPORT_WINDOW_INTERFACE_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/actions/ActionManager.cpp ovito-2.9.0+dfsg1/src/gui/actions/ActionManager.cpp --- ovito-2.8.1+dfsg2/src/gui/actions/ActionManager.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/actions/ActionManager.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -52,15 +52,15 @@ createCommandAction(ACTION_FILE_REMOTE_IMPORT, tr("Load Remote File"), ":/gui/actions/file/file_import_remote.png", tr("Import a file from a remote location."), Qt::CTRL + Qt::SHIFT + Qt::Key_I); createCommandAction(ACTION_FILE_EXPORT, tr("Export File"), ":/gui/actions/file/file_export.png", tr("Export data to a file."), Qt::CTRL + Qt::Key_E); createCommandAction(ACTION_FILE_NEW_WINDOW, tr("New Program Window"), ":/gui/actions/file/file_new.png", tr("Opens a new OVITO window.")); - createCommandAction(ACTION_HELP_ABOUT, tr("About Ovito"), NULL, tr("Show information about the application.")); - createCommandAction(ACTION_HELP_SHOW_ONLINE_HELP, tr("User Manual"), NULL, tr("Open the user manual."), QKeySequence::HelpContents); - createCommandAction(ACTION_HELP_OPENGL_INFO, tr("OpenGL Information"), NULL, tr("Display OpenGL graphics driver information.")); + createCommandAction(ACTION_HELP_ABOUT, tr("About Ovito"), nullptr, tr("Show information about the application.")); + createCommandAction(ACTION_HELP_SHOW_ONLINE_HELP, tr("User Manual"), nullptr, tr("Open the user manual."), QKeySequence::HelpContents); + createCommandAction(ACTION_HELP_OPENGL_INFO, tr("OpenGL Information"), nullptr, tr("Display OpenGL graphics driver information.")); createCommandAction(ACTION_EDIT_UNDO, tr("Undo"), ":/gui/actions/edit/edit_undo.png", tr("Reverse a user action."), QKeySequence::Undo); createCommandAction(ACTION_EDIT_REDO, tr("Redo"), ":/gui/actions/edit/edit_redo.png", tr("Redo the previously undone user action."), QKeySequence::Redo); createCommandAction(ACTION_EDIT_DELETE, tr("Delete"), ":/gui/actions/edit/edit_delete.png", tr("Deletes the selected objects.")); - createCommandAction(ACTION_SETTINGS_DIALOG, tr("&Settings...")); + createCommandAction(ACTION_SETTINGS_DIALOG, tr("&Settings..."), nullptr, QString(), QKeySequence::Preferences); createCommandAction(ACTION_RENDER_ACTIVE_VIEWPORT, tr("Render Active Viewport"), ":/gui/actions/rendering/render_active_viewport.png"); @@ -81,14 +81,14 @@ createViewportModeAction(ACTION_XFORM_MOVE_MODE, vpInputManager->moveMode(), tr("Move"), ":/gui/actions/edit/mode_move.png", tr("Move objects.")); createViewportModeAction(ACTION_XFORM_ROTATE_MODE, vpInputManager->rotateMode(), tr("Rotate"), ":/gui/actions/edit/mode_rotate.png", tr("Rotate objects.")); - createCommandAction(ACTION_GOTO_START_OF_ANIMATION, tr("Goto Start of Animation"), ":/gui/actions/animation/goto_animation_start.png", QString(), Qt::Key_Home); - createCommandAction(ACTION_GOTO_END_OF_ANIMATION, tr("Goto End of Animation"), ":/gui/actions/animation/goto_animation_end.png", QString(), Qt::Key_End); - createCommandAction(ACTION_GOTO_PREVIOUS_FRAME, tr("Goto Previous Frame"), ":/gui/actions/animation/goto_previous_frame.png", QString(), Qt::Key_Minus); - createCommandAction(ACTION_GOTO_NEXT_FRAME, tr("Goto Next Frame"), ":/gui/actions/animation/goto_next_frame.png", QString(), Qt::Key_Plus); + createCommandAction(ACTION_GOTO_START_OF_ANIMATION, tr("Go to Start of Animation"), ":/gui/actions/animation/goto_animation_start.png", QString(), Qt::Key_Home); + createCommandAction(ACTION_GOTO_END_OF_ANIMATION, tr("Go to End of Animation"), ":/gui/actions/animation/goto_animation_end.png", QString(), Qt::Key_End); + createCommandAction(ACTION_GOTO_PREVIOUS_FRAME, tr("Go to Previous Frame"), ":/gui/actions/animation/goto_previous_frame.png", QString(), Qt::ALT + Qt::Key_Left); + createCommandAction(ACTION_GOTO_NEXT_FRAME, tr("Go to Next Frame"), ":/gui/actions/animation/goto_next_frame.png", QString(), Qt::ALT + Qt::Key_Right); createCommandAction(ACTION_START_ANIMATION_PLAYBACK, tr("Start Animation Playback"), ":/gui/actions/animation/play_animation.png"); createCommandAction(ACTION_STOP_ANIMATION_PLAYBACK, tr("Stop Animation Playback"), ":/gui/actions/animation/stop_animation.png"); createCommandAction(ACTION_ANIMATION_SETTINGS, tr("Animation Settings"), ":/gui/actions/animation/animation_settings.png"); - createCommandAction(ACTION_TOGGLE_ANIMATION_PLAYBACK, tr("Play Animation"), ":/gui/actions/animation/play_animation.png")->setCheckable(true); + createCommandAction(ACTION_TOGGLE_ANIMATION_PLAYBACK, tr("Play Animation"), ":/gui/actions/animation/play_animation.png", QString(), Qt::Key_Space)->setCheckable(true); createCommandAction(ACTION_AUTO_KEY_MODE_TOGGLE, tr("Auto Key Mode"), ":/gui/actions/animation/animation_mode.png")->setCheckable(true); QMetaObject::connectSlotsByName(this); @@ -190,7 +190,7 @@ void ActionManager::addAction(QAction* action) { OVITO_CHECK_POINTER(action); - OVITO_ASSERT_MSG(action->parent() == this || findAction(action->objectName()) == NULL, "ActionManager::addAction()", "There is already an action with the same ID."); + OVITO_ASSERT_MSG(action->parent() == this || findAction(action->objectName()) == nullptr, "ActionManager::addAction()", "There is already an action with the same ID."); // Make it a child of this manager. action->setParent(this); @@ -203,8 +203,12 @@ { QAction* action = new QAction(title, this); action->setObjectName(id); - if(!shortcut.isEmpty()) action->setShortcut(shortcut); - action->setStatusTip(statusTip); + if(!shortcut.isEmpty()) + action->setShortcut(shortcut); + if(!statusTip.isEmpty()) + action->setStatusTip(statusTip); + if(!shortcut.isEmpty()) + action->setToolTip(QStringLiteral("%1 [%2]").arg(title).arg(shortcut.toString(QKeySequence::NativeText))); if(iconPath) action->setIcon(QIcon(QString(iconPath))); addAction(action); @@ -218,8 +222,11 @@ { QAction* action = new ViewportModeAction(mainWindow(), title, this, inputHandler); action->setObjectName(id); - if(!shortcut.isEmpty()) action->setShortcut(shortcut); + if(!shortcut.isEmpty()) + action->setShortcut(shortcut); action->setStatusTip(statusTip); + if(!shortcut.isEmpty()) + action->setToolTip(QStringLiteral("%1 [%2]").arg(title).arg(shortcut.toString(QKeySequence::NativeText))); if(iconPath) action->setIcon(QIcon(QString(iconPath))); addAction(action); diff -Nru ovito-2.8.1+dfsg2/src/gui/actions/ActionManager.h ovito-2.9.0+dfsg1/src/gui/actions/ActionManager.h --- ovito-2.8.1+dfsg2/src/gui/actions/ActionManager.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/actions/ActionManager.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ACTION_MANAGER_H -#define __OVITO_ACTION_MANAGER_H +#pragma once + #include #include @@ -244,4 +244,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ACTION_MANAGER_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/actions/FileActions.cpp ovito-2.9.0+dfsg1/src/gui/actions/FileActions.cpp --- ovito-2.8.1+dfsg2/src/gui/actions/FileActions.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/actions/FileActions.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -55,7 +55,7 @@ QMessageBox::Ok, mainWindow()); msgBox.setInformativeText(tr( "

A visualization and analysis software for atomistic simulation data.

" - "

Copyright (C) 2013-2016, Alexander Stukowski

" + "

Copyright (C) 2017, Alexander Stukowski

" "

" "This is free, open-source software, and you are welcome to redistribute\n" "it under certain conditions. See the source for copying conditions.

" @@ -157,7 +157,7 @@ mainWin->datasetContainer().fileNew(); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } @@ -172,7 +172,7 @@ } } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } @@ -207,7 +207,7 @@ mainWindow()->datasetContainer().fileLoad(filename); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } @@ -224,7 +224,7 @@ mainWindow()->datasetContainer().fileSave(); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } @@ -237,7 +237,7 @@ mainWindow()->datasetContainer().fileSaveAs(); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } @@ -265,7 +265,7 @@ mainWindow()->datasetContainer().importFile(QUrl::fromLocalFile(dialog.fileToImport()), dialog.selectedFileImporterType()); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } @@ -284,7 +284,7 @@ mainWindow()->datasetContainer().importFile(dialog.fileToImport(), dialog.selectedFileImporterType()); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } @@ -304,7 +304,7 @@ catch(...) { filterStrings << QString(); } } if(filterStrings.isEmpty()) { - Exception(tr("This function is disabled, because there are no export services available."), _dataset).showError(); + Exception(tr("This function is disabled, because there are no export services available."), _dataset).reportError(); return; } @@ -333,6 +333,7 @@ QStringList files = dialog.selectedFiles(); if(files.isEmpty()) return; + QString exportFile = files.front(); // Remember directory for the next time... @@ -355,8 +356,11 @@ exporter->setOutputFilename(exportFile); // Wait until the scene is ready. - if(!_dataset->waitUntilSceneIsReady(tr("Waiting for running tasks to complete."))) - return; + { + ProgressDialog progressDialog(mainWindow(), tr("File export")); + if(!progressDialog.taskManager().waitForTask(_dataset->makeSceneReady(tr("Waiting for running tasks to complete.")))) + return; + } // Choose the scene nodes to be exported. exporter->selectStandardOutputData(); @@ -367,19 +371,13 @@ return; // Show progress dialog. - QProgressDialog progressDialog(mainWindow()); - progressDialog.setWindowModality(Qt::WindowModal); - progressDialog.setAutoClose(false); - progressDialog.setAutoReset(false); - progressDialog.setMinimumDuration(0); - progressDialog.setValue(0); - ProgressDialogAdapter progressDisplay(&progressDialog); + ProgressDialog progressDialog(mainWindow(), tr("File export")); // Let the exporter do its work. - exporter->exportNodes(&progressDisplay); + exporter->exportNodes(progressDialog.taskManager()); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } diff -Nru ovito-2.8.1+dfsg2/src/gui/actions/RenderActions.cpp ovito-2.9.0+dfsg1/src/gui/actions/RenderActions.cpp --- ovito-2.8.1+dfsg2/src/gui/actions/RenderActions.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/actions/RenderActions.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include @@ -57,20 +57,14 @@ frameBufferWindow->showAndActivateWindow(); // Show progress dialog. - QProgressDialog progressDialog(frameBufferWindow); - progressDialog.setWindowModality(Qt::WindowModal); - progressDialog.setAutoClose(false); - progressDialog.setAutoReset(false); - progressDialog.setMinimumDuration(0); - progressDialog.setValue(0); - ProgressDialogAdapter progressDisplay(&progressDialog); + ProgressDialog progressDialog(frameBufferWindow, mainWindow()->datasetContainer().taskManager(), tr("Rendering")); // Call high-level rendering function, which will take care of the rest. - _dataset->renderScene(settings, viewport, frameBuffer.get(), &progressDisplay); + _dataset->renderScene(settings, viewport, frameBuffer.get(), progressDialog.taskManager()); } catch(const Exception& ex) { ex.logError(); - ex.showError(); + ex.reportError(); } } diff -Nru ovito-2.8.1+dfsg2/src/gui/actions/ViewportModeAction.h ovito-2.9.0+dfsg1/src/gui/actions/ViewportModeAction.h --- ovito-2.8.1+dfsg2/src/gui/actions/ViewportModeAction.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/actions/ViewportModeAction.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VIEWPORT_MODE_ACTION_H -#define __OVITO_VIEWPORT_MODE_ACTION_H +#pragma once + #include @@ -74,4 +74,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_VIEWPORT_MODE_ACTION_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/animation/controller/TCBInterpolationControllerEditor.cpp ovito-2.9.0+dfsg1/src/gui/animation/controller/TCBInterpolationControllerEditor.cpp --- ovito-2.8.1+dfsg2/src/gui/animation/controller/TCBInterpolationControllerEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/animation/controller/TCBInterpolationControllerEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Anim) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(Gui, PositionTCBAnimationKeyEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(PositionTCBAnimationKeyEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(PositionTCBAnimationKey, PositionTCBAnimationKeyEditor); OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/gui/animation/controller/TCBInterpolationControllerEditor.h ovito-2.9.0+dfsg1/src/gui/animation/controller/TCBInterpolationControllerEditor.h --- ovito-2.8.1+dfsg2/src/gui/animation/controller/TCBInterpolationControllerEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/animation/controller/TCBInterpolationControllerEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TCB_INTERPOLATION_CONTROLLER_EDITOR_H -#define __OVITO_TCB_INTERPOLATION_CONTROLLER_EDITOR_H +#pragma once + #include #include @@ -52,27 +52,27 @@ layout->addLayout(sublayout); // Ease to parameter. - FloatParameterUI* easeInPUI = new FloatParameterUI(this, PROPERTY_FIELD(TCBAnimationKeyType::_easeTo)); + FloatParameterUI* easeInPUI = new FloatParameterUI(this, PROPERTY_FIELD(TCBAnimationKeyType::easeTo)); sublayout->addWidget(easeInPUI->label(), 0, 0); sublayout->addLayout(easeInPUI->createFieldLayout(), 0, 1); // Ease from parameter. - FloatParameterUI* easeFromPUI = new FloatParameterUI(this, PROPERTY_FIELD(TCBAnimationKeyType::_easeFrom)); + FloatParameterUI* easeFromPUI = new FloatParameterUI(this, PROPERTY_FIELD(TCBAnimationKeyType::easeFrom)); sublayout->addWidget(easeFromPUI->label(), 1, 0); sublayout->addLayout(easeFromPUI->createFieldLayout(), 1, 1); // Tension parameter. - FloatParameterUI* tensionPUI = new FloatParameterUI(this, PROPERTY_FIELD(TCBAnimationKeyType::_tension)); + FloatParameterUI* tensionPUI = new FloatParameterUI(this, PROPERTY_FIELD(TCBAnimationKeyType::tension)); sublayout->addWidget(tensionPUI->label(), 2, 0); sublayout->addLayout(tensionPUI->createFieldLayout(), 2, 1); // Continuity parameter. - FloatParameterUI* continuityPUI = new FloatParameterUI(this, PROPERTY_FIELD(TCBAnimationKeyType::_continuity)); + FloatParameterUI* continuityPUI = new FloatParameterUI(this, PROPERTY_FIELD(TCBAnimationKeyType::continuity)); sublayout->addWidget(continuityPUI->label(), 3, 0); sublayout->addLayout(continuityPUI->createFieldLayout(), 3, 1); // Continuity parameter. - FloatParameterUI* biasPUI = new FloatParameterUI(this, PROPERTY_FIELD(TCBAnimationKeyType::_bias)); + FloatParameterUI* biasPUI = new FloatParameterUI(this, PROPERTY_FIELD(TCBAnimationKeyType::bias)); sublayout->addWidget(biasPUI->label(), 4, 0); sublayout->addLayout(biasPUI->createFieldLayout(), 4, 1); } @@ -98,4 +98,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_TCB_INTERPOLATION_CONTROLLER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/app/GuiApplication.cpp ovito-2.9.0+dfsg1/src/gui/app/GuiApplication.cpp --- ovito-2.8.1+dfsg2/src/gui/app/GuiApplication.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/app/GuiApplication.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -21,9 +21,10 @@ #include #include +#include #include -#include #include +#include #include #include "GuiApplication.h" @@ -34,11 +35,9 @@ ******************************************************************************/ void GuiApplication::registerCommandLineParameters(QCommandLineParser& parser) { - Application::registerCommandLineParameters(parser); + StandaloneApplication::registerCommandLineParameters(parser); parser.addOption(QCommandLineOption(QStringList{{"nogui"}}, tr("Run in console mode without showing the graphical user interface."))); - parser.addOption(QCommandLineOption(QStringList{{"glversion"}}, tr("Selects a specific version of the OpenGL standard."), tr("VERSION"))); - parser.addOption(QCommandLineOption(QStringList{{"glcompatprofile"}}, tr("Request the OpenGL compatibility profile instead of the core profile."))); } /****************************************************************************** @@ -46,7 +45,7 @@ ******************************************************************************/ bool GuiApplication::processCommandLineParameters() { - if(!Application::processCommandLineParameters()) + if(!StandaloneApplication::processCommandLineParameters()) return false; // Check if program was started in console mode. @@ -82,10 +81,10 @@ void GuiApplication::createQtApplication(int& argc, char** argv) { if(headlessMode()) { - Application::createQtApplication(argc, argv); + StandaloneApplication::createQtApplication(argc, argv); } else { - _app.reset(new QApplication(argc, argv)); + new QApplication(argc, argv); #if defined(Q_OS_LINUX) // Enforce Fusion UI style on Linux. @@ -93,16 +92,12 @@ #endif } - // Install GUI exception handler. - if(guiMode()) - Exception::setExceptionHandler(guiExceptionHandler); - -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) // Set the global default OpenGL surface format. // This will let Qt use core profile contexts. - QSurfaceFormat::setDefaultFormat(ViewportSceneRenderer::getDefaultSurfaceFormat()); -#endif + QSurfaceFormat::setDefaultFormat(OpenGLSceneRenderer::getDefaultSurfaceFormat()); + // Process events sent to the Qt application by the OS. + QCoreApplication::instance()->installEventFilter(this); } /****************************************************************************** @@ -169,7 +164,7 @@ if(cmdLineParser().positionalArguments().empty() == false) { QString importFilename = cmdLineParser().positionalArguments().front(); if(!importFilename.endsWith(".ovito", Qt::CaseInsensitive)) { - QUrl importURL = FileManager::instance().urlFromUserInput(importFilename); + QUrl importURL = Application::instance()->fileManager()->urlFromUserInput(importFilename); container->importFile(importURL); container->currentSet()->undoStack().setClean(); } @@ -179,46 +174,111 @@ } /****************************************************************************** +* Handles events sent to the Qt application object. +******************************************************************************/ +bool GuiApplication::eventFilter(QObject* watched, QEvent* event) +{ + if(event->type() == QEvent::FileOpen) { + QFileOpenEvent* openEvent = static_cast(event); + GuiDataSetContainer* container = static_object_cast(datasetContainer()); + try { + if(openEvent->file().endsWith(".ovito", Qt::CaseInsensitive)) { + container->fileLoad(openEvent->file()); + } + else { + container->importFile(openEvent->url()); + container->currentSet()->undoStack().setClean(); + } + } + catch(const Exception& ex) { + ex.reportError(); + } + } + return StandaloneApplication::eventFilter(watched, event); +} + +/****************************************************************************** * Handler function for exceptions used in GUI mode. ******************************************************************************/ -void GuiApplication::guiExceptionHandler(const Exception& exception) +void GuiApplication::reportError(const Exception& ex, bool blocking) { // Always display errors in the terminal window. - exception.logError(); + Application::reportError(ex, blocking); - // Prepare a message box dialog. - QMessageBox msgbox; - msgbox.setWindowTitle(tr("Error - %1").arg(QCoreApplication::applicationName())); - msgbox.setStandardButtons(QMessageBox::Ok); - msgbox.setText(exception.message()); - msgbox.setIcon(QMessageBox::Critical); + if(guiMode()) { + if(!blocking) { + + // Deferred display of the error. + if(_errorList.empty()) + QMetaObject::invokeMethod(this, "showErrorMessages", Qt::QueuedConnection); - // If the exception has been thrown within the context of a DataSet or a DataSetContainer, - // show the message box under the corresponding main window. - if(DataSet* dataset = qobject_cast(exception.context())) { - if(MainWindow* window = MainWindow::fromDataset(dataset)) { - msgbox.setParent(window); - msgbox.setWindowModality(Qt::WindowModal); + // Queue error messages. + _errorList.push_back(ex); } - } - if(GuiDataSetContainer* datasetContainer = qobject_cast(exception.context())) { - if(MainWindow* window = datasetContainer->mainWindow()) { - msgbox.setParent(window); - msgbox.setWindowModality(Qt::WindowModal); + else { + _errorList.push_back(ex); + showErrorMessages(); } } +} - // If the exception is associated with additional message strings, - // show them in the Details section of the message box dialog. - if(exception.messages().size() > 1) { - QString detailText; - for(int i = 1; i < exception.messages().size(); i++) - detailText += exception.messages()[i] + "\n"; - msgbox.setDetailedText(detailText); - } +/****************************************************************************** +* Displays an error message box. This slot is called by reportError(). +******************************************************************************/ +void GuiApplication::showErrorMessages() +{ + while(!_errorList.empty()) { - // Show message box. - msgbox.exec(); + // Show next exception from queue. + const Exception& exception = _errorList.front(); + + // Prepare a message box dialog. + QPointer msgbox = new QMessageBox(); + msgbox->setWindowTitle(tr("Error - %1").arg(QCoreApplication::applicationName())); + msgbox->setStandardButtons(QMessageBox::Ok); + msgbox->setText(exception.message()); + msgbox->setIcon(QMessageBox::Critical); + + // If the exception has been thrown within the context of a DataSet or a DataSetContainer, + // show the message box under the corresponding main window. + MainWindow* window; + if(DataSet* dataset = qobject_cast(exception.context())) { + window = MainWindow::fromDataset(dataset); + } + else if(GuiDataSetContainer* datasetContainer = qobject_cast(exception.context())) { + window = datasetContainer->mainWindow(); + } + else { + window = qobject_cast(exception.context()); + } + + if(window) { + msgbox->setParent(window); + msgbox->setWindowModality(Qt::WindowModal); + + // Stop animation playback when an error occurred. + QAction* playbackAction = window->actionManager()->getAction(ACTION_TOGGLE_ANIMATION_PLAYBACK); + if(playbackAction->isChecked()) + playbackAction->trigger(); + } + + // If the exception is associated with additional message strings, + // show them in the Details section of the message box dialog. + if(exception.messages().size() > 1) { + QString detailText; + for(int i = 1; i < exception.messages().size(); i++) + detailText += exception.messages()[i] + "\n"; + msgbox->setDetailedText(detailText); + } + + // Show message box. + msgbox->exec(); + if(!msgbox) + return; + else + delete msgbox; + _errorList.pop_front(); + } } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/gui/app/GuiApplication.h ovito-2.9.0+dfsg1/src/gui/app/GuiApplication.h --- ovito-2.8.1+dfsg2/src/gui/app/GuiApplication.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/app/GuiApplication.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,21 +19,27 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_GUI_APPLICATION_H -#define __OVITO_GUI_APPLICATION_H +#pragma once + #include #include -#include +#include namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) /** * \brief The main application with a graphical user interface. */ -class OVITO_GUI_EXPORT GuiApplication : public Application +class OVITO_GUI_EXPORT GuiApplication : public StandaloneApplication { - Q_OBJECT +public: + + /// Create the global instance of the right QCoreApplication derived class. + virtual void createQtApplication(int& argc, char** argv) override; + + /// Handler function for exceptions. + virtual void reportError(const Exception& exception, bool blocking) override; protected: @@ -43,27 +49,32 @@ /// Interprets the command line parameters provided to the application. virtual bool processCommandLineParameters() override; - /// Create the global instance of the right QCoreApplication derived class. - virtual void createQtApplication(int& argc, char** argv) override; - /// Prepares application to start running. virtual bool startupApplication() override; /// Creates the global FileManager class instance. virtual FileManager* createFileManager() override; + /// Handles events sent to the Qt application object. + virtual bool eventFilter(QObject* watched, QEvent* event) override; + +private Q_SLOTS: + + /// Displays an error message box. This slot is called by reportError(). + void showErrorMessages(); + private: /// Initializes the graphical user interface of the application. void initializeGUI(); -private: + /// List of errors to be displayed by showErrorMessages(). + std::deque _errorList; - /// Handler function for exceptions used in GUI mode. - static void guiExceptionHandler(const Exception& exception); + Q_OBJECT }; OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_GUI_APPLICATION_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/CMakeLists.txt ovito-2.9.0+dfsg1/src/gui/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/gui/CMakeLists.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -95,8 +95,6 @@ properties/VariantComboBoxParameterUI.cpp properties/Vector3ParameterUI.cpp rendering/ViewportSceneRenderer.cpp - rendering/StandardSceneRenderer.cpp - rendering/StandardSceneRendererEditor.cpp rendering/RenderSettingsEditor.cpp viewport/ViewportWindow.cpp viewport/ViewportMenu.cpp @@ -112,6 +110,7 @@ scene/objects/camera/CameraObjectEditor.cpp scene/objects/geometry/TriMeshDisplayEditor.cpp utilities/io/GuiFileManager.cpp + utilities/concurrent/ProgressDialog.cpp animation/controller/TCBInterpolationControllerEditor.cpp ) @@ -121,6 +120,9 @@ # Build library ADD_LIBRARY(Gui SHARED GUI.cpp ${SourceFiles} ${ResourceFiles}) +# Pass name of gui plugin to the code. +TARGET_COMPILE_DEFINITIONS(Gui PRIVATE "OVITO_PLUGIN_NAME=\"Gui\"") + # Set default include directory. TARGET_INCLUDE_DIRECTORIES(Gui PUBLIC "$") @@ -130,10 +132,6 @@ # Link Qt5. TARGET_LINK_LIBRARIES(Gui PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Network) -# Pass version information to source code. -SET_SOURCE_FILES_PROPERTIES("app/Application.cpp" PROPERTIES COMPILE_DEFINITIONS - "OVITO_VERSION_MAJOR=${OVITO_VERSION_MAJOR};OVITO_VERSION_MINOR=${OVITO_VERSION_MINOR};OVITO_VERSION_REVISION=${OVITO_VERSION_REVISION};OVITO_VERSION_STRING=\"${OVITO_VERSION_STRING}\"") - # Speed up compilation by using precompiled headers. ADD_PRECOMPILED_HEADER(Gui gui/GUI.h) diff -Nru ovito-2.8.1+dfsg2/src/gui/dataset/GuiDataSetContainer.cpp ovito-2.9.0+dfsg1/src/gui/dataset/GuiDataSetContainer.cpp --- ovito-2.8.1+dfsg2/src/gui/dataset/GuiDataSetContainer.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dataset/GuiDataSetContainer.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -31,15 +31,13 @@ #include #include #include -#include #include -#include #include #include "GuiDataSetContainer.h" namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) -IMPLEMENT_OVITO_OBJECT(Gui, GuiDataSetContainer, DataSetContainer); +IMPLEMENT_OVITO_OBJECT(GuiDataSetContainer, DataSetContainer); /****************************************************************************** * Initializes the dataset manager. @@ -47,6 +45,8 @@ GuiDataSetContainer::GuiDataSetContainer(MainWindow* mainWindow) : DataSetContainer(), _mainWindow(mainWindow) { + connect(&taskManager(), &TaskManager::localEventLoopEntered, this, &GuiDataSetContainer::localEventLoopEntered); + connect(&taskManager(), &TaskManager::localEventLoopExited, this, &GuiDataSetContainer::localEventLoopExited); } /****************************************************************************** @@ -67,7 +67,7 @@ currentSet()->undoStack().setClean(); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); return false; } @@ -222,7 +222,7 @@ if(!importerType) { // Download file so we can determine its format. - Future fetchFileFuture = FileManager::instance().fetchUrl(*this, url); + Future fetchFileFuture = Application::instance()->fileManager()->fetchUrl(*this, url); if(!taskManager().waitForTask(fetchFileFuture)) return false; @@ -312,76 +312,38 @@ } /****************************************************************************** -* This function blocks execution until some operation has been completed. +* Is called whenever a local event loop is entered to wait for a task to finish. ******************************************************************************/ -bool GuiDataSetContainer::waitUntil(const std::function& callback, const QString& message, AbstractProgressDisplay* progressDisplay) +void GuiDataSetContainer::localEventLoopEntered() { - OVITO_ASSERT_MSG(QThread::currentThread() == QCoreApplication::instance()->thread(), "GuiDataSetContainer::waitUntil()", "This function may only be called from the main thread."); - - // Check if operation is already completed. - if(callback()) - return true; + if(!currentSet() || !Application::instance()->guiMode()) return; // Suspend viewport updates while waiting. - ViewportSuspender viewportSuspender(currentSet()); + currentSet()->viewportConfig()->suspendViewportUpdates(); - // Check if viewports are currently being rendered. - // If yes, it's not a good idea to display a progress dialog. - bool isRendering = currentSet() ? currentSet()->viewportConfig()->isRendering() : false; - - if(!isRendering && Application::instance().guiMode()) { - - // Show a modal progress dialog to block user interface while waiting. - std::unique_ptr localDialog; - std::unique_ptr dialogAdapter; - if(!progressDisplay) { - localDialog.reset(new QProgressDialog(mainWindow())); - localDialog->setWindowModality(Qt::WindowModal); - localDialog->setAutoClose(false); - localDialog->setAutoReset(false); - localDialog->setMinimumDuration(0); - localDialog->setValue(0); - dialogAdapter.reset(new ProgressDialogAdapter(localDialog.get())); - progressDisplay = dialogAdapter.get(); - } - progressDisplay->setStatusText(message); + // Disable viewport repaints while processing events to + // avoid recursive calls to repaint(). + if(currentSet()->viewportConfig()->isRendering()) { + if(!_viewportRepaintsDisabled) + mainWindow()->viewportsPanel()->setUpdatesEnabled(false); + _viewportRepaintsDisabled++; + } +} - // Poll callback function until it returns true. - while(!callback() && !progressDisplay->wasCanceled()) { - QCoreApplication::processEvents(); - QThread::msleep(10); - } +/****************************************************************************** +* Is called whenever a local event loop was exited after waiting for a task to finish. +******************************************************************************/ +void GuiDataSetContainer::localEventLoopExited() +{ + if(!currentSet() || !Application::instance()->guiMode()) return; - return !progressDisplay->wasCanceled(); - } - else { -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - // Disable viewport repaints while processing events to - // avoid recursive calls to repaint(). - if(Application::instance().guiMode()) { - mainWindow()->viewportsPanel()->setUpdatesEnabled(false); - } -#endif - try { - bool result = DataSetContainer::waitUntil(callback, message, progressDisplay); - -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - // Resume repainting the viewports. - if(Application::instance().guiMode()) { - mainWindow()->viewportsPanel()->setUpdatesEnabled(true); - } -#endif + // Handle viewport updates again. + currentSet()->viewportConfig()->resumeViewportUpdates(); - return result; - } - catch(...) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - // Resume repainting the viewports. - if(Application::instance().guiMode()) - mainWindow()->viewportsPanel()->setUpdatesEnabled(true); -#endif - throw; - } + // Re-enable viewport repaints. + if(currentSet()->viewportConfig()->isRendering()) { + if(--_viewportRepaintsDisabled == 0) + mainWindow()->viewportsPanel()->setUpdatesEnabled(true); } } diff -Nru ovito-2.8.1+dfsg2/src/gui/dataset/GuiDataSetContainer.h ovito-2.9.0+dfsg1/src/gui/dataset/GuiDataSetContainer.h --- ovito-2.8.1+dfsg2/src/gui/dataset/GuiDataSetContainer.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dataset/GuiDataSetContainer.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_GUI_DATASET_CONTAINER_H -#define __OVITO_GUI_DATASET_CONTAINER_H +#pragma once + #include #include @@ -80,22 +80,23 @@ /// If yes, then the dataset is saved by calling fileSave(). bool askForSaveChanges(); - /// \brief This function blocks execution until some operation has been completed. - /// The function displays a progress dialog to block access to the application main window. - /// The dialog allows the user to cancel the operation. - /// \param callback This callback function will be polled to check whether the operation has finished. - /// The callback function should return true to indicate that the operation has finished. - /// \param message The text to be shown to the user while waiting. - /// \param progressDisplay The progress display/dialog to be used for showing the message. - /// If NULL, the function will create and show its own progress dialog box. - /// \return true on success; false if the operation has been canceled by the user. - virtual bool waitUntil(const std::function& callback, const QString& message, AbstractProgressDisplay* progressDisplay = nullptr) override; +private Q_SLOTS: + + /// Is called whenever a local event loop is entered to wait for a task to finish. + void localEventLoopEntered(); + + /// Is called whenever a local event loop was exited after waiting for a task to finish. + void localEventLoopExited(); private: /// The window this dataset container is linked to (may be NULL). MainWindow* _mainWindow; + /// Counts how many times viewport repaints have been disabled so that we can + /// re-enable them again the same number of times. + int _viewportRepaintsDisabled = 0; + Q_OBJECT OVITO_OBJECT }; @@ -103,4 +104,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_GUI_DATASET_CONTAINER_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dataset/importexport/AttributeFileExporterEditor.cpp ovito-2.9.0+dfsg1/src/gui/dataset/importexport/AttributeFileExporterEditor.cpp --- ovito-2.8.1+dfsg2/src/gui/dataset/importexport/AttributeFileExporterEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dataset/importexport/AttributeFileExporterEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -21,12 +21,14 @@ #include #include +#include #include +#include #include "AttributeFileExporterEditor.h" namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(DataIO) -IMPLEMENT_OVITO_OBJECT(Gui, AttributeFileExporterEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(AttributeFileExporterEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(AttributeFileExporter, AttributeFileExporterEditor); /****************************************************************************** @@ -101,7 +103,10 @@ for(SceneNode* node : exporter->outputData()) { try { - QVariantMap attrMap = exporter->getAttributes(node, node->dataset()->animationSettings()->time()); + QVariantMap attrMap; + ProgressDialog progressDialog(container(), exporter->dataset()->container()->taskManager()); + if(!exporter->getAttributes(node, node->dataset()->animationSettings()->time(), attrMap, progressDialog.taskManager())) + continue; for(const QString& attrName : attrMap.keys()) insertAttributeItem(attrName, exporter->attributesToExport()); break; diff -Nru ovito-2.8.1+dfsg2/src/gui/dataset/importexport/AttributeFileExporterEditor.h ovito-2.9.0+dfsg1/src/gui/dataset/importexport/AttributeFileExporterEditor.h --- ovito-2.8.1+dfsg2/src/gui/dataset/importexport/AttributeFileExporterEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dataset/importexport/AttributeFileExporterEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ATTRIBUTE_FILE_EXPORTER_EDITOR_H -#define __OVITO_ATTRIBUTE_FILE_EXPORTER_EDITOR_H +#pragma once + #include #include @@ -64,4 +64,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ATTRIBUTE_FILE_EXPORTER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dataset/importexport/FileImporterEditor.cpp ovito-2.9.0+dfsg1/src/gui/dataset/importexport/FileImporterEditor.cpp --- ovito-2.8.1+dfsg2/src/gui/dataset/importexport/FileImporterEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dataset/importexport/FileImporterEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(DataIO) -IMPLEMENT_OVITO_OBJECT(Gui, FileImporterEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(FileImporterEditor, PropertiesEditor); OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/gui/dataset/importexport/FileImporterEditor.h ovito-2.9.0+dfsg1/src/gui/dataset/importexport/FileImporterEditor.h --- ovito-2.8.1+dfsg2/src/gui/dataset/importexport/FileImporterEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dataset/importexport/FileImporterEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FILE_IMPORTER_EDITOR_H -#define __OVITO_FILE_IMPORTER_EDITOR_H +#pragma once + #include #include @@ -49,4 +49,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_FILE_IMPORTER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dataset/importexport/FileSourceEditor.cpp ovito-2.9.0+dfsg1/src/gui/dataset/importexport/FileSourceEditor.cpp --- ovito-2.8.1+dfsg2/src/gui/dataset/importexport/FileSourceEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dataset/importexport/FileSourceEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -20,7 +20,6 @@ /////////////////////////////////////////////////////////////////////////////// #include -#include #include #include #include @@ -32,12 +31,13 @@ #include #include #include +#include #include #include "FileSourceEditor.h" namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(DataIO) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(Gui, FileSourceEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(FileSourceEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(FileSource, FileSourceEditor); /****************************************************************************** @@ -135,30 +135,26 @@ QHBoxLayout* subsublayout = new QHBoxLayout(); subsublayout->setContentsMargins(0,0,0,0); subsublayout->setSpacing(2); - IntegerParameterUI* playbackSpeedNumeratorUI = new IntegerParameterUI(this, PROPERTY_FIELD(FileSource::_playbackSpeedNumerator)); + IntegerParameterUI* playbackSpeedNumeratorUI = new IntegerParameterUI(this, PROPERTY_FIELD(FileSource::playbackSpeedNumerator)); subsublayout->addWidget(new QLabel(tr("Playback rate:"))); subsublayout->addLayout(playbackSpeedNumeratorUI->createFieldLayout()); subsublayout->addWidget(new QLabel(tr("/"))); - IntegerParameterUI* playbackSpeedDenominatorUI = new IntegerParameterUI(this, PROPERTY_FIELD(FileSource::_playbackSpeedDenominator)); + IntegerParameterUI* playbackSpeedDenominatorUI = new IntegerParameterUI(this, PROPERTY_FIELD(FileSource::playbackSpeedDenominator)); subsublayout->addLayout(playbackSpeedDenominatorUI->createFieldLayout()); layout->addLayout(subsublayout); subsublayout = new QHBoxLayout(); subsublayout->setContentsMargins(0,0,0,0); - IntegerParameterUI* playbackStartUI = new IntegerParameterUI(this, PROPERTY_FIELD(FileSource::_playbackStartTime)); + IntegerParameterUI* playbackStartUI = new IntegerParameterUI(this, PROPERTY_FIELD(FileSource::playbackStartTime)); subsublayout->addWidget(new QLabel(tr("Start at animation frame:"))); subsublayout->addLayout(playbackStartUI->createFieldLayout()); layout->addLayout(subsublayout); - BooleanParameterUI* adjustAnimIntervalUI = new BooleanParameterUI(this, PROPERTY_FIELD(FileSource::_adjustAnimationIntervalEnabled)); + BooleanParameterUI* adjustAnimIntervalUI = new BooleanParameterUI(this, PROPERTY_FIELD(FileSource::adjustAnimationIntervalEnabled)); layout->addWidget(adjustAnimIntervalUI->checkBox()); // Show settings editor of importer class. - new SubObjectParameterUI(this, PROPERTY_FIELD(FileSource::_importer), rolloutParams.after(rollout)); - -#if 0 - _subEditorRolloutParams = rolloutParams.collapse(); -#endif + new SubObjectParameterUI(this, PROPERTY_FIELD(FileSource::importer), rolloutParams.after(rollout)); } /****************************************************************************** @@ -167,23 +163,6 @@ void FileSourceEditor::onEditorContentsReplaced(RefTarget* newObject) { updateInformationLabel(); - -#if 0 - // Close old sub-editors. - _subEditors.clear(); - if(newObject) { - FileSource* obj = static_object_cast(newObject); - // Open new sub-editors. - for(DataObject* dataObj : obj->dataObjects()) { - OORef subEditor = dataObj->createPropertiesEditor(); - if(subEditor) { - subEditor->initialize(container(), mainWindow(), _subEditorRolloutParams); - subEditor->setEditObject(dataObj); - _subEditors.push_back(subEditor); - } - } - } -#endif } /****************************************************************************** @@ -222,7 +201,7 @@ importNewFile(obj, newSourceUrl, importerType); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } @@ -264,7 +243,7 @@ importNewFile(obj, newSourceUrl, importerType); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } @@ -279,7 +258,7 @@ if(!importerType) { // Download file so we can determine its format. - Future fetchFileFuture = FileManager::instance().fetchUrl(*fileSource->dataset()->container(), url); + Future fetchFileFuture = Application::instance()->fileManager()->fetchUrl(*fileSource->dataset()->container(), url); if(!fileSource->dataset()->container()->taskManager().waitForTask(fetchFileFuture)) return false; @@ -482,32 +461,6 @@ if(event->type() == ReferenceEvent::ObjectStatusChanged || event->type() == ReferenceEvent::TitleChanged) { updateInformationLabel(); } -#if 0 - else if(event->type() == ReferenceEvent::ReferenceAdded || event->type() == ReferenceEvent::ReferenceRemoved) { - ReferenceFieldEvent* refEvent = static_cast(event); - if(refEvent->field() == PROPERTY_FIELD(FileSource::_dataObjects)) { - DataObject* dataObj = dynamic_object_cast(event->type() == ReferenceEvent::ReferenceAdded ? refEvent->newTarget() : refEvent->oldTarget()); - if(dataObj) { - if(event->type() == ReferenceEvent::ReferenceAdded) { - // Open a new sub-editor. - OORef subEditor = dataObj->createPropertiesEditor(); - if(subEditor) { - subEditor->initialize(container(), mainWindow(), _subEditorRolloutParams); - subEditor->setEditObject(dataObj); - _subEditors.push_back(subEditor); - } - } - else { - // Close sub-editor. - for(int i = (int)_subEditors.size() - 1; i >= 0; i--) { - if(_subEditors[i]->editObject() == dataObj) - _subEditors.erase(_subEditors.begin() + i); - } - } - } - } - } -#endif } return PropertiesEditor::referenceEvent(source, event); } diff -Nru ovito-2.8.1+dfsg2/src/gui/dataset/importexport/FileSourceEditor.h ovito-2.9.0+dfsg1/src/gui/dataset/importexport/FileSourceEditor.h --- ovito-2.8.1+dfsg2/src/gui/dataset/importexport/FileSourceEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dataset/importexport/FileSourceEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FILE_SOURCE_OBJECT_EDITOR_H -#define __OVITO_FILE_SOURCE_OBJECT_EDITOR_H +#pragma once + #include #include @@ -89,11 +89,6 @@ StatusWidget* _statusLabel; QComboBox* _framesListBox; -#if 0 - std::vector> _subEditors; - RolloutInsertionParameters _subEditorRolloutParams; -#endif - Q_OBJECT OVITO_OBJECT }; @@ -102,4 +97,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_FILE_SOURCE_OBJECT_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/AdjustCameraDialog.h ovito-2.9.0+dfsg1/src/gui/dialogs/AdjustCameraDialog.h --- ovito-2.8.1+dfsg2/src/gui/dialogs/AdjustCameraDialog.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/AdjustCameraDialog.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ADJUST_CAMERA_DIALOG_H -#define __OVITO_ADJUST_CAMERA_DIALOG_H +#pragma once + #include #include @@ -77,4 +77,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ADJUST_CAMERA_DIALOG_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/AnimationKeyEditorDialog.cpp ovito-2.9.0+dfsg1/src/gui/dialogs/AnimationKeyEditorDialog.cpp --- ovito-2.8.1+dfsg2/src/gui/dialogs/AnimationKeyEditorDialog.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/AnimationKeyEditorDialog.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -174,12 +174,14 @@ else if(_ctrlType == Controller::ControllerTypeVector3) { Vector3 vec = static_object_cast(key)->value(); vec[index.column()] = value.value(); - return static_object_cast(key)->setValue(vec); + static_object_cast(key)->setValue(vec); + return true; } else if(_ctrlType == Controller::ControllerTypePosition) { Vector3 vec = static_object_cast(key)->value(); vec[index.column()] = value.value(); - return static_object_cast(key)->setValue(vec); + static_object_cast(key)->setValue(vec); + return true; } else if(_ctrlType == Controller::ControllerTypeRotation) { Rotation r = static_object_cast(key)->value(); @@ -192,11 +194,12 @@ else if(index.column() == 3) { r.setAngle(value.value()); } - return static_object_cast(key)->setValue(r); + static_object_cast(key)->setValue(r); + return true; } } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } } @@ -234,7 +237,7 @@ void onCtrlEvent(ReferenceEvent* event) { if(event->type() == ReferenceEvent::ReferenceRemoved) { ReferenceFieldEvent* refEvent = static_cast(event); - if(refEvent->field() == PROPERTY_FIELD(KeyframeController::_keys)) { + if(refEvent->field() == PROPERTY_FIELD(KeyframeController::keys)) { int index = keys().indexOf(static_object_cast(refEvent->oldTarget())); if(index >= 0) { beginRemoveRows(QModelIndex(), index, index); @@ -246,7 +249,7 @@ } else if(event->type() == ReferenceEvent::ReferenceAdded) { ReferenceFieldEvent* refEvent = static_cast(event); - if(refEvent->field() == PROPERTY_FIELD(KeyframeController::_keys)) { + if(refEvent->field() == PROPERTY_FIELD(KeyframeController::keys)) { OVITO_ASSERT(keys().size() == ctrl()->keys().size() - 1); beginInsertRows(QModelIndex(), refEvent->index(), refEvent->index()); _keys.insert(refEvent->index(), static_object_cast(refEvent->newTarget())); @@ -439,7 +442,7 @@ _tableWidget->selectRow(index); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } } @@ -459,7 +462,7 @@ ctrl()->deleteKeys(keysToDelete); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/AnimationKeyEditorDialog.h ovito-2.9.0+dfsg1/src/gui/dialogs/AnimationKeyEditorDialog.h --- ovito-2.8.1+dfsg2/src/gui/dialogs/AnimationKeyEditorDialog.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/AnimationKeyEditorDialog.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ANIMATION_KEY_EDITOR_DIALOG_H -#define __OVITO_ANIMATION_KEY_EDITOR_DIALOG_H +#pragma once + #include #include @@ -69,4 +69,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ANIMATION_KEY_EDITOR_DIALOG_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/AnimationSettingsDialog.h ovito-2.9.0+dfsg1/src/gui/dialogs/AnimationSettingsDialog.h --- ovito-2.8.1+dfsg2/src/gui/dialogs/AnimationSettingsDialog.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/AnimationSettingsDialog.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ANIM_SETTINGS_DIALOG_H -#define __OVITO_ANIM_SETTINGS_DIALOG_H +#pragma once + #include #include @@ -73,4 +73,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ANIM_SETTINGS_DIALOG_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/ApplicationSettingsDialog.cpp ovito-2.9.0+dfsg1/src/gui/dialogs/ApplicationSettingsDialog.cpp --- ovito-2.8.1+dfsg2/src/gui/dialogs/ApplicationSettingsDialog.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/ApplicationSettingsDialog.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,7 +25,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Dialogs) -IMPLEMENT_OVITO_OBJECT(Gui, ApplicationSettingsDialogPage, OvitoObject); +IMPLEMENT_OVITO_OBJECT(ApplicationSettingsDialogPage, OvitoObject); /****************************************************************************** * The constructor of the settings dialog class. @@ -41,14 +41,14 @@ layout1->addWidget(_tabWidget); // Create an iterator that retrieves all ApplicationSettingsDialogPage derived classes. - Q_FOREACH(OvitoObjectType* clazz, PluginManager::instance().listClasses(ApplicationSettingsDialogPage::OOType)) { + for(OvitoObjectType* clazz : PluginManager::instance().listClasses(ApplicationSettingsDialogPage::OOType)) { try { OORef page = static_object_cast(clazz->createInstance(nullptr)); _pages.push_back(page); page->insertSettingsDialogPage(this, _tabWidget); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } _tabWidget->setCurrentIndex(0); @@ -84,8 +84,7 @@ accept(); } catch(const Exception& ex) { - ex.showError(); - return; + ex.reportError(); } } diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/ApplicationSettingsDialog.h ovito-2.9.0+dfsg1/src/gui/dialogs/ApplicationSettingsDialog.h --- ovito-2.8.1+dfsg2/src/gui/dialogs/ApplicationSettingsDialog.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/ApplicationSettingsDialog.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_APPLICATION_SETTINGS_DIALOG_H -#define __OVITO_APPLICATION_SETTINGS_DIALOG_H +#pragma once + #include #include @@ -89,4 +89,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_APPLICATION_SETTINGS_DIALOG_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/FileExporterSettingsDialog.cpp ovito-2.9.0+dfsg1/src/gui/dialogs/FileExporterSettingsDialog.cpp --- ovito-2.8.1+dfsg2/src/gui/dialogs/FileExporterSettingsDialog.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/FileExporterSettingsDialog.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -153,7 +153,7 @@ accept(); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/FileExporterSettingsDialog.h ovito-2.9.0+dfsg1/src/gui/dialogs/FileExporterSettingsDialog.h --- ovito-2.8.1+dfsg2/src/gui/dialogs/FileExporterSettingsDialog.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/FileExporterSettingsDialog.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FILE_EXPORTER_SETTINGS_DIALOG_H -#define __OVITO_FILE_EXPORTER_SETTINGS_DIALOG_H +#pragma once + #include #include @@ -60,4 +60,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_FILE_EXPORTER_SETTINGS_DIALOG_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/GeneralSettingsPage.cpp ovito-2.9.0+dfsg1/src/gui/dialogs/GeneralSettingsPage.cpp --- ovito-2.8.1+dfsg2/src/gui/dialogs/GeneralSettingsPage.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/GeneralSettingsPage.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,7 +25,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(Gui, GeneralSettingsPage, ApplicationSettingsDialogPage); +IMPLEMENT_OVITO_OBJECT(GeneralSettingsPage, ApplicationSettingsDialogPage); /****************************************************************************** * Creates the widget that contains the plugin specific setting controls. @@ -42,13 +42,19 @@ layout1->addWidget(uiGroupBox); QGridLayout* layout2 = new QGridLayout(uiGroupBox); - _useQtFileDialog = new QCheckBox(tr("Use alternative file selection dialog"), uiGroupBox); + _useQtFileDialog = new QCheckBox(tr("Load file: Use alternative file selection dialog"), uiGroupBox); _useQtFileDialog->setToolTip(tr( "

Use an alternative file selection dialog instead of the native dialog box provided by the operating system.

")); layout2->addWidget(_useQtFileDialog, 0, 0); _useQtFileDialog->setChecked(settings.value("file/use_qt_dialog", false).toBool()); - QGroupBox* openglGroupBox = new QGroupBox(tr("Display / OpenGL"), page); + _enableMRUModifierList = new QCheckBox(tr("Modifier list: Only show most recently used modifiers"), uiGroupBox); + _enableMRUModifierList->setToolTip(tr( + "

Restricts the modifiers in the Add Modification list box to the most recently used ones.

")); + layout2->addWidget(_enableMRUModifierList, 1, 0); + _enableMRUModifierList->setChecked(settings.value("core/modifier/mru/enable_mru", false).toBool()); + + QGroupBox* openglGroupBox = new QGroupBox(tr("Viewport rendering / OpenGL"), page); layout1->addWidget(openglGroupBox); layout2 = new QGridLayout(openglGroupBox); @@ -145,6 +151,7 @@ { QSettings settings; settings.setValue("file/use_qt_dialog", _useQtFileDialog->isChecked()); + settings.setValue("core/modifier/mru/enable_mru", _enableMRUModifierList->isChecked()); #if !defined(OVITO_BUILD_APPSTORE_VERSION) settings.setValue("updates/check_for_updates", _enableUpdateChecks->isChecked()); settings.setValue("updates/transmit_id", _enableUsageStatistics->isChecked()); diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/GeneralSettingsPage.h ovito-2.9.0+dfsg1/src/gui/dialogs/GeneralSettingsPage.h --- ovito-2.8.1+dfsg2/src/gui/dialogs/GeneralSettingsPage.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/GeneralSettingsPage.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_GENERAL_SETTINGS_PAGE_H -#define __OVITO_GENERAL_SETTINGS_PAGE_H +#pragma once + #include #include @@ -47,6 +47,7 @@ private: QCheckBox* _useQtFileDialog; + QCheckBox* _enableMRUModifierList; QCheckBox* _overrideGLContextSharing; QComboBox* _contextSharingMode; QCheckBox* _overrideUseOfPointSprites; @@ -66,4 +67,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_GENERAL_SETTINGS_PAGE_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/HistoryFileDialog.h ovito-2.9.0+dfsg1/src/gui/dialogs/HistoryFileDialog.h --- ovito-2.8.1+dfsg2/src/gui/dialogs/HistoryFileDialog.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/HistoryFileDialog.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_HISTORY_FILE_DIALOG_H -#define __OVITO_HISTORY_FILE_DIALOG_H +#pragma once + #include @@ -61,4 +61,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_HISTORY_FILE_DIALOG_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/ImportFileDialog.h ovito-2.9.0+dfsg1/src/gui/dialogs/ImportFileDialog.h --- ovito-2.8.1+dfsg2/src/gui/dialogs/ImportFileDialog.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/ImportFileDialog.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_IMPORT_FILE_DIALOG_H -#define __OVITO_IMPORT_FILE_DIALOG_H +#pragma once + #include #include @@ -58,4 +58,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_IMPORT_FILE_DIALOG_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/ImportRemoteFileDialog.cpp ovito-2.9.0+dfsg1/src/gui/dialogs/ImportRemoteFileDialog.cpp --- ovito-2.8.1+dfsg2/src/gui/dialogs/ImportRemoteFileDialog.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/ImportRemoteFileDialog.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -129,8 +129,7 @@ accept(); } catch(const Exception& ex) { - ex.showError(); - return; + ex.reportError(); } } diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/ImportRemoteFileDialog.h ovito-2.9.0+dfsg1/src/gui/dialogs/ImportRemoteFileDialog.h --- ovito-2.8.1+dfsg2/src/gui/dialogs/ImportRemoteFileDialog.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/ImportRemoteFileDialog.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_IMPORT_REMOTE_FILE_DIALOG_H -#define __OVITO_IMPORT_REMOTE_FILE_DIALOG_H +#pragma once + #include #include @@ -70,4 +70,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_IMPORT_REMOTE_FILE_DIALOG_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/LoadImageFileDialog.h ovito-2.9.0+dfsg1/src/gui/dialogs/LoadImageFileDialog.h --- ovito-2.8.1+dfsg2/src/gui/dialogs/LoadImageFileDialog.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/LoadImageFileDialog.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_LOAD_IMAGE_FILE_DIALOG_H -#define __OVITO_LOAD_IMAGE_FILE_DIALOG_H +#pragma once + #include #include @@ -57,4 +57,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_LOAD_IMAGE_FILE_DIALOG_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/RemoteAuthenticationDialog.h ovito-2.9.0+dfsg1/src/gui/dialogs/RemoteAuthenticationDialog.h --- ovito-2.8.1+dfsg2/src/gui/dialogs/RemoteAuthenticationDialog.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/RemoteAuthenticationDialog.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_REMOTE_AUTHENTICATION_DIALOG_H -#define __OVITO_REMOTE_AUTHENTICATION_DIALOG_H +#pragma once + #include #include @@ -64,4 +64,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_REMOTE_AUTHENTICATION_DIALOG_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/SaveImageFileDialog.h ovito-2.9.0+dfsg1/src/gui/dialogs/SaveImageFileDialog.h --- ovito-2.8.1+dfsg2/src/gui/dialogs/SaveImageFileDialog.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/SaveImageFileDialog.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SAVE_IMAGE_FILE_DIALOG_H -#define __OVITO_SAVE_IMAGE_FILE_DIALOG_H +#pragma once + #include #include @@ -61,4 +61,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_SAVE_IMAGE_FILE_DIALOG_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/ViewportSettingsPage.cpp ovito-2.9.0+dfsg1/src/gui/dialogs/ViewportSettingsPage.cpp --- ovito-2.8.1+dfsg2/src/gui/dialogs/ViewportSettingsPage.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/ViewportSettingsPage.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(Gui, ViewportSettingsPage, ApplicationSettingsDialogPage); +IMPLEMENT_OVITO_OBJECT(ViewportSettingsPage, ApplicationSettingsDialogPage); /****************************************************************************** * Creates the widget that contains the plugin specific setting controls. diff -Nru ovito-2.8.1+dfsg2/src/gui/dialogs/ViewportSettingsPage.h ovito-2.9.0+dfsg1/src/gui/dialogs/ViewportSettingsPage.h --- ovito-2.8.1+dfsg2/src/gui/dialogs/ViewportSettingsPage.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/dialogs/ViewportSettingsPage.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VIEWPORT_SETTINGS_PAGE_H -#define __OVITO_VIEWPORT_SETTINGS_PAGE_H +#pragma once + #include #include @@ -62,4 +62,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_VIEWPORT_SETTINGS_PAGE_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/ForwardDecl.h ovito-2.9.0+dfsg1/src/gui/ForwardDecl.h --- ovito-2.8.1+dfsg2/src/gui/ForwardDecl.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/ForwardDecl.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains forward declarations of OVITO's GUI classes and namespaces. */ -#ifndef __OVITO_GUI_FORWARD_DECL_H -#define __OVITO_GUI_FORWARD_DECL_H +#pragma once + // Sub-namespaces are only used for the documentation generated by Doxygen, // because current C++ compilers do not fully support C++11 inline namespaces yet. @@ -116,4 +116,4 @@ #endif } -#endif // __OVITO_GUI_FORWARD_DECL_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/GUI.h ovito-2.9.0+dfsg1/src/gui/GUI.h --- ovito-2.8.1+dfsg2/src/gui/GUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/GUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief This file includes third-party library headers required by OVITO's GUI. */ -#ifndef __OVITO_GUI_H -#define __OVITO_GUI_H +#pragma once + #include @@ -70,4 +70,4 @@ #include "ForwardDecl.h" -#endif // __OVITO_CORE_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/CommandPanel.h ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/CommandPanel.h --- ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/CommandPanel.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/CommandPanel.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COMMAND_PANEL_H -#define __OVITO_COMMAND_PANEL_H +#pragma once + #include #include @@ -78,4 +78,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_COMMAND_PANEL_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/ModificationListItem.cpp ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/ModificationListItem.cpp --- ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/ModificationListItem.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/ModificationListItem.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,9 +27,9 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(Gui, ModificationListItem, RefMaker); -DEFINE_FLAGS_REFERENCE_FIELD(ModificationListItem, _object, "Object", RefTarget, PROPERTY_FIELD_NO_UNDO|PROPERTY_FIELD_WEAK_REF|PROPERTY_FIELD_NO_CHANGE_MESSAGE); -DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(ModificationListItem, _modApps, "ModifierApplications", ModifierApplication, PROPERTY_FIELD_NO_UNDO|PROPERTY_FIELD_WEAK_REF|PROPERTY_FIELD_NO_CHANGE_MESSAGE); +IMPLEMENT_OVITO_OBJECT(ModificationListItem, RefMaker); +DEFINE_FLAGS_REFERENCE_FIELD(ModificationListItem, object, "Object", RefTarget, PROPERTY_FIELD_NO_UNDO|PROPERTY_FIELD_WEAK_REF|PROPERTY_FIELD_NO_CHANGE_MESSAGE); +DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(ModificationListItem, modifierApplications, "ModifierApplications", ModifierApplication, PROPERTY_FIELD_NO_UNDO|PROPERTY_FIELD_WEAK_REF|PROPERTY_FIELD_NO_CHANGE_MESSAGE); /****************************************************************************** * Constructor. @@ -37,10 +37,10 @@ ModificationListItem::ModificationListItem(RefTarget* object, ModificationListItem* parent, const QString& title) : _parent(parent), _title(title) { - INIT_PROPERTY_FIELD(ModificationListItem::_object); - INIT_PROPERTY_FIELD(ModificationListItem::_modApps); + INIT_PROPERTY_FIELD(object); + INIT_PROPERTY_FIELD(modifierApplications); - this->_object = object; + _object = object; } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/ModificationListItem.h ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/ModificationListItem.h --- ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/ModificationListItem.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/ModificationListItem.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_MODIFICATION_LIST_ITEM_H -#define __OVITO_MODIFICATION_LIST_ITEM_H +#pragma once + #include #include @@ -41,15 +41,6 @@ /// Constructor. ModificationListItem(RefTarget* object, ModificationListItem* parent = nullptr, const QString& title = QString()); - /// Returns the object represented by this list item. - RefTarget* object() const { return _object; } - - /// Returns the list of modifier applications if this is a modifier item. - const QVector& modifierApplications() const { return _modApps; } - - /// Sets the list of modifier applications if this is a modifier item. - void setModifierApplications(const QVector& modApps) { _modApps = modApps; } - /// Returns true if this is a sub-object entry. bool isSubObject() const { return _parent != nullptr; } @@ -78,10 +69,10 @@ private: /// The object represented by this item in the list box. - ReferenceField _object; + DECLARE_REFERENCE_FIELD(RefTarget, object); /// The list of modifier application if this is a modifier item. - VectorReferenceField _modApps; + DECLARE_MODIFIABLE_VECTOR_REFERENCE_FIELD(ModifierApplication, modifierApplications, setModifierApplications); /// If this is a sub-object entry then this points to the parent. ModificationListItem* _parent; @@ -91,13 +82,10 @@ Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_object); - DECLARE_VECTOR_REFERENCE_FIELD(_modApps); }; OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_MODIFICATION_LIST_ITEM_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/ModificationListModel.h ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/ModificationListModel.h --- ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/ModificationListModel.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/ModificationListModel.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_MODIFICATION_LIST_MODEL_H -#define __OVITO_MODIFICATION_LIST_MODEL_H +#pragma once + #include #include @@ -183,4 +183,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_MODIFICATION_LIST_MODEL_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/ModifierListBox.cpp ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/ModifierListBox.cpp --- ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/ModifierListBox.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/ModifierListBox.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -// Copyright (2013) Alexander Stukowski +// Copyright (2017) Alexander Stukowski // // This file is part of OVITO (Open Visualization Tool). // @@ -37,11 +37,20 @@ ModifierListBox::ModifierListBox(QWidget* parent, ModificationListModel* modificationList) : QComboBox(parent), _modificationList(modificationList) { + setSizeAdjustPolicy(QComboBox::AdjustToContents); + + // A category of modifiers. + struct ModifierCategory { + QString name; + QVector modifierClasses; + }; + + QVector modifierCategories; ModifierCategory otherCategory; otherCategory.name = tr("Others"); // Retrieve all installed modifier classes. - Q_FOREACH(const OvitoObjectType* clazz, PluginManager::instance().listClasses(Modifier::OOType)) { + for(const OvitoObjectType* clazz : PluginManager::instance().listClasses(Modifier::OOType)) { // Sort modifiers into categories. if(clazz->qtMetaObject()) { int infoIndex = clazz->qtMetaObject()->indexOfClassInfo("ModifierCategory"); @@ -49,7 +58,7 @@ QString categoryName = QString::fromLocal8Bit(clazz->qtMetaObject()->classInfo(infoIndex).value()); // Check if category has already been created. bool found = false; - for(auto& category : _modifierCategories) { + for(auto& category : modifierCategories) { if(category.name == categoryName) { category.modifierClasses.push_back(clazz); found = true; @@ -61,7 +70,7 @@ ModifierCategory category; category.name = categoryName; category.modifierClasses.push_back(clazz); - _modifierCategories.push_back(category); + modifierCategories.push_back(category); } continue; } @@ -71,32 +80,200 @@ otherCategory.modifierClasses.push_back(clazz); } - // Sort category list alphabetically. - std::sort(_modifierCategories.begin(), _modifierCategories.end(), [](const ModifierCategory& a, const ModifierCategory& b) { + // Sort category list. + std::sort(modifierCategories.begin(), modifierCategories.end(), [](const ModifierCategory& a, const ModifierCategory& b) { return QString::compare(a.name, b.name, Qt::CaseInsensitive) < 0; } ); // Assign modifiers that haven't been assigned to a category yet to the "Other" category. if(!otherCategory.modifierClasses.isEmpty()) - _modifierCategories.push_back(otherCategory); + modifierCategories.push_back(otherCategory); - // Sort modifier sub-lists alphabetically. - for(auto& category : _modifierCategories) { + // Sort modifiers in each category. + for(auto& category : modifierCategories) { std::sort(category.modifierClasses.begin(), category.modifierClasses.end(), [](const OvitoObjectType* a, const OvitoObjectType* b) { return QString::compare(a->displayName(), b->displayName(), Qt::CaseInsensitive) < 0; } ); } - _categoryFont = font(); - _categoryFont.setBold(true); - if(_categoryFont.pixelSize() < 0) - _categoryFont.setPointSize(_categoryFont.pointSize() * 4 / 5); + // Define font colors etc. + QFont categoryFont = font(); + categoryFont.setBold(true); + if(categoryFont.pixelSize() < 0) + categoryFont.setPointSize(categoryFont.pointSize() * 4 / 5); else - _categoryFont.setPixelSize(_categoryFont.pixelSize() * 4 / 5); - _categoryBackgroundBrush = QBrush(Qt::lightGray, Qt::Dense4Pattern); - _categoryForegroundBrush = QBrush(Qt::blue); + categoryFont.setPixelSize(categoryFont.pixelSize() * 4 / 5); + QBrush categoryBackgroundBrush(Qt::lightGray, Qt::Dense4Pattern); + QBrush categoryForegroundBrush(Qt::blue); + + // Populate item model. + _model = new QStandardItemModel(this); + + // Lists starts with the special "Add modification...", which is used just + // as a label for the combo box. + QStandardItem* titleItem = new QStandardItem(tr("Add modification...")); + titleItem->setFlags(Qt::ItemIsEnabled); + _model->appendRow(titleItem); - updateAvailableModifiers(); + QStandardItem* mruListItem = new QStandardItem(tr("Most recently used modifiers")); + mruListItem->setFont(categoryFont); + mruListItem->setBackground(categoryBackgroundBrush); + mruListItem->setForeground(categoryForegroundBrush); + mruListItem->setFlags(Qt::ItemIsEnabled); + mruListItem->setTextAlignment(Qt::AlignCenter); + _model->appendRow(mruListItem); + + // Create items for all modifiers and the category titles. + for(const ModifierCategory& category : modifierCategories) { + if(category.modifierClasses.empty()) continue; + + QStandardItem* categoryItem = new QStandardItem(category.name); + categoryItem->setFont(categoryFont); + categoryItem->setBackground(categoryBackgroundBrush); + categoryItem->setForeground(categoryForegroundBrush); + categoryItem->setFlags(Qt::ItemIsEnabled); + categoryItem->setTextAlignment(Qt::AlignCenter); + _model->appendRow(categoryItem); + + for(const OvitoObjectType* descriptor : category.modifierClasses) { + QStandardItem* modifierItem = new QStandardItem(" " + descriptor->displayName()); + modifierItem->setData(QVariant::fromValue((void*)descriptor), Qt::UserRole); + _model->appendRow(modifierItem); + _modifierItems.push_back(modifierItem); + } + } + + // Create category for custom modifiers. + QStandardItem* categoryItem = new QStandardItem(tr("Custom modifier presets")); + categoryItem->setFont(categoryFont); + categoryItem->setBackground(categoryBackgroundBrush); + categoryItem->setForeground(categoryForegroundBrush); + categoryItem->setFlags(Qt::ItemIsEnabled); + categoryItem->setTextAlignment(Qt::AlignCenter); + _model->appendRow(categoryItem); + + // Append the "Show all modifiers" item at the end of the list. + QStandardItem* showAllItem = new QStandardItem(tr("Show all modifiers...")); + QFont boldFont = font(); + boldFont.setBold(true); + showAllItem->setFont(boldFont); + showAllItem->setTextAlignment(Qt::AlignCenter); + _model->appendRow(showAllItem); + + // Filler item to workaround bug in Qt which doesnt fully show all items in the drop-down menu. + QStandardItem* fillerItem = new QStandardItem(); + fillerItem->setFlags(Qt::ItemIsEnabled); + _model->appendRow(fillerItem); + + // Expand list when the "Show all modifiers" entry is selected and update MRU list. + connect(this, (void (QComboBox::*)(int))&QComboBox::activated, this, [this](int index) { + if(!showAllModifiers() && index >= count() - 2 && !itemData(index).isValid()) { + _showAllModifiers = true; + showPopup(); + } + else { + if(itemData(index).isValid()) { + updateMRUList(itemText(index)); + } + } + }, Qt::QueuedConnection); + + // Set up filter model. + class MyFilterModel : public QSortFilterProxyModel { + public: + MyFilterModel(QObject* parent) : QSortFilterProxyModel(parent) {} + protected: + virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override { + // Delegate to parent class. + return static_cast(parent())->filterAcceptsRow(source_row, source_parent); + } + virtual bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const override { + // Delegate to parent class. + return static_cast(parent())->filterSortLessThan(source_left, source_right); + } + }; + _filterModel = new MyFilterModel(this); + _filterModel->setDynamicSortFilter(false); + _filterModel->sort(0); + _filterModel->setSourceModel(_model); + setModel(_filterModel); +} + +/****************************************************************************** +* Filters the full list of modifiers to show only most recently used ones. +******************************************************************************/ +bool ModifierListBox::filterAcceptsRow(int source_row, const QModelIndex& source_parent) +{ + if(showAllModifiers()) { + // Don't show the "Most recently used" entry if all modifier are shown. + if(source_row == 1) + return false; + // Don't show the "Show all modifiers" entry if all are already shown. + if(source_row >= _model->rowCount(source_parent) - 2) + return false; + // Don't show the "Custom modifier presets" category if there are no custom modifiers. + if(_numCustomModifiers == 0 && source_row == _model->rowCount(source_parent) - 3) + return false; + return true; + } + // Always show the "Add modification..." entry. + if(source_row == 0) + return true; + + // Always show the "Most recently used" entry. + if(source_row == 1) + return true; + + // Show the "Show all modifiers" entry + if(source_row >= _model->rowCount(source_parent) - 2) + return true; + + // Don't show modifier categories. + if(!_model->index(source_row, 0, source_parent).data(Qt::UserRole).isValid()) + return false; + + // Only show modifiers from MRU list. + QString modifierName = _model->index(source_row, 0, source_parent).data().toString(); + return _mostRecentlyUsedModifiers.contains(modifierName); +} + +/****************************************************************************** +* Determines the sort order of the modifier list. +******************************************************************************/ +bool ModifierListBox::filterSortLessThan(const QModelIndex& source_left, const QModelIndex& source_right) +{ + if(showAllModifiers() || source_left.row() <= 1 || source_right.row() <= 1 || source_left.row() >= _model->rowCount()-2 || source_right.row() >= _model->rowCount()-2) { + return source_left.row() < source_right.row(); + } + else { + return source_left.data().toString().localeAwareCompare(source_right.data().toString()) < 0; + } +} + +/****************************************************************************** +* Updates the MRU list after the user has selected a modifier. +******************************************************************************/ +void ModifierListBox::updateMRUList(const QString& selectedModifierName) +{ + QSettings settings; + settings.beginGroup("core/modifier/mru/"); + if(!settings.value("enable_mru", false).toBool()) + return; + + int index = _mostRecentlyUsedModifiers.indexOf(selectedModifierName); + if(index >= 0) { + _mostRecentlyUsedModifiers.removeAt(index); + } + else if(_mostRecentlyUsedModifiers.size() >= _maxMRUSize) { + _mostRecentlyUsedModifiers.pop_back(); + } + _mostRecentlyUsedModifiers.push_front(selectedModifierName); + + // Store MRU list in application settings. + settings.setValue("list", QVariant::fromValue(_mostRecentlyUsedModifiers)); + + // Update list of modifiers shown in the combo box. + _filterModel->invalidate(); } /****************************************************************************** @@ -105,103 +282,79 @@ ******************************************************************************/ void ModifierListBox::updateAvailableModifiers() { - clear(); - - QStandardItemModel* model = qobject_cast(this->model()); - OVITO_CHECK_POINTER(model); - QStandardItem* titleItem = new QStandardItem(tr("Add modification...")); - titleItem->setFlags(Qt::ItemIsEnabled); - model->appendRow(titleItem); + // Always select the "Add modification..." entry by default. setCurrentIndex(0); - ModificationListItem* currentItem = _modificationList->selectedItem(); - if(currentItem == nullptr) - return; - while(currentItem->parent()) { - currentItem = currentItem->parent(); - } + // Should we show MRU list? + QSettings settings; + settings.beginGroup("core/modifier/mru/"); + if(settings.value("enable_mru", false).toBool()) + _mostRecentlyUsedModifiers = settings.value("list").toStringList(); + else + _mostRecentlyUsedModifiers.clear(); + settings.endGroup(); // Retrieve the input state which a newly inserted modifier would be applied to. // This is used to filter the list of available modifiers. + ModificationListItem* currentItem = _modificationList->selectedItem(); + while(currentItem && currentItem->parent()) { + currentItem = currentItem->parent(); + } PipelineFlowState inputState; DataSet* dataset = _modificationList->datasetContainer().currentSet(); + if(!dataset) return; + if(dynamic_object_cast(currentItem->object())) { for(ModifierApplication* modApp : currentItem->modifierApplications()) { PipelineObject* pipelineObj = modApp->pipelineObject(); OVITO_CHECK_OBJECT_POINTER(pipelineObj); - inputState = pipelineObj->evaluatePipeline(dataset->animationSettings()->time(), modApp, true); + inputState = pipelineObj->evaluateImmediately(PipelineEvalRequest(dataset->animationSettings()->time(), false, modApp, true)); break; } } else if(dynamic_object_cast(currentItem->object())) { DataObject* dataObj = static_object_cast(currentItem->object()); OVITO_CHECK_OBJECT_POINTER(dataObj); - inputState = dataObj->evaluate(dataset->animationSettings()->time()); + inputState = dataObj->evaluateImmediately(PipelineEvalRequest(dataset->animationSettings()->time(), false)); } else { for(RefTarget* objNode : _modificationList->selectedNodes()) { - inputState = static_object_cast(objNode)->evalPipeline(dataset->animationSettings()->time()); + inputState = static_object_cast(objNode)->evaluatePipelineImmediately(PipelineEvalRequest(dataset->animationSettings()->time(), false)); break; } } - for(const ModifierCategory& category : _modifierCategories) { - QList categoryItems; - for(const OvitoObjectType* descriptor : category.modifierClasses) { - // Create an instance of the modifier to call its isApplicableTo() method. - OORef modifier = static_object_cast(descriptor->createInstance(dataset)); - OVITO_CHECK_OBJECT_POINTER(modifier); - if(modifier && modifier->isApplicableTo(inputState)) { - QStandardItem* modifierItem = new QStandardItem(" " + descriptor->displayName()); - modifierItem->setData(qVariantFromValue((void*)descriptor), Qt::UserRole); - categoryItems.push_back(modifierItem); - } - } - - if(!categoryItems.empty()) { - QStandardItem* categoryItem = new QStandardItem(category.name); - categoryItem->setFont(_categoryFont); - categoryItem->setBackground(_categoryBackgroundBrush); - categoryItem->setForeground(_categoryForegroundBrush); - categoryItem->setFlags(Qt::ItemIsEnabled); - categoryItem->setTextAlignment(Qt::AlignCenter); - model->appendRow(categoryItem); - for(QStandardItem* item : categoryItems) - model->appendRow(item); - } + // Update state of combo box items. + for(QStandardItem* item : _modifierItems) { + const OvitoObjectType* descriptor = static_cast(item->data(Qt::UserRole).value()); + OVITO_ASSERT(descriptor); + + // Create an instance of the modifier to call its isApplicableTo() method. + OORef modifier = static_object_cast(descriptor->createInstance(dataset)); + OVITO_CHECK_OBJECT_POINTER(modifier); + item->setEnabled(modifier && modifier->isApplicableTo(inputState)); } - if(count() <= 1) { - QStandardItem* categoryItem = new QStandardItem(tr("No modifiers applicable to this object")); - categoryItem->setFont(_categoryFont); - categoryItem->setBackground(_categoryBackgroundBrush); - categoryItem->setForeground(_categoryForegroundBrush); - categoryItem->setFlags(Qt::ItemIsEnabled); - categoryItem->setTextAlignment(Qt::AlignCenter); - model->appendRow(categoryItem); - } - else { - // Load custom modifier presets. - QSettings settings; - settings.beginGroup("core/modifier/presets/"); - QStringList keys = settings.childKeys(); - if(!keys.empty()) { - QStandardItem* categoryItem = new QStandardItem(tr("Custom modifier presets")); - categoryItem->setFont(_categoryFont); - categoryItem->setBackground(_categoryBackgroundBrush); - categoryItem->setForeground(_categoryForegroundBrush); - categoryItem->setFlags(Qt::ItemIsEnabled); - categoryItem->setTextAlignment(Qt::AlignCenter); - model->appendRow(categoryItem); - for(const QString& name : keys) { - QStandardItem* modifierItem = new QStandardItem(" " + name); - modifierItem->setData(qVariantFromValue(name), Qt::UserRole); - model->appendRow(modifierItem); - } + // Load custom modifier presets. + settings.beginGroup("core/modifier/presets/"); + QStringList keys = settings.childKeys(); + settings.endGroup(); + int numCustom = 0; + for(const QString& name : keys) { + QStandardItem* modifierItem; + if(numCustom < _numCustomModifiers) + modifierItem = _model->item(_model->rowCount() - 2 - _numCustomModifiers + numCustom); + else { + modifierItem = new QStandardItem(" " + name); + _model->insertRow(_model->rowCount() - 2, modifierItem); } + modifierItem->setData(QVariant::fromValue(name), Qt::UserRole); + numCustom++; } - - setMaxVisibleItems(count()); + // Remove unused entries. + if(numCustom < _numCustomModifiers) + _model->removeRows(_model->rowCount() - 2 - _numCustomModifiers + numCustom, _numCustomModifiers - numCustom); + _numCustomModifiers = numCustom; } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/ModifierListBox.h ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/ModifierListBox.h --- ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/ModifierListBox.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/ModifierListBox.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_MODIFIER_LIST_BOX_H -#define __OVITO_MODIFIER_LIST_BOX_H +#pragma once + #include #include @@ -28,7 +28,6 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Internal) class ModificationListModel; -class ModificationListItem; /** * A combo-box widget that lets the user insert new modifiers into the modification pipeline. @@ -43,37 +42,57 @@ /// Is called just before the drop-down box is activated. virtual void showPopup() override { updateAvailableModifiers(); + _filterModel->invalidate(); + setMaxVisibleItems(_model->rowCount()); + _showAllModifiers = false; QComboBox::showPopup(); } + /// Indicates whether the complete list of modifiers should be shown. + bool showAllModifiers() const { + return (_showAllModifiers || _mostRecentlyUsedModifiers.size() < 4); + } + private Q_SLOTS: - /// Updates the list box of modifier classes that can be applied to the current selected + /// Updates the list box of modifier classes that can be applied to the currently selected /// item in the modification list. void updateAvailableModifiers(); + /// Updates the MRU list after the user has selected a modifier. + void updateMRUList(const QString& selectedModifierName); + private: - /// A category of modifiers. - struct ModifierCategory { - QString name; - QVector modifierClasses; - }; + /// Filters the full list of modifiers to show only most recently used ones. + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent); - /// List of modifier categories. - QVector _modifierCategories; + /// Determines the sort order of the modifier list. + bool filterSortLessThan(const QModelIndex& source_left, const QModelIndex& source_right); /// The modification list model. ModificationListModel* _modificationList; - /// The font to be used for category headers. - QFont _categoryFont; + /// The list items representing modifier types. + QVector _modifierItems; + + /// The item model containing all entries of the combo box. + QStandardItemModel* _model; - /// The background brush to be used for category headers. - QBrush _categoryBackgroundBrush; + /// The item model used for filtering/storting the displayed list of modifiers. + QSortFilterProxyModel* _filterModel; - /// The foreground brush to be used for category headers. - QBrush _categoryForegroundBrush; + /// This flag asks updateAvailableModifiers() to list all modifiers, not just the most recently used ones. + bool _showAllModifiers = false; + + /// The number of custom modifier presets in the list. + int _numCustomModifiers = 0; + + /// MRU list of modifiers. + QStringList _mostRecentlyUsedModifiers; + + /// Maximum number of modifiers shown in the MRU list. + int _maxMRUSize = 8; Q_OBJECT }; @@ -82,4 +101,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_MODIFIER_LIST_BOX_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/ModifyCommandPage.cpp ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/ModifyCommandPage.cpp --- ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/ModifyCommandPage.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/ModifyCommandPage.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -680,7 +680,7 @@ settings.endGroup(); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } } diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/ModifyCommandPage.h ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/ModifyCommandPage.h --- ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/ModifyCommandPage.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/ModifyCommandPage.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_MODIFY_COMMAND_PAGE_H -#define __OVITO_MODIFY_COMMAND_PAGE_H +#pragma once + #include #include @@ -124,4 +124,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_MODIFY_COMMAND_PAGE_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/OverlayCommandPage.cpp ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/OverlayCommandPage.cpp --- ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/OverlayCommandPage.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/OverlayCommandPage.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -174,7 +174,7 @@ { if(event->type() == ReferenceEvent::ReferenceAdded) { ReferenceFieldEvent* refEvent = static_cast(event); - if(refEvent->field() == PROPERTY_FIELD(Viewport::_overlays)) { + if(refEvent->field() == PROPERTY_FIELD(Viewport::overlays)) { ViewportOverlay* overlay = static_object_cast(refEvent->newTarget()); QListWidgetItem* item = new OverlayListItem(overlay); _overlayListWidget->insertItem(refEvent->index(), item); @@ -183,7 +183,7 @@ } else if(event->type() == ReferenceEvent::ReferenceRemoved) { ReferenceFieldEvent* refEvent = static_cast(event); - if(refEvent->field() == PROPERTY_FIELD(Viewport::_overlays)) { + if(refEvent->field() == PROPERTY_FIELD(Viewport::overlays)) { delete _overlayListWidget->item(refEvent->index()); } } diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/OverlayCommandPage.h ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/OverlayCommandPage.h --- ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/OverlayCommandPage.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/OverlayCommandPage.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OVERLAY_COMMAND_PAGE_H -#define __OVITO_OVERLAY_COMMAND_PAGE_H +#pragma once + #include #include @@ -117,4 +117,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OVERLAY_COMMAND_PAGE_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/RenderCommandPage.h ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/RenderCommandPage.h --- ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/RenderCommandPage.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/RenderCommandPage.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_RENDER_COMMAND_PAGE_H -#define __OVITO_RENDER_COMMAND_PAGE_H +#pragma once + #include #include @@ -59,4 +59,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_RENDER_COMMAND_PAGE_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/UtilityCommandPage.cpp ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/UtilityCommandPage.cpp --- ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/UtilityCommandPage.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/UtilityCommandPage.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -107,7 +107,7 @@ currentUtility->openUtility(_datasetContainer.mainWindow(), rolloutContainer, RolloutInsertionParameters().animate()); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/UtilityCommandPage.h ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/UtilityCommandPage.h --- ovito-2.8.1+dfsg2/src/gui/mainwin/cmdpanel/UtilityCommandPage.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/cmdpanel/UtilityCommandPage.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_UTILITY_COMMAND_PAGE_H -#define __OVITO_UTILITY_COMMAND_PAGE_H +#pragma once + #include #include @@ -78,4 +78,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_UTILITY_COMMAND_PAGE_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/MainWindow.cpp ovito-2.9.0+dfsg1/src/gui/mainwin/MainWindow.cpp --- ovito-2.8.1+dfsg2/src/gui/mainwin/MainWindow.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/MainWindow.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -43,9 +44,6 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) -// The global list of all open main windows of the application. -std::vector MainWindow::_windowList; - /****************************************************************************** * The constructor of the main window class. ******************************************************************************/ @@ -54,9 +52,6 @@ setWindowTitle(tr("Ovito (Open Visualization Tool)")); setAttribute(Qt::WA_DeleteOnClose); - // Register window in global list. - _windowList.push_back(this); - // Setup the layout of docking widgets. setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); @@ -71,7 +66,7 @@ _actionManager = new ActionManager(this); // Let GUI auto-start objects register their actions. - for(const auto& obj : Application::instance().autostartObjects()) { + for(const auto& obj : Application::instance()->autostartObjects()) { if(auto gui_obj = dynamic_object_cast(obj)) gui_obj->registerActions(*_actionManager); } @@ -210,6 +205,9 @@ // Update window title when document path changes. connect(&_datasetContainer, &DataSetContainer::filePathChanged, [this](const QString& filePath) { setWindowFilePath(filePath); }); connect(&_datasetContainer, &DataSetContainer::modificationStatusChanged, [this](bool isClean) { setWindowModified(!isClean); }); + + // Accept files via drag & drop. + setAcceptDrops(true); } /****************************************************************************** @@ -217,8 +215,6 @@ ******************************************************************************/ MainWindow::~MainWindow() { - // Unregister from global list. - _windowList.erase(std::find(_windowList.begin(), _windowList.end(), this)); } /****************************************************************************** @@ -226,10 +222,8 @@ ******************************************************************************/ MainWindow* MainWindow::fromDataset(DataSet* dataset) { - for(MainWindow* win : _windowList) { - if(win->datasetContainer().currentSet() == dataset) - return win; - } + if(GuiDataSetContainer* container = qobject_cast(dataset->container())) + return container->mainWindow(); return nullptr; } @@ -326,6 +320,12 @@ #endif helpMenu->addAction(actionManager()->getAction(ACTION_HELP_ABOUT)); + // Let GUI auto-start objects add their actions to the main menu. + for(const auto& obj : StandaloneApplication::instance()->autostartObjects()) { + if(auto gui_obj = dynamic_object_cast(obj)) + gui_obj->addActionsToMenu(*_actionManager, menuBar); + } + setMenuBar(menuBar); } @@ -395,7 +395,7 @@ } catch(const Exception& ex) { event->ignore(); - ex.showError(); + ex.reportError(); } } @@ -426,7 +426,7 @@ // Use the web browser to display online help. QString fullPath = helpDir.absoluteFilePath(page.isEmpty() ? QStringLiteral("index.html") : page); if(!QDesktopServices::openUrl(QUrl::fromLocalFile(fullPath))) { - Exception(tr("Could not launch web browser to display online manual. The requested file path is %1").arg(fullPath)).showError(); + Exception(tr("Could not launch web browser to display online manual. The requested file path is %1").arg(fullPath)).reportError(); } } @@ -484,6 +484,40 @@ QMainWindow::setWindowFilePath(filePath); } +/****************************************************************************** +* Called by the system when a drag is in progress and the mouse enters this +* window. +******************************************************************************/ +void MainWindow::dragEnterEvent(QDragEnterEvent* event) +{ + if(event->mimeData()->hasUrls()) + event->acceptProposedAction(); +} + +/****************************************************************************** +* Called by the system when the drag is dropped on this window. +******************************************************************************/ +void MainWindow::dropEvent(QDropEvent* event) +{ + event->acceptProposedAction(); + try { + for(const QUrl& url : event->mimeData()->urls()) { + if(url.fileName().endsWith(".ovito", Qt::CaseInsensitive)) { + if(url.isLocalFile()) { + if(!datasetContainer().askForSaveChanges()) + continue; + datasetContainer().fileLoad(url.toLocalFile()); + } + } + else { + datasetContainer().importFile(url); + } + } + } + catch(const Exception& ex) { + ex.reportError(); + } +} OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/MainWindow.h ovito-2.9.0+dfsg1/src/gui/mainwin/MainWindow.h --- ovito-2.8.1+dfsg2/src/gui/mainwin/MainWindow.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/MainWindow.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_MAIN_WINDOW_H -#define __OVITO_MAIN_WINDOW_H +#pragma once + #include #include @@ -122,6 +122,12 @@ /// Is called when the window receives an event. virtual bool event(QEvent *event) override; + /// Called by the system when a drag is in progress and the mouse enters this window. + virtual void dragEnterEvent(QDragEnterEvent* event) override; + + /// Called by the system when the drag is dropped on this window. + virtual void dropEvent(QDropEvent* event) override; + private: /// Creates the main menu. @@ -167,12 +173,9 @@ /// The OpenGL context used for rendering the viewports. QPointer _glcontext; - - /// The global list of all open main windows of the application. - static std::vector _windowList; }; OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_MAIN_WINDOW_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/TaskDisplayWidget.cpp ovito-2.9.0+dfsg1/src/gui/mainwin/TaskDisplayWidget.cpp --- ovito-2.8.1+dfsg2/src/gui/mainwin/TaskDisplayWidget.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/TaskDisplayWidget.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,6 +22,7 @@ #include #include #include +#include #include "TaskDisplayWidget.h" namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Internal) @@ -59,7 +60,7 @@ /****************************************************************************** * Is called when a task has started to run. ******************************************************************************/ -void TaskDisplayWidget::taskStarted(FutureWatcher* taskWatcher) +void TaskDisplayWidget::taskStarted(PromiseWatcher* taskWatcher) { // Show progress indicator only if the task doesn't finish within 200 milliseconds. if(isHidden()) @@ -67,15 +68,15 @@ else updateIndicator(); - connect(taskWatcher, &FutureWatcher::progressRangeChanged, this, &TaskDisplayWidget::taskProgressChanged); - connect(taskWatcher, &FutureWatcher::progressValueChanged, this, &TaskDisplayWidget::taskProgressChanged); - connect(taskWatcher, &FutureWatcher::progressTextChanged, this, &TaskDisplayWidget::taskProgressChanged); + connect(taskWatcher, &PromiseWatcher::progressRangeChanged, this, &TaskDisplayWidget::taskProgressChanged); + connect(taskWatcher, &PromiseWatcher::progressValueChanged, this, &TaskDisplayWidget::taskProgressChanged); + connect(taskWatcher, &PromiseWatcher::progressTextChanged, this, &TaskDisplayWidget::taskProgressChanged); } /****************************************************************************** * Is called when a task has finished. ******************************************************************************/ -void TaskDisplayWidget::taskFinished(FutureWatcher* taskWatcher) +void TaskDisplayWidget::taskFinished(PromiseWatcher* taskWatcher) { updateIndicator(); } @@ -86,7 +87,7 @@ void TaskDisplayWidget::taskProgressChanged() { const TaskManager& taskManager = _mainWindow->datasetContainer().taskManager(); - if(taskManager.runningTasks().empty() == false && taskManager.runningTasks().back() == sender()) + if(taskManager.runningTasks().empty() == false) updateIndicator(); } @@ -118,11 +119,16 @@ _mainWindow->statusBar()->removeWidget(_progressTextDisplay); } else { - FutureWatcher* watcher = taskManager.runningTasks().back(); - _progressBar->setRange(0, watcher->totalProgressMaximum()); - _progressBar->setValue(watcher->totalProgressValue()); - _progressTextDisplay->setText(watcher->progressText()); - show(); + for(auto iter = taskManager.runningTasks().crbegin(); iter != taskManager.runningTasks().crend(); iter++) { + PromiseWatcher* watcher = *iter; + if(watcher->progressMaximum() != 0 || watcher->progressText().isEmpty() == false) { + _progressBar->setRange(0, watcher->progressMaximum()); + _progressBar->setValue(watcher->progressValue()); + _progressTextDisplay->setText(watcher->progressText()); + show(); + break; + } + } } } diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/TaskDisplayWidget.h ovito-2.9.0+dfsg1/src/gui/mainwin/TaskDisplayWidget.h --- ovito-2.8.1+dfsg2/src/gui/mainwin/TaskDisplayWidget.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/TaskDisplayWidget.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TASK_DISPLAY_WIDGET_H -#define __OVITO_TASK_DISPLAY_WIDGET_H +#pragma once + #include @@ -41,10 +41,10 @@ private Q_SLOTS: /// \brief Is called when a task has started to run. - void taskStarted(FutureWatcher* taskWatcher); + void taskStarted(PromiseWatcher* taskWatcher); /// \brief Is called when a task has finished. - void taskFinished(FutureWatcher* taskWatcher); + void taskFinished(PromiseWatcher* taskWatcher); /// \brief Is called when the progress or status of a task has changed. void taskProgressChanged(); @@ -74,4 +74,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_TASK_DISPLAY_WIDGET_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/ViewportsPanel.cpp ovito-2.9.0+dfsg1/src/gui/mainwin/ViewportsPanel.cpp --- ovito-2.8.1+dfsg2/src/gui/mainwin/ViewportsPanel.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/ViewportsPanel.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -51,9 +51,7 @@ ******************************************************************************/ QWidget* ViewportsPanel::viewportWidget(Viewport* vp) { - ViewportWindow* vpWindow = static_cast(vp->window()); - if(!vpWindow) return nullptr; - return vpWindow->widget(); + return static_cast(vp->window()); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/gui/mainwin/ViewportsPanel.h ovito-2.9.0+dfsg1/src/gui/mainwin/ViewportsPanel.h --- ovito-2.8.1+dfsg2/src/gui/mainwin/ViewportsPanel.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/mainwin/ViewportsPanel.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VIEWPORTS_PANEL_H -#define __OVITO_VIEWPORTS_PANEL_H +#pragma once + #include #include @@ -86,4 +86,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_VIEWPORTS_PANEL_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/plugins/autostart/GuiAutoStartObject.cpp ovito-2.9.0+dfsg1/src/gui/plugins/autostart/GuiAutoStartObject.cpp --- ovito-2.8.1+dfsg2/src/gui/plugins/autostart/GuiAutoStartObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/plugins/autostart/GuiAutoStartObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(PluginSystem) -IMPLEMENT_OVITO_OBJECT(Gui, GuiAutoStartObject, AutoStartObject); +IMPLEMENT_OVITO_OBJECT(GuiAutoStartObject, AutoStartObject); OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/gui/plugins/autostart/GuiAutoStartObject.h ovito-2.9.0+dfsg1/src/gui/plugins/autostart/GuiAutoStartObject.h --- ovito-2.8.1+dfsg2/src/gui/plugins/autostart/GuiAutoStartObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/plugins/autostart/GuiAutoStartObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_GUI_AUTO_START_OBJECT_H -#define __OVITO_GUI_AUTO_START_OBJECT_H +#pragma once + #include #include @@ -44,6 +44,9 @@ /// \brief Is called when a new main window is created. virtual void registerActions(ActionManager& actionManager) {} + /// \brief Is called when the main menu is created. + virtual void addActionsToMenu(ActionManager& actionManager, QMenuBar* menuBar) {} + private: Q_OBJECT @@ -53,4 +56,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_GUI_AUTO_START_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/plugins/utility/UtilityApplet.cpp ovito-2.9.0+dfsg1/src/gui/plugins/utility/UtilityApplet.cpp --- ovito-2.8.1+dfsg2/src/gui/plugins/utility/UtilityApplet.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/plugins/utility/UtilityApplet.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(PluginSystem) -IMPLEMENT_OVITO_OBJECT(Gui, UtilityApplet, RefMaker); +IMPLEMENT_OVITO_OBJECT(UtilityApplet, RefMaker); OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/gui/plugins/utility/UtilityApplet.h ovito-2.9.0+dfsg1/src/gui/plugins/utility/UtilityApplet.h --- ovito-2.8.1+dfsg2/src/gui/plugins/utility/UtilityApplet.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/plugins/utility/UtilityApplet.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_UTILITY_APPLET_H -#define __OVITO_UTILITY_APPLET_H +#pragma once + #include #include @@ -60,4 +60,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_UTILITY_APPLET_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/AffineTransformationParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/AffineTransformationParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/AffineTransformationParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/AffineTransformationParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,7 +25,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, AffineTransformationParameterUI, FloatParameterUI); +IMPLEMENT_OVITO_OBJECT(AffineTransformationParameterUI, FloatParameterUI); /****************************************************************************** * Constructor for a Qt property. @@ -78,7 +78,7 @@ Q_EMIT valueEntered(); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } } diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/AffineTransformationParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/AffineTransformationParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/AffineTransformationParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/AffineTransformationParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_AFFINE_TRANSFORMATION_PARAMETER_UI_H -#define __OVITO_AFFINE_TRANSFORMATION_PARAMETER_UI_H +#pragma once + #include #include "FloatParameterUI.h" @@ -61,4 +61,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_AFFINE_TRANSFORMATION_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/BooleanActionParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/BooleanActionParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/BooleanActionParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/BooleanActionParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,7 +26,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, BooleanActionParameterUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(BooleanActionParameterUI, PropertyParameterUI); /****************************************************************************** * Constructor for a Qt property. diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/BooleanActionParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/BooleanActionParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/BooleanActionParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/BooleanActionParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BOOLEAN_ACTION_PARAMETER_UI_H -#define __OVITO_BOOLEAN_ACTION_PARAMETER_UI_H +#pragma once + #include #include "ParameterUI.h" @@ -78,4 +78,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_BOOLEAN_ACTION_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/BooleanGroupBoxParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/BooleanGroupBoxParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/BooleanGroupBoxParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/BooleanGroupBoxParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,7 +28,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, BooleanGroupBoxParameterUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(BooleanGroupBoxParameterUI, PropertyParameterUI); /****************************************************************************** * Constructor for a Qt property. diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/BooleanGroupBoxParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/BooleanGroupBoxParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/BooleanGroupBoxParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/BooleanGroupBoxParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BOOLEAN_GROUP_BOX_PARAMETER_UI_H -#define __OVITO_BOOLEAN_GROUP_BOX_PARAMETER_UI_H +#pragma once + #include #include "ParameterUI.h" @@ -94,4 +94,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_BOOLEAN_GROUP_BOX_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/BooleanParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/BooleanParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/BooleanParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/BooleanParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, BooleanParameterUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(BooleanParameterUI, PropertyParameterUI); /****************************************************************************** * Constructor for a Qt property. diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/BooleanParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/BooleanParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/BooleanParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/BooleanParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BOOLEAN_PARAMETER_UI_H -#define __OVITO_BOOLEAN_PARAMETER_UI_H +#pragma once + #include #include "ParameterUI.h" @@ -85,4 +85,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_BOOLEAN_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/BooleanRadioButtonParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/BooleanRadioButtonParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/BooleanRadioButtonParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/BooleanRadioButtonParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,7 +26,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, BooleanRadioButtonParameterUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(BooleanRadioButtonParameterUI, PropertyParameterUI); /****************************************************************************** * Constructor for a Qt property. diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/BooleanRadioButtonParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/BooleanRadioButtonParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/BooleanRadioButtonParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/BooleanRadioButtonParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BOOLEAN_RADIO_BUTTON_PARAMETER_UI_H -#define __OVITO_BOOLEAN_RADIO_BUTTON_PARAMETER_UI_H +#pragma once + #include #include "ParameterUI.h" @@ -88,4 +88,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_BOOLEAN_RADIO_BUTTON_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/ColorParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/ColorParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/ColorParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/ColorParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, ColorParameterUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(ColorParameterUI, PropertyParameterUI); /****************************************************************************** * The constructor. diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/ColorParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/ColorParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/ColorParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/ColorParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COLOR_PARAMETER_UI_H -#define __OVITO_COLOR_PARAMETER_UI_H +#pragma once + #include #include @@ -91,4 +91,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_COLOR_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/CustomParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/CustomParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/CustomParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/CustomParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,7 +26,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, CustomParameterUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(CustomParameterUI, PropertyParameterUI); /****************************************************************************** * Constructor for a Qt property. diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/CustomParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/CustomParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/CustomParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/CustomParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CUSTOM_PARAMETER_UI_H -#define __OVITO_CUSTOM_PARAMETER_UI_H +#pragma once + #include #include "ParameterUI.h" @@ -105,4 +105,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_VARIANT_COMBO_BOX_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/FilenameParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/FilenameParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/FilenameParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/FilenameParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,7 +25,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, FilenameParameterUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(FilenameParameterUI, PropertyParameterUI); /****************************************************************************** * Constructor for a Qt property. diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/FilenameParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/FilenameParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/FilenameParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/FilenameParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FILENAME_PARAMETER_UI_H -#define __OVITO_FILENAME_PARAMETER_UI_H +#pragma once + #include #include "ParameterUI.h" @@ -85,4 +85,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_FILENAME_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/FloatParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/FloatParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/FloatParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/FloatParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,7 +28,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, FloatParameterUI, NumericalParameterUI); +IMPLEMENT_OVITO_OBJECT(FloatParameterUI, NumericalParameterUI); /****************************************************************************** * Constructor for a Qt property. @@ -97,7 +97,7 @@ } } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } } diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/FloatParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/FloatParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/FloatParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/FloatParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FLOAT_PARAMETER_UI_H -#define __OVITO_FLOAT_PARAMETER_UI_H +#pragma once + #include #include "NumericalParameterUI.h" @@ -78,4 +78,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_FLOAT_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/FontParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/FontParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/FontParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/FontParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, FontParameterUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(FontParameterUI, PropertyParameterUI); /****************************************************************************** * The constructor. diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/FontParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/FontParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/FontParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/FontParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FONT_PARAMETER_UI_H -#define __OVITO_FONT_PARAMETER_UI_H +#pragma once + #include #include "ParameterUI.h" @@ -85,4 +85,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_FONT_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/IntegerParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/IntegerParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/IntegerParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/IntegerParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,7 +28,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, IntegerParameterUI, NumericalParameterUI); +IMPLEMENT_OVITO_OBJECT(IntegerParameterUI, NumericalParameterUI); /****************************************************************************** * Constructor for a Qt property. @@ -97,7 +97,7 @@ } } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } } diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/IntegerParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/IntegerParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/IntegerParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/IntegerParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_INTEGER_PARAMETER_UI_H -#define __OVITO_INTEGER_PARAMETER_UI_H +#pragma once + #include #include "NumericalParameterUI.h" @@ -78,4 +78,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_INTEGER_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/IntegerRadioButtonParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/IntegerRadioButtonParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/IntegerRadioButtonParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/IntegerRadioButtonParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, IntegerRadioButtonParameterUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(IntegerRadioButtonParameterUI, PropertyParameterUI); /****************************************************************************** * The constructor. diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/IntegerRadioButtonParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/IntegerRadioButtonParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/IntegerRadioButtonParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/IntegerRadioButtonParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_INTEGER_RADIO_BUTTON_PARAMETER_UI_H -#define __OVITO_INTEGER_RADIO_BUTTON_PARAMETER_UI_H +#pragma once + #include #include "ParameterUI.h" @@ -97,4 +97,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_INTEGER_RADIO_BUTTON_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/NumericalParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/NumericalParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/NumericalParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/NumericalParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,7 +30,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, NumericalParameterUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(NumericalParameterUI, PropertyParameterUI); /****************************************************************************** * Constructor for a Qt property. diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/NumericalParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/NumericalParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/NumericalParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/NumericalParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_NUMERICAL_PARAMETER_UI_H -#define __OVITO_NUMERICAL_PARAMETER_UI_H +#pragma once + #include #include @@ -143,4 +143,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_NUMERICAL_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/ParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/ParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/ParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/ParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,10 +30,10 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, ParameterUI, RefMaker); -IMPLEMENT_OVITO_OBJECT(Gui, PropertyParameterUI, ParameterUI); -DEFINE_FLAGS_REFERENCE_FIELD(ParameterUI, _editObject, "EditObject", RefTarget, PROPERTY_FIELD_NO_UNDO | PROPERTY_FIELD_WEAK_REF | PROPERTY_FIELD_NO_CHANGE_MESSAGE); -DEFINE_FLAGS_REFERENCE_FIELD(PropertyParameterUI, _parameterObject, "ParameterObject", RefTarget, PROPERTY_FIELD_NO_UNDO | PROPERTY_FIELD_WEAK_REF | PROPERTY_FIELD_NO_CHANGE_MESSAGE); +IMPLEMENT_OVITO_OBJECT(ParameterUI, RefMaker); +IMPLEMENT_OVITO_OBJECT(PropertyParameterUI, ParameterUI); +DEFINE_FLAGS_REFERENCE_FIELD(ParameterUI, editObject, "EditObject", RefTarget, PROPERTY_FIELD_NO_UNDO | PROPERTY_FIELD_WEAK_REF | PROPERTY_FIELD_NO_CHANGE_MESSAGE); +DEFINE_FLAGS_REFERENCE_FIELD(PropertyParameterUI, parameterObject, "ParameterObject", RefTarget, PROPERTY_FIELD_NO_UNDO | PROPERTY_FIELD_WEAK_REF | PROPERTY_FIELD_NO_CHANGE_MESSAGE); ///////////////////////////////////// ParameterUI ///////////////////////////////////////// @@ -42,7 +42,7 @@ ******************************************************************************/ ParameterUI::ParameterUI(QObject* parent) : RefMaker(nullptr), _enabled(true) { - INIT_PROPERTY_FIELD(ParameterUI::_editObject); + INIT_PROPERTY_FIELD(editObject); setParent(parent); @@ -66,7 +66,7 @@ ParameterUI(parent), _propertyName(propertyName), _propField(nullptr) { OVITO_ASSERT(propertyName != NULL); - INIT_PROPERTY_FIELD(PropertyParameterUI::_parameterObject); + INIT_PROPERTY_FIELD(parameterObject); } /****************************************************************************** @@ -75,7 +75,7 @@ PropertyParameterUI::PropertyParameterUI(QObject* parent, const PropertyFieldDescriptor& propField) : ParameterUI(parent), _propertyName(nullptr), _propField(&propField) { - INIT_PROPERTY_FIELD(PropertyParameterUI::_parameterObject); + INIT_PROPERTY_FIELD(parameterObject); // If requested, save parameter value to application's settings store each time the user changes it. if(propField.flags().testFlag(PROPERTY_FIELD_MEMORIZE)) diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/ParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/ParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/ParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/ParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::ParameterUI class and some derived classes. */ -#ifndef __OVITO_PARAMETER_UI_H -#define __OVITO_PARAMETER_UI_H +#pragma once + #include #include @@ -50,11 +50,6 @@ /// \brief Destructor. virtual ~ParameterUI() { clearAllReferences(); } - /// \brief Gets the object whose parameter is being edited/shown in this parameter UI. - /// \return The current object being edited. - /// \sa setEditObject() - RefTarget* editObject() const { return _editObject; } - /// \brief Returns a pointer to the properties editor this parameter UI belongs to. /// \return The editor in which this parameter UI is used or NULL if the parameter UI is used outside of a PropertiesEditor. PropertiesEditor* editor() const { return qobject_cast(this->parent()); } @@ -135,15 +130,13 @@ private: /// The object whose parameter is being edited. - ReferenceField _editObject; + DECLARE_REFERENCE_FIELD(RefTarget, editObject); /// Stores whether this UI is enabled. bool _enabled; Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_editObject); }; /** @@ -188,11 +181,6 @@ /// \brief Indicates whether this parameter UI is representing a Qt property. bool isQtPropertyUI() const { return _propField == nullptr; } - /// \brief Returns the sub-object that is bound to this parameter UI. - /// \return The object stored in the reference field. This may be \c NULL either when there is no editable object selected in the parent editor - /// or if the editable object's reference field is currently empty. - RefTarget* parameterObject() const { return _parameterObject; } - /// \brief This method is called when parameter object has been assigned to the reference field of the editable object /// this parameter UI is bound to. /// @@ -225,7 +213,9 @@ private: /// The controller or sub-object whose value is being edited. - ReferenceField _parameterObject; + /// This may be \c NULL either when there is no editable object selected in the parent editor + /// or if the editable object's reference field is currently empty. + DECLARE_REFERENCE_FIELD(RefTarget, parameterObject); /// The property or reference field being edited or NULL if bound to a Qt property. const PropertyFieldDescriptor* _propField; @@ -235,12 +225,10 @@ Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_parameterObject); }; OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/PropertiesEditor.cpp ovito-2.9.0+dfsg1/src/gui/properties/PropertiesEditor.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/PropertiesEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/PropertiesEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,8 +25,8 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, PropertiesEditor, RefMaker); -DEFINE_FLAGS_REFERENCE_FIELD(PropertiesEditor, _editObject, "EditObject", RefTarget, PROPERTY_FIELD_NO_UNDO | PROPERTY_FIELD_WEAK_REF | PROPERTY_FIELD_NO_CHANGE_MESSAGE); +IMPLEMENT_OVITO_OBJECT(PropertiesEditor, RefMaker); +DEFINE_FLAGS_REFERENCE_FIELD(PropertiesEditor, editObject, "EditObject", RefTarget, PROPERTY_FIELD_NO_UNDO | PROPERTY_FIELD_WEAK_REF | PROPERTY_FIELD_NO_CHANGE_MESSAGE); /****************************************************************************** * Returns the global editor registry, which can be used to look up the editor @@ -58,7 +58,7 @@ catch(Exception& ex) { if(ex.context() == nullptr) ex.setContext(obj->dataset()); ex.prependGeneralMessage(tr("Could no create editor component for the %1 object.").arg(obj->objectTitle())); - ex.showError(); + ex.reportError(); } return nullptr; } @@ -68,7 +68,7 @@ ******************************************************************************/ PropertiesEditor::PropertiesEditor() : RefMaker(nullptr), _container(nullptr), _mainWindow(nullptr) { - INIT_PROPERTY_FIELD(PropertiesEditor::_editObject); + INIT_PROPERTY_FIELD(editObject); } /****************************************************************************** @@ -144,7 +144,7 @@ ******************************************************************************/ void PropertiesEditor::referenceReplaced(const PropertyFieldDescriptor& field, RefTarget* oldTarget, RefTarget* newTarget) { - if(field == PROPERTY_FIELD(PropertiesEditor::_editObject)) { + if(field == PROPERTY_FIELD(editObject)) { setDataset(editObject() ? editObject()->dataset() : nullptr); if(oldTarget) oldTarget->unsetObjectEditingFlag(); if(newTarget) newTarget->setObjectEditingFlag(); diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/PropertiesEditor.h ovito-2.9.0+dfsg1/src/gui/properties/PropertiesEditor.h --- ovito-2.8.1+dfsg2/src/gui/properties/PropertiesEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/PropertiesEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PROPERTIES_EDITOR_H -#define __OVITO_PROPERTIES_EDITOR_H +#pragma once + #include #include @@ -96,16 +96,6 @@ /// /// \note The rollout is automatically deleted when the editor is deleted. QWidget* createRollout(const QString& title, const RolloutInsertionParameters& rolloutParams, const char* helpPage = nullptr); - - /// \brief Returns the object currently being edited in this properties editor. - /// \return The RefTarget derived object which is being edited in this editor. - /// - /// \note This can be another object than the one used to create the editor via - /// PropertiesEditor::create(). Editors are re-usable and the object being edited - /// can be set with setEditObject(). - /// - /// \sa setEditObject() - RefTarget* editObject() const { return _editObject; } /// \brief Executes the passed functor and catches any exceptions thrown during its execution. /// If an exception is thrown by the functor, all changes done by the functor @@ -161,7 +151,7 @@ MainWindow* _mainWindow; /// The object being edited in this editor. - ReferenceField _editObject; + DECLARE_REFERENCE_FIELD(RefTarget, editObject); /// The list of rollout widgets that have been created by editor. /// The cleanup handler is used to delete them when the editor is being deleted. @@ -169,8 +159,6 @@ Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_editObject); }; /// This macro is used to assign a PropertiesEditor-derived class to a RefTarget-derived class. @@ -181,4 +169,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_PROPERTIES_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/PropertiesPanel.h ovito-2.9.0+dfsg1/src/gui/properties/PropertiesPanel.h --- ovito-2.8.1+dfsg2/src/gui/properties/PropertiesPanel.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/PropertiesPanel.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PROPERTIES_PANEL_H -#define __OVITO_PROPERTIES_PANEL_H +#pragma once + #include #include @@ -66,4 +66,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_PROPERTIES_PANEL_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/RefTargetListParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/RefTargetListParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/RefTargetListParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/RefTargetListParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,8 +25,8 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, RefTargetListParameterUI, ParameterUI); -DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(RefTargetListParameterUI, _targets, "Targets", RefTarget, PROPERTY_FIELD_NO_UNDO | PROPERTY_FIELD_WEAK_REF | PROPERTY_FIELD_NO_CHANGE_MESSAGE); +IMPLEMENT_OVITO_OBJECT(RefTargetListParameterUI, ParameterUI); +DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(RefTargetListParameterUI, targets, "Targets", RefTarget, PROPERTY_FIELD_NO_UNDO | PROPERTY_FIELD_WEAK_REF | PROPERTY_FIELD_NO_CHANGE_MESSAGE); /****************************************************************************** * The constructor. @@ -34,7 +34,7 @@ RefTargetListParameterUI::RefTargetListParameterUI(QObject* parentEditor, const PropertyFieldDescriptor& refField, const RolloutInsertionParameters& rolloutParams, const OvitoObjectType* defaultEditorClass) : ParameterUI(parentEditor), _refField(refField), _rolloutParams(rolloutParams), _defaultEditorClass(defaultEditorClass) { - INIT_PROPERTY_FIELD(RefTargetListParameterUI::_targets); + INIT_PROPERTY_FIELD(targets); OVITO_ASSERT_MSG(refField.isVector(), "RefTargetListParameterUI constructor", "The reference field bound to this parameter UI must be a vector reference field."); _model = new ListViewModel(this); @@ -186,7 +186,7 @@ } } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } @@ -219,10 +219,10 @@ int RefTargetListParameterUI::setSelectedObject(RefTarget* selObj) { if(!_viewWidget) return -1; - OVITO_ASSERT(_targetToRow.size() == _targets.size()); + OVITO_ASSERT(_targetToRow.size() == targets().size()); if(selObj != nullptr) { - for(int i = 0; i<_targets.size(); i++) { - if(_targets[i] == selObj) { + for(int i = 0; i< targets().size(); i++) { + if(targets()[i] == selObj) { int rowIndex = _targetToRow[i]; _viewWidget->selectionModel()->select(_model->index(rowIndex, 0), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); return rowIndex; @@ -251,9 +251,9 @@ _model->beginInsert(rowIndex); _targets.insert(refevent->index(), refevent->newTarget()); _targetToRow.insert(refevent->index(), rowIndex); - for(int i=rowIndex; i<_rowToTarget.size(); i++) + for(int i = rowIndex; i < _rowToTarget.size(); i++) _rowToTarget[i]++; - if(refevent->newTarget() != NULL) { + if(refevent->newTarget() != nullptr) { _rowToTarget.insert(rowIndex, refevent->index()); for(int i=refevent->index()+1; i<_targetToRow.size(); i++) _targetToRow[i]++; @@ -313,8 +313,8 @@ } else if(event->type() == ReferenceEvent::TitleChanged || event->type() == ReferenceEvent::TargetChanged) { OVITO_ASSERT(_targetToRow.size() == _targets.size()); - for(int i = 0; i < _targets.size(); i++) { - if(_targets[i] == source) { + for(int i = 0; i < targets().size(); i++) { + if(targets()[i] == source) { // Update a single item. _model->updateItem(_targetToRow[i]); } @@ -337,9 +337,9 @@ return QVariant(); int targetIndex = owner()->_rowToTarget[index.row()]; - OVITO_ASSERT(targetIndex < owner()->_targets.size()); + OVITO_ASSERT(targetIndex < owner()->targets().size()); - RefTarget* t = owner()->_targets[targetIndex]; + RefTarget* t = owner()->targets()[targetIndex]; return owner()->getItemData(t, index, role); } @@ -356,9 +356,9 @@ return QVariant(); int targetIndex = owner()->_rowToTarget[section]; - OVITO_ASSERT(targetIndex < owner()->_targets.size()); + OVITO_ASSERT(targetIndex < owner()->targets().size()); - RefTarget* t = owner()->_targets[targetIndex]; + RefTarget* t = owner()->targets()[targetIndex]; return owner()->getVerticalHeaderData(t, section, role); } else { @@ -375,9 +375,9 @@ return QAbstractItemModel::flags(index); int targetIndex = owner()->_rowToTarget[index.row()]; - OVITO_ASSERT(targetIndex < owner()->_targets.size()); + OVITO_ASSERT(targetIndex < owner()->targets().size()); - RefTarget* t = owner()->_targets[targetIndex]; + RefTarget* t = owner()->targets()[targetIndex]; return owner()->getItemFlags(t, index); } @@ -390,9 +390,9 @@ return QAbstractItemModel::setData(index, value, role); int targetIndex = owner()->_rowToTarget[index.row()]; - OVITO_ASSERT(targetIndex < owner()->_targets.size()); + OVITO_ASSERT(targetIndex < owner()->targets().size()); - RefTarget* t = owner()->_targets[targetIndex]; + RefTarget* t = owner()->targets()[targetIndex]; return owner()->setItemData(t, index, value, role); } diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/RefTargetListParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/RefTargetListParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/RefTargetListParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/RefTargetListParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_REFTARGET_LIST_PARAMETER_UI_H -#define __OVITO_REFTARGET_LIST_PARAMETER_UI_H +#pragma once + #include #include "ParameterUI.h" @@ -182,7 +182,7 @@ ListViewModel* _model; /// The list of items in the list view. - VectorReferenceField _targets; + DECLARE_VECTOR_REFERENCE_FIELD(RefTarget, targets); /// Maps reference field indices to row indices. QVector _targetToRow; @@ -196,16 +196,12 @@ /// Controls where the sub-editor is opened and whether the sub-editor is opened in a collapsed state. RolloutInsertionParameters _rolloutParams; -private: - Q_OBJECT OVITO_OBJECT - - DECLARE_VECTOR_REFERENCE_FIELD(_targets); }; OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_REFTARGET_LIST_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/StringParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/StringParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/StringParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/StringParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, StringParameterUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(StringParameterUI, PropertyParameterUI); /****************************************************************************** * Constructor for a Qt property. diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/StringParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/StringParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/StringParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/StringParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_STRING_PARAMETER_UI_H -#define __OVITO_STRING_PARAMETER_UI_H +#pragma once + #include #include "ParameterUI.h" @@ -93,4 +93,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_STRING_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/SubObjectParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/SubObjectParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/SubObjectParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/SubObjectParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,7 +26,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, SubObjectParameterUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(SubObjectParameterUI, PropertyParameterUI); /****************************************************************************** * The constructor. @@ -67,7 +67,7 @@ subEditor()->setEditObject(parameterObject()); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/SubObjectParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/SubObjectParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/SubObjectParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/SubObjectParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SUBOBJECT_PARAMETER_UI_H -#define __OVITO_SUBOBJECT_PARAMETER_UI_H +#pragma once + #include #include "ParameterUI.h" @@ -71,4 +71,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_SUBOBJECT_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/VariantComboBoxParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/VariantComboBoxParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/VariantComboBoxParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/VariantComboBoxParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,7 +26,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, VariantComboBoxParameterUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(VariantComboBoxParameterUI, PropertyParameterUI); /****************************************************************************** * Constructor for a Qt property. diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/VariantComboBoxParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/VariantComboBoxParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/VariantComboBoxParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/VariantComboBoxParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VARIANT_COMBO_BOX_PARAMETER_UI_H -#define __OVITO_VARIANT_COMBO_BOX_PARAMETER_UI_H +#pragma once + #include #include "ParameterUI.h" @@ -91,4 +91,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_VARIANT_COMBO_BOX_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/Vector3ParameterUI.cpp ovito-2.9.0+dfsg1/src/gui/properties/Vector3ParameterUI.cpp --- ovito-2.8.1+dfsg2/src/gui/properties/Vector3ParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/Vector3ParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Gui) OVITO_BEGIN_INLINE_NAMESPACE(Params) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(Gui, Vector3ParameterUI, FloatParameterUI); +IMPLEMENT_OVITO_OBJECT(Vector3ParameterUI, FloatParameterUI); /****************************************************************************** * Constructor for a Qt property. @@ -102,7 +102,7 @@ Q_EMIT valueEntered(); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } } diff -Nru ovito-2.8.1+dfsg2/src/gui/properties/Vector3ParameterUI.h ovito-2.9.0+dfsg1/src/gui/properties/Vector3ParameterUI.h --- ovito-2.8.1+dfsg2/src/gui/properties/Vector3ParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/properties/Vector3ParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VECTOR3_PARAMETER_UI_H -#define __OVITO_VECTOR3_PARAMETER_UI_H +#pragma once + #include #include "FloatParameterUI.h" @@ -61,4 +61,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_VECTOR3_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/rendering/RenderSettingsEditor.cpp ovito-2.9.0+dfsg1/src/gui/rendering/RenderSettingsEditor.cpp --- ovito-2.8.1+dfsg2/src/gui/rendering/RenderSettingsEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/rendering/RenderSettingsEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -38,7 +38,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(Gui, RenderSettingsEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(RenderSettingsEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(RenderSettings, RenderSettingsEditor); // Predefined output image dimensions. @@ -76,7 +76,7 @@ layout2c->setSpacing(2); layout2->addLayout(layout2c); - IntegerRadioButtonParameterUI* renderingRangeTypeUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(RenderSettings::_renderingRangeType)); + IntegerRadioButtonParameterUI* renderingRangeTypeUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(RenderSettings::renderingRangeType)); QRadioButton* currentFrameButton = renderingRangeTypeUI->addRadioButton(RenderSettings::CURRENT_FRAME, tr("Single frame")); layout2c->addWidget(currentFrameButton, 0, 0, 1, 5); @@ -87,11 +87,11 @@ QRadioButton* customIntervalButton = renderingRangeTypeUI->addRadioButton(RenderSettings::CUSTOM_INTERVAL, tr("Range:")); layout2c->addWidget(customIntervalButton, 2, 0, 1, 5); - IntegerParameterUI* customRangeStartUI = new IntegerParameterUI(this, PROPERTY_FIELD(RenderSettings::_customRangeStart)); + IntegerParameterUI* customRangeStartUI = new IntegerParameterUI(this, PROPERTY_FIELD(RenderSettings::customRangeStart)); customRangeStartUI->setEnabled(false); layout2c->addLayout(customRangeStartUI->createFieldLayout(), 3, 1); layout2c->addWidget(new QLabel(tr("to")), 3, 2); - IntegerParameterUI* customRangeEndUI = new IntegerParameterUI(this, PROPERTY_FIELD(RenderSettings::_customRangeEnd)); + IntegerParameterUI* customRangeEndUI = new IntegerParameterUI(this, PROPERTY_FIELD(RenderSettings::customRangeEnd)); customRangeEndUI->setEnabled(false); layout2c->addLayout(customRangeEndUI->createFieldLayout(), 3, 3); layout2c->setColumnMinimumWidth(0, 30); @@ -103,10 +103,10 @@ layout2a->setContentsMargins(0,6,0,0); layout2a->setSpacing(2); layout2->addLayout(layout2a); - IntegerParameterUI* everyNthFrameUI = new IntegerParameterUI(this, PROPERTY_FIELD(RenderSettings::_everyNthFrame)); + IntegerParameterUI* everyNthFrameUI = new IntegerParameterUI(this, PROPERTY_FIELD(RenderSettings::everyNthFrame)); layout2a->addWidget(everyNthFrameUI->label(), 0, 0); layout2a->addLayout(everyNthFrameUI->createFieldLayout(), 0, 1); - IntegerParameterUI* fileNumberBaseUI = new IntegerParameterUI(this, PROPERTY_FIELD(RenderSettings::_fileNumberBase)); + IntegerParameterUI* fileNumberBaseUI = new IntegerParameterUI(this, PROPERTY_FIELD(RenderSettings::fileNumberBase)); layout2a->addWidget(fileNumberBaseUI->label(), 1, 0); layout2a->addLayout(fileNumberBaseUI->createFieldLayout(), 1, 1); layout2a->setColumnStretch(2, 1); @@ -128,12 +128,12 @@ layout2->setColumnStretch(1, 1); // Image width parameter. - IntegerParameterUI* imageWidthUI = new IntegerParameterUI(this, PROPERTY_FIELD(RenderSettings::_outputImageWidth)); + IntegerParameterUI* imageWidthUI = new IntegerParameterUI(this, PROPERTY_FIELD(RenderSettings::outputImageWidth)); layout2->addWidget(imageWidthUI->label(), 0, 0); layout2->addLayout(imageWidthUI->createFieldLayout(), 0, 1); // Image height parameter. - IntegerParameterUI* imageHeightUI = new IntegerParameterUI(this, PROPERTY_FIELD(RenderSettings::_outputImageHeight)); + IntegerParameterUI* imageHeightUI = new IntegerParameterUI(this, PROPERTY_FIELD(RenderSettings::outputImageHeight)); layout2->addWidget(imageHeightUI->label(), 1, 0); layout2->addLayout(imageHeightUI->createFieldLayout(), 1, 1); @@ -155,7 +155,7 @@ layout2->setSpacing(2); layout2->setColumnStretch(0, 1); - BooleanParameterUI* saveFileUI = new BooleanParameterUI(this, PROPERTY_FIELD(RenderSettings::_saveToFile)); + BooleanParameterUI* saveFileUI = new BooleanParameterUI(this, PROPERTY_FIELD(RenderSettings::saveToFile)); layout2->addWidget(saveFileUI->checkBox(), 0, 0); QPushButton* chooseFilenameBtn = new QPushButton(tr("Choose..."), rollout); @@ -167,7 +167,7 @@ imageFilenameUI->setEnabled(false); layout2->addWidget(imageFilenameUI->textBox(), 1, 0, 1, 2); - //BooleanParameterUI* skipExistingImagesUI = new BooleanParameterUI(this, PROPERTY_FIELD(RenderSettings::_skipExistingImages)); + //BooleanParameterUI* skipExistingImagesUI = new BooleanParameterUI(this, PROPERTY_FIELD(RenderSettings::skipExistingImages)); //layout2->addWidget(skipExistingImagesUI->checkBox(), 2, 0, 1, 2); //connect(saveFileUI->checkBox(), &QCheckBox::toggled, skipExistingImagesUI, &BooleanParameterUI::setEnabled); } @@ -183,11 +183,11 @@ // Background color parameter. layout2->addWidget(new QLabel(tr("Background:")), 0, 0, 1, 3); - ColorParameterUI* backgroundColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(RenderSettings::_backgroundColor)); + ColorParameterUI* backgroundColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(RenderSettings::backgroundColorController)); layout2->addWidget(backgroundColorPUI->colorPicker(), 1, 1, 1, 2); // Alpha channel. - BooleanRadioButtonParameterUI* generateAlphaUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(RenderSettings::_generateAlphaChannel)); + BooleanRadioButtonParameterUI* generateAlphaUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(RenderSettings::generateAlphaChannel)); layout2->addWidget(generateAlphaUI->buttonFalse(), 1, 0, 1, 1); layout2->addWidget(generateAlphaUI->buttonTrue(), 2, 0, 1, 3); generateAlphaUI->buttonFalse()->setText(tr("Color:")); @@ -201,7 +201,7 @@ } // Open a sub-editor for the renderer. - new SubObjectParameterUI(this, PROPERTY_FIELD(RenderSettings::_renderer), rolloutParams.after(rollout)); + new SubObjectParameterUI(this, PROPERTY_FIELD(RenderSettings::renderer), rolloutParams.after(rollout)); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/gui/rendering/RenderSettingsEditor.h ovito-2.9.0+dfsg1/src/gui/rendering/RenderSettingsEditor.h --- ovito-2.8.1+dfsg2/src/gui/rendering/RenderSettingsEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/rendering/RenderSettingsEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_RENDER_SETTINGS_EDITOR_H -#define __OVITO_RENDER_SETTINGS_EDITOR_H +#pragma once + #include #include @@ -67,4 +67,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_RENDER_SETTINGS_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/rendering/StandardSceneRenderer.cpp ovito-2.9.0+dfsg1/src/gui/rendering/StandardSceneRenderer.cpp --- ovito-2.8.1+dfsg2/src/gui/rendering/StandardSceneRenderer.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/rendering/StandardSceneRenderer.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,177 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (2013) Alexander Stukowski -// -// This file is part of OVITO (Open Visualization Tool). -// -// OVITO is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// OVITO is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -/////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include -#include -#include "StandardSceneRenderer.h" -#include "StandardSceneRendererEditor.h" - -namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) - -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Gui, StandardSceneRenderer, OpenGLSceneRenderer); -SET_OVITO_OBJECT_EDITOR(StandardSceneRenderer, StandardSceneRendererEditor); -DEFINE_PROPERTY_FIELD(StandardSceneRenderer, _antialiasingLevel, "AntialiasingLevel"); -SET_PROPERTY_FIELD_LABEL(StandardSceneRenderer, _antialiasingLevel, "Antialiasing level"); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(StandardSceneRenderer, _antialiasingLevel, IntegerParameterUnit, 1, 6); - -/****************************************************************************** -* Prepares the renderer for rendering and sets the data set that is being rendered. -******************************************************************************/ -bool StandardSceneRenderer::startRender(DataSet* dataset, RenderSettings* settings) -{ - if(Application::instance().headlessMode()) - throwException(tr("Cannot use OpenGL renderer when program is running in headless mode. " - "Please use a different rendering engine or start program on a machine where access to " - "graphics hardware is possible.")); - - if(!OpenGLSceneRenderer::startRender(dataset, settings)) - return false; - - int sampling = std::max(1, antialiasingLevel()); - - QOpenGLContext* glcontext; - if(Application::instance().guiMode()) { -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - // in GUI mode, use the OpenGL context managed by the main window to render to the offscreen buffer. - glcontext = MainWindow::fromDataset(renderDataset())->getOpenGLContext(); -#else - // Create a temporary OpenGL context for rendering to an offscreen buffer. - _offscreenContext.reset(new QOpenGLContext()); - _offscreenContext->setFormat(OpenGLSceneRenderer::getDefaultSurfaceFormat()); - // It should share its resources with the viewport renderer. - const QVector& viewports = renderDataset()->viewportConfig()->viewports(); - if(!viewports.empty() && viewports.front()->window()) - _offscreenContext->setShareContext(static_cast(viewports.front()->window())->context()); - if(!_offscreenContext->create()) - throwException(tr("Failed to create OpenGL context for rendering.")); - glcontext = _offscreenContext.data(); -#endif - } - else { - // Create new OpenGL context for rendering in console mode. - OVITO_ASSERT(QOpenGLContext::currentContext() == nullptr); - _offscreenContext.reset(new QOpenGLContext()); - _offscreenContext->setFormat(OpenGLSceneRenderer::getDefaultSurfaceFormat()); - if(!_offscreenContext->create()) - throwException(tr("Failed to create OpenGL context for rendering.")); - glcontext = _offscreenContext.data(); - } - - // Create offscreen buffer. - if(_offscreenSurface.isNull()) - _offscreenSurface.reset(new QOffscreenSurface()); - _offscreenSurface->setFormat(glcontext->format()); - _offscreenSurface->create(); - if(!_offscreenSurface->isValid()) - throwException(tr("Failed to create offscreen rendering surface.")); - - // Make the context current. - if(!glcontext->makeCurrent(_offscreenSurface.data())) - throwException(tr("Failed to make OpenGL context current.")); - - // Create OpenGL framebuffer. - _framebufferSize = QSize(settings->outputImageWidth() * sampling, settings->outputImageHeight() * sampling); - QOpenGLFramebufferObjectFormat framebufferFormat; - framebufferFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); - _framebufferObject.reset(new QOpenGLFramebufferObject(_framebufferSize.width(), _framebufferSize.height(), framebufferFormat)); - if(!_framebufferObject->isValid()) - throwException(tr("Failed to create OpenGL framebuffer object for offscreen rendering.")); - - // Bind OpenGL buffer. - if(!_framebufferObject->bind()) - throwException(tr("Failed to bind OpenGL framebuffer object for offscreen rendering.")); - - return true; -} - -/****************************************************************************** -* This method is called just before renderFrame() is called. -******************************************************************************/ -void StandardSceneRenderer::beginFrame(TimePoint time, const ViewProjectionParameters& params, Viewport* vp) -{ - // Make GL context current. - QOpenGLContext* glcontext; - if(!_offscreenContext) - glcontext = MainWindow::fromDataset(renderDataset())->getOpenGLContext(); - else - glcontext = _offscreenContext.data(); - if(!glcontext->makeCurrent(_offscreenSurface.data())) - throwException(tr("Failed to make OpenGL context current.")); - - OpenGLSceneRenderer::beginFrame(time, params, vp); - - // Setup GL viewport. - setRenderingViewport(0, 0, _framebufferSize.width(), _framebufferSize.height()); - - // Set rendering background color. - if(!renderSettings()->generateAlphaChannel()) { - Color backgroundColor = renderSettings()->backgroundColor(); - setClearColor(ColorA(backgroundColor)); - } - else setClearColor(ColorA(0, 0, 0, 0)); -} - -/****************************************************************************** -* Renders the current animation frame. -******************************************************************************/ -bool StandardSceneRenderer::renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, AbstractProgressDisplay* progress) -{ - // Let the base class do the main rendering work. - if(!OpenGLSceneRenderer::renderFrame(frameBuffer, stereoTask, progress)) - return false; - - // Flush the contents to the FBO before extracting image. - glcontext()->swapBuffers(_offscreenSurface.data()); - - // Fetch rendered image from OpenGL framebuffer. - QImage bufferImage = _framebufferObject->toImage(); - - // Scale it down to the output size. - QImage image = bufferImage.scaled(frameBuffer->image().width(), frameBuffer->image().height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - - // Copy OpenGL image to the output frame buffer. - frameBuffer->image() = image; - frameBuffer->update(); - - return true; -} - -/****************************************************************************** -* Is called after rendering has finished. -******************************************************************************/ -void StandardSceneRenderer::endRender() -{ - QOpenGLFramebufferObject::bindDefault(); - QOpenGLContext* ctxt = QOpenGLContext::currentContext(); - if(ctxt) ctxt->doneCurrent(); - _framebufferObject.reset(); - _offscreenContext.reset(); - _offscreenSurface.reset(); - OpenGLSceneRenderer::endRender(); -} - -OVITO_END_INLINE_NAMESPACE -} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/gui/rendering/StandardSceneRendererEditor.cpp ovito-2.9.0+dfsg1/src/gui/rendering/StandardSceneRendererEditor.cpp --- ovito-2.8.1+dfsg2/src/gui/rendering/StandardSceneRendererEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/rendering/StandardSceneRendererEditor.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (2013) Alexander Stukowski -// -// This file is part of OVITO (Open Visualization Tool). -// -// OVITO is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// OVITO is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -/////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include "StandardSceneRenderer.h" -#include "StandardSceneRendererEditor.h" - -namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) OVITO_BEGIN_INLINE_NAMESPACE(Internal) - -IMPLEMENT_OVITO_OBJECT(Gui, StandardSceneRendererEditor, PropertiesEditor); - -/****************************************************************************** -* Constructor that creates the UI controls for the editor. -******************************************************************************/ -void StandardSceneRendererEditor::createUI(const RolloutInsertionParameters& rolloutParams) -{ - // Create the rollout. - QWidget* rollout = createRollout(tr("OpenGL renderer settings"), rolloutParams, "rendering.opengl_renderer.html"); - - QGridLayout* layout = new QGridLayout(rollout); - layout->setContentsMargins(4,4,4,4); -#ifndef Q_OS_MACX - layout->setSpacing(2); -#endif - layout->setColumnStretch(1, 1); - - // Antialiasing level - IntegerParameterUI* antialiasingLevelUI = new IntegerParameterUI(this, PROPERTY_FIELD(StandardSceneRenderer::_antialiasingLevel)); - layout->addWidget(antialiasingLevelUI->label(), 0, 0); - layout->addLayout(antialiasingLevelUI->createFieldLayout(), 0, 1); -} - -OVITO_END_INLINE_NAMESPACE -OVITO_END_INLINE_NAMESPACE -} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/gui/rendering/StandardSceneRendererEditor.h ovito-2.9.0+dfsg1/src/gui/rendering/StandardSceneRendererEditor.h --- ovito-2.8.1+dfsg2/src/gui/rendering/StandardSceneRendererEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/rendering/StandardSceneRendererEditor.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (2013) Alexander Stukowski -// -// This file is part of OVITO (Open Visualization Tool). -// -// OVITO is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// OVITO is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef __OVITO_STANDARD_SCENE_RENDERER_EDITOR_H -#define __OVITO_STANDARD_SCENE_RENDERER_EDITOR_H - -#include -#include -#include - -namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) OVITO_BEGIN_INLINE_NAMESPACE(Internal) - -/****************************************************************************** -* The editor component for the StandardSceneRenderer class. -******************************************************************************/ -class StandardSceneRendererEditor : public PropertiesEditor -{ -public: - - /// Default constructor. - Q_INVOKABLE StandardSceneRendererEditor() {} - -protected: - - /// Creates the user interface controls for the editor. - virtual void createUI(const RolloutInsertionParameters& rolloutParams) override; - -private: - - Q_OBJECT - OVITO_OBJECT -}; - -OVITO_END_INLINE_NAMESPACE -OVITO_END_INLINE_NAMESPACE -} // End of namespace - -#endif // __OVITO_STANDARD_SCENE_RENDERER_EDITOR_H diff -Nru ovito-2.8.1+dfsg2/src/gui/rendering/StandardSceneRenderer.h ovito-2.9.0+dfsg1/src/gui/rendering/StandardSceneRenderer.h --- ovito-2.8.1+dfsg2/src/gui/rendering/StandardSceneRenderer.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/rendering/StandardSceneRenderer.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (2013) Alexander Stukowski -// -// This file is part of OVITO (Open Visualization Tool). -// -// OVITO is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// OVITO is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef __OVITO_STANDARD_SCENE_RENDERER_H -#define __OVITO_STANDARD_SCENE_RENDERER_H - -#include -#include - -namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) - -/** - * \brief This is the default scene renderer used for high-quality image output. - */ -class OVITO_GUI_EXPORT StandardSceneRenderer : public OpenGLSceneRenderer -{ -public: - - /// Default constructor. - Q_INVOKABLE StandardSceneRenderer(DataSet* dataset) : OpenGLSceneRenderer(dataset), _antialiasingLevel(3) { - INIT_PROPERTY_FIELD(StandardSceneRenderer::_antialiasingLevel); - } - - /// Returns the number of sub-pixels to render. - virtual int antialiasingLevel() const override { return _antialiasingLevel; } - - /// Sets the number of sub-pixels to render. - void setAntialiasingLevel(int newLevel) { _antialiasingLevel = newLevel; } - - /// Prepares the renderer for rendering and sets the data set that is being rendered. - virtual bool startRender(DataSet* dataset, RenderSettings* settings) override; - - /// This method is called just before renderFrame() is called. - virtual void beginFrame(TimePoint time, const ViewProjectionParameters& params, Viewport* vp) override; - - /// Renders the current animation frame. - virtual bool renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, AbstractProgressDisplay* progress) override; - - /// Is called after rendering has finished. - virtual void endRender() override; - - /// Returns whether this renderer is rendering an interactive viewport. - /// \return true if rendering a real-time viewport; false if rendering an output image. - virtual bool isInteractive() const override { return false; } - -public: - - Q_PROPERTY(int antialiasingLevel READ antialiasingLevel WRITE setAntialiasingLevel); - -private: - - /// Controls the number of sub-pixels to render. - PropertyField _antialiasingLevel; - - /// The offscreen surface used to render into an image buffer using OpenGL. - QScopedPointer _offscreenSurface; - - /// The temporary OpenGL rendering context. - QScopedPointer _offscreenContext; - - /// The OpenGL framebuffer. - QScopedPointer _framebufferObject; - - /// The resolution of the offscreen framebuffer. - QSize _framebufferSize; - - Q_OBJECT - OVITO_OBJECT - - Q_CLASSINFO("DisplayName", "OpenGL renderer"); - - DECLARE_PROPERTY_FIELD(_antialiasingLevel); -}; - -OVITO_END_INLINE_NAMESPACE -} // End of namespace - -#endif // __OVITO_STANDARD_SCENE_RENDERER_H diff -Nru ovito-2.8.1+dfsg2/src/gui/rendering/ViewportSceneRenderer.cpp ovito-2.9.0+dfsg1/src/gui/rendering/ViewportSceneRenderer.cpp --- ovito-2.8.1+dfsg2/src/gui/rendering/ViewportSceneRenderer.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/rendering/ViewportSceneRenderer.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -37,7 +37,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Gui, ViewportSceneRenderer, OpenGLSceneRenderer); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ViewportSceneRenderer, OpenGLSceneRenderer); /****************************************************************************** * This method is called just before renderFrame() is called. @@ -114,8 +114,8 @@ return true; } - // Evaluate geometry pipeline of object node. - const PipelineFlowState& state = node->evalPipeline(time); + // Evaluate data pipeline of object node. + const PipelineFlowState& state = node->evaluatePipelineImmediately(PipelineEvalRequest(time, true)); for(const auto& dataObj : state.objects()) { for(DisplayObject* displayObj : dataObj->displayObjects()) { if(displayObj && displayObj->isEnabled()) { diff -Nru ovito-2.8.1+dfsg2/src/gui/rendering/ViewportSceneRenderer.h ovito-2.9.0+dfsg1/src/gui/rendering/ViewportSceneRenderer.h --- ovito-2.8.1+dfsg2/src/gui/rendering/ViewportSceneRenderer.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/rendering/ViewportSceneRenderer.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VIEWPORT_SCENE_RENDERER_H -#define __OVITO_VIEWPORT_SCENE_RENDERER_H +#pragma once + #include #include @@ -82,4 +82,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_VIEWPORT_SCENE_RENDERER_H + Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/src/gui/resources/mainwin/window_icon_50.png and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/src/gui/resources/mainwin/window_icon_50.png differ diff -Nru ovito-2.8.1+dfsg2/src/gui/scene/objects/camera/CameraObjectEditor.cpp ovito-2.9.0+dfsg1/src/gui/scene/objects/camera/CameraObjectEditor.cpp --- ovito-2.8.1+dfsg2/src/gui/scene/objects/camera/CameraObjectEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/scene/objects/camera/CameraObjectEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,7 +28,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) OVITO_BEGIN_INLINE_NAMESPACE(StdObj) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(Gui, CameraObjectEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(CameraObjectEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(CameraObject, CameraObjectEditor); /****************************************************************************** @@ -50,12 +50,12 @@ layout->addLayout(sublayout); // Camera projection parameter. - BooleanRadioButtonParameterUI* isPerspectivePUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(CameraObject::_isPerspective)); + BooleanRadioButtonParameterUI* isPerspectivePUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(CameraObject::isPerspective)); isPerspectivePUI->buttonTrue()->setText(tr("Perspective camera:")); sublayout->addWidget(isPerspectivePUI->buttonTrue(), 0, 0, 1, 3); // FOV parameter. - FloatParameterUI* fovPUI = new FloatParameterUI(this, PROPERTY_FIELD(CameraObject::_fov)); + FloatParameterUI* fovPUI = new FloatParameterUI(this, PROPERTY_FIELD(CameraObject::fovController)); sublayout->addWidget(fovPUI->label(), 1, 1); sublayout->addLayout(fovPUI->createFieldLayout(), 1, 2); @@ -63,7 +63,7 @@ sublayout->addWidget(isPerspectivePUI->buttonFalse(), 2, 0, 1, 3); // Zoom parameter. - FloatParameterUI* zoomPUI = new FloatParameterUI(this, PROPERTY_FIELD(CameraObject::_zoom)); + FloatParameterUI* zoomPUI = new FloatParameterUI(this, PROPERTY_FIELD(CameraObject::zoomController)); sublayout->addWidget(zoomPUI->label(), 3, 1); sublayout->addLayout(zoomPUI->createFieldLayout(), 3, 2); diff -Nru ovito-2.8.1+dfsg2/src/gui/scene/objects/camera/CameraObjectEditor.h ovito-2.9.0+dfsg1/src/gui/scene/objects/camera/CameraObjectEditor.h --- ovito-2.8.1+dfsg2/src/gui/scene/objects/camera/CameraObjectEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/scene/objects/camera/CameraObjectEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CAMERA_OBJECT_EDITOR_H -#define __OVITO_CAMERA_OBJECT_EDITOR_H +#pragma once + #include #include @@ -54,4 +54,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_CAMERA_OBJECT_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/scene/objects/geometry/TriMeshDisplayEditor.cpp ovito-2.9.0+dfsg1/src/gui/scene/objects/geometry/TriMeshDisplayEditor.cpp --- ovito-2.8.1+dfsg2/src/gui/scene/objects/geometry/TriMeshDisplayEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/scene/objects/geometry/TriMeshDisplayEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(ObjectSystem) OVITO_BEGIN_INLINE_NAMESPACE(Scene) OVITO_BEGIN_INLINE_NAMESPACE(StdObj) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(Gui, TriMeshDisplayEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(TriMeshDisplayEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(TriMeshDisplay, TriMeshDisplayEditor); /****************************************************************************** @@ -44,11 +44,11 @@ layout->setSpacing(4); layout->setColumnStretch(1, 1); - ColorParameterUI* colorUI = new ColorParameterUI(this, PROPERTY_FIELD(TriMeshDisplay::_color)); + ColorParameterUI* colorUI = new ColorParameterUI(this, PROPERTY_FIELD(TriMeshDisplay::color)); layout->addWidget(colorUI->label(), 0, 0); layout->addWidget(colorUI->colorPicker(), 0, 1); - FloatParameterUI* transparencyUI = new FloatParameterUI(this, PROPERTY_FIELD(TriMeshDisplay::_transparency)); + FloatParameterUI* transparencyUI = new FloatParameterUI(this, PROPERTY_FIELD(TriMeshDisplay::transparencyController)); layout->addWidget(new QLabel(tr("Transparency:")), 1, 0); layout->addLayout(transparencyUI->createFieldLayout(), 1, 1); } diff -Nru ovito-2.8.1+dfsg2/src/gui/scene/objects/geometry/TriMeshDisplayEditor.h ovito-2.9.0+dfsg1/src/gui/scene/objects/geometry/TriMeshDisplayEditor.h --- ovito-2.8.1+dfsg2/src/gui/scene/objects/geometry/TriMeshDisplayEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/scene/objects/geometry/TriMeshDisplayEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TRIMESH_DISPLAY_EDITOR_H -#define __OVITO_TRIMESH_DISPLAY_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_TRIMESH_DISPLAY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/utilities/concurrent/ProgressDialogAdapter.h ovito-2.9.0+dfsg1/src/gui/utilities/concurrent/ProgressDialogAdapter.h --- ovito-2.8.1+dfsg2/src/gui/utilities/concurrent/ProgressDialogAdapter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/utilities/concurrent/ProgressDialogAdapter.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,86 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (2016) Alexander Stukowski -// -// This file is part of OVITO (Open Visualization Tool). -// -// OVITO is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// OVITO is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef __OVITO_PROGRESS_DIALOG_ADAPTER_H -#define __OVITO_PROGRESS_DIALOG_ADAPTER_H - -#include -#include - -namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) - -class ProgressDialogAdapter : public AbstractProgressDisplay -{ -public: - - /// Constructor. - ProgressDialogAdapter(QProgressDialog* dialog) : _dialog(dialog) {} - - /// Returns whether the operation has been canceled by the user. - virtual bool wasCanceled() override { - return _dialog->wasCanceled(); - } - - /// Cancels the operation. - virtual void cancel() override { - _dialog->cancel(); - } - - /// Sets the status text to be displayed. - virtual void setStatusText(const QString& text) override { - _dialog->setLabelText(text); - } - - /// Return the current status text. - virtual QString statusText() override { - return _dialog->labelText(); - } - - /// Returns the highest value represented by the progress bar. - virtual int maximum() override { - return _dialog->maximum(); - } - - /// Sets the highest value represented by the progress bar. - virtual void setMaximum(int max) override { - _dialog->setMaximum(max); - } - - /// Returns the value displayed by the progress bar. - virtual int value() override { - return _dialog->value(); - } - - /// Sets the value displayed by the progress bar. - virtual void setValue(int v) override { - _dialog->setValue(v); - } - -private: - - QPointer _dialog; -}; - -OVITO_END_INLINE_NAMESPACE -OVITO_END_INLINE_NAMESPACE -} // End of namespace - -#endif // __OVITO_PROGRESS_DIALOG_ADAPTER_H diff -Nru ovito-2.8.1+dfsg2/src/gui/utilities/concurrent/ProgressDialog.cpp ovito-2.9.0+dfsg1/src/gui/utilities/concurrent/ProgressDialog.cpp --- ovito-2.8.1+dfsg2/src/gui/utilities/concurrent/ProgressDialog.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/utilities/concurrent/ProgressDialog.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,133 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "ProgressDialog.h" + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) + +/****************************************************************************** +* Initializes the dialog window. +******************************************************************************/ +ProgressDialog::ProgressDialog(MainWindow* mainWindow, const QString& dialogTitle) : ProgressDialog(mainWindow, mainWindow->datasetContainer().taskManager(), dialogTitle) +{ +} + +/****************************************************************************** +* Initializes the dialog window. +******************************************************************************/ +ProgressDialog::ProgressDialog(QWidget* parent, TaskManager& taskManager, const QString& dialogTitle) : QDialog(parent), _taskManager(taskManager) +{ + setWindowModality(Qt::WindowModal); + setWindowTitle(dialogTitle); + + QVBoxLayout* layout = new QVBoxLayout(this); + layout->addStretch(1); + + QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel, this); + layout->addWidget(buttonBox); + + // Cancel all currently running tasks when user presses the cancel button. + connect(buttonBox, &QDialogButtonBox::rejected, &taskManager, &TaskManager::cancelAll); + + // Helper function that sets up the UI widgets in the dialog for a newly started task. + auto createUIForTask = [this, layout](PromiseWatcher* taskWatcher) { + QLabel* statusLabel = new QLabel(taskWatcher->progressText()); + statusLabel->setMaximumWidth(400); + QProgressBar* progressBar = new QProgressBar(); + progressBar->setMaximum(taskWatcher->progressMaximum()); + progressBar->setValue(taskWatcher->progressValue()); + if(statusLabel->text().isEmpty()) { + statusLabel->hide(); + progressBar->hide(); + } + layout->insertWidget(layout->count() - 2, statusLabel); + layout->insertWidget(layout->count() - 2, progressBar); + connect(taskWatcher, &PromiseWatcher::progressRangeChanged, progressBar, &QProgressBar::setMaximum); + connect(taskWatcher, &PromiseWatcher::progressValueChanged, progressBar, &QProgressBar::setValue); + connect(taskWatcher, &PromiseWatcher::progressTextChanged, statusLabel, &QLabel::setText); + connect(taskWatcher, &PromiseWatcher::progressTextChanged, statusLabel, [statusLabel, progressBar](const QString& text) { + statusLabel->setVisible(!text.isEmpty()); + progressBar->setVisible(!text.isEmpty()); + }); + + // Remove progress display when this task finished. + connect(taskWatcher, &PromiseWatcher::finished, progressBar, &QObject::deleteLater); + connect(taskWatcher, &PromiseWatcher::finished, statusLabel, &QObject::deleteLater); + }; + + // Create UI for every running task. + for(PromiseWatcher* watcher : taskManager.runningTasks()) { + createUIForTask(watcher); + } + + // Create a separate progress bar for every new active task. + connect(&taskManager, &TaskManager::taskStarted, this, createUIForTask); + + // Show the dialog with a short delay. + // This prevents the dialog from showing up for short tasks that terminate very quickly. + QTimer::singleShot(100, this, &QDialog::show); + + // Activate local event handling to keep the dialog responsive. + taskManager.startLocalEventHandling(); +} + +/****************************************************************************** +* Destructor +******************************************************************************/ +ProgressDialog::~ProgressDialog() +{ + _taskManager.stopLocalEventHandling(); +} + +/****************************************************************************** +* Is called whenever one of the tasks was canceled. +******************************************************************************/ +void ProgressDialog::onTaskCanceled() +{ + // Cancel all tasks when one of the active tasks has been canceled. + taskManager().cancelAll(); +} + +/****************************************************************************** +* Is called when the user tries to close the dialog. +******************************************************************************/ +void ProgressDialog::closeEvent(QCloseEvent* event) +{ + taskManager().cancelAll(); + if(event->spontaneous()) + event->ignore(); + QDialog::closeEvent(event); +} + +/****************************************************************************** +* Is called when the user tries to close the dialog. +******************************************************************************/ +void ProgressDialog::reject() +{ + taskManager().cancelAll(); +} + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/gui/utilities/concurrent/ProgressDialog.h ovito-2.9.0+dfsg1/src/gui/utilities/concurrent/ProgressDialog.h --- ovito-2.8.1+dfsg2/src/gui/utilities/concurrent/ProgressDialog.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/utilities/concurrent/ProgressDialog.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,69 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Concurrency) + +class OVITO_GUI_EXPORT ProgressDialog : public QDialog +{ +public: + + /// Constructor. + ProgressDialog(MainWindow* mainWindow, const QString& dialogTitle = QString()); + + /// Constructor. + ProgressDialog(QWidget* parent, TaskManager& taskManager, const QString& dialogTitle = QString()); + + /// ~Destructor. + ~ProgressDialog(); + + /// Returns the TaskManager that manages the running task displayed in this progress dialog. + TaskManager& taskManager() { return _taskManager; } + +protected: + + /// Is called when the user tries to close the dialog. + virtual void closeEvent(QCloseEvent* event) override; + + /// Is called when the user tries to close the dialog. + virtual void reject() override; + +private Q_SLOTS: + + /// Is called whenever one of the tasks was canceled. + void onTaskCanceled(); + +private: + + /// The task manager. + TaskManager& _taskManager; +}; + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/gui/utilities/io/GuiFileManager.cpp ovito-2.9.0+dfsg1/src/gui/utilities/io/GuiFileManager.cpp --- ovito-2.8.1+dfsg2/src/gui/utilities/io/GuiFileManager.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/utilities/io/GuiFileManager.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -31,7 +31,7 @@ ******************************************************************************/ bool GuiFileManager::askUserForCredentials(QUrl& url) { - if(Application::instance().guiMode()) { + if(Application::instance()->guiMode()) { // Ask for new username/password. RemoteAuthenticationDialog dialog(nullptr, tr("Remote authentication"), diff -Nru ovito-2.8.1+dfsg2/src/gui/utilities/io/GuiFileManager.h ovito-2.9.0+dfsg1/src/gui/utilities/io/GuiFileManager.h --- ovito-2.8.1+dfsg2/src/gui/utilities/io/GuiFileManager.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/utilities/io/GuiFileManager.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_GUI_FILE_MANAGER_H -#define __OVITO_GUI_FILE_MANAGER_H +#pragma once + #include #include @@ -39,17 +39,10 @@ /// \brief Shows a dialog which asks the user for the login credentials. /// \return True on success, false if user has canceled the operation. virtual bool askUserForCredentials(QUrl& url) override; - -protected: - - /// This is a singleton class. No public instances allowed. - GuiFileManager() : FileManager() {} - - friend class GuiApplication; }; OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_GUI_FILE_MANAGER_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/input/NavigationModes.cpp ovito-2.9.0+dfsg1/src/gui/viewport/input/NavigationModes.cpp --- ovito-2.8.1+dfsg2/src/gui/viewport/input/NavigationModes.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/input/NavigationModes.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -101,19 +101,26 @@ } /****************************************************************************** +* Is called when a viewport looses the input focus. +******************************************************************************/ +void NavigationMode::focusOutEvent(ViewportWindow* vpwin, QFocusEvent* event) +{ + if(_viewport) { + if(_temporaryActivation) + inputManager()->removeInputMode(this); + } +} + +/****************************************************************************** * Handles the mouse move event for the given viewport. ******************************************************************************/ void NavigationMode::mouseMoveEvent(ViewportWindow* vpwin, QMouseEvent* event) { if(_viewport == vpwin->viewport()) { -#if 1 // Take the current mouse cursor position to make the navigation mode // look more responsive. The cursor position recorded at the time the mouse event was // generates may already be too old. - QPointF pos = vpwin->widget()->mapFromGlobal(QCursor::pos()); -#else - QPointF pos = event->localPos(); -#endif + QPointF pos = vpwin->mapFromGlobal(QCursor::pos()); _viewport->dataset()->undoStack().resetCurrentCompoundOperation(); modifyView(vpwin, _viewport, pos - _startPoint); diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/input/NavigationModes.h ovito-2.9.0+dfsg1/src/gui/viewport/input/NavigationModes.h --- ovito-2.8.1+dfsg2/src/gui/viewport/input/NavigationModes.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/input/NavigationModes.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_NAVIGATION_MODES_H -#define __OVITO_NAVIGATION_MODES_H +#pragma once + #include #include @@ -49,6 +49,9 @@ /// \brief Handles the mouse move event for the given viewport. virtual void mouseMoveEvent(ViewportWindow* vpwin, QMouseEvent* event) override; + /// Is called when a viewport looses the input focus. + virtual void focusOutEvent(ViewportWindow* vpwin, QFocusEvent* event) override; + /// \brief Lets the input mode render its overlay content in a viewport. virtual void renderOverlay3D(Viewport* vp, ViewportSceneRenderer* renderer) override; @@ -246,4 +249,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_NAVIGATION_MODES_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/input/ViewportInputManager.h ovito-2.9.0+dfsg1/src/gui/viewport/input/ViewportInputManager.h --- ovito-2.8.1+dfsg2/src/gui/viewport/input/ViewportInputManager.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/input/ViewportInputManager.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VIEWPORT_INPUT_MANAGER_H -#define __OVITO_VIEWPORT_INPUT_MANAGER_H +#pragma once + #include #include "ViewportInputMode.h" @@ -140,4 +140,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_VIEWPORT_INPUT_MANAGER_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/input/ViewportInputMode.cpp ovito-2.9.0+dfsg1/src/gui/viewport/input/ViewportInputMode.cpp --- ovito-2.8.1+dfsg2/src/gui/viewport/input/ViewportInputMode.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/input/ViewportInputMode.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -159,6 +159,14 @@ } /****************************************************************************** +* Handles the mouse up event for the given viewport. +******************************************************************************/ +void ViewportInputMode::focusOutEvent(ViewportWindow* vpwin, QFocusEvent* event) +{ + _lastMousePressEvent.reset(); +} + +/****************************************************************************** * Lets the input mode render its overlay content in a viewport. ******************************************************************************/ void ViewportInputMode::renderOverlay3D(Viewport* vp, ViewportSceneRenderer* renderer) diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/input/ViewportInputMode.h ovito-2.9.0+dfsg1/src/gui/viewport/input/ViewportInputMode.h --- ovito-2.8.1+dfsg2/src/gui/viewport/input/ViewportInputMode.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/input/ViewportInputMode.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VIEWPORT_INPUT_MODE_H -#define __OVITO_VIEWPORT_INPUT_MODE_H +#pragma once + #include @@ -107,6 +107,11 @@ /// \param event The mouse event. virtual void mouseDoubleClickEvent(ViewportWindow* vpwin, QMouseEvent* event); + /// \brief Is called when a viewport looses the input focus. + /// \param vpwin The viewport window. + /// \param event The focus event. + virtual void focusOutEvent(ViewportWindow* vpwin, QFocusEvent* event); + /// \brief Return the mouse cursor shown in the viewport windows /// while this input handler is active. const QCursor& cursor() { return _cursor; } @@ -198,4 +203,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_VIEWPORT_INPUT_MODE_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/input/XFormModes.cpp ovito-2.9.0+dfsg1/src/gui/viewport/input/XFormModes.cpp --- ovito-2.8.1+dfsg2/src/gui/viewport/input/XFormModes.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/input/XFormModes.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -228,14 +228,10 @@ void XFormMode::mouseMoveEvent(ViewportWindow* vpwin, QMouseEvent* event) { if(_viewport == vpwin->viewport()) { -#if 1 // Take the current mouse cursor position to make the input mode // look more responsive. The cursor position recorded when the mouse event was // generates may be too old. - _currentPoint = vpwin->widget()->mapFromGlobal(QCursor::pos()); -#else - _currentPoint = event->localPos(); -#endif + _currentPoint = vpwin->mapFromGlobal(QCursor::pos()); _viewport->dataset()->undoStack().resetCurrentCompoundOperation(); doXForm(); @@ -252,6 +248,19 @@ } /****************************************************************************** +* Is called when a viewport looses the input focus. +******************************************************************************/ +void XFormMode::focusOutEvent(ViewportWindow* vpwin, QFocusEvent* event) +{ + if(_viewport) { + // Restore old state if change has not been committed. + _viewport->dataset()->undoStack().endCompoundOperation(false); + _viewport->dataset()->undoStack().endCompoundOperation(false); + _viewport = nullptr; + } +} + +/****************************************************************************** * Returns the origin of the transformation system to use for xform modes. ******************************************************************************/ Point3 XFormMode::transformationCenter() @@ -376,7 +385,7 @@ if(prs_ctrl) { KeyframeController* ctrl = dynamic_object_cast(prs_ctrl->positionController()); if(ctrl) { - AnimationKeyEditorDialog dlg(ctrl, &PROPERTY_FIELD(PRSTransformationController::_position), inputManager()->mainWindow(), inputManager()->mainWindow()); + AnimationKeyEditorDialog dlg(ctrl, &PROPERTY_FIELD(PRSTransformationController::positionController), inputManager()->mainWindow(), inputManager()->mainWindow()); dlg.exec(); } } @@ -497,7 +506,7 @@ if(prs_ctrl) { KeyframeController* ctrl = dynamic_object_cast(prs_ctrl->rotationController()); if(ctrl) { - AnimationKeyEditorDialog dlg(ctrl, &PROPERTY_FIELD(PRSTransformationController::_rotation), inputManager()->mainWindow(), inputManager()->mainWindow()); + AnimationKeyEditorDialog dlg(ctrl, &PROPERTY_FIELD(PRSTransformationController::rotationController), inputManager()->mainWindow(), inputManager()->mainWindow()); dlg.exec(); } } diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/input/XFormModes.h ovito-2.9.0+dfsg1/src/gui/viewport/input/XFormModes.h --- ovito-2.8.1+dfsg2/src/gui/viewport/input/XFormModes.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/input/XFormModes.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_XFORM_VIEWPORT_MODES_H -#define __OVITO_XFORM_VIEWPORT_MODES_H +#pragma once + #include #include @@ -98,6 +98,9 @@ /// \brief Handles the mouse move event for the given viewport. virtual void mouseMoveEvent(ViewportWindow* vpwin, QMouseEvent* event) override; + /// Is called when a viewport looses the input focus. + virtual void focusOutEvent(ViewportWindow* vpwin, QFocusEvent* event) override; + /// \brief Returns the origin of the transformation system to use for xform modes. Point3 transformationCenter(); @@ -274,4 +277,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_XFORM_VIEWPORT_MODES_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/overlay/CoordinateTripodOverlayEditor.cpp ovito-2.9.0+dfsg1/src/gui/viewport/overlay/CoordinateTripodOverlayEditor.cpp --- ovito-2.8.1+dfsg2/src/gui/viewport/overlay/CoordinateTripodOverlayEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/overlay/CoordinateTripodOverlayEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -34,7 +34,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(View) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(Gui, CoordinateTripodOverlayEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(CoordinateTripodOverlayEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(CoordinateTripodOverlay, CoordinateTripodOverlayEditor); /****************************************************************************** @@ -51,7 +51,7 @@ layout->setSpacing(4); layout->setColumnStretch(1, 1); - VariantComboBoxParameterUI* alignmentPUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_alignment)); + VariantComboBoxParameterUI* alignmentPUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::alignment)); layout->addWidget(new QLabel(tr("Position:")), 0, 0); layout->addWidget(alignmentPUI->comboBox(), 0, 1); alignmentPUI->comboBox()->addItem(tr("Top left"), QVariant::fromValue((int)(Qt::AlignTop | Qt::AlignLeft))); @@ -59,11 +59,11 @@ alignmentPUI->comboBox()->addItem(tr("Bottom left"), QVariant::fromValue((int)(Qt::AlignBottom | Qt::AlignLeft))); alignmentPUI->comboBox()->addItem(tr("Bottom right"), QVariant::fromValue((int)(Qt::AlignBottom | Qt::AlignRight))); - FloatParameterUI* offsetXPUI = new FloatParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_offsetX)); + FloatParameterUI* offsetXPUI = new FloatParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::offsetX)); layout->addWidget(offsetXPUI->label(), 1, 0); layout->addLayout(offsetXPUI->createFieldLayout(), 1, 1); - FloatParameterUI* offsetYPUI = new FloatParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_offsetY)); + FloatParameterUI* offsetYPUI = new FloatParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::offsetY)); layout->addWidget(offsetYPUI->label(), 2, 0); layout->addLayout(offsetYPUI->createFieldLayout(), 2, 1); @@ -71,19 +71,19 @@ ViewportModeAction* moveOverlayAction = new ViewportModeAction(mainWindow(), tr("Move using mouse"), this, moveOverlayMode); layout->addWidget(moveOverlayAction->createPushButton(), 3, 1); - FloatParameterUI* sizePUI = new FloatParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_tripodSize)); + FloatParameterUI* sizePUI = new FloatParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::tripodSize)); layout->addWidget(sizePUI->label(), 4, 0); layout->addLayout(sizePUI->createFieldLayout(), 4, 1); - FloatParameterUI* lineWidthPUI = new FloatParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_lineWidth)); + FloatParameterUI* lineWidthPUI = new FloatParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::lineWidth)); layout->addWidget(lineWidthPUI->label(), 5, 0); layout->addLayout(lineWidthPUI->createFieldLayout(), 5, 1); - FloatParameterUI* fontSizePUI = new FloatParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_fontSize)); + FloatParameterUI* fontSizePUI = new FloatParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::fontSize)); layout->addWidget(fontSizePUI->label(), 6, 0); layout->addLayout(fontSizePUI->createFieldLayout(), 6, 1); - FontParameterUI* labelFontPUI = new FontParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_font)); + FontParameterUI* labelFontPUI = new FontParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::font)); layout->addWidget(labelFontPUI->label(), 7, 0); layout->addWidget(labelFontPUI->fontPicker(), 7, 1); @@ -103,7 +103,7 @@ BooleanGroupBoxParameterUI* axisPUI; // Axis 1. - axisPUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis1Enabled)); + axisPUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis1Enabled)); axisPUI->groupBox()->setTitle("Axis 1"); layout->addWidget(axisPUI->groupBox(), row++, 0, 1, 2); sublayout = new QGridLayout(axisPUI->childContainer()); @@ -111,24 +111,24 @@ sublayout->setSpacing(2); // Axis label. - axisLabelPUI = new StringParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis1Label)); + axisLabelPUI = new StringParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis1Label)); sublayout->addWidget(new QLabel(tr("Label:")), 0, 0); sublayout->addWidget(axisLabelPUI->textBox(), 0, 1, 1, 2); // Axis color. - axisColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis1Color)); + axisColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis1Color)); sublayout->addWidget(new QLabel(tr("Color:")), 1, 0); sublayout->addWidget(axisColorPUI->colorPicker(), 1, 1, 1, 2); // Axis direction. sublayout->addWidget(new QLabel(tr("Direction:")), 2, 0, 1, 3); for(int dim = 0; dim < 3; dim++) { - Vector3ParameterUI* axisDirPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis1Dir), dim); + Vector3ParameterUI* axisDirPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis1Dir), dim); sublayout->addLayout(axisDirPUI->createFieldLayout(), 3, dim, 1, 1); } // Axis 2 - axisPUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis2Enabled)); + axisPUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis2Enabled)); axisPUI->groupBox()->setTitle("Axis 2"); layout->addWidget(axisPUI->groupBox(), row++, 0, 1, 2); sublayout = new QGridLayout(axisPUI->childContainer()); @@ -136,24 +136,24 @@ sublayout->setSpacing(2); // Axis label. - axisLabelPUI = new StringParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis2Label)); + axisLabelPUI = new StringParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis2Label)); sublayout->addWidget(new QLabel(tr("Label:")), 0, 0); sublayout->addWidget(axisLabelPUI->textBox(), 0, 1, 1, 2); // Axis color. - axisColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis2Color)); + axisColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis2Color)); sublayout->addWidget(new QLabel(tr("Color:")), 1, 0); sublayout->addWidget(axisColorPUI->colorPicker(), 1, 1, 1, 2); // Axis direction. sublayout->addWidget(new QLabel(tr("Direction:")), 2, 0, 1, 3); for(int dim = 0; dim < 3; dim++) { - Vector3ParameterUI* axisDirPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis2Dir), dim); + Vector3ParameterUI* axisDirPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis2Dir), dim); sublayout->addLayout(axisDirPUI->createFieldLayout(), 3, dim, 1, 1); } // Axis 3. - axisPUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis3Enabled)); + axisPUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis3Enabled)); axisPUI->groupBox()->setTitle("Axis 3"); layout->addWidget(axisPUI->groupBox(), row++, 0, 1, 2); sublayout = new QGridLayout(axisPUI->childContainer()); @@ -161,24 +161,24 @@ sublayout->setSpacing(2); // Axis label. - axisLabelPUI = new StringParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis3Label)); + axisLabelPUI = new StringParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis3Label)); sublayout->addWidget(new QLabel(tr("Label:")), 0, 0); sublayout->addWidget(axisLabelPUI->textBox(), 0, 1, 1, 2); // Axis color. - axisColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis3Color)); + axisColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis3Color)); sublayout->addWidget(new QLabel(tr("Color:")), 1, 0); sublayout->addWidget(axisColorPUI->colorPicker(), 1, 1, 1, 2); // Axis direction. sublayout->addWidget(new QLabel(tr("Direction:")), 2, 0, 1, 3); for(int dim = 0; dim < 3; dim++) { - Vector3ParameterUI* axisDirPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis3Dir), dim); + Vector3ParameterUI* axisDirPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis3Dir), dim); sublayout->addLayout(axisDirPUI->createFieldLayout(), 3, dim, 1, 1); } // Axis 4. - axisPUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis4Enabled)); + axisPUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis4Enabled)); axisPUI->groupBox()->setTitle("Axis 4"); layout->addWidget(axisPUI->groupBox(), row++, 0, 1, 2); sublayout = new QGridLayout(axisPUI->childContainer()); @@ -186,19 +186,19 @@ sublayout->setSpacing(2); // Axis label. - axisLabelPUI = new StringParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis4Label)); + axisLabelPUI = new StringParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis4Label)); sublayout->addWidget(new QLabel(tr("Label:")), 0, 0); sublayout->addWidget(axisLabelPUI->textBox(), 0, 1, 1, 2); // Axis color. - axisColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis4Color)); + axisColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis4Color)); sublayout->addWidget(new QLabel(tr("Color:")), 1, 0); sublayout->addWidget(axisColorPUI->colorPicker(), 1, 1, 1, 2); // Axis direction. sublayout->addWidget(new QLabel(tr("Direction:")), 2, 0, 1, 3); for(int dim = 0; dim < 3; dim++) { - Vector3ParameterUI* axisDirPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis4Dir), dim); + Vector3ParameterUI* axisDirPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::axis4Dir), dim); sublayout->addLayout(axisDirPUI->createFieldLayout(), 3, dim, 1, 1); } } diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/overlay/CoordinateTripodOverlayEditor.h ovito-2.9.0+dfsg1/src/gui/viewport/overlay/CoordinateTripodOverlayEditor.h --- ovito-2.8.1+dfsg2/src/gui/viewport/overlay/CoordinateTripodOverlayEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/overlay/CoordinateTripodOverlayEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COORDINATE_TRIPOD_OVERLAY_EDITOR_H -#define __OVITO_COORDINATE_TRIPOD_OVERLAY_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_COORDINATE_TRIPOD_OVERLAY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/overlay/MoveOverlayInputMode.cpp ovito-2.9.0+dfsg1/src/gui/viewport/overlay/MoveOverlayInputMode.cpp --- ovito-2.8.1+dfsg2/src/gui/viewport/overlay/MoveOverlayInputMode.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/overlay/MoveOverlayInputMode.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -96,7 +96,7 @@ // Take the current mouse cursor position to make the input mode // look more responsive. The cursor position recorded when the mouse event was // generates may be too old. - _currentPoint = vpwin->widget()->mapFromGlobal(QCursor::pos()); + _currentPoint = vpwin->mapFromGlobal(QCursor::pos()); // Reset the overlay's position first before moving it again below. viewport()->dataset()->undoStack().resetCurrentCompoundOperation(); @@ -114,7 +114,7 @@ } catch(const Exception& ex) { inputManager()->removeInputMode(this); - ex.showError(); + ex.reportError(); } // Force immediate viewport repaints. diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/overlay/MoveOverlayInputMode.h ovito-2.9.0+dfsg1/src/gui/viewport/overlay/MoveOverlayInputMode.h --- ovito-2.8.1+dfsg2/src/gui/viewport/overlay/MoveOverlayInputMode.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/overlay/MoveOverlayInputMode.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_MOVE_OVERLAY_INPUT_MODE_H -#define __OVITO_MOVE_OVERLAY_INPUT_MODE_H +#pragma once + #include #include @@ -80,4 +80,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_MOVE_OVERLAY_INPUT_MODE_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/overlay/TextLabelOverlayEditor.cpp ovito-2.9.0+dfsg1/src/gui/viewport/overlay/TextLabelOverlayEditor.cpp --- ovito-2.8.1+dfsg2/src/gui/viewport/overlay/TextLabelOverlayEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/overlay/TextLabelOverlayEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -38,7 +38,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(View) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(Gui, TextLabelOverlayEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(TextLabelOverlayEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(TextLabelOverlay, TextLabelOverlayEditor); /****************************************************************************** @@ -108,13 +108,13 @@ layout->addWidget(sourcePUI->widget(), 0, 1, 1, 2); // Label text. - StringParameterUI* labelTextPUI = new StringParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::_labelText)); + StringParameterUI* labelTextPUI = new StringParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::labelText)); layout->addWidget(new QLabel(tr("Text:")), 1, 0); _textEdit = new AutocompleteTextEdit(); labelTextPUI->setTextBox(_textEdit); layout->addWidget(labelTextPUI->textBox(), 1, 1, 1, 2); - VariantComboBoxParameterUI* alignmentPUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::_alignment)); + VariantComboBoxParameterUI* alignmentPUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::alignment)); layout->addWidget(new QLabel(tr("Position:")), 2, 0); layout->addWidget(alignmentPUI->comboBox(), 2, 1); alignmentPUI->comboBox()->addItem(tr("Top"), QVariant::fromValue((int)(Qt::AlignTop | Qt::AlignHCenter))); @@ -126,11 +126,11 @@ alignmentPUI->comboBox()->addItem(tr("Left"), QVariant::fromValue((int)(Qt::AlignVCenter | Qt::AlignLeft))); alignmentPUI->comboBox()->addItem(tr("Right"), QVariant::fromValue((int)(Qt::AlignVCenter | Qt::AlignRight))); - FloatParameterUI* offsetXPUI = new FloatParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::_offsetX)); + FloatParameterUI* offsetXPUI = new FloatParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::offsetX)); layout->addWidget(offsetXPUI->label(), 3, 0); layout->addLayout(offsetXPUI->createFieldLayout(), 3, 1, 1, 2); - FloatParameterUI* offsetYPUI = new FloatParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::_offsetY)); + FloatParameterUI* offsetYPUI = new FloatParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::offsetY)); layout->addWidget(offsetYPUI->label(), 4, 0); layout->addLayout(offsetYPUI->createFieldLayout(), 4, 1, 1, 2); @@ -138,21 +138,21 @@ ViewportModeAction* moveOverlayAction = new ViewportModeAction(mainWindow(), tr("Move using mouse"), this, moveOverlayMode); layout->addWidget(moveOverlayAction->createPushButton(), 5, 1, 1, 2); - FloatParameterUI* fontSizePUI = new FloatParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::_fontSize)); + FloatParameterUI* fontSizePUI = new FloatParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::fontSize)); layout->addWidget(new QLabel(tr("Text size/color:")), 6, 0); layout->addLayout(fontSizePUI->createFieldLayout(), 6, 1); // Text color. - ColorParameterUI* textColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::_textColor)); + ColorParameterUI* textColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::textColor)); layout->addWidget(textColorPUI->colorPicker(), 6, 2); - BooleanParameterUI* outlineEnabledPUI = new BooleanParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::_outlineEnabled)); + BooleanParameterUI* outlineEnabledPUI = new BooleanParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::outlineEnabled)); layout->addWidget(outlineEnabledPUI->checkBox(), 7, 1); - ColorParameterUI* outlineColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::_outlineColor)); + ColorParameterUI* outlineColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::outlineColor)); layout->addWidget(outlineColorPUI->colorPicker(), 7, 2); - FontParameterUI* labelFontPUI = new FontParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::_font)); + FontParameterUI* labelFontPUI = new FontParameterUI(this, PROPERTY_FIELD(TextLabelOverlay::font)); layout->addWidget(labelFontPUI->label(), 8, 0); layout->addWidget(labelFontPUI->fontPicker(), 8, 1, 1, 2); @@ -190,7 +190,7 @@ QString str; QStringList variableNames; if(ObjectNode* node = overlay->sourceNode()) { - const PipelineFlowState& flowState = node->evalPipeline(node->dataset()->animationSettings()->time()); + const PipelineFlowState& flowState = node->evaluatePipelineImmediately(PipelineEvalRequest(node->dataset()->animationSettings()->time(), false)); str.append(tr("

Dynamic variables that can be referenced in the label text:

    ")); for(const QString& attrName : flowState.attributes().keys()) { str.append(QStringLiteral("
  • [%1]
  • ").arg(attrName.toHtmlEscaped())); diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/overlay/TextLabelOverlayEditor.h ovito-2.9.0+dfsg1/src/gui/viewport/overlay/TextLabelOverlayEditor.h --- ovito-2.8.1+dfsg2/src/gui/viewport/overlay/TextLabelOverlayEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/overlay/TextLabelOverlayEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TEXT_LABEL_OVERLAY_EDITOR_H -#define __OVITO_TEXT_LABEL_OVERLAY_EDITOR_H +#pragma once + #include #include @@ -63,4 +63,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_TEXT_LABEL_OVERLAY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/picking/PickingSceneRenderer.cpp ovito-2.9.0+dfsg1/src/gui/viewport/picking/PickingSceneRenderer.cpp --- ovito-2.8.1+dfsg2/src/gui/viewport/picking/PickingSceneRenderer.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/picking/PickingSceneRenderer.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(View) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(Gui, PickingSceneRenderer, ViewportSceneRenderer); +IMPLEMENT_OVITO_OBJECT(PickingSceneRenderer, ViewportSceneRenderer); /****************************************************************************** * This method is called just before renderFrame() is called. @@ -38,8 +38,8 @@ ViewportWindow* vpWindow = static_cast(vp->window()); if(!vpWindow) throwException(tr("Viewport window has not been created.")); - if(!vpWindow->isExposed()) - throwException(tr("Viewport window is not exposed.")); + if(!vpWindow->isVisible()) + throwException(tr("Viewport window is not visible.")); // Get OpenGL context. QOpenGLContext* context = vpWindow->context(); @@ -52,11 +52,7 @@ _oldSurface = _oldContext ? _oldContext->surface() : nullptr; // Make GL context current. -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - if(!context->makeCurrent(vpWindow)) -#else if(!context->makeCurrent(vpWindow->window()->windowHandle())) -#endif throwException(tr("Failed to make OpenGL context current.")); // Create OpenGL framebuffer. @@ -66,11 +62,7 @@ _framebufferObject.reset(new QOpenGLFramebufferObject(size.width(), size.height(), framebufferFormat)); // Clear OpenGL error state. -#if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0) while(context->functions()->glGetError() != GL_NO_ERROR); -#else - while(::glGetError() != GL_NO_ERROR); -#endif if(!_framebufferObject->isValid()) throwException(tr("Failed to create OpenGL framebuffer object for offscreen rendering.")); @@ -88,13 +80,13 @@ /****************************************************************************** * Renders the current animation frame. ******************************************************************************/ -bool PickingSceneRenderer::renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, AbstractProgressDisplay* progress) +bool PickingSceneRenderer::renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, TaskManager& taskManager) { // Clear previous object records. reset(); // Let the base class do the main rendering work. - if(!ViewportSceneRenderer::renderFrame(frameBuffer, stereoTask, progress)) + if(!ViewportSceneRenderer::renderFrame(frameBuffer, stereoTask, taskManager)) return false; // Clear OpenGL error state, so we start fresh for the glReadPixels() call below. @@ -142,11 +134,11 @@ /****************************************************************************** * This method is called after renderFrame() has been called. ******************************************************************************/ -void PickingSceneRenderer::endFrame() +void PickingSceneRenderer::endFrame(bool renderSuccessful) { endPickObject(); _framebufferObject.reset(); - ViewportSceneRenderer::endFrame(); + ViewportSceneRenderer::endFrame(renderSuccessful); // Reactivate old GL context. if(_oldSurface && _oldContext) diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/picking/PickingSceneRenderer.h ovito-2.9.0+dfsg1/src/gui/viewport/picking/PickingSceneRenderer.h --- ovito-2.8.1+dfsg2/src/gui/viewport/picking/PickingSceneRenderer.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/picking/PickingSceneRenderer.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PICKING_SCENE_RENDERER_H -#define __OVITO_PICKING_SCENE_RENDERER_H +#pragma once + #include #include @@ -51,10 +51,10 @@ virtual void beginFrame(TimePoint time, const ViewProjectionParameters& params, Viewport* vp) override; /// Renders the current animation frame. - virtual bool renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, AbstractProgressDisplay* progress) override; + virtual bool renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, TaskManager& taskManager) override; /// This method is called after renderFrame() has been called. - virtual void endFrame() override; + virtual void endFrame(bool renderSuccessful) override; /// When picking mode is active, this registers an object being rendered. virtual quint32 beginPickObject(ObjectNode* objNode, ObjectPickInfo* pickInfo = nullptr) override; @@ -117,4 +117,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_PICKING_SCENE_RENDERER_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/ViewportMenu.cpp ovito-2.9.0+dfsg1/src/gui/viewport/ViewportMenu.cpp --- ovito-2.8.1+dfsg2/src/gui/viewport/ViewportMenu.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/ViewportMenu.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -35,7 +35,7 @@ /****************************************************************************** * Initializes the menu. ******************************************************************************/ -ViewportMenu::ViewportMenu(ViewportWindow* vpWindow) : QMenu(vpWindow->widget()), _viewport(vpWindow->viewport()), _vpWindow(vpWindow) +ViewportMenu::ViewportMenu(ViewportWindow* vpWindow) : QMenu(vpWindow), _viewport(vpWindow->viewport()), _vpWindow(vpWindow) { QAction* action; @@ -94,10 +94,6 @@ addSeparator(); addAction(tr("Adjust View..."), this, SLOT(onAdjustView()))->setEnabled(_viewport->viewType() != Viewport::VIEW_SCENENODE); - -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) && defined(Q_OS_MACX) - connect(static_cast(QGuiApplication::instance()), &QGuiApplication::focusWindowChanged, this, &ViewportMenu::onWindowFocusChanged); -#endif } /****************************************************************************** @@ -109,7 +105,7 @@ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); // Show context menu. - exec(_vpWindow->widget()->mapToGlobal(pos)); + exec(_vpWindow->mapToGlobal(pos)); } /****************************************************************************** @@ -122,11 +118,11 @@ // Find all camera nodes in the scene. _viewport->dataset()->sceneRoot()->visitObjectNodes([this, viewNodeGroup](ObjectNode* node) -> bool { - PipelineFlowState state = node->evalPipeline(_viewport->dataset()->animationSettings()->time()); + const PipelineFlowState& state = node->evaluatePipelineImmediately(PipelineEvalRequest(_viewport->dataset()->animationSettings()->time(), false)); OORef camera = state.convertObject(_viewport->dataset()->animationSettings()->time()); if(camera) { // Add a menu entry for this camera node. - QAction* action = viewNodeGroup->addAction(node->name()); + QAction* action = viewNodeGroup->addAction(node->nodeName()); action->setCheckable(true); action->setChecked(_viewport->viewNode() == node); action->setData(qVariantFromValue((void*)node)); @@ -183,7 +179,7 @@ ******************************************************************************/ void ViewportMenu::onAdjustView() { - AdjustCameraDialog dialog(_viewport, _vpWindow->widget()->window()); + AdjustCameraDialog dialog(_viewport, _vpWindow->window()); dialog.exec(); } @@ -227,7 +223,7 @@ cameraNode->setDataProvider(cameraObj); // Give the new node a name. - cameraNode->setName(scene->makeNameUnique(tr("Camera"))); + cameraNode->setNodeName(scene->makeNameUnique(tr("Camera"))); // Position camera node to match the current view. AffineTransformation tm = _viewport->projectionParams().inverseViewMatrix; diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/ViewportMenu.h ovito-2.9.0+dfsg1/src/gui/viewport/ViewportMenu.h --- ovito-2.8.1+dfsg2/src/gui/viewport/ViewportMenu.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/ViewportMenu.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,6 +19,7 @@ // /////////////////////////////////////////////////////////////////////////////// +#include #include #include "ViewportWindow.h" @@ -49,14 +50,6 @@ void onAdjustView(); void onViewNode(QAction* action); void onCreateCamera(); - -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - void onWindowFocusChanged() { - if(QGuiApplication::focusWindow() && QGuiApplication::focusWindow()->flags().testFlag(Qt::Popup) == false) { - hide(); - } - } -#endif private: diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/ViewportWindow.cpp ovito-2.9.0+dfsg1/src/gui/viewport/ViewportWindow.cpp --- ovito-2.8.1+dfsg2/src/gui/viewport/ViewportWindow.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/ViewportWindow.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -37,10 +37,7 @@ /****************************************************************************** * Constructor. ******************************************************************************/ -ViewportWindow::ViewportWindow(Viewport* owner, QWidget* parentWidget) : -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - QOpenGLWidget(parentWidget), -#endif +ViewportWindow::ViewportWindow(Viewport* owner, QWidget* parentWidget) : QOpenGLWidget(parentWidget), _viewport(owner), _updateRequested(false), _mainWindow(MainWindow::fromDataset(owner->dataset())), _renderDebugCounter(0), _cursorInContextMenuArea(false) @@ -48,41 +45,13 @@ // Associate the viewport with this window. owner->setWindow(this); -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - _updatePending = false; - - if(OpenGLSceneRenderer::contextSharingEnabled()) { - // Get the master OpenGL context, which is managed by the main window. - OVITO_CHECK_POINTER(_mainWindow); - _context = _mainWindow->getOpenGLContext(); - } - else { - // Create a dedicated OpenGL context for this viewport window. - // All contexts still share OpenGL resources. - _context = new QOpenGLContext(this); - _context->setFormat(ViewportSceneRenderer::getDefaultSurfaceFormat()); - _context->setShareContext(_mainWindow->getOpenGLContext()); - if(!_context->create()) - throw Exception(tr("Failed to create OpenGL context.")); - } - - // Indicate that the window is to be used for OpenGL rendering. - setSurfaceType(QWindow::OpenGLSurface); - setFormat(_context->format()); -#else setMouseTracking(true); -#endif + setFocusPolicy(Qt::ClickFocus); // Determine OpenGL vendor string so other parts of the code can decide // which OpenGL features are save to use. OpenGLSceneRenderer::determineOpenGLInfo(); -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - // Create a QWidget for this QWindow. - _widget = QWidget::createWindowContainer(this, parentWidget); - _widget->setAttribute(Qt::WA_DeleteOnClose); -#endif - // Create the viewport renderer. // It is shared by all viewports of a dataset. for(Viewport* vp : owner->dataset()->viewportConfig()->viewports()) { @@ -114,16 +83,7 @@ void ViewportWindow::renderLater() { _updateRequested = true; -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - // If not already done so, put an update request event on the event loop, - // which leads to renderNow() being called once the event gets processed. - if(!_updatePending) { - _updatePending = true; - QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateLater)); - } -#else update(); -#endif } /****************************************************************************** @@ -133,13 +93,9 @@ void ViewportWindow::processViewportUpdate() { if(_updateRequested) { -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - renderNow(); -#else OVITO_ASSERT_MSG(!_viewport->isRendering(), "ViewportWindow::processUpdateRequest()", "Recursive viewport repaint detected."); OVITO_ASSERT_MSG(!_viewport->dataset()->viewportConfig()->isRendering(), "ViewportWindow::processUpdateRequest()", "Recursive viewport repaint detected."); repaint(); -#endif } } @@ -148,10 +104,6 @@ ******************************************************************************/ void ViewportWindow::showViewportMenu(const QPoint& pos) { -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - requestActivate(); -#endif - // Create the context menu for the viewport. ViewportMenu contextMenu(this); @@ -204,9 +156,6 @@ ******************************************************************************/ bool ViewportWindow::setMouseGrabEnabled(bool grab) { -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - return QWindow::setMouseGrabEnabled(grab); -#else if(grab) { grabMouse(); return true; @@ -215,36 +164,6 @@ releaseMouse(); return false; } -#endif -} - -/****************************************************************************** -* Sets the cursor shape for this viewport window. -******************************************************************************/ -void ViewportWindow::setCursor(const QCursor& cursor) -{ - // Changing the cursor leads to program crash on MacOS and Qt <= 5.2.0. -#if !defined(Q_OS_MACX) || (QT_VERSION >= QT_VERSION_CHECK(5, 2, 1)) -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - QWindow::setCursor(cursor); -#else - QOpenGLWidget::setCursor(cursor); -#endif -#endif -} - -/****************************************************************************** -* Restores the default arrow cursor for this viewport window. -******************************************************************************/ -void ViewportWindow::unsetCursor() -{ -#if !defined(Q_OS_MACX) || (QT_VERSION >= QT_VERSION_CHECK(5, 2, 1)) -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - QWindow::unsetCursor(); -#else - QOpenGLWidget::unsetCursor(); -#endif -#endif } /****************************************************************************** @@ -349,7 +268,7 @@ ViewportPickResult ViewportWindow::pick(const QPointF& pos) { // Cannot perform picking while viewport is not visible or currently rendering or when updates are disabled. - if(isExposed() && !viewport()->isRendering() && !viewport()->dataset()->viewportConfig()->isSuspended()) { + if(isVisible() && !viewport()->isRendering() && !viewport()->dataset()->viewportConfig()->isSuspended()) { try { if(_pickingRenderer->isRefreshRequired()) { // Let the viewport do the actual rendering work. @@ -371,46 +290,12 @@ } } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } return {}; } -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - -/****************************************************************************** -* This internal method receives events to the viewport window. -******************************************************************************/ -bool ViewportWindow::event(QEvent* event) -{ - // Handle update request events posted by renderLater(). - if(event->type() == QEvent::UpdateLater) { - _updatePending = false; - processViewportUpdate(); - return true; - } - return QWindow::event(event); -} - -/****************************************************************************** -* Handles the expose events. -******************************************************************************/ -void ViewportWindow::exposeEvent(QExposeEvent*) -{ - renderNow(); -} - -/****************************************************************************** -* Handles the resize events. -******************************************************************************/ -void ViewportWindow::resizeEvent(QResizeEvent*) -{ - renderNow(); -} - -#else - /****************************************************************************** * Is called whenever the GL context needs to be initialized. ******************************************************************************/ @@ -437,8 +322,6 @@ update(); } -#endif - /****************************************************************************** * Handles double click events. ******************************************************************************/ @@ -506,9 +389,6 @@ if(_contextMenuArea.contains(event->pos()) && !_cursorInContextMenuArea) { _cursorInContextMenuArea = true; viewport()->updateViewport(); -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - startTimer(0); -#endif } else if(!_contextMenuArea.contains(event->pos()) && _cursorInContextMenuArea) { _cursorInContextMenuArea = false; @@ -544,38 +424,34 @@ } } -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - /****************************************************************************** -* Is called in periodic intervals. +* Is called when the mouse cursor leaves the widget. ******************************************************************************/ -void ViewportWindow::timerEvent(QTimerEvent* event) +void ViewportWindow::leaveEvent(QEvent* event) { - if(_contextMenuArea.contains(mapFromGlobal(QCursor::pos()))) - return; - if(_cursorInContextMenuArea) { _cursorInContextMenuArea = false; viewport()->updateViewport(); } - killTimer(event->timerId()); } -#else - /****************************************************************************** -* Is called when the mouse cursor leaves the widget. +* Is called when the widgets looses the input focus. ******************************************************************************/ -void ViewportWindow::leaveEvent(QEvent* event) +void ViewportWindow::focusOutEvent(QFocusEvent* event) { - if(_cursorInContextMenuArea) { - _cursorInContextMenuArea = false; - viewport()->updateViewport(); + ViewportInputMode* mode = _mainWindow->viewportInputManager()->activeMode(); + if(mode) { + try { + mode->focusOutEvent(this, event); + } + catch(const Exception& ex) { + qWarning() << "Uncaught exception in viewport event handler:"; + ex.logError(); + } } } -#endif - /****************************************************************************** * Renders custom GUI elements in the viewport on top of the scene. ******************************************************************************/ @@ -599,31 +475,12 @@ ******************************************************************************/ void ViewportWindow::renderNow() { -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - if(!isExposed()) - return; -#endif - _updateRequested = false; // Do not re-enter rendering function of the same viewport. if(!viewport() || viewport()->isRendering()) return; -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - // Before making our GL context current, remember the old context that - // is currently active so we can restore it when we are done. - // This is necessary, because multiple viewport repaint requests can be - // processed simultaneously. - QPointer oldContext = QOpenGLContext::currentContext(); - QSurface* oldSurface = oldContext ? oldContext->surface() : nullptr; - - if(!_context->makeCurrent(this)) { - qWarning() << "ViewportWindow::renderNow(): Failed to make OpenGL context current."; - return; - } -#endif - QSurfaceFormat format = context()->format(); // OpenGL in a VirtualBox machine Windows guest reports "2.1 Chromium 1.9" as version string, which is // not correctly parsed by Qt. We have to workaround this. @@ -657,8 +514,9 @@ ); QCoreApplication::removePostedEvents(nullptr, 0); if(_mainWindow) _mainWindow->close(); - ex.showError(); - QCoreApplication::instance()->quit(); + ex.reportError(true); + QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); + QCoreApplication::exit(); } return; } @@ -674,6 +532,7 @@ catch(Exception& ex) { if(ex.context() == nullptr) ex.setContext(viewport()->dataset()); ex.prependGeneralMessage(tr("An unexpected error occurred while rendering the viewport contents. The program will quit.")); + viewport()->dataset()->viewportConfig()->suspendViewportUpdates(); QString openGLReport; QTextStream stream(&openGLReport, QIODevice::WriteOnly | QIODevice::Text); @@ -690,22 +549,18 @@ stream << "Context sharing: " << OpenGLSceneRenderer::contextSharingEnabled() << endl; ex.appendDetailMessage(openGLReport); - viewport()->dataset()->viewportConfig()->suspendViewportUpdates(); QCoreApplication::removePostedEvents(nullptr, 0); - ex.showError(); - QCoreApplication::instance()->quit(); + if(_mainWindow) _mainWindow->close(); + ex.reportError(true); + QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); + QCoreApplication::exit(); } } else { // When viewport updates are disabled, just clear the frame buffer with the background color. Color backgroundColor = Viewport::viewportColor(ViewportSettings::COLOR_VIEWPORT_BKG); -#if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0) context()->functions()->glClearColor(backgroundColor.r(), backgroundColor.g(), backgroundColor.b(), 1); context()->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); -#else - ::glClearColor(backgroundColor.r(), backgroundColor.g(), backgroundColor.b(), 1); - ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); -#endif // Make sure viewport is refreshed once updates are enables again. _viewport->dataset()->viewportConfig()->updateViewports(); } @@ -715,21 +570,6 @@ if(viewport()->dataset()->viewportConfig()->isSuspended()) { _viewport->dataset()->viewportConfig()->updateViewports(); } - -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - context()->swapBuffers(this); -#endif - -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - // Restore old GL context. - if(oldSurface && oldContext) { - if(!oldContext->makeCurrent(oldSurface)) - qWarning() << "ViewportWindow::renderNow(): Failed to restore old OpenGL context."; - } - else { - _context->doneCurrent(); - } -#endif } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/gui/viewport/ViewportWindow.h ovito-2.9.0+dfsg1/src/gui/viewport/ViewportWindow.h --- ovito-2.8.1+dfsg2/src/gui/viewport/ViewportWindow.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/viewport/ViewportWindow.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VIEWPORT_WINDOW_H -#define __OVITO_VIEWPORT_WINDOW_H +#pragma once + #include #include @@ -54,11 +54,7 @@ /** * \brief The internal render window/widget used by the Viewport class. */ -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) -class OVITO_GUI_EXPORT ViewportWindow : public QWindow, public ViewportWindowInterface -#else class OVITO_GUI_EXPORT ViewportWindow : public QOpenGLWidget, public ViewportWindowInterface -#endif { public: @@ -106,36 +102,13 @@ /// Renders custom GUI elements in the viewport on top of the scene. virtual void renderGui() override; -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - - /// Returns the window's OpenGL context used for rendering. - QOpenGLContext* context() const { return _context; } - - /// Returns the QWidget that has been created for this QWindow. - QWidget* widget() { return _widget; } - -#else - - /// Mimic isExposed() function of QWindow. - bool isExposed() const { return isVisible(); } - - /// Returns this widget. - QWidget* widget() { return this; } - -#endif + /// Provides access to the OpenGL context used by the viewport window for rendering. + virtual QOpenGLContext* glcontext() override { return this->context(); } /// If the return value is true, the viewport window receives all mouse events until /// setMouseGrabEnabled(false) is called; other windows get no mouse events at all. bool setMouseGrabEnabled(bool grab); - /// Sets the cursor shape for this viewport window. - /// The mouse cursor will assume this shape when it is over this viewport window, - /// unless an override cursor is set. - void setCursor(const QCursor& cursor); - - /// Restores the default arrow cursor for this viewport window. - void unsetCursor(); - /// \brief Determines the object that is visible under the given mouse cursor position. ViewportPickResult pick(const QPointF& pos); @@ -145,19 +118,6 @@ protected: -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - /// Handles the expose events. - virtual void exposeEvent(QExposeEvent* event) override; - - /// Handles the resize events. - virtual void resizeEvent(QResizeEvent* event) override; - - /// Is called in periodic intervals. - virtual void timerEvent(QTimerEvent* event) override; - - /// This internal method receives events to the viewport window. - virtual bool event(QEvent* event) override; -#else /// Is called whenever the widget needs to be painted. virtual void paintGL() override; @@ -169,7 +129,6 @@ /// Is called when the viewport becomes visible. virtual void showEvent(QShowEvent* event) override; -#endif /// Handles double click events. virtual void mouseDoubleClickEvent(QMouseEvent* event) override; @@ -186,6 +145,9 @@ /// Handles mouse wheel events. virtual void wheelEvent(QWheelEvent* event) override; + /// Is called when the widgets looses the input focus. + virtual void focusOutEvent(QFocusEvent* event) override; + private: /// Renders the contents of the viewport window. @@ -209,17 +171,6 @@ /// A flag that indicates that a viewport update has been requested. bool _updateRequested; -#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) - /// A flag that indicates that an update request event has been put on the event queue. - bool _updatePending; - - /// The OpenGL context used for rendering. - QOpenGLContext* _context; - - /// The QWidget that has been created for this QWindow. - QWidget* _widget; -#endif - /// The zone in the upper left corner of the viewport where /// the context menu can be activated by the user. QRect _contextMenuArea; @@ -261,4 +212,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_VIEWPORT_WINDOW_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/animation/AnimationFramesToolButton.h ovito-2.9.0+dfsg1/src/gui/widgets/animation/AnimationFramesToolButton.h --- ovito-2.8.1+dfsg2/src/gui/widgets/animation/AnimationFramesToolButton.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/animation/AnimationFramesToolButton.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ANIMATION_FRAMES_TOOL_BUTTON_H -#define __OVITO_ANIMATION_FRAMES_TOOL_BUTTON_H +#pragma once + #include #include @@ -87,4 +87,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ANIMATION_FRAMES_TOOL_BUTTON_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/animation/AnimationTimeSlider.cpp ovito-2.9.0+dfsg1/src/gui/widgets/animation/AnimationTimeSlider.cpp --- ovito-2.8.1+dfsg2/src/gui/widgets/animation/AnimationTimeSlider.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/animation/AnimationTimeSlider.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -45,6 +45,7 @@ setFrameShape(QFrame::NoFrame); setAutoFillBackground(true); setMouseTracking(true); + setFocusPolicy(Qt::ClickFocus); connect(&mainWindow->datasetContainer(), &DataSetContainer::animationSettingsReplaced, this, &AnimationTimeSlider::onAnimationSettingsReplaced); } @@ -194,15 +195,26 @@ _dragPos = thumbRect.width() / 2; mouseMoveEvent(event); } + event->accept(); update(); } /****************************************************************************** +* Is called when the widgets looses the input focus. +******************************************************************************/ +void AnimationTimeSlider::focusOutEvent(QFocusEvent* event) +{ + _dragPos = -1; + QFrame::focusOutEvent(event); +} + +/****************************************************************************** * Handles mouse up events. ******************************************************************************/ void AnimationTimeSlider::mouseReleaseEvent(QMouseEvent* event) { _dragPos = -1; + event->accept(); update(); } @@ -211,6 +223,8 @@ ******************************************************************************/ void AnimationTimeSlider::mouseMoveEvent(QMouseEvent* event) { + event->accept(); + int newPos; int thumbSize = thumbWidth(); diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/animation/AnimationTimeSlider.h ovito-2.9.0+dfsg1/src/gui/widgets/animation/AnimationTimeSlider.h --- ovito-2.8.1+dfsg2/src/gui/widgets/animation/AnimationTimeSlider.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/animation/AnimationTimeSlider.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ANIMATION_TIME_SLIDER_H -#define __OVITO_ANIMATION_TIME_SLIDER_H +#pragma once + #include @@ -69,6 +69,9 @@ /// Handles mouse move events. virtual void mouseMoveEvent(QMouseEvent* event) override; + + /// Is called when the widgets looses the input focus. + virtual void focusOutEvent(QFocusEvent* event) override; /// Returns the recommended size of the widget. virtual QSize sizeHint() const override; @@ -114,4 +117,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ANIMATION_TIME_SLIDER_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/animation/AnimationTimeSpinner.h ovito-2.9.0+dfsg1/src/gui/widgets/animation/AnimationTimeSpinner.h --- ovito-2.8.1+dfsg2/src/gui/widgets/animation/AnimationTimeSpinner.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/animation/AnimationTimeSpinner.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ANIMATION_TIME_SPINNER_H -#define __OVITO_ANIMATION_TIME_SPINNER_H +#pragma once + #include #include @@ -69,4 +69,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ANIMATION_TIME_SPINNER_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/animation/AnimationTrackBar.cpp ovito-2.9.0+dfsg1/src/gui/widgets/animation/AnimationTrackBar.cpp --- ovito-2.8.1+dfsg2/src/gui/widgets/animation/AnimationTrackBar.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/animation/AnimationTrackBar.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -348,6 +348,7 @@ _dragStartPos = event->pos().x(); } _isDragging = false; + event->accept(); update(); } else if(event->button() == Qt::RightButton) { @@ -365,6 +366,7 @@ } showKeyContextMenu(event->pos(), clickedKeys); } + event->accept(); } } @@ -413,6 +415,7 @@ ctrl->moveKeys(_selectedKeys.targets(), timeDelta); } } + event->accept(); } } @@ -425,6 +428,7 @@ _isDragging = false; if(event->button() == Qt::LeftButton) _animSettings->dataset()->undoStack().endCompoundOperation(true); + event->accept(); } } diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/animation/AnimationTrackBar.h ovito-2.9.0+dfsg1/src/gui/widgets/animation/AnimationTrackBar.h --- ovito-2.8.1+dfsg2/src/gui/widgets/animation/AnimationTrackBar.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/animation/AnimationTrackBar.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ANIMATION_TRACK_BAR_H -#define __OVITO_ANIMATION_TRACK_BAR_H +#pragma once + #include #include @@ -149,4 +149,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ANIMATION_TRACK_BAR_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/display/CoordinateDisplayWidget.h ovito-2.9.0+dfsg1/src/gui/widgets/display/CoordinateDisplayWidget.h --- ovito-2.8.1+dfsg2/src/gui/widgets/display/CoordinateDisplayWidget.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/display/CoordinateDisplayWidget.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COORDINATE_DISPLAY_WIDGET_H -#define __OVITO_COORDINATE_DISPLAY_WIDGET_H +#pragma once + #include #include @@ -101,4 +101,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_COORDINATE_DISPLAY_WIDGET_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/display/StatusWidget.h ovito-2.9.0+dfsg1/src/gui/widgets/display/StatusWidget.h --- ovito-2.8.1+dfsg2/src/gui/widgets/display/StatusWidget.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/display/StatusWidget.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_STATUS_WIDGET_H -#define __OVITO_STATUS_WIDGET_H +#pragma once + #include #include @@ -77,4 +77,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_STATUS_WIDGET_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/general/AutocompleteLineEdit.h ovito-2.9.0+dfsg1/src/gui/widgets/general/AutocompleteLineEdit.h --- ovito-2.8.1+dfsg2/src/gui/widgets/general/AutocompleteLineEdit.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/general/AutocompleteLineEdit.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::AutocompleteLineEdit class. */ -#ifndef __OVITO_AUTOCOMPLETE_LINE_EDIT_H -#define __OVITO_AUTOCOMPLETE_LINE_EDIT_H +#pragma once + #include @@ -75,4 +75,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_AUTOCOMPLETE_LINE_EDIT_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/general/AutocompleteTextEdit.h ovito-2.9.0+dfsg1/src/gui/widgets/general/AutocompleteTextEdit.h --- ovito-2.8.1+dfsg2/src/gui/widgets/general/AutocompleteTextEdit.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/general/AutocompleteTextEdit.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_AUTOCOMPLETE_TEXT_EDIT_H -#define __OVITO_AUTOCOMPLETE_TEXT_EDIT_H +#pragma once + #include @@ -81,4 +81,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_AUTOCOMPLETE_TEXT_EDIT_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/general/ColorPickerWidget.h ovito-2.9.0+dfsg1/src/gui/widgets/general/ColorPickerWidget.h --- ovito-2.8.1+dfsg2/src/gui/widgets/general/ColorPickerWidget.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/general/ColorPickerWidget.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::ColorPickerWidget class. */ -#ifndef __OVITO_COLOR_PICKER_WIDGET_H -#define __OVITO_COLOR_PICKER_WIDGET_H +#pragma once + #include @@ -85,4 +85,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_COLOR_PICKER_WIDGET_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/general/ElidedTextLabel.h ovito-2.9.0+dfsg1/src/gui/widgets/general/ElidedTextLabel.h --- ovito-2.8.1+dfsg2/src/gui/widgets/general/ElidedTextLabel.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/general/ElidedTextLabel.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::ElidedTextLabel class. */ -#ifndef __OVITO_ELIDED_TEXT_LABEL_H -#define __OVITO_ELIDED_TEXT_LABEL_H +#pragma once + #include @@ -64,4 +64,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ELIDED_TEXT_LABEL_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/general/HtmlListWidget.h ovito-2.9.0+dfsg1/src/gui/widgets/general/HtmlListWidget.h --- ovito-2.8.1+dfsg2/src/gui/widgets/general/HtmlListWidget.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/general/HtmlListWidget.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_HTML_LIST_WIDGET_H -#define __OVITO_HTML_LIST_WIDGET_H +#pragma once + #include @@ -47,4 +47,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ELIDED_TEXT_LABEL_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/general/RolloutContainer.h ovito-2.9.0+dfsg1/src/gui/widgets/general/RolloutContainer.h --- ovito-2.8.1+dfsg2/src/gui/widgets/general/RolloutContainer.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/general/RolloutContainer.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ROLLOUT_CONTAINER_H -#define __OVITO_ROLLOUT_CONTAINER_H +#pragma once + #include @@ -243,4 +243,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ROLLOUT_CONTAINER_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/general/SpinnerWidget.cpp ovito-2.9.0+dfsg1/src/gui/widgets/general/SpinnerWidget.cpp --- ovito-2.8.1+dfsg2/src/gui/widgets/general/SpinnerWidget.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/general/SpinnerWidget.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -33,6 +33,7 @@ _upperBtnPressed(false), _lowerBtnPressed(false), _unit(nullptr) { setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum, QSizePolicy::SpinBox)); + setFocusPolicy(Qt::ClickFocus); setTextBox(textBox); } @@ -139,10 +140,12 @@ ******************************************************************************/ void SpinnerWidget::setFloatValue(FloatType newVal, bool emitChangeSignal) { - // Clamp value. if(newVal == _value) return; - newVal = std::max(minValue(), newVal); - newVal = std::min(maxValue(), newVal); + // Clamp value if it was entered by the user. + if(emitChangeSignal) { + newVal = std::max(minValue(), newVal); + newVal = std::min(maxValue(), newVal); + } if(_value != newVal) { _value = newVal; if(emitChangeSignal) @@ -159,9 +162,11 @@ FloatType newVal = (FloatType)newValInt; if(newVal == _value) return; - // Clamp value. - newVal = std::max((FloatType)ceil(minValue()), newVal); - newVal = std::min((FloatType)floor(maxValue()), newVal); + // Clamp value if it was entered by the user. + if(emitChangeSignal) { + newVal = std::max((FloatType)ceil(minValue()), newVal); + newVal = std::min((FloatType)floor(maxValue()), newVal); + } if(_value != newVal) { _value = newVal; if(emitChangeSignal) @@ -238,23 +243,26 @@ _lowerBtnPressed = true; _currentStepSize = unit() ? unit()->stepSize(floatValue(), _upperBtnPressed) : 1; - if(textBox()) textBox()->setFocus(Qt::OtherFocusReason); + event->accept(); grabMouse(); repaint(); } else if(event->button() == Qt::RightButton) { - // restore old value - setFloatValue(_oldValue, true); + if(_upperBtnPressed || _lowerBtnPressed) { + // restore old value + setFloatValue(_oldValue, true); + } - if(_upperBtnPressed == _lowerBtnPressed) { + if(_upperBtnPressed && _lowerBtnPressed) { Q_EMIT spinnerDragAbort(); } _upperBtnPressed = false; _lowerBtnPressed = false; + event->accept(); releaseMouse(); update(); } @@ -266,7 +274,7 @@ void SpinnerWidget::mouseReleaseEvent(QMouseEvent* event) { if(_upperBtnPressed || _lowerBtnPressed) { - if(_upperBtnPressed == _lowerBtnPressed) { + if(_upperBtnPressed && _lowerBtnPressed) { Q_EMIT spinnerDragStop(); } else { @@ -275,22 +283,24 @@ if(unit()) newValue = unit()->roundValue(floatValue() + unit()->stepSize(floatValue(), true)); else - newValue = floatValue() + 1.0f; + newValue = floatValue() + FloatType(1); } else { if(unit()) newValue = unit()->roundValue(floatValue() - unit()->stepSize(floatValue(), false)); else - newValue = floatValue() - 1.0f; + newValue = floatValue() - FloatType(1); } setFloatValue(newValue, true); } _upperBtnPressed = false; _lowerBtnPressed = false; + if(textBox()) textBox()->setFocus(Qt::OtherFocusReason); // Repaint spinner. update(); + event->accept(); } releaseMouse(); } @@ -322,15 +332,15 @@ int screenY = cursorPos.y(); if(screenY != _lastMouseY) { int screenHeight = QApplication::desktop()->screenGeometry().height(); - if(screenY <= 5 && _lastMouseY == screenHeight-1) return; + if(screenY <= 5 && _lastMouseY == screenHeight - 1) return; if(screenY >= screenHeight - 5 && _lastMouseY == 0) return; - FloatType newVal = _oldValue + _currentStepSize * (FloatType)(_startMouseY - screenY) * 0.1f; + FloatType newVal = _oldValue + _currentStepSize * (FloatType)(_startMouseY - screenY) * FloatType(0.1); if(unit()) newVal = unit()->roundValue(newVal); if(screenY < _lastMouseY && screenY <= 5) { - _lastMouseY = screenHeight-1; + _lastMouseY = screenHeight - 1; _startMouseY += _lastMouseY - screenY; QCursor::setPos(cursorPos.x(), _lastMouseY); } @@ -354,9 +364,25 @@ } } } + event->accept(); } } +/****************************************************************************** +* Is called when the widgets looses the input focus. +******************************************************************************/ +void SpinnerWidget::focusOutEvent(QFocusEvent* event) +{ + if(_upperBtnPressed && _lowerBtnPressed) { + Q_EMIT spinnerDragAbort(); + } + _upperBtnPressed = false; + _lowerBtnPressed = false; + releaseMouse(); + + QWidget::focusOutEvent(event); +} + OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/general/SpinnerWidget.h ovito-2.9.0+dfsg1/src/gui/widgets/general/SpinnerWidget.h --- ovito-2.8.1+dfsg2/src/gui/widgets/general/SpinnerWidget.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/general/SpinnerWidget.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SPINNER_WIDGET_H -#define __OVITO_SPINNER_WIDGET_H +#pragma once + #include #include @@ -200,10 +200,11 @@ virtual void mouseReleaseEvent(QMouseEvent* event) override; virtual void mouseMoveEvent(QMouseEvent* event) override; virtual void changeEvent(QEvent* event) override; + virtual void focusOutEvent(QFocusEvent* event) override; }; OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_SPINNER_WIDGET_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/rendering/FrameBufferWidget.h ovito-2.9.0+dfsg1/src/gui/widgets/rendering/FrameBufferWidget.h --- ovito-2.8.1+dfsg2/src/gui/widgets/rendering/FrameBufferWidget.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/rendering/FrameBufferWidget.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FRAME_BUFFER_WIDGET_H -#define __OVITO_FRAME_BUFFER_WIDGET_H +#pragma once + #include #include @@ -76,4 +76,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_FRAME_BUFFER_WIDGET_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/rendering/FrameBufferWindow.cpp ovito-2.9.0+dfsg1/src/gui/widgets/rendering/FrameBufferWindow.cpp --- ovito-2.8.1+dfsg2/src/gui/widgets/rendering/FrameBufferWindow.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/rendering/FrameBufferWindow.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,15 +29,8 @@ * Constructor. ******************************************************************************/ FrameBufferWindow::FrameBufferWindow(QWidget* parent) : -#if !defined(Q_OS_MAC) || QT_VERSION >= QT_VERSION_CHECK(5, 3, 1) QMainWindow(parent, (Qt::WindowFlags)(Qt::Tool | Qt::CustomizeWindowHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint)) -#else - QMainWindow(parent, (Qt::WindowFlags)(Qt::Window | Qt::CustomizeWindowHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint)) -#endif { -#if defined(Q_OS_MAC) && QT_VERSION < QT_VERSION_CHECK(5, 3, 1) - setWindowModality(Qt::ApplicationModal); -#endif _frameBufferWidget = new FrameBufferWidget(); class MyScrollArea : public QScrollArea { @@ -113,7 +106,7 @@ QString imageFilename = fileDialog.imageInfo().filename(); if(!frameBuffer()->image().save(imageFilename, fileDialog.imageInfo().format())) { Exception ex(tr("Failed to save image to file '%1'.").arg(imageFilename)); - ex.showError(); + ex.reportError(); } } } diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/rendering/FrameBufferWindow.h ovito-2.9.0+dfsg1/src/gui/widgets/rendering/FrameBufferWindow.h --- ovito-2.8.1+dfsg2/src/gui/widgets/rendering/FrameBufferWindow.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/rendering/FrameBufferWindow.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FRAME_BUFFER_WINDOW_H -#define __OVITO_FRAME_BUFFER_WINDOW_H +#pragma once + #include #include @@ -76,4 +76,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_FRAME_BUFFER_WINDOW_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/selection/SceneNodeSelectionBox.h ovito-2.9.0+dfsg1/src/gui/widgets/selection/SceneNodeSelectionBox.h --- ovito-2.8.1+dfsg2/src/gui/widgets/selection/SceneNodeSelectionBox.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/selection/SceneNodeSelectionBox.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SCENE_NODE_SELECTION_BOX_H -#define __OVITO_SCENE_NODE_SELECTION_BOX_H +#pragma once + #include @@ -60,4 +60,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_ANIMATION_FRAMES_TOOL_BUTTON_H + diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/selection/SceneNodesListModel.cpp ovito-2.9.0+dfsg1/src/gui/widgets/selection/SceneNodesListModel.cpp --- ovito-2.8.1+dfsg2/src/gui/widgets/selection/SceneNodesListModel.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/selection/SceneNodesListModel.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -100,7 +100,7 @@ // Whenever a new node is being inserted into the scene, add it to our internal list. if(event->type() == ReferenceEvent::ReferenceAdded) { ReferenceFieldEvent* refEvent = static_cast(event); - if(refEvent->field() == PROPERTY_FIELD(SceneNode::_children)) { + if(refEvent->field() == PROPERTY_FIELD(SceneNode::children)) { if(SceneNode* node = dynamic_object_cast(refEvent->newTarget())) { beginInsertRows(QModelIndex(), _nodeListener.targets().size(), _nodeListener.targets().size()); _nodeListener.push_back(node); diff -Nru ovito-2.8.1+dfsg2/src/gui/widgets/selection/SceneNodesListModel.h ovito-2.9.0+dfsg1/src/gui/widgets/selection/SceneNodesListModel.h --- ovito-2.8.1+dfsg2/src/gui/widgets/selection/SceneNodesListModel.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/gui/widgets/selection/SceneNodesListModel.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SCENE_NODES_LIST_MODEL_H -#define __OVITO_SCENE_NODES_LIST_MODEL_H +#pragma once + #include #include @@ -72,4 +72,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_SCENE_NODES_LIST_MODEL_H + diff -Nru ovito-2.8.1+dfsg2/src/main/CMakeLists.txt ovito-2.9.0+dfsg1/src/main/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/main/CMakeLists.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/main/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -68,7 +68,7 @@ INSTALL(DIRECTORY "resources/fonts" DESTINATION "${OVITO_RELATIVE_SHARE_DIRECTORY}/") ENDIF() -IF(UNIX AND NOT APPLE AND OVITO_MONOLITHIC_BUILD) +IF(UNIX AND NOT APPLE AND OVITO_REDISTRIBUTABLE_PACKAGE) # Install copies of the Qt libraries. FOREACH(component IN ITEMS Core Gui Widgets Concurrent Network PrintSupport) GET_TARGET_PROPERTY(lib Qt5::${component} LOCATION) @@ -91,9 +91,6 @@ INSTALL(DIRECTORY "${QtBinaryPath}/../plugins/platforms" DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}/plugins_qt/") INSTALL(DIRECTORY "${QtBinaryPath}/../plugins/bearer" DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}/plugins_qt/") INSTALL(DIRECTORY "${QtBinaryPath}/../plugins/imageformats" DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}/plugins_qt/" PATTERN "libqsvg.so" EXCLUDE) - IF(Qt5Core_VERSION VERSION_LESS "5.4") - INSTALL(DIRECTORY "${QtBinaryPath}/../plugins/accessible" DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}/plugins_qt/") - ENDIF() IF(NOT Qt5Core_VERSION VERSION_LESS "5.6") INSTALL(DIRECTORY "${QtBinaryPath}/../plugins/xcbglintegrations" DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}/plugins_qt/") OVITO_INSTALL_SHARED_LIB("${QtBinaryPath}/libQt5DBus.so" "${OVITO_RELATIVE_LIBRARY_DIRECTORY}/lib") @@ -103,12 +100,15 @@ # Make the executable look in lib/ovito/ directory for shared libraries. SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib/ovito") SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES BUILD_WITH_INSTALL_RPATH "1") - FIND_LIBRARY(OVITO_LIBSTDCXX NAMES libstdc++.so.6 PATHS /usr/lib /usr/lib/x86_64-linux-gnu NO_DEFAULT_PATH) - IF(NOT OVITO_LIBSTDCXX) - MESSAGE(FATAL_ERROR "Please specify the location of the C++ standard library with the OVITO_LIBSTDCXX option.") - ENDIF() - GET_FILENAME_COMPONENT(OVITO_LIBSTDCXX_REAL ${OVITO_LIBSTDCXX} REALPATH) - INSTALL(FILES "${OVITO_LIBSTDCXX}" "${OVITO_LIBSTDCXX_REAL}" DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}/") + + # Update: No longer bundle libstdc++.so.6 with OVITO, because it causes conflicts with the OpenGL driver on + # some systems. + #FIND_LIBRARY(OVITO_LIBSTDCXX NAMES libstdc++.so.6 PATHS /usr/lib /usr/lib/x86_64-linux-gnu NO_DEFAULT_PATH) + #IF(NOT OVITO_LIBSTDCXX) + # MESSAGE(FATAL_ERROR "Please specify the location of the C++ standard library with the OVITO_LIBSTDCXX option.") + #ENDIF() + #GET_FILENAME_COMPONENT(OVITO_LIBSTDCXX_REAL ${OVITO_LIBSTDCXX} REALPATH) + #INSTALL(FILES "${OVITO_LIBSTDCXX}" "${OVITO_LIBSTDCXX_REAL}" DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}/") ENDIF() @@ -137,16 +137,10 @@ INSTALL(FILES "${QtBinaryPath}/../plugins/platforms/qwindowsd.dll" DESTINATION "${OVITO_RELATIVE_BINARY_DIRECTORY}/plugins/platforms/") INSTALL(FILES "${QtBinaryPath}/../plugins/imageformats/qjpegd.dll" DESTINATION "${OVITO_RELATIVE_BINARY_DIRECTORY}/plugins/imageformats/") INSTALL(FILES "${QtBinaryPath}/../plugins/imageformats/qgifd.dll" DESTINATION "${OVITO_RELATIVE_BINARY_DIRECTORY}/plugins/imageformats/") - IF(Qt5Core_VERSION VERSION_LESS "5.4") - INSTALL(FILES "${QtBinaryPath}/../plugins/accessible/qtaccessiblewidgetsd.dll" DESTINATION "${OVITO_RELATIVE_BINARY_DIRECTORY}/plugins/accessible/") - ENDIF() ELSE() INSTALL(FILES "${QtBinaryPath}/../plugins/platforms/qwindows.dll" DESTINATION "${OVITO_RELATIVE_BINARY_DIRECTORY}/plugins/platforms/") INSTALL(FILES "${QtBinaryPath}/../plugins/imageformats/qjpeg.dll" DESTINATION "${OVITO_RELATIVE_BINARY_DIRECTORY}/plugins/imageformats/") INSTALL(FILES "${QtBinaryPath}/../plugins/imageformats/qgif.dll" DESTINATION "${OVITO_RELATIVE_BINARY_DIRECTORY}/plugins/imageformats/") - IF(Qt5Core_VERSION VERSION_LESS "5.4") - INSTALL(FILES "${QtBinaryPath}/../plugins/accessible/qtaccessiblewidgets.dll" DESTINATION "${OVITO_RELATIVE_BINARY_DIRECTORY}/plugins/accessible/") - ENDIF() ENDIF() # Create a qt.conf file. diff -Nru ovito-2.8.1+dfsg2/src/main/resources/appxmanifest.xml ovito-2.9.0+dfsg1/src/main/resources/appxmanifest.xml --- ovito-2.8.1+dfsg2/src/main/resources/appxmanifest.xml 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/main/resources/appxmanifest.xml 2017-07-27 16:52:45.000000000 +0000 @@ -3,10 +3,14 @@ xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"> - + Ovito ovito.org diff -Nru ovito-2.8.1+dfsg2/src/main/resources/Info.plist ovito-2.9.0+dfsg1/src/main/resources/Info.plist --- ovito-2.8.1+dfsg2/src/main/resources/Info.plist 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/main/resources/Info.plist 2017-07-27 16:52:45.000000000 +0000 @@ -29,12 +29,60 @@ LSRequiresCarbon NSHumanReadableCopyright - Copyright (C) 2016 Alexander Stukowski. This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. See the source for copying conditions. + Copyright (C) 2017 Alexander Stukowski. This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. See the source for copying conditions. LSMinimumSystemVersion 10.8.0 NSPrincipalClass NSApplication NSHighResolutionCapable + CFBundleDocumentTypes + + + CFBundleTypeRole + Editor + CFBundleTypeName + OVITO + CFBundleTypeExtensions + + ovito + + CFBundleTypeIconFile + ovito.icns + LSIsAppleDefaultForType + + + + CFBundleTypeRole + Viewer + CFBundleTypeName + XYZ + CFBundleTypeExtensions + + xyz + + + + CFBundleTypeRole + Viewer + CFBundleTypeName + LAMMPS + CFBundleTypeExtensions + + dump + data + + + + CFBundleTypeRole + Viewer + CFBundleTypeName + PDB + CFBundleTypeExtensions + + pdb + + + diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/CMakeLists.txt ovito-2.9.0+dfsg1/src/opengl_renderer/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/opengl_renderer/CMakeLists.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -35,6 +35,7 @@ OpenGLMarkerPrimitive.cpp OpenGLSharedResource.cpp OpenGLSceneRenderer.cpp + StandardSceneRenderer.cpp ) # Compile resources. @@ -43,6 +44,9 @@ # Build library ADD_LIBRARY(OpenGLRenderer SHARED ${SourceFiles} ${ResourceFiles}) +# Pass name of gui plugin to the code. +TARGET_COMPILE_DEFINITIONS(OpenGLRenderer PRIVATE "OVITO_PLUGIN_NAME=\"OpenGLRenderer\"") + # Set default include directory. TARGET_INCLUDE_DIRECTORIES(OpenGLRenderer PUBLIC "$") @@ -73,3 +77,11 @@ IF(CMAKE_VERSION VERSION_LESS "3") EXPORT(TARGETS OpenGLRenderer NAMESPACE "Ovito::" APPEND FILE "${${PROJECT_NAME}_BINARY_DIR}/OVITOTargets.cmake") ENDIF() + +# Build corresponding GUI plugin. +IF(OVITO_BUILD_GUI) + ADD_SUBDIRECTORY(gui) +ENDIF() + +# Propagate list of plugins to parent scope. +SET(OVITO_PLUGIN_LIST ${OVITO_PLUGIN_LIST} PARENT_SCOPE) diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/gui/CMakeLists.txt ovito-2.9.0+dfsg1/src/opengl_renderer/gui/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/opengl_renderer/gui/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/gui/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,30 @@ +############################################################################### +# +# Copyright (2017) Alexander Stukowski +# +# This file is part of OVITO (Open Visualization Tool). +# +# OVITO is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# OVITO is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################### + +SET(SourceFiles + StandardSceneRendererEditor.cpp +) + +OVITO_STANDARD_PLUGIN(OpenGLRendererGui + SOURCES ${SourceFiles} + PLUGIN_DEPENDENCIES OpenGLRenderer + GUI_PLUGIN +) diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/gui/StandardSceneRendererEditor.cpp ovito-2.9.0+dfsg1/src/opengl_renderer/gui/StandardSceneRendererEditor.cpp --- ovito-2.8.1+dfsg2/src/opengl_renderer/gui/StandardSceneRendererEditor.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/gui/StandardSceneRendererEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,55 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2013) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "StandardSceneRendererEditor.h" + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) OVITO_BEGIN_INLINE_NAMESPACE(Internal) + +IMPLEMENT_OVITO_OBJECT(StandardSceneRendererEditor, PropertiesEditor); +SET_OVITO_OBJECT_EDITOR(StandardSceneRenderer, StandardSceneRendererEditor); + +/****************************************************************************** +* Constructor that creates the UI controls for the editor. +******************************************************************************/ +void StandardSceneRendererEditor::createUI(const RolloutInsertionParameters& rolloutParams) +{ + // Create the rollout. + QWidget* rollout = createRollout(tr("OpenGL renderer settings"), rolloutParams, "rendering.opengl_renderer.html"); + + QGridLayout* layout = new QGridLayout(rollout); + layout->setContentsMargins(4,4,4,4); +#ifndef Q_OS_MACX + layout->setSpacing(2); +#endif + layout->setColumnStretch(1, 1); + + // Antialiasing level + IntegerParameterUI* antialiasingLevelUI = new IntegerParameterUI(this, PROPERTY_FIELD(StandardSceneRenderer::antialiasingLevel)); + layout->addWidget(antialiasingLevelUI->label(), 0, 0); + layout->addLayout(antialiasingLevelUI->createFieldLayout(), 0, 1); +} + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/gui/StandardSceneRendererEditor.h ovito-2.9.0+dfsg1/src/opengl_renderer/gui/StandardSceneRendererEditor.h --- ovito-2.8.1+dfsg2/src/opengl_renderer/gui/StandardSceneRendererEditor.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/gui/StandardSceneRendererEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,56 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2013) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include +#include + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) OVITO_BEGIN_INLINE_NAMESPACE(Internal) + +/****************************************************************************** +* The editor component for the StandardSceneRenderer class. +******************************************************************************/ +class StandardSceneRendererEditor : public PropertiesEditor +{ +public: + + /// Default constructor. + Q_INVOKABLE StandardSceneRendererEditor() {} + +protected: + + /// Creates the user interface controls for the editor. + virtual void createUI(const RolloutInsertionParameters& rolloutParams) override; + +private: + + Q_OBJECT + OVITO_OBJECT +}; + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLArrowPrimitive.h ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLArrowPrimitive.h --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLArrowPrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLArrowPrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OPENGL_ARROW_GEOMETRY_BUFFER_H -#define __OVITO_OPENGL_ARROW_GEOMETRY_BUFFER_H +#pragma once + #include #include @@ -159,4 +159,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OPENGL_ARROW_GEOMETRY_BUFFER_H + diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLBuffer.h ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLBuffer.h --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLBuffer.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLBuffer.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OPENGL_BUFFER_H -#define __OVITO_OPENGL_BUFFER_H +#pragma once + #include #include "OpenGLHelpers.h" @@ -291,4 +291,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OPENGL_BUFFER_H + diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLHelpers.h ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLHelpers.h --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLHelpers.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLHelpers.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OPENGL_HELPERS_H -#define __OVITO_OPENGL_HELPERS_H +#pragma once + #include @@ -54,4 +54,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OPENGL_HELPERS_H + diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLImagePrimitive.cpp ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLImagePrimitive.cpp --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLImagePrimitive.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLImagePrimitive.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -111,11 +111,12 @@ // Transform rectangle to normalized device coordinates. FloatType x = pos.x(), y = pos.y(); FloatType w = size.x(), h = size.y(); - if(vpRenderer->antialiasingLevel() > 1) { - x = (int)(x / vpRenderer->antialiasingLevel()) * vpRenderer->antialiasingLevel(); - y = (int)(y / vpRenderer->antialiasingLevel()) * vpRenderer->antialiasingLevel(); - int x2 = (int)((x + w) / vpRenderer->antialiasingLevel()) * vpRenderer->antialiasingLevel(); - int y2 = (int)((y + h) / vpRenderer->antialiasingLevel()) * vpRenderer->antialiasingLevel(); + int aaLevel = vpRenderer->antialiasingLevelInternal(); + if(aaLevel > 1) { + x = (int)(x / aaLevel) * aaLevel; + y = (int)(y / aaLevel) * aaLevel; + int x2 = (int)((x + w) / aaLevel) * aaLevel; + int y2 = (int)((y + h) / aaLevel) * aaLevel; w = x2 - x; h = y2 - y; } diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLImagePrimitive.h ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLImagePrimitive.h --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLImagePrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLImagePrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OPENGL_IMAGE_PRIMITIVE_H -#define __OVITO_OPENGL_IMAGE_PRIMITIVE_H +#pragma once + #include #include @@ -80,4 +80,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OPENGL_IMAGE_PRIMITIVE_H + diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLLinePrimitive.h ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLLinePrimitive.h --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLLinePrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLLinePrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OPENGL_LINE_PRIMITIVE_H -#define __OVITO_OPENGL_LINE_PRIMITIVE_H +#pragma once + #include #include @@ -110,4 +110,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OPENGL_LINE_PRIMITIVE_H + diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLMarkerPrimitive.h ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLMarkerPrimitive.h --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLMarkerPrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLMarkerPrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OPENGL_MARKER_PRIMITIVE_H -#define __OVITO_OPENGL_MARKER_PRIMITIVE_H +#pragma once + #include #include @@ -81,4 +81,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OPENGL_MARKER_PRIMITIVE_H + diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLMeshPrimitive.cpp ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLMeshPrimitive.cpp --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLMeshPrimitive.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLMeshPrimitive.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -69,81 +69,110 @@ ColoredVertexWithNormal* renderVertices = _vertexBuffer.map(QOpenGLBuffer::ReadWrite); - quint32 allMask = 0; + if(!mesh.hasNormals()) { + quint32 allMask = 0; - // Compute face normals. - std::vector> faceNormals(mesh.faceCount()); - auto faceNormal = faceNormals.begin(); - for(auto face = mesh.faces().constBegin(); face != mesh.faces().constEnd(); ++face, ++faceNormal) { - const Point3& p0 = mesh.vertex(face->vertex(0)); - Vector3 d1 = mesh.vertex(face->vertex(1)) - p0; - Vector3 d2 = mesh.vertex(face->vertex(2)) - p0; - *faceNormal = (Vector_3)d1.cross(d2); - if(*faceNormal != Vector_3::Zero()) { - faceNormal->normalize(); - allMask |= face->smoothingGroups(); + // Compute face normals. + std::vector> faceNormals(mesh.faceCount()); + auto faceNormal = faceNormals.begin(); + for(auto face = mesh.faces().constBegin(); face != mesh.faces().constEnd(); ++face, ++faceNormal) { + const Point3& p0 = mesh.vertex(face->vertex(0)); + Vector3 d1 = mesh.vertex(face->vertex(1)) - p0; + Vector3 d2 = mesh.vertex(face->vertex(2)) - p0; + *faceNormal = (Vector_3)d1.cross(d2); + if(*faceNormal != Vector_3::Zero()) { + //faceNormal->normalize(); + allMask |= face->smoothingGroups(); + } } - } - // Initialize render vertices. - ColoredVertexWithNormal* rv = renderVertices; - faceNormal = faceNormals.begin(); - ColorAT defaultVertexColor = (ColorAT)meshColor; - for(auto face = mesh.faces().constBegin(); face != mesh.faces().constEnd(); ++face, ++faceNormal) { - - // Initialize render vertices for this face. - for(size_t v = 0; v < 3; v++, rv++) { - if(face->smoothingGroups()) - rv->normal = Vector_3::Zero(); - else - rv->normal = *faceNormal; - rv->pos = (Point_3)mesh.vertex(face->vertex(v)); - if(mesh.hasVertexColors()) { - rv->color = (ColorAT)mesh.vertexColor(face->vertex(v)); - _hasAlpha |= (rv->color.a() != 1); - } - else if(mesh.hasFaceColors()) { - rv->color = (ColorAT)mesh.faceColor(face - mesh.faces().constBegin()); - _hasAlpha |= (rv->color.a() != 1); - } - else if(face->materialIndex() < materialColors().size() && face->materialIndex() >= 0) { - rv->color = (ColorAT)materialColors()[face->materialIndex()]; - } - else { - rv->color = defaultVertexColor; + // Initialize render vertices. + ColoredVertexWithNormal* rv = renderVertices; + faceNormal = faceNormals.begin(); + ColorAT defaultVertexColor = (ColorAT)meshColor; + for(auto face = mesh.faces().constBegin(); face != mesh.faces().constEnd(); ++face, ++faceNormal) { + + // Initialize render vertices for this face. + for(size_t v = 0; v < 3; v++, rv++) { + if(face->smoothingGroups()) + rv->normal = Vector_3::Zero(); + else + rv->normal = *faceNormal; + rv->pos = (Point_3)mesh.vertex(face->vertex(v)); + if(mesh.hasVertexColors()) { + rv->color = (ColorAT)mesh.vertexColor(face->vertex(v)); + _hasAlpha |= (rv->color.a() != 1); + } + else if(mesh.hasFaceColors()) { + rv->color = (ColorAT)mesh.faceColor(face - mesh.faces().constBegin()); + _hasAlpha |= (rv->color.a() != 1); + } + else if(face->materialIndex() < materialColors().size() && face->materialIndex() >= 0) { + rv->color = (ColorAT)materialColors()[face->materialIndex()]; + } + else { + rv->color = defaultVertexColor; + } } } - } - if(allMask) { - std::vector> groupVertexNormals(mesh.vertexCount()); - for(int group = 0; group < OVITO_MAX_NUM_SMOOTHING_GROUPS; group++) { - quint32 groupMask = quint32(1) << group; - if((allMask & groupMask) == 0) - continue; // Group is not used. - - // Reset work arrays. - std::fill(groupVertexNormals.begin(), groupVertexNormals.end(), Vector_3::Zero()); - - // Compute vertex normals at original vertices for current smoothing group. - faceNormal = faceNormals.begin(); - for(auto face = mesh.faces().constBegin(); face != mesh.faces().constEnd(); ++face, ++faceNormal) { - // Skip faces that do not belong to the current smoothing group. - if((face->smoothingGroups() & groupMask) == 0) continue; - - // Add face's normal to vertex normals. - for(size_t fv = 0; fv < 3; fv++) - groupVertexNormals[face->vertex(fv)] += *faceNormal; - } + if(allMask) { + std::vector> groupVertexNormals(mesh.vertexCount()); + for(int group = 0; group < OVITO_MAX_NUM_SMOOTHING_GROUPS; group++) { + quint32 groupMask = quint32(1) << group; + if((allMask & groupMask) == 0) + continue; // Group is not used. + + // Reset work arrays. + std::fill(groupVertexNormals.begin(), groupVertexNormals.end(), Vector_3::Zero()); + + // Compute vertex normals at original vertices for current smoothing group. + faceNormal = faceNormals.begin(); + for(auto face = mesh.faces().constBegin(); face != mesh.faces().constEnd(); ++face, ++faceNormal) { + // Skip faces that do not belong to the current smoothing group. + if((face->smoothingGroups() & groupMask) == 0) continue; + + // Add face's normal to vertex normals. + for(size_t fv = 0; fv < 3; fv++) + groupVertexNormals[face->vertex(fv)] += *faceNormal; + } - // Transfer vertex normals from original vertices to render vertices. - rv = renderVertices; - for(const auto& face : mesh.faces()) { - if(face.smoothingGroups() & groupMask) { - for(size_t fv = 0; fv < 3; fv++, ++rv) - rv->normal += groupVertexNormals[face.vertex(fv)]; + // Transfer vertex normals from original vertices to render vertices. + rv = renderVertices; + for(const auto& face : mesh.faces()) { + if(face.smoothingGroups() & groupMask) { + for(size_t fv = 0; fv < 3; fv++, ++rv) + rv->normal += groupVertexNormals[face.vertex(fv)]; + } + else rv += 3; + } + } + } + } + else { + // Use normals stored in the mesh. + ColoredVertexWithNormal* rv = renderVertices; + const Vector3* faceNormal = mesh.normals().begin(); + ColorAT defaultVertexColor = (ColorAT)meshColor; + for(auto face = mesh.faces().constBegin(); face != mesh.faces().constEnd(); ++face) { + // Initialize render vertices for this face. + for(size_t v = 0; v < 3; v++, rv++) { + rv->normal = *faceNormal++; + rv->pos = (Point_3)mesh.vertex(face->vertex(v)); + if(mesh.hasVertexColors()) { + rv->color = (ColorAT)mesh.vertexColor(face->vertex(v)); + _hasAlpha |= (rv->color.a() != 1); + } + else if(mesh.hasFaceColors()) { + rv->color = (ColorAT)mesh.faceColor(face - mesh.faces().constBegin()); + _hasAlpha |= (rv->color.a() != 1); + } + else if(face->materialIndex() < materialColors().size() && face->materialIndex() >= 0) { + rv->color = (ColorAT)materialColors()[face->materialIndex()]; + } + else { + rv->color = defaultVertexColor; } - else rv += 3; } } } diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLMeshPrimitive.h ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLMeshPrimitive.h --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLMeshPrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLMeshPrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OPENGL_MESH_PRIMITIVE_H -#define __OVITO_OPENGL_MESH_PRIMITIVE_H +#pragma once + #include #include @@ -83,4 +83,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OPENGL_MESH_PRIMITIVE_H + diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLParticlePrimitive.cpp ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLParticlePrimitive.cpp --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLParticlePrimitive.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLParticlePrimitive.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -558,6 +558,11 @@ OVITO_CHECK_OPENGL(renderer->glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, distanceAttenuation.data())); } + // Account for possible scaling in the model-view TM. + float radius_scalingfactor = (float)pow(renderer->modelViewTM().determinant(), FloatType(1.0/3.0)); + shader->setUniformValue("radius_scalingfactor", radius_scalingfactor); + param *= radius_scalingfactor; + shader->setUniformValue("basePointSize", param); shader->setUniformValue("projection_matrix", (QMatrix4x4)renderer->projParams().projectionMatrix); shader->setUniformValue("modelview_matrix", (QMatrix4x4)renderer->modelViewTM()); @@ -664,7 +669,11 @@ } if(particleShape() != SphericalShape && !renderer->isPicking()) { - shader->setUniformValue("normal_matrix", (QMatrix3x3)(renderer->modelViewTM().linear().inverse().transposed())); + Matrix3 normal_matrix = renderer->modelViewTM().linear().inverse().transposed(); + normal_matrix.column(0).normalize(); + normal_matrix.column(1).normalize(); + normal_matrix.column(2).normalize(); + shader->setUniformValue("normal_matrix", (QMatrix3x3)normal_matrix); if(!_usingGeometryShader) { // The normal vectors for the cube triangle strip. static const QVector3D normals[14] = { @@ -692,6 +701,7 @@ shader->setUniformValue("modelview_matrix", (QMatrix4x4)renderer->modelViewTM()); shader->setUniformValue("modelviewprojection_matrix", (QMatrix4x4)(renderer->projParams().projectionMatrix * renderer->modelViewTM())); shader->setUniformValue("is_perspective", renderer->projParams().isPerspective); + shader->setUniformValue("radius_scalingfactor", (float)pow(renderer->modelViewTM().determinant(), FloatType(1.0/3.0))); GLint viewportCoords[4]; renderer->glGetIntegerv(GL_VIEWPORT, viewportCoords); @@ -828,6 +838,9 @@ shader->setUniformValue("modelview_matrix", (QMatrix4x4)renderer->modelViewTM()); shader->setUniformValue("modelviewprojection_matrix", (QMatrix4x4)(renderer->projParams().projectionMatrix * renderer->modelViewTM())); + // Account for possible scaling in the model-view TM. + shader->setUniformValue("radius_scalingfactor", (float)pow(renderer->modelViewTM().determinant(), FloatType(1.0/3.0))); + if(!renderer->isPicking() && translucentParticles()) { renderer->glEnable(GL_BLEND); renderer->glBlendEquation(GL_FUNC_ADD); diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLParticlePrimitive.h ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLParticlePrimitive.h --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLParticlePrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLParticlePrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OPENGL_PARTICLE_PRIMITIVE_H -#define __OVITO_OPENGL_PARTICLE_PRIMITIVE_H +#pragma once + #include #include @@ -180,4 +180,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OPENGL_PARTICLE_PRIMITIVE_H + diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLSceneRenderer.cpp ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLSceneRenderer.cpp --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLSceneRenderer.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLSceneRenderer.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -46,7 +46,7 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Gui, OpenGLSceneRenderer, SceneRenderer); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(OpenGLSceneRenderer, SceneRenderer); /// The vendor of the OpenGL implementation in use. QByteArray OpenGLSceneRenderer::_openGLVendor; @@ -82,7 +82,7 @@ tempContext.setFormat(getDefaultSurfaceFormat()); if(!tempContext.create()) throw Exception(tr("Failed to create temporary OpenGL context.")); - if(Application::instance().headlessMode() == false) { + if(Application::instance()->headlessMode() == false) { // Create a hidden, temporary window to make the GL context current. window.reset(new QWindow()); window->setSurfaceType(QSurface::OpenGLSurface); @@ -103,17 +103,10 @@ OVITO_ASSERT(QOpenGLContext::currentContext() == &tempContext); } -#if QT_VERSION < QT_VERSION_CHECK(5, 3, 0) - _openGLVendor = reinterpret_cast(::glGetString(GL_VENDOR)); - _openGLRenderer = reinterpret_cast(::glGetString(GL_RENDERER)); - _openGLVersion = reinterpret_cast(::glGetString(GL_VERSION)); - _openGLSLVersion = reinterpret_cast(::glGetString(GL_SHADING_LANGUAGE_VERSION)); -#else _openGLVendor = reinterpret_cast(tempContext.functions()->glGetString(GL_VENDOR)); _openGLRenderer = reinterpret_cast(tempContext.functions()->glGetString(GL_RENDERER)); _openGLVersion = reinterpret_cast(tempContext.functions()->glGetString(GL_VERSION)); _openGLSLVersion = reinterpret_cast(tempContext.functions()->glGetString(GL_SHADING_LANGUAGE_VERSION)); -#endif _openglSupportsGeomShaders = QOpenGLShader::hasOpenGLShaders(QOpenGLShader::Geometry); _openglSurfaceFormat = QOpenGLContext::currentContext()->format(); } @@ -191,7 +184,7 @@ return false; #endif - if(Application::instance().guiMode()) + if(Application::instance()->guiMode()) return geometryShadersSupported(); else if(QOpenGLContext::currentContext()) return QOpenGLShader::hasOpenGLShaders(QOpenGLShader::Geometry); @@ -207,27 +200,10 @@ { QSurfaceFormat format; format.setDepthBufferSize(24); -#if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0) format.setSwapInterval(0); -#endif format.setMajorVersion(OVITO_OPENGL_REQUESTED_VERSION_MAJOR); format.setMinorVersion(OVITO_OPENGL_REQUESTED_VERSION_MINOR); - if(Application::instance().cmdLineParser().isSet(QStringLiteral("glversion"))) { - QStringList tokens = Application::instance().cmdLineParser().value(QStringLiteral("glversion")).split(QChar('.')); - if(tokens.size() == 2) { - int majorVersion = tokens[0].toInt(); - int minorVersion = tokens[1].toInt(); - if(majorVersion >= 1) { - format.setMajorVersion(majorVersion); - format.setMinorVersion(minorVersion); - } - } - } format.setProfile(QSurfaceFormat::CoreProfile); - if(Application::instance().cmdLineParser().isSet(QStringLiteral("glcompatprofile"))) { - format.setProfile(QSurfaceFormat::CompatibilityProfile); - format.setOption(QSurfaceFormat::DeprecatedFunctions); - } #ifdef Q_OS_WIN // Always request deprecated functions to be included in the context profile on Windows // to work around a compatibility issue between Qt 5.4.1 and the Intel OpenGL driver. @@ -244,8 +220,9 @@ void OpenGLSceneRenderer::beginFrame(TimePoint time, const ViewProjectionParameters& params, Viewport* vp) { SceneRenderer::beginFrame(time, params, vp); + OVITO_REPORT_OPENGL_ERRORS(); - if(Application::instance().headlessMode()) + if(Application::instance()->headlessMode()) throwException(tr("Cannot use OpenGL renderer in headless mode.")); _glcontext = QOpenGLContext::currentContext(); @@ -323,19 +300,19 @@ /****************************************************************************** * This method is called after renderFrame() has been called. ******************************************************************************/ -void OpenGLSceneRenderer::endFrame() +void OpenGLSceneRenderer::endFrame(bool renderSuccessful) { OVITO_REPORT_OPENGL_ERRORS(); OVITO_CHECK_OPENGL(_vertexArrayObject.reset()); _glcontext = nullptr; - SceneRenderer::endFrame(); + SceneRenderer::endFrame(renderSuccessful); } /****************************************************************************** * Renders the current animation frame. ******************************************************************************/ -bool OpenGLSceneRenderer::renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, AbstractProgressDisplay* progress) +bool OpenGLSceneRenderer::renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, TaskManager& taskManager) { OVITO_ASSERT(_glcontext == QOpenGLContext::currentContext()); @@ -358,12 +335,15 @@ // Clear background. clearFrameBuffer(); + OVITO_REPORT_OPENGL_ERRORS(); // Render the 3D scene objects. renderScene(); + OVITO_REPORT_OPENGL_ERRORS(); // Call subclass to render additional content that is only visible in the interactive viewports. renderInteractiveContent(); + OVITO_REPORT_OPENGL_ERRORS(); // Render translucent objects in a second pass. _translucentPass = true; @@ -375,6 +355,7 @@ // Restore default OpenGL state. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + OVITO_REPORT_OPENGL_ERRORS(); return true; } @@ -504,6 +485,8 @@ } OVITO_ASSERT(contextGroup->findChild(id) == program.data()); + OVITO_REPORT_OPENGL_ERRORS(); + return program.take(); } @@ -583,6 +566,8 @@ ex.appendDetailMessage(shaderSource); throw ex; } + + OVITO_REPORT_OPENGL_ERRORS(); } /****************************************************************************** @@ -770,20 +755,6 @@ } } - -#if QT_VERSION < QT_VERSION_CHECK(5, 3, 0) -void OpenGLSceneRenderer::glEnable(GLenum cap) { ::glEnable(cap); } -void OpenGLSceneRenderer::glDisable(GLenum cap) { ::glDisable(cap); } -void OpenGLSceneRenderer::glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices) { ::glDrawElements(mode, count, type, indices); } -void OpenGLSceneRenderer::glGetIntegerv(GLenum pname, GLint * params) { ::glGetIntegerv(pname, params); } -void OpenGLSceneRenderer::glCullFace(GLenum mode) { ::glCullFace(mode); } -void OpenGLSceneRenderer::glDrawArrays(GLenum mode, GLint first, GLsizei count) { ::glDrawArrays(mode, first, count); } -void OpenGLSceneRenderer::glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * pixels) { ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); } -void OpenGLSceneRenderer::glTexParameteri(GLenum target, GLenum pname, GLint param) { ::glTexParameteri(target, pname, param); } -GLboolean OpenGLSceneRenderer::glIsEnabled(GLenum cap) { return ::glIsEnabled(cap); } -void OpenGLSceneRenderer::glBlendFunc(GLenum sfactor, GLenum dfactor) { ::glBlendFunc(sfactor, dfactor); } -#endif - OVITO_BEGIN_INLINE_NAMESPACE(Internal) /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLSceneRenderer.h ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLSceneRenderer.h --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLSceneRenderer.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLSceneRenderer.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OPENGL_SCENE_RENDERER_H -#define __OVITO_OPENGL_SCENE_RENDERER_H +#pragma once + #include #include @@ -58,13 +58,13 @@ _glVertexIDBufferSize(-1) {} /// Renders the current animation frame. - virtual bool renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, AbstractProgressDisplay* progress) override; + virtual bool renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, TaskManager& taskManager) override; /// This method is called just before renderFrame() is called. virtual void beginFrame(TimePoint time, const ViewProjectionParameters& params, Viewport* vp) override; /// This method is called after renderFrame() has been called. - virtual void endFrame() override; + virtual void endFrame(bool renderSuccessful) override; /// Changes the current local to world transformation matrix. virtual void setWorldTransform(const AffineTransformation& tm) override; @@ -105,9 +105,6 @@ /// Renders a 2d polyline in the viewport. void render2DPolyline(const Point2* points, int count, const ColorA& color, bool closed); - /// Returns the supersampling level. - virtual int antialiasingLevel() const { return 1; } - /// Returns the OpenGL context this renderer uses. QOpenGLContext* glcontext() const { return _glcontext; } @@ -218,21 +215,8 @@ /// visible in the interactive viewports. virtual void renderInteractiveContent() {} -#if QT_VERSION < QT_VERSION_CHECK(5, 3, 0) - - // Need this, because Qt5.2 did not yet expose the standard OpenGL functions through the QOpenGLFunctions class. - void glEnable(GLenum cap); - void glDisable(GLenum cap); - void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices); - void glGetIntegerv(GLenum pname, GLint * params); - void glCullFace(GLenum mode); - void glDrawArrays(GLenum mode, GLint first, GLsizei count); - void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * pixels); - void glTexParameteri(GLenum target, GLenum pname, GLint param); - GLboolean glIsEnabled(GLenum cap); - void glBlendFunc(GLenum sfactor, GLenum dfactor); - -#endif + /// Returns the supersampling level to use. + virtual int antialiasingLevelInternal() { return 1; } /// The OpenGL glPointParameterf() function. void glPointSize(GLfloat size) { @@ -352,5 +336,5 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OPENGL_SCENE_RENDERER_H + diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLSharedResource.cpp ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLSharedResource.cpp --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLSharedResource.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLSharedResource.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -50,7 +50,7 @@ } /// The OpenGL context wrapped by this object. - QOpenGLContext* _context; + QPointer _context; /// The window surface needed to make the OpenGL context current. QPointer _windowSurface; @@ -171,7 +171,7 @@ if(_prev) _prev->_next = _next; else _contextInfo->_resources = _next; - QOpenGLContext* ownerContext = _contextInfo->_context; + QOpenGLContext* ownerContext = _contextInfo->_context; QSurface* ownerSurface = _contextInfo->_windowSurface.data(); if(!ownerSurface) ownerSurface = _contextInfo->_offscreenSurface.data(); _contextInfo = nullptr; @@ -180,6 +180,8 @@ // Switch back to the owning context temporarily and delete the id. QOpenGLContext* currentContext = QOpenGLContext::currentContext(); + if(!ownerContext) return; + if(currentContext != ownerContext && (!currentContext || !QOpenGLContext::areSharing(ownerContext, currentContext))) { if(ownerSurface != nullptr) { QSurface* currentSurface = currentContext ? currentContext->surface() : nullptr; diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLSharedResource.h ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLSharedResource.h --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLSharedResource.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLSharedResource.h 2017-07-27 16:52:45.000000000 +0000 @@ -24,8 +24,8 @@ * \brief Contains the definition of the Ovito::OpenGLSharedResource class. */ -#ifndef __OVITO_SHARED_OPENGL_RESOURCE_H -#define __OVITO_SHARED_OPENGL_RESOURCE_H +#pragma once + #include @@ -65,4 +65,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_SHARED_OPENGL_RESOURCE_H + diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLTextPrimitive.cpp ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLTextPrimitive.cpp --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLTextPrimitive.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLTextPrimitive.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -97,7 +97,7 @@ } Point2 alignedPos = pos; - Vector2 size = Vector2(_imageBuffer->image().width(), _imageBuffer->image().height()) * (FloatType)vpRenderer->antialiasingLevel(); + Vector2 size = Vector2(_imageBuffer->image().width(), _imageBuffer->image().height()) * (FloatType)vpRenderer->antialiasingLevelInternal(); if(alignment & Qt::AlignRight) alignedPos.x() += -size.x(); else if(alignment & Qt::AlignHCenter) alignedPos.x() += -size.x() / 2; if(alignment & Qt::AlignBottom) alignedPos.y() += -size.y(); diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLTextPrimitive.h ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLTextPrimitive.h --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLTextPrimitive.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLTextPrimitive.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OPENGL_TEXT_PRIMITIVE_H -#define __OVITO_OPENGL_TEXT_PRIMITIVE_H +#pragma once + #include #include @@ -95,4 +95,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OPENGL_TEXT_PRIMITIVE_H + diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLTexture.h ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLTexture.h --- ovito-2.8.1+dfsg2/src/opengl_renderer/OpenGLTexture.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/OpenGLTexture.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OPENGL_TEXTURE_H -#define __OVITO_OPENGL_TEXTURE_H +#pragma once + #include #include "OpenGLSharedResource.h" @@ -49,11 +49,7 @@ QOpenGLContext::currentContext()->functions()->glActiveTexture(GL_TEXTURE0); // Create OpenGL texture. -#if QT_VERSION < QT_VERSION_CHECK(5, 3, 0) - ::glGenTextures(1, &_id); -#else QOpenGLContext::currentContext()->functions()->glGenTextures(1, &_id); -#endif // Make sure texture gets deleted when this object is destroyed. attachOpenGLResources(); @@ -65,11 +61,7 @@ /// Makes this the active texture. void bind() { QOpenGLContext::currentContext()->functions()->glActiveTexture(GL_TEXTURE0); -#if QT_VERSION < QT_VERSION_CHECK(5, 3, 0) - ::glBindTexture(GL_TEXTURE_2D, _id); -#else QOpenGLContext::currentContext()->functions()->glBindTexture(GL_TEXTURE_2D, _id); -#endif } protected: @@ -77,11 +69,7 @@ /// This method that takes care of freeing the shared OpenGL resources owned by this class. virtual void freeOpenGLResources() override { if(_id) { -#if QT_VERSION < QT_VERSION_CHECK(5, 3, 0) - glDeleteTextures(1, &_id); -#else QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &_id); -#endif _id = 0; } } @@ -96,4 +84,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_OPENGL_TEXTURE_H + diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/cylinder/cylinder_raytraced.fs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/cylinder/cylinder_raytraced.fs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/cylinder/cylinder_raytraced.fs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/cylinder/cylinder_raytraced.fs 2017-07-27 16:52:45.000000000 +0000 @@ -72,8 +72,10 @@ vec3 view_intersection_pnt = ray_origin; vec3 surface_normal; + + bool skip = false; - if(ln < 1e-7) { + if(ln < 1e-7 * cylinder_length) { // Handle case where view ray is parallel to cylinder axis: float t = dot(RC, ray_dir); @@ -107,7 +109,7 @@ float t = dot(cross(cylinder_view_axis, RC), n) / ln; float s = abs(sqrt(cylinder_radius_sq_fs - d) / dot(cross(n, cylinder_view_axis),ray_dir) * cylinder_length); float tnear = t - s; - + // Calculate intersection point in view coordinate system. view_intersection_pnt += tnear * ray_dir; @@ -126,11 +128,11 @@ // Compute intersection with cylinder caps. if(anear < 0 && afar > 0) { - view_intersection_pnt += (anear / (anear - afar) * 2.0 * s + 1e-6) * ray_dir; + view_intersection_pnt += (anear / (anear - afar) * 2.0 * s + 1e-6 * ln) * ray_dir; surface_normal = -cylinder_view_axis; } else if(anear > 1.0 && afar < 1.0) { - view_intersection_pnt += ((anear - 1.0) / (anear - afar) * 2.0 * s + 1e-6) * ray_dir; + view_intersection_pnt += ((anear - 1.0) / (anear - afar) * 2.0 * s + 1e-6 * ln) * ray_dir; surface_normal = cylinder_view_axis; } else { @@ -139,7 +141,7 @@ } } } - + // Output the ray-cylinder intersection point as the fragment depth // rather than the depth of the bounding box polygons. // The eye coordinate Z value must be transformed to normalized device diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/cylinder/cylinder_raytraced.gs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/cylinder/cylinder_raytraced.gs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/cylinder/cylinder_raytraced.gs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/cylinder/cylinder_raytraced.gs 2017-07-27 16:52:45.000000000 +0000 @@ -45,12 +45,13 @@ // Compute local coordinate system. vec4 u; if(cylinder_view_axis_gs[0].y != 0.0 || cylinder_view_axis_gs[0].x != 0.0) - u = normalize(vec4(cylinder_view_axis_gs[0].y, -cylinder_view_axis_gs[0].x, 0.0, 0.0)) * cylinder_radius_gs[0]; + u = normalize(vec4(cylinder_view_axis_gs[0].y, -cylinder_view_axis_gs[0].x, 0.0, 0.0)); else if(cylinder_view_axis_gs[0].z != 0.0) - u = normalize(vec4(-cylinder_view_axis_gs[0].z, 0.0, cylinder_view_axis_gs[0].x, 0.0)) * cylinder_radius_gs[0]; + u = normalize(vec4(-cylinder_view_axis_gs[0].z, 0.0, cylinder_view_axis_gs[0].x, 0.0)); else u = vec4(0.0); vec4 v = vec4(normalize(cross(cylinder_view_axis_gs[0].xyz, u.xyz)), 0.0) * cylinder_radius_gs[0]; + u *= cylinder_radius_gs[0]; cylinder_color_fs = cylinder_color_gs[0]; cylinder_radius_sq_fs = cylinder_radius_gs[0]*cylinder_radius_gs[0]; diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/cylinder/picking/cylinder_raytraced.fs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/cylinder/picking/cylinder_raytraced.fs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/cylinder/picking/cylinder_raytraced.fs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/cylinder/picking/cylinder_raytraced.fs 2017-07-27 16:52:45.000000000 +0000 @@ -67,7 +67,7 @@ vec3 view_intersection_pnt = ray_origin; - if(ln < 1e-7) { + if(ln < 1e-7 * cylinder_length) { float t = dot(RC, ray_dir); float v = dot(RC, RC); if(v-t*t > cylinder_radius_sq_fs) { @@ -114,10 +114,10 @@ float afar = dot(far_view_intersection_pnt - cylinder_view_base, cylinder_view_axis) / (cylinder_length*cylinder_length); if(anear < 0 && afar >= 0) { - view_intersection_pnt += (anear / (anear - afar) * 2.0 * s + 1e-6) * ray_dir; + view_intersection_pnt += (anear / (anear - afar) * 2.0 * s + 1e-6 * ln) * ray_dir; } else if(anear > 1.0 && afar < 1.0) { - view_intersection_pnt += ((anear - 1.0) / (anear - afar) * 2.0 * s + 1e-6) * ray_dir; + view_intersection_pnt += ((anear - 1.0) / (anear - afar) * 2.0 * s + 1e-6 * ln) * ray_dir; } else { discard; diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/cylinder/picking/cylinder_raytraced.gs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/cylinder/picking/cylinder_raytraced.gs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/cylinder/picking/cylinder_raytraced.gs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/cylinder/picking/cylinder_raytraced.gs 2017-07-27 16:52:45.000000000 +0000 @@ -44,12 +44,13 @@ vec4 u; if(cylinder_view_axis_gs[0].y != 0.0 || cylinder_view_axis_gs[0].x != 0.0) - u = normalize(vec4(cylinder_view_axis_gs[0].y, -cylinder_view_axis_gs[0].x, 0.0, 0.0)) * cylinder_radius_gs[0]; + u = normalize(vec4(cylinder_view_axis_gs[0].y, -cylinder_view_axis_gs[0].x, 0.0, 0.0)); else if(cylinder_view_axis_gs[0].z != 0.0) - u = normalize(vec4(-cylinder_view_axis_gs[0].z, 0.0, cylinder_view_axis_gs[0].x, 0.0)) * cylinder_radius_gs[0]; + u = normalize(vec4(-cylinder_view_axis_gs[0].z, 0.0, cylinder_view_axis_gs[0].x, 0.0)); else u = vec4(0.0); vec4 v = vec4(normalize(cross(cylinder_view_axis_gs[0].xyz, u.xyz)), 0.0) * cylinder_radius_gs[0]; + u *= cylinder_radius_gs[0]; cylinder_color_fs = cylinder_color_gs[0]; cylinder_radius_sq_fs = cylinder_radius_gs[0] * cylinder_radius_gs[0]; diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/geometry/sphere/picking/sphere.gs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/geometry/sphere/picking/sphere.gs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/geometry/sphere/picking/sphere.gs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/geometry/sphere/picking/sphere.gs 2017-07-27 16:52:45.000000000 +0000 @@ -24,6 +24,7 @@ // Inputs from calling program: uniform mat4 projection_matrix; +uniform float radius_scalingfactor; // Inputs from vertex shader in vec4 particle_color_gs[1]; @@ -36,7 +37,8 @@ void main() { - float rsq = particle_radius_gs[0] * particle_radius_gs[0]; + float radius = radius_scalingfactor * particle_radius_gs[0]; + float rsq = radius * radius; #if 0 // This code leads, which generates a single triangle strip for the cube, seems to be @@ -145,10 +147,10 @@ // Generate 6 triangle strips to be compatible with the Intel graphics driver on Linux. - vec4 corner = projection_matrix * (gl_in[0].gl_Position - vec4(particle_radius_gs[0], particle_radius_gs[0], particle_radius_gs[0], 0)); - vec4 dx = projection_matrix * vec4(2 * particle_radius_gs[0], 0, 0, 0); - vec4 dy = projection_matrix * vec4(0, 2 * particle_radius_gs[0], 0, 0); - vec4 dz = projection_matrix * vec4(0, 0, 2 * particle_radius_gs[0], 0); + vec4 corner = projection_matrix * (gl_in[0].gl_Position - vec4(radius, radius, radius, 0)); + vec4 dx = projection_matrix * vec4(2 * radius, 0, 0, 0); + vec4 dy = projection_matrix * vec4(0, 2 * radius, 0, 0); + vec4 dz = projection_matrix * vec4(0, 0, 2 * radius, 0); // -X particle_color_fs = particle_color_gs[0]; diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/geometry/sphere/picking/sphere_tristrip.vs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/geometry/sphere/picking/sphere_tristrip.vs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/geometry/sphere/picking/sphere_tristrip.vs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/geometry/sphere/picking/sphere_tristrip.vs 2017-07-27 16:52:45.000000000 +0000 @@ -25,6 +25,7 @@ uniform mat4 modelviewprojection_matrix; uniform int pickingBaseID; uniform vec3 cubeVerts[14]; +uniform float radius_scalingfactor; #if __VERSION__ >= 130 @@ -54,7 +55,7 @@ { #if __VERSION__ >= 130 - particle_radius_squared_fs = particle_radius * particle_radius; + particle_radius_squared_fs = particle_radius * particle_radius * radius_scalingfactor * radius_scalingfactor; particle_view_pos_fs = vec3(modelview_matrix * vec4(position, 1)); // Compute color from object ID. @@ -66,11 +67,11 @@ float((objectID >> 24) & 0xFF) / 255.0); // Transform and project vertex. - gl_Position = modelviewprojection_matrix * vec4(position + cubeVerts[gl_VertexID % 14] * particle_radius, 1); + gl_Position = modelviewprojection_matrix * vec4(position + cubeVerts[gl_VertexID % 14] * particle_radius * radius_scalingfactor, 1); #else - particle_radius_squared_fs = particle_radius * particle_radius; + particle_radius_squared_fs = particle_radius * particle_radius * radius_scalingfactor * radius_scalingfactor; particle_view_pos_fs = vec3(modelview_matrix * gl_Vertex); // Compute color from object ID. @@ -83,7 +84,7 @@ // Transform and project vertex. int cubeCorner = int(mod(vertexID+0.5, 14.0)); - gl_Position = modelviewprojection_matrix * (gl_Vertex + vec4(cubeVerts[cubeCorner] * particle_radius, 0)); + gl_Position = modelviewprojection_matrix * (gl_Vertex + vec4(cubeVerts[cubeCorner] * particle_radius * radius_scalingfactor, 0)); #endif } diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/geometry/sphere/sphere.gs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/geometry/sphere/sphere.gs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/geometry/sphere/sphere.gs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/geometry/sphere/sphere.gs 2017-07-27 16:52:45.000000000 +0000 @@ -24,6 +24,7 @@ // Inputs from calling program: uniform mat4 projection_matrix; +uniform float radius_scalingfactor; // Inputs from vertex shader in vec4 particle_color_gs[1]; @@ -36,7 +37,8 @@ void main() { - float rsq = particle_radius_gs[0] * particle_radius_gs[0]; + float radius = radius_scalingfactor * particle_radius_gs[0]; + float rsq = radius * radius; #if 0 // This code leads, which generates a single triangle strip for the cube, seems to be @@ -144,10 +146,10 @@ // Generate 6 triangle strips to be compatible with the Intel graphics driver on Linux. - vec4 corner = projection_matrix * (gl_in[0].gl_Position - vec4(particle_radius_gs[0], particle_radius_gs[0], particle_radius_gs[0], 0)); - vec4 dx = projection_matrix * vec4(2 * particle_radius_gs[0], 0, 0, 0); - vec4 dy = projection_matrix * vec4(0, 2 * particle_radius_gs[0], 0, 0); - vec4 dz = projection_matrix * vec4(0, 0, 2 * particle_radius_gs[0], 0); + vec4 corner = projection_matrix * (gl_in[0].gl_Position - vec4(radius, radius, radius, 0)); + vec4 dx = projection_matrix * vec4(2 * radius, 0, 0, 0); + vec4 dy = projection_matrix * vec4(0, 2 * radius, 0, 0); + vec4 dz = projection_matrix * vec4(0, 0, 2 * radius, 0); // -X particle_color_fs = particle_color_gs[0]; diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/geometry/sphere/sphere_tristrip.vs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/geometry/sphere/sphere_tristrip.vs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/geometry/sphere/sphere_tristrip.vs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/geometry/sphere/sphere_tristrip.vs 2017-07-27 16:52:45.000000000 +0000 @@ -24,6 +24,7 @@ uniform mat4 projection_matrix; uniform mat4 modelviewprojection_matrix; uniform vec3 cubeVerts[14]; +uniform float radius_scalingfactor; #if __VERSION__ >= 130 @@ -54,7 +55,7 @@ #if __VERSION__ >= 130 // Forward color to fragment shader. particle_color_fs = color; - particle_radius_squared_fs = particle_radius * particle_radius; + particle_radius_squared_fs = particle_radius * particle_radius * radius_scalingfactor * radius_scalingfactor; particle_view_pos_fs = vec3(modelview_matrix * vec4(position, 1)); // Transform and project vertex. @@ -62,11 +63,11 @@ #else // Forward color to fragment shader. gl_FrontColor = gl_Color; - particle_radius_squared_fs = particle_radius * particle_radius; + particle_radius_squared_fs = particle_radius * particle_radius * radius_scalingfactor * radius_scalingfactor; particle_view_pos_fs = vec3(modelview_matrix * gl_Vertex); // Transform and project vertex. int cubeCorner = int(mod(vertexID+0.5, 14.0)); - gl_Position = modelviewprojection_matrix * (gl_Vertex + vec4(cubeVerts[cubeCorner] * particle_radius, 0)); + gl_Position = modelviewprojection_matrix * (gl_Vertex + vec4(cubeVerts[cubeCorner] * particle_radius * radius_scalingfactor, 0)); #endif } diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/with_depth_tri.vs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/with_depth_tri.vs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/with_depth_tri.vs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/with_depth_tri.vs 2017-07-27 16:52:45.000000000 +0000 @@ -24,6 +24,7 @@ uniform mat4 projection_matrix; uniform vec2 imposter_texcoords[6]; uniform vec4 imposter_voffsets[6]; +uniform float radius_scalingfactor; uniform int pickingBaseID; #if __VERSION__ >= 130 @@ -69,7 +70,7 @@ texcoords = imposter_texcoords[gl_VertexID % 6]; // Transform and project particle position. - gl_Position = projection_matrix * (eye_position + particle_radius * imposter_voffsets[gl_VertexID % 6]); + gl_Position = projection_matrix * (eye_position + (particle_radius * radius_scalingfactor) * imposter_voffsets[gl_VertexID % 6]); #else float objectID = pickingBaseID + floor(vertexID / 6); @@ -88,12 +89,12 @@ gl_TexCoord[0].xy = imposter_texcoords[cornerIndex]; // Transform and project particle position. - gl_Position = projection_matrix * (eye_position + particle_radius * imposter_voffsets[cornerIndex]); + gl_Position = projection_matrix * (eye_position + (particle_radius * radius_scalingfactor) * imposter_voffsets[cornerIndex]); #endif // Forward particle radius to fragment shader. - particle_radius_fs = particle_radius; + particle_radius_fs = particle_radius * radius_scalingfactor; // Pass particle position in eye coordinates to fragment shader. ze0 = eye_position.z; diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/with_depth.vs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/with_depth.vs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/with_depth.vs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/with_depth.vs 2017-07-27 16:52:45.000000000 +0000 @@ -22,6 +22,7 @@ // Inputs from calling program: uniform mat4 modelviewprojection_matrix; uniform mat4 modelview_matrix; +uniform float radius_scalingfactor; uniform int pickingBaseID; #if __VERSION__ >= 130 @@ -48,7 +49,7 @@ float((objectID >> 16) & 0xFF) / 255.0, float((objectID >> 24) & 0xFF) / 255.0); - particle_radius_gs = particle_radius; + particle_radius_gs = particle_radius * radius_scalingfactor; particle_ze0_gs = modelview_matrix[0][2] * position.x + modelview_matrix[1][2] * position.y + modelview_matrix[2][2] * position.z + modelview_matrix[3][2]; gl_Position = modelviewprojection_matrix * vec4(position, 1.0); #endif diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/without_depth_tri.vs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/without_depth_tri.vs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/without_depth_tri.vs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/without_depth_tri.vs 2017-07-27 16:52:45.000000000 +0000 @@ -24,6 +24,7 @@ uniform mat4 projection_matrix; uniform vec2 imposter_texcoords[6]; uniform vec4 imposter_voffsets[6]; +uniform float radius_scalingfactor; uniform int pickingBaseID; #if __VERSION__ >= 130 @@ -63,7 +64,7 @@ texcoords = imposter_texcoords[gl_VertexID % 6]; // Transform and project particle position. - gl_Position = projection_matrix * (eye_position + particle_radius * imposter_voffsets[gl_VertexID % 6]); + gl_Position = projection_matrix * (eye_position + (particle_radius * radius_scalingfactor) * imposter_voffsets[gl_VertexID % 6]); #else float objectID = pickingBaseID + floor(vertexID / 6); @@ -82,6 +83,6 @@ gl_TexCoord[0].xy = imposter_texcoords[cornerIndex]; // Transform and project particle position. - gl_Position = projection_matrix * (eye_position + particle_radius * imposter_voffsets[cornerIndex]); + gl_Position = projection_matrix * (eye_position + (particle_radius * radius_scalingfactor) * imposter_voffsets[cornerIndex]); #endif } diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/without_depth.vs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/without_depth.vs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/without_depth.vs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/picking/without_depth.vs 2017-07-27 16:52:45.000000000 +0000 @@ -21,6 +21,7 @@ // Inputs from calling program: uniform mat4 modelviewprojection_matrix; +uniform float radius_scalingfactor; uniform int pickingBaseID; #if __VERSION__ >= 130 @@ -46,7 +47,7 @@ float((objectID >> 16) & 0xFF) / 255.0, float((objectID >> 24) & 0xFF) / 255.0); - particle_radius_gs = particle_radius; + particle_radius_gs = particle_radius * radius_scalingfactor; gl_Position = modelviewprojection_matrix * vec4(position, 1.0); #endif } diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/with_depth_tri.vs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/with_depth_tri.vs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/with_depth_tri.vs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/with_depth_tri.vs 2017-07-27 16:52:45.000000000 +0000 @@ -24,6 +24,7 @@ uniform mat4 projection_matrix; uniform vec2 imposter_texcoords[6]; uniform vec4 imposter_voffsets[6]; +uniform float radius_scalingfactor; #if __VERSION__ >= 130 @@ -62,7 +63,7 @@ texcoords = imposter_texcoords[gl_VertexID % 6]; // Transform and project particle position. - gl_Position = projection_matrix * (eye_position + particle_radius * imposter_voffsets[gl_VertexID % 6]); + gl_Position = projection_matrix * (eye_position + (particle_radius * radius_scalingfactor) * imposter_voffsets[gl_VertexID % 6]); #else // Pass color to fragment shader. @@ -77,11 +78,11 @@ gl_TexCoord[0].xy = imposter_texcoords[cornerIndex]; // Transform and project particle position. - gl_Position = projection_matrix * (eye_position + particle_radius * imposter_voffsets[cornerIndex]); + gl_Position = projection_matrix * (eye_position + (particle_radius * radius_scalingfactor) * imposter_voffsets[cornerIndex]); #endif // Forward particle radius to fragment shader. - particle_radius_fs = particle_radius; + particle_radius_fs = particle_radius * radius_scalingfactor; // Pass particle position in eye coordinates to fragment shader. ze0 = eye_position.z; diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/with_depth.vs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/with_depth.vs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/with_depth.vs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/with_depth.vs 2017-07-27 16:52:45.000000000 +0000 @@ -22,6 +22,7 @@ // Inputs from calling program: uniform mat4 modelviewprojection_matrix; uniform mat4 modelview_matrix; +uniform float radius_scalingfactor; #if __VERSION__ >= 130 @@ -41,7 +42,7 @@ { #if __VERSION__ >= 130 particle_color_gs = color; - particle_radius_gs = particle_radius; + particle_radius_gs = particle_radius * radius_scalingfactor; particle_ze0_gs = modelview_matrix[0][2] * position.x + modelview_matrix[1][2] * position.y + modelview_matrix[2][2] * position.z + modelview_matrix[3][2]; gl_Position = modelviewprojection_matrix * vec4(position, 1.0); #endif diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/without_depth_tri.vs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/without_depth_tri.vs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/without_depth_tri.vs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/without_depth_tri.vs 2017-07-27 16:52:45.000000000 +0000 @@ -24,6 +24,7 @@ uniform mat4 projection_matrix; uniform vec2 imposter_texcoords[6]; uniform vec4 imposter_voffsets[6]; +uniform float radius_scalingfactor; #if __VERSION__ >= 130 // The particle data: @@ -53,7 +54,7 @@ // Transform and project particle position. vec4 eye_position = modelview_matrix * vec4(position, 1); - gl_Position = projection_matrix * (eye_position + particle_radius * imposter_voffsets[gl_VertexID % 6]); + gl_Position = projection_matrix * (eye_position + (particle_radius * radius_scalingfactor) * imposter_voffsets[gl_VertexID % 6]); #else // Pass color to fragment shader. particle_color_fs = gl_Color; @@ -66,7 +67,7 @@ // Assign texture coordinates. gl_TexCoord[0].xy = imposter_texcoords[cornerIndex]; - gl_Position = projection_matrix * (eye_position + particle_radius * imposter_voffsets[cornerIndex]); + gl_Position = projection_matrix * (eye_position + (particle_radius * radius_scalingfactor) * imposter_voffsets[cornerIndex]); #endif } diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/without_depth.vs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/without_depth.vs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/imposter/sphere/without_depth.vs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/imposter/sphere/without_depth.vs 2017-07-27 16:52:45.000000000 +0000 @@ -21,6 +21,7 @@ // Inputs from calling program: uniform mat4 modelviewprojection_matrix; +uniform float radius_scalingfactor; #if __VERSION__ >= 130 @@ -39,7 +40,7 @@ { #if __VERSION__ >= 130 particle_color_gs = color; - particle_radius_gs = particle_radius; + particle_radius_gs = particle_radius * radius_scalingfactor; gl_Position = modelviewprojection_matrix * vec4(position, 1.0); #endif } diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/pointsprites/sphere/picking/with_depth.vs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/pointsprites/sphere/picking/with_depth.vs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/pointsprites/sphere/picking/with_depth.vs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/pointsprites/sphere/picking/with_depth.vs 2017-07-27 16:52:45.000000000 +0000 @@ -24,6 +24,7 @@ uniform mat4 modelview_matrix; uniform mat4 projection_matrix; uniform int pickingBaseID; +uniform float radius_scalingfactor; #if __VERSION__ >= 130 @@ -84,7 +85,7 @@ gl_PointSize = basePointSize * particle_radius / (eye_position.z * projection_matrix[2][3] + projection_matrix[3][3]); // Forward particle radius to fragment shader. - particle_radius_fs = particle_radius; + particle_radius_fs = particle_radius * radius_scalingfactor; // Pass particle position in eye coordinates to fragment shader. ze0 = eye_position.z; diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/pointsprites/sphere/with_depth.vs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/pointsprites/sphere/with_depth.vs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/pointsprites/sphere/with_depth.vs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/pointsprites/sphere/with_depth.vs 2017-07-27 16:52:45.000000000 +0000 @@ -23,6 +23,7 @@ uniform float basePointSize; uniform mat4 modelview_matrix; uniform mat4 projection_matrix; +uniform float radius_scalingfactor; #if __VERSION__ >= 130 @@ -67,11 +68,11 @@ gl_Position = projection_matrix * eye_position; - // Compute sprite size. + // Compute sprite size. gl_PointSize = basePointSize * particle_radius / (eye_position.z * projection_matrix[2][3] + projection_matrix[3][3]); // Forward particle radius to fragment shader. - particle_radius_fs = particle_radius; + particle_radius_fs = particle_radius * radius_scalingfactor; // Pass particle position in eye coordinates to fragment shader. ze0 = eye_position.z; diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/pointsprites/sphere/without_depth.vs ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/pointsprites/sphere/without_depth.vs --- ovito-2.8.1+dfsg2/src/opengl_renderer/resources/glsl/particles/pointsprites/sphere/without_depth.vs 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/resources/glsl/particles/pointsprites/sphere/without_depth.vs 2017-07-27 16:52:45.000000000 +0000 @@ -58,4 +58,3 @@ // Compute sprite size. gl_PointSize = basePointSize * particle_radius / (eye_position.z * projection_matrix[2][3] + projection_matrix[3][3]); } - diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/StandardSceneRenderer.cpp ovito-2.9.0+dfsg1/src/opengl_renderer/StandardSceneRenderer.cpp --- ovito-2.8.1+dfsg2/src/opengl_renderer/StandardSceneRenderer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/StandardSceneRenderer.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,160 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2013) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "StandardSceneRenderer.h" + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(StandardSceneRenderer, OpenGLSceneRenderer); +DEFINE_PROPERTY_FIELD(StandardSceneRenderer, antialiasingLevel, "AntialiasingLevel"); +SET_PROPERTY_FIELD_LABEL(StandardSceneRenderer, antialiasingLevel, "Antialiasing level"); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(StandardSceneRenderer, antialiasingLevel, IntegerParameterUnit, 1, 6); + +/****************************************************************************** +* Prepares the renderer for rendering and sets the data set that is being rendered. +******************************************************************************/ +bool StandardSceneRenderer::startRender(DataSet* dataset, RenderSettings* settings) +{ + if(Application::instance()->headlessMode()) + throwException(tr("Cannot use OpenGL renderer when running in headless mode. " + "Please use a different rendering engine or run program on a machine where access to " + "graphics hardware is possible.")); + + if(!OpenGLSceneRenderer::startRender(dataset, settings)) + return false; + + int sampling = std::max(1, antialiasingLevel()); + + if(Application::instance()->guiMode()) { + // Create a temporary OpenGL context for rendering to an offscreen buffer. + _offscreenContext.reset(new QOpenGLContext()); + _offscreenContext->setFormat(OpenGLSceneRenderer::getDefaultSurfaceFormat()); + // It should share its resources with the viewport renderer. + const QVector& viewports = renderDataset()->viewportConfig()->viewports(); + if(!viewports.empty() && viewports.front()->window()) + _offscreenContext->setShareContext(viewports.front()->window()->glcontext()); + if(!_offscreenContext->create()) + throwException(tr("Failed to create OpenGL context for rendering.")); + } + else { + // Create new OpenGL context for rendering in console mode. + OVITO_ASSERT(QOpenGLContext::currentContext() == nullptr); + _offscreenContext.reset(new QOpenGLContext()); + _offscreenContext->setFormat(OpenGLSceneRenderer::getDefaultSurfaceFormat()); + if(!_offscreenContext->create()) + throwException(tr("Failed to create OpenGL context for rendering.")); + } + + // Create offscreen buffer. + if(_offscreenSurface.isNull()) + _offscreenSurface.reset(new QOffscreenSurface()); + _offscreenSurface->setFormat(_offscreenContext->format()); + _offscreenSurface->create(); + if(!_offscreenSurface->isValid()) + throwException(tr("Failed to create offscreen rendering surface.")); + + // Make the context current. + if(!_offscreenContext->makeCurrent(_offscreenSurface.data())) + throwException(tr("Failed to make OpenGL context current.")); + + // Create OpenGL framebuffer. + _framebufferSize = QSize(settings->outputImageWidth() * sampling, settings->outputImageHeight() * sampling); + QOpenGLFramebufferObjectFormat framebufferFormat; + framebufferFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + _framebufferObject.reset(new QOpenGLFramebufferObject(_framebufferSize.width(), _framebufferSize.height(), framebufferFormat)); + if(!_framebufferObject->isValid()) + throwException(tr("Failed to create OpenGL framebuffer object for offscreen rendering.")); + + // Bind OpenGL buffer. + if(!_framebufferObject->bind()) + throwException(tr("Failed to bind OpenGL framebuffer object for offscreen rendering.")); + + return true; +} + +/****************************************************************************** +* This method is called just before renderFrame() is called. +******************************************************************************/ +void StandardSceneRenderer::beginFrame(TimePoint time, const ViewProjectionParameters& params, Viewport* vp) +{ + // Make GL context current. + if(!_offscreenContext || !_offscreenContext->makeCurrent(_offscreenSurface.data())) + throwException(tr("Failed to make OpenGL context current.")); + + OpenGLSceneRenderer::beginFrame(time, params, vp); + + // Setup GL viewport. + setRenderingViewport(0, 0, _framebufferSize.width(), _framebufferSize.height()); + + // Set rendering background color. + if(!renderSettings()->generateAlphaChannel()) { + Color backgroundColor = renderSettings()->backgroundColor(); + setClearColor(ColorA(backgroundColor)); + } + else setClearColor(ColorA(0, 0, 0, 0)); +} + +/****************************************************************************** +* Renders the current animation frame. +******************************************************************************/ +bool StandardSceneRenderer::renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, TaskManager& taskManager) +{ + // Let the base class do the main rendering work. + if(!OpenGLSceneRenderer::renderFrame(frameBuffer, stereoTask, taskManager)) + return false; + + // Flush the contents to the FBO before extracting image. + glcontext()->swapBuffers(_offscreenSurface.data()); + + // Fetch rendered image from OpenGL framebuffer. + QImage bufferImage = _framebufferObject->toImage(); + + // Scale it down to the output size. + QImage image = bufferImage.scaled(frameBuffer->image().width(), frameBuffer->image().height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + + // Copy OpenGL image to the output frame buffer. + frameBuffer->image() = image; + frameBuffer->update(); + + return true; +} + +/****************************************************************************** +* Is called after rendering has finished. +******************************************************************************/ +void StandardSceneRenderer::endRender() +{ + QOpenGLFramebufferObject::bindDefault(); + QOpenGLContext* ctxt = QOpenGLContext::currentContext(); + if(ctxt) ctxt->doneCurrent(); + _framebufferObject.reset(); + _offscreenContext.reset(); + _offscreenSurface.reset(); + OpenGLSceneRenderer::endRender(); +} + +OVITO_END_INLINE_NAMESPACE +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/opengl_renderer/StandardSceneRenderer.h ovito-2.9.0+dfsg1/src/opengl_renderer/StandardSceneRenderer.h --- ovito-2.8.1+dfsg2/src/opengl_renderer/StandardSceneRenderer.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/opengl_renderer/StandardSceneRenderer.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,93 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2013) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include "OpenGLSceneRenderer.h" + +#include +#include +#include + +namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) + +/** + * \brief This is the default scene renderer used for high-quality image output. + */ +class OVITO_OPENGL_RENDERER_EXPORT StandardSceneRenderer : public OpenGLSceneRenderer +{ +public: + + /// Default constructor. + Q_INVOKABLE StandardSceneRenderer(DataSet* dataset) : OpenGLSceneRenderer(dataset), _antialiasingLevel(3) { + INIT_PROPERTY_FIELD(antialiasingLevel); + } + + /// Prepares the renderer for rendering and sets the data set that is being rendered. + virtual bool startRender(DataSet* dataset, RenderSettings* settings) override; + + /// This method is called just before renderFrame() is called. + virtual void beginFrame(TimePoint time, const ViewProjectionParameters& params, Viewport* vp) override; + + /// Renders the current animation frame. + virtual bool renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, TaskManager& taskManager) override; + + /// Is called after rendering has finished. + virtual void endRender() override; + + /// Returns whether this renderer is rendering an interactive viewport. + /// \return true if rendering a real-time viewport; false if rendering an output image. + virtual bool isInteractive() const override { return false; } + +protected: + + /// Returns the supersampling level to use. + virtual int antialiasingLevelInternal() override { return antialiasingLevel(); } + +private: + + /// Controls the number of sub-pixels to render. + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, antialiasingLevel, setAntialiasingLevel); + + /// The offscreen surface used to render into an image buffer using OpenGL. + QScopedPointer _offscreenSurface; + + /// The temporary OpenGL rendering context. + QScopedPointer _offscreenContext; + + /// The OpenGL framebuffer. + QScopedPointer _framebufferObject; + + /// The resolution of the offscreen framebuffer. + QSize _framebufferSize; + + Q_OBJECT + OVITO_OBJECT + + Q_CLASSINFO("DisplayName", "OpenGL renderer"); +}; + +OVITO_END_INLINE_NAMESPACE +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/plugins/CMakeLists.txt ovito-2.9.0+dfsg1/src/plugins/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/plugins/CMakeLists.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -19,62 +19,52 @@ # ############################################################################### -# Create the plugins directory. -FILE(MAKE_DIRECTORY ${OVITO_PLUGINS_DIRECTORY}) +# Create the plugins library and manifest directories. +FILE(MAKE_DIRECTORY "${OVITO_PLUGINS_DIRECTORY}") IF(OVITO_BUILD_PLUGIN_PYSCRIPT) ADD_SUBDIRECTORY(pyscript) SET(OVITOS_EXECUTABLE ${OVITOS_EXECUTABLE} PARENT_SCOPE) -ELSE() - FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/PyScript.json) - FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/PyScriptGui.json) ENDIF() IF(OVITO_BUILD_PLUGIN_PARTICLES) ADD_SUBDIRECTORY(particles) -ELSE() - FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/Particles.json) - FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/ParticlesGui.json) ENDIF() IF(OVITO_BUILD_PLUGIN_TACHYON) ADD_SUBDIRECTORY(tachyon) -ELSE() - FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/Tachyon.json) - FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/TachyonGui.json) ENDIF() IF(OVITO_BUILD_PLUGIN_MESH) ADD_SUBDIRECTORY(mesh) -ELSE() - FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/Mesh.json) ENDIF() IF(OVITO_BUILD_PLUGIN_CRYSTALANALYSIS) ADD_SUBDIRECTORY(crystalanalysis) -ELSE() - FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/CrystalAnalysis.json) - FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/CrystalAnalysisGui.json) ENDIF() IF(OVITO_BUILD_PLUGIN_NETCDFPLUGIN) ADD_SUBDIRECTORY(netcdf) -ELSE() - FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/NetCDFPlugin.json) - FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/NetCDFPluginGui.json) ENDIF() IF(OVITO_BUILD_PLUGIN_POVRAY) ADD_SUBDIRECTORY(povray) -ELSE() - FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/POVRay.json) - FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/POVRayGui.json) ENDIF() IF(OVITO_BUILD_PLUGIN_OPENBABELPLUGIN) ADD_SUBDIRECTORY(openbabel) -ELSE() - FILE(REMOVE ${OVITO_PLUGINS_DIRECTORY}/OpenBabelPlugin.json) +ENDIF() + +IF(OVITO_BUILD_PLUGIN_VR) + ADD_SUBDIRECTORY(vr) +ENDIF() + +IF(OVITO_BUILD_PLUGIN_CORRELATION) + ADD_SUBDIRECTORY(correlation) +ENDIF() + +IF(OVITO_BUILD_PLUGIN_VOROTOP) + ADD_SUBDIRECTORY(vorotop) ENDIF() # Propagate list of plugins to parent scope. diff -Nru ovito-2.8.1+dfsg2/src/plugins/correlation/CMakeLists.txt ovito-2.9.0+dfsg1/src/plugins/correlation/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/plugins/correlation/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/correlation/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,56 @@ +############################################################################### +# +# Copyright (2017) Alexander Stukowski +# Copyright (2016) Lars Pastewka +# +# This file is part of OVITO (Open Visualization Tool). +# +# OVITO is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# OVITO is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################### + +# Locate the FFTW library. +FIND_PACKAGE(FFTW3 REQUIRED) + +SET(SourceFiles + CorrelationFunctionModifier.cpp +) + +OVITO_STANDARD_PLUGIN( + CorrelationFunctionPlugin + SOURCES ${SourceFiles} + PLUGIN_DEPENDENCIES Particles + PRIVATE_LIB_DEPENDENCIES ${FFTW3_LIBRARIES} +) + +TARGET_INCLUDE_DIRECTORIES(CorrelationFunctionPlugin PRIVATE "${FFTW3_INCLUDE_DIRS}") + +# Build corresponding GUI plugin. +IF(OVITO_BUILD_GUI) + ADD_SUBDIRECTORY(gui) +ENDIF() + +IF(WIN32) + # Deploy FFTW3 dll. + LIST(GET FFTW3_LIBRARIES 0 FFTW3_FIRST_LIBRARY) + GET_FILENAME_COMPONENT(FFTW3_LIBRARY_DIR "${FFTW3_FIRST_LIBRARY}" PATH) + GET_FILENAME_COMPONENT(FFTW3_LIBRARY_NAME "${FFTW3_FIRST_LIBRARY}" NAME_WE) + OVITO_INSTALL_DLL("${FFTW3_LIBRARY_DIR}/${FFTW3_LIBRARY_NAME}.dll") +ELSEIF(UNIX AND NOT APPLE AND OVITO_REDISTRIBUTABLE_PACKAGE) + # Deploy FFTW3 shared library. + OVITO_INSTALL_SHARED_LIB("${FFTW3_LIBRARIES}" "${OVITO_RELATIVE_LIBRARY_DIRECTORY}") +ENDIF() + +# Propagate list of plugins to parent scope. +SET(OVITO_PLUGIN_LIST ${OVITO_PLUGIN_LIST} PARENT_SCOPE) diff -Nru ovito-2.8.1+dfsg2/src/plugins/correlation/CorrelationFunctionModifier.cpp ovito-2.9.0+dfsg1/src/plugins/correlation/CorrelationFunctionModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/correlation/CorrelationFunctionModifier.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/correlation/CorrelationFunctionModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,839 @@ +// +// Copyright (2014) Alexander Stukowski +// Copyright (2017) Lars Pastewka +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "CorrelationFunctionModifier.h" + +#include + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CorrelationFunctionModifier, AsynchronousParticleModifier); +DEFINE_PROPERTY_FIELD(CorrelationFunctionModifier, sourceProperty1, "SourceProperty1"); +DEFINE_PROPERTY_FIELD(CorrelationFunctionModifier, sourceProperty2, "SourceProperty2"); +DEFINE_FLAGS_PROPERTY_FIELD(CorrelationFunctionModifier, averagingDirection, "BinDirection", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(CorrelationFunctionModifier, fftGridSpacing, "FftGridSpacing"); +DEFINE_FLAGS_PROPERTY_FIELD(CorrelationFunctionModifier, applyWindow, "applyWindow", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CorrelationFunctionModifier, doComputeNeighCorrelation, "doComputeNeighCorrelation", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CorrelationFunctionModifier, neighCutoff, "NeighCutoff", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CorrelationFunctionModifier, numberOfNeighBins, "NumberOfNeighBins", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CorrelationFunctionModifier, normalizeRealSpace, "NormalizeRealSpace", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(CorrelationFunctionModifier, typeOfRealSpacePlot, "TypeOfRealSpacePlot"); +DEFINE_FLAGS_PROPERTY_FIELD(CorrelationFunctionModifier, normalizeReciprocalSpace, "NormalizeReciprocalSpace", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(CorrelationFunctionModifier, typeOfReciprocalSpacePlot, "TypeOfReciprocalSpacePlot"); +DEFINE_PROPERTY_FIELD(CorrelationFunctionModifier, fixRealSpaceXAxisRange, "FixRealSpaceXAxisRange"); +DEFINE_FLAGS_PROPERTY_FIELD(CorrelationFunctionModifier, realSpaceXAxisRangeStart, "RealSpaceXAxisRangeStart", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CorrelationFunctionModifier, realSpaceXAxisRangeEnd, "RealSpaceXAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(CorrelationFunctionModifier, fixRealSpaceYAxisRange, "FixRealSpaceYAxisRange"); +DEFINE_FLAGS_PROPERTY_FIELD(CorrelationFunctionModifier, realSpaceYAxisRangeStart, "RealSpaceYAxisRangeStart", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CorrelationFunctionModifier, realSpaceYAxisRangeEnd, "RealSpaceYAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(CorrelationFunctionModifier, fixReciprocalSpaceXAxisRange, "FixReciprocalSpaceXAxisRange"); +DEFINE_FLAGS_PROPERTY_FIELD(CorrelationFunctionModifier, reciprocalSpaceXAxisRangeStart, "ReciprocalSpaceXAxisRangeStart", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CorrelationFunctionModifier, reciprocalSpaceXAxisRangeEnd, "ReciprocalSpaceXAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(CorrelationFunctionModifier, fixReciprocalSpaceYAxisRange, "FixReciprocalSpaceYAxisRange"); +DEFINE_FLAGS_PROPERTY_FIELD(CorrelationFunctionModifier, reciprocalSpaceYAxisRangeStart, "ReciprocalSpaceYAxisRangeStart", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CorrelationFunctionModifier, reciprocalSpaceYAxisRangeEnd, "ReciprocalSpaceYAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, sourceProperty1, "First property"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, sourceProperty2, "Second property"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, averagingDirection, "Averaging direction"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, fftGridSpacing, "FFT grid spacing"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, applyWindow, "Apply window function to nonperiodic directions"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, doComputeNeighCorrelation, "Direct summation"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, neighCutoff, "Neighbor cutoff radius"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, numberOfNeighBins, "Number of neighbor bins"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, normalizeRealSpace, "Normalize correlation function"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, normalizeReciprocalSpace, "Normalize correlation function"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CorrelationFunctionModifier, fftGridSpacing, WorldParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CorrelationFunctionModifier, neighCutoff, WorldParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(CorrelationFunctionModifier, numberOfNeighBins, IntegerParameterUnit, 4, 100000); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, fixRealSpaceXAxisRange, "Fix x-range"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, realSpaceXAxisRangeStart, "X-range start"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, realSpaceXAxisRangeEnd, "X-range end"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, fixRealSpaceYAxisRange, "Fix y-range"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, realSpaceYAxisRangeStart, "Y-range start"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, realSpaceYAxisRangeEnd, "Y-range end"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, fixReciprocalSpaceXAxisRange, "Fix x-range"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, reciprocalSpaceXAxisRangeStart, "X-range start"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, reciprocalSpaceXAxisRangeEnd, "X-range end"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, fixReciprocalSpaceYAxisRange, "Fix y-range"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, reciprocalSpaceYAxisRangeStart, "Y-range start"); +SET_PROPERTY_FIELD_LABEL(CorrelationFunctionModifier, reciprocalSpaceYAxisRangeEnd, "Y-range end"); + +/****************************************************************************** +* Constructs the modifier object. +******************************************************************************/ +CorrelationFunctionModifier::CorrelationFunctionModifier(DataSet* dataset) : AsynchronousParticleModifier(dataset), + _averagingDirection(RADIAL), _fftGridSpacing(3.0), _applyWindow(true), _doComputeNeighCorrelation(false), _neighCutoff(5.0), _numberOfNeighBins(50), + _normalizeRealSpace(DO_NOT_NORMALIZE), _typeOfRealSpacePlot(0), _normalizeReciprocalSpace(false), _typeOfReciprocalSpacePlot(0), + _fixRealSpaceXAxisRange(false), _realSpaceXAxisRangeStart(0.0), _realSpaceXAxisRangeEnd(1.0), + _fixRealSpaceYAxisRange(false), _realSpaceYAxisRangeStart(0.0), _realSpaceYAxisRangeEnd(1.0), + _fixReciprocalSpaceXAxisRange(false), _reciprocalSpaceXAxisRangeStart(0.0), _reciprocalSpaceXAxisRangeEnd(1.0), + _fixReciprocalSpaceYAxisRange(false), _reciprocalSpaceYAxisRangeStart(0.0), _reciprocalSpaceYAxisRangeEnd(1.0) +{ + INIT_PROPERTY_FIELD(averagingDirection); + INIT_PROPERTY_FIELD(sourceProperty1); + INIT_PROPERTY_FIELD(sourceProperty2); + INIT_PROPERTY_FIELD(fftGridSpacing); + INIT_PROPERTY_FIELD(applyWindow); + INIT_PROPERTY_FIELD(doComputeNeighCorrelation); + INIT_PROPERTY_FIELD(neighCutoff); + INIT_PROPERTY_FIELD(numberOfNeighBins); + INIT_PROPERTY_FIELD(normalizeRealSpace); + INIT_PROPERTY_FIELD(typeOfRealSpacePlot); + INIT_PROPERTY_FIELD(normalizeReciprocalSpace); + INIT_PROPERTY_FIELD(typeOfReciprocalSpacePlot); + INIT_PROPERTY_FIELD(fixRealSpaceXAxisRange); + INIT_PROPERTY_FIELD(realSpaceXAxisRangeStart); + INIT_PROPERTY_FIELD(realSpaceXAxisRangeEnd); + INIT_PROPERTY_FIELD(fixRealSpaceYAxisRange); + INIT_PROPERTY_FIELD(realSpaceYAxisRangeStart); + INIT_PROPERTY_FIELD(realSpaceYAxisRangeEnd); + INIT_PROPERTY_FIELD(fixReciprocalSpaceXAxisRange); + INIT_PROPERTY_FIELD(reciprocalSpaceXAxisRangeStart); + INIT_PROPERTY_FIELD(reciprocalSpaceXAxisRangeEnd); + INIT_PROPERTY_FIELD(fixReciprocalSpaceYAxisRange); + INIT_PROPERTY_FIELD(reciprocalSpaceYAxisRangeStart); + INIT_PROPERTY_FIELD(reciprocalSpaceYAxisRangeEnd); +} + + +/****************************************************************************** +* This method is called by the system when the modifier has been inserted +* into a pipeline. +******************************************************************************/ +void CorrelationFunctionModifier::initializeModifier(PipelineObject* pipeline, ModifierApplication* modApp) +{ + ParticleModifier::initializeModifier(pipeline, modApp); + + // Use the first available particle property from the input state as data source when the modifier is newly created. + if(sourceProperty1().isNull() || sourceProperty2().isNull()) { + PipelineFlowState input = getModifierInput(modApp); + ParticlePropertyReference bestProperty; + for(DataObject* o : input.objects()) { + ParticlePropertyObject* property = dynamic_object_cast(o); + if(property && (property->dataType() == qMetaTypeId() || property->dataType() == qMetaTypeId())) { + bestProperty = ParticlePropertyReference(property, (property->componentCount() > 1) ? 0 : -1); + } + } + if(!bestProperty.isNull()) { + if (sourceProperty1().isNull()) + setSourceProperty1(bestProperty); + if (sourceProperty2().isNull()) + setSourceProperty2(bestProperty); + } + } +} + +/****************************************************************************** +* Creates and initializes a computation engine that will compute the modifier's results. +******************************************************************************/ +std::shared_ptr CorrelationFunctionModifier::createEngine(TimePoint time, TimeInterval validityInterval) +{ + // Get the source + if(sourceProperty1().isNull()) + throwException(tr("Select a first particle property first.")); + if(sourceProperty2().isNull()) + throwException(tr("Select a second particle property first.")); + + // Get the current positions. + ParticlePropertyObject* posProperty = expectStandardProperty(ParticleProperty::PositionProperty); + + // Get the current selected properties. + ParticlePropertyObject* property1 = sourceProperty1().findInState(input()); + ParticlePropertyObject* property2 = sourceProperty2().findInState(input()); + + // Get simulation cell. + SimulationCellObject* inputCell = expectSimulationCell(); + + // Create engine object. Pass all relevant modifier parameters to the engine as well as the input data. + return std::make_shared(validityInterval, + posProperty->storage(), + property1->storage(), + std::max(0, sourceProperty1().vectorComponent()), + property2->storage(), + std::max(0, sourceProperty2().vectorComponent()), + inputCell->data(), + fftGridSpacing(), + applyWindow(), + doComputeNeighCorrelation(), + neighCutoff(), + numberOfNeighBins(), + averagingDirection()); +} + +/****************************************************************************** +* Map property onto grid. +******************************************************************************/ +void CorrelationFunctionModifier::CorrelationAnalysisEngine::mapToSpatialGrid(ParticleProperty *property, + size_t propertyVectorComponent, + const AffineTransformation &reciprocalCellMatrix, + int nX, int nY, int nZ, + QVector &gridData, + bool applyWindow) +{ + size_t vecComponent = std::max(size_t(0), propertyVectorComponent); + size_t vecComponentCount = 0; + if (property) vecComponentCount = property->componentCount(); + + int numberOfGridPoints = nX*nY*nZ; + + // Resize real space grid. + gridData.fill(0.0, numberOfGridPoints); + + // Get periodic boundary flag. + std::array pbc = cell().pbcFlags(); + + if(!property || property->size() > 0) { + const Point3* pos = positions()->constDataPoint3(); + const Point3* pos_end = pos + positions()->size(); + + if (!property) { + for (; pos != pos_end; ++pos) { + Point3 fractionalPos = reciprocalCellMatrix*(*pos); + int binIndexX = int( fractionalPos.x() * nX ); + int binIndexY = int( fractionalPos.y() * nY ); + int binIndexZ = int( fractionalPos.z() * nZ ); + FloatType window = 1; + if(pbc[0]) binIndexX = SimulationCell::modulo(binIndexX, nX); + else window *= sqrt(2./3)*(1-cos(2*FLOATTYPE_PI*fractionalPos.x())); + if(pbc[1]) binIndexY = SimulationCell::modulo(binIndexY, nY); + else window *= sqrt(2./3)*(1-cos(2*FLOATTYPE_PI*fractionalPos.y())); + if(pbc[2]) binIndexZ = SimulationCell::modulo(binIndexZ, nZ); + else window *= sqrt(2./3)*(1-cos(2*FLOATTYPE_PI*fractionalPos.z())); + if (!applyWindow) window = 1; + if(binIndexX >= 0 && binIndexX < nX && binIndexY >= 0 && binIndexY < nY && binIndexZ >= 0 && binIndexZ < nZ) { + // Store in row-major format. + size_t binIndex = binIndexZ+nZ*(binIndexY+nY*binIndexX); + gridData[binIndex] += window; + } + } + } + else if(property->dataType() == qMetaTypeId()) { + const FloatType* v = property->constDataFloat() + vecComponent; + const FloatType* v_end = v + (property->size() * vecComponentCount); + for(; v != v_end; v += vecComponentCount, ++pos) { + if(!std::isnan(*v)) { + Point3 fractionalPos = reciprocalCellMatrix*(*pos); + int binIndexX = int( fractionalPos.x() * nX ); + int binIndexY = int( fractionalPos.y() * nY ); + int binIndexZ = int( fractionalPos.z() * nZ ); + FloatType window = 1; + if(pbc[0]) binIndexX = SimulationCell::modulo(binIndexX, nX); + else window *= sqrt(2./3)*(1-cos(2*FLOATTYPE_PI*fractionalPos.x())); + if(pbc[1]) binIndexY = SimulationCell::modulo(binIndexY, nY); + else window *= sqrt(2./3)*(1-cos(2*FLOATTYPE_PI*fractionalPos.y())); + if(pbc[2]) binIndexZ = SimulationCell::modulo(binIndexZ, nZ); + else window *= sqrt(2./3)*(1-cos(2*FLOATTYPE_PI*fractionalPos.z())); + if (!applyWindow) window = 1; + if(binIndexX >= 0 && binIndexX < nX && binIndexY >= 0 && binIndexY < nY && binIndexZ >= 0 && binIndexZ < nZ) { + // Store in row-major format. + size_t binIndex = binIndexZ+nZ*(binIndexY+nY*binIndexX); + gridData[binIndex] += window*(*v); + } + } + } + } + else if(property->dataType() == qMetaTypeId()) { + const int* v = property->constDataInt() + vecComponent; + const int* v_end = v + (property->size() * vecComponentCount); + for(; v != v_end; v += vecComponentCount, ++pos) { + Point3 fractionalPos = reciprocalCellMatrix*(*pos); + int binIndexX = int( fractionalPos.x() * nX ); + int binIndexY = int( fractionalPos.y() * nY ); + int binIndexZ = int( fractionalPos.z() * nZ ); + FloatType window = 1; + if(pbc[0]) binIndexX = SimulationCell::modulo(binIndexX, nX); + else window *= sqrt(2./3)*(1-cos(2*FLOATTYPE_PI*fractionalPos.x())); + if(pbc[1]) binIndexY = SimulationCell::modulo(binIndexY, nY); + else window *= sqrt(2./3)*(1-cos(2*FLOATTYPE_PI*fractionalPos.y())); + if(pbc[2]) binIndexZ = SimulationCell::modulo(binIndexZ, nZ); + else window *= sqrt(2./3)*(1-cos(2*FLOATTYPE_PI*fractionalPos.z())); + if (!applyWindow) window = 1; + if(binIndexX >= 0 && binIndexX < nX && binIndexY >= 0 && binIndexY < nY && binIndexZ >= 0 && binIndexZ < nZ) { + // Store in row-major format. + size_t binIndex = binIndexZ+nZ*(binIndexY+nY*binIndexX); + gridData[binIndex] += window*(*v); + } + } + } + } +} + +// Use single precision FFTW if Ovito is compiled with single precision +// floating point type. +#ifdef FLOATTYPE_FLOAT +#define fftw_complex fftwf_complex +#define fftw_plan_dft_r2c_3d fftwf_plan_dft_r2c_3d +#define fftw_plan_dft_c2r_3d fftwf_plan_dft_c2r_3d +#define fftw_execute fftwf_execute +#define fftw_destroy_plan fftwf_destroy_plan +#endif + +void CorrelationFunctionModifier::CorrelationAnalysisEngine::r2cFFT(int nX, int nY, int nZ, + QVector &rData, + QVector> &cData) +{ + cData.resize(nX*nY*(nZ/2+1)); + auto plan = fftw_plan_dft_r2c_3d( + nX, nY, nZ, + rData.data(), + reinterpret_cast(cData.data()), + FFTW_ESTIMATE); + fftw_execute(plan); + fftw_destroy_plan(plan); +} + +void CorrelationFunctionModifier::CorrelationAnalysisEngine::c2rFFT(int nX, int nY, int nZ, + QVector> &cData, + QVector &rData) +{ + rData.resize(nX*nY*nZ); + auto plan = fftw_plan_dft_c2r_3d( + nX, nY, nZ, + reinterpret_cast(cData.data()), + rData.data(), + FFTW_ESTIMATE); + fftw_execute(plan); + fftw_destroy_plan(plan); +} + +/****************************************************************************** +* Compute real and reciprocal space correlation function via FFT. +******************************************************************************/ +void CorrelationFunctionModifier::CorrelationAnalysisEngine::computeFftCorrelation() +{ + // Get reciprocal cell. + AffineTransformation cellMatrix = cell().matrix(); + AffineTransformation reciprocalCellMatrix = cell().inverseMatrix(); + + // Note: Cell vectors are in columns. Those are 3-vectors. + int nX = cellMatrix.column(0).length()/fftGridSpacing(); + int nY = cellMatrix.column(1).length()/fftGridSpacing(); + int nZ = cellMatrix.column(2).length()/fftGridSpacing(); + + // Map all quantities onto a spatial grid. + QVector gridProperty1, gridProperty2; + mapToSpatialGrid(sourceProperty1(), + _vecComponent1, + reciprocalCellMatrix, + nX, nY, nZ, + gridProperty1, + _applyWindow); + + incrementProgressValue(); + if (isCanceled()) + return; + + mapToSpatialGrid(sourceProperty2(), + _vecComponent2, + reciprocalCellMatrix, + nX, nY, nZ, + gridProperty2, + _applyWindow); + + QVector gridDensity; + mapToSpatialGrid(nullptr, + _vecComponent1, + reciprocalCellMatrix, + nX, nY, nZ, + gridDensity, + _applyWindow); + incrementProgressValue(); + if (isCanceled()) + return; + + // FIXME. Apply windowing function in nonperiodic directions here. + + // Compute reciprocal-space correlation function from a product in Fourier space. + + // Compute Fourier transform of spatial grid. + QVector> ftProperty1; + r2cFFT(nX, nY, nZ, gridProperty1, ftProperty1); + + incrementProgressValue(); + if (isCanceled()) + return; + + QVector> ftProperty2; + r2cFFT(nX, nY, nZ, gridProperty2, ftProperty2); + + incrementProgressValue(); + if (isCanceled()) + return; + + QVector> ftDensity; + r2cFFT(nX, nY, nZ, gridDensity, ftDensity); + + incrementProgressValue(); + if (isCanceled()) + return; + + // Note: Reciprocal cell vectors are in rows. Those are 4-vectors. + Vector_4 recCell1 = reciprocalCellMatrix.row(0); + Vector_4 recCell2 = reciprocalCellMatrix.row(1); + Vector_4 recCell3 = reciprocalCellMatrix.row(2); + + // Compute distance of cell faces. + FloatType cellFaceDistance1 = 1/sqrt(recCell1.x()*recCell1.x() + recCell1.y()*recCell1.y() + recCell1.z()*recCell1.z()); + FloatType cellFaceDistance2 = 1/sqrt(recCell2.x()*recCell2.x() + recCell2.y()*recCell2.y() + recCell2.z()*recCell2.z()); + FloatType cellFaceDistance3 = 1/sqrt(recCell3.x()*recCell3.x() + recCell3.y()*recCell3.y() + recCell3.z()*recCell3.z()); + + FloatType minCellFaceDistance = std::min({cellFaceDistance1, cellFaceDistance2, cellFaceDistance3}); + + // Minimum reciprocal space vector is given by the minimum distance of cell faces. + FloatType minReciprocalSpaceVector = 1/minCellFaceDistance; + int numberOfWavevectorBins, dir1, dir2; + Vector_3 n(nX, nY, nZ); + + if (_averagingDirection == RADIAL) { + numberOfWavevectorBins = 1/(2*minReciprocalSpaceVector*fftGridSpacing()); + } + else { + dir1 = (_averagingDirection+1)%3; + dir2 = (_averagingDirection+2)%3; + numberOfWavevectorBins = n[dir1]*n[dir2]; + } + + // Averaged reciprocal space correlation function. + _reciprocalSpaceCorrelation.fill(0.0, numberOfWavevectorBins); + _reciprocalSpaceCorrelationX.resize(numberOfWavevectorBins); + QVector numberOfValues(numberOfWavevectorBins, 0); + + // Populate array with reciprocal space vectors. + for (int wavevectorBinIndex = 0; wavevectorBinIndex < numberOfWavevectorBins; wavevectorBinIndex++) { + _reciprocalSpaceCorrelationX[wavevectorBinIndex] = 2*FLOATTYPE_PI*(wavevectorBinIndex+0.5)*minReciprocalSpaceVector; + } + + // Compute Fourier-transformed correlation function and put it on a radial + // grid. + int binIndex = 0; + for (int binIndexX = 0; binIndexX < nX; binIndexX++) { + for (int binIndexY = 0; binIndexY < nY; binIndexY++) { + for (int binIndexZ = 0; binIndexZ < nZ/2+1; binIndexZ++, binIndex++) { + // Compute correlation function. + std::complex corr = ftProperty1[binIndex]*std::conj(ftProperty2[binIndex]); + + // Store correlation function to property1 for back transform. + ftProperty1[binIndex] = corr; + + // Compute structure factor/radial distribution function. + ftDensity[binIndex] = ftDensity[binIndex]*std::conj(ftDensity[binIndex]); + + int wavevectorBinIndex; + if (_averagingDirection == RADIAL) { + // Ignore Gamma-point for radial average. + if (binIndex == 0 && binIndexY == 0 && binIndexZ == 0) + continue; + + // Compute wavevector. + int iX = SimulationCell::modulo(binIndexX+nX/2, nX)-nX/2; + int iY = SimulationCell::modulo(binIndexY+nY/2, nY)-nY/2; + int iZ = SimulationCell::modulo(binIndexZ+nZ/2, nZ)-nZ/2; + // This is the reciprocal space vector (without a factor of 2*pi). + Vector_4 wavevector = FloatType(iX)*reciprocalCellMatrix.row(0) + + FloatType(iY)*reciprocalCellMatrix.row(1) + + FloatType(iZ)*reciprocalCellMatrix.row(2); + wavevector.w() = 0.0; + + // Compute bin index. + wavevectorBinIndex = int(std::floor(wavevector.length()/minReciprocalSpaceVector)); + } + else { + Vector_3 binIndexXYZ(binIndexX, binIndexY, binIndexZ); + wavevectorBinIndex = binIndexXYZ[dir2]+n[dir2]*binIndexXYZ[dir1]; + } + + if (wavevectorBinIndex >= 0 && wavevectorBinIndex < numberOfWavevectorBins) { + _reciprocalSpaceCorrelation[wavevectorBinIndex] += std::real(corr); + numberOfValues[wavevectorBinIndex]++; + } + } + } + } + + // Compute averages and normalize reciprocal-space correlation function. + FloatType normalizationFactor = cell().volume3D()/(sourceProperty1()->size()*sourceProperty2()->size()); + for (int wavevectorBinIndex = 0; wavevectorBinIndex < numberOfWavevectorBins; wavevectorBinIndex++) { + if (numberOfValues[wavevectorBinIndex] > 0) { + _reciprocalSpaceCorrelation[wavevectorBinIndex] *= normalizationFactor/numberOfValues[wavevectorBinIndex]; + } + } + + incrementProgressValue(); + if (isCanceled()) + return; + + // Compute long-ranged part of the real-space correlation function from the FFT convolution. + + // Computer inverse Fourier transform of correlation function. + c2rFFT(nX, nY, nZ, ftProperty1, gridProperty1); + + incrementProgressValue(); + if (isCanceled()) + return; + + c2rFFT(nX, nY, nZ, ftDensity, gridDensity); + + incrementProgressValue(); + if (isCanceled()) + return; + + // Determine number of grid points for reciprocal-spacespace correlation function. + int numberOfDistanceBins = minCellFaceDistance/(2*fftGridSpacing()); + FloatType gridSpacing = minCellFaceDistance/(2*numberOfDistanceBins); + + // Radially averaged real space correlation function. + _realSpaceCorrelation.fill(0.0, numberOfDistanceBins); + _realSpaceRDF.fill(0.0, numberOfDistanceBins); + _realSpaceCorrelationX.resize(numberOfDistanceBins); + numberOfValues.fill(0, numberOfDistanceBins); + + // Populate array with real space vectors. + for (int distanceBinIndex = 0; distanceBinIndex < numberOfDistanceBins; distanceBinIndex++) { + _realSpaceCorrelationX[distanceBinIndex] = (distanceBinIndex+0.5)*gridSpacing; + } + + // Put real-space correlation function on a radial grid. + binIndex = 0; + for (int binIndexX = 0; binIndexX < nX; binIndexX++) { + for (int binIndexY = 0; binIndexY < nY; binIndexY++) { + for (int binIndexZ = 0; binIndexZ < nZ; binIndexZ++, binIndex++) { + // Ignore origin for radial average (which is just the covariance of the quantities). + if (binIndex == 0 && binIndexY == 0 && binIndexZ == 0) + continue; + + // Compute distance. (FIXME! Check that this is actually correct for even and odd numbers of grid points.) + FloatType fracX = FloatType(SimulationCell::modulo(binIndexX+nX/2, nX)-nX/2)/nX; + FloatType fracY = FloatType(SimulationCell::modulo(binIndexY+nY/2, nY)-nY/2)/nY; + FloatType fracZ = FloatType(SimulationCell::modulo(binIndexZ+nZ/2, nZ)-nZ/2)/nZ; + // This is the real space vector. + Vector_3 distance = fracX*cellMatrix.column(0) + + fracY*cellMatrix.column(1) + + fracZ*cellMatrix.column(2); + + // Length of real space vector. + int distanceBinIndex = int(std::floor(distance.length()/gridSpacing)); + if (distanceBinIndex >= 0 && distanceBinIndex < numberOfDistanceBins) { + _realSpaceCorrelation[distanceBinIndex] += gridProperty1[binIndex]; + _realSpaceRDF[distanceBinIndex] += gridDensity[binIndex]; + numberOfValues[distanceBinIndex]++; + } + } + } + } + + // Compute averages and normalize real-space correlation function. Note FFTW computes an unnormalized transform. + normalizationFactor = 1.0/(sourceProperty1()->size()*sourceProperty2()->size()); + for (int distanceBinIndex = 0; distanceBinIndex < numberOfDistanceBins; distanceBinIndex++) { + if (numberOfValues[distanceBinIndex] > 0) { + _realSpaceCorrelation[distanceBinIndex] *= normalizationFactor/numberOfValues[distanceBinIndex]; + _realSpaceRDF[distanceBinIndex] *= normalizationFactor/numberOfValues[distanceBinIndex]; + } + } + + incrementProgressValue(); +} + +/****************************************************************************** +* Compute real space correlation function via direction summation over neighbors. +******************************************************************************/ +void CorrelationFunctionModifier::CorrelationAnalysisEngine::computeNeighCorrelation() +{ + // Get number of particles. + size_t particleCount = positions()->size(); + + // Get pointers to data. + const FloatType *floatData1 = nullptr, *floatData2 = nullptr; + const int *intData1 = nullptr, *intData2 = nullptr; + size_t componentCount1 = sourceProperty1()->componentCount(); + size_t componentCount2 = sourceProperty2()->componentCount(); + if(sourceProperty1()->dataType() == qMetaTypeId()) { + floatData1 = sourceProperty1()->constDataFloat(); + } + else if (sourceProperty1()->dataType() == qMetaTypeId()) { + intData1 = sourceProperty1()->constDataInt(); + } + if(sourceProperty2()->dataType() == qMetaTypeId()) { + floatData2 = sourceProperty2()->constDataFloat(); + } + else if (sourceProperty2()->dataType() == qMetaTypeId()) { + intData2 = sourceProperty2()->constDataInt(); + } + + // Resize neighbor RDF and fill with zeros. + _neighRDF.fill(0.0, _neighCorrelation.size()); + + // Prepare the neighbor list. + CutoffNeighborFinder neighborListBuilder; + if (!neighborListBuilder.prepare(_neighCutoff, positions(), cell(), nullptr, *this)) + return; + + // Perform analysis on each particle in parallel. + std::vector workers; + size_t num_threads = Application::instance()->idealThreadCount(); + size_t chunkSize = particleCount / num_threads; + size_t startIndex = 0; + size_t endIndex = chunkSize; + size_t vecComponent1 = _vecComponent1; + size_t vecComponent2 = _vecComponent2; + std::mutex mutex; + for (size_t t = 0; t < num_threads; t++) { + if (t == num_threads - 1) { + endIndex += particleCount % num_threads; + } + workers.push_back(std::thread([&neighborListBuilder, startIndex, endIndex, + floatData1, intData1, componentCount1, vecComponent1, + floatData2, intData2, componentCount2, vecComponent2, + &mutex, this]() { + FloatType gridSpacing = (_neighCutoff + FLOATTYPE_EPSILON) / _neighCorrelation.size(); + std::vector threadLocalCorrelation(_neighCorrelation.size(), 0); + std::vector threadLocalRDF(_neighCorrelation.size(), 0); + for (size_t i = startIndex; i < endIndex;) { + for (CutoffNeighborFinder::Query neighQuery(neighborListBuilder, i); !neighQuery.atEnd(); neighQuery.next()) { + size_t distanceBinIndex = (size_t)(sqrt(neighQuery.distanceSquared()) / gridSpacing); + distanceBinIndex = std::min(distanceBinIndex, threadLocalCorrelation.size() - 1); + FloatType data1 = 0.0, data2 = 0.0; + if (floatData1) + data1 = floatData1[i*componentCount1 + vecComponent1]; + else if (intData1) + data1 = intData1[i*componentCount1 + vecComponent1]; + if (floatData2) + data2 = floatData2[neighQuery.current() * componentCount2 + vecComponent2]; + else if (intData2) + data2 = intData2[neighQuery.current() * componentCount2 + vecComponent2]; + threadLocalCorrelation[distanceBinIndex] += data1*data2; + threadLocalRDF[distanceBinIndex] += 1; + } + i++; + // Abort loop when operation was canceled by the user. + if (isCanceled()) + return; + } + std::lock_guard lock(mutex); + auto iter_corr_out = _neighCorrelation.begin(); + for (auto iter_corr = threadLocalCorrelation.cbegin(); iter_corr != threadLocalCorrelation.cend(); ++iter_corr, ++iter_corr_out) + *iter_corr_out += *iter_corr; + auto iter_rdf_out = _neighRDF.begin(); + for (auto iter_rdf = threadLocalRDF.cbegin(); iter_rdf != threadLocalRDF.cend(); ++iter_rdf, ++iter_rdf_out) + *iter_rdf_out += *iter_rdf; + })); + startIndex = endIndex; + endIndex += chunkSize; + } + + for (auto& t: workers) + t.join(); + incrementProgressValue(); + + // Normalize short-ranged real-space correlation function and populate x-array. + FloatType gridSpacing = (_neighCutoff + FLOATTYPE_EPSILON) / _neighCorrelation.size(); + FloatType normalizationFactor = 3.0*cell().volume3D()/(4.0*FLOATTYPE_PI*sourceProperty1()->size()*sourceProperty2()->size()); + for (int distanceBinIndex = 0; distanceBinIndex < _neighCorrelation.size(); distanceBinIndex++) { + FloatType distance = distanceBinIndex*gridSpacing; + FloatType distance2 = (distanceBinIndex+1)*gridSpacing; + _neighCorrelationX[distanceBinIndex] = (distance+distance2)/2; + _neighCorrelation[distanceBinIndex] *= normalizationFactor/(distance2*distance2*distance2-distance*distance*distance); + _neighRDF[distanceBinIndex] *= normalizationFactor/(distance2*distance2*distance2-distance*distance*distance); + } + + incrementProgressValue(); +} + +/****************************************************************************** +* Compute means and covariance. +******************************************************************************/ +void CorrelationFunctionModifier::CorrelationAnalysisEngine::computeLimits() +{ + // Get pointers to data. + const FloatType *floatData1 = nullptr, *floatData2 = nullptr; + const int *intData1 = nullptr, *intData2 = nullptr; + size_t componentCount1 = sourceProperty1()->componentCount(); + size_t componentCount2 = sourceProperty2()->componentCount(); + if(sourceProperty1()->dataType() == qMetaTypeId()) { + floatData1 = sourceProperty1()->constDataFloat(); + } + else if (sourceProperty1()->dataType() == qMetaTypeId()) { + intData1 = sourceProperty1()->constDataInt(); + } + if(sourceProperty2()->dataType() == qMetaTypeId()) { + floatData2 = sourceProperty2()->constDataFloat(); + } + else if (sourceProperty2()->dataType() == qMetaTypeId()) { + intData2 = sourceProperty2()->constDataInt(); + } + + // Compute mean and covariance values. + _mean1 = _mean2 = _covariance = 0.0; + if (sourceProperty1()->size() != sourceProperty2()->size()) + return; + for (int particleIndex = 0; particleIndex < sourceProperty1()->size(); particleIndex++) { + FloatType data1, data2; + if (floatData1) + data1 = floatData1[particleIndex*componentCount1 + _vecComponent1]; + else if (intData1) + data1 = intData1[particleIndex*componentCount1 + _vecComponent1]; + if (floatData2) + data2 = floatData2[particleIndex*componentCount2 + _vecComponent2]; + else if (intData2) + data2 = intData2[particleIndex*componentCount2 + _vecComponent2]; + _mean1 += data1; + _mean2 += data2; + _covariance += data1*data2; + } + _mean1 /= sourceProperty1()->size(); + _mean2 /= sourceProperty2()->size(); + _covariance /= sourceProperty1()->size(); + + incrementProgressValue(); +} + +/****************************************************************************** +* Performs the actual computation. This method is executed in a worker thread. +******************************************************************************/ +void CorrelationFunctionModifier::CorrelationAnalysisEngine::perform() +{ + setProgressText(tr("Computing correlation function")); + setProgressValue(0); + int range = 12; + if (!_neighCorrelation.empty()) + range+=2; + setProgressMaximum(range); + + // Compute reciprocal space correlation function and long-ranged part of + // the real-space correlation function from an FFT. + computeFftCorrelation(); + if (isCanceled()) + return; + + // Compute short-ranged part of the real-space correlation function from a direct loop over particle neighbors. + if (!_neighCorrelation.empty()) { + if (isCanceled()) + return; + computeNeighCorrelation(); + } + + computeLimits(); +} + +/****************************************************************************** +* Update plot ranges. +******************************************************************************/ +void CorrelationFunctionModifier::updateRanges(FloatType offset, FloatType fac, FloatType reciprocalFac) +{ + // Compute data ranges + if (!_fixRealSpaceXAxisRange) { + if (!_realSpaceCorrelationX.empty() && !_neighCorrelationX.empty() && _doComputeNeighCorrelation) { + _realSpaceXAxisRangeStart = std::min(_realSpaceCorrelationX.first(), _neighCorrelationX.first()); + _realSpaceXAxisRangeEnd = std::max(_realSpaceCorrelationX.last(), _neighCorrelationX.last()); + } + else if (!_realSpaceCorrelationX.empty()) { + _realSpaceXAxisRangeStart = _realSpaceCorrelationX.first(); + _realSpaceXAxisRangeEnd = _realSpaceCorrelationX.last(); + } + else if (!_neighCorrelationX.empty() && _doComputeNeighCorrelation) { + _realSpaceXAxisRangeStart = _neighCorrelationX.first(); + _realSpaceXAxisRangeEnd = _neighCorrelationX.last(); + } + } + if (!_fixRealSpaceYAxisRange) { + if (!_realSpaceCorrelation.empty() && !_neighCorrelation.empty() && _doComputeNeighCorrelation) { + auto realSpace = std::minmax_element(_realSpaceCorrelation.begin(), _realSpaceCorrelation.end()); + auto neigh = std::minmax_element(_neighCorrelation.begin(), _neighCorrelation.end()); + _realSpaceYAxisRangeStart = fac*(std::min(*realSpace.first, *neigh.first)-offset); + _realSpaceYAxisRangeEnd = fac*(std::max(*realSpace.second, *neigh.second)-offset); + } + else if (!_realSpaceCorrelation.empty()) { + auto realSpace = std::minmax_element(_realSpaceCorrelation.begin(), _realSpaceCorrelation.end()); + _realSpaceYAxisRangeStart = fac*(*realSpace.first-offset); + _realSpaceYAxisRangeEnd = fac*(*realSpace.second-offset); + } + else if (!_neighCorrelation.empty() && _doComputeNeighCorrelation) { + auto neigh = std::minmax_element(_neighCorrelation.begin(), _neighCorrelation.end()); + _realSpaceYAxisRangeStart = fac*(*neigh.first-offset); + _realSpaceYAxisRangeEnd = fac*(*neigh.second-offset); + } + } + if (!_fixReciprocalSpaceXAxisRange && !_reciprocalSpaceCorrelationX.empty()) { + _reciprocalSpaceXAxisRangeStart = _reciprocalSpaceCorrelationX.first(); + _reciprocalSpaceXAxisRangeEnd = _reciprocalSpaceCorrelationX.last(); + } + if (!_fixReciprocalSpaceYAxisRange && !_reciprocalSpaceCorrelation.empty()) { + auto reciprocalSpace = std::minmax_element(_reciprocalSpaceCorrelation.begin(), _reciprocalSpaceCorrelation.end()); + _reciprocalSpaceYAxisRangeStart = reciprocalFac*(*reciprocalSpace.first); + _reciprocalSpaceYAxisRangeEnd = reciprocalFac*(*reciprocalSpace.second); + } +} + +/****************************************************************************** +* Unpacks the results of the computation engine and stores them in the modifier. +******************************************************************************/ +void CorrelationFunctionModifier::transferComputationResults(ComputeEngine* engine) +{ + CorrelationAnalysisEngine* eng = static_cast(engine); + _realSpaceCorrelation = eng->realSpaceCorrelation(); + _realSpaceRDF = eng->realSpaceRDF(); + _realSpaceCorrelationX = eng->realSpaceCorrelationX(); + _neighCorrelation = eng->neighCorrelation(); + _neighRDF = eng->neighRDF(); + _neighCorrelationX = eng->neighCorrelationX(); + _reciprocalSpaceCorrelation = eng->reciprocalSpaceCorrelation(); + _reciprocalSpaceCorrelationX = eng->reciprocalSpaceCorrelationX(); + _mean1 = eng->mean1(); + _mean2 = eng->mean2(); + _covariance = eng->covariance(); +} + +/****************************************************************************** +* Lets the modifier insert the cached computation results into the +* modification pipeline. +******************************************************************************/ +PipelineStatus CorrelationFunctionModifier::applyComputationResults(TimePoint time, TimeInterval& validityInterval) +{ + return PipelineStatus::Success; +} + +/****************************************************************************** +* Is called when the value of a property of this object has changed. +******************************************************************************/ +void CorrelationFunctionModifier::propertyChanged(const PropertyFieldDescriptor& field) +{ + AsynchronousParticleModifier::propertyChanged(field); + + // Recompute modifier results when the parameters have been changed. + if (field == PROPERTY_FIELD(sourceProperty1) || + field == PROPERTY_FIELD(sourceProperty2) || + field == PROPERTY_FIELD(fftGridSpacing) || + field == PROPERTY_FIELD(applyWindow) || + field == PROPERTY_FIELD(doComputeNeighCorrelation) || + field == PROPERTY_FIELD(neighCutoff) || + field == PROPERTY_FIELD(numberOfNeighBins)) { + invalidateCachedResults(); + } +} + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/correlation/CorrelationFunctionModifier.h ovito-2.9.0+dfsg1/src/plugins/correlation/CorrelationFunctionModifier.h --- ovito-2.8.1+dfsg2/src/plugins/correlation/CorrelationFunctionModifier.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/correlation/CorrelationFunctionModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,347 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2014) Alexander Stukowski +// Copyright (2017) Lars Pastewka +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __OVITO_CORRELATION_FUNCTION_MODIFIER_H +#define __OVITO_CORRELATION_FUNCTION_MODIFIER_H + +#include +#include +#include +#include "../particles/modifier/AsynchronousParticleModifier.h" + +#include + +#ifdef CorrelationFunctionPlugin_EXPORTS // This is defined by CMake when building the plugin library. +# define OVITO_CORRELATION_FUNCTION_EXPORT Q_DECL_EXPORT +#else +# define OVITO_CORRELATION_FUNCTION_EXPORT Q_DECL_IMPORT +#endif + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) + +/** + * \brief This modifier computes the coordination number of each particle (i.e. the number of neighbors within a given cutoff radius). + */ +class OVITO_CORRELATION_FUNCTION_EXPORT CorrelationFunctionModifier : public AsynchronousParticleModifier +{ +public: + + enum AveragingDirectionType { CELL_VECTOR_1 = 0, CELL_VECTOR_2 = 1, CELL_VECTOR_3 = 2, RADIAL = 3 }; + enum NormalizationType { DO_NOT_NORMALIZE = 0, NORMALIZE_BY_COVARIANCE = 1, NORMALIZE_BY_RDF = 2 }; + Q_ENUMS(AveragingDirectionType); + Q_ENUMS(NormalizationType); + + /// Constructor. + Q_INVOKABLE CorrelationFunctionModifier(DataSet* dataset); + + /// Returns the Y coordinates of the real-space correlation function. + const QVector& realSpaceCorrelation() const { return _realSpaceCorrelation; } + + /// Returns the RDF evaluated from an FFT correlation. + const QVector& realSpaceRDF() const { return _realSpaceRDF; } + + /// Returns the X coordinates of the real-space correlation function. + const QVector& realSpaceCorrelationX() const { return _realSpaceCorrelationX; } + + /// Returns the Y coordinates of the short-ranged part of the real-space correlation function. + const QVector& neighCorrelation() const { return _neighCorrelation; } + + /// Returns the RDF evalauted from a direct sum over neighbor shells. + const QVector& neighRDF() const { return _neighRDF; } + + /// Returns the X coordinates of the short-ranged part of the real-space correlation function. + const QVector& neighCorrelationX() const { return _neighCorrelationX; } + + /// Returns the Y coordinates of the reciprocal-space correlation function. + const QVector& reciprocalSpaceCorrelation() const { return _reciprocalSpaceCorrelation; } + + /// Returns the X coordinates of the reciprocal-space correlation function. + const QVector& reciprocalSpaceCorrelationX() const { return _reciprocalSpaceCorrelationX; } + + /// Returns the mean of the first property. + FloatType mean1() const { return _mean1; } + + /// Returns the mean of the second property. + FloatType mean2() const { return _mean2; } + + /// Returns the (co)variance. + FloatType covariance() const { return _covariance; } + + /// Update plot ranges. + virtual void updateRanges(FloatType offset, FloatType fac, FloatType reciprocalFac); + +private: + + /// Computes the modifier's results. + class CorrelationAnalysisEngine : public ComputeEngine + { + public: + + /// Constructor. + CorrelationAnalysisEngine(const TimeInterval& validityInterval, + ParticleProperty* positions, + ParticleProperty* sourceProperty1, + size_t vecComponent1, + ParticleProperty* sourceProperty2, + size_t vecComponent2, + const SimulationCell& simCell, + FloatType fftGridSpacing, + bool applyWindow, + bool doComputeNeighCorrelation, + FloatType neighCutoff, + int numberOfNeighBins, + AveragingDirectionType averagingDirection) : + ComputeEngine(validityInterval), _positions(positions), + _sourceProperty1(sourceProperty1), _vecComponent1(vecComponent1), + _sourceProperty2(sourceProperty2), _vecComponent2(vecComponent2), + _simCell(simCell), _fftGridSpacing(fftGridSpacing), + _applyWindow(applyWindow), _neighCutoff(neighCutoff), + _neighCorrelation(numberOfNeighBins, 0.0), + _neighCorrelationX(numberOfNeighBins), + _averagingDirection(averagingDirection) { + if (!doComputeNeighCorrelation) { + _neighCorrelation.clear(); + _neighCorrelationX.clear(); + } + } + + /// Compute real and reciprocal space correlation function via FFT. + void computeFftCorrelation(); + + /// Compute real space correlation function via direction summation over neighbors. + void computeNeighCorrelation(); + + /// Compute means and covariance. + void computeLimits(); + + /// Computes the modifier's results and stores them in this object for later retrieval. + virtual void perform() override; + + /// Returns the property storage that contains the input particle positions. + ParticleProperty* positions() const { return _positions.data(); } + + /// Returns the property storage that contains the first input particle property. + ParticleProperty* sourceProperty1() const { return _sourceProperty1.data(); } + + /// Returns the property storage that contains the second input particle property. + ParticleProperty* sourceProperty2() const { return _sourceProperty2.data(); } + + /// Returns the simulation cell data. + const SimulationCell& cell() const { return _simCell; } + + /// Returns the FFT cutoff radius. + FloatType fftGridSpacing() const { return _fftGridSpacing; } + + /// Returns the neighbor cutoff radius. + FloatType neighCutoff() const { return _neighCutoff; } + + /// Returns the real-space correlation function. + const QVector& realSpaceCorrelation() const { return _realSpaceCorrelation; } + + /// Returns the RDF evaluated from an FFT correlation. + const QVector& realSpaceRDF() const { return _realSpaceRDF; } + + /// Returns the distances for which the real-space correlation function is tabulAveated. + const QVector& realSpaceCorrelationX() const { return _realSpaceCorrelationX; } + + /// Returns the short-ranged real-space correlation function. + const QVector& neighCorrelation() const { return _neighCorrelation; } + + /// Returns the RDF evalauted from a direct sum over neighbor shells. + const QVector& neighRDF() const { return _neighRDF; } + + /// Returns the distances for which the short-ranged real-space correlation function is tabulated. + const QVector& neighCorrelationX() const { return _neighCorrelationX; } + + /// Returns the reciprocal-space correlation function. + const QVector& reciprocalSpaceCorrelation() const { return _reciprocalSpaceCorrelation; } + + /// Returns the wavevectors for which the reciprocal-space correlation function is tabulated. + const QVector& reciprocalSpaceCorrelationX() const { return _reciprocalSpaceCorrelationX; } + + /// Returns the mean of the first property. + FloatType mean1() const { return _mean1; } + + /// Returns the mean of the second property. + FloatType mean2() const { return _mean2; } + + /// Returns the (co)variance. + FloatType covariance() const { return _covariance; } + + private: + + /// Real-to-complex FFT. + void r2cFFT(int nX, int nY, int nZ, QVector &rData, QVector> &cData); + + /// Complex-to-real inverse FFT + void c2rFFT(int nX, int nY, int nZ, QVector> &cData, QVector &rData); + + /// Map property onto grid. + void mapToSpatialGrid(ParticleProperty *property, + size_t propertyVectorComponent, + const AffineTransformation &reciprocalCell, + int nX, int nY, int nZ, + QVector &gridData, + bool applyWindow); + + size_t _vecComponent1; + size_t _vecComponent2; + FloatType _fftGridSpacing; + bool _applyWindow; + FloatType _neighCutoff; + AveragingDirectionType _averagingDirection; + SimulationCell _simCell; + QExplicitlySharedDataPointer _positions; + QExplicitlySharedDataPointer _sourceProperty1; + QExplicitlySharedDataPointer _sourceProperty2; + QVector _realSpaceCorrelation; + QVector _realSpaceRDF; + QVector _realSpaceCorrelationX; + QVector _neighCorrelation; + QVector _neighRDF; + QVector _neighCorrelationX; + QVector _reciprocalSpaceCorrelation; + QVector _reciprocalSpaceCorrelationX; + FloatType _mean1; + FloatType _mean2; + FloatType _covariance; + }; + +protected: + + /// This virtual method is called by the system when the modifier has been inserted into a PipelineObject. + virtual void initializeModifier(PipelineObject* pipelineObject, ModifierApplication* modApp) override; + + /// Is called when the value of a property of this object has changed. + virtual void propertyChanged(const PropertyFieldDescriptor& field) override; + + /// Creates a computation engine that will compute the modifier's results. + virtual std::shared_ptr createEngine(TimePoint time, TimeInterval validityInterval) override; + + /// Unpacks the results of the computation engine and stores them in the modifier. + virtual void transferComputationResults(ComputeEngine* engine) override; + + /// Lets the modifier insert the cached computation results into the modification pipeline. + virtual PipelineStatus applyComputationResults(TimePoint time, TimeInterval& validityInterval) override; + +private: + + /// The real-space correlation function. + QVector _realSpaceCorrelation; + + /// The radial distribution function computed from an FFT convolution. + QVector _realSpaceRDF; + + /// The distances for which the real-space correlation function is tabulated. + QVector _realSpaceCorrelationX; + + /// The short-ranged part of the real-space correlation function. + QVector _neighCorrelation; + + /// The radial distribution function computed from a direct sum over neighbor shells. + QVector _neighRDF; + + /// The distances for which short-ranged part of the real-space correlation function is tabulated. + QVector _neighCorrelationX; + + /// The reciprocal-space correlation function. + QVector _reciprocalSpaceCorrelation; + + /// The wavevevtors for which the reciprocal-space correlation function is tabulated. + QVector _reciprocalSpaceCorrelationX; + + /// Mean of the first property. + FloatType _mean1; + + /// Mean of the second property. + FloatType _mean2; + + /// (Co)variance. + FloatType _covariance; + + Q_OBJECT + OVITO_OBJECT + + Q_CLASSINFO("DisplayName", "Correlation function"); + Q_CLASSINFO("ModifierCategory", "Analysis"); + + /// The particle property that serves as the first data source for the correlation function. + DECLARE_MODIFIABLE_PROPERTY_FIELD(ParticlePropertyReference, sourceProperty1, setSourceProperty1); + /// The particle property that serves as the second data source for the correlation function. + DECLARE_MODIFIABLE_PROPERTY_FIELD(ParticlePropertyReference, sourceProperty2, setSourceProperty2); + /// Controls the cutoff radius for the FFT grid. + DECLARE_PROPERTY_FIELD(FloatType, fftGridSpacing); + /// Controls if a windowing function should be applied in nonperiodic directions. + DECLARE_PROPERTY_FIELD(bool, applyWindow); + /// Controls whether the real-space correlation should be computed by direct summation. + DECLARE_PROPERTY_FIELD(bool, doComputeNeighCorrelation); + /// Controls the cutoff radius for the neighbor lists. + DECLARE_PROPERTY_FIELD(FloatType, neighCutoff); + /// Controls the number of bins for the neighbor part of the real-space correlation function. + DECLARE_PROPERTY_FIELD(int, numberOfNeighBins); + /// Controls the averaging direction. + DECLARE_PROPERTY_FIELD(AveragingDirectionType, averagingDirection); + /// Controls the normalization of the real-space correlation function. + DECLARE_PROPERTY_FIELD(NormalizationType, normalizeRealSpace); + /// Type of real-space plot (lin-lin, log-lin or log-log) + DECLARE_PROPERTY_FIELD(int, typeOfRealSpacePlot); + /// Controls the whether the range of the x-axis of the plot should be fixed. + DECLARE_PROPERTY_FIELD(bool, fixRealSpaceXAxisRange); + /// Controls the start value of the x-axis. + DECLARE_PROPERTY_FIELD(FloatType, realSpaceXAxisRangeStart); + /// Controls the end value of the x-axis. + DECLARE_PROPERTY_FIELD(FloatType, realSpaceXAxisRangeEnd); + /// Controls the whether the range of the y-axis of the plot should be fixed. + DECLARE_PROPERTY_FIELD(bool, fixRealSpaceYAxisRange); + /// Controls the start value of the y-axis. + DECLARE_PROPERTY_FIELD(FloatType, realSpaceYAxisRangeStart); + /// Controls the end value of the y-axis. + DECLARE_PROPERTY_FIELD(FloatType, realSpaceYAxisRangeEnd); + /// Controls the normalization of the reciprocal-space correlation function. + DECLARE_PROPERTY_FIELD(bool, normalizeReciprocalSpace); + /// Type of reciprocal-space plot (lin-lin, log-lin or log-log) + DECLARE_PROPERTY_FIELD(int, typeOfReciprocalSpacePlot); + /// Controls the whether the range of the x-axis of the plot should be fixed. + DECLARE_PROPERTY_FIELD(bool, fixReciprocalSpaceXAxisRange); + /// Controls the start value of the x-axis. + DECLARE_PROPERTY_FIELD(FloatType, reciprocalSpaceXAxisRangeStart); + /// Controls the end value of the x-axis. + DECLARE_PROPERTY_FIELD(FloatType, reciprocalSpaceXAxisRangeEnd); + /// Controls the whether the range of the y-axis of the plot should be fixed. + DECLARE_PROPERTY_FIELD(bool, fixReciprocalSpaceYAxisRange); + /// Controls the start value of the y-axis. + DECLARE_PROPERTY_FIELD(FloatType, reciprocalSpaceYAxisRangeStart); + /// Controls the end value of the y-axis. + DECLARE_PROPERTY_FIELD(FloatType, reciprocalSpaceYAxisRangeEnd); +}; + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace + +Q_DECLARE_METATYPE(Ovito::Particles::CorrelationFunctionModifier::AveragingDirectionType); +Q_DECLARE_METATYPE(Ovito::Particles::CorrelationFunctionModifier::NormalizationType); +Q_DECLARE_TYPEINFO(Ovito::Particles::CorrelationFunctionModifier::AveragingDirectionType, Q_PRIMITIVE_TYPE); +Q_DECLARE_TYPEINFO(Ovito::Particles::CorrelationFunctionModifier::NormalizationType, Q_PRIMITIVE_TYPE); + +#endif // __OVITO_CORRELATION_FUNCTION_MODIFIER_H diff -Nru ovito-2.8.1+dfsg2/src/plugins/correlation/gui/CMakeLists.txt ovito-2.9.0+dfsg1/src/plugins/correlation/gui/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/plugins/correlation/gui/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/correlation/gui/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,27 @@ +############################################################################### +# +# Copyright (2017) Alexander Stukowski +# +# This file is part of OVITO (Open Visualization Tool). +# +# OVITO is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# OVITO is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################### + +OVITO_STANDARD_PLUGIN(CorrelationFunctionPluginGui + SOURCES CorrelationFunctionModifierEditor.cpp + PRIVATE_LIB_DEPENDENCIES Qwt + PLUGIN_DEPENDENCIES CorrelationFunctionPlugin ParticlesGui + GUI_PLUGIN +) diff -Nru ovito-2.8.1+dfsg2/src/plugins/correlation/gui/CorrelationFunctionModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/correlation/gui/CorrelationFunctionModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/correlation/gui/CorrelationFunctionModifierEditor.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/correlation/gui/CorrelationFunctionModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,495 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2016) Alexander Stukowski +// Copyright (2017) Lars Pastewka +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "CorrelationFunctionModifierEditor.h" + +#include +#include +#include +#include + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) + +IMPLEMENT_OVITO_OBJECT(CorrelationFunctionModifierEditor, ParticleModifierEditor); +SET_OVITO_OBJECT_EDITOR(CorrelationFunctionModifier, CorrelationFunctionModifierEditor); + +/****************************************************************************** +* Sets up the UI widgets of the editor. +******************************************************************************/ +void CorrelationFunctionModifierEditor::createUI(const RolloutInsertionParameters& rolloutParams) +{ + // Create a rollout. + QWidget* rollout = createRollout(tr("Correlation function"), rolloutParams, "particles.modifiers.correlation_function.html"); + + // Create the rollout contents. + QVBoxLayout* layout = new QVBoxLayout(rollout); + layout->setContentsMargins(4,4,4,4); + layout->setSpacing(4); + + ParticlePropertyParameterUI* sourceProperty1UI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::sourceProperty1)); + layout->addWidget(new QLabel(tr("First property:"), rollout)); + layout->addWidget(sourceProperty1UI->comboBox()); + + ParticlePropertyParameterUI* sourceProperty2UI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::sourceProperty2)); + layout->addWidget(new QLabel(tr("Second property:"), rollout)); + layout->addWidget(sourceProperty2UI->comboBox()); + + QGridLayout* gridlayout = new QGridLayout(); + gridlayout->setContentsMargins(4,4,4,4); + gridlayout->setColumnStretch(1, 1); + + // FFT grid spacing parameter. + FloatParameterUI* fftGridSpacingRadiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::fftGridSpacing)); + gridlayout->addWidget(fftGridSpacingRadiusPUI->label(), 0, 0); + gridlayout->addLayout(fftGridSpacingRadiusPUI->createFieldLayout(), 0, 1); + + layout->addLayout(gridlayout); + + BooleanParameterUI* applyWindowUI = new BooleanParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::applyWindow)); + layout->addWidget(applyWindowUI->checkBox()); + +#if 0 + gridlayout = new QGridLayout(); + gridlayout->addWidget(new QLabel(tr("Average:"), rollout), 0, 0); + VariantComboBoxParameterUI* averagingDirectionPUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::averagingDirection)); + averagingDirectionPUI->comboBox()->addItem("radial", qVariantFromValue(CorrelationFunctionModifier::RADIAL)); + averagingDirectionPUI->comboBox()->addItem("cell vector 1", qVariantFromValue(CorrelationFunctionModifier::CELL_VECTOR_1)); + averagingDirectionPUI->comboBox()->addItem("cell vector 2", qVariantFromValue(CorrelationFunctionModifier::CELL_VECTOR_2)); + averagingDirectionPUI->comboBox()->addItem("cell vector 3", qVariantFromValue(CorrelationFunctionModifier::CELL_VECTOR_3)); + gridlayout->addWidget(averagingDirectionPUI->comboBox(), 0, 1); + layout->addLayout(gridlayout); +#endif + + QGroupBox* realSpaceGroupBox = new QGroupBox(tr("Real-space correlation function")); + layout->addWidget(realSpaceGroupBox); + + BooleanParameterUI* doComputeNeighCorrelationUI = new BooleanParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::doComputeNeighCorrelation)); + + QGridLayout* realSpaceGridLayout = new QGridLayout(); + realSpaceGridLayout->setContentsMargins(4,4,4,4); + realSpaceGridLayout->setColumnStretch(1, 1); + + // Neighbor cutoff parameter. + FloatParameterUI *neighCutoffRadiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::neighCutoff)); + neighCutoffRadiusPUI->setEnabled(false); + realSpaceGridLayout->addWidget(neighCutoffRadiusPUI->label(), 1, 0); + realSpaceGridLayout->addLayout(neighCutoffRadiusPUI->createFieldLayout(), 1, 1); + + // Number of bins parameter. + IntegerParameterUI* numberOfNeighBinsPUI = new IntegerParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::numberOfNeighBins)); + numberOfNeighBinsPUI->setEnabled(false); + realSpaceGridLayout->addWidget(numberOfNeighBinsPUI->label(), 2, 0); + realSpaceGridLayout->addLayout(numberOfNeighBinsPUI->createFieldLayout(), 2, 1); + + connect(doComputeNeighCorrelationUI->checkBox(), &QCheckBox::toggled, neighCutoffRadiusPUI, &FloatParameterUI::setEnabled); + connect(doComputeNeighCorrelationUI->checkBox(), &QCheckBox::toggled, numberOfNeighBinsPUI, &IntegerParameterUI::setEnabled); + + QGridLayout *normalizeRealSpaceLayout = new QGridLayout(); + normalizeRealSpaceLayout->addWidget(new QLabel(tr("Normalization:"), rollout), 0, 0); + VariantComboBoxParameterUI* normalizeRealSpacePUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::normalizeRealSpace)); + normalizeRealSpacePUI->comboBox()->addItem("Do not normalize", qVariantFromValue(CorrelationFunctionModifier::DO_NOT_NORMALIZE)); + normalizeRealSpacePUI->comboBox()->addItem("by covariance", qVariantFromValue(CorrelationFunctionModifier::NORMALIZE_BY_COVARIANCE)); + normalizeRealSpacePUI->comboBox()->addItem("by RDF", qVariantFromValue(CorrelationFunctionModifier::NORMALIZE_BY_RDF)); + normalizeRealSpaceLayout->addWidget(normalizeRealSpacePUI->comboBox(), 0, 1); + + QGridLayout* typeOfRealSpacePlotLayout = new QGridLayout(); + IntegerRadioButtonParameterUI *typeOfRealSpacePlotPUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::typeOfRealSpacePlot)); + typeOfRealSpacePlotLayout->addWidget(new QLabel(tr("Display as:")), 0, 0); + typeOfRealSpacePlotLayout->addWidget(typeOfRealSpacePlotPUI->addRadioButton(0, tr("lin-lin")), 0, 1); + typeOfRealSpacePlotLayout->addWidget(typeOfRealSpacePlotPUI->addRadioButton(1, tr("log-lin")), 0, 2); + typeOfRealSpacePlotLayout->addWidget(typeOfRealSpacePlotPUI->addRadioButton(3, tr("log-log")), 0, 3); + + _realSpacePlot = new QwtPlot(); + _realSpacePlot->setMinimumHeight(200); + _realSpacePlot->setMaximumHeight(200); + _realSpacePlot->setCanvasBackground(Qt::white); + _realSpacePlot->setAxisTitle(QwtPlot::xBottom, tr("Distance r")); + _realSpacePlot->setAxisTitle(QwtPlot::yLeft, tr("C(r)")); + + // Axes. + QGroupBox* axesBox = new QGroupBox(tr("Plot axes"), rollout); + QVBoxLayout* axesSublayout = new QVBoxLayout(axesBox); + axesSublayout->setContentsMargins(4,4,4,4); + layout->addWidget(axesBox); + // x-axis. + { + BooleanParameterUI* rangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::fixRealSpaceXAxisRange)); + axesSublayout->addWidget(rangeUI->checkBox()); + + QHBoxLayout* hlayout = new QHBoxLayout(); + axesSublayout->addLayout(hlayout); + FloatParameterUI* startPUI = new FloatParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::realSpaceXAxisRangeStart)); + FloatParameterUI* endPUI = new FloatParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::realSpaceXAxisRangeEnd)); + hlayout->addWidget(new QLabel(tr("From:"))); + hlayout->addLayout(startPUI->createFieldLayout()); + hlayout->addSpacing(12); + hlayout->addWidget(new QLabel(tr("To:"))); + hlayout->addLayout(endPUI->createFieldLayout()); + startPUI->setEnabled(false); + endPUI->setEnabled(false); + connect(rangeUI->checkBox(), &QCheckBox::toggled, startPUI, &FloatParameterUI::setEnabled); + connect(rangeUI->checkBox(), &QCheckBox::toggled, endPUI, &FloatParameterUI::setEnabled); + } + // y-axis. + { + BooleanParameterUI* rangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::fixRealSpaceYAxisRange)); + axesSublayout->addWidget(rangeUI->checkBox()); + + QHBoxLayout* hlayout = new QHBoxLayout(); + axesSublayout->addLayout(hlayout); + FloatParameterUI* startPUI = new FloatParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::realSpaceYAxisRangeStart)); + FloatParameterUI* endPUI = new FloatParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::realSpaceYAxisRangeEnd)); + hlayout->addWidget(new QLabel(tr("From:"))); + hlayout->addLayout(startPUI->createFieldLayout()); + hlayout->addSpacing(12); + hlayout->addWidget(new QLabel(tr("To:"))); + hlayout->addLayout(endPUI->createFieldLayout()); + startPUI->setEnabled(false); + endPUI->setEnabled(false); + connect(rangeUI->checkBox(), &QCheckBox::toggled, startPUI, &FloatParameterUI::setEnabled); + connect(rangeUI->checkBox(), &QCheckBox::toggled, endPUI, &FloatParameterUI::setEnabled); + } + + QVBoxLayout* realSpaceLayout = new QVBoxLayout(realSpaceGroupBox); + realSpaceLayout->addWidget(doComputeNeighCorrelationUI->checkBox()); + realSpaceLayout->addLayout(realSpaceGridLayout); + realSpaceLayout->addLayout(normalizeRealSpaceLayout); + realSpaceLayout->addLayout(typeOfRealSpacePlotLayout); + realSpaceLayout->addWidget(_realSpacePlot); + realSpaceLayout->addWidget(axesBox); + + QGroupBox* reciprocalSpaceGroupBox = new QGroupBox(tr("Reciprocal-space correlation function")); + layout->addWidget(reciprocalSpaceGroupBox); + + BooleanParameterUI* normalizeReciprocalSpaceUI = new BooleanParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::normalizeReciprocalSpace)); + + QGridLayout* typeOfReciprocalSpacePlotLayout = new QGridLayout(); + IntegerRadioButtonParameterUI *typeOfReciprocalSpacePlotPUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::typeOfReciprocalSpacePlot)); + typeOfReciprocalSpacePlotLayout->addWidget(new QLabel(tr("Display as:")), 0, 0); + typeOfReciprocalSpacePlotLayout->addWidget(typeOfReciprocalSpacePlotPUI->addRadioButton(0, tr("lin-lin")), 0, 1); + typeOfReciprocalSpacePlotLayout->addWidget(typeOfReciprocalSpacePlotPUI->addRadioButton(1, tr("log-lin")), 0, 2); + typeOfReciprocalSpacePlotLayout->addWidget(typeOfReciprocalSpacePlotPUI->addRadioButton(3, tr("log-log")), 0, 3); + + _reciprocalSpacePlot = new QwtPlot(); + _reciprocalSpacePlot->setMinimumHeight(200); + _reciprocalSpacePlot->setMaximumHeight(200); + _reciprocalSpacePlot->setCanvasBackground(Qt::white); + _reciprocalSpacePlot->setAxisTitle(QwtPlot::xBottom, tr("Wavevector q")); + _reciprocalSpacePlot->setAxisTitle(QwtPlot::yLeft, tr("C(q)")); + + // Axes. + axesBox = new QGroupBox(tr("Plot axes"), rollout); + axesSublayout = new QVBoxLayout(axesBox); + axesSublayout->setContentsMargins(4,4,4,4); + layout->addWidget(axesBox); + // x-axis. + { + BooleanParameterUI* rangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::fixReciprocalSpaceXAxisRange)); + axesSublayout->addWidget(rangeUI->checkBox()); + + QHBoxLayout* hlayout = new QHBoxLayout(); + axesSublayout->addLayout(hlayout); + FloatParameterUI* startPUI = new FloatParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::reciprocalSpaceXAxisRangeStart)); + FloatParameterUI* endPUI = new FloatParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::reciprocalSpaceXAxisRangeEnd)); + hlayout->addWidget(new QLabel(tr("From:"))); + hlayout->addLayout(startPUI->createFieldLayout()); + hlayout->addSpacing(12); + hlayout->addWidget(new QLabel(tr("To:"))); + hlayout->addLayout(endPUI->createFieldLayout()); + startPUI->setEnabled(false); + endPUI->setEnabled(false); + connect(rangeUI->checkBox(), &QCheckBox::toggled, startPUI, &FloatParameterUI::setEnabled); + connect(rangeUI->checkBox(), &QCheckBox::toggled, endPUI, &FloatParameterUI::setEnabled); + } + // y-axis. + { + BooleanParameterUI* rangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::fixReciprocalSpaceYAxisRange)); + axesSublayout->addWidget(rangeUI->checkBox()); + + QHBoxLayout* hlayout = new QHBoxLayout(); + axesSublayout->addLayout(hlayout); + FloatParameterUI* startPUI = new FloatParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::reciprocalSpaceYAxisRangeStart)); + FloatParameterUI* endPUI = new FloatParameterUI(this, PROPERTY_FIELD(CorrelationFunctionModifier::reciprocalSpaceYAxisRangeEnd)); + hlayout->addWidget(new QLabel(tr("From:"))); + hlayout->addLayout(startPUI->createFieldLayout()); + hlayout->addSpacing(12); + hlayout->addWidget(new QLabel(tr("To:"))); + hlayout->addLayout(endPUI->createFieldLayout()); + startPUI->setEnabled(false); + endPUI->setEnabled(false); + connect(rangeUI->checkBox(), &QCheckBox::toggled, startPUI, &FloatParameterUI::setEnabled); + connect(rangeUI->checkBox(), &QCheckBox::toggled, endPUI, &FloatParameterUI::setEnabled); + } + + QVBoxLayout* reciprocalSpaceLayout = new QVBoxLayout(reciprocalSpaceGroupBox); + reciprocalSpaceLayout->addWidget(normalizeReciprocalSpaceUI->checkBox()); + reciprocalSpaceLayout->addLayout(typeOfReciprocalSpacePlotLayout); + reciprocalSpaceLayout->addWidget(_reciprocalSpacePlot); + reciprocalSpaceLayout->addWidget(axesBox); + + connect(this, &CorrelationFunctionModifierEditor::contentsReplaced, this, &CorrelationFunctionModifierEditor::plotAllData); + + layout->addSpacing(12); + QPushButton* saveDataButton = new QPushButton(tr("Export data to text file")); + layout->addWidget(saveDataButton); + connect(saveDataButton, &QPushButton::clicked, this, &CorrelationFunctionModifierEditor::onSaveData); + + // Status label. + layout->addSpacing(6); + layout->addWidget(statusLabel()); +} + +/****************************************************************************** +* This method is called when a reference target changes. +******************************************************************************/ +bool CorrelationFunctionModifierEditor::referenceEvent(RefTarget* source, ReferenceEvent* event) +{ + if (event->sender() == editObject() && + (event->type() == ReferenceEvent::TargetChanged || + event->type() == ReferenceEvent::ObjectStatusChanged)) { + plotAllDataLater(this); + } + return ParticleModifierEditor::referenceEvent(source, event); +} + +/****************************************************************************** +* Plot correlation function. +******************************************************************************/ +void CorrelationFunctionModifierEditor::plotData(const QVector &xData, + const QVector &yData, + QwtPlot *plot, + QwtPlotCurve *&curve, + FloatType offset, FloatType fac) +{ + if (xData.size() != yData.size()) + throwException("Argument to plotData must have same size."); + + if(!curve) { + curve = new QwtPlotCurve(); + curve->setRenderHint(QwtPlotItem::RenderAntialiased, true); + curve->setBrush(Qt::lightGray); + curve->attach(plot); + QwtPlotGrid* plotGrid = new QwtPlotGrid(); + plotGrid->setPen(Qt::gray, 0, Qt::DotLine); + plotGrid->attach(plot); + } + + // Set data to plot. + size_t numberOfDataPoints = yData.size(); + int startAt = 0; + QVector plotData(numberOfDataPoints-startAt); + for (int i = startAt; i < numberOfDataPoints; i++) { + FloatType xValue = xData[i]; + FloatType yValue = fac*(yData[i]-offset); + plotData[i-startAt].rx() = xValue; + plotData[i-startAt].ry() = yValue; + } + curve->setSamples(plotData); +} + +/****************************************************************************** +* Updates the plot of the RDF computed by the modifier. +******************************************************************************/ +void CorrelationFunctionModifierEditor::plotAllData() +{ + CorrelationFunctionModifier* modifier = static_object_cast(editObject()); + if(!modifier) + return; + + FloatType offset = 0.0; + FloatType fac = 1.0; + if (modifier->normalizeRealSpace() == CorrelationFunctionModifier::NORMALIZE_BY_COVARIANCE) { + offset = modifier->mean1()*modifier->mean2(); + fac = 1.0/(modifier->covariance()-offset); + } + FloatType rfac = 1.0; + if (modifier->normalizeReciprocalSpace()) { + rfac = 1.0/(modifier->covariance()-modifier->mean1()*modifier->mean2()); + } + + modifier->updateRanges(offset, fac, rfac); + + // Plot real-space correlation function + if(!modifier->realSpaceCorrelationX().empty() && + !modifier->realSpaceCorrelation().empty()) { + QVector y = modifier->realSpaceCorrelation(); + if (modifier->normalizeRealSpace() == CorrelationFunctionModifier::NORMALIZE_BY_RDF) + std::transform(y.begin(), y.end(), modifier->realSpaceRDF().constBegin(), y.begin(), std::divides()); + plotData(modifier->realSpaceCorrelationX(), y, + _realSpacePlot, _realSpaceCurve, + offset, fac); + } + + if(!modifier->neighCorrelationX().empty() && + !modifier->neighCorrelation().empty() && + modifier->doComputeNeighCorrelation()) { + if(!_neighCurve) { + _neighCurve = new QwtPlotCurve(); + _neighCurve->setRenderHint(QwtPlotItem::RenderAntialiased, true); + _neighCurve->setPen(Qt::red); + _neighCurve->attach(_realSpacePlot); + } + + // Set data to plot. + auto &xData = modifier->neighCorrelationX(); + auto &yData = modifier->neighCorrelation(); + auto &rdfData = modifier->neighRDF(); + size_t numberOfDataPoints = yData.size(); + QVector plotData(numberOfDataPoints); + bool normByRDF = modifier->normalizeRealSpace() == CorrelationFunctionModifier::NORMALIZE_BY_RDF; + for (int i = 0; i < numberOfDataPoints; i++) { + FloatType xValue = xData[i]; + FloatType yValue = fac*(yData[i]-offset); + if (normByRDF) + yValue /= rdfData[i]; + plotData[i].rx() = xValue; + plotData[i].ry() = yValue; + } + _neighCurve->setSamples(plotData); + } + else { + // Remove curve from plot if it exists. + if (_neighCurve) { + _neighCurve->detach(); + delete _neighCurve; + _neighCurve = nullptr; + } + } + + // Plot reciprocal-space correlation function + if(!modifier->reciprocalSpaceCorrelationX().empty() && + !modifier->reciprocalSpaceCorrelation().empty()) { + plotData(modifier->reciprocalSpaceCorrelationX(), + modifier->reciprocalSpaceCorrelation(), + _reciprocalSpacePlot, + _reciprocalSpaceCurve, + 0.0, rfac); + } + + // Set type of plot. + if (modifier->typeOfRealSpacePlot() & 1) + _realSpacePlot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLogScaleEngine()); + else + _realSpacePlot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine()); + if (modifier->typeOfRealSpacePlot() & 2) + _realSpacePlot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLogScaleEngine()); + else + _realSpacePlot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine()); + + if (modifier->typeOfReciprocalSpacePlot() & 1) + _reciprocalSpacePlot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLogScaleEngine()); + else + _reciprocalSpacePlot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine()); + if (modifier->typeOfReciprocalSpacePlot() & 2) + _reciprocalSpacePlot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLogScaleEngine()); + else + _reciprocalSpacePlot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine()); + + _realSpacePlot->setAxisScale(QwtPlot::xBottom, modifier->realSpaceXAxisRangeStart(), modifier->realSpaceXAxisRangeEnd()); + _realSpacePlot->setAxisScale(QwtPlot::yLeft, modifier->realSpaceYAxisRangeStart(), modifier->realSpaceYAxisRangeEnd()); + _reciprocalSpacePlot->setAxisScale(QwtPlot::xBottom, modifier->reciprocalSpaceXAxisRangeStart(), modifier->reciprocalSpaceXAxisRangeEnd()); + _reciprocalSpacePlot->setAxisScale(QwtPlot::yLeft, modifier->reciprocalSpaceYAxisRangeStart(), modifier->reciprocalSpaceYAxisRangeEnd()); + + _realSpacePlot->replot(); + _reciprocalSpacePlot->replot(); +} + +/****************************************************************************** +* This is called when the user has clicked the "Save Data" button. +******************************************************************************/ +void CorrelationFunctionModifierEditor::onSaveData() +{ + CorrelationFunctionModifier* modifier = static_object_cast(editObject()); + if(!modifier) + return; + + if(modifier->realSpaceCorrelation().empty() && modifier->neighCorrelation().empty() && modifier->reciprocalSpaceCorrelation().empty()) + return; + + QString fileName = QFileDialog::getSaveFileName(mainWindow(), + tr("Save Correlation Data"), QString(), tr("Text files (*.txt);;All files (*)")); + if(fileName.isEmpty()) + return; + + try { + QFile file(fileName); + if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) + modifier->throwException(tr("Could not open file for writing: %1").arg(file.errorString())); + + QTextStream stream(&file); + + stream << "# This file contains the correlation between the following property:" << endl; + stream << "# " << modifier->sourceProperty1().name() << " with mean value " << modifier->mean1() << endl; + stream << "# " << modifier->sourceProperty2().name() << " with mean value " << modifier->mean2() << endl; + stream << "# Covariance is " << modifier->covariance() << endl << endl; + + if (!modifier->realSpaceCorrelation().empty()) { + stream << "# Real-space correlation function from FFT follows." << endl; + stream << "# 1: Bin number" << endl; + stream << "# 2: Distance r" << endl; + stream << "# 3: Correlation function C(r)" << endl; + for(int i = 0; i < modifier->realSpaceCorrelation().size(); i++) { + stream << i << "\t" << modifier->realSpaceCorrelationX()[i] << "\t" << modifier->realSpaceCorrelation()[i] << endl; + } + stream << endl; + } + + if (!modifier->neighCorrelation().empty()) { + stream << "# Real-space correlation function from direct sum over neighbors follows." << endl; + stream << "# 1: Bin number" << endl; + stream << "# 2: Distance r" << endl; + stream << "# 3: Correlation function C(r)" << endl; + for(int i = 0; i < modifier->neighCorrelation().size(); i++) { + stream << i << "\t" << modifier->neighCorrelationX()[i] << "\t" << modifier->neighCorrelation()[i] << endl; + } + stream << endl; + } + + if (!modifier->reciprocalSpaceCorrelation().empty()) { + stream << "# Reciprocal-space correlation function from FFT follows." << endl; + stream << "# 1: Bin number" << endl; + stream << "# 2: Wavevector q (includes a factor of 2*pi)" << endl; + stream << "# 3: Correlation function C(q)" << endl; + for(int i = 0; i < modifier->reciprocalSpaceCorrelation().size(); i++) { + stream << i << "\t" << modifier->reciprocalSpaceCorrelationX()[i] << "\t" << modifier->reciprocalSpaceCorrelation()[i] << endl; + } + } + } + catch(const Exception& ex) { + ex.reportError(); + } +} + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/correlation/gui/CorrelationFunctionModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/correlation/gui/CorrelationFunctionModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/correlation/gui/CorrelationFunctionModifierEditor.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/correlation/gui/CorrelationFunctionModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,96 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2016) Alexander Stukowski +// Copyright (2017) Lars Pastewka +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __OVITO_CORRELATION_FUNCTION_MODIFIER_EDITOR_H +#define __OVITO_CORRELATION_FUNCTION_MODIFIER_EDITOR_H + +#include +#include +#include + +class QwtPlot; +class QwtPlotCurve; + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) + +/** + * A properties editor for the CorrelationFunctionModifier class. + */ +class CorrelationFunctionModifierEditor : public ParticleModifierEditor +{ +public: + + /// Default constructor. + Q_INVOKABLE CorrelationFunctionModifierEditor() {} + +protected: + + /// Creates the user interface controls for the editor. + virtual void createUI(const RolloutInsertionParameters& rolloutParams) override; + + /// This method is called when a reference target changes. + virtual bool referenceEvent(RefTarget* source, ReferenceEvent* event) override; + + /// Replots one of the correlation function computed by the modifier. + void plotData(const QVector &xData, const QVector &yData, + QwtPlot *plot, QwtPlotCurve *&curve, + FloatType offset=0.0, FloatType fac=1.0); + +protected Q_SLOTS: + + /// Replots the correlation function computed by the modifier. + void plotAllData(); + + /// This is called when the user has clicked the "Save Data" button. + void onSaveData(); + +private: + + /// The plotting widget for displaying the computed real-space correlation function. + QwtPlot* _realSpacePlot; + + /// The plotting widget for displaying the computed reciprocal-space correlation function. + QwtPlot* _reciprocalSpacePlot; + + /// The plot item for the real-space correlation function. + QwtPlotCurve* _realSpaceCurve = nullptr; + + /// The plot item for the short-ranged part of the real-space correlation function. + QwtPlotCurve* _neighCurve = nullptr; + + /// The plot item for the reciprocal-space correlation function. + QwtPlotCurve* _reciprocalSpaceCurve = nullptr; + + /// For deferred invocation of the plot repaint function. + DeferredMethodInvocation plotAllDataLater; + + Q_OBJECT + OVITO_OBJECT +}; + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace + +#endif // __OVITO_CORRELATION_FUNCTION_MODIFIER_EDITOR_H diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/CrystalAnalysis.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/CrystalAnalysis.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/CrystalAnalysis.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/CrystalAnalysis.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CRYSTALANALYSIS_H -#define __OVITO_CRYSTALANALYSIS_H +#pragma once + #include @@ -50,5 +50,3 @@ } } } - -#endif diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/data/ClusterGraph.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/data/ClusterGraph.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/data/ClusterGraph.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/data/ClusterGraph.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_CLUSTER_GRAPH_H -#define __OVITO_CA_CLUSTER_GRAPH_H +#pragma once + #include #include @@ -100,4 +100,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CA_CLUSTER_GRAPH_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/data/Cluster.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/data/Cluster.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/data/Cluster.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/data/Cluster.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_CLUSTER_STRUCT_H -#define __OVITO_CA_CLUSTER_STRUCT_H +#pragma once + #include @@ -238,4 +238,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CA_CLUSTER_STRUCT_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/data/DislocationNetwork.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/data/DislocationNetwork.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/data/DislocationNetwork.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/data/DislocationNetwork.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_DISLOCATION_NETWORK_H -#define __OVITO_CA_DISLOCATION_NETWORK_H +#pragma once + #include #include @@ -296,4 +296,4 @@ } // End of namespace -#endif // __OVITO_CA_DISLOCATION_NETWORK_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/data/PlanarDefects.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/data/PlanarDefects.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/data/PlanarDefects.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/data/PlanarDefects.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_PLANAR_DEFECTS_H -#define __OVITO_CA_PLANAR_DEFECTS_H +#pragma once + #include #include @@ -57,4 +57,4 @@ } // End of namespace -#endif // __OVITO_CA_PLANAR_DEFECTS_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/exporter/CAExporter.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/exporter/CAExporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/exporter/CAExporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/exporter/CAExporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,14 +26,14 @@ #include #include #include -#include +#include #include #include #include "CAExporter.h" namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, CAExporter, FileExporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CAExporter, FileExporter); /****************************************************************************** * Selects the natural scene nodes to be exported by this exporter under @@ -79,14 +79,11 @@ /****************************************************************************** * Exports a single animation frame to the current output file. *****************************************************************************/ -bool CAExporter::exportFrame(int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) +bool CAExporter::exportFrame(int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) { - if(!FileExporter::exportFrame(frameNumber, time, filePath, progressDisplay)) + if(!FileExporter::exportFrame(frameNumber, time, filePath, taskManager)) return false; - if(progressDisplay) - progressDisplay->setStatusText(tr("Exporting frame %1 to file '%2'.").arg(frameNumber).arg(filePath)); - // Export the first scene node from the selection set. if(outputData().empty()) throwException(tr("The selection set to be exported is empty.")); @@ -96,7 +93,10 @@ throwException(tr("The scene node to be exported is not an object node.")); // Evaluate pipeline of object node. - const PipelineFlowState& state = objectNode->evalPipeline(time); + auto evalFuture = objectNode->evaluatePipelineAsync(PipelineEvalRequest(time, false)); + if(!taskManager.waitForTask(evalFuture)) + return false; + const PipelineFlowState& state = evalFuture.result(); if(state.isEmpty()) throwException(tr("The object to be exported does not contain any data.")); diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/exporter/CAExporter.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/exporter/CAExporter.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/exporter/CAExporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/exporter/CAExporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CRYSTALANALYSIS_EXPORTER_H -#define __OVITO_CRYSTALANALYSIS_EXPORTER_H +#pragma once + #include #include @@ -56,7 +56,7 @@ protected: /// \brief Exports a single animation frame to the current output file. - virtual bool exportFrame(int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) override; + virtual bool exportFrame(int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) override; /// \brief This is called once for every output file to be written and before exportData() is called. virtual bool openOutputFile(const QString& filePath, int numberOfFrames) override; @@ -89,4 +89,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CRYSTALANALYSIS_EXPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/importer/CAImporterEditor.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/importer/CAImporterEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/importer/CAImporterEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/importer/CAImporterEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,7 +26,7 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_OVITO_OBJECT(CrystalAnalysisGui, CAImporterEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(CAImporterEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(CAImporter, CAImporterEditor); /****************************************************************************** @@ -42,11 +42,11 @@ layout->setContentsMargins(4,4,4,4); layout->setSpacing(4); - BooleanParameterUI* loadParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(CAImporter::_loadParticles)); + BooleanParameterUI* loadParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(CAImporter::loadParticles)); layout->addWidget(loadParticlesUI->checkBox()); // Multi-timestep file - BooleanParameterUI* multitimestepUI = new BooleanParameterUI(this, PROPERTY_FIELD(ParticleImporter::_isMultiTimestepFile)); + BooleanParameterUI* multitimestepUI = new BooleanParameterUI(this, PROPERTY_FIELD(ParticleImporter::isMultiTimestepFile)); layout->addWidget(multitimestepUI->checkBox()); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/importer/CAImporterEditor.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/importer/CAImporterEditor.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/importer/CAImporterEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/importer/CAImporterEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CRYSTALANALYSIS_IMPORTER_EDITOR_H -#define __OVITO_CRYSTALANALYSIS_IMPORTER_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CRYSTALANALYSIS_IMPORTER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/ConstructSurfaceModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/ConstructSurfaceModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/ConstructSurfaceModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/ConstructSurfaceModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_OVITO_OBJECT(CrystalAnalysisGui, ConstructSurfaceModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(ConstructSurfaceModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(ConstructSurfaceModifier, ConstructSurfaceModifierEditor); /****************************************************************************** @@ -45,15 +45,15 @@ layout->setSpacing(6); layout->setColumnStretch(1, 1); - FloatParameterUI* radiusUI = new FloatParameterUI(this, PROPERTY_FIELD(ConstructSurfaceModifier::_probeSphereRadius)); + FloatParameterUI* radiusUI = new FloatParameterUI(this, PROPERTY_FIELD(ConstructSurfaceModifier::probeSphereRadius)); layout->addWidget(radiusUI->label(), 0, 0); layout->addLayout(radiusUI->createFieldLayout(), 0, 1); - IntegerParameterUI* smoothingLevelUI = new IntegerParameterUI(this, PROPERTY_FIELD(ConstructSurfaceModifier::_smoothingLevel)); + IntegerParameterUI* smoothingLevelUI = new IntegerParameterUI(this, PROPERTY_FIELD(ConstructSurfaceModifier::smoothingLevel)); layout->addWidget(smoothingLevelUI->label(), 1, 0); layout->addLayout(smoothingLevelUI->createFieldLayout(), 1, 1); - BooleanParameterUI* onlySelectedUI = new BooleanParameterUI(this, PROPERTY_FIELD(ConstructSurfaceModifier::_onlySelectedParticles)); + BooleanParameterUI* onlySelectedUI = new BooleanParameterUI(this, PROPERTY_FIELD(ConstructSurfaceModifier::onlySelectedParticles)); layout->addWidget(onlySelectedUI->checkBox(), 2, 0, 1, 2); // Status label. @@ -62,7 +62,7 @@ statusLabel()->setMinimumHeight(100); // Open a sub-editor for the mesh display object. - new SubObjectParameterUI(this, PROPERTY_FIELD(ConstructSurfaceModifier::_surfaceMeshDisplay), rolloutParams.after(rollout)); + new SubObjectParameterUI(this, PROPERTY_FIELD(ConstructSurfaceModifier::surfaceMeshDisplay), rolloutParams.after(rollout)); } } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/ConstructSurfaceModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/ConstructSurfaceModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/ConstructSurfaceModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/ConstructSurfaceModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CONSTRUCT_SURFACE_MODIFIER_EDITOR_H -#define __OVITO_CONSTRUCT_SURFACE_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CONSTRUCT_SURFACE_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/DislocationAnalysisModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/DislocationAnalysisModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/DislocationAnalysisModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/DislocationAnalysisModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,11 +30,11 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_OVITO_OBJECT(CrystalAnalysisGui, DislocationAnalysisModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(DislocationAnalysisModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(DislocationAnalysisModifier, DislocationAnalysisModifierEditor); -IMPLEMENT_OVITO_OBJECT(CrystalAnalysisGui, DislocationTypeListParameterUI, RefTargetListParameterUI); -DEFINE_FLAGS_REFERENCE_FIELD(DislocationTypeListParameterUI, _modifier, "Modifier", DislocationAnalysisModifier, PROPERTY_FIELD_NO_UNDO | PROPERTY_FIELD_WEAK_REF | PROPERTY_FIELD_NO_CHANGE_MESSAGE); +IMPLEMENT_OVITO_OBJECT(DislocationTypeListParameterUI, RefTargetListParameterUI); +DEFINE_FLAGS_REFERENCE_FIELD(DislocationTypeListParameterUI, modifier, "Modifier", DislocationAnalysisModifier, PROPERTY_FIELD_NO_UNDO | PROPERTY_FIELD_WEAK_REF | PROPERTY_FIELD_NO_CHANGE_MESSAGE); /****************************************************************************** * Sets up the UI widgets of the editor. @@ -52,7 +52,7 @@ layout->addWidget(structureBox); QVBoxLayout* sublayout1 = new QVBoxLayout(structureBox); sublayout1->setContentsMargins(4,4,4,4); - VariantComboBoxParameterUI* crystalStructureUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::_inputCrystalStructure)); + VariantComboBoxParameterUI* crystalStructureUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::inputCrystalStructure)); crystalStructureUI->comboBox()->addItem(tr("Face-centered cubic (FCC)"), QVariant::fromValue((int)StructureAnalysis::LATTICE_FCC)); crystalStructureUI->comboBox()->addItem(tr("Hexagonal close-packed (HCP)"), QVariant::fromValue((int)StructureAnalysis::LATTICE_HCP)); @@ -68,11 +68,11 @@ sublayout->setSpacing(4); sublayout->setColumnStretch(1, 1); - IntegerParameterUI* maxTrialCircuitSizeUI = new IntegerParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::_maxTrialCircuitSize)); + IntegerParameterUI* maxTrialCircuitSizeUI = new IntegerParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::maxTrialCircuitSize)); sublayout->addWidget(maxTrialCircuitSizeUI->label(), 0, 0); sublayout->addLayout(maxTrialCircuitSizeUI->createFieldLayout(), 0, 1); - IntegerParameterUI* circuitStretchabilityUI = new IntegerParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::_circuitStretchability)); + IntegerParameterUI* circuitStretchabilityUI = new IntegerParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::circuitStretchability)); sublayout->addWidget(circuitStretchabilityUI->label(), 1, 0); sublayout->addLayout(circuitStretchabilityUI->createFieldLayout(), 1, 1); @@ -84,17 +84,17 @@ sublayout->setColumnStretch(0, 1); #if 0 - BooleanParameterUI* reconstructEdgeVectorsUI = new BooleanParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::_reconstructEdgeVectors)); + BooleanParameterUI* reconstructEdgeVectorsUI = new BooleanParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::reconstructEdgeVectors)); sublayout->addWidget(reconstructEdgeVectorsUI->checkBox(), 0, 0); #endif - BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::_onlySelectedParticles)); + BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::onlySelectedParticles)); sublayout->addWidget(onlySelectedParticlesUI->checkBox(), 0, 0); - BooleanParameterUI* outputInterfaceMeshUI = new BooleanParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::_outputInterfaceMesh)); + BooleanParameterUI* outputInterfaceMeshUI = new BooleanParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::outputInterfaceMesh)); sublayout->addWidget(outputInterfaceMeshUI->checkBox(), 1, 0); - BooleanParameterUI* onlyPerfectDislocationsUI = new BooleanParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::_onlyPerfectDislocations)); + BooleanParameterUI* onlyPerfectDislocationsUI = new BooleanParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::onlyPerfectDislocations)); sublayout->addWidget(onlyPerfectDislocationsUI->checkBox(), 2, 0); // Status label. @@ -108,16 +108,16 @@ layout->addWidget(structureTypesPUI->tableWidget()); // Open a sub-editor for the mesh display object. - //new SubObjectParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::_defectMeshDisplay), rolloutParams.after(rollout)); + //new SubObjectParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::defectMeshDisplay), rolloutParams.after(rollout)); // Open a sub-editor for the internal surface smoothing modifier. - new SubObjectParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::_smoothSurfaceModifier), rolloutParams.after(rollout).setTitle(tr("Post-processing"))); + new SubObjectParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::smoothSurfaceModifier), rolloutParams.after(rollout).setTitle(tr("Post-processing"))); // Open a sub-editor for the dislocation display object. //new SubObjectParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::_dislocationDisplay), rolloutParams.after(rollout)); // Open a sub-editor for the internal line smoothing modifier. - new SubObjectParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::_smoothDislocationsModifier), rolloutParams.after(rollout).setTitle(tr("Post-processing"))); + new SubObjectParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::smoothDislocationsModifier), rolloutParams.after(rollout).setTitle(tr("Post-processing"))); // Burgers vector list. _burgersFamilyListUI.reset(new DislocationTypeListParameterUI()); @@ -133,9 +133,9 @@ * Constructor. ******************************************************************************/ DislocationTypeListParameterUI::DislocationTypeListParameterUI(QObject* parent) - : RefTargetListParameterUI(parent, PROPERTY_FIELD(StructurePattern::_burgersVectorFamilies)) + : RefTargetListParameterUI(parent, PROPERTY_FIELD(StructurePattern::burgersVectorFamilies)) { - INIT_PROPERTY_FIELD(DislocationTypeListParameterUI::_modifier); + INIT_PROPERTY_FIELD(modifier); connect(tableWidget(160), &QTableWidget::doubleClicked, this, &DislocationTypeListParameterUI::onDoubleClickDislocationType); tableWidget()->setAutoScroll(false); diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/DislocationAnalysisModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/DislocationAnalysisModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/DislocationAnalysisModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/DislocationAnalysisModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DISLOCATION_ANALYSIS_MODIFIER_EDITOR_H -#define __OVITO_DISLOCATION_ANALYSIS_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -86,12 +86,10 @@ private: /// The modifier whose results are being displayed. - ReferenceField _modifier; + DECLARE_REFERENCE_FIELD(DislocationAnalysisModifier, modifier); Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_modifier); }; /** @@ -121,4 +119,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_DISLOCATION_ANALYSIS_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/ElasticStrainModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/ElasticStrainModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/ElasticStrainModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/ElasticStrainModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -31,7 +31,7 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_OVITO_OBJECT(CrystalAnalysisGui, ElasticStrainModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(ElasticStrainModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(ElasticStrainModifier, ElasticStrainModifierEditor); /****************************************************************************** @@ -52,7 +52,7 @@ sublayout1->setContentsMargins(4,4,4,4); sublayout1->setSpacing(4); sublayout1->setColumnStretch(1,1); - VariantComboBoxParameterUI* crystalStructureUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(ElasticStrainModifier::_inputCrystalStructure)); + VariantComboBoxParameterUI* crystalStructureUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(ElasticStrainModifier::inputCrystalStructure)); crystalStructureUI->comboBox()->addItem(tr("Face-centered cubic (FCC)"), QVariant::fromValue((int)StructureAnalysis::LATTICE_FCC)); crystalStructureUI->comboBox()->addItem(tr("Hexagonal close-packed (HCP)"), QVariant::fromValue((int)StructureAnalysis::LATTICE_HCP)); @@ -61,11 +61,11 @@ crystalStructureUI->comboBox()->addItem(tr("Diamond hexagonal / Wurtzite"), QVariant::fromValue((int)StructureAnalysis::LATTICE_HEX_DIAMOND)); sublayout1->addWidget(crystalStructureUI->comboBox(), 0, 0, 1, 2); - FloatParameterUI* latticeConstantUI = new FloatParameterUI(this, PROPERTY_FIELD(ElasticStrainModifier::_latticeConstant)); + FloatParameterUI* latticeConstantUI = new FloatParameterUI(this, PROPERTY_FIELD(ElasticStrainModifier::latticeConstant)); sublayout1->addWidget(latticeConstantUI->label(), 1, 0); sublayout1->addLayout(latticeConstantUI->createFieldLayout(), 1, 1); - _caRatioUI = new FloatParameterUI(this, PROPERTY_FIELD(ElasticStrainModifier::_caRatio)); + _caRatioUI = new FloatParameterUI(this, PROPERTY_FIELD(ElasticStrainModifier::axialRatio)); sublayout1->addWidget(_caRatioUI->label(), 2, 0); sublayout1->addLayout(_caRatioUI->createFieldLayout(), 2, 1); @@ -77,10 +77,10 @@ sublayout2->setColumnStretch(1, 1); sublayout2->setColumnMinimumWidth(0, 12); - BooleanParameterUI* outputStrainTensorsUI = new BooleanParameterUI(this, PROPERTY_FIELD(ElasticStrainModifier::_calculateStrainTensors)); + BooleanParameterUI* outputStrainTensorsUI = new BooleanParameterUI(this, PROPERTY_FIELD(ElasticStrainModifier::calculateStrainTensors)); sublayout2->addWidget(outputStrainTensorsUI->checkBox(), 0, 0, 1, 2); - BooleanRadioButtonParameterUI* pushStrainTensorsForwardUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(ElasticStrainModifier::_pushStrainTensorsForward)); + BooleanRadioButtonParameterUI* pushStrainTensorsForwardUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(ElasticStrainModifier::pushStrainTensorsForward)); pushStrainTensorsForwardUI->buttonTrue()->setText(tr("in spatial frame")); pushStrainTensorsForwardUI->buttonFalse()->setText(tr("in lattice frame")); sublayout2->addWidget(pushStrainTensorsForwardUI->buttonTrue(), 1, 1); @@ -89,7 +89,7 @@ pushStrainTensorsForwardUI->setEnabled(false); connect(outputStrainTensorsUI->checkBox(), &QCheckBox::toggled, pushStrainTensorsForwardUI, &BooleanRadioButtonParameterUI::setEnabled); - BooleanParameterUI* outputDeformationGradientsUI = new BooleanParameterUI(this, PROPERTY_FIELD(ElasticStrainModifier::_calculateDeformationGradients)); + BooleanParameterUI* outputDeformationGradientsUI = new BooleanParameterUI(this, PROPERTY_FIELD(ElasticStrainModifier::calculateDeformationGradients)); sublayout2->addWidget(outputDeformationGradientsUI->checkBox(), 3, 0, 1, 2); // Status label. diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/ElasticStrainModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/ElasticStrainModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/ElasticStrainModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/ElasticStrainModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ELASTIC_STRAIN_MODIFIER_EDITOR_H -#define __OVITO_ELASTIC_STRAIN_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -59,4 +59,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_ELASTIC_STRAIN_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/GrainSegmentationModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/GrainSegmentationModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/GrainSegmentationModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/GrainSegmentationModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -32,7 +32,7 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_OVITO_OBJECT(CrystalAnalysisGui, GrainSegmentationModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(GrainSegmentationModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(GrainSegmentationModifier, GrainSegmentationModifierEditor); /****************************************************************************** @@ -53,7 +53,7 @@ sublayout1->setContentsMargins(4,4,4,4); sublayout1->setSpacing(4); sublayout1->setColumnStretch(1,1); - VariantComboBoxParameterUI* crystalStructureUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::_inputCrystalStructure)); + VariantComboBoxParameterUI* crystalStructureUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::inputCrystalStructure)); crystalStructureUI->comboBox()->addItem(tr("Face-centered cubic (FCC)"), QVariant::fromValue((int)StructureAnalysis::LATTICE_FCC)); crystalStructureUI->comboBox()->addItem(tr("Hexagonal close-packed (HCP)"), QVariant::fromValue((int)StructureAnalysis::LATTICE_HCP)); @@ -62,7 +62,7 @@ crystalStructureUI->comboBox()->addItem(tr("Diamond hexagonal / Wurtzite"), QVariant::fromValue((int)StructureAnalysis::LATTICE_HEX_DIAMOND)); sublayout1->addWidget(crystalStructureUI->comboBox(), 0, 0, 1, 2); - BooleanParameterUI* onlySelectedUI = new BooleanParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::_onlySelectedParticles)); + BooleanParameterUI* onlySelectedUI = new BooleanParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::onlySelectedParticles)); sublayout1->addWidget(onlySelectedUI->checkBox(), 1, 0, 1, 2); QGroupBox* paramsBox = new QGroupBox(tr("Parameters")); @@ -72,30 +72,30 @@ sublayout2->setSpacing(4); sublayout2->setColumnStretch(1, 1); - FloatParameterUI* misorientationThresholdUI = new FloatParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::_misorientationThreshold)); + FloatParameterUI* misorientationThresholdUI = new FloatParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::misorientationThreshold)); sublayout2->addWidget(misorientationThresholdUI->label(), 0, 0); sublayout2->addLayout(misorientationThresholdUI->createFieldLayout(), 0, 1); - FloatParameterUI* fluctuationToleranceUI = new FloatParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::_fluctuationTolerance)); + FloatParameterUI* fluctuationToleranceUI = new FloatParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::fluctuationTolerance)); sublayout2->addWidget(fluctuationToleranceUI->label(), 1, 0); sublayout2->addLayout(fluctuationToleranceUI->createFieldLayout(), 1, 1); - IntegerParameterUI* minGrainAtomCountUI = new IntegerParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::_minGrainAtomCount)); + IntegerParameterUI* minGrainAtomCountUI = new IntegerParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::minGrainAtomCount)); sublayout2->addWidget(minGrainAtomCountUI->label(), 2, 0); sublayout2->addLayout(minGrainAtomCountUI->createFieldLayout(), 2, 1); - BooleanGroupBoxParameterUI* generateMeshUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::_outputPartitionMesh)); + BooleanGroupBoxParameterUI* generateMeshUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::outputPartitionMesh)); generateMeshUI->groupBox()->setTitle(tr("Generate boundary mesh")); sublayout2 = new QGridLayout(generateMeshUI->childContainer()); sublayout2->setContentsMargins(4,4,4,4); sublayout2->setColumnStretch(1, 1); layout->addWidget(generateMeshUI->groupBox()); - FloatParameterUI* radiusUI = new FloatParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::_probeSphereRadius)); + FloatParameterUI* radiusUI = new FloatParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::probeSphereRadius)); sublayout2->addWidget(radiusUI->label(), 0, 0); sublayout2->addLayout(radiusUI->createFieldLayout(), 0, 1); - IntegerParameterUI* smoothingLevelUI = new IntegerParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::_smoothingLevel)); + IntegerParameterUI* smoothingLevelUI = new IntegerParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::smoothingLevel)); sublayout2->addWidget(smoothingLevelUI->label(), 1, 0); sublayout2->addLayout(smoothingLevelUI->createFieldLayout(), 1, 1); @@ -108,7 +108,7 @@ layout->addWidget(structureTypesPUI->tableWidget()); // Open a sub-editor for the mesh display object. - new SubObjectParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::_meshDisplay), rolloutParams.after(rollout)); + new SubObjectParameterUI(this, PROPERTY_FIELD(GrainSegmentationModifier::meshDisplay), rolloutParams.after(rollout)); } } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/GrainSegmentationModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/GrainSegmentationModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/GrainSegmentationModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/GrainSegmentationModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_GRAIN_SEGMENTATION_MODIFIER_EDITOR_H -#define __OVITO_GRAIN_SEGMENTATION_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_GRAIN_SEGMENTATION_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/SmoothDislocationsModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/SmoothDislocationsModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/SmoothDislocationsModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/SmoothDislocationsModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,7 +28,7 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_OVITO_OBJECT(CrystalAnalysisGui, SmoothDislocationsModifierEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(SmoothDislocationsModifierEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(SmoothDislocationsModifier, SmoothDislocationsModifierEditor); /****************************************************************************** @@ -42,25 +42,25 @@ QVBoxLayout* layout = new QVBoxLayout(rollout); layout->setContentsMargins(4,4,4,4); - BooleanGroupBoxParameterUI* smoothingEnabledUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(SmoothDislocationsModifier::_smoothingEnabled)); + BooleanGroupBoxParameterUI* smoothingEnabledUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(SmoothDislocationsModifier::smoothingEnabled)); smoothingEnabledUI->groupBox()->setTitle(tr("Line smoothing")); QGridLayout* sublayout = new QGridLayout(smoothingEnabledUI->childContainer()); sublayout->setContentsMargins(4,4,4,4); sublayout->setColumnStretch(1, 1); layout->addWidget(smoothingEnabledUI->groupBox()); - IntegerParameterUI* smoothingLevelUI = new IntegerParameterUI(this, PROPERTY_FIELD(SmoothDislocationsModifier::_smoothingLevel)); + IntegerParameterUI* smoothingLevelUI = new IntegerParameterUI(this, PROPERTY_FIELD(SmoothDislocationsModifier::smoothingLevel)); sublayout->addWidget(smoothingLevelUI->label(), 0, 0); sublayout->addLayout(smoothingLevelUI->createFieldLayout(), 0, 1); - BooleanGroupBoxParameterUI* coarseningEnabledUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(SmoothDislocationsModifier::_coarseningEnabled)); + BooleanGroupBoxParameterUI* coarseningEnabledUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(SmoothDislocationsModifier::coarseningEnabled)); coarseningEnabledUI->groupBox()->setTitle(tr("Line coarsening")); sublayout = new QGridLayout(coarseningEnabledUI->childContainer()); sublayout->setContentsMargins(4,4,4,4); sublayout->setColumnStretch(1, 1); layout->addWidget(coarseningEnabledUI->groupBox()); - FloatParameterUI* linePointIntervalUI = new FloatParameterUI(this, PROPERTY_FIELD(SmoothDislocationsModifier::_linePointInterval)); + FloatParameterUI* linePointIntervalUI = new FloatParameterUI(this, PROPERTY_FIELD(SmoothDislocationsModifier::linePointInterval)); sublayout->addWidget(linePointIntervalUI->label(), 0, 0); sublayout->addLayout(linePointIntervalUI->createFieldLayout(), 0, 1); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/SmoothDislocationsModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/SmoothDislocationsModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/SmoothDislocationsModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/SmoothDislocationsModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_SMOOTH_DISLOCATIONS_MODIFIER_EDITOR_H -#define __OVITO_CA_SMOOTH_DISLOCATIONS_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CA_SMOOTH_DISLOCATIONS_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/SmoothSurfaceModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/SmoothSurfaceModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/SmoothSurfaceModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/SmoothSurfaceModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,11 +22,12 @@ #include #include #include +#include #include "SmoothSurfaceModifierEditor.h" namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_OVITO_OBJECT(CrystalAnalysisGui, SmoothSurfaceModifierEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(SmoothSurfaceModifierEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(SmoothSurfaceModifier, SmoothSurfaceModifierEditor); /****************************************************************************** @@ -42,9 +43,13 @@ layout->setSpacing(6); layout->setColumnStretch(1, 1); - IntegerParameterUI* smoothingLevelUI = new IntegerParameterUI(this, PROPERTY_FIELD(SmoothSurfaceModifier::_smoothingLevel)); + IntegerParameterUI* smoothingLevelUI = new IntegerParameterUI(this, PROPERTY_FIELD(SmoothSurfaceModifier::smoothingLevel)); layout->addWidget(smoothingLevelUI->label(), 0, 0); layout->addLayout(smoothingLevelUI->createFieldLayout(), 0, 1); + + FloatParameterUI* minEdgeLengthUI = new FloatParameterUI(this, PROPERTY_FIELD(SmoothSurfaceModifier::minEdgeLength)); + layout->addWidget(minEdgeLengthUI->label(), 1, 0); + layout->addLayout(minEdgeLengthUI->createFieldLayout(), 1, 1); } } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/SmoothSurfaceModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/SmoothSurfaceModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/modifier/SmoothSurfaceModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/modifier/SmoothSurfaceModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_SMOOTH_SURFACE_MODIFIER_EDITOR_H -#define __OVITO_CA_SMOOTH_SURFACE_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CA_SMOOTH_SURFACE_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/dislocations/DislocationDisplayEditor.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/dislocations/DislocationDisplayEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/dislocations/DislocationDisplayEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/dislocations/DislocationDisplayEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -31,7 +31,7 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_OVITO_OBJECT(CrystalAnalysisGui, DislocationDisplayEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(DislocationDisplayEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(DislocationDisplay, DislocationDisplayEditor); /****************************************************************************** @@ -55,23 +55,23 @@ layout->addWidget(linesGroupBox); // Shading mode. - VariantComboBoxParameterUI* shadingModeUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(DislocationDisplay::_shadingMode)); + VariantComboBoxParameterUI* shadingModeUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(DislocationDisplay::shadingMode)); shadingModeUI->comboBox()->addItem(tr("Normal"), qVariantFromValue(ArrowPrimitive::NormalShading)); shadingModeUI->comboBox()->addItem(tr("Flat"), qVariantFromValue(ArrowPrimitive::FlatShading)); sublayout->addWidget(new QLabel(tr("Shading mode:")), 0, 0); sublayout->addWidget(shadingModeUI->comboBox(), 0, 1); // Line width parameter. - FloatParameterUI* lineWidthUI = new FloatParameterUI(this, PROPERTY_FIELD(DislocationDisplay::_lineWidth)); + FloatParameterUI* lineWidthUI = new FloatParameterUI(this, PROPERTY_FIELD(DislocationDisplay::lineWidth)); sublayout->addWidget(lineWidthUI->label(), 1, 0); sublayout->addLayout(lineWidthUI->createFieldLayout(), 1, 1); // Show line directions. - BooleanParameterUI* showLineDirectionsUI = new BooleanParameterUI(this, PROPERTY_FIELD(DislocationDisplay::_showLineDirections)); + BooleanParameterUI* showLineDirectionsUI = new BooleanParameterUI(this, PROPERTY_FIELD(DislocationDisplay::showLineDirections)); sublayout->addWidget(showLineDirectionsUI->checkBox(), 2, 0, 1, 2); // Show Burgers vectors. - BooleanGroupBoxParameterUI* showBurgersVectorsGroupUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(DislocationDisplay::_showBurgersVectors)); + BooleanGroupBoxParameterUI* showBurgersVectorsGroupUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(DislocationDisplay::showBurgersVectors)); showBurgersVectorsGroupUI->groupBox()->setTitle(tr("Burgers vectors")); sublayout = new QGridLayout(showBurgersVectorsGroupUI->childContainer()); sublayout->setContentsMargins(4,4,4,4); @@ -80,17 +80,17 @@ layout->addWidget(showBurgersVectorsGroupUI->groupBox()); // Arrow scaling. - FloatParameterUI* burgersVectorScalingUI = new FloatParameterUI(this, PROPERTY_FIELD(DislocationDisplay::_burgersVectorScaling)); + FloatParameterUI* burgersVectorScalingUI = new FloatParameterUI(this, PROPERTY_FIELD(DislocationDisplay::burgersVectorScaling)); sublayout->addWidget(new QLabel(tr("Scaling factor:")), 0, 0); sublayout->addLayout(burgersVectorScalingUI->createFieldLayout(), 0, 1); // Arrow width. - FloatParameterUI* burgersVectorWidthUI = new FloatParameterUI(this, PROPERTY_FIELD(DislocationDisplay::_burgersVectorWidth)); + FloatParameterUI* burgersVectorWidthUI = new FloatParameterUI(this, PROPERTY_FIELD(DislocationDisplay::burgersVectorWidth)); sublayout->addWidget(new QLabel(tr("Width:")), 1, 0); sublayout->addLayout(burgersVectorWidthUI->createFieldLayout(), 1, 1); // Arrow color. - ColorParameterUI* burgersVectorColorUI = new ColorParameterUI(this, PROPERTY_FIELD(DislocationDisplay::_burgersVectorColor)); + ColorParameterUI* burgersVectorColorUI = new ColorParameterUI(this, PROPERTY_FIELD(DislocationDisplay::burgersVectorColor)); sublayout->addWidget(new QLabel(tr("Color:")), 2, 0); sublayout->addWidget(burgersVectorColorUI->colorPicker(), 2, 1); @@ -102,7 +102,7 @@ sublayout->setColumnStretch(1, 1); layout->addWidget(coloringGroupBox); - IntegerRadioButtonParameterUI* coloringModeUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(DislocationDisplay::_lineColoringMode)); + IntegerRadioButtonParameterUI* coloringModeUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(DislocationDisplay::lineColoringMode)); sublayout->addWidget(coloringModeUI->addRadioButton(DislocationDisplay::ColorByDislocationType, tr("Dislocation type")), 0, 0, 1, 2); sublayout->addWidget(coloringModeUI->addRadioButton(DislocationDisplay::ColorByBurgersVector, tr("Burgers vector")), 1, 0, 1, 2); sublayout->addWidget(coloringModeUI->addRadioButton(DislocationDisplay::ColorByCharacter, tr("Local character")), 2, 0); diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/dislocations/DislocationDisplayEditor.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/dislocations/DislocationDisplayEditor.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/dislocations/DislocationDisplayEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/dislocations/DislocationDisplayEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_DISLOCATION_DISPLAY_EDITOR_H -#define __OVITO_CA_DISLOCATION_DISPLAY_EDITOR_H +#pragma once + #include #include @@ -50,4 +50,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CA_DISLOCATION_DISPLAY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/partition_mesh/PartitionMeshDisplayEditor.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/partition_mesh/PartitionMeshDisplayEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/partition_mesh/PartitionMeshDisplayEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/partition_mesh/PartitionMeshDisplayEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_OVITO_OBJECT(CrystalAnalysisGui, PartitionMeshDisplayEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(PartitionMeshDisplayEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(PartitionMeshDisplay, PartitionMeshDisplayEditor); /****************************************************************************** @@ -52,21 +52,21 @@ sublayout->setColumnStretch(1, 1); layout->addWidget(surfaceGroupBox); - ColorParameterUI* surfaceColorUI = new ColorParameterUI(this, PROPERTY_FIELD(PartitionMeshDisplay::_surfaceColor)); + ColorParameterUI* surfaceColorUI = new ColorParameterUI(this, PROPERTY_FIELD(PartitionMeshDisplay::surfaceColor)); sublayout->addWidget(surfaceColorUI->label(), 0, 0); sublayout->addWidget(surfaceColorUI->colorPicker(), 0, 1); - FloatParameterUI* surfaceTransparencyUI = new FloatParameterUI(this, PROPERTY_FIELD(PartitionMeshDisplay::_surfaceTransparency)); + FloatParameterUI* surfaceTransparencyUI = new FloatParameterUI(this, PROPERTY_FIELD(PartitionMeshDisplay::surfaceTransparencyController)); sublayout->addWidget(new QLabel(tr("Transparency:")), 1, 0); sublayout->addLayout(surfaceTransparencyUI->createFieldLayout(), 1, 1); - BooleanParameterUI* smoothShadingUI = new BooleanParameterUI(this, PROPERTY_FIELD(PartitionMeshDisplay::_smoothShading)); + BooleanParameterUI* smoothShadingUI = new BooleanParameterUI(this, PROPERTY_FIELD(PartitionMeshDisplay::smoothShading)); sublayout->addWidget(smoothShadingUI->checkBox(), 2, 0, 1, 2); - BooleanParameterUI* flipOrientationUI = new BooleanParameterUI(this, PROPERTY_FIELD(PartitionMeshDisplay::_flipOrientation)); + BooleanParameterUI* flipOrientationUI = new BooleanParameterUI(this, PROPERTY_FIELD(PartitionMeshDisplay::flipOrientation)); sublayout->addWidget(flipOrientationUI->checkBox(), 3, 0, 1, 2); - BooleanGroupBoxParameterUI* capGroupUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(PartitionMeshDisplay::_showCap)); + BooleanGroupBoxParameterUI* capGroupUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(PartitionMeshDisplay::showCap)); capGroupUI->groupBox()->setTitle(tr("Cap polygons")); sublayout = new QGridLayout(capGroupUI->childContainer()); sublayout->setContentsMargins(4,4,4,4); @@ -74,7 +74,7 @@ sublayout->setColumnStretch(1, 1); layout->addWidget(capGroupUI->groupBox()); - FloatParameterUI* capTransparencyUI = new FloatParameterUI(this, PROPERTY_FIELD(PartitionMeshDisplay::_capTransparency)); + FloatParameterUI* capTransparencyUI = new FloatParameterUI(this, PROPERTY_FIELD(PartitionMeshDisplay::capTransparencyController)); sublayout->addWidget(new QLabel(tr("Transparency:")), 0, 0); sublayout->addLayout(capTransparencyUI->createFieldLayout(), 0, 1); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/partition_mesh/PartitionMeshDisplayEditor.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/partition_mesh/PartitionMeshDisplayEditor.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/partition_mesh/PartitionMeshDisplayEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/partition_mesh/PartitionMeshDisplayEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTITION_MESH_DISPLAY_EDITOR_H -#define __OVITO_PARTITION_MESH_DISPLAY_EDITOR_H +#pragma once + #include #include @@ -50,4 +50,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARTITION_MESH_DISPLAY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/patterns/BurgersVectorFamilyEditor.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/patterns/BurgersVectorFamilyEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/patterns/BurgersVectorFamilyEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/patterns/BurgersVectorFamilyEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_OVITO_OBJECT(CrystalAnalysisGui, BurgersVectorFamilyEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(BurgersVectorFamilyEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(BurgersVectorFamily, BurgersVectorFamilyEditor); /****************************************************************************** @@ -45,12 +45,12 @@ layout1->setColumnStretch(1, 1); // Text box for the name of atom type. - StringParameterUI* namePUI = new StringParameterUI(this, PROPERTY_FIELD(BurgersVectorFamily::_name)); + StringParameterUI* namePUI = new StringParameterUI(this, PROPERTY_FIELD(BurgersVectorFamily::name)); layout1->addWidget(new QLabel(tr("Name:")), 0, 0); layout1->addWidget(namePUI->textBox(), 0, 1); // Color parameter. - ColorParameterUI* colorPUI = new ColorParameterUI(this, PROPERTY_FIELD(BurgersVectorFamily::_color)); + ColorParameterUI* colorPUI = new ColorParameterUI(this, PROPERTY_FIELD(BurgersVectorFamily::color)); layout1->addWidget(colorPUI->label(), 1, 0); layout1->addWidget(colorPUI->colorPicker(), 1, 1); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/patterns/BurgersVectorFamilyEditor.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/patterns/BurgersVectorFamilyEditor.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/patterns/BurgersVectorFamilyEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/patterns/BurgersVectorFamilyEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_BURGERS_VECTOR_FAMILY_EDITOR_H -#define __OVITO_CA_BURGERS_VECTOR_FAMILY_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CA_BURGERS_VECTOR_FAMILY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/patterns/PatternCatalogEditor.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/patterns/PatternCatalogEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/patterns/PatternCatalogEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/patterns/PatternCatalogEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_OVITO_OBJECT(CrystalAnalysisGui, PatternCatalogEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(PatternCatalogEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(PatternCatalog, PatternCatalogEditor); /****************************************************************************** @@ -87,7 +87,7 @@ layout->addWidget(subEditorContainer); layout->insertWidget(0, new QLabel(tr("Structure types:"))); - typesListUI = new CustomRefTargetListParameterUI(this, PROPERTY_FIELD(PatternCatalog::_patterns), RolloutInsertionParameters().insertInto(subEditorContainer)); + typesListUI = new CustomRefTargetListParameterUI(this, PROPERTY_FIELD(PatternCatalog::patterns), RolloutInsertionParameters().insertInto(subEditorContainer)); layout->insertWidget(1, typesListUI->tableWidget(200)); typesListUI->tableWidget()->setAutoScroll(false); connect(typesListUI->tableWidget(), &QTableWidget::doubleClicked, this, &PatternCatalogEditor::onDoubleClickPattern); diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/patterns/PatternCatalogEditor.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/patterns/PatternCatalogEditor.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/patterns/PatternCatalogEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/patterns/PatternCatalogEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_PATTERN_CATALOG_EDITOR_H -#define __OVITO_CA_PATTERN_CATALOG_EDITOR_H +#pragma once + #include #include @@ -59,4 +59,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CA_PATTERN_CATALOG_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/patterns/StructurePatternEditor.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/patterns/StructurePatternEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/patterns/StructurePatternEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/patterns/StructurePatternEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,7 +28,7 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_OVITO_OBJECT(CrystalAnalysisGui, StructurePatternEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(StructurePatternEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(StructurePattern, StructurePatternEditor); /****************************************************************************** @@ -84,7 +84,7 @@ }; layout1->addWidget(new QLabel(tr("Burgers vector families:"))); - familiesListUI = new CustomRefTargetListParameterUI(this, PROPERTY_FIELD(StructurePattern::_burgersVectorFamilies)); + familiesListUI = new CustomRefTargetListParameterUI(this, PROPERTY_FIELD(StructurePattern::burgersVectorFamilies)); layout1->addWidget(familiesListUI->tableWidget(200)); familiesListUI->tableWidget()->setAutoScroll(false); connect(familiesListUI->tableWidget(), &QTableWidget::doubleClicked, this, &StructurePatternEditor::onDoubleClickBurgersFamily); diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/patterns/StructurePatternEditor.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/patterns/StructurePatternEditor.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/patterns/StructurePatternEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/patterns/StructurePatternEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_STRUCTURE_PATTERN_EDITOR_H -#define __OVITO_CA_STRUCTURE_PATTERN_EDITOR_H +#pragma once + #include #include @@ -59,4 +59,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CA_STRUCTURE_PATTERN_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/slip_surface/SlipSurfaceDisplayEditor.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/slip_surface/SlipSurfaceDisplayEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/slip_surface/SlipSurfaceDisplayEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/slip_surface/SlipSurfaceDisplayEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,7 +28,7 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_OVITO_OBJECT(CrystalAnalysisGui, SlipSurfaceDisplayEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(SlipSurfaceDisplayEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(SlipSurfaceDisplay, SlipSurfaceDisplayEditor); /****************************************************************************** @@ -44,18 +44,18 @@ layout->setContentsMargins(4,4,4,4); layout->setSpacing(4); - QGroupBox* surfaceGroupBox = new QGroupBox(tr("Surface")); + QGroupBox* surfaceGroupBox = new QGroupBox(tr("Surface display")); QGridLayout* sublayout = new QGridLayout(surfaceGroupBox); sublayout->setContentsMargins(4,4,4,4); sublayout->setSpacing(4); sublayout->setColumnStretch(1, 1); layout->addWidget(surfaceGroupBox); - FloatParameterUI* surfaceTransparencyUI = new FloatParameterUI(this, PROPERTY_FIELD(SlipSurfaceDisplay::_surfaceTransparency)); + FloatParameterUI* surfaceTransparencyUI = new FloatParameterUI(this, PROPERTY_FIELD(SlipSurfaceDisplay::surfaceTransparencyController)); sublayout->addWidget(new QLabel(tr("Transparency:")), 0, 0); sublayout->addLayout(surfaceTransparencyUI->createFieldLayout(), 0, 1); - BooleanParameterUI* smoothShadingUI = new BooleanParameterUI(this, PROPERTY_FIELD(SlipSurfaceDisplay::_smoothShading)); + BooleanParameterUI* smoothShadingUI = new BooleanParameterUI(this, PROPERTY_FIELD(SlipSurfaceDisplay::smoothShading)); sublayout->addWidget(smoothShadingUI->checkBox(), 1, 0, 1, 2); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/slip_surface/SlipSurfaceDisplayEditor.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/slip_surface/SlipSurfaceDisplayEditor.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/objects/slip_surface/SlipSurfaceDisplayEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/objects/slip_surface/SlipSurfaceDisplayEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SLIP_SURFACE_DISPLAY_EDITOR_H -#define __OVITO_SLIP_SURFACE_DISPLAY_EDITOR_H +#pragma once + #include #include @@ -50,4 +50,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SLIP_SURFACE_DISPLAY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/util/DislocationInformationApplet.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/util/DislocationInformationApplet.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/util/DislocationInformationApplet.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/util/DislocationInformationApplet.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -33,7 +33,7 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_OVITO_OBJECT(CrystalAnalysisGui, DislocationInformationApplet, UtilityApplet); +IMPLEMENT_OVITO_OBJECT(DislocationInformationApplet, UtilityApplet); /****************************************************************************** * Shows the UI of the utility in the given RolloutContainer. @@ -93,7 +93,7 @@ for(auto& pickedDislocation : _inputMode->_pickedDislocations) { OVITO_ASSERT(pickedDislocation.objNode); - const PipelineFlowState& flowState = pickedDislocation.objNode->evalPipeline(dataset->animationSettings()->time()); + const PipelineFlowState& flowState = pickedDislocation.objNode->evaluatePipelineImmediately(PipelineEvalRequest(dataset->animationSettings()->time(), false)); DislocationNetworkObject* dislocationObj = flowState.findObject(); if(!dislocationObj || pickedDislocation.segmentIndex >= dislocationObj->segments().size()) continue; @@ -244,7 +244,7 @@ for(const auto& pickedDislocation : _pickedDislocations) { - const PipelineFlowState& flowState = pickedDislocation.objNode->evalPipeline(vp->dataset()->animationSettings()->time()); + const PipelineFlowState& flowState = pickedDislocation.objNode->evaluatePipelineImmediately(PipelineEvalRequest(vp->dataset()->animationSettings()->time(), true)); DislocationNetworkObject* dislocationObj = flowState.findObject(); if(!dislocationObj) continue; diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/util/DislocationInformationApplet.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/util/DislocationInformationApplet.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/gui/util/DislocationInformationApplet.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/gui/util/DislocationInformationApplet.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DISLOCATION_INFORMATION_APPLET_H -#define __OVITO_DISLOCATION_INFORMATION_APPLET_H +#pragma once + #include #include @@ -124,4 +124,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_DISLOCATION_INFORMATION_APPLET_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/importer/CAImporter.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/importer/CAImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/importer/CAImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/importer/CAImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -41,16 +41,16 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, CAImporter, ParticleImporter); -DEFINE_PROPERTY_FIELD(CAImporter, _loadParticles, "LoadParticles"); -SET_PROPERTY_FIELD_LABEL(CAImporter, _loadParticles, "Load particles"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CAImporter, ParticleImporter); +DEFINE_PROPERTY_FIELD(CAImporter, loadParticles, "LoadParticles"); +SET_PROPERTY_FIELD_LABEL(CAImporter, loadParticles, "Load particles"); /****************************************************************************** * Is called when the value of a property of this object has changed. ******************************************************************************/ void CAImporter::propertyChanged(const PropertyFieldDescriptor& field) { - if(field == PROPERTY_FIELD(CAImporter::_loadParticles)) { + if(field == PROPERTY_FIELD(CAImporter::loadParticles)) { requestReload(); } ParticleImporter::propertyChanged(field); @@ -77,10 +77,10 @@ /****************************************************************************** * Scans the given input file to find all contained simulation frames. ******************************************************************************/ -void CAImporter::scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) +void CAImporter::scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) { - futureInterface.setProgressText(tr("Scanning CA file %1").arg(stream.filename())); - futureInterface.setProgressRange(stream.underlyingSize() / 1000); + promise.setProgressText(tr("Scanning CA file %1").arg(stream.filename())); + promise.setProgressMaximum(stream.underlyingSize() / 1000); QFileInfo fileInfo(stream.device().fileName()); QString filename = fileInfo.fileName(); @@ -88,7 +88,7 @@ int frameNumber = 0; qint64 byteOffset; - while(!stream.eof()) { + while(!stream.eof() && !promise.isCanceled()) { if(frameNumber == 0) { byteOffset = stream.byteOffset(); @@ -115,7 +115,7 @@ stream.readLineTrimLeft(); if(stream.lineStartsWith("CA_FILE_VERSION ")) break; if((stream.lineNumber() % 4096) == 0) - futureInterface.setProgressValue(stream.underlyingByteOffset() / 1000); + promise.setProgressValue(stream.underlyingByteOffset() / 1000); } } } @@ -249,7 +249,7 @@ if(sscanf(stream.line(), "CLUSTERS %i", &numClusters) != 1) throw Exception(tr("Failed to parse file. Invalid number of clusters in line %1.").arg(stream.lineNumber())); setProgressText(tr("Reading clusters")); - setProgressRange(numClusters); + setProgressMaximum(numClusters); _clusterGraph = new ClusterGraph(); for(int index = 0; index < numClusters; index++) { if(!setProgressValueIntermittent(index)) @@ -327,7 +327,7 @@ if(sscanf(stream.line(), "CLUSTER_TRANSITIONS %i", &numClusterTransitions) != 1) throw Exception(tr("Failed to parse file. Invalid number of cluster transitions in line %1.").arg(stream.lineNumber())); setProgressText(tr("Reading cluster transitions")); - setProgressRange(numClusterTransitions); + setProgressMaximum(numClusterTransitions); for(int index = 0; index < numClusterTransitions; index++) { if(!setProgressValueIntermittent(index)) return; @@ -351,7 +351,7 @@ if(sscanf(stream.line(), "DISLOCATIONS %i", &numDislocationSegments) != 1) throw Exception(tr("Failed to parse file. Invalid number of dislocation segments in line %1.").arg(stream.lineNumber())); setProgressText(tr("Reading dislocations")); - setProgressRange(numDislocationSegments); + setProgressMaximum(numDislocationSegments); _dislocations = new DislocationNetwork(_clusterGraph.data()); for(int index = 0; index < numDislocationSegments; index++) { if(!setProgressValueIntermittent(index)) @@ -429,7 +429,7 @@ if(sscanf(stream.line(), "DEFECT_MESH_VERTICES %i", &numDefectMeshVertices) != 1) throw Exception(tr("Failed to parse file. Invalid number of defect mesh vertices in line %1.").arg(stream.lineNumber())); setProgressText(tr("Reading defect surface")); - setProgressRange(numDefectMeshVertices); + setProgressMaximum(numDefectMeshVertices); _defectSurface = new HalfEdgeMesh<>(); _defectSurface->reserveVertices(numDefectMeshVertices); for(int index = 0; index < numDefectMeshVertices; index++) { @@ -445,7 +445,7 @@ int numDefectMeshFacets; if(sscanf(stream.line(), "DEFECT_MESH_FACETS %i", &numDefectMeshFacets) != 1) throw Exception(tr("Failed to parse file. Invalid number of defect mesh facets in line %1.").arg(stream.lineNumber())); - setProgressRange(numDefectMeshFacets * 2); + setProgressMaximum(numDefectMeshFacets * 2); _defectSurface->reserveFaces(numDefectMeshFacets); for(int index = 0; index < numDefectMeshFacets; index++) { if(!setProgressValueIntermittent(index)) @@ -480,7 +480,7 @@ if(sscanf(stream.line(), "PARTITION_MESH_VERTICES %i", &numVertices) != 1) throw Exception(tr("Failed to parse file. Invalid number of mesh vertices in line %1.").arg(stream.lineNumber())); setProgressText(tr("Reading partition mesh")); - setProgressRange(numVertices); + setProgressMaximum(numVertices); _partitionMesh = new PartitionMeshData(); _partitionMesh->reserveVertices(numVertices); for(int index = 0; index < numVertices; index++) { @@ -496,7 +496,7 @@ int numFacets; if(sscanf(stream.line(), "PARTITION_MESH_FACETS %i", &numFacets) != 1) throw Exception(tr("Failed to parse file. Invalid number of mesh facets in line %1.").arg(stream.lineNumber())); - setProgressRange(numFacets * 2); + setProgressMaximum(numFacets * 2); _partitionMesh->reserveFaces(numFacets); for(int index = 0; index < numFacets; index++) { if(!setProgressValueIntermittent(index)) @@ -543,7 +543,7 @@ if(sscanf(stream.line(), "SLIP_SURFACE_VERTICES %i", &numVertices) != 1) throw Exception(tr("Failed to parse file. Invalid number of mesh vertices in line %1.").arg(stream.lineNumber())); setProgressText(tr("Reading slip surfaces")); - setProgressRange(numVertices); + setProgressMaximum(numVertices); _slipSurface = new SlipSurfaceData(); _slipSurface->reserveVertices(numVertices); for(int index = 0; index < numVertices; index++) { @@ -559,7 +559,7 @@ int numFacets; if(sscanf(stream.line(), "SLIP_SURFACE_FACETS %i", &numFacets) != 1) throw Exception(tr("Failed to parse file. Invalid number of mesh facets in line %1.").arg(stream.lineNumber())); - setProgressRange(numFacets); + setProgressMaximum(numFacets); _slipSurface->reserveFaces(numFacets); for(int index = 0; index < numFacets; index++) { if(!setProgressValueIntermittent(index)) @@ -577,6 +577,46 @@ face->slipVector = ClusterVector(slipVector, cluster); } } + else if(stream.lineStartsWith("STACKING_FAULT_VERTICES ")) { + // Read slip surface vertices. + int numVertices; + if(sscanf(stream.line(), "STACKING_FAULT_VERTICES %i", &numVertices) != 1) + throw Exception(tr("Failed to parse file. Invalid number of mesh vertices in line %1.").arg(stream.lineNumber())); + setProgressText(tr("Reading stacking faults")); + setProgressMaximum(numVertices); + _stackingFaults = new SlipSurfaceData(); + _stackingFaults->reserveVertices(numVertices); + for(int index = 0; index < numVertices; index++) { + if(!setProgressValueIntermittent(index)) return; + Point3 p; + if(sscanf(stream.readLine(), FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING, &p.x(), &p.y(), &p.z()) != 3) + throw Exception(tr("Failed to parse file. Invalid point in line %1.").arg(stream.lineNumber())); + _stackingFaults->createVertex(p); + } + } + else if(stream.lineStartsWith("STACKING_FAULT_FACETS ") && _stackingFaults) { + // Read slip surface facets. + int numFacets; + if(sscanf(stream.line(), "STACKING_FAULT_FACETS %i", &numFacets) != 1) + throw Exception(tr("Failed to parse file. Invalid number of mesh facets in line %1.").arg(stream.lineNumber())); + setProgressMaximum(numFacets); + _stackingFaults->reserveFaces(numFacets); + for(int index = 0; index < numFacets; index++) { + if(!setProgressValueIntermittent(index)) + return; + Vector3 slipVector; + int clusterId; + int v[3]; + if(sscanf(stream.readLine(), FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING " %i %i %i %i", &slipVector.x(), &slipVector.y(), &slipVector.z(), &clusterId, &v[0], &v[1], &v[2]) != 7) + throw Exception(tr("Failed to parse file. Invalid triangle facet in line %1.").arg(stream.lineNumber())); + + SlipSurfaceData::Face* face = _stackingFaults->createFace({ _stackingFaults->vertex(v[0]), _stackingFaults->vertex(v[1]), _stackingFaults->vertex(v[2]) }); + Cluster* cluster = _clusterGraph->findCluster(clusterId); + if(!cluster) + throw Exception(tr("Failed to parse file. Invalid cluster reference in line %1.").arg(stream.lineNumber())); + face->slipVector = ClusterVector(slipVector, cluster); + } + } else if(stream.lineStartsWith("METADATA ")) { // Ignore. This is for future use. } @@ -662,8 +702,16 @@ partitionMeshObj->setStorage(_partitionMesh.data()); } + OORef slipSurfaceObj; + OORef stackingFaultsObj; + for(DataObject* dataObj : oldObjects.objects()) { + if(SlipSurface* surfaceObj = dynamic_object_cast(dataObj)) { + if(!slipSurfaceObj) slipSurfaceObj = surfaceObj; + else if(!stackingFaultsObj) stackingFaultsObj = surfaceObj; + } + } + // Insert slip surface. - OORef slipSurfaceObj = oldObjects.findObject(); if(_slipSurface) { if(!slipSurfaceObj) { slipSurfaceObj = new SlipSurface(container->dataset(), _slipSurface.data()); @@ -674,6 +722,18 @@ slipSurfaceObj->setStorage(_slipSurface.data()); } + // Insert stacking faults. + if(_stackingFaults) { + if(!stackingFaultsObj) { + stackingFaultsObj = new SlipSurface(container->dataset(), _stackingFaults.data()); + OORef displayObj = new SlipSurfaceDisplay(container->dataset()); + displayObj->loadUserDefaults(); + displayObj->setObjectTitle(tr("Stacking faults")); + stackingFaultsObj->setDisplayObject(displayObj); + } + stackingFaultsObj->setStorage(_stackingFaults.data()); + } + // Insert pattern catalog. OORef patternCatalog = oldObjects.findObject(); if(!patternCatalog) { @@ -766,6 +826,8 @@ container->addDataObject(partitionMeshObj); if(_slipSurface) container->addDataObject(slipSurfaceObj); + if(_stackingFaults) + container->addDataObject(stackingFaultsObj); if(patternCatalog) container->addDataObject(patternCatalog); if(clusterGraph) diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/importer/CAImporter.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/importer/CAImporter.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/importer/CAImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/importer/CAImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CRYSTALANALYSIS_IMPORTER_H -#define __OVITO_CRYSTALANALYSIS_IMPORTER_H +#pragma once + #include #include @@ -43,7 +43,7 @@ /// \brief Constructs a new instance of this class. Q_INVOKABLE CAImporter(DataSet* dataset) : ParticleImporter(dataset), _loadParticles(false) { - INIT_PROPERTY_FIELD(CAImporter::_loadParticles); + INIT_PROPERTY_FIELD(loadParticles); } /// \brief Returns the file filter that specifies the files that can be imported by this service. @@ -58,12 +58,6 @@ /// Returns the title of this object. virtual QString objectTitle() override { return tr("CA File"); } - /// Returns whether loading of the associated particle file is enabled. - bool loadParticles() const { return _loadParticles; } - - /// Controls the loading of the associated particle file. - void setLoadParticles(bool enable) { _loadParticles = enable; } - /// Creates an asynchronous loader object that loads the data for the given frame from the external file. virtual std::shared_ptr createFrameLoader(const Frame& frame, bool isNewlySelectedFile) override { return std::make_shared(dataset()->container(), frame, _loadParticles); @@ -124,6 +118,9 @@ /// The slip surfaces. QExplicitlySharedDataPointer _slipSurface; + /// The stacking faults. + QExplicitlySharedDataPointer _stackingFaults; + /// Controls whether particles should be loaded too. bool _loadParticles; @@ -138,21 +135,19 @@ virtual void propertyChanged(const PropertyFieldDescriptor& field) override; /// \brief Scans the given input file to find all contained simulation frames. - virtual void scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; + virtual void scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; private: /// Controls whether the associated particle file should be loaded too. - PropertyField _loadParticles; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, loadParticles, setLoadParticles); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_loadParticles); }; } // End of namespace } // End of namespace } // End of namespace -#endif // __OVITO_CRYSTALANALYSIS_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/ConstructSurfaceModifier.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/ConstructSurfaceModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/ConstructSurfaceModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/ConstructSurfaceModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,17 +28,17 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, ConstructSurfaceModifier, AsynchronousParticleModifier); -DEFINE_FLAGS_PROPERTY_FIELD(ConstructSurfaceModifier, _smoothingLevel, "SmoothingLevel", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ConstructSurfaceModifier, _probeSphereRadius, "Radius", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_REFERENCE_FIELD(ConstructSurfaceModifier, _surfaceMeshDisplay, "SurfaceMeshDisplay", SurfaceMeshDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(ConstructSurfaceModifier, _onlySelectedParticles, "OnlySelectedParticles"); -SET_PROPERTY_FIELD_LABEL(ConstructSurfaceModifier, _smoothingLevel, "Smoothing level"); -SET_PROPERTY_FIELD_LABEL(ConstructSurfaceModifier, _probeSphereRadius, "Probe sphere radius"); -SET_PROPERTY_FIELD_LABEL(ConstructSurfaceModifier, _surfaceMeshDisplay, "Surface mesh display"); -SET_PROPERTY_FIELD_LABEL(ConstructSurfaceModifier, _onlySelectedParticles, "Use only selected particles"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ConstructSurfaceModifier, _probeSphereRadius, WorldParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ConstructSurfaceModifier, _smoothingLevel, IntegerParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ConstructSurfaceModifier, AsynchronousParticleModifier); +DEFINE_FLAGS_PROPERTY_FIELD(ConstructSurfaceModifier, smoothingLevel, "SmoothingLevel", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ConstructSurfaceModifier, probeSphereRadius, "Radius", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(ConstructSurfaceModifier, surfaceMeshDisplay, "SurfaceMeshDisplay", SurfaceMeshDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(ConstructSurfaceModifier, onlySelectedParticles, "OnlySelectedParticles"); +SET_PROPERTY_FIELD_LABEL(ConstructSurfaceModifier, smoothingLevel, "Smoothing level"); +SET_PROPERTY_FIELD_LABEL(ConstructSurfaceModifier, probeSphereRadius, "Probe sphere radius"); +SET_PROPERTY_FIELD_LABEL(ConstructSurfaceModifier, surfaceMeshDisplay, "Surface mesh display"); +SET_PROPERTY_FIELD_LABEL(ConstructSurfaceModifier, onlySelectedParticles, "Use only selected particles"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ConstructSurfaceModifier, probeSphereRadius, WorldParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ConstructSurfaceModifier, smoothingLevel, IntegerParameterUnit, 0); /****************************************************************************** * Constructs the modifier object. @@ -47,10 +47,10 @@ _smoothingLevel(8), _probeSphereRadius(4), _onlySelectedParticles(false), _solidVolume(0), _totalVolume(0), _surfaceArea(0) { - INIT_PROPERTY_FIELD(ConstructSurfaceModifier::_smoothingLevel); - INIT_PROPERTY_FIELD(ConstructSurfaceModifier::_probeSphereRadius); - INIT_PROPERTY_FIELD(ConstructSurfaceModifier::_surfaceMeshDisplay); - INIT_PROPERTY_FIELD(ConstructSurfaceModifier::_onlySelectedParticles); + INIT_PROPERTY_FIELD(smoothingLevel); + INIT_PROPERTY_FIELD(probeSphereRadius); + INIT_PROPERTY_FIELD(surfaceMeshDisplay); + INIT_PROPERTY_FIELD(onlySelectedParticles); // Create the display object. _surfaceMeshDisplay = new SurfaceMeshDisplay(dataset); @@ -64,9 +64,9 @@ AsynchronousParticleModifier::propertyChanged(field); // Recompute results when the parameters have changed. - if(field == PROPERTY_FIELD(ConstructSurfaceModifier::_smoothingLevel) - || field == PROPERTY_FIELD(ConstructSurfaceModifier::_probeSphereRadius) - || field == PROPERTY_FIELD(ConstructSurfaceModifier::_onlySelectedParticles)) + if(field == PROPERTY_FIELD(smoothingLevel) + || field == PROPERTY_FIELD(probeSphereRadius) + || field == PROPERTY_FIELD(onlySelectedParticles)) invalidateCachedResults(); } @@ -83,15 +83,6 @@ } /****************************************************************************** -* Resets the modifier's result cache. -******************************************************************************/ -void ConstructSurfaceModifier::invalidateCachedResults() -{ - AsynchronousParticleModifier::invalidateCachedResults(); - _surfaceMesh.reset(); -} - -/****************************************************************************** * Creates and initializes a computation engine that will compute the modifier's results. ******************************************************************************/ std::shared_ptr ConstructSurfaceModifier::createEngine(TimePoint time, TimeInterval validityInterval) @@ -102,6 +93,8 @@ if(onlySelectedParticles()) selProperty = expectStandardProperty(ParticleProperty::SelectionProperty); SimulationCellObject* simCell = expectSimulationCell(); + if(simCell->is2D()) + throwException(tr("The construct surface mesh modifier does not support 2d simulation cells.")); // Create engine object. Pass all relevant modifier parameters to the engine as well as the input data. return std::make_shared(validityInterval, posProperty->storage(), @@ -133,7 +126,7 @@ // Create the output data object. OORef meshObj(new SurfaceMesh(dataset(), _surfaceMesh.data())); - meshObj->setCompletelySolid(_isCompletelySolid); + meshObj->setIsCompletelySolid(_isCompletelySolid); meshObj->addDisplayObject(_surfaceMeshDisplay); // Insert output object into the pipeline. @@ -187,7 +180,7 @@ // Generate Delaunay tessellation. DelaunayTessellation tessellation; if(!tessellation.generateTessellation(_simCell, positions()->constDataPoint3(), positions()->size(), ghostLayerSize, - selection() ? selection()->constDataInt() : nullptr, this)) + selection() ? selection()->constDataInt() : nullptr, *this)) return; nextProgressSubStep(); @@ -206,7 +199,7 @@ }; ManifoldConstructionHelper, true> manifoldConstructor(tessellation, *mesh(), alpha, positions()); - if(!manifoldConstructor.construct(tetrahedronRegion, this)) + if(!manifoldConstructor.construct(tetrahedronRegion, *this)) return; _isCompletelySolid = (manifoldConstructor.spaceFillingRegion() == 1); @@ -216,10 +209,11 @@ _mesh->duplicateSharedVertices(); nextProgressSubStep(); - SurfaceMesh::smoothMesh(*_mesh, _simCell, _smoothingLevel, this); + if(!SurfaceMesh::smoothMesh(*mesh(), _simCell, _smoothingLevel, *this)) + return; // Compute surface area. - for(const HalfEdgeMesh<>::Face* facet : _mesh->faces()) { + for(const HalfEdgeMesh<>::Face* facet : mesh()->faces()) { if(isCanceled()) return; Vector3 e1 = _simCell.wrapVector(facet->edges()->vertex1()->pos() - facet->edges()->vertex2()->pos()); Vector3 e2 = _simCell.wrapVector(facet->edges()->prevFaceEdge()->vertex1()->pos() - facet->edges()->vertex2()->pos()); diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/ConstructSurfaceModifier.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/ConstructSurfaceModifier.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/ConstructSurfaceModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/ConstructSurfaceModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CONSTRUCT_SURFACE_MODIFIER_H -#define __OVITO_CONSTRUCT_SURFACE_MODIFIER_H +#pragma once + #include #include @@ -39,27 +39,6 @@ /// Constructor. Q_INVOKABLE ConstructSurfaceModifier(DataSet* dataset); - /// \brief Returns the display object that is responsible for rendering the surface mesh. - SurfaceMeshDisplay* surfaceMeshDisplay() const { return _surfaceMeshDisplay; } - - /// \brief Returns the radius parameter used during construction of the surface. - FloatType probeSphereRadius() const { return _probeSphereRadius; } - - /// \brief Sets the radius parameter used during construction of the surface. - void setProbeSphereRadius(FloatType radius) { _probeSphereRadius = radius; } - - /// \brief Returns the level of smoothing applied to the constructed surface mesh. - int smoothingLevel() const { return _smoothingLevel; } - - /// \brief Sets the level of smoothing applied to the constructed surface mesh. - void setSmoothingLevel(int level) { _smoothingLevel = level; } - - /// Returns whether only selected particles are taken into account. - bool onlySelectedParticles() const { return _onlySelectedParticles; } - - /// Sets whether only selected particles should be taken into account. - void setOnlySelectedParticles(bool onlySelected) { _onlySelectedParticles = onlySelected; } - /// Returns the solid volume computed during the last evaluation of the modifier. FloatType solidVolume() const { return _solidVolume; } @@ -69,9 +48,6 @@ /// Returns the surface area computed during the last evaluation of the modifier. FloatType surfaceArea() const { return _surfaceArea; } - /// Resets the modifier's result cache. - virtual void invalidateCachedResults() override; - protected: /// Handles reference events sent by reference targets of this object. @@ -138,16 +114,16 @@ }; /// Controls the radius of the probe sphere. - PropertyField _probeSphereRadius; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, probeSphereRadius, setProbeSphereRadius); /// Controls the amount of smoothing. - PropertyField _smoothingLevel; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, smoothingLevel, setSmoothingLevel); /// Controls whether only selected particles should be taken into account. - PropertyField _onlySelectedParticles; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, onlySelectedParticles, setOnlySelectedParticles); /// The display object for rendering the surface mesh. - ReferenceField _surfaceMeshDisplay; + DECLARE_MODIFIABLE_REFERENCE_FIELD(SurfaceMeshDisplay, surfaceMeshDisplay, setSurfaceMeshDisplay); /// This stores the cached surface mesh produced by the modifier. QExplicitlySharedDataPointer> _surfaceMesh; @@ -169,15 +145,10 @@ Q_CLASSINFO("DisplayName", "Construct surface mesh"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_PROPERTY_FIELD(_probeSphereRadius); - DECLARE_PROPERTY_FIELD(_smoothingLevel); - DECLARE_PROPERTY_FIELD(_onlySelectedParticles); - DECLARE_REFERENCE_FIELD(_surfaceMeshDisplay); }; } // End of namespace } // End of namespace } // End of namespace -#endif // __OVITO_CONSTRUCT_SURFACE_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/BurgersCircuit.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/BurgersCircuit.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/BurgersCircuit.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/BurgersCircuit.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_BURGERS_CIRCUIT_H -#define __OVITO_CA_BURGERS_CIRCUIT_H +#pragma once + #include #include @@ -147,4 +147,4 @@ } // End of namespace -#endif // __OVITO_CA_BURGERS_CIRCUIT_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisEngine.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisEngine.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisEngine.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisEngine.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -106,7 +106,7 @@ nextProgressSubStep(); FloatType ghostLayerSize = 3.0f * _structureAnalysis.maximumNeighborDistance(); if(!_tessellation.generateTessellation(_structureAnalysis.cell(), _structureAnalysis.positions()->constDataPoint3(), - _structureAnalysis.atomCount(), ghostLayerSize, selection() ? selection()->constDataInt() : nullptr, this)) + _structureAnalysis.atomCount(), ghostLayerSize, selection() ? selection()->constDataInt() : nullptr, *this)) return; // Build list of edges in the tessellation. diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisEngine.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisEngine.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisEngine.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisEngine.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DISLOCATION_ANALYSIS_ENGINE_H -#define __OVITO_DISLOCATION_ANALYSIS_ENGINE_H +#pragma once + #include #include @@ -107,4 +107,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_DISLOCATION_ANALYSIS_ENGINE_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisModifier.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -21,39 +21,41 @@ #include #include -#include -#include #include #include #include #include #include +#include +#include +#include +#include #include "DislocationAnalysisModifier.h" #include "DislocationAnalysisEngine.h" namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, DislocationAnalysisModifier, StructureIdentificationModifier); -DEFINE_FLAGS_PROPERTY_FIELD(DislocationAnalysisModifier, _inputCrystalStructure, "CrystalStructure", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(DislocationAnalysisModifier, _maxTrialCircuitSize, "MaxTrialCircuitSize"); -DEFINE_PROPERTY_FIELD(DislocationAnalysisModifier, _circuitStretchability, "CircuitStretchability"); -DEFINE_PROPERTY_FIELD(DislocationAnalysisModifier, _outputInterfaceMesh, "OutputInterfaceMesh"); -DEFINE_PROPERTY_FIELD(DislocationAnalysisModifier, _reconstructEdgeVectors, "ReconstructEdgeVectors"); -DEFINE_PROPERTY_FIELD(DislocationAnalysisModifier, _onlyPerfectDislocations, "OnlyPerfectDislocations"); -DEFINE_FLAGS_REFERENCE_FIELD(DislocationAnalysisModifier, _patternCatalog, "PatternCatalog", PatternCatalog, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_REFERENCE_FIELD(DislocationAnalysisModifier, _dislocationDisplay, "DislocationDisplay", DislocationDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_REFERENCE_FIELD(DislocationAnalysisModifier, _defectMeshDisplay, "DefectMeshDisplay", SurfaceMeshDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_REFERENCE_FIELD(DislocationAnalysisModifier, _interfaceMeshDisplay, "InterfaceMeshDisplay", SurfaceMeshDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_REFERENCE_FIELD(DislocationAnalysisModifier, _smoothDislocationsModifier, "SmoothDislocationsModifier", SmoothDislocationsModifier, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_REFERENCE_FIELD(DislocationAnalysisModifier, _smoothSurfaceModifier, "SmoothSurfaceModifier", SmoothSurfaceModifier, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(DislocationAnalysisModifier, _inputCrystalStructure, "Input crystal structure"); -SET_PROPERTY_FIELD_LABEL(DislocationAnalysisModifier, _maxTrialCircuitSize, "Trial circuit length"); -SET_PROPERTY_FIELD_LABEL(DislocationAnalysisModifier, _circuitStretchability, "Circuit stretchability"); -SET_PROPERTY_FIELD_LABEL(DislocationAnalysisModifier, _outputInterfaceMesh, "Output interface mesh"); -SET_PROPERTY_FIELD_LABEL(DislocationAnalysisModifier, _reconstructEdgeVectors, "Reconstruct edge vectors"); -SET_PROPERTY_FIELD_LABEL(DislocationAnalysisModifier, _onlyPerfectDislocations, "Generate perfect dislocations"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(DislocationAnalysisModifier, _maxTrialCircuitSize, IntegerParameterUnit, 3); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(DislocationAnalysisModifier, _circuitStretchability, IntegerParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(DislocationAnalysisModifier, StructureIdentificationModifier); +DEFINE_FLAGS_PROPERTY_FIELD(DislocationAnalysisModifier, inputCrystalStructure, "CrystalStructure", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(DislocationAnalysisModifier, maxTrialCircuitSize, "MaxTrialCircuitSize"); +DEFINE_PROPERTY_FIELD(DislocationAnalysisModifier, circuitStretchability, "CircuitStretchability"); +DEFINE_PROPERTY_FIELD(DislocationAnalysisModifier, outputInterfaceMesh, "OutputInterfaceMesh"); +DEFINE_PROPERTY_FIELD(DislocationAnalysisModifier, reconstructEdgeVectors, "ReconstructEdgeVectors"); +DEFINE_PROPERTY_FIELD(DislocationAnalysisModifier, onlyPerfectDislocations, "OnlyPerfectDislocations"); +DEFINE_FLAGS_REFERENCE_FIELD(DislocationAnalysisModifier, patternCatalog, "PatternCatalog", PatternCatalog, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(DislocationAnalysisModifier, dislocationDisplay, "DislocationDisplay", DislocationDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(DislocationAnalysisModifier, defectMeshDisplay, "DefectMeshDisplay", SurfaceMeshDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(DislocationAnalysisModifier, interfaceMeshDisplay, "InterfaceMeshDisplay", SurfaceMeshDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(DislocationAnalysisModifier, smoothDislocationsModifier, "SmoothDislocationsModifier", SmoothDislocationsModifier, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(DislocationAnalysisModifier, smoothSurfaceModifier, "SmoothSurfaceModifier", SmoothSurfaceModifier, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(DislocationAnalysisModifier, inputCrystalStructure, "Input crystal structure"); +SET_PROPERTY_FIELD_LABEL(DislocationAnalysisModifier, maxTrialCircuitSize, "Trial circuit length"); +SET_PROPERTY_FIELD_LABEL(DislocationAnalysisModifier, circuitStretchability, "Circuit stretchability"); +SET_PROPERTY_FIELD_LABEL(DislocationAnalysisModifier, outputInterfaceMesh, "Output interface mesh"); +SET_PROPERTY_FIELD_LABEL(DislocationAnalysisModifier, reconstructEdgeVectors, "Reconstruct edge vectors"); +SET_PROPERTY_FIELD_LABEL(DislocationAnalysisModifier, onlyPerfectDislocations, "Generate perfect dislocations"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(DislocationAnalysisModifier, maxTrialCircuitSize, IntegerParameterUnit, 3); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(DislocationAnalysisModifier, circuitStretchability, IntegerParameterUnit, 0); /****************************************************************************** * Constructs the modifier object. @@ -62,42 +64,42 @@ _inputCrystalStructure(StructureAnalysis::LATTICE_FCC), _maxTrialCircuitSize(14), _circuitStretchability(9), _outputInterfaceMesh(false), _reconstructEdgeVectors(false), _onlyPerfectDislocations(false) { - INIT_PROPERTY_FIELD(DislocationAnalysisModifier::_inputCrystalStructure); - INIT_PROPERTY_FIELD(DislocationAnalysisModifier::_maxTrialCircuitSize); - INIT_PROPERTY_FIELD(DislocationAnalysisModifier::_circuitStretchability); - INIT_PROPERTY_FIELD(DislocationAnalysisModifier::_outputInterfaceMesh); - INIT_PROPERTY_FIELD(DislocationAnalysisModifier::_reconstructEdgeVectors); - INIT_PROPERTY_FIELD(DislocationAnalysisModifier::_onlyPerfectDislocations); - INIT_PROPERTY_FIELD(DislocationAnalysisModifier::_patternCatalog); - INIT_PROPERTY_FIELD(DislocationAnalysisModifier::_dislocationDisplay); - INIT_PROPERTY_FIELD(DislocationAnalysisModifier::_defectMeshDisplay); - INIT_PROPERTY_FIELD(DislocationAnalysisModifier::_interfaceMeshDisplay); - INIT_PROPERTY_FIELD(DislocationAnalysisModifier::_smoothDislocationsModifier); - INIT_PROPERTY_FIELD(DislocationAnalysisModifier::_smoothSurfaceModifier); + INIT_PROPERTY_FIELD(inputCrystalStructure); + INIT_PROPERTY_FIELD(maxTrialCircuitSize); + INIT_PROPERTY_FIELD(circuitStretchability); + INIT_PROPERTY_FIELD(outputInterfaceMesh); + INIT_PROPERTY_FIELD(reconstructEdgeVectors); + INIT_PROPERTY_FIELD(onlyPerfectDislocations); + INIT_PROPERTY_FIELD(patternCatalog); + INIT_PROPERTY_FIELD(dislocationDisplay); + INIT_PROPERTY_FIELD(defectMeshDisplay); + INIT_PROPERTY_FIELD(interfaceMeshDisplay); + INIT_PROPERTY_FIELD(smoothDislocationsModifier); + INIT_PROPERTY_FIELD(smoothSurfaceModifier); // Create the display objects. - _dislocationDisplay = new DislocationDisplay(dataset); + setDislocationDisplay(new DislocationDisplay(dataset)); - _defectMeshDisplay = new SurfaceMeshDisplay(dataset); - _defectMeshDisplay->setShowCap(true); - _defectMeshDisplay->setSmoothShading(true); - _defectMeshDisplay->setCapTransparency(0.5); - _defectMeshDisplay->setObjectTitle(tr("Defect mesh")); - - _interfaceMeshDisplay = new SurfaceMeshDisplay(dataset); - _interfaceMeshDisplay->setShowCap(false); - _interfaceMeshDisplay->setSmoothShading(false); - _interfaceMeshDisplay->setCapTransparency(0.5); - _interfaceMeshDisplay->setObjectTitle(tr("Interface mesh")); + setDefectMeshDisplay(new SurfaceMeshDisplay(dataset)); + defectMeshDisplay()->setShowCap(true); + defectMeshDisplay()->setSmoothShading(true); + defectMeshDisplay()->setCapTransparency(0.5); + defectMeshDisplay()->setObjectTitle(tr("Defect mesh")); + + setInterfaceMeshDisplay(new SurfaceMeshDisplay(dataset)); + interfaceMeshDisplay()->setShowCap(false); + interfaceMeshDisplay()->setSmoothShading(false); + interfaceMeshDisplay()->setCapTransparency(0.5); + interfaceMeshDisplay()->setObjectTitle(tr("Interface mesh")); // Create the internal modifiers. - _smoothDislocationsModifier = new SmoothDislocationsModifier(dataset); - _smoothSurfaceModifier = new SmoothSurfaceModifier(dataset); + setSmoothDislocationsModifier(new SmoothDislocationsModifier(dataset)); + setSmoothSurfaceModifier(new SmoothSurfaceModifier(dataset)); // Create pattern catalog. - _patternCatalog = new PatternCatalog(dataset); - while(_patternCatalog->patterns().empty() == false) - _patternCatalog->removePattern(0); + setPatternCatalog(new PatternCatalog(dataset)); + while(patternCatalog()->patterns().empty() == false) + patternCatalog()->removePattern(0); // Create the structure types. ParticleTypeProperty::PredefinedStructureType predefTypes[] = { @@ -110,12 +112,12 @@ }; OVITO_STATIC_ASSERT(sizeof(predefTypes)/sizeof(predefTypes[0]) == StructureAnalysis::NUM_LATTICE_TYPES); for(int id = 0; id < StructureAnalysis::NUM_LATTICE_TYPES; id++) { - OORef stype = _patternCatalog->structureById(id); + OORef stype = patternCatalog()->structureById(id); if(!stype) { stype = new StructurePattern(dataset); stype->setId(id); stype->setStructureType(StructurePattern::Lattice); - _patternCatalog->addPattern(stype); + patternCatalog()->addPattern(stype); } stype->setName(ParticleTypeProperty::getPredefinedStructureTypeName(predefTypes[id])); stype->setColor(ParticleTypeProperty::getDefaultParticleColor(ParticleProperty::StructureTypeProperty, stype->name(), id)); @@ -124,7 +126,7 @@ // Create Burgers vector families. - StructurePattern* fccPattern = _patternCatalog->structureById(StructureAnalysis::LATTICE_FCC); + StructurePattern* fccPattern = patternCatalog()->structureById(StructureAnalysis::LATTICE_FCC); fccPattern->setSymmetryType(StructurePattern::CubicSymmetry); fccPattern->setShortName(QStringLiteral("fcc")); fccPattern->addBurgersVectorFamily(new BurgersVectorFamily(dataset, tr("1/2<110> (Perfect)"), Vector3(1.0f/2.0f, 1.0f/2.0f, 0.0f), Color(0.2f,0.2f,1))); @@ -133,14 +135,14 @@ fccPattern->addBurgersVectorFamily(new BurgersVectorFamily(dataset, tr("1/3<001> (Hirth)"), Vector3(1.0f/3.0f, 0.0f, 0.0f), Color(1,1,0))); fccPattern->addBurgersVectorFamily(new BurgersVectorFamily(dataset, tr("1/3<111> (Frank)"), Vector3(1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f), Color(0,1,1))); - StructurePattern* bccPattern = _patternCatalog->structureById(StructureAnalysis::LATTICE_BCC); + StructurePattern* bccPattern = patternCatalog()->structureById(StructureAnalysis::LATTICE_BCC); bccPattern->setSymmetryType(StructurePattern::CubicSymmetry); bccPattern->setShortName(QStringLiteral("bcc")); bccPattern->addBurgersVectorFamily(new BurgersVectorFamily(dataset, tr("1/2<111>"), Vector3(1.0f/2.0f, 1.0f/2.0f, 1.0f/2.0f), Color(0,1,0))); bccPattern->addBurgersVectorFamily(new BurgersVectorFamily(dataset, tr("<100>"), Vector3(1.0f, 0.0f, 0.0f), Color(1, 0.3f, 0.8f))); bccPattern->addBurgersVectorFamily(new BurgersVectorFamily(dataset, tr("<110>"), Vector3(1.0f, 1.0f, 0.0f), Color(0.2f, 0.5f, 1.0f))); - StructurePattern* hcpPattern = _patternCatalog->structureById(StructureAnalysis::LATTICE_HCP); + StructurePattern* hcpPattern = patternCatalog()->structureById(StructureAnalysis::LATTICE_HCP); hcpPattern->setShortName(QStringLiteral("hcp")); hcpPattern->setSymmetryType(StructurePattern::HexagonalSymmetry); hcpPattern->addBurgersVectorFamily(new BurgersVectorFamily(dataset, tr("1/3<1-210>"), Vector3(sqrt(0.5f), 0.0f, 0.0f), Color(0,1,0))); @@ -149,7 +151,7 @@ hcpPattern->addBurgersVectorFamily(new BurgersVectorFamily(dataset, tr("1/3<1-100>"), Vector3(0.0f, sqrt(3.0f/2.0f)/3.0f, 0.0f), Color(1,0.5f,0))); hcpPattern->addBurgersVectorFamily(new BurgersVectorFamily(dataset, tr("1/3<1-213>"), Vector3(sqrt(0.5f), 0.0f, sqrt(4.0f/3.0f)), Color(1,1,0))); - StructurePattern* cubicDiaPattern = _patternCatalog->structureById(StructureAnalysis::LATTICE_CUBIC_DIAMOND); + StructurePattern* cubicDiaPattern = patternCatalog()->structureById(StructureAnalysis::LATTICE_CUBIC_DIAMOND); cubicDiaPattern->setShortName(QStringLiteral("diamond")); cubicDiaPattern->setSymmetryType(StructurePattern::CubicSymmetry); cubicDiaPattern->addBurgersVectorFamily(new BurgersVectorFamily(dataset, tr("1/2<110>"), Vector3(1.0f/2.0f, 1.0f/2.0f, 0.0f), Color(0.2f,0.2f,1))); @@ -157,7 +159,7 @@ cubicDiaPattern->addBurgersVectorFamily(new BurgersVectorFamily(dataset, tr("1/6<110>"), Vector3(1.0f/6.0f, 1.0f/6.0f, 0.0f), Color(1,0,1))); cubicDiaPattern->addBurgersVectorFamily(new BurgersVectorFamily(dataset, tr("1/3<111>"), Vector3(1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f), Color(0,1,1))); - StructurePattern* hexDiaPattern = _patternCatalog->structureById(StructureAnalysis::LATTICE_HEX_DIAMOND); + StructurePattern* hexDiaPattern = patternCatalog()->structureById(StructureAnalysis::LATTICE_HEX_DIAMOND); hexDiaPattern->setShortName(QStringLiteral("hex_diamond")); hexDiaPattern->setSymmetryType(StructurePattern::HexagonalSymmetry); hexDiaPattern->addBurgersVectorFamily(new BurgersVectorFamily(dataset, tr("1/3<1-210>"), Vector3(sqrt(0.5f), 0.0f, 0.0f), Color(0,1,0))); @@ -174,12 +176,12 @@ StructureIdentificationModifier::propertyChanged(field); // Recompute results when the parameters have changed. - if(field == PROPERTY_FIELD(DislocationAnalysisModifier::_inputCrystalStructure) - || field == PROPERTY_FIELD(DislocationAnalysisModifier::_maxTrialCircuitSize) - || field == PROPERTY_FIELD(DislocationAnalysisModifier::_circuitStretchability) - || field == PROPERTY_FIELD(DislocationAnalysisModifier::_outputInterfaceMesh) - || field == PROPERTY_FIELD(DislocationAnalysisModifier::_reconstructEdgeVectors) - || field == PROPERTY_FIELD(DislocationAnalysisModifier::_onlyPerfectDislocations)) + if(field == PROPERTY_FIELD(inputCrystalStructure) + || field == PROPERTY_FIELD(maxTrialCircuitSize) + || field == PROPERTY_FIELD(circuitStretchability) + || field == PROPERTY_FIELD(outputInterfaceMesh) + || field == PROPERTY_FIELD(reconstructEdgeVectors) + || field == PROPERTY_FIELD(onlyPerfectDislocations)) invalidateCachedResults(); } @@ -221,6 +223,8 @@ // Get modifier inputs. ParticlePropertyObject* posProperty = expectStandardProperty(ParticleProperty::PositionProperty); SimulationCellObject* simCell = expectSimulationCell(); + if(simCell->is2D()) + throwException(tr("The DXA modifier does not support 2d simulation cells.")); // Get particle selection. ParticleProperty* selectionProperty = nullptr; @@ -287,16 +291,18 @@ // Output defect mesh. OORef defectMeshObj(new SurfaceMesh(dataset(), _defectMesh.data())); - defectMeshObj->setCompletelySolid(_isBadEverywhere); - if(smoothSurfaceModifier() && smoothSurfaceModifier()->isEnabled() && smoothSurfaceModifier()->smoothingLevel() > 0) - defectMeshObj->smoothMesh(_simCell, smoothSurfaceModifier()->smoothingLevel()); + defectMeshObj->setIsCompletelySolid(_isBadEverywhere); + if(smoothSurfaceModifier() && smoothSurfaceModifier()->isEnabled() && smoothSurfaceModifier()->smoothingLevel() > 0) { + SynchronousTask smoothingTask(dataset()->container()->taskManager()); + defectMeshObj->smoothMesh(_simCell, smoothSurfaceModifier()->smoothingLevel(), smoothingTask.promise()); + } defectMeshObj->setDisplayObject(_defectMeshDisplay); output().addObject(defectMeshObj); // Output interface mesh. if(_interfaceMesh) { OORef interfaceMeshObj(new SurfaceMesh(dataset(), _interfaceMesh.data())); - interfaceMeshObj->setCompletelySolid(_isBadEverywhere); + interfaceMeshObj->setIsCompletelySolid(_isBadEverywhere); interfaceMeshObj->setDisplayObject(_interfaceMeshDisplay); output().addObject(interfaceMeshObj); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisModifier.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisModifier.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/DislocationAnalysisModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DISLOCATION_ANALYSIS_MODIFIER_H -#define __OVITO_DISLOCATION_ANALYSIS_MODIFIER_H +#pragma once + #include #include @@ -46,54 +46,6 @@ /// Constructor. Q_INVOKABLE DislocationAnalysisModifier(DataSet* dataset); - /// \brief Returns the display object that is responsible for rendering the defect mesh. - SurfaceMeshDisplay* defectMeshDisplay() const { return _defectMeshDisplay; } - - /// \brief Returns the display object that is responsible for rendering the interface mesh. - SurfaceMeshDisplay* interfaceMeshDisplay() const { return _interfaceMeshDisplay; } - - /// \brief Returns the display object that is responsible for rendering the dislocations. - DislocationDisplay* dislocationDisplay() const { return _dislocationDisplay; } - - /// \brief Returns the internal modifier that smoothes the extracted dislocation lines. - SmoothDislocationsModifier* smoothDislocationsModifier() const { return _smoothDislocationsModifier; } - - /// \brief Returns the internal modifier that smoothes the defect surface mesh. - SmoothSurfaceModifier* smoothSurfaceModifier() const { return _smoothSurfaceModifier; } - - /// Return the catalog of structure patterns. - PatternCatalog* patternCatalog() const { return _patternCatalog; } - - /// Returns the maximum length of trial circuits. - int maxTrialCircuitSize() const { return _maxTrialCircuitSize; } - - /// Sets the maximum length of trial circuits. - void setMaxTrialCircuitSize(int maxLength) { _maxTrialCircuitSize = maxLength; } - - /// Returns the maximum elongation of Burgers circuits while they are being advanced. - int circuitStretchability() const { return _circuitStretchability; } - - /// Sets maximum elongation of Burgers circuits while they are being advanced. - void setCircuitStretchability(int stretchability) { _circuitStretchability = stretchability; } - - /// Returns the type of crystal to be analyzed. - StructureAnalysis::LatticeStructureType inputCrystalStructure() const { return static_cast(_inputCrystalStructure.value()); } - - /// Sets the type of crystal to be analyzed. - void setInputCrystalStructure(StructureAnalysis::LatticeStructureType structureType) { _inputCrystalStructure = structureType; } - - /// Returns whether the interface mesh is output. - bool outputInterfaceMesh() const { return _outputInterfaceMesh; } - - /// Controls whether the interface mesh is output. - void setOutputInterfaceMesh(bool enable) { _outputInterfaceMesh = enable; } - - /// Returns whether the reconstruction of missing tessellation edge lattice vectors is enabled. - bool reconstructEdgeVectors() const { return _reconstructEdgeVectors; } - - /// Sets whether the reconstruction of missing tessellation edge lattice vectors is enabled. - void setReconstructEdgeVectors(bool enable) { _reconstructEdgeVectors = enable; } - /// Returns the number of segments found per dislocation type. const std::map& segmentCounts() const { return _segmentCounts; } @@ -133,12 +85,6 @@ /// Sets the surface smoothing strength for the defect mesh. void setDefectMeshSmoothingLevel(int level) { smoothSurfaceModifier()->setSmoothingLevel(level); } - /// Returns whether identification is restricted to perfect lattice dislocations. - bool onlyPerfectDislocations() const { return _onlyPerfectDislocations; } - - /// Controls whether identification is restricted to perfect lattice dislocations. - void setOnlyPerfectDislocations(bool onlyPerfect) { _onlyPerfectDislocations = onlyPerfect; } - protected: /// Handles reference events sent by reference targets of this object. @@ -159,40 +105,40 @@ private: /// The type of crystal to be analyzed. - PropertyField _inputCrystalStructure; + DECLARE_MODIFIABLE_PROPERTY_FIELD(StructureAnalysis::LatticeStructureType, inputCrystalStructure, setInputCrystalStructure); /// The maximum length of trial circuits. - PropertyField _maxTrialCircuitSize; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, maxTrialCircuitSize, setMaxTrialCircuitSize); /// The maximum elongation of Burgers circuits while they are being advanced. - PropertyField _circuitStretchability; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, circuitStretchability, setCircuitStretchability); /// Controls the output of the interface mesh. - PropertyField _outputInterfaceMesh; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, outputInterfaceMesh, setOutputInterfaceMesh); /// Enables the reconstruction of missing tessellation edge lattice vectors. - PropertyField _reconstructEdgeVectors; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, reconstructEdgeVectors, setReconstructEdgeVectors); /// Restricts the identification to perfect lattice dislocations. - PropertyField _onlyPerfectDislocations; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, onlyPerfectDislocations, setOnlyPerfectDislocations); /// The catalog of structure patterns. - ReferenceField _patternCatalog; + DECLARE_MODIFIABLE_REFERENCE_FIELD(PatternCatalog, patternCatalog, setPatternCatalog); /// The display object for rendering the defect mesh. - ReferenceField _defectMeshDisplay; + DECLARE_MODIFIABLE_REFERENCE_FIELD(SurfaceMeshDisplay, defectMeshDisplay, setDefectMeshDisplay); /// The display object for rendering the interface mesh. - ReferenceField _interfaceMeshDisplay; + DECLARE_MODIFIABLE_REFERENCE_FIELD(SurfaceMeshDisplay, interfaceMeshDisplay, setInterfaceMeshDisplay); /// The display object for rendering the dislocations. - ReferenceField _dislocationDisplay; + DECLARE_MODIFIABLE_REFERENCE_FIELD(DislocationDisplay, dislocationDisplay, setDislocationDisplay); /// The internal modifier that smoothes the extracted dislocation lines. - ReferenceField _smoothDislocationsModifier; + DECLARE_MODIFIABLE_REFERENCE_FIELD(SmoothDislocationsModifier, smoothDislocationsModifier, setSmoothDislocationsModifier); /// The internal modifier that smoothes the defect surface mesh. - ReferenceField _smoothSurfaceModifier; + DECLARE_MODIFIABLE_REFERENCE_FIELD(SmoothSurfaceModifier, smoothSurfaceModifier, setSmoothSurfaceModifier); /// This stores the cached defect mesh produced by the modifier. QExplicitlySharedDataPointer> _defectMesh; @@ -238,23 +184,10 @@ Q_CLASSINFO("DisplayName", "Dislocation analysis (DXA)"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_PROPERTY_FIELD(_inputCrystalStructure); - DECLARE_PROPERTY_FIELD(_maxTrialCircuitSize); - DECLARE_PROPERTY_FIELD(_circuitStretchability); - DECLARE_PROPERTY_FIELD(_outputInterfaceMesh); - DECLARE_PROPERTY_FIELD(_reconstructEdgeVectors); - DECLARE_PROPERTY_FIELD(_onlyPerfectDislocations); - DECLARE_REFERENCE_FIELD(_patternCatalog); - DECLARE_REFERENCE_FIELD(_dislocationDisplay); - DECLARE_REFERENCE_FIELD(_defectMeshDisplay); - DECLARE_REFERENCE_FIELD(_interfaceMeshDisplay); - DECLARE_REFERENCE_FIELD(_smoothDislocationsModifier); - DECLARE_REFERENCE_FIELD(_smoothSurfaceModifier); }; } // End of namespace } // End of namespace } // End of namespace -#endif // __OVITO_DISLOCATION_ANALYSIS_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/DislocationTracer.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/DislocationTracer.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/DislocationTracer.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/DislocationTracer.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -53,7 +53,7 @@ * trial Burgers circuits. Identified dislocation segments are converted to * a continuous line representation. ******************************************************************************/ -bool DislocationTracer::traceDislocationSegments(FutureInterfaceBase& progress) +bool DislocationTracer::traceDislocationSegments(PromiseBase& promise) { if(_maxBurgersCircuitSize < 3 || _maxBurgersCircuitSize > _maxExtendedBurgersCircuitSize) throw Exception("Invalid maximum circuit size parameter(s)."); @@ -63,7 +63,7 @@ std::vector subStepWeights(_maxExtendedBurgersCircuitSize - 2); for(int i = 0; i < subStepWeights.size(); i++) subStepWeights[i] = (i+3)*(i+3); - progress.beginProgressSubSteps(subStepWeights); + promise.beginProgressSubSteps(subStepWeights); mesh().clearFaceFlag(0); @@ -84,7 +84,7 @@ // Find dislocation segments by generating trial Burgers circuits on the interface mesh // and then moving them in both directions along the dislocation segment. if(circuitLength <= _maxBurgersCircuitSize && (circuitLength % 2) != 0) { - if(!findPrimarySegments(circuitLength, progress)) + if(!findPrimarySegments(circuitLength, promise)) return false; } @@ -104,14 +104,14 @@ } if(circuitLength < _maxExtendedBurgersCircuitSize) - progress.nextProgressSubStep(); + promise.nextProgressSubStep(); } //qDebug() << "Number of dislocation segments:" << network().segments().size(); //qDebug() << "Number of dislocation junctions:" << numJunctions; - progress.endProgressSubSteps(); - return true; + promise.endProgressSubSteps(); + return !promise.isCanceled(); } /****************************************************************************** @@ -209,14 +209,15 @@ * Then moves the Burgers circuit in both directions along the dislocation * segment until the maximum circuit size has been reached. ******************************************************************************/ -bool DislocationTracer::findPrimarySegments(int maxBurgersCircuitSize, FutureInterfaceBase& progress) +bool DislocationTracer::findPrimarySegments(int maxBurgersCircuitSize, PromiseBase& promise) { int searchDepth = (maxBurgersCircuitSize - 1) / 2; OVITO_ASSERT(searchDepth >= 1); MemoryPool structPool; - progress.setProgressRange(mesh().vertexCount()); + promise.setProgressValue(0); + promise.setProgressMaximum(mesh().vertexCount()); int progressCounter = 0; // Find an appropriate start node for the recursive search. @@ -225,7 +226,7 @@ OVITO_ASSERT(startNode->burgersSearchStruct == nullptr); // Update progress indicator. - if(!progress.setProgressValueIntermittent(progressCounter++)) + if(!promise.setProgressValueIntermittent(progressCounter++)) return false; // The first node is the seed of our recursive walk. @@ -319,7 +320,7 @@ structPool.clear(true); } - return true; + return !promise.isCanceled(); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/DislocationTracer.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/DislocationTracer.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/DislocationTracer.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/DislocationTracer.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_DISLOCATION_TRACER_H -#define __OVITO_CA_DISLOCATION_TRACER_H +#pragma once + #include #include @@ -72,7 +72,7 @@ /// Performs a dislocation search on the interface mesh by generating /// trial Burgers circuits. Identified dislocation segments are converted to /// a continuous line representation - bool traceDislocationSegments(FutureInterfaceBase& progress); + bool traceDislocationSegments(PromiseBase& promise); /// After dislocation segments have been extracted, this method trims /// dangling lines and finds the optimal cluster to express each segment's @@ -86,7 +86,7 @@ BurgersCircuit* allocateCircuit(); void discardCircuit(BurgersCircuit* circuit); - bool findPrimarySegments(int maxBurgersCircuitSize, FutureInterfaceBase& progress); + bool findPrimarySegments(int maxBurgersCircuitSize, PromiseBase& promise); bool createBurgersCircuit(InterfaceMesh::Edge* edge, int maxBurgersCircuitSize); void createAndTraceSegment(const ClusterVector& burgersVector, BurgersCircuit* forwardCircuit, int maxCircuitLength); bool intersectsOtherCircuits(BurgersCircuit* circuit); @@ -152,4 +152,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CA_DISLOCATION_TRACER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/ElasticMapping.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/ElasticMapping.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/ElasticMapping.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/ElasticMapping.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -33,9 +33,10 @@ /****************************************************************************** * Builds the list of edges in the tetrahedral tessellation. ******************************************************************************/ -bool ElasticMapping::generateTessellationEdges(FutureInterfaceBase& progress) +bool ElasticMapping::generateTessellationEdges(PromiseBase& promise) { - progress.setProgressRange(tessellation().numberOfPrimaryTetrahedra()); + promise.setProgressValue(0); + promise.setProgressMaximum(tessellation().numberOfPrimaryTetrahedra()); // Generate list of tessellation edges. for(DelaunayTessellation::CellIterator cell = tessellation().begin_cells(); cell != tessellation().end_cells(); ++cell) { @@ -44,7 +45,7 @@ if(tessellation().isGhostCell(cell)) continue; // Update progress indicator. - if(!progress.setProgressValueIntermittent(tessellation().getCellIndex(cell))) + if(!promise.setProgressValueIntermittent(tessellation().getCellIndex(cell))) return false; // Create edge data structure for each of the six edges of the cell. @@ -71,16 +72,17 @@ } } - return true; + return !promise.isCanceled(); } /****************************************************************************** * Assigns each tessellation vertex to a cluster. ******************************************************************************/ -bool ElasticMapping::assignVerticesToClusters(FutureInterfaceBase& progress) +bool ElasticMapping::assignVerticesToClusters(PromiseBase& promise) { // Unknown runtime length. - progress.setProgressRange(0); + promise.setProgressValue(0); + promise.setProgressMaximum(0); // Assign a cluster to each vertex of the tessellation, which will be used to express // reference vectors assigned to the edges leaving the vertex. @@ -95,7 +97,7 @@ // from an already assigned vertex to all its unassigned neighbors. bool notDone; do { - if(progress.isCanceled()) + if(promise.isCanceled()) return false; notDone = false; @@ -122,22 +124,23 @@ } while(notDone); - return true; + return !promise.isCanceled(); } /****************************************************************************** * Determines the ideal vector corresponding to each edge of the tessellation. ******************************************************************************/ -bool ElasticMapping::assignIdealVectorsToEdges(bool reconstructEdgeVectors, int crystalPathSteps, FutureInterfaceBase& progress) +bool ElasticMapping::assignIdealVectorsToEdges(bool reconstructEdgeVectors, int crystalPathSteps, PromiseBase& promise) { CrystalPathFinder pathFinder(_structureAnalysis, crystalPathSteps); // Try to assign a reference vector to the tessellation edges. - progress.setProgressRange(_vertexEdges.size()); + promise.setProgressValue(0); + promise.setProgressMaximum(_vertexEdges.size()); int progressCounter = 0; for(const auto& firstEdge : _vertexEdges) { - if(!progress.setProgressValueIntermittent(progressCounter++)) + if(!promise.setProgressValueIntermittent(progressCounter++)) return false; for(TessellationEdge* edge = firstEdge.first; edge != nullptr; edge = edge->nextLeavingEdge) { @@ -194,14 +197,14 @@ } #endif - return true; + return !promise.isCanceled(); } /****************************************************************************** * Tries to determine the ideal vectors of tessellation edges, which haven't * been assigned one during the first phase. ******************************************************************************/ -bool ElasticMapping::reconstructIdealEdgeVectors(FutureInterfaceBase& progress) +bool ElasticMapping::reconstructIdealEdgeVectors(PromiseBase& promise) { #if 0 auto reconstructRecursive = [this](std::deque& toBeVisited) { diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/ElasticMapping.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/ElasticMapping.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/ElasticMapping.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/ElasticMapping.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,13 +19,13 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_ELASTIC_MAPPING_H -#define __OVITO_CA_ELASTIC_MAPPING_H +#pragma once + #include #include #include -#include +#include #include #include #include @@ -107,17 +107,17 @@ ClusterGraph& clusterGraph() { return _clusterGraph; } /// Builds the list of edges in the tetrahedral tessellation. - bool generateTessellationEdges(FutureInterfaceBase& progress); + bool generateTessellationEdges(PromiseBase& promise); /// Assigns each tessellation vertex to a cluster. - bool assignVerticesToClusters(FutureInterfaceBase& progress); + bool assignVerticesToClusters(PromiseBase& promise); /// Determines the ideal vector corresponding to each edge of the tessellation. - bool assignIdealVectorsToEdges(bool reconstructEdgeVectors, int crystalPathSteps, FutureInterfaceBase& progress); + bool assignIdealVectorsToEdges(bool reconstructEdgeVectors, int crystalPathSteps, PromiseBase& promise); /// Tries to determine the ideal vectors of tessellation edges, which haven't - // been assigned one during the first phase. - bool reconstructIdealEdgeVectors(FutureInterfaceBase& progress); + /// been assigned one during the first phase. + bool reconstructIdealEdgeVectors(PromiseBase& promise); /// Determines whether the elastic mapping from the physical configuration /// of the crystal to the imaginary, stress-free configuration is compatible @@ -193,4 +193,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CA_ELASTIC_MAPPING_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/InterfaceMesh.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/InterfaceMesh.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/InterfaceMesh.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/InterfaceMesh.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -58,9 +58,9 @@ /****************************************************************************** * Creates the mesh facets separating good and bad tetrahedra. ******************************************************************************/ -bool InterfaceMesh::createMesh(FloatType maximumNeighborDistance, ParticleProperty* crystalClusters, FutureInterfaceBase& progress) +bool InterfaceMesh::createMesh(FloatType maximumNeighborDistance, ParticleProperty* crystalClusters, PromiseBase& promise) { - progress.beginProgressSubSteps(2); + promise.beginProgressSubSteps(2); _isCompletelyGood = true; _isCompletelyBad = true; @@ -110,10 +110,10 @@ double alpha = 5.0 * maximumNeighborDistance; ManifoldConstructionHelper manifoldConstructor(tessellation(), *this, alpha, structureAnalysis().positions()); - if(!manifoldConstructor.construct(tetrahedronRegion, &progress, prepareMeshFace)) + if(!manifoldConstructor.construct(tetrahedronRegion, promise, prepareMeshFace)) return false; - progress.nextProgressSubStep(); + promise.nextProgressSubStep(); // Make sure each vertex is only part of a single manifold. duplicateSharedVertices(); @@ -150,14 +150,14 @@ } #endif - progress.endProgressSubSteps(); - return true; + promise.endProgressSubSteps(); + return !promise.isCanceled(); } /****************************************************************************** * Generates the nodes and facets of the defect mesh based on the interface mesh. ******************************************************************************/ -bool InterfaceMesh::generateDefectMesh(const DislocationTracer& tracer, HalfEdgeMesh<>& defectMesh, FutureInterfaceBase& progress) +bool InterfaceMesh::generateDefectMesh(const DislocationTracer& tracer, HalfEdgeMesh<>& defectMesh, PromiseBase& progress) { // Copy vertices. defectMesh.reserveVertices(vertexCount()); diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/InterfaceMesh.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/InterfaceMesh.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/InterfaceMesh.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/InterfaceMesh.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,11 +19,11 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_INTERFACE_MESH_H -#define __OVITO_CA_INTERFACE_MESH_H +#pragma once + #include -#include +#include #include #include "ElasticMapping.h" @@ -96,7 +96,7 @@ const StructureAnalysis& structureAnalysis() const { return elasticMapping().structureAnalysis(); } /// Creates the mesh facets separating good and bad tetrahedra. - bool createMesh(FloatType maximumNeighborDistance, ParticleProperty* crystalClusters, FutureInterfaceBase& progress); + bool createMesh(FloatType maximumNeighborDistance, ParticleProperty* crystalClusters, PromiseBase& progress); /// Returns whether all tessellation cells belong to the good region. bool isCompletelyGood() const { return _isCompletelyGood; } @@ -105,7 +105,7 @@ bool isCompletelyBad() const { return _isCompletelyBad; } /// Generates the nodes and facets of the defect mesh based on the interface mesh. - bool generateDefectMesh(const DislocationTracer& tracer, HalfEdgeMesh<>& defectMesh, FutureInterfaceBase& progress); + bool generateDefectMesh(const DislocationTracer& tracer, HalfEdgeMesh<>& defectMesh, PromiseBase& progress); private: @@ -124,4 +124,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CA_INTERFACE_MESH_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/PlanarDefectIdentification.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/PlanarDefectIdentification.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/PlanarDefectIdentification.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/PlanarDefectIdentification.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_PLANAR_DEFECT_IDENTIFICATION_H -#define __OVITO_CA_PLANAR_DEFECT_IDENTIFICATION_H +#pragma once + #include #include @@ -78,4 +78,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CA_PLANAR_DEFECT_IDENTIFICATION_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/StructureAnalysis.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/StructureAnalysis.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/StructureAnalysis.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/StructureAnalysis.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -444,18 +444,18 @@ /****************************************************************************** * Identifies the atomic structures. ******************************************************************************/ -bool StructureAnalysis::identifyStructures(FutureInterfaceBase& progress) +bool StructureAnalysis::identifyStructures(PromiseBase& promise) { // Prepare the neighbor list. int maxNeighborListSize = std::min((int)_neighborLists->componentCount() + 1, (int)MAX_NEIGHBORS); NearestNeighborFinder neighFinder(maxNeighborListSize); - if(!neighFinder.prepare(positions(), cell(), _particleSelection.data(), &progress)) + if(!neighFinder.prepare(positions(), cell(), _particleSelection.data(), promise)) return false; // Identify local structure around each particle. _maximumNeighborDistance = 0; - return parallelFor(positions()->size(), progress, [this, &neighFinder](size_t index) { + return parallelFor(positions()->size(), promise, [this, &neighFinder](size_t index) { determineLocalStructure(neighFinder, index); }); } @@ -752,9 +752,10 @@ /****************************************************************************** * Combines adjacent atoms to clusters. ******************************************************************************/ -bool StructureAnalysis::buildClusters(FutureInterfaceBase& progress) +bool StructureAnalysis::buildClusters(PromiseBase& promise) { - progress.setProgressRange(positions()->size()); + promise.setProgressValue(0); + promise.setProgressMaximum(positions()->size()); int progressCounter = 0; // Iterate over atoms, looking for those that have not been visited yet. @@ -788,7 +789,7 @@ atomsToVisit.pop_front(); // Update progress indicator. - if(!progress.setProgressValueIntermittent(++progressCounter)) + if(!promise.setProgressValueIntermittent(++progressCounter)) return false; // Look up symmetry permutation of current atom. @@ -915,15 +916,16 @@ //qDebug() << "Number of clusters:" << (clusterGraph().clusters().size() - 1); - return true; + return !promise.isCanceled(); } /****************************************************************************** * Determines the transition matrices between clusters. ******************************************************************************/ -bool StructureAnalysis::connectClusters(FutureInterfaceBase& progress) +bool StructureAnalysis::connectClusters(PromiseBase& promise) { - progress.setProgressRange(positions()->size()); + promise.setProgressValue(0); + promise.setProgressMaximum(positions()->size()); for(size_t atomIndex = 0; atomIndex < positions()->size(); atomIndex++) { int clusterId = _atomClusters->getInt(atomIndex); @@ -932,7 +934,7 @@ OVITO_ASSERT(cluster1); // Update progress indicator. - if(!progress.setProgressValueIntermittent(atomIndex)) + if(!promise.setProgressValueIntermittent(atomIndex)) return false; // Look up symmetry permutation of current atom. @@ -1019,13 +1021,13 @@ //qDebug() << "Number of cluster transitions:" << clusterGraph().clusterTransitions().size(); - return true; + return !promise.isCanceled(); } /****************************************************************************** * Combines clusters to super clusters. ******************************************************************************/ -bool StructureAnalysis::formSuperClusters(FutureInterfaceBase& progress) +bool StructureAnalysis::formSuperClusters(PromiseBase& promise) { size_t oldTransitionCount = clusterGraph().clusterTransitions().size(); @@ -1034,7 +1036,7 @@ cluster->rank = 0; if(cluster->id == 0) continue; - if(progress.isCanceled()) + if(promise.isCanceled()) return false; OVITO_ASSERT(cluster->parentTransition == nullptr); @@ -1097,7 +1099,7 @@ Cluster* parentCluster2 = getParentGrain(t->cluster2); if(parentCluster1 == parentCluster2) continue; - if(progress.isCanceled()) + if(promise.isCanceled()) return false; ClusterTransition* parentTransition = t; @@ -1125,7 +1127,7 @@ getParentGrain(cluster); } - return true; + return !promise.isCanceled(); } } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/StructureAnalysis.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/StructureAnalysis.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/dxa/StructureAnalysis.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/dxa/StructureAnalysis.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,13 +19,13 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_STRUCTURE_ANALYSIS_H -#define __OVITO_CA_STRUCTURE_ANALYSIS_H +#pragma once + #include #include #include -#include +#include namespace Ovito { namespace Plugins { namespace CrystalAnalysis { @@ -103,16 +103,16 @@ bool identifyPlanarDefects = true); /// Identifies the atomic structures. - bool identifyStructures(FutureInterfaceBase& progress); + bool identifyStructures(PromiseBase& promise); /// Combines adjacent atoms to clusters. - bool buildClusters(FutureInterfaceBase& progress); + bool buildClusters(PromiseBase& promise); /// Determines the transition matrices between clusters. - bool connectClusters(FutureInterfaceBase& progress); + bool connectClusters(PromiseBase& promise); /// Combines clusters to super clusters. - bool formSuperClusters(FutureInterfaceBase& progress); + bool formSuperClusters(PromiseBase& promise); /// Returns the number of input atoms. int atomCount() const { return positions()->size(); } @@ -232,4 +232,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CA_STRUCTURE_ANALYSIS_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/elasticstrain/ElasticStrainEngine.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/elasticstrain/ElasticStrainEngine.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/elasticstrain/ElasticStrainEngine.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/elasticstrain/ElasticStrainEngine.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ELASTIC_STRAIN_ENGINE_H -#define __OVITO_ELASTIC_STRAIN_ENGINE_H +#pragma once + #include #include @@ -76,4 +76,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_ELASTIC_STRAIN_ENGINE_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/elasticstrain/ElasticStrainModifier.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/elasticstrain/ElasticStrainModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/elasticstrain/ElasticStrainModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/elasticstrain/ElasticStrainModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,37 +28,37 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, ElasticStrainModifier, StructureIdentificationModifier); -DEFINE_FLAGS_PROPERTY_FIELD(ElasticStrainModifier, _inputCrystalStructure, "CrystalStructure", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ElasticStrainModifier, _calculateDeformationGradients, "CalculateDeformationGradients", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ElasticStrainModifier, _calculateStrainTensors, "CalculateStrainTensors", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ElasticStrainModifier, _latticeConstant, "LatticeConstant", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ElasticStrainModifier, _caRatio, "CtoARatio", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ElasticStrainModifier, _pushStrainTensorsForward, "PushStrainTensorsForward", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_REFERENCE_FIELD(ElasticStrainModifier, _patternCatalog, "PatternCatalog", PatternCatalog, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(ElasticStrainModifier, _inputCrystalStructure, "Input crystal structure"); -SET_PROPERTY_FIELD_LABEL(ElasticStrainModifier, _calculateDeformationGradients, "Output deformation gradient tensors"); -SET_PROPERTY_FIELD_LABEL(ElasticStrainModifier, _calculateStrainTensors, "Output strain tensors"); -SET_PROPERTY_FIELD_LABEL(ElasticStrainModifier, _latticeConstant, "Lattice constant"); -SET_PROPERTY_FIELD_LABEL(ElasticStrainModifier, _caRatio, "c/a ratio"); -SET_PROPERTY_FIELD_LABEL(ElasticStrainModifier, _pushStrainTensorsForward, "Strain tensor in spatial frame (push-forward)"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ElasticStrainModifier, _latticeConstant, WorldParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ElasticStrainModifier, _caRatio, FloatParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ElasticStrainModifier, StructureIdentificationModifier); +DEFINE_FLAGS_PROPERTY_FIELD(ElasticStrainModifier, inputCrystalStructure, "CrystalStructure", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ElasticStrainModifier, calculateDeformationGradients, "CalculateDeformationGradients", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ElasticStrainModifier, calculateStrainTensors, "CalculateStrainTensors", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ElasticStrainModifier, latticeConstant, "LatticeConstant", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ElasticStrainModifier, axialRatio, "CtoARatio", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ElasticStrainModifier, pushStrainTensorsForward, "PushStrainTensorsForward", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(ElasticStrainModifier, patternCatalog, "PatternCatalog", PatternCatalog, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(ElasticStrainModifier, inputCrystalStructure, "Input crystal structure"); +SET_PROPERTY_FIELD_LABEL(ElasticStrainModifier, calculateDeformationGradients, "Output deformation gradient tensors"); +SET_PROPERTY_FIELD_LABEL(ElasticStrainModifier, calculateStrainTensors, "Output strain tensors"); +SET_PROPERTY_FIELD_LABEL(ElasticStrainModifier, latticeConstant, "Lattice constant"); +SET_PROPERTY_FIELD_LABEL(ElasticStrainModifier, axialRatio, "c/a ratio"); +SET_PROPERTY_FIELD_LABEL(ElasticStrainModifier, pushStrainTensorsForward, "Strain tensor in spatial frame (push-forward)"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ElasticStrainModifier, latticeConstant, WorldParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ElasticStrainModifier, axialRatio, FloatParameterUnit, 0); /****************************************************************************** * Constructs the modifier object. ******************************************************************************/ ElasticStrainModifier::ElasticStrainModifier(DataSet* dataset) : StructureIdentificationModifier(dataset), _inputCrystalStructure(StructureAnalysis::LATTICE_FCC), _calculateDeformationGradients(false), _calculateStrainTensors(true), - _latticeConstant(1), _caRatio(sqrt(8.0/3.0)), _pushStrainTensorsForward(true) + _latticeConstant(1), _axialRatio(sqrt(8.0/3.0)), _pushStrainTensorsForward(true) { - INIT_PROPERTY_FIELD(ElasticStrainModifier::_inputCrystalStructure); - INIT_PROPERTY_FIELD(ElasticStrainModifier::_patternCatalog); - INIT_PROPERTY_FIELD(ElasticStrainModifier::_calculateDeformationGradients); - INIT_PROPERTY_FIELD(ElasticStrainModifier::_calculateStrainTensors); - INIT_PROPERTY_FIELD(ElasticStrainModifier::_latticeConstant); - INIT_PROPERTY_FIELD(ElasticStrainModifier::_caRatio); - INIT_PROPERTY_FIELD(ElasticStrainModifier::_pushStrainTensorsForward); + INIT_PROPERTY_FIELD(inputCrystalStructure); + INIT_PROPERTY_FIELD(patternCatalog); + INIT_PROPERTY_FIELD(calculateDeformationGradients); + INIT_PROPERTY_FIELD(calculateStrainTensors); + INIT_PROPERTY_FIELD(latticeConstant); + INIT_PROPERTY_FIELD(axialRatio); + INIT_PROPERTY_FIELD(pushStrainTensorsForward); // Create pattern catalog. _patternCatalog = new PatternCatalog(dataset); @@ -95,12 +95,12 @@ StructureIdentificationModifier::propertyChanged(field); // Recompute results when the parameters have changed. - if(field == PROPERTY_FIELD(ElasticStrainModifier::_inputCrystalStructure) || - field == PROPERTY_FIELD(ElasticStrainModifier::_calculateDeformationGradients) || - field == PROPERTY_FIELD(ElasticStrainModifier::_calculateStrainTensors) || - field == PROPERTY_FIELD(ElasticStrainModifier::_latticeConstant) || - field == PROPERTY_FIELD(ElasticStrainModifier::_caRatio) || - field == PROPERTY_FIELD(ElasticStrainModifier::_pushStrainTensorsForward)) + if(field == PROPERTY_FIELD(inputCrystalStructure) || + field == PROPERTY_FIELD(calculateDeformationGradients) || + field == PROPERTY_FIELD(calculateStrainTensors) || + field == PROPERTY_FIELD(latticeConstant) || + field == PROPERTY_FIELD(axialRatio) || + field == PROPERTY_FIELD(pushStrainTensorsForward)) invalidateCachedResults(); } @@ -120,6 +120,8 @@ // Get modifier inputs. ParticlePropertyObject* posProperty = expectStandardProperty(ParticleProperty::PositionProperty); SimulationCellObject* simCell = expectSimulationCell(); + if(simCell->is2D()) + throwException(tr("The elastic strain calculation modifier does not support 2d simulation cells.")); // Build list of preferred crystal orientations. std::vector preferredCrystalOrientations; diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/elasticstrain/ElasticStrainModifier.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/elasticstrain/ElasticStrainModifier.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/elasticstrain/ElasticStrainModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/elasticstrain/ElasticStrainModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ELASTIC_STRAIN_MODIFIER_H -#define __OVITO_ELASTIC_STRAIN_MODIFIER_H +#pragma once + #include #include @@ -40,45 +40,6 @@ /// Constructor. Q_INVOKABLE ElasticStrainModifier(DataSet* dataset); - /// Return the catalog of structure patterns. - PatternCatalog* patternCatalog() const { return _patternCatalog; } - - /// Returns the type of crystal to be analyzed. - StructureAnalysis::LatticeStructureType inputCrystalStructure() const { return static_cast(_inputCrystalStructure.value()); } - - /// Sets the type of crystal to be analyzed. - void setInputCrystalStructure(StructureAnalysis::LatticeStructureType structureType) { _inputCrystalStructure = structureType; } - - /// Returns whether atomic deformation gradient tensors should be computed and stored. - bool calculateDeformationGradients() const { return _calculateDeformationGradients; } - - /// Sets whether atomic deformation gradient tensors should be computed and stored. - void setCalculateDeformationGradients(bool enableCalculation) { _calculateDeformationGradients = enableCalculation; } - - /// Returns whether atomic strain tensors should be computed and stored. - bool calculateStrainTensors() const { return _calculateStrainTensors; } - - /// Sets whether atomic strain tensors should be computed and stored. - void setCalculateStrainTensors(bool enableCalculation) { _calculateStrainTensors = enableCalculation; } - - /// Returns whether the calculated strain tensors are pushed forward to the spatial reference frame. - bool pushStrainTensorsForward() const { return _pushStrainTensorsForward; } - - /// Returns whether the calculated strain tensors should be pushed forward to the spatial reference frame. - void setPushStrainTensorsForward(bool enable) { _pushStrainTensorsForward = enable; } - - /// Returns the lattice parameter of the ideal crystal. - FloatType latticeConstant() const { return _latticeConstant; } - - /// Sets the lattice parameter of the ideal crystal. - void setLatticeConstant(FloatType a) { _latticeConstant = a; } - - /// Returns the c/a ratio of the ideal crystal. - FloatType axialRatio() const { return _caRatio; } - - /// Sets the c/a ratio of the ideal crystal. - void setAxialRatio(FloatType ratio) { _caRatio = ratio; } - /// Resets the modifier's result cache. virtual void invalidateCachedResults() override; @@ -99,25 +60,25 @@ private: /// The type of crystal to be analyzed. - PropertyField _inputCrystalStructure; + DECLARE_MODIFIABLE_PROPERTY_FIELD(StructureAnalysis::LatticeStructureType, inputCrystalStructure, setInputCrystalStructure); /// Controls whether atomic deformation gradient tensors should be computed and stored. - PropertyField _calculateDeformationGradients; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, calculateDeformationGradients, setCalculateDeformationGradients); /// Controls whether atomic strain tensors should be computed and stored. - PropertyField _calculateStrainTensors; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, calculateStrainTensors, setCalculateStrainTensors); /// Controls whether the calculated strain tensors should be pushed forward to the spatial reference frame. - PropertyField _pushStrainTensorsForward; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, pushStrainTensorsForward, setPushStrainTensorsForward); /// The lattice parameter of ideal crystal. - PropertyField _latticeConstant; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, latticeConstant, setLatticeConstant); /// The c/a ratio of the ideal crystal. - PropertyField _caRatio; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, axialRatio, setAxialRatio); /// The catalog of structure patterns. - ReferenceField _patternCatalog; + DECLARE_MODIFIABLE_REFERENCE_FIELD(PatternCatalog, patternCatalog, setPatternCatalog); /// This stores the cached atom-to-cluster assignments computed by the modifier. QExplicitlySharedDataPointer _atomClusters; @@ -139,18 +100,10 @@ Q_CLASSINFO("DisplayName", "Elastic strain calculation"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_PROPERTY_FIELD(_inputCrystalStructure); - DECLARE_PROPERTY_FIELD(_calculateDeformationGradients); - DECLARE_PROPERTY_FIELD(_calculateStrainTensors); - DECLARE_PROPERTY_FIELD(_latticeConstant); - DECLARE_PROPERTY_FIELD(_caRatio); - DECLARE_PROPERTY_FIELD(_pushStrainTensorsForward); - DECLARE_REFERENCE_FIELD(_patternCatalog); }; } // End of namespace } // End of namespace } // End of namespace -#endif // __OVITO_ELASTIC_STRAIN_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationEngine.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationEngine.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationEngine.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationEngine.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -132,7 +132,7 @@ // Build grain graph. std::vector bulkEdges; - setProgressRange(_grains.size()); + setProgressMaximum(_grains.size()); for(int atomA = 0; atomA < _grains.size(); atomA++) { if(!setProgressValueIntermittent(atomA)) return; Grain& grainA = _grains[atomA]; @@ -202,7 +202,7 @@ // Prepare the neighbor list builder. NearestNeighborFinder neighborFinder(12); - if(!neighborFinder.prepare(positions(), cell(), nullptr, this)) + if(!neighborFinder.prepare(positions(), cell(), nullptr, *this)) return; nextProgressSubStep(); @@ -230,7 +230,7 @@ } else { NearestNeighborFinder::Query<12> neighQuery(neighborFinder); - neighQuery.findNeighbors(neighborFinder.particlePos(atomA)); + neighQuery.findNeighbors(atomA); for(int i = 0; i < neighQuery.results().size(); i++) { int atomB = neighQuery.results()[i].index; @@ -464,7 +464,7 @@ // Generate Delaunay tessellation. DelaunayTessellation tessellation; if(!tessellation.generateTessellation(cell(), positions()->constDataPoint3(), positions()->size(), ghostLayerSize, - selection() ? selection()->constDataInt() : nullptr, this)) + selection() ? selection()->constDataInt() : nullptr, *this)) return false; nextProgressSubStep(); @@ -498,7 +498,7 @@ }; ManifoldConstructionHelper manifoldConstructor(tessellation, *_mesh, alpha, positions()); - if(!manifoldConstructor.construct(tetrahedronRegion, this, prepareMeshFace, linkManifolds)) + if(!manifoldConstructor.construct(tetrahedronRegion, *this, prepareMeshFace, linkManifolds)) return false; _spaceFillingGrain = manifoldConstructor.spaceFillingRegion(); @@ -585,7 +585,8 @@ } // Smooth the generated triangle mesh. - PartitionMesh::smoothMesh(*_mesh, cell(), _meshSmoothingLevel, this); + if(!PartitionMesh::smoothMesh(*_mesh, cell(), _meshSmoothingLevel, *this)) + return false; // Make sure every mesh vertex is only part of one surface manifold. _mesh->duplicateSharedVertices(); diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationEngine.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationEngine.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationEngine.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationEngine.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_GRAIN_SEGMENTATION_ENGINE_H -#define __OVITO_GRAIN_SEGMENTATION_ENGINE_H +#pragma once + #include #include @@ -200,4 +200,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_GRAIN_SEGMENTATION_ENGINE_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationModifier.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,31 +28,31 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, GrainSegmentationModifier, StructureIdentificationModifier); -DEFINE_FLAGS_PROPERTY_FIELD(GrainSegmentationModifier, _inputCrystalStructure, "CrystalStructure", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(GrainSegmentationModifier, _misorientationThreshold, "MisorientationThreshold", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(GrainSegmentationModifier, _fluctuationTolerance, "FluctuationTolerance", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(GrainSegmentationModifier, _minGrainAtomCount, "MinGrainAtomCount", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_REFERENCE_FIELD(GrainSegmentationModifier, _patternCatalog, "PatternCatalog", PatternCatalog, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(GrainSegmentationModifier, _smoothingLevel, "SmoothingLevel", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(GrainSegmentationModifier, _probeSphereRadius, "Radius", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_REFERENCE_FIELD(GrainSegmentationModifier, _meshDisplay, "MeshDisplay", PartitionMeshDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(GrainSegmentationModifier, _onlySelectedParticles, "OnlySelectedParticles"); -DEFINE_PROPERTY_FIELD(GrainSegmentationModifier, _outputPartitionMesh, "OutputPartitionMesh"); -SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, _inputCrystalStructure, "Input crystal structure"); -SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, _misorientationThreshold, "Misorientation threshold"); -SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, _fluctuationTolerance, "Tolerance"); -SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, _minGrainAtomCount, "Minimum grain size"); -SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, _smoothingLevel, "Smoothing level"); -SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, _probeSphereRadius, "Probe sphere radius"); -SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, _meshDisplay, "Surface mesh display"); -SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, _onlySelectedParticles, "Use only selected particles"); -SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, _outputPartitionMesh, "Generate mesh"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(GrainSegmentationModifier, _misorientationThreshold, AngleParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(GrainSegmentationModifier, _fluctuationTolerance, AngleParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(GrainSegmentationModifier, _probeSphereRadius, WorldParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(GrainSegmentationModifier, _minGrainAtomCount, IntegerParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(GrainSegmentationModifier, _smoothingLevel, IntegerParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(GrainSegmentationModifier, StructureIdentificationModifier); +DEFINE_FLAGS_PROPERTY_FIELD(GrainSegmentationModifier, inputCrystalStructure, "CrystalStructure", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(GrainSegmentationModifier, misorientationThreshold, "MisorientationThreshold", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(GrainSegmentationModifier, fluctuationTolerance, "FluctuationTolerance", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(GrainSegmentationModifier, minGrainAtomCount, "MinGrainAtomCount", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(GrainSegmentationModifier, patternCatalog, "PatternCatalog", PatternCatalog, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(GrainSegmentationModifier, smoothingLevel, "SmoothingLevel", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(GrainSegmentationModifier, probeSphereRadius, "Radius", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(GrainSegmentationModifier, meshDisplay, "MeshDisplay", PartitionMeshDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(GrainSegmentationModifier, onlySelectedParticles, "OnlySelectedParticles"); +DEFINE_PROPERTY_FIELD(GrainSegmentationModifier, outputPartitionMesh, "OutputPartitionMesh"); +SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, inputCrystalStructure, "Input crystal structure"); +SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, misorientationThreshold, "Misorientation threshold"); +SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, fluctuationTolerance, "Tolerance"); +SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, minGrainAtomCount, "Minimum grain size"); +SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, smoothingLevel, "Smoothing level"); +SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, probeSphereRadius, "Probe sphere radius"); +SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, meshDisplay, "Surface mesh display"); +SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, onlySelectedParticles, "Use only selected particles"); +SET_PROPERTY_FIELD_LABEL(GrainSegmentationModifier, outputPartitionMesh, "Generate mesh"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(GrainSegmentationModifier, misorientationThreshold, AngleParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(GrainSegmentationModifier, fluctuationTolerance, AngleParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(GrainSegmentationModifier, probeSphereRadius, WorldParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(GrainSegmentationModifier, minGrainAtomCount, IntegerParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(GrainSegmentationModifier, smoothingLevel, IntegerParameterUnit, 0); /****************************************************************************** * Constructs the modifier object. @@ -67,16 +67,16 @@ _onlySelectedParticles(false), _outputPartitionMesh(false) { - INIT_PROPERTY_FIELD(GrainSegmentationModifier::_inputCrystalStructure); - INIT_PROPERTY_FIELD(GrainSegmentationModifier::_misorientationThreshold); - INIT_PROPERTY_FIELD(GrainSegmentationModifier::_fluctuationTolerance); - INIT_PROPERTY_FIELD(GrainSegmentationModifier::_minGrainAtomCount); - INIT_PROPERTY_FIELD(GrainSegmentationModifier::_patternCatalog); - INIT_PROPERTY_FIELD(GrainSegmentationModifier::_smoothingLevel); - INIT_PROPERTY_FIELD(GrainSegmentationModifier::_probeSphereRadius); - INIT_PROPERTY_FIELD(GrainSegmentationModifier::_meshDisplay); - INIT_PROPERTY_FIELD(GrainSegmentationModifier::_onlySelectedParticles); - INIT_PROPERTY_FIELD(GrainSegmentationModifier::_outputPartitionMesh); + INIT_PROPERTY_FIELD(inputCrystalStructure); + INIT_PROPERTY_FIELD(misorientationThreshold); + INIT_PROPERTY_FIELD(fluctuationTolerance); + INIT_PROPERTY_FIELD(minGrainAtomCount); + INIT_PROPERTY_FIELD(patternCatalog); + INIT_PROPERTY_FIELD(smoothingLevel); + INIT_PROPERTY_FIELD(probeSphereRadius); + INIT_PROPERTY_FIELD(meshDisplay); + INIT_PROPERTY_FIELD(onlySelectedParticles); + INIT_PROPERTY_FIELD(outputPartitionMesh); // Create the display object. _meshDisplay = new PartitionMeshDisplay(dataset); @@ -116,14 +116,14 @@ StructureIdentificationModifier::propertyChanged(field); // Recompute results when the parameters have changed. - if(field == PROPERTY_FIELD(GrainSegmentationModifier::_inputCrystalStructure) || - field == PROPERTY_FIELD(GrainSegmentationModifier::_misorientationThreshold) || - field == PROPERTY_FIELD(GrainSegmentationModifier::_fluctuationTolerance) || - field == PROPERTY_FIELD(GrainSegmentationModifier::_minGrainAtomCount) || - field == PROPERTY_FIELD(GrainSegmentationModifier::_smoothingLevel) || - field == PROPERTY_FIELD(GrainSegmentationModifier::_probeSphereRadius) || - field == PROPERTY_FIELD(GrainSegmentationModifier::_onlySelectedParticles) || - field == PROPERTY_FIELD(GrainSegmentationModifier::_outputPartitionMesh)) + if(field == PROPERTY_FIELD(inputCrystalStructure) || + field == PROPERTY_FIELD(misorientationThreshold) || + field == PROPERTY_FIELD(fluctuationTolerance) || + field == PROPERTY_FIELD(minGrainAtomCount) || + field == PROPERTY_FIELD(smoothingLevel) || + field == PROPERTY_FIELD(probeSphereRadius) || + field == PROPERTY_FIELD(onlySelectedParticles) || + field == PROPERTY_FIELD(outputPartitionMesh)) invalidateCachedResults(); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationModifier.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationModifier.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/grains/GrainSegmentationModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_GRAIN_SEGMENTATION_MODIFIER_H -#define __OVITO_GRAIN_SEGMENTATION_MODIFIER_H +#pragma once + #include #include @@ -42,60 +42,6 @@ /// Constructor. Q_INVOKABLE GrainSegmentationModifier(DataSet* dataset); - /// Return the catalog of structure patterns. - PatternCatalog* patternCatalog() const { return _patternCatalog; } - - /// Returns the type of crystal to be analyzed. - StructureAnalysis::LatticeStructureType inputCrystalStructure() const { return static_cast(_inputCrystalStructure.value()); } - - /// Sets the type of crystal to be analyzed. - void setInputCrystalStructure(StructureAnalysis::LatticeStructureType structureType) { _inputCrystalStructure = structureType; } - - /// Returns the minimum misorientation angle between adjacent grains. - FloatType misorientationThreshold() const { return _misorientationThreshold; } - - /// Sets the minimum misorientation angle between adjacent grains. - void setMisorientationThreshold(FloatType threshold) { _misorientationThreshold = threshold; } - - /// Returns the amount of noise tolerated within a grain. - FloatType fluctuationTolerance() const { return _fluctuationTolerance; } - - /// Sets the amount of noise tolerated within a grain. - void setFluctuationTolerance(FloatType tolerance) { _fluctuationTolerance = tolerance; } - - /// Returns the minimum number of crystalline atoms per grain. - int minGrainAtomCount() const { return _minGrainAtomCount; } - - /// Sets the minimum number of crystalline atoms per grain. - void setMinGrainAtomCount(int minAtoms) { _minGrainAtomCount = minAtoms; } - - /// \brief Returns the radius parameter used during construction of the free surface. - FloatType probeSphereRadius() const { return _probeSphereRadius; } - - /// \brief Sets the radius parameter used during construction of the free surface. - void setProbeSphereRadius(FloatType radius) { _probeSphereRadius = radius; } - - /// \brief Returns the level of smoothing applied to the constructed partition mesh. - int smoothingLevel() const { return _smoothingLevel; } - - /// \brief Sets the level of smoothing applied to the constructed partition mesh. - void setSmoothingLevel(int level) { _smoothingLevel = level; } - - /// Returns whether only selected particles are taken into account. - bool onlySelectedParticles() const { return _onlySelectedParticles; } - - /// Sets whether only selected particles should be taken into account. - void setOnlySelectedParticles(bool onlySelected) { _onlySelectedParticles = onlySelected; } - - /// Returns whether the generation of the partition mesh is enabled. - bool outputPartitionMesh() const { return _outputPartitionMesh; } - - /// Enables the generation of the partition mesh. - void setOutputPartitionMesh(bool enable) { _outputPartitionMesh = enable; } - - /// \brief Returns the display object that is responsible for rendering the grain boundary mesh. - PartitionMeshDisplay* meshDisplay() const { return _meshDisplay; } - /// Resets the modifier's result cache. virtual void invalidateCachedResults() override; @@ -119,31 +65,31 @@ private: /// The type of crystal to be analyzed. - PropertyField _inputCrystalStructure; + DECLARE_MODIFIABLE_PROPERTY_FIELD(StructureAnalysis::LatticeStructureType, inputCrystalStructure, setInputCrystalStructure); /// The minimum misorientation angle between adjacent grains. - PropertyField _misorientationThreshold; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, misorientationThreshold, setMisorientationThreshold); /// Controls the amount of noise allowed inside a grain. - PropertyField _fluctuationTolerance; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, fluctuationTolerance, setFluctuationTolerance); /// The minimum number of crystalline atoms per grain. - PropertyField _minGrainAtomCount; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, minGrainAtomCount, setMinGrainAtomCount); /// Enables the generation of the partition mesh. - PropertyField _outputPartitionMesh; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, outputPartitionMesh, setOutputPartitionMesh); /// Controls the radius of the probe sphere used when constructing the free surfaces. - PropertyField _probeSphereRadius; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, probeSphereRadius, setProbeSphereRadius); /// Controls the amount of smoothing applied to the mesh. - PropertyField _smoothingLevel; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, smoothingLevel, setSmoothingLevel); /// Controls whether only selected particles should be taken into account. - PropertyField _onlySelectedParticles; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, onlySelectedParticles, setOnlySelectedParticles); /// The display object for rendering the mesh. - ReferenceField _meshDisplay; + DECLARE_MODIFIABLE_REFERENCE_FIELD(PartitionMeshDisplay, meshDisplay, setMeshDisplay); /// This stores the cached mesh produced by the modifier. QExplicitlySharedDataPointer _partitionMesh; @@ -152,7 +98,7 @@ int _spaceFillingRegion; /// The catalog of structure patterns. - ReferenceField _patternCatalog; + DECLARE_MODIFIABLE_REFERENCE_FIELD(PatternCatalog, patternCatalog, setPatternCatalog); /// This stores the cached atom-to-cluster assignments computed by the modifier. QExplicitlySharedDataPointer _atomClusters; @@ -165,21 +111,10 @@ Q_CLASSINFO("DisplayName", "Grain segmentation"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_PROPERTY_FIELD(_inputCrystalStructure); - DECLARE_PROPERTY_FIELD(_misorientationThreshold); - DECLARE_PROPERTY_FIELD(_fluctuationTolerance); - DECLARE_PROPERTY_FIELD(_minGrainAtomCount); - DECLARE_PROPERTY_FIELD(_outputPartitionMesh); - DECLARE_PROPERTY_FIELD(_probeSphereRadius); - DECLARE_PROPERTY_FIELD(_smoothingLevel); - DECLARE_PROPERTY_FIELD(_onlySelectedParticles); - DECLARE_REFERENCE_FIELD(_patternCatalog); - DECLARE_REFERENCE_FIELD(_meshDisplay); }; } // End of namespace } // End of namespace } // End of namespace -#endif // __OVITO_GRAIN_SEGMENTATION_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/SliceSurfaceModifier.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/SliceSurfaceModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/SliceSurfaceModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/SliceSurfaceModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,8 +29,8 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, SliceSurfaceFunction, SliceModifierFunction); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, SliceDislocationsFunction, SliceModifierFunction); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SliceSurfaceFunction, SliceModifierFunction); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SliceDislocationsFunction, SliceModifierFunction); /****************************************************************************** * Performs the actual rejection of particles. diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/SliceSurfaceModifier.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/SliceSurfaceModifier.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/SliceSurfaceModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/SliceSurfaceModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SLICE_SURFACE_MODIFIER_H -#define __OVITO_SLICE_SURFACE_MODIFIER_H +#pragma once + #include #include @@ -83,4 +83,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SLICE_SURFACE_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/SmoothDislocationsModifier.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/SmoothDislocationsModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/SmoothDislocationsModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/SmoothDislocationsModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,17 +26,17 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, SmoothDislocationsModifier, Modifier); -DEFINE_FLAGS_PROPERTY_FIELD(SmoothDislocationsModifier, _smoothingEnabled, "SmoothingEnabled", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(SmoothDislocationsModifier, _smoothingLevel, "SmoothingLevel", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(SmoothDislocationsModifier, _coarseningEnabled, "CoarseningEnabled", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(SmoothDislocationsModifier, _linePointInterval, "LinePointInterval", PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(SmoothDislocationsModifier, _smoothingEnabled, "Enable smoothing"); -SET_PROPERTY_FIELD_LABEL(SmoothDislocationsModifier, _smoothingLevel, "Smoothing level"); -SET_PROPERTY_FIELD_LABEL(SmoothDislocationsModifier, _coarseningEnabled, "Enable coarsening"); -SET_PROPERTY_FIELD_LABEL(SmoothDislocationsModifier, _linePointInterval, "Point separation"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(SmoothDislocationsModifier, _smoothingLevel, IntegerParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(SmoothDislocationsModifier, _linePointInterval, FloatParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SmoothDislocationsModifier, Modifier); +DEFINE_FLAGS_PROPERTY_FIELD(SmoothDislocationsModifier, smoothingEnabled, "SmoothingEnabled", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(SmoothDislocationsModifier, smoothingLevel, "SmoothingLevel", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(SmoothDislocationsModifier, coarseningEnabled, "CoarseningEnabled", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(SmoothDislocationsModifier, linePointInterval, "LinePointInterval", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(SmoothDislocationsModifier, smoothingEnabled, "Enable smoothing"); +SET_PROPERTY_FIELD_LABEL(SmoothDislocationsModifier, smoothingLevel, "Smoothing level"); +SET_PROPERTY_FIELD_LABEL(SmoothDislocationsModifier, coarseningEnabled, "Enable coarsening"); +SET_PROPERTY_FIELD_LABEL(SmoothDislocationsModifier, linePointInterval, "Point separation"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(SmoothDislocationsModifier, smoothingLevel, IntegerParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(SmoothDislocationsModifier, linePointInterval, FloatParameterUnit, 0); /****************************************************************************** * Constructs the modifier object. @@ -45,10 +45,10 @@ _smoothingEnabled(true), _coarseningEnabled(true), _smoothingLevel(1), _linePointInterval(2.5) { - INIT_PROPERTY_FIELD(SmoothDislocationsModifier::_smoothingEnabled); - INIT_PROPERTY_FIELD(SmoothDislocationsModifier::_smoothingLevel); - INIT_PROPERTY_FIELD(SmoothDislocationsModifier::_coarseningEnabled); - INIT_PROPERTY_FIELD(SmoothDislocationsModifier::_linePointInterval); + INIT_PROPERTY_FIELD(smoothingEnabled); + INIT_PROPERTY_FIELD(smoothingLevel); + INIT_PROPERTY_FIELD(coarseningEnabled); + INIT_PROPERTY_FIELD(linePointInterval); } /****************************************************************************** @@ -197,7 +197,7 @@ count++; ++inputPtr; } - while(count*count < (int)(linePointInterval * sum) && count < input.size()/minNumPoints-1 && inputPtr != inputPtrEnd); + while(count*count < (int)(linePointInterval * sum) && count+1 < input.size()/minNumPoints && inputPtr != inputPtrEnd); output.push_back(Point3::Origin() + com / count); outputCoreSize.push_back(sum / count); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/SmoothDislocationsModifier.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/SmoothDislocationsModifier.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/SmoothDislocationsModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/SmoothDislocationsModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_SMOOTH_DISLOCATIONS_MODIFIER_H -#define __OVITO_CA_SMOOTH_DISLOCATIONS_MODIFIER_H +#pragma once + #include #include @@ -47,30 +47,6 @@ /// Smoothes the given dislocation lines. void smoothDislocationLines(DislocationNetworkObject* dislocationsObj); - /// Returns whether smoothing is enabled. - bool smoothingEnabled() const { return _smoothingEnabled; } - - /// Enables/disables smoothing. - void setSmoothingEnabled(bool enable) { _smoothingEnabled = enable; } - - /// Returns the smoothing strength. - int smoothingLevel() const { return _smoothingLevel; } - - /// Sets the smoothing strength. - void setSmoothingLevel(int level) { _smoothingLevel = level; } - - /// Returns whether coarsening of dislocation line points is enabled. - bool coarseningEnabled() const { return _coarseningEnabled; } - - /// Enables/disables coarsening of dislocation line points. - void setCoarseningEnabled(bool enable) { _coarseningEnabled = enable; } - - /// Returns the target distance between successive line points after coarsening. - FloatType linePointInterval() const { return _linePointInterval; } - - /// Sets the target distance between successive line points after coarsening. - void setLinePointInterval(FloatType d) { _linePointInterval = d; } - protected: /// Removes some of the sampling points from a dislocation line. @@ -82,31 +58,26 @@ private: /// Stores whether smoothing is enabled. - PropertyField _smoothingEnabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, smoothingEnabled, setSmoothingEnabled); /// Controls the degree of smoothing. - PropertyField _smoothingLevel; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, smoothingLevel, setSmoothingLevel); /// Stores whether coarsening is enabled. - PropertyField _coarseningEnabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, coarseningEnabled, setCoarseningEnabled); /// Controls the coarsening of dislocation lines. - PropertyField _linePointInterval; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, linePointInterval, setLinePointInterval); Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Smooth dislocations"); - Q_CLASSINFO("ModifierCategory", "Crystal analysis"); - - DECLARE_PROPERTY_FIELD(_smoothingEnabled); - DECLARE_PROPERTY_FIELD(_smoothingLevel); - DECLARE_PROPERTY_FIELD(_coarseningEnabled); - DECLARE_PROPERTY_FIELD(_linePointInterval); + Q_CLASSINFO("ModifierCategory", "Modification"); }; } // End of namespace } // End of namespace } // End of namespace -#endif // __OVITO_CA_SMOOTH_DISLOCATIONS_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/SmoothSurfaceModifier.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/SmoothSurfaceModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/SmoothSurfaceModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/SmoothSurfaceModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,21 +23,28 @@ #include #include #include +#include +#include +#include #include "SmoothSurfaceModifier.h" namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, SmoothSurfaceModifier, Modifier); -DEFINE_FLAGS_PROPERTY_FIELD(SmoothSurfaceModifier, _smoothingLevel, "SmoothingLevel", PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(SmoothSurfaceModifier, _smoothingLevel, "Smoothing level"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(SmoothSurfaceModifier, _smoothingLevel, IntegerParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SmoothSurfaceModifier, Modifier); +DEFINE_FLAGS_PROPERTY_FIELD(SmoothSurfaceModifier, smoothingLevel, "SmoothingLevel", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(SmoothSurfaceModifier, minEdgeLength, "MinEdgeLength", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(SmoothSurfaceModifier, smoothingLevel, "Smoothing level"); +SET_PROPERTY_FIELD_LABEL(SmoothSurfaceModifier, minEdgeLength, "Minimum edge length"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(SmoothSurfaceModifier, smoothingLevel, IntegerParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(SmoothSurfaceModifier, minEdgeLength, WorldParameterUnit, 0); /****************************************************************************** * Constructs the modifier object. ******************************************************************************/ -SmoothSurfaceModifier::SmoothSurfaceModifier(DataSet* dataset) : Modifier(dataset), _smoothingLevel(8) +SmoothSurfaceModifier::SmoothSurfaceModifier(DataSet* dataset) : Modifier(dataset), _smoothingLevel(8), _minEdgeLength(0) { - INIT_PROPERTY_FIELD(SmoothSurfaceModifier::_smoothingLevel); + INIT_PROPERTY_FIELD(smoothingLevel); + INIT_PROPERTY_FIELD(minEdgeLength); } /****************************************************************************** @@ -53,7 +60,7 @@ ******************************************************************************/ PipelineStatus SmoothSurfaceModifier::modifyObject(TimePoint time, ModifierApplication* modApp, PipelineFlowState& state) { - if(_smoothingLevel <= 0) + if(smoothingLevel() <= 0 && minEdgeLength() <= 0) return PipelineStatus::Success; // Get simulation cell geometry and periodic boundary flags. @@ -63,16 +70,39 @@ else cell.setPbcFlags(false, false, false); + // Helper function required by the mesh simplification routine. + auto pointPointVector = [&cell](const Point3& p0, const Point3& p1) { + return cell.wrapVector(p1 - p0); + }; + CloneHelper cloneHelper; for(int index = 0; index < state.objects().size(); index++) { if(SurfaceMesh* inputSurface = dynamic_object_cast(state.objects()[index])) { OORef outputSurface = cloneHelper.cloneObject(inputSurface, false); - outputSurface->smoothMesh(cell, _smoothingLevel); + SynchronousTask smoothingTask(dataset()->container()->taskManager()); + if(smoothingLevel() > 0) { + outputSurface->smoothMesh(cell, smoothingLevel(), smoothingTask.promise()); + } + if(minEdgeLength() > 0) { + EdgeCollapseMeshSimplification, decltype(pointPointVector)> simplification(*outputSurface->modifiableStorage(), pointPointVector); + simplification.perform(minEdgeLength(), smoothingTask.promise()); + outputSurface->changed(); + } state.replaceObject(inputSurface, outputSurface); } else if(SlipSurface* inputSurface = dynamic_object_cast(state.objects()[index])) { OORef outputSurface = cloneHelper.cloneObject(inputSurface, false); - outputSurface->smoothMesh(cell, _smoothingLevel, nullptr, 0.1f, 0.6f); + SynchronousTask smoothingTask(dataset()->container()->taskManager()); + if(smoothingLevel() > 0) { + outputSurface->smoothMesh(cell, smoothingLevel(), smoothingTask.promise(), FloatType(0.1), FloatType(0.6)); + } +#if 0 + if(minEdgeLength() > 0) { + EdgeCollapseMeshSimplification simplification(*outputSurface->modifiableStorage(), pointPointVector); + simplification.perform(minEdgeLength(), smoothingTask.promise()); + outputSurface->changed(); + } +#endif state.replaceObject(inputSurface, outputSurface); } } diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/SmoothSurfaceModifier.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/SmoothSurfaceModifier.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/modifier/SmoothSurfaceModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/modifier/SmoothSurfaceModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_SMOOTH_SURFACE_MODIFIER_H -#define __OVITO_CA_SMOOTH_SURFACE_MODIFIER_H +#pragma once + #include #include @@ -44,28 +44,23 @@ /// This modifies the input object. virtual PipelineStatus modifyObject(TimePoint time, ModifierApplication* modApp, PipelineFlowState& state) override; - /// Returns the smoothing strength. - int smoothingLevel() const { return _smoothingLevel; } - - /// Sets the smoothing strength. - void setSmoothingLevel(int level) { _smoothingLevel = level; } - private: - /// Controls the amount of smoothing. - PropertyField _smoothingLevel; + /// The number of iterations of the smoothing algorithm. + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, smoothingLevel, setSmoothingLevel); + + /// The minimum edge length stopping criterion for the mesh simplification algorithm. + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, minEdgeLength, setMinEdgeLength); Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Smooth surface"); - Q_CLASSINFO("ModifierCategory", "Crystal analysis"); - - DECLARE_PROPERTY_FIELD(_smoothingLevel); + Q_CLASSINFO("ModifierCategory", "Modification"); }; } // End of namespace } // End of namespace } // End of namespace -#endif // __OVITO_CA_SMOOTH_SURFACE_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/clusters/ClusterGraphObject.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/clusters/ClusterGraphObject.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/clusters/ClusterGraphObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/clusters/ClusterGraphObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, ClusterGraphObject, DataObject); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ClusterGraphObject, DataObject); /****************************************************************************** * Constructs a cluster graph object. diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/clusters/ClusterGraphObject.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/clusters/ClusterGraphObject.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/clusters/ClusterGraphObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/clusters/ClusterGraphObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_CLUSTER_GRAPH_OBJECT_H -#define __OVITO_CA_CLUSTER_GRAPH_OBJECT_H +#pragma once + #include #include @@ -63,5 +63,5 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CA_CLUSTER_GRAPH_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/dislocations/DislocationDisplay.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/dislocations/DislocationDisplay.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/dislocations/DislocationDisplay.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/dislocations/DislocationDisplay.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,26 +26,26 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, DislocationDisplay, DisplayObject); -IMPLEMENT_OVITO_OBJECT(CrystalAnalysis, DislocationPickInfo, ObjectPickInfo); -DEFINE_FLAGS_PROPERTY_FIELD(DislocationDisplay, _lineWidth, "LineWidth", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(DislocationDisplay, _shadingMode, "ShadingMode", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(DislocationDisplay, _burgersVectorWidth, "BurgersVectorWidth", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(DislocationDisplay, _burgersVectorScaling, "BurgersVectorScaling", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(DislocationDisplay, _burgersVectorColor, "BurgersVectorColor", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(DislocationDisplay, _showBurgersVectors, "ShowBurgersVectors"); -DEFINE_PROPERTY_FIELD(DislocationDisplay, _showLineDirections, "ShowLineDirections"); -DEFINE_PROPERTY_FIELD(DislocationDisplay, _lineColoringMode, "LineColoringMode"); -SET_PROPERTY_FIELD_LABEL(DislocationDisplay, _lineWidth, "Dislocation line width"); -SET_PROPERTY_FIELD_LABEL(DislocationDisplay, _shadingMode, "Shading mode"); -SET_PROPERTY_FIELD_LABEL(DislocationDisplay, _burgersVectorWidth, "Burgers vector width"); -SET_PROPERTY_FIELD_LABEL(DislocationDisplay, _burgersVectorScaling, "Burgers vector scaling"); -SET_PROPERTY_FIELD_LABEL(DislocationDisplay, _burgersVectorColor, "Burgers vector color"); -SET_PROPERTY_FIELD_LABEL(DislocationDisplay, _showBurgersVectors, "Show Burgers vectors"); -SET_PROPERTY_FIELD_LABEL(DislocationDisplay, _showLineDirections, "Indicate line directions"); -SET_PROPERTY_FIELD_LABEL(DislocationDisplay, _lineColoringMode, "Line coloring"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(DislocationDisplay, _lineWidth, WorldParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(DislocationDisplay, _burgersVectorWidth, WorldParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(DislocationDisplay, DisplayObject); +IMPLEMENT_OVITO_OBJECT(DislocationPickInfo, ObjectPickInfo); +DEFINE_FLAGS_PROPERTY_FIELD(DislocationDisplay, lineWidth, "LineWidth", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(DislocationDisplay, shadingMode, "ShadingMode", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(DislocationDisplay, burgersVectorWidth, "BurgersVectorWidth", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(DislocationDisplay, burgersVectorScaling, "BurgersVectorScaling", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(DislocationDisplay, burgersVectorColor, "BurgersVectorColor", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(DislocationDisplay, showBurgersVectors, "ShowBurgersVectors"); +DEFINE_PROPERTY_FIELD(DislocationDisplay, showLineDirections, "ShowLineDirections"); +DEFINE_PROPERTY_FIELD(DislocationDisplay, lineColoringMode, "LineColoringMode"); +SET_PROPERTY_FIELD_LABEL(DislocationDisplay, lineWidth, "Dislocation line width"); +SET_PROPERTY_FIELD_LABEL(DislocationDisplay, shadingMode, "Shading mode"); +SET_PROPERTY_FIELD_LABEL(DislocationDisplay, burgersVectorWidth, "Burgers vector width"); +SET_PROPERTY_FIELD_LABEL(DislocationDisplay, burgersVectorScaling, "Burgers vector scaling"); +SET_PROPERTY_FIELD_LABEL(DislocationDisplay, burgersVectorColor, "Burgers vector color"); +SET_PROPERTY_FIELD_LABEL(DislocationDisplay, showBurgersVectors, "Show Burgers vectors"); +SET_PROPERTY_FIELD_LABEL(DislocationDisplay, showLineDirections, "Indicate line directions"); +SET_PROPERTY_FIELD_LABEL(DislocationDisplay, lineColoringMode, "Line coloring"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(DislocationDisplay, lineWidth, WorldParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(DislocationDisplay, burgersVectorWidth, WorldParameterUnit, 0); /****************************************************************************** * Constructor. @@ -56,14 +56,14 @@ _burgersVectorColor(0.7, 0.7, 0.7), _showBurgersVectors(false), _showLineDirections(false), _lineColoringMode(ColorByDislocationType) { - INIT_PROPERTY_FIELD(DislocationDisplay::_lineWidth); - INIT_PROPERTY_FIELD(DislocationDisplay::_shadingMode); - INIT_PROPERTY_FIELD(DislocationDisplay::_burgersVectorWidth); - INIT_PROPERTY_FIELD(DislocationDisplay::_burgersVectorScaling); - INIT_PROPERTY_FIELD(DislocationDisplay::_burgersVectorColor); - INIT_PROPERTY_FIELD(DislocationDisplay::_showBurgersVectors); - INIT_PROPERTY_FIELD(DislocationDisplay::_showLineDirections); - INIT_PROPERTY_FIELD(DislocationDisplay::_lineColoringMode); + INIT_PROPERTY_FIELD(lineWidth); + INIT_PROPERTY_FIELD(shadingMode); + INIT_PROPERTY_FIELD(burgersVectorWidth); + INIT_PROPERTY_FIELD(burgersVectorScaling); + INIT_PROPERTY_FIELD(burgersVectorColor); + INIT_PROPERTY_FIELD(showBurgersVectors); + INIT_PROPERTY_FIELD(showLineDirections); + INIT_PROPERTY_FIELD(lineColoringMode); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/dislocations/DislocationDisplay.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/dislocations/DislocationDisplay.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/dislocations/DislocationDisplay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/dislocations/DislocationDisplay.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_DISLOCATION_DISPLAY_H -#define __OVITO_CA_DISLOCATION_DISPLAY_H +#pragma once + #include #include @@ -112,54 +112,6 @@ /// \brief Computes the bounding box of the object. virtual Box3 boundingBox(TimePoint time, DataObject* dataObject, ObjectNode* contextNode, const PipelineFlowState& flowState) override; - /// \brief Returns the line width used for dislocation rendering. - FloatType lineWidth() const { return _lineWidth; } - - /// \brief Sets the line width used for dislocation rendering. - void setLineWidth(FloatType width) { _lineWidth = width; } - - /// \brief Returns the selected shading mode for dislocation lines. - ArrowPrimitive::ShadingMode shadingMode() const { return _shadingMode; } - - /// \brief Sets the shading mode for dislocation lines. - void setShadingMode(ArrowPrimitive::ShadingMode mode) { _shadingMode = mode; } - - /// Returns the rendering width for Burgers vectors. - FloatType burgersVectorWidth() const { return _burgersVectorWidth; } - - /// Sets the rendering width for Burgers vectors. - void setBurgersVectorWidth(FloatType width) { _burgersVectorWidth = width; } - - /// Returns the scaling factor Burgers vectors. - FloatType burgersVectorScaling() const { return _burgersVectorScaling; } - - /// Sets the scaling factor Burgers vectors. - void setBurgersVectorScaling(FloatType factor) { _burgersVectorScaling = factor; } - - /// Returns the display color for Burgers vector arrows. - const Color& burgersVectorColor() const { return _burgersVectorColor; } - - /// Sets the display color for Burgers vector arrows. - void setBurgersVectorColor(const Color& color) { _burgersVectorColor = color; } - - /// Returns whether the display of Burgers vector arrows is enabled. - bool showBurgersVectors() const { return _showBurgersVectors; } - - /// Controls the display of Burgers vector arrows. - void setShowBurgersVectors(bool enabled) { _showBurgersVectors = enabled; } - - /// Returns whether line directions are indicated. - bool showLineDirections() const { return _showLineDirections; } - - /// Sets whether line directions should be indicated. - void setShowLineDirections(bool enabled) { _showLineDirections = enabled; } - - /// Returns how the display color of dislocation lines is chosen. - LineColoringMode lineColoringMode() const { return _lineColoringMode; } - - /// Sets how the display color of dislocation lines is chosen. - void setLineColoringMode(LineColoringMode mode) { _lineColoringMode = mode; } - /// \brief Renders an overlay marker for a single dislocation segment. void renderOverlayMarker(TimePoint time, DataObject* dataObject, const PipelineFlowState& flowState, int segmentIndex, SceneRenderer* renderer, ObjectNode* contextNode); @@ -168,7 +120,6 @@ public: - Q_PROPERTY(FloatType lineWidth READ lineWidth WRITE setLineWidth); Q_PROPERTY(Ovito::ArrowPrimitive::ShadingMode shadingMode READ shadingMode WRITE setShadingMode); protected: @@ -216,51 +167,40 @@ > _boundingBoxCacheHelper; /// The rendering width for dislocation lines. - PropertyField _lineWidth; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, lineWidth, setLineWidth); /// The shading mode for dislocation lines. - PropertyField _shadingMode; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ArrowPrimitive::ShadingMode, shadingMode, setShadingMode); /// The rendering width for Burgers vectors. - PropertyField _burgersVectorWidth; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, burgersVectorWidth, setBurgersVectorWidth); /// The scaling factor Burgers vectors. - PropertyField _burgersVectorScaling; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, burgersVectorScaling, setBurgersVectorScaling); /// Display color for Burgers vectors. - PropertyField _burgersVectorColor; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, burgersVectorColor, setBurgersVectorColor); /// Controls the display of Burgers vectors. - PropertyField _showBurgersVectors; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, showBurgersVectors, setShowBurgersVectors); /// Controls the display of the line directions. - PropertyField _showLineDirections; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, showLineDirections, setShowLineDirections); /// Controls how the display color of dislocation lines is chosen. - PropertyField _lineColoringMode; + DECLARE_MODIFIABLE_PROPERTY_FIELD(LineColoringMode, lineColoringMode, setLineColoringMode); /// The data record used for picking dislocations in the viewports. OORef _pickInfo; -private: - Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Dislocations"); - - DECLARE_PROPERTY_FIELD(_lineWidth); - DECLARE_PROPERTY_FIELD(_shadingMode); - DECLARE_PROPERTY_FIELD(_burgersVectorWidth); - DECLARE_PROPERTY_FIELD(_burgersVectorScaling); - DECLARE_PROPERTY_FIELD(_burgersVectorColor); - DECLARE_PROPERTY_FIELD(_showBurgersVectors); - DECLARE_PROPERTY_FIELD(_showLineDirections); - DECLARE_PROPERTY_FIELD(_lineColoringMode); }; } // End of namespace } // End of namespace } // End of namespace -#endif // __OVITO_CA_DISLOCATION_DISPLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/dislocations/DislocationNetworkObject.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/dislocations/DislocationNetworkObject.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/dislocations/DislocationNetworkObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/dislocations/DislocationNetworkObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, DislocationNetworkObject, DataObject); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(DislocationNetworkObject, DataObject); /****************************************************************************** * Constructor. diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/dislocations/DislocationNetworkObject.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/dislocations/DislocationNetworkObject.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/dislocations/DislocationNetworkObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/dislocations/DislocationNetworkObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_DISLOCATION_NETWORK_OBJECT_H -#define __OVITO_CA_DISLOCATION_NETWORK_OBJECT_H +#pragma once + #include #include @@ -80,4 +80,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CA_DISLOCATION_NETWORK_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMesh.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMesh.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMesh.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMesh.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,8 +25,8 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, PartitionMesh, DataObject); -DEFINE_PROPERTY_FIELD(PartitionMesh, _spaceFillingRegion, "SpaceFillingRegion"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(PartitionMesh, DataObject); +DEFINE_PROPERTY_FIELD(PartitionMesh, spaceFillingRegion, "SpaceFillingRegion"); /****************************************************************************** * Constructs an empty surface mesh object. @@ -34,7 +34,7 @@ PartitionMesh::PartitionMesh(DataSet* dataset, PartitionMeshData* mesh) : DataObjectWithSharedStorage(dataset, mesh ? mesh : new PartitionMeshData()), _spaceFillingRegion(0) { - INIT_PROPERTY_FIELD(PartitionMesh::_spaceFillingRegion); + INIT_PROPERTY_FIELD(spaceFillingRegion); } /****************************************************************************** @@ -54,7 +54,7 @@ /****************************************************************************** * Fairs a closed triangle mesh. ******************************************************************************/ -void PartitionMesh::smoothMesh(PartitionMeshData& mesh, const SimulationCell& cell, int numIterations, FutureInterfaceBase* progress, FloatType k_PB, FloatType lambda) +bool PartitionMesh::smoothMesh(PartitionMeshData& mesh, const SimulationCell& cell, int numIterations, PromiseBase& promise, FloatType k_PB, FloatType lambda) { // This is the implementation of the mesh smoothing algorithm: // @@ -62,15 +62,17 @@ // A Signal Processing Approach To Fair Surface Design // In SIGGRAPH 95 Conference Proceedings, pages 351-358 (1995) - FloatType mu = 1.0f / (k_PB - 1.0f/lambda); - if(progress) progress->setProgressRange(numIterations); + FloatType mu = FloatType(1) / (k_PB - FloatType(1)/lambda); + promise.setProgressMaximum(numIterations); for(int iteration = 0; iteration < numIterations; iteration++) { + if(!promise.setProgressValue(iteration)) + return false; smoothMeshIteration(mesh, lambda, cell); smoothMeshIteration(mesh, mu, cell); - if(progress && !progress->setProgressValue(iteration+1)) - return; } + + return !promise.isCanceled(); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMeshDisplay.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMeshDisplay.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMeshDisplay.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMeshDisplay.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,21 +29,21 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, PartitionMeshDisplay, AsynchronousDisplayObject); -DEFINE_FLAGS_PROPERTY_FIELD(PartitionMeshDisplay, _surfaceColor, "SurfaceColor", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(PartitionMeshDisplay, _showCap, "ShowCap", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(PartitionMeshDisplay, _smoothShading, "SmoothShading"); -DEFINE_PROPERTY_FIELD(PartitionMeshDisplay, _flipOrientation, "FlipOrientation"); -DEFINE_REFERENCE_FIELD(PartitionMeshDisplay, _surfaceTransparency, "SurfaceTransparency", Controller); -DEFINE_REFERENCE_FIELD(PartitionMeshDisplay, _capTransparency, "CapTransparency", Controller); -SET_PROPERTY_FIELD_LABEL(PartitionMeshDisplay, _surfaceColor, "Free surface color"); -SET_PROPERTY_FIELD_LABEL(PartitionMeshDisplay, _showCap, "Show cap polygons"); -SET_PROPERTY_FIELD_LABEL(PartitionMeshDisplay, _smoothShading, "Smooth shading"); -SET_PROPERTY_FIELD_LABEL(PartitionMeshDisplay, _surfaceTransparency, "Surface transparency"); -SET_PROPERTY_FIELD_LABEL(PartitionMeshDisplay, _capTransparency, "Cap transparency"); -SET_PROPERTY_FIELD_LABEL(PartitionMeshDisplay, _flipOrientation, "Flip surface orientation"); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(PartitionMeshDisplay, _surfaceTransparency, PercentParameterUnit, 0, 1); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(PartitionMeshDisplay, _capTransparency, PercentParameterUnit, 0, 1); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(PartitionMeshDisplay, AsynchronousDisplayObject); +DEFINE_FLAGS_PROPERTY_FIELD(PartitionMeshDisplay, surfaceColor, "SurfaceColor", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(PartitionMeshDisplay, showCap, "ShowCap", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(PartitionMeshDisplay, smoothShading, "SmoothShading"); +DEFINE_PROPERTY_FIELD(PartitionMeshDisplay, flipOrientation, "FlipOrientation"); +DEFINE_REFERENCE_FIELD(PartitionMeshDisplay, surfaceTransparencyController, "SurfaceTransparency", Controller); +DEFINE_REFERENCE_FIELD(PartitionMeshDisplay, capTransparencyController, "CapTransparency", Controller); +SET_PROPERTY_FIELD_LABEL(PartitionMeshDisplay, surfaceColor, "Free surface color"); +SET_PROPERTY_FIELD_LABEL(PartitionMeshDisplay, showCap, "Show cap polygons"); +SET_PROPERTY_FIELD_LABEL(PartitionMeshDisplay, smoothShading, "Smooth shading"); +SET_PROPERTY_FIELD_LABEL(PartitionMeshDisplay, surfaceTransparencyController, "Surface transparency"); +SET_PROPERTY_FIELD_LABEL(PartitionMeshDisplay, capTransparencyController, "Cap transparency"); +SET_PROPERTY_FIELD_LABEL(PartitionMeshDisplay, flipOrientation, "Flip surface orientation"); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(PartitionMeshDisplay, surfaceTransparencyController, PercentParameterUnit, 0, 1); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(PartitionMeshDisplay, capTransparencyController, PercentParameterUnit, 0, 1); /****************************************************************************** * Constructor. @@ -51,15 +51,15 @@ PartitionMeshDisplay::PartitionMeshDisplay(DataSet* dataset) : AsynchronousDisplayObject(dataset), _surfaceColor(1, 1, 1), _showCap(true), _smoothShading(true), _flipOrientation(false), _trimeshUpdate(true) { - INIT_PROPERTY_FIELD(PartitionMeshDisplay::_surfaceColor); - INIT_PROPERTY_FIELD(PartitionMeshDisplay::_showCap); - INIT_PROPERTY_FIELD(PartitionMeshDisplay::_smoothShading); - INIT_PROPERTY_FIELD(PartitionMeshDisplay::_surfaceTransparency); - INIT_PROPERTY_FIELD(PartitionMeshDisplay::_capTransparency); - INIT_PROPERTY_FIELD(PartitionMeshDisplay::_flipOrientation); + INIT_PROPERTY_FIELD(surfaceColor); + INIT_PROPERTY_FIELD(showCap); + INIT_PROPERTY_FIELD(smoothShading); + INIT_PROPERTY_FIELD(surfaceTransparencyController); + INIT_PROPERTY_FIELD(capTransparencyController); + INIT_PROPERTY_FIELD(flipOrientation); - _surfaceTransparency = ControllerManager::instance().createFloatController(dataset); - _capTransparency = ControllerManager::instance().createFloatController(dataset); + setSurfaceTransparencyController(ControllerManager::createFloatController(dataset)); + setCapTransparencyController(ControllerManager::createFloatController(dataset)); } /****************************************************************************** @@ -109,7 +109,7 @@ { setProgressText(tr("Preparing microstructure mesh for display")); - if(!buildMesh(*_inputMesh, _simCell, _cuttingPlanes, _surfaceMesh, this)) + if(!buildMesh(*_inputMesh, _simCell, _cuttingPlanes, _surfaceMesh, *this)) throw Exception(tr("Failed to generate non-periodic version of microstructure mesh for display. Simulation cell might be too small.")); if(_flipOrientation) @@ -155,13 +155,13 @@ FloatType transp_surface = 0; FloatType transp_cap = 0; TimeInterval iv; - if(_surfaceTransparency) transp_surface = _surfaceTransparency->getFloatValue(time, iv); - if(_capTransparency) transp_cap = _capTransparency->getFloatValue(time, iv); - ColorA color_surface(surfaceColor(), 1.0f - transp_surface); + if(surfaceTransparencyController()) transp_surface = surfaceTransparencyController()->getFloatValue(time, iv); + if(capTransparencyController()) transp_cap = capTransparencyController()->getFloatValue(time, iv); + ColorA color_surface(surfaceColor(), FloatType(1) - transp_surface); // Do we have to re-create the render primitives from scratch? bool recreateSurfaceBuffer = !_surfaceBuffer || !_surfaceBuffer->isValid(renderer); - bool recreateCapBuffer = _showCap && (!_capBuffer || !_capBuffer->isValid(renderer)); + bool recreateCapBuffer = showCap() && (!_capBuffer || !_capBuffer->isValid(renderer)); // Do we have to update the render primitives? bool updateContents = _geometryCacheHelper.updateState(color_surface, smoothShading(), clusterGraph) @@ -177,7 +177,7 @@ if(updateContents) { // Assign smoothing group to faces to interpolate normals. - const quint32 smoothingGroup = _smoothShading ? 1 : 0; + const quint32 smoothingGroup = smoothShading() ? 1 : 0; for(auto& face : _surfaceMesh.faces()) { face.setSmoothingGroups(smoothingGroup); } @@ -202,7 +202,7 @@ _surfaceBuffer->setMesh(_surfaceMesh, color_surface); _surfaceBuffer->setCullFaces(true); - if(_showCap) + if(showCap()) _capBuffer->setMesh(_capPolygonsMesh, color_surface); // Reset update flag. @@ -212,7 +212,7 @@ // Handle picking of triangles. renderer->beginPickObject(contextNode); _surfaceBuffer->render(renderer); - if(_showCap) + if(showCap()) _capBuffer->render(renderer); else _capBuffer.reset(); @@ -222,7 +222,7 @@ /****************************************************************************** * Generates the final triangle mesh, which will be rendered. ******************************************************************************/ -bool PartitionMeshDisplay::buildMesh(const PartitionMeshData& input, const SimulationCell& cell, const QVector& cuttingPlanes, TriMesh& output, FutureInterfaceBase* progress) +bool PartitionMeshDisplay::buildMesh(const PartitionMeshData& input, const SimulationCell& cell, const QVector& cuttingPlanes, TriMesh& output, PromiseBase& promise) { // Convert half-edge mesh to triangle mesh. input.convertToTriMesh(output); @@ -237,8 +237,7 @@ } OVITO_ASSERT(fout == output.faces().end()); - // Check for early abortion. - if(progress && progress->isCanceled()) + if(promise.isCanceled()) return false; // Convert vertex positions to reduced coordinates. @@ -251,7 +250,7 @@ for(size_t dim = 0; dim < 3; dim++) { if(cell.pbcFlags()[dim] == false) continue; - if(progress && progress->isCanceled()) + if(promise.isCanceled()) return false; // Make sure all vertices are located inside the periodic box. @@ -277,7 +276,7 @@ } // Check for early abortion. - if(progress && progress->isCanceled()) + if(promise.isCanceled()) return false; // Convert vertex positions back from reduced coordinates to absolute coordinates. @@ -287,7 +286,7 @@ // Clip mesh at cutting planes. for(const Plane3& plane : cuttingPlanes) { - if(progress && progress->isCanceled()) + if(promise.isCanceled()) return false; output.clipAtPlane(plane); @@ -296,7 +295,7 @@ output.invalidateVertices(); output.invalidateFaces(); - return true; + return !promise.isCanceled(); } /****************************************************************************** @@ -319,14 +318,14 @@ OVITO_ASSERT(z[2] - z[1] == -(z[1] - z[2])); OVITO_ASSERT(z[0] - z[2] == -(z[2] - z[0])); - if(std::abs(zd[0]) < 0.5f && std::abs(zd[1]) < 0.5f && std::abs(zd[2]) < 0.5f) + if(std::abs(zd[0]) < FloatType(0.5) && std::abs(zd[1]) < FloatType(0.5) && std::abs(zd[2]) < FloatType(0.5)) return true; // Face is not crossing the periodic boundary. // Create four new vertices (or use existing ones created during splitting of adjacent faces). int properEdge = -1; int newVertexIndices[3][2]; for(int i = 0; i < 3; i++) { - if(std::abs(zd[i]) < 0.5f) { + if(std::abs(zd[i]) < FloatType(0.5)) { if(properEdge != -1) return false; // The simulation box may be too small or invalid. properEdge = i; @@ -335,7 +334,7 @@ int vi1 = face.vertex(i); int vi2 = face.vertex((i+1)%3); int oi1, oi2; - if(zd[i] <= -0.5f) { + if(zd[i] <= FloatType(-0.5)) { std::swap(vi1, vi2); oi1 = 1; oi2 = 0; } @@ -349,7 +348,7 @@ } else { Vector3 delta = output.vertex(vi2) - output.vertex(vi1); - delta[dim] -= 1.0f; + delta[dim] -= FloatType(1); for(size_t d = dim + 1; d < 3; d++) { if(cell.pbcFlags()[d]) delta[d] -= floor(delta[d] + FloatType(0.5)); @@ -358,14 +357,14 @@ if(delta[dim] != 0) t = output.vertex(vi1)[dim] / (-delta[dim]); else - t = 0.5f; + t = FloatType(0.5); OVITO_ASSERT(std::isfinite(t)); Point3 p = delta * t + output.vertex(vi1); newVertexIndices[i][oi1] = oldVertexCount + (int)newVertices.size(); newVertexIndices[i][oi2] = oldVertexCount + (int)newVertices.size() + 1; newVertexLookupMap.insert(std::make_pair(std::pair(vi1, vi2), std::pair(newVertexIndices[i][oi1], newVertexIndices[i][oi2]))); newVertices.push_back(p); - p[dim] += 1.0f; + p[dim] += FloatType(1); newVertices.push_back(p); } } diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMeshDisplay.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMeshDisplay.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMeshDisplay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMeshDisplay.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTITION_MESH_DISPLAY_H -#define __OVITO_PARTITION_MESH_DISPLAY_H +#pragma once + #include #include @@ -50,44 +50,20 @@ /// \brief Computes the bounding box of the object. virtual Box3 boundingBox(TimePoint time, DataObject* dataObject, ObjectNode* contextNode, const PipelineFlowState& flowState) override; - /// Returns the color of the outer surface. - const Color& surfaceColor() const { return _surfaceColor; } - - /// Sets the color of the outer surface. - void setSurfaceColor(const Color& color) { _surfaceColor = color; } - - /// Returns whether the cap polygons are rendered. - bool showCap() const { return _showCap; } - - /// Sets whether the cap polygons are rendered. - void setShowCap(bool show) { _showCap = show; } - - /// Returns whether the mesh is rendered using smooth shading. - bool smoothShading() const { return _smoothShading; } - - /// Sets whether the mesh is rendered using smooth shading. - void setSmoothShading(bool smoothShading) { _smoothShading = smoothShading; } - - /// Returns whether the orientation of mesh faces is flipped. - bool flipOrientation() const { return _flipOrientation; } - - /// Sets whether the orientation of mesh faces is flipped. - void setFlipOrientation(bool flipOrientation) { _flipOrientation = flipOrientation; } - /// Returns the transparency of the surface mesh. - FloatType surfaceTransparency() const { return _surfaceTransparency ? _surfaceTransparency->currentFloatValue() : 0.0f; } + FloatType surfaceTransparency() const { return surfaceTransparencyController() ? surfaceTransparencyController()->currentFloatValue() : 0.0f; } /// Sets the transparency of the surface mesh. - void setSurfaceTransparency(FloatType transparency) { if(_surfaceTransparency) _surfaceTransparency->setCurrentFloatValue(transparency); } + void setSurfaceTransparency(FloatType transparency) { if(surfaceTransparencyController()) surfaceTransparencyController()->setCurrentFloatValue(transparency); } /// Returns the transparency of the cap polygons. - FloatType capTransparency() const { return _capTransparency ? _capTransparency->currentFloatValue() : 0.0f; } + FloatType capTransparency() const { return capTransparencyController() ? capTransparencyController()->currentFloatValue() : 0.0f; } /// Sets the transparency of the cap polygons. - void setCapTransparency(FloatType transparency) { if(_capTransparency) _capTransparency->setCurrentFloatValue(transparency); } + void setCapTransparency(FloatType transparency) { if(capTransparencyController()) capTransparencyController()->setCurrentFloatValue(transparency); } /// Generates the final triangle mesh, which will be rendered. - static bool buildMesh(const PartitionMeshData& input, const SimulationCell& cell, const QVector& cuttingPlanes, TriMesh& output, FutureInterfaceBase* progress = nullptr); + static bool buildMesh(const PartitionMeshData& input, const SimulationCell& cell, const QVector& cuttingPlanes, TriMesh& output, PromiseBase& promise); protected: @@ -129,22 +105,22 @@ static bool splitFace(TriMesh& output, int faceIndex, int oldVertexCount, std::vector& newVertices, std::map,std::pair>& newVertexLookupMap, const SimulationCell& cell, size_t dim); /// Controls the display color of the outer surface mesh. - PropertyField _surfaceColor; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, surfaceColor, setSurfaceColor); /// Controls whether the cap polygons are rendered. - PropertyField _showCap; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, showCap, setShowCap); /// Controls whether the mesh is rendered using smooth shading. - PropertyField _smoothShading; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, smoothShading, setSmoothShading); /// Controls whether the orientation of mesh faces is flipped. - PropertyField _flipOrientation; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, flipOrientation, setFlipOrientation); /// Controls the transparency of the surface mesh. - ReferenceField _surfaceTransparency; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, surfaceTransparencyController, setSurfaceTransparencyController); /// Controls the transparency of the surface cap mesh. - ReferenceField _capTransparency; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, capTransparencyController, setCapTransparencyController); /// The buffered geometry used to render the surface mesh. std::shared_ptr _surfaceBuffer; @@ -177,23 +153,14 @@ /// Indicates that the triangle mesh representation of the surface has recently been updated. bool _trimeshUpdate; -private: - Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Microstructure"); - - DECLARE_PROPERTY_FIELD(_surfaceColor); - DECLARE_PROPERTY_FIELD(_showCap); - DECLARE_PROPERTY_FIELD(_smoothShading); - DECLARE_PROPERTY_FIELD(_flipOrientation); - DECLARE_REFERENCE_FIELD(_surfaceTransparency); - DECLARE_REFERENCE_FIELD(_capTransparency); }; } // End of namespace } // End of namespace } // End of namespace -#endif // __OVITO_PARTITION_MESH_DISPLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMesh.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMesh.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMesh.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/partition_mesh/PartitionMesh.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,14 +19,14 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTITION_MESH_H -#define __OVITO_PARTITION_MESH_H +#pragma once + #include #include #include #include -#include +#include namespace Ovito { namespace Plugins { namespace CrystalAnalysis { @@ -68,12 +68,6 @@ /// Return false because this object cannot be edited. virtual bool isSubObjectEditable() const override { return false; } - /// Indicates whether the entire simulation cell is filled with one region that has no boundaries. - int spaceFillingRegion() const { return _spaceFillingRegion; } - - /// Specifies that the entire simulation cell filled with one region that has no boundaries. - void setSpaceFillingRegion(int regionId) { _spaceFillingRegion = regionId; } - /// Returns the planar cuts applied to this mesh. const QVector& cuttingPlanes() const { return _cuttingPlanes; } @@ -84,7 +78,7 @@ } /// Fairs a triangle mesh. - static void smoothMesh(PartitionMeshData& mesh, const SimulationCell& cell, int numIterations, FutureInterfaceBase* progress = nullptr, FloatType k_PB = 0.1f, FloatType lambda = 0.5f); + static bool smoothMesh(PartitionMeshData& mesh, const SimulationCell& cell, int numIterations, PromiseBase& promise, FloatType k_PB = FloatType(0.1), FloatType lambda = FloatType(0.5)); protected: @@ -97,19 +91,17 @@ private: /// Indicates that the entire simulation cell is part of one region without boundaries. - PropertyField _spaceFillingRegion; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, spaceFillingRegion, setSpaceFillingRegion); /// The planar cuts applied to this mesh. QVector _cuttingPlanes; Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_spaceFillingRegion); }; } // End of namespace } // End of namespace } // End of namespace -#endif // __OVITO_PARTITION_MESH_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/patterns/BurgersVectorFamily.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/patterns/BurgersVectorFamily.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/patterns/BurgersVectorFamily.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/patterns/BurgersVectorFamily.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,13 +26,14 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, BurgersVectorFamily, RefTarget); -DEFINE_PROPERTY_FIELD(BurgersVectorFamily, _name, "Name"); -DEFINE_PROPERTY_FIELD(BurgersVectorFamily, _color, "Color"); -DEFINE_PROPERTY_FIELD(BurgersVectorFamily, _burgersVector, "BurgersVector"); -SET_PROPERTY_FIELD_LABEL(BurgersVectorFamily, _name, "Name"); -SET_PROPERTY_FIELD_LABEL(BurgersVectorFamily, _color, "Color"); -SET_PROPERTY_FIELD_LABEL(BurgersVectorFamily, _burgersVector, "Burgers vector"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(BurgersVectorFamily, RefTarget); +DEFINE_PROPERTY_FIELD(BurgersVectorFamily, name, "Name"); +DEFINE_PROPERTY_FIELD(BurgersVectorFamily, color, "Color"); +DEFINE_PROPERTY_FIELD(BurgersVectorFamily, burgersVector, "BurgersVector"); +SET_PROPERTY_FIELD_LABEL(BurgersVectorFamily, name, "Name"); +SET_PROPERTY_FIELD_LABEL(BurgersVectorFamily, color, "Color"); +SET_PROPERTY_FIELD_LABEL(BurgersVectorFamily, burgersVector, "Burgers vector"); +SET_PROPERTY_FIELD_CHANGE_EVENT(BurgersVectorFamily, name, ReferenceEvent::TitleChanged); /****************************************************************************** * Constructs a new BurgersVectorFamily. @@ -40,9 +41,9 @@ BurgersVectorFamily::BurgersVectorFamily(DataSet* dataset, const QString& name, const Vector3& burgersVector, const Color& color) : RefTarget(dataset), _name(name), _burgersVector(burgersVector), _color(color) { - INIT_PROPERTY_FIELD(BurgersVectorFamily::_name); - INIT_PROPERTY_FIELD(BurgersVectorFamily::_color); - INIT_PROPERTY_FIELD(BurgersVectorFamily::_burgersVector); + INIT_PROPERTY_FIELD(name); + INIT_PROPERTY_FIELD(color); + INIT_PROPERTY_FIELD(burgersVector); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/patterns/BurgersVectorFamily.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/patterns/BurgersVectorFamily.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/patterns/BurgersVectorFamily.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/patterns/BurgersVectorFamily.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_BURGERS_VECTOR_FAMILY_H -#define __OVITO_CA_BURGERS_VECTOR_FAMILY_H +#pragma once + #include #include @@ -37,24 +37,6 @@ /// \brief Constructs a new BurgersVectorFamily. Q_INVOKABLE BurgersVectorFamily(DataSet* dataset, const QString& name = QString(), const Vector3& burgersVector = Vector3::Zero(), const Color& color = Color(0,0,0)); - /// Returns the family's display name. - const QString& name() const { return _name; } - - /// Sets the family's display name. - void setName(const QString& name) { _name = name; } - - /// Returns the color that is used to display dislocation of this family. - const Color& color() const { return _color; } - - /// Sets the color that is used to display dislocation of this family. - void setColor(const Color& color) { _color = color; } - - /// Returns the prototype Burgers vector of this family. - const Vector3& burgersVector() const { return _burgersVector; } - - /// Sets the prototype Burgers vector of this family. - void setBurgersVector(const Vector3& v) { _burgersVector = v; } - /// Checks if the given Burgers vector is a member of this family. bool isMember(const Vector3& v, StructurePattern* latticeStructure) const; @@ -66,29 +48,23 @@ Q_PROPERTY(QString name READ name WRITE setName); Q_PROPERTY(Color color READ color WRITE setColor); -protected: +private: /// The name of this atom type. - PropertyField _name; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, name, setName); /// This visualization color of this family. - PropertyField _color; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, color, setColor); /// This prototype Burgers vector of this family. - PropertyField _burgersVector; - -private: + DECLARE_MODIFIABLE_PROPERTY_FIELD(Vector3, burgersVector, setBurgersVector); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_name); - DECLARE_PROPERTY_FIELD(_color); - DECLARE_PROPERTY_FIELD(_burgersVector); }; } // End of namespace } // End of namespace } // End of namespace -#endif // __OVITO_CA_BURGERS_VECTOR_FAMILY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/patterns/PatternCatalog.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/patterns/PatternCatalog.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/patterns/PatternCatalog.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/patterns/PatternCatalog.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,16 +24,16 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, PatternCatalog, DataObject); -DEFINE_VECTOR_REFERENCE_FIELD(PatternCatalog, _patterns, "Patterns", StructurePattern); -SET_PROPERTY_FIELD_LABEL(PatternCatalog, _patterns, "Structure patterns"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(PatternCatalog, DataObject); +DEFINE_VECTOR_REFERENCE_FIELD(PatternCatalog, patterns, "Patterns", StructurePattern); +SET_PROPERTY_FIELD_LABEL(PatternCatalog, patterns, "Structure patterns"); /****************************************************************************** * Constructs the PatternCatalog object. ******************************************************************************/ PatternCatalog::PatternCatalog(DataSet* dataset) : DataObject(dataset) { - INIT_PROPERTY_FIELD(PatternCatalog::_patterns); + INIT_PROPERTY_FIELD(patterns); // Create the "undefined" structure. OORef undefinedAtomType(new StructurePattern(dataset)); diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/patterns/PatternCatalog.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/patterns/PatternCatalog.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/patterns/PatternCatalog.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/patterns/PatternCatalog.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_PATTERN_CATALOG_H -#define __OVITO_CA_PATTERN_CATALOG_H +#pragma once + #include #include @@ -38,9 +38,6 @@ /// \brief Constructor. Q_INVOKABLE PatternCatalog(DataSet* dataset); - /// Returns the list of structure patterns in this catalog. - const QVector& patterns() const { return _patterns; } - /// Adds a new patterns to the catalog. void addPattern(StructurePattern* pattern) { _patterns.push_back(pattern); } @@ -61,16 +58,14 @@ private: /// List of structure patterns. - VectorReferenceField _patterns; + DECLARE_MODIFIABLE_VECTOR_REFERENCE_FIELD(StructurePattern, patterns, setPatterns); Q_OBJECT OVITO_OBJECT - - DECLARE_VECTOR_REFERENCE_FIELD(_patterns); }; } // End of namespace } // End of namespace } // End of namespace -#endif // __OVITO_CA_PATTERN_CATALOG_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/patterns/StructurePattern.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/patterns/StructurePattern.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/patterns/StructurePattern.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/patterns/StructurePattern.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,15 +24,15 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, StructurePattern, ParticleType); -DEFINE_PROPERTY_FIELD(StructurePattern, _shortName, "ShortName"); -DEFINE_PROPERTY_FIELD(StructurePattern, _structureType, "StructureType"); -DEFINE_PROPERTY_FIELD(StructurePattern, _symmetryType, "SymmetryType"); -DEFINE_VECTOR_REFERENCE_FIELD(StructurePattern, _burgersVectorFamilies, "BurgersVectorFamilies", BurgersVectorFamily); -SET_PROPERTY_FIELD_LABEL(StructurePattern, _shortName, "Short name"); -SET_PROPERTY_FIELD_LABEL(StructurePattern, _structureType, "Structure type"); -SET_PROPERTY_FIELD_LABEL(StructurePattern, _symmetryType, "Symmetry type"); -SET_PROPERTY_FIELD_LABEL(StructurePattern, _burgersVectorFamilies, "Burgers vector families"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(StructurePattern, ParticleType); +DEFINE_PROPERTY_FIELD(StructurePattern, shortName, "ShortName"); +DEFINE_PROPERTY_FIELD(StructurePattern, structureType, "StructureType"); +DEFINE_PROPERTY_FIELD(StructurePattern, symmetryType, "SymmetryType"); +DEFINE_VECTOR_REFERENCE_FIELD(StructurePattern, burgersVectorFamilies, "BurgersVectorFamilies", BurgersVectorFamily); +SET_PROPERTY_FIELD_LABEL(StructurePattern, shortName, "Short name"); +SET_PROPERTY_FIELD_LABEL(StructurePattern, structureType, "Structure type"); +SET_PROPERTY_FIELD_LABEL(StructurePattern, symmetryType, "Symmetry type"); +SET_PROPERTY_FIELD_LABEL(StructurePattern, burgersVectorFamilies, "Burgers vector families"); /****************************************************************************** * Constructs the StructurePattern object. @@ -40,10 +40,10 @@ StructurePattern::StructurePattern(DataSet* dataset) : ParticleType(dataset), _structureType(OtherStructure), _symmetryType(OtherSymmetry) { - INIT_PROPERTY_FIELD(StructurePattern::_shortName); - INIT_PROPERTY_FIELD(StructurePattern::_structureType); - INIT_PROPERTY_FIELD(StructurePattern::_symmetryType); - INIT_PROPERTY_FIELD(StructurePattern::_burgersVectorFamilies); + INIT_PROPERTY_FIELD(shortName); + INIT_PROPERTY_FIELD(structureType); + INIT_PROPERTY_FIELD(symmetryType); + INIT_PROPERTY_FIELD(burgersVectorFamilies); // Create "unknown" Burgers vector family. BurgersVectorFamily* family = new BurgersVectorFamily(dataset); @@ -58,30 +58,77 @@ ******************************************************************************/ Color StructurePattern::getBurgersVectorColor(const QString& latticeName, const Vector3& b) { - static const Color predefinedLineColors[] = { - Color(0.4f,1.0f,0.4f), - Color(1.0f,0.2f,0.2f), - Color(0.4f,0.4f,1.0f), - Color(0.9f,0.5f,0.0f), - Color(1.0f,1.0f,0.0f), - Color(1.0f,0.4f,1.0f), - Color(0.7f,0.0f,1.0f), - Color(0.2f,1.0f,1.0f) - }; - if(latticeName == "bcc") { - static const Vector3 bccBurgersVectors[] = { - { 0.5, 0.5, 0.5 }, - { -0.5, 0.5, 0.5 }, - { 0.5, -0.5, 0.5 }, - { 0.5, 0.5, -0.5 }, - { 1.0, 0.0, 0.0 }, - { 0.0, 1.0, 0.0 }, - { 0.0, 0.0, 1.0 }, + static const Color predefinedLineColors[] = { + Color(0.4f,1.0f,0.4f), + Color(1.0f,0.2f,0.2f), + Color(0.4f,0.4f,1.0f), + Color(0.9f,0.5f,0.0f), + Color(1.0f,1.0f,0.0f), + Color(1.0f,0.4f,1.0f), + Color(0.7f,0.0f,1.0f) + }; + static const Vector3 burgersVectors[] = { + { FloatType(0.5), FloatType(0.5), FloatType(0.5) }, + { FloatType(-0.5), FloatType(0.5), FloatType(0.5) }, + { FloatType(0.5), FloatType(-0.5), FloatType(0.5) }, + { FloatType(0.5), FloatType(0.5), FloatType(-0.5) }, + { FloatType(1.0), FloatType(0.0), FloatType(0.0) }, + { FloatType(0.0), FloatType(1.0), FloatType(0.0) }, + { FloatType(0.0), FloatType(0.0), FloatType(1.0) } + }; + OVITO_STATIC_ASSERT(sizeof(burgersVectors)/sizeof(burgersVectors[0]) == sizeof(predefinedLineColors)/sizeof(predefinedLineColors[0])); + for(size_t i = 0; i < sizeof(burgersVectors)/sizeof(burgersVectors[0]); i++) { + if(b.equals(burgersVectors[i]) || b.equals(-burgersVectors[i])) + return predefinedLineColors[i]; + } + } + else if(latticeName == "fcc") { + static const Color predefinedLineColors[] = { + Color(0.4f,1.0f,0.4f), + Color(1.0f,0.2f,0.2f), + Color(0.4f,0.4f,1.0f), + Color(0.9f,0.5f,0.0f), + Color(1.0f,1.0f,0.0f), + Color(1.0f,0.4f,1.0f), + Color(0.7f,0.0f,1.0f), + Color(0.2f,1.0f,1.0f), + Color(0.2f,1.0f,0.2f), + Color(0.2f,0.0f,1.0f), + Color(0.0f,0.8f,0.2f), + Color(0.2f,0.0f,0.8f), + + Color(0.5f,0.5f,0.5f), + Color(0.5f,0.5f,0.5f), + Color(0.5f,0.5f,0.5f), + Color(0.5f,0.5f,0.5f), + Color(0.5f,0.5f,0.5f), + Color(0.5f,0.5f,0.5f), + }; + static const Vector3 burgersVectors[] = { + { FloatType(1.0/6.0), FloatType(-2.0/6.0), FloatType(-1.0/6.0) }, + { FloatType(1.0/6.0), FloatType(-2.0/6.0), FloatType(1.0/6.0) }, + { FloatType(1.0/6.0), FloatType(-1.0/6.0), FloatType(2.0/6.0) }, + { FloatType(1.0/6.0), FloatType(-1.0/6.0), FloatType(-2.0/6.0) }, + { FloatType(1.0/6.0), FloatType(1.0/6.0), FloatType(2.0/6.0) }, + { FloatType(1.0/6.0), FloatType(1.0/6.0), FloatType(-2.0/6.0) }, + { FloatType(1.0/6.0), FloatType(2.0/6.0), FloatType(1.0/6.0) }, + { FloatType(1.0/6.0), FloatType(2.0/6.0), FloatType(-1.0/6.0) }, + { FloatType(2.0/6.0), FloatType(-1.0/6.0), FloatType(-1.0/6.0) }, + { FloatType(2.0/6.0), FloatType(-1.0/6.0), FloatType(1.0/6.0) }, + { FloatType(2.0/6.0), FloatType(1.0/6.0), FloatType(-1.0/6.0) }, + { FloatType(2.0/6.0), FloatType(1.0/6.0), FloatType(1.0/6.0) }, + + { 0, FloatType(1.0/6.0), FloatType(1.0/6.0) }, + { 0, FloatType(1.0/6.0), FloatType(-1.0/6.0) }, + { FloatType(1.0/6.0), 0, FloatType(1.0/6.0) }, + { FloatType(1.0/6.0), 0, FloatType(-1.0/6.0) }, + { FloatType(1.0/6.0), FloatType(1.0/6.0), 0 }, + { FloatType(1.0/6.0), FloatType(-1.0/6.0), 0 }, }; - OVITO_ASSERT(sizeof(bccBurgersVectors)/sizeof(bccBurgersVectors[0]) < sizeof(predefinedLineColors)/sizeof(predefinedLineColors[0])); - for(size_t i = 0; i < sizeof(bccBurgersVectors)/sizeof(bccBurgersVectors[0]); i++) { - if(b.equals(bccBurgersVectors[i]) || b.equals(-bccBurgersVectors[i])) + OVITO_STATIC_ASSERT(sizeof(burgersVectors)/sizeof(burgersVectors[0]) == sizeof(predefinedLineColors)/sizeof(predefinedLineColors[0])); + for(size_t i = 0; i < sizeof(burgersVectors)/sizeof(burgersVectors[0]); i++) { + if(b.equals(burgersVectors[i]) || b.equals(-burgersVectors[i])) return predefinedLineColors[i]; } } diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/patterns/StructurePattern.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/patterns/StructurePattern.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/patterns/StructurePattern.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/patterns/StructurePattern.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CA_STRUCTURE_PATTERN_H -#define __OVITO_CA_STRUCTURE_PATTERN_H +#pragma once + #include #include @@ -63,15 +63,6 @@ /// Assigns a long name to this pattern. void setLongName(const QString& name) { setName(name); } - /// Returns the short name of this pattern. - const QString& shortName() const { return _shortName; } - - /// Sets the short name to this pattern. - void setShortName(const QString& name) { _shortName = name; } - - /// Returns the list of Burgers vector families defined for this lattice pattern. - const QVector& burgersVectorFamilies() const { return _burgersVectorFamilies; } - /// Adds a new family to this lattice pattern's list of Burgers vector families. void addBurgersVectorFamily(BurgersVectorFamily* family) { _burgersVectorFamilies.push_back(family); } @@ -82,42 +73,25 @@ /// don't belong to any family. BurgersVectorFamily* defaultBurgersVectorFamily() const { return _burgersVectorFamilies.front(); } - /// Returns the type of structure described by this pattern. - StructureType structureType() const { return _structureType; } - - /// Sets the type of structure described by this pattern. - void setStructureType(StructureType type) { _structureType = type; } - - /// Returns the symmetry type of lattice structure described by this pattern. - SymmetryType symmetryType() const { return _symmetryType; } - - /// Sets the symmetry type of lattice structure described by this pattern. - void setSymmetryType(SymmetryType type) { _symmetryType = type; } - /// Returns the display color to be used for a given Burgers vector. static Color getBurgersVectorColor(const QString& latticeName, const Vector3& b); private: /// The short name of this pattern. - PropertyField _shortName; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, shortName, setShortName); /// The type of structure described by this pattern. - PropertyField _structureType; + DECLARE_MODIFIABLE_PROPERTY_FIELD(StructureType, structureType, setStructureType); /// The type of crystal symmetry of the lattice. - PropertyField _symmetryType; + DECLARE_MODIFIABLE_PROPERTY_FIELD(SymmetryType, symmetryType, setSymmetryType); /// List of Burgers vector families. - VectorReferenceField _burgersVectorFamilies; + DECLARE_MODIFIABLE_VECTOR_REFERENCE_FIELD(BurgersVectorFamily, burgersVectorFamilies, setBurgersVectorFamilies); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_shortName); - DECLARE_PROPERTY_FIELD(_structureType); - DECLARE_PROPERTY_FIELD(_symmetryType); - DECLARE_VECTOR_REFERENCE_FIELD(_burgersVectorFamilies); }; } // End of namespace @@ -129,4 +103,4 @@ Q_DECLARE_METATYPE(Ovito::Plugins::CrystalAnalysis::StructurePattern::SymmetryType); Q_DECLARE_TYPEINFO(Ovito::Plugins::CrystalAnalysis::StructurePattern::SymmetryType, Q_PRIMITIVE_TYPE); -#endif // __OVITO_CA_STRUCTURE_PATTERN_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/slip_surface/SlipSurface.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/slip_surface/SlipSurface.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/slip_surface/SlipSurface.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/slip_surface/SlipSurface.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,7 +25,7 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, SlipSurface, DataObject); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SlipSurface, DataObject); /****************************************************************************** * Constructor. @@ -51,7 +51,7 @@ /****************************************************************************** * Fairs a closed triangle mesh. ******************************************************************************/ -void SlipSurface::smoothMesh(SlipSurfaceData& mesh, const SimulationCell& cell, int numIterations, FutureInterfaceBase* progress, FloatType k_PB, FloatType lambda) +bool SlipSurface::smoothMesh(SlipSurfaceData& mesh, const SimulationCell& cell, int numIterations, PromiseBase& promise, FloatType k_PB, FloatType lambda) { // This is the implementation of the mesh smoothing algorithm: // @@ -59,15 +59,17 @@ // A Signal Processing Approach To Fair Surface Design // In SIGGRAPH 95 Conference Proceedings, pages 351-358 (1995) - FloatType mu = 1.0f / (k_PB - 1.0f/lambda); - if(progress) progress->setProgressRange(numIterations); + FloatType mu = FloatType(1) / (k_PB - FloatType(1)/lambda); + promise.setProgressMaximum(numIterations); for(int iteration = 0; iteration < numIterations; iteration++) { + if(!promise.setProgressValue(iteration)) + return false; smoothMeshIteration(mesh, lambda, cell); smoothMeshIteration(mesh, mu, cell); - if(progress && !progress->setProgressValue(iteration+1)) - return; } + + return !promise.isCanceled(); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/slip_surface/SlipSurfaceDisplay.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/slip_surface/SlipSurfaceDisplay.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/slip_surface/SlipSurfaceDisplay.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/slip_surface/SlipSurfaceDisplay.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,12 +30,12 @@ namespace Ovito { namespace Plugins { namespace CrystalAnalysis { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CrystalAnalysis, SlipSurfaceDisplay, AsynchronousDisplayObject); -DEFINE_PROPERTY_FIELD(SlipSurfaceDisplay, _smoothShading, "SmoothShading"); -DEFINE_REFERENCE_FIELD(SlipSurfaceDisplay, _surfaceTransparency, "SurfaceTransparency", Controller); -SET_PROPERTY_FIELD_LABEL(SlipSurfaceDisplay, _smoothShading, "Smooth shading"); -SET_PROPERTY_FIELD_LABEL(SlipSurfaceDisplay, _surfaceTransparency, "Surface transparency"); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(SlipSurfaceDisplay, _surfaceTransparency, PercentParameterUnit, 0, 1); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SlipSurfaceDisplay, AsynchronousDisplayObject); +DEFINE_PROPERTY_FIELD(SlipSurfaceDisplay, smoothShading, "SmoothShading"); +DEFINE_REFERENCE_FIELD(SlipSurfaceDisplay, surfaceTransparencyController, "SurfaceTransparency", Controller); +SET_PROPERTY_FIELD_LABEL(SlipSurfaceDisplay, smoothShading, "Smooth shading"); +SET_PROPERTY_FIELD_LABEL(SlipSurfaceDisplay, surfaceTransparencyController, "Surface transparency"); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(SlipSurfaceDisplay, surfaceTransparencyController, PercentParameterUnit, 0, 1); /****************************************************************************** * Constructor. @@ -43,10 +43,10 @@ SlipSurfaceDisplay::SlipSurfaceDisplay(DataSet* dataset) : AsynchronousDisplayObject(dataset), _smoothShading(true), _trimeshUpdate(true) { - INIT_PROPERTY_FIELD(SlipSurfaceDisplay::_smoothShading); - INIT_PROPERTY_FIELD(SlipSurfaceDisplay::_surfaceTransparency); + INIT_PROPERTY_FIELD(smoothShading); + INIT_PROPERTY_FIELD(surfaceTransparencyController); - _surfaceTransparency = ControllerManager::instance().createFloatController(dataset); + setSurfaceTransparencyController(ControllerManager::createFloatController(dataset)); } /****************************************************************************** @@ -114,7 +114,7 @@ { setProgressText(tr("Preparing slip surface for display")); - if(!buildMesh(*_inputMesh, _simCell, _cuttingPlanes, _structureNames, _surfaceMesh, _materialColors, this)) + if(!buildMesh(*_inputMesh, _simCell, _cuttingPlanes, _structureNames, _surfaceMesh, _materialColors, *this)) throw Exception(tr("Failed to generate non-periodic version of slip surface for display. Simulation cell might be too small.")); if(isCanceled()) @@ -157,7 +157,7 @@ // Get the rendering colors for the surface. FloatType surface_alpha = 1; TimeInterval iv; - if(_surfaceTransparency) surface_alpha = FloatType(1) - _surfaceTransparency->getFloatValue(time, iv); + if(surfaceTransparencyController()) surface_alpha = FloatType(1) - surfaceTransparencyController()->getFloatValue(time, iv); ColorA color_surface(1, 1, 1, surface_alpha); // Do we have to re-create the render primitives from scratch? @@ -175,7 +175,7 @@ if(updateContents) { // Assign smoothing group to faces to interpolate normals. - const quint32 smoothingGroup = _smoothShading ? 1 : 0; + const quint32 smoothingGroup = smoothShading() ? 1 : 0; for(auto& face : _surfaceMesh.faces()) { face.setSmoothingGroups(smoothingGroup); } @@ -199,11 +199,11 @@ /****************************************************************************** * Generates the final triangle mesh, which will be rendered. ******************************************************************************/ -bool SlipSurfaceDisplay::buildMesh(const SlipSurfaceData& input, const SimulationCell& cell, const QVector& cuttingPlanes, const QStringList& structureNames, TriMesh& output, std::vector& materialColors, FutureInterfaceBase* progress) +bool SlipSurfaceDisplay::buildMesh(const SlipSurfaceData& input, const SimulationCell& cell, const QVector& cuttingPlanes, const QStringList& structureNames, TriMesh& output, std::vector& materialColors, PromiseBase& promise) { // Convert half-edge mesh to triangle mesh. input.convertToTriMesh(output); - + // Color faces according to slip vector. auto fout = output.faces().begin(); for(SlipSurfaceData::Face* face : input.faces()) { @@ -227,7 +227,7 @@ OVITO_ASSERT(fout == output.faces().end()); // Check for early abortion. - if(progress && progress->isCanceled()) + if(promise.isCanceled()) return false; // Convert vertex positions to reduced coordinates. @@ -240,7 +240,7 @@ for(size_t dim = 0; dim < 3; dim++) { if(cell.pbcFlags()[dim] == false) continue; - if(progress && progress->isCanceled()) + if(promise.isCanceled()) return false; // Make sure all vertices are located inside the periodic box. @@ -266,7 +266,7 @@ } // Check for early abortion. - if(progress && progress->isCanceled()) + if(promise.isCanceled()) return false; // Convert vertex positions back from reduced coordinates to absolute coordinates. @@ -276,7 +276,7 @@ // Clip mesh at cutting planes. for(const Plane3& plane : cuttingPlanes) { - if(progress && progress->isCanceled()) + if(promise.isCanceled()) return false; output.clipAtPlane(plane); @@ -285,7 +285,7 @@ output.invalidateVertices(); output.invalidateFaces(); - return true; + return !promise.isCanceled(); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/slip_surface/SlipSurfaceDisplay.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/slip_surface/SlipSurfaceDisplay.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/slip_surface/SlipSurfaceDisplay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/slip_surface/SlipSurfaceDisplay.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SLIP_SURFACE_DISPLAY_H -#define __OVITO_SLIP_SURFACE_DISPLAY_H +#pragma once + #include #include @@ -50,20 +50,14 @@ /// \brief Computes the bounding box of the object. virtual Box3 boundingBox(TimePoint time, DataObject* dataObject, ObjectNode* contextNode, const PipelineFlowState& flowState) override; - /// Returns whether the mesh is rendered using smooth shading. - bool smoothShading() const { return _smoothShading; } - - /// Sets whether the mesh is rendered using smooth shading. - void setSmoothShading(bool smoothShading) { _smoothShading = smoothShading; } - /// Returns the transparency of the surface mesh. - FloatType surfaceTransparency() const { return _surfaceTransparency ? _surfaceTransparency->currentFloatValue() : 0.0f; } + FloatType surfaceTransparency() const { return surfaceTransparencyController() ? surfaceTransparencyController()->currentFloatValue() : 0.0f; } /// Sets the transparency of the surface mesh. - void setSurfaceTransparency(FloatType transparency) { if(_surfaceTransparency) _surfaceTransparency->setCurrentFloatValue(transparency); } + void setSurfaceTransparency(FloatType transparency) { if(surfaceTransparencyController()) surfaceTransparencyController()->setCurrentFloatValue(transparency); } /// Generates the final triangle mesh, which will be rendered. - static bool buildMesh(const SlipSurfaceData& input, const SimulationCell& cell, const QVector& cuttingPlanes, const QStringList& structureNames, TriMesh& output, std::vector& materialColors, FutureInterfaceBase* progress = nullptr); + static bool buildMesh(const SlipSurfaceData& input, const SimulationCell& cell, const QVector& cuttingPlanes, const QStringList& structureNames, TriMesh& output, std::vector& materialColors, PromiseBase& promise); protected: @@ -107,10 +101,10 @@ static bool splitFace(TriMesh& output, int faceIndex, int oldVertexCount, std::vector& newVertices, std::map,std::pair>& newVertexLookupMap, const SimulationCell& cell, size_t dim); /// Controls whether the mesh is rendered using smooth shading. - PropertyField _smoothShading; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, smoothShading, setSmoothShading); /// Controls the transparency of the surface mesh. - ReferenceField _surfaceTransparency; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, surfaceTransparencyController, setSurfaceTransparencyController); /// The buffered geometry used to render the surface mesh. std::shared_ptr _surfaceBuffer; @@ -138,19 +132,14 @@ /// Indicates that the triangle mesh representation of the surface has recently been updated. bool _trimeshUpdate; -private: - Q_OBJECT OVITO_OBJECT - Q_CLASSINFO("DisplayName", "Slip surface"); - - DECLARE_PROPERTY_FIELD(_smoothShading); - DECLARE_REFERENCE_FIELD(_surfaceTransparency); + Q_CLASSINFO("DisplayName", "Slip surfaces"); }; } // End of namespace } // End of namespace } // End of namespace -#endif // __OVITO_SLIP_SURFACE_DISPLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/slip_surface/SlipSurface.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/slip_surface/SlipSurface.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/objects/slip_surface/SlipSurface.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/objects/slip_surface/SlipSurface.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,14 +19,14 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SLIP_SURFACE_H -#define __OVITO_SLIP_SURFACE_H +#pragma once + #include #include #include #include -#include +#include #include namespace Ovito { namespace Plugins { namespace CrystalAnalysis { @@ -81,13 +81,15 @@ } /// Fairs the mesh stored in this object. - void smoothMesh(const SimulationCell& cell, int numIterations, FutureInterfaceBase* progress = nullptr, FloatType k_PB = 0.1f, FloatType lambda = 0.5f) { - smoothMesh(*modifiableStorage(), cell, numIterations, progress, k_PB, lambda); + bool smoothMesh(const SimulationCell& cell, int numIterations, PromiseBase& promise, FloatType k_PB = FloatType(0.1), FloatType lambda = FloatType(0.5)) { + if(!smoothMesh(*modifiableStorage(), cell, numIterations, promise, k_PB, lambda)) + return false; changed(); + return true; } /// Fairs a mesh. - static void smoothMesh(SlipSurfaceData& mesh, const SimulationCell& cell, int numIterations, FutureInterfaceBase* progress = nullptr, FloatType k_PB = 0.1f, FloatType lambda = 0.5f); + static bool smoothMesh(SlipSurfaceData& mesh, const SimulationCell& cell, int numIterations, PromiseBase& promise, FloatType k_PB = FloatType(0.1), FloatType lambda = FloatType(0.5)); protected: @@ -110,4 +112,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SLIP_SURFACE_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/resources/python/ovito/data/crystalanalysis/__init__.py ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/resources/python/ovito/data/crystalanalysis/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/resources/python/ovito/data/crystalanalysis/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/resources/python/ovito/data/crystalanalysis/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -6,15 +6,14 @@ import numpy # Load the native code modules -import Particles -import ParticlesImporter -import ParticlesExporter -import CrystalAnalysis +import ovito.plugins.Particles +import ovito.plugins.CrystalAnalysis # Inject selected classes into parent module. -ovito.data.DislocationNetwork = CrystalAnalysis.DislocationNetwork -ovito.data.DislocationSegment = CrystalAnalysis.DislocationSegment -ovito.data.PartitionMesh = CrystalAnalysis.PartitionMesh +ovito.data.DislocationNetwork = ovito.plugins.CrystalAnalysis.DislocationNetwork +ovito.data.DislocationSegment = ovito.plugins.CrystalAnalysis.DislocationSegment +ovito.data.PartitionMesh = ovito.plugins.CrystalAnalysis.PartitionMesh +ovito.data.__all__ += ['DislocationNetwork', 'DislocationSegment', 'PartitionMesh'] # Implement 'dislocations' attribute of DataCollection class. def _DataCollection_dislocations(self): diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/resources/python/ovito/io/crystalanalysis/__init__.py ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/resources/python/ovito/io/crystalanalysis/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/resources/python/ovito/io/crystalanalysis/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/resources/python/ovito/io/crystalanalysis/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -3,7 +3,8 @@ import ovito.io.particles # Load the native code modules -import CrystalAnalysis +import ovito.plugins.Particles.Importers +import ovito.plugins.CrystalAnalysis # Register export formats. -ovito.io.export_file._formatTable["ca"] = CrystalAnalysis.CAExporter +ovito.io.export_file._formatTable["ca"] = ovito.plugins.CrystalAnalysis.CAExporter diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/resources/python/ovito/modifiers/crystalanalysis/__init__.py ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/resources/python/ovito/modifiers/crystalanalysis/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/resources/python/ovito/modifiers/crystalanalysis/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/resources/python/ovito/modifiers/crystalanalysis/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -3,18 +3,19 @@ import ovito.modifiers.particles # Load the native code modules. -import Particles -import ParticlesImporter -import ParticlesExporter -import CrystalAnalysis +import ovito.plugins.Particles +import ovito.plugins.CrystalAnalysis # Inject modifier classes into parent module. -ovito.modifiers.ConstructSurfaceModifier = CrystalAnalysis.ConstructSurfaceModifier -ovito.modifiers.SmoothDislocationsModifier = CrystalAnalysis.SmoothDislocationsModifier -ovito.modifiers.SmoothSurfaceModifier = CrystalAnalysis.SmoothSurfaceModifier -ovito.modifiers.DislocationAnalysisModifier = CrystalAnalysis.DislocationAnalysisModifier -ovito.modifiers.ElasticStrainModifier = CrystalAnalysis.ElasticStrainModifier -#ovito.modifiers.GrainSegmentationModifier = CrystalAnalysis.GrainSegmentationModifier +ovito.modifiers.ConstructSurfaceModifier = ovito.plugins.CrystalAnalysis.ConstructSurfaceModifier +ovito.modifiers.SmoothDislocationsModifier = ovito.plugins.CrystalAnalysis.SmoothDislocationsModifier +ovito.modifiers.SmoothSurfaceModifier = ovito.plugins.CrystalAnalysis.SmoothSurfaceModifier +ovito.modifiers.DislocationAnalysisModifier = ovito.plugins.CrystalAnalysis.DislocationAnalysisModifier +ovito.modifiers.ElasticStrainModifier = ovito.plugins.CrystalAnalysis.ElasticStrainModifier +#ovito.modifiers.GrainSegmentationModifier = ovito.plugins.CrystalAnalysis.GrainSegmentationModifier +ovito.modifiers.__all__ += ['ConstructSurfaceModifier', 'SmoothDislocationsModifier', 'SmoothSurfaceModifier', 'DislocationAnalysisModifier', + 'ElasticStrainModifier'] +#ovito.modifiers.__all__ += ['GrainSegmentationModifier'] # Copy enum list. ovito.modifiers.ElasticStrainModifier.Lattice = ovito.modifiers.DislocationAnalysisModifier.Lattice diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/resources/python/ovito/vis/crystalanalysis/__init__.py ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/resources/python/ovito/vis/crystalanalysis/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/resources/python/ovito/vis/crystalanalysis/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/resources/python/ovito/vis/crystalanalysis/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -2,14 +2,13 @@ import ovito.vis # Load the native code modules. -import Particles -import ParticlesImporter -import ParticlesExporter -import CrystalAnalysis +import ovito.plugins.Particles +import ovito.plugins.CrystalAnalysis # Inject selected classes into parent module. -ovito.vis.DislocationDisplay = CrystalAnalysis.DislocationDisplay -ovito.vis.PartitionMeshDisplay = CrystalAnalysis.PartitionMeshDisplay +ovito.vis.DislocationDisplay = ovito.plugins.CrystalAnalysis.DislocationDisplay +ovito.vis.PartitionMeshDisplay = ovito.plugins.CrystalAnalysis.PartitionMeshDisplay +ovito.vis.__all__ += ['DislocationDisplay', 'PartitionMeshDisplay'] # Inject enum types. -ovito.vis.DislocationDisplay.Shading = ovito.vis.ArrowShadingMode \ No newline at end of file +ovito.vis.DislocationDisplay.Shading = ovito.vis.ArrowShadingMode diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/scripting/PythonInterface.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/scripting/PythonInterface.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/scripting/PythonInterface.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/scripting/PythonInterface.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -39,6 +39,7 @@ #include #include #include +#include namespace Ovito { namespace Plugins { namespace CrystalAnalysis { @@ -46,6 +47,9 @@ PYBIND11_PLUGIN(CrystalAnalysis) { + // Register the classes of this plugin with the global PluginManager. + PluginManager::instance().registerLoadedPluginClasses(); + py::options options; options.disable_function_signatures(); @@ -74,7 +78,8 @@ " The volume of the solid region bounded by the surface mesh.\n" "\n\n" "Example:\n\n" - ".. literalinclude:: ../example_snippets/construct_surface_modifier.py" + ".. literalinclude:: ../example_snippets/construct_surface_modifier.py\n" + " :lines: 4-\n" ) .def_property("radius", &ConstructSurfaceModifier::probeSphereRadius, &ConstructSurfaceModifier::setProbeSphereRadius, "The radius of the probe sphere used in the surface construction algorithm." @@ -142,7 +147,8 @@ " The number of particles with local hexagonal diamond structure.\n" "\n\n" "Example:\n\n" - ".. literalinclude:: ../example_snippets/dislocation_analysis_modifier.py" + ".. literalinclude:: ../example_snippets/dislocation_analysis_modifier.py\n" + " :lines: 4-\n" ) .def_property("trial_circuit_length", &DislocationAnalysisModifier::maxTrialCircuitSize, &DislocationAnalysisModifier::setMaxTrialCircuitSize, "The maximum length of trial Burgers circuits constructed by the DXA to discover dislocations. " @@ -197,6 +203,7 @@ "large Burgers circuits are needed to identify dissociated dislocations with a wide core. " "\n\n" ":Default: False\n") + .def_property("output_interface_mesh", &DislocationAnalysisModifier::outputInterfaceMesh, &DislocationAnalysisModifier::setOutputInterfaceMesh) ; py::enum_(DislocationAnalysisModifier_py, "Lattice") @@ -269,12 +276,12 @@ ; #if 0 - ovito_class() - .add_property("input_crystal_structure", &GrainSegmentationModifier::inputCrystalStructure, &GrainSegmentationModifier::setInputCrystalStructure) - .add_property("misorientation_threshold", &GrainSegmentationModifier::misorientationThreshold, &GrainSegmentationModifier::setMisorientationThreshold) - .add_property("fluctuation_tolerance", &GrainSegmentationModifier::fluctuationTolerance, &GrainSegmentationModifier::setFluctuationTolerance) - .add_property("min_atom_count", &GrainSegmentationModifier::minGrainAtomCount, &GrainSegmentationModifier::setMinGrainAtomCount) - .add_property("probe_sphere_radius", &GrainSegmentationModifier::probeSphereRadius, &GrainSegmentationModifier::setProbeSphereRadius, + ovito_class(m) + .def_property("input_crystal_structure", &GrainSegmentationModifier::inputCrystalStructure, &GrainSegmentationModifier::setInputCrystalStructure) + .def_property("misorientation_threshold", &GrainSegmentationModifier::misorientationThreshold, &GrainSegmentationModifier::setMisorientationThreshold) + .def_property("fluctuation_tolerance", &GrainSegmentationModifier::fluctuationTolerance, &GrainSegmentationModifier::setFluctuationTolerance) + .def_property("min_atom_count", &GrainSegmentationModifier::minGrainAtomCount, &GrainSegmentationModifier::setMinGrainAtomCount) + .def_property("probe_sphere_radius", &GrainSegmentationModifier::probeSphereRadius, &GrainSegmentationModifier::setProbeSphereRadius, "The radius of the probe sphere used in the free surface construction algorithm." "\n\n" "A rule of thumb is that the probe sphere radius should be slightly larger than the typical distance between " @@ -283,17 +290,17 @@ "This parameter is ignored if :py:attr:`.output_mesh` is false." "\n\n" ":Default: 4.0\n") - .add_property("smoothing_level", &GrainSegmentationModifier::smoothingLevel, &GrainSegmentationModifier::setSmoothingLevel, + .def_property("smoothing_level", &GrainSegmentationModifier::smoothingLevel, &GrainSegmentationModifier::setSmoothingLevel, "The number of iterations of the smoothing algorithm applied to the computed grain boundary mesh. " "\n\n" "This parameter is ignored if :py:attr:`.output_mesh` is false." "\n\n" ":Default: 8\n") - .add_property("only_selected", &GrainSegmentationModifier::onlySelectedParticles, &GrainSegmentationModifier::setOnlySelectedParticles, + .def_property("only_selected", &GrainSegmentationModifier::onlySelectedParticles, &GrainSegmentationModifier::setOnlySelectedParticles, "This flag tells the modifier to ignore unselected particles." "\n\n" ":Default: ``False``\n") - .add_property("output_mesh", &GrainSegmentationModifier::outputPartitionMesh, &GrainSegmentationModifier::setOutputPartitionMesh, + .def_property("output_mesh", &GrainSegmentationModifier::outputPartitionMesh, &GrainSegmentationModifier::setOutputPartitionMesh, "This flag controls the generation of the grain boundary mesh. " "If true, the modifier will generate a geometric representation of the grain boundary network " "in addition to assigning each input atom to a grain. " @@ -377,7 +384,8 @@ "the :py:attr:`~DataObject.display` attribute of the :py:class:`~DataObject` base class." "\n\n" "Example:\n\n" - ".. literalinclude:: ../example_snippets/dislocation_analysis_modifier.py", + ".. literalinclude:: ../example_snippets/dislocation_analysis_modifier.py\n" + " :lines: 4-\n", // Python class name: "DislocationNetwork") diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/util/DelaunayTessellation.cpp ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/util/DelaunayTessellation.cpp --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/util/DelaunayTessellation.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/util/DelaunayTessellation.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -34,9 +34,9 @@ /****************************************************************************** * Generates the tessellation. ******************************************************************************/ -bool DelaunayTessellation::generateTessellation(const SimulationCell& simCell, const Point3* positions, size_t numPoints, FloatType ghostLayerSize, const int* selectedPoints, FutureInterfaceBase* progress) +bool DelaunayTessellation::generateTessellation(const SimulationCell& simCell, const Point3* positions, size_t numPoints, FloatType ghostLayerSize, const int* selectedPoints, PromiseBase& promise) { - if(progress) progress->setProgressRange(0); + promise.setProgressMaximum(0); const double epsilon = 2e-5; @@ -74,7 +74,7 @@ _pointData.push_back((double)wp.z() + displacement(rng)); _particleIndices.push_back((int)i); - if(progress && progress->isCanceled()) + if(promise.isCanceled()) return false; } _primaryVertexCount = _particleIndices.size(); @@ -108,7 +108,7 @@ Vector3 shift = simCell.reducedToAbsolute(Vector3(ix,iy,iz)); Vector_3 shiftd = (Vector_3)shift; for(size_t vertexIndex = 0; vertexIndex < _primaryVertexCount; vertexIndex++) { - if(progress && progress->isCanceled()) + if(promise.isCanceled()) return false; double x = _pointData[vertexIndex*3+0] + shiftd.x(); @@ -148,12 +148,9 @@ _dt->set_reorder(true); // Construct Delaunay tessellation. - bool result = _dt->set_vertices(_pointData.size()/3, _pointData.data(), [progress](int value, int maxProgress) { - if(progress) { - if(maxProgress != progress->progressMaximum()) progress->setProgressRange(maxProgress); - return progress->setProgressValueIntermittent(value); - } - else return true; + bool result = _dt->set_vertices(_pointData.size()/3, _pointData.data(), [&promise](int value, int maxProgress) { + if(maxProgress != promise.progressMaximum()) promise.setProgressMaximum(maxProgress); + return promise.setProgressValueIntermittent(value); }); if(!result) return false; @@ -244,6 +241,6 @@ return (num_x*num_x + num_y*num_y + num_z*num_z) / (4 * den * den) < alpha; } -} // End of namespace -} // End of namespace +} // End of namespace +} // End of namespace } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/util/DelaunayTessellation.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/util/DelaunayTessellation.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/util/DelaunayTessellation.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/util/DelaunayTessellation.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,13 +19,13 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DELAUNAY_TESSELLATION_H -#define __OVITO_DELAUNAY_TESSELLATION_H +#pragma once + #include #include #include -#include +#include #include @@ -115,7 +115,7 @@ }; /// Generates the Delaunay tessellation. - bool generateTessellation(const SimulationCell& simCell, const Point3* positions, size_t numPoints, FloatType ghostLayerSize, const int* selectedPoints = nullptr, FutureInterfaceBase* progress = nullptr); + bool generateTessellation(const SimulationCell& simCell, const Point3* positions, size_t numPoints, FloatType ghostLayerSize, const int* selectedPoints, PromiseBase& promise); /// Returns the total number of tetrahedra in the tessellation. size_type numberOfTetrahedra() const { return _dt->nb_cells(); } @@ -234,4 +234,4 @@ } // End of namespace -#endif // __OVITO_DELAUNAY_TESSELLATION_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/util/ManifoldConstructionHelper.h ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/util/ManifoldConstructionHelper.h --- ovito-2.8.1+dfsg2/src/plugins/crystalanalysis/util/ManifoldConstructionHelper.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/crystalanalysis/util/ManifoldConstructionHelper.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,13 +19,13 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_MANIFOLD_CONSTRUCTION_HELPER_H -#define __OVITO_MANIFOLD_CONSTRUCTION_HELPER_H +#pragma once + #include #include #include -#include +#include #include #include @@ -62,32 +62,32 @@ /// This is the main function, which constructs the manifold triangle mesh. template - bool construct(CellRegionFunc&& determineCellRegion, FutureInterfaceBase* progress, + bool construct(CellRegionFunc&& determineCellRegion, PromiseBase& promise, PrepareMeshFaceFunc&& prepareMeshFaceFunc = PrepareMeshFaceFunc(), LinkManifoldsFunc&& linkManifoldsFunc = LinkManifoldsFunc()) { // Algorithm is divided into several sub-steps. // Assign weights to sub-steps according to estimated runtime. - if(progress) progress->beginProgressSubSteps({ 1, 1, 1 }); + promise.beginProgressSubSteps({ 1, 1, 1 }); /// Assign tetrahedra to regions. - if(!classifyTetrahedra(std::move(determineCellRegion), progress)) + if(!classifyTetrahedra(std::move(determineCellRegion), promise)) return false; - if(progress) progress->nextProgressSubStep(); + promise.nextProgressSubStep(); // Create triangle facets at interfaces between two different regions. - if(!createInterfaceFacets(std::move(prepareMeshFaceFunc), progress)) + if(!createInterfaceFacets(std::move(prepareMeshFaceFunc), promise)) return false; - if(progress) progress->nextProgressSubStep(); + promise.nextProgressSubStep(); // Connect triangles with one another to form a closed manifold. - if(!linkHalfedges(std::move(linkManifoldsFunc), progress)) + if(!linkHalfedges(std::move(linkManifoldsFunc), promise)) return false; - if(progress) progress->endProgressSubSteps(); + promise.endProgressSubSteps(); - return true; + return !promise.isCanceled(); } /// Returns the region to which all tetrahedra belong (or -1 if they belong to multiple regions). @@ -97,10 +97,10 @@ /// Assigns each tetrahedron to a region. template - bool classifyTetrahedra(CellRegionFunc&& determineCellRegion, FutureInterfaceBase* progress) + bool classifyTetrahedra(CellRegionFunc&& determineCellRegion, PromiseBase& promise) { - if(progress) - progress->setProgressRange(_tessellation.numberOfTetrahedra()); + promise.setProgressValue(0); + promise.setProgressMaximum(_tessellation.numberOfTetrahedra()); _numSolidCells = 0; _spaceFillingRegion = -2; @@ -108,7 +108,7 @@ for(DelaunayTessellation::CellIterator cell = _tessellation.begin_cells(); cell != _tessellation.end_cells(); ++cell) { // Update progress indicator. - if(progress && !progress->setProgressValueIntermittent(progressCounter++)) + if(!promise.setProgressValueIntermittent(progressCounter++)) return false; // Alpha shape criterion: This determines whether the Delaunay tetrahedron is part of the solid region. @@ -135,20 +135,20 @@ } if(_spaceFillingRegion == -2) _spaceFillingRegion = 0; - return true; + return !promise.isCanceled(); } /// Constructs the triangle facets that separate different regions in the tetrahedral mesh. template - bool createInterfaceFacets(PrepareMeshFaceFunc&& prepareMeshFaceFunc, FutureInterfaceBase* progress) + bool createInterfaceFacets(PrepareMeshFaceFunc&& prepareMeshFaceFunc, PromiseBase& promise) { // Stores the triangle mesh vertices created for the vertices of the tetrahedral mesh. std::vector vertexMap(_positions->size(), nullptr); _tetrahedraFaceList.clear(); _faceLookupMap.clear(); - if(progress) - progress->setProgressRange(_numSolidCells); + promise.setProgressValue(0); + promise.setProgressMaximum(_numSolidCells); for(DelaunayTessellation::CellIterator cell = _tessellation.begin_cells(); cell != _tessellation.end_cells(); ++cell) { @@ -158,7 +158,7 @@ OVITO_ASSERT(solidRegion != 0); // Update progress indicator. - if(progress && !progress->setProgressValueIntermittent(_tessellation.getCellIndex(cell))) + if(!promise.setProgressValueIntermittent(_tessellation.getCellIndex(cell))) return false; Point3 unwrappedVerts[4]; @@ -240,7 +240,7 @@ } } - return true; + return !promise.isCanceled(); } typename HalfEdgeStructureType::Face* findAdjacentFace(DelaunayTessellation::CellHandle cell, int f, int e) @@ -282,9 +282,10 @@ } template - bool linkHalfedges(LinkManifoldsFunc&& linkManifoldsFunc, FutureInterfaceBase* progress) + bool linkHalfedges(LinkManifoldsFunc&& linkManifoldsFunc, PromiseBase& promise) { - if(progress) progress->setProgressRange(_tetrahedraFaceList.size()); + promise.setProgressValue(0); + promise.setProgressMaximum(_tetrahedraFaceList.size()); auto tet = _tetrahedraFaceList.cbegin(); for(DelaunayTessellation::CellIterator cell = _tessellation.begin_cells(); cell != _tessellation.end_cells(); ++cell) { @@ -293,7 +294,7 @@ if(_tessellation.getCellIndex(cell) == -1) continue; // Update progress indicator. - if(progress && !progress->setProgressValueIntermittent(_tessellation.getCellIndex(cell))) + if(!promise.setProgressValueIntermittent(_tessellation.getCellIndex(cell))) return false; for(int f = 0; f < 4; f++) { @@ -353,7 +354,7 @@ } OVITO_ASSERT(tet == _tetrahedraFaceList.cend()); OVITO_ASSERT(_mesh.isClosed()); - return true; + return !promise.isCanceled(); } typename HalfEdgeStructureType::Face* findCellFace(const std::pair& facet) @@ -415,4 +416,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_MANIFOLD_CONSTRUCTION_HELPER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/mesh/import/TriMeshLoader.cpp ovito-2.9.0+dfsg1/src/plugins/mesh/import/TriMeshLoader.cpp --- ovito-2.8.1+dfsg2/src/plugins/mesh/import/TriMeshLoader.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/mesh/import/TriMeshLoader.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,6 +24,7 @@ #include #include #include +#include #include "TriMeshLoader.h" namespace Mesh { @@ -36,7 +37,7 @@ setProgressText(QString("Reading file %1").arg(frame().sourceFile.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded))); // Fetch file. - Future fetchFileFuture = FileManager::instance().fetchUrl(datasetContainer(), frame().sourceFile); + Future fetchFileFuture = Application::instance()->fileManager()->fetchUrl(datasetContainer(), frame().sourceFile); if(!waitForSubTask(fetchFileFuture)) return; diff -Nru ovito-2.8.1+dfsg2/src/plugins/mesh/import/TriMeshLoader.h ovito-2.9.0+dfsg1/src/plugins/mesh/import/TriMeshLoader.h --- ovito-2.8.1+dfsg2/src/plugins/mesh/import/TriMeshLoader.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/mesh/import/TriMeshLoader.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TRIMESH_LOADER_H -#define __OVITO_TRIMESH_LOADER_H +#pragma once + #include #include @@ -68,4 +68,4 @@ }; -#endif // __OVITO_TRIMESH_LOADER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/mesh/import/VTKFileImporter.cpp ovito-2.9.0+dfsg1/src/plugins/mesh/import/VTKFileImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/mesh/import/VTKFileImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/mesh/import/VTKFileImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,7 +25,7 @@ namespace Mesh { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Mesh, VTKFileImporter, FileSourceImporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(VTKFileImporter, FileSourceImporter); /****************************************************************************** * Checks if the given file has format that can be read by this importer. @@ -78,9 +78,7 @@ throw Exception(tr("Can read only read VTK files containing triangle polydata or unstructured grids with triangle cells.")); // Read point count. - stream.readNonEmptyLine(); - if(!stream.lineStartsWith("POINTS")) - throw Exception(tr("Invalid VTK file. Expected POINTS token in line %1 but found '%2'.").arg(stream.lineNumber()).arg(stream.lineString().trimmed())); + expectKeyword(stream, "POINTS"); int pointCount; if(sscanf(stream.line() + 6, "%i", &pointCount) != 1 || pointCount < 0) throw Exception(tr("Invalid number of points in VTK file (line %1): %2").arg(stream.lineNumber()).arg(stream.lineString())); @@ -106,44 +104,46 @@ } mesh().invalidateVertices(); - stream.readNonEmptyLine(); - int triangleCount; + int polygonCount; if(!isPolyData) { // Parse number of cells. - if(!stream.lineStartsWith("CELLS")) - throw Exception(tr("Invalid VTK file. Expected token CELLS in line %1, but found '%2'.").arg(stream.lineNumber()).arg(stream.lineString().trimmed())); - if(sscanf(stream.line() + 5, "%i", &triangleCount) != 1 || triangleCount < 0) + expectKeyword(stream, "CELLS"); + if(sscanf(stream.line() + 5, "%i", &polygonCount) != 1 || polygonCount < 0) throw Exception(tr("Invalid number of cells in VTK file (line %1): %2").arg(stream.lineNumber()).arg(stream.lineString())); } else { // Parse number of polygons. - if(!stream.lineStartsWith("POLYGONS")) - throw Exception(tr("Invalid VTK file. Expected token POLYGONS in line %1, but found '%2'.").arg(stream.lineNumber()).arg(stream.lineString().trimmed())); - if(sscanf(stream.line() + 8, "%i", &triangleCount) != 1 || triangleCount < 0) + expectKeyword(stream, "POLYGONS"); + if(sscanf(stream.line() + 8, "%i", &polygonCount) != 1 || polygonCount < 0) throw Exception(tr("Invalid number of polygons in VTK file (line %1): %2").arg(stream.lineNumber()).arg(stream.lineString())); } - // Parse triangles. - mesh().setFaceCount(triangleCount); - auto f = mesh().faces().begin(); - for(int i = 0; i < triangleCount; i++, ++f) { - int vcount = 0, a, b, c, token_count; - token_count = sscanf(stream.readLine(), "%i %i %i %i", &vcount, &a, &b, &c); - if(vcount != 3) - throw Exception(tr("Only triangle cells/polygons are supported in VTK files. Wrong number of vertices in line %1 of VTK file: %2").arg(stream.lineNumber()).arg(stream.lineString().trimmed())); - if(token_count != 4) - throw Exception(tr("Invalid triangle in VTK file (line %1): %2").arg(stream.lineNumber()).arg(stream.lineString())); - if(a >= pointCount || b >= pointCount || c >= pointCount) - throw Exception(tr("Vertex indices out of range in triangle cell (line %1): %2").arg(stream.lineNumber()).arg(stream.lineString())); - f->setVertices(a,b,c); + + // Parse polygons. + for(int i = 0; i < polygonCount; i++) { + int vcount, s; + const char* line = stream.readLine(); + if(sscanf(line, "%i%n", &vcount, &s) != 1 || vcount <= 2) + throw Exception(tr("Invalid polygon/cell definition in VTK file (line %1): %2").arg(stream.lineNumber()).arg(stream.lineString())); + unsigned int vindices[3]; + for(int j = 0; j < vcount; j++) { + line += s; + if(sscanf(line, "%u%n", &vindices[std::min(j,2)], &s) != 1) + throw Exception(tr("Invalid polygon/cell definition in VTK file (line %1): %2").arg(stream.lineNumber()).arg(stream.lineString())); + if(j >= 2) { + if(vindices[0] >= pointCount || vindices[1] >= pointCount || vindices[2] >= pointCount) + throw Exception(tr("Vertex indices out of range in polygon/cell (line %1): %2").arg(stream.lineNumber()).arg(stream.lineString())); + TriMeshFace& f = mesh().addFace(); + f.setVertices(vindices[0], vindices[1], vindices[2]); + vindices[1] = vindices[2]; + } + } } mesh().invalidateFaces(); if(!isPolyData) { // Parse cell types - stream.readNonEmptyLine(); - if(!stream.lineStartsWith("CELL_TYPES")) - throw Exception(tr("Invalid VTK file. Expected token CELL_TYPES in line %1, but found '%2'.").arg(stream.lineNumber()).arg(stream.lineString())); - for(int i = 0; i < triangleCount; i++) { + expectKeyword(stream, "CELL_TYPES"); + for(int i = 0; i < polygonCount; i++) { int t; if(sscanf(stream.readLine(), "%i", &t) != 1 || t != 5) throw Exception(tr("Invalid cell type in VTK file (line %1): %2. Only triangle cells are supported by OVITO.").arg(stream.lineNumber()).arg(stream.lineString())); @@ -162,13 +162,13 @@ auto& faceColors = mesh().faceColors(); std::fill(faceColors.begin(), faceColors.end(), ColorA(1,1,1,1)); component = 0; - for(int i = 0; i < triangleCount;) { + for(int i = 0; i < polygonCount;) { if(stream.eof()) throw Exception(tr("Unexpected end of VTK file in line %1.").arg(stream.lineNumber())); const char* s = stream.readLine(); for(; ;) { while(*s <= ' ' && *s != '\0') ++s; // Skip whitespace in front of token - if(!*s || i >= triangleCount) break; + if(!*s || i >= polygonCount) break; faceColors[i][component++] = (FloatType)std::atof(s); if(component == componentCount) { component = 0; @@ -187,4 +187,25 @@ setStatus(tr("%1 vertices, %2 triangles").arg(pointCount).arg(mesh().faceCount())); } +/****************************************************************************** +* Reads from the input stream and throws an exception if the given keyword +* is not present. +******************************************************************************/ +void VTKFileImporter::VTKFileImportTask::expectKeyword(CompressedTextReader& stream, const char* keyword) +{ + stream.readNonEmptyLine(); + + // Skip METADATA sections written by Paraview. + if(stream.lineStartsWith("METADATA")) { + while(!stream.eof()) { + const char* line = stream.readLineTrimLeft(); + if(line[0] <= ' ') break; + } + stream.readNonEmptyLine(); + } + + if(!stream.lineStartsWith(keyword)) + throw Exception(tr("Invalid or unsupported VTK file format. Expected token '%1' in line %2, but found '%3'.").arg(keyword).arg(stream.lineNumber()).arg(stream.lineString().trimmed())); +} + }; diff -Nru ovito-2.8.1+dfsg2/src/plugins/mesh/import/VTKFileImporter.h ovito-2.9.0+dfsg1/src/plugins/mesh/import/VTKFileImporter.h --- ovito-2.8.1+dfsg2/src/plugins/mesh/import/VTKFileImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/mesh/import/VTKFileImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VTK_FILE_IMPORTER_H -#define __OVITO_VTK_FILE_IMPORTER_H +#pragma once + #include #include @@ -73,10 +73,12 @@ /// Parses the given input file and stores the data in this container object. virtual void parseFile(CompressedTextReader& stream) override; - }; -protected: + /// Reads from the input stream and throws an exception if the given keyword is not present. + static void expectKeyword(CompressedTextReader& stream, const char* keyword); + }; +private: Q_OBJECT OVITO_OBJECT @@ -84,4 +86,4 @@ }; -#endif // __OVITO_VTK_FILE_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/mesh/Mesh.h ovito-2.9.0+dfsg1/src/plugins/mesh/Mesh.h --- ovito-2.8.1+dfsg2/src/plugins/mesh/Mesh.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/mesh/Mesh.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,9 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_MESH_H -#define __OVITO_MESH_H +#pragma once + #include -#endif diff -Nru ovito-2.8.1+dfsg2/src/plugins/mesh/resources/python/ovito/io/mesh/__init__.py ovito-2.9.0+dfsg1/src/plugins/mesh/resources/python/ovito/io/mesh/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/mesh/resources/python/ovito/io/mesh/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/mesh/resources/python/ovito/io/mesh/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -2,4 +2,4 @@ import ovito.io # Load the native code module -from Mesh import * +from ovito.plugins.Mesh import * diff -Nru ovito-2.8.1+dfsg2/src/plugins/mesh/scripting/PythonInterface.cpp ovito-2.9.0+dfsg1/src/plugins/mesh/scripting/PythonInterface.cpp --- ovito-2.8.1+dfsg2/src/plugins/mesh/scripting/PythonInterface.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/mesh/scripting/PythonInterface.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,6 +22,7 @@ #include #include #include +#include namespace Mesh { @@ -30,6 +31,9 @@ PYBIND11_PLUGIN(Mesh) { + // Register the classes of this plugin with the global PluginManager. + PluginManager::instance().registerLoadedPluginClasses(); + py::options options; options.disable_function_signatures(); diff -Nru ovito-2.8.1+dfsg2/src/plugins/netcdf/CMakeLists.txt ovito-2.9.0+dfsg1/src/plugins/netcdf/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/plugins/netcdf/CMakeLists.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/netcdf/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -19,7 +19,7 @@ # ############################################################################### -IF(WIN32 OR (UNIX AND NOT APPLE AND OVITO_MONOLITHIC_BUILD)) +IF(WIN32 OR (UNIX AND NOT APPLE AND OVITO_REDISTRIBUTABLE_PACKAGE)) # Locate the HDF5 library. FIND_PACKAGE(HDF5 COMPONENTS hdf5 REQUIRED NO_MODULE) ENDIF() @@ -73,7 +73,7 @@ ENDIF() OVITO_INSTALL_DLL("${HDF5_HL_DLL_LOCATION}") -ELSEIF(UNIX AND NOT APPLE AND OVITO_MONOLITHIC_BUILD) +ELSEIF(UNIX AND NOT APPLE AND OVITO_REDISTRIBUTABLE_PACKAGE) # Deploy NetCDF shared library. GET_TARGET_PROPERTY(NETCDF_LIBRARY netcdf LOCATION) diff -Nru ovito-2.8.1+dfsg2/src/plugins/netcdf/gui/NetCDFImporterEditor.cpp ovito-2.9.0+dfsg1/src/plugins/netcdf/gui/NetCDFImporterEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/netcdf/gui/NetCDFImporterEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/netcdf/gui/NetCDFImporterEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -49,7 +49,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(NetCDFPluginGui, NetCDFImporterEditor, FileImporterEditor); +IMPLEMENT_OVITO_OBJECT(NetCDFImporterEditor, FileImporterEditor); SET_OVITO_OBJECT_EDITOR(NetCDFImporter, NetCDFImporterEditor); /****************************************************************************** @@ -98,7 +98,7 @@ sublayout->setContentsMargins(4,4,4,4); layout->addWidget(columnMappingBox); - BooleanRadioButtonParameterUI* useCustomMappingUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(NetCDFImporter::_useCustomColumnMapping)); + BooleanRadioButtonParameterUI* useCustomMappingUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(NetCDFImporter::useCustomColumnMapping)); useCustomMappingUI->buttonFalse()->setText(tr("Automatic mapping")); sublayout->addWidget(useCustomMappingUI->buttonFalse()); useCustomMappingUI->buttonTrue()->setText(tr("User-defined mapping to particle properties")); diff -Nru ovito-2.8.1+dfsg2/src/plugins/netcdf/gui/NetCDFImporterEditor.h ovito-2.9.0+dfsg1/src/plugins/netcdf/gui/NetCDFImporterEditor.h --- ovito-2.8.1+dfsg2/src/plugins/netcdf/gui/NetCDFImporterEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/netcdf/gui/NetCDFImporterEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_NETCDF_IMPORTER_EDITOR_H -#define __OVITO_NETCDF_IMPORTER_EDITOR_H +#pragma once + #include #include @@ -63,4 +63,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_NETCDF_IMPORTER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/netcdf/NetCDFExporter.cpp ovito-2.9.0+dfsg1/src/plugins/netcdf/NetCDFExporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/netcdf/NetCDFExporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/netcdf/NetCDFExporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,9 +22,10 @@ #include #include #include -#include +#include #include "NetCDFExporter.h" +#include #include #define NCERR(x) ncerr(x, __FILE__, __LINE__) @@ -54,7 +55,7 @@ #define NC_OVITO_FLOATTYPE NC_DOUBLE #endif -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(NetCDFPlugin, NetCDFExporter, FileColumnParticleExporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(NetCDFExporter, FileColumnParticleExporter); /****************************************************************************** * Check for NetCDF error and throw exception @@ -86,6 +87,7 @@ // Open the input file for writing. NCERR(nc_create(filePath.toLocal8Bit().constData(), NC_64BIT_OFFSET, &_ncid)); + //NCERR(nc_create(filePath.toLocal8Bit().constData(), NC_NETCDF4, &_ncid)); // Define dimensions. NCERR(nc_def_dim(_ncid, NC_FRAME_STR, NC_UNLIMITED, &_frame_dim)); @@ -158,6 +160,7 @@ NCERR(nc_close(_ncid)); _ncid = -1; } + _atom_dim = -1; if(!exportCompleted) outputFile().remove(); @@ -166,10 +169,16 @@ /****************************************************************************** * Writes the particles of one animation frame to the current output file. ******************************************************************************/ -bool NetCDFExporter::exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progress) +bool NetCDFExporter::exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) { + // Get particle data to be exported. + PipelineFlowState state; + if(!getParticleData(sceneNode, time, state, taskManager)) + return false; + + SynchronousTask exportTask(taskManager); + // Get particle positions. - const PipelineFlowState& state = getParticleData(sceneNode, time); ParticlePropertyObject* posProperty = ParticlePropertyObject::findInState(state, ParticleProperty::PositionProperty); // Get simulation cell info. @@ -197,7 +206,7 @@ _attributes_vars.insert(entry.key(), var); } - // Define NetCDF variable for atomci positions. + // Define NetCDF variable for atomic positions. int dims[3] = { _frame_dim, _atom_dim, _spatial_dim }; NCERR(nc_def_var(_ncid, "coordinates", NC_OVITO_FLOATTYPE, 3, dims, &_coords_var)); @@ -205,9 +214,9 @@ for(auto c = columnMapping().begin(); c != columnMapping().end(); ++c) { if(c->type() == ParticleProperty::PositionProperty) continue; - - // Can export particle properties only as a whole, not individual components. - if(std::find_if(columnMapping().begin(), c, [c](const ParticlePropertyReference& pr) { return pr.type() == c->type(); })) + + // Can export a particle property only as a whole, not individual components. + if(std::find_if(columnMapping().begin(), c, [c](const ParticlePropertyReference& pr) { return pr.type() == c->type(); }) != c) continue; ParticlePropertyObject* prop = c->findInState(state); @@ -217,34 +226,49 @@ throwException(tr("The output vector component selected for column %1 is out of range. The particle property '%2' has only %3 component(s).").arg(c-columnMapping().begin()+1).arg(c->name()).arg(prop->componentCount())); if(prop->type() != ParticleProperty::UserProperty) { - const char* mangledNamed = nullptr; - if(prop->type() == ParticleProperty::ForceProperty) + const char* mangledName = nullptr; + if(prop->type() == ParticleProperty::ForceProperty) { mangledName = "forces"; - else if(prop->type() == ParticleProperty::VelocityProperty) + dims[2] = _spatial_dim; + } + else if(prop->type() == ParticleProperty::VelocityProperty) { mangledName = "velocities"; - else if(prop->type() == ParticleProperty::ParticleTypesProperty) + dims[2] = _spatial_dim; + } + else if(prop->type() == ParticleProperty::ParticleTypeProperty) { mangledName = "atom_types"; + } + else if(prop->type() == ParticleProperty::ColorProperty) { + mangledName = "color"; + dims[2] = _spatial_dim; + } if(mangledName) { - if(std::find_if(columnMapping().begin(), c, [c](const ParticlePropertyReference& pr) { return pr.type() == c->type(); })) + if(std::find_if(columnMapping().begin(), c, [c](const ParticlePropertyReference& pr) { return pr.type() == c->type(); }) != c) continue; if(prop->dataType() == qMetaTypeId()) { int ncvar; - NCERR(nc_def_var(_ncid, mangledName, NC_INT, 2, dims, &ncvar)); - _columns.emplace_back({ *c, qMetaTypeId(), 1, ncvar }); + NCERR(nc_def_var(_ncid, mangledName, NC_INT, prop->componentCount() > 1 ? 3 : 2, dims, &ncvar)); + _columns.emplace_back(*c, prop->dataType(), prop->componentCount(), ncvar); + } + else if(prop->dataType() == qMetaTypeId()) { + int ncvar; + NCERR(nc_def_var(_ncid, mangledName, NC_OVITO_FLOATTYPE, prop->componentCount() > 1 ? 3 : 2, dims, &ncvar)); + _columns.emplace_back(*c, prop->dataType(), prop->componentCount(), ncvar); } + continue; } } if(prop->dataType() == qMetaTypeId()) { int ncvar; NCERR(nc_def_var(_ncid, c->nameWithComponent().toUtf8().constData(), NC_INT, 2, dims, &ncvar)); - _columns.emplace_back({ *c, qMetaTypeId(), 1, ncvar }); + _columns.emplace_back(*c, qMetaTypeId(), 1, ncvar); } else if(prop->dataType() == qMetaTypeId()) { int ncvar; NCERR(nc_def_var(_ncid, c->nameWithComponent().toUtf8().constData(), NC_OVITO_FLOATTYPE, 2, dims, &ncvar)); - _columns.emplace_back({ *c, qMetaTypeId(), 1, ncvar }); + _columns.emplace_back(*c, qMetaTypeId(), 1, ncvar); } } @@ -293,9 +317,9 @@ double cosbeta = h[4]/sqrt(h[2]*h[2]+h[3]*h[3]+h[4]*h[4]); double cosgamma = h[5]/sqrt(h[1]*h[1]+h[5]*h[5]); - cell_angles[0] = acos(cosalpha) * 180.0/M_PI; - cell_angles[1] = acos(cosbeta) * 180.0/M_PI; - cell_angles[2] = acos(cosgamma) * 180.0/M_PI; + cell_angles[0] = qRadiansToDegrees(acos(cosalpha)); + cell_angles[1] = qRadiansToDegrees(acos(cosbeta)); + cell_angles[2] = qRadiansToDegrees(acos(cosgamma)); // AMBER convention says that nonperiodic boundaries should have 'cell_lengths' set to zero. if(!simulationCell->pbcX()) cell_lengths[0] = 0; @@ -317,8 +341,34 @@ NCERR(nc_put_vara_double(_ncid, _coords_var, start, count, posProperty->constDataFloat())); #endif + // Write out other particle properties. + for(const NCOutputColumn& outColumn : _columns) { + + // Look up property to be exported. + ParticlePropertyObject* prop = outColumn.property.findInState(state); + if(!prop) + throwException(tr("The property '%1' cannot be exported, because it does not exist at frame %2.").arg(outColumn.property.name()).arg(frameNumber)); + if((int)prop->componentCount() != outColumn.componentCount) + throwException(tr("Particle property '%1' cannot be exported, because its number of components has changed at frame %2.").arg(outColumn.property.name()).arg(frameNumber)); + if(prop->dataType() != outColumn.dataType) + throwException(tr("Particle property '%1' cannot be exported, because its data type has changed at frame %2.").arg(outColumn.property.name()).arg(frameNumber)); + + // Write property data to file. + count[2] = outColumn.componentCount; + if(outColumn.dataType == qMetaTypeId()) { + NCERR(nc_put_vara_int(_ncid, outColumn.ncvar, start, count, prop->constDataInt())); + } + else if(outColumn.dataType == qMetaTypeId()) { +#ifdef FLOATTYPE_FLOAT + NCERR(nc_put_vara_float(_ncid, outColumn.ncvar, start, count, prop->constDataFloat())); +#else + NCERR(nc_put_vara_double(_ncid, outColumn.ncvar, start, count, prop->constDataFloat())); +#endif + } + } + _frameCounter++; - return true; + return !exportTask.isCanceled(); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/plugins/netcdf/NetCDFExporter.h ovito-2.9.0+dfsg1/src/plugins/netcdf/NetCDFExporter.h --- ovito-2.8.1+dfsg2/src/plugins/netcdf/NetCDFExporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/netcdf/NetCDFExporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_NETCDF_FILE_EXPORTER_H -#define __OVITO_NETCDF_FILE_EXPORTER_H +#pragma once + #include #include @@ -58,7 +58,7 @@ virtual void closeOutputFile(bool exportCompleted) override; /// \brief Writes the particles of one animation frame to the current output file. - virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) override; + virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) override; private: @@ -94,6 +94,9 @@ QMap _attributes_vars; struct NCOutputColumn { + NCOutputColumn(const ParticlePropertyReference& p, int dt, size_t cc, int ncv) : + property(p), dataType(dt), componentCount(cc), ncvar(ncv) {} + ParticlePropertyReference property; int dataType; size_t componentCount; @@ -114,4 +117,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_NETCDF_FILE_EXPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/netcdf/NetCDFImporter.cpp ovito-2.9.0+dfsg1/src/plugins/netcdf/NetCDFImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/netcdf/NetCDFImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/netcdf/NetCDFImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -53,9 +53,11 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(NetCDFPlugin, NetCDFImporter, ParticleImporter); -DEFINE_PROPERTY_FIELD(NetCDFImporter, _useCustomColumnMapping, "UseCustomColumnMapping"); -SET_PROPERTY_FIELD_LABEL(NetCDFImporter, _useCustomColumnMapping, "Custom file column mapping"); +QMutex NetCDFImporter::_netcdfMutex; + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(NetCDFImporter, ParticleImporter); +DEFINE_PROPERTY_FIELD(NetCDFImporter, useCustomColumnMapping, "UseCustomColumnMapping"); +SET_PROPERTY_FIELD_LABEL(NetCDFImporter, useCustomColumnMapping, "Custom file column mapping"); // Convert full tensor to Voigt tensor template @@ -106,6 +108,9 @@ { QString filename = QDir::toNativeSeparators(input.fileName()); + // Only serial access to NetCDF functions allowed because they are not thread-safe. + QMutexLocker locker(&netcdfMutex()); + // Check if we can open the input file for reading. int tmp_ncid; int err = nc_open(filename.toLocal8Bit().constData(), NC_NOWRITE, &tmp_ncid); @@ -132,8 +137,11 @@ /****************************************************************************** * Scans the input file for simulation timesteps. ******************************************************************************/ -void NetCDFImporter::scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) +void NetCDFImporter::scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) { + // Only serial access to NetCDF functions allowed because they are not thread-safe. + QMutexLocker locker(&netcdfMutex()); + QString filename = QDir::toNativeSeparators(stream.device().fileName()); // Open the input NetCDF file. @@ -338,6 +346,8 @@ // Get frame number. size_t movieFrame = frame().lineNumber; + // Only serial access to NetCDF functions allowed because they are not thread-safe. + QMutexLocker locker(&netcdfMutex()); try { openNetCDF(filename); @@ -476,7 +486,7 @@ NCERR( nc_inq_varid(_ncid, columnName.toLocal8Bit().constData(), &varId) ); NCERR( nc_inq_var(_ncid, varId, NULL, &type, &nDims, dimIds, NULL) ); - if (nDims > 0 && type == NC_FLOAT) { + if(nDims > 0 && type == NC_FLOAT) { // Detect dims int nDimsDetected = -1, componentCount = 1, nativeComponentCount = 1; detectDims(movieFrame, particleCount, nDims, dimIds, nDimsDetected, componentCount, nativeComponentCount, startp, countp); @@ -561,7 +571,7 @@ for(int j = 0; j < (int)particleProperties().size(); j++) { const auto& p = particleProperties()[j]; if(p->name() == propertyName) { - if(property->dataType() == dataType) + if(p->dataType() == dataType) property = p.get(); else removeParticleProperty(j); @@ -642,7 +652,7 @@ size_t totalCount = countp[1]; size_t remaining = totalCount; countp[1] = 1000000; - setProgressRange(totalCount / countp[1] + 1); + setProgressMaximum(totalCount / countp[1] + 1); OVITO_ASSERT(totalCount <= property->size()); for(size_t chunk = 0; chunk < totalCount; chunk += countp[1], startp[1] += countp[1]) { countp[1] = std::min(countp[1], remaining); @@ -674,7 +684,7 @@ size_t totalCount = countp[1]; size_t remaining = totalCount; countp[1] = 1000000; - setProgressRange(totalCount / countp[1] + 1); + setProgressMaximum(totalCount / countp[1] + 1); for(size_t chunk = 0; chunk < totalCount; chunk += countp[1], startp[1] += countp[1]) { countp[1] = std::min(countp[1], remaining); remaining -= countp[1]; @@ -751,6 +761,7 @@ else if(loweredName == "type" || loweredName == "element" || loweredName == "atom_types" || loweredName == "species") column.mapStandardColumn(ParticleProperty::ParticleTypeProperty); else if(loweredName == "mass") column.mapStandardColumn(ParticleProperty::MassProperty); else if(loweredName == "radius") column.mapStandardColumn(ParticleProperty::RadiusProperty); + else if(loweredName == "color") column.mapStandardColumn(ParticleProperty::ColorProperty); else if(loweredName == "c_cna" || loweredName == "pattern") column.mapStandardColumn(ParticleProperty::StructureTypeProperty); else if(loweredName == "c_epot") column.mapStandardColumn(ParticleProperty::PotentialEnergyProperty); else if(loweredName == "c_kpot") column.mapStandardColumn(ParticleProperty::KineticEnergyProperty); diff -Nru ovito-2.8.1+dfsg2/src/plugins/netcdf/NetCDFImporter.h ovito-2.9.0+dfsg1/src/plugins/netcdf/NetCDFImporter.h --- ovito-2.8.1+dfsg2/src/plugins/netcdf/NetCDFImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/netcdf/NetCDFImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_NETCDF_IMPORTER_H -#define __OVITO_NETCDF_IMPORTER_H +#pragma once + #include #include @@ -43,7 +43,7 @@ /// \brief Constructs a new instance of this class. Q_INVOKABLE NetCDFImporter(DataSet *dataset) : ParticleImporter(dataset), _useCustomColumnMapping(false) { - INIT_PROPERTY_FIELD(NetCDFImporter::_useCustomColumnMapping); + INIT_PROPERTY_FIELD(useCustomColumnMapping); setMultiTimestepFile(true); } @@ -69,14 +69,6 @@ /// the internal particle properties. void setCustomColumnMapping(const InputColumnMapping& mapping); - /// Returns whether the mapping between input file columns and particle - /// properties is done automatically or by the user. - bool useCustomColumnMapping() const { return _useCustomColumnMapping; } - - /// Sets whether the mapping between input file columns and particle - /// properties is done automatically or by the user. - void setUseCustomColumnMapping(bool useCustomMapping) { _useCustomColumnMapping = useCustomMapping; } - /// Creates an asynchronous loader object that loads the data for the given frame from the external file. virtual std::shared_ptr createFrameLoader(const Frame& frame, bool isNewlySelectedFile) override { return std::make_shared(dataset()->container(), frame, isNewlySelectedFile, _useCustomColumnMapping, _customColumnMapping); @@ -85,6 +77,10 @@ /// Inspects the header of the given file and returns the number of file columns. InputColumnMapping inspectFileHeader(const Frame& frame); + /// Return the global mutex used to serialize access to the NetCDF library functions, + /// which are not thread-safe. + static QMutex& netcdfMutex() { return _netcdfMutex; } + private: /// The format-specific task object that is responsible for reading an input file in the background. @@ -148,7 +144,7 @@ virtual OORef clone(bool deepCopy, CloneHelper& cloneHelper) override; /// \brief Scans the given input file to find all contained simulation frames. - virtual void scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; + virtual void scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; /// \brief Guesses the mapping of an input file field to one of OVITO's internal particle properties. static InputColumnInfo mapVariableToColumn(const QString& name, int dataType); @@ -157,16 +153,18 @@ /// Controls whether the mapping between input file columns and particle /// properties is done automatically or by the user. - PropertyField _useCustomColumnMapping; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, useCustomColumnMapping, setUseCustomColumnMapping); /// Stores the user-defined mapping between data columns in the input file and /// the internal particle properties. InputColumnMapping _customColumnMapping; + /// This global mutex is used to serialize access to the NetCDF library functions, + /// which are not thread-safe. + static QMutex _netcdfMutex; + Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_useCustomColumnMapping); }; OVITO_END_INLINE_NAMESPACE @@ -174,4 +172,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_NETCDF_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/netcdf/PythonInterface.cpp ovito-2.9.0+dfsg1/src/plugins/netcdf/PythonInterface.cpp --- ovito-2.8.1+dfsg2/src/plugins/netcdf/PythonInterface.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/netcdf/PythonInterface.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,6 +23,7 @@ #include #include #include +#include namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) OVITO_BEGIN_INLINE_NAMESPACE(Internal) @@ -30,6 +31,9 @@ PYBIND11_PLUGIN(NetCDFPlugin) { + // Register the classes of this plugin with the global PluginManager. + PluginManager::instance().registerLoadedPluginClasses(); + py::options options; options.disable_function_signatures(); diff -Nru ovito-2.8.1+dfsg2/src/plugins/netcdf/resources/python/ovito/io/particles/netcdf/__init__.py ovito-2.9.0+dfsg1/src/plugins/netcdf/resources/python/ovito/io/particles/netcdf/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/netcdf/resources/python/ovito/io/particles/netcdf/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/netcdf/resources/python/ovito/io/particles/netcdf/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -2,7 +2,7 @@ import ovito.io.particles # Load the native code module -import NetCDFPlugin +import ovito.plugins.NetCDFPlugin # Inject selected classes into parent module. -ovito.io.particles.NetCDFImporter = NetCDFPlugin.NetCDFImporter +ovito.io.particles.NetCDFImporter = ovito.plugins.NetCDFPlugin.NetCDFImporter diff -Nru ovito-2.8.1+dfsg2/src/plugins/openbabel/import/CIFImporter.cpp ovito-2.9.0+dfsg1/src/plugins/openbabel/import/CIFImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/openbabel/import/CIFImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/openbabel/import/CIFImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,7 +26,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(OpenBabelPlugin, CIFImporter, OpenBabelImporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CIFImporter, OpenBabelImporter); /****************************************************************************** * Checks if the given file has format that can be read by this importer. diff -Nru ovito-2.8.1+dfsg2/src/plugins/openbabel/import/CIFImporter.h ovito-2.9.0+dfsg1/src/plugins/openbabel/import/CIFImporter.h --- ovito-2.8.1+dfsg2/src/plugins/openbabel/import/CIFImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/openbabel/import/CIFImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CIF_IMPORTER_H -#define __OVITO_CIF_IMPORTER_H +#pragma once + #include #include "OpenBabelImporter.h" @@ -65,4 +65,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CIF_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/openbabel/import/OpenBabelImporter.cpp ovito-2.9.0+dfsg1/src/plugins/openbabel/import/OpenBabelImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/openbabel/import/OpenBabelImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/openbabel/import/OpenBabelImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -32,7 +32,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(OpenBabelPlugin, OpenBabelImporter, ParticleImporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(OpenBabelImporter, ParticleImporter); /****************************************************************************** * Parses the given input file and stores the data in this container object. diff -Nru ovito-2.8.1+dfsg2/src/plugins/openbabel/import/OpenBabelImporter.h ovito-2.9.0+dfsg1/src/plugins/openbabel/import/OpenBabelImporter.h --- ovito-2.8.1+dfsg2/src/plugins/openbabel/import/OpenBabelImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/openbabel/import/OpenBabelImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OPENBABEL_IMPORTER_H -#define __OVITO_OPENBABEL_IMPORTER_H +#pragma once + #include #include @@ -78,4 +78,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_OPENBABEL_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/openbabel/python/ovito/io/particles/openbabel/__init__.py ovito-2.9.0+dfsg1/src/plugins/openbabel/python/ovito/io/particles/openbabel/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/openbabel/python/ovito/io/particles/openbabel/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/openbabel/python/ovito/io/particles/openbabel/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -2,8 +2,8 @@ import ovito.io.particles # Load the native code module -import OpenBabelPlugin +import ovito.plugins.OpenBabelPlugin # Inject selected classes into parent module. -ovito.io.particles.OpenBabelImporter = OpenBabelPlugin.OpenBabelImporter -ovito.io.particles.CIFImporter = OpenBabelPlugin.CIFImporter +ovito.io.particles.OpenBabelImporter = ovito.plugins.OpenBabelPlugin.OpenBabelImporter +ovito.io.particles.CIFImporter = ovito.plugins.OpenBabelPlugin.CIFImporter diff -Nru ovito-2.8.1+dfsg2/src/plugins/openbabel/PythonInterface.cpp ovito-2.9.0+dfsg1/src/plugins/openbabel/PythonInterface.cpp --- ovito-2.8.1+dfsg2/src/plugins/openbabel/PythonInterface.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/openbabel/PythonInterface.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,6 +23,7 @@ #include #include #include +#include namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) OVITO_BEGIN_INLINE_NAMESPACE(Internal) @@ -30,6 +31,9 @@ PYBIND11_PLUGIN(OpenBabelPlugin) { + // Register the classes of this plugin with the global PluginManager. + PluginManager::instance().registerLoadedPluginClasses(); + py::options options; options.disable_function_signatures(); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/CMakeLists.txt ovito-2.9.0+dfsg1/src/plugins/particles/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/plugins/particles/CMakeLists.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -37,10 +37,12 @@ objects/TrajectoryObject.cpp objects/TrajectoryDisplay.cpp objects/TrajectoryGeneratorObject.cpp + objects/FieldQuantityObject.cpp data/ParticleProperty.cpp data/BondProperty.cpp data/PropertyBase.cpp data/BondsStorage.cpp + data/FieldQuantity.cpp modifier/ParticleModifier.cpp modifier/AsynchronousParticleModifier.cpp modifier/coloring/AssignColorModifier.cpp @@ -56,6 +58,7 @@ modifier/modify/CreateBondsModifier.cpp modifier/modify/LoadTrajectoryModifier.cpp modifier/modify/CombineParticleSetsModifier.cpp + modifier/modify/CoordinationPolyhedraModifier.cpp modifier/analysis/StructureIdentificationModifier.cpp modifier/analysis/binandreduce/BinAndReduceModifier.cpp modifier/analysis/bondangle/BondAngleAnalysisModifier.cpp @@ -81,6 +84,8 @@ modifier/properties/ComputePropertyModifier.cpp modifier/properties/FreezePropertyModifier.cpp modifier/properties/ComputeBondLengthsModifier.cpp + modifier/fields/CreateIsosurfaceModifier.cpp + modifier/fields/MarchingCubes.cpp import/ParticleImporter.cpp import/ParticleFrameLoader.cpp import/InputColumnMapping.cpp @@ -97,6 +102,8 @@ import/fhi_aims/FHIAimsLogFileImporter.cpp import/gsd/GSDImporter.cpp import/gsd/gsd.c + import/castep/CastepCellImporter.cpp + import/castep/CastepMDImporter.cpp export/ParticleExporter.cpp export/FileColumnParticleExporter.cpp export/OutputColumnMapping.cpp diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/data/BondProperty.h ovito-2.9.0+dfsg1/src/plugins/particles/data/BondProperty.h --- ovito-2.8.1+dfsg2/src/plugins/particles/data/BondProperty.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/data/BondProperty.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BOND_PROPERTY_H -#define __OVITO_BOND_PROPERTY_H +#pragma once + #include #include "PropertyBase.h" @@ -137,4 +137,4 @@ Q_DECLARE_METATYPE(Ovito::Particles::BondProperty::Type); Q_DECLARE_TYPEINFO(Ovito::Particles::BondProperty::Type, Q_PRIMITIVE_TYPE); -#endif // __OVITO_BOND_PROPERTY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/data/BondsStorage.h ovito-2.9.0+dfsg1/src/plugins/particles/data/BondsStorage.h --- ovito-2.8.1+dfsg2/src/plugins/particles/data/BondsStorage.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/data/BondsStorage.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BONDS_STORAGE_H -#define __OVITO_BONDS_STORAGE_H +#pragma once + #include #include @@ -148,4 +148,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_BONDS_STORAGE_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/data/FieldQuantity.cpp ovito-2.9.0+dfsg1/src/plugins/particles/data/FieldQuantity.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/data/FieldQuantity.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/data/FieldQuantity.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,72 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include "FieldQuantity.h" + +namespace Ovito { namespace Particles { + +/****************************************************************************** +* Constructor. +******************************************************************************/ +FieldQuantity::FieldQuantity(std::vector shape, int dataType, size_t componentCount, size_t stride, const QString& name, bool initializeMemory) + : PropertyBase(std::accumulate(shape.begin(), shape.end(), 1, std::multiplies()), dataType, componentCount, stride, name, initializeMemory), _shape(std::move(shape)) +{ +} + +/****************************************************************************** +* Copy constructor. +******************************************************************************/ +FieldQuantity::FieldQuantity(const FieldQuantity& other) + : PropertyBase(other), _shape(other._shape) +{ +} + +/****************************************************************************** +* Saves the class' contents to the given stream. +******************************************************************************/ +void FieldQuantity::saveToStream(SaveStream& stream, bool onlyMetadata) const +{ + PropertyBase::saveToStream(stream, onlyMetadata, 0); + stream.beginChunk(0x01); + stream.writeSizeT(shape().size()); + for(size_t d : shape()) + stream.writeSizeT(d); + stream.endChunk(); +} + +/****************************************************************************** +* Loads the class' contents from the given stream. +******************************************************************************/ +void FieldQuantity::loadFromStream(LoadStream& stream) +{ + PropertyBase::loadFromStream(stream); + stream.expectChunk(0x01); + size_t ndim; + stream.readSizeT(ndim); + _shape.resize(ndim); + for(size_t d = 0; d < ndim; d++) + stream.readSizeT(_shape[d]); + stream.closeChunk(); +} + +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/data/FieldQuantity.h ovito-2.9.0+dfsg1/src/plugins/particles/data/FieldQuantity.h --- ovito-2.8.1+dfsg2/src/plugins/particles/data/FieldQuantity.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/data/FieldQuantity.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,69 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include "PropertyBase.h" + +namespace Ovito { namespace Particles { + +/** + * \brief Memory storage for a field quantity. + */ +class OVITO_PARTICLES_EXPORT FieldQuantity : public PropertyBase +{ +public: + + /// \brief Default constructor that creates an empty, uninitialized storage. + FieldQuantity() : PropertyBase() {} + + /// \brief Constructor that creates a field quantity storage. + /// \param shape The number of grid samples along each dimension. + /// \param dataType Specifies the data type (integer, floating-point, ...) of the elements. + /// The data type is specified as identifier according to the Qt metatype system. + /// \param componentCount The number of components per field value (each of type \a dataType). + /// \param stride The number of bytes per field value (pass 0 to use the smallest possible stride). + /// \param name The name of the field quantity. + /// \param initializeMemory Controls whether the newly allocated memory is initialized with zeros. + FieldQuantity(std::vector shape, int dataType, size_t componentCount, size_t stride, const QString& name, bool initializeMemory); + + /// \brief Copy constructor. + FieldQuantity(const FieldQuantity& other); + + /// Writes the object to an output stream. + void saveToStream(SaveStream& stream, bool onlyMetadata = false) const; + + /// Reads the object from an input stream. + void loadFromStream(LoadStream& stream); + + /// Returns the number of grid points along each dimension. + const std::vector& shape() const { return _shape; } + +protected: + + /// The number of grid points along each dimension. + std::vector _shape; +}; + +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/data/ParticleProperty.h ovito-2.9.0+dfsg1/src/plugins/particles/data/ParticleProperty.h --- ovito-2.8.1+dfsg2/src/plugins/particles/data/ParticleProperty.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/data/ParticleProperty.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_PROPERTY_H -#define __OVITO_PARTICLE_PROPERTY_H +#pragma once + #include #include "PropertyBase.h" @@ -174,4 +174,4 @@ Q_DECLARE_METATYPE(Ovito::Particles::ParticleProperty::Type); Q_DECLARE_TYPEINFO(Ovito::Particles::ParticleProperty::Type, Q_PRIMITIVE_TYPE); -#endif // __OVITO_PARTICLE_PROPERTY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/data/PropertyBase.h ovito-2.9.0+dfsg1/src/plugins/particles/data/PropertyBase.h --- ovito-2.8.1+dfsg2/src/plugins/particles/data/PropertyBase.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/data/PropertyBase.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,11 +19,10 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PROPERTY_BASE_H -#define __OVITO_PROPERTY_BASE_H +#pragma once -#include +#include #include namespace Ovito { namespace Particles { @@ -508,4 +507,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PROPERTY_BASE_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/data/SimulationCell.h ovito-2.9.0+dfsg1/src/plugins/particles/data/SimulationCell.h --- ovito-2.8.1+dfsg2/src/plugins/particles/data/SimulationCell.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/data/SimulationCell.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SIMULATION_CELL_H -#define __OVITO_SIMULATION_CELL_H +#pragma once + #include @@ -209,4 +209,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SIMULATION_CELL_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/fhi_aims/FHIAimsExporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/export/fhi_aims/FHIAimsExporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/export/fhi_aims/FHIAimsExporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/fhi_aims/FHIAimsExporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,20 +23,26 @@ #include #include #include -#include +#include #include "FHIAimsExporter.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Export) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, FHIAimsExporter, ParticleExporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(FHIAimsExporter, ParticleExporter); /****************************************************************************** * Writes the particles of one animation frame to the current output file. ******************************************************************************/ -bool FHIAimsExporter::exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progress) +bool FHIAimsExporter::exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) { + // Get particle data to be exported. + PipelineFlowState state; + if(!getParticleData(sceneNode, time, state, taskManager)) + return false; + + SynchronousTask exportTask(taskManager); + // Get particle positions and types. - const PipelineFlowState& state = getParticleData(sceneNode, time); ParticlePropertyObject* posProperty = ParticlePropertyObject::findInState(state, ParticleProperty::PositionProperty); ParticleTypeProperty* particleTypeProperty = dynamic_object_cast(ParticlePropertyObject::findInState(state, ParticleProperty::ParticleTypeProperty)); @@ -46,7 +52,7 @@ Point3 origin = Point3::Origin(); SimulationCellObject* simulationCell = state.findObject(); if(simulationCell) { - origin = simulationCell->origin(); + origin = simulationCell->cellOrigin(); if(simulationCell->pbcX() || simulationCell->pbcY() || simulationCell->pbcZ()) { AffineTransformation cell = simulationCell->cellMatrix(); for(size_t i = 0; i < 3; i++) @@ -55,7 +61,7 @@ } // Output atoms. - if(progress) progress->setMaximum(100); + exportTask.setProgressMaximum(100); for(size_t i = 0; i < posProperty->size(); i++) { const Point3& p = posProperty->getPoint3(i); const ParticleType* type = particleTypeProperty->particleType(particleTypeProperty->getInt(i)); @@ -69,14 +75,14 @@ textStream() << ' ' << particleTypeProperty->getInt(i) << '\n'; } - if(progress && (i % 1000) == 0) { - progress->setValue((qint64)i * 100 / posProperty->size()); - if(progress->wasCanceled()) + if((i % 1000) == 0) { + exportTask.setProgressValue((qint64)i * 100 / posProperty->size()); + if(exportTask.isCanceled()) return false; } } - return true; + return !exportTask.isCanceled(); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/fhi_aims/FHIAimsExporter.h ovito-2.9.0+dfsg1/src/plugins/particles/export/fhi_aims/FHIAimsExporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/export/fhi_aims/FHIAimsExporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/fhi_aims/FHIAimsExporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FHI_AIMS_EXPORTER_H -#define __OVITO_FHI_AIMS_EXPORTER_H +#pragma once + #include #include "../ParticleExporter.h" @@ -46,7 +46,7 @@ protected: /// \brief Writes the particles of one animation frame to the current output file. - virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) override; + virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) override; private: @@ -59,4 +59,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_FHI_AIMS_EXPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/FileColumnParticleExporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/export/FileColumnParticleExporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/export/FileColumnParticleExporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/FileColumnParticleExporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Export) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, FileColumnParticleExporter, ParticleExporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(FileColumnParticleExporter, ParticleExporter); /****************************************************************************** * Loads the user-defined default values of this object's parameter fields from the diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/FileColumnParticleExporter.h ovito-2.9.0+dfsg1/src/plugins/particles/export/FileColumnParticleExporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/export/FileColumnParticleExporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/FileColumnParticleExporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FILE_COLUMN_PARTICLE_EXPORTER_H -#define __OVITO_FILE_COLUMN_PARTICLE_EXPORTER_H +#pragma once + #include #include "ParticleExporter.h" @@ -67,4 +67,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_FILE_COLUMN_PARTICLE_EXPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/imd/IMDExporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/export/imd/IMDExporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/export/imd/IMDExporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/imd/IMDExporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,21 +23,26 @@ #include #include #include -#include +#include #include "IMDExporter.h" #include "../OutputColumnMapping.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Export) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, IMDExporter, FileColumnParticleExporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(IMDExporter, FileColumnParticleExporter); /****************************************************************************** * Writes the particles of one animation frame to the current output file. ******************************************************************************/ -bool IMDExporter::exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progress) +bool IMDExporter::exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) { - // Get particle positions. - const PipelineFlowState& state = getParticleData(sceneNode, time); + // Get particle data to be exported. + PipelineFlowState state; + if(!getParticleData(sceneNode, time, state, taskManager)) + return false; + + SynchronousTask exportTask(taskManager); + ParticlePropertyObject* posProperty = ParticlePropertyObject::findInState(state, ParticleProperty::PositionProperty); ParticleTypeProperty* typeProperty = nullptr; ParticlePropertyObject* identifierProperty = nullptr; @@ -150,19 +155,19 @@ textStream() << "## IMD file written by " << QCoreApplication::applicationName() << "\n"; textStream() << "#E\n"; - if(progress) progress->setMaximum(100); + exportTask.setProgressMaximum(100); OutputColumnWriter columnWriter(colMapping, state); for(size_t i = 0; i < atomsCount; i++) { columnWriter.writeParticle(i, textStream()); - if(progress && (i % 4096) == 0) { - progress->setValue((quint64)i * 100 / atomsCount); - if(progress->wasCanceled()) + if((i % 4096) == 0) { + exportTask.setProgressValue((quint64)i * 100 / atomsCount); + if(exportTask.isCanceled()) return false; } } - return true; + return !exportTask.isCanceled(); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/imd/IMDExporter.h ovito-2.9.0+dfsg1/src/plugins/particles/export/imd/IMDExporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/export/imd/IMDExporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/imd/IMDExporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_IMD_FILE_EXPORTER_H -#define __OVITO_IMD_FILE_EXPORTER_H +#pragma once + #include #include "../FileColumnParticleExporter.h" @@ -46,7 +46,7 @@ protected: /// \brief Writes the particles of one animation frame to the current output file. - virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) override; + virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) override; private: @@ -59,4 +59,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_IMD_FILE_EXPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/lammps/LAMMPSDataExporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/export/lammps/LAMMPSDataExporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/export/lammps/LAMMPSDataExporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/lammps/LAMMPSDataExporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,22 +25,27 @@ #include #include #include -#include +#include #include "LAMMPSDataExporter.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Export) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, LAMMPSDataExporter, ParticleExporter); -DEFINE_FLAGS_PROPERTY_FIELD(LAMMPSDataExporter, _atomStyle, "AtomStyle", PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(LAMMPSDataExporter, _atomStyle, "Atom style"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(LAMMPSDataExporter, ParticleExporter); +DEFINE_FLAGS_PROPERTY_FIELD(LAMMPSDataExporter, atomStyle, "AtomStyle", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(LAMMPSDataExporter, atomStyle, "Atom style"); /****************************************************************************** * Writes the particles of one animation frame to the current output file. ******************************************************************************/ -bool LAMMPSDataExporter::exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progress) +bool LAMMPSDataExporter::exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) { - // Get particle positions. - const PipelineFlowState& state = getParticleData(sceneNode, time); + // Get particle data to be exported. + PipelineFlowState state; + if(!getParticleData(sceneNode, time, state, taskManager)) + return false; + + SynchronousTask exportTask(taskManager); + ParticlePropertyObject* posProperty = ParticlePropertyObject::findInState(state, ParticleProperty::PositionProperty); ParticlePropertyObject* velocityProperty = ParticlePropertyObject::findInState(state, ParticleProperty::VelocityProperty); ParticlePropertyObject* identifierProperty = ParticlePropertyObject::findInState(state, ParticleProperty::IdentifierProperty); @@ -142,10 +147,11 @@ case LAMMPSDataImporter::AtomStyle_Charge: textStream() << " # charge"; break; case LAMMPSDataImporter::AtomStyle_Dipole: textStream() << " # dipole"; break; case LAMMPSDataImporter::AtomStyle_Sphere: textStream() << " # sphere"; break; - } + default: break; // Do nothing + } textStream() << "\n\n"; - if(progress) progress->setMaximum(100); + exportTask.setProgressMaximum(100); for(size_t i = 0; i < posProperty->size(); i++) { // atom-ID textStream() << (identifierProperty ? identifierProperty->getInt(i) : (i+1)); @@ -191,9 +197,9 @@ textStream() << '\n'; currentProgress++; - if(progress && (currentProgress % 4096) == 0) { - progress->setValue(currentProgress * 100 / totalProgressCount); - if(progress->wasCanceled()) + if((currentProgress % 4096) == 0) { + exportTask.setProgressValue(currentProgress * 100 / totalProgressCount); + if(exportTask.isCanceled()) return false; } } @@ -215,9 +221,9 @@ textStream() << '\n'; currentProgress++; - if(progress && (currentProgress % 4096) == 0) { - progress->setValue(currentProgress * 100 / totalProgressCount); - if(progress->wasCanceled()) + if((currentProgress % 4096) == 0) { + exportTask.setProgressValue(currentProgress * 100 / totalProgressCount); + if(exportTask.isCanceled()) return false; } } @@ -241,16 +247,16 @@ textStream() << '\n'; currentProgress++; - if(progress && (currentProgress % 4096) == 0) { - progress->setValue(currentProgress * 100 / totalProgressCount); - if(progress->wasCanceled()) + if((currentProgress % 4096) == 0) { + exportTask.setProgressValue(currentProgress * 100 / totalProgressCount); + if(exportTask.isCanceled()) return false; } } OVITO_ASSERT(bondIndex == bondsObj->storage()->size() / 2 + 1); } - return true; + return !exportTask.isCanceled(); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/lammps/LAMMPSDataExporter.h ovito-2.9.0+dfsg1/src/plugins/particles/export/lammps/LAMMPSDataExporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/export/lammps/LAMMPSDataExporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/lammps/LAMMPSDataExporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_LAMMPS_DATA_FILE_EXPORTER_H -#define __OVITO_LAMMPS_DATA_FILE_EXPORTER_H +#pragma once + #include #include "../ParticleExporter.h" @@ -37,7 +37,7 @@ /// \brief Constructs a new instance of this class. Q_INVOKABLE LAMMPSDataExporter(DataSet* dataset) : ParticleExporter(dataset), _atomStyle(LAMMPSDataImporter::AtomStyle_Atomic) { - INIT_PROPERTY_FIELD(LAMMPSDataExporter::_atomStyle); + INIT_PROPERTY_FIELD(atomStyle); } /// \brief Returns the file filter that specifies the files that can be exported by this service. @@ -46,26 +46,18 @@ /// \brief Returns the filter description that is displayed in the drop-down box of the file dialog. virtual QString fileFilterDescription() override { return tr("LAMMPS Data File"); } - /// Returns the format variant being written by this data file exporter. - LAMMPSDataImporter::LAMMPSAtomStyle atomStyle() const { return _atomStyle; } - - /// Sets the kind of data file to write. - void setAtomStyle(LAMMPSDataImporter::LAMMPSAtomStyle style) { _atomStyle = style; } - protected: /// \brief Writes the particles of one animation frame to the current output file. - virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) override; + virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) override; private: /// Selects the kind of data file to write. - PropertyField _atomStyle; + DECLARE_MODIFIABLE_PROPERTY_FIELD(LAMMPSDataImporter::LAMMPSAtomStyle, atomStyle, setAtomStyle); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_atomStyle); }; OVITO_END_INLINE_NAMESPACE @@ -73,4 +65,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_LAMMPS_DATA_FILE_EXPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/lammps/LAMMPSDumpExporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/export/lammps/LAMMPSDumpExporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/export/lammps/LAMMPSDumpExporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/lammps/LAMMPSDumpExporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,20 +22,26 @@ #include #include #include -#include +#include #include "LAMMPSDumpExporter.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Export) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, LAMMPSDumpExporter, FileColumnParticleExporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(LAMMPSDumpExporter, FileColumnParticleExporter); /****************************************************************************** * Writes the particles of one animation frame to the current output file. ******************************************************************************/ -bool LAMMPSDumpExporter::exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progress) +bool LAMMPSDumpExporter::exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) { + // Get particle data to be exported. + PipelineFlowState state; + if(!getParticleData(sceneNode, time, state, taskManager)) + return false; + + SynchronousTask exportTask(taskManager); + // Get particle positions. - const PipelineFlowState& state = getParticleData(sceneNode, time); ParticlePropertyObject* posProperty = ParticlePropertyObject::findInState(state, ParticleProperty::PositionProperty); // Get simulation cell info. @@ -140,18 +146,18 @@ textStream() << '\n'; OutputColumnWriter columnWriter(mapping, state); - if(progress) progress->setMaximum(100); + exportTask.setProgressMaximum(1000); for(size_t i = 0; i < atomsCount; i++) { columnWriter.writeParticle(i, textStream()); - if(progress && (i % 4096) == 0) { - progress->setValue((quint64)i * 100 / atomsCount); - if(progress->wasCanceled()) + if((i % 4096) == 0) { + exportTask.setProgressValue((quint64)i * 1000 / atomsCount); + if(exportTask.isCanceled()) return false; } } - return true; + return !exportTask.isCanceled(); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/lammps/LAMMPSDumpExporter.h ovito-2.9.0+dfsg1/src/plugins/particles/export/lammps/LAMMPSDumpExporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/export/lammps/LAMMPSDumpExporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/lammps/LAMMPSDumpExporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_LAMMPS_DUMP_FILE_EXPORTER_H -#define __OVITO_LAMMPS_DUMP_FILE_EXPORTER_H +#pragma once + #include #include "../FileColumnParticleExporter.h" @@ -46,7 +46,7 @@ protected: /// \brief Writes the particles of one animation frame to the current output file. - virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) override; + virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) override; private: @@ -59,4 +59,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_LAMMPS_DUMP_FILE_EXPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/OutputColumnMapping.h ovito-2.9.0+dfsg1/src/plugins/particles/export/OutputColumnMapping.h --- ovito-2.8.1+dfsg2/src/plugins/particles/export/OutputColumnMapping.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/OutputColumnMapping.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OUTPUT_COLUMN_MAPPING_H -#define __OVITO_OUTPUT_COLUMN_MAPPING_H +#pragma once + #include #include @@ -112,4 +112,4 @@ Q_DECLARE_METATYPE(Ovito::Particles::OutputColumnMapping); -#endif // __OVITO_OUTPUT_COLUMN_MAPPING_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/ParticleExporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/export/ParticleExporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/export/ParticleExporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/ParticleExporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -21,14 +21,14 @@ #include #include -#include +#include #include #include #include "ParticleExporter.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Export) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ParticleExporter, FileExporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ParticleExporter, FileExporter); /****************************************************************************** * Constructs a new instance of the class. @@ -53,14 +53,17 @@ * Evaluates the pipeline of an ObjectNode and makes sure that the data to be * exported contains particles and throws an exception if not. ******************************************************************************/ -const PipelineFlowState& ParticleExporter::getParticleData(SceneNode* sceneNode, TimePoint time) +bool ParticleExporter::getParticleData(SceneNode* sceneNode, TimePoint time, PipelineFlowState& state, TaskManager& taskManager) { ObjectNode* objectNode = dynamic_object_cast(sceneNode); if(!objectNode) throwException(tr("The scene node to be exported is not an object node.")); // Evaluate pipeline of object node. - const PipelineFlowState& state = objectNode->evalPipeline(time); + auto evalFuture = objectNode->evaluatePipelineAsync(PipelineEvalRequest(time, false)); + if(!taskManager.waitForTask(evalFuture)) + return false; + state = evalFuture.result(); if(state.isEmpty()) throwException(tr("The object to be exported does not contain any data.")); @@ -76,7 +79,7 @@ } } - return state; + return true; } /****************************************************************************** @@ -111,17 +114,14 @@ /****************************************************************************** * Exports a single animation frame to the current output file. *****************************************************************************/ -bool ParticleExporter::exportFrame(int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) +bool ParticleExporter::exportFrame(int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) { - if(!FileExporter::exportFrame(frameNumber, time, filePath, progressDisplay)) + if(!FileExporter::exportFrame(frameNumber, time, filePath, taskManager)) return false; - if(progressDisplay) - progressDisplay->setStatusText(tr("Exporting frame %1 to file '%2'.").arg(frameNumber).arg(filePath)); - // Export the first scene node from the selection set. if(!outputData().empty()) - return exportObject(outputData().front(), frameNumber, time, filePath, progressDisplay); + return exportObject(outputData().front(), frameNumber, time, filePath, taskManager); else throwException(tr("The selection set to be exported is empty.")); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/ParticleExporter.h ovito-2.9.0+dfsg1/src/plugins/particles/export/ParticleExporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/export/ParticleExporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/ParticleExporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_EXPORTER_H -#define __OVITO_PARTICLE_EXPORTER_H +#pragma once + #include #include @@ -39,7 +39,7 @@ /// \brief Evaluates the pipeline of an ObjectNode and makes sure that the data to be /// exported contains particles and throws an exception if not. - const PipelineFlowState& getParticleData(SceneNode* sceneNode, TimePoint time); + bool getParticleData(SceneNode* sceneNode, TimePoint time, PipelineFlowState& state, TaskManager& taskManager); /// \brief Selects the natural scene nodes to be exported by this exporter under normal circumstances. virtual void selectStandardOutputData() override; @@ -62,7 +62,7 @@ CompressedTextWriter& textStream() { return *_outputStream; } /// \brief Exports a single animation frame to the current output file. - virtual bool exportFrame(int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) override; + virtual bool exportFrame(int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) override; /// \brief Writes the data of one object at one animation frame to the current output file. /// \param sceneNode The object to be exported. @@ -71,7 +71,7 @@ /// \param filePath The path of the output file. /// \throws Exception on error. /// \return \a false when the operation has been canceled by the user; \a true on success. - virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) = 0; + virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) = 0; private: @@ -81,8 +81,6 @@ /// The stream object used to write into the output file. std::unique_ptr _outputStream; -private: - Q_OBJECT OVITO_OBJECT }; @@ -91,4 +89,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_EXPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/vasp/POSCARExporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/export/vasp/POSCARExporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/export/vasp/POSCARExporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/vasp/POSCARExporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,20 +23,26 @@ #include #include #include -#include +#include #include "POSCARExporter.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Export) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, POSCARExporter, ParticleExporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(POSCARExporter, ParticleExporter); /****************************************************************************** * Writes the particles of one animation frame to the current output file. ******************************************************************************/ -bool POSCARExporter::exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progress) +bool POSCARExporter::exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) { - // Get particle positions. - const PipelineFlowState& state = getParticleData(sceneNode, time); + // Get particle data to be exported. + PipelineFlowState state; + if(!getParticleData(sceneNode, time, state, taskManager)) + return false; + + SynchronousTask exportTask(taskManager); + + // Get particle positions and velocities. ParticlePropertyObject* posProperty = ParticlePropertyObject::findInState(state, ParticleProperty::PositionProperty); ParticlePropertyObject* velocityProperty = ParticlePropertyObject::findInState(state, ParticleProperty::VelocityProperty); @@ -92,7 +98,7 @@ size_t totalProgressCount = posProperty->size(); if(velocityProperty) totalProgressCount += posProperty->size(); size_t currentProgress = 0; - if(progress) progress->setMaximum(100); + exportTask.setProgressMaximum(100); // Write atomic positions. textStream() << "Cartesian\n"; @@ -105,9 +111,9 @@ textStream() << (p->x() - origin.x()) << ' ' << (p->y() - origin.y()) << ' ' << (p->z() - origin.z()) << '\n'; currentProgress++; - if(progress && (currentProgress % 1000) == 0) { - progress->setValue(currentProgress * 100 / totalProgressCount); - if(progress->wasCanceled()) + if((currentProgress % 1000) == 0) { + exportTask.setProgressValue(currentProgress * 100 / totalProgressCount); + if(exportTask.isCanceled()) return false; } } @@ -125,16 +131,16 @@ textStream() << v->x() << ' ' << v->y() << ' ' << v->z() << '\n'; currentProgress++; - if(progress && (currentProgress % 1000) == 0) { - progress->setValue(currentProgress * 100 / totalProgressCount); - if(progress->wasCanceled()) + if((currentProgress % 1000) == 0) { + exportTask.setProgressValue(currentProgress * 100 / totalProgressCount); + if(exportTask.isCanceled()) return false; } } } } - return true; + return !exportTask.isCanceled(); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/vasp/POSCARExporter.h ovito-2.9.0+dfsg1/src/plugins/particles/export/vasp/POSCARExporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/export/vasp/POSCARExporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/vasp/POSCARExporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_POSCAR_EXPORTER_H -#define __OVITO_POSCAR_EXPORTER_H +#pragma once + #include #include "../ParticleExporter.h" @@ -46,7 +46,7 @@ protected: /// \brief Writes the particles of one animation frame to the current output file. - virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) override; + virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) override; private: @@ -59,4 +59,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_POSCAR_EXPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/xyz/XYZExporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/export/xyz/XYZExporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/export/xyz/XYZExporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/xyz/XYZExporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,22 +22,28 @@ #include #include #include -#include +#include #include "XYZExporter.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Export) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, XYZExporter, FileColumnParticleExporter); -DEFINE_FLAGS_PROPERTY_FIELD(XYZExporter, _subFormat, "XYZSubFormat", PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(XYZExporter, _subFormat, "Format style"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(XYZExporter, FileColumnParticleExporter); +DEFINE_FLAGS_PROPERTY_FIELD(XYZExporter, subFormat, "XYZSubFormat", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(XYZExporter, subFormat, "Format style"); /****************************************************************************** * Writes the particles of one animation frame to the current output file. ******************************************************************************/ -bool XYZExporter::exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progress) +bool XYZExporter::exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) { + // Get particle data to be exported. + PipelineFlowState state; + if(!getParticleData(sceneNode, time, state, taskManager)) + return false; + + SynchronousTask exportTask(taskManager); + // Get particle positions. - const PipelineFlowState& state = getParticleData(sceneNode, time); ParticlePropertyObject* posProperty = ParticlePropertyObject::findInState(state, ParticleProperty::PositionProperty); size_t atomsCount = posProperty->size(); @@ -153,18 +159,18 @@ } textStream() << '\n'; - if(progress) progress->setMaximum(100); + exportTask.setProgressMaximum(100); for(size_t i = 0; i < atomsCount; i++) { columnWriter.writeParticle(i, textStream()); - if(progress && (i % 4096) == 0) { - progress->setValue((quint64)i * 100 / atomsCount); - if(progress->wasCanceled()) + if((i % 4096) == 0) { + exportTask.setProgressValue((quint64)i * 100 / atomsCount); + if(exportTask.isCanceled()) return false; } } - return true; + return !exportTask.isCanceled(); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/export/xyz/XYZExporter.h ovito-2.9.0+dfsg1/src/plugins/particles/export/xyz/XYZExporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/export/xyz/XYZExporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/export/xyz/XYZExporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_XYZ_FILE_EXPORTER_H -#define __OVITO_XYZ_FILE_EXPORTER_H +#pragma once + #include #include "../FileColumnParticleExporter.h" @@ -45,7 +45,7 @@ /// \brief Constructs a new instance of this class. Q_INVOKABLE XYZExporter(DataSet* dataset) : FileColumnParticleExporter(dataset), _subFormat(ExtendedFormat) { - INIT_PROPERTY_FIELD(XYZExporter::_subFormat); + INIT_PROPERTY_FIELD(subFormat); } /// \brief Returns the file filter that specifies the files that can be exported by this service. @@ -54,26 +54,18 @@ /// \brief Returns the filter description that is displayed in the drop-down box of the file dialog. virtual QString fileFilterDescription() override { return tr("XYZ File"); } - /// Returns the format variant being written by this XYZ file exporter. - XYZSubFormat subFormat() const { return _subFormat; } - - /// Sets the kind of XYZ file to write. - void setSubFormat(XYZSubFormat subFormat) { _subFormat = subFormat; } - protected: /// \brief Writes the particles of one animation frame to the current output file. - virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) override; + virtual bool exportObject(SceneNode* sceneNode, int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) override; private: /// Selects the kind of XYZ file to write. - PropertyField _subFormat; + DECLARE_MODIFIABLE_PROPERTY_FIELD(XYZSubFormat, subFormat, setSubFormat); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_subFormat); }; OVITO_END_INLINE_NAMESPACE @@ -84,4 +76,4 @@ Q_DECLARE_METATYPE(Ovito::Particles::XYZExporter::XYZSubFormat); Q_DECLARE_TYPEINFO(Ovito::Particles::XYZExporter::XYZSubFormat, Q_PRIMITIVE_TYPE); -#endif // __OVITO_XYZ_FILE_EXPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/CMakeLists.txt ovito-2.9.0+dfsg1/src/plugins/particles/gui/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/CMakeLists.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -65,6 +65,7 @@ modifier/selection/ManualSelectionModifierEditor.cpp modifier/properties/ComputePropertyModifierEditor.cpp modifier/properties/FreezePropertyModifierEditor.cpp + modifier/fields/CreateIsosurfaceModifierEditor.cpp util/ParticlePropertyComboBox.cpp util/CutoffRadiusPresetsUI.cpp util/ParticleInformationApplet.cpp @@ -72,6 +73,8 @@ util/ParticlePropertyParameterUI.cpp util/BondPropertyComboBox.cpp util/BondPropertyParameterUI.cpp + util/FieldQuantityComboBox.cpp + util/FieldQuantityParameterUI.cpp util/CreateTrajectoryApplet.cpp util/ParticleSettingsPage.cpp import/InputColumnMappingDialog.cpp diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/export/FileColumnParticleExporterEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/export/FileColumnParticleExporterEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/export/FileColumnParticleExporterEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/export/FileColumnParticleExporterEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,11 +22,13 @@ #include #include #include +#include +#include #include "FileColumnParticleExporterEditor.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Export) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, FileColumnParticleExporterEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(FileColumnParticleExporterEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(FileColumnParticleExporter, FileColumnParticleExporterEditor); /****************************************************************************** @@ -101,7 +103,10 @@ for(SceneNode* node : particleExporter->outputData()) { try { - const PipelineFlowState& state = particleExporter->getParticleData(node, node->dataset()->animationSettings()->time()); + ProgressDialog progressDialog(container(), particleExporter->dataset()->container()->taskManager()); + PipelineFlowState state; + if(!particleExporter->getParticleData(node, node->dataset()->animationSettings()->time(), state, progressDialog.taskManager())) + continue; bool hasParticleIdentifiers = false; for(DataObject* o : state.objects()) { ParticlePropertyObject* property = dynamic_object_cast(o); @@ -128,6 +133,9 @@ _columnMappingWidget->addItems(ex.messages()); } } + + // Update the settings stored in the exporter to match the current settings in the UI. + saveChanges(particleExporter); } /****************************************************************************** @@ -165,13 +173,10 @@ } /****************************************************************************** -* Is called when the user checked/unchecked an item. +* This writes the settings made in the UI back to the exporter. ******************************************************************************/ -void FileColumnParticleExporterEditor::onListChanged() +void FileColumnParticleExporterEditor::saveChanges(FileColumnParticleExporter* particleExporter) { - FileColumnParticleExporter* particleExporter = dynamic_object_cast(editObject()); - if(!particleExporter) return; - OutputColumnMapping newMapping; for(int index = 0; index < _columnMappingWidget->count(); index++) { if(_columnMappingWidget->item(index)->checkState() == Qt::Checked) { @@ -179,11 +184,23 @@ } } particleExporter->setColumnMapping(newMapping); +} + +/****************************************************************************** +* Is called when the user checked/unchecked an item. +******************************************************************************/ +void FileColumnParticleExporterEditor::onListChanged() +{ + FileColumnParticleExporter* particleExporter = dynamic_object_cast(editObject()); + if(!particleExporter) return; + + // Stores current settings in exporter object. + saveChanges(particleExporter); // Remember the output column mapping for the next time. QSettings settings; settings.beginGroup("exporter/particles/"); - settings.setValue("columnmapping", newMapping.toByteArray()); + settings.setValue("columnmapping", particleExporter->columnMapping().toByteArray()); settings.endGroup(); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/export/FileColumnParticleExporterEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/export/FileColumnParticleExporterEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/export/FileColumnParticleExporterEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/export/FileColumnParticleExporterEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,12 +19,13 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FILE_COLUMN_PARTICLE_EXPORTER_EDITOR_H -#define __OVITO_FILE_COLUMN_PARTICLE_EXPORTER_EDITOR_H +#pragma once + #include #include #include +#include #include namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Export) @@ -57,6 +58,9 @@ /// Populates the column mapping list box with an entry. void insertPropertyItem(ParticlePropertyReference propRef, const QString& displayName, const OutputColumnMapping& columnMapping); + /// This writes the settings made in the UI back to the exporter. + void saveChanges(FileColumnParticleExporter* particleExporter); + QListWidget* _columnMappingWidget; Q_OBJECT @@ -67,4 +71,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_FILE_COLUMN_PARTICLE_EXPORTER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/export/lammps/LAMMPSDataExporterEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/export/lammps/LAMMPSDataExporterEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/export/lammps/LAMMPSDataExporterEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/export/lammps/LAMMPSDataExporterEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Export) OVITO_BEGIN_INLINE_NAMESPACE(Formats) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, LAMMPSDataExporterEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(LAMMPSDataExporterEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(LAMMPSDataExporter, LAMMPSDataExporterEditor); /****************************************************************************** @@ -45,7 +45,7 @@ layout->setColumnStretch(1,1); layout->addWidget(new QLabel(tr("LAMMPS atom style:")), 0, 0); - VariantComboBoxParameterUI* atomStyleUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(LAMMPSDataExporter::_atomStyle)); + VariantComboBoxParameterUI* atomStyleUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(LAMMPSDataExporter::atomStyle)); atomStyleUI->comboBox()->addItem("angle", QVariant::fromValue(LAMMPSDataImporter::AtomStyle_Angle)); atomStyleUI->comboBox()->addItem("atomic", QVariant::fromValue(LAMMPSDataImporter::AtomStyle_Atomic)); atomStyleUI->comboBox()->addItem("bond", QVariant::fromValue(LAMMPSDataImporter::AtomStyle_Bond)); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/export/lammps/LAMMPSDataExporterEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/export/lammps/LAMMPSDataExporterEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/export/lammps/LAMMPSDataExporterEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/export/lammps/LAMMPSDataExporterEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_LAMMPS_DATA_FILE_EXPORTER_EDITOR_H -#define __OVITO_LAMMPS_DATA_FILE_EXPORTER_EDITOR_H +#pragma once + #include #include @@ -54,4 +54,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_LAMMPS_DATA_FILE_EXPORTER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/export/xyz/XYZExporterEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/export/xyz/XYZExporterEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/export/xyz/XYZExporterEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/export/xyz/XYZExporterEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,7 +26,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Export) OVITO_BEGIN_INLINE_NAMESPACE(Formats) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, XYZExporterEditor, FileColumnParticleExporterEditor); +IMPLEMENT_OVITO_OBJECT(XYZExporterEditor, FileColumnParticleExporterEditor); SET_OVITO_OBJECT_EDITOR(XYZExporter, XYZExporterEditor); /****************************************************************************** @@ -44,7 +44,7 @@ layout->setColumnStretch(1,1); layout->addWidget(new QLabel(tr("Format style:")), 0, 0); - VariantComboBoxParameterUI* subFormatUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(XYZExporter::_subFormat)); + VariantComboBoxParameterUI* subFormatUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(XYZExporter::subFormat)); subFormatUI->comboBox()->addItem("Extended (default)", QVariant::fromValue(XYZExporter::ExtendedFormat)); subFormatUI->comboBox()->addItem("Parcas", QVariant::fromValue(XYZExporter::ParcasFormat)); layout->addWidget(subFormatUI->comboBox(), 0, 1); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/export/xyz/XYZExporterEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/export/xyz/XYZExporterEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/export/xyz/XYZExporterEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/export/xyz/XYZExporterEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_XYZ_EXPORTER_EDITOR_H -#define __OVITO_XYZ_EXPORTER_EDITOR_H +#pragma once + #include #include @@ -54,4 +54,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_XYZ_EXPORTER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/InputColumnMappingDialog.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/InputColumnMappingDialog.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/InputColumnMappingDialog.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/InputColumnMappingDialog.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -128,7 +128,7 @@ accept(); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); return; } } @@ -301,7 +301,7 @@ settings.endArray(); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } @@ -349,7 +349,7 @@ } } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/InputColumnMappingDialog.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/InputColumnMappingDialog.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/InputColumnMappingDialog.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/InputColumnMappingDialog.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_INPUT_COLUMN_MAPPING_DIALOG_H -#define __OVITO_INPUT_COLUMN_MAPPING_DIALOG_H +#pragma once + #include #include @@ -82,4 +82,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_INPUT_COLUMN_MAPPING_DIALOG_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/lammps/LAMMPSBinaryDumpImporterEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/lammps/LAMMPSBinaryDumpImporterEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/lammps/LAMMPSBinaryDumpImporterEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/lammps/LAMMPSBinaryDumpImporterEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,7 +30,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, LAMMPSBinaryDumpImporterEditor, FileImporterEditor); +IMPLEMENT_OVITO_OBJECT(LAMMPSBinaryDumpImporterEditor, FileImporterEditor); SET_OVITO_OBJECT_EDITOR(LAMMPSBinaryDumpImporter, LAMMPSBinaryDumpImporterEditor); /****************************************************************************** @@ -116,7 +116,7 @@ layout->addWidget(animFramesBox); // Multi-timestep file - BooleanParameterUI* multitimestepUI = new BooleanParameterUI(this, PROPERTY_FIELD(ParticleImporter::_isMultiTimestepFile)); + BooleanParameterUI* multitimestepUI = new BooleanParameterUI(this, PROPERTY_FIELD(ParticleImporter::isMultiTimestepFile)); sublayout->addWidget(multitimestepUI->checkBox()); QGroupBox* columnMappingBox = new QGroupBox(tr("File columns"), rollout); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/lammps/LAMMPSBinaryDumpImporterEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/lammps/LAMMPSBinaryDumpImporterEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/lammps/LAMMPSBinaryDumpImporterEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/lammps/LAMMPSBinaryDumpImporterEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_LAMMPS_BINARY_DUMP_IMPORTER_EDITOR_H -#define __OVITO_LAMMPS_BINARY_DUMP_IMPORTER_EDITOR_H +#pragma once + #include #include @@ -66,4 +66,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_LAMMPS_BINARY_DUMP_IMPORTER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/lammps/LAMMPSDataImporterEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/lammps/LAMMPSDataImporterEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/lammps/LAMMPSDataImporterEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/lammps/LAMMPSDataImporterEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,7 +25,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, LAMMPSDataImporterEditor, FileImporterEditor); +IMPLEMENT_OVITO_OBJECT(LAMMPSDataImporterEditor, FileImporterEditor); SET_OVITO_OBJECT_EDITOR(LAMMPSDataImporter, LAMMPSDataImporterEditor); /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/lammps/LAMMPSDataImporterEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/lammps/LAMMPSDataImporterEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/lammps/LAMMPSDataImporterEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/lammps/LAMMPSDataImporterEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_LAMMPS_DATA_IMPORTER_EDITOR_H -#define __OVITO_LAMMPS_DATA_IMPORTER_EDITOR_H +#pragma once + #include #include @@ -58,4 +58,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_LAMMPS_DATA_IMPORTER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/lammps/LAMMPSTextDumpImporterEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/lammps/LAMMPSTextDumpImporterEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/lammps/LAMMPSTextDumpImporterEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/lammps/LAMMPSTextDumpImporterEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,7 +30,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, LAMMPSTextDumpImporterEditor, FileImporterEditor); +IMPLEMENT_OVITO_OBJECT(LAMMPSTextDumpImporterEditor, FileImporterEditor); SET_OVITO_OBJECT_EDITOR(LAMMPSTextDumpImporter, LAMMPSTextDumpImporterEditor); /****************************************************************************** @@ -80,7 +80,7 @@ layout->addWidget(animFramesBox); // Multi-timestep file - BooleanParameterUI* multitimestepUI = new BooleanParameterUI(this, PROPERTY_FIELD(ParticleImporter::_isMultiTimestepFile)); + BooleanParameterUI* multitimestepUI = new BooleanParameterUI(this, PROPERTY_FIELD(ParticleImporter::isMultiTimestepFile)); sublayout->addWidget(multitimestepUI->checkBox()); QGroupBox* columnMappingBox = new QGroupBox(tr("File columns"), rollout); @@ -88,7 +88,7 @@ sublayout->setContentsMargins(4,4,4,4); layout->addWidget(columnMappingBox); - BooleanRadioButtonParameterUI* useCustomMappingUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(LAMMPSTextDumpImporter::_useCustomColumnMapping)); + BooleanRadioButtonParameterUI* useCustomMappingUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(LAMMPSTextDumpImporter::useCustomColumnMapping)); useCustomMappingUI->buttonFalse()->setText(tr("Automatic mapping")); sublayout->addWidget(useCustomMappingUI->buttonFalse()); useCustomMappingUI->buttonTrue()->setText(tr("User-defined mapping to particle properties")); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/lammps/LAMMPSTextDumpImporterEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/lammps/LAMMPSTextDumpImporterEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/lammps/LAMMPSTextDumpImporterEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/lammps/LAMMPSTextDumpImporterEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_LAMMPS_TEXT_DUMP_IMPORTER_EDITOR_H -#define __OVITO_LAMMPS_TEXT_DUMP_IMPORTER_EDITOR_H +#pragma once + #include #include @@ -63,4 +63,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_LAMMPS_TEXT_DUMP_IMPORTER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/xyz/XYZImporterEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/xyz/XYZImporterEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/xyz/XYZImporterEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/xyz/XYZImporterEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, XYZImporterEditor, FileImporterEditor); +IMPLEMENT_OVITO_OBJECT(XYZImporterEditor, FileImporterEditor); SET_OVITO_OBJECT_EDITOR(XYZImporter, XYZImporterEditor); /****************************************************************************** @@ -133,7 +133,7 @@ layout->addWidget(animFramesBox); // Multi-timestep file - BooleanParameterUI* multitimestepUI = new BooleanParameterUI(this, PROPERTY_FIELD(ParticleImporter::_isMultiTimestepFile)); + BooleanParameterUI* multitimestepUI = new BooleanParameterUI(this, PROPERTY_FIELD(ParticleImporter::isMultiTimestepFile)); sublayout->addWidget(multitimestepUI->checkBox()); QGroupBox* columnMappingBox = new QGroupBox(tr("File columns"), rollout); @@ -151,7 +151,7 @@ layout->addWidget(settingsBox); // Auto-rescale reduced coordinates. - BooleanParameterUI* rescaleReducedUI = new BooleanParameterUI(this, PROPERTY_FIELD(XYZImporter::_autoRescaleCoordinates)); + BooleanParameterUI* rescaleReducedUI = new BooleanParameterUI(this, PROPERTY_FIELD(XYZImporter::autoRescaleCoordinates)); sublayout->addWidget(rescaleReducedUI->checkBox()); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/xyz/XYZImporterEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/xyz/XYZImporterEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/import/xyz/XYZImporterEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/import/xyz/XYZImporterEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_XYZ_IMPORTER_EDITOR_H -#define __OVITO_XYZ_IMPORTER_EDITOR_H +#pragma once + #include #include @@ -66,4 +66,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_XYZ_IMPORTER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/binandreduce/BinAndReduceModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/binandreduce/BinAndReduceModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/binandreduce/BinAndReduceModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/binandreduce/BinAndReduceModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -42,7 +42,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, BinAndReduceModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(BinAndReduceModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(BinAndReduceModifier, BinAndReduceModifierEditor); /****************************************************************************** @@ -58,13 +58,13 @@ layout->setContentsMargins(4,4,4,4); layout->setSpacing(4); - ParticlePropertyParameterUI* sourcePropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::_sourceProperty)); + ParticlePropertyParameterUI* sourcePropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::sourceProperty)); layout->addWidget(new QLabel(tr("Particle property:"), rollout)); layout->addWidget(sourcePropertyUI->comboBox()); QGridLayout* gridlayout = new QGridLayout(); gridlayout->addWidget(new QLabel(tr("Reduction operation:"), rollout), 0, 0); - VariantComboBoxParameterUI* reductionOperationPUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::_reductionOperation)); + VariantComboBoxParameterUI* reductionOperationPUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::reductionOperation)); reductionOperationPUI->comboBox()->addItem(tr("mean"), qVariantFromValue(BinAndReduceModifier::RED_MEAN)); reductionOperationPUI->comboBox()->addItem(tr("sum"), qVariantFromValue(BinAndReduceModifier::RED_SUM)); reductionOperationPUI->comboBox()->addItem(tr("sum divided by bin volume"), qVariantFromValue(BinAndReduceModifier::RED_SUM_VOL)); @@ -75,7 +75,7 @@ gridlayout = new QGridLayout(); gridlayout->addWidget(new QLabel(tr("Binning direction:"), rollout), 0, 0); - VariantComboBoxParameterUI* binDirectionPUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::_binDirection)); + VariantComboBoxParameterUI* binDirectionPUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::binDirection)); binDirectionPUI->comboBox()->addItem("cell vector 1", qVariantFromValue(BinAndReduceModifier::CELL_VECTOR_1)); binDirectionPUI->comboBox()->addItem("cell vector 2", qVariantFromValue(BinAndReduceModifier::CELL_VECTOR_2)); binDirectionPUI->comboBox()->addItem("cell vector 3", qVariantFromValue(BinAndReduceModifier::CELL_VECTOR_3)); @@ -85,7 +85,7 @@ gridlayout->addWidget(binDirectionPUI->comboBox(), 0, 1); layout->addLayout(gridlayout); - _firstDerivativePUI = new BooleanParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::_firstDerivative)); + _firstDerivativePUI = new BooleanParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::firstDerivative)); _firstDerivativePUI->setEnabled(false); layout->addWidget(_firstDerivativePUI->checkBox()); @@ -95,10 +95,10 @@ gridlayout->setColumnStretch(2, 1); // Number of bins parameters. - IntegerParameterUI* numBinsXPUI = new IntegerParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::_numberOfBinsX)); + IntegerParameterUI* numBinsXPUI = new IntegerParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::numberOfBinsX)); gridlayout->addWidget(numBinsXPUI->label(), 0, 0); gridlayout->addLayout(numBinsXPUI->createFieldLayout(), 0, 1); - _numBinsYPUI = new IntegerParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::_numberOfBinsY)); + _numBinsYPUI = new IntegerParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::numberOfBinsY)); gridlayout->addLayout(_numBinsYPUI->createFieldLayout(), 0, 2); _numBinsYPUI->setEnabled(false); @@ -124,7 +124,7 @@ sublayout->setContentsMargins(4,4,4,4); layout->addWidget(inputBox); - BooleanParameterUI* onlySelectedUI = new BooleanParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::_onlySelected)); + BooleanParameterUI* onlySelectedUI = new BooleanParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::onlySelected)); sublayout->addWidget(onlySelectedUI->checkBox()); // Axes. @@ -132,13 +132,13 @@ QVBoxLayout* axesSublayout = new QVBoxLayout(axesBox); axesSublayout->setContentsMargins(4,4,4,4); layout->addWidget(axesBox); - BooleanParameterUI* rangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::_fixPropertyAxisRange)); + BooleanParameterUI* rangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::fixPropertyAxisRange)); axesSublayout->addWidget(rangeUI->checkBox()); QHBoxLayout* hlayout = new QHBoxLayout(); axesSublayout->addLayout(hlayout); - FloatParameterUI* startPUI = new FloatParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::_propertyAxisRangeStart)); - FloatParameterUI* endPUI = new FloatParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::_propertyAxisRangeEnd)); + FloatParameterUI* startPUI = new FloatParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::propertyAxisRangeStart)); + FloatParameterUI* endPUI = new FloatParameterUI(this, PROPERTY_FIELD(BinAndReduceModifier::propertyAxisRangeEnd)); hlayout->addWidget(new QLabel(tr("From:"))); hlayout->addLayout(startPUI->createFieldLayout()); hlayout->addSpacing(12); @@ -349,7 +349,7 @@ } } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/binandreduce/BinAndReduceModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/binandreduce/BinAndReduceModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/binandreduce/BinAndReduceModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/binandreduce/BinAndReduceModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BIN_AND_REDUCE_MODIFIER_EDITOR_H -#define __OVITO_BIN_AND_REDUCE_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -104,4 +104,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_BIN_AND_REDUCE_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/bondangle/BondAngleAnalysisModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/bondangle/BondAngleAnalysisModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/bondangle/BondAngleAnalysisModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/bondangle/BondAngleAnalysisModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, BondAngleAnalysisModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(BondAngleAnalysisModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(BondAngleAnalysisModifier, BondAngleAnalysisModifierEditor); /****************************************************************************** @@ -44,7 +44,7 @@ layout1->setSpacing(4); // Use only selected particles. - BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::_onlySelectedParticles)); + BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::onlySelectedParticles)); layout1->addWidget(onlySelectedParticlesUI->checkBox()); // Status label. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/bondangle/BondAngleAnalysisModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/bondangle/BondAngleAnalysisModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/bondangle/BondAngleAnalysisModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/bondangle/BondAngleAnalysisModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BOND_ANGLE_ANALYSIS_MODIFIER_EDITOR_H -#define __OVITO_BOND_ANGLE_ANALYSIS_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_BOND_ANGLE_ANALYSIS_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/centrosymmetry/CentroSymmetryModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/centrosymmetry/CentroSymmetryModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/centrosymmetry/CentroSymmetryModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/centrosymmetry/CentroSymmetryModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,7 +26,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, CentroSymmetryModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(CentroSymmetryModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(CentroSymmetryModifier, CentroSymmetryModifierEditor); /****************************************************************************** @@ -49,7 +49,7 @@ layout1->addLayout(layout2); // Num neighbors parameter. - IntegerParameterUI* numNeighborsPUI = new IntegerParameterUI(this, PROPERTY_FIELD(CentroSymmetryModifier::_numNeighbors)); + IntegerParameterUI* numNeighborsPUI = new IntegerParameterUI(this, PROPERTY_FIELD(CentroSymmetryModifier::numNeighbors)); layout2->addWidget(numNeighborsPUI->label(), 0, 0); layout2->addLayout(numNeighborsPUI->createFieldLayout(), 0, 1); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/centrosymmetry/CentroSymmetryModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/centrosymmetry/CentroSymmetryModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/centrosymmetry/CentroSymmetryModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/centrosymmetry/CentroSymmetryModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CENTRO_SYMMETRY_MODIFIER_EDITOR_H -#define __OVITO_CENTRO_SYMMETRY_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CENTRO_SYMMETRY_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/cluster/ClusterAnalysisModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/cluster/ClusterAnalysisModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/cluster/ClusterAnalysisModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/cluster/ClusterAnalysisModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,11 +23,12 @@ #include #include #include +#include #include "ClusterAnalysisModifierEditor.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, ClusterAnalysisModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(ClusterAnalysisModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(ClusterAnalysisModifier, ClusterAnalysisModifierEditor); /****************************************************************************** @@ -45,20 +46,30 @@ QGridLayout* gridlayout = new QGridLayout(); gridlayout->setContentsMargins(4,4,4,4); - gridlayout->setColumnStretch(1, 1); + gridlayout->setColumnStretch(2, 1); + gridlayout->setColumnMinimumWidth(0, 10); + + gridlayout->addWidget(new QLabel(tr("Neighbor mode:")), 0, 0, 1, 3); + + IntegerRadioButtonParameterUI* neighborModePUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(ClusterAnalysisModifier::neighborMode)); + QRadioButton* cutoffModeBtn = neighborModePUI->addRadioButton(ClusterAnalysisModifier::CutoffRange, tr("Cutoff distance:")); + gridlayout->addWidget(cutoffModeBtn, 1, 1); + QRadioButton* bondModeBtn = neighborModePUI->addRadioButton(ClusterAnalysisModifier::Bonding, tr("Bonds")); + gridlayout->addWidget(bondModeBtn, 2, 1, 1, 2); // Cutoff parameter. - FloatParameterUI* cutoffRadiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(ClusterAnalysisModifier::_cutoff)); - gridlayout->addWidget(cutoffRadiusPUI->label(), 0, 0); - gridlayout->addLayout(cutoffRadiusPUI->createFieldLayout(), 0, 1); + FloatParameterUI* cutoffRadiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(ClusterAnalysisModifier::cutoff)); + gridlayout->addLayout(cutoffRadiusPUI->createFieldLayout(), 1, 2); + cutoffRadiusPUI->setEnabled(false); + connect(cutoffModeBtn, &QRadioButton::toggled, cutoffRadiusPUI, &FloatParameterUI::setEnabled); // Sort by size - BooleanParameterUI* sortBySizeUI = new BooleanParameterUI(this, PROPERTY_FIELD(ClusterAnalysisModifier::_sortBySize)); - gridlayout->addWidget(sortBySizeUI->checkBox(), 1, 0, 1, 2); + BooleanParameterUI* sortBySizeUI = new BooleanParameterUI(this, PROPERTY_FIELD(ClusterAnalysisModifier::sortBySize)); + gridlayout->addWidget(sortBySizeUI->checkBox(), 3, 0, 1, 3); // Use only selected particles. - BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(ClusterAnalysisModifier::_onlySelectedParticles)); - gridlayout->addWidget(onlySelectedParticlesUI->checkBox(), 2, 0, 1, 2); + BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(ClusterAnalysisModifier::onlySelectedParticles)); + gridlayout->addWidget(onlySelectedParticlesUI->checkBox(), 4, 0, 1, 3); layout->addLayout(gridlayout); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/cluster/ClusterAnalysisModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/cluster/ClusterAnalysisModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/cluster/ClusterAnalysisModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/cluster/ClusterAnalysisModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CLUSTER_ANALYSIS_MODIFIER_EDITOR_H -#define __OVITO_CLUSTER_ANALYSIS_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -54,4 +54,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CLUSTER_ANALYSIS_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/cna/CommonNeighborAnalysisModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/cna/CommonNeighborAnalysisModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/cna/CommonNeighborAnalysisModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/cna/CommonNeighborAnalysisModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,7 +30,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, CommonNeighborAnalysisModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(CommonNeighborAnalysisModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(CommonNeighborAnalysisModifier, CommonNeighborAnalysisModifierEditor); /****************************************************************************** @@ -46,7 +46,7 @@ layout1->setContentsMargins(4,4,4,4); layout1->setSpacing(6); - IntegerRadioButtonParameterUI* modeUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(CommonNeighborAnalysisModifier::_cnaMode)); + IntegerRadioButtonParameterUI* modeUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(CommonNeighborAnalysisModifier::mode)); QRadioButton* bondModeBtn = modeUI->addRadioButton(CommonNeighborAnalysisModifier::BondMode, tr("Bond-based CNA (without cutoff)")); QRadioButton* adaptiveModeBtn = modeUI->addRadioButton(CommonNeighborAnalysisModifier::AdaptiveCutoffMode, tr("Adaptive CNA (variable cutoff)")); QRadioButton* fixedCutoffModeBtn = modeUI->addRadioButton(CommonNeighborAnalysisModifier::FixedCutoffMode, tr("Conventional CNA (fixed cutoff)")); @@ -60,11 +60,11 @@ gridlayout->setColumnMinimumWidth(0, 20); // Cutoff parameter. - FloatParameterUI* cutoffRadiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(CommonNeighborAnalysisModifier::_cutoff)); + FloatParameterUI* cutoffRadiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(CommonNeighborAnalysisModifier::cutoff)); gridlayout->addWidget(cutoffRadiusPUI->label(), 0, 1); gridlayout->addLayout(cutoffRadiusPUI->createFieldLayout(), 0, 2); - CutoffRadiusPresetsUI* cutoffPresetsPUI = new CutoffRadiusPresetsUI(this, PROPERTY_FIELD(CommonNeighborAnalysisModifier::_cutoff)); + CutoffRadiusPresetsUI* cutoffPresetsPUI = new CutoffRadiusPresetsUI(this, PROPERTY_FIELD(CommonNeighborAnalysisModifier::cutoff)); gridlayout->addWidget(cutoffPresetsPUI->comboBox(), 1, 1, 1, 2); layout1->addLayout(gridlayout); @@ -74,7 +74,7 @@ cutoffPresetsPUI->setEnabled(false); // Use only selected particles. - BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::_onlySelectedParticles)); + BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::onlySelectedParticles)); layout1->addWidget(onlySelectedParticlesUI->checkBox()); // Status label. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/cna/CommonNeighborAnalysisModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/cna/CommonNeighborAnalysisModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/cna/CommonNeighborAnalysisModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/cna/CommonNeighborAnalysisModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COMMON_NEIGHBOR_ANALYSIS_MODIFIER_EDITOR_H -#define __OVITO_COMMON_NEIGHBOR_ANALYSIS_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -54,4 +54,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_COMMON_NEIGHBOR_ANALYSIS_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/coordination/CoordinationNumberModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/coordination/CoordinationNumberModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/coordination/CoordinationNumberModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/coordination/CoordinationNumberModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -32,7 +32,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, CoordinationNumberModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(CoordinationNumberModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(CoordinationNumberModifier, CoordinationNumberModifierEditor); /****************************************************************************** @@ -53,12 +53,12 @@ gridlayout->setColumnStretch(1, 1); // Cutoff parameter. - FloatParameterUI* cutoffRadiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(CoordinationNumberModifier::_cutoff)); + FloatParameterUI* cutoffRadiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(CoordinationNumberModifier::cutoff)); gridlayout->addWidget(cutoffRadiusPUI->label(), 0, 0); gridlayout->addLayout(cutoffRadiusPUI->createFieldLayout(), 0, 1); // Number of bins parameter. - IntegerParameterUI* numBinsPUI = new IntegerParameterUI(this, PROPERTY_FIELD(CoordinationNumberModifier::_numberOfBins)); + IntegerParameterUI* numBinsPUI = new IntegerParameterUI(this, PROPERTY_FIELD(CoordinationNumberModifier::numberOfBins)); gridlayout->addWidget(numBinsPUI->label(), 1, 0); gridlayout->addLayout(numBinsPUI->createFieldLayout(), 1, 1); @@ -166,7 +166,7 @@ } } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/coordination/CoordinationNumberModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/coordination/CoordinationNumberModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/coordination/CoordinationNumberModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/coordination/CoordinationNumberModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COORDINATION_NUMBER_MODIFIER_EDITOR_H -#define __OVITO_COORDINATION_NUMBER_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -78,4 +78,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_COORDINATION_NUMBER_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/diamond/IdentifyDiamondModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/diamond/IdentifyDiamondModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/diamond/IdentifyDiamondModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/diamond/IdentifyDiamondModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, IdentifyDiamondModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(IdentifyDiamondModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(IdentifyDiamondModifier, IdentifyDiamondModifierEditor); /****************************************************************************** @@ -44,7 +44,7 @@ layout1->setSpacing(6); // Use only selected particles. - BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::_onlySelectedParticles)); + BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::onlySelectedParticles)); layout1->addWidget(onlySelectedParticlesUI->checkBox()); // Status label. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/diamond/IdentifyDiamondModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/diamond/IdentifyDiamondModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/diamond/IdentifyDiamondModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/diamond/IdentifyDiamondModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_IDENTIFY_DIAMOND_MODIFIER_EDITOR_H -#define __OVITO_IDENTIFY_DIAMOND_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -54,4 +54,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_IDENTIFY_DIAMOND_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/displacements/CalculateDisplacementsModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/displacements/CalculateDisplacementsModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/displacements/CalculateDisplacementsModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/displacements/CalculateDisplacementsModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,12 +24,14 @@ #include #include #include +#include #include +#include #include "CalculateDisplacementsModifierEditor.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, CalculateDisplacementsModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(CalculateDisplacementsModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(CalculateDisplacementsModifier, CalculateDisplacementsModifierEditor); /****************************************************************************** @@ -45,18 +47,28 @@ layout->setContentsMargins(4,4,4,4); layout->setSpacing(4); - BooleanParameterUI* eliminateCellDeformationUI = new BooleanParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::_eliminateCellDeformation)); - layout->addWidget(eliminateCellDeformationUI->checkBox()); - - BooleanParameterUI* assumeUnwrappedUI = new BooleanParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::_assumeUnwrappedCoordinates)); - layout->addWidget(assumeUnwrappedUI->checkBox()); - #if 0 - BooleanParameterUI* showReferenceUI = new BooleanParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::_referenceShown)); + BooleanParameterUI* showReferenceUI = new BooleanParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::referenceShown)); layout->addWidget(showReferenceUI->checkBox()); #endif - QGroupBox* referenceFrameGroupBox = new QGroupBox(tr("Reference frame")); + QGroupBox* mappingGroupBox = new QGroupBox(tr("Affine mapping")); + layout->addWidget(mappingGroupBox); + + QGridLayout* sublayout1 = new QGridLayout(mappingGroupBox); + sublayout1->setContentsMargins(4,4,4,4); + sublayout1->setSpacing(4); + + IntegerRadioButtonParameterUI* eliminateCellDeformationPUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::affineMapping)); + sublayout1->addWidget(eliminateCellDeformationPUI->addRadioButton(CalculateDisplacementsModifier::NO_MAPPING, tr("Off")), 0, 0); + sublayout1->addWidget(eliminateCellDeformationPUI->addRadioButton(CalculateDisplacementsModifier::TO_REFERENCE_CELL, tr("To reference")), 0, 1); + sublayout1->addWidget(eliminateCellDeformationPUI->addRadioButton(CalculateDisplacementsModifier::TO_CURRENT_CELL, tr("To current")), 1, 1); + + BooleanParameterUI* assumeUnwrappedUI = new BooleanParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::assumeUnwrappedCoordinates)); + layout->addWidget(assumeUnwrappedUI->checkBox()); + + + QGroupBox* referenceFrameGroupBox = new QGroupBox(tr("Reference animation frame")); layout->addWidget(referenceFrameGroupBox); QGridLayout* sublayout = new QGridLayout(referenceFrameGroupBox); @@ -66,12 +78,12 @@ sublayout->setColumnStretch(2, 95); // Add box for selection between absolute and relative reference frames. - BooleanRadioButtonParameterUI* useFrameOffsetUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::_useReferenceFrameOffset)); + BooleanRadioButtonParameterUI* useFrameOffsetUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::useReferenceFrameOffset)); useFrameOffsetUI->buttonTrue()->setText(tr("Relative to current frame")); useFrameOffsetUI->buttonFalse()->setText(tr("Fixed reference configuration")); sublayout->addWidget(useFrameOffsetUI->buttonFalse(), 0, 0, 1, 3); - IntegerParameterUI* frameNumberUI = new IntegerParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::_referenceFrameNumber)); + IntegerParameterUI* frameNumberUI = new IntegerParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::referenceFrameNumber)); frameNumberUI->label()->setText(tr("Frame number:")); sublayout->addWidget(frameNumberUI->label(), 1, 1, 1, 1); sublayout->addLayout(frameNumberUI->createFieldLayout(), 1, 2, 1, 1); @@ -79,7 +91,7 @@ connect(useFrameOffsetUI->buttonFalse(), &QRadioButton::toggled, frameNumberUI, &IntegerParameterUI::setEnabled); sublayout->addWidget(useFrameOffsetUI->buttonTrue(), 2, 0, 1, 3); - IntegerParameterUI* frameOffsetUI = new IntegerParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::_referenceFrameOffset)); + IntegerParameterUI* frameOffsetUI = new IntegerParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::referenceFrameOffset)); frameOffsetUI->label()->setText(tr("Frame offset:")); sublayout->addWidget(frameOffsetUI->label(), 3, 1, 1, 1); sublayout->addLayout(frameOffsetUI->createFieldLayout(), 3, 2, 1, 1); @@ -91,10 +103,10 @@ layout->addWidget(statusLabel()); // Open a sub-editor for the vector display object. - new SubObjectParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::_vectorDisplay), rolloutParams.after(rollout)); + new SubObjectParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::vectorDisplay), rolloutParams.after(rollout)); // Open a sub-editor for the reference object. - new SubObjectParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::_referenceObject), RolloutInsertionParameters().setTitle(tr("Reference"))); + new SubObjectParameterUI(this, PROPERTY_FIELD(CalculateDisplacementsModifier::referenceConfiguration), RolloutInsertionParameters().setTitle(tr("Reference"))); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/displacements/CalculateDisplacementsModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/displacements/CalculateDisplacementsModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/displacements/CalculateDisplacementsModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/displacements/CalculateDisplacementsModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CALCULATE_DISPLACEMENTS_MODIFIER_EDITOR_H -#define __OVITO_CALCULATE_DISPLACEMENTS_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CALCULATE_DISPLACEMENTS_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/histogram/HistogramModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/histogram/HistogramModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/histogram/HistogramModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/histogram/HistogramModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,7 +22,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -35,7 +37,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, HistogramModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(HistogramModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(HistogramModifier, HistogramModifierEditor); /****************************************************************************** @@ -51,16 +53,42 @@ layout->setContentsMargins(4,4,4,4); layout->setSpacing(4); - ParticlePropertyParameterUI* sourcePropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(HistogramModifier::_sourceProperty)); - layout->addWidget(new QLabel(tr("Property:"), rollout)); - layout->addWidget(sourcePropertyUI->comboBox()); + QHBoxLayout* layout3 = new QHBoxLayout(); + layout3->setContentsMargins(0,0,0,0); + layout3->setSpacing(4); + layout3->addWidget(new QLabel(tr("Input:"))); + IntegerRadioButtonParameterUI* sourceTypeUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(HistogramModifier::dataSourceType)); + QRadioButton* particlesModeBtn = sourceTypeUI->addRadioButton(HistogramModifier::Particles, tr("particles")); + QRadioButton* bondsModeBtn = sourceTypeUI->addRadioButton(HistogramModifier::Bonds, tr("bonds")); + layout3->addWidget(particlesModeBtn); + layout3->addWidget(bondsModeBtn); + layout3->addStretch(1); + layout->addLayout(layout3); + layout->addSpacing(4); + + ParticlePropertyParameterUI* sourceParticlePropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(HistogramModifier::sourceParticleProperty)); + BondPropertyParameterUI* sourceBondPropertyUI = new BondPropertyParameterUI(this, PROPERTY_FIELD(HistogramModifier::sourceBondProperty)); + QLabel* particlePropertyLabel = new QLabel(tr("Particle property:")); + layout->addWidget(particlePropertyLabel); + layout->addWidget(sourceParticlePropertyUI->comboBox()); + QLabel* bondPropertyLabel = new QLabel(tr("Bond property:")); + layout->addWidget(bondPropertyLabel); + layout->addWidget(sourceBondPropertyUI->comboBox()); + + bondPropertyLabel->hide(); + sourceBondPropertyUI->comboBox()->hide(); + particlesModeBtn->setChecked(true); + connect(bondsModeBtn, &QRadioButton::toggled, sourceParticlePropertyUI->comboBox(), &QWidget::setHidden); + connect(bondsModeBtn, &QRadioButton::toggled, particlePropertyLabel, &QWidget::setHidden); + connect(bondsModeBtn, &QRadioButton::toggled, sourceBondPropertyUI->comboBox(), &QWidget::setVisible); + connect(bondsModeBtn, &QRadioButton::toggled, bondPropertyLabel, &QWidget::setVisible); QGridLayout* gridlayout = new QGridLayout(); gridlayout->setContentsMargins(4,4,4,4); gridlayout->setColumnStretch(1, 1); // Number of bins parameter. - IntegerParameterUI* numBinsPUI = new IntegerParameterUI(this, PROPERTY_FIELD(HistogramModifier::_numberOfBins)); + IntegerParameterUI* numBinsPUI = new IntegerParameterUI(this, PROPERTY_FIELD(HistogramModifier::numberOfBins)); gridlayout->addWidget(numBinsPUI->label(), 0, 0); gridlayout->addLayout(numBinsPUI->createFieldLayout(), 0, 1); @@ -70,7 +98,7 @@ _histogramPlot->setMinimumHeight(240); _histogramPlot->setMaximumHeight(240); _histogramPlot->setCanvasBackground(Qt::white); - _histogramPlot->setAxisTitle(QwtPlot::yLeft, tr("Particle count")); + _histogramPlot->setAxisTitle(QwtPlot::yLeft, tr("Count")); layout->addWidget(new QLabel(tr("Histogram:"))); layout->addWidget(_histogramPlot); @@ -86,7 +114,7 @@ sublayout->setContentsMargins(4,4,4,4); layout->addWidget(inputBox); - BooleanParameterUI* onlySelectedUI = new BooleanParameterUI(this, PROPERTY_FIELD(HistogramModifier::_onlySelected)); + BooleanParameterUI* onlySelectedUI = new BooleanParameterUI(this, PROPERTY_FIELD(HistogramModifier::onlySelected)); sublayout->addWidget(onlySelectedUI->checkBox()); // Create selection. @@ -95,13 +123,13 @@ sublayout->setContentsMargins(4,4,4,4); layout->addWidget(selectionBox); - BooleanParameterUI* selectInRangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(HistogramModifier::_selectInRange)); + BooleanParameterUI* selectInRangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(HistogramModifier::selectInRange)); sublayout->addWidget(selectInRangeUI->checkBox()); QHBoxLayout* hlayout = new QHBoxLayout(); sublayout->addLayout(hlayout); - FloatParameterUI* selRangeStartPUI = new FloatParameterUI(this, PROPERTY_FIELD(HistogramModifier::_selectionRangeStart)); - FloatParameterUI* selRangeEndPUI = new FloatParameterUI(this, PROPERTY_FIELD(HistogramModifier::_selectionRangeEnd)); + FloatParameterUI* selRangeStartPUI = new FloatParameterUI(this, PROPERTY_FIELD(HistogramModifier::selectionRangeStart)); + FloatParameterUI* selRangeEndPUI = new FloatParameterUI(this, PROPERTY_FIELD(HistogramModifier::selectionRangeEnd)); hlayout->addWidget(new QLabel(tr("From:"))); hlayout->addLayout(selRangeStartPUI->createFieldLayout()); hlayout->addSpacing(12); @@ -119,13 +147,13 @@ layout->addWidget(axesBox); // x-axis. { - BooleanParameterUI* rangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(HistogramModifier::_fixXAxisRange)); + BooleanParameterUI* rangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(HistogramModifier::fixXAxisRange)); axesSublayout->addWidget(rangeUI->checkBox()); QHBoxLayout* hlayout = new QHBoxLayout(); axesSublayout->addLayout(hlayout); - FloatParameterUI* startPUI = new FloatParameterUI(this, PROPERTY_FIELD(HistogramModifier::_xAxisRangeStart)); - FloatParameterUI* endPUI = new FloatParameterUI(this, PROPERTY_FIELD(HistogramModifier::_xAxisRangeEnd)); + FloatParameterUI* startPUI = new FloatParameterUI(this, PROPERTY_FIELD(HistogramModifier::xAxisRangeStart)); + FloatParameterUI* endPUI = new FloatParameterUI(this, PROPERTY_FIELD(HistogramModifier::xAxisRangeEnd)); hlayout->addWidget(new QLabel(tr("From:"))); hlayout->addLayout(startPUI->createFieldLayout()); hlayout->addSpacing(12); @@ -138,13 +166,13 @@ } // y-axis. { - BooleanParameterUI* rangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(HistogramModifier::_fixYAxisRange)); + BooleanParameterUI* rangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(HistogramModifier::fixYAxisRange)); axesSublayout->addWidget(rangeUI->checkBox()); QHBoxLayout* hlayout = new QHBoxLayout(); axesSublayout->addLayout(hlayout); - FloatParameterUI* startPUI = new FloatParameterUI(this, PROPERTY_FIELD(HistogramModifier::_yAxisRangeStart)); - FloatParameterUI* endPUI = new FloatParameterUI(this, PROPERTY_FIELD(HistogramModifier::_yAxisRangeEnd)); + FloatParameterUI* startPUI = new FloatParameterUI(this, PROPERTY_FIELD(HistogramModifier::yAxisRangeStart)); + FloatParameterUI* endPUI = new FloatParameterUI(this, PROPERTY_FIELD(HistogramModifier::yAxisRangeEnd)); hlayout->addWidget(new QLabel(tr("From:"))); hlayout->addLayout(startPUI->createFieldLayout()); hlayout->addSpacing(12); @@ -181,7 +209,10 @@ if(!modifier) return; - _histogramPlot->setAxisTitle(QwtPlot::xBottom, modifier->sourceProperty().nameWithComponent()); + QString axisTitle = modifier->dataSourceType() == HistogramModifier::Particles ? + modifier->sourceParticleProperty().nameWithComponent() : + modifier->sourceBondProperty().nameWithComponent(); + _histogramPlot->setAxisTitle(QwtPlot::xBottom, axisTitle); if(modifier->histogramData().empty()) return; @@ -259,15 +290,19 @@ QTextStream stream(&file); + QString sourceTitle = modifier->dataSourceType() == HistogramModifier::Particles ? + modifier->sourceParticleProperty().nameWithComponent() : + modifier->sourceBondProperty().nameWithComponent(); + FloatType binSize = (modifier->xAxisRangeEnd() - modifier->xAxisRangeStart()) / modifier->histogramData().size(); - stream << "# " << modifier->sourceProperty().nameWithComponent() << " histogram (bin size: " << binSize << ")" << endl; + stream << "# " << sourceTitle << " histogram (bin size: " << binSize << ")" << endl; for(int i = 0; i < modifier->histogramData().size(); i++) { stream << (binSize * (FloatType(i) + FloatType(0.5)) + modifier->xAxisRangeStart()) << " " << modifier->histogramData()[i] << endl; } } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/histogram/HistogramModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/histogram/HistogramModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/histogram/HistogramModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/histogram/HistogramModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_HISTOGRAM_MODIFIER_EDITOR_H -#define __OVITO_HISTOGRAM_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -82,4 +82,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_HISTOGRAM_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/ptm/PolyhedralTemplateMatchingModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/ptm/PolyhedralTemplateMatchingModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/ptm/PolyhedralTemplateMatchingModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/ptm/PolyhedralTemplateMatchingModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -33,7 +33,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, PolyhedralTemplateMatchingModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(PolyhedralTemplateMatchingModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(PolyhedralTemplateMatchingModifier, PolyhedralTemplateMatchingModifierEditor); /****************************************************************************** @@ -56,12 +56,12 @@ layout1->addWidget(paramsBox); // RMSD cutoff parameter. - FloatParameterUI* rmsdCutoffPUI = new FloatParameterUI(this, PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_rmsdCutoff)); + FloatParameterUI* rmsdCutoffPUI = new FloatParameterUI(this, PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::rmsdCutoff)); gridlayout->addWidget(rmsdCutoffPUI->label(), 0, 0); gridlayout->addLayout(rmsdCutoffPUI->createFieldLayout(), 0, 1); // Use only selected particles. - BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::_onlySelectedParticles)); + BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::onlySelectedParticles)); gridlayout->addWidget(onlySelectedParticlesUI->checkBox(), 1, 0, 1, 2); QGroupBox* outputBox = new QGroupBox(tr("Output"), rollout); @@ -70,19 +70,19 @@ layout1->addWidget(outputBox); // Output controls. - BooleanParameterUI* outputRmsdUI = new BooleanParameterUI(this, PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_outputRmsd)); + BooleanParameterUI* outputRmsdUI = new BooleanParameterUI(this, PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::outputRmsd)); sublayout->addWidget(outputRmsdUI->checkBox()); outputRmsdUI->checkBox()->setText(tr("RMSD value")); - BooleanParameterUI* outputInteratomicDistanceUI = new BooleanParameterUI(this, PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_outputInteratomicDistance)); + BooleanParameterUI* outputInteratomicDistanceUI = new BooleanParameterUI(this, PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::outputInteratomicDistance)); sublayout->addWidget(outputInteratomicDistanceUI->checkBox()); outputInteratomicDistanceUI->checkBox()->setText(tr("Interatomic distance")); - BooleanParameterUI* outputOrientationUI = new BooleanParameterUI(this, PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_outputOrientation)); + BooleanParameterUI* outputOrientationUI = new BooleanParameterUI(this, PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::outputOrientation)); sublayout->addWidget(outputOrientationUI->checkBox()); outputOrientationUI->checkBox()->setText(tr("Lattice orientation")); - BooleanParameterUI* outputDeformationGradientUI = new BooleanParameterUI(this, PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_outputDeformationGradient)); + BooleanParameterUI* outputDeformationGradientUI = new BooleanParameterUI(this, PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::outputDeformationGradient)); sublayout->addWidget(outputDeformationGradientUI->checkBox()); outputDeformationGradientUI->checkBox()->setText(tr("Elastic deformation gradient")); - BooleanParameterUI* outputAlloyTypesUI = new BooleanParameterUI(this, PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_outputAlloyTypes)); + BooleanParameterUI* outputAlloyTypesUI = new BooleanParameterUI(this, PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::outputAlloyTypes)); sublayout->addWidget(outputAlloyTypesUI->checkBox()); outputAlloyTypesUI->checkBox()->setText(tr("Alloy type")); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/ptm/PolyhedralTemplateMatchingModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/ptm/PolyhedralTemplateMatchingModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/ptm/PolyhedralTemplateMatchingModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/ptm/PolyhedralTemplateMatchingModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PTM_MODIFIER_EDITOR_H -#define __OVITO_PTM_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -79,4 +79,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PTM_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/scatterplot/ScatterPlotModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/scatterplot/ScatterPlotModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/scatterplot/ScatterPlotModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/scatterplot/ScatterPlotModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -37,7 +37,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, ScatterPlotModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(ScatterPlotModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(ScatterPlotModifier, ScatterPlotModifierEditor); /****************************************************************************** @@ -53,10 +53,10 @@ layout->setContentsMargins(4,4,4,4); layout->setSpacing(4); - ParticlePropertyParameterUI* xPropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::_xAxisProperty)); + ParticlePropertyParameterUI* xPropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::xAxisProperty)); layout->addWidget(new QLabel(tr("X-axis property:"), rollout)); layout->addWidget(xPropertyUI->comboBox()); - ParticlePropertyParameterUI* yPropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::_yAxisProperty)); + ParticlePropertyParameterUI* yPropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::yAxisProperty)); layout->addWidget(new QLabel(tr("Y-axis property:"), rollout)); layout->addWidget(yPropertyUI->comboBox()); @@ -79,13 +79,13 @@ sublayout->setContentsMargins(4,4,4,4); layout->addWidget(selectionBox); - BooleanParameterUI* selectInRangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::_selectXAxisInRange)); + BooleanParameterUI* selectInRangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::selectXAxisInRange)); sublayout->addWidget(selectInRangeUI->checkBox()); QHBoxLayout* hlayout = new QHBoxLayout(); sublayout->addLayout(hlayout); - FloatParameterUI* selRangeStartPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::_selectionXAxisRangeStart)); - FloatParameterUI* selRangeEndPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::_selectionXAxisRangeEnd)); + FloatParameterUI* selRangeStartPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::selectionXAxisRangeStart)); + FloatParameterUI* selRangeEndPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::selectionXAxisRangeEnd)); hlayout->addWidget(new QLabel(tr("From:"))); hlayout->addLayout(selRangeStartPUI->createFieldLayout()); hlayout->addSpacing(12); @@ -96,13 +96,13 @@ connect(selectInRangeUI->checkBox(), &QCheckBox::toggled, selRangeStartPUI, &FloatParameterUI::setEnabled); connect(selectInRangeUI->checkBox(), &QCheckBox::toggled, selRangeEndPUI, &FloatParameterUI::setEnabled); - selectInRangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::_selectYAxisInRange)); + selectInRangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::selectYAxisInRange)); sublayout->addWidget(selectInRangeUI->checkBox()); hlayout = new QHBoxLayout(); sublayout->addLayout(hlayout); - selRangeStartPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::_selectionYAxisRangeStart)); - selRangeEndPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::_selectionYAxisRangeEnd)); + selRangeStartPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::selectionYAxisRangeStart)); + selRangeEndPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::selectionYAxisRangeEnd)); hlayout->addWidget(new QLabel(tr("From:"))); hlayout->addLayout(selRangeStartPUI->createFieldLayout()); hlayout->addSpacing(12); @@ -120,13 +120,13 @@ layout->addWidget(axesBox); // x-axis. { - BooleanParameterUI* rangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::_fixXAxisRange)); + BooleanParameterUI* rangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::fixXAxisRange)); axesSublayout->addWidget(rangeUI->checkBox()); QHBoxLayout* hlayout = new QHBoxLayout(); axesSublayout->addLayout(hlayout); - FloatParameterUI* startPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::_xAxisRangeStart)); - FloatParameterUI* endPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::_xAxisRangeEnd)); + FloatParameterUI* startPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::xAxisRangeStart)); + FloatParameterUI* endPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::xAxisRangeEnd)); hlayout->addWidget(new QLabel(tr("From:"))); hlayout->addLayout(startPUI->createFieldLayout()); hlayout->addSpacing(12); @@ -139,13 +139,13 @@ } // y-axis. { - BooleanParameterUI* rangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::_fixYAxisRange)); + BooleanParameterUI* rangeUI = new BooleanParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::fixYAxisRange)); axesSublayout->addWidget(rangeUI->checkBox()); QHBoxLayout* hlayout = new QHBoxLayout(); axesSublayout->addLayout(hlayout); - FloatParameterUI* startPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::_yAxisRangeStart)); - FloatParameterUI* endPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::_yAxisRangeEnd)); + FloatParameterUI* startPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::yAxisRangeStart)); + FloatParameterUI* endPUI = new FloatParameterUI(this, PROPERTY_FIELD(ScatterPlotModifier::yAxisRangeEnd)); hlayout->addWidget(new QLabel(tr("From:"))); hlayout->addLayout(startPUI->createFieldLayout()); hlayout->addSpacing(12); @@ -307,7 +307,7 @@ } } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/scatterplot/ScatterPlotModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/scatterplot/ScatterPlotModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/scatterplot/ScatterPlotModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/scatterplot/ScatterPlotModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SCATTER_PLOT_MODIFIER_EDITOR_H -#define __OVITO_SCATTER_PLOT_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -85,4 +85,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SCATTER_PLOT_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/strain/AtomicStrainModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/strain/AtomicStrainModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/strain/AtomicStrainModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/strain/AtomicStrainModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,7 +30,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, AtomicStrainModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(AtomicStrainModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(AtomicStrainModifier, AtomicStrainModifierEditor); /****************************************************************************** @@ -51,20 +51,20 @@ gridlayout->setColumnStretch(1, 1); // Cutoff parameter. - FloatParameterUI* cutoffRadiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::_cutoff)); + FloatParameterUI* cutoffRadiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::cutoff)); gridlayout->addWidget(cutoffRadiusPUI->label(), 0, 0); gridlayout->addLayout(cutoffRadiusPUI->createFieldLayout(), 0, 1); layout->addLayout(gridlayout); - BooleanParameterUI* eliminateCellDeformationUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::_eliminateCellDeformation)); + BooleanParameterUI* eliminateCellDeformationUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::eliminateCellDeformation)); layout->addWidget(eliminateCellDeformationUI->checkBox()); - BooleanParameterUI* assumeUnwrappedUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::_assumeUnwrappedCoordinates)); + BooleanParameterUI* assumeUnwrappedUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::assumeUnwrappedCoordinates)); layout->addWidget(assumeUnwrappedUI->checkBox()); #if 0 - BooleanParameterUI* showReferenceUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::_referenceShown)); + BooleanParameterUI* showReferenceUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::referenceShown)); layout->addWidget(showReferenceUI->checkBox()); #endif @@ -78,22 +78,22 @@ calculateVolumetricStrainsBox->setChecked(true); layout->addWidget(calculateVolumetricStrainsBox); - BooleanParameterUI* calculateDeformationGradientsUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::_calculateDeformationGradients)); + BooleanParameterUI* calculateDeformationGradientsUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::calculateDeformationGradients)); layout->addWidget(calculateDeformationGradientsUI->checkBox()); - BooleanParameterUI* calculateStrainTensorsUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::_calculateStrainTensors)); + BooleanParameterUI* calculateStrainTensorsUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::calculateStrainTensors)); layout->addWidget(calculateStrainTensorsUI->checkBox()); - BooleanParameterUI* calculateNonaffineSquaredDisplacementsUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::_calculateNonaffineSquaredDisplacements)); + BooleanParameterUI* calculateNonaffineSquaredDisplacementsUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::calculateNonaffineSquaredDisplacements)); layout->addWidget(calculateNonaffineSquaredDisplacementsUI->checkBox()); - BooleanParameterUI* calculateRotationsUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::_calculateRotations)); + BooleanParameterUI* calculateRotationsUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::calculateRotations)); layout->addWidget(calculateRotationsUI->checkBox()); - BooleanParameterUI* calculateStretchTensorsUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::_calculateStretchTensors)); + BooleanParameterUI* calculateStretchTensorsUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::calculateStretchTensors)); layout->addWidget(calculateStretchTensorsUI->checkBox()); - BooleanParameterUI* selectInvalidParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::_selectInvalidParticles)); + BooleanParameterUI* selectInvalidParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::selectInvalidParticles)); layout->addWidget(selectInvalidParticlesUI->checkBox()); QGroupBox* referenceFrameGroupBox = new QGroupBox(tr("Reference frame")); @@ -106,12 +106,12 @@ sublayout->setColumnStretch(2, 95); // Add box for selection between absolute and relative reference frames. - BooleanRadioButtonParameterUI* useFrameOffsetUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::_useReferenceFrameOffset)); + BooleanRadioButtonParameterUI* useFrameOffsetUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::useReferenceFrameOffset)); useFrameOffsetUI->buttonTrue()->setText(tr("Relative to current frame")); useFrameOffsetUI->buttonFalse()->setText(tr("Fixed reference configuration")); sublayout->addWidget(useFrameOffsetUI->buttonFalse(), 0, 0, 1, 3); - IntegerParameterUI* frameNumberUI = new IntegerParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::_referenceFrameNumber)); + IntegerParameterUI* frameNumberUI = new IntegerParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::referenceFrameNumber)); frameNumberUI->label()->setText(tr("Frame number:")); sublayout->addWidget(frameNumberUI->label(), 1, 1, 1, 1); sublayout->addLayout(frameNumberUI->createFieldLayout(), 1, 2, 1, 1); @@ -119,7 +119,7 @@ connect(useFrameOffsetUI->buttonFalse(), &QRadioButton::toggled, frameNumberUI, &IntegerParameterUI::setEnabled); sublayout->addWidget(useFrameOffsetUI->buttonTrue(), 2, 0, 1, 3); - IntegerParameterUI* frameOffsetUI = new IntegerParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::_referenceFrameOffset)); + IntegerParameterUI* frameOffsetUI = new IntegerParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::referenceFrameOffset)); frameOffsetUI->label()->setText(tr("Frame offset:")); sublayout->addWidget(frameOffsetUI->label(), 3, 1, 1, 1); sublayout->addLayout(frameOffsetUI->createFieldLayout(), 3, 2, 1, 1); @@ -131,7 +131,7 @@ layout->addWidget(statusLabel()); // Open a sub-editor for the reference object. - new SubObjectParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::_referenceObject), RolloutInsertionParameters().setTitle(tr("Reference"))); + new SubObjectParameterUI(this, PROPERTY_FIELD(AtomicStrainModifier::referenceConfiguration), RolloutInsertionParameters().setTitle(tr("Reference"))); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/strain/AtomicStrainModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/strain/AtomicStrainModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/strain/AtomicStrainModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/strain/AtomicStrainModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ATOMIC_STRAIN_MODIFIER_EDITOR_H -#define __OVITO_ATOMIC_STRAIN_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -54,4 +54,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_ATOMIC_STRAIN_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/structural_clustering/StructuralClusteringModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/structural_clustering/StructuralClusteringModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/structural_clustering/StructuralClusteringModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/structural_clustering/StructuralClusteringModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, StructuralClusteringModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(StructuralClusteringModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(StructuralClusteringModifier, StructuralClusteringModifierEditor); /****************************************************************************** @@ -48,12 +48,12 @@ gridlayout->setColumnStretch(1, 1); // Voronoi face threshold parameter. - FloatParameterUI* faceThresholdPUI = new FloatParameterUI(this, PROPERTY_FIELD(StructuralClusteringModifier::_faceThreshold)); + FloatParameterUI* faceThresholdPUI = new FloatParameterUI(this, PROPERTY_FIELD(StructuralClusteringModifier::faceThreshold)); gridlayout->addWidget(faceThresholdPUI->label(), 0, 0); gridlayout->addLayout(faceThresholdPUI->createFieldLayout(), 0, 1); // RMSD threshold parameter. - FloatParameterUI* rmsdThresholdPUI = new FloatParameterUI(this, PROPERTY_FIELD(StructuralClusteringModifier::_rmsdThreshold)); + FloatParameterUI* rmsdThresholdPUI = new FloatParameterUI(this, PROPERTY_FIELD(StructuralClusteringModifier::rmsdThreshold)); gridlayout->addWidget(rmsdThresholdPUI->label(), 1, 0); gridlayout->addLayout(rmsdThresholdPUI->createFieldLayout(), 1, 1); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/structural_clustering/StructuralClusteringModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/structural_clustering/StructuralClusteringModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/structural_clustering/StructuralClusteringModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/structural_clustering/StructuralClusteringModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_STRUCTURAL_CLUSTERING_MODIFIER_EDITOR_H -#define __OVITO_STRUCTURAL_CLUSTERING_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -54,4 +54,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_STRUCTURAL_CLUSTERING_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/StructureListParameterUI.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/StructureListParameterUI.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/StructureListParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/StructureListParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ * Constructor. ******************************************************************************/ StructureListParameterUI::StructureListParameterUI(PropertiesEditor* parentEditor, bool showCheckBoxes) - : RefTargetListParameterUI(parentEditor, PROPERTY_FIELD(StructureIdentificationModifier::_structureTypes)), + : RefTargetListParameterUI(parentEditor, PROPERTY_FIELD(StructureIdentificationModifier::structureTypes)), _showCheckBoxes(showCheckBoxes) { connect(tableWidget(220), &QTableWidget::doubleClicked, this, &StructureListParameterUI::onDoubleClickStructureType); @@ -73,7 +73,7 @@ } else if(role == Qt::CheckStateRole && _showCheckBoxes) { if(index.column() == 0) - return stype->isEnabled() ? Qt::Checked : Qt::Unchecked; + return stype->enabled() ? Qt::Checked : Qt::Unchecked; } } return QVariant(); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/StructureListParameterUI.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/StructureListParameterUI.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/StructureListParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/StructureListParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_STRUCTURE_LIST_PARAMETER_UI_H -#define __OVITO_STRUCTURE_LIST_PARAMETER_UI_H +#pragma once + #include #include @@ -99,4 +99,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_STRUCTURE_LIST_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/voronoi/VoronoiAnalysisModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/voronoi/VoronoiAnalysisModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/voronoi/VoronoiAnalysisModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/voronoi/VoronoiAnalysisModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, VoronoiAnalysisModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(VoronoiAnalysisModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(VoronoiAnalysisModifier, VoronoiAnalysisModifierEditor); /****************************************************************************** @@ -53,12 +53,17 @@ int row = 0; // Face threshold. - FloatParameterUI* faceThresholdPUI = new FloatParameterUI(this, PROPERTY_FIELD(VoronoiAnalysisModifier::_faceThreshold)); + FloatParameterUI* faceThresholdPUI = new FloatParameterUI(this, PROPERTY_FIELD(VoronoiAnalysisModifier::faceThreshold)); gridlayout->addWidget(faceThresholdPUI->label(), row, 0); gridlayout->addLayout(faceThresholdPUI->createFieldLayout(), row++, 1); + // Relative face threshold. + FloatParameterUI* relativeFaceThresholdPUI = new FloatParameterUI(this, PROPERTY_FIELD(VoronoiAnalysisModifier::relativeFaceThreshold)); + gridlayout->addWidget(relativeFaceThresholdPUI->label(), row, 0); + gridlayout->addLayout(relativeFaceThresholdPUI->createFieldLayout(), row++, 1); + // Compute indices. - BooleanGroupBoxParameterUI* computeIndicesPUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(VoronoiAnalysisModifier::_computeIndices)); + BooleanGroupBoxParameterUI* computeIndicesPUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(VoronoiAnalysisModifier::computeIndices)); gridlayout->addWidget(computeIndicesPUI->groupBox(), row++, 0, 1, 2); sublayout = new QGridLayout(computeIndicesPUI->childContainer()); sublayout->setContentsMargins(4,4,4,4); @@ -66,25 +71,25 @@ sublayout->setColumnStretch(1, 1); // Edge count parameter. - IntegerParameterUI* edgeCountPUI = new IntegerParameterUI(this, PROPERTY_FIELD(VoronoiAnalysisModifier::_edgeCount)); + IntegerParameterUI* edgeCountPUI = new IntegerParameterUI(this, PROPERTY_FIELD(VoronoiAnalysisModifier::edgeCount)); sublayout->addWidget(edgeCountPUI->label(), 0, 0); sublayout->addLayout(edgeCountPUI->createFieldLayout(), 0, 1); // Edge threshold. - FloatParameterUI* edgeThresholdPUI = new FloatParameterUI(this, PROPERTY_FIELD(VoronoiAnalysisModifier::_edgeThreshold)); + FloatParameterUI* edgeThresholdPUI = new FloatParameterUI(this, PROPERTY_FIELD(VoronoiAnalysisModifier::edgeThreshold)); sublayout->addWidget(edgeThresholdPUI->label(), 1, 0); sublayout->addLayout(edgeThresholdPUI->createFieldLayout(), 1, 1); // Generate bonds. - BooleanParameterUI* computeBondsPUI = new BooleanParameterUI(this, PROPERTY_FIELD(VoronoiAnalysisModifier::_computeBonds)); + BooleanParameterUI* computeBondsPUI = new BooleanParameterUI(this, PROPERTY_FIELD(VoronoiAnalysisModifier::computeBonds)); gridlayout->addWidget(computeBondsPUI->checkBox(), row++, 0, 1, 2); // Atomic radii. - BooleanParameterUI* useRadiiPUI = new BooleanParameterUI(this, PROPERTY_FIELD(VoronoiAnalysisModifier::_useRadii)); + BooleanParameterUI* useRadiiPUI = new BooleanParameterUI(this, PROPERTY_FIELD(VoronoiAnalysisModifier::useRadii)); gridlayout->addWidget(useRadiiPUI->checkBox(), row++, 0, 1, 2); // Only selected particles. - BooleanParameterUI* onlySelectedPUI = new BooleanParameterUI(this, PROPERTY_FIELD(VoronoiAnalysisModifier::_onlySelected)); + BooleanParameterUI* onlySelectedPUI = new BooleanParameterUI(this, PROPERTY_FIELD(VoronoiAnalysisModifier::onlySelected)); gridlayout->addWidget(onlySelectedPUI->checkBox(), row++, 0, 1, 2); layout->addLayout(gridlayout); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/voronoi/VoronoiAnalysisModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/voronoi/VoronoiAnalysisModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/voronoi/VoronoiAnalysisModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/voronoi/VoronoiAnalysisModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VORONOI_ANALYSIS_MODIFIER_EDITOR_H -#define __OVITO_VORONOI_ANALYSIS_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -54,4 +54,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_VORONOI_ANALYSIS_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, WignerSeitzAnalysisModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(WignerSeitzAnalysisModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(WignerSeitzAnalysisModifier, WignerSeitzAnalysisModifierEditor); /****************************************************************************** @@ -45,48 +45,21 @@ layout->setContentsMargins(4,4,4,4); layout->setSpacing(4); - BooleanParameterUI* eliminateCellDeformationUI = new BooleanParameterUI(this, PROPERTY_FIELD(WignerSeitzAnalysisModifier::_eliminateCellDeformation)); + BooleanParameterUI* eliminateCellDeformationUI = new BooleanParameterUI(this, PROPERTY_FIELD(WignerSeitzAnalysisModifier::eliminateCellDeformation)); layout->addWidget(eliminateCellDeformationUI->checkBox()); - BooleanParameterUI* perTypeOccupancyUI = new BooleanParameterUI(this, PROPERTY_FIELD(WignerSeitzAnalysisModifier::_perTypeOccupancy)); + BooleanParameterUI* perTypeOccupancyUI = new BooleanParameterUI(this, PROPERTY_FIELD(WignerSeitzAnalysisModifier::perTypeOccupancy)); layout->addWidget(perTypeOccupancyUI->checkBox()); QGroupBox* referenceFrameGroupBox = new QGroupBox(tr("Reference frame")); layout->addWidget(referenceFrameGroupBox); - QGridLayout* sublayout = new QGridLayout(referenceFrameGroupBox); - sublayout->setContentsMargins(4,4,4,4); - sublayout->setSpacing(4); - sublayout->setColumnStretch(0, 5); - sublayout->setColumnStretch(2, 95); - - // Add box for selection between absolute and relative reference frames. - BooleanRadioButtonParameterUI* useFrameOffsetUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(WignerSeitzAnalysisModifier::_useReferenceFrameOffset)); - useFrameOffsetUI->buttonTrue()->setText(tr("Relative to current frame")); - useFrameOffsetUI->buttonFalse()->setText(tr("Fixed reference configuration")); - sublayout->addWidget(useFrameOffsetUI->buttonFalse(), 0, 0, 1, 3); - - IntegerParameterUI* frameNumberUI = new IntegerParameterUI(this, PROPERTY_FIELD(WignerSeitzAnalysisModifier::_referenceFrameNumber)); - frameNumberUI->label()->setText(tr("Frame number:")); - sublayout->addWidget(frameNumberUI->label(), 1, 1, 1, 1); - sublayout->addLayout(frameNumberUI->createFieldLayout(), 1, 2, 1, 1); - frameNumberUI->setEnabled(false); - connect(useFrameOffsetUI->buttonFalse(), &QRadioButton::toggled, frameNumberUI, &IntegerParameterUI::setEnabled); - - sublayout->addWidget(useFrameOffsetUI->buttonTrue(), 2, 0, 1, 3); - IntegerParameterUI* frameOffsetUI = new IntegerParameterUI(this, PROPERTY_FIELD(WignerSeitzAnalysisModifier::_referenceFrameOffset)); - frameOffsetUI->label()->setText(tr("Frame offset:")); - sublayout->addWidget(frameOffsetUI->label(), 3, 1, 1, 1); - sublayout->addLayout(frameOffsetUI->createFieldLayout(), 3, 2, 1, 1); - frameOffsetUI->setEnabled(false); - connect(useFrameOffsetUI->buttonTrue(), &QRadioButton::toggled, frameOffsetUI, &IntegerParameterUI::setEnabled); - // Status label. layout->addSpacing(6); layout->addWidget(statusLabel()); // Open a sub-editor for the reference object. - new SubObjectParameterUI(this, PROPERTY_FIELD(WignerSeitzAnalysisModifier::_referenceObject), RolloutInsertionParameters().setTitle(tr("Reference"))); + new SubObjectParameterUI(this, PROPERTY_FIELD(WignerSeitzAnalysisModifier::referenceConfiguration), RolloutInsertionParameters().setTitle(tr("Reference"))); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_WIGNER_SEITZ_ANALYSIS_MODIFIER_EDITOR_H -#define __OVITO_WIGNER_SEITZ_ANALYSIS_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -54,4 +54,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_WIGNER_SEITZ_ANALYSIS_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/AmbientOcclusionModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/AmbientOcclusionModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/AmbientOcclusionModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/AmbientOcclusionModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,7 +28,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Coloring) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, AmbientOcclusionModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(AmbientOcclusionModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(AmbientOcclusionModifier, AmbientOcclusionModifierEditor); /****************************************************************************** @@ -51,17 +51,17 @@ layout1->addLayout(layout2); // Intensity parameter. - FloatParameterUI* intensityPUI = new FloatParameterUI(this, PROPERTY_FIELD(AmbientOcclusionModifier::_intensity)); + FloatParameterUI* intensityPUI = new FloatParameterUI(this, PROPERTY_FIELD(AmbientOcclusionModifier::intensity)); layout2->addWidget(intensityPUI->label(), 0, 0); layout2->addLayout(intensityPUI->createFieldLayout(), 0, 1); // Sampling level parameter. - IntegerParameterUI* samplingCountPUI = new IntegerParameterUI(this, PROPERTY_FIELD(AmbientOcclusionModifier::_samplingCount)); + IntegerParameterUI* samplingCountPUI = new IntegerParameterUI(this, PROPERTY_FIELD(AmbientOcclusionModifier::samplingCount)); layout2->addWidget(samplingCountPUI->label(), 1, 0); layout2->addLayout(samplingCountPUI->createFieldLayout(), 1, 1); // Buffer resolution parameter. - IntegerParameterUI* bufferResPUI = new IntegerParameterUI(this, PROPERTY_FIELD(AmbientOcclusionModifier::_bufferResolution)); + IntegerParameterUI* bufferResPUI = new IntegerParameterUI(this, PROPERTY_FIELD(AmbientOcclusionModifier::bufferResolution)); layout2->addWidget(bufferResPUI->label(), 2, 0); layout2->addLayout(bufferResPUI->createFieldLayout(), 2, 1); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/AmbientOcclusionModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/AmbientOcclusionModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/AmbientOcclusionModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/AmbientOcclusionModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_AMBIENT_OCCLUSION_MODIFIER_EDITOR_H -#define __OVITO_AMBIENT_OCCLUSION_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_AMBIENT_OCCLUSION_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/AssignColorModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/AssignColorModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/AssignColorModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/AssignColorModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Coloring) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, AssignColorModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(AssignColorModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(AssignColorModifier, AssignColorModifierEditor); /****************************************************************************** @@ -45,12 +45,12 @@ layout->setColumnStretch(1, 1); // Color parameter. - ColorParameterUI* constColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(AssignColorModifier::_colorCtrl)); + ColorParameterUI* constColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(AssignColorModifier::colorController)); layout->addWidget(constColorPUI->label(), 0, 0); layout->addWidget(constColorPUI->colorPicker(), 0, 1); // Keep selection parameter. - BooleanParameterUI* keepSelectionPUI = new BooleanParameterUI(this, PROPERTY_FIELD(AssignColorModifier::_keepSelection)); + BooleanParameterUI* keepSelectionPUI = new BooleanParameterUI(this, PROPERTY_FIELD(AssignColorModifier::keepSelection)); layout->addWidget(keepSelectionPUI->checkBox(), 1, 0, 1, 2); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/AssignColorModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/AssignColorModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/AssignColorModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/AssignColorModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ASSIGN_COLOR_MODIFIER_EDITOR_H -#define __OVITO_ASSIGN_COLOR_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -54,4 +54,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_ASSIGN_COLOR_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/ColorCodingModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/ColorCodingModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/ColorCodingModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/ColorCodingModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -32,12 +32,13 @@ #include #include #include +#include #include #include "ColorCodingModifierEditor.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Coloring) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, ColorCodingModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(ColorCodingModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(ColorCodingModifier, ColorCodingModifierEditor); /****************************************************************************** @@ -57,7 +58,7 @@ layout3->setContentsMargins(0,0,0,0); layout3->setSpacing(4); layout3->addWidget(new QLabel(tr("Operate on:"))); - IntegerRadioButtonParameterUI* modeUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(ColorCodingModifier::_colorApplicationMode)); + IntegerRadioButtonParameterUI* modeUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(ColorCodingModifier::colorApplicationMode)); QRadioButton* particlesModeBtn = modeUI->addRadioButton(ColorCodingModifier::Particles, tr("particles")); QRadioButton* bondsModeBtn = modeUI->addRadioButton(ColorCodingModifier::Bonds, tr("bonds")); QRadioButton* vectorsModeBtn = modeUI->addRadioButton(ColorCodingModifier::Vectors, tr("vectors")); @@ -68,8 +69,8 @@ layout1->addLayout(layout3); layout1->addSpacing(4); - ParticlePropertyParameterUI* sourceParticlePropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(ColorCodingModifier::_sourceParticleProperty)); - BondPropertyParameterUI* sourceBondPropertyUI = new BondPropertyParameterUI(this, PROPERTY_FIELD(ColorCodingModifier::_sourceBondProperty)); + ParticlePropertyParameterUI* sourceParticlePropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(ColorCodingModifier::sourceParticleProperty)); + BondPropertyParameterUI* sourceBondPropertyUI = new BondPropertyParameterUI(this, PROPERTY_FIELD(ColorCodingModifier::sourceBondProperty)); QLabel* particlePropertyLabel = new QLabel(tr("Particle property:")); layout1->addWidget(particlePropertyLabel); layout1->addWidget(sourceParticlePropertyUI->comboBox()); @@ -112,7 +113,7 @@ layout1->addLayout(layout2); // End value parameter. - FloatParameterUI* endValuePUI = new FloatParameterUI(this, PROPERTY_FIELD(ColorCodingModifier::_endValueCtrl)); + FloatParameterUI* endValuePUI = new FloatParameterUI(this, PROPERTY_FIELD(ColorCodingModifier::endValueController)); layout2->addWidget(endValuePUI->label(), 0, 0); layout2->addLayout(endValuePUI->createFieldLayout(), 0, 1); @@ -122,7 +123,7 @@ layout2->addWidget(colorLegendLabel, 1, 1); // Start value parameter. - FloatParameterUI* startValuePUI = new FloatParameterUI(this, PROPERTY_FIELD(ColorCodingModifier::_startValueCtrl)); + FloatParameterUI* startValuePUI = new FloatParameterUI(this, PROPERTY_FIELD(ColorCodingModifier::startValueController)); layout2->addWidget(startValuePUI->label(), 2, 0); layout2->addLayout(startValuePUI->createFieldLayout(), 2, 1); @@ -136,9 +137,13 @@ layout2->addWidget(exportBtn, 1, 0, Qt::AlignCenter); layout1->addSpacing(8); - QPushButton* adjustBtn = new QPushButton(tr("Adjust range"), rollout); - connect(adjustBtn, &QPushButton::clicked, this, &ColorCodingModifierEditor::onAdjustRange); - layout1->addWidget(adjustBtn); + QPushButton* adjustRangeBtn = new QPushButton(tr("Adjust range"), rollout); + connect(adjustRangeBtn, &QPushButton::clicked, this, &ColorCodingModifierEditor::onAdjustRange); + layout1->addWidget(adjustRangeBtn); + layout1->addSpacing(4); + QPushButton* adjustRangeGlobalBtn = new QPushButton(tr("Adjust range (all frames)"), rollout); + connect(adjustRangeGlobalBtn, &QPushButton::clicked, this, &ColorCodingModifierEditor::onAdjustRangeGlobal); + layout1->addWidget(adjustRangeGlobalBtn); layout1->addSpacing(4); QPushButton* reverseBtn = new QPushButton(tr("Reverse range"), rollout); connect(reverseBtn, &QPushButton::clicked, this, &ColorCodingModifierEditor::onReverseRange); @@ -147,11 +152,11 @@ layout1->addSpacing(8); // Only selected particles/bonds. - BooleanParameterUI* onlySelectedPUI = new BooleanParameterUI(this, PROPERTY_FIELD(ColorCodingModifier::_colorOnlySelected)); + BooleanParameterUI* onlySelectedPUI = new BooleanParameterUI(this, PROPERTY_FIELD(ColorCodingModifier::colorOnlySelected)); layout1->addWidget(onlySelectedPUI->checkBox()); // Keep selection - BooleanParameterUI* keepSelectionPUI = new BooleanParameterUI(this, PROPERTY_FIELD(ColorCodingModifier::_keepSelection)); + BooleanParameterUI* keepSelectionPUI = new BooleanParameterUI(this, PROPERTY_FIELD(ColorCodingModifier::keepSelection)); layout1->addWidget(keepSelectionPUI->checkBox()); connect(onlySelectedPUI->checkBox(), &QCheckBox::toggled, keepSelectionPUI, &BooleanParameterUI::setEnabled); keepSelectionPUI->setEnabled(false); @@ -210,7 +215,7 @@ bool ColorCodingModifierEditor::referenceEvent(RefTarget* source, ReferenceEvent* event) { if(source == editObject() && event->type() == ReferenceEvent::ReferenceChanged && - static_cast(event)->field() == PROPERTY_FIELD(ColorCodingModifier::_colorGradient)) { + static_cast(event)->field() == PROPERTY_FIELD(ColorCodingModifier::colorGradient)) { updateColorGradient(); } return ParticleModifierEditor::referenceEvent(source, event); @@ -235,7 +240,7 @@ QSettings settings; settings.beginGroup(ColorCodingModifier::OOType.plugin()->pluginId()); settings.beginGroup(ColorCodingModifier::OOType.name()); - settings.setValue(PROPERTY_FIELD(ColorCodingModifier::_colorGradient).identifier(), + settings.setValue(PROPERTY_FIELD(ColorCodingModifier::colorGradient).identifier(), QVariant::fromValue(OvitoObjectType::encodeAsString(descriptor))); } }); @@ -266,6 +271,20 @@ } /****************************************************************************** +* Is called when the user presses the "Adjust range over all frames" button. +******************************************************************************/ +void ColorCodingModifierEditor::onAdjustRangeGlobal() +{ + ColorCodingModifier* mod = static_object_cast(editObject()); + OVITO_CHECK_OBJECT_POINTER(mod); + + undoableTransaction(tr("Adjust range"), [this, mod]() { + ProgressDialog progressDialog(container(), mod->dataset()->container()->taskManager(), tr("Determining min/max property values")); + mod->adjustRangeGlobal(progressDialog.taskManager()); + }); +} + +/****************************************************************************** * Is called when the user presses the "Reverse Range" button. ******************************************************************************/ void ColorCodingModifierEditor::onReverseRange() @@ -306,7 +325,7 @@ QString imageFilename = fileDialog.imageInfo().filename(); if(!image.scaled(legendWidth, legendHeight, Qt::IgnoreAspectRatio, Qt::FastTransformation).save(imageFilename, fileDialog.imageInfo().format())) { Exception ex(tr("Failed to save image to file '%1'.").arg(imageFilename)); - ex.showError(); + ex.reportError(); } } } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/ColorCodingModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/ColorCodingModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/ColorCodingModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/ColorCodingModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COLOR_CODING_MODIFIER_EDITOR_H -#define __OVITO_COLOR_CODING_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -68,10 +68,13 @@ /// Is called when the user selects a color gradient in the list box. void onColorGradientSelected(int index); - /// Is called when the user presses the "Adjust Range" button. + /// Is called when the user presses the "Adjust range" button. void onAdjustRange(); - /// Is called when the user presses the "Reverse Range" button. + /// Is called when the user presses the "Adjust range over all frames" button. + void onAdjustRangeGlobal(); + + /// Is called when the user presses the "Reverse range" button. void onReverseRange(); /// Is called when the user presses the "Export color scale" button. @@ -94,4 +97,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_COLOR_CODING_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/ColorLegendOverlayEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/ColorLegendOverlayEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/ColorLegendOverlayEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/ColorLegendOverlayEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -39,7 +39,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Coloring) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, ColorLegendOverlayEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(ColorLegendOverlayEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(ColorLegendOverlay, ColorLegendOverlayEditor); /****************************************************************************** @@ -133,7 +133,7 @@ sublayout->setSpacing(4); sublayout->setColumnStretch(1, 1); - VariantComboBoxParameterUI* alignmentPUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::_alignment)); + VariantComboBoxParameterUI* alignmentPUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::alignment)); sublayout->addWidget(alignmentPUI->comboBox(), 0, 0); alignmentPUI->comboBox()->addItem(tr("Top"), QVariant::fromValue((int)(Qt::AlignTop | Qt::AlignHCenter))); alignmentPUI->comboBox()->addItem(tr("Top left"), QVariant::fromValue((int)(Qt::AlignTop | Qt::AlignLeft))); @@ -144,16 +144,16 @@ alignmentPUI->comboBox()->addItem(tr("Left"), QVariant::fromValue((int)(Qt::AlignVCenter | Qt::AlignLeft))); alignmentPUI->comboBox()->addItem(tr("Right"), QVariant::fromValue((int)(Qt::AlignVCenter | Qt::AlignRight))); - VariantComboBoxParameterUI* orientationPUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::_orientation)); + VariantComboBoxParameterUI* orientationPUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::orientation)); sublayout->addWidget(orientationPUI->comboBox(), 0, 1); orientationPUI->comboBox()->addItem(tr("Vertical"), QVariant::fromValue((int)Qt::Vertical)); orientationPUI->comboBox()->addItem(tr("Horizontal"), QVariant::fromValue((int)Qt::Horizontal)); - FloatParameterUI* offsetXPUI = new FloatParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::_offsetX)); + FloatParameterUI* offsetXPUI = new FloatParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::offsetX)); sublayout->addWidget(offsetXPUI->label(), 1, 0); sublayout->addLayout(offsetXPUI->createFieldLayout(), 1, 1); - FloatParameterUI* offsetYPUI = new FloatParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::_offsetY)); + FloatParameterUI* offsetYPUI = new FloatParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::offsetY)); sublayout->addWidget(offsetYPUI->label(), 2, 0); sublayout->addLayout(offsetYPUI->createFieldLayout(), 2, 1); @@ -168,11 +168,11 @@ sublayout->setSpacing(4); sublayout->setColumnStretch(1, 1); - FloatParameterUI* sizePUI = new FloatParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::_legendSize)); + FloatParameterUI* sizePUI = new FloatParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::legendSize)); sublayout->addWidget(sizePUI->label(), 0, 0); sublayout->addLayout(sizePUI->createFieldLayout(), 0, 1); - FloatParameterUI* aspectRatioPUI = new FloatParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::_aspectRatio)); + FloatParameterUI* aspectRatioPUI = new FloatParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::aspectRatio)); sublayout->addWidget(aspectRatioPUI->label(), 1, 0); sublayout->addLayout(aspectRatioPUI->createFieldLayout(), 1, 1); @@ -184,36 +184,36 @@ sublayout->setColumnStretch(1, 3); sublayout->setColumnStretch(2, 1); - StringParameterUI* titlePUI = new StringParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::_title)); + StringParameterUI* titlePUI = new StringParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::title)); sublayout->addWidget(new QLabel(tr("Custom title:")), 0, 0); sublayout->addWidget(titlePUI->textBox(), 0, 1, 1, 2); - StringParameterUI* label1PUI = new StringParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::_label1)); + StringParameterUI* label1PUI = new StringParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::label1)); sublayout->addWidget(new QLabel(tr("Custom label 1:")), 1, 0); sublayout->addWidget(label1PUI->textBox(), 1, 1, 1, 2); - StringParameterUI* label2PUI = new StringParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::_label2)); + StringParameterUI* label2PUI = new StringParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::label2)); sublayout->addWidget(new QLabel(tr("Custom label 2:")), 2, 0); sublayout->addWidget(label2PUI->textBox(), 2, 1, 1, 2); - StringParameterUI* valueFormatStringPUI = new StringParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::_valueFormatString)); + StringParameterUI* valueFormatStringPUI = new StringParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::valueFormatString)); sublayout->addWidget(new QLabel(tr("Format string:")), 3, 0); sublayout->addWidget(valueFormatStringPUI->textBox(), 3, 1, 1, 2); - FloatParameterUI* fontSizePUI = new FloatParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::_fontSize)); + FloatParameterUI* fontSizePUI = new FloatParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::fontSize)); sublayout->addWidget(new QLabel(tr("Text size/color:")), 4, 0); sublayout->addLayout(fontSizePUI->createFieldLayout(), 4, 1); - ColorParameterUI* textColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::_textColor)); + ColorParameterUI* textColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::textColor)); sublayout->addWidget(textColorPUI->colorPicker(), 4, 2); - BooleanParameterUI* outlineEnabledPUI = new BooleanParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::_outlineEnabled)); + BooleanParameterUI* outlineEnabledPUI = new BooleanParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::outlineEnabled)); sublayout->addWidget(outlineEnabledPUI->checkBox(), 5, 1); - ColorParameterUI* outlineColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::_outlineColor)); + ColorParameterUI* outlineColorPUI = new ColorParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::outlineColor)); sublayout->addWidget(outlineColorPUI->colorPicker(), 5, 2); - FontParameterUI* labelFontPUI = new FontParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::_font)); + FontParameterUI* labelFontPUI = new FontParameterUI(this, PROPERTY_FIELD(ColorLegendOverlay::font)); sublayout->addWidget(labelFontPUI->label(), 6, 0); sublayout->addWidget(labelFontPUI->fontPicker(), 6, 1, 1, 2); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/ColorLegendOverlayEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/ColorLegendOverlayEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/coloring/ColorLegendOverlayEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/coloring/ColorLegendOverlayEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COLOR_LEGEND_OVERLAY_EDITOR_H -#define __OVITO_COLOR_LEGEND_OVERLAY_EDITOR_H +#pragma once + #include #include @@ -54,4 +54,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_COLOR_LEGEND_OVERLAY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/fields/CreateIsosurfaceModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/fields/CreateIsosurfaceModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/fields/CreateIsosurfaceModifierEditor.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/fields/CreateIsosurfaceModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,76 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include "CreateIsosurfaceModifierEditor.h" + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Fields) OVITO_BEGIN_INLINE_NAMESPACE(Internal) + +IMPLEMENT_OVITO_OBJECT(CreateIsosurfaceModifierEditor, ParticleModifierEditor); +SET_OVITO_OBJECT_EDITOR(CreateIsosurfaceModifier, CreateIsosurfaceModifierEditor); + +/****************************************************************************** +* Sets up the UI widgets of the editor. +******************************************************************************/ +void CreateIsosurfaceModifierEditor::createUI(const RolloutInsertionParameters& rolloutParams) +{ + // Create a rollout. + QWidget* rollout = createRollout(tr("Create isosurface"), rolloutParams, "particles.modifiers.create_isosurface.html"); + + // Create the rollout contents. + QVBoxLayout* layout1 = new QVBoxLayout(rollout); + layout1->setContentsMargins(4,4,4,4); + layout1->setSpacing(4); + + QGridLayout* layout2 = new QGridLayout(); + layout2->setContentsMargins(0,0,0,0); + layout2->setSpacing(4); + layout2->setColumnStretch(1, 1); + layout1->addLayout(layout2); + + FieldQuantityParameterUI* fieldQuantityUI = new FieldQuantityParameterUI(this, PROPERTY_FIELD(CreateIsosurfaceModifier::sourceQuantity)); + layout2->addWidget(new QLabel(tr("Field quantity:")), 0, 0); + layout2->addWidget(fieldQuantityUI->comboBox(), 0, 1); + + // Isolevel parameter. + FloatParameterUI* isolevelPUI = new FloatParameterUI(this, PROPERTY_FIELD(CreateIsosurfaceModifier::isolevelController)); + layout2->addWidget(isolevelPUI->label(), 1, 0); + layout2->addLayout(isolevelPUI->createFieldLayout(), 1, 1); + + // Status label. + layout1->addSpacing(8); + layout1->addWidget(statusLabel()); + + // Open a sub-editor for the mesh display object. + new SubObjectParameterUI(this, PROPERTY_FIELD(CreateIsosurfaceModifier::surfaceMeshDisplay), rolloutParams.after(rollout)); +} + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/fields/CreateIsosurfaceModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/fields/CreateIsosurfaceModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/fields/CreateIsosurfaceModifierEditor.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/fields/CreateIsosurfaceModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,55 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Fields) OVITO_BEGIN_INLINE_NAMESPACE(Internal) + +/** + * \brief A properties editor for the CreateIsosurfaceModifier class. + */ +class CreateIsosurfaceModifierEditor : public ParticleModifierEditor +{ +public: + + /// Default constructor. + Q_INVOKABLE CreateIsosurfaceModifierEditor() {} + +protected: + + /// Creates the user interface controls for the editor. + virtual void createUI(const RolloutInsertionParameters& rolloutParams) override; + + Q_OBJECT + OVITO_OBJECT +}; + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/AffineTransformationModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/AffineTransformationModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/AffineTransformationModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/AffineTransformationModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,7 +28,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, AffineTransformationModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(AffineTransformationModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(AffineTransformationModifier, AffineTransformationModifierEditor); /****************************************************************************** @@ -45,26 +45,29 @@ layout->setColumnStretch(0, 5); layout->setColumnStretch(1, 95); - BooleanParameterUI* applyToSimulationBoxUI = new BooleanParameterUI(this, PROPERTY_FIELD(AffineTransformationModifier::_applyToSimulationBox)); + BooleanParameterUI* applyToSimulationBoxUI = new BooleanParameterUI(this, PROPERTY_FIELD(AffineTransformationModifier::applyToSimulationBox)); layout->addWidget(applyToSimulationBoxUI->checkBox(), 0, 0, 1, 2); - BooleanParameterUI* applyToParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(AffineTransformationModifier::_applyToParticles)); + BooleanParameterUI* applyToParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(AffineTransformationModifier::applyToParticles)); layout->addWidget(applyToParticlesUI->checkBox(), 1, 0, 1, 2); - BooleanRadioButtonParameterUI* selectionUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(AffineTransformationModifier::_toSelectionOnly)); + BooleanRadioButtonParameterUI* selectionUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(AffineTransformationModifier::selectionOnly)); selectionUI->buttonFalse()->setText(tr("All particles")); selectionUI->buttonFalse()->setEnabled(false); layout->addWidget(selectionUI->buttonFalse(), 2, 1); connect(applyToParticlesUI->checkBox(), &QCheckBox::toggled, selectionUI->buttonFalse(), &QRadioButton::setEnabled); - selectionUI->buttonTrue()->setText(tr("Only to selected particles")); + selectionUI->buttonTrue()->setText(tr("Only selected particles")); selectionUI->buttonTrue()->setEnabled(false); layout->addWidget(selectionUI->buttonTrue(), 3, 1); connect(applyToParticlesUI->checkBox(), &QCheckBox::toggled, selectionUI->buttonTrue(), &QRadioButton::setEnabled); - BooleanParameterUI* applyToSurfaceMeshUI = new BooleanParameterUI(this, PROPERTY_FIELD(AffineTransformationModifier::_applyToSurfaceMesh)); - layout->addWidget(applyToSurfaceMeshUI->checkBox(), 4, 0, 1, 2); + BooleanParameterUI* applyToVectorPropertiesUI = new BooleanParameterUI(this, PROPERTY_FIELD(AffineTransformationModifier::applyToVectorProperties)); + layout->addWidget(applyToVectorPropertiesUI->checkBox(), 4, 0, 1, 2); + + BooleanParameterUI* applyToSurfaceMeshUI = new BooleanParameterUI(this, PROPERTY_FIELD(AffineTransformationModifier::applyToSurfaceMesh)); + layout->addWidget(applyToSurfaceMeshUI->checkBox(), 5, 0, 1, 2); // Create the second rollout. rollout = createRollout(tr("Transformation"), rolloutParams.after(rollout), "particles.modifiers.affine_transformation.html"); @@ -73,7 +76,7 @@ topLayout->setContentsMargins(8,8,8,8); topLayout->setSpacing(4); - BooleanRadioButtonParameterUI* relativeModeUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(AffineTransformationModifier::_relativeMode)); + BooleanRadioButtonParameterUI* relativeModeUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(AffineTransformationModifier::relativeMode)); relativeModeUI->buttonTrue()->setText(tr("Transformation matrix:")); topLayout->addWidget(relativeModeUI->buttonTrue()); @@ -151,7 +154,7 @@ for(size_t v = 0; v < 3; v++) { layout->addWidget(new QLabel(tr("Cell vector %1:").arg(v+1)), v*2, 0, 1, 8); for(size_t r = 0; r < 3; r++) { - destinationCellUI = new AffineTransformationParameterUI(this, PROPERTY_FIELD(AffineTransformationModifier::_targetCell), r, v); + destinationCellUI = new AffineTransformationParameterUI(this, PROPERTY_FIELD(AffineTransformationModifier::targetCell), r, v); destinationCellUI->setEnabled(false); layout->addLayout(destinationCellUI->createFieldLayout(), v*2+1, r*2); connect(relativeModeUI->buttonFalse(), &QRadioButton::toggled, destinationCellUI, &AffineTransformationParameterUI::setEnabled); @@ -160,7 +163,7 @@ layout->addWidget(new QLabel(tr("Cell origin:")), 6, 0, 1, 8); for(size_t r = 0; r < 3; r++) { - destinationCellUI = new AffineTransformationParameterUI(this, PROPERTY_FIELD(AffineTransformationModifier::_targetCell), r, 3); + destinationCellUI = new AffineTransformationParameterUI(this, PROPERTY_FIELD(AffineTransformationModifier::targetCell), r, 3); destinationCellUI->setEnabled(false); layout->addLayout(destinationCellUI->createFieldLayout(), 7, r*2); connect(relativeModeUI->buttonFalse(), &QRadioButton::toggled, destinationCellUI, &AffineTransformationParameterUI::setEnabled); @@ -178,7 +181,7 @@ AffineTransformationModifier* mod = dynamic_object_cast(editObject()); if(!mod) return; - const AffineTransformation& tm = mod->transformation(); + const AffineTransformation& tm = mod->transformationTM(); for(int row = 0; row < 3; row++) { for(int column = 0; column < 4; column++) { @@ -216,13 +219,13 @@ SpinnerWidget* spinner = qobject_cast(sender()); OVITO_CHECK_POINTER(spinner); - AffineTransformation tm = mod->transformation(); + AffineTransformation tm = mod->transformationTM(); int column = spinner->property("column").toInt(); int row = spinner->property("row").toInt(); tm(row, column) = spinner->floatValue(); - mod->setTransformation(tm); + mod->setTransformationTM(tm); } /****************************************************************************** @@ -325,12 +328,12 @@ layout->addWidget(centerSpinnerZ, 5, 7); mainLayout->addLayout(layout); - Rotation rot(mod->transformation()); + Rotation rot(mod->transformationTM()); angleSpinner->setFloatValue(rot.angle()); axisSpinnerX->setFloatValue(rot.axis().x()); axisSpinnerY->setFloatValue(rot.axis().y()); axisSpinnerZ->setFloatValue(rot.axis().z()); - Matrix3 r = mod->transformation().linear(); + Matrix3 r = mod->transformationTM().linear(); r(0,0) -= 1; r(1,1) -= 1; r(2,2) -= 1; @@ -338,20 +341,20 @@ size_t i = 0; for(i = 0; i < 3; i++) if(!r.row(i).isZero()) { - p1 = Plane3(r.row(i), -mod->transformation()(i, 3)); + p1 = Plane3(r.row(i), -mod->transformationTM()(i, 3)); i++; break; } for(; i < 3; i++) if(!r.row(i).isZero()) { - p2 = Plane3(r.row(i), -mod->transformation()(i, 3)); + p2 = Plane3(r.row(i), -mod->transformationTM()(i, 3)); break; } if(i != 3) { p1.normalizePlane(); p2.normalizePlane(); FloatType d = p1.normal.dot(p2.normal); - FloatType denom = (1.0f - d*d); + FloatType denom = (FloatType(1) - d*d); if(fabs(denom) > FLOATTYPE_EPSILON) { FloatType c1 = (p1.dist - p2.dist * d) / denom; FloatType c2 = (p2.dist - p1.dist * d) / denom; @@ -369,7 +372,7 @@ Rotation rot(axis, angleSpinner->floatValue()); AffineTransformation tm = AffineTransformation::translation(center) * AffineTransformation::rotation(rot) * AffineTransformation::translation(-center); mod->dataset()->undoStack().resetCurrentCompoundOperation(); - mod->setTransformation(tm); + mod->setTransformationTM(tm); }; connect(angleSpinner, &SpinnerWidget::spinnerValueChanged, updateMatrix); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/AffineTransformationModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/AffineTransformationModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/AffineTransformationModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/AffineTransformationModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_AFFINE_TRANSFORMATION_MODIFIER_EDITOR_H -#define __OVITO_AFFINE_TRANSFORMATION_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -78,5 +78,3 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace } // End of namespace - -#endif // __AFFINE_TRANSFORMATION_MODIFIER_EDITOR_H diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/CombineParticleSetsModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/CombineParticleSetsModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/CombineParticleSetsModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/CombineParticleSetsModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,7 +26,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, CombineParticleSetsModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(CombineParticleSetsModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(CombineParticleSetsModifier, CombineParticleSetsModifierEditor); /****************************************************************************** @@ -47,7 +47,7 @@ layout->addWidget(statusLabel()); // Open a sub-editor for the source object. - new SubObjectParameterUI(this, PROPERTY_FIELD(CombineParticleSetsModifier::_secondarySource), RolloutInsertionParameters().setTitle(tr("Secondary Source"))); + new SubObjectParameterUI(this, PROPERTY_FIELD(CombineParticleSetsModifier::secondaryDataSource), RolloutInsertionParameters().setTitle(tr("Secondary Source"))); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/CombineParticleSetsModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/CombineParticleSetsModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/CombineParticleSetsModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/CombineParticleSetsModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COMBINE_PARTICLE_SETS_MODIFIER_EDITOR_H -#define __OVITO_COMBINE_PARTICLE_SETS_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_COMBINE_PARTICLE_SETS_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/CreateBondsModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/CreateBondsModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/CreateBondsModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/CreateBondsModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,7 +30,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, CreateBondsModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(CreateBondsModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(CreateBondsModifier, CreateBondsModifierEditor); /****************************************************************************** @@ -50,11 +50,11 @@ gridlayout->setContentsMargins(0,0,0,0); gridlayout->setColumnStretch(1, 1); - IntegerRadioButtonParameterUI* cutoffModePUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(CreateBondsModifier::_cutoffMode)); + IntegerRadioButtonParameterUI* cutoffModePUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(CreateBondsModifier::cutoffMode)); QRadioButton* uniformCutoffModeBtn = cutoffModePUI->addRadioButton(CreateBondsModifier::UniformCutoff, tr("Uniform cutoff radius")); // Cutoff parameter. - FloatParameterUI* cutoffRadiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(CreateBondsModifier::_uniformCutoff)); + FloatParameterUI* cutoffRadiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(CreateBondsModifier::uniformCutoff)); gridlayout->addWidget(uniformCutoffModeBtn, 0, 0); gridlayout->addLayout(cutoffRadiusPUI->createFieldLayout(), 0, 1); cutoffRadiusPUI->setEnabled(false); @@ -73,14 +73,14 @@ connect(pairCutoffModeBtn,&QRadioButton::toggled, _pairCutoffTable, &QTableView::setEnabled); layout1->addWidget(_pairCutoffTable); - BooleanParameterUI* onlyIntraMoleculeBondsUI = new BooleanParameterUI(this, PROPERTY_FIELD(CreateBondsModifier::_onlyIntraMoleculeBonds)); + BooleanParameterUI* onlyIntraMoleculeBondsUI = new BooleanParameterUI(this, PROPERTY_FIELD(CreateBondsModifier::onlyIntraMoleculeBonds)); layout1->addWidget(onlyIntraMoleculeBondsUI->checkBox()); // Lower cutoff parameter. gridlayout = new QGridLayout(); gridlayout->setContentsMargins(0,0,0,0); gridlayout->setColumnStretch(1, 1); - FloatParameterUI* minCutoffPUI = new FloatParameterUI(this, PROPERTY_FIELD(CreateBondsModifier::_minCutoff)); + FloatParameterUI* minCutoffPUI = new FloatParameterUI(this, PROPERTY_FIELD(CreateBondsModifier::minimumCutoff)); gridlayout->addWidget(minCutoffPUI->label(), 0, 0); gridlayout->addLayout(minCutoffPUI->createFieldLayout(), 0, 1); layout1->addLayout(gridlayout); @@ -90,7 +90,7 @@ layout1->addWidget(statusLabel()); // Open a sub-editor for the bonds display object. - new SubObjectParameterUI(this, PROPERTY_FIELD(CreateBondsModifier::_bondsDisplay), rolloutParams.after(rollout)); + new SubObjectParameterUI(this, PROPERTY_FIELD(CreateBondsModifier::bondsDisplay), rolloutParams.after(rollout)); // Update pair-wise cutoff table whenever a modifier has been loaded into the editor. connect(this, &CreateBondsModifierEditor::contentsReplaced, this, &CreateBondsModifierEditor::updatePairCutoffList); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/CreateBondsModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/CreateBondsModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/CreateBondsModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/CreateBondsModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CREATE_BONDS_MODIFIER_EDITOR_H -#define __OVITO_CREATE_BONDS_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -102,4 +102,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CREATE_BONDS_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/DeleteParticlesModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/DeleteParticlesModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/DeleteParticlesModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/DeleteParticlesModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,7 +25,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, DeleteParticlesModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(DeleteParticlesModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(DeleteParticlesModifier, DeleteParticlesModifierEditor); /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/DeleteParticlesModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/DeleteParticlesModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/DeleteParticlesModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/DeleteParticlesModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DELETE_PARTICLES_MODIFIER_EDITOR_H -#define __OVITO_DELETE_PARTICLES_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -54,4 +54,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_DELETE_PARTICLES_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/LoadTrajectoryModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/LoadTrajectoryModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/LoadTrajectoryModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/LoadTrajectoryModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,7 +26,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, LoadTrajectoryModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(LoadTrajectoryModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(LoadTrajectoryModifier, LoadTrajectoryModifierEditor); /****************************************************************************** @@ -47,7 +47,7 @@ layout->addWidget(statusLabel()); // Open a sub-editor for the source object. - new SubObjectParameterUI(this, PROPERTY_FIELD(LoadTrajectoryModifier::_trajectorySource), RolloutInsertionParameters().setTitle(tr("Trajectory Source"))); + new SubObjectParameterUI(this, PROPERTY_FIELD(LoadTrajectoryModifier::trajectorySource), RolloutInsertionParameters().setTitle(tr("Trajectory Source"))); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/LoadTrajectoryModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/LoadTrajectoryModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/LoadTrajectoryModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/LoadTrajectoryModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_LOAD_TRAJECTORY_MODIFIER_EDITOR_H -#define __OVITO_LOAD_TRAJECTORY_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_LOAD_TRAJECTORY_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/ShowPeriodicImagesModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/ShowPeriodicImagesModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/ShowPeriodicImagesModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/ShowPeriodicImagesModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, ShowPeriodicImagesModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(ShowPeriodicImagesModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(ShowPeriodicImagesModifier, ShowPeriodicImagesModifierEditor); /****************************************************************************** @@ -46,25 +46,25 @@ #endif layout->setColumnStretch(1, 1); - BooleanParameterUI* showPeriodicImageXUI = new BooleanParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::_showImageX)); + BooleanParameterUI* showPeriodicImageXUI = new BooleanParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::showImageX)); layout->addWidget(showPeriodicImageXUI->checkBox(), 0, 0); - IntegerParameterUI* numImagesXPUI = new IntegerParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::_numImagesX)); + IntegerParameterUI* numImagesXPUI = new IntegerParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::numImagesX)); layout->addLayout(numImagesXPUI->createFieldLayout(), 0, 1); - BooleanParameterUI* showPeriodicImageYUI = new BooleanParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::_showImageY)); + BooleanParameterUI* showPeriodicImageYUI = new BooleanParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::showImageY)); layout->addWidget(showPeriodicImageYUI->checkBox(), 1, 0); - IntegerParameterUI* numImagesYPUI = new IntegerParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::_numImagesY)); + IntegerParameterUI* numImagesYPUI = new IntegerParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::numImagesY)); layout->addLayout(numImagesYPUI->createFieldLayout(), 1, 1); - BooleanParameterUI* showPeriodicImageZUI = new BooleanParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::_showImageZ)); + BooleanParameterUI* showPeriodicImageZUI = new BooleanParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::showImageZ)); layout->addWidget(showPeriodicImageZUI->checkBox(), 2, 0); - IntegerParameterUI* numImagesZPUI = new IntegerParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::_numImagesZ)); + IntegerParameterUI* numImagesZPUI = new IntegerParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::numImagesZ)); layout->addLayout(numImagesZPUI->createFieldLayout(), 2, 1); - BooleanParameterUI* adjustBoxSizeUI = new BooleanParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::_adjustBoxSize)); + BooleanParameterUI* adjustBoxSizeUI = new BooleanParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::adjustBoxSize)); layout->addWidget(adjustBoxSizeUI->checkBox(), 3, 0, 1, 2); - BooleanParameterUI* uniqueIdentifiersUI = new BooleanParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::_uniqueIdentifiers)); + BooleanParameterUI* uniqueIdentifiersUI = new BooleanParameterUI(this, PROPERTY_FIELD(ShowPeriodicImagesModifier::uniqueIdentifiers)); layout->addWidget(uniqueIdentifiersUI->checkBox(), 4, 0, 1, 2); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/ShowPeriodicImagesModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/ShowPeriodicImagesModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/ShowPeriodicImagesModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/ShowPeriodicImagesModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SHOW_PERIODIC_IMAGES_MODIFIER_EDITOR_H -#define __OVITO_SHOW_PERIODIC_IMAGES_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -54,4 +54,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SHOW_PERIODIC_IMAGES_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/SliceModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/SliceModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/SliceModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/SliceModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -38,14 +38,12 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, SliceModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(SliceModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(SliceModifier, SliceModifierEditor); /****************************************************************************** * Sets up the UI widgets of the editor. -************************************************axisLabelPUI = new StringParameterUI(this, PROPERTY_FIELD(CoordinateTripodOverlay::_axis1Label)); - sublayout->addWidget(new QLabel(tr("Label:")), 0, 0); - sublayout->addWidget(axisLabelPUI->textBox(), 0, 1, 1, 2);******************************/ +*******************************************************************************/ void SliceModifierEditor::createUI(const RolloutInsertionParameters& rolloutParams) { // Create a rollout. @@ -61,14 +59,14 @@ gridlayout->setColumnStretch(1, 1); // Distance parameter. - FloatParameterUI* distancePUI = new FloatParameterUI(this, PROPERTY_FIELD(SliceModifier::_distanceCtrl)); + FloatParameterUI* distancePUI = new FloatParameterUI(this, PROPERTY_FIELD(SliceModifier::distanceController)); gridlayout->addWidget(distancePUI->label(), 0, 0); gridlayout->addLayout(distancePUI->createFieldLayout(), 0, 1); // Normal parameter. static const QString axesNames[3] = { QStringLiteral("X"), QStringLiteral("Y"), QStringLiteral("Z") }; for(int i = 0; i < 3; i++) { - Vector3ParameterUI* normalPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(SliceModifier::_normalCtrl), i); + Vector3ParameterUI* normalPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(SliceModifier::normalController), i); normalPUI->label()->setTextFormat(Qt::RichText); normalPUI->label()->setTextInteractionFlags(Qt::LinksAccessibleByMouse); normalPUI->label()->setText(QStringLiteral("%2").arg(i).arg(normalPUI->label()->text())); @@ -79,7 +77,7 @@ } // Slice width parameter. - FloatParameterUI* widthPUI = new FloatParameterUI(this, PROPERTY_FIELD(SliceModifier::_widthCtrl)); + FloatParameterUI* widthPUI = new FloatParameterUI(this, PROPERTY_FIELD(SliceModifier::widthController)); gridlayout->addWidget(widthPUI->label(), 4, 0); gridlayout->addLayout(widthPUI->createFieldLayout(), 4, 1); @@ -87,15 +85,15 @@ layout->addSpacing(8); // Invert parameter. - BooleanParameterUI* invertPUI = new BooleanParameterUI(this, PROPERTY_FIELD(SliceModifier::_inverse)); + BooleanParameterUI* invertPUI = new BooleanParameterUI(this, PROPERTY_FIELD(SliceModifier::inverse)); layout->addWidget(invertPUI->checkBox()); // Create selection parameter. - BooleanParameterUI* createSelectionPUI = new BooleanParameterUI(this, PROPERTY_FIELD(SliceModifier::_createSelection)); + BooleanParameterUI* createSelectionPUI = new BooleanParameterUI(this, PROPERTY_FIELD(SliceModifier::createSelection)); layout->addWidget(createSelectionPUI->checkBox()); // Apply to selection only parameter. - BooleanParameterUI* applyToSelectionPUI = new BooleanParameterUI(this, PROPERTY_FIELD(SliceModifier::_applyToSelection)); + BooleanParameterUI* applyToSelectionPUI = new BooleanParameterUI(this, PROPERTY_FIELD(SliceModifier::applyToSelection)); layout->addWidget(applyToSelectionPUI->checkBox()); layout->addSpacing(8); @@ -331,7 +329,7 @@ }); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/SliceModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/SliceModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/modify/SliceModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/modify/SliceModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SLICE_MODIFIER_EDITOR_H -#define __OVITO_SLICE_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -120,4 +120,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SLICE_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/ParticleModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/ParticleModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/ParticleModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/ParticleModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,7 +25,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, ParticleModifierEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(ParticleModifierEditor, PropertiesEditor); /****************************************************************************** * This method is called when a reference target changes. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/ParticleModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/ParticleModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/ParticleModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/ParticleModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_MODIFIER_EDITOR_H -#define __OVITO_PARTICLE_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -67,4 +67,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/properties/ComputePropertyModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/properties/ComputePropertyModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/properties/ComputePropertyModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/properties/ComputePropertyModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -34,7 +34,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Properties) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, ComputePropertyModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(ComputePropertyModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(ComputePropertyModifier, ComputePropertyModifierEditor); /****************************************************************************** @@ -55,11 +55,11 @@ propertiesLayout->setSpacing(4); // Output property - ParticlePropertyParameterUI* outputPropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(ComputePropertyModifier::_outputProperty), false, false); + ParticlePropertyParameterUI* outputPropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(ComputePropertyModifier::outputProperty), false, false); propertiesLayout->addWidget(outputPropertyUI->comboBox()); // Create the check box for the selection flag. - BooleanParameterUI* selectionFlagUI = new BooleanParameterUI(this, PROPERTY_FIELD(ComputePropertyModifier::_onlySelectedParticles)); + BooleanParameterUI* selectionFlagUI = new BooleanParameterUI(this, PROPERTY_FIELD(ComputePropertyModifier::onlySelectedParticles)); propertiesLayout->addWidget(selectionFlagUI->checkBox()); expressionsGroupBox = new QGroupBox(tr("Expression")); @@ -78,7 +78,7 @@ mainLayout = new QVBoxLayout(neighorRollout); mainLayout->setContentsMargins(4,4,4,4); - BooleanGroupBoxParameterUI* neighborModeUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(ComputePropertyModifier::_neighborModeEnabled)); + BooleanGroupBoxParameterUI* neighborModeUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(ComputePropertyModifier::neighborModeEnabled)); mainLayout->addWidget(neighborModeUI->groupBox()); QGridLayout* gridlayout = new QGridLayout(neighborModeUI->childContainer()); @@ -87,7 +87,7 @@ gridlayout->setRowStretch(1, 1); // Cutoff parameter. - FloatParameterUI* cutoffRadiusUI = new FloatParameterUI(this, PROPERTY_FIELD(ComputePropertyModifier::_cutoff)); + FloatParameterUI* cutoffRadiusUI = new FloatParameterUI(this, PROPERTY_FIELD(ComputePropertyModifier::cutoff)); gridlayout->addWidget(cutoffRadiusUI->label(), 0, 0); gridlayout->addLayout(cutoffRadiusUI->createFieldLayout(), 0, 1); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/properties/ComputePropertyModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/properties/ComputePropertyModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/properties/ComputePropertyModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/properties/ComputePropertyModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COMPUTE_PROPERTY_MODIFIER_EDITOR_H -#define __OVITO_COMPUTE_PROPERTY_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -80,4 +80,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_COMPUTE_PROPERTY_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/properties/FreezePropertyModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/properties/FreezePropertyModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/properties/FreezePropertyModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/properties/FreezePropertyModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,11 +23,13 @@ #include #include #include +#include +#include #include "FreezePropertyModifierEditor.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Properties) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, FreezePropertyModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(FreezePropertyModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(FreezePropertyModifier, FreezePropertyModifierEditor); /****************************************************************************** @@ -42,13 +44,13 @@ layout->setContentsMargins(4,4,4,4); layout->setSpacing(2); - ParticlePropertyParameterUI* sourcePropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(FreezePropertyModifier::_sourceProperty), false, true); + ParticlePropertyParameterUI* sourcePropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(FreezePropertyModifier::sourceProperty), false, true); layout->addWidget(new QLabel(tr("Property to freeze:"), rollout)); layout->addWidget(sourcePropertyUI->comboBox()); connect(sourcePropertyUI, &ParticlePropertyParameterUI::valueEntered, this, &FreezePropertyModifierEditor::onSourcePropertyChanged); layout->addSpacing(8); - ParticlePropertyParameterUI* destPropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(FreezePropertyModifier::_destinationProperty), false, false); + ParticlePropertyParameterUI* destPropertyUI = new ParticlePropertyParameterUI(this, PROPERTY_FIELD(FreezePropertyModifier::destinationProperty), false, false); layout->addWidget(new QLabel(tr("Output property:"), rollout)); layout->addWidget(destPropertyUI->comboBox()); layout->addSpacing(8); @@ -70,8 +72,9 @@ FreezePropertyModifier* mod = static_object_cast(editObject()); if(!mod) return; - undoableTransaction(tr("Take property snapshot"), [mod]() { - mod->takePropertySnapshot(mod->dataset()->animationSettings()->time(), true); + undoableTransaction(tr("Take property snapshot"), [this,mod]() { + ProgressDialog progressDialog(container(), mod->dataset()->container()->taskManager(), tr("Property snapshot")); + mod->takePropertySnapshot(mod->dataset()->animationSettings()->time(), progressDialog.taskManager(), true); }); } @@ -83,11 +86,12 @@ FreezePropertyModifier* mod = static_object_cast(editObject()); if(!mod) return; - undoableTransaction(tr("Freeze property"), [mod]() { + undoableTransaction(tr("Freeze property"), [this,mod]() { // When the user selects a different source property, adjust the destination property automatically. mod->setDestinationProperty(mod->sourceProperty()); // Also take a current snapshot of the source property values. - mod->takePropertySnapshot(mod->dataset()->animationSettings()->time(), true); + ProgressDialog progressDialog(container(), mod->dataset()->container()->taskManager()); + mod->takePropertySnapshot(mod->dataset()->animationSettings()->time(), progressDialog.taskManager(), true); }); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/properties/FreezePropertyModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/properties/FreezePropertyModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/properties/FreezePropertyModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/properties/FreezePropertyModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FREEZE_PROPERTY_MODIFIER_EDITOR_H -#define __OVITO_FREEZE_PROPERTY_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -62,4 +62,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_FREEZE_PROPERTY_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/ExpandSelectionModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/ExpandSelectionModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/ExpandSelectionModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/ExpandSelectionModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,7 +28,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Selection) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, ExpandSelectionModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(ExpandSelectionModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(ExpandSelectionModifier, ExpandSelectionModifierEditor); /****************************************************************************** @@ -48,13 +48,13 @@ label->setWordWrap(true); layout->addWidget(label); - IntegerRadioButtonParameterUI* modePUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(ExpandSelectionModifier::_mode)); + IntegerRadioButtonParameterUI* modePUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(ExpandSelectionModifier::mode)); QRadioButton* cutoffModeBtn = modePUI->addRadioButton(ExpandSelectionModifier::CutoffRange, tr("... within the range:")); layout->addSpacing(10); layout->addWidget(cutoffModeBtn); // Cutoff parameter. - FloatParameterUI* cutoffRadiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(ExpandSelectionModifier::_cutoffRange)); + FloatParameterUI* cutoffRadiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(ExpandSelectionModifier::cutoffRange)); QHBoxLayout* sublayout = new QHBoxLayout(); sublayout->setContentsMargins(0,0,0,0); sublayout->addSpacing(20); @@ -69,7 +69,7 @@ layout->addWidget(nearestNeighborsModeBtn); // Number of nearest neighbors. - IntegerParameterUI* numNearestNeighborsPUI = new IntegerParameterUI(this, PROPERTY_FIELD(ExpandSelectionModifier::_numNearestNeighbors)); + IntegerParameterUI* numNearestNeighborsPUI = new IntegerParameterUI(this, PROPERTY_FIELD(ExpandSelectionModifier::numNearestNeighbors)); sublayout = new QHBoxLayout(); sublayout->setContentsMargins(0,0,0,0); sublayout->addSpacing(20); @@ -84,7 +84,7 @@ layout->addWidget(bondModeBtn); layout->addSpacing(10); - IntegerParameterUI* numIterationsPUI = new IntegerParameterUI(this, PROPERTY_FIELD(ExpandSelectionModifier::_numIterations)); + IntegerParameterUI* numIterationsPUI = new IntegerParameterUI(this, PROPERTY_FIELD(ExpandSelectionModifier::numberOfIterations)); sublayout = new QHBoxLayout(); sublayout->setContentsMargins(0,0,0,0); sublayout->addWidget(numIterationsPUI->label()); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/ExpandSelectionModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/ExpandSelectionModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/ExpandSelectionModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/ExpandSelectionModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_EXPAND_SELECTION_MODIFIER_EDITOR_H -#define __OVITO_EXPAND_SELECTION_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -54,4 +54,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_EXPAND_SELECTION_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/ManualSelectionModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/ManualSelectionModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/ManualSelectionModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/ManualSelectionModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -34,7 +34,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Selection) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, ManualSelectionModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(ManualSelectionModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(ManualSelectionModifier, ManualSelectionModifierEditor); /** @@ -215,7 +215,7 @@ if(!mod) return; undoableTransaction(tr("Reset selection"), [mod]() { - for(const auto& modInput : mod->getModifierInputs()) + for(const auto& modInput : mod->getModifierInputs(mod->dataset()->animationSettings()->time())) mod->resetSelection(modInput.first, modInput.second); }); } @@ -229,7 +229,7 @@ if(!mod) return; undoableTransaction(tr("Select all"), [mod]() { - for(const auto& modInput : mod->getModifierInputs()) + for(const auto& modInput : mod->getModifierInputs(mod->dataset()->animationSettings()->time())) mod->selectAll(modInput.first, modInput.second); }); } @@ -243,7 +243,7 @@ if(!mod) return; undoableTransaction(tr("Clear selection"), [mod]() { - for(const auto& modInput : mod->getModifierInputs()) + for(const auto& modInput : mod->getModifierInputs(mod->dataset()->animationSettings()->time())) mod->clearSelection(modInput.first, modInput.second); }); } @@ -257,7 +257,7 @@ if(!mod) return; undoableTransaction(tr("Toggle particle selection"), [mod, &pickResult]() { - for(const auto& modInput : mod->getModifierInputs()) { + for(const auto& modInput : mod->getModifierInputs(mod->dataset()->animationSettings()->time())) { // Lookup the right particle in the modifier's input. // Since we cannot rely on the particle's index or identifier, we use the @@ -286,7 +286,7 @@ if(!mod) return; undoableTransaction(tr("Select particles"), [mod, &fence, viewport, mode]() { - for(const auto& modInput : mod->getModifierInputs()) { + for(const auto& modInput : mod->getModifierInputs(mod->dataset()->animationSettings()->time())) { // Lookup the right particle in the modifier's input. // Since we cannot rely on the particle's index or identifier, we use the diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/ManualSelectionModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/ManualSelectionModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/ManualSelectionModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/ManualSelectionModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_MANUAL_SELECTION_MODIFIER_EDITOR_H -#define __OVITO_MANUAL_SELECTION_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -74,4 +74,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_MANUAL_SELECTION_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/SelectExpressionModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/SelectExpressionModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/SelectExpressionModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/SelectExpressionModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Selection) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, SelectExpressionModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(SelectExpressionModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(SelectExpressionModifier, SelectExpressionModifierEditor); /****************************************************************************** @@ -43,7 +43,7 @@ layout->setSpacing(0); layout->addWidget(new QLabel(tr("Boolean expression:"))); - StringParameterUI* expressionUI = new StringParameterUI(this, PROPERTY_FIELD(SelectExpressionModifier::_expression)); + StringParameterUI* expressionUI = new StringParameterUI(this, PROPERTY_FIELD(SelectExpressionModifier::expression)); expressionEdit = new AutocompleteTextEdit(); expressionUI->setTextBox(expressionEdit); layout->addWidget(expressionUI->textBox()); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/SelectExpressionModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/SelectExpressionModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/SelectExpressionModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/SelectExpressionModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SELECT_EXPRESSION_MODIFIER_EDITOR_H -#define __OVITO_SELECT_EXPRESSION_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -65,4 +65,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SELECT_EXPRESSION_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/SelectParticleTypeModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/SelectParticleTypeModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/SelectParticleTypeModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/SelectParticleTypeModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Selection) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, SelectParticleTypeModifierEditor, ParticleModifierEditor); +IMPLEMENT_OVITO_OBJECT(SelectParticleTypeModifierEditor, ParticleModifierEditor); SET_OVITO_OBJECT_EDITOR(SelectParticleTypeModifier, SelectParticleTypeModifierEditor); /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/SelectParticleTypeModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/SelectParticleTypeModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/modifier/selection/SelectParticleTypeModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/modifier/selection/SelectParticleTypeModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SELECT_PARTICLE_TYPE_MODIFIER_EDITOR_H -#define __OVITO_SELECT_PARTICLE_TYPE_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -80,4 +80,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SELECT_PARTICLE_TYPE_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/BondsDisplayEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/BondsDisplayEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/BondsDisplayEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/BondsDisplayEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, BondsDisplayEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(BondsDisplayEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(BondsDisplay, BondsDisplayEditor); /****************************************************************************** @@ -47,14 +47,14 @@ layout->setColumnStretch(1, 1); // Shading mode. - VariantComboBoxParameterUI* shadingModeUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(BondsDisplay::_shadingMode)); + VariantComboBoxParameterUI* shadingModeUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(BondsDisplay::shadingMode)); shadingModeUI->comboBox()->addItem(tr("Normal"), qVariantFromValue(ArrowPrimitive::NormalShading)); shadingModeUI->comboBox()->addItem(tr("Flat"), qVariantFromValue(ArrowPrimitive::FlatShading)); layout->addWidget(new QLabel(tr("Shading mode:")), 0, 0); layout->addWidget(shadingModeUI->comboBox(), 0, 1); // Rendering quality. - VariantComboBoxParameterUI* renderingQualityUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(BondsDisplay::_renderingQuality)); + VariantComboBoxParameterUI* renderingQualityUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(BondsDisplay::renderingQuality)); renderingQualityUI->comboBox()->addItem(tr("Low"), qVariantFromValue(ArrowPrimitive::LowQuality)); renderingQualityUI->comboBox()->addItem(tr("Medium"), qVariantFromValue(ArrowPrimitive::MediumQuality)); renderingQualityUI->comboBox()->addItem(tr("High"), qVariantFromValue(ArrowPrimitive::HighQuality)); @@ -62,17 +62,17 @@ layout->addWidget(renderingQualityUI->comboBox(), 1, 1); // Bond width. - FloatParameterUI* bondWidthUI = new FloatParameterUI(this, PROPERTY_FIELD(BondsDisplay::_bondWidth)); + FloatParameterUI* bondWidthUI = new FloatParameterUI(this, PROPERTY_FIELD(BondsDisplay::bondWidth)); layout->addWidget(bondWidthUI->label(), 2, 0); layout->addLayout(bondWidthUI->createFieldLayout(), 2, 1); // Bond color. - ColorParameterUI* bondColorUI = new ColorParameterUI(this, PROPERTY_FIELD(BondsDisplay::_bondColor)); + ColorParameterUI* bondColorUI = new ColorParameterUI(this, PROPERTY_FIELD(BondsDisplay::bondColor)); layout->addWidget(bondColorUI->label(), 3, 0); layout->addWidget(bondColorUI->colorPicker(), 3, 1); // Use particle colors. - BooleanParameterUI* useParticleColorsUI = new BooleanParameterUI(this, PROPERTY_FIELD(BondsDisplay::_useParticleColors)); + BooleanParameterUI* useParticleColorsUI = new BooleanParameterUI(this, PROPERTY_FIELD(BondsDisplay::useParticleColors)); layout->addWidget(useParticleColorsUI->checkBox(), 4, 0, 1, 2); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/BondsDisplayEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/BondsDisplayEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/BondsDisplayEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/BondsDisplayEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BONDS_DISPLAY_EDITOR_H -#define __OVITO_BONDS_DISPLAY_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_BONDS_DISPLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/BondTypeEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/BondTypeEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/BondTypeEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/BondTypeEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,7 +28,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, BondTypeEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(BondTypeEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(BondType, BondTypeEditor); /****************************************************************************** @@ -48,12 +48,12 @@ layout1->setColumnStretch(1, 1); // Text box for the name of particle type. - StringParameterUI* namePUI = new StringParameterUI(this, PROPERTY_FIELD(BondType::_name)); + StringParameterUI* namePUI = new StringParameterUI(this, PROPERTY_FIELD(BondType::name)); layout1->addWidget(new QLabel(tr("Name:")), 0, 0); layout1->addWidget(namePUI->textBox(), 0, 1); // Display color parameter. - ColorParameterUI* colorPUI = new ColorParameterUI(this, PROPERTY_FIELD(BondType::_color)); + ColorParameterUI* colorPUI = new ColorParameterUI(this, PROPERTY_FIELD(BondType::color)); layout1->addWidget(colorPUI->label(), 1, 0); layout1->addWidget(colorPUI->colorPicker(), 1, 1); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/BondTypeEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/BondTypeEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/BondTypeEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/BondTypeEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BOND_TYPE_EDITOR_H -#define __OVITO_BOND_TYPE_EDITOR_H +#pragma once + #include #include @@ -55,4 +55,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_BOND_TYPE_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/BondTypePropertyEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/BondTypePropertyEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/BondTypePropertyEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/BondTypePropertyEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, BondTypePropertyEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(BondTypePropertyEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(BondTypeProperty, BondTypePropertyEditor); /****************************************************************************** @@ -64,7 +64,7 @@ sublayout->setContentsMargins(0,0,0,0); layout->addWidget(subEditorContainer); - RefTargetListParameterUI* bondTypesListUI = new CustomRefTargetListParameterUI(this, PROPERTY_FIELD(BondTypeProperty::_bondTypes), RolloutInsertionParameters().insertInto(subEditorContainer)); + RefTargetListParameterUI* bondTypesListUI = new CustomRefTargetListParameterUI(this, PROPERTY_FIELD(BondTypeProperty::bondTypes), RolloutInsertionParameters().insertInto(subEditorContainer)); layout->insertWidget(0, bondTypesListUI->listWidget()); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/BondTypePropertyEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/BondTypePropertyEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/BondTypePropertyEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/BondTypePropertyEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BOND_TYPE_PROPERTY_EDITOR_H -#define __OVITO_BOND_TYPE_PROPERTY_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_BOND_TYPE_PROPERTY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/ParticleDisplayEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/ParticleDisplayEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/ParticleDisplayEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/ParticleDisplayEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, ParticleDisplayEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(ParticleDisplayEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(ParticleDisplay, ParticleDisplayEditor); /****************************************************************************** @@ -45,7 +45,7 @@ layout->setColumnStretch(1, 1); // Shape. - VariantComboBoxParameterUI* particleShapeUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(ParticleDisplay::_particleShape)); + VariantComboBoxParameterUI* particleShapeUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(ParticleDisplay::particleShape)); particleShapeUI->comboBox()->addItem(QIcon(":/particles/icons/particle_shape_sphere.png"), tr("Sphere/Ellipsoid"), QVariant::fromValue(ParticleDisplay::Sphere)); particleShapeUI->comboBox()->addItem(QIcon(":/particles/icons/particle_shape_circle.png"), tr("Circle"), QVariant::fromValue(ParticleDisplay::Circle)); particleShapeUI->comboBox()->addItem(QIcon(":/particles/icons/particle_shape_cube.png"), tr("Cube/Box"), QVariant::fromValue(ParticleDisplay::Box)); @@ -56,7 +56,7 @@ layout->addWidget(particleShapeUI->comboBox(), 1, 1); // Default radius. - FloatParameterUI* radiusUI = new FloatParameterUI(this, PROPERTY_FIELD(ParticleDisplay::_defaultParticleRadius)); + FloatParameterUI* radiusUI = new FloatParameterUI(this, PROPERTY_FIELD(ParticleDisplay::defaultParticleRadius)); layout->addWidget(radiusUI->label(), 2, 0); layout->addLayout(radiusUI->createFieldLayout(), 2, 1); @@ -70,7 +70,7 @@ layout->setColumnStretch(1, 1); // Rendering quality. - VariantComboBoxParameterUI* renderingQualityUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(ParticleDisplay::_renderingQuality)); + VariantComboBoxParameterUI* renderingQualityUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(ParticleDisplay::renderingQuality)); renderingQualityUI->comboBox()->addItem(tr("Low"), QVariant::fromValue(ParticlePrimitive::LowQuality)); renderingQualityUI->comboBox()->addItem(tr("Medium"), QVariant::fromValue(ParticlePrimitive::MediumQuality)); renderingQualityUI->comboBox()->addItem(tr("High"), QVariant::fromValue(ParticlePrimitive::HighQuality)); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/ParticleDisplayEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/ParticleDisplayEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/ParticleDisplayEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/ParticleDisplayEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_DISPLAY_EDITOR_H -#define __OVITO_PARTICLE_DISPLAY_EDITOR_H +#pragma once + #include #include @@ -53,4 +53,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_DISPLAY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/ParticleTypeEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/ParticleTypeEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/ParticleTypeEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/ParticleTypeEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -31,7 +31,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, ParticleTypeEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(ParticleTypeEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(ParticleType, ParticleTypeEditor); /****************************************************************************** @@ -51,17 +51,17 @@ layout1->setColumnStretch(1, 1); // Text box for the name of particle type. - StringParameterUI* namePUI = new StringParameterUI(this, PROPERTY_FIELD(ParticleType::_name)); + StringParameterUI* namePUI = new StringParameterUI(this, PROPERTY_FIELD(ParticleType::name)); layout1->addWidget(new QLabel(tr("Name:")), 0, 0); layout1->addWidget(namePUI->textBox(), 0, 1); // Display color parameter. - ColorParameterUI* colorPUI = new ColorParameterUI(this, PROPERTY_FIELD(ParticleType::_color)); + ColorParameterUI* colorPUI = new ColorParameterUI(this, PROPERTY_FIELD(ParticleType::color)); layout1->addWidget(colorPUI->label(), 1, 0); layout1->addWidget(colorPUI->colorPicker(), 1, 1); // Display radius parameter. - FloatParameterUI* radiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(ParticleType::_radius)); + FloatParameterUI* radiusPUI = new FloatParameterUI(this, PROPERTY_FIELD(ParticleType::radius)); layout1->addWidget(radiusPUI->label(), 2, 0); layout1->addLayout(radiusPUI->createFieldLayout(), 2, 1); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/ParticleTypeEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/ParticleTypeEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/ParticleTypeEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/ParticleTypeEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_TYPE_EDITOR_H -#define __OVITO_PARTICLE_TYPE_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_TYPE_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/ParticleTypePropertyEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/ParticleTypePropertyEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/ParticleTypePropertyEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/ParticleTypePropertyEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, ParticleTypePropertyEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(ParticleTypePropertyEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(ParticleTypeProperty, ParticleTypePropertyEditor); /****************************************************************************** @@ -64,7 +64,7 @@ sublayout->setContentsMargins(0,0,0,0); layout->addWidget(subEditorContainer); - RefTargetListParameterUI* particleTypesListUI = new CustomRefTargetListParameterUI(this, PROPERTY_FIELD(ParticleTypeProperty::_particleTypes), RolloutInsertionParameters().insertInto(subEditorContainer)); + RefTargetListParameterUI* particleTypesListUI = new CustomRefTargetListParameterUI(this, PROPERTY_FIELD(ParticleTypeProperty::particleTypes), RolloutInsertionParameters().insertInto(subEditorContainer)); layout->insertWidget(0, particleTypesListUI->listWidget()); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/ParticleTypePropertyEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/ParticleTypePropertyEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/ParticleTypePropertyEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/ParticleTypePropertyEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_TYPE_PROPERTY_EDITOR_H -#define __OVITO_PARTICLE_TYPE_PROPERTY_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_TYPE_PROPERTY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/SimulationCellDisplayEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/SimulationCellDisplayEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/SimulationCellDisplayEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/SimulationCellDisplayEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,7 +28,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, SimulationCellDisplayEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(SimulationCellDisplayEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(SimulationCellDisplay, SimulationCellDisplayEditor); /****************************************************************************** @@ -46,16 +46,16 @@ layout->setColumnStretch(1, 1); // Render cell - BooleanParameterUI* renderCellUI = new BooleanParameterUI(this, PROPERTY_FIELD(SimulationCellDisplay::_renderSimulationCell)); + BooleanParameterUI* renderCellUI = new BooleanParameterUI(this, PROPERTY_FIELD(SimulationCellDisplay::renderCellEnabled)); layout->addWidget(renderCellUI->checkBox(), 0, 0, 1, 2); // Line width - FloatParameterUI* lineWidthUI = new FloatParameterUI(this, PROPERTY_FIELD(SimulationCellDisplay::_simulationCellLineWidth)); + FloatParameterUI* lineWidthUI = new FloatParameterUI(this, PROPERTY_FIELD(SimulationCellDisplay::cellLineWidth)); layout->addWidget(lineWidthUI->label(), 1, 0); layout->addLayout(lineWidthUI->createFieldLayout(), 1, 1); // Line color - ColorParameterUI* lineColorUI = new ColorParameterUI(this, PROPERTY_FIELD(SimulationCellDisplay::_simulationCellColor)); + ColorParameterUI* lineColorUI = new ColorParameterUI(this, PROPERTY_FIELD(SimulationCellDisplay::cellColor)); layout->addWidget(lineColorUI->label(), 2, 0); layout->addWidget(lineColorUI->colorPicker(), 2, 1); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/SimulationCellDisplayEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/SimulationCellDisplayEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/SimulationCellDisplayEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/SimulationCellDisplayEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SIMULATION_CELL_DISPLAY_EDITOR_H -#define __OVITO_SIMULATION_CELL_DISPLAY_EDITOR_H +#pragma once + #include #include @@ -50,4 +50,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SIMULATION_CELL_DISPLAY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/SimulationCellObjectEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/SimulationCellObjectEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/SimulationCellObjectEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/SimulationCellObjectEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, SimulationCellEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(SimulationCellEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(SimulationCellObject, SimulationCellEditor); /****************************************************************************** @@ -52,7 +52,7 @@ layout2->setContentsMargins(4,4,4,4); layout2->setSpacing(2); - BooleanRadioButtonParameterUI* is2dPUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(SimulationCellObject::_is2D)); + BooleanRadioButtonParameterUI* is2dPUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(SimulationCellObject::is2D)); is2dPUI->buttonTrue()->setText("2D"); is2dPUI->buttonFalse()->setText("3D"); layout2->addWidget(is2dPUI->buttonTrue(), 0, 0); @@ -67,15 +67,15 @@ layout2->setContentsMargins(4,4,4,4); layout2->setSpacing(2); - BooleanParameterUI* pbcxPUI = new BooleanParameterUI(this, PROPERTY_FIELD(SimulationCellObject::_pbcX)); + BooleanParameterUI* pbcxPUI = new BooleanParameterUI(this, PROPERTY_FIELD(SimulationCellObject::pbcX)); pbcxPUI->checkBox()->setText("X"); layout2->addWidget(pbcxPUI->checkBox(), 0, 0); - BooleanParameterUI* pbcyPUI = new BooleanParameterUI(this, PROPERTY_FIELD(SimulationCellObject::_pbcY)); + BooleanParameterUI* pbcyPUI = new BooleanParameterUI(this, PROPERTY_FIELD(SimulationCellObject::pbcY)); pbcyPUI->checkBox()->setText("Y"); layout2->addWidget(pbcyPUI->checkBox(), 0, 1); - pbczPUI = new BooleanParameterUI(this, PROPERTY_FIELD(SimulationCellObject::_pbcZ)); + pbczPUI = new BooleanParameterUI(this, PROPERTY_FIELD(SimulationCellObject::pbcZ)); pbczPUI->checkBox()->setText("Z"); layout2->addWidget(pbczPUI->checkBox(), 0, 2); } @@ -139,7 +139,7 @@ layout2->setSpacing(0); sublayout->addLayout(layout2); for(int i = 0; i < 3; i++) { - Vector3ParameterUI* vPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(SimulationCellObject::_cellVector1), i); + Vector3ParameterUI* vPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(SimulationCellObject::cellVector1), i); layout2->addLayout(vPUI->createFieldLayout(), 0, i*2); layout2->setColumnStretch(i*2, 1); if(i != 2) @@ -155,7 +155,7 @@ layout2->setSpacing(0); sublayout->addLayout(layout2); for(int i = 0; i < 3; i++) { - Vector3ParameterUI* vPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(SimulationCellObject::_cellVector2), i); + Vector3ParameterUI* vPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(SimulationCellObject::cellVector2), i); layout2->addLayout(vPUI->createFieldLayout(), 0, i*2); layout2->setColumnStretch(i*2, 1); if(i != 2) @@ -171,7 +171,7 @@ layout2->setSpacing(0); sublayout->addLayout(layout2); for(int i = 0; i < 3; i++) { - Vector3ParameterUI* vPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(SimulationCellObject::_cellVector3), i); + Vector3ParameterUI* vPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(SimulationCellObject::cellVector3), i); zvectorPUI[i] = vPUI; layout2->addLayout(vPUI->createFieldLayout(), 0, i*2); layout2->setColumnStretch(i*2, 1); @@ -188,7 +188,7 @@ layout2->setSpacing(0); sublayout->addLayout(layout2); for(int i = 0; i < 3; i++) { - Vector3ParameterUI* vPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(SimulationCellObject::_cellOrigin), i); + Vector3ParameterUI* vPUI = new Vector3ParameterUI(this, PROPERTY_FIELD(SimulationCellObject::cellOrigin), i); if(i == 2) zoriginPUI = vPUI; layout2->addLayout(vPUI->createFieldLayout(), 0, i*2); layout2->setColumnStretch(i*2, 1); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/SimulationCellObjectEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/SimulationCellObjectEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/SimulationCellObjectEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/SimulationCellObjectEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SIMULATION_CELL_OBJECT_EDITOR_H -#define __OVITO_SIMULATION_CELL_OBJECT_EDITOR_H +#pragma once + #include #include @@ -78,4 +78,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SIMULATION_CELL_OBJECT_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/SurfaceMeshDisplayEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/SurfaceMeshDisplayEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/SurfaceMeshDisplayEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/SurfaceMeshDisplayEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, SurfaceMeshDisplayEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(SurfaceMeshDisplayEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(SurfaceMeshDisplay, SurfaceMeshDisplayEditor); /****************************************************************************** @@ -52,18 +52,18 @@ sublayout->setColumnStretch(1, 1); layout->addWidget(surfaceGroupBox); - ColorParameterUI* surfaceColorUI = new ColorParameterUI(this, PROPERTY_FIELD(SurfaceMeshDisplay::_surfaceColor)); + ColorParameterUI* surfaceColorUI = new ColorParameterUI(this, PROPERTY_FIELD(SurfaceMeshDisplay::surfaceColor)); sublayout->addWidget(surfaceColorUI->label(), 0, 0); sublayout->addWidget(surfaceColorUI->colorPicker(), 0, 1); - FloatParameterUI* surfaceTransparencyUI = new FloatParameterUI(this, PROPERTY_FIELD(SurfaceMeshDisplay::_surfaceTransparency)); + FloatParameterUI* surfaceTransparencyUI = new FloatParameterUI(this, PROPERTY_FIELD(SurfaceMeshDisplay::surfaceTransparencyController)); sublayout->addWidget(new QLabel(tr("Transparency:")), 1, 0); sublayout->addLayout(surfaceTransparencyUI->createFieldLayout(), 1, 1); - BooleanParameterUI* smoothShadingUI = new BooleanParameterUI(this, PROPERTY_FIELD(SurfaceMeshDisplay::_smoothShading)); + BooleanParameterUI* smoothShadingUI = new BooleanParameterUI(this, PROPERTY_FIELD(SurfaceMeshDisplay::smoothShading)); sublayout->addWidget(smoothShadingUI->checkBox(), 2, 0, 1, 2); - BooleanGroupBoxParameterUI* capGroupUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(SurfaceMeshDisplay::_showCap)); + BooleanGroupBoxParameterUI* capGroupUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(SurfaceMeshDisplay::showCap)); capGroupUI->groupBox()->setTitle(tr("Cap polygons")); sublayout = new QGridLayout(capGroupUI->childContainer()); sublayout->setContentsMargins(4,4,4,4); @@ -71,15 +71,15 @@ sublayout->setColumnStretch(1, 1); layout->addWidget(capGroupUI->groupBox()); - ColorParameterUI* capColorUI = new ColorParameterUI(this, PROPERTY_FIELD(SurfaceMeshDisplay::_capColor)); + ColorParameterUI* capColorUI = new ColorParameterUI(this, PROPERTY_FIELD(SurfaceMeshDisplay::capColor)); sublayout->addWidget(capColorUI->label(), 0, 0); sublayout->addWidget(capColorUI->colorPicker(), 0, 1); - FloatParameterUI* capTransparencyUI = new FloatParameterUI(this, PROPERTY_FIELD(SurfaceMeshDisplay::_capTransparency)); + FloatParameterUI* capTransparencyUI = new FloatParameterUI(this, PROPERTY_FIELD(SurfaceMeshDisplay::capTransparencyController)); sublayout->addWidget(new QLabel(tr("Transparency:")), 1, 0); sublayout->addLayout(capTransparencyUI->createFieldLayout(), 1, 1); - BooleanParameterUI* reverseOrientationUI = new BooleanParameterUI(this, PROPERTY_FIELD(SurfaceMeshDisplay::_reverseOrientation)); + BooleanParameterUI* reverseOrientationUI = new BooleanParameterUI(this, PROPERTY_FIELD(SurfaceMeshDisplay::reverseOrientation)); sublayout->addWidget(reverseOrientationUI->checkBox(), 2, 0, 1, 2); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/SurfaceMeshDisplayEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/SurfaceMeshDisplayEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/SurfaceMeshDisplayEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/SurfaceMeshDisplayEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SURFACE_MESH_DISPLAY_EDITOR_H -#define __OVITO_SURFACE_MESH_DISPLAY_EDITOR_H +#pragma once + #include #include @@ -50,4 +50,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SURFACE_MESH_DISPLAY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/TrajectoryDisplayEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/TrajectoryDisplayEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/TrajectoryDisplayEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/TrajectoryDisplayEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, TrajectoryDisplayEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(TrajectoryDisplayEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(TrajectoryDisplay, TrajectoryDisplayEditor); /****************************************************************************** @@ -47,24 +47,24 @@ layout->setColumnStretch(1, 1); // Shading mode. - VariantComboBoxParameterUI* shadingModeUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(TrajectoryDisplay::_shadingMode)); + VariantComboBoxParameterUI* shadingModeUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(TrajectoryDisplay::shadingMode)); shadingModeUI->comboBox()->addItem(tr("Normal"), qVariantFromValue(ArrowPrimitive::NormalShading)); shadingModeUI->comboBox()->addItem(tr("Flat"), qVariantFromValue(ArrowPrimitive::FlatShading)); layout->addWidget(new QLabel(tr("Shading:")), 0, 0); layout->addWidget(shadingModeUI->comboBox(), 0, 1); // Line width. - FloatParameterUI* lineWidthUI = new FloatParameterUI(this, PROPERTY_FIELD(TrajectoryDisplay::_lineWidth)); + FloatParameterUI* lineWidthUI = new FloatParameterUI(this, PROPERTY_FIELD(TrajectoryDisplay::lineWidth)); layout->addWidget(lineWidthUI->label(), 1, 0); layout->addLayout(lineWidthUI->createFieldLayout(), 1, 1); // Line color. - ColorParameterUI* lineColorUI = new ColorParameterUI(this, PROPERTY_FIELD(TrajectoryDisplay::_lineColor)); + ColorParameterUI* lineColorUI = new ColorParameterUI(this, PROPERTY_FIELD(TrajectoryDisplay::lineColor)); layout->addWidget(lineColorUI->label(), 2, 0); layout->addWidget(lineColorUI->colorPicker(), 2, 1); // Up to current time. - BooleanParameterUI* showUpToCurrentTimeUI = new BooleanParameterUI(this, PROPERTY_FIELD(TrajectoryDisplay::_showUpToCurrentTime)); + BooleanParameterUI* showUpToCurrentTimeUI = new BooleanParameterUI(this, PROPERTY_FIELD(TrajectoryDisplay::showUpToCurrentTime)); layout->addWidget(showUpToCurrentTimeUI->checkBox(), 3, 0, 1, 2); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/TrajectoryDisplayEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/TrajectoryDisplayEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/TrajectoryDisplayEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/TrajectoryDisplayEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TRAJECTORY_DISPLAY_EDITOR_H -#define __OVITO_TRAJECTORY_DISPLAY_EDITOR_H +#pragma once + #include #include @@ -52,4 +52,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_TRAJECTORY_DISPLAY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/TrajectoryGeneratorObjectEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/TrajectoryGeneratorObjectEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/TrajectoryGeneratorObjectEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/TrajectoryGeneratorObjectEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,13 +28,13 @@ #include #include #include -#include +#include #include #include "TrajectoryGeneratorObjectEditor.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, TrajectoryGeneratorObjectEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(TrajectoryGeneratorObjectEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(TrajectoryGeneratorObject, TrajectoryGeneratorObjectEditor); /****************************************************************************** @@ -77,7 +77,7 @@ layout2->addWidget(new QLabel(tr("Generate trajectories for:")), 2, 0, 1, 2); - BooleanRadioButtonParameterUI* onlySelectedParticlesUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(TrajectoryGeneratorObject::_onlySelectedParticles)); + BooleanRadioButtonParameterUI* onlySelectedParticlesUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(TrajectoryGeneratorObject::onlySelectedParticles)); QRadioButton* allParticlesButton = onlySelectedParticlesUI->buttonFalse(); allParticlesButton->setText(tr("All particles")); @@ -97,7 +97,7 @@ layout2->setContentsMargins(4,4,4,4); layout2->setSpacing(2); - BooleanParameterUI* unwrapTrajectoriesUI = new BooleanParameterUI(this, PROPERTY_FIELD(TrajectoryGeneratorObject::_unwrapTrajectories)); + BooleanParameterUI* unwrapTrajectoriesUI = new BooleanParameterUI(this, PROPERTY_FIELD(TrajectoryGeneratorObject::unwrapTrajectories)); layout2->addWidget(unwrapTrajectoriesUI->checkBox(), 0, 0); } @@ -114,7 +114,7 @@ layout2c->setSpacing(2); layout2->addLayout(layout2c); - BooleanRadioButtonParameterUI* useCustomIntervalUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(TrajectoryGeneratorObject::_useCustomInterval)); + BooleanRadioButtonParameterUI* useCustomIntervalUI = new BooleanRadioButtonParameterUI(this, PROPERTY_FIELD(TrajectoryGeneratorObject::useCustomInterval)); QRadioButton* animationIntervalButton = useCustomIntervalUI->buttonFalse(); animationIntervalButton->setText(tr("Complete trajectory")); @@ -124,11 +124,11 @@ customIntervalButton->setText(tr("Frame interval:")); layout2c->addWidget(customIntervalButton, 1, 0, 1, 5); - IntegerParameterUI* customRangeStartUI = new IntegerParameterUI(this, PROPERTY_FIELD(TrajectoryGeneratorObject::_customIntervalStart)); + IntegerParameterUI* customRangeStartUI = new IntegerParameterUI(this, PROPERTY_FIELD(TrajectoryGeneratorObject::customIntervalStart)); customRangeStartUI->setEnabled(false); layout2c->addLayout(customRangeStartUI->createFieldLayout(), 2, 1); layout2c->addWidget(new QLabel(tr("to")), 2, 2); - IntegerParameterUI* customRangeEndUI = new IntegerParameterUI(this, PROPERTY_FIELD(TrajectoryGeneratorObject::_customIntervalEnd)); + IntegerParameterUI* customRangeEndUI = new IntegerParameterUI(this, PROPERTY_FIELD(TrajectoryGeneratorObject::customIntervalEnd)); customRangeEndUI->setEnabled(false); layout2c->addLayout(customRangeEndUI->createFieldLayout(), 2, 3); layout2c->setColumnMinimumWidth(0, 30); @@ -140,7 +140,7 @@ layout2a->setContentsMargins(0,6,0,0); layout2a->setSpacing(2); layout2->addLayout(layout2a); - IntegerParameterUI* everyNthFrameUI = new IntegerParameterUI(this, PROPERTY_FIELD(TrajectoryGeneratorObject::_everyNthFrame)); + IntegerParameterUI* everyNthFrameUI = new IntegerParameterUI(this, PROPERTY_FIELD(TrajectoryGeneratorObject::everyNthFrame)); layout2a->addWidget(everyNthFrameUI->label(), 0, 0); layout2a->addLayout(everyNthFrameUI->createFieldLayout(), 0, 1); layout2a->setColumnStretch(2, 1); @@ -159,18 +159,12 @@ TrajectoryGeneratorObject* trajObj = static_object_cast(editObject()); if(!trajObj) return; - undoableTransaction(tr("Generate trajectory"), [trajObj]() { + undoableTransaction(tr("Generate trajectory"), [this,trajObj]() { // Show progress dialog. - QProgressDialog progressDialog(MainWindow::fromDataset(trajObj->dataset())); - progressDialog.setWindowModality(Qt::WindowModal); - progressDialog.setAutoClose(false); - progressDialog.setAutoReset(false); - progressDialog.setMinimumDuration(0); - progressDialog.setValue(0); - ProgressDialogAdapter progressDisplay(&progressDialog); + ProgressDialog progressDialog(container(), trajObj->dataset()->container()->taskManager(), tr("Generating trajectory lines")); - trajObj->generateTrajectories(&progressDisplay); + trajObj->generateTrajectories(progressDialog.taskManager()); }); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/TrajectoryGeneratorObjectEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/TrajectoryGeneratorObjectEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/TrajectoryGeneratorObjectEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/TrajectoryGeneratorObjectEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TRAJECTORY_GENERATOR_OBJECT_EDITOR_H -#define __OVITO_TRAJECTORY_GENERATOR_OBJECT_EDITOR_H +#pragma once + #include #include @@ -57,4 +57,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_TRAJECTORY_GENERATOR_OBJECT_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/VectorDisplayEditor.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/VectorDisplayEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/VectorDisplayEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/VectorDisplayEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, VectorDisplayEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(VectorDisplayEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(VectorDisplay, VectorDisplayEditor); /****************************************************************************** @@ -48,44 +48,34 @@ int row = 0; // Shading mode. - VariantComboBoxParameterUI* shadingModeUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(VectorDisplay::_shadingMode)); + VariantComboBoxParameterUI* shadingModeUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(VectorDisplay::shadingMode)); shadingModeUI->comboBox()->addItem(tr("Normal"), QVariant::fromValue(ArrowPrimitive::NormalShading)); shadingModeUI->comboBox()->addItem(tr("Flat"), QVariant::fromValue(ArrowPrimitive::FlatShading)); layout->addWidget(new QLabel(tr("Shading mode:")), row, 0); layout->addWidget(shadingModeUI->comboBox(), row++, 1); -#if 0 - // Rendering quality. - VariantComboBoxParameterUI* renderingQualityUI = new VariantComboBoxParameterUI(this, "renderingQuality"); - renderingQualityUI->comboBox()->addItem(tr("Low"), qVariantFromValue(ArrowPrimitive::LowQuality)); - renderingQualityUI->comboBox()->addItem(tr("Medium"), qVariantFromValue(ArrowPrimitive::MediumQuality)); - renderingQualityUI->comboBox()->addItem(tr("High"), qVariantFromValue(ArrowPrimitive::HighQuality)); - layout->addWidget(new QLabel(tr("Rendering quality:")), row, 0); - layout->addWidget(renderingQualityUI->comboBox(), row++, 1); -#endif - // Scaling factor. - FloatParameterUI* scalingFactorUI = new FloatParameterUI(this, PROPERTY_FIELD(VectorDisplay::_scalingFactor)); + FloatParameterUI* scalingFactorUI = new FloatParameterUI(this, PROPERTY_FIELD(VectorDisplay::scalingFactor)); layout->addWidget(scalingFactorUI->label(), row, 0); layout->addLayout(scalingFactorUI->createFieldLayout(), row++, 1); // Arrow width factor. - FloatParameterUI* arrowWidthUI = new FloatParameterUI(this, PROPERTY_FIELD(VectorDisplay::_arrowWidth)); + FloatParameterUI* arrowWidthUI = new FloatParameterUI(this, PROPERTY_FIELD(VectorDisplay::arrowWidth)); layout->addWidget(arrowWidthUI->label(), row, 0); layout->addLayout(arrowWidthUI->createFieldLayout(), row++, 1); - VariantComboBoxParameterUI* arrowPositionUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(VectorDisplay::_arrowPosition)); + VariantComboBoxParameterUI* arrowPositionUI = new VariantComboBoxParameterUI(this, PROPERTY_FIELD(VectorDisplay::arrowPosition)); arrowPositionUI->comboBox()->addItem(QIcon(":/particles/icons/arrow_alignment_base.png"), tr("Base"), QVariant::fromValue(VectorDisplay::Base)); arrowPositionUI->comboBox()->addItem(QIcon(":/particles/icons/arrow_alignment_center.png"), tr("Center"), QVariant::fromValue(VectorDisplay::Center)); arrowPositionUI->comboBox()->addItem(QIcon(":/particles/icons/arrow_alignment_head.png"), tr("Head"), QVariant::fromValue(VectorDisplay::Head)); layout->addWidget(new QLabel(tr("Alignment:")), row, 0); layout->addWidget(arrowPositionUI->comboBox(), row++, 1); - ColorParameterUI* arrowColorUI = new ColorParameterUI(this, PROPERTY_FIELD(VectorDisplay::_arrowColor)); + ColorParameterUI* arrowColorUI = new ColorParameterUI(this, PROPERTY_FIELD(VectorDisplay::arrowColor)); layout->addWidget(arrowColorUI->label(), row, 0); layout->addWidget(arrowColorUI->colorPicker(), row++, 1); - BooleanParameterUI* reverseArrowDirectionUI = new BooleanParameterUI(this, PROPERTY_FIELD(VectorDisplay::_reverseArrowDirection)); + BooleanParameterUI* reverseArrowDirectionUI = new BooleanParameterUI(this, PROPERTY_FIELD(VectorDisplay::reverseArrowDirection)); layout->addWidget(reverseArrowDirectionUI->checkBox(), row++, 1, 1, 1); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/VectorDisplayEditor.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/VectorDisplayEditor.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/objects/VectorDisplayEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/objects/VectorDisplayEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VECTOR_DISPLAY_EDITOR_H -#define __OVITO_VECTOR_DISPLAY_EDITOR_H +#pragma once + #include #include @@ -50,4 +50,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_VECTOR_DISPLAY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/ParticlesGui.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/ParticlesGui.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/ParticlesGui.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/ParticlesGui.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLES_GUI_H -#define __OVITO_PARTICLES_GUI_H +#pragma once + #include #include @@ -38,5 +38,3 @@ OVITO_END_INLINE_NAMESPACE } } - -#endif diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/BondPropertyComboBox.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/BondPropertyComboBox.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/BondPropertyComboBox.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/BondPropertyComboBox.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BOND_PROPERTY_COMBO_BOX_H -#define __OVITO_BOND_PROPERTY_COMBO_BOX_H +#pragma once + #include #include @@ -96,4 +96,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_BOND_PROPERTY_COMBO_BOX_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/BondPropertyParameterUI.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/BondPropertyParameterUI.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/BondPropertyParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/BondPropertyParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Util) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(ParticlesGui, BondPropertyParameterUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(BondPropertyParameterUI, PropertyParameterUI); /****************************************************************************** * Constructor. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/BondPropertyParameterUI.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/BondPropertyParameterUI.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/BondPropertyParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/BondPropertyParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BOND_PROPERTY_PARAMETER_UI_H -#define __OVITO_BOND_PROPERTY_PARAMETER_UI_H +#pragma once + #include #include @@ -99,4 +99,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_BOND_PROPERTY_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/CreateTrajectoryApplet.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/CreateTrajectoryApplet.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/CreateTrajectoryApplet.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/CreateTrajectoryApplet.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,14 +27,14 @@ #include #include #include -#include +#include #include #include #include "CreateTrajectoryApplet.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, CreateTrajectoryApplet, UtilityApplet); +IMPLEMENT_OVITO_OBJECT(CreateTrajectoryApplet, UtilityApplet); /****************************************************************************** * Shows the UI of the utility in the given RolloutContainer. @@ -177,18 +177,22 @@ if(!dataset) return; try { + // Show progress dialog. + ProgressDialog progressDialog(_panel, dataset->container()->taskManager(), tr("Generating trajectory lines")); + UndoableTransaction transaction(dataset->undoStack(), tr("Create trajectory lines")); AnimationSuspender noAnim(dataset->animationSettings()); TimePoint time = dataset->animationSettings()->time(); // Get input particles. - ParticlePropertyObject* posProperty = nullptr; - ParticlePropertyObject* selectionProperty = nullptr; + OORef posProperty; + OORef selectionProperty; ObjectNode* inputNode = dynamic_object_cast(dataset->selection()->front()); if(inputNode) { - if(!inputNode->waitUntilReady(time, tr("Waiting for input particles to become ready."))) + Future stateFuture = inputNode->evaluatePipelineAsync(PipelineEvalRequest(time, false)); + if(!progressDialog.taskManager().waitForTask(stateFuture)) return; - const PipelineFlowState& state = inputNode->evalPipeline(time); + const PipelineFlowState& state = stateFuture.result(); posProperty = ParticlePropertyObject::findInState(state, ParticleProperty::PositionProperty); selectionProperty = ParticlePropertyObject::findInState(state, ParticleProperty::SelectionProperty); } @@ -235,17 +239,8 @@ if(interval.duration() <= 0) dataset->throwException(tr("Loaded simulation sequence consists only of a single frame. No trajectory lines were created.")); - // Show progress dialog. - QProgressDialog progressDialog(MainWindow::fromDataset(trajObj->dataset())); - progressDialog.setWindowModality(Qt::WindowModal); - progressDialog.setAutoClose(false); - progressDialog.setAutoReset(false); - progressDialog.setMinimumDuration(0); - progressDialog.setValue(0); - ProgressDialogAdapter progressDisplay(&progressDialog); - // Generate trajectories. - if(!trajObj->generateTrajectories(&progressDisplay)) + if(!trajObj->generateTrajectories(progressDialog.taskManager())) return; // Create scene node. @@ -262,13 +257,14 @@ // Commit actions. transaction.commit(); - - // Switch to the modify tab to show the newly created trajectory object. - _mainWindow->setCurrentCommandPanelPage(MainWindow::MODIFY_PAGE); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); + return; } + + // Switch to the modify tab to show the newly created trajectory object. + _mainWindow->setCurrentCommandPanelPage(MainWindow::MODIFY_PAGE); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/CreateTrajectoryApplet.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/CreateTrajectoryApplet.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/CreateTrajectoryApplet.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/CreateTrajectoryApplet.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CREATE_TRAJECTORY_APPLET_H -#define __OVITO_CREATE_TRAJECTORY_APPLET_H +#pragma once + #include #include @@ -72,4 +72,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CREATE_TRAJECTORY_APPLET_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/CutoffRadiusPresetsUI.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/CutoffRadiusPresetsUI.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/CutoffRadiusPresetsUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/CutoffRadiusPresetsUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -124,7 +124,7 @@ const size_t NumberOfChemicalElements = (sizeof(ChemicalElements) / sizeof(ChemicalElements[0])); -IMPLEMENT_OVITO_OBJECT(ParticlesGui, CutoffRadiusPresetsUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(CutoffRadiusPresetsUI, PropertyParameterUI); /****************************************************************************** * Constructor. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/CutoffRadiusPresetsUI.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/CutoffRadiusPresetsUI.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/CutoffRadiusPresetsUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/CutoffRadiusPresetsUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CUTOFF_RADIUS_PRESETS_H -#define __OVITO_CUTOFF_RADIUS_PRESETS_H +#pragma once + #include #include @@ -91,4 +91,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CUTOFF_RADIUS_PRESETS_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/FieldQuantityComboBox.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/FieldQuantityComboBox.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/FieldQuantityComboBox.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/FieldQuantityComboBox.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include "FieldQuantityComboBox.h" + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Util) + +/****************************************************************************** +* Returns the quantity that is currently selected in the combo box. +******************************************************************************/ +FieldQuantityReference FieldQuantityComboBox::currentFieldQuantity() const +{ + if(!isEditable()) { + int index = currentIndex(); + if(index < 0) + return FieldQuantityReference(); + return itemData(index).value(); + } + else { + QString name = currentText().simplified(); + if(!name.isEmpty()) { + return FieldQuantityReference(name); + } + return FieldQuantityReference(); + } +} + +/****************************************************************************** +* Sets the selection of the combo box to the given quantity. +******************************************************************************/ +void FieldQuantityComboBox::setCurrentFieldQuantity(const FieldQuantityReference& quantity) +{ + for(int index = 0; index < count(); index++) { + if(quantity == itemData(index).value()) { + setCurrentIndex(index); + return; + } + } + if(isEditable() && !quantity.isNull()) { + setCurrentText(quantity.name()); + } + else { + setCurrentIndex(-1); + } +} + +/****************************************************************************** +* Is called when the widget loses the input focus. +******************************************************************************/ +void FieldQuantityComboBox::focusOutEvent(QFocusEvent* event) +{ + if(isEditable()) { + int index = findText(currentText()); + if(index == -1 && currentText().isEmpty() == false) { + addItem(currentText()); + index = count() - 1; + } + setCurrentIndex(index); + Q_EMIT activated(index); + Q_EMIT activated(currentText()); + } + QComboBox::focusOutEvent(event); +} + + +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/FieldQuantityComboBox.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/FieldQuantityComboBox.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/FieldQuantityComboBox.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/FieldQuantityComboBox.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Util) + +/** + * \brief Widget that allows the user to select a field quantity from a list. + */ +class OVITO_PARTICLES_GUI_EXPORT FieldQuantityComboBox : public QComboBox +{ + Q_OBJECT + +public: + + /// \brief Default constructor. + /// \param parent The parent widget of the combo box. + FieldQuantityComboBox(QWidget* parent = nullptr) : QComboBox(parent) {} + + /// \brief Adds a quantity to the end of the list. + /// \param quantity The quantity to be added. + void addItem(const FieldQuantityReference& quantity, const QString& label = QString()) { + QComboBox::addItem(label.isEmpty() ? quantity.name() : label, QVariant::fromValue(quantity)); + } + + /// \brief Adds a quantity to the end of the list. + /// \param quantity The quantity to be added. + void addItem(FieldQuantityObject* quantity, int vectorComponent = -1) { + QString label = quantity->nameWithComponent(vectorComponent); + FieldQuantityReference quantityRef(quantity, vectorComponent); + QComboBox::addItem(label, QVariant::fromValue(quantityRef)); + } + + /// \brief Adds multiple quantities to the combo box. + /// \param list The list of quantities to be added. + void addItems(const QVector& list) { + for(FieldQuantityObject* q : list) + addItem(q); + } + + /// \brief Returns the field quantity that is currently selected in the + /// combo box. + /// \return The selected item. The returned reference can be null if + /// no item is currently selected. + FieldQuantityReference currentFieldQuantity() const; + + /// \brief Sets the selection of the combo box to the given quantity. + /// \param quantity The field quantity to be selected. + void setCurrentFieldQuantity(const FieldQuantityReference& quantity); + + /// \brief Returns the list index of the given quantity, or -1 if not found. + int quantityIndex(const FieldQuantityReference& quantity) const { + for(int index = 0; index < count(); index++) { + if(quantity == itemData(index).value()) + return index; + } + return -1; + } + + /// \brief Returns the quantity at the given index. + FieldQuantityReference quantity(int index) const { + return itemData(index).value(); + } + +protected: + + /// Is called when the widget loses the input focus. + virtual void focusOutEvent(QFocusEvent* event) override; + +}; + +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/FieldQuantityParameterUI.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/FieldQuantityParameterUI.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/FieldQuantityParameterUI.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/FieldQuantityParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,202 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "FieldQuantityParameterUI.h" + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Util) + +// Gives the class run-time type information. +IMPLEMENT_OVITO_OBJECT(FieldQuantityParameterUI, PropertyParameterUI); + +/****************************************************************************** +* Constructor. +******************************************************************************/ +FieldQuantityParameterUI::FieldQuantityParameterUI(QObject* parentEditor, const char* propertyName, bool showComponents, bool inputProperty) : + PropertyParameterUI(parentEditor, propertyName), _comboBox(new FieldQuantityComboBox()), _showComponents(showComponents), _inputProperty(inputProperty) +{ + connect(comboBox(), (void (QComboBox::*)(const QString&))&QComboBox::activated, this, &FieldQuantityParameterUI::updatePropertyValue); + + if(!inputProperty) + comboBox()->setEditable(true); +} + +/****************************************************************************** +* Constructor. +******************************************************************************/ +FieldQuantityParameterUI::FieldQuantityParameterUI(QObject* parentEditor, const PropertyFieldDescriptor& propField, bool showComponents, bool inputProperty) : + PropertyParameterUI(parentEditor, propField), _comboBox(new FieldQuantityComboBox()), _showComponents(showComponents), _inputProperty(inputProperty) +{ + connect(comboBox(), (void (QComboBox::*)(const QString&))&QComboBox::activated, this, &FieldQuantityParameterUI::updatePropertyValue); + + if(!inputProperty) + comboBox()->setEditable(true); +} + +/****************************************************************************** +* Destructor. +******************************************************************************/ +FieldQuantityParameterUI::~FieldQuantityParameterUI() +{ + // Release GUI controls. + delete comboBox(); +} + +/****************************************************************************** +* This method is called when a new editable object has been assigned to the properties owner this +* parameter UI belongs to. +******************************************************************************/ +void FieldQuantityParameterUI::resetUI() +{ + PropertyParameterUI::resetUI(); + + if(comboBox()) + comboBox()->setEnabled(editObject() != NULL && isEnabled()); +} + +/****************************************************************************** +* This method is called when a new editable object has been assigned to the properties owner this +* parameter UI belongs to. +******************************************************************************/ +void FieldQuantityParameterUI::updateUI() +{ + PropertyParameterUI::updateUI(); + + if(comboBox() && editObject()) { + + FieldQuantityReference pref; + if(isQtPropertyUI()) { + QVariant val = editObject()->property(propertyName()); + OVITO_ASSERT_MSG(val.isValid() && val.canConvert(), "FieldQuantityParameterUI::updateUI()", QString("The object class %1 does not define a property with the name %2 of type FieldQuantityReference.").arg(editObject()->metaObject()->className(), QString(propertyName())).toLocal8Bit().constData()); + if(!val.isValid() || !val.canConvert()) { + editObject()->throwException(tr("The object class %1 does not define a property with the name %2 that can be cast to a FieldQuantityReference.").arg(editObject()->metaObject()->className(), QString(propertyName()))); + } + pref = val.value(); + } + else if(isPropertyFieldUI()) { + QVariant val = editObject()->getPropertyFieldValue(*propertyField()); + OVITO_ASSERT_MSG(val.isValid() && val.canConvert(), "FieldQuantityParameterUI::updateUI()", QString("The property field of object class %1 is not of type FieldQuantityReference.").arg(editObject()->metaObject()->className()).toLocal8Bit().constData()); + pref = val.value(); + } + + if(_inputProperty) { + _comboBox->clear(); + + // Obtain the list of input properties. + Modifier* mod = dynamic_object_cast(editObject()); + if(mod) { + PipelineFlowState inputState = mod->getModifierInput(); + + // Populate property list from input object. + int initialIndex = -1; + for(DataObject* o : inputState.objects()) { + FieldQuantityObject* quantity = dynamic_object_cast(o); + if(!quantity) continue; + + // Properties with a non-numeric data type cannot be used as source properties. + if(quantity->dataType() != qMetaTypeId() && quantity->dataType() != qMetaTypeId()) + continue; + + if(quantity->componentNames().empty() || !_showComponents) { + // Scalar property: + _comboBox->addItem(quantity); + } + else { + // Vector property: + for(int vectorComponent = 0; vectorComponent < (int)quantity->componentCount(); vectorComponent++) { + _comboBox->addItem(quantity, vectorComponent); + } + } + } + } + + if(_comboBox->count() == 0) + _comboBox->addItem(FieldQuantityReference(), tr("")); + + // Select the right item in the list box. + int selIndex = _comboBox->quantityIndex(pref); + if(selIndex < 0 && !pref.isNull()) { + // Add a place-holder item if the selected quantity does not exist anymore. + _comboBox->addItem(pref, tr("%1 (no longer available)").arg(pref.name())); + selIndex = _comboBox->count() - 1; + } + _comboBox->setCurrentIndex(selIndex); + } + else { + _comboBox->setCurrentFieldQuantity(pref); + } + } + else if(comboBox()) + comboBox()->clear(); +} + +/****************************************************************************** +* Sets the enabled state of the UI. +******************************************************************************/ +void FieldQuantityParameterUI::setEnabled(bool enabled) +{ + if(enabled == isEnabled()) return; + PropertyParameterUI::setEnabled(enabled); + if(comboBox()) comboBox()->setEnabled(editObject() != NULL && isEnabled()); +} + +/****************************************************************************** +* Takes the value entered by the user and stores it in the property field +* this property UI is bound to. +******************************************************************************/ +void FieldQuantityParameterUI::updatePropertyValue() +{ + if(comboBox() && editObject() && comboBox()->currentText().isEmpty() == false) { + undoableTransaction(tr("Change parameter"), [this]() { + FieldQuantityReference pref = _comboBox->currentFieldQuantity(); + if(isQtPropertyUI()) { + + // Check if new value differs from old value. + QVariant oldval = editObject()->property(propertyName()); + if(pref == oldval.value()) + return; + + if(!editObject()->setProperty(propertyName(), QVariant::fromValue(pref))) { + OVITO_ASSERT_MSG(false, "FieldQuantityParameterUI::updatePropertyValue()", QString("The value of property %1 of object class %2 could not be set.").arg(QString(propertyName()), editObject()->metaObject()->className()).toLocal8Bit().constData()); + } + } + else if(isPropertyFieldUI()) { + + // Check if new value differs from old value. + QVariant oldval = editObject()->getPropertyFieldValue(*propertyField()); + if(pref == oldval.value()) + return; + + editObject()->setPropertyFieldValue(*propertyField(), QVariant::fromValue(pref)); + } + else return; + + Q_EMIT valueEntered(); + }); + } +} + +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/FieldQuantityParameterUI.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/FieldQuantityParameterUI.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/FieldQuantityParameterUI.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/FieldQuantityParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,102 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include +#include "FieldQuantityComboBox.h" + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Util) + +/** + * \brief This parameter UI lets the user select a field quantity. + */ +class OVITO_PARTICLES_GUI_EXPORT FieldQuantityParameterUI : public PropertyParameterUI +{ +public: + + /// Constructor. + FieldQuantityParameterUI(QObject* parentEditor, const char* propertyName, bool showComponents = true, bool inputProperty = true); + + /// Constructor. + FieldQuantityParameterUI(QObject* parentEditor, const PropertyFieldDescriptor& propField, bool showComponents = true, bool inputProperty = true); + + /// Destructor. + virtual ~FieldQuantityParameterUI(); + + /// This returns the combo box managed by this ParameterUI. + QComboBox* comboBox() const { return _comboBox; } + + /// This method is called when a new editable object has been assigned to the properties owner this + /// parameter UI belongs to. + virtual void resetUI() override; + + /// This method updates the displayed value of the property UI. + virtual void updateUI() override; + + /// Sets the enabled state of the UI. + virtual void setEnabled(bool enabled) override; + + /// Sets the tooltip text for the combo box widget. + void setToolTip(const QString& text) const { + if(comboBox()) comboBox()->setToolTip(text); + } + + /// Sets the What's This helper text for the combo box. + void setWhatsThis(const QString& text) const { + if(comboBox()) comboBox()->setWhatsThis(text); + } + +public: + + Q_PROPERTY(QComboBox comboBox READ comboBox); + +public Q_SLOTS: + + /// Takes the value entered by the user and stores it in the property field + /// this property UI is bound to. + void updatePropertyValue(); + +protected: + + /// The combo box of the UI component. + QPointer _comboBox; + + /// Controls whether the combo box should display a separate entry for each component of + /// a quantity. + bool _showComponents; + + /// Controls whether the combo box should list input or output properties. + bool _inputProperty; + +private: + + Q_OBJECT + OVITO_OBJECT +}; + +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticleInformationApplet.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticleInformationApplet.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticleInformationApplet.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticleInformationApplet.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,17 +23,20 @@ #include #include #include +#include #include #include #include #include +#include #include #include +#include #include "ParticleInformationApplet.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Util) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, ParticleInformationApplet, UtilityApplet); +IMPLEMENT_OVITO_OBJECT(ParticleInformationApplet, UtilityApplet); /****************************************************************************** * Shows the UI of the utility in the given RolloutContainer. @@ -45,17 +48,27 @@ // Create a rollout. _panel = new QWidget(); - container->addRollout(_panel, tr("Particle information"), rolloutParams.useAvailableSpace()); + container->addRollout(_panel, tr("Particle information"), rolloutParams.useAvailableSpace(), "utilities.particle_inspection.html"); // Create the rollout contents. QVBoxLayout* layout = new QVBoxLayout(_panel); layout->setContentsMargins(4,4,4,4); - layout->setSpacing(4); + layout->setSpacing(2); _inputMode = new ParticleInformationInputMode(this); ViewportModeAction* pickModeAction = new ViewportModeAction(_mainWindow, tr("Selection mode"), this, _inputMode); - //layout->addWidget(pickModeAction->createPushButton()); + layout->addWidget(new QLabel(tr("Particle selection expression:"))); + _expressionEdit = new AutocompleteTextEdit(); + layout->addWidget(_expressionEdit); + connect(_expressionEdit, &AutocompleteTextEdit::editingFinished, this, [this]() { + _userSelectionExpression = _expressionEdit->toPlainText(); + updateInformationDisplay(); + }); + + layout->addSpacing(2); + _displayHeader = new QLabel(tr("Particle information:")); + layout->addWidget(_displayHeader); _infoDisplay = new QTextEdit(_panel); _infoDisplay->setReadOnly(true); _infoDisplay->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); @@ -66,9 +79,28 @@ #endif layout->addWidget(_infoDisplay, 1); + // Install signal handlers to automatically update displayed information upon animation time change. connect(&_mainWindow->datasetContainer(), &DataSetContainer::animationSettingsReplaced, this, &ParticleInformationApplet::onAnimationSettingsReplaced); _timeChangeCompleteConnection = connect(_mainWindow->datasetContainer().currentSet()->animationSettings(), &AnimationSettings::timeChangeComplete, this, &ParticleInformationApplet::updateInformationDisplay); + + // Also update displayed information whenever scene selection changes. + connect(&_mainWindow->datasetContainer(), &DataSetContainer::selectionChangeComplete, this, &ParticleInformationApplet::updateInformationDisplay); + + // Activate the viewport input mode which allows picking particles with the mouse. _mainWindow->viewportInputManager()->pushInputMode(_inputMode); + + // Update the list of variables that can be referenced in the selection expression. + try { + if(DataSet* dataset = _mainWindow->datasetContainer().currentSet()) { + if(ObjectNode* node = dynamic_object_cast(dataset->selection()->front())) { + const PipelineFlowState& state = node->evaluatePipelineImmediately(PipelineEvalRequest(dataset->animationSettings()->time(), false)); + ParticleExpressionEvaluator evaluator; + evaluator.initialize(QStringList(), state, 0); + _expressionEdit->setWordList(evaluator.inputVariableNames()); + } + } + } + catch(const Exception& ex) {} } /****************************************************************************** @@ -100,65 +132,151 @@ if(!dataset) return; QString infoText; + size_t nselected = 0; QTextStream stream(&infoText, QIODevice::WriteOnly); - for(auto& pickedParticle : _inputMode->_pickedParticles) { - OVITO_ASSERT(pickedParticle.objNode); - const PipelineFlowState& flowState = pickedParticle.objNode->evalPipeline(dataset->animationSettings()->time()); - - // If selection is based on particle ID, update the stored particle index in case order has changed. - if(pickedParticle.particleId >= 0) { - for(DataObject* dataObj : flowState.objects()) { - ParticlePropertyObject* property = dynamic_object_cast(dataObj); - if(property && property->type() == ParticleProperty::IdentifierProperty) { - const int* begin = property->constDataInt(); - const int* end = begin + property->size(); - const int* iter = std::find(begin, end, pickedParticle.particleId); - if(iter != end) - pickedParticle.particleIndex = (iter - begin); + + // In case a user-defined selection expression has been entered, + // apply it the current particle system to generate a new selection set. + if(!_userSelectionExpression.isEmpty()) { + _inputMode->_pickedParticles.clear(); + try { + // Check if expression contain an assignment ('=' operator). + // This should be considered an error, because the user is probably referring the comparison operator '=='. + if(_userSelectionExpression.contains(QRegExp("[^=!><]=(?!=)"))) + throwException(tr("The entered expression contains the assignment operator '='. Please use the comparison operator '==' instead.")); + + // Get the currently selected scene node and obtains its pipeline results. + ObjectNode* node = dynamic_object_cast(dataset->selection()->front()); + if(!node) throwException(tr("No scene object is currently selected.")); + const PipelineFlowState& state = node->evaluatePipelineImmediately(PipelineEvalRequest(dataset->animationSettings()->time(), false)); + TimeInterval iv; + const AffineTransformation nodeTM = node->getWorldTransform(dataset->animationSettings()->time(), iv); + ParticlePropertyObject* posProperty = ParticlePropertyObject::findInState(state, ParticleProperty::PositionProperty); + ParticlePropertyObject* identifierProperty = ParticlePropertyObject::findInState(state, ParticleProperty::IdentifierProperty); + + // Generate particle selection set. + ParticleExpressionEvaluator evaluator; + evaluator.setMaxThreadCount(1); // Disable multi-threading to make the selection order deterministic. + evaluator.initialize(QStringList(_userSelectionExpression), state, dataset->animationSettings()->currentFrame()); + evaluator.evaluate([this, node, &nodeTM, posProperty, identifierProperty, &nselected](size_t particleIndex, size_t componentIndex, double value) { + if(value) { + ParticlePickingHelper::PickResult pickRes; + pickRes.objNode = node; + pickRes.particleIndex = particleIndex; + pickRes.localPos = posProperty ? posProperty->getPoint3(particleIndex) : Point3::Origin(); + pickRes.worldPos = nodeTM * pickRes.localPos; + pickRes.particleId = identifierProperty ? identifierProperty->getInt(particleIndex) : -1; + ++nselected; + if(_inputMode->_pickedParticles.size() < _maxSelectionSize) + _inputMode->_pickedParticles.push_back(pickRes); } - } + }); } + catch(const Exception& ex) { + stream << QStringLiteral("

    Evaluation error: ") << ex.messages().join("
    ") << QStringLiteral("

    "); + } + // Update the displayed particle markers to reflect the new selection set. + dataset->viewportConfig()->updateViewports(); + } + + QString autoExpressionText; + for(auto pickedParticle = _inputMode->_pickedParticles.begin(); pickedParticle != _inputMode->_pickedParticles.end(); ) { + OVITO_ASSERT(pickedParticle->objNode); + + // Check if the scene node to which the selected particle belongs still exists. + if(pickedParticle->objNode->isInScene()) { + + const PipelineFlowState& flowState = pickedParticle->objNode->evaluatePipelineImmediately(PipelineEvalRequest(dataset->animationSettings()->time(), false)); + + // If selection is based on particle ID, update the stored particle index in case order has changed. + if(pickedParticle->particleId >= 0) { + for(DataObject* dataObj : flowState.objects()) { + ParticlePropertyObject* property = dynamic_object_cast(dataObj); + if(property && property->type() == ParticleProperty::IdentifierProperty) { + const int* begin = property->constDataInt(); + const int* end = begin + property->size(); + const int* iter = std::find(begin, end, pickedParticle->particleId); + if(iter != end) { + pickedParticle->particleIndex = (iter - begin); + } + else { + pickedParticle->particleIndex = std::numeric_limits::max(); + } + } + } + } - stream << QStringLiteral("") << tr("Particle index") << QStringLiteral(" ") << (pickedParticle.particleIndex + 1) << QStringLiteral(":"); - stream << QStringLiteral(""); + // Generate an automatic selection expression. + if(_userSelectionExpression.isEmpty()) { + if(!autoExpressionText.isEmpty()) autoExpressionText += QStringLiteral(" ||\n"); + if(pickedParticle->particleId >= 0) + autoExpressionText += QStringLiteral("ParticleIdentifier==%1").arg(pickedParticle->particleId); + else + autoExpressionText += QStringLiteral("ParticleIndex==%1").arg(pickedParticle->particleIndex); + } - for(DataObject* dataObj : flowState.objects()) { - ParticlePropertyObject* property = dynamic_object_cast(dataObj); - if(!property || property->size() <= pickedParticle.particleIndex) continue; - - // Update saved particle position in case it has changed. - if(property->type() == ParticleProperty::PositionProperty) - pickedParticle.localPos = property->getPoint3(pickedParticle.particleIndex); - - if(property->dataType() != qMetaTypeId() && property->dataType() != qMetaTypeId()) continue; - for(size_t component = 0; component < property->componentCount(); component++) { - QString propertyName = property->name(); - if(property->componentNames().empty() == false) { - propertyName.append("."); - propertyName.append(property->componentNames()[component]); - } - QString valueString; - if(property->dataType() == qMetaTypeId()) { - valueString = QString::number(property->getIntComponent(pickedParticle.particleIndex, component)); - ParticleTypeProperty* typeProperty = dynamic_object_cast(property); - if(typeProperty && typeProperty->particleTypes().empty() == false) { - ParticleType* ptype = typeProperty->particleType(property->getIntComponent(pickedParticle.particleIndex, component)); - if(ptype) { - valueString.append(" (" + ptype->name() + ")"); + ParticlePropertyObject* posProperty = ParticlePropertyObject::findInState(flowState, ParticleProperty::PositionProperty); + if(posProperty && posProperty->size() > pickedParticle->particleIndex) { + + stream << QStringLiteral("") << tr("Particle index") << QStringLiteral(" ") << pickedParticle->particleIndex << QStringLiteral(":"); + stream << QStringLiteral("
    "); + + for(DataObject* dataObj : flowState.objects()) { + ParticlePropertyObject* property = dynamic_object_cast(dataObj); + if(!property || property->size() <= pickedParticle->particleIndex) continue; + + // Update saved particle position in case it has changed. + if(property->type() == ParticleProperty::PositionProperty) + pickedParticle->localPos = property->getPoint3(pickedParticle->particleIndex); + + if(property->dataType() != qMetaTypeId() && property->dataType() != qMetaTypeId()) continue; + for(size_t component = 0; component < property->componentCount(); component++) { + QString propertyName = property->name(); + if(property->componentNames().empty() == false) { + propertyName.append("."); + propertyName.append(property->componentNames()[component]); + } + QString valueString; + if(property->dataType() == qMetaTypeId()) { + valueString = QString::number(property->getIntComponent(pickedParticle->particleIndex, component)); + ParticleTypeProperty* typeProperty = dynamic_object_cast(property); + if(typeProperty && typeProperty->particleTypes().empty() == false) { + ParticleType* ptype = typeProperty->particleType(property->getIntComponent(pickedParticle->particleIndex, component)); + if(ptype) { + valueString.append(" (" + ptype->name() + ")"); + } + } } + else if(property->dataType() == qMetaTypeId()) + valueString = QString::number(property->getFloatComponent(pickedParticle->particleIndex, component)); + + stream << QStringLiteral(""); } } - else if(property->dataType() == qMetaTypeId()) - valueString = QString::number(property->getFloatComponent(pickedParticle.particleIndex, component)); - - stream << QStringLiteral(""); + stream << QStringLiteral("
    ") << propertyName << QStringLiteral(":") << valueString << QStringLiteral("
    ") << propertyName << QStringLiteral(":") << valueString << QStringLiteral("

    "); + ++pickedParticle; + continue; } } - stream << QStringLiteral("
    "); + // Remove non-existent particle from the list. + pickedParticle = _inputMode->_pickedParticles.erase(pickedParticle); + } + + if(_userSelectionExpression.isEmpty()) + _expressionEdit->setPlainText(autoExpressionText); + + if(_inputMode->_pickedParticles.empty()) { + stream << tr("No particles selected."); + _displayHeader->setText(tr("Particle information:")); } - if(_inputMode->_pickedParticles.empty()) - infoText = tr("No particles selected."); - else if(_inputMode->_pickedParticles.size() >= 2) { + else if(_inputMode->_pickedParticles.size() >= nselected) { + _displayHeader->setText(tr("Particle information (%1):").arg(_inputMode->_pickedParticles.size())); + } + else { + _displayHeader->setText(tr("Particle information (%1 out of %2):").arg(_inputMode->_pickedParticles.size()).arg(nselected)); + } + + if(_inputMode->_pickedParticles.size() >= 2) { stream << QStringLiteral("") << tr("Pair vectors:") << QStringLiteral(""); stream << QStringLiteral(""); for(size_t i = 0; i < _inputMode->_pickedParticles.size(); i++) { @@ -166,9 +284,9 @@ for(size_t j = i + 1; j < _inputMode->_pickedParticles.size(); j++) { const auto& p2 = _inputMode->_pickedParticles[j]; Vector3 delta = p2.localPos - p1.localPos; - stream << QStringLiteral(""); + stream << QStringLiteral(""); stream << QStringLiteral(""); } @@ -192,8 +310,8 @@ v2.normalizeSafely(); FloatType angle = acos(v1.dot(v2)); stream << QStringLiteral(""); + p2.particleIndex << QStringLiteral(" - ") << p1.particleIndex << QStringLiteral(" - ") << p3.particleIndex << + QStringLiteral("):"); } } } @@ -213,7 +331,7 @@ if(!event->modifiers().testFlag(Qt::ControlModifier)) _pickedParticles.clear(); if(pickResult.objNode) { - // Don't select the same particle twice. + // Don't select the same particle twice. Instead, toggle selection. bool alreadySelected = false; for(auto p = _pickedParticles.begin(); p != _pickedParticles.end(); ++p) { if(p->objNode == pickResult.objNode && p->particleIndex == pickResult.particleIndex) { @@ -225,6 +343,7 @@ if(!alreadySelected) _pickedParticles.push_back(pickResult); } + _applet->resetUserExpression(); _applet->updateInformationDisplay(); vpwin->viewport()->dataset()->viewportConfig()->updateViewports(); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticleInformationApplet.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticleInformationApplet.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticleInformationApplet.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticleInformationApplet.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_INFORMATION_APPLET_H -#define __OVITO_PARTICLE_INFORMATION_APPLET_H +#pragma once + #include #include @@ -56,13 +56,21 @@ /// Updates the display of particle properties. void updateInformationDisplay(); + /// Switches back to the auto-generated selection expression. + void resetUserExpression() { _userSelectionExpression.clear(); } + private: MainWindow* _mainWindow; + AutocompleteTextEdit* _expressionEdit; + QString _userSelectionExpression; QTextEdit* _infoDisplay; - QWidget* _panel; + QLabel* _displayHeader; + QWidget* _panel; ParticleInformationInputMode* _inputMode; QMetaObject::Connection _timeChangeCompleteConnection; + + size_t _maxSelectionSize = 10; Q_CLASSINFO("DisplayName", "Inspect particles"); @@ -105,7 +113,7 @@ ParticleInformationApplet* _applet; /// The selected particles whose properties are being displayed. - std::deque _pickedParticles; + std::vector _pickedParticles; friend class ParticleInformationApplet; }; @@ -115,4 +123,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_INFORMATION_APPLET_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticlePickingHelper.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticlePickingHelper.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticlePickingHelper.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticlePickingHelper.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -77,7 +77,7 @@ if(!pickRecord.objNode) return Box3(); - const PipelineFlowState& flowState = pickRecord.objNode->evalPipeline(vp->dataset()->animationSettings()->time()); + const PipelineFlowState& flowState = pickRecord.objNode->evaluatePipelineImmediately(PipelineEvalRequest(vp->dataset()->animationSettings()->time(), true)); // If particle selection is based on ID, find particle with the given ID. size_t particleIndex = pickRecord.particleIndex; @@ -123,7 +123,7 @@ if(!renderer->isInteractive() || renderer->isPicking()) return; - const PipelineFlowState& flowState = pickRecord.objNode->evalPipeline(vp->dataset()->animationSettings()->time()); + const PipelineFlowState& flowState = pickRecord.objNode->evaluatePipelineImmediately(PipelineEvalRequest(vp->dataset()->animationSettings()->time(), true)); // If particle selection is based on ID, find particle with the given ID. size_t particleIndex = pickRecord.particleIndex; diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticlePickingHelper.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticlePickingHelper.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticlePickingHelper.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticlePickingHelper.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_PICKING_HELPER_H -#define __OVITO_PARTICLE_PICKING_HELPER_H +#pragma once + #include #include @@ -97,4 +97,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_PICKING_HELPER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticlePropertyComboBox.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticlePropertyComboBox.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticlePropertyComboBox.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticlePropertyComboBox.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_PROPERTY_COMBO_BOX_H -#define __OVITO_PARTICLE_PROPERTY_COMBO_BOX_H +#pragma once + #include #include @@ -96,4 +96,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_PROPERTY_COMBO_BOX_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticlePropertyParameterUI.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticlePropertyParameterUI.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticlePropertyParameterUI.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticlePropertyParameterUI.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Util) // Gives the class run-time type information. -IMPLEMENT_OVITO_OBJECT(ParticlesGui, ParticlePropertyParameterUI, PropertyParameterUI); +IMPLEMENT_OVITO_OBJECT(ParticlePropertyParameterUI, PropertyParameterUI); /****************************************************************************** * Constructor. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticlePropertyParameterUI.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticlePropertyParameterUI.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticlePropertyParameterUI.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticlePropertyParameterUI.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_PROPERTY_PARAMETER_UI_H -#define __OVITO_PARTICLE_PROPERTY_PARAMETER_UI_H +#pragma once + #include #include @@ -104,4 +104,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_PROPERTY_PARAMETER_UI_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticleSettingsPage.cpp ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticleSettingsPage.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticleSettingsPage.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticleSettingsPage.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,7 +25,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(ParticlesGui, ParticleSettingsPage, ApplicationSettingsDialogPage); +IMPLEMENT_OVITO_OBJECT(ParticleSettingsPage, ApplicationSettingsDialogPage); class NameColumnDelegate : public QStyledItemDelegate { diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticleSettingsPage.h ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticleSettingsPage.h --- ovito-2.8.1+dfsg2/src/plugins/particles/gui/util/ParticleSettingsPage.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/gui/util/ParticleSettingsPage.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_SETTINGS_PAGE_H -#define __OVITO_PARTICLE_SETTINGS_PAGE_H +#pragma once + #include #include @@ -63,4 +63,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_SETTINGS_PAGE_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/castep/CastepCellImporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/castep/CastepCellImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/castep/CastepCellImporter.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/castep/CastepCellImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,224 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include "CastepCellImporter.h" + +#include + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CastepCellImporter, ParticleImporter); + +static const char* chemical_symbols[] = { + // 0 + "X", + // 1 + "H", "He", + // 2 + "Li", "Be", "B", "C", "N", "O", "F", "Ne", + // 3 + "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", + // 4 + "K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", + "Ga", "Ge", "As", "Se", "Br", "Kr", + // 5 + "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", + "In", "Sn", "Sb", "Te", "I", "Xe", + // 6 + "Cs", "Ba", "La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", "Dy", + "Ho", "Er", "Tm", "Yb", "Lu", + "Hf", "Ta", "W", "Re", "Os", "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi", + "Po", "At", "Rn", + // 7 + "Fr", "Ra", "Ac", "Th", "Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", + "Cf", "Es", "Fm", "Md", "No", "Lr", + "Rf", "Db", "Sg", "Bh", "Hs", "Mt", "Ds", "Rg", "Cn", "Nh", "Fl", "Mc", + "Lv", "Ts", "Og" +}; + +/****************************************************************************** +* Checks if the given file has format that can be read by this importer. +******************************************************************************/ +bool CastepCellImporter::checkFileFormat(QFileDevice& input, const QUrl& sourceLocation) +{ + // Open input file. + CompressedTextReader stream(input, sourceLocation.path()); + + // Look for string '%BLOCK POSITIONS' to occur within the first 100 lines of the .cell file. + for(int i = 0; i < 100 && !stream.eof(); i++) { + if(boost::algorithm::istarts_with(stream.readLineTrimLeft(1024), "%BLOCK POSITIONS")) + return true; + } + + return false; +} + +/****************************************************************************** +* Parses the given input file and stores the data in the given container object. +******************************************************************************/ +void CastepCellImporter::ImportTask::parseFile(CompressedTextReader& stream) +{ + setProgressText(tr("Reading CASTEP file %1").arg(frame().sourceFile.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded))); + + // Helper function that reads and returns the next line from the .cell file + // that is not a comment line: + auto readNonCommentLine = [&stream]() { + while(!stream.eof()) { + const char* line = stream.readLineTrimLeft(); + if(line[0] == '\0' || line[0] == '#' || line[0] == ';' || line[0] == '!') continue; + if(boost::algorithm::istarts_with(line, "COMMENT")) continue; + return line; + } + return ""; + }; + + while(!isCanceled()) { + + // Parse line by line. + const char* line = readNonCommentLine(); + if(line[0] == '\0') break; + + // Interpret only certain known keywords from the .cell file: + + if(boost::algorithm::istarts_with(line, "%BLOCK LATTICE_CART")) { + line = readNonCommentLine(); + // Skip optional units. + if((line[0] < '0' || line[0] > '9') && line[0] != '.') + line = readNonCommentLine(); + // Parse cell vectors. + AffineTransformation cell = AffineTransformation::Identity(); + for(int i = 0; i < 3; i++) { + if(sscanf(line, FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING, + &cell(0,i), &cell(1,i), &cell(2,i)) != 3) + throw Exception(tr("Invalid simulation cell in CASTEP file at line %1").arg(stream.lineNumber())); + line = readNonCommentLine(); + } + simulationCell().setMatrix(cell); + } + else if(boost::algorithm::istarts_with(line, "%BLOCK LATTICE_ABC")) { + line = readNonCommentLine(); + // Skip optional units.. + if((line[0] < '0' || line[0] > '9') && line[0] != '.') + line = readNonCommentLine(); + // Parse cell side lengths and angles. + FloatType a,b,c,alpha,beta,gamma; + if(sscanf(line, FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING, &a, &b, &c) != 3) + throw Exception(tr("Invalid simulation cell in CASTEP file at line %1").arg(stream.lineNumber())); + line = readNonCommentLine(); + if(sscanf(line, FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING, &alpha, &beta, &gamma) != 3) + throw Exception(tr("Invalid simulation cell in CASTEP file at line %1").arg(stream.lineNumber())); + line = readNonCommentLine(); + AffineTransformation cell = AffineTransformation::Identity(); + if(alpha == 90 && beta == 90 && gamma == 90) { + cell(0,0) = a; + cell(1,1) = b; + cell(2,2) = c; + } + else if(alpha == 90 && beta == 90) { + gamma *= FLOATTYPE_PI / 180; + cell(0,0) = a; + cell(0,1) = b * cos(gamma); + cell(1,1) = b * sin(gamma); + cell(2,2) = c; + } + else { + alpha *= FLOATTYPE_PI / 180; + beta *= FLOATTYPE_PI / 180; + gamma *= FLOATTYPE_PI / 180; + FloatType v = a*b*c*sqrt(1.0 - cos(alpha)*cos(alpha) - cos(beta)*cos(beta) - cos(gamma)*cos(gamma) + 2.0 * cos(alpha) * cos(beta) * cos(gamma)); + cell(0,0) = a; + cell(0,1) = b * cos(gamma); + cell(1,1) = b * sin(gamma); + cell(0,2) = c * cos(beta); + cell(1,2) = c * (cos(alpha) - cos(beta)*cos(gamma)) / sin(gamma); + cell(2,2) = v / (a*b*sin(gamma)); + } + simulationCell().setMatrix(cell); + } + else if((boost::algorithm::istarts_with(line, "%BLOCK POSITIONS_FRAC") && !boost::algorithm::istarts_with(line, "%BLOCK POSITIONS_FRAC_")) + || (boost::algorithm::istarts_with(line, "%BLOCK POSITIONS_ABS") && !boost::algorithm::istarts_with(line, "%BLOCK POSITIONS_ABS_"))) { + bool fractionalCoords = boost::algorithm::istarts_with(line, "%BLOCK POSITIONS_FRAC"); + line = readNonCommentLine(); + std::vector coords; + std::vector types; + std::unique_ptr typeList(new ParticleFrameLoader::ParticleTypeList()); + while(!boost::algorithm::istarts_with(line, "%ENDBLOCK") && !isCanceled() && !stream.eof()) { + Point3 pos; + int atomicNumber; + if(sscanf(line, "%u " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING, &atomicNumber, &pos.x(), &pos.y(), &pos.z()) == 4) { + coords.push_back(pos); + if(atomicNumber < 0 || atomicNumber >= sizeof(chemical_symbols)/sizeof(chemical_symbols[0])) + atomicNumber = 0; + types.push_back(typeList->addParticleTypeName(chemical_symbols[atomicNumber])); + } + else if(sscanf(line, "%*s " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING, &pos.x(), &pos.y(), &pos.z()) == 3) { + coords.push_back(pos); + const char* typeNameEnd = line; + while(*typeNameEnd > ' ') typeNameEnd++; + types.push_back(typeList->addParticleTypeName(line, typeNameEnd)); + } + else { + // Ignore parsing error, skip optional units. + } + line = readNonCommentLine(); + } + + // Convert from fractional to cartesian coordinates. + if(fractionalCoords) { + const AffineTransformation& cell = simulationCell().matrix(); + for(Point3& p : coords) + p = cell * p; + } + + ParticleProperty* posProperty = new ParticleProperty(coords.size(), ParticleProperty::PositionProperty, 0, false); + addParticleProperty(posProperty); + std::copy(coords.begin(), coords.end(), posProperty->dataPoint3()); + + ParticleProperty* typeProperty = new ParticleProperty(types.size(), ParticleProperty::ParticleTypeProperty, 0, false); + addParticleProperty(typeProperty, typeList.release()); + std::copy(types.begin(), types.end(), typeProperty->dataInt()); + getTypeListOfParticleProperty(typeProperty)->sortParticleTypesByName(typeProperty); + + setStatus(tr("%1 atoms").arg(coords.size())); + } + else if(boost::algorithm::istarts_with(line, "%BLOCK IONIC_VELOCITIES")) { + line = readNonCommentLine(); + std::vector velocities; + while(!boost::algorithm::istarts_with(line, "%ENDBLOCK") && !isCanceled() && !stream.eof()) { + Vector3 v; + if(sscanf(line, FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING, &v.x(), &v.y(), &v.z()) == 3) + velocities.push_back(v); + // Ignore parsing error, skip optional units. + line = readNonCommentLine(); + } + + ParticleProperty* velocityProperty = new ParticleProperty(velocities.size(), ParticleProperty::VelocityProperty, 0, false); + addParticleProperty(velocityProperty); + std::copy(velocities.begin(), velocities.end(), velocityProperty->dataVector3()); + } + } +} + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/castep/CastepCellImporter.h ovito-2.9.0+dfsg1/src/plugins/particles/import/castep/CastepCellImporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/castep/CastepCellImporter.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/castep/CastepCellImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,85 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) + +/** + * \brief File parser for CASTEP .cell files. + */ +class OVITO_PARTICLES_EXPORT CastepCellImporter : public ParticleImporter +{ +public: + + /// \brief Constructs a new instance of this class. + Q_INVOKABLE CastepCellImporter(DataSet* dataset) : ParticleImporter(dataset) {} + + /// \brief Returns the file filter that specifies the files that can be imported by this service. + /// \return A wild-card pattern that specifies the file types that can be handled by this import class. + virtual QString fileFilter() override { return QStringLiteral("*.cell"); } + + /// \brief Returns the filter description that is displayed in the drop-down box of the file dialog. + /// \return A string that describes the file format. + virtual QString fileFilterDescription() override { return tr("CASTEP Cell Files"); } + + /// \brief Checks if the given file has format that can be read by this importer. + virtual bool checkFileFormat(QFileDevice& input, const QUrl& sourceLocation) override; + + /// Returns the title of this object. + virtual QString objectTitle() override { return tr("CASTEP"); } + + /// Creates an asynchronous loader object that loads the data for the given frame from the external file. + virtual std::shared_ptr createFrameLoader(const Frame& frame, bool isNewlySelectedFile) override { + return std::make_shared(dataset()->container(), frame, isNewlySelectedFile); + } + +private: + + /// The format-specific task object that is responsible for reading an input file in the background. + class ImportTask : public ParticleFrameLoader + { + public: + + /// Normal constructor. + ImportTask(DataSetContainer* container, const FileSourceImporter::Frame& frame, bool isNewFile) + : ParticleFrameLoader(container, frame, isNewFile) {} + + protected: + + /// Parses the given input file and stores the data in this container object. + virtual void parseFile(CompressedTextReader& stream) override; + }; + + Q_OBJECT + OVITO_OBJECT +}; + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/castep/CastepMDImporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/castep/CastepMDImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/castep/CastepMDImporter.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/castep/CastepMDImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,189 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include "CastepMDImporter.h" + +#include + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CastepMDImporter, ParticleImporter); + +/****************************************************************************** +* Checks if the given file has format that can be read by this importer. +******************************************************************************/ +bool CastepMDImporter::checkFileFormat(QFileDevice& input, const QUrl& sourceLocation) +{ + // Open input file. + CompressedTextReader stream(input, sourceLocation.path()); + + // Look for string 'BEGIN header' to occur on first line. + if(!boost::algorithm::istarts_with(stream.readLineTrimLeft(32), "BEGIN header")) + return false; + + // Look for string 'END header' to occur within the first 50 lines of the file. + for(int i = 0; i < 50 && !stream.eof(); i++) { + if(boost::algorithm::istarts_with(stream.readLineTrimLeft(1024), "END header")) + return true; + } + + return false; +} + +/****************************************************************************** +* Scans the given input file to find all contained simulation frames. +******************************************************************************/ +void CastepMDImporter::scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) +{ + promise.setProgressText(tr("Scanning CASTEP file %1").arg(stream.filename())); + promise.setProgressMaximum(stream.underlyingSize() / 1000); + + // Look for string 'BEGIN header' to occur on first line. + if(!boost::algorithm::istarts_with(stream.readLineTrimLeft(32), "BEGIN header")) + throw Exception(tr("Invalid CASTEP md/geom file header")); + + // Fast forward to line 'END header'. + for(;;) { + if(promise.isCanceled()) + return; + if(stream.eof()) + throw Exception(tr("Invalid CASTEP md/geom file. Unexpected end of file.")); + if(boost::algorithm::istarts_with(stream.readLineTrimLeft(), "END header")) + break; + promise.setProgressValueIntermittent(stream.underlyingByteOffset() / 1000); + } + + QFileInfo fileInfo(stream.device().fileName()); + QString filename = fileInfo.fileName(); + QDateTime lastModified = fileInfo.lastModified(); + int frameNumber = 0; + + while(!stream.eof()) { + auto byteOffset = stream.byteOffset(); + const char* line = stream.readLineTrimLeft(); + if(boost::algorithm::icontains(line, "<-- h")) { + Frame frame; + frame.sourceFile = sourceUrl; + frame.byteOffset = byteOffset; + frame.lineNumber = stream.lineNumber(); + frame.lastModificationTime = lastModified; + frame.label = QString("%1 (Frame %2)").arg(filename).arg(frameNumber++); + frames.push_back(frame); + // Skip the two other lines of the cell matrix + stream.readLine(); + stream.readLine(); + } + + promise.setProgressValueIntermittent(stream.underlyingByteOffset() / 1000); + if(promise.isCanceled()) + return; + } +} + +/****************************************************************************** +* Parses the given input file and stores the data in the given container object. +******************************************************************************/ +void CastepMDImporter::ImportTask::parseFile(CompressedTextReader& stream) +{ + setProgressText(tr("Reading CASTEP file %1").arg(frame().sourceFile.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded))); + + std::vector coords; + std::vector types; + std::vector velocities; + std::vector forces; + std::unique_ptr typeList(new ParticleFrameLoader::ParticleTypeList()); + + AffineTransformation cell = AffineTransformation::Identity(); + int numCellVectors = 0; + + while(!stream.eof()) { + const char* line = stream.readLineTrimLeft(); + + if(boost::algorithm::icontains(line, "<-- h")) { + if(numCellVectors == 3) break; + if(sscanf(line, FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING, + &cell(0,numCellVectors), &cell(1,numCellVectors), &cell(2,numCellVectors)) != 3) + throw Exception(tr("Invalid simulation cell in CASTEP file at line %1").arg(stream.lineNumber())); + numCellVectors++; + } + else if(boost::algorithm::icontains(line, "<-- r")) { + Point3 pos; + if(sscanf(line, "%*s %*u " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING, + &pos.x(), &pos.y(), &pos.z()) != 3) + throw Exception(tr("Invalid coordinates in CASTEP file at line %1").arg(stream.lineNumber())); + coords.push_back(pos); + const char* typeNameEnd = line; + while(*typeNameEnd > ' ') typeNameEnd++; + types.push_back(typeList->addParticleTypeName(line, typeNameEnd)); + } + else if(boost::algorithm::icontains(line, "<-- v")) { + Vector3 v; + if(sscanf(line, "%*s %*u " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING, + &v.x(), &v.y(), &v.z()) != 3) + throw Exception(tr("Invalid velocity in CASTEP file at line %1").arg(stream.lineNumber())); + velocities.push_back(v); + } + else if(boost::algorithm::icontains(line, "<-- f")) { + Vector3 f; + if(sscanf(line, "%*s %*u " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING " " FLOATTYPE_SCANF_STRING, + &f.x(), &f.y(), &f.z()) != 3) + throw Exception(tr("Invalid force in CASTEP file at line %1").arg(stream.lineNumber())); + forces.push_back(f); + } + + if(isCanceled()) + return; + } + simulationCell().setMatrix(cell); + + // Create the particle properties. + ParticleProperty* posProperty = new ParticleProperty(coords.size(), ParticleProperty::PositionProperty, 0, false); + addParticleProperty(posProperty); + std::copy(coords.begin(), coords.end(), posProperty->dataPoint3()); + + ParticleProperty* typeProperty = new ParticleProperty(types.size(), ParticleProperty::ParticleTypeProperty, 0, false); + addParticleProperty(typeProperty, typeList.release()); + std::copy(types.begin(), types.end(), typeProperty->dataInt()); + + // Since we created particle types on the go while reading the particles, the assigned particle type IDs + // depend on the storage order of particles in the file. We rather want a well-defined particle type ordering, that's + // why we sort them now. + getTypeListOfParticleProperty(typeProperty)->sortParticleTypesByName(typeProperty); + + if(velocities.size() == coords.size()) { + ParticleProperty* velocityProperty = new ParticleProperty(velocities.size(), ParticleProperty::VelocityProperty, 0, false); + addParticleProperty(velocityProperty); + std::copy(velocities.begin(), velocities.end(), velocityProperty->dataVector3()); + } + if(forces.size() == coords.size()) { + ParticleProperty* forceProperty = new ParticleProperty(forces.size(), ParticleProperty::ForceProperty, 0, false); + addParticleProperty(forceProperty); + std::copy(forces.begin(), forces.end(), forceProperty->dataVector3()); + } + + setStatus(tr("%1 atoms").arg(coords.size())); +} + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/castep/CastepMDImporter.h ovito-2.9.0+dfsg1/src/plugins/particles/import/castep/CastepMDImporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/castep/CastepMDImporter.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/castep/CastepMDImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,92 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) + +/** + * \brief File parser for CASTEP .md and .geom files. + */ +class OVITO_PARTICLES_EXPORT CastepMDImporter : public ParticleImporter +{ +public: + + /// \brief Constructs a new instance of this class. + Q_INVOKABLE CastepMDImporter(DataSet* dataset) : ParticleImporter(dataset) { + setMultiTimestepFile(true); + } + + /// \brief Returns the file filter that specifies the files that can be imported by this service. + /// \return A wild-card pattern that specifies the file types that can be handled by this import class. + virtual QString fileFilter() override { return QStringLiteral("*.md *.geom"); } + + /// \brief Returns the filter description that is displayed in the drop-down box of the file dialog. + /// \return A string that describes the file format. + virtual QString fileFilterDescription() override { return tr("CASTEP MD/GEOM Files"); } + + /// \brief Checks if the given file has format that can be read by this importer. + virtual bool checkFileFormat(QFileDevice& input, const QUrl& sourceLocation) override; + + /// Returns the title of this object. + virtual QString objectTitle() override { return tr("CASTEP"); } + + /// Creates an asynchronous loader object that loads the data for the given frame from the external file. + virtual std::shared_ptr createFrameLoader(const Frame& frame, bool isNewlySelectedFile) override { + return std::make_shared(dataset()->container(), frame, isNewlySelectedFile); + } + +protected: + + /// \brief Scans the given input file to find all contained simulation frames. + virtual void scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; + +private: + + /// The format-specific task object that is responsible for reading an input file in the background. + class ImportTask : public ParticleFrameLoader + { + public: + + /// Normal constructor. + ImportTask(DataSetContainer* container, const FileSourceImporter::Frame& frame, bool isNewFile) + : ParticleFrameLoader(container, frame, isNewFile) {} + + protected: + + /// Parses the given input file and stores the data in this container object. + virtual void parseFile(CompressedTextReader& stream) override; + }; + + Q_OBJECT + OVITO_OBJECT +}; + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/cfg/CFGImporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/cfg/CFGImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/cfg/CFGImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/cfg/CFGImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,7 +26,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, CFGImporter, ParticleImporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CFGImporter, ParticleImporter); struct CFGHeader { @@ -193,7 +193,7 @@ generateAutomaticColumnMapping(cfgMapping, header.auxiliaryFields); } - setProgressRange(header.numParticles); + setProgressMaximum(header.numParticles); // Prepare the mapping between input file columns and particle properties. InputColumnReader columnParser(cfgMapping, *this, header.numParticles); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/cfg/CFGImporter.h ovito-2.9.0+dfsg1/src/plugins/particles/import/cfg/CFGImporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/cfg/CFGImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/cfg/CFGImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CFG_FILE_IMPORTER_H -#define __OVITO_CFG_FILE_IMPORTER_H +#pragma once + #include #include @@ -88,4 +88,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CFG_FILE_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/fhi_aims/FHIAimsImporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/fhi_aims/FHIAimsImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/fhi_aims/FHIAimsImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/fhi_aims/FHIAimsImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, FHIAimsImporter, ParticleImporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(FHIAimsImporter, ParticleImporter); /****************************************************************************** * Checks if the given file has format that can be read by this importer. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/fhi_aims/FHIAimsImporter.h ovito-2.9.0+dfsg1/src/plugins/particles/import/fhi_aims/FHIAimsImporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/fhi_aims/FHIAimsImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/fhi_aims/FHIAimsImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FHI_AIMS_IMPORTER_H -#define __OVITO_FHI_AIMS_IMPORTER_H +#pragma once + #include #include "../ParticleImporter.h" @@ -83,4 +83,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_FHI_AIMS_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/fhi_aims/FHIAimsLogFileImporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/fhi_aims/FHIAimsLogFileImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/fhi_aims/FHIAimsLogFileImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/fhi_aims/FHIAimsLogFileImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,7 +30,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, FHIAimsLogFileImporter, ParticleImporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(FHIAimsLogFileImporter, ParticleImporter); /****************************************************************************** * Checks if the given file has format that can be read by this importer. @@ -54,10 +54,10 @@ /****************************************************************************** * Scans the given input file to find all contained simulation frames. ******************************************************************************/ -void FHIAimsLogFileImporter::scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) +void FHIAimsLogFileImporter::scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) { - futureInterface.setProgressText(tr("Scanning FHI-aims log file %1").arg(stream.filename())); - futureInterface.setProgressRange(stream.underlyingSize() / 1000); + promise.setProgressText(tr("Scanning FHI-aims log file %1").arg(stream.filename())); + promise.setProgressMaximum(stream.underlyingSize() / 1000); // Regular expression for whitespace characters. QRegularExpression ws_re(QStringLiteral("\\s+")); @@ -67,7 +67,7 @@ QDateTime lastModified = fileInfo.lastModified(); int frameNumber = 0; - while(!stream.eof()) { + while(!stream.eof() && !promise.isCanceled()) { const char* line = stream.readLineTrimLeft(); if(boost::algorithm::starts_with(line, "Updated atomic structure:")) { stream.readLine(); @@ -80,8 +80,8 @@ frames.push_back(frame); } - futureInterface.setProgressValueIntermittent(stream.underlyingByteOffset() / 1000); - if(futureInterface.isCanceled()) + promise.setProgressValueIntermittent(stream.underlyingByteOffset() / 1000); + if(promise.isCanceled()) return; } } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/fhi_aims/FHIAimsLogFileImporter.h ovito-2.9.0+dfsg1/src/plugins/particles/import/fhi_aims/FHIAimsLogFileImporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/fhi_aims/FHIAimsLogFileImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/fhi_aims/FHIAimsLogFileImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FHI_AIMS_LOG_FILE_IMPORTER_H -#define __OVITO_FHI_AIMS_LOG_FILE_IMPORTER_H +#pragma once + #include #include "../ParticleImporter.h" @@ -61,7 +61,7 @@ protected: /// \brief Scans the given input file to find all contained simulation frames. - virtual void scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; + virtual void scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; private: @@ -90,4 +90,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_FHI_AIMS_LOG_FILE_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/gsd/gsd.c ovito-2.9.0+dfsg1/src/plugins/particles/import/gsd/gsd.c --- ovito-2.8.1+dfsg2/src/plugins/particles/import/gsd/gsd.c 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/gsd/gsd.c 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Regents of the University of Michigan +// Copyright (c) 2016-2017 The Regents of the University of Michigan // This file is part of the General Simulation Data (GSD) project, released under the BSD 2-Clause License. #ifdef _WIN32 @@ -19,6 +19,7 @@ #include #include #include +#include #include "gsd.h" @@ -97,9 +98,7 @@ // in append mode, we don't have the whole index stored in memory. Instead, we need to copy it in chunks // from the file's old position to the new position const size_t buf_size = 1024*16; - char *buf = malloc(buf_size); - if (buf == NULL) - return -1; + char buf[1024*16]; int64_t new_index_location = lseek(handle->fd, 0, SEEK_END); int64_t old_index_location = handle->header.index_location; @@ -136,8 +135,6 @@ total_bytes_written += bytes_written; } - free(buf); - // update to the new index location in the header handle->header.index_location = new_index_location; handle->file_size = handle->header.index_location + total_bytes_written; @@ -271,7 +268,12 @@ lseek(handle->fd, 0, SEEK_SET); size_t bytes_read = read(handle->fd, &handle->header, sizeof(struct gsd_header)); if (bytes_read != sizeof(struct gsd_header)) - return -1; + { + if (errno != 0) + return -1; + else + return -2; + } // validate the header if (handle->header.magic != 0x65DF65DF65DF65DF) diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/gsd/GSDFile.h ovito-2.9.0+dfsg1/src/plugins/particles/import/gsd/GSDFile.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/gsd/GSDFile.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/gsd/GSDFile.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_GSD_FILE_H -#define __OVITO_GSD_FILE_H +#pragma once + #include #include "GSDImporter.h" @@ -78,13 +78,17 @@ /// Returns whether a chunk with the given name exists. bool hasChunk(const char* chunkName, uint64_t frame) { - return ::gsd_find_chunk(&_handle, frame, chunkName) != nullptr; + if(::gsd_find_chunk(&_handle, frame, chunkName) != nullptr) return true; + if(frame != 0 && ::gsd_find_chunk(&_handle, 0, chunkName) != nullptr) return true; + return false; } /// Reads a single unsigned 64-bit integer from the GSD file, or returns a default value if the chunk is not present in the file. template T readOptionalScalar(const char* chunkName, uint64_t frame, T defaultValue) { - if(auto chunk = ::gsd_find_chunk(&_handle, frame, chunkName)) { + auto chunk = ::gsd_find_chunk(&_handle, frame, chunkName); + if(!chunk && frame != 0) chunk = ::gsd_find_chunk(&_handle, 0, chunkName); + if(chunk) { if(chunk->N != 1 || chunk->M != 1) throw Exception(GSDImporter::tr("GSD file I/O error: Chunk '%1' does not contain a scalar value.").arg(chunkName)); if(chunk->type != gsdDataType()) @@ -104,7 +108,9 @@ /// Reads an one-dimensional array from the GSD file if the data chunk is present. template void readOptional1DArray(const char* chunkName, uint64_t frame, std::array& a) { - if(auto chunk = ::gsd_find_chunk(&_handle, frame, chunkName)) { + auto chunk = ::gsd_find_chunk(&_handle, frame, chunkName); + if(!chunk && frame != 0) chunk = ::gsd_find_chunk(&_handle, 0, chunkName); + if(chunk) { if(chunk->N != a.size() || chunk->M != 1) throw Exception(GSDImporter::tr("GSD file I/O error: Chunk '%1' does not contain a 1-dimensional array of the expected size.").arg(chunkName)); if(chunk->type != gsdDataType()) @@ -123,7 +129,9 @@ /// Reads an array of strings from the GSD file. QStringList readStringTable(const char* chunkName, uint64_t frame) { QStringList result; - if(auto chunk = ::gsd_find_chunk(&_handle, frame, chunkName)) { + auto chunk = ::gsd_find_chunk(&_handle, frame, chunkName); + if(!chunk && frame != 0) chunk = ::gsd_find_chunk(&_handle, 0, chunkName); + if(chunk) { if(chunk->type != GSD_TYPE_INT8 && chunk->type != GSD_TYPE_UINT8) throw Exception(GSDImporter::tr("GSD file I/O error: Data type of chunk '%1' is not GSD_TYPE_UINT8 but %2.").arg(chunkName).arg(chunk->type)); std::vector buffer(chunk->N * chunk->M); @@ -146,8 +154,9 @@ template void readFloatArray(const char* chunkName, uint64_t frame, T* buffer, size_t numElements, size_t componentCount = 1) { auto chunk = ::gsd_find_chunk(&_handle, frame, chunkName); + if(!chunk && frame != 0) chunk = ::gsd_find_chunk(&_handle, 0, chunkName); if(!chunk) - throw Exception(GSDImporter::tr("GSD file I/O error: Chunk '%1' does not exist at frame %2.").arg(chunkName).arg(frame)); + throw Exception(GSDImporter::tr("GSD file I/O error: Chunk '%1' does not exist at frame %2 (or the initial frame).").arg(chunkName).arg(frame)); if(chunk->type != GSD_TYPE_FLOAT) throw Exception(GSDImporter::tr("GSD file I/O error: Data type of chunk '%1' is not GSD_TYPE_FLOAT but %2.").arg(chunkName).arg(chunk->type)); if(chunk->N != numElements) @@ -175,8 +184,9 @@ void readIntArray(const char* chunkName, uint64_t frame, int* buffer, size_t numElements, size_t intsPerElement = 1) { auto chunk = ::gsd_find_chunk(&_handle, frame, chunkName); + if(!chunk && frame != 0) chunk = ::gsd_find_chunk(&_handle, 0, chunkName); if(!chunk) - throw Exception(GSDImporter::tr("GSD file I/O error: Chunk '%1' does not exist at frame %2.").arg(chunkName).arg(frame)); + throw Exception(GSDImporter::tr("GSD file I/O error: Chunk '%1' does not exist at frame %2 (or the initial frame).").arg(chunkName).arg(frame)); if(chunk->type != GSD_TYPE_INT32 && chunk->type != GSD_TYPE_UINT32) throw Exception(GSDImporter::tr("GSD file I/O error: Data type of chunk '%1' is not GSD_TYPE_INT32 but %2.").arg(chunkName).arg(chunk->type)); if(chunk->N != numElements) @@ -202,4 +212,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_GSD_FILE_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/gsd/gsd.h ovito-2.9.0+dfsg1/src/plugins/particles/import/gsd/gsd.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/gsd/gsd.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/gsd/gsd.h 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright (c) 2016 The Regents of the University of Michigan +// Copyright (c) 2016-2017 The Regents of the University of Michigan // This file is part of the General Simulation Data (GSD) project, released under the BSD 2-Clause License. #ifndef __GSD_H__ diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/gsd/GSDImporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/gsd/GSDImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/gsd/GSDImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/gsd/GSDImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,7 +25,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, GSDImporter, ParticleImporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(GSDImporter, ParticleImporter); /****************************************************************************** * Checks if the given file has format that can be read by this importer. @@ -46,7 +46,7 @@ /****************************************************************************** * Scans the input file for simulation timesteps. ******************************************************************************/ -void GSDImporter::scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) +void GSDImporter::scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) { // First close text stream, we don't need it here. QFileDevice& file = stream.device(); @@ -146,10 +146,6 @@ ParticleProperty* massProperty = readOptionalParticleProperty(gsd, "particles/mass", frameNumber, numParticles, ParticleProperty::MassProperty); readOptionalParticleProperty(gsd, "particles/charge", frameNumber, numParticles, ParticleProperty::ChargeProperty); ParticleProperty* velocityProperty = readOptionalParticleProperty(gsd, "particles/velocity", frameNumber, numParticles, ParticleProperty::VelocityProperty); - if(!velocityProperty && nFrames > 1 && gsd.hasChunk("particles/velocity", 1)) { - velocityProperty = new ParticleProperty(numParticles, ParticleProperty::VelocityProperty, 0, true); - addParticleProperty(velocityProperty); - } ParticleProperty* radiusProperty = readOptionalParticleProperty(gsd, "particles/diameter", frameNumber, numParticles, ParticleProperty::RadiusProperty); if(radiusProperty) { // Convert particle diameter to radius by dividing by 2. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/gsd/GSDImporter.h ovito-2.9.0+dfsg1/src/plugins/particles/import/gsd/GSDImporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/gsd/GSDImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/gsd/GSDImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_GSD_FILE_IMPORTER_H -#define __OVITO_GSD_FILE_IMPORTER_H +#pragma once + #include #include @@ -63,7 +63,7 @@ protected: /// \brief Scans the given input file to find all contained simulation frames. - virtual void scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; + virtual void scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; private: @@ -94,4 +94,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_GSD_FILE_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/imd/IMDImporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/imd/IMDImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/imd/IMDImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/imd/IMDImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, IMDImporter, ParticleImporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(IMDImporter, ParticleImporter); /****************************************************************************** * Checks if the given file has format that can be read by this importer. @@ -147,7 +147,7 @@ return; } - setProgressRange(numAtoms); + setProgressMaximum(numAtoms); // Jump back to beginning of atom list. stream.seek(headerOffset); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/imd/IMDImporter.h ovito-2.9.0+dfsg1/src/plugins/particles/import/imd/IMDImporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/imd/IMDImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/imd/IMDImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_IMD_FILE_IMPORTER_H -#define __OVITO_IMD_FILE_IMPORTER_H +#pragma once + #include #include @@ -82,4 +82,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_IMD_FILE_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/InputColumnMapping.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/InputColumnMapping.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/InputColumnMapping.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/InputColumnMapping.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -20,12 +20,9 @@ /////////////////////////////////////////////////////////////////////////////// #include +#include #include "InputColumnMapping.h" -#include -#include -#include - namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) /****************************************************************************** @@ -213,47 +210,6 @@ } /****************************************************************************** - * Helper function that converts a string to a floating-point number. - *****************************************************************************/ -inline bool parseFloatType(const char* s, const char* s_end, float& f) -{ - return boost::spirit::qi::parse(s, s_end, boost::spirit::qi::float_, f); -} - -/****************************************************************************** - * Helper function that converts a string to a floating-point number. - *****************************************************************************/ -inline bool parseFloatType(const char* s, const char* s_end, double& f) -{ - return boost::spirit::qi::parse(s, s_end, boost::spirit::qi::double_, f); -} - -/****************************************************************************** - * Helper function that converts a string to an integer number. - *****************************************************************************/ -inline bool parseInt(const char* s, const char* s_end, int& i) -{ - return boost::spirit::qi::parse(s, s_end, boost::spirit::qi::int_, i); -} - -/****************************************************************************** - * Helper function that converts a string repr. of a bool ('T' or 'F') to an int - *****************************************************************************/ -inline bool parseBool(const char* s, const char* s_end, int& d) -{ - if(s_end != s + 1) return false; - if(s[0] == 'T') { - d = 1; - return true; - } - else if(s[0] == 'F') { - d = 0; - return true; - } - return false; -} - -/****************************************************************************** * Parses the string tokens from one line of the input file and stores the values * in the data channels of the destination AtomsObject. *****************************************************************************/ diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/InputColumnMapping.h ovito-2.9.0+dfsg1/src/plugins/particles/import/InputColumnMapping.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/InputColumnMapping.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/InputColumnMapping.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_INPUT_COLUMN_MAPPING_H -#define __OVITO_INPUT_COLUMN_MAPPING_H +#pragma once + #include #include @@ -212,4 +212,4 @@ Q_DECLARE_METATYPE(Ovito::Particles::InputColumnInfo); Q_DECLARE_METATYPE(Ovito::Particles::InputColumnMapping); -#endif // __OVITO_INPUT_COLUMN_MAPPING_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/lammps/LAMMPSBinaryDumpImporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/lammps/LAMMPSBinaryDumpImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/lammps/LAMMPSBinaryDumpImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/lammps/LAMMPSBinaryDumpImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, LAMMPSBinaryDumpImporter, ParticleImporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(LAMMPSBinaryDumpImporter, ParticleImporter); struct LAMMPSBinaryDumpHeader { @@ -80,7 +80,7 @@ { _columnMapping = mapping; - if(Application::instance().guiMode()) { + if(Application::instance()->guiMode()) { // Remember the mapping for the next time. QSettings settings; settings.beginGroup("viz/importer/lammps_binary_dump/"); @@ -119,10 +119,10 @@ /****************************************************************************** * Scans the given input file to find all contained simulation frames. ******************************************************************************/ -void LAMMPSBinaryDumpImporter::scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) +void LAMMPSBinaryDumpImporter::scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) { - futureInterface.setProgressText(tr("Scanning binary LAMMPS dump file %1").arg(stream.filename())); - futureInterface.setProgressRange(stream.underlyingSize() / 1000); + promise.setProgressText(tr("Scanning binary LAMMPS dump file %1").arg(stream.filename())); + promise.setProgressMaximum(stream.underlyingSize() / 1000); // First close text stream so we can re-open it in binary mode. QIODevice& file = stream.device(); @@ -136,7 +136,7 @@ QString filename = fileInfo.fileName(); QDateTime lastModified = fileInfo.lastModified(); - while(!file.atEnd()) { + while(!file.atEnd() && !promise.isCanceled()) { qint64 byteOffset = file.pos(); // Parse file header. @@ -158,8 +158,8 @@ if(!file.seek(filePos)) throw Exception(tr("Unexpected end of file.")); - futureInterface.setProgressValue(filePos / 1000); - if(futureInterface.isCanceled()) + promise.setProgressValue(filePos / 1000); + if(promise.isCanceled()) return; } @@ -284,7 +284,7 @@ return; } - setProgressRange(header.natoms); + setProgressMaximum(header.natoms); // LAMMPS only stores the outer bounding box of the simulation cell in the dump file. // We have to determine the size of the actual triclinic cell. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/lammps/LAMMPSBinaryDumpImporter.h ovito-2.9.0+dfsg1/src/plugins/particles/import/lammps/LAMMPSBinaryDumpImporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/lammps/LAMMPSBinaryDumpImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/lammps/LAMMPSBinaryDumpImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_LAMMPS_BINARY_DUMP_IMPORTER_H -#define __OVITO_LAMMPS_BINARY_DUMP_IMPORTER_H +#pragma once + #include #include @@ -113,7 +113,7 @@ virtual OORef clone(bool deepCopy, CloneHelper& cloneHelper) override; /// \brief Scans the given input file to find all contained simulation frames. - virtual void scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; + virtual void scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; private: @@ -130,4 +130,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_LAMMPS_BINARY_DUMP_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/lammps/LAMMPSDataImporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/lammps/LAMMPSDataImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/lammps/LAMMPSDataImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/lammps/LAMMPSDataImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -31,9 +31,9 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, LAMMPSDataImporter, ParticleImporter); -DEFINE_PROPERTY_FIELD(LAMMPSDataImporter, _atomStyle, "AtomStyle"); -SET_PROPERTY_FIELD_LABEL(LAMMPSDataImporter, _atomStyle, "Atom style"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(LAMMPSDataImporter, ParticleImporter); +DEFINE_PROPERTY_FIELD(LAMMPSDataImporter, atomStyle, "AtomStyle"); +SET_PROPERTY_FIELD_LABEL(LAMMPSDataImporter, atomStyle, "Atom style"); /****************************************************************************** * Checks if the given file has format that can be read by this importer. @@ -123,7 +123,7 @@ if(sscanf(line.c_str(), "%u", &natoms) != 1) throw Exception(tr("Invalid number of atoms (line %1): %2").arg(stream.lineNumber()).arg(line.c_str())); - setProgressRange(natoms); + setProgressMaximum(natoms); } else if(line.find("atom types") != string::npos) { if(sscanf(line.c_str(), "%u", &natomtypes) != 1) @@ -235,7 +235,6 @@ // Skip blank line after keyword. if(stream.eof()) break; stream.readLine(); - if(stream.eof()) break; if(keyword.startsWith("Atoms")) { if(natoms != 0) { @@ -464,7 +463,7 @@ for(int i = 1; i <= nbondtypes; i++) bondTypeList->addBondTypeId(i); - setProgressRange(nbonds); + setProgressMaximum(nbonds); for(int i = 0; i < nbonds; i++) { if(!setProgressValueIntermittent(i)) return; stream.readLine(); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/lammps/LAMMPSDataImporter.h ovito-2.9.0+dfsg1/src/plugins/particles/import/lammps/LAMMPSDataImporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/lammps/LAMMPSDataImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/lammps/LAMMPSDataImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_LAMMPS_DATA_IMPORTER_H -#define __OVITO_LAMMPS_DATA_IMPORTER_H +#pragma once + #include #include @@ -62,7 +62,7 @@ /// \brief Constructs a new instance of this class. Q_INVOKABLE LAMMPSDataImporter(DataSet* dataset) : ParticleImporter(dataset), _atomStyle(AtomStyle_Unknown) { - INIT_PROPERTY_FIELD(LAMMPSDataImporter::_atomStyle); + INIT_PROPERTY_FIELD(atomStyle); } /// \brief Returns the file filter that specifies the files that can be imported by this service. @@ -79,12 +79,6 @@ /// Returns the title of this object. virtual QString objectTitle() override { return tr("LAMMPS Data"); } - /// Returns the LAMMPS atom style used in the data file. - LAMMPSAtomStyle atomStyle() const { return _atomStyle; } - - /// Specifies the LAMMPS atom style used in the data file. - void setAtomStyle(LAMMPSAtomStyle atomStyle) { _atomStyle = atomStyle; } - /// Creates an asynchronous loader object that loads the data for the given frame from the external file. virtual std::shared_ptr createFrameLoader(const Frame& frame, bool isNewlySelectedFile) override { return std::make_shared(dataset()->container(), frame, isNewlySelectedFile, atomStyle()); @@ -123,12 +117,10 @@ }; /// The LAMMPS atom style used by the data format. - PropertyField _atomStyle; + DECLARE_MODIFIABLE_PROPERTY_FIELD(LAMMPSAtomStyle, atomStyle, setAtomStyle); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_atomStyle); }; OVITO_END_INLINE_NAMESPACE @@ -139,4 +131,4 @@ Q_DECLARE_METATYPE(Ovito::Particles::LAMMPSDataImporter::LAMMPSAtomStyle); Q_DECLARE_TYPEINFO(Ovito::Particles::LAMMPSDataImporter::LAMMPSAtomStyle, Q_PRIMITIVE_TYPE); -#endif // __OVITO_LAMMPS_DATA_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/lammps/LAMMPSTextDumpImporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/lammps/LAMMPSTextDumpImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/lammps/LAMMPSTextDumpImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/lammps/LAMMPSTextDumpImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -31,9 +31,9 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, LAMMPSTextDumpImporter, ParticleImporter); -DEFINE_PROPERTY_FIELD(LAMMPSTextDumpImporter, _useCustomColumnMapping, "UseCustomColumnMaspping"); -SET_PROPERTY_FIELD_LABEL(LAMMPSTextDumpImporter, _useCustomColumnMapping, "Custom file column mapping"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(LAMMPSTextDumpImporter, ParticleImporter); +DEFINE_PROPERTY_FIELD(LAMMPSTextDumpImporter, useCustomColumnMapping, "UseCustomColumnMaspping"); +SET_PROPERTY_FIELD_LABEL(LAMMPSTextDumpImporter, useCustomColumnMapping, "Custom file column mapping"); /****************************************************************************** * Sets the user-defined mapping between data columns in the input file and @@ -76,10 +76,10 @@ /****************************************************************************** * Scans the given input file to find all contained simulation frames. ******************************************************************************/ -void LAMMPSTextDumpImporter::scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) +void LAMMPSTextDumpImporter::scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) { - futureInterface.setProgressText(tr("Scanning LAMMPS dump file %1").arg(stream.filename())); - futureInterface.setProgressRange(stream.underlyingSize() / 1000); + promise.setProgressText(tr("Scanning LAMMPS dump file %1").arg(stream.filename())); + promise.setProgressMaximum(stream.underlyingSize() / 1000); // Regular expression for whitespace characters. QRegularExpression ws_re(QStringLiteral("\\s+")); @@ -90,7 +90,7 @@ QString filename = fileInfo.fileName(); QDateTime lastModified = fileInfo.lastModified(); - while(!stream.eof()) { + while(!stream.eof() && !promise.isCanceled()) { qint64 byteOffset = stream.byteOffset(); // Parse next line. @@ -122,8 +122,8 @@ for(size_t i = 0; i < numParticles; i++) { stream.readLine(); if((i % 4096) == 0) - futureInterface.setProgressValue(stream.underlyingByteOffset() / 1000); - if(futureInterface.isCanceled()) + promise.setProgressValue(stream.underlyingByteOffset() / 1000); + if(promise.isCanceled()) return; } break; @@ -175,7 +175,7 @@ throw Exception(tr("LAMMPS dump file parsing error. Invalid number of atoms in line %1:\n%2").arg(stream.lineNumber()).arg(stream.lineString())); numParticles = u; - setProgressRange(u); + setProgressMaximum(u); } else if(stream.lineStartsWith("ITEM: BOX BOUNDS xy xz yz")) { diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/lammps/LAMMPSTextDumpImporter.h ovito-2.9.0+dfsg1/src/plugins/particles/import/lammps/LAMMPSTextDumpImporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/lammps/LAMMPSTextDumpImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/lammps/LAMMPSTextDumpImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_LAMMPS_TEXT_DUMP_IMPORTER_H -#define __OVITO_LAMMPS_TEXT_DUMP_IMPORTER_H +#pragma once + #include #include @@ -37,7 +37,7 @@ /// \brief Constructs a new instance of this class. Q_INVOKABLE LAMMPSTextDumpImporter(DataSet* dataset) : ParticleImporter(dataset), _useCustomColumnMapping(false) { - INIT_PROPERTY_FIELD(LAMMPSTextDumpImporter::_useCustomColumnMapping); + INIT_PROPERTY_FIELD(useCustomColumnMapping); } /// \brief Returns the file filter that specifies the files that can be imported by this service. @@ -62,14 +62,6 @@ /// the internal particle properties. void setCustomColumnMapping(const InputColumnMapping& mapping); - /// Returns whether the mapping between input file columns and particle - /// properties is done automatically or by the user. - bool useCustomColumnMapping() const { return _useCustomColumnMapping; } - - /// Sets whether the mapping between input file columns and particle - /// properties is done automatically or by the user. - void setUseCustomColumnMapping(bool useCustomMapping) { _useCustomColumnMapping = useCustomMapping; } - /// Creates an asynchronous loader object that loads the data for the given frame from the external file. virtual std::shared_ptr createFrameLoader(const Frame& frame, bool isNewlySelectedFile) override { return std::make_shared(dataset()->container(), frame, isNewlySelectedFile, _useCustomColumnMapping, _customColumnMapping); @@ -131,7 +123,7 @@ virtual OORef clone(bool deepCopy, CloneHelper& cloneHelper) override; /// \brief Scans the given input file to find all contained simulation frames. - virtual void scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; + virtual void scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; /// \brief Guesses the mapping of input file columns to internal particle properties. static InputColumnMapping generateAutomaticColumnMapping(const QStringList& columnNames); @@ -140,7 +132,7 @@ /// Controls whether the mapping between input file columns and particle /// properties is done automatically or by the user. - PropertyField _useCustomColumnMapping; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, useCustomColumnMapping, setUseCustomColumnMapping); /// Stores the user-defined mapping between data columns in the input file and /// the internal particle properties. @@ -148,8 +140,6 @@ Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_useCustomColumnMapping); }; OVITO_END_INLINE_NAMESPACE @@ -157,4 +147,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_LAMMPS_TEXT_DUMP_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/parcas/ParcasFileImporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/parcas/ParcasFileImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/parcas/ParcasFileImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/parcas/ParcasFileImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ParcasFileImporter, ParticleImporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ParcasFileImporter, ParticleImporter); // Byte-swaps a 32 bit word. #define SWAP32(x) (((uint32_t)(x) >> 24) | \ @@ -259,7 +259,7 @@ if(!file.seek((qint64)atom_off)) throw Exception(tr("PARCAS file parsing error: Seek error: %1").arg(file.errorString())); - setProgressRange(numAtoms); + setProgressMaximum(numAtoms); // Parse atoms. for(int i = 0; i < numAtoms; i++) { diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/parcas/ParcasFileImporter.h ovito-2.9.0+dfsg1/src/plugins/particles/import/parcas/ParcasFileImporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/parcas/ParcasFileImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/parcas/ParcasFileImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARCAS_FILE_IMPORTER_H -#define __OVITO_PARCAS_FILE_IMPORTER_H +#pragma once + #include #include @@ -82,4 +82,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARCAS_FILE_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/ParticleFrameLoader.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/ParticleFrameLoader.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/ParticleFrameLoader.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/ParticleFrameLoader.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include #include "ParticleFrameLoader.h" #include "ParticleImporter.h" @@ -48,7 +50,7 @@ setProgressText(ParticleImporter::tr("Reading file %1").arg(frame().sourceFile.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded))); // Fetch file. - Future fetchFileFuture = FileManager::instance().fetchUrl(datasetContainer(), frame().sourceFile); + Future fetchFileFuture = Application::instance()->fileManager()->fetchUrl(datasetContainer(), frame().sourceFile); if(!waitForSubTask(fetchFileFuture)) return; OVITO_ASSERT(fetchFileFuture.isCanceled() == false); @@ -135,7 +137,7 @@ simulationCell().matrix().column(0) + simulationCell().matrix().column(1) + simulationCell().matrix().column(2)).length(); - cellDisplay->setSimulationCellLineWidth(cellDiameter * 1.4e-3f); + cellDisplay->setCellLineWidth(cellDiameter * FloatType(1.4e-3)); } } @@ -225,6 +227,28 @@ } } + // Transfer field quantities. + for(auto& fq : _fieldQuantities) { + OORef fqObj; + for(const auto& dataObj : container->dataObjects()) { + FieldQuantityObject* po = dynamic_object_cast(dataObj); + if(po != nullptr && po->name() == fq->name()) { + fqObj = po; + break; + } + } + + if(fqObj) { + fqObj->setStorage(QSharedDataPointer(fq.release())); + } + else { + fqObj = FieldQuantityObject::createFromStorage(container->dataset(), QSharedDataPointer(fq.release())); + container->addDataObject(fqObj); + } + + activeObjects.insert(fqObj); + } + // Pass timestep information and other metadata to modification pipeline. container->setAttributes(attributes()); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/ParticleFrameLoader.h ovito-2.9.0+dfsg1/src/plugins/particles/import/ParticleFrameLoader.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/ParticleFrameLoader.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/ParticleFrameLoader.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_FRAME_LOADER_H -#define __OVITO_PARTICLE_FRAME_LOADER_H +#pragma once + #include #include @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -235,6 +236,7 @@ /// Removes a particle property from the list. void removeParticleProperty(int index) { + OVITO_ASSERT(index >= 0 && index < _particleProperties.size()); _particleTypeLists.erase(_particleProperties[index].get()); _particleProperties.erase(_particleProperties.begin() + index); } @@ -265,6 +267,7 @@ /// Removes a bond property from the list. void removeBondProperty(int index) { + OVITO_ASSERT(index >= 0 && index < _bondProperties.size()); _bondTypeLists.erase(_bondProperties[index].get()); _bondProperties.erase(_bondProperties.begin() + index); } @@ -276,6 +279,20 @@ return nullptr; } + /// Returns the list of field quantities. + const std::vector>& fieldQuantities() const { return _fieldQuantities; } + + /// Adds a new field quantity. + void addFieldQuantity(FieldQuantity* quantity) { + _fieldQuantities.push_back(std::unique_ptr(quantity)); + } + + /// Removes a field quantity from the list. + void removeFieldQuantity(int index) { + OVITO_ASSERT(index >= 0 && index < _fieldQuantities.size()); + _fieldQuantities.erase(_fieldQuantities.begin() + index); + } + /// Returns the metadata read from the file header. QVariantMap& attributes() { return _attributes; } @@ -316,6 +333,9 @@ /// Stores the lists of bond types for type properties. std::map> _bondTypeLists; + /// Structured field quantities. + std::vector> _fieldQuantities; + /// The metadata read from the file header. QVariantMap _attributes; @@ -330,4 +350,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_FRAME_LOADER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/ParticleImporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/ParticleImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/ParticleImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/ParticleImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,15 +22,16 @@ #include #include #include +#include #include #include #include "ParticleImporter.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ParticleImporter, FileSourceImporter); -DEFINE_PROPERTY_FIELD(ParticleImporter, _isMultiTimestepFile, "IsMultiTimestepFile"); -SET_PROPERTY_FIELD_LABEL(ParticleImporter, _isMultiTimestepFile, "File contains time series"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ParticleImporter, FileSourceImporter); +DEFINE_PROPERTY_FIELD(ParticleImporter, isMultiTimestepFile, "IsMultiTimestepFile"); +SET_PROPERTY_FIELD_LABEL(ParticleImporter, isMultiTimestepFile, "File contains time series"); /****************************************************************************** * Scans the given external path (which may be a directory and a wild-card pattern, @@ -50,7 +51,7 @@ /****************************************************************************** * Scans the input file for simulation timesteps. ******************************************************************************/ -QVector ParticleImporter::discoverFramesInFile(const QUrl sourceUrl, FutureInterfaceBase& futureInterface) +QVector ParticleImporter::discoverFramesInFile(const QUrl sourceUrl, PromiseBase& promise) { QVector result; @@ -59,19 +60,19 @@ QFileInfo fileInfo(sourceUrl.path()); if(fileInfo.fileName().contains('*') || fileInfo.fileName().contains('?')) { auto findFilesFuture = FileSourceImporter::findWildcardMatches(sourceUrl, dataset()->container()); - if(!futureInterface.waitForSubTask(findFilesFuture)) + if(!promise.waitForSubTask(findFilesFuture)) return result; for(auto item : findFilesFuture.result()) { - result += discoverFramesInFile(item.sourceFile, futureInterface); + result += discoverFramesInFile(item.sourceFile, promise); } return result; } - futureInterface.setProgressText(tr("Scanning file %1").arg(sourceUrl.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded))); + promise.setProgressText(tr("Scanning file %1").arg(sourceUrl.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded))); // Fetch file. - Future fetchFileFuture = FileManager::instance().fetchUrl(*dataset()->container(), sourceUrl); - if(!futureInterface.waitForSubTask(fetchFileFuture)) + Future fetchFileFuture = Application::instance()->fileManager()->fetchUrl(*dataset()->container(), sourceUrl); + if(!promise.waitForSubTask(fetchFileFuture)) return result; // Open file. @@ -80,7 +81,7 @@ // Scan file. try { - scanFileForTimesteps(futureInterface, result, sourceUrl, stream); + scanFileForTimesteps(promise, result, sourceUrl, stream); } catch(const Exception&) { // Silently ignore parsing and I/O errors if at least two frames have been read. @@ -97,7 +98,7 @@ /****************************************************************************** * Scans the given input file to find all contained simulation frames. ******************************************************************************/ -void ParticleImporter::scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) +void ParticleImporter::scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) { // By default, register a single frame. QFileInfo fileInfo(stream.filename()); @@ -109,7 +110,7 @@ ******************************************************************************/ void ParticleImporter::propertyChanged(const PropertyFieldDescriptor& field) { - if(field == PROPERTY_FIELD(ParticleImporter::_isMultiTimestepFile)) { + if(field == PROPERTY_FIELD(isMultiTimestepFile)) { // Automatically rescan input file for animation frames when this option has been activated. requestFramesUpdate(); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/ParticleImporter.h ovito-2.9.0+dfsg1/src/plugins/particles/import/ParticleImporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/ParticleImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/ParticleImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_IMPORTER_H -#define __OVITO_PARTICLE_IMPORTER_H +#pragma once + #include #include @@ -39,15 +39,9 @@ /// \brief Constructs a new instance of this class. ParticleImporter(DataSet* dataset) : FileSourceImporter(dataset), _isMultiTimestepFile(false) { - INIT_PROPERTY_FIELD(ParticleImporter::_isMultiTimestepFile); + INIT_PROPERTY_FIELD(isMultiTimestepFile); } - /// \brief Returns true if the input file contains multiple timesteps. - bool isMultiTimestepFile() const { return _isMultiTimestepFile; } - - /// \brief Tells the importer that the input file contains multiple timesteps. - void setMultiTimestepFile(bool enable) { _isMultiTimestepFile = enable; } - /// Scans the given external path (which may be a directory and a wild-card pattern, /// or a single file containing multiple frames) to find all available animation frames. /// @@ -70,24 +64,22 @@ } /// \brief Scans the given input file to find all contained simulation frames. - virtual void scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream); + virtual void scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream); private: /// Retrieves the given file in the background and scans it for simulation timesteps. - QVector discoverFramesInFile(const QUrl sourceUrl, FutureInterfaceBase& futureInterface); + QVector discoverFramesInFile(const QUrl sourceUrl, PromiseBase& promise); /// Indicates that the input file contains multiple timesteps. - PropertyField _isMultiTimestepFile; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, isMultiTimestepFile, setMultiTimestepFile); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_isMultiTimestepFile); }; OVITO_END_INLINE_NAMESPACE } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/pdb/PDBImporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/pdb/PDBImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/pdb/PDBImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/pdb/PDBImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, PDBImporter, ParticleImporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(PDBImporter, ParticleImporter); /****************************************************************************** * Checks if the given file has format that can be read by this importer. @@ -110,7 +110,7 @@ } } - setProgressRange(numAtoms); + setProgressMaximum(numAtoms); // Jump back to beginning of file. stream.seek(0); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/pdb/PDBImporter.h ovito-2.9.0+dfsg1/src/plugins/particles/import/pdb/PDBImporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/pdb/PDBImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/pdb/PDBImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PDB_IMPORTER_H -#define __OVITO_PDB_IMPORTER_H +#pragma once + #include #include "../ParticleImporter.h" @@ -82,4 +82,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PDB_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/vasp/POSCARImporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/vasp/POSCARImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/vasp/POSCARImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/vasp/POSCARImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -21,6 +21,7 @@ #include #include +#include #include #include #include "POSCARImporter.h" @@ -29,7 +30,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, POSCARImporter, ParticleImporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(POSCARImporter, ParticleImporter); /****************************************************************************** * Checks if the given file has format that can be read by this importer. @@ -92,10 +93,10 @@ /****************************************************************************** * Scans the given input file to find all contained simulation frames. ******************************************************************************/ -void POSCARImporter::scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) +void POSCARImporter::scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) { - futureInterface.setProgressText(tr("Scanning file %1").arg(stream.filename())); - futureInterface.setProgressRange(stream.underlyingSize() / 1000); + promise.setProgressText(tr("Scanning file %1").arg(stream.filename())); + promise.setProgressMaximum(stream.underlyingSize() / 1000); // Regular expression for whitespace characters. QRegularExpression ws_re(QStringLiteral("\\s+")); @@ -123,7 +124,7 @@ Frame frame; frame.sourceFile = sourceUrl; frame.lastModificationTime = fileInfo.lastModified(); - while(!stream.eof()) { + while(!stream.eof() && !promise.isCanceled()) { frame.byteOffset = stream.byteOffset(); frame.lineNumber = stream.lineNumber(); frame.label = QString("%1 (Frame %2)").arg(filename).arg(frameNumber++); @@ -136,8 +137,8 @@ } } - futureInterface.setProgressValueIntermittent(stream.underlyingByteOffset() / 1000); - if(futureInterface.isCanceled()) + promise.setProgressValueIntermittent(stream.underlyingByteOffset() / 1000); + if(promise.isCanceled()) return; } } @@ -224,16 +225,19 @@ } } - // Parse optional velocity vectors. + QString statusString = tr("%1 atoms").arg(totalAtomCount); + + // Parse optional atomic velocity vectors or CHGCAR electron density data. + // Do this only for the first frame. if(byteOffset == 0) { if(!stream.eof()) - stream.readLine(); - if(!stream.eof() && stream.line()[0] != '\0') { + stream.readLineTrimLeft(); + if(!stream.eof() && stream.line()[0] > ' ') { isCartesian = false; if(stream.line()[0] == 'C' || stream.line()[0] == 'c' || stream.line()[0] == 'K' || stream.line()[0] == 'k') isCartesian = true; - // Read atom velocities. + // Read atomic velocities. ParticleProperty* velocityProperty = new ParticleProperty(totalAtomCount, ParticleProperty::VelocityProperty, 0, false); addParticleProperty(velocityProperty); Vector3* v = velocityProperty->dataVector3(); @@ -247,9 +251,88 @@ } } } + else if(!stream.eof()) { + size_t nx, ny, nz; + // Parse charge density volumetric grid. + if(sscanf(stream.readLine(), "%zu %zu %zu", &nx, &ny, &nz) == 3 && nx > 0 && ny > 0 && nz > 0) { + auto parseFieldData = [this, &stream](size_t nx, size_t ny, size_t nz, const QString& name) -> FieldQuantity* { + std::unique_ptr fieldQuantity(new FieldQuantity({nx,ny,nz}, qMetaTypeId(), 1, 0, name, false)); + const char* s = stream.readLine(); + FloatType* data = fieldQuantity->dataFloat(); + setProgressMaximum(fieldQuantity->size()); + FloatType cellVolume = simulationCell().volume3D(); + for(size_t i = 0; i < fieldQuantity->size(); i++, ++data) { + const char* token; + for(;;) { + while(*s == ' ' || *s == '\t') ++s; + token = s; + while(*s > ' ' || *s < 0) ++s; + if(s != token) break; + s = stream.readLine(); + } + if(!parseFloatType(token, s, *data)) + throw Exception(tr("Invalid value in charge density section (line %1): \"%2\"").arg(stream.lineNumber()).arg(QString::fromLocal8Bit(token, s - token))); + *data /= cellVolume; + if(*s != '\0') + s++; + + if(!setProgressValueIntermittent(i)) return nullptr; + } + return fieldQuantity.release(); + }; + + // Parse spin up + spin down denisty. + FieldQuantity* chargeDensity = parseFieldData(nx, ny, nz, tr("Charge density")); + if(!chargeDensity) return; + addFieldQuantity(chargeDensity); + statusString += tr("\nCharge density grid: %1 x %2 x %3").arg(nx).arg(ny).arg(nz); + + // Look for spin up - spin down density. + std::unique_ptr magnetizationDensity; + while(!stream.eof()) { + if(sscanf(stream.readLine(), "%zu %zu %zu", &nx, &ny, &nz) == 3 && nx > 0 && ny > 0 && nz > 0) { + magnetizationDensity.reset(parseFieldData(nx, ny, nz, tr("Magnetization density"))); + if(!magnetizationDensity) return; + statusString += tr("\nMagnetization density grid: %1 x %2 x %3").arg(nx).arg(ny).arg(nz); + break; + } + } + + // Look for more vector components in case file contains vector magnetization. + std::unique_ptr magnetizationDensityY; + std::unique_ptr magnetizationDensityZ; + while(!stream.eof()) { + if(sscanf(stream.readLine(), "%zu %zu %zu", &nx, &ny, &nz) == 3 && nx > 0 && ny > 0 && nz > 0) { + magnetizationDensityY.reset(parseFieldData(nx, ny, nz, tr("Magnetization density"))); + if(!magnetizationDensityY) return; + break; + } + } + while(!stream.eof()) { + if(sscanf(stream.readLine(), "%zu %zu %zu", &nx, &ny, &nz) == 3 && nx > 0 && ny > 0 && nz > 0) { + magnetizationDensityZ.reset(parseFieldData(nx, ny, nz, tr("Magnetization density"))); + if(!magnetizationDensityZ) return; + break; + } + } + + if(magnetizationDensity && magnetizationDensityY && magnetizationDensityZ && + magnetizationDensityY->shape() == magnetizationDensityZ->shape() && + magnetizationDensity->shape() == magnetizationDensityY->shape()) { + std::unique_ptr vectorMagnetization(new FieldQuantity({nx,ny,nz}, qMetaTypeId(), 3, 0, tr("Magnetization density"), false)); + vectorMagnetization->setComponentNames(QStringList() << "X" << "Y" << "Z"); + for(size_t i = 0; i < vectorMagnetization->size(); i++) + vectorMagnetization->setVector3(i, { magnetizationDensity->getFloat(i), magnetizationDensityY->getFloat(i), magnetizationDensityZ->getFloat(i) }); + addFieldQuantity(vectorMagnetization.release()); + } + else if(magnetizationDensity) { + addFieldQuantity(magnetizationDensity.release()); + } + } + } } - setStatus(tr("%1 atoms").arg(totalAtomCount)); + setStatus(statusString); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/vasp/POSCARImporter.h ovito-2.9.0+dfsg1/src/plugins/particles/import/vasp/POSCARImporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/vasp/POSCARImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/vasp/POSCARImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_POSCAR_IMPORTER_H -#define __OVITO_POSCAR_IMPORTER_H +#pragma once + #include #include "../ParticleImporter.h" @@ -62,7 +62,7 @@ virtual bool shouldScanFileForTimesteps(const QUrl& sourceUrl) override; /// \brief Scans the given input file to find all contained simulation frames. - virtual void scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; + virtual void scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; /// \brief Parses the list of atom types from the POSCAR file. static void parseAtomTypeNamesAndCounts(CompressedTextReader& stream, QStringList& atomTypeNames, QVector& atomCounts); @@ -94,4 +94,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_POSCAR_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/xyz/XYZImporter.cpp ovito-2.9.0+dfsg1/src/plugins/particles/import/xyz/XYZImporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/import/xyz/XYZImporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/xyz/XYZImporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -35,9 +35,9 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Import) OVITO_BEGIN_INLINE_NAMESPACE(Formats) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, XYZImporter, ParticleImporter); -DEFINE_PROPERTY_FIELD(XYZImporter, _autoRescaleCoordinates, "AutoRescaleCoordinates"); -SET_PROPERTY_FIELD_LABEL(XYZImporter, _autoRescaleCoordinates, "Detect reduced coordinates"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(XYZImporter, ParticleImporter); +DEFINE_PROPERTY_FIELD(XYZImporter, autoRescaleCoordinates, "AutoRescaleCoordinates"); +SET_PROPERTY_FIELD_LABEL(XYZImporter, autoRescaleCoordinates, "Detect reduced coordinates"); /****************************************************************************** * Sets the user-defined mapping between data columns in the input file and @@ -101,10 +101,10 @@ /****************************************************************************** * Scans the given input file to find all contained simulation frames. ******************************************************************************/ -void XYZImporter::scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) +void XYZImporter::scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) { - futureInterface.setProgressText(tr("Scanning XYZ file %1").arg(stream.filename())); - futureInterface.setProgressRange(stream.underlyingSize() / 1000); + promise.setProgressText(tr("Scanning XYZ file %1").arg(stream.filename())); + promise.setProgressMaximum(stream.underlyingSize() / 1000); // Regular expression for whitespace characters. QRegularExpression ws_re(QStringLiteral("\\s+")); @@ -115,7 +115,7 @@ QDateTime lastModified = fileInfo.lastModified(); int frameNumber = 0; - while(!stream.eof()) { + while(!stream.eof() && !promise.isCanceled()) { qint64 byteOffset = stream.byteOffset(); // Parse number of atoms. @@ -142,8 +142,8 @@ for(int i = 0; i < numParticles; i++) { stream.readLine(); if((i % 4096) == 0) - futureInterface.setProgressValue(stream.underlyingByteOffset() / 1000); - if(futureInterface.isCanceled()) + promise.setProgressValue(stream.underlyingByteOffset() / 1000); + if(promise.isCanceled()) return; } } @@ -223,14 +223,13 @@ ******************************************************************************/ void XYZImporter::XYZImportTask::parseFile(CompressedTextReader& stream) { - setProgressText( - tr("Reading XYZ file %1").arg(frame().sourceFile.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded))); + setProgressText(tr("Reading XYZ file %1").arg(frame().sourceFile.toString(QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::PrettyDecoded))); // Parse number of atoms. int numParticles; if(sscanf(stream.readLine(), "%u", &numParticles) != 1 || numParticles < 0 || numParticles > 1e9) throw Exception(tr("Invalid number of particles in line %1 of XYZ file: %2").arg(stream.lineNumber()).arg(stream.lineString())); - setProgressRange(numParticles); + setProgressMaximum(numParticles); QString fileExcerpt = stream.lineString(); // Regular expression for whitespace characters. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/import/xyz/XYZImporter.h ovito-2.9.0+dfsg1/src/plugins/particles/import/xyz/XYZImporter.h --- ovito-2.8.1+dfsg2/src/plugins/particles/import/xyz/XYZImporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/import/xyz/XYZImporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_XYZ_IMPORTER_H -#define __OVITO_XYZ_IMPORTER_H +#pragma once + #include #include @@ -37,7 +37,7 @@ /// \brief Constructs a new instance of this class. Q_INVOKABLE XYZImporter(DataSet* dataset) : ParticleImporter(dataset), _autoRescaleCoordinates(true) { - INIT_PROPERTY_FIELD(XYZImporter::_autoRescaleCoordinates); + INIT_PROPERTY_FIELD(autoRescaleCoordinates); } /// \brief Returns the file filter that specifies the files that can be imported by this service. @@ -73,12 +73,6 @@ /// Inspects the header of the given file and returns the number of file columns. InputColumnMapping inspectFileHeader(const Frame& frame); - /// Returns whether reduced atom coordinates in the input file should be automatically detected. - bool autoRescaleCoordinates() const { return _autoRescaleCoordinates; } - - /// Sets whether reduced atom coordinates in the input file should be automatically detected. - void setAutoRescaleCoordinates(bool enable) { _autoRescaleCoordinates = enable; } - public: Q_PROPERTY(Ovito::Particles::InputColumnMapping columnMapping READ columnMapping WRITE setColumnMapping); @@ -125,7 +119,7 @@ virtual OORef clone(bool deepCopy, CloneHelper& cloneHelper) override; /// \brief Scans the given input file to find all contained simulation frames. - virtual void scanFileForTimesteps(FutureInterfaceBase& futureInterface, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; + virtual void scanFileForTimesteps(PromiseBase& promise, QVector& frames, const QUrl& sourceUrl, CompressedTextReader& stream) override; private: @@ -134,12 +128,10 @@ InputColumnMapping _columnMapping; /// Controls the automatic detection of reduced atom coordinates in the input file. - PropertyField _autoRescaleCoordinates; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, autoRescaleCoordinates, setAutoRescaleCoordinates); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_autoRescaleCoordinates); }; OVITO_END_INLINE_NAMESPACE @@ -147,4 +139,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_XYZ_IMPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/binandreduce/BinAndReduceModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/binandreduce/BinAndReduceModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/binandreduce/BinAndReduceModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/binandreduce/BinAndReduceModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,29 +27,29 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, BinAndReduceModifier, ParticleModifier); -DEFINE_FLAGS_PROPERTY_FIELD(BinAndReduceModifier, _reductionOperation, "ReductionOperation", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(BinAndReduceModifier, _firstDerivative, "firstDerivative", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(BinAndReduceModifier, _binDirection, "BinDirection", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(BinAndReduceModifier, _numberOfBinsX, "NumberOfBinsX", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(BinAndReduceModifier, _numberOfBinsY, "NumberOfBinsY", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(BinAndReduceModifier, _fixPropertyAxisRange, "FixPropertyAxisRange"); -DEFINE_FLAGS_PROPERTY_FIELD(BinAndReduceModifier, _propertyAxisRangeStart, "PropertyAxisRangeStart", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(BinAndReduceModifier, _propertyAxisRangeEnd, "PropertyAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(BinAndReduceModifier, _sourceProperty, "SourceProperty"); -DEFINE_PROPERTY_FIELD(BinAndReduceModifier, _onlySelected, "OnlySelected"); -SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, _reductionOperation, "Reduction operation"); -SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, _firstDerivative, "Compute first derivative"); -SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, _binDirection, "Bin direction"); -SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, _numberOfBinsX, "Number of spatial bins"); -SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, _numberOfBinsY, "Number of spatial bins"); -SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, _fixPropertyAxisRange, "Fix property axis range"); -SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, _propertyAxisRangeStart, "Property axis range start"); -SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, _propertyAxisRangeEnd, "Property axis range end"); -SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, _sourceProperty, "Source property"); -SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, _onlySelected, "Use only selected particles"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(BinAndReduceModifier, _numberOfBinsX, IntegerParameterUnit, 1); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(BinAndReduceModifier, _numberOfBinsY, IntegerParameterUnit, 1); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(BinAndReduceModifier, ParticleModifier); +DEFINE_FLAGS_PROPERTY_FIELD(BinAndReduceModifier, reductionOperation, "ReductionOperation", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(BinAndReduceModifier, firstDerivative, "firstDerivative", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(BinAndReduceModifier, binDirection, "BinDirection", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(BinAndReduceModifier, numberOfBinsX, "NumberOfBinsX", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(BinAndReduceModifier, numberOfBinsY, "NumberOfBinsY", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(BinAndReduceModifier, fixPropertyAxisRange, "FixPropertyAxisRange"); +DEFINE_FLAGS_PROPERTY_FIELD(BinAndReduceModifier, propertyAxisRangeStart, "PropertyAxisRangeStart", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(BinAndReduceModifier, propertyAxisRangeEnd, "PropertyAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(BinAndReduceModifier, sourceProperty, "SourceProperty"); +DEFINE_PROPERTY_FIELD(BinAndReduceModifier, onlySelected, "OnlySelected"); +SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, reductionOperation, "Reduction operation"); +SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, firstDerivative, "Compute first derivative"); +SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, binDirection, "Bin direction"); +SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, numberOfBinsX, "Number of spatial bins"); +SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, numberOfBinsY, "Number of spatial bins"); +SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, fixPropertyAxisRange, "Fix property axis range"); +SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, propertyAxisRangeStart, "Property axis range start"); +SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, propertyAxisRangeEnd, "Property axis range end"); +SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, sourceProperty, "Source property"); +SET_PROPERTY_FIELD_LABEL(BinAndReduceModifier, onlySelected, "Use only selected particles"); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(BinAndReduceModifier, numberOfBinsX, IntegerParameterUnit, 1, 100000); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(BinAndReduceModifier, numberOfBinsY, IntegerParameterUnit, 1, 100000); /****************************************************************************** * Constructs the modifier object. @@ -62,16 +62,16 @@ _yAxisRangeStart(0), _yAxisRangeEnd(0), _onlySelected(false) { - INIT_PROPERTY_FIELD(BinAndReduceModifier::_reductionOperation); - INIT_PROPERTY_FIELD(BinAndReduceModifier::_firstDerivative); - INIT_PROPERTY_FIELD(BinAndReduceModifier::_binDirection); - INIT_PROPERTY_FIELD(BinAndReduceModifier::_numberOfBinsX); - INIT_PROPERTY_FIELD(BinAndReduceModifier::_numberOfBinsY); - INIT_PROPERTY_FIELD(BinAndReduceModifier::_fixPropertyAxisRange); - INIT_PROPERTY_FIELD(BinAndReduceModifier::_propertyAxisRangeStart); - INIT_PROPERTY_FIELD(BinAndReduceModifier::_propertyAxisRangeEnd); - INIT_PROPERTY_FIELD(BinAndReduceModifier::_sourceProperty); - INIT_PROPERTY_FIELD(BinAndReduceModifier::_onlySelected); + INIT_PROPERTY_FIELD(reductionOperation); + INIT_PROPERTY_FIELD(firstDerivative); + INIT_PROPERTY_FIELD(binDirection); + INIT_PROPERTY_FIELD(numberOfBinsX); + INIT_PROPERTY_FIELD(numberOfBinsY); + INIT_PROPERTY_FIELD(fixPropertyAxisRange); + INIT_PROPERTY_FIELD(propertyAxisRangeStart); + INIT_PROPERTY_FIELD(propertyAxisRangeEnd); + INIT_PROPERTY_FIELD(sourceProperty); + INIT_PROPERTY_FIELD(onlySelected); } /****************************************************************************** @@ -84,7 +84,7 @@ // Use the first available particle property from the input state as data source when the modifier is newly created. if(sourceProperty().isNull()) { - PipelineFlowState input = pipeline->evaluatePipeline(dataset()->animationSettings()->time(), modApp, false); + PipelineFlowState input = getModifierInput(modApp); ParticlePropertyReference bestProperty; for(DataObject* o : input.objects()) { ParticlePropertyObject* property = dynamic_object_cast(o); @@ -111,8 +111,8 @@ std::fill(_binData.begin(), _binData.end(), 0.0); // Return coordinate indices (0, 1 or 2). - int binDirX = binDirectionX(_binDirection); - int binDirY = binDirectionY(_binDirection); + int binDirX = binDirectionX(binDirection()); + int binDirY = binDirectionY(binDirection()); // Number of particles for averaging. std::vector numberOfParticlesPerBin(binDataSize, 0); @@ -145,40 +145,41 @@ // Compute the surface normal vector. Vector3 normalX, normalY(1, 1, 1); - if(_binDirection == CELL_VECTOR_1) { - normalX = expectSimulationCell()->edgeVector2().cross(expectSimulationCell()->edgeVector3()); + if(binDirection() == CELL_VECTOR_1) { + normalX = expectSimulationCell()->cellVector2().cross(expectSimulationCell()->cellVector3()); } - else if(_binDirection == CELL_VECTOR_2) { - normalX = expectSimulationCell()->edgeVector3().cross(expectSimulationCell()->edgeVector1()); + else if(binDirection() == CELL_VECTOR_2) { + normalX = expectSimulationCell()->cellVector3().cross(expectSimulationCell()->cellVector1()); } - else if(_binDirection == CELL_VECTOR_3) { - normalX = expectSimulationCell()->edgeVector1().cross(expectSimulationCell()->edgeVector2()); + else if(binDirection() == CELL_VECTOR_3) { + normalX = expectSimulationCell()->cellVector1().cross(expectSimulationCell()->cellVector2()); } - else if(_binDirection == CELL_VECTORS_1_2) { - normalX = expectSimulationCell()->edgeVector2().cross(expectSimulationCell()->edgeVector3()); - normalY = expectSimulationCell()->edgeVector3().cross(expectSimulationCell()->edgeVector1()); + else if(binDirection() == CELL_VECTORS_1_2) { + normalX = expectSimulationCell()->cellVector2().cross(expectSimulationCell()->cellVector3()); + normalY = expectSimulationCell()->cellVector3().cross(expectSimulationCell()->cellVector1()); } else if(_binDirection == CELL_VECTORS_2_3) { - normalX = expectSimulationCell()->edgeVector3().cross(expectSimulationCell()->edgeVector1()); - normalY = expectSimulationCell()->edgeVector1().cross(expectSimulationCell()->edgeVector2()); + normalX = expectSimulationCell()->cellVector3().cross(expectSimulationCell()->cellVector1()); + normalY = expectSimulationCell()->cellVector1().cross(expectSimulationCell()->cellVector2()); } - else if(_binDirection == CELL_VECTORS_1_3) { - normalX = expectSimulationCell()->edgeVector2().cross(expectSimulationCell()->edgeVector3()); - normalY = expectSimulationCell()->edgeVector1().cross(expectSimulationCell()->edgeVector2()); + else if(binDirection() == CELL_VECTORS_1_3) { + normalX = expectSimulationCell()->cellVector2().cross(expectSimulationCell()->cellVector3()); + normalY = expectSimulationCell()->cellVector1().cross(expectSimulationCell()->cellVector2()); } if(normalX == Vector3::Zero() || normalY == Vector3::Zero()) throwException(tr("Simulation cell is degenerate.")); // Compute the distance of the two cell faces (normal.length() is area of face). FloatType cellVolume = cell.volume3D(); - _xAxisRangeStart = (expectSimulationCell()->origin() - Point3::Origin()).dot(normalX.normalized()); + _xAxisRangeStart = (expectSimulationCell()->cellOrigin() - Point3::Origin()).dot(normalX.normalized()); _xAxisRangeEnd = _xAxisRangeStart + cellVolume / normalX.length(); if(!is1D()) { - _yAxisRangeStart = (expectSimulationCell()->origin() - Point3::Origin()).dot(normalY.normalized()); + _yAxisRangeStart = (expectSimulationCell()->cellOrigin() - Point3::Origin()).dot(normalY.normalized()); _yAxisRangeEnd = _yAxisRangeStart + cellVolume / normalY.length(); } else { - _yAxisRangeStart = _yAxisRangeEnd = 0; + _yAxisRangeStart = 0; + _yAxisRangeEnd = 0; } // Get the particle positions. @@ -260,7 +261,7 @@ } } - if(_reductionOperation == RED_MEAN) { + if(reductionOperation() == RED_MEAN) { // Normalize. auto a = _binData.begin(); for(auto n : numberOfParticlesPerBin) { @@ -268,7 +269,7 @@ ++a; } } - else if(_reductionOperation == RED_SUM_VOL) { + else if(reductionOperation() == RED_SUM_VOL) { // Divide by bin volume. double binVolume = cellVolume / (binDataSizeX*binDataSizeY); std::for_each(_binData.begin(), _binData.end(), [binVolume](double &x) { x /= binVolume; }); @@ -276,7 +277,7 @@ } // Compute first derivative using finite differences. - if(_firstDerivative) { + if(firstDerivative()) { FloatType binSpacingX = (_xAxisRangeEnd - _xAxisRangeStart) / binDataSizeX; if(binDataSizeX > 1 && _xAxisRangeEnd > _xAxisRangeStart) { QVector derivativeData(binDataSize); @@ -303,10 +304,10 @@ else std::fill(_binData.begin(), _binData.end(), 0.0); } - if(!_fixPropertyAxisRange) { + if(!fixPropertyAxisRange()) { auto minmax = std::minmax_element(_binData.begin(), _binData.end()); - _propertyAxisRangeStart = *minmax.first; - _propertyAxisRangeEnd = *minmax.second; + setPropertyAxisRangeStart(*minmax.first); + setPropertyAxisRangeEnd(*minmax.second); } // Inform the editor component that the stored data has changed diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/binandreduce/BinAndReduceModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/binandreduce/BinAndReduceModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/binandreduce/BinAndReduceModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/binandreduce/BinAndReduceModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -20,8 +20,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BIN_AND_REDUCE_MODIFIER_H -#define __OVITO_BIN_AND_REDUCE_MODIFIER_H +#pragma once + #include #include @@ -46,45 +46,12 @@ /// Constructor. Q_INVOKABLE BinAndReduceModifier(DataSet* dataset); - /// Sets the source particle property for which the average should be computed. - void setSourceProperty(const ParticlePropertyReference& prop) { _sourceProperty = prop; } - - /// Returns the source particle property for which the average is computed. - const ParticlePropertyReference& sourceProperty() const { return _sourceProperty; } - - /// Returns the reduction operation - ReductionOperationType reductionOperation() const { return _reductionOperation; } - - /// Sets the reduction operation - void setReductionOperation(ReductionOperationType o) { _reductionOperation = o; } - - /// Returns compute first derivative - bool firstDerivative() const { return _firstDerivative; } - - /// Sets compute first derivative - void setFirstDerivative(bool d) { _firstDerivative = d; } - - /// Returns the bin direction - BinDirectionType binDirection() const { return _binDirection; } - - /// Sets the bin direction - void setBinDirection(BinDirectionType o) { _binDirection = o; } - - /// Returns the number of spatial bins of the computed average value. - int numberOfBinsX() const { return _numberOfBinsX; } - - /// Sets the number of spatial bins of the computed average value. - void setNumberOfBinsX(int n) { _numberOfBinsX = n; } - - /// Returns the number of spatial bins of the computed average value. - int numberOfBinsY() const { return _numberOfBinsY; } - - /// Sets the number of spatial bins of the computed average value. - void setNumberOfBinsY(int n) { _numberOfBinsY = n; } - /// Returns the stored average data. const QVector& binData() const { return _binData; } + /// Set start and end value of the plotting property axis. + void setPropertyAxisRange(FloatType start, FloatType end) { _propertyAxisRangeStart = start; _propertyAxisRangeEnd = end; } + /// Returns the start value of the plotting x-axis. FloatType xAxisRangeStart() const { return _xAxisRangeStart; } @@ -97,27 +64,6 @@ /// Returns the end value of the plotting y-axis. FloatType yAxisRangeEnd() const { return _yAxisRangeEnd; } - /// Set whether the plotting range of the property axis should be fixed. - void setFixPropertyAxisRange(bool fix) { _fixPropertyAxisRange = fix; } - - /// Returns whether the plotting range of the property axis should be fixed. - bool fixPropertyAxisRange() const { return _fixPropertyAxisRange; } - - /// Set start and end value of the plotting property axis. - void setPropertyAxisRange(FloatType start, FloatType end) { _propertyAxisRangeStart = start; _propertyAxisRangeEnd = end; } - - /// Returns the start value of the plotting y-axis. - FloatType propertyAxisRangeStart() const { return _propertyAxisRangeStart; } - - /// Returns the end value of the plotting y-axis. - FloatType propertyAxisRangeEnd() const { return _propertyAxisRangeEnd; } - - /// Returns whether analysis takes only selected particles into account. - bool onlySelected() const { return _onlySelected; } - - /// Sets whether analysis only selected particles are taken into account. - void setOnlySelected(bool onlySelected) { _onlySelected = onlySelected; } - /// Returns true if binning in a single direction only. bool is1D() { return bin1D(_binDirection); @@ -149,34 +95,34 @@ private: /// The particle property that serves as data source to be averaged. - PropertyField _sourceProperty; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ParticlePropertyReference, sourceProperty, setSourceProperty); /// Type of reduction operation - PropertyField _reductionOperation; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ReductionOperationType, reductionOperation, setReductionOperation); /// Compute first derivative. - PropertyField _firstDerivative; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, firstDerivative, setFirstDerivative); /// Bin alignment - PropertyField _binDirection; + DECLARE_MODIFIABLE_PROPERTY_FIELD(BinDirectionType, binDirection, setBinDirection); /// Controls the number of spatial bins. - PropertyField _numberOfBinsX; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, numberOfBinsX, setNumberOfBinsX); /// Controls the number of spatial bins. - PropertyField _numberOfBinsY; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, numberOfBinsY, setNumberOfBinsY); /// Controls the whether the plotting range along the y-axis should be fixed. - PropertyField _fixPropertyAxisRange; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, fixPropertyAxisRange, setFixPropertyAxisRange); /// Controls the start value of the plotting y-axis. - PropertyField _propertyAxisRangeStart; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, propertyAxisRangeStart, setPropertyAxisRangeStart); /// Controls the end value of the plotting y-axis. - PropertyField _propertyAxisRangeEnd; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, propertyAxisRangeEnd, setPropertyAxisRangeEnd); /// Controls whether the modifier should take into account only selected particles. - PropertyField _onlySelected; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, onlySelected, setOnlySelected); /// Stores the start value of the plotting x-axis. FloatType _xAxisRangeStart; @@ -199,17 +145,6 @@ Q_CLASSINFO("DisplayName", "Bin and reduce"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_PROPERTY_FIELD(_reductionOperation); - DECLARE_PROPERTY_FIELD(_firstDerivative); - DECLARE_PROPERTY_FIELD(_binDirection); - DECLARE_PROPERTY_FIELD(_numberOfBinsX); - DECLARE_PROPERTY_FIELD(_numberOfBinsY); - DECLARE_PROPERTY_FIELD(_fixPropertyAxisRange); - DECLARE_PROPERTY_FIELD(_propertyAxisRangeStart); - DECLARE_PROPERTY_FIELD(_propertyAxisRangeEnd); - DECLARE_PROPERTY_FIELD(_sourceProperty); - DECLARE_PROPERTY_FIELD(_onlySelected); }; OVITO_END_INLINE_NAMESPACE @@ -222,4 +157,4 @@ Q_DECLARE_TYPEINFO(Ovito::Particles::BinAndReduceModifier::ReductionOperationType, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::Particles::BinAndReduceModifier::BinDirectionType, Q_PRIMITIVE_TYPE); -#endif // __OVITO_BIN_AND_REDUCE_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/bondangle/BondAngleAnalysisModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/bondangle/BondAngleAnalysisModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/bondangle/BondAngleAnalysisModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/bondangle/BondAngleAnalysisModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,7 +28,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, BondAngleAnalysisModifier, StructureIdentificationModifier); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(BondAngleAnalysisModifier, StructureIdentificationModifier); /****************************************************************************** * Constructs the modifier object. @@ -54,6 +54,8 @@ // Get modifier input. ParticlePropertyObject* posProperty = expectStandardProperty(ParticleProperty::PositionProperty); SimulationCellObject* simCell = expectSimulationCell(); + if(simCell->is2D()) + throwException(tr("The bond-angle ananlysis modifier does not support 2d simulation cells.")); // Get particle selection. ParticleProperty* selectionProperty = nullptr; @@ -73,7 +75,7 @@ // Prepare the neighbor list. NearestNeighborFinder neighborFinder(14); - if(!neighborFinder.prepare(positions(), cell(), selection(), this)) + if(!neighborFinder.prepare(positions(), cell(), selection(), *this)) return; // Create output storage. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/bondangle/BondAngleAnalysisModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/bondangle/BondAngleAnalysisModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/bondangle/BondAngleAnalysisModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/bondangle/BondAngleAnalysisModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BOND_ANGLE_ANALYSIS_MODIFIER_H -#define __OVITO_BOND_ANGLE_ANALYSIS_MODIFIER_H +#pragma once + #include #include @@ -91,4 +91,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_BOND_ANGLE_ANALYSIS_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/centrosymmetry/CentroSymmetryModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/centrosymmetry/CentroSymmetryModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/centrosymmetry/CentroSymmetryModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/centrosymmetry/CentroSymmetryModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,10 +26,10 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, CentroSymmetryModifier, AsynchronousParticleModifier); -DEFINE_FLAGS_PROPERTY_FIELD(CentroSymmetryModifier, _numNeighbors, "NumNeighbors", PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(CentroSymmetryModifier, _numNeighbors, "Number of neighbors"); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(CentroSymmetryModifier, _numNeighbors, IntegerParameterUnit, 2, CentroSymmetryModifier::MAX_CSP_NEIGHBORS); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CentroSymmetryModifier, AsynchronousParticleModifier); +DEFINE_FLAGS_PROPERTY_FIELD(CentroSymmetryModifier, numNeighbors, "NumNeighbors", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(CentroSymmetryModifier, numNeighbors, "Number of neighbors"); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(CentroSymmetryModifier, numNeighbors, IntegerParameterUnit, 2, CentroSymmetryModifier::MAX_CSP_NEIGHBORS); /****************************************************************************** * Constructs the modifier object. @@ -37,7 +37,7 @@ CentroSymmetryModifier::CentroSymmetryModifier(DataSet* dataset) : AsynchronousParticleModifier(dataset), _numNeighbors(12) { - INIT_PROPERTY_FIELD(CentroSymmetryModifier::_numNeighbors); + INIT_PROPERTY_FIELD(numNeighbors); } /****************************************************************************** @@ -68,7 +68,7 @@ // Prepare the neighbor list. NearestNeighborFinder neighFinder(_nneighbors); - if(!neighFinder.prepare(positions(), cell(), nullptr, this)) { + if(!neighFinder.prepare(positions(), cell(), nullptr, *this)) { return; } @@ -140,7 +140,7 @@ AsynchronousParticleModifier::propertyChanged(field); // Recompute brightness values when the parameters have been changed. - if(field == PROPERTY_FIELD(CentroSymmetryModifier::_numNeighbors)) + if(field == PROPERTY_FIELD(numNeighbors)) invalidateCachedResults(); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/centrosymmetry/CentroSymmetryModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/centrosymmetry/CentroSymmetryModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/centrosymmetry/CentroSymmetryModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/centrosymmetry/CentroSymmetryModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CENTRO_SYMMETRY_MODIFIER_H -#define __OVITO_CENTRO_SYMMETRY_MODIFIER_H +#pragma once + #include #include @@ -42,12 +42,6 @@ /// Constructor. Q_INVOKABLE CentroSymmetryModifier(DataSet* dataset); - /// Returns the number of nearest neighbors to take into account when computing the CSP. - int numNeighbors() const { return _numNeighbors; } - - /// Sets the number of nearest neighbors to take into account when computing the CSP. - void setNumNeighbors(int count) { _numNeighbors = count; } - protected: /// Is called when the value of a property of this object has changed. @@ -104,15 +98,13 @@ QExplicitlySharedDataPointer _cspValues; /// Specifies the number of nearest neighbors to take into account when computing the CSP. - PropertyField _numNeighbors; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, numNeighbors, setNumNeighbors); Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Centrosymmetry parameter"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_PROPERTY_FIELD(_numNeighbors); }; OVITO_END_INLINE_NAMESPACE @@ -120,4 +112,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CENTRO_SYMMETRY_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/cluster/ClusterAnalysisModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/cluster/ClusterAnalysisModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/cluster/ClusterAnalysisModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/cluster/ClusterAnalysisModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -20,28 +20,34 @@ /////////////////////////////////////////////////////////////////////////////// #include +#include +#include #include "ClusterAnalysisModifier.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ClusterAnalysisModifier, AsynchronousParticleModifier); -DEFINE_FLAGS_PROPERTY_FIELD(ClusterAnalysisModifier, _cutoff, "Cutoff", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(ClusterAnalysisModifier, _onlySelectedParticles, "OnlySelectedParticles"); -DEFINE_PROPERTY_FIELD(ClusterAnalysisModifier, _sortBySize, "SortBySize"); -SET_PROPERTY_FIELD_LABEL(ClusterAnalysisModifier, _cutoff, "Cutoff distance"); -SET_PROPERTY_FIELD_LABEL(ClusterAnalysisModifier, _onlySelectedParticles, "Use only selected particles"); -SET_PROPERTY_FIELD_LABEL(ClusterAnalysisModifier, _sortBySize, "Sort clusters by size"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ClusterAnalysisModifier, _cutoff, WorldParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ClusterAnalysisModifier, AsynchronousParticleModifier); +DEFINE_FLAGS_PROPERTY_FIELD(ClusterAnalysisModifier, neighborMode, "NeighborMode", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ClusterAnalysisModifier, cutoff, "Cutoff", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(ClusterAnalysisModifier, onlySelectedParticles, "OnlySelectedParticles"); +DEFINE_PROPERTY_FIELD(ClusterAnalysisModifier, sortBySize, "SortBySize"); +SET_PROPERTY_FIELD_LABEL(ClusterAnalysisModifier, neighborMode, "Neighbor mode"); +SET_PROPERTY_FIELD_LABEL(ClusterAnalysisModifier, cutoff, "Cutoff distance"); +SET_PROPERTY_FIELD_LABEL(ClusterAnalysisModifier, onlySelectedParticles, "Use only selected particles"); +SET_PROPERTY_FIELD_LABEL(ClusterAnalysisModifier, sortBySize, "Sort clusters by size"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ClusterAnalysisModifier, cutoff, WorldParameterUnit, 0); /****************************************************************************** * Constructs the modifier object. ******************************************************************************/ ClusterAnalysisModifier::ClusterAnalysisModifier(DataSet* dataset) : AsynchronousParticleModifier(dataset), - _cutoff(3.2), _onlySelectedParticles(false), _sortBySize(false), _numClusters(0), _largestClusterSize(0) + _cutoff(3.2), _onlySelectedParticles(false), _sortBySize(false), _numClusters(0), _largestClusterSize(0), + _neighborMode(CutoffRange) { - INIT_PROPERTY_FIELD(ClusterAnalysisModifier::_cutoff); - INIT_PROPERTY_FIELD(ClusterAnalysisModifier::_onlySelectedParticles); - INIT_PROPERTY_FIELD(ClusterAnalysisModifier::_sortBySize); + INIT_PROPERTY_FIELD(neighborMode); + INIT_PROPERTY_FIELD(cutoff); + INIT_PROPERTY_FIELD(onlySelectedParticles); + INIT_PROPERTY_FIELD(sortBySize); } /****************************************************************************** @@ -61,7 +67,18 @@ selectionProperty = expectStandardProperty(ParticleProperty::SelectionProperty)->storage(); // Create engine object. Pass all relevant modifier parameters to the engine as well as the input data. - return std::make_shared(validityInterval, posProperty->storage(), inputCell->data(), cutoff(), sortBySize(), selectionProperty); + if(neighborMode() == CutoffRange) { + return std::make_shared(validityInterval, posProperty->storage(), inputCell->data(), sortBySize(), selectionProperty, cutoff()); + } + else if(neighborMode() == Bonding) { + BondsObject* bonds = input().findObject(); + if(!bonds) + throwException(tr("Input of cluster analysis modifier does not contain any bonds.")); + return std::make_shared(validityInterval, posProperty->storage(), inputCell->data(), sortBySize(), selectionProperty, bonds->storage()); + } + else { + throwException(tr("Invalid cluster neighbor mode")); + } } /****************************************************************************** @@ -71,34 +88,73 @@ { setProgressText(tr("Performing cluster analysis")); + // Initialize. + std::fill(_particleClusters->dataInt(), _particleClusters->dataInt() + _particleClusters->size(), -1); + _numClusters = 0; + + // Perform the actual clustering. + doClustering(); + if(isCanceled()) + return; + + // Sort clusters by size. + if(_sortBySize && _numClusters != 0) { + + // Determine cluster sizes. + std::vector clusterSizes(_numClusters + 1, 0); + for(int id : _particleClusters->constIntRange()) { + clusterSizes[id]++; + } + + // Sort clusters by size. + std::vector mapping(_numClusters + 1); + std::iota(mapping.begin(), mapping.end(), 0); + std::sort(mapping.begin() + 1, mapping.end(), [&clusterSizes](int a, int b) { + return clusterSizes[a] > clusterSizes[b]; + }); + _largestClusterSize = clusterSizes[mapping[1]]; + clusterSizes.clear(); + clusterSizes.shrink_to_fit(); + + // Remap cluster IDs. + std::vector inverseMapping(_numClusters + 1); + for(size_t i = 0; i <= _numClusters; i++) + inverseMapping[mapping[i]] = i; + for(int& id : _particleClusters->intRange()) + id = inverseMapping[id]; + } +} + +/****************************************************************************** +* Performs the actual clustering algorithm. +******************************************************************************/ +void ClusterAnalysisModifier::CutoffClusterAnalysisEngine::doClustering() +{ // Prepare the neighbor finder. CutoffNeighborFinder neighborFinder; - if(!neighborFinder.prepare(_cutoff, positions(), cell(), selection(), this)) + if(!neighborFinder.prepare(cutoff(), positions(), cell(), selection(), *this)) return; size_t particleCount = positions()->size(); - setProgressRange(particleCount); - - // Initialize. - std::fill(_particleClusters->dataInt(), _particleClusters->dataInt() + _particleClusters->size(), -1); - _numClusters = 0; + setProgressValue(0); + setProgressMaximum(particleCount); - std::deque toProcess; + std::deque toProcess; for(size_t seedParticleIndex = 0; seedParticleIndex < particleCount; seedParticleIndex++) { // Skip unselected particles that are not included in the analysis. if(selection() && !selection()->getInt(seedParticleIndex)) { - _particleClusters->setInt(seedParticleIndex, 0); + particleClusters()->setInt(seedParticleIndex, 0); continue; } // Skip particles that have already been assigned to a cluster. - if(_particleClusters->getInt(seedParticleIndex) != -1) + if(particleClusters()->getInt(seedParticleIndex) != -1) continue; // Start a new cluster. int cluster = ++_numClusters; - _particleClusters->setInt(seedParticleIndex, cluster); + particleClusters()->setInt(seedParticleIndex, cluster); // Now recursively iterate over all neighbors of the seed particle and add them to the cluster too. OVITO_ASSERT(toProcess.empty()); @@ -113,40 +169,74 @@ toProcess.pop_front(); for(CutoffNeighborFinder::Query neighQuery(neighborFinder, currentParticle); !neighQuery.atEnd(); neighQuery.next()) { int neighborIndex = neighQuery.current(); - if(_particleClusters->getInt(neighborIndex) == -1) { - _particleClusters->setInt(neighborIndex, cluster); + if(particleClusters()->getInt(neighborIndex) == -1) { + particleClusters()->setInt(neighborIndex, cluster); toProcess.push_back(neighborIndex); } } } while(toProcess.empty() == false); } +} - // Sort clusters by size. - if(_sortBySize && _numClusters != 0) { +/****************************************************************************** +* Performs the actual clustering algorithm. +******************************************************************************/ +void ClusterAnalysisModifier::BondClusterAnalysisEngine::doClustering() +{ + size_t particleCount = positions()->size(); + setProgressValue(0); + setProgressMaximum(particleCount); - // Determine cluster sizes. - std::vector clusterSizes(_numClusters + 1, 0); - for(int id : _particleClusters->constIntRange()) { - clusterSizes[id]++; + // Prepare particle bond map. + ParticleBondMap bondMap(bonds()); + + std::deque toProcess; + for(size_t seedParticleIndex = 0; seedParticleIndex < particleCount; seedParticleIndex++) { + + // Skip unselected particles that are not included in the analysis. + if(selection() && !selection()->getInt(seedParticleIndex)) { + particleClusters()->setInt(seedParticleIndex, 0); + continue; } - // Sort clusters by size. - std::vector mapping(_numClusters + 1); - std::iota(mapping.begin(), mapping.end(), 0); - std::sort(mapping.begin() + 1, mapping.end(), [&clusterSizes](int a, int b) { - return clusterSizes[a] > clusterSizes[b]; - }); - _largestClusterSize = clusterSizes[mapping[1]]; - clusterSizes.clear(); - clusterSizes.shrink_to_fit(); + // Skip particles that have already been assigned to a cluster. + if(particleClusters()->getInt(seedParticleIndex) != -1) + continue; - // Remap cluster IDs. - std::vector inverseMapping(_numClusters + 1); - for(size_t i = 0; i <= _numClusters; i++) - inverseMapping[mapping[i]] = i; - for(int& id : _particleClusters->intRange()) - id = inverseMapping[id]; + // Start a new cluster. + int cluster = ++_numClusters; + particleClusters()->setInt(seedParticleIndex, cluster); + + // Now recursively iterate over all neighbors of the seed particle and add them to the cluster too. + OVITO_ASSERT(toProcess.empty()); + toProcess.push_back(seedParticleIndex); + + do { + incrementProgressValue(); + if(isCanceled()) + return; + + size_t currentParticle = toProcess.front(); + toProcess.pop_front(); + + // Iterate over all bonds of the current particle. + for(size_t neighborBondIndex : bondMap.bondsOfParticle(currentParticle)) { + const Bond& neighborBond = bonds()[neighborBondIndex]; + OVITO_ASSERT(neighborBond.index1 == currentParticle); + size_t neighborIndex = neighborBond.index2; + if(neighborIndex >= particleCount) + continue; + if(particleClusters()->getInt(neighborIndex) != -1) + continue; + if(selection() && !selection()->getInt(neighborIndex)) + continue; + + particleClusters()->setInt(neighborIndex, cluster); + toProcess.push_back(neighborIndex); + } + } + while(toProcess.empty() == false); } } @@ -190,9 +280,10 @@ AsynchronousParticleModifier::propertyChanged(field); // Recompute modifier results when the parameters have been changed. - if(field == PROPERTY_FIELD(ClusterAnalysisModifier::_cutoff) || - field == PROPERTY_FIELD(ClusterAnalysisModifier::_onlySelectedParticles) || - field == PROPERTY_FIELD(ClusterAnalysisModifier::_sortBySize)) + if(field == PROPERTY_FIELD(neighborMode) || + field == PROPERTY_FIELD(cutoff) || + field == PROPERTY_FIELD(onlySelectedParticles) || + field == PROPERTY_FIELD(sortBySize)) invalidateCachedResults(); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/cluster/ClusterAnalysisModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/cluster/ClusterAnalysisModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/cluster/ClusterAnalysisModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/cluster/ClusterAnalysisModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,44 +19,33 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CLUSTER_ANALYSIS_MODIFIER_H -#define __OVITO_CLUSTER_ANALYSIS_MODIFIER_H +#pragma once + #include #include #include +#include #include "../../AsynchronousParticleModifier.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) /** - * \brief This modifier determines decomposes the particle set into clusters. + * \brief This modifier builds clusters of particles. */ class OVITO_PARTICLES_EXPORT ClusterAnalysisModifier : public AsynchronousParticleModifier { public: + enum NeighborMode { + CutoffRange, ///< Treats particles as neighbors which are within a certain distance. + Bonding, ///< Treats particles as neighbors which are connected by a bond. + }; + Q_ENUMS(NeighborMode); + /// Constructor. Q_INVOKABLE ClusterAnalysisModifier(DataSet* dataset); - /// Returns the cutoff radius used to build the neighbor lists for the analysis. - FloatType cutoff() const { return _cutoff; } - - /// \brief Sets the cutoff radius used to build the neighbor lists for the analysis. - void setCutoff(FloatType newCutoff) { _cutoff = newCutoff; } - - /// Returns whether analysis takes only selected particles into account. - bool onlySelectedParticles() const { return _onlySelectedParticles; } - - /// Sets whether analysis only selected particles are taken into account. - void setOnlySelectedParticles(bool onlySelected) { _onlySelectedParticles = onlySelected; } - - /// Returns whether cluster IDs are sorted by size. - bool sortBySize() const { return _sortBySize; } - - /// Sets whether cluster IDs are sorted by size. - void setSortBySize(bool sort) { _sortBySize = sort; } - /// Returns the number of clusters found during the last successful evaluation of the modifier. size_t clusterCount() const { return _numClusters; } @@ -82,9 +71,9 @@ public: /// Constructor. - ClusterAnalysisEngine(const TimeInterval& validityInterval, ParticleProperty* positions, const SimulationCell& simCell, FloatType cutoff, bool sortBySize, ParticleProperty* selection) : + ClusterAnalysisEngine(const TimeInterval& validityInterval, ParticleProperty* positions, const SimulationCell& simCell, bool sortBySize, ParticleProperty* selection) : ComputeEngine(validityInterval), - _positions(positions), _simCell(simCell), _cutoff(cutoff), + _positions(positions), _simCell(simCell), _sortBySize(sortBySize), _selection(selection), _largestClusterSize(0), @@ -93,6 +82,9 @@ /// Computes the modifier's results and stores them in this object for later retrieval. virtual void perform() override; + /// Performs the actual clustering algorithm. + virtual void doClustering() = 0; + /// Returns the property storage that contains the input particle positions. ParticleProperty* positions() const { return _positions.data(); } @@ -102,9 +94,6 @@ /// Returns the property storage that contains the computed cluster number of each particle. ParticleProperty* particleClusters() const { return _particleClusters.data(); } - /// Returns the cutoff radius. - FloatType cutoff() const { return _cutoff; } - /// Returns the property storage that contains the particle selection (optional). ParticleProperty* selection() const { return _selection.data(); } @@ -114,9 +103,8 @@ /// Returns the size of the largest cluster. size_t largestClusterSize() const { return _largestClusterSize; } - private: + protected: - FloatType _cutoff; SimulationCell _simCell; bool _sortBySize; size_t _numClusters; @@ -126,17 +114,62 @@ QExplicitlySharedDataPointer _particleClusters; }; + /// Computes the modifier's results. + class CutoffClusterAnalysisEngine : public ClusterAnalysisEngine + { + public: + + /// Constructor. + CutoffClusterAnalysisEngine(const TimeInterval& validityInterval, ParticleProperty* positions, const SimulationCell& simCell, bool sortBySize, ParticleProperty* selection, FloatType cutoff) : + ClusterAnalysisEngine(validityInterval, positions, simCell, sortBySize, selection), + _cutoff(cutoff) {} + + /// Performs the actual clustering algorithm. + virtual void doClustering() override; + + /// Returns the cutoff radius. + FloatType cutoff() const { return _cutoff; } + + private: + + FloatType _cutoff; + }; + + /// Computes the modifier's results. + class BondClusterAnalysisEngine : public ClusterAnalysisEngine + { + public: + + /// Constructor. + BondClusterAnalysisEngine(const TimeInterval& validityInterval, ParticleProperty* positions, const SimulationCell& simCell, bool sortBySize, ParticleProperty* selection, BondsStorage* bonds) : + ClusterAnalysisEngine(validityInterval, positions, simCell, sortBySize, selection), + _bonds(bonds) {} + + /// Performs the actual clustering algorithm. + virtual void doClustering() override; + + /// Returns the list of input bonds. + const BondsStorage& bonds() const { return *_bonds; } + + private: + + QExplicitlySharedDataPointer _bonds; + }; + /// This stores the cached results of the modifier. QExplicitlySharedDataPointer _particleClusters; - /// Controls the cutoff radius for the neighbor lists. - PropertyField _cutoff; + /// The neighbor mode. + DECLARE_MODIFIABLE_PROPERTY_FIELD(NeighborMode, neighborMode, setNeighborMode); + + /// The cutoff radius for the distance-based neighbor criterion. + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, cutoff, setCutoff); /// Controls whether analysis should take into account only selected particles. - PropertyField _onlySelectedParticles; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, onlySelectedParticles, setOnlySelectedParticles); - /// Controls the sorting of cluster IDs by size. - PropertyField _sortBySize; + /// Controls the sorting of cluster IDs by cluster size. + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, sortBySize, setSortBySize); /// The number of clusters identified during the last evaluation of the modifier. size_t _numClusters; @@ -144,17 +177,11 @@ /// The size of the largest cluster. size_t _largestClusterSize; -private: - Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Cluster analysis"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_PROPERTY_FIELD(_cutoff); - DECLARE_PROPERTY_FIELD(_onlySelectedParticles); - DECLARE_PROPERTY_FIELD(_sortBySize); }; OVITO_END_INLINE_NAMESPACE @@ -162,4 +189,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CLUSTER_ANALYSIS_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/cna/CommonNeighborAnalysisModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/cna/CommonNeighborAnalysisModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/cna/CommonNeighborAnalysisModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/cna/CommonNeighborAnalysisModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,21 +30,21 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, CommonNeighborAnalysisModifier, StructureIdentificationModifier); -DEFINE_FLAGS_PROPERTY_FIELD(CommonNeighborAnalysisModifier, _cutoff, "Cutoff", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(CommonNeighborAnalysisModifier, _cnaMode, "CNAMode", PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(CommonNeighborAnalysisModifier, _cutoff, "Cutoff radius"); -SET_PROPERTY_FIELD_LABEL(CommonNeighborAnalysisModifier, _cnaMode, "Mode"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CommonNeighborAnalysisModifier, _cutoff, WorldParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CommonNeighborAnalysisModifier, StructureIdentificationModifier); +DEFINE_FLAGS_PROPERTY_FIELD(CommonNeighborAnalysisModifier, cutoff, "Cutoff", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CommonNeighborAnalysisModifier, mode, "CNAMode", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(CommonNeighborAnalysisModifier, cutoff, "Cutoff radius"); +SET_PROPERTY_FIELD_LABEL(CommonNeighborAnalysisModifier, mode, "Mode"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CommonNeighborAnalysisModifier, cutoff, WorldParameterUnit, 0); /****************************************************************************** * Constructs the modifier object. ******************************************************************************/ CommonNeighborAnalysisModifier::CommonNeighborAnalysisModifier(DataSet* dataset) : StructureIdentificationModifier(dataset), - _cutoff(3.2), _cnaMode(AdaptiveCutoffMode) + _cutoff(3.2), _mode(AdaptiveCutoffMode) { - INIT_PROPERTY_FIELD(CommonNeighborAnalysisModifier::_cutoff); - INIT_PROPERTY_FIELD(CommonNeighborAnalysisModifier::_cnaMode); + INIT_PROPERTY_FIELD(cutoff); + INIT_PROPERTY_FIELD(mode); // Create the structure types. createStructureType(OTHER, ParticleTypeProperty::PredefinedStructureType::OTHER); @@ -62,8 +62,8 @@ StructureIdentificationModifier::propertyChanged(field); // Recompute results when the parameters have been changed. - if(field == PROPERTY_FIELD(CommonNeighborAnalysisModifier::_cutoff) || - field == PROPERTY_FIELD(CommonNeighborAnalysisModifier::_cnaMode)) + if(field == PROPERTY_FIELD(cutoff) || + field == PROPERTY_FIELD(mode)) invalidateCachedResults(); } @@ -95,6 +95,8 @@ // Get modifier input. ParticlePropertyObject* posProperty = expectStandardProperty(ParticleProperty::PositionProperty); SimulationCellObject* simCell = expectSimulationCell(); + if(simCell->is2D()) + throwException(tr("The CNA modifier does not support 2d simulation cells.")); // Get particle selection. ParticleProperty* selectionProperty = nullptr; @@ -127,7 +129,7 @@ // Prepare the neighbor list. NearestNeighborFinder neighFinder(MAX_NEIGHBORS); - if(!neighFinder.prepare(positions(), cell(), selection(), this)) + if(!neighFinder.prepare(positions(), cell(), selection(), *this)) return; // Create output storage. @@ -152,7 +154,7 @@ // Prepare the neighbor list. CutoffNeighborFinder neighborListBuilder; - if(!neighborListBuilder.prepare(_cutoff, positions(), cell(), selection(), this)) + if(!neighborListBuilder.prepare(_cutoff, positions(), cell(), selection(), *this)) return; // Create output storage. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/cna/CommonNeighborAnalysisModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/cna/CommonNeighborAnalysisModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/cna/CommonNeighborAnalysisModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/cna/CommonNeighborAnalysisModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COMMON_NEIGHBOR_ANALYSIS_MODIFIER_H -#define __OVITO_COMMON_NEIGHBOR_ANALYSIS_MODIFIER_H +#pragma once + #include #include @@ -107,23 +107,6 @@ /// Constructor. Q_INVOKABLE CommonNeighborAnalysisModifier(DataSet* dataset); - /// \brief Returns the cutoff radius used in the conventional common neighbor analysis. - /// \return The cutoff radius in world units. - /// \sa setCutoff() - FloatType cutoff() const { return _cutoff; } - - /// \brief Sets the cutoff radius used in the conventional common neighbor analysis. - /// \param newCutoff The new cutoff radius in world units. - /// \undoable - /// \sa cutoff() - void setCutoff(FloatType newCutoff) { _cutoff = newCutoff; } - - /// Returns the selected mode of operation. - CNAMode mode() const { return _cnaMode; } - - /// Sets the mode of operation. - void setMode(CNAMode mode) { _cnaMode = mode; } - /// Find all atoms that are nearest neighbors of the given pair of atoms. static int findCommonNeighbors(const NeighborBondArray& neighborArray, int neighborIndex, unsigned int& commonNeighbors, int numNeighbors); @@ -216,10 +199,10 @@ static StructureType determineStructureFixed(CutoffNeighborFinder& neighList, size_t particleIndex, const QVector& typesToIdentify); /// The cutoff radius used for the conventional CNA. - PropertyField _cutoff; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, cutoff, setCutoff); /// Controls how the CNA is performed. - PropertyField _cnaMode; + DECLARE_MODIFIABLE_PROPERTY_FIELD(CNAMode, mode, setMode); /// This stores the computed CNA bond indices. QExplicitlySharedDataPointer _cnaIndicesData; @@ -231,9 +214,6 @@ Q_CLASSINFO("DisplayName", "Common neighbor analysis"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_PROPERTY_FIELD(_cutoff); - DECLARE_PROPERTY_FIELD(_cnaMode); }; OVITO_END_INLINE_NAMESPACE @@ -241,4 +221,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_COMMON_NEIGHBOR_ANALYSIS_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/coordination/CoordinationNumberModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/coordination/CoordinationNumberModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/coordination/CoordinationNumberModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/coordination/CoordinationNumberModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,13 +26,13 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, CoordinationNumberModifier, AsynchronousParticleModifier); -DEFINE_FLAGS_PROPERTY_FIELD(CoordinationNumberModifier, _cutoff, "Cutoff", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(CoordinationNumberModifier, _numberOfBins, "NumberOfBins", PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(CoordinationNumberModifier, _cutoff, "Cutoff radius"); -SET_PROPERTY_FIELD_LABEL(CoordinationNumberModifier, _numberOfBins, "Number of histogram bins"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CoordinationNumberModifier, _cutoff, WorldParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CoordinationNumberModifier, _numberOfBins, IntegerParameterUnit, 4); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CoordinationNumberModifier, AsynchronousParticleModifier); +DEFINE_FLAGS_PROPERTY_FIELD(CoordinationNumberModifier, cutoff, "Cutoff", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(CoordinationNumberModifier, numberOfBins, "NumberOfBins", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(CoordinationNumberModifier, cutoff, "Cutoff radius"); +SET_PROPERTY_FIELD_LABEL(CoordinationNumberModifier, numberOfBins, "Number of histogram bins"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CoordinationNumberModifier, cutoff, WorldParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(CoordinationNumberModifier, numberOfBins, IntegerParameterUnit, 4, 100000); /****************************************************************************** * Constructs the modifier object. @@ -40,8 +40,8 @@ CoordinationNumberModifier::CoordinationNumberModifier(DataSet* dataset) : AsynchronousParticleModifier(dataset), _cutoff(3.2), _numberOfBins(200) { - INIT_PROPERTY_FIELD(CoordinationNumberModifier::_cutoff); - INIT_PROPERTY_FIELD(CoordinationNumberModifier::_numberOfBins); + INIT_PROPERTY_FIELD(cutoff); + INIT_PROPERTY_FIELD(numberOfBins); } /****************************************************************************** @@ -57,6 +57,8 @@ // The number of sampling intervals for the radial distribution function. int rdfSampleCount = std::max(numberOfBins(), 4); + if(rdfSampleCount > 100000) + throwException(tr("Number of histogram bins is too large.")); // Create engine object. Pass all relevant modifier parameters to the engine as well as the input data. return std::make_shared(validityInterval, posProperty->storage(), inputCell->data(), cutoff(), rdfSampleCount); @@ -71,16 +73,16 @@ // Prepare the neighbor list. CutoffNeighborFinder neighborListBuilder; - if(!neighborListBuilder.prepare(_cutoff, positions(), cell(), nullptr, this)) + if(!neighborListBuilder.prepare(_cutoff, positions(), cell(), nullptr, *this)) return; size_t particleCount = positions()->size(); setProgressValue(0); - setProgressRange(particleCount / 1000); + setProgressMaximum(particleCount / 1000); // Perform analysis on each particle in parallel. std::vector workers; - size_t num_threads = Application::instance().idealThreadCount(); + size_t num_threads = Application::instance()->idealThreadCount(); size_t chunkSize = particleCount / num_threads; size_t startIndex = 0; size_t endIndex = chunkSize; @@ -182,8 +184,8 @@ AsynchronousParticleModifier::propertyChanged(field); // Recompute modifier results when the parameters have been changed. - if(field == PROPERTY_FIELD(CoordinationNumberModifier::_cutoff) || - field == PROPERTY_FIELD(CoordinationNumberModifier::_numberOfBins)) + if(field == PROPERTY_FIELD(cutoff) || + field == PROPERTY_FIELD(numberOfBins)) invalidateCachedResults(); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/coordination/CoordinationNumberModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/coordination/CoordinationNumberModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/coordination/CoordinationNumberModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/coordination/CoordinationNumberModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COORDINATION_NUMBER_MODIFIER_H -#define __OVITO_COORDINATION_NUMBER_MODIFIER_H +#pragma once + #include #include @@ -39,24 +39,12 @@ /// Constructor. Q_INVOKABLE CoordinationNumberModifier(DataSet* dataset); - /// Returns the cutoff radius used to build the neighbor lists for the analysis. - FloatType cutoff() const { return _cutoff; } - - /// \brief Sets the cutoff radius used to build the neighbor lists for the analysis. - void setCutoff(FloatType newCutoff) { _cutoff = newCutoff; } - /// Returns the X coordinates of the RDF data points. const QVector& rdfX() const { return _rdfX; } /// Returns the Y coordinates of the RDF data points. const QVector& rdfY() const { return _rdfY; } - /// Returns the number of bins in the computed RDF histogram. - int numberOfBins() const { return _numberOfBins; } - - /// Sets the number of bins in the computed RDF histogram. - void setNumberOfBins(int n) { _numberOfBins = n; } - private: /// Computes the modifier's results. @@ -118,10 +106,10 @@ QExplicitlySharedDataPointer _coordinationNumbers; /// Controls the cutoff radius for the neighbor lists. - PropertyField _cutoff; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, cutoff, setCutoff); /// Controls the number of RDF histogram bins. - PropertyField _numberOfBins; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, numberOfBins, setNumberOfBins); /// The X coordinates of the RDF data points. QVector _rdfX; @@ -134,9 +122,6 @@ Q_CLASSINFO("DisplayName", "Coordination analysis"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_PROPERTY_FIELD(_cutoff); - DECLARE_PROPERTY_FIELD(_numberOfBins); }; OVITO_END_INLINE_NAMESPACE @@ -144,4 +129,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_COORDINATION_NUMBER_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/diamond/IdentifyDiamondModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/diamond/IdentifyDiamondModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/diamond/IdentifyDiamondModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/diamond/IdentifyDiamondModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, IdentifyDiamondModifier, StructureIdentificationModifier); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(IdentifyDiamondModifier, StructureIdentificationModifier); /****************************************************************************** * Constructs the modifier object. @@ -55,6 +55,8 @@ // Get modifier input. ParticlePropertyObject* posProperty = expectStandardProperty(ParticleProperty::PositionProperty); SimulationCellObject* simCell = expectSimulationCell(); + if(simCell->is2D()) + throwException(tr("The modifier does not support 2d simulation cells.")); // Get particle selection. ParticleProperty* selectionProperty = nullptr; @@ -74,7 +76,7 @@ // Prepare the neighbor list builder. NearestNeighborFinder neighborFinder(4); - if(!neighborFinder.prepare(positions(), cell(), selection(), this)) + if(!neighborFinder.prepare(positions(), cell(), selection(), *this)) return; // This data structure stores information about a single neighbor. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/diamond/IdentifyDiamondModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/diamond/IdentifyDiamondModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/diamond/IdentifyDiamondModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/diamond/IdentifyDiamondModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_IDENTIFY_DIAMOND_MODIFIER_H -#define __OVITO_IDENTIFY_DIAMOND_MODIFIER_H +#pragma once + #include #include @@ -88,4 +88,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_IDENTIFY_DIAMOND_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/displacements/CalculateDisplacementsModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/displacements/CalculateDisplacementsModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/displacements/CalculateDisplacementsModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/displacements/CalculateDisplacementsModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,41 +28,41 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, CalculateDisplacementsModifier, ParticleModifier); -DEFINE_FLAGS_REFERENCE_FIELD(CalculateDisplacementsModifier, _referenceObject, "Reference Configuration", DataObject, PROPERTY_FIELD_NO_SUB_ANIM); -DEFINE_PROPERTY_FIELD(CalculateDisplacementsModifier, _referenceShown, "ShowReferenceConfiguration"); -DEFINE_FLAGS_PROPERTY_FIELD(CalculateDisplacementsModifier, _eliminateCellDeformation, "EliminateCellDeformation", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(CalculateDisplacementsModifier, _assumeUnwrappedCoordinates, "AssumeUnwrappedCoordinates"); -DEFINE_PROPERTY_FIELD(CalculateDisplacementsModifier, _useReferenceFrameOffset, "UseReferenceFrameOffet"); -DEFINE_PROPERTY_FIELD(CalculateDisplacementsModifier, _referenceFrameNumber, "ReferenceFrameNumber"); -DEFINE_FLAGS_PROPERTY_FIELD(CalculateDisplacementsModifier, _referenceFrameOffset, "ReferenceFrameOffset", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_REFERENCE_FIELD(CalculateDisplacementsModifier, _vectorDisplay, "VectorDisplay", VectorDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, _referenceObject, "Reference Configuration"); -SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, _referenceShown, "Show reference configuration"); -SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, _eliminateCellDeformation, "Eliminate homogeneous cell deformation"); -SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, _assumeUnwrappedCoordinates, "Assume unwrapped coordinates"); -SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, _useReferenceFrameOffset, "Use reference frame offset"); -SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, _referenceFrameNumber, "Reference frame number"); -SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, _referenceFrameOffset, "Reference frame offset"); -SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, _vectorDisplay, "Vector display"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CalculateDisplacementsModifier, _referenceFrameNumber, IntegerParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CalculateDisplacementsModifier, ParticleModifier); +DEFINE_FLAGS_REFERENCE_FIELD(CalculateDisplacementsModifier, referenceConfiguration, "Reference Configuration", DataObject, PROPERTY_FIELD_NO_SUB_ANIM); +DEFINE_PROPERTY_FIELD(CalculateDisplacementsModifier, referenceShown, "ShowReferenceConfiguration"); +DEFINE_FLAGS_PROPERTY_FIELD(CalculateDisplacementsModifier, affineMapping, "AffineMapping", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(CalculateDisplacementsModifier, assumeUnwrappedCoordinates, "AssumeUnwrappedCoordinates"); +DEFINE_PROPERTY_FIELD(CalculateDisplacementsModifier, useReferenceFrameOffset, "UseReferenceFrameOffet"); +DEFINE_PROPERTY_FIELD(CalculateDisplacementsModifier, referenceFrameNumber, "ReferenceFrameNumber"); +DEFINE_FLAGS_PROPERTY_FIELD(CalculateDisplacementsModifier, referenceFrameOffset, "ReferenceFrameOffset", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(CalculateDisplacementsModifier, vectorDisplay, "VectorDisplay", VectorDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, referenceConfiguration, "Reference Configuration"); +SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, referenceShown, "Show reference configuration"); +SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, affineMapping, "Affine mapping"); +SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, assumeUnwrappedCoordinates, "Assume unwrapped coordinates"); +SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, useReferenceFrameOffset, "Use reference frame offset"); +SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, referenceFrameNumber, "Reference frame number"); +SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, referenceFrameOffset, "Reference frame offset"); +SET_PROPERTY_FIELD_LABEL(CalculateDisplacementsModifier, vectorDisplay, "Vector display"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CalculateDisplacementsModifier, referenceFrameNumber, IntegerParameterUnit, 0); /****************************************************************************** * Constructs the modifier object. ******************************************************************************/ CalculateDisplacementsModifier::CalculateDisplacementsModifier(DataSet* dataset) : ParticleModifier(dataset), - _referenceShown(false), _eliminateCellDeformation(false), + _referenceShown(false), _affineMapping(NO_MAPPING), _useReferenceFrameOffset(false), _referenceFrameNumber(0), _referenceFrameOffset(-1), _assumeUnwrappedCoordinates(false) { - INIT_PROPERTY_FIELD(CalculateDisplacementsModifier::_referenceObject); - INIT_PROPERTY_FIELD(CalculateDisplacementsModifier::_referenceShown); - INIT_PROPERTY_FIELD(CalculateDisplacementsModifier::_eliminateCellDeformation); - INIT_PROPERTY_FIELD(CalculateDisplacementsModifier::_assumeUnwrappedCoordinates); - INIT_PROPERTY_FIELD(CalculateDisplacementsModifier::_useReferenceFrameOffset); - INIT_PROPERTY_FIELD(CalculateDisplacementsModifier::_referenceFrameNumber); - INIT_PROPERTY_FIELD(CalculateDisplacementsModifier::_referenceFrameOffset); - INIT_PROPERTY_FIELD(CalculateDisplacementsModifier::_vectorDisplay); + INIT_PROPERTY_FIELD(referenceConfiguration); + INIT_PROPERTY_FIELD(referenceShown); + INIT_PROPERTY_FIELD(affineMapping); + INIT_PROPERTY_FIELD(assumeUnwrappedCoordinates); + INIT_PROPERTY_FIELD(useReferenceFrameOffset); + INIT_PROPERTY_FIELD(referenceFrameNumber); + INIT_PROPERTY_FIELD(referenceFrameOffset); + INIT_PROPERTY_FIELD(vectorDisplay); // Create the file source object, which will be responsible for loading // and storing the reference configuration. @@ -75,25 +75,44 @@ setReferenceConfiguration(linkedFileObj); // Create display object for vectors. - _vectorDisplay = new VectorDisplay(dataset); - _vectorDisplay->setObjectTitle(tr("Displacements")); + setVectorDisplay(new VectorDisplay(dataset)); + vectorDisplay()->setObjectTitle(tr("Displacements")); // Don't show vectors by default, because too many vectors can make the // program freeze. User has to enable the display manually. - _vectorDisplay->setEnabled(false); + vectorDisplay()->setEnabled(false); // Configure vector display such that arrows point from the reference particle positions // to the current particle positions. - _vectorDisplay->setReverseArrowDirection(false); - _vectorDisplay->setArrowPosition(VectorDisplay::Head); + vectorDisplay()->setReverseArrowDirection(false); + vectorDisplay()->setArrowPosition(VectorDisplay::Head); } + +/****************************************************************************** +* Allows the object to parse the serialized contents of a property field in a +* custom way. +******************************************************************************/ +bool CalculateDisplacementsModifier::loadPropertyFieldFromStream(ObjectLoadStream& stream, const ObjectLoadStream::SerializedPropertyField& serializedField) +{ + // This is for backward compatibility with OVITO 2.8.2: + if(serializedField.identifier == "EliminateCellDeformation" && serializedField.definingClass == &CalculateDisplacementsModifier::OOType) { + bool eliminateEnabled; + stream >> eliminateEnabled; + if(eliminateEnabled) + setAffineMapping(TO_REFERENCE_CELL); + return true; + } + + return ParticleModifier::loadPropertyFieldFromStream(stream, serializedField); +} + /****************************************************************************** * Handles reference events sent by reference targets of this object. ******************************************************************************/ bool CalculateDisplacementsModifier::referenceEvent(RefTarget* source, ReferenceEvent* event) { // Do not propagate messages sent by the attached display object. - if(source == _vectorDisplay) + if(source == vectorDisplay()) return false; return ParticleModifier::referenceEvent(source, event); @@ -110,21 +129,21 @@ // What is the reference frame number to use? int referenceFrame; - if(_useReferenceFrameOffset) { + if(useReferenceFrameOffset()) { // Determine the current frame, preferably from the attributes stored with the pipeline flow state. // If the "SourceFrame" attribute is not present, infer it from the current animation time. int currentFrame = input().attributes().value(QStringLiteral("SourceFrame"), dataset()->animationSettings()->timeToFrame(time)).toInt(); // Use frame offset relative to current configuration. - referenceFrame = currentFrame + _referenceFrameOffset; + referenceFrame = currentFrame + referenceFrameOffset(); // Results are only valid for current frame. validityInterval.intersect(time); } else { // Always use the same, user-specified frame as reference configuration. - referenceFrame = _referenceFrameNumber; + referenceFrame = referenceFrameNumber(); } // Get the reference configuration. @@ -136,7 +155,7 @@ refState = fileSource->requestFrame(referenceFrame); } } - else refState = referenceConfiguration()->evaluate(dataset()->animationSettings()->frameToTime(referenceFrame)); + else refState = referenceConfiguration()->evaluateImmediately(PipelineEvalRequest(dataset()->animationSettings()->frameToTime(referenceFrame), false)); // Make sure the obtained reference configuration is valid and ready to use. if(refState.status().type() == PipelineStatus::Error) @@ -247,7 +266,7 @@ // Compute inverse cell transformation. AffineTransformation simCellInv; AffineTransformation simCellRefInv; - if(eliminateCellDeformation()) { + if(affineMapping() != NO_MAPPING) { if(std::abs(simCell.determinant()) < FLOATTYPE_EPSILON || std::abs(simCellRef.determinant()) < FLOATTYPE_EPSILON) throwException(tr("Simulation cell is degenerate in either the deformed or the reference configuration.")); @@ -262,8 +281,9 @@ Vector3* d_begin = displacementProperty->dataVector3(); FloatType* dmag_begin = displacementMagnitudeProperty->dataFloat(); auto index_begin = indexToIndexMap.begin(); - if(eliminateCellDeformation()) { - parallelForChunks(displacementProperty->size(), [d_begin, dmag_begin, u_begin, index_begin, u0, unwrap, pbc, simCellRef, simCellInv, simCellRefInv] (size_t startIndex, size_t count) { + if(affineMapping() != NO_MAPPING) { + auto affMapping = affineMapping(); + parallelForChunks(displacementProperty->size(), [d_begin, dmag_begin, affMapping, u_begin, index_begin, u0, unwrap, pbc, simCell, simCellRef, simCellInv, simCellRefInv] (size_t startIndex, size_t count) { Vector3* d = d_begin + startIndex; FloatType* dmag = dmag_begin + startIndex; const Point3* u = u_begin + startIndex; @@ -275,11 +295,14 @@ if(unwrap) { for(int k = 0; k < 3; k++) { if(!pbc[k]) continue; - if(delta[k] > 0.5) delta[k] -= 1.0; - else if(delta[k] < -0.5) delta[k] += 1.0; + if(delta[k] > FloatType(0.5)) delta[k] -= FloatType(1); + else if(delta[k] < FloatType(-0.5)) delta[k] += FloatType(1); } } - *d = simCellRef * delta; + if(affMapping == TO_REFERENCE_CELL) + *d = simCellRef * delta; + else + *d = simCell * delta; *dmag = d->length(); } }); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/displacements/CalculateDisplacementsModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/displacements/CalculateDisplacementsModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/displacements/CalculateDisplacementsModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/displacements/CalculateDisplacementsModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CALCULATE_DISPLACEMENTS_MODIFIER_H -#define __OVITO_CALCULATE_DISPLACEMENTS_MODIFIER_H +#pragma once + #include #include @@ -36,98 +36,52 @@ { public: + enum AffineMappingType { NO_MAPPING = 0, TO_REFERENCE_CELL = 1, TO_CURRENT_CELL = 2 }; + Q_ENUMS(AffineMappingType); + /// Constructor. Q_INVOKABLE CalculateDisplacementsModifier(DataSet* dataset); - /// Returns the object that contains the reference configuration of the particles - /// used for calculating the displacement vectors. - DataObject* referenceConfiguration() const { return _referenceObject; } - - /// Sets the object that contains the reference configuration of the particles - /// used for calculating the displacement vectors. - void setReferenceConfiguration(DataObject* refConf) { _referenceObject = refConf; } - - /// Returns true if the homogeneous deformation of the simulation cell is eliminated from the calculated displacement vectors. - bool eliminateCellDeformation() const { return _eliminateCellDeformation; } - - /// Sets whether the homogeneous deformation of the simulation cell is eliminated from the calculated displacement vectors. - void setEliminateCellDeformation(bool enable) { _eliminateCellDeformation = enable; } - - /// Returns true if we assume the particle coordinates are unwrapped when calculating the displacement vectors. - bool assumeUnwrappedCoordinates() const { return _assumeUnwrappedCoordinates; } - - /// Sets we assume the particle coordinates are unwrapped when calculating the displacement vectors. - void setAssumeUnwrappedCoordinates(bool enable) { _assumeUnwrappedCoordinates = enable; } - - /// Returns whether to use a reference frame relative to current frame. - bool useReferenceFrameOffset() const { return _useReferenceFrameOffset; } - - /// Sets whether to use a reference frame relative to current frame. - void setUseReferenceFrameOffset(bool useOffset) { _useReferenceFrameOffset = useOffset; } - - /// Returns the absolute frame number from reference file to use when calculating displacement vectors. - int referenceFrameNumber() const { return _referenceFrameNumber; } - - /// Sets the absolute frame number from reference file to use when calculating displacement vectors. - void setReferenceFrameNumber(int frame) { _referenceFrameNumber = frame; } - - /// Returns the relative frame offset to use. - int referenceFrameOffset() const { return _referenceFrameOffset; } - - /// Sets the relative frame offset to use. - void setReferenceFrameOffset(int frameOffset) { _referenceFrameOffset = frameOffset; } - - /// Returns the vector display object, which is responsible for rendering the computed displacement vectors. - VectorDisplay* vectorDisplay() const { return _vectorDisplay; } - protected: /// Handles reference events sent by reference targets of this object. virtual bool referenceEvent(RefTarget* source, ReferenceEvent* event) override; + /// Allows the object to parse the serialized contents of a property field in a custom way. + virtual bool loadPropertyFieldFromStream(ObjectLoadStream& stream, const ObjectLoadStream::SerializedPropertyField& serializedField) override; + /// Modifies the particle object. virtual PipelineStatus modifyParticles(TimePoint time, TimeInterval& validityInterval) override; /// The reference configuration. - ReferenceField _referenceObject; + DECLARE_MODIFIABLE_REFERENCE_FIELD(DataObject, referenceConfiguration, setReferenceConfiguration); /// Controls the whether the reference configuration is shown instead of the current configuration. - PropertyField _referenceShown; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, referenceShown, setReferenceShown); /// Controls the whether the homogeneous deformation of the simulation cell is eliminated from the calculated displacement vectors. - PropertyField _eliminateCellDeformation; + DECLARE_MODIFIABLE_PROPERTY_FIELD(AffineMappingType, affineMapping, setAffineMapping); /// Controls the whether we assume the particle coordinates are unwrapped when calculating the displacement vectors. - PropertyField _assumeUnwrappedCoordinates; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, assumeUnwrappedCoordinates, setAssumeUnwrappedCoordinates); /// Specify reference frame relative to current frame. - PropertyField _useReferenceFrameOffset; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, useReferenceFrameOffset, setUseReferenceFrameOffset); /// Absolute frame number from reference file to use when calculating displacement vectors. - PropertyField _referenceFrameNumber; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, referenceFrameNumber, setReferenceFrameNumber); /// Relative frame offset for reference coordinates. - PropertyField _referenceFrameOffset; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, referenceFrameOffset, setReferenceFrameOffset); /// The vector display object for rendering the displacement vectors. - ReferenceField _vectorDisplay; - -private: - + DECLARE_MODIFIABLE_REFERENCE_FIELD(VectorDisplay, vectorDisplay, setVectorDisplay); + Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Displacement vectors"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_REFERENCE_FIELD(_referenceObject); - DECLARE_PROPERTY_FIELD(_referenceShown); - DECLARE_PROPERTY_FIELD(_eliminateCellDeformation); - DECLARE_PROPERTY_FIELD(_assumeUnwrappedCoordinates); - DECLARE_PROPERTY_FIELD(_useReferenceFrameOffset); - DECLARE_PROPERTY_FIELD(_referenceFrameNumber); - DECLARE_PROPERTY_FIELD(_referenceFrameOffset); - DECLARE_REFERENCE_FIELD(_vectorDisplay); }; OVITO_END_INLINE_NAMESPACE @@ -135,4 +89,5 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CALCULATE_DISPLACEMENTS_MODIFIER_H +Q_DECLARE_METATYPE(Ovito::Particles::CalculateDisplacementsModifier::AffineMappingType); +Q_DECLARE_TYPEINFO(Ovito::Particles::CalculateDisplacementsModifier::AffineMappingType, Q_PRIMITIVE_TYPE); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/histogram/HistogramModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/histogram/HistogramModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/histogram/HistogramModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/histogram/HistogramModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,32 +26,36 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, HistogramModifier, ParticleModifier); -DEFINE_FLAGS_PROPERTY_FIELD(HistogramModifier, _numberOfBins, "NumberOfBins", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(HistogramModifier, _selectInRange, "SelectInRange"); -DEFINE_FLAGS_PROPERTY_FIELD(HistogramModifier, _selectionRangeStart, "SelectionRangeStart", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(HistogramModifier, _selectionRangeEnd, "SelectionRangeEnd", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(HistogramModifier, _fixXAxisRange, "FixXAxisRange"); -DEFINE_FLAGS_PROPERTY_FIELD(HistogramModifier, _xAxisRangeStart, "XAxisRangeStart", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(HistogramModifier, _xAxisRangeEnd, "XAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(HistogramModifier, _fixYAxisRange, "FixYAxisRange"); -DEFINE_FLAGS_PROPERTY_FIELD(HistogramModifier, _yAxisRangeStart, "YAxisRangeStart", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(HistogramModifier, _yAxisRangeEnd, "YAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(HistogramModifier, _sourceProperty, "SourceProperty"); -DEFINE_PROPERTY_FIELD(HistogramModifier, _onlySelected, "OnlySelected"); -SET_PROPERTY_FIELD_LABEL(HistogramModifier, _numberOfBins, "Number of histogram bins"); -SET_PROPERTY_FIELD_LABEL(HistogramModifier, _selectInRange, "Select particles in range"); -SET_PROPERTY_FIELD_LABEL(HistogramModifier, _selectionRangeStart, "Selection range start"); -SET_PROPERTY_FIELD_LABEL(HistogramModifier, _selectionRangeEnd, "Selection range end"); -SET_PROPERTY_FIELD_LABEL(HistogramModifier, _fixXAxisRange, "Fix x-range"); -SET_PROPERTY_FIELD_LABEL(HistogramModifier, _xAxisRangeStart, "X-range start"); -SET_PROPERTY_FIELD_LABEL(HistogramModifier, _xAxisRangeEnd, "X-range end"); -SET_PROPERTY_FIELD_LABEL(HistogramModifier, _fixYAxisRange, "Fix y-range"); -SET_PROPERTY_FIELD_LABEL(HistogramModifier, _yAxisRangeStart, "Y-range start"); -SET_PROPERTY_FIELD_LABEL(HistogramModifier, _yAxisRangeEnd, "Y-range end"); -SET_PROPERTY_FIELD_LABEL(HistogramModifier, _sourceProperty, "Source property"); -SET_PROPERTY_FIELD_LABEL(HistogramModifier, _onlySelected, "Use only selected particles"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(HistogramModifier, _numberOfBins, IntegerParameterUnit, 1); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(HistogramModifier, ParticleModifier); +DEFINE_FLAGS_PROPERTY_FIELD(HistogramModifier, numberOfBins, "NumberOfBins", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(HistogramModifier, selectInRange, "SelectInRange"); +DEFINE_FLAGS_PROPERTY_FIELD(HistogramModifier, selectionRangeStart, "SelectionRangeStart", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(HistogramModifier, selectionRangeEnd, "SelectionRangeEnd", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(HistogramModifier, fixXAxisRange, "FixXAxisRange"); +DEFINE_FLAGS_PROPERTY_FIELD(HistogramModifier, xAxisRangeStart, "XAxisRangeStart", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(HistogramModifier, xAxisRangeEnd, "XAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(HistogramModifier, fixYAxisRange, "FixYAxisRange"); +DEFINE_FLAGS_PROPERTY_FIELD(HistogramModifier, yAxisRangeStart, "YAxisRangeStart", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(HistogramModifier, yAxisRangeEnd, "YAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(HistogramModifier, sourceParticleProperty, "SourceProperty"); +DEFINE_PROPERTY_FIELD(HistogramModifier, sourceBondProperty, "SourceBondProperty"); +DEFINE_PROPERTY_FIELD(HistogramModifier, onlySelected, "OnlySelected"); +DEFINE_PROPERTY_FIELD(HistogramModifier, dataSourceType, "DataSourceType"); +SET_PROPERTY_FIELD_LABEL(HistogramModifier, numberOfBins, "Number of histogram bins"); +SET_PROPERTY_FIELD_LABEL(HistogramModifier, selectInRange, "Select value range"); +SET_PROPERTY_FIELD_LABEL(HistogramModifier, selectionRangeStart, "Selection range start"); +SET_PROPERTY_FIELD_LABEL(HistogramModifier, selectionRangeEnd, "Selection range end"); +SET_PROPERTY_FIELD_LABEL(HistogramModifier, fixXAxisRange, "Fix x-range"); +SET_PROPERTY_FIELD_LABEL(HistogramModifier, xAxisRangeStart, "X-range start"); +SET_PROPERTY_FIELD_LABEL(HistogramModifier, xAxisRangeEnd, "X-range end"); +SET_PROPERTY_FIELD_LABEL(HistogramModifier, fixYAxisRange, "Fix y-range"); +SET_PROPERTY_FIELD_LABEL(HistogramModifier, yAxisRangeStart, "Y-range start"); +SET_PROPERTY_FIELD_LABEL(HistogramModifier, yAxisRangeEnd, "Y-range end"); +SET_PROPERTY_FIELD_LABEL(HistogramModifier, sourceParticleProperty, "Source property"); +SET_PROPERTY_FIELD_LABEL(HistogramModifier, sourceBondProperty, "Source property"); +SET_PROPERTY_FIELD_LABEL(HistogramModifier, onlySelected, "Use only selected particles/bonds"); +SET_PROPERTY_FIELD_LABEL(HistogramModifier, dataSourceType, "Source type"); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(HistogramModifier, numberOfBins, IntegerParameterUnit, 1, 100000); /****************************************************************************** * Constructs the modifier object. @@ -61,20 +65,22 @@ _selectionRangeStart(0), _selectionRangeEnd(1), _fixXAxisRange(false), _xAxisRangeStart(0), _xAxisRangeEnd(0), _fixYAxisRange(false), _yAxisRangeStart(0), _yAxisRangeEnd(0), - _onlySelected(false) + _onlySelected(false), _dataSourceType(Particles) { - INIT_PROPERTY_FIELD(HistogramModifier::_numberOfBins); - INIT_PROPERTY_FIELD(HistogramModifier::_selectInRange); - INIT_PROPERTY_FIELD(HistogramModifier::_selectionRangeStart); - INIT_PROPERTY_FIELD(HistogramModifier::_selectionRangeEnd); - INIT_PROPERTY_FIELD(HistogramModifier::_fixXAxisRange); - INIT_PROPERTY_FIELD(HistogramModifier::_xAxisRangeStart); - INIT_PROPERTY_FIELD(HistogramModifier::_xAxisRangeEnd); - INIT_PROPERTY_FIELD(HistogramModifier::_fixYAxisRange); - INIT_PROPERTY_FIELD(HistogramModifier::_yAxisRangeStart); - INIT_PROPERTY_FIELD(HistogramModifier::_yAxisRangeEnd); - INIT_PROPERTY_FIELD(HistogramModifier::_sourceProperty); - INIT_PROPERTY_FIELD(HistogramModifier::_onlySelected); + INIT_PROPERTY_FIELD(numberOfBins); + INIT_PROPERTY_FIELD(selectInRange); + INIT_PROPERTY_FIELD(selectionRangeStart); + INIT_PROPERTY_FIELD(selectionRangeEnd); + INIT_PROPERTY_FIELD(fixXAxisRange); + INIT_PROPERTY_FIELD(xAxisRangeStart); + INIT_PROPERTY_FIELD(xAxisRangeEnd); + INIT_PROPERTY_FIELD(fixYAxisRange); + INIT_PROPERTY_FIELD(yAxisRangeStart); + INIT_PROPERTY_FIELD(yAxisRangeEnd); + INIT_PROPERTY_FIELD(sourceParticleProperty); + INIT_PROPERTY_FIELD(sourceBondProperty); + INIT_PROPERTY_FIELD(onlySelected); + INIT_PROPERTY_FIELD(dataSourceType); } /****************************************************************************** @@ -86,8 +92,8 @@ ParticleModifier::initializeModifier(pipeline, modApp); // Use the first available particle property from the input state as data source when the modifier is newly created. - if(sourceProperty().isNull()) { - PipelineFlowState input = pipeline->evaluatePipeline(dataset()->animationSettings()->time(), modApp, false); + if(sourceParticleProperty().isNull()) { + PipelineFlowState input = getModifierInput(modApp); ParticlePropertyReference bestProperty; for(DataObject* o : input.objects()) { ParticlePropertyObject* property = dynamic_object_cast(o); @@ -96,9 +102,23 @@ } } if(!bestProperty.isNull()) { - setSourceProperty(bestProperty); + setSourceParticleProperty(bestProperty); } } + + // Select the first available bond property from the input by default. + if(sourceBondProperty().isNull()) { + PipelineFlowState input = getModifierInput(modApp); + BondPropertyReference bestProperty; + for(DataObject* o : input.objects()) { + BondPropertyObject* property = dynamic_object_cast(o); + if(property && (property->dataType() == qMetaTypeId() || property->dataType() == qMetaTypeId())) { + bestProperty = BondPropertyReference(property, (property->componentCount() > 1) ? 0 : -1); + } + } + if(!bestProperty.isNull()) + setSourceBondProperty(bestProperty); + } } /****************************************************************************** @@ -110,34 +130,67 @@ std::fill(_histogramData.begin(), _histogramData.end(), 0); // Get the source property. - if(sourceProperty().isNull()) - throwException(tr("Select a particle property first.")); - ParticlePropertyObject* property = sourceProperty().findInState(input()); - if(!property) - throwException(tr("The selected particle property with the name '%1' does not exist.").arg(sourceProperty().name())); - if(sourceProperty().vectorComponent() >= (int)property->componentCount()) - throwException(tr("The selected vector component is out of range. The particle property '%1' contains only %2 values per particle.").arg(sourceProperty().name()).arg(property->componentCount())); + PropertyBase* property; + PropertyBase* inputSelection = nullptr; + PropertyBase* outputSelection = nullptr; + ParticlePropertyObject* outputParticleSelectionObj = nullptr; + BondPropertyObject* outputBondSelectionObj = nullptr; + size_t vecComponent; + if(dataSourceType() == Particles) { + if(sourceParticleProperty().isNull()) + throwException(tr("Select a particle property first.")); + ParticlePropertyObject* propertyObj = sourceParticleProperty().findInState(input()); + if(!propertyObj) + throwException(tr("The selected particle property with the name '%1' does not exist.").arg(sourceParticleProperty().name())); + if(sourceParticleProperty().vectorComponent() >= (int)propertyObj->componentCount()) + throwException(tr("The selected vector component is out of range. The particle property '%1' contains only %2 values per particle.").arg(sourceParticleProperty().name()).arg(propertyObj->componentCount())); + property = propertyObj->storage(); + vecComponent = std::max(0, sourceParticleProperty().vectorComponent()); + + // Get the particle selection property if enabled by the user. + if(onlySelected()) { + ParticlePropertyObject* selPropertyObj = expectStandardProperty(ParticleProperty::SelectionProperty); + OVITO_ASSERT(selPropertyObj->size() == property->size()); + inputSelection = selPropertyObj->storage(); + } - size_t vecComponent = std::max(0, sourceProperty().vectorComponent()); - size_t vecComponentCount = property->componentCount(); + // Create selection property for output. + if(selectInRange()) { + outputParticleSelectionObj = outputStandardProperty(ParticleProperty::SelectionProperty, true); + outputSelection = outputParticleSelectionObj->modifiableStorage(); + } + } + else { + if(sourceBondProperty().isNull()) + throwException(tr("Select a bond property first.")); + BondPropertyObject* propertyObj = sourceBondProperty().findInState(input()); + if(!propertyObj) + throwException(tr("The selected bond property with the name '%1' does not exist.").arg(sourceBondProperty().name())); + if(sourceBondProperty().vectorComponent() >= (int)propertyObj->componentCount()) + throwException(tr("The selected vector component is out of range. The bond property '%1' contains only %2 values per bond.").arg(sourceBondProperty().name()).arg(propertyObj->componentCount())); + property = propertyObj->storage(); + vecComponent = std::max(0, sourceBondProperty().vectorComponent()); + + // Get the bond selection property if enabled by the user. + if(onlySelected()) { + BondPropertyObject* selPropertyObj = expectStandardBondProperty(BondProperty::SelectionProperty); + OVITO_ASSERT(selPropertyObj->size() == property->size()); + inputSelection = selPropertyObj->storage(); + } - // Get input selection. - ParticleProperty* inputSelectionProperty = nullptr; - if(onlySelected()) { - inputSelectionProperty = expectStandardProperty(ParticleProperty::SelectionProperty)->storage(); - OVITO_ASSERT(inputSelectionProperty->size() == property->size()); + // Create selection property for output. + if(selectInRange()) { + outputBondSelectionObj = outputStandardBondProperty(BondProperty::SelectionProperty, true); + outputSelection = outputBondSelectionObj->modifiableStorage(); + } } + size_t vecComponentCount = property->componentCount(); // Create selection property for output. - ParticlePropertyObject* outputSelectionProperty = nullptr; FloatType selectionRangeStart = _selectionRangeStart; FloatType selectionRangeEnd = _selectionRangeEnd; + if(selectionRangeStart > selectionRangeEnd) std::swap(selectionRangeStart, selectionRangeEnd); size_t numSelected = 0; - if(selectInRange()) { - outputSelectionProperty = outputStandardProperty(ParticleProperty::SelectionProperty, true); - if(selectionRangeStart > selectionRangeEnd) - std::swap(selectionRangeStart, selectionRangeEnd); - } double intervalStart = _xAxisRangeStart; double intervalEnd = _xAxisRangeEnd; @@ -150,7 +203,7 @@ if(!fixXAxisRange()) { intervalStart = std::numeric_limits::max(); intervalEnd = std::numeric_limits::lowest(); - const int* sel = inputSelectionProperty ? inputSelectionProperty->constDataInt() : nullptr; + const int* sel = inputSelection ? inputSelection->constDataInt() : nullptr; for(auto v = v_begin; v != v_end; v += vecComponentCount) { if(sel && !*sel++) continue; if(*v < intervalStart) intervalStart = *v; @@ -160,7 +213,7 @@ // Perform binning. if(intervalEnd > intervalStart) { FloatType binSize = (intervalEnd - intervalStart) / _histogramData.size(); - const int* sel = inputSelectionProperty ? inputSelectionProperty->constDataInt() : nullptr; + const int* sel = inputSelection ? inputSelection->constDataInt() : nullptr; for(auto v = v_begin; v != v_end; v += vecComponentCount) { if(sel && !*sel++) continue; if(*v < intervalStart || *v > intervalEnd) continue; @@ -169,16 +222,16 @@ } } else { - if(!inputSelectionProperty) + if(!inputSelection) _histogramData[0] = property->size(); else - _histogramData[0] = property->size() - std::count(inputSelectionProperty->constDataInt(), inputSelectionProperty->constDataInt() + inputSelectionProperty->size(), 0); + _histogramData[0] = property->size() - std::count(inputSelection->constDataInt(), inputSelection->constDataInt() + inputSelection->size(), 0); } - if(outputSelectionProperty) { - OVITO_ASSERT(outputSelectionProperty->size() == property->size()); - int* s = outputSelectionProperty->dataInt(); - int* s_end = s + outputSelectionProperty->size(); - const int* sel = inputSelectionProperty ? inputSelectionProperty->constDataInt() : nullptr; + if(outputSelection) { + OVITO_ASSERT(outputSelection->size() == property->size()); + int* s = outputSelection->dataInt(); + int* s_end = s + outputSelection->size(); + const int* sel = inputSelection ? inputSelection->constDataInt() : nullptr; for(auto v = v_begin; v != v_end; v += vecComponentCount, ++s) { if((!sel || *sel++) && *v >= selectionRangeStart && *v <= selectionRangeEnd) { *s = 1; @@ -195,7 +248,7 @@ if(!fixXAxisRange()) { intervalStart = std::numeric_limits::max(); intervalEnd = std::numeric_limits::lowest(); - const int* sel = inputSelectionProperty ? inputSelectionProperty->constDataInt() : nullptr; + const int* sel = inputSelection ? inputSelection->constDataInt() : nullptr; for(auto v = v_begin; v != v_end; v += vecComponentCount) { if(sel && !*sel++) continue; if(*v < intervalStart) intervalStart = *v; @@ -205,7 +258,7 @@ // Perform binning. if(intervalEnd > intervalStart) { FloatType binSize = (intervalEnd - intervalStart) / _histogramData.size(); - const int* sel = inputSelectionProperty ? inputSelectionProperty->constDataInt() : nullptr; + const int* sel = inputSelection ? inputSelection->constDataInt() : nullptr; for(auto v = v_begin; v != v_end; v += vecComponentCount) { if(sel && !*sel++) continue; if(*v < intervalStart || *v > intervalEnd) continue; @@ -214,16 +267,16 @@ } } else { - if(!inputSelectionProperty) + if(!inputSelection) _histogramData[0] = property->size(); else - _histogramData[0] = property->size() - std::count(inputSelectionProperty->constDataInt(), inputSelectionProperty->constDataInt() + inputSelectionProperty->size(), 0); + _histogramData[0] = property->size() - std::count(inputSelection->constDataInt(), inputSelection->constDataInt() + inputSelection->size(), 0); } - if(outputSelectionProperty) { - OVITO_ASSERT(outputSelectionProperty->size() == property->size()); - int* s = outputSelectionProperty->dataInt(); - int* s_end = s + outputSelectionProperty->size(); - const int* sel = inputSelectionProperty ? inputSelectionProperty->constDataInt() : nullptr; + if(outputSelection) { + OVITO_ASSERT(outputSelection->size() == property->size()); + int* s = outputSelection->dataInt(); + int* s_end = s + outputSelection->size(); + const int* sel = inputSelection ? inputSelection->constDataInt() : nullptr; for(auto v = v_begin; v != v_end; v += vecComponentCount, ++s) { if((!sel || *sel++) && *v >= selectionRangeStart && *v <= selectionRangeEnd) { *s = 1; @@ -239,17 +292,19 @@ } QString statusMessage; - if(outputSelectionProperty) { - outputSelectionProperty->changed(); - statusMessage += tr("%1 particles selected (%2%)").arg(numSelected).arg((FloatType)numSelected * 100 / std::max(1,(int)outputSelectionProperty->size()), 0, 'f', 1); + if(outputParticleSelectionObj) { + outputParticleSelectionObj->changed(); + statusMessage += tr("%1 particles selected (%2%)").arg(numSelected).arg((FloatType)numSelected * 100 / std::max(1,(int)outputParticleSelectionObj->size()), 0, 'f', 1); + } + else if(outputBondSelectionObj) { + outputBondSelectionObj->changed(); + statusMessage += tr("%1 bonds selected (%2%)").arg(numSelected).arg((FloatType)numSelected * 100 / std::max(1,(int)outputBondSelectionObj->size()), 0, 'f', 1); } - _xAxisRangeStart = intervalStart; - _xAxisRangeEnd = intervalEnd; + setXAxisRange(intervalStart, intervalEnd); if(!fixYAxisRange()) { - _yAxisRangeStart = 0.0; - _yAxisRangeEnd = *std::max_element(_histogramData.begin(), _histogramData.end()); + setYAxisRange(0, *std::max_element(_histogramData.begin(), _histogramData.end())); } // Inform the editor component that the stored histogram data has changed diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/histogram/HistogramModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/histogram/HistogramModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/histogram/HistogramModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/histogram/HistogramModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,12 +19,13 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_HISTOGRAM_MODIFIER_H -#define __OVITO_HISTOGRAM_MODIFIER_H +#pragma once + #include #include #include +#include #include "../../ParticleModifier.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) @@ -36,71 +37,26 @@ { public: - /// Constructor. - Q_INVOKABLE HistogramModifier(DataSet* dataset); - - /// Sets the source particle property for which the histogram should be computed. - void setSourceProperty(const ParticlePropertyReference& prop) { _sourceProperty = prop; } + /// The data sources supported by the histogram modifier. + enum DataSourceType { + Particles, //< Particle property values + Bonds, //< Bond property values + }; + Q_ENUMS(DataSourceType); - /// Returns the source particle property for which the histogram is computed. - const ParticlePropertyReference& sourceProperty() const { return _sourceProperty; } - - /// Returns the number of bins in the computed histogram. - int numberOfBins() const { return _numberOfBins; } +public: - /// Sets the number of bins in the computed histogram. - void setNumberOfBins(int n) { _numberOfBins = n; } + /// Constructor. + Q_INVOKABLE HistogramModifier(DataSet* dataset); /// Returns the stored histogram data. const QVector& histogramData() const { return _histogramData; } - /// Returns whether particles within the specified range should be selected. - bool selectInRange() const { return _selectInRange; } - - /// Sets whether particles within the specified range should be selected. - void setSelectInRange(bool select) { _selectInRange = select; } - - /// Returns the start value of the selection interval. - FloatType selectionRangeStart() const { return _selectionRangeStart; } - - /// Returns the end value of the selection interval. - FloatType selectionRangeEnd() const { return _selectionRangeEnd; } - - /// Set whether the range of the x-axis of the scatter plot should be fixed. - void setFixXAxisRange(bool fix) { _fixXAxisRange = fix; } - - /// Returns whether the range of the x-axis of the histogram should be fixed. - bool fixXAxisRange() const { return _fixXAxisRange; } - /// Set start and end value of the x-axis. void setXAxisRange(FloatType start, FloatType end) { _xAxisRangeStart = start; _xAxisRangeEnd = end; } - /// Set start value of the x-axis. - void setXAxisRangeStart(FloatType start) { _xAxisRangeStart = start; } - - /// Set end value of the x-axis. - void setXAxisRangeEnd(FloatType end) { _xAxisRangeEnd = end; } - - /// Returns the start value of the x-axis. - FloatType xAxisRangeStart() const { return _xAxisRangeStart; } - - /// Returns the end value of the x-axis. - FloatType xAxisRangeEnd() const { return _xAxisRangeEnd; } - - /// Returns whether the range of the y-axis of the histogram should be fixed. - bool fixYAxisRange() const { return _fixYAxisRange; } - - /// Returns the start value of the y-axis. - FloatType yAxisRangeStart() const { return _yAxisRangeStart; } - - /// Returns the end value of the y-axis. - FloatType yAxisRangeEnd() const { return _yAxisRangeEnd; } - - /// Returns whether analysis takes only selected particles into account. - bool onlySelected() const { return _onlySelected; } - - /// Sets whether analysis only selected particles are taken into account. - void setOnlySelected(bool onlySelected) { _onlySelected = onlySelected; } + /// Set start and end value of the y-axis. + void setYAxisRange(FloatType start, FloatType end) { _yAxisRangeStart = start; _yAxisRangeEnd = end; } protected: @@ -113,40 +69,46 @@ private: /// The particle property that serves as data source of the histogram. - PropertyField _sourceProperty; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ParticlePropertyReference, sourceParticleProperty, setSourceParticleProperty); + + /// The bond property that serves as data source of the histogram. + DECLARE_MODIFIABLE_PROPERTY_FIELD(BondPropertyReference, sourceBondProperty, setSourceBondProperty); /// Controls the number of histogram bins. - PropertyField _numberOfBins; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, numberOfBins, setNumberOfBins); /// Controls the whether particles within the specified range should be selected. - PropertyField _selectInRange; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, selectInRange, setSelectInRange); /// Controls the start value of the selection interval. - PropertyField _selectionRangeStart; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, selectionRangeStart, setSelectionRangeStart); /// Controls the end value of the selection interval. - PropertyField _selectionRangeEnd; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, selectionRangeEnd, setSelectionRangeEnd); /// Controls the whether the range of the x-axis of the histogram should be fixed. - PropertyField _fixXAxisRange; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, fixXAxisRange, setFixXAxisRange); /// Controls the start value of the x-axis. - PropertyField _xAxisRangeStart; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, xAxisRangeStart, setXAxisRangeStart); /// Controls the end value of the x-axis. - PropertyField _xAxisRangeEnd; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, xAxisRangeEnd, setXAxisRangeEnd); /// Controls the whether the range of the y-axis of the histogram should be fixed. - PropertyField _fixYAxisRange; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, fixYAxisRange, setFixYAxisRange); /// Controls the start value of the y-axis. - PropertyField _yAxisRangeStart; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, yAxisRangeStart, setYAxisRangeStart); /// Controls the end value of the y-axis. - PropertyField _yAxisRangeEnd; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, yAxisRangeEnd, setYAxisRangeEnd); /// Controls whether the modifier should take into account only selected particles. - PropertyField _onlySelected; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, onlySelected, setOnlySelected); + + /// Controls where this modifier takes its input values from. + DECLARE_MODIFIABLE_PROPERTY_FIELD(DataSourceType, dataSourceType, setDataSourceType); /// Stores the histogram data. QVector _histogramData; @@ -156,19 +118,6 @@ Q_CLASSINFO("DisplayName", "Histogram"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_PROPERTY_FIELD(_numberOfBins); - DECLARE_PROPERTY_FIELD(_selectInRange); - DECLARE_PROPERTY_FIELD(_selectionRangeStart); - DECLARE_PROPERTY_FIELD(_selectionRangeEnd); - DECLARE_PROPERTY_FIELD(_fixXAxisRange); - DECLARE_PROPERTY_FIELD(_xAxisRangeStart); - DECLARE_PROPERTY_FIELD(_xAxisRangeEnd); - DECLARE_PROPERTY_FIELD(_fixYAxisRange); - DECLARE_PROPERTY_FIELD(_yAxisRangeStart); - DECLARE_PROPERTY_FIELD(_yAxisRangeEnd); - DECLARE_PROPERTY_FIELD(_sourceProperty); - DECLARE_PROPERTY_FIELD(_onlySelected); }; OVITO_END_INLINE_NAMESPACE @@ -176,4 +125,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_HISTOGRAM_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/ptm/PolyhedralTemplateMatchingModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/ptm/PolyhedralTemplateMatchingModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/ptm/PolyhedralTemplateMatchingModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/ptm/PolyhedralTemplateMatchingModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,20 +28,20 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, PolyhedralTemplateMatchingModifier, StructureIdentificationModifier); -DEFINE_FLAGS_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier, _rmsdCutoff, "RMSDCutoff", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier, _outputRmsd, "OutputRmsd"); -DEFINE_FLAGS_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier, _outputInteratomicDistance, "OutputInteratomicDistance", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier, _outputOrientation, "OutputOrientation", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier, _outputDeformationGradient, "OutputDeformationGradient"); -DEFINE_FLAGS_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier, _outputAlloyTypes, "OutputAlloyTypes", PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(PolyhedralTemplateMatchingModifier, _rmsdCutoff, "RMSD cutoff"); -SET_PROPERTY_FIELD_LABEL(PolyhedralTemplateMatchingModifier, _outputRmsd, "Output RMSD values"); -SET_PROPERTY_FIELD_LABEL(PolyhedralTemplateMatchingModifier, _outputInteratomicDistance, "Output interatomic distance"); -SET_PROPERTY_FIELD_LABEL(PolyhedralTemplateMatchingModifier, _outputOrientation, "Output orientations"); -SET_PROPERTY_FIELD_LABEL(PolyhedralTemplateMatchingModifier, _outputDeformationGradient, "Output deformation gradients"); -SET_PROPERTY_FIELD_LABEL(PolyhedralTemplateMatchingModifier, _outputAlloyTypes, "Output alloy types"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(PolyhedralTemplateMatchingModifier, _rmsdCutoff, FloatParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(PolyhedralTemplateMatchingModifier, StructureIdentificationModifier); +DEFINE_FLAGS_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier, rmsdCutoff, "RMSDCutoff", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier, outputRmsd, "OutputRmsd"); +DEFINE_FLAGS_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier, outputInteratomicDistance, "OutputInteratomicDistance", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier, outputOrientation, "OutputOrientation", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier, outputDeformationGradient, "OutputDeformationGradient"); +DEFINE_FLAGS_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier, outputAlloyTypes, "OutputAlloyTypes", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(PolyhedralTemplateMatchingModifier, rmsdCutoff, "RMSD cutoff"); +SET_PROPERTY_FIELD_LABEL(PolyhedralTemplateMatchingModifier, outputRmsd, "Output RMSD values"); +SET_PROPERTY_FIELD_LABEL(PolyhedralTemplateMatchingModifier, outputInteratomicDistance, "Output interatomic distance"); +SET_PROPERTY_FIELD_LABEL(PolyhedralTemplateMatchingModifier, outputOrientation, "Output orientations"); +SET_PROPERTY_FIELD_LABEL(PolyhedralTemplateMatchingModifier, outputDeformationGradient, "Output deformation gradients"); +SET_PROPERTY_FIELD_LABEL(PolyhedralTemplateMatchingModifier, outputAlloyTypes, "Output alloy types"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(PolyhedralTemplateMatchingModifier, rmsdCutoff, FloatParameterUnit, 0); /****************************************************************************** * Constructs the modifier object. @@ -50,12 +50,12 @@ _rmsdCutoff(0), _rmsdHistogramBinSize(0), _outputRmsd(false), _outputInteratomicDistance(false), _outputOrientation(false), _outputDeformationGradient(false), _outputAlloyTypes(false) { - INIT_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_rmsdCutoff); - INIT_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_outputRmsd); - INIT_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_outputInteratomicDistance); - INIT_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_outputOrientation); - INIT_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_outputDeformationGradient); - INIT_PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_outputAlloyTypes); + INIT_PROPERTY_FIELD(rmsdCutoff); + INIT_PROPERTY_FIELD(outputRmsd); + INIT_PROPERTY_FIELD(outputInteratomicDistance); + INIT_PROPERTY_FIELD(outputOrientation); + INIT_PROPERTY_FIELD(outputDeformationGradient); + INIT_PROPERTY_FIELD(outputAlloyTypes); // Define the structure types. createStructureType(OTHER, ParticleTypeProperty::PredefinedStructureType::OTHER); @@ -74,11 +74,11 @@ StructureIdentificationModifier::propertyChanged(field); // Re-perform analysis when settings change. - if(field == PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_outputRmsd) || - field == PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_outputInteratomicDistance) || - field == PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_outputOrientation) || - field == PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_outputDeformationGradient) || - field == PROPERTY_FIELD(PolyhedralTemplateMatchingModifier::_outputAlloyTypes)) + if(field == PROPERTY_FIELD(outputRmsd) || + field == PROPERTY_FIELD(outputInteratomicDistance) || + field == PROPERTY_FIELD(outputOrientation) || + field == PROPERTY_FIELD(outputDeformationGradient) || + field == PROPERTY_FIELD(outputAlloyTypes)) invalidateCachedResults(); } @@ -93,6 +93,8 @@ // Get modifier input. ParticlePropertyObject* posProperty = expectStandardProperty(ParticleProperty::PositionProperty); SimulationCellObject* simCell = expectSimulationCell(); + if(simCell->is2D()) + throwException(tr("The PTM modifier does not support 2d simulation cells.")); // Get particle selection. ParticleProperty* selectionProperty = nullptr; @@ -121,17 +123,17 @@ // Prepare the neighbor list. NearestNeighborFinder neighFinder(MAX_NEIGHBORS); - if(!neighFinder.prepare(positions(), cell(), selection(), this)) + if(!neighFinder.prepare(positions(), cell(), selection(), *this)) return; // Create output storage. ParticleProperty* output = structures(); - setProgressRange(positions()->size()); setProgressValue(0); + setProgressMaximum(positions()->size()); // Perform analysis on each particle. - parallelForChunks(positions()->size(), *this, [this, &neighFinder, output](size_t startIndex, size_t count, FutureInterfaceBase& progress) { + parallelForChunks(positions()->size(), *this, [this, &neighFinder, output](size_t startIndex, size_t count, PromiseBase& promise) { // Initialize thread-local storage for PTM routine. ptm_local_handle_t ptm_local_handle = ptm_initialize_local(); @@ -141,10 +143,10 @@ // Update progress indicator. if((index % 256) == 0) - progress.incrementProgressValue(256); + promise.incrementProgressValue(256); // Break out of loop when operation was canceled. - if(progress.isCanceled()) + if(promise.isCanceled()) break; // Skip particles that are not included in the analysis. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/ptm/PolyhedralTemplateMatchingModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/ptm/PolyhedralTemplateMatchingModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/ptm/PolyhedralTemplateMatchingModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/ptm/PolyhedralTemplateMatchingModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PTM_MODIFIER_H -#define __OVITO_PTM_MODIFIER_H +#pragma once + #include #include @@ -73,48 +73,12 @@ /// Constructor. Q_INVOKABLE PolyhedralTemplateMatchingModifier(DataSet* dataset); - /// \brief Returns the RMSD cutoff. - FloatType rmsdCutoff() const { return _rmsdCutoff; } - - /// \brief Sets the RMSD cutoff. - void setRmsdCutoff(FloatType cutoff) { _rmsdCutoff = cutoff; } - /// Returns the computed histogram of RMSD values. const QVector& rmsdHistogramData() const { return _rmsdHistogramData; } /// Returns the bin size of the RMSD histogram. FloatType rmsdHistogramBinSize() const { return _rmsdHistogramBinSize; } - /// Returns whether per-particle RMSD values are output by the modifier. - bool outputRmsd() const { return _outputRmsd; } - - /// Sets whether per-particle RMSD values are output by the modifier. - void setOutputRmsd(bool enable) { _outputRmsd = enable; } - - /// Returns whether local interatomic distances are output by the modifier. - bool outputInteratomicDistance() const { return _outputInteratomicDistance; } - - /// Sets whether local interatomic distances are output by the modifier. - void setOutputInteratomicDistance(bool enable) { _outputInteratomicDistance = enable; } - - /// Returns whether local orientations are output by the modifier. - bool outputOrientation() const { return _outputOrientation; } - - /// Sets whether local orientations are output by the modifier. - void setOutputOrientation(bool enable) { _outputOrientation = enable; } - - /// Returns whether elastic deformation gradients are output by the modifier. - bool outputDeformationGradient() const { return _outputDeformationGradient; } - - /// Sets whether elastic deformation gradients are output by the modifier. - void setOutputDeformationGradient(bool enable) { _outputDeformationGradient = enable; } - - /// Returns whether alloy types should be identified by the modifier. - bool outputAlloyTypes() const { return _outputAlloyTypes; } - - /// Sets whether local alloy types should be identified by the modifier. - void setOutputAlloyTypes(bool enable) { _outputAlloyTypes = enable; } - protected: /// Is called when the value of a property of this object has changed. @@ -182,22 +146,22 @@ QExplicitlySharedDataPointer _alloyTypes; /// The RMSD cutoff. - PropertyField _rmsdCutoff; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, rmsdCutoff, setRmsdCutoff); /// Controls the output of the per-particle RMSD values. - PropertyField _outputRmsd; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, outputRmsd, setOutputRmsd); /// Controls the output of local interatomic distances. - PropertyField _outputInteratomicDistance; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, outputInteratomicDistance, setOutputInteratomicDistance); /// Controls the output of local orientations. - PropertyField _outputOrientation; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, outputOrientation, setOutputOrientation); /// Controls the output of elastic deformation gradients. - PropertyField _outputDeformationGradient; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, outputDeformationGradient, setOutputDeformationGradient); /// Controls the output of alloy structure types. - PropertyField _outputAlloyTypes; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, outputAlloyTypes, setOutputAlloyTypes); /// The computed histogram of RMSD values. QVector _rmsdHistogramData; @@ -210,13 +174,6 @@ Q_CLASSINFO("DisplayName", "Polyhedral template matching"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_PROPERTY_FIELD(_rmsdCutoff); - DECLARE_PROPERTY_FIELD(_outputRmsd); - DECLARE_PROPERTY_FIELD(_outputInteratomicDistance); - DECLARE_PROPERTY_FIELD(_outputOrientation); - DECLARE_PROPERTY_FIELD(_outputDeformationGradient); - DECLARE_PROPERTY_FIELD(_outputAlloyTypes); }; OVITO_END_INLINE_NAMESPACE @@ -224,4 +181,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PTM_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/scatterplot/ScatterPlotModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/scatterplot/ScatterPlotModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/scatterplot/ScatterPlotModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/scatterplot/ScatterPlotModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,35 +27,35 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ScatterPlotModifier, ParticleModifier); -DEFINE_PROPERTY_FIELD(ScatterPlotModifier, _selectXAxisInRange, "SelectXAxisInRange"); -DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, _selectionXAxisRangeStart, "SelectionXAxisRangeStart", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, _selectionXAxisRangeEnd, "SelectionXAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(ScatterPlotModifier, _selectYAxisInRange, "SelectYAxisInRange"); -DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, _selectionYAxisRangeStart, "SelectionYAxisRangeStart", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, _selectionYAxisRangeEnd, "SelectionYAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(ScatterPlotModifier, _fixXAxisRange, "FixXAxisRange"); -DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, _xAxisRangeStart, "XAxisRangeStart", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, _xAxisRangeEnd, "XAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(ScatterPlotModifier, _fixYAxisRange, "FixYAxisRange"); -DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, _yAxisRangeStart, "YAxisRangeStart", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, _yAxisRangeEnd, "YAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(ScatterPlotModifier, _xAxisProperty, "XAxisProperty"); -DEFINE_PROPERTY_FIELD(ScatterPlotModifier, _yAxisProperty, "YAxisProperty"); -SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, _selectXAxisInRange, "Select particles in x-range"); -SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, _selectionXAxisRangeStart, "Selection x-range start"); -SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, _selectionXAxisRangeEnd, "Selection x-range end"); -SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, _selectYAxisInRange, "Select particles in y-range"); -SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, _selectionYAxisRangeStart, "Selection y-range start"); -SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, _selectionYAxisRangeEnd, "Selection y-range end"); -SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, _fixXAxisRange, "Fix x-range"); -SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, _xAxisRangeStart, "X-range start"); -SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, _xAxisRangeEnd, "X-range end"); -SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, _fixYAxisRange, "Fix y-range"); -SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, _yAxisRangeStart, "Y-range start"); -SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, _yAxisRangeEnd, "Y-range end"); -SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, _xAxisProperty, "X-axis property"); -SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, _yAxisProperty, "Y-axis property"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ScatterPlotModifier, ParticleModifier); +DEFINE_PROPERTY_FIELD(ScatterPlotModifier, selectXAxisInRange, "SelectXAxisInRange"); +DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, selectionXAxisRangeStart, "SelectionXAxisRangeStart", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, selectionXAxisRangeEnd, "SelectionXAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(ScatterPlotModifier, selectYAxisInRange, "SelectYAxisInRange"); +DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, selectionYAxisRangeStart, "SelectionYAxisRangeStart", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, selectionYAxisRangeEnd, "SelectionYAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(ScatterPlotModifier, fixXAxisRange, "FixXAxisRange"); +DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, xAxisRangeStart, "XAxisRangeStart", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, xAxisRangeEnd, "XAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(ScatterPlotModifier, fixYAxisRange, "FixYAxisRange"); +DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, yAxisRangeStart, "YAxisRangeStart", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ScatterPlotModifier, yAxisRangeEnd, "YAxisRangeEnd", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(ScatterPlotModifier, xAxisProperty, "XAxisProperty"); +DEFINE_PROPERTY_FIELD(ScatterPlotModifier, yAxisProperty, "YAxisProperty"); +SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, selectXAxisInRange, "Select particles in x-range"); +SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, selectionXAxisRangeStart, "Selection x-range start"); +SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, selectionXAxisRangeEnd, "Selection x-range end"); +SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, selectYAxisInRange, "Select particles in y-range"); +SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, selectionYAxisRangeStart, "Selection y-range start"); +SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, selectionYAxisRangeEnd, "Selection y-range end"); +SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, fixXAxisRange, "Fix x-range"); +SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, xAxisRangeStart, "X-range start"); +SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, xAxisRangeEnd, "X-range end"); +SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, fixYAxisRange, "Fix y-range"); +SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, yAxisRangeStart, "Y-range start"); +SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, yAxisRangeEnd, "Y-range end"); +SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, xAxisProperty, "X-axis property"); +SET_PROPERTY_FIELD_LABEL(ScatterPlotModifier, yAxisProperty, "Y-axis property"); /****************************************************************************** * Constructs the modifier object. @@ -66,20 +66,20 @@ _fixXAxisRange(false), _xAxisRangeStart(0), _xAxisRangeEnd(0), _fixYAxisRange(false), _yAxisRangeStart(0), _yAxisRangeEnd(0) { - INIT_PROPERTY_FIELD(ScatterPlotModifier::_selectXAxisInRange); - INIT_PROPERTY_FIELD(ScatterPlotModifier::_selectionXAxisRangeStart); - INIT_PROPERTY_FIELD(ScatterPlotModifier::_selectionXAxisRangeEnd); - INIT_PROPERTY_FIELD(ScatterPlotModifier::_selectYAxisInRange); - INIT_PROPERTY_FIELD(ScatterPlotModifier::_selectionYAxisRangeStart); - INIT_PROPERTY_FIELD(ScatterPlotModifier::_selectionYAxisRangeEnd); - INIT_PROPERTY_FIELD(ScatterPlotModifier::_fixXAxisRange); - INIT_PROPERTY_FIELD(ScatterPlotModifier::_xAxisRangeStart); - INIT_PROPERTY_FIELD(ScatterPlotModifier::_xAxisRangeEnd); - INIT_PROPERTY_FIELD(ScatterPlotModifier::_fixYAxisRange); - INIT_PROPERTY_FIELD(ScatterPlotModifier::_yAxisRangeStart); - INIT_PROPERTY_FIELD(ScatterPlotModifier::_yAxisRangeEnd); - INIT_PROPERTY_FIELD(ScatterPlotModifier::_xAxisProperty); - INIT_PROPERTY_FIELD(ScatterPlotModifier::_yAxisProperty); + INIT_PROPERTY_FIELD(selectXAxisInRange); + INIT_PROPERTY_FIELD(selectionXAxisRangeStart); + INIT_PROPERTY_FIELD(selectionXAxisRangeEnd); + INIT_PROPERTY_FIELD(selectYAxisInRange); + INIT_PROPERTY_FIELD(selectionYAxisRangeStart); + INIT_PROPERTY_FIELD(selectionYAxisRangeEnd); + INIT_PROPERTY_FIELD(fixXAxisRange); + INIT_PROPERTY_FIELD(xAxisRangeStart); + INIT_PROPERTY_FIELD(xAxisRangeEnd); + INIT_PROPERTY_FIELD(fixYAxisRange); + INIT_PROPERTY_FIELD(yAxisRangeStart); + INIT_PROPERTY_FIELD(yAxisRangeEnd); + INIT_PROPERTY_FIELD(xAxisProperty); + INIT_PROPERTY_FIELD(yAxisProperty); } /****************************************************************************** @@ -93,7 +93,7 @@ ParticlePropertyReference bestProperty; if(xAxisProperty().isNull() || yAxisProperty().isNull()) { // Select the first available particle property from the input state. - PipelineFlowState input = pipeline->evaluatePipeline(dataset()->animationSettings()->time(), modApp, false); + PipelineFlowState input = getModifierInput(modApp); for(DataObject* o : input.objects()) { ParticlePropertyObject* property = dynamic_object_cast(o); if(property && (property->dataType() == qMetaTypeId() || property->dataType() == qMetaTypeId())) { diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/scatterplot/ScatterPlotModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/scatterplot/ScatterPlotModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/scatterplot/ScatterPlotModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/scatterplot/ScatterPlotModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SCATTER_PLOT_MODIFIER_H -#define __OVITO_SCATTER_PLOT_MODIFIER_H +#pragma once + #include #include @@ -38,18 +38,6 @@ /// Constructor. Q_INVOKABLE ScatterPlotModifier(DataSet* dataset); - /// Sets the source particle property for which the scatter plot should be computed. - void setXAxisProperty(const ParticlePropertyReference& prop) { _xAxisProperty = prop; } - - /// Returns the source particle property for which the scatter plot is computed. - const ParticlePropertyReference& xAxisProperty() const { return _xAxisProperty; } - - /// Sets the source particle property for which the scatter plot should be computed. - void setYAxisProperty(const ParticlePropertyReference& prop) { _yAxisProperty = prop; } - - /// Returns the source particle property for which the scatter plot is computed. - const ParticlePropertyReference& yAxisProperty() const { return _yAxisProperty; } - /// Returns the stored scatter plot data. const QVector& xyData() const { return _xyData; } @@ -59,60 +47,12 @@ /// Returns the map from particle types to colors. const std::map& colorMap() const { return _colorMap; } - /// Returns whether particles within the specified range should be selected (x-axis). - bool selectXAxisInRange() const { return _selectXAxisInRange; } - - /// Sets whether particles within the specified range should be selected (x-axis). - void setSelectXAxisInRange(bool select) { _selectXAxisInRange = select; } - - /// Returns the start value of the selection interval (x-axis). - FloatType selectionXAxisRangeStart() const { return _selectionXAxisRangeStart; } - - /// Returns the end value of the selection interval (x-axis). - FloatType selectionXAxisRangeEnd() const { return _selectionXAxisRangeEnd; } - - /// Returns whether particles within the specified range should be selected (y-axis). - bool selectYAxisInRange() const { return _selectYAxisInRange; } - - /// Sets whether particles within the specified range should be selected (y-axis). - void setSelectYAxisInRange(bool select) { _selectYAxisInRange = select; } - - /// Returns the start value of the selection interval (y-axis). - FloatType selectionYAxisRangeStart() const { return _selectionYAxisRangeStart; } - - /// Returns the end value of the selection interval (y-axis). - FloatType selectionYAxisRangeEnd() const { return _selectionYAxisRangeEnd; } - - /// Set whether the range of the x-axis of the scatter plot should be fixed. - void setFixXAxisRange(bool fix) { _fixXAxisRange = fix; } - - /// Returns whether the range of the x-axis of the scatter plot should be fixed. - bool fixXAxisRange() const { return _fixXAxisRange; } - /// Set start and end value of the x-axis. void setXAxisRange(FloatType start, FloatType end) { _xAxisRangeStart = start; _xAxisRangeEnd = end; } - /// Returns the start value of the x-axis. - FloatType xAxisRangeStart() const { return _xAxisRangeStart; } - - /// Returns the end value of the x-axis. - FloatType xAxisRangeEnd() const { return _xAxisRangeEnd; } - - /// Set whether the range of the y-axis of the scatter plot should be fixed. - void setFixYAxisRange(bool fix) { _fixYAxisRange = fix; } - - /// Returns whether the range of the y-axis of the scatter plot should be fixed. - bool fixYAxisRange() const { return _fixYAxisRange; } - /// Set start and end value of the y-axis. void setYAxisRange(FloatType start, FloatType end) { _yAxisRangeStart = start; _yAxisRangeEnd = end; } - /// Returns the start value of the y-axis. - FloatType yAxisRangeStart() const { return _yAxisRangeStart; } - - /// Returns the end value of the y-axis. - FloatType yAxisRangeEnd() const { return _yAxisRangeEnd; } - protected: /// Modifies the particle object. @@ -124,46 +64,46 @@ private: /// The particle type property that is used as source for the x-axis. - PropertyField _xAxisProperty; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ParticlePropertyReference, xAxisProperty, setXAxisProperty); /// The particle type property that is used as source for the y-axis. - PropertyField _yAxisProperty; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ParticlePropertyReference, yAxisProperty, setYAxisProperty); /// Controls the whether particles within the specified range should be selected (x-axis). - PropertyField _selectXAxisInRange; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, selectXAxisInRange, setSelectXAxisInRange); /// Controls the start value of the selection interval (x-axis). - PropertyField _selectionXAxisRangeStart; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, selectionXAxisRangeStart, setSelectionXAxisRangeStart); /// Controls the end value of the selection interval (x-axis). - PropertyField _selectionXAxisRangeEnd; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, selectionXAxisRangeEnd, setSelectionXAxisRangeEnd); /// Controls the whether particles within the specified range should be selected (y-axis). - PropertyField _selectYAxisInRange; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, selectYAxisInRange, setSelectYAxisInRange); /// Controls the start value of the selection interval (y-axis). - PropertyField _selectionYAxisRangeStart; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, selectionYAxisRangeStart, setSelectionYAxisRangeStart); /// Controls the end value of the selection interval (y-axis). - PropertyField _selectionYAxisRangeEnd; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, selectionYAxisRangeEnd, setSelectionYAxisRangeEnd); /// Controls the whether the range of the x-axis of the scatter plot should be fixed. - PropertyField _fixXAxisRange; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, fixXAxisRange, setFixXAxisRange); /// Controls the start value of the x-axis. - PropertyField _xAxisRangeStart; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, xAxisRangeStart, setXAxisRangeStart); /// Controls the end value of the x-axis. - PropertyField _xAxisRangeEnd; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, xAxisRangeEnd, setXAxisRangeEnd); /// Controls the whether the range of the y-axis of the scatter plot should be fixed. - PropertyField _fixYAxisRange; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, fixYAxisRange, setFixYAxisRange); /// Controls the start value of the y-axis. - PropertyField _yAxisRangeStart; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, yAxisRangeStart, setYAxisRangeStart); /// Controls the end value of the y-axis. - PropertyField _yAxisRangeEnd; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, yAxisRangeEnd, setYAxisRangeEnd); /// Stores the scatter plot data. QVector _xyData; @@ -179,21 +119,6 @@ Q_CLASSINFO("DisplayName", "Scatter plot"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_PROPERTY_FIELD(_selectXAxisInRange); - DECLARE_PROPERTY_FIELD(_selectionXAxisRangeStart); - DECLARE_PROPERTY_FIELD(_selectionXAxisRangeEnd); - DECLARE_PROPERTY_FIELD(_selectYAxisInRange); - DECLARE_PROPERTY_FIELD(_selectionYAxisRangeStart); - DECLARE_PROPERTY_FIELD(_selectionYAxisRangeEnd); - DECLARE_PROPERTY_FIELD(_fixXAxisRange); - DECLARE_PROPERTY_FIELD(_xAxisRangeStart); - DECLARE_PROPERTY_FIELD(_xAxisRangeEnd); - DECLARE_PROPERTY_FIELD(_fixYAxisRange); - DECLARE_PROPERTY_FIELD(_yAxisRangeStart); - DECLARE_PROPERTY_FIELD(_yAxisRangeEnd); - DECLARE_PROPERTY_FIELD(_xAxisProperty); - DECLARE_PROPERTY_FIELD(_yAxisProperty); }; OVITO_END_INLINE_NAMESPACE @@ -201,4 +126,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SCATTER_PLOT_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/strain/AtomicStrainModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/strain/AtomicStrainModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/strain/AtomicStrainModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/strain/AtomicStrainModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -29,37 +30,37 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, AtomicStrainModifier, AsynchronousParticleModifier); -DEFINE_FLAGS_REFERENCE_FIELD(AtomicStrainModifier, _referenceObject, "Reference Configuration", DataObject, PROPERTY_FIELD_NO_SUB_ANIM); -DEFINE_PROPERTY_FIELD(AtomicStrainModifier, _referenceShown, "ShowReferenceConfiguration"); -DEFINE_FLAGS_PROPERTY_FIELD(AtomicStrainModifier, _eliminateCellDeformation, "EliminateCellDeformation", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(AtomicStrainModifier, _assumeUnwrappedCoordinates, "AssumeUnwrappedCoordinates"); -DEFINE_FLAGS_PROPERTY_FIELD(AtomicStrainModifier, _cutoff, "Cutoff", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(AtomicStrainModifier, _calculateDeformationGradients, "CalculateDeformationGradients"); -DEFINE_PROPERTY_FIELD(AtomicStrainModifier, _calculateStrainTensors, "CalculateStrainTensors"); -DEFINE_PROPERTY_FIELD(AtomicStrainModifier, _calculateNonaffineSquaredDisplacements, "CalculateNonaffineSquaredDisplacements"); -DEFINE_PROPERTY_FIELD(AtomicStrainModifier, _selectInvalidParticles, "SelectInvalidParticles"); -DEFINE_PROPERTY_FIELD(AtomicStrainModifier, _useReferenceFrameOffset, "UseReferenceFrameOffet"); -DEFINE_PROPERTY_FIELD(AtomicStrainModifier, _referenceFrameNumber, "ReferenceFrameNumber"); -DEFINE_FLAGS_PROPERTY_FIELD(AtomicStrainModifier, _referenceFrameOffset, "ReferenceFrameOffset", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(AtomicStrainModifier, _calculateStretchTensors, "CalculateStretchTensors"); -DEFINE_PROPERTY_FIELD(AtomicStrainModifier, _calculateRotations, "CalculateRotations"); -SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, _referenceObject, "Reference Configuration"); -SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, _referenceShown, "Show reference configuration"); -SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, _eliminateCellDeformation, "Eliminate homogeneous cell deformation"); -SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, _assumeUnwrappedCoordinates, "Assume unwrapped coordinates"); -SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, _cutoff, "Cutoff radius"); -SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, _calculateDeformationGradients, "Output deformation gradient tensors"); -SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, _calculateStrainTensors, "Output strain tensors"); -SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, _calculateNonaffineSquaredDisplacements, "Output non-affine squared displacements (D^2_min)"); -SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, _selectInvalidParticles, "Select invalid particles"); -SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, _useReferenceFrameOffset, "Use reference frame offset"); -SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, _referenceFrameNumber, "Reference frame number"); -SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, _referenceFrameOffset, "Reference frame offset"); -SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, _calculateStretchTensors, "Output stretch tensors"); -SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, _calculateRotations, "Output rotations"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(AtomicStrainModifier, _cutoff, WorldParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(AtomicStrainModifier, _referenceFrameNumber, IntegerParameterUnit, 1); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(AtomicStrainModifier, AsynchronousParticleModifier); +DEFINE_FLAGS_REFERENCE_FIELD(AtomicStrainModifier, referenceConfiguration, "Reference Configuration", DataObject, PROPERTY_FIELD_NO_SUB_ANIM); +DEFINE_PROPERTY_FIELD(AtomicStrainModifier, referenceShown, "ShowReferenceConfiguration"); +DEFINE_FLAGS_PROPERTY_FIELD(AtomicStrainModifier, eliminateCellDeformation, "EliminateCellDeformation", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(AtomicStrainModifier, assumeUnwrappedCoordinates, "AssumeUnwrappedCoordinates"); +DEFINE_FLAGS_PROPERTY_FIELD(AtomicStrainModifier, cutoff, "Cutoff", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(AtomicStrainModifier, calculateDeformationGradients, "CalculateDeformationGradients"); +DEFINE_PROPERTY_FIELD(AtomicStrainModifier, calculateStrainTensors, "CalculateStrainTensors"); +DEFINE_PROPERTY_FIELD(AtomicStrainModifier, calculateNonaffineSquaredDisplacements, "CalculateNonaffineSquaredDisplacements"); +DEFINE_PROPERTY_FIELD(AtomicStrainModifier, selectInvalidParticles, "SelectInvalidParticles"); +DEFINE_PROPERTY_FIELD(AtomicStrainModifier, useReferenceFrameOffset, "UseReferenceFrameOffet"); +DEFINE_PROPERTY_FIELD(AtomicStrainModifier, referenceFrameNumber, "ReferenceFrameNumber"); +DEFINE_FLAGS_PROPERTY_FIELD(AtomicStrainModifier, referenceFrameOffset, "ReferenceFrameOffset", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(AtomicStrainModifier, calculateStretchTensors, "CalculateStretchTensors"); +DEFINE_PROPERTY_FIELD(AtomicStrainModifier, calculateRotations, "CalculateRotations"); +SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, referenceConfiguration, "Reference Configuration"); +SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, referenceShown, "Show reference configuration"); +SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, eliminateCellDeformation, "Eliminate homogeneous cell deformation"); +SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, assumeUnwrappedCoordinates, "Assume unwrapped coordinates"); +SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, cutoff, "Cutoff radius"); +SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, calculateDeformationGradients, "Output deformation gradient tensors"); +SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, calculateStrainTensors, "Output strain tensors"); +SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, calculateNonaffineSquaredDisplacements, "Output non-affine squared displacements (D^2_min)"); +SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, selectInvalidParticles, "Select invalid particles"); +SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, useReferenceFrameOffset, "Use reference frame offset"); +SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, referenceFrameNumber, "Reference frame number"); +SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, referenceFrameOffset, "Reference frame offset"); +SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, calculateStretchTensors, "Output stretch tensors"); +SET_PROPERTY_FIELD_LABEL(AtomicStrainModifier, calculateRotations, "Output rotations"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(AtomicStrainModifier, cutoff, WorldParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(AtomicStrainModifier, referenceFrameNumber, IntegerParameterUnit, 1); /****************************************************************************** * Constructs the modifier object. @@ -71,20 +72,20 @@ _selectInvalidParticles(true), _useReferenceFrameOffset(false), _referenceFrameNumber(0), _referenceFrameOffset(-1) { - INIT_PROPERTY_FIELD(AtomicStrainModifier::_referenceObject); - INIT_PROPERTY_FIELD(AtomicStrainModifier::_referenceShown); - INIT_PROPERTY_FIELD(AtomicStrainModifier::_eliminateCellDeformation); - INIT_PROPERTY_FIELD(AtomicStrainModifier::_assumeUnwrappedCoordinates); - INIT_PROPERTY_FIELD(AtomicStrainModifier::_cutoff); - INIT_PROPERTY_FIELD(AtomicStrainModifier::_calculateDeformationGradients); - INIT_PROPERTY_FIELD(AtomicStrainModifier::_calculateStrainTensors); - INIT_PROPERTY_FIELD(AtomicStrainModifier::_calculateNonaffineSquaredDisplacements); - INIT_PROPERTY_FIELD(AtomicStrainModifier::_selectInvalidParticles); - INIT_PROPERTY_FIELD(AtomicStrainModifier::_useReferenceFrameOffset); - INIT_PROPERTY_FIELD(AtomicStrainModifier::_referenceFrameNumber); - INIT_PROPERTY_FIELD(AtomicStrainModifier::_referenceFrameOffset); - INIT_PROPERTY_FIELD(AtomicStrainModifier::_calculateStretchTensors); - INIT_PROPERTY_FIELD(AtomicStrainModifier::_calculateRotations); + INIT_PROPERTY_FIELD(referenceConfiguration); + INIT_PROPERTY_FIELD(referenceShown); + INIT_PROPERTY_FIELD(eliminateCellDeformation); + INIT_PROPERTY_FIELD(assumeUnwrappedCoordinates); + INIT_PROPERTY_FIELD(cutoff); + INIT_PROPERTY_FIELD(calculateDeformationGradients); + INIT_PROPERTY_FIELD(calculateStrainTensors); + INIT_PROPERTY_FIELD(calculateNonaffineSquaredDisplacements); + INIT_PROPERTY_FIELD(selectInvalidParticles); + INIT_PROPERTY_FIELD(useReferenceFrameOffset); + INIT_PROPERTY_FIELD(referenceFrameNumber); + INIT_PROPERTY_FIELD(referenceFrameOffset); + INIT_PROPERTY_FIELD(calculateStretchTensors); + INIT_PROPERTY_FIELD(calculateRotations); // Create the file source object, which will be responsible for loading // and storing the reference configuration. @@ -137,7 +138,7 @@ refState = fileSource->requestFrame(referenceFrame); } } - else refState = referenceConfiguration()->evaluate(dataset()->animationSettings()->frameToTime(referenceFrame)); + else refState = referenceConfiguration()->evaluateImmediately(PipelineEvalRequest(dataset()->animationSettings()->frameToTime(referenceFrame), false)); // Make sure the obtained reference configuration is valid and ready to use. if(refState.status().type() == PipelineStatus::Error) @@ -282,7 +283,7 @@ // Prepare the neighbor list for the reference configuration. CutoffNeighborFinder neighborFinder; - if(!neighborFinder.prepare(_cutoff, refPositions(), refCell(), nullptr, this)) + if(!neighborFinder.prepare(_cutoff, refPositions(), refCell(), nullptr, *this)) return; // Perform individual strain calculation for each particle. @@ -511,17 +512,17 @@ AsynchronousParticleModifier::propertyChanged(field); // Recompute results when the parameters change. - if(field == PROPERTY_FIELD(AtomicStrainModifier::_eliminateCellDeformation) || - field == PROPERTY_FIELD(AtomicStrainModifier::_assumeUnwrappedCoordinates) || - field == PROPERTY_FIELD(AtomicStrainModifier::_cutoff) || - field == PROPERTY_FIELD(AtomicStrainModifier::_calculateDeformationGradients) || - field == PROPERTY_FIELD(AtomicStrainModifier::_calculateStrainTensors) || - field == PROPERTY_FIELD(AtomicStrainModifier::_calculateNonaffineSquaredDisplacements) || - field == PROPERTY_FIELD(AtomicStrainModifier::_calculateRotations) || - field == PROPERTY_FIELD(AtomicStrainModifier::_calculateStretchTensors) || - field == PROPERTY_FIELD(AtomicStrainModifier::_useReferenceFrameOffset) || - field == PROPERTY_FIELD(AtomicStrainModifier::_referenceFrameNumber) || - field == PROPERTY_FIELD(AtomicStrainModifier::_referenceFrameOffset)) + if(field == PROPERTY_FIELD(eliminateCellDeformation) || + field == PROPERTY_FIELD(assumeUnwrappedCoordinates) || + field == PROPERTY_FIELD(cutoff) || + field == PROPERTY_FIELD(calculateDeformationGradients) || + field == PROPERTY_FIELD(calculateStrainTensors) || + field == PROPERTY_FIELD(calculateNonaffineSquaredDisplacements) || + field == PROPERTY_FIELD(calculateRotations) || + field == PROPERTY_FIELD(calculateStretchTensors) || + field == PROPERTY_FIELD(useReferenceFrameOffset) || + field == PROPERTY_FIELD(referenceFrameNumber) || + field == PROPERTY_FIELD(referenceFrameOffset)) invalidateCachedResults(); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/strain/AtomicStrainModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/strain/AtomicStrainModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/strain/AtomicStrainModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/strain/AtomicStrainModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ATOMIC_STRAIN_MODIFIER_H -#define __OVITO_ATOMIC_STRAIN_MODIFIER_H +#pragma once + #include #include @@ -39,74 +39,6 @@ /// Constructor. Q_INVOKABLE AtomicStrainModifier(DataSet* dataset); - /// Returns the object that contains the reference configuration of the particles - /// used for calculating the displacement vectors. - DataObject* referenceConfiguration() const { return _referenceObject; } - - /// Sets the object that contains the reference configuration of the particles - /// used for calculating the displacement vectors. - void setReferenceConfiguration(DataObject* refConf) { _referenceObject = refConf; } - - /// Returns whether the reference configuration is shown instead of the current configuration. - bool referenceShown() const { return _referenceShown; } - - /// Sets whether the reference configuration is shown instead of the current configuration. - void setReferenceShown(bool show) { _referenceShown = show; } - - /// Returns true if the homogeneous deformation of the simulation cell is eliminated from the calculated displacement vectors. - bool eliminateCellDeformation() const { return _eliminateCellDeformation; } - - /// Sets whether the homogeneous deformation of the simulation cell is eliminated from the calculated displacement vectors. - void setEliminateCellDeformation(bool enable) { _eliminateCellDeformation = enable; } - - /// Returns true if we assume the particle coordinates are unwrapped when calculating the displacement vectors. - bool assumeUnwrappedCoordinates() const { return _assumeUnwrappedCoordinates; } - - /// Sets we assume the particle coordinates are unwrapped when calculating the displacement vectors. - void setAssumeUnwrappedCoordinates(bool enable) { _assumeUnwrappedCoordinates = enable; } - - /// Returns the cutoff radius used to build the neighbor lists for the analysis. - FloatType cutoff() const { return _cutoff; } - - /// \brief Sets the cutoff radius used to build the neighbor lists for the analysis. - void setCutoff(FloatType newCutoff) { _cutoff = newCutoff; } - - /// Returns whether atomic deformation gradient tensors should be computed and stored. - bool calculateDeformationGradients() const { return _calculateDeformationGradients; } - - /// Sets whether atomic deformation gradient tensors should be computed and stored. - void setCalculateDeformationGradients(bool enableCalculation) { _calculateDeformationGradients = enableCalculation; } - - /// Returns whether atomic strain tensors should be computed and stored. - bool calculateStrainTensors() const { return _calculateStrainTensors; } - - /// Sets whether atomic strain tensors should be computed and stored. - void setCalculateStrainTensors(bool enableCalculation) { _calculateStrainTensors = enableCalculation; } - - /// Returns whether non-affine displacements should be computed and stored. - bool calculateNonaffineSquaredDisplacements() const { return _calculateNonaffineSquaredDisplacements; } - - /// Sets whether non-affine displacements should be computed and stored. - void setCalculateNonaffineSquaredDisplacements(bool enableCalculation) { _calculateNonaffineSquaredDisplacements = enableCalculation; } - - /// Returns whether atomic stretch tensors should be computed and stored. - bool calculateStretchTensors() const { return _calculateStretchTensors; } - - /// Sets whether atomic stretch tensors should be computed and stored. - void setCalculateStretchTensors(bool enableCalculation) { _calculateStretchTensors = enableCalculation; } - - /// Returns whether atomic rotations should be computed and stored. - bool calculateRotations() const { return _calculateRotations; } - - /// Sets whether atomic rotations should be computed and stored. - void setCalculateRotations(bool enableCalculation) { _calculateRotations = enableCalculation; } - - /// Returns whether particles, for which the strain tensor could not be computed, are selected. - bool selectInvalidParticles() const { return _selectInvalidParticles; } - - /// Sets whether particles, for which the strain tensor could not be computed, are selected. - void setSelectInvalidParticles(bool enableSelection) { _selectInvalidParticles = enableSelection; } - /// Returns the computed von Mises shear strain values. const ParticleProperty& shearStrainValues() const { OVITO_CHECK_POINTER(_shearStrainValues.constData()); return *_shearStrainValues; } @@ -114,24 +46,6 @@ /// the strain tensor could not be computed. size_t invalidParticleCount() const { return _numInvalidParticles; } - /// Returns whether to use a reference frame relative to current frame. - bool useReferenceFrameOffset() const { return _useReferenceFrameOffset; } - - /// Sets whether to use a reference frame relative to current frame. - void setUseReferenceFrameOffset(bool useOffset) { _useReferenceFrameOffset = useOffset; } - - /// Returns the absolute frame number from reference file to use when calculating displacement vectors. - int referenceFrameNumber() const { return _referenceFrameNumber; } - - /// Sets the absolute frame number from reference file to use when calculating displacement vectors. - void setReferenceFrameNumber(int frame) { _referenceFrameNumber = frame; } - - /// Returns the relative frame offset to use. - int referenceFrameOffset() const { return _referenceFrameOffset; } - - /// Sets the relative frame offset to use. - void setReferenceFrameOffset(int frameOffset) { _referenceFrameOffset = frameOffset; } - protected: /// Is called when the value of a property of this object has changed. @@ -271,72 +185,55 @@ QExplicitlySharedDataPointer _stretchTensors; /// The reference configuration. - ReferenceField _referenceObject; + DECLARE_MODIFIABLE_REFERENCE_FIELD(DataObject, referenceConfiguration, setReferenceConfiguration); /// Controls the whether the reference configuration is shown instead of the current configuration. - PropertyField _referenceShown; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, referenceShown, setReferenceShown); /// Controls the whether the homogeneous deformation of the simulation cell is eliminated from the calculated displacement vectors. - PropertyField _eliminateCellDeformation; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, eliminateCellDeformation, setEliminateCellDeformation); /// Controls the whether we assume the particle coordinates are unwrapped when calculating the displacement vectors. - PropertyField _assumeUnwrappedCoordinates; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, assumeUnwrappedCoordinates, setAssumeUnwrappedCoordinates); /// Controls the cutoff radius for the neighbor lists. - PropertyField _cutoff; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, cutoff, setCutoff); /// Controls the whether atomic deformation gradient tensors should be computed and stored. - PropertyField _calculateDeformationGradients; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, calculateDeformationGradients, setCalculateDeformationGradients); /// Controls the whether atomic strain tensors should be computed and stored. - PropertyField _calculateStrainTensors; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, calculateStrainTensors, setCalculateStrainTensors); /// Controls the whether non-affine displacements should be computed and stored. - PropertyField _calculateNonaffineSquaredDisplacements; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, calculateNonaffineSquaredDisplacements, setCalculateNonaffineSquaredDisplacements); /// Controls the whether local rotations should be computed and stored. - PropertyField _calculateRotations; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, calculateRotations, setCalculateRotations); /// Controls the whether atomic stretch tensors should be computed and stored. - PropertyField _calculateStretchTensors; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, calculateStretchTensors, setCalculateStretchTensors); /// Controls the whether particles, for which the strain tensor could not be computed, are selected. - PropertyField _selectInvalidParticles; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, selectInvalidParticles, setSelectInvalidParticles); /// Specify reference frame relative to current frame. - PropertyField _useReferenceFrameOffset; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, useReferenceFrameOffset, setUseReferenceFrameOffset); /// Absolute frame number from reference file to use when calculating displacement vectors. - PropertyField _referenceFrameNumber; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, referenceFrameNumber, setReferenceFrameNumber); /// Relative frame offset for reference coordinates. - PropertyField _referenceFrameOffset; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, referenceFrameOffset, setReferenceFrameOffset); /// Counts the number of invalid particles for which the strain tensor could not be computed. size_t _numInvalidParticles; -private: - Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Atomic strain"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_REFERENCE_FIELD(_referenceObject); - DECLARE_PROPERTY_FIELD(_referenceShown); - DECLARE_PROPERTY_FIELD(_eliminateCellDeformation); - DECLARE_PROPERTY_FIELD(_assumeUnwrappedCoordinates); - DECLARE_PROPERTY_FIELD(_cutoff); - DECLARE_PROPERTY_FIELD(_calculateDeformationGradients); - DECLARE_PROPERTY_FIELD(_calculateStrainTensors); - DECLARE_PROPERTY_FIELD(_calculateNonaffineSquaredDisplacements); - DECLARE_PROPERTY_FIELD(_selectInvalidParticles); - DECLARE_PROPERTY_FIELD(_useReferenceFrameOffset); - DECLARE_PROPERTY_FIELD(_referenceFrameNumber); - DECLARE_PROPERTY_FIELD(_referenceFrameOffset); - DECLARE_PROPERTY_FIELD(_calculateRotations); - DECLARE_PROPERTY_FIELD(_calculateStretchTensors); }; OVITO_END_INLINE_NAMESPACE @@ -344,4 +241,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_ATOMIC_STRAIN_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/structural_clustering/StructuralClusteringModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/structural_clustering/StructuralClusteringModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/structural_clustering/StructuralClusteringModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/structural_clustering/StructuralClusteringModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,13 +29,13 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, StructuralClusteringModifier, AsynchronousParticleModifier); -DEFINE_FLAGS_PROPERTY_FIELD(StructuralClusteringModifier, _faceThreshold, "FaceThreshold", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(StructuralClusteringModifier, _rmsdThreshold, "RMSDThreshold", PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(StructuralClusteringModifier, _faceThreshold, "Voronoi face threshold"); -SET_PROPERTY_FIELD_LABEL(StructuralClusteringModifier, _rmsdThreshold, "RMSD threshold"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(StructuralClusteringModifier, _faceThreshold, FloatParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(StructuralClusteringModifier, _rmsdThreshold, FloatParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(StructuralClusteringModifier, AsynchronousParticleModifier); +DEFINE_FLAGS_PROPERTY_FIELD(StructuralClusteringModifier, faceThreshold, "FaceThreshold", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(StructuralClusteringModifier, rmsdThreshold, "RMSDThreshold", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(StructuralClusteringModifier, faceThreshold, "Voronoi face threshold"); +SET_PROPERTY_FIELD_LABEL(StructuralClusteringModifier, rmsdThreshold, "RMSD threshold"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(StructuralClusteringModifier, faceThreshold, FloatParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(StructuralClusteringModifier, rmsdThreshold, FloatParameterUnit, 0); /****************************************************************************** * Constructs the modifier object. @@ -43,8 +43,8 @@ StructuralClusteringModifier::StructuralClusteringModifier(DataSet* dataset) : AsynchronousParticleModifier(dataset), _numClusters(0), _faceThreshold(0.02), _rmsdThreshold(0.1) { - INIT_PROPERTY_FIELD(StructuralClusteringModifier::_faceThreshold); - INIT_PROPERTY_FIELD(StructuralClusteringModifier::_rmsdThreshold); + INIT_PROPERTY_FIELD(faceThreshold); + INIT_PROPERTY_FIELD(rmsdThreshold); } /****************************************************************************** @@ -55,8 +55,8 @@ AsynchronousParticleModifier::propertyChanged(field); // Recompute modifier results when the parameters have been changed. - if( field == PROPERTY_FIELD(StructuralClusteringModifier::_faceThreshold) || - field == PROPERTY_FIELD(StructuralClusteringModifier::_rmsdThreshold)) + if( field == PROPERTY_FIELD(faceThreshold) || + field == PROPERTY_FIELD(rmsdThreshold)) invalidateCachedResults(); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/structural_clustering/StructuralClusteringModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/structural_clustering/StructuralClusteringModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/structural_clustering/StructuralClusteringModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/structural_clustering/StructuralClusteringModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_STRUCTURAL_CLUSTERING_MODIFIER_H -#define __OVITO_STRUCTURAL_CLUSTERING_MODIFIER_H +#pragma once + #include #include @@ -38,18 +38,6 @@ /// Constructor. Q_INVOKABLE StructuralClusteringModifier(DataSet* dataset); - /// Returns the threshold for Voronoi faces. - FloatType faceThreshold() const { return _faceThreshold; } - - /// Sets the threshold for Voronoi faces. - void setFaceThreshold(FloatType t) { _faceThreshold = t; } - - /// Returns how similar two structures need to be. - FloatType rmsdThreshold() const { return _rmsdThreshold; } - - /// Sets how similar two structures need to be. - void setRmsdThreshold(FloatType threshold) { _rmsdThreshold = threshold; } - protected: /// Is called when the value of a property of this object has changed. @@ -110,10 +98,10 @@ }; /// Controls the threshold for Voronoi faces - PropertyField _faceThreshold; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, faceThreshold, setFaceThreshold); /// Controls how similar two structures need to be. - PropertyField _rmsdThreshold; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, rmsdThreshold, setRmsdThreshold); /// This stores the cached results of the modifier. QExplicitlySharedDataPointer _particleClusters; @@ -131,10 +119,6 @@ Q_CLASSINFO("DisplayName", "Structural clustering"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_PROPERTY_FIELD(_faceThreshold); - DECLARE_PROPERTY_FIELD(_numNeighbors); - DECLARE_PROPERTY_FIELD(_rmsdThreshold); }; OVITO_END_INLINE_NAMESPACE @@ -142,4 +126,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_STRUCTURAL_CLUSTERING_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/StructureIdentificationModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/StructureIdentificationModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/StructureIdentificationModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/StructureIdentificationModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,11 +25,11 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, StructureIdentificationModifier, AsynchronousParticleModifier); -DEFINE_VECTOR_REFERENCE_FIELD(StructureIdentificationModifier, _structureTypes, "StructureTypes", ParticleType); -DEFINE_PROPERTY_FIELD(StructureIdentificationModifier, _onlySelectedParticles, "OnlySelectedParticles"); -SET_PROPERTY_FIELD_LABEL(StructureIdentificationModifier, _structureTypes, "Structure types"); -SET_PROPERTY_FIELD_LABEL(StructureIdentificationModifier, _onlySelectedParticles, "Use only selected particles"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(StructureIdentificationModifier, AsynchronousParticleModifier); +DEFINE_VECTOR_REFERENCE_FIELD(StructureIdentificationModifier, structureTypes, "StructureTypes", ParticleType); +DEFINE_PROPERTY_FIELD(StructureIdentificationModifier, onlySelectedParticles, "OnlySelectedParticles"); +SET_PROPERTY_FIELD_LABEL(StructureIdentificationModifier, structureTypes, "Structure types"); +SET_PROPERTY_FIELD_LABEL(StructureIdentificationModifier, onlySelectedParticles, "Use only selected particles"); /****************************************************************************** * Constructs the modifier object. @@ -37,8 +37,8 @@ StructureIdentificationModifier::StructureIdentificationModifier(DataSet* dataset) : AsynchronousParticleModifier(dataset), _onlySelectedParticles(false) { - INIT_PROPERTY_FIELD(StructureIdentificationModifier::_structureTypes); - INIT_PROPERTY_FIELD(StructureIdentificationModifier::_onlySelectedParticles); + INIT_PROPERTY_FIELD(structureTypes); + INIT_PROPERTY_FIELD(onlySelectedParticles); } /****************************************************************************** @@ -61,7 +61,7 @@ AsynchronousParticleModifier::propertyChanged(field); // Recompute results when the parameters have changed. - if(field == PROPERTY_FIELD(StructureIdentificationModifier::_onlySelectedParticles)) + if(field == PROPERTY_FIELD(onlySelectedParticles)) invalidateCachedResults(); } @@ -107,7 +107,7 @@ QVector typesToIdentify(numTypes, true); for(ParticleType* type : structureTypes()) { if(type->id() >= 0 && type->id() < numTypes) - typesToIdentify[type->id()] = type->isEnabled(); + typesToIdentify[type->id()] = type->enabled(); } return typesToIdentify; } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/StructureIdentificationModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/StructureIdentificationModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/StructureIdentificationModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/StructureIdentificationModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_STRUCTURE_IDENTIFICATION_MODIFIER_H -#define __OVITO_STRUCTURE_IDENTIFICATION_MODIFIER_H +#pragma once + #include #include @@ -78,18 +78,9 @@ /// Constructor. StructureIdentificationModifier(DataSet* dataset); - /// Returns the array of structure types that are assigned to the particles by this modifier. - const QVector& structureTypes() const { return _structureTypes; } - /// Returns an array that contains the number of matching particles for each structure type. const QList& structureCounts() const { return _structureCounts; } - /// Returns whether analysis takes only selected particles into account. - bool onlySelectedParticles() const { return _onlySelectedParticles; } - - /// Sets whether analysis only selected particles are taken into account. - void setOnlySelectedParticles(bool onlySelected) { _onlySelectedParticles = onlySelected; } - /// Returns the cached results of the modifier, i.e. the structures assigned to the particles. ParticleProperty* structureData() const { return _structureData.data(); } @@ -131,21 +122,16 @@ QExplicitlySharedDataPointer _structureData; /// Contains the list of structure types recognized by this analysis modifier. - VectorReferenceField _structureTypes; - - /// The number of matching particles for each structure type. - QList _structureCounts; + DECLARE_MODIFIABLE_VECTOR_REFERENCE_FIELD(ParticleType, structureTypes, setStructureTypes); /// Controls whether analysis should take into account only selected particles. - PropertyField _onlySelectedParticles; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, onlySelectedParticles, setOnlySelectedParticles); -private: + /// The number of matching particles for each structure type. + QList _structureCounts; Q_OBJECT OVITO_OBJECT - - DECLARE_VECTOR_REFERENCE_FIELD(_structureTypes); - DECLARE_PROPERTY_FIELD(_onlySelectedParticles); }; OVITO_END_INLINE_NAMESPACE @@ -153,4 +139,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_STRUCTURE_IDENTIFICATION_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/voronoi/VoronoiAnalysisModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/voronoi/VoronoiAnalysisModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/voronoi/VoronoiAnalysisModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/voronoi/VoronoiAnalysisModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,26 +29,29 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, VoronoiAnalysisModifier, AsynchronousParticleModifier); -DEFINE_PROPERTY_FIELD(VoronoiAnalysisModifier, _onlySelected, "OnlySelected"); -DEFINE_PROPERTY_FIELD(VoronoiAnalysisModifier, _useRadii, "UseRadii"); -DEFINE_PROPERTY_FIELD(VoronoiAnalysisModifier, _computeIndices, "ComputeIndices"); -DEFINE_PROPERTY_FIELD(VoronoiAnalysisModifier, _computeBonds, "ComputeBonds"); -DEFINE_PROPERTY_FIELD(VoronoiAnalysisModifier, _edgeCount, "EdgeCount"); -DEFINE_PROPERTY_FIELD(VoronoiAnalysisModifier, _edgeThreshold, "EdgeThreshold"); -DEFINE_PROPERTY_FIELD(VoronoiAnalysisModifier, _faceThreshold, "FaceThreshold"); -DEFINE_FLAGS_REFERENCE_FIELD(VoronoiAnalysisModifier, _bondsDisplay, "BondsDisplay", BondsDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, _onlySelected, "Use only selected particles"); -SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, _useRadii, "Use particle radii"); -SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, _computeIndices, "Compute Voronoi indices"); -SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, _computeBonds, "Generate neighbor bonds"); -SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, _edgeCount, "Maximum edge count"); -SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, _edgeThreshold, "Edge length threshold"); -SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, _faceThreshold, "Face area threshold"); -SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, _bondsDisplay, "Bonds display"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(VoronoiAnalysisModifier, _edgeThreshold, WorldParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(VoronoiAnalysisModifier, _faceThreshold, FloatParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(VoronoiAnalysisModifier, _edgeCount, IntegerParameterUnit, 3, 18); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(VoronoiAnalysisModifier, AsynchronousParticleModifier); +DEFINE_PROPERTY_FIELD(VoronoiAnalysisModifier, onlySelected, "OnlySelected"); +DEFINE_PROPERTY_FIELD(VoronoiAnalysisModifier, useRadii, "UseRadii"); +DEFINE_PROPERTY_FIELD(VoronoiAnalysisModifier, computeIndices, "ComputeIndices"); +DEFINE_PROPERTY_FIELD(VoronoiAnalysisModifier, computeBonds, "ComputeBonds"); +DEFINE_PROPERTY_FIELD(VoronoiAnalysisModifier, edgeCount, "EdgeCount"); +DEFINE_PROPERTY_FIELD(VoronoiAnalysisModifier, edgeThreshold, "EdgeThreshold"); +DEFINE_PROPERTY_FIELD(VoronoiAnalysisModifier, faceThreshold, "FaceThreshold"); +DEFINE_PROPERTY_FIELD(VoronoiAnalysisModifier, relativeFaceThreshold, "RelativeFaceThreshold"); +DEFINE_FLAGS_REFERENCE_FIELD(VoronoiAnalysisModifier, bondsDisplay, "BondsDisplay", BondsDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, onlySelected, "Use only selected particles"); +SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, useRadii, "Use particle radii"); +SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, computeIndices, "Compute Voronoi indices"); +SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, computeBonds, "Generate neighbor bonds"); +SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, edgeCount, "Maximum edge count"); +SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, edgeThreshold, "Edge length threshold"); +SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, faceThreshold, "Absolute face area threshold"); +SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, relativeFaceThreshold, "Relative face area threshold"); +SET_PROPERTY_FIELD_LABEL(VoronoiAnalysisModifier, bondsDisplay, "Bonds display"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(VoronoiAnalysisModifier, edgeThreshold, WorldParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(VoronoiAnalysisModifier, faceThreshold, FloatParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(VoronoiAnalysisModifier, relativeFaceThreshold, PercentParameterUnit, 0, 1); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(VoronoiAnalysisModifier, edgeCount, IntegerParameterUnit, 3, 18); /****************************************************************************** * Constructs the modifier object. @@ -56,19 +59,21 @@ VoronoiAnalysisModifier::VoronoiAnalysisModifier(DataSet* dataset) : AsynchronousParticleModifier(dataset), _onlySelected(false), _computeIndices(false), _edgeCount(6), _useRadii(false), _edgeThreshold(0), _faceThreshold(0), - _simulationBoxVolume(0), _voronoiVolumeSum(0), _maxFaceOrder(0), _computeBonds(false) + _simulationBoxVolume(0), _voronoiVolumeSum(0), _maxFaceOrder(0), _computeBonds(false), + _relativeFaceThreshold(0) { - INIT_PROPERTY_FIELD(VoronoiAnalysisModifier::_onlySelected); - INIT_PROPERTY_FIELD(VoronoiAnalysisModifier::_useRadii); - INIT_PROPERTY_FIELD(VoronoiAnalysisModifier::_computeIndices); - INIT_PROPERTY_FIELD(VoronoiAnalysisModifier::_computeBonds); - INIT_PROPERTY_FIELD(VoronoiAnalysisModifier::_edgeCount); - INIT_PROPERTY_FIELD(VoronoiAnalysisModifier::_edgeThreshold); - INIT_PROPERTY_FIELD(VoronoiAnalysisModifier::_faceThreshold); - INIT_PROPERTY_FIELD(VoronoiAnalysisModifier::_bondsDisplay); + INIT_PROPERTY_FIELD(onlySelected); + INIT_PROPERTY_FIELD(useRadii); + INIT_PROPERTY_FIELD(computeIndices); + INIT_PROPERTY_FIELD(computeBonds); + INIT_PROPERTY_FIELD(edgeCount); + INIT_PROPERTY_FIELD(edgeThreshold); + INIT_PROPERTY_FIELD(faceThreshold); + INIT_PROPERTY_FIELD(relativeFaceThreshold); + INIT_PROPERTY_FIELD(bondsDisplay); // Create the display object for bonds rendering. - _bondsDisplay = new BondsDisplay(dataset); + setBondsDisplay(new BondsDisplay(dataset)); } /****************************************************************************** @@ -93,6 +98,8 @@ // Get simulation cell. SimulationCellObject* inputCell = expectSimulationCell(); + if(inputCell->is2D()) + throwException(tr("The Voronoi modifier does not support 2d simulation cells.")); // Get selection particle property. ParticlePropertyObject* selectionProperty = nullptr; @@ -115,7 +122,8 @@ computeIndices(), computeBonds(), edgeThreshold(), - faceThreshold()); + faceThreshold(), + relativeFaceThreshold()); } /****************************************************************************** @@ -135,16 +143,23 @@ // Add additional factor of 4 because Voronoi cell vertex coordinates are all scaled by factor of 2. FloatType sqEdgeThreshold = _edgeThreshold * _edgeThreshold * 4; - auto processCell = [this, sqEdgeThreshold](voro::voronoicell_neighbor& v, size_t index, QMutex* mutex) { + auto processCell = [this, sqEdgeThreshold](voro::voronoicell_neighbor& v, size_t index, QMutex* mutex) + { // Compute cell volume. double vol = v.volume(); _atomicVolumes->setFloat(index, (FloatType)vol); - // Compute total volume of Voronoi cells. + // Accumulate total volume of Voronoi cells. // Loop is for lock-free write access to shared max counter. double prevVolumeSum = _voronoiVolumeSum; while(!_voronoiVolumeSum.compare_exchange_weak(prevVolumeSum, prevVolumeSum + vol)); + // Compute total surface area of Voronoi cell when relative area threshold is used to + // filter out small faces. + double faceAreaThreshold = _faceThreshold; + if(_relativeFaceThreshold > 0) + faceAreaThreshold = std::max(v.surface_area() * _relativeFaceThreshold, faceAreaThreshold); + int localMaxFaceOrder = 0; // Iterate over the Voronoi faces and their edges. int coordNumber = 0; @@ -170,7 +185,7 @@ faceOrder++; } else faceOrder++; - if(_faceThreshold != 0) { + if(faceAreaThreshold != 0) { Vector3 w(v.pts[3*m] - v.pts[3*i], v.pts[3*m+1] - v.pts[3*i+1], v.pts[3*m+2] - v.pts[3*i+2]); area += d.cross(w).length() / 8; d = w; @@ -180,7 +195,7 @@ k = m; } while(k != i); - if((_faceThreshold == 0 || area > _faceThreshold) && faceOrder >= 3) { + if((faceAreaThreshold == 0 || area > faceAreaThreshold) && faceOrder >= 3) { coordNumber++; if(faceOrder > localMaxFaceOrder) localMaxFaceOrder = faceOrder; @@ -246,8 +261,8 @@ } if(!count) return; - setProgressRange(count); setProgressValue(0); + setProgressMaximum(count); #if 1 voro::c_loop_all cl(voroContainer); voro::voronoicell_neighbor v; @@ -311,8 +326,8 @@ } if(!count) return; - setProgressRange(count); setProgressValue(0); + setProgressMaximum(count); voro::c_loop_all cl(voroContainer); voro::voronoicell_neighbor v; @@ -375,7 +390,7 @@ else { // Prepare the nearest neighbor list generator. NearestNeighborFinder nearestNeighborFinder; - if(!nearestNeighborFinder.prepare(_positions.data(), _simCell, _selection.data(), this)) + if(!nearestNeighborFinder.prepare(_positions.data(), _simCell, _selection.data(), *this)) return; // Squared particle radii (input was just radii). diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/voronoi/VoronoiAnalysisModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/voronoi/VoronoiAnalysisModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/voronoi/VoronoiAnalysisModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/voronoi/VoronoiAnalysisModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VORONOI_ANALYSIS_MODIFIER_H -#define __OVITO_VORONOI_ANALYSIS_MODIFIER_H +#pragma once + #include #include @@ -40,48 +40,6 @@ /// Constructor. Q_INVOKABLE VoronoiAnalysisModifier(DataSet* dataset); - /// Returns whether the modifier takes into account only selected particles. - bool onlySelected() const { return _onlySelected; } - - /// Sets whether the modifier takes into account only selected particles. - void setOnlySelected(bool onlySelected) { _onlySelected = onlySelected; } - - /// Returns whether the modifier takes into account particle radii. - bool useRadii() const { return _useRadii; } - - /// Sets whether the modifier takes into account particle radii. - void setUseRadii(bool useRadii) { _useRadii = useRadii; } - - /// Returns whether the modifier generates nearest neighbor bonds. - bool computeBonds() const { return _computeBonds; } - - /// Sets whether the modifier generates nearest neighbor bonds. - void setComputeBonds(bool computeBonds) { _computeBonds = computeBonds; } - - /// Returns whether the modifier computes Voronoi indices. - bool computeIndices() const { return _computeIndices; } - - /// Sets whether the modifier computes Voronoi indices. - void setComputeIndices(bool computeIndices) { _computeIndices = computeIndices; } - - /// Returns up to which edge count Voronoi indices are being computed. - int edgeCount() const { return _edgeCount; } - - /// Sets up to which edge count Voronoi indices are being computed. - void setEdgeCount(int edgeCount) { _edgeCount = edgeCount; } - - /// Returns the minimum length for an edge to be counted. - FloatType edgeThreshold() const { return _edgeThreshold; } - - /// Sets the minimum length for an edge to be counted. - void setEdgeThreshold(FloatType threshold) { _edgeThreshold = threshold; } - - /// Returns the minimum area for a face to be counted. - FloatType faceThreshold() const { return _faceThreshold; } - - /// Sets the minimum area for a face to be counted. - void setFaceThreshold(FloatType threshold) { _faceThreshold = threshold; } - /// Returns the total volume of the simulation cell computed by the modifier. double simulationBoxVolume() const { return _simulationBoxVolume; } @@ -91,9 +49,6 @@ /// Returns the maximum number of edges of any Voronoi face. int maxFaceOrder() const { return _maxFaceOrder; } - /// Returns the display object that is responsible for rendering the bonds generated by the modifier. - BondsDisplay* bondsDisplay() const { return _bondsDisplay; } - protected: /// Is called when the value of a property of this object has changed. @@ -121,7 +76,7 @@ /// Constructor. VoronoiAnalysisEngine(const TimeInterval& validityInterval, ParticleProperty* positions, ParticleProperty* selection, std::vector&& radii, const SimulationCell& simCell, - int edgeCount, bool computeIndices, bool computeBonds, FloatType edgeThreshold, FloatType faceThreshold) : + int edgeCount, bool computeIndices, bool computeBonds, FloatType edgeThreshold, FloatType faceThreshold, FloatType relativeFaceThreshold) : ComputeEngine(validityInterval), _positions(positions), _selection(selection), @@ -130,6 +85,7 @@ _maxFaceOrder(0), _edgeThreshold(edgeThreshold), _faceThreshold(faceThreshold), + _relativeFaceThreshold(relativeFaceThreshold), _voronoiVolumeSum(0), _simulationBoxVolume(0), _coordinationNumbers(new ParticleProperty(positions->size(), ParticleProperty::CoordinationProperty, 0, true)), @@ -165,6 +121,7 @@ FloatType _edgeThreshold; FloatType _faceThreshold; + FloatType _relativeFaceThreshold; double _simulationBoxVolume; std::atomic _voronoiVolumeSum; std::atomic _maxFaceOrder; @@ -188,25 +145,28 @@ QExplicitlySharedDataPointer _voronoiIndices; /// Controls whether the modifier takes into account only selected particles. - PropertyField _onlySelected; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, onlySelected, setOnlySelected); /// Controls whether the modifier takes into account particle radii. - PropertyField _useRadii; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, useRadii, setUseRadii); /// Controls whether the modifier computes Voronoi indices. - PropertyField _computeIndices; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, computeIndices, setComputeIndices); /// Controls up to which edge count Voronoi indices are being computed. - PropertyField _edgeCount; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, edgeCount, setEdgeCount); /// The minimum length for an edge to be counted. - PropertyField _edgeThreshold; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, edgeThreshold, setEdgeThreshold); /// The minimum area for a face to be counted. - PropertyField _faceThreshold; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, faceThreshold, setFaceThreshold); + + /// The minimum area for a face to be counted relative to the total polyhedron surface. + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, relativeFaceThreshold, setRelativeFaceThreshold); /// Controls whether the modifier output nearest neighbor bonds. - PropertyField _computeBonds; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, computeBonds, setComputeBonds); /// The total volume of the simulation cell computed by the modifier. double _simulationBoxVolume; @@ -218,7 +178,7 @@ int _maxFaceOrder; /// The display object for rendering the bonds generated by the modifier. - ReferenceField _bondsDisplay; + DECLARE_MODIFIABLE_REFERENCE_FIELD(BondsDisplay, bondsDisplay, setBondsDisplay); /// This stores the cached results of the modifier, i.e. the bonds information. QExplicitlySharedDataPointer _bonds; @@ -230,15 +190,6 @@ Q_CLASSINFO("DisplayName", "Voronoi analysis"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_PROPERTY_FIELD(_onlySelected); - DECLARE_PROPERTY_FIELD(_useRadii); - DECLARE_PROPERTY_FIELD(_computeIndices); - DECLARE_PROPERTY_FIELD(_computeBonds); - DECLARE_PROPERTY_FIELD(_edgeCount); - DECLARE_PROPERTY_FIELD(_edgeThreshold); - DECLARE_PROPERTY_FIELD(_faceThreshold); - DECLARE_REFERENCE_FIELD(_bondsDisplay); }; OVITO_END_INLINE_NAMESPACE @@ -246,4 +197,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_VORONOI_ANALYSIS_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,24 +24,25 @@ #include #include #include +#include #include "WignerSeitzAnalysisModifier.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Analysis) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, WignerSeitzAnalysisModifier, AsynchronousParticleModifier); -DEFINE_REFERENCE_FIELD(WignerSeitzAnalysisModifier, _referenceObject, "Reference Configuration", DataObject); -DEFINE_FLAGS_PROPERTY_FIELD(WignerSeitzAnalysisModifier, _eliminateCellDeformation, "EliminateCellDeformation", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(WignerSeitzAnalysisModifier, _useReferenceFrameOffset, "UseReferenceFrameOffet"); -DEFINE_PROPERTY_FIELD(WignerSeitzAnalysisModifier, _referenceFrameNumber, "ReferenceFrameNumber"); -DEFINE_FLAGS_PROPERTY_FIELD(WignerSeitzAnalysisModifier, _referenceFrameOffset, "ReferenceFrameOffset", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(WignerSeitzAnalysisModifier, _perTypeOccupancy, "PerTypeOccupancy", PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(WignerSeitzAnalysisModifier, _referenceObject, "Reference Configuration"); -SET_PROPERTY_FIELD_LABEL(WignerSeitzAnalysisModifier, _eliminateCellDeformation, "Eliminate homogeneous cell deformation"); -SET_PROPERTY_FIELD_LABEL(WignerSeitzAnalysisModifier, _useReferenceFrameOffset, "Use reference frame offset"); -SET_PROPERTY_FIELD_LABEL(WignerSeitzAnalysisModifier, _referenceFrameNumber, "Reference frame number"); -SET_PROPERTY_FIELD_LABEL(WignerSeitzAnalysisModifier, _referenceFrameOffset, "Reference frame offset"); -SET_PROPERTY_FIELD_LABEL(WignerSeitzAnalysisModifier, _perTypeOccupancy, "Output per-type occupancies"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(WignerSeitzAnalysisModifier, _referenceFrameNumber, IntegerParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(WignerSeitzAnalysisModifier, AsynchronousParticleModifier); +DEFINE_REFERENCE_FIELD(WignerSeitzAnalysisModifier, referenceConfiguration, "Reference Configuration", DataObject); +DEFINE_FLAGS_PROPERTY_FIELD(WignerSeitzAnalysisModifier, eliminateCellDeformation, "EliminateCellDeformation", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(WignerSeitzAnalysisModifier, useReferenceFrameOffset, "UseReferenceFrameOffet"); +DEFINE_PROPERTY_FIELD(WignerSeitzAnalysisModifier, referenceFrameNumber, "ReferenceFrameNumber"); +DEFINE_FLAGS_PROPERTY_FIELD(WignerSeitzAnalysisModifier, referenceFrameOffset, "ReferenceFrameOffset", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(WignerSeitzAnalysisModifier, perTypeOccupancy, "PerTypeOccupancy", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(WignerSeitzAnalysisModifier, referenceConfiguration, "Reference Configuration"); +SET_PROPERTY_FIELD_LABEL(WignerSeitzAnalysisModifier, eliminateCellDeformation, "Eliminate homogeneous cell deformation"); +SET_PROPERTY_FIELD_LABEL(WignerSeitzAnalysisModifier, useReferenceFrameOffset, "Use reference frame offset"); +SET_PROPERTY_FIELD_LABEL(WignerSeitzAnalysisModifier, referenceFrameNumber, "Reference frame number"); +SET_PROPERTY_FIELD_LABEL(WignerSeitzAnalysisModifier, referenceFrameOffset, "Reference frame offset"); +SET_PROPERTY_FIELD_LABEL(WignerSeitzAnalysisModifier, perTypeOccupancy, "Output per-type occupancies"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(WignerSeitzAnalysisModifier, referenceFrameNumber, IntegerParameterUnit, 0); /****************************************************************************** * Constructs the modifier object. @@ -52,12 +53,12 @@ _vacancyCount(0), _interstitialCount(0), _perTypeOccupancy(false) { - INIT_PROPERTY_FIELD(WignerSeitzAnalysisModifier::_referenceObject); - INIT_PROPERTY_FIELD(WignerSeitzAnalysisModifier::_eliminateCellDeformation); - INIT_PROPERTY_FIELD(WignerSeitzAnalysisModifier::_useReferenceFrameOffset); - INIT_PROPERTY_FIELD(WignerSeitzAnalysisModifier::_referenceFrameNumber); - INIT_PROPERTY_FIELD(WignerSeitzAnalysisModifier::_referenceFrameOffset); - INIT_PROPERTY_FIELD(WignerSeitzAnalysisModifier::_perTypeOccupancy); + INIT_PROPERTY_FIELD(referenceConfiguration); + INIT_PROPERTY_FIELD(eliminateCellDeformation); + INIT_PROPERTY_FIELD(useReferenceFrameOffset); + INIT_PROPERTY_FIELD(referenceFrameNumber); + INIT_PROPERTY_FIELD(referenceFrameOffset); + INIT_PROPERTY_FIELD(perTypeOccupancy); // Create the file source object that will be responsible for loading // and storing the reference configuration. @@ -153,7 +154,7 @@ refState = linkedFileObj->requestFrame(referenceFrame); } } - else refState = referenceConfiguration()->evaluate(dataset()->animationSettings()->frameToTime(referenceFrame)); + else refState = referenceConfiguration()->evaluateImmediately(PipelineEvalRequest(dataset()->animationSettings()->frameToTime(referenceFrame), false)); // Make sure the obtained reference configuration is valid and ready to use. if(refState.status().type() == PipelineStatus::Error) @@ -185,7 +186,7 @@ // Prepare the closest-point query structure. NearestNeighborFinder neighborTree(0); - if(!neighborTree.prepare(refPositions(), refCell(), nullptr, this)) + if(!neighborTree.prepare(refPositions(), refCell(), nullptr, *this)) return; // Determine the number of components of the occupancy property. @@ -218,7 +219,7 @@ // Assign particles to reference sites. FloatType closestDistanceSq; int particleIndex = 0; - setProgressRange(particleCount); + setProgressMaximum(particleCount); for(const Point3& p : positions()->constPoint3Range()) { int closestIndex = neighborTree.findClosestParticle(_eliminateCellDeformation ? (tm * p) : p, closestDistanceSq); @@ -313,11 +314,11 @@ AsynchronousParticleModifier::propertyChanged(field); // Recompute modifier results when the parameters have changed. - if(field == PROPERTY_FIELD(WignerSeitzAnalysisModifier::_eliminateCellDeformation) - || field == PROPERTY_FIELD(WignerSeitzAnalysisModifier::_perTypeOccupancy) - || field == PROPERTY_FIELD(WignerSeitzAnalysisModifier::_useReferenceFrameOffset) - || field == PROPERTY_FIELD(WignerSeitzAnalysisModifier::_referenceFrameNumber) - || field == PROPERTY_FIELD(WignerSeitzAnalysisModifier::_referenceFrameOffset)) + if(field == PROPERTY_FIELD(eliminateCellDeformation) + || field == PROPERTY_FIELD(perTypeOccupancy) + || field == PROPERTY_FIELD(useReferenceFrameOffset) + || field == PROPERTY_FIELD(referenceFrameNumber) + || field == PROPERTY_FIELD(referenceFrameOffset)) invalidateCachedResults(); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/analysis/wignerseitz/WignerSeitzAnalysisModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_WIGNER_SEITZ_ANALYSIS_MODIFIER_H -#define __OVITO_WIGNER_SEITZ_ANALYSIS_MODIFIER_H +#pragma once + #include #include @@ -39,44 +39,6 @@ /// Constructor. Q_INVOKABLE WignerSeitzAnalysisModifier(DataSet* dataset); - /// Returns the object that contains the reference configuration of the particles - /// used for the Wigner-Seitz analysis. - DataObject* referenceConfiguration() const { return _referenceObject; } - - /// Sets the object that contains the reference configuration of the particles - /// used for the Wigner-Seitz analysis. - void setReferenceConfiguration(DataObject* refConf) { _referenceObject = refConf; } - - /// Returns true if the homogeneous deformation of the simulation cell is eliminated before performing the analysis. - bool eliminateCellDeformation() const { return _eliminateCellDeformation; } - - /// Sets whether the homogeneous deformation of the simulation cell is eliminated before performing the analysis. - void setEliminateCellDeformation(bool enable) { _eliminateCellDeformation = enable; } - - /// Returns whether to use a reference frame relative to current frame. - bool useReferenceFrameOffset() const { return _useReferenceFrameOffset; } - - /// Sets whether to use a reference frame relative to current frame. - void setUseReferenceFrameOffset(bool useOffset) { _useReferenceFrameOffset = useOffset; } - - /// Returns the absolute frame number from reference file to use for the analysis. - int referenceFrameNumber() const { return _referenceFrameNumber; } - - /// Sets the absolute frame number from reference file to use for the analysis. - void setReferenceFrameNumber(int frame) { _referenceFrameNumber = frame; } - - /// Returns the relative frame offset to use. - int referenceFrameOffset() const { return _referenceFrameOffset; } - - /// Sets the relative frame offset to use. - void setReferenceFrameOffset(int frameOffset) { _referenceFrameOffset = frameOffset; } - - /// Returns whether per-type occupancy numbers are computed by the modifier. - bool perTypeOccupancy() const { return _perTypeOccupancy; } - - /// Sets whether per-type occupancy numbers are computed by the modifier. - void setPerTypeOccupancy(bool enable) { _perTypeOccupancy = enable; } - /// Returns the number of vacant sites found during the last analysis run. int vacancyCount() const { return _vacancyCount; } @@ -166,22 +128,22 @@ QExplicitlySharedDataPointer _occupancyNumbers; /// The reference configuration. - ReferenceField _referenceObject; + DECLARE_MODIFIABLE_REFERENCE_FIELD(DataObject, referenceConfiguration, setReferenceConfiguration); /// Controls the whether the homogeneous deformation of the simulation cell is eliminated from the calculated displacement vectors. - PropertyField _eliminateCellDeformation; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, eliminateCellDeformation, setEliminateCellDeformation); /// Specify reference frame relative to current frame. - PropertyField _useReferenceFrameOffset; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, useReferenceFrameOffset, setUseReferenceFrameOffset); /// Absolute frame number from reference file to use when calculating displacement vectors. - PropertyField _referenceFrameNumber; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, referenceFrameNumber, setReferenceFrameNumber); /// Relative frame offset for reference coordinates. - PropertyField _referenceFrameOffset; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, referenceFrameOffset, setReferenceFrameOffset); /// Enable per-type occupancy numbers. - PropertyField _perTypeOccupancy; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, perTypeOccupancy, setPerTypeOccupancy) /// The number of vacant sites found during the last analysis run. int _vacancyCount; @@ -189,20 +151,11 @@ /// The number of interstitial atoms found during the last analysis run. int _interstitialCount; -private: - Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Wigner-Seitz defect analysis"); Q_CLASSINFO("ModifierCategory", "Analysis"); - - DECLARE_REFERENCE_FIELD(_referenceObject); - DECLARE_PROPERTY_FIELD(_eliminateCellDeformation); - DECLARE_PROPERTY_FIELD(_useReferenceFrameOffset); - DECLARE_PROPERTY_FIELD(_referenceFrameNumber); - DECLARE_PROPERTY_FIELD(_referenceFrameOffset); - DECLARE_PROPERTY_FIELD(_perTypeOccupancy); }; OVITO_END_INLINE_NAMESPACE @@ -210,4 +163,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_WIGNER_SEITZ_ANALYSIS_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/AsynchronousParticleModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/AsynchronousParticleModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/AsynchronousParticleModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/AsynchronousParticleModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -32,7 +32,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, AsynchronousParticleModifier, ParticleModifier); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(AsynchronousParticleModifier, ParticleModifier); /****************************************************************************** * Constructs the modifier object. @@ -40,7 +40,7 @@ AsynchronousParticleModifier::AsynchronousParticleModifier(DataSet* dataset) : ParticleModifier(dataset), _cacheValidity(TimeInterval::empty()) { - connect(&_engineWatcher, &FutureWatcher::finished, this, &AsynchronousParticleModifier::computeEngineFinished); + connect(&_engineWatcher, &PromiseWatcher::finished, this, &AsynchronousParticleModifier::computeEngineFinished); } /****************************************************************************** @@ -72,7 +72,7 @@ return; try { - _engineWatcher.unsetFuture(); + _engineWatcher.unsetPromise(); _runningEngine->cancel(); _runningEngine->waitForFinished(); } catch(...) {} @@ -103,7 +103,7 @@ } // Start compute engine. dataset()->container()->taskManager().runTaskAsync(_runningEngine); - _engineWatcher.setFutureInterface(_runningEngine); + _engineWatcher.setPromise(_runningEngine); } } } @@ -163,6 +163,10 @@ // Transfer exception message into evaluation status. _computationStatus = PipelineStatus(PipelineStatus::Error, ex.messages().join(QChar('\n'))); } + catch(const std::bad_alloc&) { + // Transfer exception message into evaluation status. + _computationStatus = PipelineStatus(PipelineStatus::Error, tr("Not enough memory to execute this modifier.")); + } _cacheValidity = _runningEngine->validityInterval(); } else { @@ -171,7 +175,7 @@ } // Reset everything. - _engineWatcher.unsetFuture(); + _engineWatcher.unsetPromise(); _runningEngine.reset(); // Set the new modifier status. @@ -222,7 +226,7 @@ ParticleModifier::propertyChanged(field); // Stop compute engine when modifier is disbaled. - if(field == PROPERTY_FIELD(Modifier::_isEnabled) && !isEnabled()) + if(field == PROPERTY_FIELD(Modifier::isEnabled) && !isEnabled()) stopRunningEngine(); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/AsynchronousParticleModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/AsynchronousParticleModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/AsynchronousParticleModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/AsynchronousParticleModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ASYNC_PARTICLE_MODIFIER_H -#define __OVITO_ASYNC_PARTICLE_MODIFIER_H +#pragma once + #include #include @@ -111,7 +111,7 @@ std::shared_ptr _runningEngine; /// The watcher that is used to monitor the currently running compute engine. - FutureWatcher _engineWatcher; + PromiseWatcher _engineWatcher; /// The validity interval of the cached computation results. TimeInterval _cacheValidity; @@ -119,8 +119,6 @@ /// The status returned by the compute engine. PipelineStatus _computationStatus; -private: - Q_OBJECT OVITO_OBJECT }; @@ -129,4 +127,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_ASYNC_PARTICLE_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/AmbientOcclusionModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/AmbientOcclusionModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/AmbientOcclusionModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/AmbientOcclusionModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,16 +28,16 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Coloring) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, AmbientOcclusionModifier, AsynchronousParticleModifier); -DEFINE_PROPERTY_FIELD(AmbientOcclusionModifier, _intensity, "Intensity"); -DEFINE_PROPERTY_FIELD(AmbientOcclusionModifier, _samplingCount, "SamplingCount"); -DEFINE_PROPERTY_FIELD(AmbientOcclusionModifier, _bufferResolution, "BufferResolution"); -SET_PROPERTY_FIELD_LABEL(AmbientOcclusionModifier, _intensity, "Shading intensity"); -SET_PROPERTY_FIELD_LABEL(AmbientOcclusionModifier, _samplingCount, "Number of exposure samples"); -SET_PROPERTY_FIELD_LABEL(AmbientOcclusionModifier, _bufferResolution, "Render buffer resolution"); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(AmbientOcclusionModifier, _intensity, PercentParameterUnit, 0, 1); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(AmbientOcclusionModifier, _samplingCount, IntegerParameterUnit, 3, 2000); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(AmbientOcclusionModifier, _bufferResolution, IntegerParameterUnit, 1, AmbientOcclusionModifier::MAX_AO_RENDER_BUFFER_RESOLUTION); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(AmbientOcclusionModifier, AsynchronousParticleModifier); +DEFINE_PROPERTY_FIELD(AmbientOcclusionModifier, intensity, "Intensity"); +DEFINE_PROPERTY_FIELD(AmbientOcclusionModifier, samplingCount, "SamplingCount"); +DEFINE_PROPERTY_FIELD(AmbientOcclusionModifier, bufferResolution, "BufferResolution"); +SET_PROPERTY_FIELD_LABEL(AmbientOcclusionModifier, intensity, "Shading intensity"); +SET_PROPERTY_FIELD_LABEL(AmbientOcclusionModifier, samplingCount, "Number of exposure samples"); +SET_PROPERTY_FIELD_LABEL(AmbientOcclusionModifier, bufferResolution, "Render buffer resolution"); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(AmbientOcclusionModifier, intensity, PercentParameterUnit, 0, 1); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(AmbientOcclusionModifier, samplingCount, IntegerParameterUnit, 3, 2000); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(AmbientOcclusionModifier, bufferResolution, IntegerParameterUnit, 1, AmbientOcclusionModifier::MAX_AO_RENDER_BUFFER_RESOLUTION); /****************************************************************************** * Constructs the modifier object. @@ -45,9 +45,9 @@ AmbientOcclusionModifier::AmbientOcclusionModifier(DataSet* dataset) : AsynchronousParticleModifier(dataset), _intensity(0.7f), _samplingCount(40), _bufferResolution(3) { - INIT_PROPERTY_FIELD(AmbientOcclusionModifier::_intensity); - INIT_PROPERTY_FIELD(AmbientOcclusionModifier::_samplingCount); - INIT_PROPERTY_FIELD(AmbientOcclusionModifier::_bufferResolution); + INIT_PROPERTY_FIELD(intensity); + INIT_PROPERTY_FIELD(samplingCount); + INIT_PROPERTY_FIELD(bufferResolution); } /****************************************************************************** @@ -55,7 +55,7 @@ ******************************************************************************/ std::shared_ptr AmbientOcclusionModifier::createEngine(TimePoint time, TimeInterval validityInterval) { - if(Application::instance().headlessMode()) + if(Application::instance()->headlessMode()) throwException(tr("Ambient occlusion modifier requires OpenGL support and cannot be used when program is running in headless mode. " "Please run program on a machine where access to graphics hardware is possible.")); @@ -79,20 +79,21 @@ TimeInterval interval; // Create engine object. Pass all relevant modifier parameters to the engine as well as the input data. - return std::make_shared(validityInterval, resolution, samplingCount(), posProperty->storage(), boundingBox, inputParticleRadii(time, interval)); + return std::make_shared(validityInterval, resolution, samplingCount(), posProperty->storage(), boundingBox, inputParticleRadii(time, interval), dataset()); } /****************************************************************************** * Compute engine constructor. ******************************************************************************/ -AmbientOcclusionModifier::AmbientOcclusionEngine::AmbientOcclusionEngine(const TimeInterval& validityInterval, int resolution, int samplingCount, ParticleProperty* positions, const Box3& boundingBox, std::vector&& particleRadii) : +AmbientOcclusionModifier::AmbientOcclusionEngine::AmbientOcclusionEngine(const TimeInterval& validityInterval, int resolution, int samplingCount, ParticleProperty* positions, const Box3& boundingBox, std::vector&& particleRadii, DataSet* dataset) : ComputeEngine(validityInterval), _resolution(resolution), _samplingCount(samplingCount), _positions(positions), _boundingBox(boundingBox), _brightness(new ParticleProperty(positions->size(), qMetaTypeId(), 1, 0, tr("Brightness"), true)), - _particleRadii(particleRadii) + _particleRadii(particleRadii), + _dataset(dataset) { _offscreenSurface.setFormat(OpenGLSceneRenderer::getDefaultSurfaceFormat()); _offscreenSurface.create(); @@ -103,21 +104,20 @@ ******************************************************************************/ void AmbientOcclusionModifier::AmbientOcclusionEngine::perform() { + if(_boundingBox.isEmpty() || positions()->size() == 0) + throw Exception(tr("Modifier input is degenerate or contains no particles.")); + setProgressText(tr("Computing ambient occlusion")); - // Create a temporary dataset, which is needed to host an instance of AmbientOcclusionRenderer. - OORef dataset(new DataSet()); // Create the AmbientOcclusionRenderer instance. - OORef renderer(new AmbientOcclusionRenderer(dataset, QSize(_resolution, _resolution), _offscreenSurface)); + OORef renderer(new AmbientOcclusionRenderer(_dataset, QSize(_resolution, _resolution), _offscreenSurface)); renderer->startRender(nullptr, nullptr); try { - OVITO_ASSERT(!_boundingBox.isEmpty()); - // The buffered particle geometry used to render the particles. std::shared_ptr particleBuffer; - setProgressRange(_samplingCount); + setProgressMaximum(_samplingCount); for(int sample = 0; sample < _samplingCount; sample++) { if(!setProgressValue(sample)) break; @@ -125,7 +125,7 @@ // Generate lighting direction on unit sphere. FloatType y = (FloatType)sample * 2 / _samplingCount - FloatType(1) + FloatType(1) / _samplingCount; FloatType r = sqrt(FloatType(1) - y * y); - FloatType phi = (FloatType)sample * FLOATTYPE_PI * (3.0f - sqrt(5.0f)); + FloatType phi = (FloatType)sample * FLOATTYPE_PI * (FloatType(3) - sqrt(FloatType(5))); Vector3 dir(cos(phi), y, sin(phi)); // Set up view projection. @@ -133,7 +133,7 @@ projParams.viewMatrix = AffineTransformation::lookAlong(_boundingBox.center(), dir, Vector3(0,0,1)); // Transform bounding box to camera space. - Box3 bb = _boundingBox.transformed(projParams.viewMatrix).centerScale(1.01f); + Box3 bb = _boundingBox.transformed(projParams.viewMatrix).centerScale(FloatType(1.01)); // Complete projection parameters. projParams.aspectRatio = 1; @@ -161,10 +161,10 @@ particleBuffer->render(renderer); } catch(...) { - renderer->endFrame(); + renderer->endFrame(false); throw; } - renderer->endFrame(); + renderer->endFrame(true); // Extract brightness values from rendered image. const QImage image = renderer->image(); @@ -239,7 +239,7 @@ auto c_in = existingColors.cbegin(); for(; c != c_end; ++b, ++c, ++c_in) { FloatType factor = FloatType(1) - intens + (*b); - if(factor < 1.0f) + if(factor < FloatType(1)) *c = factor * (*c_in); else *c = *c_in; @@ -257,8 +257,8 @@ AsynchronousParticleModifier::propertyChanged(field); // Recompute brightness values when the AO parameters have been changed. - if(field == PROPERTY_FIELD(AmbientOcclusionModifier::_samplingCount) || - field == PROPERTY_FIELD(AmbientOcclusionModifier::_bufferResolution)) + if(field == PROPERTY_FIELD(samplingCount) || + field == PROPERTY_FIELD(bufferResolution)) invalidateCachedResults(); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/AmbientOcclusionModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/AmbientOcclusionModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/AmbientOcclusionModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/AmbientOcclusionModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_AMBIENT_OCCLUSION_MODIFIER_H -#define __OVITO_AMBIENT_OCCLUSION_MODIFIER_H +#pragma once + #include #include @@ -44,7 +44,7 @@ public: /// Constructor. - AmbientOcclusionEngine(const TimeInterval& validityInterval, int resolution, int samplingCount, ParticleProperty* positions, const Box3& boundingBox, std::vector&& particleRadii); + AmbientOcclusionEngine(const TimeInterval& validityInterval, int resolution, int samplingCount, ParticleProperty* positions, const Box3& boundingBox, std::vector&& particleRadii, DataSet* dataset); /// Computes the modifier's results and stores them in this object for later retrieval. virtual void perform() override; @@ -57,6 +57,7 @@ private: + DataSet* _dataset; int _resolution; int _samplingCount; QExplicitlySharedDataPointer _positions; @@ -71,24 +72,6 @@ /// Constructor. Q_INVOKABLE AmbientOcclusionModifier(DataSet* dataset); - /// Returns the intensity of the shading. - FloatType intensity() const { return _intensity; } - - /// Sets the intensity of the shading. - void setIntensity(FloatType newIntensity) { _intensity = newIntensity; } - - /// Returns the amount of spherical sampling points used in the shading computation. - int samplingCount() const { return _samplingCount; } - - /// Sets the amount of spherical sampling points used in the shading computation. - void setSamplingCount(int count) { _samplingCount = count; } - - /// Returns the buffer resolution level. - int bufferResolution() const { return _bufferResolution; } - - /// Sets the buffer resolution level. - void setBufferResolution(int res) { _bufferResolution = res; } - protected: /// Is called when the value of a property of this object has changed. @@ -109,13 +92,13 @@ QExplicitlySharedDataPointer _brightnessValues; /// This controls the intensity of the shading effect. - PropertyField _intensity; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, intensity, setIntensity); /// Controls the quality of the lighting computation. - PropertyField _samplingCount; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, samplingCount, setSamplingCount); /// Controls the resolution of the offscreen rendering buffer. - PropertyField _bufferResolution; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, bufferResolution, setBufferResolution); private: @@ -124,10 +107,6 @@ Q_CLASSINFO("DisplayName", "Ambient occlusion"); Q_CLASSINFO("ModifierCategory", "Coloring"); - - DECLARE_PROPERTY_FIELD(_intensity); - DECLARE_PROPERTY_FIELD(_samplingCount); - DECLARE_PROPERTY_FIELD(_bufferResolution); }; OVITO_END_INLINE_NAMESPACE @@ -135,4 +114,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_AMBIENT_OCCLUSION_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/AmbientOcclusionRenderer.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/AmbientOcclusionRenderer.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/AmbientOcclusionRenderer.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/AmbientOcclusionRenderer.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,7 +25,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Coloring) OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(Particles, AmbientOcclusionRenderer, OpenGLSceneRenderer); +IMPLEMENT_OVITO_OBJECT(AmbientOcclusionRenderer, OpenGLSceneRenderer); /****************************************************************************** * Prepares the renderer for rendering and sets the data set that is being rendered. @@ -40,19 +40,19 @@ _offscreenContext.reset(new QOpenGLContext()); _offscreenContext->setFormat(OpenGLSceneRenderer::getDefaultSurfaceFormat()); if(!_offscreenContext->create()) - dataset->throwException(tr("Failed to create OpenGL context.")); + throwException(tr("Failed to create OpenGL context.")); // Check offscreen buffer. if(!_offscreenSurface.isValid()) - dataset->throwException(tr("Failed to create offscreen rendering surface.")); + throwException(tr("Failed to create offscreen rendering surface.")); // Make the context current. if(!_offscreenContext->makeCurrent(&_offscreenSurface)) - dataset->throwException(tr("Failed to make OpenGL context current.")); + throwException(tr("Failed to make OpenGL context current.")); // Check OpenGL version. if(_offscreenContext->format().majorVersion() < OVITO_OPENGL_MINIMUM_VERSION_MAJOR || (_offscreenContext->format().majorVersion() == OVITO_OPENGL_MINIMUM_VERSION_MAJOR && _offscreenContext->format().minorVersion() < OVITO_OPENGL_MINIMUM_VERSION_MINOR)) { - dataset->throwException(tr( + throwException(tr( "The OpenGL implementation available on this system does not support OpenGL version %4.%5 or newer.\n\n" "Ovito requires modern graphics hardware to accelerate 3d rendering. You current system configuration is not compatible with Ovito.\n\n" "To avoid this error message, please install the newest graphics driver, or upgrade your graphics card.\n\n" @@ -74,11 +74,11 @@ framebufferFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); _framebufferObject.reset(new QOpenGLFramebufferObject(_resolution, framebufferFormat)); if(!_framebufferObject->isValid()) - dataset->throwException(tr("Failed to create OpenGL framebuffer object for offscreen rendering.")); + throwException(tr("Failed to create OpenGL framebuffer object for offscreen rendering.")); // Bind OpenGL buffer. if(!_framebufferObject->bind()) - dataset->throwException(tr("Failed to bind OpenGL framebuffer object for offscreen rendering.")); + throwException(tr("Failed to bind OpenGL framebuffer object for offscreen rendering.")); return true; } @@ -90,7 +90,7 @@ { // Make GL context current. if(!_offscreenContext->makeCurrent(&_offscreenSurface)) - vp->throwException(tr("Failed to make OpenGL context current.")); + throwException(tr("Failed to make OpenGL context current.")); OpenGLSceneRenderer::beginFrame(time, params, vp); @@ -106,23 +106,25 @@ /****************************************************************************** * This method is called after renderFrame() has been called. ******************************************************************************/ -void AmbientOcclusionRenderer::endFrame() +void AmbientOcclusionRenderer::endFrame(bool renderSuccessful) { - // Flush the contents to the FBO before extracting image. - _offscreenContext->swapBuffers(&_offscreenSurface); - - // Fetch rendered image from OpenGL framebuffer. - QSize size = _framebufferObject->size(); - if(_image.isNull() || _image.size() != size) - _image = QImage(size, QImage::Format_ARGB32); - while(glGetError() != GL_NO_ERROR); - glReadPixels(0, 0, size.width(), size.height(), GL_BGRA, GL_UNSIGNED_BYTE, _image.bits()); - if(glGetError() != GL_NO_ERROR) { - glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_BYTE, _image.bits()); - _image = _image.rgbSwapped(); + if(renderSuccessful) { + // Flush the contents to the FBO before extracting image. + _offscreenContext->swapBuffers(&_offscreenSurface); + + // Fetch rendered image from OpenGL framebuffer. + QSize size = _framebufferObject->size(); + if(_image.isNull() || _image.size() != size) + _image = QImage(size, QImage::Format_ARGB32); + while(glGetError() != GL_NO_ERROR); + glReadPixels(0, 0, size.width(), size.height(), GL_BGRA, GL_UNSIGNED_BYTE, _image.bits()); + if(glGetError() != GL_NO_ERROR) { + glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_BYTE, _image.bits()); + _image = _image.rgbSwapped(); + } } - OpenGLSceneRenderer::endFrame(); + OpenGLSceneRenderer::endFrame(renderSuccessful); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/AmbientOcclusionRenderer.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/AmbientOcclusionRenderer.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/AmbientOcclusionRenderer.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/AmbientOcclusionRenderer.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_AMBIENT_OCCLUSION_RENDERER_H -#define __OVITO_AMBIENT_OCCLUSION_RENDERER_H +#pragma once + #include #include @@ -49,7 +49,7 @@ virtual void beginFrame(TimePoint time, const ViewProjectionParameters& params, Viewport* vp) override; /// This method is called after renderFrame() has been called. - virtual void endFrame() override; + virtual void endFrame(bool renderSuccessful) override; /// Is called after rendering has finished. virtual void endRender() override; @@ -93,4 +93,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_AMBIENT_OCCLUSION_RENDERER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/AssignColorModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/AssignColorModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/AssignColorModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/AssignColorModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,22 +25,22 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Coloring) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, AssignColorModifier, ParticleModifier); -DEFINE_FLAGS_REFERENCE_FIELD(AssignColorModifier, _colorCtrl, "Color", Controller, PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(AssignColorModifier, _keepSelection, "KeepSelection"); -SET_PROPERTY_FIELD_LABEL(AssignColorModifier, _colorCtrl, "Color"); -SET_PROPERTY_FIELD_LABEL(AssignColorModifier, _keepSelection, "Keep selection"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(AssignColorModifier, ParticleModifier); +DEFINE_FLAGS_REFERENCE_FIELD(AssignColorModifier, colorController, "Color", Controller, PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(AssignColorModifier, keepSelection, "KeepSelection"); +SET_PROPERTY_FIELD_LABEL(AssignColorModifier, colorController, "Color"); +SET_PROPERTY_FIELD_LABEL(AssignColorModifier, keepSelection, "Keep selection"); /****************************************************************************** * Constructs the modifier object. ******************************************************************************/ AssignColorModifier::AssignColorModifier(DataSet* dataset) : ParticleModifier(dataset), _keepSelection(false) { - INIT_PROPERTY_FIELD(AssignColorModifier::_colorCtrl); - INIT_PROPERTY_FIELD(AssignColorModifier::_keepSelection); + INIT_PROPERTY_FIELD(colorController); + INIT_PROPERTY_FIELD(keepSelection); - _colorCtrl = ControllerManager::instance().createColorController(dataset); - _colorCtrl->setColorValue(0, Color(0.3f, 0.3f, 1.0f)); + setColorController(ControllerManager::createColorController(dataset)); + colorController()->setColorValue(0, Color(0.3f, 0.3f, 1.0f)); } /****************************************************************************** @@ -49,7 +49,7 @@ TimeInterval AssignColorModifier::modifierValidity(TimePoint time) { TimeInterval interval = Modifier::modifierValidity(time); - interval.intersect(_colorCtrl->validityInterval(time)); + if(colorController()) interval.intersect(colorController()->validityInterval(time)); return interval; } @@ -66,8 +66,8 @@ // Get the color to be assigned. Color color(1,1,1); - if(_colorCtrl) - _colorCtrl->getColorValue(time, color, validityInterval); + if(colorController()) + colorController()->getColorValue(time, color, validityInterval); if(selProperty) { OVITO_ASSERT(colorProperty->size() == selProperty->size()); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/AssignColorModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/AssignColorModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/AssignColorModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/AssignColorModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_ASSIGN_COLOR_MODIFIER_H -#define __OVITO_ASSIGN_COLOR_MODIFIER_H +#pragma once + #include #include @@ -43,24 +43,10 @@ virtual TimeInterval modifierValidity(TimePoint time) override; /// Returns the color that is assigned to the selected atoms. - Color color() const { return _colorCtrl ? _colorCtrl->currentColorValue() : Color(0,0,0); } + Color color() const { return colorController() ? colorController()->currentColorValue() : Color(0,0,0); } /// Sets the color that is assigned to the selected atoms. - void setColor(const Color& color) { if(_colorCtrl) _colorCtrl->setCurrentColorValue(color); } - - /// Returns the controller for the color that is assigned to the selected atoms. - Controller* colorController() const { return _colorCtrl; } - - /// Sets the controller for the color that is assigned to the selected atoms. - void setColorController(Controller* ctrl) { _colorCtrl = ctrl; } - - /// Returns whether the input particle selection is preserved. - /// If false, the selection is cleared by the modifier. - bool keepSelection() const { return _keepSelection; } - - /// Sets whether the input particle selection is preserved. - /// If false, the selection is cleared by the modifier. - void setKeepSelection(bool keep) { _keepSelection = keep; } + void setColor(const Color& color) { if(colorController()) colorController()->setCurrentColorValue(color); } protected: @@ -68,22 +54,17 @@ virtual PipelineStatus modifyParticles(TimePoint time, TimeInterval& validityInterval) override; /// This controller stores the constant color to be assigned to all atoms. - ReferenceField _colorCtrl; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, colorController, setColorController); /// Controls whether the input particle selection is preserved. /// If false, the selection is cleared by the modifier. - PropertyField _keepSelection; - -private: + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, keepSelection, setKeepSelection); Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Assign color"); Q_CLASSINFO("ModifierCategory", "Coloring"); - - DECLARE_REFERENCE_FIELD(_colorCtrl); - DECLARE_PROPERTY_FIELD(_keepSelection); }; OVITO_END_INLINE_NAMESPACE @@ -91,4 +72,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_ASSIGN_COLOR_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/ColorCodingModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/ColorCodingModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/ColorCodingModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/ColorCodingModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,38 +27,40 @@ #include #include #include +#include +#include #include "ColorCodingModifier.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Coloring) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ColorCodingModifier, ParticleModifier); -DEFINE_REFERENCE_FIELD(ColorCodingModifier, _startValueCtrl, "StartValue", Controller); -DEFINE_REFERENCE_FIELD(ColorCodingModifier, _endValueCtrl, "EndValue", Controller); -DEFINE_REFERENCE_FIELD(ColorCodingModifier, _colorGradient, "ColorGradient", ColorCodingGradient); -DEFINE_PROPERTY_FIELD(ColorCodingModifier, _colorOnlySelected, "SelectedOnly"); -DEFINE_PROPERTY_FIELD(ColorCodingModifier, _keepSelection, "KeepSelection"); -DEFINE_PROPERTY_FIELD(ColorCodingModifier, _sourceParticleProperty, "SourceProperty"); -DEFINE_PROPERTY_FIELD(ColorCodingModifier, _sourceBondProperty, "SourceBondProperty"); -DEFINE_PROPERTY_FIELD(ColorCodingModifier, _colorApplicationMode, "ColorApplicationMode"); -SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, _startValueCtrl, "Start value"); -SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, _endValueCtrl, "End value"); -SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, _colorGradient, "Color gradient"); -SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, _colorOnlySelected, "Color only selected particles/bonds"); -SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, _keepSelection, "Keep selection"); -SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, _sourceParticleProperty, "Source property"); -SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, _sourceBondProperty, "Source property"); -SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, _colorApplicationMode, "Target"); - -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ColorCodingGradient, RefTarget); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ColorCodingHSVGradient, ColorCodingGradient); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ColorCodingGrayscaleGradient, ColorCodingGradient); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ColorCodingHotGradient, ColorCodingGradient); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ColorCodingJetGradient, ColorCodingGradient); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ColorCodingBlueWhiteRedGradient, ColorCodingGradient); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ColorCodingViridisGradient, ColorCodingGradient); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ColorCodingMagmaGradient, ColorCodingGradient); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ColorCodingImageGradient, ColorCodingGradient); -DEFINE_PROPERTY_FIELD(ColorCodingImageGradient, _image, "Image"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ColorCodingModifier, ParticleModifier); +DEFINE_REFERENCE_FIELD(ColorCodingModifier, startValueController, "StartValue", Controller); +DEFINE_REFERENCE_FIELD(ColorCodingModifier, endValueController, "EndValue", Controller); +DEFINE_REFERENCE_FIELD(ColorCodingModifier, colorGradient, "ColorGradient", ColorCodingGradient); +DEFINE_PROPERTY_FIELD(ColorCodingModifier, colorOnlySelected, "SelectedOnly"); +DEFINE_PROPERTY_FIELD(ColorCodingModifier, keepSelection, "KeepSelection"); +DEFINE_PROPERTY_FIELD(ColorCodingModifier, sourceParticleProperty, "SourceProperty"); +DEFINE_PROPERTY_FIELD(ColorCodingModifier, sourceBondProperty, "SourceBondProperty"); +DEFINE_PROPERTY_FIELD(ColorCodingModifier, colorApplicationMode, "ColorApplicationMode"); +SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, startValueController, "Start value"); +SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, endValueController, "End value"); +SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, colorGradient, "Color gradient"); +SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, colorOnlySelected, "Color only selected particles/bonds"); +SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, keepSelection, "Keep selection"); +SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, sourceParticleProperty, "Source property"); +SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, sourceBondProperty, "Source property"); +SET_PROPERTY_FIELD_LABEL(ColorCodingModifier, colorApplicationMode, "Target"); + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ColorCodingGradient, RefTarget); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ColorCodingHSVGradient, ColorCodingGradient); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ColorCodingGrayscaleGradient, ColorCodingGradient); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ColorCodingHotGradient, ColorCodingGradient); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ColorCodingJetGradient, ColorCodingGradient); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ColorCodingBlueWhiteRedGradient, ColorCodingGradient); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ColorCodingViridisGradient, ColorCodingGradient); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ColorCodingMagmaGradient, ColorCodingGradient); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ColorCodingImageGradient, ColorCodingGradient); +DEFINE_PROPERTY_FIELD(ColorCodingImageGradient, image, "Image"); /****************************************************************************** * Constructs the modifier object. @@ -66,18 +68,18 @@ ColorCodingModifier::ColorCodingModifier(DataSet* dataset) : ParticleModifier(dataset), _colorOnlySelected(false), _keepSelection(false), _colorApplicationMode(Particles) { - INIT_PROPERTY_FIELD(ColorCodingModifier::_startValueCtrl); - INIT_PROPERTY_FIELD(ColorCodingModifier::_endValueCtrl); - INIT_PROPERTY_FIELD(ColorCodingModifier::_colorGradient); - INIT_PROPERTY_FIELD(ColorCodingModifier::_colorOnlySelected); - INIT_PROPERTY_FIELD(ColorCodingModifier::_keepSelection); - INIT_PROPERTY_FIELD(ColorCodingModifier::_sourceParticleProperty); - INIT_PROPERTY_FIELD(ColorCodingModifier::_sourceBondProperty); - INIT_PROPERTY_FIELD(ColorCodingModifier::_colorApplicationMode); - - _colorGradient = new ColorCodingHSVGradient(dataset); - _startValueCtrl = ControllerManager::instance().createFloatController(dataset); - _endValueCtrl = ControllerManager::instance().createFloatController(dataset); + INIT_PROPERTY_FIELD(startValueController); + INIT_PROPERTY_FIELD(endValueController); + INIT_PROPERTY_FIELD(colorGradient); + INIT_PROPERTY_FIELD(colorOnlySelected); + INIT_PROPERTY_FIELD(keepSelection); + INIT_PROPERTY_FIELD(sourceParticleProperty); + INIT_PROPERTY_FIELD(sourceBondProperty); + INIT_PROPERTY_FIELD(colorApplicationMode); + + setColorGradient(new ColorCodingHSVGradient(dataset)); + setStartValueController(ControllerManager::createFloatController(dataset)); + setEndValueController(ControllerManager::createFloatController(dataset)); } /****************************************************************************** @@ -92,7 +94,7 @@ QSettings settings; settings.beginGroup(ColorCodingModifier::OOType.plugin()->pluginId()); settings.beginGroup(ColorCodingModifier::OOType.name()); - QString typeString = settings.value(PROPERTY_FIELD(ColorCodingModifier::_colorGradient).identifier()).toString(); + QString typeString = settings.value(PROPERTY_FIELD(colorGradient).identifier()).toString(); if(!typeString.isEmpty()) { try { OvitoObjectType* gradientType = OvitoObjectType::decodeFromString(typeString); @@ -111,8 +113,8 @@ TimeInterval ColorCodingModifier::modifierValidity(TimePoint time) { TimeInterval interval = ParticleModifier::modifierValidity(time); - if(_startValueCtrl) interval.intersect(_startValueCtrl->validityInterval(time)); - if(_endValueCtrl) interval.intersect(_endValueCtrl->validityInterval(time)); + if(startValueController()) interval.intersect(startValueController()->validityInterval(time)); + if(endValueController()) interval.intersect(endValueController()->validityInterval(time)); return interval; } @@ -178,7 +180,7 @@ if(sourceParticleProperty().vectorComponent() >= (int)property->componentCount()) throwException(tr("The vector component is out of range. The particle property '%1' contains only %2 values per particle.").arg(sourceParticleProperty().name()).arg(property->componentCount())); vecComponent = std::max(0, sourceParticleProperty().vectorComponent()); - + // Get the particle selection property if enabled by the user. if(colorOnlySelected()) { if(ParticlePropertyObject* selPropertyObj = inputStandardProperty(ParticleProperty::SelectionProperty)) { @@ -226,8 +228,8 @@ // Get modifier's parameter values. FloatType startValue = 0, endValue = 0; - if(_startValueCtrl) startValue = _startValueCtrl->getFloatValue(time, validityInterval); - if(_endValueCtrl) endValue = _endValueCtrl->getFloatValue(time, validityInterval); + if(startValueController()) startValue = startValueController()->getFloatValue(time, validityInterval); + if(endValueController()) endValue = endValueController()->getFloatValue(time, validityInterval); // Clamp to finite range. if(!std::isfinite(startValue)) startValue = std::numeric_limits::min(); @@ -324,19 +326,14 @@ } /****************************************************************************** -* Sets the start and end value to the minimum and maximum value -* in the selected particle or bond property. +* Determines the range of values in the input data for the selected property. ******************************************************************************/ -bool ColorCodingModifier::adjustRange() +bool ColorCodingModifier::determinePropertyValueRange(const PipelineFlowState& state, FloatType& min, FloatType& max) { - // Determine the minimum and maximum values of the selected property. - - // Get the input property. - PipelineFlowState inputState = getModifierInput(); PropertyBase* property; int vecComponent; if(colorApplicationMode() != ColorCodingModifier::Bonds) { - ParticlePropertyObject* propertyObj = sourceParticleProperty().findInState(inputState); + ParticlePropertyObject* propertyObj = sourceParticleProperty().findInState(state); if(!propertyObj) return false; property = propertyObj->storage(); @@ -345,7 +342,7 @@ vecComponent = std::max(0, sourceParticleProperty().vectorComponent()); } else { - BondPropertyObject* propertyObj = sourceBondProperty().findInState(inputState); + BondPropertyObject* propertyObj = sourceBondProperty().findInState(state); if(!propertyObj) return false; property = propertyObj->storage(); @@ -382,6 +379,29 @@ if(!std::isfinite(minValue)) minValue = std::numeric_limits::min(); if(!std::isfinite(maxValue)) maxValue = std::numeric_limits::max(); + if(minValue < min) min = minValue; + if(maxValue > min) max = maxValue; + + return true; +} + +/****************************************************************************** +* Sets the start and end value to the minimum and maximum value +* in the selected particle or bond property. +* Returns true if successful. +******************************************************************************/ +bool ColorCodingModifier::adjustRange() +{ + // Get the input data. + PipelineFlowState inputState = getModifierInput(); + + // Determine the minimum and maximum values of the selected property. + FloatType minValue = std::numeric_limits::max(); + FloatType maxValue = std::numeric_limits::min(); + if(!determinePropertyValueRange(inputState, minValue, maxValue)) + return false; + + // Adjust range of color coding. if(startValueController()) startValueController()->setCurrentFloatValue(minValue); if(endValueController()) @@ -391,6 +411,54 @@ } /****************************************************************************** +* Sets the start and end value to the minimum and maximum value of the selected +* particle or bond property determined over the entire animation sequence. +******************************************************************************/ +bool ColorCodingModifier::adjustRangeGlobal(TaskManager& taskManager) +{ + ViewportSuspender noVPUpdates(this); + SynchronousTask task(taskManager); + + TimeInterval interval = dataset()->animationSettings()->animationInterval(); + task.setProgressMaximum(interval.duration() / dataset()->animationSettings()->ticksPerFrame() + 1); + + FloatType minValue = std::numeric_limits::max(); + FloatType maxValue = std::numeric_limits::min(); + + TimePoint oldAnimTime = dataset()->animationSettings()->time(); + for(TimePoint time = interval.start(); time <= interval.end(); time += dataset()->animationSettings()->ticksPerFrame()) { + if(task.isCanceled()) break; + task.setProgressText(tr("Analyzing frame %1").arg(dataset()->animationSettings()->timeToFrame(time))); + dataset()->animationSettings()->setTime(time); + + for(ModifierApplication* modApp : modifierApplications()) { + + PipelineObject* pipelineObj = modApp->pipelineObject(); + if(!pipelineObj) continue; + + Future stateFuture = pipelineObj->evaluateAsync(PipelineEvalRequest(time, false, modApp, false)); + if(!taskManager.waitForTask(stateFuture)) + break; + + determinePropertyValueRange(stateFuture.result(), minValue, maxValue); + } + task.setProgressValue(task.progressValue() + 1); + } + dataset()->animationSettings()->setTime(oldAnimTime); + + if(!task.isCanceled()) { + // Adjust range of color coding. + if(startValueController() && minValue != std::numeric_limits::max()) + startValueController()->setCurrentFloatValue(minValue); + if(endValueController() && maxValue != std::numeric_limits::min()) + endValueController()->setCurrentFloatValue(maxValue); + + return true; + } + return false; +} + +/****************************************************************************** * Saves the class' contents to the given stream. ******************************************************************************/ void ColorCodingModifier::saveToStream(ObjectSaveStream& stream) diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/ColorCodingModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/ColorCodingModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/ColorCodingModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/ColorCodingModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COLOR_CODING_MODIFIER_H -#define __OVITO_COLOR_CODING_MODIFIER_H +#pragma once + #include #include @@ -244,7 +244,7 @@ /// Constructor. Q_INVOKABLE ColorCodingImageGradient(DataSet* dataset) : ColorCodingGradient(dataset) { - INIT_PROPERTY_FIELD(ColorCodingImageGradient::_image); + INIT_PROPERTY_FIELD(image); } /// \brief Converts a scalar value to a color value. @@ -252,25 +252,17 @@ /// \return The color that visualizes the given scalar value. virtual Color valueToColor(FloatType t) override; - /// Changes the image to be used for mapping values to colors. - void setImage(const QImage& image) { _image = image; } - /// Loads the given image file from disk. void loadImage(const QString& filename); - /// Returns the image being used for mapping values to colors. - const QImage& image() const { return _image; } - private: /// The user-defined color map image. - PropertyField _image; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QImage, image, setImage); Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "User image"); - - DECLARE_PROPERTY_FIELD(_image); }; @@ -301,69 +293,26 @@ /// Asks the modifier for its validity interval at the given time. virtual TimeInterval modifierValidity(TimePoint time) override; - /// Sets the source particle property that is used for coloring of particles. - void setSourceParticleProperty(const ParticlePropertyReference& prop) { _sourceParticleProperty = prop; } - - /// Returns the source particle property that is used for coloring of particles. - const ParticlePropertyReference& sourceParticleProperty() const { return _sourceParticleProperty; } - - /// Sets the source bond property that is used for coloring of bonds. - void setSourceBondProperty(const BondPropertyReference& prop) { _sourceBondProperty = prop; } - - /// Returns the source bond property that is used for coloring of bonds. - const BondPropertyReference& sourceBondProperty() const { return _sourceBondProperty; } - /// Returns the range start value. - FloatType startValue() const { return _startValueCtrl ? _startValueCtrl->currentFloatValue() : 0; } + FloatType startValue() const { return startValueController() ? startValueController()->currentFloatValue() : 0; } /// Sets the range start value. - void setStartValue(FloatType value) { if(_startValueCtrl) _startValueCtrl->setCurrentFloatValue(value); } - - /// Returns the controller for the range start value. - Controller* startValueController() const { return _startValueCtrl; } - - /// Sets the controller for the range start value. - void setStartValueController(Controller* ctrl) { _startValueCtrl = ctrl; } + void setStartValue(FloatType value) { if(startValueController()) startValueController()->setCurrentFloatValue(value); } /// Returns the range end value. - FloatType endValue() const { return _endValueCtrl ? _endValueCtrl->currentFloatValue() : 0; } + FloatType endValue() const { return endValueController() ? endValueController()->currentFloatValue() : 0; } /// Sets the range end value. - void setEndValue(FloatType value) { if(_endValueCtrl) _endValueCtrl->setCurrentFloatValue(value); } - - /// Returns the controller for the range end value. - Controller* endValueController() const { return _endValueCtrl; } - - /// Sets the controller for the range end value. - void setEndValueController(Controller* ctrl) { _endValueCtrl = ctrl; } - - /// Returns the color gradient used by the modifier to convert scalar atom properties to colors. - ColorCodingGradient* colorGradient() const { return _colorGradient; } + void setEndValue(FloatType value) { if(endValueController()) endValueController()->setCurrentFloatValue(value); } - /// Sets the color gradient for the modifier to convert scalar atom properties to colors. - void setColorGradient(ColorCodingGradient* gradient) { _colorGradient = gradient; } - - /// Returns whether the modifier assigns a color only to selected particles. - bool colorOnlySelected() const { return _colorOnlySelected; } - - /// Sets whether the modifier should assign a color only to selected particles. - void setColorOnlySelected(bool colorOnlySelected) { _colorOnlySelected = colorOnlySelected; } - - /// Returns whether the input particle selection is preserved by the modifier. - bool keepSelection() const { return _keepSelection; } - - /// Sets whether the input particle selection should be preserved by the modifier. - void setKeepSelection(bool keepSel) { _keepSelection = keepSel; } - - /// Returns what is being assigned colors by the modifier. - ColorApplicationMode colorApplicationMode() const { return _colorApplicationMode; } - - /// Sets what is being assigned colors by the modifier. - void setColorApplicationMode(ColorApplicationMode mode) { _colorApplicationMode = mode; } + /// Sets the start and end value to the minimum and maximum value of the selected particle or bond property + /// determined over the entire animation sequence. + bool adjustRangeGlobal(TaskManager& taskManager); public Q_SLOTS: - /// Sets the start and end value to the minimum and maximum value in the selected data channel. + /// Sets the start and end value to the minimum and maximum value of the selected particle or bond property. + /// Returns true if successful. bool adjustRange(); protected: @@ -383,47 +332,41 @@ /// Modifies the particles. virtual PipelineStatus modifyParticles(TimePoint time, TimeInterval& validityInterval) override; + /// Determines the range of values in the input data for the selected property. + bool determinePropertyValueRange(const PipelineFlowState& state, FloatType& min, FloatType& max); + +private: + /// This controller stores the start value of the color scale. - ReferenceField _startValueCtrl; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, startValueController, setStartValueController); /// This controller stores the end value of the color scale. - ReferenceField _endValueCtrl; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, endValueController, setEndValueController); /// This object converts scalar atom properties to colors. - ReferenceField _colorGradient; + DECLARE_MODIFIABLE_REFERENCE_FIELD(ColorCodingGradient, colorGradient, setColorGradient); /// The particle type property that is used as source for the coloring. - PropertyField _sourceParticleProperty; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ParticlePropertyReference, sourceParticleProperty, setSourceParticleProperty); /// The bond type property that is used as source for the coloring. - PropertyField _sourceBondProperty; + DECLARE_MODIFIABLE_PROPERTY_FIELD(BondPropertyReference, sourceBondProperty, setSourceBondProperty); /// Controls whether the modifier assigns a color only to selected particles. - PropertyField _colorOnlySelected; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, colorOnlySelected, setColorOnlySelected); /// Controls whether the input particle selection is preserved. /// If false, the selection is cleared by the modifier. - PropertyField _keepSelection; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, keepSelection, setKeepSelection); /// Controls what is being assigned colors by the modifier. - PropertyField _colorApplicationMode; - -private: + DECLARE_MODIFIABLE_PROPERTY_FIELD(ColorApplicationMode, colorApplicationMode, setColorApplicationMode); Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Color coding"); Q_CLASSINFO("ModifierCategory", "Coloring"); - - DECLARE_REFERENCE_FIELD(_startValueCtrl); - DECLARE_REFERENCE_FIELD(_endValueCtrl); - DECLARE_REFERENCE_FIELD(_colorGradient); - DECLARE_PROPERTY_FIELD(_colorOnlySelected); - DECLARE_PROPERTY_FIELD(_keepSelection); - DECLARE_PROPERTY_FIELD(_sourceParticleProperty); - DECLARE_PROPERTY_FIELD(_sourceBondProperty); - DECLARE_PROPERTY_FIELD(_colorApplicationMode); }; OVITO_END_INLINE_NAMESPACE @@ -434,4 +377,4 @@ Q_DECLARE_METATYPE(Ovito::Particles::ColorCodingModifier::ColorApplicationMode); Q_DECLARE_TYPEINFO(Ovito::Particles::ColorCodingModifier::ColorApplicationMode, Q_PRIMITIVE_TYPE); -#endif // __OVITO_COLOR_CODING_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/ColorLegendOverlay.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/ColorLegendOverlay.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/ColorLegendOverlay.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/ColorLegendOverlay.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,42 +30,42 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Coloring) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ColorLegendOverlay, ViewportOverlay); -DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, _alignment, "Alignment", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, _orientation, "Orientation", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, _legendSize, "Size", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, _font, "Font", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, _fontSize, "FontSize", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(ColorLegendOverlay, _offsetX, "OffsetX"); -DEFINE_PROPERTY_FIELD(ColorLegendOverlay, _offsetY, "OffsetY"); -DEFINE_PROPERTY_FIELD(ColorLegendOverlay, _title, "Title"); -DEFINE_PROPERTY_FIELD(ColorLegendOverlay, _label1, "Label1"); -DEFINE_PROPERTY_FIELD(ColorLegendOverlay, _label2, "Label2"); -DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, _aspectRatio, "AspectRatio", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(ColorLegendOverlay, _valueFormatString, "ValueFormatString"); -DEFINE_FLAGS_REFERENCE_FIELD(ColorLegendOverlay, _modifier, "Modifier", ColorCodingModifier, PROPERTY_FIELD_NO_SUB_ANIM); -DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, _textColor, "TextColor", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, _outlineColor, "OutlineColor", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, _outlineEnabled, "OutlineEnabled", PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, _alignment, "Position"); -SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, _orientation, "Orientation"); -SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, _legendSize, "Size factor"); -SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, _font, "Font"); -SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, _fontSize, "Font size"); -SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, _offsetX, "Offset X"); -SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, _offsetY, "Offset Y"); -SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, _aspectRatio, "Aspect ratio"); -SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, _textColor, "Font color"); -SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, _outlineColor, "Outline color"); -SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, _outlineEnabled, "Enable outline"); -SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, _title, "Title"); -SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, _label1, "Label 1"); -SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, _label2, "Label 2"); -SET_PROPERTY_FIELD_UNITS(ColorLegendOverlay, _offsetX, PercentParameterUnit); -SET_PROPERTY_FIELD_UNITS(ColorLegendOverlay, _offsetY, PercentParameterUnit); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ColorLegendOverlay, _legendSize, FloatParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ColorLegendOverlay, _aspectRatio, FloatParameterUnit, 1); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ColorLegendOverlay, _fontSize, FloatParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ColorLegendOverlay, ViewportOverlay); +DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, alignment, "Alignment", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, orientation, "Orientation", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, legendSize, "Size", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, font, "Font", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, fontSize, "FontSize", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(ColorLegendOverlay, offsetX, "OffsetX"); +DEFINE_PROPERTY_FIELD(ColorLegendOverlay, offsetY, "OffsetY"); +DEFINE_PROPERTY_FIELD(ColorLegendOverlay, title, "Title"); +DEFINE_PROPERTY_FIELD(ColorLegendOverlay, label1, "Label1"); +DEFINE_PROPERTY_FIELD(ColorLegendOverlay, label2, "Label2"); +DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, aspectRatio, "AspectRatio", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(ColorLegendOverlay, valueFormatString, "ValueFormatString"); +DEFINE_FLAGS_REFERENCE_FIELD(ColorLegendOverlay, modifier, "Modifier", ColorCodingModifier, PROPERTY_FIELD_NO_SUB_ANIM); +DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, textColor, "TextColor", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, outlineColor, "OutlineColor", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ColorLegendOverlay, outlineEnabled, "OutlineEnabled", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, alignment, "Position"); +SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, orientation, "Orientation"); +SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, legendSize, "Size factor"); +SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, font, "Font"); +SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, fontSize, "Font size"); +SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, offsetX, "Offset X"); +SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, offsetY, "Offset Y"); +SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, aspectRatio, "Aspect ratio"); +SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, textColor, "Font color"); +SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, outlineColor, "Outline color"); +SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, outlineEnabled, "Enable outline"); +SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, title, "Title"); +SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, label1, "Label 1"); +SET_PROPERTY_FIELD_LABEL(ColorLegendOverlay, label2, "Label 2"); +SET_PROPERTY_FIELD_UNITS(ColorLegendOverlay, offsetX, PercentParameterUnit); +SET_PROPERTY_FIELD_UNITS(ColorLegendOverlay, offsetY, PercentParameterUnit); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ColorLegendOverlay, legendSize, FloatParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ColorLegendOverlay, aspectRatio, FloatParameterUnit, 1); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ColorLegendOverlay, fontSize, FloatParameterUnit, 0); /****************************************************************************** * Constructor. @@ -78,22 +78,22 @@ _outlineColor(1,1,1), _outlineEnabled(false) { - INIT_PROPERTY_FIELD(ColorLegendOverlay::_alignment); - INIT_PROPERTY_FIELD(ColorLegendOverlay::_orientation); - INIT_PROPERTY_FIELD(ColorLegendOverlay::_legendSize); - INIT_PROPERTY_FIELD(ColorLegendOverlay::_offsetX); - INIT_PROPERTY_FIELD(ColorLegendOverlay::_offsetY); - INIT_PROPERTY_FIELD(ColorLegendOverlay::_aspectRatio); - INIT_PROPERTY_FIELD(ColorLegendOverlay::_font); - INIT_PROPERTY_FIELD(ColorLegendOverlay::_fontSize); - INIT_PROPERTY_FIELD(ColorLegendOverlay::_title); - INIT_PROPERTY_FIELD(ColorLegendOverlay::_label1); - INIT_PROPERTY_FIELD(ColorLegendOverlay::_label2); - INIT_PROPERTY_FIELD(ColorLegendOverlay::_valueFormatString); - INIT_PROPERTY_FIELD(ColorLegendOverlay::_modifier); - INIT_PROPERTY_FIELD(ColorLegendOverlay::_textColor); - INIT_PROPERTY_FIELD(ColorLegendOverlay::_outlineColor); - INIT_PROPERTY_FIELD(ColorLegendOverlay::_outlineEnabled); + INIT_PROPERTY_FIELD(alignment); + INIT_PROPERTY_FIELD(orientation); + INIT_PROPERTY_FIELD(legendSize); + INIT_PROPERTY_FIELD(offsetX); + INIT_PROPERTY_FIELD(offsetY); + INIT_PROPERTY_FIELD(aspectRatio); + INIT_PROPERTY_FIELD(font); + INIT_PROPERTY_FIELD(fontSize); + INIT_PROPERTY_FIELD(title); + INIT_PROPERTY_FIELD(label1); + INIT_PROPERTY_FIELD(label2); + INIT_PROPERTY_FIELD(valueFormatString); + INIT_PROPERTY_FIELD(modifier); + INIT_PROPERTY_FIELD(textColor); + INIT_PROPERTY_FIELD(outlineColor); + INIT_PROPERTY_FIELD(outlineEnabled); // Find a ColorCodingModifiers in the scene that we can connect to. dataset->sceneRoot()->visitObjectNodes([this](ObjectNode* node) { @@ -122,26 +122,26 @@ { if(!modifier()) return; - FloatType legendSize = _legendSize.value() * renderSettings->outputImageHeight(); + FloatType legendSize = this->legendSize() * renderSettings->outputImageHeight(); if(legendSize <= 0) return; FloatType colorBarWidth = legendSize; - FloatType colorBarHeight = colorBarWidth / std::max(FloatType(0.01), _aspectRatio.value()); - bool vertical = (_orientation.value() == Qt::Vertical); + FloatType colorBarHeight = colorBarWidth / std::max(FloatType(0.01), aspectRatio()); + bool vertical = (orientation() == Qt::Vertical); if(vertical) std::swap(colorBarWidth, colorBarHeight); - QPointF origin(_offsetX.value() * renderSettings->outputImageWidth(), -_offsetY.value() * renderSettings->outputImageHeight()); - FloatType hmargin = 0.01 * renderSettings->outputImageWidth(); - FloatType vmargin = 0.01 * renderSettings->outputImageHeight(); - - if(_alignment.value() & Qt::AlignLeft) origin.rx() += hmargin; - else if(_alignment.value() & Qt::AlignRight) origin.rx() += renderSettings->outputImageWidth() - hmargin - colorBarWidth; - else if(_alignment.value() & Qt::AlignHCenter) origin.rx() += 0.5 * renderSettings->outputImageWidth() - 0.5 * colorBarWidth; - - if(_alignment.value() & Qt::AlignTop) origin.ry() += vmargin; - else if(_alignment.value() & Qt::AlignBottom) origin.ry() += renderSettings->outputImageHeight() - vmargin - colorBarHeight; - else if(_alignment.value() & Qt::AlignVCenter) origin.ry() += 0.5 * renderSettings->outputImageHeight() - 0.5 * colorBarHeight; + QPointF origin(offsetX() * renderSettings->outputImageWidth(), -offsetY() * renderSettings->outputImageHeight()); + FloatType hmargin = FloatType(0.01) * renderSettings->outputImageWidth(); + FloatType vmargin = FloatType(0.01) * renderSettings->outputImageHeight(); + + if(alignment() & Qt::AlignLeft) origin.rx() += hmargin; + else if(alignment() & Qt::AlignRight) origin.rx() += renderSettings->outputImageWidth() - hmargin - colorBarWidth; + else if(alignment() & Qt::AlignHCenter) origin.rx() += FloatType(0.5) * renderSettings->outputImageWidth() - FloatType(0.5) * colorBarWidth; + + if(alignment() & Qt::AlignTop) origin.ry() += vmargin; + else if(alignment() & Qt::AlignBottom) origin.ry() += renderSettings->outputImageHeight() - vmargin - colorBarHeight; + else if(alignment() & Qt::AlignVCenter) origin.ry() += FloatType(0.5) * renderSettings->outputImageHeight() - FloatType(0.5) * colorBarHeight; painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::TextAntialiasing); @@ -157,9 +157,9 @@ } painter.drawImage(QRectF(origin, QSizeF(colorBarWidth, colorBarHeight)), image); - qreal fontSize = legendSize * std::max(0.0, (double)_fontSize.value()); + qreal fontSize = legendSize * std::max(FloatType(0), this->fontSize()); if(fontSize == 0) return; - QFont font = _font.value(); + QFont font = this->font(); // Always render the outline pen 3 pixels wide, irrespective of frame buffer resolution. qreal outlineWidth = 3.0 / painter.combinedTransform().m11(); @@ -193,34 +193,33 @@ font.setPointSizeF(fontSize); painter.setFont(font); - qreal textMargin = 0.2 * legendSize / std::max(FloatType(0.01), _aspectRatio.value()); + qreal textMargin = 0.2 * legendSize / std::max(FloatType(0.01), aspectRatio()); - - bool drawOutline = (bool)_outlineEnabled.value(); + bool drawOutline = outlineEnabled(); // Create text at QPainterPaths so that we can easily draw an outline around the text QPainterPath titlePath = QPainterPath(); titlePath.addText(origin, font, titleLabel); // QPainterPath::addText uses the baseline as point where text is drawn. Compensate for this. - titlePath.translate(0,-QFontMetrics(font).descent()); + titlePath.translate(0, -QFontMetrics(font).descent()); QRectF titleBounds = titlePath.boundingRect(); // Move the text path to the correct place based on colorbar direction and position - if(!vertical || (_alignment.value() & Qt::AlignHCenter)) { + if(!vertical || (alignment() & Qt::AlignHCenter)) { // Q: Why factor 0.5 ? - titlePath.translate(0.5*colorBarWidth - titleBounds.width()/2.0, -0.5*textMargin); + titlePath.translate(0.5 * colorBarWidth - titleBounds.width()/2.0, -0.5 * textMargin); } else { - if(_alignment.value() & Qt::AlignLeft) + if(alignment() & Qt::AlignLeft) titlePath.translate(0, -textMargin); - else if(_alignment.value() & Qt::AlignRight) + else if(alignment() & Qt::AlignRight) titlePath.translate(-titleBounds.width(), -textMargin); } if(drawOutline) painter.drawPath(titlePath); - painter.fillPath(titlePath, (QColor)_textColor.value()); + painter.fillPath(titlePath, (QColor)textColor()); font.setPointSizeF(fontSize * 0.8); painter.setFont(font); @@ -240,25 +239,25 @@ } else { topPath.translate(0, topBounds.height()); - if(_alignment.value() & Qt::AlignLeft) { + if(alignment() & Qt::AlignLeft) { topPath.translate(colorBarWidth + textMargin, 0); bottomPath.translate(colorBarWidth + textMargin, colorBarHeight); } - else if(_alignment.value() & Qt::AlignRight) { + else if(alignment() & Qt::AlignRight) { topPath.translate(-textMargin -topBounds.width(), 0); bottomPath.translate(-textMargin - bottomBounds.width(), colorBarHeight); } - else if(_alignment.value() & Qt::AlignHCenter) { // Q: Same as Qt:AlignLeft case on purpose? + else if(alignment() & Qt::AlignHCenter) { // Q: Same as Qt:AlignLeft case on purpose? topPath.translate(colorBarWidth + textMargin, 0); bottomPath.translate(colorBarWidth + textMargin, colorBarHeight); } } if(drawOutline) painter.drawPath(topPath); - painter.fillPath(topPath, (QColor)_textColor.value()); + painter.fillPath(topPath, (QColor)textColor()); if(drawOutline) painter.drawPath(bottomPath); - painter.fillPath(bottomPath, (QColor)_textColor.value()); + painter.fillPath(bottomPath, (QColor)textColor()); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/ColorLegendOverlay.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/ColorLegendOverlay.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/ColorLegendOverlay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/ColorLegendOverlay.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COLOR_LEGEND_OVERLAY_H -#define __OVITO_COLOR_LEGEND_OVERLAY_H +#pragma once + #include #include @@ -41,48 +41,6 @@ /// \brief This method asks the overlay to paint its contents over the given viewport. virtual void render(Viewport* viewport, QPainter& painter, const ViewProjectionParameters& projParams, RenderSettings* renderSettings) override; - /// Returns the ColorCodingModifier for which to display the legend. - ColorCodingModifier* modifier() const { return _modifier; } - - /// Sets the ColorCodingModifier for which to display the legend. - void setModifier(ColorCodingModifier* mod) { _modifier = mod; } - - /// Returns the formatting of the value labels in the color legend. - const QString& valueFormatString() const { return _valueFormatString; } - - /// Sets the formatting of the value labels in the color legend. - void setValueFormatString(const QString& format) { _valueFormatString = format; } - - /// Returns the title text of the color legend. - const QString& title() const { return _title; } - - /// Sets the title text of the color legend. - void setTitle(const QString& text) { _title = text; } - - /// Returns the user-defined text to be used for the first numeric label. - const QString& label1() const { return _label1; } - - /// Returns the user-defined text to be used for the second numeric label. - const QString& label2() const { return _label2; } - - /// Returns the display color of the labels. - const Color& textColor() const { return _textColor; } - - /// Sets the display color of the labels. - void setTextColor(const Color& c) { _textColor = c; } - - /// Returns the outline color of the font. - const Color& outlineColor() const { return _outlineColor; } - - /// Sets the outline color of the font. - void setOutlineColor(const Color& c) { _outlineColor = c; } - - /// Returns whether a text outline is drawn. - bool outlineEnabled() const { return _outlineEnabled; } - - /// Sets whether a text outline is drawn. - void setOutlineEnabled(bool enable) { _outlineEnabled = enable; } - /// Moves the position of the overlay in the viewport by the given amount, /// which is specified as a fraction of the viewport render size. virtual void moveOverlayInViewport(const Vector2& delta) override { @@ -97,69 +55,52 @@ private: /// The corner of the viewport where the color legend is displayed. - PropertyField _alignment; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, alignment, setAlignment); /// The orientation (horizontal/vertical) of the color legend. - PropertyField _orientation; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, orientation, setOrientation); /// Controls the overall size of the color legend. - PropertyField _legendSize; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, legendSize, setLegendSize); /// Controls the aspect ration of the color bar. - PropertyField _aspectRatio; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, aspectRatio, setAspectRatio); /// Controls the horizontal offset of legend position. - PropertyField _offsetX; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, offsetX, setOffsetX) /// Controls the vertical offset of legend position. - PropertyField _offsetY; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, offsetY, setOffsetY); /// Controls the label font. - PropertyField _font; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QFont, font, setFont); /// Controls the label font size. - PropertyField _fontSize; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, fontSize, setFontSize); /// The title label. - PropertyField _title; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, title, setTitle); /// User-defined text for the first numeric label. - PropertyField _label1; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, label1, setLabel1); /// User-defined text for the second numeric label. - PropertyField _label2; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, label2, setLabel2); /// The ColorCodingModifier for which to display the legend. - ReferenceField _modifier; + DECLARE_MODIFIABLE_REFERENCE_FIELD(ColorCodingModifier, modifier, setModifier); /// Controls the formatting of the value labels in the color legend. - PropertyField _valueFormatString; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, valueFormatString, setValueFormatString); /// Controls the text color. - PropertyField _textColor; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, textColor, setTextColor); /// The text outline color. - PropertyField _outlineColor; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, outlineColor, setOutlineColor); /// Controls the outlining of the font. - PropertyField _outlineEnabled; - - DECLARE_PROPERTY_FIELD(_alignment); - DECLARE_PROPERTY_FIELD(_orientation); - DECLARE_PROPERTY_FIELD(_aspectRatio); - DECLARE_PROPERTY_FIELD(_font); - DECLARE_PROPERTY_FIELD(_fontSize); - DECLARE_PROPERTY_FIELD(_legendSize); - DECLARE_PROPERTY_FIELD(_offsetX); - DECLARE_PROPERTY_FIELD(_offsetY); - DECLARE_PROPERTY_FIELD(_title); - DECLARE_PROPERTY_FIELD(_label1); - DECLARE_PROPERTY_FIELD(_label2); - DECLARE_PROPERTY_FIELD(_valueFormatString); - DECLARE_PROPERTY_FIELD(_textColor); - DECLARE_PROPERTY_FIELD(_outlineColor); - DECLARE_PROPERTY_FIELD(_outlineEnabled); - DECLARE_REFERENCE_FIELD(_modifier); + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, outlineEnabled, setOutlineEnabled) Q_CLASSINFO("DisplayName", "Color legend"); @@ -172,4 +113,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_COLOR_LEGEND_OVERLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/ColormapsData.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/ColormapsData.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/coloring/ColormapsData.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/coloring/ColormapsData.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COLORMAPS_DATA_H -#define __OVITO_COLORMAPS_DATA_H +#pragma once + namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Coloring) @@ -552,5 +552,3 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace } // End of namespace - -#endif diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/fields/CreateIsosurfaceModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/fields/CreateIsosurfaceModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/fields/CreateIsosurfaceModifier.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/fields/CreateIsosurfaceModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,221 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "CreateIsosurfaceModifier.h" +#include "MarchingCubes.h" + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Fields) + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CreateIsosurfaceModifier, AsynchronousParticleModifier); +DEFINE_PROPERTY_FIELD(CreateIsosurfaceModifier, sourceQuantity, "SourceQuantity"); +DEFINE_FLAGS_REFERENCE_FIELD(CreateIsosurfaceModifier, isolevelController, "IsolevelController", Controller, PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(CreateIsosurfaceModifier, surfaceMeshDisplay, "SurfaceMeshDisplay", SurfaceMeshDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(CreateIsosurfaceModifier, sourceQuantity, "Source quantity"); +SET_PROPERTY_FIELD_LABEL(CreateIsosurfaceModifier, isolevelController, "Isolevel"); +SET_PROPERTY_FIELD_LABEL(CreateIsosurfaceModifier, surfaceMeshDisplay, "Surface mesh display"); + +/****************************************************************************** +* Constructs the modifier object. +******************************************************************************/ +CreateIsosurfaceModifier::CreateIsosurfaceModifier(DataSet* dataset) : AsynchronousParticleModifier(dataset) +{ + INIT_PROPERTY_FIELD(sourceQuantity); + INIT_PROPERTY_FIELD(isolevelController); + INIT_PROPERTY_FIELD(surfaceMeshDisplay); + + setIsolevelController(ControllerManager::createFloatController(dataset)); + + // Create the display object. + _surfaceMeshDisplay = new SurfaceMeshDisplay(dataset); + _surfaceMeshDisplay->setShowCap(false); + _surfaceMeshDisplay->setSmoothShading(true); + _surfaceMeshDisplay->setObjectTitle(tr("Isosurface")); +} + +/****************************************************************************** +* Asks the modifier for its validity interval at the given time. +******************************************************************************/ +TimeInterval CreateIsosurfaceModifier::modifierValidity(TimePoint time) +{ + TimeInterval interval = AsynchronousParticleModifier::modifierValidity(time); + if(isolevelController()) interval.intersect(isolevelController()->validityInterval(time)); + return interval; +} + +/****************************************************************************** +* Asks the modifier whether it can be applied to the given input data. +******************************************************************************/ +bool CreateIsosurfaceModifier::isApplicableTo(const PipelineFlowState& input) +{ + return (input.findObject() != nullptr); +} + +/****************************************************************************** +* This method is called by the system when the modifier has been inserted +* into a pipeline. +******************************************************************************/ +void CreateIsosurfaceModifier::initializeModifier(PipelineObject* pipeline, ModifierApplication* modApp) +{ + ParticleModifier::initializeModifier(pipeline, modApp); + + // Use the first available particle property from the input state as data source when the modifier is newly created. + if(sourceQuantity().isNull()) { + PipelineFlowState input = getModifierInput(modApp); + for(DataObject* o : input.objects()) { + FieldQuantityObject* fq = dynamic_object_cast(o); + if(fq && fq->componentCount() <= 1) { + setSourceQuantity(FieldQuantityReference(fq, (fq->componentCount() > 1) ? 0 : -1)); + } + } + } +} + +/****************************************************************************** +* Is called when the value of a property of this object has changed. +******************************************************************************/ +void CreateIsosurfaceModifier::propertyChanged(const PropertyFieldDescriptor& field) +{ + AsynchronousParticleModifier::propertyChanged(field); + + // Recompute results when the parameters have changed. + if(field == PROPERTY_FIELD(sourceQuantity)) + invalidateCachedResults(); +} + +/****************************************************************************** +* Handles reference events sent by reference targets of this object. +******************************************************************************/ +bool CreateIsosurfaceModifier::referenceEvent(RefTarget* source, ReferenceEvent* event) +{ + // Do not propagate messages from the attached display object. + if(source == surfaceMeshDisplay()) + return false; + + // Recompute results when the input parameters have changed. + if(source == isolevelController() && event->type() == ReferenceEvent::TargetChanged) + invalidateCachedResults(); + + return AsynchronousParticleModifier::referenceEvent(source, event); +} + +/****************************************************************************** +* Creates and initializes a computation engine that will compute the modifier's results. +******************************************************************************/ +std::shared_ptr CreateIsosurfaceModifier::createEngine(TimePoint time, TimeInterval validityInterval) +{ + // Get modifier inputs. + SimulationCellObject* simCell = expectSimulationCell(); + if(sourceQuantity().isNull()) + throwException(tr("Select a field quantity first.")); + FieldQuantityObject* quantity = sourceQuantity().findInState(input()); + if(!quantity) + throwException(tr("The selected field quantity with the name '%1' does not exist.").arg(sourceQuantity().name())); + if(sourceQuantity().vectorComponent() >= (int)quantity->componentCount()) + throwException(tr("The selected vector component is out of range. The field quantity '%1' contains only %2 values per field value.").arg(sourceQuantity().name()).arg(quantity->componentCount())); + + FloatType isolevel = isolevelController() ? isolevelController()->getFloatValue(time, validityInterval) : 0; + + // Create engine object. Pass all relevant modifier parameters to the engine as well as the input data. + return std::make_shared(validityInterval, quantity->storage(), + sourceQuantity().vectorComponent(), simCell->data(), isolevel); +} + +/****************************************************************************** +* Unpacks the results of the computation engine and stores them in the modifier. +******************************************************************************/ +void CreateIsosurfaceModifier::transferComputationResults(ComputeEngine* engine) +{ + ComputeIsosurfaceEngine* eng = static_cast(engine); + _surfaceMesh = eng->mesh(); + _isCompletelySolid = eng->isCompletelySolid(); + _minValue = eng->minValue(); + _maxValue = eng->maxValue(); +} + +/****************************************************************************** +* Lets the modifier insert the cached computation results into the +* modification pipeline. +******************************************************************************/ +PipelineStatus CreateIsosurfaceModifier::applyComputationResults(TimePoint time, TimeInterval& validityInterval) +{ + if(!_surfaceMesh) + throwException(tr("No computation results available.")); + + // Create the output data object. + OORef meshObj(new SurfaceMesh(dataset(), _surfaceMesh.data())); + meshObj->setIsCompletelySolid(_isCompletelySolid); + meshObj->addDisplayObject(_surfaceMeshDisplay); + + // Insert output object into the pipeline. + output().addObject(meshObj); + + return PipelineStatus(PipelineStatus::Success, tr("Minimum value: %1\nMaximum value: %2").arg(_minValue).arg(_maxValue)); +} + +/****************************************************************************** +* Performs the actual analysis. This method is executed in a worker thread. +******************************************************************************/ +void CreateIsosurfaceModifier::ComputeIsosurfaceEngine::perform() +{ + setProgressText(tr("Constructing isosurface")); + + if(quantity()->shape().size() != 3) + throw Exception(tr("Can construct isosurface only for three-dimensional fields")); + if(quantity()->dataType() != qMetaTypeId()) + throw Exception(tr("Can construct isosurface only for floating-point data")); + + const FloatType* fieldData = quantity()->constDataFloat() + std::max(_vectorComponent, 0); + const size_t shape[3] = {quantity()->shape()[0], quantity()->shape()[1], quantity()->shape()[2]}; + + MarchingCubes mc(shape[0], shape[1], shape[2], fieldData, quantity()->componentCount(), *mesh()); + if(!mc.generateIsosurface(_isolevel, *this)) + return; + _isCompletelySolid = mc.isCompletelySolid(); + + // Determin min/max field values. + const FloatType* fieldDataEnd = fieldData + shape[0]*shape[1]*shape[2]*quantity()->componentCount(); + _minValue = FLOATTYPE_MAX; + _maxValue = -FLOATTYPE_MAX; + for(; fieldData != fieldDataEnd; fieldData += quantity()->componentCount()) { + if(*fieldData < _minValue) _minValue = *fieldData; + if(*fieldData > _maxValue) _maxValue = *fieldData; + } + + // Transform mesh vertices from orthogonal grid space to world space. + const AffineTransformation tm = _simCell.matrix() * + Matrix3(FloatType(1) / shape[0], 0, 0, 0, FloatType(1) / shape[1], 0, 0, 0, FloatType(1) / shape[2]); + for(HalfEdgeMesh<>::Vertex* vertex : mesh()->vertices()) + vertex->setPos(tm * vertex->pos()); + + if(isCanceled()) + return; + + if(!mesh()->connectOppositeHalfedges()) + throw Exception("Isosurface mesh is not closed."); +} + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/fields/CreateIsosurfaceModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/fields/CreateIsosurfaceModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/fields/CreateIsosurfaceModifier.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/fields/CreateIsosurfaceModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,146 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include +#include +#include +#include + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Fields) + +/* + * Constructs a surface mesh from a particle system. + */ +class OVITO_PARTICLES_EXPORT CreateIsosurfaceModifier : public AsynchronousParticleModifier +{ +public: + + /// Constructor. + Q_INVOKABLE CreateIsosurfaceModifier(DataSet* dataset); + + /// Asks the modifier whether it can be applied to the given input data. + virtual bool isApplicableTo(const PipelineFlowState& input) override; + + /// Asks the modifier for its validity interval at the given time. + virtual TimeInterval modifierValidity(TimePoint time) override; + + /// Returns the level at which to create the isosurface. + FloatType isolevel() const { return isolevelController() ? isolevelController()->currentFloatValue() : 0; } + + /// Sets the level at which to create the isosurface. + void setIsolevel(FloatType value) { if(isolevelController()) isolevelController()->setCurrentFloatValue(value); } + +protected: + + /// This virtual method is called by the system when the modifier has been inserted into a PipelineObject. + virtual void initializeModifier(PipelineObject* pipelineObject, ModifierApplication* modApp) override; + + /// Handles reference events sent by reference targets of this object. + virtual bool referenceEvent(RefTarget* source, ReferenceEvent* event) override; + + /// Is called when the value of a property of this object has changed. + virtual void propertyChanged(const PropertyFieldDescriptor& field) override; + + /// Creates a computation engine that will compute the modifier's results. + virtual std::shared_ptr createEngine(TimePoint time, TimeInterval validityInterval) override; + + /// Unpacks the results of the computation engine and stores them in the modifier. + virtual void transferComputationResults(ComputeEngine* engine) override; + + /// Lets the modifier insert the cached computation results into the modification pipeline. + virtual PipelineStatus applyComputationResults(TimePoint time, TimeInterval& validityInterval) override; + +private: + + /// Computation engine that builds the isosurface mesh. + class ComputeIsosurfaceEngine : public ComputeEngine + { + public: + + /// Constructor. + ComputeIsosurfaceEngine(const TimeInterval& validityInterval, FieldQuantity* quantity, int vectorComponent, const SimulationCell& simCell, FloatType isolevel) : + ComputeEngine(validityInterval), _quantity(quantity), _vectorComponent(vectorComponent), _simCell(simCell), _isolevel(isolevel), _isCompletelySolid(false), _mesh(new HalfEdgeMesh<>()) {} + + /// Computes the modifier's results and stores them in this object for later retrieval. + virtual void perform() override; + + /// Returns the generated mesh. + HalfEdgeMesh<>* mesh() { return _mesh.data(); } + + /// Returns the input field quantity. + FieldQuantity* quantity() const { return _quantity.data(); } + + /// Indicates whether the entire simulation cell is part of the solid region. + bool isCompletelySolid() const { return _isCompletelySolid; } + + /// Returns the minimum field value that was encountered. + FloatType minValue() const { return _minValue; } + + /// Returns the maximum field value that was encountered. + FloatType maxValue() const { return _maxValue; } + + private: + + FloatType _isolevel; + int _vectorComponent; + QExplicitlySharedDataPointer _quantity; + QExplicitlySharedDataPointer> _mesh; + SimulationCell _simCell; + bool _isCompletelySolid; + FloatType _minValue, _maxValue; + }; + + /// The field quantity that serves input. + DECLARE_MODIFIABLE_PROPERTY_FIELD(FieldQuantityReference, sourceQuantity, setSourceQuantity); + + /// This controller stores the level at which to create the isosurface. + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, isolevelController, setIsolevelController); + + /// The display object for rendering the surface mesh. + DECLARE_MODIFIABLE_REFERENCE_FIELD(SurfaceMeshDisplay, surfaceMeshDisplay, setSurfaceMeshDisplay); + + /// This stores the cached surface mesh produced by the modifier. + QExplicitlySharedDataPointer> _surfaceMesh; + + /// Indicates that the entire simulation cell is part of the solid region. + bool _isCompletelySolid; + + /// The minimum field value that was encountered. + FloatType _minValue; + + /// The maximum field value that was encountered. + FloatType _maxValue; + + Q_OBJECT + OVITO_OBJECT + + Q_CLASSINFO("DisplayName", "Create isosurface"); + Q_CLASSINFO("ModifierCategory", "Fields"); +}; + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/fields/MarchingCubes.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/fields/MarchingCubes.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/fields/MarchingCubes.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/fields/MarchingCubes.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,671 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include "MarchingCubes.h" +#include "MarchingCubesLookupTable.h" + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Fields) + +/****************************************************************************** +* Constructor. +******************************************************************************/ +MarchingCubes::MarchingCubes(int size_x, int size_y, int size_z, const FloatType* data, size_t stride, HalfEdgeMesh<>& outputMesh) : + _size_x(size_x), _size_y(size_y), _size_z(size_z), + _data(data), _dataStride(stride), _outputMesh(outputMesh), + _cubeVerts(size_x * size_y * size_z * 3, nullptr), + _isCompletelySolid(false) +{ + OVITO_ASSERT(stride >= 1); +} + +/****************************************************************************** +* Main method that constructs the isosurface mesh. +******************************************************************************/ +bool MarchingCubes::generateIsosurface(FloatType isolevel, PromiseBase& promise) +{ + promise.setProgressMaximum(_size_z*2); + promise.setProgressValue(0); + computeIntersectionPoints(isolevel, promise); + if(promise.isCanceled()) return false; + + for(int k = 0; k < _size_z && !promise.isCanceled(); k++, promise.incrementProgressValue()) { + for(int j = 0; j < _size_y; j++) { + for(int i = 0; i < _size_x; i++) { + _lut_entry = 0; + for(int p = 0; p < 8; ++p) { + _cube[p] = getFieldValue(i+((p^(p>>1))&1), j+((p>>1)&1), k+((p>>2)&1)) - isolevel; + if(std::abs(_cube[p]) < _epsilon) _cube[p] = _epsilon; + if(_cube[p] > 0) _lut_entry += 1 << p; + } + processCube(i,j,k); + } + } + } + return !promise.isCanceled(); +} + +/****************************************************************************** +* Compute the intersection points with the isosurface along the cube edges. +******************************************************************************/ +void MarchingCubes::computeIntersectionPoints(FloatType isolevel, PromiseBase& promise) +{ + _isCompletelySolid = true; + for(int k = 0; k < _size_z && !promise.isCanceled(); k++, promise.incrementProgressValue()) { + for(int j = 0; j < _size_y; j++) { + for(int i = 0; i < _size_x; i++) { + FloatType cube[8]; + cube[0] = getFieldValue(i, j, k ) - isolevel; + cube[1] = getFieldValue(i+1, j, k ) - isolevel; + cube[3] = getFieldValue(i, j+1, k ) - isolevel; + cube[4] = getFieldValue(i, j, k+1) - isolevel; + + if(std::abs(cube[0]) < _epsilon) cube[0] = _epsilon; + if(std::abs(cube[1]) < _epsilon) cube[1] = _epsilon; + if(std::abs(cube[3]) < _epsilon) cube[3] = _epsilon; + if(std::abs(cube[4]) < _epsilon) cube[4] = _epsilon; + + if(cube[0] < 0) _isCompletelySolid = false; + if(cube[1]*cube[0] < 0) createEdgeVertexX(i,j,k, cube[0] / (cube[0] - cube[1])); + if(cube[3]*cube[0] < 0) createEdgeVertexY(i,j,k, cube[0] / (cube[0] - cube[3])); + if(cube[4]*cube[0] < 0) createEdgeVertexZ(i,j,k, cube[0] / (cube[0] - cube[4])); + } + } + } +} + +/****************************************************************************** +* Test a face. +* if face>0 return true if the face contains a part of the surface +******************************************************************************/ +bool MarchingCubes::testFace(char face) +{ + FloatType A,B,C,D; + + switch(face) + { + case -1: case 1: A = _cube[0]; B = _cube[4]; C = _cube[5]; D = _cube[1]; break; + case -2: case 2: A = _cube[1]; B = _cube[5]; C = _cube[6]; D = _cube[2]; break; + case -3: case 3: A = _cube[2]; B = _cube[6]; C = _cube[7]; D = _cube[3]; break; + case -4: case 4: A = _cube[3]; B = _cube[7]; C = _cube[4]; D = _cube[0]; break; + case -5: case 5: A = _cube[0]; B = _cube[3]; C = _cube[2]; D = _cube[1]; break; + case -6: case 6: A = _cube[4]; B = _cube[7]; C = _cube[6]; D = _cube[5]; break; + default: OVITO_ASSERT_MSG(false, "Marching cubes", "Invalid face code"); + }; + + if(std::abs(A*C - B*D) < _epsilon) + return face >= 0; + return face * A * (A*C - B*D) >= 0; // face and A invert signs +} + + +/****************************************************************************** +* Test the interior of a cube. +* if s == 7, return true if the interior is empty +* if s ==-7, return false if the interior is empty +******************************************************************************/ +bool MarchingCubes::testInterior(char s) +{ + FloatType t, At=0, Bt=0, Ct=0, Dt=0, a, b; + char test = 0; + char edge = -1; // reference edge of the triangulation + + switch( _case ) + { + case 4 : + case 10 : + a = ( _cube[4] - _cube[0]) * ( _cube[6] - _cube[2]) - ( _cube[7] - _cube[3]) * ( _cube[5] - _cube[1]); + b = _cube[2] * ( _cube[4] - _cube[0]) + _cube[0] * ( _cube[6] - _cube[2] ) + - _cube[1] * ( _cube[7] - _cube[3]) - _cube[3] * ( _cube[5] - _cube[1]); + t = - b / (2*a); + if(t<0 || t>1) return s>0; + + At = _cube[0] + ( _cube[4] - _cube[0]) * t; + Bt = _cube[3] + ( _cube[7] - _cube[3]) * t; + Ct = _cube[2] + ( _cube[6] - _cube[2]) * t; + Dt = _cube[1] + ( _cube[5] - _cube[1]) * t; + break; + + case 6 : + case 7 : + case 12 : + case 13 : + switch( _case ) + { + case 6: edge = test6 [_config][2]; break; + case 7: edge = test7 [_config][4]; break; + case 12: edge = test12[_config][3]; break; + case 13: edge = tiling13_5_1[_config][_subconfig][0]; break; + } + switch( edge ) + { + case 0 : + t = _cube[0] / ( _cube[0] - _cube[1]); + At = 0; + Bt = _cube[3] + ( _cube[2] - _cube[3]) * t; + Ct = _cube[7] + ( _cube[6] - _cube[7]) * t; + Dt = _cube[4] + ( _cube[5] - _cube[4]) * t; + break; + case 1 : + t = _cube[1] / ( _cube[1] - _cube[2]); + At = 0; + Bt = _cube[0] + ( _cube[3] - _cube[0]) * t; + Ct = _cube[4] + ( _cube[7] - _cube[4]) * t; + Dt = _cube[5] + ( _cube[6] - _cube[5]) * t; + break; + case 2 : + t = _cube[2] / ( _cube[2] - _cube[3]); + At = 0; + Bt = _cube[1] + ( _cube[0] - _cube[1]) * t; + Ct = _cube[5] + ( _cube[4] - _cube[5]) * t; + Dt = _cube[6] + ( _cube[7] - _cube[6]) * t; + break; + case 3 : + t = _cube[3] / ( _cube[3] - _cube[0]); + At = 0; + Bt = _cube[2] + ( _cube[1] - _cube[2]) * t; + Ct = _cube[6] + ( _cube[5] - _cube[6]) * t; + Dt = _cube[7] + ( _cube[4] - _cube[7]) * t; + break; + case 4 : + t = _cube[4] / ( _cube[4] - _cube[5]); + At = 0; + Bt = _cube[7] + ( _cube[6] - _cube[7]) * t; + Ct = _cube[3] + ( _cube[2] - _cube[3]) * t; + Dt = _cube[0] + ( _cube[1] - _cube[0]) * t; + break; + case 5 : + t = _cube[5] / ( _cube[5] - _cube[6]); + At = 0; + Bt = _cube[4] + ( _cube[7] - _cube[4]) * t; + Ct = _cube[0] + ( _cube[3] - _cube[0]) * t; + Dt = _cube[1] + ( _cube[2] - _cube[1]) * t; + break; + case 6 : + t = _cube[6] / ( _cube[6] - _cube[7]); + At = 0; + Bt = _cube[5] + ( _cube[4] - _cube[5]) * t; + Ct = _cube[1] + ( _cube[0] - _cube[1]) * t; + Dt = _cube[2] + ( _cube[3] - _cube[2]) * t; + break; + case 7 : + t = _cube[7] / ( _cube[7] - _cube[4]); + At = 0; + Bt = _cube[6] + ( _cube[5] - _cube[6]) * t; + Ct = _cube[2] + ( _cube[1] - _cube[2]) * t; + Dt = _cube[3] + ( _cube[0] - _cube[3]) * t; + break; + case 8 : + t = _cube[0] / ( _cube[0] - _cube[4]); + At = 0; + Bt = _cube[3] + ( _cube[7] - _cube[3]) * t; + Ct = _cube[2] + ( _cube[6] - _cube[2]) * t; + Dt = _cube[1] + ( _cube[5] - _cube[1]) * t; + break; + case 9 : + t = _cube[1] / ( _cube[1] - _cube[5]); + At = 0; + Bt = _cube[0] + ( _cube[4] - _cube[0]) * t; + Ct = _cube[3] + ( _cube[7] - _cube[3]) * t; + Dt = _cube[2] + ( _cube[6] - _cube[2]) * t; + break; + case 10 : + t = _cube[2] / ( _cube[2] - _cube[6]); + At = 0; + Bt = _cube[1] + ( _cube[5] - _cube[1]) * t; + Ct = _cube[0] + ( _cube[4] - _cube[0]) * t; + Dt = _cube[3] + ( _cube[7] - _cube[3]) * t; + break; + case 11 : + t = _cube[3] / ( _cube[3] - _cube[7]); + At = 0; + Bt = _cube[2] + ( _cube[6] - _cube[2]) * t; + Ct = _cube[1] + ( _cube[5] - _cube[1]) * t; + Dt = _cube[0] + ( _cube[4] - _cube[0]) * t; + break; + default: OVITO_ASSERT_MSG(false, "Marching cubes", "Invalid edge"); break; + } + break; + + default: OVITO_ASSERT_MSG(false, "Marching cubes", "Invalid ambiguous case"); break; + } + + if(At >= 0) test ++; + if(Bt >= 0) test += 2; + if(Ct >= 0) test += 4; + if(Dt >= 0) test += 8; + switch( test ) + { + case 0: return s>0; + case 1: return s>0; + case 2: return s>0; + case 3: return s>0; + case 4: return s>0; + case 5: if(At * Ct - Bt * Dt < _epsilon) return s>0; break; + case 6: return s>0; + case 7: return s<0; + case 8: return s>0; + case 9: return s>0; + case 10: if(At * Ct - Bt * Dt >= _epsilon) return s>0; break; + case 11: return s<0; + case 12: return s>0; + case 13: return s<0; + case 14: return s<0; + case 15: return s<0; + } + + return s<0; +} + +/****************************************************************************** +* Processes a single cube. +******************************************************************************/ +void MarchingCubes::processCube(int i, int j, int k) +{ + HalfEdgeMesh<>::Vertex* v12 = nullptr; + _case = cases[_lut_entry][0]; + _config = cases[_lut_entry][1]; + _subconfig = 0; + + switch(_case) { + case 0 : + break; + + case 1 : + addTriangle(i,j,k, tiling1[_config], 1); + break; + + case 2 : + addTriangle(i,j,k, tiling2[_config], 2); + break; + + case 3 : + if(testFace(test3[_config]) ) + addTriangle(i,j,k, tiling3_2[_config], 4); // 3.2 + else + addTriangle(i,j,k, tiling3_1[_config], 2); // 3.1 + break; + + case 4 : + if(testInterior(test4[_config]) ) + addTriangle(i,j,k, tiling4_1[_config], 2); // 4.1.1 + else + addTriangle(i,j,k, tiling4_2[_config], 6); // 4.1.2 + break; + + case 5 : + addTriangle(i,j,k, tiling5[_config], 3); + break; + + case 6 : + if(testFace(test6[_config][0]) ) + addTriangle(i,j,k, tiling6_2[_config], 5); // 6.2 + else + { + if(testInterior(test6[_config][1]) ) + addTriangle(i,j,k, tiling6_1_1[_config], 3); // 6.1.1 + else + { + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling6_1_2[_config], 9 , v12); // 6.1.2 + } + } + break; + + case 7 : + if(testFace(test7[_config][0])) _subconfig += 1; + if(testFace(test7[_config][1])) _subconfig += 2; + if(testFace(test7[_config][2])) _subconfig += 4; + switch( _subconfig ) + { + case 0 : + addTriangle(i,j,k, tiling7_1[_config], 3); break; + case 1 : + addTriangle(i,j,k, tiling7_2[_config][0], 5); break; + case 2 : + addTriangle(i,j,k, tiling7_2[_config][1], 5); break; + case 3 : + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling7_3[_config][0], 9, v12); break; + case 4 : + addTriangle(i,j,k, tiling7_2[_config][2], 5); break; + case 5 : + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling7_3[_config][1], 9, v12); break; + case 6 : + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling7_3[_config][2], 9, v12); break; + case 7 : + if(testInterior(test7[_config][3]) ) + addTriangle(i,j,k, tiling7_4_2[_config], 9); + else + addTriangle(i,j,k, tiling7_4_1[_config], 5); + break; + }; + break; + + case 8 : + addTriangle(i,j,k, tiling8[_config], 2); + break; + + case 9 : + addTriangle(i,j,k, tiling9[_config], 4); + break; + + case 10 : + if(testFace(test10[_config][0]) ) + { + if(testFace(test10[_config][1]) ) + addTriangle(i,j,k, tiling10_1_1_[_config], 4); // 10.1.1 + else + { + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling10_2[_config], 8, v12); // 10.2 + } + } + else + { + if(testFace(test10[_config][1]) ) + { + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling10_2_[_config], 8, v12); // 10.2 + } + else + { + if(testInterior(test10[_config][2]) ) + addTriangle(i,j,k, tiling10_1_1[_config], 4); // 10.1.1 + else + addTriangle(i,j,k, tiling10_1_2[_config], 8); // 10.1.2 + } + } + break; + + case 11 : + addTriangle(i,j,k, tiling11[_config], 4); + break; + + case 12 : + if(testFace(test12[_config][0]) ) + { + if(testFace(test12[_config][1]) ) + addTriangle(i,j,k, tiling12_1_1_[_config], 4); // 12.1.1 + else + { + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling12_2[_config], 8, v12); // 12.2 + } + } + else + { + if(testFace(test12[_config][1]) ) + { + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling12_2_[_config], 8, v12); // 12.2 + } + else + { + if(testInterior(test12[_config][2]) ) + addTriangle(i,j,k, tiling12_1_1[_config], 4); // 12.1.1 + else + addTriangle(i,j,k, tiling12_1_2[_config], 8); // 12.1.2 + } + } + break; + + case 13 : + if(testFace(test13[_config][0])) _subconfig += 1; + if(testFace(test13[_config][1])) _subconfig += 2; + if(testFace(test13[_config][2])) _subconfig += 4; + if(testFace(test13[_config][3])) _subconfig += 8; + if(testFace(test13[_config][4])) _subconfig += 16; + if(testFace(test13[_config][5])) _subconfig += 32; + switch(subconfig13[_subconfig]) { + case 0 :/* 13.1 */ + addTriangle(i,j,k, tiling13_1[_config], 4); break; + + case 1 :/* 13.2 */ + addTriangle(i,j,k, tiling13_2[_config][0], 6); break; + case 2 :/* 13.2 */ + addTriangle(i,j,k, tiling13_2[_config][1], 6); break; + case 3 :/* 13.2 */ + addTriangle(i,j,k, tiling13_2[_config][2], 6); break; + case 4 :/* 13.2 */ + addTriangle(i,j,k, tiling13_2[_config][3], 6); break; + case 5 :/* 13.2 */ + addTriangle(i,j,k, tiling13_2[_config][4], 6); break; + case 6 :/* 13.2 */ + addTriangle(i,j,k, tiling13_2[_config][5], 6); break; + + case 7 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3[_config][0], 10, v12); break; + case 8 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3[_config][1], 10, v12); break; + case 9 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3[_config][2], 10, v12); break; + case 10 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3[_config][3], 10, v12); break; + case 11 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3[_config][4], 10, v12); break; + case 12 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3[_config][5], 10, v12); break; + case 13 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3[_config][6], 10, v12); break; + case 14 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3[_config][7], 10, v12); break; + case 15 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3[_config][8], 10, v12); break; + case 16 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3[_config][9], 10, v12); break; + case 17 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3[_config][10], 10, v12); break; + case 18 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3[_config][11], 10, v12); break; + + case 19 :/* 13.4 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_4[_config][0], 12, v12); break; + case 20 :/* 13.4 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_4[_config][1], 12, v12); break; + case 21 :/* 13.4 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_4[_config][2], 12, v12); break; + case 22 :/* 13.4 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_4[_config][3], 12, v12); break; + + case 23 :/* 13.5 */ + _subconfig = 0; + if(testInterior(test13[_config][6]) ) + addTriangle(i,j,k, tiling13_5_1[_config][0], 6); + else + addTriangle(i,j,k, tiling13_5_2[_config][0], 10); + break; + case 24 :/* 13.5 */ + _subconfig = 1; + if(testInterior(test13[_config][6]) ) + addTriangle(i,j,k, tiling13_5_1[_config][1], 6); + else + addTriangle(i,j,k, tiling13_5_2[_config][1], 10); + break; + case 25 :/* 13.5 */ + _subconfig = 2; + if(testInterior(test13[_config][6]) ) + addTriangle(i,j,k, tiling13_5_1[_config][2], 6); + else + addTriangle(i,j,k, tiling13_5_2[_config][2], 10); + break; + case 26 :/* 13.5 */ + _subconfig = 3; + if(testInterior(test13[_config][6]) ) + addTriangle(i,j,k, tiling13_5_1[_config][3], 6); + else + addTriangle(i,j,k, tiling13_5_2[_config][3], 10); + break; + + case 27 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3_[_config][0], 10, v12); break; + case 28 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3_[_config][1], 10, v12); break; + case 29 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3_[_config][2], 10, v12); break; + case 30 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3_[_config][3], 10, v12); break; + case 31 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3_[_config][4], 10, v12); break; + case 32 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3_[_config][5], 10, v12); break; + case 33 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3_[_config][6], 10, v12); break; + case 34 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3_[_config][7], 10, v12); break; + case 35 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3_[_config][8], 10, v12); break; + case 36 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3_[_config][9], 10, v12); break; + case 37 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3_[_config][10], 10, v12); break; + case 38 :/* 13.3 */ + v12 = createCenterVertex(i,j,k); + addTriangle(i,j,k, tiling13_3_[_config][11], 10, v12); break; + + case 39 :/* 13.2 */ + addTriangle(i,j,k, tiling13_2_[_config][0], 6); break; + case 40 :/* 13.2 */ + addTriangle(i,j,k, tiling13_2_[_config][1], 6); break; + case 41 :/* 13.2 */ + addTriangle(i,j,k, tiling13_2_[_config][2], 6); break; + case 42 :/* 13.2 */ + addTriangle(i,j,k, tiling13_2_[_config][3], 6); break; + case 43 :/* 13.2 */ + addTriangle(i,j,k, tiling13_2_[_config][4], 6); break; + case 44 :/* 13.2 */ + addTriangle(i,j,k, tiling13_2_[_config][5], 6); break; + + case 45 :/* 13.1 */ + addTriangle(i,j,k, tiling13_1_[_config], 4); break; + + default : + OVITO_ASSERT_MSG(false, "Marching cubes", "Impossible case 13?"); + } + break; + + case 14 : + addTriangle(i,j,k, tiling14[_config], 4); + break; + }; +} + +/****************************************************************************** +* Adds triangles to the mesh. +******************************************************************************/ +void MarchingCubes::addTriangle(int i, int j, int k, const char* trig, char n, HalfEdgeMesh<>::Vertex* v12) +{ + HalfEdgeMesh<>::Vertex* tv[3]; + + for(int t = 0; t < 3*n; t++) { + switch(trig[t]) { + case 0: tv[t % 3] = getEdgeVert(i , j , k, 0); break; + case 1: tv[t % 3] = getEdgeVert(i+1, j , k, 1); break; + case 2: tv[t % 3] = getEdgeVert(i , j+1, k, 0); break; + case 3: tv[t % 3] = getEdgeVert(i , j , k, 1); break; + case 4: tv[t % 3] = getEdgeVert(i , j , k+1,0); break; + case 5: tv[t % 3] = getEdgeVert(i+1, j , k+1,1); break; + case 6: tv[t % 3] = getEdgeVert(i , j+1, k+1,0); break; + case 7: tv[t % 3] = getEdgeVert(i , j , k+1,1); break; + case 8: tv[t % 3] = getEdgeVert(i , j , k, 2); break; + case 9: tv[t % 3] = getEdgeVert(i+1, j , k, 2); break; + case 10: tv[t % 3] = getEdgeVert(i+1, j+1, k, 2); break; + case 11: tv[t % 3] = getEdgeVert(i , j+1, k, 2); break; + case 12: tv[t % 3] = v12; break; + default: break; + } + OVITO_ASSERT_MSG(tv[t%3] != nullptr, "Marching cubes", "invalid triangle"); + + if(t%3 == 2) + _outputMesh.createFace({tv[2], tv[1], tv[0]}); + } +} + +/****************************************************************************** +* Adds a vertex inside the current cube. +******************************************************************************/ +HalfEdgeMesh<>::Vertex* MarchingCubes::createCenterVertex(int i, int j, int k) +{ + int u = 0; + Point3 p = Point3::Origin(); + + // Computes the average of the intersection points of the cube + auto addPosition = [&p, &u](const HalfEdgeMesh<>::Vertex* v) { + if(v) { + ++u; + p.x() += v->pos().x(); + p.y() += v->pos().y(); + p.z() += v->pos().z(); + } + }; + addPosition(getEdgeVert(i , j , k, 0)); + addPosition(getEdgeVert(i+1, j , k, 1)); + addPosition(getEdgeVert(i , j+1, k, 0)); + addPosition(getEdgeVert(i , j , k, 1)); + addPosition(getEdgeVert(i , j , k+1,0)); + addPosition(getEdgeVert(i+1, j , k+1,1)); + addPosition(getEdgeVert(i , j+1, k+1,0)); + addPosition(getEdgeVert(i , j , k+1,1)); + addPosition(getEdgeVert(i , j , k, 2)); + addPosition(getEdgeVert(i+1, j , k, 2)); + addPosition(getEdgeVert(i+1, j+1, k, 2)); + addPosition(getEdgeVert(i , j+1, k, 2)); + + p.x() /= u; + p.y() /= u; + p.z() /= u; + + return _outputMesh.createVertex(p); +} + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/fields/MarchingCubes.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/fields/MarchingCubes.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/fields/MarchingCubes.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/fields/MarchingCubes.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,153 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include +#include + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Fields) + +/** +* The Marching Cubes algorithm for constructing isosurfaces from grid data. +*/ +class MarchingCubes +{ +public: + + // Constructor + MarchingCubes(int size_x, int size_y, int size_z, const FloatType* fielddata, size_t stride, HalfEdgeMesh<>& outputMesh); + + /// Returns the field value in a specific cube of the grid. + /// Takes into account periodic boundary conditions. + inline const FloatType getFieldValue(int i, int j, int k) const { + if(i == _size_x) i = 0; + if(j == _size_y) j = 0; + if(k == _size_z) k = 0; + OVITO_ASSERT(i >= 0 && i < _size_x); + OVITO_ASSERT(j >= 0 && j < _size_y); + OVITO_ASSERT(k >= 0 && k < _size_z); + return _data[(i + j*_size_x + k*_size_x*_size_y) * _dataStride]; + } + + bool isCompletelySolid() const { return _isCompletelySolid; } + + bool generateIsosurface(FloatType iso, PromiseBase& promise); + +protected: + + /// Tessellates one cube. + void processCube(int i, int j, int k); + + /// tTests if the components of the tessellation of the cube should be + /// connected by the interior of an ambiguous face. + bool testFace(char face); + + /// Tests if the components of the tessellation of the cube should be + /// connected through the interior of the cube. + bool testInterior(char s); + + /// Computes almost all the vertices of the mesh by interpolation along the cubes edges. + void computeIntersectionPoints(FloatType iso, PromiseBase& promise); + + /// Adds triangles to the mesh. + void addTriangle(int i, int j, int k, const char* trig, char n, HalfEdgeMesh<>::Vertex* v12 = nullptr); + + /// Adds a vertex on the current horizontal edge. + HalfEdgeMesh<>::Vertex* createEdgeVertexX(int i, int j, int k, FloatType u) { + OVITO_ASSERT(i >= 0 && i < _size_x); + OVITO_ASSERT(j >= 0 && j < _size_y); + OVITO_ASSERT(k >= 0 && k < _size_z); + auto v = _outputMesh.createVertex(Point3(i + u, j, k)); + _cubeVerts[(i + j*_size_x + k*_size_x*_size_y)*3 + 0] = v; + return v; + } + + /// Adds a vertex on the current longitudinal edge. + HalfEdgeMesh<>::Vertex* createEdgeVertexY(int i, int j, int k, FloatType u) { + OVITO_ASSERT(i >= 0 && i < _size_x); + OVITO_ASSERT(j >= 0 && j < _size_y); + OVITO_ASSERT(k >= 0 && k < _size_z); + auto v = _outputMesh.createVertex(Point3(i, j + u, k)); + _cubeVerts[(i + j*_size_x + k*_size_x*_size_y)*3 + 1] = v; + return v; + } + + /// Adds a vertex on the current vertical edge. + HalfEdgeMesh<>::Vertex* createEdgeVertexZ(int i, int j, int k, FloatType u) { + OVITO_ASSERT(i >= 0 && i < _size_x); + OVITO_ASSERT(j >= 0 && j < _size_y); + OVITO_ASSERT(k >= 0 && k < _size_z); + auto v = _outputMesh.createVertex(Point3(i, j, k + u)); + _cubeVerts[(i + j*_size_x + k*_size_x*_size_y)*3 + 2] = v; + return v; + } + + /// Adds a vertex inside the current cube. + HalfEdgeMesh<>::Vertex* createCenterVertex(int i, int j, int k); + + /// Accesses the pre-computed vertex on a lower edge of a specific cube. + HalfEdgeMesh<>::Vertex* getEdgeVert(int i, int j, int k, int axis) const { + OVITO_ASSERT(i >= 0 && i <= _size_x); + OVITO_ASSERT(j >= 0 && j <= _size_y); + OVITO_ASSERT(k >= 0 && k <= _size_z); + OVITO_ASSERT(axis >= 0 && axis < 3); + if(i == _size_x) i = 0; + if(j == _size_y) j = 0; + if(k == _size_z) k = 0; + return _cubeVerts[(i + j*_size_x + k*_size_x*_size_y)*3 + axis]; + } + +protected : + int _size_x; ///< width of the grid + int _size_y; ///< depth of the grid + int _size_z; ///< height of the grid + const FloatType* _data; ///< implicit function values sampled on the grid + size_t _dataStride; + + /// Vertices created along cube edges. + std::vector::Vertex*> _cubeVerts; + + FloatType _cube[8]; ///< values of the implicit function on the active cube + unsigned char _lut_entry; ///< cube sign representation in [0..255] + unsigned char _case; ///< case of the active cube in [0..15] + unsigned char _config; ///< configuration of the active cube + unsigned char _subconfig; ///< subconfiguration of the active cube + + /// The generated mesh. + HalfEdgeMesh<>& _outputMesh; + + /// Flag that indicates whether all cube cells are on one side of the isosurface. + bool _isCompletelySolid; + +#ifdef FLOATTYPE_FLOAT + static constexpr FloatType _epsilon = FloatType(1e-12); +#else + static constexpr FloatType _epsilon = FloatType(1e-18); +#endif +}; + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/fields/MarchingCubesLookupTable.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/fields/MarchingCubesLookupTable.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/fields/MarchingCubesLookupTable.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/fields/MarchingCubesLookupTable.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,2322 @@ +/** + * @file LookUpTable.h + * @author Thomas Lewiner + * @author Math Dept, PUC-Rio + * @version 0.2 + * @date 12/08/2002 + * + * @brief LookUpTable for the MarchingCubes 33 Algorithm + */ +//________________________________________________ + + + +#ifndef _LOOKUPTABLE_H_ +#define _LOOKUPTABLE_H_ + + + + + +//_____________________________________________________________________________ +/** + * \brief case mapping + * For each of the possible vertex states listed in this table there is a + * specific triangulation of the edge intersection points. The table lists + * all of them in the form of 0-5 edge triples with the list terminated by + * the invalid value -1. For example: case[3] list the 2 triangles + * formed when cube[0] and cube[1] are inside of the surface, but the rest of + * the cube is not. + * + * Cube description: + * 7 ________ 6 _____6__ ________ + * /| /| 7/| /| /| /| + * / | / | / | /5 | / 6 / | + * 4 /_______ / | /__4____ / 10 /_______3/ | + * | | |5 | | 11 | | | | | 2 | + * | 3|__|_____|2 | |__|__2__| | 4 |__|_____| + * | / | / 8 3/ 9 / | / | / + * | / | / | / | /1 | / 5 / + * |/_______|/ |/___0___|/ |/_1_____|/ + * 0 1 0 1 + */ +//----------------------------------------------------------------------------- +static const char cases[256][2] = { +/* 0: */ { 0, -1 }, +/* 1: 0, */ { 1, 0 }, +/* 2: 1, */ { 1, 1 }, +/* 3: 0, 1, */ { 2, 0 }, +/* 4: 2, */ { 1, 2 }, +/* 5: 0, 2, */ { 3, 0 }, +/* 6: 1, 2, */ { 2, 3 }, +/* 7: 0, 1, 2, */ { 5, 0 }, +/* 8: 3, */ { 1, 3 }, +/* 9: 0, 3, */ { 2, 1 }, +/* 10: 1, 3, */ { 3, 3 }, +/* 11: 0, 1, 3, */ { 5, 1 }, +/* 12: 2, 3, */ { 2, 5 }, +/* 13: 0, 2, 3, */ { 5, 4 }, +/* 14: 1, 2, 3, */ { 5, 9 }, +/* 15: 0, 1, 2, 3, */ { 8, 0 }, +/* 16: 4, */ { 1, 4 }, +/* 17: 0, 4, */ { 2, 2 }, +/* 18: 1, 4, */ { 3, 4 }, +/* 19: 0, 1, 4, */ { 5, 2 }, +/* 20: 2, 4, */ { 4, 2 }, +/* 21: 0, 2, 4, */ { 6, 2 }, +/* 22: 1, 2, 4, */ { 6, 9 }, +/* 23: 0, 1, 2, 4, */ { 11, 0 }, +/* 24: 3, 4, */ { 3, 8 }, +/* 25: 0, 3, 4, */ { 5, 5 }, +/* 26: 1, 3, 4, */ { 7, 3 }, +/* 27: 0, 1, 3, 4, */ { 9, 1 }, +/* 28: 2, 3, 4, */ { 6, 16 }, +/* 29: 0, 2, 3, 4, */ { 14, 3 }, +/* 30: 1, 2, 3, 4, */ { 12, 12 }, +/* 31: 0, 1, 2, 3, 4, */ { 5, 24 }, +/* 32: 5, */ { 1, 5 }, +/* 33: 0, 5, */ { 3, 1 }, +/* 34: 1, 5, */ { 2, 4 }, +/* 35: 0, 1, 5, */ { 5, 3 }, +/* 36: 2, 5, */ { 3, 6 }, +/* 37: 0, 2, 5, */ { 7, 0 }, +/* 38: 1, 2, 5, */ { 5, 10 }, +/* 39: 0, 1, 2, 5, */ { 9, 0 }, +/* 40: 3, 5, */ { 4, 3 }, +/* 41: 0, 3, 5, */ { 6, 4 }, +/* 42: 1, 3, 5, */ { 6, 11 }, +/* 43: 0, 1, 3, 5, */ { 14, 1 }, +/* 44: 2, 3, 5, */ { 6, 17 }, +/* 45: 0, 2, 3, 5, */ { 12, 4 }, +/* 46: 1, 2, 3, 5, */ { 11, 6 }, +/* 47: 0, 1, 2, 3, 5, */ { 5, 25 }, +/* 48: 4, 5, */ { 2, 8 }, +/* 49: 0, 4, 5, */ { 5, 7 }, +/* 50: 1, 4, 5, */ { 5, 12 }, +/* 51: 0, 1, 4, 5, */ { 8, 1 }, +/* 52: 2, 4, 5, */ { 6, 18 }, +/* 53: 0, 2, 4, 5, */ { 12, 5 }, +/* 54: 1, 2, 4, 5, */ { 14, 7 }, +/* 55: 0, 1, 2, 4, 5, */ { 5, 28 }, +/* 56: 3, 4, 5, */ { 6, 21 }, +/* 57: 0, 3, 4, 5, */ { 11, 4 }, +/* 58: 1, 3, 4, 5, */ { 12, 15 }, +/* 59: 0, 1, 3, 4, 5, */ { 5, 30 }, +/* 60: 2, 3, 4, 5, */ { 10, 5 }, +/* 61: 0, 2, 3, 4, 5, */ { 6, 32 }, +/* 62: 1, 2, 3, 4, 5, */ { 6, 39 }, +/* 63: 0, 1, 2, 3, 4, 5, */ { 2, 12 }, +/* 64: 6, */ { 1, 6 }, +/* 65: 0, 6, */ { 4, 0 }, +/* 66: 1, 6, */ { 3, 5 }, +/* 67: 0, 1, 6, */ { 6, 0 }, +/* 68: 2, 6, */ { 2, 6 }, +/* 69: 0, 2, 6, */ { 6, 3 }, +/* 70: 1, 2, 6, */ { 5, 11 }, +/* 71: 0, 1, 2, 6, */ { 14, 0 }, +/* 72: 3, 6, */ { 3, 9 }, +/* 73: 0, 3, 6, */ { 6, 5 }, +/* 74: 1, 3, 6, */ { 7, 4 }, +/* 75: 0, 1, 3, 6, */ { 12, 1 }, +/* 76: 2, 3, 6, */ { 5, 14 }, +/* 77: 0, 2, 3, 6, */ { 11, 3 }, +/* 78: 1, 2, 3, 6, */ { 9, 4 }, +/* 79: 0, 1, 2, 3, 6, */ { 5, 26 }, +/* 80: 4, 6, */ { 3, 10 }, +/* 81: 0, 4, 6, */ { 6, 6 }, +/* 82: 1, 4, 6, */ { 7, 5 }, +/* 83: 0, 1, 4, 6, */ { 12, 2 }, +/* 84: 2, 4, 6, */ { 6, 19 }, +/* 85: 0, 2, 4, 6, */ { 10, 1 }, +/* 86: 1, 2, 4, 6, */ { 12, 13 }, +/* 87: 0, 1, 2, 4, 6, */ { 6, 24 }, +/* 88: 3, 4, 6, */ { 7, 7 }, +/* 89: 0, 3, 4, 6, */ { 12, 9 }, +/* 90: 1, 3, 4, 6, */ { 13, 1 }, +/* 91: 0, 1, 3, 4, 6, */ { 7, 9 }, +/* 92: 2, 3, 4, 6, */ { 12, 20 }, +/* 93: 0, 2, 3, 4, 6, */ { 6, 33 }, +/* 94: 1, 2, 3, 4, 6, */ { 7, 13 }, +/* 95: 0, 1, 2, 3, 4, 6, */ { 3, 12 }, +/* 96: 5, 6, */ { 2, 10 }, +/* 97: 0, 5, 6, */ { 6, 7 }, +/* 98: 1, 5, 6, */ { 5, 13 }, +/* 99: 0, 1, 5, 6, */ { 11, 2 }, +/* 100: 2, 5, 6, */ { 5, 16 }, +/* 101: 0, 2, 5, 6, */ { 12, 7 }, +/* 102: 1, 2, 5, 6, */ { 8, 3 }, +/* 103: 0, 1, 2, 5, 6, */ { 5, 29 }, +/* 104: 3, 5, 6, */ { 6, 22 }, +/* 105: 0, 3, 5, 6, */ { 10, 2 }, +/* 106: 1, 3, 5, 6, */ { 12, 17 }, +/* 107: 0, 1, 3, 5, 6, */ { 6, 27 }, +/* 108: 2, 3, 5, 6, */ { 14, 9 }, +/* 109: 0, 2, 3, 5, 6, */ { 6, 34 }, +/* 110: 1, 2, 3, 5, 6, */ { 5, 39 }, +/* 111: 0, 1, 2, 3, 5, 6, */ { 2, 14 }, +/* 112: 4, 5, 6, */ { 5, 20 }, +/* 113: 0, 4, 5, 6, */ { 14, 5 }, +/* 114: 1, 4, 5, 6, */ { 9, 5 }, +/* 115: 0, 1, 4, 5, 6, */ { 5, 32 }, +/* 116: 2, 4, 5, 6, */ { 11, 10 }, +/* 117: 0, 2, 4, 5, 6, */ { 6, 35 }, +/* 118: 1, 2, 4, 5, 6, */ { 5, 41 }, +/* 119: 0, 1, 2, 4, 5, 6, */ { 2, 16 }, +/* 120: 3, 4, 5, 6, */ { 12, 23 }, +/* 121: 0, 3, 4, 5, 6, */ { 6, 37 }, +/* 122: 1, 3, 4, 5, 6, */ { 7, 14 }, +/* 123: 0, 1, 3, 4, 5, 6, */ { 3, 16 }, +/* 124: 2, 3, 4, 5, 6, */ { 6, 46 }, +/* 125: 0, 2, 3, 4, 5, 6, */ { 4, 6 }, +/* 126: 1, 2, 3, 4, 5, 6, */ { 3, 21 }, +/* 127: 0, 1, 2, 3, 4, 5, 6, */ { 1, 8 }, +/* 128: 7, */ { 1, 7 }, +/* 129: 0, 7, */ { 3, 2 }, +/* 130: 1, 7, */ { 4, 1 }, +/* 131: 0, 1, 7, */ { 6, 1 }, +/* 132: 2, 7, */ { 3, 7 }, +/* 133: 0, 2, 7, */ { 7, 1 }, +/* 134: 1, 2, 7, */ { 6, 10 }, +/* 135: 0, 1, 2, 7, */ { 12, 0 }, +/* 136: 3, 7, */ { 2, 7 }, +/* 137: 0, 3, 7, */ { 5, 6 }, +/* 138: 1, 3, 7, */ { 6, 12 }, +/* 139: 0, 1, 3, 7, */ { 11, 1 }, +/* 140: 2, 3, 7, */ { 5, 15 }, +/* 141: 0, 2, 3, 7, */ { 9, 2 }, +/* 142: 1, 2, 3, 7, */ { 14, 6 }, +/* 143: 0, 1, 2, 3, 7, */ { 5, 27 }, +/* 144: 4, 7, */ { 2, 9 }, +/* 145: 0, 4, 7, */ { 5, 8 }, +/* 146: 1, 4, 7, */ { 6, 13 }, +/* 147: 0, 1, 4, 7, */ { 14, 2 }, +/* 148: 2, 4, 7, */ { 6, 20 }, +/* 149: 0, 2, 4, 7, */ { 12, 6 }, +/* 150: 1, 2, 4, 7, */ { 10, 3 }, +/* 151: 0, 1, 2, 4, 7, */ { 6, 25 }, +/* 152: 3, 4, 7, */ { 5, 18 }, +/* 153: 0, 3, 4, 7, */ { 8, 2 }, +/* 154: 1, 3, 4, 7, */ { 12, 16 }, +/* 155: 0, 1, 3, 4, 7, */ { 5, 31 }, +/* 156: 2, 3, 4, 7, */ { 11, 9 }, +/* 157: 0, 2, 3, 4, 7, */ { 5, 34 }, +/* 158: 1, 2, 3, 4, 7, */ { 6, 40 }, +/* 159: 0, 1, 2, 3, 4, 7, */ { 2, 13 }, +/* 160: 5, 7, */ { 3, 11 }, +/* 161: 0, 5, 7, */ { 7, 2 }, +/* 162: 1, 5, 7, */ { 6, 14 }, +/* 163: 0, 1, 5, 7, */ { 12, 3 }, +/* 164: 2, 5, 7, */ { 7, 6 }, +/* 165: 0, 2, 5, 7, */ { 13, 0 }, +/* 166: 1, 2, 5, 7, */ { 12, 14 }, +/* 167: 0, 1, 2, 5, 7, */ { 7, 8 }, +/* 168: 3, 5, 7, */ { 6, 23 }, +/* 169: 0, 3, 5, 7, */ { 12, 10 }, +/* 170: 1, 3, 5, 7, */ { 10, 4 }, +/* 171: 0, 1, 3, 5, 7, */ { 6, 28 }, +/* 172: 2, 3, 5, 7, */ { 12, 21 }, +/* 173: 0, 2, 3, 5, 7, */ { 7, 10 }, +/* 174: 1, 2, 3, 5, 7, */ { 6, 41 }, +/* 175: 0, 1, 2, 3, 5, 7, */ { 3, 13 }, +/* 176: 4, 5, 7, */ { 5, 21 }, +/* 177: 0, 4, 5, 7, */ { 9, 3 }, +/* 178: 1, 4, 5, 7, */ { 11, 8 }, +/* 179: 0, 1, 4, 5, 7, */ { 5, 33 }, +/* 180: 2, 4, 5, 7, */ { 12, 22 }, +/* 181: 0, 2, 4, 5, 7, */ { 7, 11 }, +/* 182: 1, 2, 4, 5, 7, */ { 6, 42 }, +/* 183: 0, 1, 2, 4, 5, 7, */ { 3, 14 }, +/* 184: 3, 4, 5, 7, */ { 14, 11 }, +/* 185: 0, 3, 4, 5, 7, */ { 5, 36 }, +/* 186: 1, 3, 4, 5, 7, */ { 6, 44 }, +/* 187: 0, 1, 3, 4, 5, 7, */ { 2, 17 }, +/* 188: 2, 3, 4, 5, 7, */ { 6, 47 }, +/* 189: 0, 2, 3, 4, 5, 7, */ { 3, 18 }, +/* 190: 1, 2, 3, 4, 5, 7, */ { 4, 7 }, +/* 191: 0, 1, 2, 3, 4, 5, 7, */ { 1, 9 }, +/* 192: 6, 7, */ { 2, 11 }, +/* 193: 0, 6, 7, */ { 6, 8 }, +/* 194: 1, 6, 7, */ { 6, 15 }, +/* 195: 0, 1, 6, 7, */ { 10, 0 }, +/* 196: 2, 6, 7, */ { 5, 17 }, +/* 197: 0, 2, 6, 7, */ { 12, 8 }, +/* 198: 1, 2, 6, 7, */ { 11, 7 }, +/* 199: 0, 1, 2, 6, 7, */ { 6, 26 }, +/* 200: 3, 6, 7, */ { 5, 19 }, +/* 201: 0, 3, 6, 7, */ { 14, 4 }, +/* 202: 1, 3, 6, 7, */ { 12, 18 }, +/* 203: 0, 1, 3, 6, 7, */ { 6, 29 }, +/* 204: 2, 3, 6, 7, */ { 8, 4 }, +/* 205: 0, 2, 3, 6, 7, */ { 5, 35 }, +/* 206: 1, 2, 3, 6, 7, */ { 5, 40 }, +/* 207: 0, 1, 2, 3, 6, 7, */ { 2, 15 }, +/* 208: 4, 6, 7, */ { 5, 22 }, +/* 209: 0, 4, 6, 7, */ { 11, 5 }, +/* 210: 1, 4, 6, 7, */ { 12, 19 }, +/* 211: 0, 1, 4, 6, 7, */ { 6, 30 }, +/* 212: 2, 4, 6, 7, */ { 14, 10 }, +/* 213: 0, 2, 4, 6, 7, */ { 6, 36 }, +/* 214: 1, 2, 4, 6, 7, */ { 6, 43 }, +/* 215: 0, 1, 2, 4, 6, 7, */ { 4, 4 }, +/* 216: 3, 4, 6, 7, */ { 9, 7 }, +/* 217: 0, 3, 4, 6, 7, */ { 5, 37 }, +/* 218: 1, 3, 4, 6, 7, */ { 7, 15 }, +/* 219: 0, 1, 3, 4, 6, 7, */ { 3, 17 }, +/* 220: 2, 3, 4, 6, 7, */ { 5, 44 }, +/* 221: 0, 2, 3, 4, 6, 7, */ { 2, 19 }, +/* 222: 1, 2, 3, 4, 6, 7, */ { 3, 22 }, +/* 223: 0, 1, 2, 3, 4, 6, 7, */ { 1, 10 }, +/* 224: 5, 6, 7, */ { 5, 23 }, +/* 225: 0, 5, 6, 7, */ { 12, 11 }, +/* 226: 1, 5, 6, 7, */ { 14, 8 }, +/* 227: 0, 1, 5, 6, 7, */ { 6, 31 }, +/* 228: 2, 5, 6, 7, */ { 9, 6 }, +/* 229: 0, 2, 5, 6, 7, */ { 7, 12 }, +/* 230: 1, 2, 5, 6, 7, */ { 5, 42 }, +/* 231: 0, 1, 2, 5, 6, 7, */ { 3, 15 }, +/* 232: 3, 5, 6, 7, */ { 11, 11 }, +/* 233: 0, 3, 5, 6, 7, */ { 6, 38 }, +/* 234: 1, 3, 5, 6, 7, */ { 6, 45 }, +/* 235: 0, 1, 3, 5, 6, 7, */ { 4, 5 }, +/* 236: 2, 3, 5, 6, 7, */ { 5, 45 }, +/* 237: 0, 2, 3, 5, 6, 7, */ { 3, 19 }, +/* 238: 1, 2, 3, 5, 6, 7, */ { 2, 21 }, +/* 239: 0, 1, 2, 3, 5, 6, 7, */ { 1, 11 }, +/* 240: 4, 5, 6, 7, */ { 8, 5 }, +/* 241: 0, 4, 5, 6, 7, */ { 5, 38 }, +/* 242: 1, 4, 5, 6, 7, */ { 5, 43 }, +/* 243: 0, 1, 4, 5, 6, 7, */ { 2, 18 }, +/* 244: 2, 4, 5, 6, 7, */ { 5, 46 }, +/* 245: 0, 2, 4, 5, 6, 7, */ { 3, 20 }, +/* 246: 1, 2, 4, 5, 6, 7, */ { 2, 22 }, +/* 247: 0, 1, 2, 4, 5, 6, 7, */ { 1, 12 }, +/* 248: 3, 4, 5, 6, 7, */ { 5, 47 }, +/* 249: 0, 3, 4, 5, 6, 7, */ { 2, 20 }, +/* 250: 1, 3, 4, 5, 6, 7, */ { 3, 23 }, +/* 251: 0, 1, 3, 4, 5, 6, 7, */ { 1, 13 }, +/* 252: 2, 3, 4, 5, 6, 7, */ { 2, 23 }, +/* 253: 0, 2, 3, 4, 5, 6, 7, */ { 1, 14 }, +/* 254: 1, 2, 3, 4, 5, 6, 7, */ { 1, 15 }, +/* 255: 0, 1, 2, 3, 4, 5, 6, 7, */ { 0, -1 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling1[16][3] = { +/* 1: 0, */ { 0, 8, 3 }, +/* 2: 1, */ { 0, 1, 9 }, +/* 4: 2, */ { 1, 2, 10 }, +/* 8: 3, */ { 3, 11, 2 }, +/* 16: 4, */ { 4, 7, 8 }, +/* 32: 5, */ { 9, 5, 4 }, +/* 64: 6, */ { 10, 6, 5 }, +/* 128: 7, */ { 7, 6, 11 }, +/* 127: 0, 1, 2, 3, 4, 5, 6, */ { 7, 11, 6 }, +/* 191: 0, 1, 2, 3, 4, 5, 7, */ { 10, 5, 6 }, +/* 223: 0, 1, 2, 3, 4, 6, 7, */ { 9, 4, 5 }, +/* 239: 0, 1, 2, 3, 5, 6, 7, */ { 4, 8, 7 }, +/* 247: 0, 1, 2, 4, 5, 6, 7, */ { 3, 2, 11 }, +/* 251: 0, 1, 3, 4, 5, 6, 7, */ { 1, 10, 2 }, +/* 253: 0, 2, 3, 4, 5, 6, 7, */ { 0, 9, 1 }, +/* 254: 1, 2, 3, 4, 5, 6, 7, */ { 0, 3, 8 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling2[24][6] = { +/* 3: 0, 1, */ { 1, 8, 3, 9, 8, 1 }, +/* 9: 0, 3, */ { 0, 11, 2, 8, 11, 0 }, +/* 17: 0, 4, */ { 4, 3, 0, 7, 3, 4 }, +/* 6: 1, 2, */ { 9, 2, 10, 0, 2, 9 }, +/* 34: 1, 5, */ { 0, 5, 4, 1, 5, 0 }, +/* 12: 2, 3, */ { 3, 10, 1, 11, 10, 3 }, +/* 68: 2, 6, */ { 1, 6, 5, 2, 6, 1 }, +/* 136: 3, 7, */ { 7, 2, 3, 6, 2, 7 }, +/* 48: 4, 5, */ { 9, 7, 8, 5, 7, 9 }, +/* 144: 4, 7, */ { 6, 8, 4, 11, 8, 6 }, +/* 96: 5, 6, */ { 10, 4, 9, 6, 4, 10 }, +/* 192: 6, 7, */ { 11, 5, 10, 7, 5, 11 }, +/* 63: 0, 1, 2, 3, 4, 5, */ { 11, 10, 5, 7, 11, 5 }, +/* 159: 0, 1, 2, 3, 4, 7, */ { 10, 9, 4, 6, 10, 4 }, +/* 111: 0, 1, 2, 3, 5, 6, */ { 6, 4, 8, 11, 6, 8 }, +/* 207: 0, 1, 2, 3, 6, 7, */ { 9, 8, 7, 5, 9, 7 }, +/* 119: 0, 1, 2, 4, 5, 6, */ { 7, 3, 2, 6, 7, 2 }, +/* 187: 0, 1, 3, 4, 5, 7, */ { 1, 5, 6, 2, 1, 6 }, +/* 243: 0, 1, 4, 5, 6, 7, */ { 3, 1, 10, 11, 3, 10 }, +/* 221: 0, 2, 3, 4, 6, 7, */ { 0, 4, 5, 1, 0, 5 }, +/* 249: 0, 3, 4, 5, 6, 7, */ { 9, 10, 2, 0, 9, 2 }, +/* 238: 1, 2, 3, 5, 6, 7, */ { 4, 0, 3, 7, 4, 3 }, +/* 246: 1, 2, 4, 5, 6, 7, */ { 0, 2, 11, 8, 0, 11 }, +/* 252: 2, 3, 4, 5, 6, 7, */ { 1, 3, 8, 9, 1, 8 } +}; +//_____________________________________________________________________________ + +//_____________________________________________________________________________ +/** + * \brief test table for case 3 + * One face to test + * When the test on the specified face is positive : 4 first triangles + * When the test on the specified face is negative : 2 last triangles + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char test3[24] = { +/* 5: 0, 2, */ 5, +/* 33: 0, 5, */ 1, +/* 129: 0, 7, */ 4, +/* 10: 1, 3, */ 5, +/* 18: 1, 4, */ 1, +/* 66: 1, 6, */ 2, +/* 36: 2, 5, */ 2, +/* 132: 2, 7, */ 3, +/* 24: 3, 4, */ 4, +/* 72: 3, 6, */ 3, +/* 80: 4, 6, */ 6, +/* 160: 5, 7, */ 6, +/* 95: 0, 1, 2, 3, 4, 6, */ -6, +/* 175: 0, 1, 2, 3, 5, 7, */ -6, +/* 183: 0, 1, 2, 4, 5, 7, */ -3, +/* 231: 0, 1, 2, 5, 6, 7, */ -4, +/* 123: 0, 1, 3, 4, 5, 6, */ -3, +/* 219: 0, 1, 3, 4, 6, 7, */ -2, +/* 189: 0, 2, 3, 4, 5, 7, */ -2, +/* 237: 0, 2, 3, 5, 6, 7, */ -1, +/* 245: 0, 2, 4, 5, 6, 7, */ -5, +/* 126: 1, 2, 3, 4, 5, 6, */ -4, +/* 222: 1, 2, 3, 4, 6, 7, */ -1, +/* 250: 1, 3, 4, 5, 6, 7, */ -5 +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 3.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling3_1[24][6] = { +/* 5: 0, 2, */ { 0, 8, 3, 1, 2, 10 }, +/* 33: 0, 5, */ { 9, 5, 4, 0, 8, 3 }, +/* 129: 0, 7, */ { 3, 0, 8, 11, 7, 6 }, +/* 10: 1, 3, */ { 1, 9, 0, 2, 3, 11 }, +/* 18: 1, 4, */ { 0, 1, 9, 8, 4, 7 }, +/* 66: 1, 6, */ { 9, 0, 1, 5, 10, 6 }, +/* 36: 2, 5, */ { 1, 2, 10, 9, 5, 4 }, +/* 132: 2, 7, */ { 10, 1, 2, 6, 11, 7 }, +/* 24: 3, 4, */ { 8, 4, 7, 3, 11, 2 }, +/* 72: 3, 6, */ { 2, 3, 11, 10, 6, 5 }, +/* 80: 4, 6, */ { 5, 10, 6, 4, 7, 8 }, +/* 160: 5, 7, */ { 4, 9, 5, 7, 6, 11 }, +/* 95: 0, 1, 2, 3, 4, 6, */ { 5, 9, 4, 11, 6, 7 }, +/* 175: 0, 1, 2, 3, 5, 7, */ { 6, 10, 5, 8, 7, 4 }, +/* 183: 0, 1, 2, 4, 5, 7, */ { 11, 3, 2, 5, 6, 10 }, +/* 231: 0, 1, 2, 5, 6, 7, */ { 7, 4, 8, 2, 11, 3 }, +/* 123: 0, 1, 3, 4, 5, 6, */ { 2, 1, 10, 7, 11, 6 }, +/* 219: 0, 1, 3, 4, 6, 7, */ { 10, 2, 1, 4, 5, 9 }, +/* 189: 0, 2, 3, 4, 5, 7, */ { 1, 0, 9, 6, 10, 5 }, +/* 237: 0, 2, 3, 5, 6, 7, */ { 9, 1, 0, 7, 4, 8 }, +/* 245: 0, 2, 4, 5, 6, 7, */ { 0, 9, 1, 11, 3, 2 }, +/* 126: 1, 2, 3, 4, 5, 6, */ { 8, 0, 3, 6, 7, 11 }, +/* 222: 1, 2, 3, 4, 6, 7, */ { 4, 5, 9, 3, 8, 0 }, +/* 250: 1, 3, 4, 5, 6, 7, */ { 3, 8, 0, 10, 2, 1 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 3.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling3_2[24][12] = { +/* 5: 0, 2, */ { 10, 3, 2, 10, 8, 3, 10, 1, 0, 8, 10, 0 }, +/* 33: 0, 5, */ { 3, 4, 8, 3, 5, 4, 3, 0, 9, 5, 3, 9 }, +/* 129: 0, 7, */ { 6, 8, 7, 6, 0, 8, 6, 11, 3, 0, 6, 3 }, +/* 10: 1, 3, */ { 11, 0, 3, 11, 9, 0, 11, 2, 1, 9, 11, 1 }, +/* 18: 1, 4, */ { 7, 9, 4, 7, 1, 9, 7, 8, 0, 1, 7, 0 }, +/* 66: 1, 6, */ { 6, 1, 10, 6, 0, 1, 9, 0, 6, 9, 6, 5 }, +/* 36: 2, 5, */ { 4, 10, 5, 4, 2, 10, 4, 9, 1, 2, 4, 1 }, +/* 132: 2, 7, */ { 7, 2, 11, 7, 1, 2, 7, 6, 10, 1, 7, 10 }, +/* 24: 3, 4, */ { 2, 7, 11, 2, 4, 7, 2, 3, 8, 4, 2, 8 }, +/* 72: 3, 6, */ { 5, 11, 6, 5, 3, 11, 5, 10, 2, 3, 5, 2 }, +/* 80: 4, 6, */ { 8, 6, 7, 8, 10, 6, 8, 4, 5, 10, 8, 5 }, +/* 160: 5, 7, */ { 11, 5, 6, 11, 9, 5, 11, 7, 4, 9, 11, 4 }, +/* 95: 0, 1, 2, 3, 4, 6, */ { 6, 5, 11, 5, 9, 11, 4, 7, 11, 4, 11, 9 }, +/* 175: 0, 1, 2, 3, 5, 7, */ { 7, 6, 8, 6, 10, 8, 5, 4, 8, 5, 8, 10 }, +/* 183: 0, 1, 2, 4, 5, 7, */ { 6, 11, 5, 11, 3, 5, 2, 10, 5, 2, 5, 3 }, +/* 231: 0, 1, 2, 5, 6, 7, */ { 11, 7, 2, 7, 4, 2, 8, 3, 2, 8, 2, 4 }, +/* 123: 0, 1, 3, 4, 5, 6, */ { 11, 2, 7, 2, 1, 7, 10, 6, 7, 10, 7, 1 }, +/* 219: 0, 1, 3, 4, 6, 7, */ { 5, 10, 4, 10, 2, 4, 1, 9, 4, 1, 4, 2 }, +/* 189: 0, 2, 3, 4, 5, 7, */ { 10, 1, 6, 1, 0, 6, 6, 0, 9, 5, 6, 9 }, +/* 237: 0, 2, 3, 5, 6, 7, */ { 4, 9, 7, 9, 1, 7, 0, 8, 7, 0, 7, 1 }, +/* 245: 0, 2, 4, 5, 6, 7, */ { 3, 0, 11, 0, 9, 11, 1, 2, 11, 1, 11, 9 }, +/* 126: 1, 2, 3, 4, 5, 6, */ { 7, 8, 6, 8, 0, 6, 3, 11, 6, 3, 6, 0 }, +/* 222: 1, 2, 3, 4, 6, 7, */ { 8, 4, 3, 4, 5, 3, 9, 0, 3, 9, 3, 5 }, +/* 250: 1, 3, 4, 5, 6, 7, */ { 2, 3, 10, 3, 8, 10, 0, 1, 10, 0, 10, 8 } +}; +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +/** + * \brief test table for case 4 + * Interior to test + * When the test on the interior is negative : 2 first triangles + * When the test on the interior is positive : 6 last triangles + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char test4[8] = { +/* 65: 0, 6, */ 7, +/* 130: 1, 7, */ 7, +/* 20: 2, 4, */ 7, +/* 40: 3, 5, */ 7, +/* 215: 0, 1, 2, 4, 6, 7, */ -7, +/* 235: 0, 1, 3, 5, 6, 7, */ -7, +/* 125: 0, 2, 3, 4, 5, 6, */ -7, +/* 190: 1, 2, 3, 4, 5, 7, */ -7 +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 4.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling4_1[8][6] = { +/* 65: 0, 6, */ { 0, 8, 3, 5, 10, 6 }, +/* 130: 1, 7, */ { 0, 1, 9, 11, 7, 6 }, +/* 20: 2, 4, */ { 1, 2, 10, 8, 4, 7 }, +/* 40: 3, 5, */ { 9, 5, 4, 2, 3, 11 }, +/* 215: 0, 1, 2, 4, 6, 7, */ { 4, 5, 9, 11, 3, 2 }, +/* 235: 0, 1, 3, 5, 6, 7, */ { 10, 2, 1, 7, 4, 8 }, +/* 125: 0, 2, 3, 4, 5, 6, */ { 9, 1, 0, 6, 7, 11 }, +/* 190: 1, 2, 3, 4, 5, 7, */ { 3, 8, 0, 6, 10, 5 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 4.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling4_2[8][18] = { +/* 65: 0, 6, */ { 8, 5, 0, 5, 8, 6, 3, 6, 8, 6, 3, 10, 0, 10, 3, 10, 0, 5 }, +/* 130: 1, 7, */ { 9, 6, 1, 6, 9, 7, 0, 7, 9, 7, 0, 11, 1, 11, 0, 11, 1, 6 }, +/* 20: 2, 4, */ { 10, 7, 2, 7, 10, 4, 1, 4, 10, 4, 1, 8, 2, 8, 1, 8, 2, 7 }, +/* 40: 3, 5, */ { 11, 4, 3, 4, 11, 5, 2, 5, 11, 5, 2, 9, 3, 9, 2, 9, 3, 4 }, +/* 215: 0, 1, 2, 4, 6, 7, */ { 3, 4, 11, 5, 11, 4, 11, 5, 2, 9, 2, 5, 2, 9, 3, 4, 3, 9 }, +/* 235: 0, 1, 3, 5, 6, 7, */ { 2, 7, 10, 4, 10, 7, 10, 4, 1, 8, 1, 4, 1, 8, 2, 7, 2, 8 }, +/* 125: 0, 2, 3, 4, 5, 6, */ { 1, 6, 9, 7, 9, 6, 9, 7, 0, 11, 0, 7, 0, 11, 1, 6, 1, 11 }, +/* 190: 1, 2, 3, 4, 5, 7, */ { 0, 5, 8, 6, 8, 5, 8, 6, 3, 10, 3, 6, 3, 10, 0, 5, 0, 10 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 5 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling5[48][9] = { +/* 7: 0, 1, 2, */ { 2, 8, 3, 2, 10, 8, 10, 9, 8 }, +/* 11: 0, 1, 3, */ { 1, 11, 2, 1, 9, 11, 9, 8, 11 }, +/* 19: 0, 1, 4, */ { 4, 1, 9, 4, 7, 1, 7, 3, 1 }, +/* 35: 0, 1, 5, */ { 8, 5, 4, 8, 3, 5, 3, 1, 5 }, +/* 13: 0, 2, 3, */ { 0, 10, 1, 0, 8, 10, 8, 11, 10 }, +/* 25: 0, 3, 4, */ { 11, 4, 7, 11, 2, 4, 2, 0, 4 }, +/* 137: 0, 3, 7, */ { 7, 0, 8, 7, 6, 0, 6, 2, 0 }, +/* 49: 0, 4, 5, */ { 9, 3, 0, 9, 5, 3, 5, 7, 3 }, +/* 145: 0, 4, 7, */ { 3, 6, 11, 3, 0, 6, 0, 4, 6 }, +/* 14: 1, 2, 3, */ { 3, 9, 0, 3, 11, 9, 11, 10, 9 }, +/* 38: 1, 2, 5, */ { 5, 2, 10, 5, 4, 2, 4, 0, 2 }, +/* 70: 1, 2, 6, */ { 9, 6, 5, 9, 0, 6, 0, 2, 6 }, +/* 50: 1, 4, 5, */ { 0, 7, 8, 0, 1, 7, 1, 5, 7 }, +/* 98: 1, 5, 6, */ { 10, 0, 1, 10, 6, 0, 6, 4, 0 }, +/* 76: 2, 3, 6, */ { 6, 3, 11, 6, 5, 3, 5, 1, 3 }, +/* 140: 2, 3, 7, */ { 10, 7, 6, 10, 1, 7, 1, 3, 7 }, +/* 100: 2, 5, 6, */ { 1, 4, 9, 1, 2, 4, 2, 6, 4 }, +/* 196: 2, 6, 7, */ { 11, 1, 2, 11, 7, 1, 7, 5, 1 }, +/* 152: 3, 4, 7, */ { 8, 2, 3, 8, 4, 2, 4, 6, 2 }, +/* 200: 3, 6, 7, */ { 2, 5, 10, 2, 3, 5, 3, 7, 5 }, +/* 112: 4, 5, 6, */ { 7, 10, 6, 7, 8, 10, 8, 9, 10 }, +/* 176: 4, 5, 7, */ { 6, 9, 5, 6, 11, 9, 11, 8, 9 }, +/* 208: 4, 6, 7, */ { 5, 8, 4, 5, 10, 8, 10, 11, 8 }, +/* 224: 5, 6, 7, */ { 4, 11, 7, 4, 9, 11, 9, 10, 11 }, +/* 31: 0, 1, 2, 3, 4, */ { 4, 7, 11, 4, 11, 9, 9, 11, 10 }, +/* 47: 0, 1, 2, 3, 5, */ { 5, 4, 8, 5, 8, 10, 10, 8, 11 }, +/* 79: 0, 1, 2, 3, 6, */ { 6, 5, 9, 6, 9, 11, 11, 9, 8 }, +/* 143: 0, 1, 2, 3, 7, */ { 7, 6, 10, 7, 10, 8, 8, 10, 9 }, +/* 55: 0, 1, 2, 4, 5, */ { 2, 10, 5, 2, 5, 3, 3, 5, 7 }, +/* 103: 0, 1, 2, 5, 6, */ { 8, 3, 2, 8, 2, 4, 4, 2, 6 }, +/* 59: 0, 1, 3, 4, 5, */ { 11, 2, 1, 11, 1, 7, 7, 1, 5 }, +/* 155: 0, 1, 3, 4, 7, */ { 1, 9, 4, 1, 4, 2, 2, 4, 6 }, +/* 115: 0, 1, 4, 5, 6, */ { 10, 6, 7, 10, 7, 1, 1, 7, 3 }, +/* 179: 0, 1, 4, 5, 7, */ { 6, 11, 3, 6, 3, 5, 5, 3, 1 }, +/* 157: 0, 2, 3, 4, 7, */ { 10, 1, 0, 10, 0, 6, 6, 0, 4 }, +/* 205: 0, 2, 3, 6, 7, */ { 0, 8, 7, 0, 7, 1, 1, 7, 5 }, +/* 185: 0, 3, 4, 5, 7, */ { 9, 5, 6, 9, 6, 0, 0, 6, 2 }, +/* 217: 0, 3, 4, 6, 7, */ { 5, 10, 2, 5, 2, 4, 4, 2, 0 }, +/* 241: 0, 4, 5, 6, 7, */ { 3, 0, 9, 3, 9, 11, 11, 9, 10 }, +/* 110: 1, 2, 3, 5, 6, */ { 3, 11, 6, 3, 6, 0, 0, 6, 4 }, +/* 206: 1, 2, 3, 6, 7, */ { 9, 0, 3, 9, 3, 5, 5, 3, 7 }, +/* 118: 1, 2, 4, 5, 6, */ { 7, 8, 0, 7, 0, 6, 6, 0, 2 }, +/* 230: 1, 2, 5, 6, 7, */ { 11, 7, 4, 11, 4, 2, 2, 4, 0 }, +/* 242: 1, 4, 5, 6, 7, */ { 0, 1, 10, 0, 10, 8, 8, 10, 11 }, +/* 220: 2, 3, 4, 6, 7, */ { 8, 4, 5, 8, 5, 3, 3, 5, 1 }, +/* 236: 2, 3, 5, 6, 7, */ { 4, 9, 1, 4, 1, 7, 7, 1, 3 }, +/* 244: 2, 4, 5, 6, 7, */ { 1, 2, 11, 1, 11, 9, 9, 11, 8 }, +/* 248: 3, 4, 5, 6, 7, */ { 2, 3, 8, 2, 8, 10, 10, 8, 9 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief test table for case 6 + * 1 face to test + eventually the interior + * When the test on the specified face is positive : 5 first triangles + * When the test on the specified face is negative : + * - if the test on the interior is negative : 3 middle triangles + * - if the test on the interior is positive : 8 last triangles + * The support edge for the interior test is marked as the 3rd column. + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char test6[48][3] = { +/* 67: 0, 1, 6, */ { 2, 7, 10 }, +/* 131: 0, 1, 7, */ { 4, 7, 11 }, +/* 21: 0, 2, 4, */ { 5, 7, 1 }, +/* 69: 0, 2, 6, */ { 5, 7, 3 }, +/* 41: 0, 3, 5, */ { 1, 7, 9 }, +/* 73: 0, 3, 6, */ { 3, 7, 10 }, +/* 81: 0, 4, 6, */ { 6, 7, 5 }, +/* 97: 0, 5, 6, */ { 1, 7, 8 }, +/* 193: 0, 6, 7, */ { 4, 7, 8 }, +/* 22: 1, 2, 4, */ { 1, 7, 8 }, +/* 134: 1, 2, 7, */ { 3, 7, 11 }, +/* 42: 1, 3, 5, */ { 5, 7, 2 }, +/* 138: 1, 3, 7, */ { 5, 7, 0 }, +/* 146: 1, 4, 7, */ { 1, 7, 9 }, +/* 162: 1, 5, 7, */ { 6, 7, 6 }, +/* 194: 1, 6, 7, */ { 2, 7, 9 }, +/* 28: 2, 3, 4, */ { 4, 7, 8 }, +/* 44: 2, 3, 5, */ { 2, 7, 9 }, +/* 52: 2, 4, 5, */ { 2, 7, 10 }, +/* 84: 2, 4, 6, */ { 6, 7, 7 }, +/* 148: 2, 4, 7, */ { 3, 7, 10 }, +/* 56: 3, 4, 5, */ { 4, 7, 11 }, +/* 104: 3, 5, 6, */ { 3, 7, 11 }, +/* 168: 3, 5, 7, */ { 6, 7, 4 }, +/* 87: 0, 1, 2, 4, 6, */ { -6, -7, 4 }, +/* 151: 0, 1, 2, 4, 7, */ { -3, -7, 11 }, +/* 199: 0, 1, 2, 6, 7, */ { -4, -7, 11 }, +/* 107: 0, 1, 3, 5, 6, */ { -3, -7, 10 }, +/* 171: 0, 1, 3, 5, 7, */ { -6, -7, 7 }, +/* 203: 0, 1, 3, 6, 7, */ { -2, -7, 10 }, +/* 211: 0, 1, 4, 6, 7, */ { -2, -7, 9 }, +/* 227: 0, 1, 5, 6, 7, */ { -4, -7, 8 }, +/* 61: 0, 2, 3, 4, 5, */ { -2, -7, 9 }, +/* 93: 0, 2, 3, 4, 6, */ { -6, -7, 6 }, +/* 109: 0, 2, 3, 5, 6, */ { -1, -7, 9 }, +/* 117: 0, 2, 4, 5, 6, */ { -5, -7, 0 }, +/* 213: 0, 2, 4, 6, 7, */ { -5, -7, 2 }, +/* 121: 0, 3, 4, 5, 6, */ { -3, -7, 11 }, +/* 233: 0, 3, 5, 6, 7, */ { -1, -7, 8 }, +/* 62: 1, 2, 3, 4, 5, */ { -4, -7, 8 }, +/* 158: 1, 2, 3, 4, 7, */ { -1, -7, 8 }, +/* 174: 1, 2, 3, 5, 7, */ { -6, -7, 5 }, +/* 182: 1, 2, 4, 5, 7, */ { -3, -7, 10 }, +/* 214: 1, 2, 4, 6, 7, */ { -1, -7, 9 }, +/* 186: 1, 3, 4, 5, 7, */ { -5, -7, 3 }, +/* 234: 1, 3, 5, 6, 7, */ { -5, -7, 1 }, +/* 124: 2, 3, 4, 5, 6, */ { -4, -7, 11 }, +/* 188: 2, 3, 4, 5, 7, */ { -2, -7, 10 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 6.1.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling6_1_1[48][9] = { +/* 67: 0, 1, 6, */ { 6, 5, 10, 3, 1, 8, 9, 8, 1 }, +/* 131: 0, 1, 7, */ { 11, 7, 6, 9, 3, 1, 3, 9, 8 }, +/* 21: 0, 2, 4, */ { 1, 2, 10, 7, 0, 4, 0, 7, 3 }, +/* 69: 0, 2, 6, */ { 3, 0, 8, 5, 2, 6, 2, 5, 1 }, +/* 41: 0, 3, 5, */ { 5, 4, 9, 2, 0, 11, 8, 11, 0 }, +/* 73: 0, 3, 6, */ { 10, 6, 5, 8, 2, 0, 2, 8, 11 }, +/* 81: 0, 4, 6, */ { 10, 6, 5, 0, 4, 3, 7, 3, 4 }, +/* 97: 0, 5, 6, */ { 3, 0, 8, 6, 4, 10, 9, 10, 4 }, +/* 193: 0, 6, 7, */ { 8, 3, 0, 10, 7, 5, 7, 10, 11 }, +/* 22: 1, 2, 4, */ { 8, 4, 7, 10, 0, 2, 0, 10, 9 }, +/* 134: 1, 2, 7, */ { 7, 6, 11, 0, 2, 9, 10, 9, 2 }, +/* 42: 1, 3, 5, */ { 2, 3, 11, 4, 1, 5, 1, 4, 0 }, +/* 138: 1, 3, 7, */ { 0, 1, 9, 6, 3, 7, 3, 6, 2 }, +/* 146: 1, 4, 7, */ { 9, 0, 1, 11, 4, 6, 4, 11, 8 }, +/* 162: 1, 5, 7, */ { 11, 7, 6, 1, 5, 0, 4, 0, 5 }, +/* 194: 1, 6, 7, */ { 0, 1, 9, 7, 5, 11, 10, 11, 5 }, +/* 28: 2, 3, 4, */ { 4, 7, 8, 1, 3, 10, 11, 10, 3 }, +/* 44: 2, 3, 5, */ { 9, 5, 4, 11, 1, 3, 1, 11, 10 }, +/* 52: 2, 4, 5, */ { 10, 1, 2, 8, 5, 7, 5, 8, 9 }, +/* 84: 2, 4, 6, */ { 8, 4, 7, 2, 6, 1, 5, 1, 6 }, +/* 148: 2, 4, 7, */ { 1, 2, 10, 4, 6, 8, 11, 8, 6 }, +/* 56: 3, 4, 5, */ { 2, 3, 11, 5, 7, 9, 8, 9, 7 }, +/* 104: 3, 5, 6, */ { 11, 2, 3, 9, 6, 4, 6, 9, 10 }, +/* 168: 3, 5, 7, */ { 9, 5, 4, 3, 7, 2, 6, 2, 7 }, +/* 87: 0, 1, 2, 4, 6, */ { 4, 5, 9, 2, 7, 3, 7, 2, 6 }, +/* 151: 0, 1, 2, 4, 7, */ { 3, 2, 11, 4, 6, 9, 10, 9, 6 }, +/* 199: 0, 1, 2, 6, 7, */ { 11, 3, 2, 9, 7, 5, 7, 9, 8 }, +/* 107: 0, 1, 3, 5, 6, */ { 10, 2, 1, 8, 6, 4, 6, 8, 11 }, +/* 171: 0, 1, 3, 5, 7, */ { 7, 4, 8, 1, 6, 2, 6, 1, 5 }, +/* 203: 0, 1, 3, 6, 7, */ { 2, 1, 10, 7, 5, 8, 9, 8, 5 }, +/* 211: 0, 1, 4, 6, 7, */ { 4, 5, 9, 3, 1, 11, 10, 11, 1 }, +/* 227: 0, 1, 5, 6, 7, */ { 8, 7, 4, 10, 3, 1, 3, 10, 11 }, +/* 61: 0, 2, 3, 4, 5, */ { 9, 1, 0, 11, 5, 7, 5, 11, 10 }, +/* 93: 0, 2, 3, 4, 6, */ { 6, 7, 11, 0, 5, 1, 5, 0, 4 }, +/* 109: 0, 2, 3, 5, 6, */ { 1, 0, 9, 6, 4, 11, 8, 11, 4 }, +/* 117: 0, 2, 4, 5, 6, */ { 9, 1, 0, 7, 3, 6, 2, 6, 3 }, +/* 213: 0, 2, 4, 6, 7, */ { 11, 3, 2, 5, 1, 4, 0, 4, 1 }, +/* 121: 0, 3, 4, 5, 6, */ { 11, 6, 7, 9, 2, 0, 2, 9, 10 }, +/* 233: 0, 3, 5, 6, 7, */ { 7, 4, 8, 2, 0, 10, 9, 10, 0 }, +/* 62: 1, 2, 3, 4, 5, */ { 0, 3, 8, 5, 7, 10, 11, 10, 7 }, +/* 158: 1, 2, 3, 4, 7, */ { 8, 0, 3, 10, 4, 6, 4, 10, 9 }, +/* 174: 1, 2, 3, 5, 7, */ { 5, 6, 10, 3, 4, 0, 4, 3, 7 }, +/* 182: 1, 2, 4, 5, 7, */ { 5, 6, 10, 0, 2, 8, 11, 8, 2 }, +/* 214: 1, 2, 4, 6, 7, */ { 9, 4, 5, 11, 0, 2, 0, 11, 8 }, +/* 186: 1, 3, 4, 5, 7, */ { 8, 0, 3, 6, 2, 5, 1, 5, 2 }, +/* 234: 1, 3, 5, 6, 7, */ { 10, 2, 1, 4, 0, 7, 3, 7, 0 }, +/* 124: 2, 3, 4, 5, 6, */ { 6, 7, 11, 1, 3, 9, 8, 9, 3 }, +/* 188: 2, 3, 4, 5, 7, */ { 10, 5, 6, 8, 1, 3, 1, 8, 9 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 6.1.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling6_1_2[48][27] = { + /* 67: 0, 1, 6, */ { 1, 12, 3, 12, 10, 3, 6, 3, 10, 3, 6, 8, 5, 8, 6, 8, 5, 12, 12, 9, 8, 1, 9, 12, 12, 5, 10 }, + /* 131: 0, 1, 7, */ { 1, 12, 3, 1, 11, 12, 11, 1, 6, 9, 6, 1, 6, 9, 7, 12, 7, 9, 9, 8, 12, 12, 8, 3, 11, 7, 12 }, + /* 21: 0, 2, 4, */ { 4, 12, 0, 4, 1, 12, 1, 4, 10, 7, 10, 4, 10, 7, 2, 12, 2, 7, 7, 3, 12, 12, 3, 0, 1, 2, 12 }, + /* 69: 0, 2, 6, */ { 6, 12, 2, 6, 3, 12, 3, 6, 8, 5, 8, 6, 8, 5, 0, 12, 0, 5, 5, 1, 12, 12, 1, 2, 3, 0, 12 }, + /* 41: 0, 3, 5, */ { 0, 12, 2, 12, 9, 2, 5, 2, 9, 2, 5, 11, 4, 11, 5, 11, 4, 12, 12, 8, 11, 0, 8, 12, 12, 4, 9 }, + /* 73: 0, 3, 6, */ { 0, 12, 2, 0, 10, 12, 10, 0, 5, 8, 5, 0, 5, 8, 6, 12, 6, 8, 8, 11, 12, 12, 11, 2, 10, 6, 12 }, + /* 81: 0, 4, 6, */ { 4, 12, 0, 12, 5, 0, 10, 0, 5, 0, 10, 3, 6, 3, 10, 3, 6, 12, 12, 7, 3, 4, 7, 12, 12, 6, 5 }, + /* 97: 0, 5, 6, */ { 4, 12, 6, 12, 8, 6, 3, 6, 8, 6, 3, 10, 0, 10, 3, 10, 0, 12, 12, 9, 10, 4, 9, 12, 12, 0, 8 }, + /* 193: 0, 6, 7, */ { 5, 12, 7, 5, 8, 12, 8, 5, 0, 10, 0, 5, 0, 10, 3, 12, 3, 10, 10, 11, 12, 12, 11, 7, 8, 3, 12 }, + /* 22: 1, 2, 4, */ { 2, 12, 0, 2, 8, 12, 8, 2, 7, 10, 7, 2, 7, 10, 4, 12, 4, 10, 10, 9, 12, 12, 9, 0, 8, 4, 12 }, + /* 134: 1, 2, 7, */ { 2, 12, 0, 12, 11, 0, 7, 0, 11, 0, 7, 9, 6, 9, 7, 9, 6, 12, 12, 10, 9, 2, 10, 12, 12, 6, 11 }, + /* 42: 1, 3, 5, */ { 5, 12, 1, 5, 2, 12, 2, 5, 11, 4, 11, 5, 11, 4, 3, 12, 3, 4, 4, 0, 12, 12, 0, 1, 2, 3, 12 }, + /* 138: 1, 3, 7, */ { 7, 12, 3, 7, 0, 12, 0, 7, 9, 6, 9, 7, 9, 6, 1, 12, 1, 6, 6, 2, 12, 12, 2, 3, 0, 1, 12 }, + /* 146: 1, 4, 7, */ { 6, 12, 4, 6, 9, 12, 9, 6, 1, 11, 1, 6, 1, 11, 0, 12, 0, 11, 11, 8, 12, 12, 8, 4, 9, 0, 12 }, + /* 162: 1, 5, 7, */ { 5, 12, 1, 12, 6, 1, 11, 1, 6, 1, 11, 0, 7, 0, 11, 0, 7, 12, 12, 4, 0, 5, 4, 12, 12, 7, 6 }, + /* 194: 1, 6, 7, */ { 5, 12, 7, 12, 9, 7, 0, 7, 9, 7, 0, 11, 1, 11, 0, 11, 1, 12, 12, 10, 11, 5, 10, 12, 12, 1, 9 }, + /* 28: 2, 3, 4, */ { 3, 12, 1, 12, 8, 1, 4, 1, 8, 1, 4, 10, 7, 10, 4, 10, 7, 12, 12, 11, 10, 3, 11, 12, 12, 7, 8 }, + /* 44: 2, 3, 5, */ { 3, 12, 1, 3, 9, 12, 9, 3, 4, 11, 4, 3, 4, 11, 5, 12, 5, 11, 11, 10, 12, 12, 10, 1, 9, 5, 12 }, + /* 52: 2, 4, 5, */ { 7, 12, 5, 7, 10, 12, 10, 7, 2, 8, 2, 7, 2, 8, 1, 12, 1, 8, 8, 9, 12, 12, 9, 5, 10, 1, 12 }, + /* 84: 2, 4, 6, */ { 6, 12, 2, 12, 7, 2, 8, 2, 7, 2, 8, 1, 4, 1, 8, 1, 4, 12, 12, 5, 1, 6, 5, 12, 12, 4, 7 }, + /* 148: 2, 4, 7, */ { 6, 12, 4, 12, 10, 4, 1, 4, 10, 4, 1, 8, 2, 8, 1, 8, 2, 12, 12, 11, 8, 6, 11, 12, 12, 2, 10 }, + /* 56: 3, 4, 5, */ { 7, 12, 5, 12, 11, 5, 2, 5, 11, 5, 2, 9, 3, 9, 2, 9, 3, 12, 12, 8, 9, 7, 8, 12, 12, 3, 11 }, + /* 104: 3, 5, 6, */ { 4, 12, 6, 4, 11, 12, 11, 4, 3, 9, 3, 4, 3, 9, 2, 12, 2, 9, 9, 10, 12, 12, 10, 6, 11, 2, 12 }, + /* 168: 3, 5, 7, */ { 7, 12, 3, 12, 4, 3, 9, 3, 4, 3, 9, 2, 5, 2, 9, 2, 5, 12, 12, 6, 2, 7, 6, 12, 12, 5, 4 }, + /* 87: 0, 1, 2, 4, 6, */ { 3, 12, 7, 3, 4, 12, 4, 3, 9, 2, 9, 3, 9, 2, 5, 12, 5, 2, 2, 6, 12, 12, 6, 7, 4, 5, 12 }, + /* 151: 0, 1, 2, 4, 7, */ { 6, 12, 4, 12, 11, 4, 3, 4, 11, 4, 3, 9, 2, 9, 3, 9, 2, 12, 12, 10, 9, 6, 10, 12, 12, 2, 11 }, + /* 199: 0, 1, 2, 6, 7, */ { 5, 12, 7, 5, 11, 12, 11, 5, 2, 9, 2, 5, 2, 9, 3, 12, 3, 9, 9, 8, 12, 12, 8, 7, 11, 3, 12 }, + /* 107: 0, 1, 3, 5, 6, */ { 4, 12, 6, 4, 10, 12, 10, 4, 1, 8, 1, 4, 1, 8, 2, 12, 2, 8, 8, 11, 12, 12, 11, 6, 10, 2, 12 }, + /* 171: 0, 1, 3, 5, 7, */ { 2, 12, 6, 2, 7, 12, 7, 2, 8, 1, 8, 2, 8, 1, 4, 12, 4, 1, 1, 5, 12, 12, 5, 6, 7, 4, 12 }, + /* 203: 0, 1, 3, 6, 7, */ { 5, 12, 7, 12, 10, 7, 2, 7, 10, 7, 2, 8, 1, 8, 2, 8, 1, 12, 12, 9, 8, 5, 9, 12, 12, 1, 10 }, + /* 211: 0, 1, 4, 6, 7, */ { 1, 12, 3, 12, 9, 3, 4, 3, 9, 3, 4, 11, 5, 11, 4, 11, 5, 12, 12, 10, 11, 1, 10, 12, 12, 5, 9 }, + /* 227: 0, 1, 5, 6, 7, */ { 1, 12, 3, 1, 8, 12, 8, 1, 4, 10, 4, 1, 4, 10, 7, 12, 7, 10, 10, 11, 12, 12, 11, 3, 8, 7, 12 }, + /* 61: 0, 2, 3, 4, 5, */ { 7, 12, 5, 7, 9, 12, 9, 7, 0, 11, 0, 7, 0, 11, 1, 12, 1, 11, 11, 10, 12, 12, 10, 5, 9, 1, 12 }, + /* 93: 0, 2, 3, 4, 6, */ { 1, 12, 5, 1, 6, 12, 6, 1, 11, 0, 11, 1, 11, 0, 7, 12, 7, 0, 0, 4, 12, 12, 4, 5, 6, 7, 12 }, + /* 109: 0, 2, 3, 5, 6, */ { 4, 12, 6, 12, 9, 6, 1, 6, 9, 6, 1, 11, 0, 11, 1, 11, 0, 12, 12, 8, 11, 4, 8, 12, 12, 0, 9 }, + /* 117: 0, 2, 4, 5, 6, */ { 3, 12, 7, 12, 0, 7, 9, 7, 0, 7, 9, 6, 1, 6, 9, 6, 1, 12, 12, 2, 6, 3, 2, 12, 12, 1, 0 }, + /* 213: 0, 2, 4, 6, 7, */ { 1, 12, 5, 12, 2, 5, 11, 5, 2, 5, 11, 4, 3, 4, 11, 4, 3, 12, 12, 0, 4, 1, 0, 12, 12, 3, 2 }, + /* 121: 0, 3, 4, 5, 6, */ { 0, 12, 2, 0, 11, 12, 11, 0, 7, 9, 7, 0, 7, 9, 6, 12, 6, 9, 9, 10, 12, 12, 10, 2, 11, 6, 12 }, + /* 233: 0, 3, 5, 6, 7, */ { 0, 12, 2, 12, 8, 2, 7, 2, 8, 2, 7, 10, 4, 10, 7, 10, 4, 12, 12, 9, 10, 0, 9, 12, 12, 4, 8 }, + /* 62: 1, 2, 3, 4, 5, */ { 7, 12, 5, 12, 8, 5, 0, 5, 8, 5, 0, 10, 3, 10, 0, 10, 3, 12, 12, 11, 10, 7, 11, 12, 12, 3, 8 }, + /* 158: 1, 2, 3, 4, 7, */ { 6, 12, 4, 6, 8, 12, 8, 6, 3, 10, 3, 6, 3, 10, 0, 12, 0, 10, 10, 9, 12, 12, 9, 4, 8, 0, 12 }, + /* 174: 1, 2, 3, 5, 7, */ { 0, 12, 4, 0, 5, 12, 5, 0, 10, 3, 10, 0, 10, 3, 6, 12, 6, 3, 3, 7, 12, 12, 7, 4, 5, 6, 12 }, + /* 182: 1, 2, 4, 5, 7, */ { 2, 12, 0, 12, 10, 0, 5, 0, 10, 0, 5, 8, 6, 8, 5, 8, 6, 12, 12, 11, 8, 2, 11, 12, 12, 6, 10 }, + /* 214: 1, 2, 4, 6, 7, */ { 2, 12, 0, 2, 9, 12, 9, 2, 5, 11, 5, 2, 5, 11, 4, 12, 4, 11, 11, 8, 12, 12, 8, 0, 9, 4, 12 }, + /* 186: 1, 3, 4, 5, 7, */ { 2, 12, 6, 12, 3, 6, 8, 6, 3, 6, 8, 5, 0, 5, 8, 5, 0, 12, 12, 1, 5, 2, 1, 12, 12, 0, 3 }, + /* 234: 1, 3, 5, 6, 7, */ { 0, 12, 4, 12, 1, 4, 10, 4, 1, 4, 10, 7, 2, 7, 10, 7, 2, 12, 12, 3, 7, 0, 3, 12, 12, 2, 1 }, + /* 124: 2, 3, 4, 5, 6, */ { 3, 12, 1, 12, 11, 1, 6, 1, 11, 1, 6, 9, 7, 9, 6, 9, 7, 12, 12, 8, 9, 3, 8, 12, 12, 7, 11 }, + /* 188: 2, 3, 4, 5, 7, */ { 3, 12, 1, 3, 10, 12, 10, 3, 6, 8, 6, 3, 6, 8, 5, 12, 5, 8, 8, 9, 12, 12, 9, 1, 10, 5, 12 }, +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 6.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling6_2[48][15] = { +/* 67: 0, 1, 6, */ { 1, 10, 3, 6, 3, 10, 3, 6, 8, 5, 8, 6, 8, 5, 9 }, +/* 131: 0, 1, 7, */ { 1, 11, 3, 11, 1, 6, 9, 6, 1, 6, 9, 7, 8, 7, 9 }, +/* 21: 0, 2, 4, */ { 4, 1, 0, 1, 4, 10, 7, 10, 4, 10, 7, 2, 3, 2, 7 }, +/* 69: 0, 2, 6, */ { 6, 3, 2, 3, 6, 8, 5, 8, 6, 8, 5, 0, 1, 0, 5 }, +/* 41: 0, 3, 5, */ { 0, 9, 2, 5, 2, 9, 2, 5, 11, 4, 11, 5, 11, 4, 8 }, +/* 73: 0, 3, 6, */ { 0, 10, 2, 10, 0, 5, 8, 5, 0, 5, 8, 6, 11, 6, 8 }, +/* 81: 0, 4, 6, */ { 4, 5, 0, 10, 0, 5, 0, 10, 3, 6, 3, 10, 3, 6, 7 }, +/* 97: 0, 5, 6, */ { 4, 8, 6, 3, 6, 8, 6, 3, 10, 0, 10, 3, 10, 0, 9 }, +/* 193: 0, 6, 7, */ { 5, 8, 7, 8, 5, 0, 10, 0, 5, 0, 10, 3, 11, 3, 10 }, +/* 22: 1, 2, 4, */ { 2, 8, 0, 8, 2, 7, 10, 7, 2, 7, 10, 4, 9, 4, 10 }, +/* 134: 1, 2, 7, */ { 2, 11, 0, 7, 0, 11, 0, 7, 9, 6, 9, 7, 9, 6, 10 }, +/* 42: 1, 3, 5, */ { 5, 2, 1, 2, 5, 11, 4, 11, 5, 11, 4, 3, 0, 3, 4 }, +/* 138: 1, 3, 7, */ { 7, 0, 3, 0, 7, 9, 6, 9, 7, 9, 6, 1, 2, 1, 6 }, +/* 146: 1, 4, 7, */ { 6, 9, 4, 9, 6, 1, 11, 1, 6, 1, 11, 0, 8, 0, 11 }, +/* 162: 1, 5, 7, */ { 5, 6, 1, 11, 1, 6, 1, 11, 0, 7, 0, 11, 0, 7, 4 }, +/* 194: 1, 6, 7, */ { 5, 9, 7, 0, 7, 9, 7, 0, 11, 1, 11, 0, 11, 1, 10 }, +/* 28: 2, 3, 4, */ { 3, 8, 1, 4, 1, 8, 1, 4, 10, 7, 10, 4, 10, 7, 11 }, +/* 44: 2, 3, 5, */ { 3, 9, 1, 9, 3, 4, 11, 4, 3, 4, 11, 5, 10, 5, 11 }, +/* 52: 2, 4, 5, */ { 7, 10, 5, 10, 7, 2, 8, 2, 7, 2, 8, 1, 9, 1, 8 }, +/* 84: 2, 4, 6, */ { 6, 7, 2, 8, 2, 7, 2, 8, 1, 4, 1, 8, 1, 4, 5 }, +/* 148: 2, 4, 7, */ { 6, 10, 4, 1, 4, 10, 4, 1, 8, 2, 8, 1, 8, 2, 11 }, +/* 56: 3, 4, 5, */ { 7, 11, 5, 2, 5, 11, 5, 2, 9, 3, 9, 2, 9, 3, 8 }, +/* 104: 3, 5, 6, */ { 4, 11, 6, 11, 4, 3, 9, 3, 4, 3, 9, 2, 10, 2, 9 }, +/* 168: 3, 5, 7, */ { 7, 4, 3, 9, 3, 4, 3, 9, 2, 5, 2, 9, 2, 5, 6 }, +/* 87: 0, 1, 2, 4, 6, */ { 3, 4, 7, 4, 3, 9, 2, 9, 3, 9, 2, 5, 6, 5, 2 }, +/* 151: 0, 1, 2, 4, 7, */ { 6, 11, 4, 3, 4, 11, 4, 3, 9, 2, 9, 3, 9, 2, 10 }, +/* 199: 0, 1, 2, 6, 7, */ { 5, 11, 7, 11, 5, 2, 9, 2, 5, 2, 9, 3, 8, 3, 9 }, +/* 107: 0, 1, 3, 5, 6, */ { 4, 10, 6, 10, 4, 1, 8, 1, 4, 1, 8, 2, 11, 2, 8 }, +/* 171: 0, 1, 3, 5, 7, */ { 2, 7, 6, 7, 2, 8, 1, 8, 2, 8, 1, 4, 5, 4, 1 }, +/* 203: 0, 1, 3, 6, 7, */ { 5, 10, 7, 2, 7, 10, 7, 2, 8, 1, 8, 2, 8, 1, 9 }, +/* 211: 0, 1, 4, 6, 7, */ { 1, 9, 3, 4, 3, 9, 3, 4, 11, 5, 11, 4, 11, 5, 10 }, +/* 227: 0, 1, 5, 6, 7, */ { 1, 8, 3, 8, 1, 4, 10, 4, 1, 4, 10, 7, 11, 7, 10 }, +/* 61: 0, 2, 3, 4, 5, */ { 7, 9, 5, 9, 7, 0, 11, 0, 7, 0, 11, 1, 10, 1, 11 }, +/* 93: 0, 2, 3, 4, 6, */ { 1, 6, 5, 6, 1, 11, 0, 11, 1, 11, 0, 7, 4, 7, 0 }, +/* 109: 0, 2, 3, 5, 6, */ { 4, 9, 6, 1, 6, 9, 6, 1, 11, 0, 11, 1, 11, 0, 8 }, +/* 117: 0, 2, 4, 5, 6, */ { 3, 0, 7, 9, 7, 0, 7, 9, 6, 1, 6, 9, 6, 1, 2 }, +/* 213: 0, 2, 4, 6, 7, */ { 1, 2, 5, 11, 5, 2, 5, 11, 4, 3, 4, 11, 4, 3, 0 }, +/* 121: 0, 3, 4, 5, 6, */ { 0, 11, 2, 11, 0, 7, 9, 7, 0, 7, 9, 6, 10, 6, 9 }, +/* 233: 0, 3, 5, 6, 7, */ { 0, 8, 2, 7, 2, 8, 2, 7, 10, 4, 10, 7, 10, 4, 9 }, +/* 62: 1, 2, 3, 4, 5, */ { 7, 8, 5, 0, 5, 8, 5, 0, 10, 3, 10, 0, 10, 3, 11 }, +/* 158: 1, 2, 3, 4, 7, */ { 6, 8, 4, 8, 6, 3, 10, 3, 6, 3, 10, 0, 9, 0, 10 }, +/* 174: 1, 2, 3, 5, 7, */ { 0, 5, 4, 5, 0, 10, 3, 10, 0, 10, 3, 6, 7, 6, 3 }, +/* 182: 1, 2, 4, 5, 7, */ { 2, 10, 0, 5, 0, 10, 0, 5, 8, 6, 8, 5, 8, 6, 11 }, +/* 214: 1, 2, 4, 6, 7, */ { 2, 9, 0, 9, 2, 5, 11, 5, 2, 5, 11, 4, 8, 4, 11 }, +/* 186: 1, 3, 4, 5, 7, */ { 2, 3, 6, 8, 6, 3, 6, 8, 5, 0, 5, 8, 5, 0, 1 }, +/* 234: 1, 3, 5, 6, 7, */ { 0, 1, 4, 10, 4, 1, 4, 10, 7, 2, 7, 10, 7, 2, 3 }, +/* 124: 2, 3, 4, 5, 6, */ { 3, 11, 1, 6, 1, 11, 1, 6, 9, 7, 9, 6, 9, 7, 8 }, +/* 188: 2, 3, 4, 5, 7, */ { 3, 10, 1, 10, 3, 6, 8, 6, 3, 6, 8, 5, 9, 5, 8 } +}; +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +/** + * \brief test table for case 7 + * 3 faces to test + eventually the interior + * When the tests on the 3 specified faces are positive : + * - if the test on the interior is positive : 5 first triangles + * - if the test on the interior is negative : 9 next triangles + * When the tests on the first and the second specified faces are positive : 9 next triangles + * When the tests on the first and the third specified faces are positive : 9 next triangles + * When the tests on the second and the third specified faces are positive : 9 next triangles + * When the test on the first specified face is positive : 5 next triangles + * When the test on the second specified face is positive : 5 next triangles + * When the test on the third specified face is positive : 5 next triangles + * When the tests on the 3 specified faces are negative : 3 last triangles + * The support edge for the interior test is marked as the 5th column. + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char test7[16][5] = { +/* 37: 0, 2, 5, */ { 1, 2, 5, 7, 1 }, +/* 133: 0, 2, 7, */ { 3, 4, 5, 7, 3 }, +/* 161: 0, 5, 7, */ { 4, 1, 6, 7, 4 }, +/* 26: 1, 3, 4, */ { 4, 1, 5, 7, 0 }, +/* 74: 1, 3, 6, */ { 2, 3, 5, 7, 2 }, +/* 82: 1, 4, 6, */ { 1, 2, 6, 7, 5 }, +/* 164: 2, 5, 7, */ { 2, 3, 6, 7, 6 }, +/* 88: 3, 4, 6, */ { 3, 4, 6, 7, 7 }, +/* 167: 0, 1, 2, 5, 7, */ { -3, -4, -6, -7, 7 }, +/* 91: 0, 1, 3, 4, 6, */ { -2, -3, -6, -7, 6 }, +/* 173: 0, 2, 3, 5, 7, */ { -1, -2, -6, -7, 5 }, +/* 181: 0, 2, 4, 5, 7, */ { -2, -3, -5, -7, 2 }, +/* 229: 0, 2, 5, 6, 7, */ { -4, -1, -5, -7, 0 }, +/* 94: 1, 2, 3, 4, 6, */ { -4, -1, -6, -7, 4 }, +/* 122: 1, 3, 4, 5, 6, */ { -3, -4, -5, -7, 3 }, +/* 218: 1, 3, 4, 6, 7, */ { -1, -2, -5, -7, 1 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 7.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling7_1[16][9] = { +/* 37: 0, 2, 5, */ { 9, 5, 4, 10, 1, 2, 8, 3, 0 }, +/* 133: 0, 2, 7, */ { 11, 7, 6, 8, 3, 0, 10, 1, 2 }, +/* 161: 0, 5, 7, */ { 3, 0, 8, 5, 4, 9, 7, 6, 11 }, +/* 26: 1, 3, 4, */ { 8, 4, 7, 9, 0, 1, 11, 2, 3 }, +/* 74: 1, 3, 6, */ { 10, 6, 5, 11, 2, 3, 9, 0, 1 }, +/* 82: 1, 4, 6, */ { 0, 1, 9, 6, 5, 10, 4, 7, 8 }, +/* 164: 2, 5, 7, */ { 1, 2, 10, 7, 6, 11, 5, 4, 9 }, +/* 88: 3, 4, 6, */ { 2, 3, 11, 4, 7, 8, 6, 5, 10 }, +/* 167: 0, 1, 2, 5, 7, */ { 11, 3, 2, 8, 7, 4, 10, 5, 6 }, +/* 91: 0, 1, 3, 4, 6, */ { 10, 2, 1, 11, 6, 7, 9, 4, 5 }, +/* 173: 0, 2, 3, 5, 7, */ { 9, 1, 0, 10, 5, 6, 8, 7, 4 }, +/* 181: 0, 2, 4, 5, 7, */ { 5, 6, 10, 3, 2, 11, 1, 0, 9 }, +/* 229: 0, 2, 5, 6, 7, */ { 7, 4, 8, 1, 0, 9, 3, 2, 11 }, +/* 94: 1, 2, 3, 4, 6, */ { 8, 0, 3, 9, 4, 5, 11, 6, 7 }, +/* 122: 1, 3, 4, 5, 6, */ { 6, 7, 11, 0, 3, 8, 2, 1, 10 }, +/* 218: 1, 3, 4, 6, 7, */ { 4, 5, 9, 2, 1, 10, 0, 3, 8 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 7.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling7_2[16][3][15] = { +/* 37: 0, 2, 5, */ { + /* 1,0 */ { 1, 2, 10, 3, 4, 8, 4, 3, 5, 0, 5, 3, 5, 0, 9 }, + /* 0,1 */ { 3, 0, 8, 9, 1, 4, 2, 4, 1, 4, 2, 5, 10, 5, 2 }, + /* 1,1 */ { 9, 5, 4, 0, 10, 1, 10, 0, 8, 10, 8, 2, 3, 2, 8 } +}, +/* 133: 0, 2, 7, */ { + /* 1,0 */ { 3, 0, 8, 1, 6, 10, 6, 1, 7, 2, 7, 1, 7, 2, 11 }, + /* 0,1 */ { 1, 2, 10, 11, 3, 6, 0, 6, 3, 6, 0, 7, 8, 7, 0 }, + /* 1,1 */ { 11, 7, 6, 2, 8, 3, 8, 2, 10, 8, 10, 0, 1, 0, 10 } +}, +/* 161: 0, 5, 7, */ { + /* 1,0 */ { 9, 5, 4, 11, 3, 6, 0, 6, 3, 6, 0, 7, 8, 7, 0 }, + /* 0,1 */ { 11, 7, 6, 3, 4, 8, 4, 3, 5, 0, 5, 3, 5, 0, 9 }, + /* 1,1 */ { 3, 0, 8, 4, 9, 7, 11, 7, 9, 5, 11, 9, 11, 5, 6 } +}, +/* 26: 1, 3, 4, */ { + /* 1,0 */ { 0, 1, 9, 2, 7, 11, 7, 2, 4, 3, 4, 2, 4, 3, 8 }, + /* 0,1 */ { 2, 3, 11, 8, 0, 7, 1, 7, 0, 7, 1, 4, 9, 4, 1 }, + /* 1,1 */ { 8, 4, 7, 3, 9, 0, 9, 3, 11, 9, 11, 1, 2, 1, 11 } +}, +/* 74: 1, 3, 6, */ { + /* 1,0 */ { 2, 3, 11, 0, 5, 9, 5, 0, 6, 1, 6, 0, 6, 1, 10 }, + /* 0,1 */ { 0, 1, 9, 10, 2, 5, 3, 5, 2, 5, 3, 6, 11, 6, 3 }, + /* 1,1 */ { 6, 5, 10, 1, 11, 2, 11, 1, 9, 11, 9, 3, 0, 3, 9 } +}, +/* 82: 1, 4, 6, */ { + /* 1,0 */ { 6, 5, 10, 8, 0, 7, 1, 7, 0, 7, 1, 4, 9, 4, 1 }, + /* 0,1 */ { 8, 4, 7, 0, 5, 9, 5, 0, 6, 1, 6, 0, 6, 1, 10 }, + /* 1,1 */ { 0, 1, 9, 5, 10, 4, 8, 4, 10, 6, 8, 10, 8, 6, 7 } +}, +/* 164: 2, 5, 7, */ { + /* 1,0 */ { 11, 7, 6, 9, 1, 4, 2, 4, 1, 4, 2, 5, 10, 5, 2 }, + /* 0,1 */ { 9, 5, 4, 1, 6, 10, 6, 1, 7, 2, 7, 1, 7, 2, 11 }, + /* 1,1 */ { 1, 2, 10, 6, 11, 5, 9, 5, 11, 7, 9, 11, 9, 7, 4 } +}, +/* 88: 3, 4, 6, */ { + /* 1,0 */ { 8, 4, 7, 10, 2, 5, 3, 5, 2, 5, 3, 6, 11, 6, 3 }, + /* 0,1 */ { 6, 5, 10, 2, 7, 11, 7, 2, 4, 3, 4, 2, 4, 3, 8 }, + /* 1,1 */ { 2, 3, 11, 7, 8, 6, 10, 6, 8, 4, 10, 8, 10, 4, 5 } +}, +/* 167: 0, 1, 2, 5, 7, */ { + /* 1,0 */ { 7, 4, 8, 5, 2, 10, 2, 5, 3, 6, 3, 5, 3, 6, 11 }, + /* 0,1 */ { 10, 5, 6, 11, 7, 2, 4, 2, 7, 2, 4, 3, 8, 3, 4 }, + /* 1,1 */ { 11, 3, 2, 6, 8, 7, 8, 6, 10, 8, 10, 4, 5, 4, 10 } +}, +/* 91: 0, 1, 3, 4, 6, */ { + /* 1,0 */ { 6, 7, 11, 4, 1, 9, 1, 4, 2, 5, 2, 4, 2, 5, 10 }, + /* 0,1 */ { 4, 5, 9, 10, 6, 1, 7, 1, 6, 1, 7, 2, 11, 2, 7 }, + /* 1,1 */ { 10, 2, 1, 5, 11, 6, 11, 5, 9, 11, 9, 7, 4, 7, 9 } +}, +/* 173: 0, 2, 3, 5, 7, */ { + /* 1,0 */ { 10, 5, 6, 7, 0, 8, 0, 7, 1, 4, 1, 7, 1, 4, 9 }, + /* 0,1 */ { 7, 4, 8, 9, 5, 0, 6, 0, 5, 0, 6, 1, 10, 1, 6 }, + /* 1,1 */ { 9, 1, 0, 4, 10, 5, 10, 4, 8, 10, 8, 6, 7, 6, 8 } +}, +/* 181: 0, 2, 4, 5, 7, */ { + /* 1,0 */ { 11, 3, 2, 9, 5, 0, 6, 0, 5, 0, 6, 1, 10, 1, 6 }, + /* 0,1 */ { 9, 1, 0, 5, 2, 10, 2, 5, 3, 6, 3, 5, 3, 6, 11 }, + /* 1,1 */ { 10, 5, 6, 2, 11, 1, 9, 1, 11, 3, 9, 11, 9, 3, 0 } +}, +/* 229: 0, 2, 5, 6, 7, */ { + /* 1,0 */ { 9, 1, 0, 11, 7, 2, 4, 2, 7, 2, 4, 3, 8, 3, 4 }, + /* 0,1 */ { 11, 3, 2, 7, 0, 8, 0, 7, 1, 4, 1, 7, 1, 4, 9 }, + /* 1,1 */ { 7, 4, 8, 0, 9, 3, 11, 3, 9, 1, 11, 9, 11, 1, 2 } +}, +/* 94: 1, 2, 3, 4, 6, */ { + /* 1,0 */ { 4, 5, 9, 6, 3, 11, 3, 6, 0, 7, 0, 6, 0, 7, 8 }, + /* 0,1 */ { 6, 7, 11, 8, 4, 3, 5, 3, 4, 3, 5, 0, 9, 0, 5 }, + /* 1,1 */ { 8, 0, 3, 7, 9, 4, 9, 7, 11, 9, 11, 5, 6, 5, 11 } +}, +/* 122: 1, 3, 4, 5, 6, */ { + /* 1,0 */ { 8, 0, 3, 10, 6, 1, 7, 1, 6, 1, 7, 2, 11, 2, 7 }, + /* 0,1 */ { 10, 2, 1, 6, 3, 11, 3, 6, 0, 7, 0, 6, 0, 7, 8 }, + /* 1,1 */ { 6, 7, 11, 3, 8, 2, 10, 2, 8, 0, 10, 8, 10, 0, 1 } +}, +/* 218: 1, 3, 4, 6, 7, */ { + /* 1,0 */ { 10, 2, 1, 8, 4, 3, 5, 3, 4, 3, 5, 0, 9, 0, 5 }, + /* 0,1 */ { 8, 0, 3, 4, 1, 9, 1, 4, 2, 5, 2, 4, 2, 5, 10 }, + /* 1,1 */ { 4, 5, 9, 1, 10, 0, 8, 0, 10, 2, 8, 10, 8, 2, 3 } } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 7.3 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling7_3[16][3][27] = { +/* 37: 0, 2, 5, */ { + /* 1,0 */ { 12, 2, 10, 12, 10, 5, 12, 5, 4, 12, 4, 8, 12, 8, 3, 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2 }, + /* 0,1 */ { 12, 5, 4, 12, 4, 8, 12, 8, 3, 12, 3, 2, 12, 2, 10, 12, 10, 1, 12, 1, 0, 12, 0, 9, 12, 9, 5 }, + /* 1,1 */ { 5, 4, 12, 10, 5, 12, 2, 10, 12, 3, 2, 12, 8, 3, 12, 0, 8, 12, 1, 0, 12, 9, 1, 12, 4, 9, 12 } +}, +/* 133: 0, 2, 7, */ { + /* 1,0 */ { 12, 0, 8, 12, 8, 7, 12, 7, 6, 12, 6, 10, 12, 10, 1, 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0 }, + /* 0,1 */ { 12, 7, 6, 12, 6, 10, 12, 10, 1, 12, 1, 0, 12, 0, 8, 12, 8, 3, 12, 3, 2, 12, 2, 11, 12, 11, 7 }, + /* 1,1 */ { 7, 6, 12, 8, 7, 12, 0, 8, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12, 11, 3, 12, 6, 11, 12 } +}, +/* 161: 0, 5, 7, */ { + /* 1,0 */ { 9, 5, 12, 0, 9, 12, 3, 0, 12, 11, 3, 12, 6, 11, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12 }, + /* 0,1 */ { 3, 0, 12, 11, 3, 12, 6, 11, 12, 5, 6, 12, 9, 5, 12, 4, 9, 12, 7, 4, 12, 8, 7, 12, 0, 8, 12 }, + /* 1,1 */ { 12, 3, 0, 12, 0, 9, 12, 9, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4, 12, 4, 8, 12, 8, 3 } +}, +/* 26: 1, 3, 4, */ { + /* 1,0 */ { 12, 1, 9, 12, 9, 4, 12, 4, 7, 12, 7, 11, 12, 11, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1 }, + /* 0,1 */ { 12, 4, 7, 12, 7, 11, 12, 11, 2, 12, 2, 1, 12, 1, 9, 12, 9, 0, 12, 0, 3, 12, 3, 8, 12, 8, 4 }, + /* 1,1 */ { 4, 7, 12, 9, 4, 12, 1, 9, 12, 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12, 8, 0, 12, 7, 8, 12 } +}, +/* 74: 1, 3, 6, */ { + /* 1,0 */ { 12, 3, 11, 12, 11, 6, 12, 6, 5, 12, 5, 9, 12, 9, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3 }, + /* 0,1 */ { 12, 6, 5, 12, 5, 9, 12, 9, 0, 12, 0, 3, 12, 3, 11, 12, 11, 2, 12, 2, 1, 12, 1, 10, 12, 10, 6 }, + /* 1,1 */ { 6, 5, 12, 11, 6, 12, 3, 11, 12, 0, 3, 12, 9, 0, 12, 1, 9, 12, 2, 1, 12, 10, 2, 12, 5, 10, 12 } +}, +/* 82: 1, 4, 6, */ { + /* 1,0 */ { 10, 6, 12, 1, 10, 12, 0, 1, 12, 8, 0, 12, 7, 8, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12 }, + /* 0,1 */ { 0, 1, 12, 8, 0, 12, 7, 8, 12, 6, 7, 12, 10, 6, 12, 5, 10, 12, 4, 5, 12, 9, 4, 12, 1, 9, 12 }, + /* 1,1 */ { 12, 0, 1, 12, 1, 10, 12, 10, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5, 12, 5, 9, 12, 9, 0 } +}, +/* 164: 2, 5, 7, */ { + /* 1,0 */ { 11, 7, 12, 2, 11, 12, 1, 2, 12, 9, 1, 12, 4, 9, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12 }, + /* 0,1 */ { 1, 2, 12, 9, 1, 12, 4, 9, 12, 7, 4, 12, 11, 7, 12, 6, 11, 12, 5, 6, 12, 10, 5, 12, 2, 10, 12 }, + /* 1,1 */ { 12, 1, 2, 12, 2, 11, 12, 11, 7, 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6, 12, 6, 10, 12, 10, 1 } +}, +/* 88: 3, 4, 6, */ { + /* 1,0 */ { 8, 4, 12, 3, 8, 12, 2, 3, 12, 10, 2, 12, 5, 10, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12 }, + /* 0,1 */ { 2, 3, 12, 10, 2, 12, 5, 10, 12, 4, 5, 12, 8, 4, 12, 7, 8, 12, 6, 7, 12, 11, 6, 12, 3, 11, 12 }, + /* 1,1 */ { 12, 2, 3, 12, 3, 8, 12, 8, 4, 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7, 12, 7, 11, 12, 11, 2 } +}, +/* 167: 0, 1, 2, 5, 7, */ { + /* 1,0 */ { 12, 4, 8, 12, 8, 3, 12, 3, 2, 12, 2, 10, 12, 10, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4 }, + /* 0,1 */ { 12, 3, 2, 12, 2, 10, 12, 10, 5, 12, 5, 4, 12, 4, 8, 12, 8, 7, 12, 7, 6, 12, 6, 11, 12, 11, 3 }, + /* 1,1 */ { 3, 2, 12, 8, 3, 12, 4, 8, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12, 11, 7, 12, 2, 11, 12 } +}, +/* 91: 0, 1, 3, 4, 6, */ { + /* 1,0 */ { 12, 7, 11, 12, 11, 2, 12, 2, 1, 12, 1, 9, 12, 9, 4, 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7 }, + /* 0,1 */ { 12, 2, 1, 12, 1, 9, 12, 9, 4, 12, 4, 7, 12, 7, 11, 12, 11, 6, 12, 6, 5, 12, 5, 10, 12, 10, 2 }, + /* 1,1 */ { 2, 1, 12, 11, 2, 12, 7, 11, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12, 10, 6, 12, 1, 10, 12 } +}, +/* 173: 0, 2, 3, 5, 7, */ { + /* 1,0 */ { 12, 6, 10, 12, 10, 1, 12, 1, 0, 12, 0, 8, 12, 8, 7, 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6 }, + /* 0,1 */ { 12, 1, 0, 12, 0, 8, 12, 8, 7, 12, 7, 6, 12, 6, 10, 12, 10, 5, 12, 5, 4, 12, 4, 9, 12, 9, 1 }, + /* 1,1 */ { 1, 0, 12, 10, 1, 12, 6, 10, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12, 9, 5, 12, 0, 9, 12 } +}, +/* 181: 0, 2, 4, 5, 7, */ { + /* 1,0 */ { 11, 3, 12, 6, 11, 12, 5, 6, 12, 9, 5, 12, 0, 9, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12 }, + /* 0,1 */ { 5, 6, 12, 9, 5, 12, 0, 9, 12, 3, 0, 12, 11, 3, 12, 2, 11, 12, 1, 2, 12, 10, 1, 12, 6, 10, 12 }, + /* 1,1 */ { 12, 5, 6, 12, 6, 11, 12, 11, 3, 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2, 12, 2, 10, 12, 10, 5 } +}, +/* 229: 0, 2, 5, 6, 7, */ { + /* 1,0 */ { 9, 1, 12, 4, 9, 12, 7, 4, 12, 11, 7, 12, 2, 11, 12, 3, 2, 12, 8, 3, 12, 0, 8, 12, 1, 0, 12 }, + /* 0,1 */ { 7, 4, 12, 11, 7, 12, 2, 11, 12, 1, 2, 12, 9, 1, 12, 0, 9, 12, 3, 0, 12, 8, 3, 12, 4, 8, 12 }, + /* 1,1 */ { 12, 7, 4, 12, 4, 9, 12, 9, 1, 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0, 12, 0, 8, 12, 8, 7 } +}, +/* 94: 1, 2, 3, 4, 6, */ { + /* 1,0 */ { 12, 5, 9, 12, 9, 0, 12, 0, 3, 12, 3, 11, 12, 11, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5 }, + /* 0,1 */ { 12, 0, 3, 12, 3, 11, 12, 11, 6, 12, 6, 5, 12, 5, 9, 12, 9, 4, 12, 4, 7, 12, 7, 8, 12, 8, 0 }, + /* 1,1 */ { 0, 3, 12, 9, 0, 12, 5, 9, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12, 8, 4, 12, 3, 8, 12 } +}, +/* 122: 1, 3, 4, 5, 6, */ { + /* 1,0 */ { 8, 0, 12, 7, 8, 12, 6, 7, 12, 10, 6, 12, 1, 10, 12, 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12 }, + /* 0,1 */ { 6, 7, 12, 10, 6, 12, 1, 10, 12, 0, 1, 12, 8, 0, 12, 3, 8, 12, 2, 3, 12, 11, 2, 12, 7, 11, 12 }, + /* 1,1 */ { 12, 6, 7, 12, 7, 8, 12, 8, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3, 12, 3, 11, 12, 11, 6 } +}, +/* 218: 1, 3, 4, 6, 7, */ { + /* 1,0 */ { 10, 2, 12, 5, 10, 12, 4, 5, 12, 8, 4, 12, 3, 8, 12, 0, 3, 12, 9, 0, 12, 1, 9, 12, 2, 1, 12 }, + /* 0,1 */ { 4, 5, 12, 8, 4, 12, 3, 8, 12, 2, 3, 12, 10, 2, 12, 1, 10, 12, 0, 1, 12, 9, 0, 12, 5, 9, 12 }, + /* 1,1 */ { 12, 4, 5, 12, 5, 10, 12, 10, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1, 12, 1, 9, 12, 9, 4 } } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 7.4.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling7_4_1[16][15] = { +/* 37: 0, 2, 5, */ { 3, 4, 8, 4, 3, 10, 2, 10, 3, 4, 10, 5, 9, 1, 0 }, +/* 133: 0, 2, 7, */ { 1, 6, 10, 6, 1, 8, 0, 8, 1, 6, 8, 7, 11, 3, 2 }, +/* 161: 0, 5, 7, */ { 11, 3, 6, 9, 6, 3, 6, 9, 5, 0, 9, 3, 7, 4, 8 }, +/* 26: 1, 3, 4, */ { 2, 7, 11, 7, 2, 9, 1, 9, 2, 7, 9, 4, 8, 0, 3 }, +/* 74: 1, 3, 6, */ { 0, 5, 9, 5, 0, 11, 3, 11, 0, 5, 11, 6, 10, 2, 1 }, +/* 82: 1, 4, 6, */ { 8, 0, 7, 10, 7, 0, 7, 10, 6, 1, 10, 0, 4, 5, 9 }, +/* 164: 2, 5, 7, */ { 9, 1, 4, 11, 4, 1, 4, 11, 7, 2, 11, 1, 5, 6, 10 }, +/* 88: 3, 4, 6, */ { 10, 2, 5, 8, 5, 2, 5, 8, 4, 3, 8, 2, 6, 7, 11 }, +/* 167: 0, 1, 2, 5, 7, */ { 5, 2, 10, 2, 5, 8, 4, 8, 5, 2, 8, 3, 11, 7, 6 }, +/* 91: 0, 1, 3, 4, 6, */ { 4, 1, 9, 1, 4, 11, 7, 11, 4, 1, 11, 2, 10, 6, 5 }, +/* 173: 0, 2, 3, 5, 7, */ { 7, 0, 8, 0, 7, 10, 6, 10, 7, 0, 10, 1, 9, 5, 4 }, +/* 181: 0, 2, 4, 5, 7, */ { 9, 5, 0, 11, 0, 5, 0, 11, 3, 6, 11, 5, 1, 2, 10 }, +/* 229: 0, 2, 5, 6, 7, */ { 11, 7, 2, 9, 2, 7, 2, 9, 1, 4, 9, 7, 3, 0, 8 }, +/* 94: 1, 2, 3, 4, 6, */ { 6, 3, 11, 3, 6, 9, 5, 9, 6, 3, 9, 0, 8, 4, 7 }, +/* 122: 1, 3, 4, 5, 6, */ { 10, 6, 1, 8, 1, 6, 1, 8, 0, 7, 8, 6, 2, 3, 11 }, +/* 218: 1, 3, 4, 6, 7, */ { 8, 4, 3, 10, 3, 4, 3, 10, 2, 5, 10, 4, 0, 1, 9 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 7.4.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling7_4_2[16][27] = { +/* 37: 0, 2, 5, */ { 9, 4, 8, 4, 9, 5, 10, 5, 9, 1, 10, 9, 10, 1, 2, 0, 2, 1, 2, 0, 3, 8, 3, 0, 9, 8, 0 }, +/* 133: 0, 2, 7, */ { 11, 6, 10, 6, 11, 7, 8, 7, 11, 3, 8, 11, 8, 3, 0, 2, 0, 3, 0, 2, 1, 10, 1, 2, 11, 10, 2 }, +/* 161: 0, 5, 7, */ { 11, 3, 8, 0, 8, 3, 8, 0, 9, 8, 9, 4, 5, 4, 9, 4, 5, 7, 6, 7, 5, 7, 6, 11, 7, 11, 8 }, +/* 26: 1, 3, 4, */ { 8, 7, 11, 7, 8, 4, 9, 4, 8, 0, 9, 8, 9, 0, 1, 3, 1, 0, 1, 3, 2, 11, 2, 3, 8, 11, 3 }, +/* 74: 1, 3, 6, */ { 10, 5, 9, 5, 10, 6, 11, 6, 10, 2, 11, 10, 11, 2, 3, 1, 3, 2, 3, 1, 0, 9, 0, 1, 10, 9, 1 }, +/* 82: 1, 4, 6, */ { 8, 0, 9, 1, 9, 0, 9, 1, 10, 9, 10, 5, 6, 5, 10, 5, 6, 4, 7, 4, 6, 4, 7, 8, 4, 8, 9 }, +/* 164: 2, 5, 7, */ { 9, 1, 10, 2, 10, 1, 10, 2, 11, 10, 11, 6, 7, 6, 11, 6, 7, 5, 4, 5, 7, 5, 4, 9, 5, 9, 10 }, +/* 88: 3, 4, 6, */ { 10, 2, 11, 3, 11, 2, 11, 3, 8, 11, 8, 7, 4, 7, 8, 7, 4, 6, 5, 6, 4, 6, 5, 10, 6, 10, 11 }, +/* 167: 0, 1, 2, 5, 7, */ { 11, 2, 10, 2, 11, 3, 8, 3, 11, 7, 8, 11, 8, 7, 4, 6, 4, 7, 4, 6, 5, 10, 5, 6, 11, 10, 6 }, +/* 91: 0, 1, 3, 4, 6, */ { 10, 1, 9, 1, 10, 2, 11, 2, 10, 6, 11, 10, 11, 6, 7, 5, 7, 6, 7, 5, 4, 9, 4, 5, 10, 9, 5 }, +/* 173: 0, 2, 3, 5, 7, */ { 9, 0, 8, 0, 9, 1, 10, 1, 9, 5, 10, 9, 10, 5, 6, 4, 6, 5, 6, 4, 7, 8, 7, 4, 9, 8, 4 }, +/* 181: 0, 2, 4, 5, 7, */ { 9, 5, 10, 6, 10, 5, 10, 6, 11, 10, 11, 2, 3, 2, 11, 2, 3, 1, 0, 1, 3, 1, 0, 9, 1, 9, 10 }, +/* 229: 0, 2, 5, 6, 7, */ { 11, 7, 8, 4, 8, 7, 8, 4, 9, 8, 9, 0, 1, 0, 9, 0, 1, 3, 2, 3, 1, 3, 2, 11, 3, 11, 8 }, +/* 94: 1, 2, 3, 4, 6, */ { 8, 3, 11, 3, 8, 0, 9, 0, 8, 4, 9, 8, 9, 4, 5, 7, 5, 4, 5, 7, 6, 11, 6, 7, 8, 11, 7 }, +/* 122: 1, 3, 4, 5, 6, */ { 10, 6, 11, 7, 11, 6, 11, 7, 8, 11, 8, 3, 0, 3, 8, 3, 0, 2, 1, 2, 0, 2, 1, 10, 2, 10, 11 }, +/* 218: 1, 3, 4, 6, 7, */ { 8, 4, 9, 5, 9, 4, 9, 5, 10, 9, 10, 1, 2, 1, 10, 1, 2, 0, 3, 0, 2, 0, 3, 8, 0, 8, 9 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 8 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling8[6][6] = { +/* 15: 0, 1, 2, 3, */ { 9, 8, 10, 10, 8, 11 }, +/* 51: 0, 1, 4, 5, */ { 1, 5, 3, 3, 5, 7 }, +/* 153: 0, 3, 4, 7, */ { 0, 4, 2, 4, 6, 2 }, +/* 102: 1, 2, 5, 6, */ { 0, 2, 4, 4, 2, 6 }, +/* 204: 2, 3, 6, 7, */ { 1, 3, 5, 3, 7, 5 }, +/* 240: 4, 5, 6, 7, */ { 9, 10, 8, 10, 11, 8 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 9 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling9[8][12] = { +/* 39: 0, 1, 2, 5, */ { 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8 }, +/* 27: 0, 1, 3, 4, */ { 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1 }, +/* 141: 0, 2, 3, 7, */ { 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8 }, +/* 177: 0, 4, 5, 7, */ { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5 }, +/* 78: 1, 2, 3, 6, */ { 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9 }, +/* 114: 1, 4, 5, 6, */ { 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0 }, +/* 228: 2, 5, 6, 7, */ { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2 }, +/* 216: 3, 4, 6, 7, */ { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4 } +}; +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +/** + * \brief test table for case 10 + * 2 faces to test + eventually the interior + * When the tests on both specified faces are positive : 4 middle triangles (1) + * When the test on the first specified face is positive : 8 first triangles + * When the test on the second specified face is positive : 8 next triangles + * When the tests on both specified faces are negative : + * - if the test on the interior is negative : 4 middle triangles + * - if the test on the interior is positive : 8 last triangles + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char test10[6][3] = { +/* 195: 0, 1, 6, 7, */ { 2, 4, 7 }, +/* 85: 0, 2, 4, 6, */ { 5, 6, 7 }, +/* 105: 0, 3, 5, 6, */ { 1, 3, 7 }, +/* 150: 1, 2, 4, 7, */ { 1, 3, 7 }, +/* 170: 1, 3, 5, 7, */ { 5, 6, 7 }, +/* 60: 2, 3, 4, 5, */ { 2, 4, 7 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 10.1.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling10_1_1[6][12] = { +/* 195: 0, 1, 6, 7, */ { 5, 10, 7, 11, 7, 10, 8, 1, 9, 1, 8, 3 }, +/* 85: 0, 2, 4, 6, */ { 1, 2, 5, 6, 5, 2, 4, 3, 0, 3, 4, 7 }, +/* 105: 0, 3, 5, 6, */ { 11, 0, 8, 0, 11, 2, 4, 9, 6, 10, 6, 9 }, +/* 150: 1, 2, 4, 7, */ { 9, 0, 10, 2, 10, 0, 6, 8, 4, 8, 6, 11 }, +/* 170: 1, 3, 5, 7, */ { 7, 2, 3, 2, 7, 6, 0, 1, 4, 5, 4, 1 }, +/* 60: 2, 3, 4, 5, */ { 7, 9, 5, 9, 7, 8, 10, 1, 11, 3, 11, 1 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 10.1.1 inverted + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling10_1_1_[6][12] = { +/* 195: 0, 1, 6, 7, */ { 5, 9, 7, 8, 7, 9, 11, 1, 10, 1, 11, 3 }, +/* 85: 0, 2, 4, 6, */ { 3, 2, 7, 6, 7, 2, 4, 1, 0, 1, 4, 5 }, +/* 105: 0, 3, 5, 6, */ { 10, 0, 9, 0, 10, 2, 4, 8, 6, 11, 6, 8 }, +/* 150: 1, 2, 4, 7, */ { 8, 0, 11, 2, 11, 0, 6, 9, 4, 9, 6, 10 }, +/* 170: 1, 3, 5, 7, */ { 5, 2, 1, 2, 5, 6, 0, 3, 4, 7, 4, 3 }, +/* 60: 2, 3, 4, 5, */ { 7, 10, 5, 10, 7, 11, 9, 1, 8, 3, 8, 1 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 10.1.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling10_1_2[6][24] = { +/* 195: 0, 1, 6, 7, */ { 3, 11, 7, 3, 7, 8, 9, 8, 7, 5, 9, 7, 9, 5, 10, 9, 10, 1, 3, 1, 10, 11, 3, 10 }, +/* 85: 0, 2, 4, 6, */ { 7, 6, 5, 7, 5, 4, 0, 4, 5, 1, 0, 5, 0, 1, 2, 0, 2, 3, 7, 3, 2, 6, 7, 2 }, +/* 105: 0, 3, 5, 6, */ { 11, 2, 10, 6, 11, 10, 11, 6, 4, 11, 4, 8, 0, 8, 4, 9, 0, 4, 0, 9, 10, 0, 10, 2 }, +/* 150: 1, 2, 4, 7, */ { 11, 2, 10, 11, 10, 6, 4, 6, 10, 9, 4, 10, 4, 9, 0, 4, 0, 8, 11, 8, 0, 2, 11, 0 }, +/* 170: 1, 3, 5, 7, */ { 7, 6, 5, 4, 7, 5, 7, 4, 0, 7, 0, 3, 2, 3, 0, 1, 2, 0, 2, 1, 5, 2, 5, 6 }, +/* 60: 2, 3, 4, 5, */ { 7, 8, 3, 11, 7, 3, 7, 11, 10, 7, 10, 5, 9, 5, 10, 1, 9, 10, 9, 1, 3, 9, 3, 8 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 10.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling10_2[6][24] = { +/* 195: 0, 1, 6, 7, */ { 12, 5, 9, 12, 9, 8, 12, 8, 3, 12, 3, 1, 12, 1, 10, 12, 10, 11, 12, 11, 7, 12, 7, 5 }, +/* 85: 0, 2, 4, 6, */ { 12, 1, 0, 12, 0, 4, 12, 4, 7, 12, 7, 3, 12, 3, 2, 12, 2, 6, 12, 6, 5, 12, 5, 1 }, +/* 105: 0, 3, 5, 6, */ { 4, 8, 12, 6, 4, 12, 10, 6, 12, 9, 10, 12, 0, 9, 12, 2, 0, 12, 11, 2, 12, 8, 11, 12 }, +/* 150: 1, 2, 4, 7, */ { 12, 9, 4, 12, 4, 6, 12, 6, 11, 12, 11, 8, 12, 8, 0, 12, 0, 2, 12, 2, 10, 12, 10, 9 }, +/* 170: 1, 3, 5, 7, */ { 0, 3, 12, 4, 0, 12, 5, 4, 12, 1, 5, 12, 2, 1, 12, 6, 2, 12, 7, 6, 12, 3, 7, 12 }, +/* 60: 2, 3, 4, 5, */ { 10, 5, 12, 11, 10, 12, 3, 11, 12, 1, 3, 12, 9, 1, 12, 8, 9, 12, 7, 8, 12, 5, 7, 12 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 10.2 inverted + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling10_2_[6][24] = { +/* 195: 0, 1, 6, 7, */ { 8, 7, 12, 9, 8, 12, 1, 9, 12, 3, 1, 12, 11, 3, 12, 10, 11, 12, 5, 10, 12, 7, 5, 12 }, +/* 85: 0, 2, 4, 6, */ { 4, 5, 12, 0, 4, 12, 3, 0, 12, 7, 3, 12, 6, 7, 12, 2, 6, 12, 1, 2, 12, 5, 1, 12 }, +/* 105: 0, 3, 5, 6, */ { 12, 11, 6, 12, 6, 4, 12, 4, 9, 12, 9, 10, 12, 10, 2, 12, 2, 0, 12, 0, 8, 12, 8, 11 }, +/* 150: 1, 2, 4, 7, */ { 6, 10, 12, 4, 6, 12, 8, 4, 12, 11, 8, 12, 2, 11, 12, 0, 2, 12, 9, 0, 12, 10, 9, 12 }, +/* 170: 1, 3, 5, 7, */ { 12, 7, 4, 12, 4, 0, 12, 0, 1, 12, 1, 5, 12, 5, 6, 12, 6, 2, 12, 2, 3, 12, 3, 7 }, +/* 60: 2, 3, 4, 5, */ { 12, 7, 11, 12, 11, 10, 12, 10, 1, 12, 1, 3, 12, 3, 8, 12, 8, 9, 12, 9, 5, 12, 5, 7 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 11 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling11[12][12] = { +/* 23: 0, 1, 2, 4, */ { 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4 }, +/* 139: 0, 1, 3, 7, */ { 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6 }, +/* 99: 0, 1, 5, 6, */ { 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10 }, +/* 77: 0, 2, 3, 6, */ { 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6 }, +/* 57: 0, 3, 4, 5, */ { 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11 }, +/* 209: 0, 4, 6, 7, */ { 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0 }, +/* 46: 1, 2, 3, 5, */ { 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3 }, +/* 198: 1, 2, 6, 7, */ { 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7 }, +/* 178: 1, 4, 5, 7, */ { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11 }, +/* 156: 2, 3, 4, 7, */ { 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1 }, +/* 116: 2, 4, 5, 6, */ { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7 }, +/* 232: 3, 5, 6, 7, */ { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9 } +}; +//_____________________________________________________________________________ + + +//_____________________________________________________________________________ +/** + * \brief test table for case 12 + * 2 faces to test + eventually the interior + * When the tests on both specified faces are positive : 4 middle triangles (1) + * When the test on the first specified face is positive : 8 first triangles + * When the test on the second specified face is positive : 8 next triangles + * When the tests on both specified faces are negative : + * - if the test on the interior is negative : 4 middle triangles + * - if the test on the interior is positive : 8 last triangles + * The support edge for the interior test is marked as the 4th column. + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char test12[24][4] = { +/* 135: 0, 1, 2, 7, */ { 4, 3, 7, 11 }, +/* 75: 0, 1, 3, 6, */ { 3, 2, 7, 10 }, +/* 83: 0, 1, 4, 6, */ { 2, 6, 7, 5 }, +/* 163: 0, 1, 5, 7, */ { 6, 4, 7, 7 }, +/* 45: 0, 2, 3, 5, */ { 2, 1, 7, 9 }, +/* 53: 0, 2, 4, 5, */ { 5, 2, 7, 1 }, +/* 149: 0, 2, 4, 7, */ { 5, 3, 7, 2 }, +/* 101: 0, 2, 5, 6, */ { 5, 1, 7, 0 }, +/* 197: 0, 2, 6, 7, */ { 5, 4, 7, 3 }, +/* 89: 0, 3, 4, 6, */ { 6, 3, 7, 6 }, +/* 169: 0, 3, 5, 7, */ { 1, 6, 7, 4 }, +/* 225: 0, 5, 6, 7, */ { 1, 4, 7, 8 }, +/* 30: 1, 2, 3, 4, */ { 4, 1, 7, 8 }, +/* 86: 1, 2, 4, 6, */ { 6, 1, 7, 4 }, +/* 166: 1, 2, 5, 7, */ { 3, 6, 7, 6 }, +/* 58: 1, 3, 4, 5, */ { 4, 5, 7, 3 }, +/* 154: 1, 3, 4, 7, */ { 1, 5, 7, 0 }, +/* 106: 1, 3, 5, 6, */ { 3, 5, 7, 2 }, +/* 202: 1, 3, 6, 7, */ { 2, 5, 7, 1 }, +/* 210: 1, 4, 6, 7, */ { 1, 2, 7, 9 }, +/* 92: 2, 3, 4, 6, */ { 4, 6, 7, 7 }, +/* 172: 2, 3, 5, 7, */ { 6, 2, 7, 5 }, +/* 180: 2, 4, 5, 7, */ { 2, 3, 7, 10 }, +/* 120: 3, 4, 5, 6, */ { 3, 4, 7, 11 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 12.1.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling12_1_1[24][12] = { +/* 135: 0, 1, 2, 7, */ { 7, 6, 11, 10, 3, 2, 3, 10, 8, 9, 8, 10 }, +/* 75: 0, 1, 3, 6, */ { 6, 5, 10, 9, 2, 1, 2, 9, 11, 8, 11, 9 }, +/* 83: 0, 1, 4, 6, */ { 10, 6, 5, 7, 9, 4, 9, 7, 1, 3, 1, 7 }, +/* 163: 0, 1, 5, 7, */ { 7, 6, 11, 4, 8, 5, 3, 5, 8, 5, 3, 1 }, +/* 45: 0, 2, 3, 5, */ { 5, 4, 9, 8, 1, 0, 1, 8, 10, 11, 10, 8 }, +/* 53: 0, 2, 4, 5, */ { 1, 2, 10, 0, 9, 3, 5, 3, 9, 3, 5, 7 }, +/* 149: 0, 2, 4, 7, */ { 10, 1, 2, 0, 11, 3, 11, 0, 6, 4, 6, 0 }, +/* 101: 0, 2, 5, 6, */ { 8, 3, 0, 2, 9, 1, 9, 2, 4, 6, 4, 2 }, +/* 197: 0, 2, 6, 7, */ { 3, 0, 8, 2, 11, 1, 7, 1, 11, 1, 7, 5 }, +/* 89: 0, 3, 4, 6, */ { 6, 5, 10, 7, 11, 4, 2, 4, 11, 4, 2, 0 }, +/* 169: 0, 3, 5, 7, */ { 9, 5, 4, 6, 8, 7, 8, 6, 0, 2, 0, 6 }, +/* 225: 0, 5, 6, 7, */ { 8, 3, 0, 7, 4, 11, 9, 11, 4, 11, 9, 10 }, +/* 30: 1, 2, 3, 4, */ { 4, 7, 8, 11, 0, 3, 0, 11, 9, 10, 9, 11 }, +/* 86: 1, 2, 4, 6, */ { 4, 7, 8, 5, 9, 6, 0, 6, 9, 6, 0, 2 }, +/* 166: 1, 2, 5, 7, */ { 11, 7, 6, 4, 10, 5, 10, 4, 2, 0, 2, 4 }, +/* 58: 1, 3, 4, 5, */ { 11, 2, 3, 1, 8, 0, 8, 1, 7, 5, 7, 1 }, +/* 154: 1, 3, 4, 7, */ { 0, 1, 9, 3, 8, 2, 4, 2, 8, 2, 4, 6 }, +/* 106: 1, 3, 5, 6, */ { 2, 3, 11, 1, 10, 0, 6, 0, 10, 0, 6, 4 }, +/* 202: 1, 3, 6, 7, */ { 9, 0, 1, 3, 10, 2, 10, 3, 5, 7, 5, 3 }, +/* 210: 1, 4, 6, 7, */ { 9, 0, 1, 4, 5, 8, 10, 8, 5, 8, 10, 11 }, +/* 92: 2, 3, 4, 6, */ { 8, 4, 7, 5, 11, 6, 11, 5, 3, 1, 3, 5 }, +/* 172: 2, 3, 5, 7, */ { 5, 4, 9, 6, 10, 7, 1, 7, 10, 7, 1, 3 }, +/* 180: 2, 4, 5, 7, */ { 10, 1, 2, 5, 6, 9, 11, 9, 6, 9, 11, 8 }, +/* 120: 3, 4, 5, 6, */ { 11, 2, 3, 6, 7, 10, 8, 10, 7, 10, 8, 9 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 12.1.1 inverted + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling12_1_1_[24][12] = { +/* 135: 0, 1, 2, 7, */ { 3, 2, 11, 10, 7, 6, 7, 10, 8, 9, 8, 10 }, +/* 75: 0, 1, 3, 6, */ { 2, 1, 10, 9, 6, 5, 6, 9, 11, 8, 11, 9 }, +/* 83: 0, 1, 4, 6, */ { 9, 4, 5, 7, 10, 6, 10, 7, 1, 3, 1, 7 }, +/* 163: 0, 1, 5, 7, */ { 7, 4, 8, 6, 11, 5, 3, 5, 11, 5, 3, 1 }, +/* 45: 0, 2, 3, 5, */ { 1, 0, 9, 8, 5, 4, 5, 8, 10, 11, 10, 8 }, +/* 53: 0, 2, 4, 5, */ { 1, 0, 9, 2, 10, 3, 5, 3, 10, 3, 5, 7 }, +/* 149: 0, 2, 4, 7, */ { 11, 3, 2, 0, 10, 1, 10, 0, 6, 4, 6, 0 }, +/* 101: 0, 2, 5, 6, */ { 9, 1, 0, 2, 8, 3, 8, 2, 4, 6, 4, 2 }, +/* 197: 0, 2, 6, 7, */ { 3, 2, 11, 0, 8, 1, 7, 1, 8, 1, 7, 5 }, +/* 89: 0, 3, 4, 6, */ { 6, 7, 11, 5, 10, 4, 2, 4, 10, 4, 2, 0 }, +/* 169: 0, 3, 5, 7, */ { 8, 7, 4, 6, 9, 5, 9, 6, 0, 2, 0, 6 }, +/* 225: 0, 5, 6, 7, */ { 8, 7, 4, 3, 0, 11, 9, 11, 0, 11, 9, 10 }, +/* 30: 1, 2, 3, 4, */ { 0, 3, 8, 11, 4, 7, 4, 11, 9, 10, 9, 11 }, +/* 86: 1, 2, 4, 6, */ { 4, 5, 9, 7, 8, 6, 0, 6, 8, 6, 0, 2 }, +/* 166: 1, 2, 5, 7, */ { 10, 5, 6, 4, 11, 7, 11, 4, 2, 0, 2, 4 }, +/* 58: 1, 3, 4, 5, */ { 8, 0, 3, 1, 11, 2, 11, 1, 7, 5, 7, 1 }, +/* 154: 1, 3, 4, 7, */ { 0, 3, 8, 1, 9, 2, 4, 2, 9, 2, 4, 6 }, +/* 106: 1, 3, 5, 6, */ { 2, 1, 10, 3, 11, 0, 6, 0, 11, 0, 6, 4 }, +/* 202: 1, 3, 6, 7, */ { 10, 2, 1, 3, 9, 0, 9, 3, 5, 7, 5, 3 }, +/* 210: 1, 4, 6, 7, */ { 9, 4, 5, 0, 1, 8, 10, 8, 1, 8, 10, 11 }, +/* 92: 2, 3, 4, 6, */ { 11, 6, 7, 5, 8, 4, 8, 5, 3, 1, 3, 5 }, +/* 172: 2, 3, 5, 7, */ { 5, 6, 10, 4, 9, 7, 1, 7, 9, 7, 1, 3 }, +/* 180: 2, 4, 5, 7, */ { 10, 5, 6, 1, 2, 9, 11, 9, 2, 9, 11, 8 }, +/* 120: 3, 4, 5, 6, */ { 11, 6, 7, 2, 3, 10, 8, 10, 3, 10, 8, 9 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 12.1.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling12_1_2[24][24] = { +/* 135: 0, 1, 2, 7, */ { 7, 3, 11, 3, 7, 8, 9, 8, 7, 6, 9, 7, 9, 6, 10, 2, 10, 6, 11, 2, 6, 2, 11, 3 }, +/* 75: 0, 1, 3, 6, */ { 6, 2, 10, 2, 6, 11, 8, 11, 6, 5, 8, 6, 8, 5, 9, 1, 9, 5, 10, 1, 5, 1, 10, 2 }, +/* 83: 0, 1, 4, 6, */ { 10, 9, 5, 9, 10, 1, 3, 1, 10, 6, 3, 10, 3, 6, 7, 4, 7, 6, 5, 4, 6, 4, 5, 9 }, +/* 163: 0, 1, 5, 7, */ { 7, 8, 11, 3, 11, 8, 11, 3, 1, 11, 1, 6, 5, 6, 1, 6, 5, 4, 6, 4, 7, 8, 7, 4 }, +/* 45: 0, 2, 3, 5, */ { 5, 1, 9, 1, 5, 10, 11, 10, 5, 4, 11, 5, 11, 4, 8, 0, 8, 4, 9, 0, 4, 0, 9, 1 }, +/* 53: 0, 2, 4, 5, */ { 1, 9, 10, 5, 10, 9, 10, 5, 7, 10, 7, 2, 3, 2, 7, 2, 3, 0, 2, 0, 1, 9, 1, 0 }, +/* 149: 0, 2, 4, 7, */ { 10, 11, 2, 11, 10, 6, 4, 6, 10, 1, 4, 10, 4, 1, 0, 3, 0, 1, 2, 3, 1, 3, 2, 11 }, +/* 101: 0, 2, 5, 6, */ { 8, 9, 0, 9, 8, 4, 6, 4, 8, 3, 6, 8, 6, 3, 2, 1, 2, 3, 0, 1, 3, 1, 0, 9 }, +/* 197: 0, 2, 6, 7, */ { 3, 11, 8, 7, 8, 11, 8, 7, 5, 8, 5, 0, 1, 0, 5, 0, 1, 2, 0, 2, 3, 11, 3, 2 }, +/* 89: 0, 3, 4, 6, */ { 6, 11, 10, 2, 10, 11, 10, 2, 0, 10, 0, 5, 4, 5, 0, 5, 4, 7, 5, 7, 6, 11, 6, 7 }, +/* 169: 0, 3, 5, 7, */ { 9, 8, 4, 8, 9, 0, 2, 0, 9, 5, 2, 9, 2, 5, 6, 7, 6, 5, 4, 7, 5, 7, 4, 8 }, +/* 225: 0, 5, 6, 7, */ { 8, 4, 0, 9, 0, 4, 0, 9, 10, 0, 10, 3, 11, 3, 10, 3, 11, 7, 3, 7, 8, 4, 8, 7 }, +/* 30: 1, 2, 3, 4, */ { 4, 0, 8, 0, 4, 9, 10, 9, 4, 7, 10, 4, 10, 7, 11, 3, 11, 7, 8, 3, 7, 3, 8, 0 }, +/* 86: 1, 2, 4, 6, */ { 4, 9, 8, 0, 8, 9, 8, 0, 2, 8, 2, 7, 6, 7, 2, 7, 6, 5, 7, 5, 4, 9, 4, 5 }, +/* 166: 1, 2, 5, 7, */ { 11, 10, 6, 10, 11, 2, 0, 2, 11, 7, 0, 11, 0, 7, 4, 5, 4, 7, 6, 5, 7, 5, 6, 10 }, +/* 58: 1, 3, 4, 5, */ { 11, 8, 3, 8, 11, 7, 5, 7, 11, 2, 5, 11, 5, 2, 1, 0, 1, 2, 3, 0, 2, 0, 3, 8 }, +/* 154: 1, 3, 4, 7, */ { 0, 8, 9, 4, 9, 8, 9, 4, 6, 9, 6, 1, 2, 1, 6, 1, 2, 3, 1, 3, 0, 8, 0, 3 }, +/* 106: 1, 3, 5, 6, */ { 2, 10, 11, 6, 11, 10, 11, 6, 4, 11, 4, 3, 0, 3, 4, 3, 0, 1, 3, 1, 2, 10, 2, 1 }, +/* 202: 1, 3, 6, 7, */ { 9, 10, 1, 10, 9, 5, 7, 5, 9, 0, 7, 9, 7, 0, 3, 2, 3, 0, 1, 2, 0, 2, 1, 10 }, +/* 210: 1, 4, 6, 7, */ { 9, 5, 1, 10, 1, 5, 1, 10, 11, 1, 11, 0, 8, 0, 11, 0, 8, 4, 0, 4, 9, 5, 9, 4 }, +/* 92: 2, 3, 4, 6, */ { 8, 11, 7, 11, 8, 3, 1, 3, 8, 4, 1, 8, 1, 4, 5, 6, 5, 4, 7, 6, 4, 6, 7, 11 }, +/* 172: 2, 3, 5, 7, */ { 5, 10, 9, 1, 9, 10, 9, 1, 3, 9, 3, 4, 7, 4, 3, 4, 7, 6, 4, 6, 5, 10, 5, 6 }, +/* 180: 2, 4, 5, 7, */ { 10, 6, 2, 11, 2, 6, 2, 11, 8, 2, 8, 1, 9, 1, 8, 1, 9, 5, 1, 5, 10, 6, 10, 5 }, +/* 120: 3, 4, 5, 6, */ { 11, 7, 3, 8, 3, 7, 3, 8, 9, 3, 9, 2, 10, 2, 9, 2, 10, 6, 2, 6, 11, 7, 11, 6 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 12.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling12_2[24][24] = { +/* 135: 0, 1, 2, 7, */ { 9, 8, 12, 10, 9, 12, 2, 10, 12, 3, 2, 12, 11, 3, 12, 6, 11, 12, 7, 6, 12, 8, 7, 12 }, +/* 75: 0, 1, 3, 6, */ { 8, 11, 12, 9, 8, 12, 1, 9, 12, 2, 1, 12, 10, 2, 12, 5, 10, 12, 6, 5, 12, 11, 6, 12 }, +/* 83: 0, 1, 4, 6, */ { 3, 1, 12, 7, 3, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12, 10, 6, 12, 1, 10, 12 }, +/* 163: 0, 1, 5, 7, */ { 12, 3, 1, 12, 1, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4, 12, 4, 8, 12, 8, 3 }, +/* 45: 0, 2, 3, 5, */ { 11, 10, 12, 8, 11, 12, 0, 8, 12, 1, 0, 12, 9, 1, 12, 4, 9, 12, 5, 4, 12, 10, 5, 12 }, +/* 53: 0, 2, 4, 5, */ { 12, 5, 7, 12, 7, 3, 12, 3, 2, 12, 2, 10, 12, 10, 1, 12, 1, 0, 12, 0, 9, 12, 9, 5 }, +/* 149: 0, 2, 4, 7, */ { 4, 6, 12, 0, 4, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12, 11, 3, 12, 6, 11, 12 }, +/* 101: 0, 2, 5, 6, */ { 6, 4, 12, 2, 6, 12, 3, 2, 12, 8, 3, 12, 0, 8, 12, 1, 0, 12, 9, 1, 12, 4, 9, 12 }, +/* 197: 0, 2, 6, 7, */ { 12, 7, 5, 12, 5, 1, 12, 1, 0, 12, 0, 8, 12, 8, 3, 12, 3, 2, 12, 2, 11, 12, 11, 7 }, +/* 89: 0, 3, 4, 6, */ { 12, 2, 0, 12, 0, 4, 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7, 12, 7, 11, 12, 11, 2 }, +/* 169: 0, 3, 5, 7, */ { 2, 0, 12, 6, 2, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12, 9, 5, 12, 0, 9, 12 }, +/* 225: 0, 5, 6, 7, */ { 12, 9, 10, 12, 10, 11, 12, 11, 7, 12, 7, 4, 12, 4, 8, 12, 8, 3, 12, 3, 0, 12, 0, 9 }, +/* 30: 1, 2, 3, 4, */ { 10, 9, 12, 11, 10, 12, 7, 11, 12, 4, 7, 12, 8, 4, 12, 3, 8, 12, 0, 3, 12, 9, 0, 12 }, +/* 86: 1, 2, 4, 6, */ { 12, 0, 2, 12, 2, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5, 12, 5, 9, 12, 9, 0 }, +/* 166: 1, 2, 5, 7, */ { 0, 2, 12, 4, 0, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12, 11, 7, 12, 2, 11, 12 }, +/* 58: 1, 3, 4, 5, */ { 5, 7, 12, 1, 5, 12, 0, 1, 12, 8, 0, 12, 3, 8, 12, 2, 3, 12, 11, 2, 12, 7, 11, 12 }, +/* 154: 1, 3, 4, 7, */ { 12, 4, 6, 12, 6, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1, 12, 1, 9, 12, 9, 4 }, +/* 106: 1, 3, 5, 6, */ { 12, 6, 4, 12, 4, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3, 12, 3, 11, 12, 11, 6 }, +/* 202: 1, 3, 6, 7, */ { 7, 5, 12, 3, 7, 12, 2, 3, 12, 10, 2, 12, 1, 10, 12, 0, 1, 12, 9, 0, 12, 5, 9, 12 }, +/* 210: 1, 4, 6, 7, */ { 12, 10, 11, 12, 11, 8, 12, 8, 0, 12, 0, 1, 12, 1, 9, 12, 9, 4, 12, 4, 5, 12, 5, 10 }, +/* 92: 2, 3, 4, 6, */ { 1, 3, 12, 5, 1, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12, 8, 4, 12, 3, 8, 12 }, +/* 172: 2, 3, 5, 7, */ { 12, 1, 3, 12, 3, 7, 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6, 12, 6, 10, 12, 10, 1 }, +/* 180: 2, 4, 5, 7, */ { 12, 11, 8, 12, 8, 9, 12, 9, 1, 12, 1, 2, 12, 2, 10, 12, 10, 5, 12, 5, 6, 12, 6, 11 }, +/* 120: 3, 4, 5, 6, */ { 12, 8, 9, 12, 9, 10, 12, 10, 2, 12, 2, 3, 12, 3, 11, 12, 11, 6, 12, 6, 7, 12, 7, 8 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 12.2 inverted + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling12_2_[24][24] = { +/* 135: 0, 1, 2, 7, */ { 12, 2, 11, 12, 11, 7, 12, 7, 6, 12, 6, 10, 12, 10, 9, 12, 9, 8, 12, 8, 3, 12, 3, 2 }, +/* 75: 0, 1, 3, 6, */ { 12, 1, 10, 12, 10, 6, 12, 6, 5, 12, 5, 9, 12, 9, 8, 12, 8, 11, 12, 11, 2, 12, 2, 1 }, +/* 83: 0, 1, 4, 6, */ { 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7, 12, 7, 3, 12, 3, 1, 12, 1, 9, 12, 9, 4 }, +/* 163: 0, 1, 5, 7, */ { 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12, 1, 5, 12, 3, 1, 12, 11, 3, 12, 6, 11, 12 }, +/* 45: 0, 2, 3, 5, */ { 12, 0, 9, 12, 9, 5, 12, 5, 4, 12, 4, 8, 12, 8, 11, 12, 11, 10, 12, 10, 1, 12, 1, 0 }, +/* 53: 0, 2, 4, 5, */ { 1, 2, 12, 9, 1, 12, 0, 9, 12, 3, 0, 12, 7, 3, 12, 5, 7, 12, 10, 5, 12, 2, 10, 12 }, +/* 149: 0, 2, 4, 7, */ { 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0, 12, 0, 4, 12, 4, 6, 12, 6, 10, 12, 10, 1 }, +/* 101: 0, 2, 5, 6, */ { 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2, 12, 2, 6, 12, 6, 4, 12, 4, 8, 12, 8, 3 }, +/* 197: 0, 2, 6, 7, */ { 3, 0, 12, 11, 3, 12, 2, 11, 12, 1, 2, 12, 5, 1, 12, 7, 5, 12, 8, 7, 12, 0, 8, 12 }, +/* 89: 0, 3, 4, 6, */ { 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12, 0, 4, 12, 2, 0, 12, 10, 2, 12, 5, 10, 12 }, +/* 169: 0, 3, 5, 7, */ { 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6, 12, 6, 2, 12, 2, 0, 12, 0, 8, 12, 8, 7 }, +/* 225: 0, 5, 6, 7, */ { 8, 7, 12, 0, 8, 12, 3, 0, 12, 11, 3, 12, 10, 11, 12, 9, 10, 12, 4, 9, 12, 7, 4, 12 }, +/* 30: 1, 2, 3, 4, */ { 12, 7, 8, 12, 8, 0, 12, 0, 3, 12, 3, 11, 12, 11, 10, 12, 10, 9, 12, 9, 4, 12, 4, 7 }, +/* 86: 1, 2, 4, 6, */ { 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12, 2, 6, 12, 0, 2, 12, 8, 0, 12, 7, 8, 12 }, +/* 166: 1, 2, 5, 7, */ { 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4, 12, 4, 0, 12, 0, 2, 12, 2, 10, 12, 10, 5 }, +/* 58: 1, 3, 4, 5, */ { 12, 0, 3, 12, 3, 11, 12, 11, 2, 12, 2, 1, 12, 1, 5, 12, 5, 7, 12, 7, 8, 12, 8, 0 }, +/* 154: 1, 3, 4, 7, */ { 0, 3, 12, 9, 0, 12, 1, 9, 12, 2, 1, 12, 6, 2, 12, 4, 6, 12, 8, 4, 12, 3, 8, 12 }, +/* 106: 1, 3, 5, 6, */ { 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12, 4, 0, 12, 6, 4, 12, 10, 6, 12, 1, 10, 12 }, +/* 202: 1, 3, 6, 7, */ { 12, 2, 1, 12, 1, 9, 12, 9, 0, 12, 0, 3, 12, 3, 7, 12, 7, 5, 12, 5, 10, 12, 10, 2 }, +/* 210: 1, 4, 6, 7, */ { 9, 0, 12, 5, 9, 12, 4, 5, 12, 8, 4, 12, 11, 8, 12, 10, 11, 12, 1, 10, 12, 0, 1, 12 }, +/* 92: 2, 3, 4, 6, */ { 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5, 12, 5, 1, 12, 1, 3, 12, 3, 11, 12, 11, 6 }, +/* 172: 2, 3, 5, 7, */ { 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12, 3, 7, 12, 1, 3, 12, 9, 1, 12, 4, 9, 12 }, +/* 180: 2, 4, 5, 7, */ { 10, 1, 12, 6, 10, 12, 5, 6, 12, 9, 5, 12, 8, 9, 12, 11, 8, 12, 2, 11, 12, 1, 2, 12 }, +/* 120: 3, 4, 5, 6, */ { 11, 2, 12, 7, 11, 12, 6, 7, 12, 10, 6, 12, 9, 10, 12, 8, 9, 12, 3, 8, 12, 2, 3, 12 } +}; +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +/** + * \brief test table for case 13 + * All faces are to be tested + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13: face test */ +static const char test13[2][7] = { +/* 165: 0, 2, 5, 7, */ { 1,2,3,4,5,6,7 }, +/* 90: 1, 3, 4, 6, */ { 2,3,4,1,5,6,7 }, +}; + + + +//_____________________________________________________________________________ +/** + * \brief subconfiguration table for case 13 + * Hard-coded tests for the subconfiguration determination + * + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13: sub configs */ +static const char subconfig13[64] = { +/* 0: 0,0,0,0,0,0 */ 0, +/* 1: 1,0,0,0,0,0 */ 1, +/* 2: 0,1,0,0,0,0 */ 2, +/* 3: 1,1,0,0,0,0 */ 7, +/* 4: 0,0,1,0,0,0 */ 3, +/* 5: 1,0,1,0,0,0 */ -1, +/* 6: 0,1,1,0,0,0 */ 11, +/* 7: 1,1,1,0,0,0 */ -1, +/* 8: 0,0,0,1,0,0 */ 4, +/* 9: 1,0,0,1,0,0 */ 8, +/* 10: 0,1,0,1,0,0 */ -1, +/* 11: 1,1,0,1,0,0 */ -1, +/* 12: 0,0,1,1,0,0 */ 14, +/* 13: 1,0,1,1,0,0 */ -1, +/* 14: 0,1,1,1,0,0 */ -1, +/* 15: 1,1,1,1,0,0 */ -1, +/* 16: 0,0,0,0,1,0 */ 5, +/* 17: 1,0,0,0,1,0 */ 9, +/* 18: 0,1,0,0,1,0 */ 12, +/* 19: 1,1,0,0,1,0 */ 23, +/* 20: 0,0,1,0,1,0 */ 15, +/* 21: 1,0,1,0,1,0 */ -1, +/* 22: 0,1,1,0,1,0 */ 21, +/* 23: 1,1,1,0,1,0 */ 38, +/* 24: 0,0,0,1,1,0 */ 17, +/* 25: 1,0,0,1,1,0 */ 20, +/* 26: 0,1,0,1,1,0 */ -1, +/* 27: 1,1,0,1,1,0 */ 36, +/* 28: 0,0,1,1,1,0 */ 26, +/* 29: 1,0,1,1,1,0 */ 33, +/* 30: 0,1,1,1,1,0 */ 30, +/* 31: 1,1,1,1,1,0 */ 44, +/* 32: 0,0,0,0,0,1 */ 6, +/* 33: 1,0,0,0,0,1 */ 10, +/* 34: 0,1,0,0,0,1 */ 13, +/* 35: 1,1,0,0,0,1 */ 19, +/* 36: 0,0,1,0,0,1 */ 16, +/* 37: 1,0,1,0,0,1 */ -1, +/* 38: 0,1,1,0,0,1 */ 25, +/* 39: 1,1,1,0,0,1 */ 37, +/* 40: 0,0,0,1,0,1 */ 18, +/* 41: 1,0,0,1,0,1 */ 24, +/* 42: 0,1,0,1,0,1 */ -1, +/* 43: 1,1,0,1,0,1 */ 35, +/* 44: 0,0,1,1,0,1 */ 22, +/* 45: 1,0,1,1,0,1 */ 32, +/* 46: 0,1,1,1,0,1 */ 29, +/* 47: 1,1,1,1,0,1 */ 43, +/* 48: 0,0,0,0,1,1 */ -1, +/* 49: 1,0,0,0,1,1 */ -1, +/* 50: 0,1,0,0,1,1 */ -1, +/* 51: 1,1,0,0,1,1 */ 34, +/* 52: 0,0,1,0,1,1 */ -1, +/* 53: 1,0,1,0,1,1 */ -1, +/* 54: 0,1,1,0,1,1 */ 28, +/* 55: 1,1,1,0,1,1 */ 42, +/* 56: 0,0,0,1,1,1 */ -1, +/* 57: 1,0,0,1,1,1 */ 31, +/* 58: 0,1,0,1,1,1 */ -1, +/* 59: 1,1,0,1,1,1 */ 41, +/* 60: 0,0,1,1,1,1 */ 27, +/* 61: 1,0,1,1,1,1 */ 40, +/* 62: 0,1,1,1,1,1 */ 39, +/* 63: 1,1,1,1,1,1 */ 45, +}; + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.1 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.1 */ +static const char tiling13_1[2][12] = { +/* 165: 0, 2, 5, 7, */ { 11, 7, 6, 1, 2, 10, 8, 3, 0, 9, 5, 4 }, +/* 90: 1, 3, 4, 6, */ { 8, 4, 7, 2, 3, 11, 9, 0, 1, 10, 6, 5 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.1 inverted + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.1 */ +static const char tiling13_1_[2][12] = { +/* 165: 0, 2, 5, 7, */ { 7, 4, 8, 11, 3, 2, 1, 0, 9, 5, 6, 10 }, +/* 90: 1, 3, 4, 6, */ { 6, 7, 11, 10, 2, 1, 0, 3, 8, 4, 5, 9 } +}; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.2 */ +static const char tiling13_2[2][6][18] = { +/* 165: 0, 2, 5, 7, */ { + /* 1 */ { 1, 2, 10, 11, 7, 6, 3, 4, 8, 4, 3, 5, 0, 5, 3, 5, 0, 9 }, + /* 2 */ { 8, 3, 0, 11, 7, 6, 9, 1, 4, 2, 4, 1, 4, 2, 5, 10, 5, 2 }, + /* 3 */ { 9, 5, 4, 8, 3, 0, 1, 6, 10, 6, 1, 7, 2, 7, 1, 7, 2, 11 }, + /* 4 */ { 9, 5, 4, 1, 2, 10, 11, 3, 6, 0, 6, 3, 6, 0, 7, 8, 7, 0 }, + /* 5 */ { 9, 5, 4, 11, 7, 6, 0, 10, 1, 10, 0, 8, 10, 8, 2, 3, 2, 8 }, + /* 6 */ { 1, 2, 10, 3, 0, 8, 4, 9, 7, 11, 7, 9, 5, 11, 9, 11, 5, 6 } +}, +/* 90: 1, 3, 4, 6, */ { + /* 1 */ { 2, 3, 11, 8, 4, 7, 0, 5, 9, 5, 0, 6, 1, 6, 0, 6, 1, 10 }, + /* 2 */ { 9, 0, 1, 8, 4, 7, 10, 2, 5, 3, 5, 2, 5, 3, 6, 11, 6, 3 }, + /* 3 */ { 6, 5, 10, 9, 0, 1, 2, 7, 11, 7, 2, 4, 3, 4, 2, 4, 3, 8 }, + /* 4 */ { 6, 5, 10, 2, 3, 11, 8, 0, 7, 1, 7, 0, 7, 1, 4, 9, 4, 1 }, + /* 5 */ { 6, 5, 10, 8, 4, 7, 1, 11, 2, 11, 1, 9, 11, 9, 3, 0, 3, 9 }, + /* 6 */ { 2, 3, 11, 0, 1, 9, 5, 10, 4, 8, 4, 10, 6, 8, 10, 8, 6, 7 } +} }; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.2 inverted + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.2 */ +static const char tiling13_2_[2][6][18] = { +/* 165: 0, 2, 5, 7, */ { + /* 1 */ { 10, 5, 6, 11, 3, 2, 7, 0, 8, 0, 7, 1, 4, 1, 7, 1, 4, 9 }, + /* 2 */ { 11, 3, 2, 7, 4, 8, 9, 5, 0, 6, 0, 5, 0, 6, 1, 10, 1, 6 }, + /* 3 */ { 1, 0, 9, 7, 4, 8, 5, 2, 10, 2, 5, 3, 6, 3, 5, 3, 6, 11 }, + /* 4 */ { 10, 5, 6, 1, 0, 9, 11, 7, 2, 4, 2, 7, 2, 4, 3, 8, 3, 4 }, + /* 5 */ { 10, 5, 6, 7, 4, 8, 2, 11, 1, 9, 1, 11, 3, 9, 11, 9, 3, 0 }, + /* 6 */ { 11, 3, 2, 9, 1, 0, 4, 10, 5, 10, 4, 8, 10, 8, 6, 7, 6, 8 } +}, +/* 90: 1, 3, 4, 6, */ { + /* 1 */ { 6, 7, 11, 8, 0, 3, 4, 1, 9, 1, 4, 2, 5, 2, 4, 2, 5, 10 }, + /* 2 */ { 8, 0, 3, 4, 5, 9, 10, 6, 1, 7, 1, 6, 1, 7, 2, 11, 2, 7 }, + /* 3 */ { 2, 1, 10, 4, 5, 9, 6, 3, 11, 3, 6, 0, 7, 0, 6, 0, 7, 8 }, + /* 4 */ { 6, 7, 11, 2, 1, 10, 8, 4, 3, 5, 3, 4, 3, 5, 0, 9, 0, 5 }, + /* 5 */ { 6, 7, 11, 4, 5, 9, 3, 8, 2, 10, 2, 8, 0, 10, 8, 10, 0, 1 }, + /* 6 */ { 8, 0, 3, 10, 2, 1, 5, 11, 6, 11, 5, 9, 11, 9, 7, 4, 7, 9 } +} }; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.3 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.3 */ +static const char tiling13_3[2][12][30] = { +/* 165: 0, 2, 5, 7, */ { + /* 1,2 */ { 11, 7, 6, 12, 2, 10, 12, 10, 5, 12, 5, 4, 12, 4, 8, 12, 8, 3, 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2 }, + /* 1,4 */ { 1, 2, 10, 9, 5, 12, 0, 9, 12, 3, 0, 12, 11, 3, 12, 6, 11, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12 }, + /* 1,5 */ { 11, 7, 6, 12, 5, 4, 12, 4, 8, 12, 8, 3, 12, 3, 2, 12, 2, 10, 12, 10, 1, 12, 1, 0, 12, 0, 9, 12, 9, 5 }, + /* 1,6 */ { 1, 2, 10, 12, 3, 0, 12, 0, 9, 12, 9, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4, 12, 4, 8, 12, 8, 3 }, + /* 2,3 */ { 8, 3, 0, 11, 7, 12, 2, 11, 12, 1, 2, 12, 9, 1, 12, 4, 9, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12 }, + /* 2,5 */ { 11, 7, 6, 5, 4, 12, 10, 5, 12, 2, 10, 12, 3, 2, 12, 8, 3, 12, 0, 8, 12, 1, 0, 12, 9, 1, 12, 4, 9, 12 }, + /* 2,6 */ { 8, 3, 0, 1, 2, 12, 9, 1, 12, 4, 9, 12, 7, 4, 12, 11, 7, 12, 6, 11, 12, 5, 6, 12, 10, 5, 12, 2, 10, 12 }, + /* 3,4 */ { 9, 5, 4, 12, 0, 8, 12, 8, 7, 12, 7, 6, 12, 6, 10, 12, 10, 1, 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0 }, + /* 3,5 */ { 9, 5, 4, 12, 7, 6, 12, 6, 10, 12, 10, 1, 12, 1, 0, 12, 0, 8, 12, 8, 3, 12, 3, 2, 12, 2, 11, 12, 11, 7 }, + /* 3,6 */ { 8, 3, 0, 12, 1, 2, 12, 2, 11, 12, 11, 7, 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6, 12, 6, 10, 12, 10, 1 }, + /* 4,5 */ { 9, 5, 4, 7, 6, 12, 8, 7, 12, 0, 8, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12, 11, 3, 12, 6, 11, 12 }, + /* 4,6 */ { 1, 2, 10, 3, 0, 12, 11, 3, 12, 6, 11, 12, 5, 6, 12, 9, 5, 12, 4, 9, 12, 7, 4, 12, 8, 7, 12, 0, 8, 12 } +}, +/* 90: 1, 3, 4, 6, */ { + /* 1,2 */ { 8, 4, 7, 12, 3, 11, 12, 11, 6, 12, 6, 5, 12, 5, 9, 12, 9, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3 }, + /* 1,4 */ { 2, 3, 11, 10, 6, 12, 1, 10, 12, 0, 1, 12, 8, 0, 12, 7, 8, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12 }, + /* 1,5 */ { 8, 4, 7, 12, 6, 5, 12, 5, 9, 12, 9, 0, 12, 0, 3, 12, 3, 11, 12, 11, 2, 12, 2, 1, 12, 1, 10, 12, 10, 6 }, + /* 1,6 */ { 2, 3, 11, 12, 0, 1, 12, 1, 10, 12, 10, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5, 12, 5, 9, 12, 9, 0 }, + /* 2,3 */ { 0, 1, 9, 8, 4, 12, 3, 8, 12, 2, 3, 12, 10, 2, 12, 5, 10, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12 }, + /* 2,5 */ { 8, 4, 7, 6, 5, 12, 11, 6, 12, 3, 11, 12, 0, 3, 12, 9, 0, 12, 1, 9, 12, 2, 1, 12, 10, 2, 12, 5, 10, 12 }, + /* 2,6 */ { 9, 0, 1, 2, 3, 12, 10, 2, 12, 5, 10, 12, 4, 5, 12, 8, 4, 12, 7, 8, 12, 6, 7, 12, 11, 6, 12, 3, 11, 12 }, + /* 3,4 */ { 6, 5, 10, 12, 1, 9, 12, 9, 4, 12, 4, 7, 12, 7, 11, 12, 11, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1 }, + /* 3,5 */ { 6, 5, 10, 12, 4, 7, 12, 7, 11, 12, 11, 2, 12, 2, 1, 12, 1, 9, 12, 9, 0, 12, 0, 3, 12, 3, 8, 12, 8, 4 }, + /* 3,6 */ { 9, 0, 1, 12, 2, 3, 12, 3, 8, 12, 8, 4, 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7, 12, 7, 11, 12, 11, 2 }, + /* 4,5 */ { 6, 5, 10, 4, 7, 12, 9, 4, 12, 1, 9, 12, 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12, 8, 0, 12, 7, 8, 12 }, + /* 4,6 */ { 2, 3, 11, 0, 1, 12, 8, 0, 12, 7, 8, 12, 6, 7, 12, 10, 6, 12, 5, 10, 12, 4, 5, 12, 9, 4, 12, 1, 9, 12 } +} }; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.3, inverted + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.3 */ +static const char tiling13_3_[2][12][30] = { +/* 165: 0, 2, 5, 7, */ { + /* 1,2 */ { 3, 2, 11, 8, 7, 12, 0, 8, 12, 1, 0, 12, 10, 1, 12, 6, 10, 12, 5, 6, 12, 9, 5, 12, 4, 9, 12, 7, 4, 12 }, + /* 1,4 */ { 5, 6, 10, 12, 2, 11, 12, 11, 7, 12, 7, 4, 12, 4, 9, 12, 9, 1, 12, 1, 0, 12, 0, 8, 12, 8, 3, 12, 3, 2 }, + /* 1,5 */ { 10, 5, 6, 12, 7, 4, 12, 4, 9, 12, 9, 1, 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0, 12, 0, 8, 12, 8, 7 }, + /* 1,6 */ { 11, 3, 2, 12, 1, 0, 12, 0, 8, 12, 8, 7, 12, 7, 6, 12, 6, 10, 12, 10, 5, 12, 5, 4, 12, 4, 9, 12, 9, 1 }, + /* 2,3 */ { 7, 4, 8, 11, 3, 12, 6, 11, 12, 5, 6, 12, 9, 5, 12, 0, 9, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12 }, + /* 2,5 */ { 7, 4, 8, 5, 6, 12, 9, 5, 12, 0, 9, 12, 3, 0, 12, 11, 3, 12, 2, 11, 12, 1, 2, 12, 10, 1, 12, 6, 10, 12 }, + /* 2,6 */ { 11, 3, 2, 1, 0, 12, 10, 1, 12, 6, 10, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12, 9, 5, 12, 0, 9, 12 }, + /* 3,4 */ { 1, 0, 9, 12, 4, 8, 12, 8, 3, 12, 3, 2, 12, 2, 10, 12, 10, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4 }, + /* 3,5 */ { 7, 4, 8, 12, 5, 6, 12, 6, 11, 12, 11, 3, 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2, 12, 2, 10, 12, 10, 5 }, + /* 3,6 */ { 1, 0, 9, 12, 3, 2, 12, 2, 10, 12, 10, 5, 12, 5, 4, 12, 4, 8, 12, 8, 7, 12, 7, 6, 12, 6, 11, 12, 11, 3 }, + /* 4,5 */ { 10, 5, 6, 7, 4, 12, 11, 7, 12, 2, 11, 12, 1, 2, 12, 9, 1, 12, 0, 9, 12, 3, 0, 12, 8, 3, 12, 4, 8, 12 }, + /* 4,6 */ { 9, 1, 0, 3, 2, 12, 8, 3, 12, 4, 8, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12, 11, 7, 12, 2, 11, 12 } +}, +/* 90: 1, 3, 4, 6, */ { + /* 1,2 */ { 0, 3, 8, 9, 4, 12, 1, 9, 12, 2, 1, 12, 11, 2, 12, 7, 11, 12, 6, 7, 12, 10, 6, 12, 5, 10, 12, 4, 5, 12 }, + /* 1,4 */ { 11, 6, 7, 12, 3, 8, 12, 8, 4, 12, 4, 5, 12, 5, 10, 12, 10, 2, 12, 2, 1, 12, 1, 9, 12, 9, 0, 12, 0, 3 }, + /* 1,5 */ { 6, 7, 11, 12, 4, 5, 12, 5, 10, 12, 10, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1, 12, 1, 9, 12, 9, 4 }, + /* 1,6 */ { 8, 0, 3, 12, 2, 1, 12, 1, 9, 12, 9, 4, 12, 4, 7, 12, 7, 11, 12, 11, 6, 12, 6, 5, 12, 5, 10, 12, 10, 2 }, + /* 2,3 */ { 4, 5, 9, 8, 0, 12, 7, 8, 12, 6, 7, 12, 10, 6, 12, 1, 10, 12, 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12 }, + /* 2,5 */ { 4, 5, 9, 6, 7, 12, 10, 6, 12, 1, 10, 12, 0, 1, 12, 8, 0, 12, 3, 8, 12, 2, 3, 12, 11, 2, 12, 7, 11, 12 }, + /* 2,6 */ { 8, 0, 3, 2, 1, 12, 11, 2, 12, 7, 11, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12, 10, 6, 12, 1, 10, 12 }, + /* 3,4 */ { 2, 1, 10, 12, 5, 9, 12, 9, 0, 12, 0, 3, 12, 3, 11, 12, 11, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5 }, + /* 3,5 */ { 4, 5, 9, 12, 6, 7, 12, 7, 8, 12, 8, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3, 12, 3, 11, 12, 11, 6 }, + /* 3,6 */ { 2, 1, 10, 12, 0, 3, 12, 3, 11, 12, 11, 6, 12, 6, 5, 12, 5, 9, 12, 9, 4, 12, 4, 7, 12, 7, 8, 12, 8, 0 }, + /* 4,5 */ { 6, 7, 11, 4, 5, 12, 8, 4, 12, 3, 8, 12, 2, 3, 12, 10, 2, 12, 1, 10, 12, 0, 1, 12, 9, 0, 12, 5, 9, 12 }, + /* 4,6 */ { 10, 2, 1, 0, 3, 12, 9, 0, 12, 5, 9, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12, 8, 4, 12, 3, 8, 12 } +} }; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.4 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.4 */ +static const char tiling13_4[2][4][36] = { +/* 165: 0, 2, 5, 7, */ { +/* 1,2,6 */ { 12, 2, 10, 12, 10, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4, 12, 4, 8, 12, 8, 3, 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2 }, +/* 1,4,5 */ { 11, 3, 12, 6, 11, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12, 9, 5, 12, 0, 9, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12 }, +/* 2,3,5 */ { 9, 1, 12, 4, 9, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12, 11, 7, 12, 2, 11, 12, 3, 2, 12, 8, 3, 12, 0, 8, 12, 1, 0, 12 }, +/* 3,4,6 */ { 12, 0, 8, 12, 8, 7, 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6, 12, 6, 10, 12, 10, 1, 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0 } +}, +/* 90: 1, 3, 4, 6, */ { +/* 1,2,6 */ { 12, 3, 11, 12, 11, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5, 12, 5, 9, 12, 9, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3 }, +/* 1,4,5 */ { 8, 0, 12, 7, 8, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12, 10, 6, 12, 1, 10, 12, 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12 }, +/* 2,3,5 */ { 10, 2, 12, 5, 10, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12, 8, 4, 12, 3, 8, 12, 0, 3, 12, 9, 0, 12, 1, 9, 12, 2, 1, 12 }, +/* 3,4,6 */ { 12, 1, 9, 12, 9, 4, 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7, 12, 7, 11, 12, 11, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1 } +} }; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.5.1 + * The support edge for the interior test is marked as the 1st column. + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.5.1 */ +static const char tiling13_5_1[2][4][18] = { +/* 165: 0, 2, 5, 7, */ { +/* 1,2,5 */ { 7, 6, 11, 1, 0, 9, 10, 3, 2, 3, 10, 5, 3, 5, 8, 4, 8, 5 }, +/* 1,4,6 */ { 1, 2, 10, 7, 4, 8, 3, 0, 11, 6, 11, 0, 9, 6, 0, 6, 9, 5 }, +/* 2,3,6 */ { 3, 0, 8, 5, 6, 10, 1, 2, 9, 4, 9, 2, 11, 4, 2, 4, 11, 7 }, +/* 3,4,5 */ { 5, 4, 9, 3, 2, 11, 8, 1, 0, 1, 8, 7, 1, 7, 10, 6, 10, 7 } +}, +/* 90: 1, 3, 4, 6, */ { +/* 1,2,5 */ { 4, 7, 8, 2, 1, 10, 11, 0, 3, 0, 11, 6, 0, 6, 9, 5, 9, 6 }, +/* 1,4,6 */ { 2, 3, 11, 4, 5, 9, 0, 1, 8, 7, 8, 1, 10, 7, 1, 7, 10, 6 }, +/* 2,3,6 */ { 0, 1, 9, 6, 7, 11, 2, 3, 10, 5, 10, 3, 8, 5, 3, 5, 8, 4 }, +/* 3,4,5 */ { 6, 5, 10, 0, 3, 8, 9, 2, 1, 2, 9, 4, 2, 4, 11, 7, 11, 4 } +} }; + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 13.5.2 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +/* 13.5.2 */ +static const char tiling13_5_2[2][4][30] = { +/* 165: 0, 2, 5, 7, */ { +/* 1,2,5 */ { 1, 0, 9, 7, 4, 8, 7, 8, 3, 7, 3, 11, 2, 11, 3, 11, 2, 10, 11, 10, 6, 5, 6, 10, 6, 5, 7, 4, 7, 5 }, +/* 1,4,6 */ { 7, 4, 8, 11, 3, 2, 6, 11, 2, 10, 6, 2, 6, 10, 5, 9, 5, 10, 1, 9, 10, 9, 1, 0, 2, 0, 1, 0, 2, 3 }, +/* 2,3,6 */ { 5, 6, 10, 9, 1, 0, 4, 9, 0, 8, 4, 0, 4, 8, 7, 11, 7, 8, 3, 11, 8, 11, 3, 2, 0, 2, 3, 2, 0, 1 }, +/* 3,4,5 */ { 3, 2, 11, 5, 6, 10, 5, 10, 1, 5, 1, 9, 0, 9, 1, 9, 0, 8, 9, 8, 4, 4, 8, 7, 4, 7, 5, 6, 5, 7 } +}, +/* 90: 1, 3, 4, 6, */ { +/* 1,2,5 */ { 2, 1, 10, 4, 5, 9, 4, 9, 0, 4, 0, 8, 3, 8, 0, 8, 3, 11, 8, 11, 7, 6, 7, 11, 7, 6, 4, 5, 4, 6 }, +/* 1,4,6 */ { 4, 5, 9, 8, 0, 3, 7, 8, 3, 11, 7, 3, 7, 11, 6, 10, 6, 11, 2, 10, 11, 10, 2, 1, 3, 1, 2, 1, 3, 0 }, +/* 2,3,6 */ { 6, 7, 11, 10, 2, 1, 5, 10, 1, 9, 5, 1, 5, 9, 4, 8, 4, 9, 0, 8, 9, 8, 0, 3, 1, 3, 0, 3, 1, 2 }, +/* 3,4,5 */ { 0, 3, 8, 6, 7, 11, 6, 11, 2, 6, 2, 10, 1, 10, 2, 10, 1, 9, 10, 9, 5, 5, 9, 4, 5, 4, 6, 7, 6, 4 } +} }; +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +/** + * \brief tiling table for case 14 + * For each of the case above, the specific triangulation of the edge + * intersection points is given. + * When a case is ambiguous, there is an auxiliary table that contains + * the face number to test and the tiling table contains the specific + * triangulations depending on the results + * A minus sign means to invert the result of the test. + */ +//----------------------------------------------------------------------------- +static const char tiling14[12][12] = { +/* 71: 0, 1, 2, 6, */ { 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8 }, +/* 43: 0, 1, 3, 5, */ { 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5 }, +/* 147: 0, 1, 4, 7, */ { 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6 }, +/* 29: 0, 2, 3, 4, */ { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4 }, +/* 201: 0, 3, 6, 7, */ { 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5 }, +/* 113: 0, 4, 5, 6, */ { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10 }, +/* 142: 1, 2, 3, 7, */ { 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7 }, +/* 54: 1, 2, 4, 5, */ { 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2 }, +/* 226: 1, 5, 6, 7, */ { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11 }, +/* 108: 2, 3, 5, 6, */ { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3 }, +/* 212: 2, 4, 6, 7, */ { 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8 }, +/* 184: 3, 4, 5, 7, */ { 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2 } +}; +//_____________________________________________________________________________ + + + +//_____________________________________________________________________________ +/** + * \brief original Marching Cubes implementation + * For each of the possible vertex states listed in this table there is a + * specific triangulation of the edge intersection points. The table lists + * all of them in the form of 0-5 edge triples with the list terminated by + * the invalid value -1. For example: casesClassic[3] list the 2 triangles + * formed when cube[0] and cube[1] are inside of the surface, but the rest of + * the cube is not. + */ +//----------------------------------------------------------------------------- +static const char casesClassic[256][16] = { +/* 0: */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 1: 0, */ { 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 2: 1, */ { 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 3: 0, 1, */ { 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 4: 2, */ { 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 5: 0, 2, */ { 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 6: 1, 2, */ { 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 7: 0, 1, 2, */ { 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, +/* 8: 3, */ { 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 9: 0, 3, */ { 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 10: 1, 3, */ { 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 11: 0, 1, 3, */ { 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 12: 2, 3, */ { 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 13: 0, 2, 3, */ { 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, +/* 14: 1, 2, 3, */ { 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, +/* 15: 0, 1, 2, 3, */ { 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 16: 4, */ { 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 17: 0, 4, */ { 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 18: 1, 4, */ { 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 19: 0, 1, 4, */ { 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, +/* 20: 2, 4, */ { 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 21: 0, 2, 4, */ { 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 }, +/* 22: 1, 2, 4, */ { 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 23: 0, 1, 2, 4, */ { 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, +/* 24: 3, 4, */ { 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 25: 0, 3, 4, */ { 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, +/* 26: 1, 3, 4, */ { 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 27: 0, 1, 3, 4, */ { 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 }, +/* 28: 2, 3, 4, */ { 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 }, +/* 29: 0, 2, 3, 4, */ { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 }, +/* 30: 1, 2, 3, 4, */ { 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, +/* 31: 0, 1, 2, 3, 4, */ { 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, +/* 32: 5, */ { 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 33: 0, 5, */ { 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 34: 1, 5, */ { 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 35: 0, 1, 5, */ { 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 36: 2, 5, */ { 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 37: 0, 2, 5, */ { 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 38: 1, 2, 5, */ { 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, +/* 39: 0, 1, 2, 5, */ { 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 }, +/* 40: 3, 5, */ { 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 41: 0, 3, 5, */ { 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 42: 1, 3, 5, */ { 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 43: 0, 1, 3, 5, */ { 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 }, +/* 44: 2, 3, 5, */ { 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 }, +/* 45: 0, 2, 3, 5, */ { 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 }, +/* 46: 1, 2, 3, 5, */ { 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, +/* 47: 0, 1, 2, 3, 5, */ { 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 48: 4, 5, */ { 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 49: 0, 4, 5, */ { 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, +/* 50: 1, 4, 5, */ { 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 51: 0, 1, 4, 5, */ { 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 52: 2, 4, 5, */ { 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 }, +/* 53: 0, 2, 4, 5, */ { 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 }, +/* 54: 1, 2, 4, 5, */ { 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 }, +/* 55: 0, 1, 2, 4, 5, */ { 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 56: 3, 4, 5, */ { 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 }, +/* 57: 0, 3, 4, 5, */ { 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, +/* 58: 1, 3, 4, 5, */ { 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 }, +/* 59: 0, 1, 3, 4, 5, */ { 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 60: 2, 3, 4, 5, */ { 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1 }, +/* 61: 0, 2, 3, 4, 5, */ { 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1 }, +/* 62: 1, 2, 3, 4, 5, */ { 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1 }, +/* 63: 0, 1, 2, 3, 4, 5, */ { 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 64: 6, */ { 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 65: 0, 6, */ { 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 66: 1, 6, */ { 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 67: 0, 1, 6, */ { 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 68: 2, 6, */ { 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 69: 0, 2, 6, */ { 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 }, +/* 70: 1, 2, 6, */ { 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 71: 0, 1, 2, 6, */ { 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 }, +/* 72: 3, 6, */ { 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 73: 0, 3, 6, */ { 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 74: 1, 3, 6, */ { 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 75: 0, 1, 3, 6, */ { 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 }, +/* 76: 2, 3, 6, */ { 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, +/* 77: 0, 2, 3, 6, */ { 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, +/* 78: 1, 2, 3, 6, */ { 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 }, +/* 79: 0, 1, 2, 3, 6, */ { 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, +/* 80: 4, 6, */ { 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 81: 0, 4, 6, */ { 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 }, +/* 82: 1, 4, 6, */ { 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 83: 0, 1, 4, 6, */ { 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, +/* 84: 2, 4, 6, */ { 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 }, +/* 85: 0, 2, 4, 6, */ { 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 }, +/* 86: 1, 2, 4, 6, */ { 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 }, +/* 87: 0, 1, 2, 4, 6, */ { 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 }, +/* 88: 3, 4, 6, */ { 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 89: 0, 3, 4, 6, */ { 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, +/* 90: 1, 3, 4, 6, */ { 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 }, +/* 91: 0, 1, 3, 4, 6, */ { 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 }, +/* 92: 2, 3, 4, 6, */ { 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, +/* 93: 0, 2, 3, 4, 6, */ { 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1 }, +/* 94: 1, 2, 3, 4, 6, */ { 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1 }, +/* 95: 0, 1, 2, 3, 4, 6, */ { 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1 }, +/* 96: 5, 6, */ { 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 97: 0, 5, 6, */ { 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1 }, +/* 98: 1, 5, 6, */ { 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, +/* 99: 0, 1, 5, 6, */ { 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, +/* 100: 2, 5, 6, */ { 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, +/* 101: 0, 2, 5, 6, */ { 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1 }, +/* 102: 1, 2, 5, 6, */ { 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 103: 0, 1, 2, 5, 6, */ { 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 104: 3, 5, 6, */ { 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1 }, +/* 105: 0, 3, 5, 6, */ { 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1 }, +/* 106: 1, 3, 5, 6, */ { 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, +/* 107: 0, 1, 3, 5, 6, */ { 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1 }, +/* 108: 2, 3, 5, 6, */ { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1 }, +/* 109: 0, 2, 3, 5, 6, */ { 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1 }, +/* 110: 1, 2, 3, 5, 6, */ { 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, +/* 111: 0, 1, 2, 3, 5, 6, */ { 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 112: 4, 5, 6, */ { 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, +/* 113: 0, 4, 5, 6, */ { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1 }, +/* 114: 1, 4, 5, 6, */ { 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1 }, +/* 115: 0, 1, 4, 5, 6, */ { 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, +/* 116: 2, 4, 5, 6, */ { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, +/* 117: 0, 2, 4, 5, 6, */ { 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1 }, +/* 118: 1, 2, 4, 5, 6, */ { 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, +/* 119: 0, 1, 2, 4, 5, 6, */ { 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 120: 3, 4, 5, 6, */ { 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, +/* 121: 0, 3, 4, 5, 6, */ { 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1 }, +/* 122: 1, 3, 4, 5, 6, */ { 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1 }, +/* 123: 0, 1, 3, 4, 5, 6, */ { 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1 }, +/* 124: 2, 3, 4, 5, 6, */ { 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 }, +/* 125: 0, 2, 3, 4, 5, 6, */ { 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 126: 1, 2, 3, 4, 5, 6, */ { 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 }, +/* 127: 0, 1, 2, 3, 4, 5, 6, */ { 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 128: 7, */ { 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 129: 0, 7, */ { 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 130: 1, 7, */ { 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 131: 0, 1, 7, */ { 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 132: 2, 7, */ { 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 133: 0, 2, 7, */ { 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 134: 1, 2, 7, */ { 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 135: 0, 1, 2, 7, */ { 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 }, +/* 136: 3, 7, */ { 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 137: 0, 3, 7, */ { 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, +/* 138: 1, 3, 7, */ { 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 }, +/* 139: 0, 1, 3, 7, */ { 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 }, +/* 140: 2, 3, 7, */ { 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 141: 0, 2, 3, 7, */ { 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 }, +/* 142: 1, 2, 3, 7, */ { 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 }, +/* 143: 0, 1, 2, 3, 7, */ { 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, +/* 144: 4, 7, */ { 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 145: 0, 4, 7, */ { 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 146: 1, 4, 7, */ { 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 }, +/* 147: 0, 1, 4, 7, */ { 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 }, +/* 148: 2, 4, 7, */ { 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 }, +/* 149: 0, 2, 4, 7, */ { 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 }, +/* 150: 1, 2, 4, 7, */ { 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 }, +/* 151: 0, 1, 2, 4, 7, */ { 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 }, +/* 152: 3, 4, 7, */ { 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, +/* 153: 0, 3, 4, 7, */ { 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 154: 1, 3, 4, 7, */ { 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 }, +/* 155: 0, 1, 3, 4, 7, */ { 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 156: 2, 3, 4, 7, */ { 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 }, +/* 157: 0, 2, 3, 4, 7, */ { 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, +/* 158: 1, 2, 3, 4, 7, */ { 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 }, +/* 159: 0, 1, 2, 3, 4, 7, */ { 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 160: 5, 7, */ { 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 161: 0, 5, 7, */ { 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, +/* 162: 1, 5, 7, */ { 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 163: 0, 1, 5, 7, */ { 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 }, +/* 164: 2, 5, 7, */ { 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 165: 0, 2, 5, 7, */ { 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 }, +/* 166: 1, 2, 5, 7, */ { 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 }, +/* 167: 0, 1, 2, 5, 7, */ { 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1 }, +/* 168: 3, 5, 7, */ { 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1 }, +/* 169: 0, 3, 5, 7, */ { 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1 }, +/* 170: 1, 3, 5, 7, */ { 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1 }, +/* 171: 0, 1, 3, 5, 7, */ { 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1 }, +/* 172: 2, 3, 5, 7, */ { 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1 }, +/* 173: 0, 2, 3, 5, 7, */ { 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1 }, +/* 174: 1, 2, 3, 5, 7, */ { 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1 }, +/* 175: 0, 1, 2, 3, 5, 7, */ { 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1 }, +/* 176: 4, 5, 7, */ { 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, +/* 177: 0, 4, 5, 7, */ { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1 }, +/* 178: 1, 4, 5, 7, */ { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1 }, +/* 179: 0, 1, 4, 5, 7, */ { 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, +/* 180: 2, 4, 5, 7, */ { 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1 }, +/* 181: 0, 2, 4, 5, 7, */ { 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 }, +/* 182: 1, 2, 4, 5, 7, */ { 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 }, +/* 183: 0, 1, 2, 4, 5, 7, */ { 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 }, +/* 184: 3, 4, 5, 7, */ { 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 }, +/* 185: 0, 3, 4, 5, 7, */ { 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, +/* 186: 1, 3, 4, 5, 7, */ { 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1 }, +/* 187: 0, 1, 3, 4, 5, 7, */ { 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 188: 2, 3, 4, 5, 7, */ { 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1 }, +/* 189: 0, 2, 3, 4, 5, 7, */ { 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1 }, +/* 190: 1, 2, 3, 4, 5, 7, */ { 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 191: 0, 1, 2, 3, 4, 5, 7, */ { 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 192: 6, 7, */ { 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 193: 0, 6, 7, */ { 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1 }, +/* 194: 1, 6, 7, */ { 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 }, +/* 195: 0, 1, 6, 7, */ { 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 }, +/* 196: 2, 6, 7, */ { 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, +/* 197: 0, 2, 6, 7, */ { 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 }, +/* 198: 1, 2, 6, 7, */ { 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 }, +/* 199: 0, 1, 2, 6, 7, */ { 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 }, +/* 200: 3, 6, 7, */ { 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 201: 0, 3, 6, 7, */ { 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1 }, +/* 202: 1, 3, 6, 7, */ { 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1 }, +/* 203: 0, 1, 3, 6, 7, */ { 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1 }, +/* 204: 2, 3, 6, 7, */ { 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 205: 0, 2, 3, 6, 7, */ { 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, +/* 206: 1, 2, 3, 6, 7, */ { 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, +/* 207: 0, 1, 2, 3, 6, 7, */ { 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 208: 4, 6, 7, */ { 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, +/* 209: 0, 4, 6, 7, */ { 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1 }, +/* 210: 1, 4, 6, 7, */ { 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1 }, +/* 211: 0, 1, 4, 6, 7, */ { 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1 }, +/* 212: 2, 4, 6, 7, */ { 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1 }, +/* 213: 0, 2, 4, 6, 7, */ { 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1 }, +/* 214: 1, 2, 4, 6, 7, */ { 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1 }, +/* 215: 0, 1, 2, 4, 6, 7, */ { 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 216: 3, 4, 6, 7, */ { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1 }, +/* 217: 0, 3, 4, 6, 7, */ { 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, +/* 218: 1, 3, 4, 6, 7, */ { 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1 }, +/* 219: 0, 1, 3, 4, 6, 7, */ { 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1 }, +/* 220: 2, 3, 4, 6, 7, */ { 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, +/* 221: 0, 2, 3, 4, 6, 7, */ { 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 222: 1, 2, 3, 4, 6, 7, */ { 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1 }, +/* 223: 0, 1, 2, 3, 4, 6, 7, */ { 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 224: 5, 6, 7, */ { 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 225: 0, 5, 6, 7, */ { 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1 }, +/* 226: 1, 5, 6, 7, */ { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1 }, +/* 227: 0, 1, 5, 6, 7, */ { 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1 }, +/* 228: 2, 5, 6, 7, */ { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1 }, +/* 229: 0, 2, 5, 6, 7, */ { 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1 }, +/* 230: 1, 2, 5, 6, 7, */ { 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, +/* 231: 0, 1, 2, 5, 6, 7, */ { 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1 }, +/* 232: 3, 5, 6, 7, */ { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1 }, +/* 233: 0, 3, 5, 6, 7, */ { 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1 }, +/* 234: 1, 3, 5, 6, 7, */ { 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1 }, +/* 235: 0, 1, 3, 5, 6, 7, */ { 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 236: 2, 3, 5, 6, 7, */ { 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, +/* 237: 0, 2, 3, 5, 6, 7, */ { 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1 }, +/* 238: 1, 2, 3, 5, 6, 7, */ { 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 239: 0, 1, 2, 3, 5, 6, 7, */ { 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 240: 4, 5, 6, 7, */ { 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 241: 0, 4, 5, 6, 7, */ { 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, +/* 242: 1, 4, 5, 6, 7, */ { 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, +/* 243: 0, 1, 4, 5, 6, 7, */ { 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 244: 2, 4, 5, 6, 7, */ { 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, +/* 245: 0, 2, 4, 5, 6, 7, */ { 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1 }, +/* 246: 1, 2, 4, 5, 6, 7, */ { 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 247: 0, 1, 2, 4, 5, 6, 7, */ { 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 248: 3, 4, 5, 6, 7, */ { 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, +/* 249: 0, 3, 4, 5, 6, 7, */ { 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 250: 1, 3, 4, 5, 6, 7, */ { 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 }, +/* 251: 0, 1, 3, 4, 5, 6, 7, */ { 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 252: 2, 3, 4, 5, 6, 7, */ { 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 253: 0, 2, 3, 4, 5, 6, 7, */ { 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 254: 1, 2, 3, 4, 5, 6, 7, */ { 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, +/* 255: 0, 1, 2, 3, 4, 5, 6, 7, */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } +}; +//_____________________________________________________________________________ + + + +#endif // _LOOKUPTABLE_H_ diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/AffineTransformationModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/AffineTransformationModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/AffineTransformationModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/AffineTransformationModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,37 +29,40 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, AffineTransformationModifier, ParticleModifier); -DEFINE_PROPERTY_FIELD(AffineTransformationModifier, _transformationTM, "Transformation"); -DEFINE_PROPERTY_FIELD(AffineTransformationModifier, _applyToParticles, "ApplyToParticles"); -DEFINE_PROPERTY_FIELD(AffineTransformationModifier, _toSelectionOnly, "SelectionOnly"); -DEFINE_PROPERTY_FIELD(AffineTransformationModifier, _applyToSimulationBox, "ApplyToSimulationBox"); -DEFINE_PROPERTY_FIELD(AffineTransformationModifier, _targetCell, "DestinationCell"); -DEFINE_PROPERTY_FIELD(AffineTransformationModifier, _relativeMode, "RelativeMode"); -DEFINE_PROPERTY_FIELD(AffineTransformationModifier, _applyToSurfaceMesh, "ApplyToSurfaceMesh"); -SET_PROPERTY_FIELD_LABEL(AffineTransformationModifier, _transformationTM, "Transformation"); -SET_PROPERTY_FIELD_LABEL(AffineTransformationModifier, _applyToParticles, "Transform particles"); -SET_PROPERTY_FIELD_LABEL(AffineTransformationModifier, _toSelectionOnly, "Selected particles only"); -SET_PROPERTY_FIELD_LABEL(AffineTransformationModifier, _applyToSimulationBox, "Transform simulation cell"); -SET_PROPERTY_FIELD_LABEL(AffineTransformationModifier, _targetCell, "Destination cell geometry"); -SET_PROPERTY_FIELD_LABEL(AffineTransformationModifier, _relativeMode, "Relative transformation"); -SET_PROPERTY_FIELD_LABEL(AffineTransformationModifier, _applyToSurfaceMesh, "Transform surface mesh"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(AffineTransformationModifier, ParticleModifier); +DEFINE_PROPERTY_FIELD(AffineTransformationModifier, transformationTM, "Transformation"); +DEFINE_PROPERTY_FIELD(AffineTransformationModifier, applyToParticles, "ApplyToParticles"); +DEFINE_PROPERTY_FIELD(AffineTransformationModifier, selectionOnly, "SelectionOnly"); +DEFINE_PROPERTY_FIELD(AffineTransformationModifier, applyToSimulationBox, "ApplyToSimulationBox"); +DEFINE_PROPERTY_FIELD(AffineTransformationModifier, targetCell, "DestinationCell"); +DEFINE_PROPERTY_FIELD(AffineTransformationModifier, relativeMode, "RelativeMode"); +DEFINE_PROPERTY_FIELD(AffineTransformationModifier, applyToSurfaceMesh, "ApplyToSurfaceMesh"); +DEFINE_PROPERTY_FIELD(AffineTransformationModifier, applyToVectorProperties, "ApplyToVectorProperties"); +SET_PROPERTY_FIELD_LABEL(AffineTransformationModifier, transformationTM, "Transformation"); +SET_PROPERTY_FIELD_LABEL(AffineTransformationModifier, applyToParticles, "Transform particle positions"); +SET_PROPERTY_FIELD_LABEL(AffineTransformationModifier, selectionOnly, "Selected particles only"); +SET_PROPERTY_FIELD_LABEL(AffineTransformationModifier, applyToSimulationBox, "Transform simulation cell"); +SET_PROPERTY_FIELD_LABEL(AffineTransformationModifier, targetCell, "Destination cell geometry"); +SET_PROPERTY_FIELD_LABEL(AffineTransformationModifier, relativeMode, "Relative transformation"); +SET_PROPERTY_FIELD_LABEL(AffineTransformationModifier, applyToSurfaceMesh, "Transform surface mesh"); +SET_PROPERTY_FIELD_LABEL(AffineTransformationModifier, applyToVectorProperties, "Transform vector properties"); /****************************************************************************** * Constructs the modifier object. ******************************************************************************/ AffineTransformationModifier::AffineTransformationModifier(DataSet* dataset) : ParticleModifier(dataset), - _applyToParticles(true), _toSelectionOnly(false), _applyToSimulationBox(false), + _applyToParticles(true), _selectionOnly(false), _applyToSimulationBox(false), _transformationTM(AffineTransformation::Identity()), _targetCell(AffineTransformation::Zero()), - _relativeMode(true), _applyToSurfaceMesh(true) + _relativeMode(true), _applyToSurfaceMesh(true), _applyToVectorProperties(false) { - INIT_PROPERTY_FIELD(AffineTransformationModifier::_transformationTM); - INIT_PROPERTY_FIELD(AffineTransformationModifier::_applyToParticles); - INIT_PROPERTY_FIELD(AffineTransformationModifier::_toSelectionOnly); - INIT_PROPERTY_FIELD(AffineTransformationModifier::_applyToSimulationBox); - INIT_PROPERTY_FIELD(AffineTransformationModifier::_targetCell); - INIT_PROPERTY_FIELD(AffineTransformationModifier::_relativeMode); - INIT_PROPERTY_FIELD(AffineTransformationModifier::_applyToSurfaceMesh); + INIT_PROPERTY_FIELD(transformationTM); + INIT_PROPERTY_FIELD(applyToParticles); + INIT_PROPERTY_FIELD(selectionOnly); + INIT_PROPERTY_FIELD(applyToSimulationBox); + INIT_PROPERTY_FIELD(targetCell); + INIT_PROPERTY_FIELD(relativeMode); + INIT_PROPERTY_FIELD(applyToSurfaceMesh); + INIT_PROPERTY_FIELD(applyToVectorProperties); } /****************************************************************************** @@ -86,7 +89,7 @@ { AffineTransformation tm; if(relativeMode()) { - tm = transformation(); + tm = transformationTM(); if(applyToSimulationBox()) { AffineTransformation deformedCell = tm * expectSimulationCell()->cellMatrix(); outputSimulationCell()->setCellMatrix(deformedCell); @@ -111,7 +114,7 @@ const int* sbegin = selProperty->constDataInt(); Point3* pbegin = posProperty->dataPoint3(); Point3* pend = pbegin + posProperty->size(); - QtConcurrent::blockingMap(pbegin, pend, [tm, pbegin, sbegin](Point3& p) { + QtConcurrent::blockingMap(pbegin, pend, [&tm, pbegin, sbegin](Point3& p) { if(sbegin[&p - pbegin]) p = tm * p; }); @@ -129,13 +132,42 @@ *p += translation; } else { - QtConcurrent::blockingMap(pbegin, pend, [tm](Point3& p) { p = tm * p; }); + QtConcurrent::blockingMap(pbegin, pend, [&tm](Point3& p) { p = tm * p; }); } } posProperty->changed(); } + if(applyToVectorProperties()) { + for(DataObject* obj : input().objects()) { + if(OORef inputProperty = dynamic_object_cast(obj)) { + if( inputProperty->type() == ParticleProperty::VelocityProperty || + inputProperty->type() == ParticleProperty::ForceProperty || + inputProperty->type() == ParticleProperty::DisplacementProperty) { + + PropertyBase* property = outputStandardProperty(inputProperty->type(), true)->modifiableStorage(); + OVITO_ASSERT(property->dataType() == qMetaTypeId()); + OVITO_ASSERT(property->componentCount() == 3); + Vector3* const pbegin = property->dataVector3(); + Vector3* const pend = pbegin + property->size(); + if(!selectionOnly()) { + QtConcurrent::blockingMap(pbegin, pend, [&tm](Vector3& v) { v = tm * v; }); + } + else { + ParticlePropertyObject* selProperty = inputStandardProperty(ParticleProperty::SelectionProperty); + if(selProperty) { + QtConcurrent::blockingMap(pbegin, pend, [&tm, pbegin, selProperty](Vector3& v) { + if(selProperty->getInt(&v - pbegin)) + v = tm * v; + }); + } + } + } + } + } + } + if(applyToSurfaceMesh()) { for(int index = 0; index < input().objects().size(); index++) { // Apply transformation to vertices of surface mesh. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/AffineTransformationModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/AffineTransformationModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/AffineTransformationModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/AffineTransformationModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_AFFINE_TRANSFORMATION_MODIFIER_H -#define __OVITO_AFFINE_TRANSFORMATION_MODIFIER_H +#pragma once + #include #include "../ParticleModifier.h" @@ -40,50 +40,6 @@ /// \brief Constructor. Q_INVOKABLE AffineTransformationModifier(DataSet* dataset); - // Property access functions: - - /// Returns the affine transformation matrix. - const AffineTransformation& transformation() const { return _transformationTM; } - - /// Sets the affine transformation. - void setTransformation(const AffineTransformation& tm) { _transformationTM = tm; } - - /// Returns the target cell matrix matrix for absolute transformation mode. - const AffineTransformation& targetCell() const { return _targetCell; } - - /// Sets the target cell matrix for absolute transformation mode. - void setTargetCell(const AffineTransformation& cell) { _targetCell = cell; } - - /// Returns true if relative transformation mode is selected; returns false if absolute transformation mode is active. - bool relativeMode() const { return _relativeMode; } - - /// Switches between relative and absolute transformation mode. - void setRelativeMode(bool relative) { _relativeMode = relative; } - - /// Returns whether the transformation is applied to the particles. - bool applyToParticles() const { return _applyToParticles; } - - /// Sets whether the transformation is applied to the particles. - void setApplyToParticles(bool apply) { _applyToParticles = apply; } - - /// Returns whether the transformation is applied only to the selected particles. - bool selectionOnly() const { return _toSelectionOnly; } - - /// Sets whether the transformation is applied only to the selected particles. - void setSelectionOnly(bool onlySelected) { _toSelectionOnly = onlySelected; } - - /// Returns whether the transformation is applied to the simulation box. - bool applyToSimulationBox() const { return _applyToSimulationBox; } - - /// Sets whether the transformation is applied to the simulation box. - void setApplyToSimulationBox(bool apply) { _applyToSimulationBox = apply; } - - /// Returns whether the transformation is applied to a surface mesh. - bool applyToSurfaceMesh() const { return _applyToSurfaceMesh; } - - /// Sets whether the transformation is applied to a surface mesh. - void setApplyToSurfaceMesh(bool apply) { _applyToSurfaceMesh = apply; } - protected: /// \brief This virtual method is called by the system when the modifier has been inserted into a PipelineObject. @@ -93,47 +49,38 @@ virtual PipelineStatus modifyParticles(TimePoint time, TimeInterval& validityInterval) override; /// This property fields stores the transformation matrix (used in 'relative' mode). - PropertyField _transformationTM; + DECLARE_MODIFIABLE_PROPERTY_FIELD(AffineTransformation, transformationTM, setTransformationTM); /// This property fields stores the simulation cell geometry (used in 'absolute' mode). - PropertyField _targetCell; + DECLARE_MODIFIABLE_PROPERTY_FIELD(AffineTransformation, targetCell, setTargetCell); /// This controls whether the transformation is applied to the particles. - PropertyField _applyToParticles; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, applyToParticles, setApplyToParticles); /// This controls whether the transformation is applied only to the selected particles. - PropertyField _toSelectionOnly; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, selectionOnly, setSelectionOnly); /// This controls whether the transformation is applied to the simulation box. - PropertyField _applyToSimulationBox; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, applyToSimulationBox, setApplyToSimulationBox); /// This controls whether a relative transformation is applied to the simulation box or /// the absolute cell geometry has been specified. - PropertyField _relativeMode; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, relativeMode, setRelativeMode); /// This controls whether the transformation is applied to surface meshes. - PropertyField _applyToSurfaceMesh; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, applyToSurfaceMesh, setApplyToSurfaceMesh); -private: + /// This controls whether the transformation is applied to vector particle and bond properties. + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, applyToVectorProperties, setApplyToVectorProperties); Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Affine transformation"); Q_CLASSINFO("ModifierCategory", "Modification"); - - DECLARE_PROPERTY_FIELD(_transformationTM); - DECLARE_PROPERTY_FIELD(_applyToParticles); - DECLARE_PROPERTY_FIELD(_toSelectionOnly); - DECLARE_PROPERTY_FIELD(_applyToSimulationBox); - DECLARE_PROPERTY_FIELD(_targetCell); - DECLARE_PROPERTY_FIELD(_relativeMode); - DECLARE_PROPERTY_FIELD(_applyToSurfaceMesh); }; OVITO_END_INLINE_NAMESPACE OVITO_END_INLINE_NAMESPACE } // End of namespace } // End of namespace - -#endif // __AFFINE_TRANSFORMATION_MODIFIER_H diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/CombineParticleSetsModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/CombineParticleSetsModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/CombineParticleSetsModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/CombineParticleSetsModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,16 +29,16 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, CombineParticleSetsModifier, ParticleModifier); -DEFINE_FLAGS_REFERENCE_FIELD(CombineParticleSetsModifier, _secondarySource, "SecondarySource", DataObject, PROPERTY_FIELD_NO_SUB_ANIM); -SET_PROPERTY_FIELD_LABEL(CombineParticleSetsModifier, _secondarySource, "Secondary source"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CombineParticleSetsModifier, ParticleModifier); +DEFINE_FLAGS_REFERENCE_FIELD(CombineParticleSetsModifier, secondaryDataSource, "SecondarySource", DataObject, PROPERTY_FIELD_NO_SUB_ANIM); +SET_PROPERTY_FIELD_LABEL(CombineParticleSetsModifier, secondaryDataSource, "Secondary source"); /****************************************************************************** * Constructs the modifier object. ******************************************************************************/ CombineParticleSetsModifier::CombineParticleSetsModifier(DataSet* dataset) : ParticleModifier(dataset) { - INIT_PROPERTY_FIELD(CombineParticleSetsModifier::_secondarySource); + INIT_PROPERTY_FIELD(secondaryDataSource); // Create the file source object, which will be responsible for loading // and caching the data to be merged. @@ -60,7 +60,7 @@ throwException(tr("No particle data to be merged has been provided.")); // Get the data to be merged into the pipeline. - PipelineFlowState secondaryState = secondaryDataSource()->evaluate(time); + PipelineFlowState secondaryState = secondaryDataSource()->evaluateImmediately(PipelineEvalRequest(time, false)); // Make sure the obtained dataset is valid and ready to use. if(secondaryState.status().type() == PipelineStatus::Error) { diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/CombineParticleSetsModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/CombineParticleSetsModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/CombineParticleSetsModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/CombineParticleSetsModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COMBINE_PARTICLE_SETS_MODIFIER_H -#define __OVITO_COMBINE_PARTICLE_SETS_MODIFIER_H +#pragma once + #include #include @@ -37,29 +37,19 @@ /// Constructor. Q_INVOKABLE CombineParticleSetsModifier(DataSet* dataset); - /// Returns the data object that provides the particles to be merged into the pipeline. - DataObject* secondaryDataSource() const { return _secondarySource; } - - /// Sets the object that will provide the particles to be merged into the pipeline. - void setSecondaryDataSource(DataObject* source) { _secondarySource = source; } - protected: /// Modifies the particle object. virtual PipelineStatus modifyParticles(TimePoint time, TimeInterval& validityInterval) override; /// The source for particle data to be merged into the pipeline. - ReferenceField _secondarySource; - -private: + DECLARE_MODIFIABLE_REFERENCE_FIELD(DataObject, secondaryDataSource, setSecondaryDataSource); Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Combine particle sets"); Q_CLASSINFO("ModifierCategory", "Modification"); - - DECLARE_REFERENCE_FIELD(_secondarySource); }; OVITO_END_INLINE_NAMESPACE @@ -67,4 +57,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_COMBINE_PARTICLE_SETS_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/CoordinationPolyhedraModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/CoordinationPolyhedraModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/CoordinationPolyhedraModifier.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/CoordinationPolyhedraModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,363 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include "CoordinationPolyhedraModifier.h" + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CoordinationPolyhedraModifier, AsynchronousParticleModifier); +DEFINE_FLAGS_REFERENCE_FIELD(CoordinationPolyhedraModifier, surfaceMeshDisplay, "SurfaceMeshDisplay", SurfaceMeshDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(CoordinationPolyhedraModifier, surfaceMeshDisplay, "Surface mesh display"); + +/****************************************************************************** +* Constructs the modifier object. +******************************************************************************/ +CoordinationPolyhedraModifier::CoordinationPolyhedraModifier(DataSet* dataset) : AsynchronousParticleModifier(dataset) +{ + INIT_PROPERTY_FIELD(surfaceMeshDisplay); + + // Create the display object for rendering the created polyhedra. + _surfaceMeshDisplay = new SurfaceMeshDisplay(dataset); + _surfaceMeshDisplay->setShowCap(false); + _surfaceMeshDisplay->setSmoothShading(false); + _surfaceMeshDisplay->setSurfaceTransparency(FloatType(0.25)); + _surfaceMeshDisplay->setObjectTitle(tr("Polyhedra")); +} + +/****************************************************************************** +* Is called when the value of a property of this object has changed. +******************************************************************************/ +void CoordinationPolyhedraModifier::propertyChanged(const PropertyFieldDescriptor& field) +{ + AsynchronousParticleModifier::propertyChanged(field); +} + +/****************************************************************************** +* Handles reference events sent by reference targets of this object. +******************************************************************************/ +bool CoordinationPolyhedraModifier::referenceEvent(RefTarget* source, ReferenceEvent* event) +{ + // Do not propagate messages from the attached display object. + if(source == surfaceMeshDisplay()) + return false; + + return AsynchronousParticleModifier::referenceEvent(source, event); +} + +/****************************************************************************** +* Resets the modifier's result cache. +******************************************************************************/ +void CoordinationPolyhedraModifier::invalidateCachedResults() +{ + AsynchronousParticleModifier::invalidateCachedResults(); + + // Reset computed mesh when the input has changed. + _polyhedraMesh.reset(); +} + +/****************************************************************************** +* This method is called by the system when the modifier has been inserted +* into a pipeline. +******************************************************************************/ +void CoordinationPolyhedraModifier::initializeModifier(PipelineObject* pipeline, ModifierApplication* modApp) +{ + AsynchronousParticleModifier::initializeModifier(pipeline, modApp); +} + +/****************************************************************************** +* Creates and initializes a computation engine that will compute the modifier's results. +******************************************************************************/ +std::shared_ptr CoordinationPolyhedraModifier::createEngine(TimePoint time, TimeInterval validityInterval) +{ + // Get modifier inputs. + ParticlePropertyObject* posProperty = expectStandardProperty(ParticleProperty::PositionProperty); + ParticlePropertyObject* typeProperty = inputStandardProperty(ParticleProperty::ParticleTypeProperty); + ParticlePropertyObject* selectionProperty = inputStandardProperty(ParticleProperty::SelectionProperty); + BondsObject* bondsObj = input().findObject(); + SimulationCellObject* simCell = expectSimulationCell(); + + // Create engine object. Pass all relevant modifier parameters to the engine as well as the input data. + return std::make_shared(validityInterval, posProperty->storage(), + selectionProperty ? selectionProperty->storage() : nullptr, + typeProperty ? typeProperty->storage() : nullptr, + bondsObj ? bondsObj->storage() : nullptr, simCell->data()); +} + +/****************************************************************************** +* Performs the actual analysis. This method is executed in a worker thread. +******************************************************************************/ +void CoordinationPolyhedraModifier::ComputePolyhedraEngine::perform() +{ + if(!_selection) + throw Exception(tr("Please select particles first for which coordination polyhedra should be generated.")); + if(!_bonds) + throw Exception(tr("Please create bonds between particles first. They are needed for coordination polyhedra.")); + + setProgressText(tr("Generating coordination polyhedra")); + + // Determine number of selected particles. + size_t npoly = std::count_if(_selection->constDataInt(), _selection->constDataInt() + _selection->size(), [](int s) { return s != 0; }); + setProgressMaximum(npoly); + + std::vector bondVectors; + ParticleBondMap bondMap(*_bonds); + + for(size_t i = 0; i < _positions->size(); i++) { + if(_selection->getInt(i) == 0) continue; + + // Collect the bonds that are part of the coordination polyhedron. + const Point3& p1 = _positions->getPoint3(i); + for(auto bondIndex : bondMap.bondsOfParticle(i)) { + const Bond& bond = (*_bonds)[bondIndex]; + if(_positions->size() > bond.index2) { + Vector3 delta = _positions->getPoint3(bond.index2) - p1; + if(bond.pbcShift.x()) delta += _simCell.matrix().column(0) * (FloatType)bond.pbcShift.x(); + if(bond.pbcShift.y()) delta += _simCell.matrix().column(1) * (FloatType)bond.pbcShift.y(); + if(bond.pbcShift.z()) delta += _simCell.matrix().column(2) * (FloatType)bond.pbcShift.z(); + bondVectors.push_back(p1 + delta); + } + } + + // Construct the polyhedron (i.e. convex hull) from the bond vectors. + constructConvexHull(bondVectors); + bondVectors.clear(); + + if(!incrementProgressValue()) + return; + } + mesh()->reindexVerticesAndFaces(); +} + +/****************************************************************************** +* Constructs the convex hull from a set of points and adds the resulting +* polyhedron to the mesh. +******************************************************************************/ +void CoordinationPolyhedraModifier::ComputePolyhedraEngine::constructConvexHull(std::vector& vecs) +{ + using Vertex = HalfEdgeMesh<>::Vertex; + using Edge = HalfEdgeMesh<>::Edge; + using Face = HalfEdgeMesh<>::Face; + + if(vecs.size() < 4) return; // Convex hull requires at least 4 input points. + + // Keep track of how many faces and vertices we started with. + // We won't touch the existing mesh faces and vertices. + int originalFaceCount = mesh()->faceCount(); + int originalVertexCount = mesh()->vertexCount(); + + // Determine which points should form the initial tetrahedron. + // Make sure they are not co-planar. + size_t tetrahedraCorners[4]; + tetrahedraCorners[0] = 0; + size_t n = 1; + Matrix3 m; + for(size_t i = 1; i < vecs.size(); i++) { + if(n == 1) { + m.column(0) = vecs[i] - vecs[0]; + tetrahedraCorners[1] = i; + if(!m.column(0).isZero()) n = 2; + } + else if(n == 2) { + m.column(1) = vecs[i] - vecs[0]; + tetrahedraCorners[2] = i; + if(!m.column(0).cross(m.column(1)).isZero()) n = 3; + } + else if(n == 3) { + m.column(2) = vecs[i] - vecs[0]; + FloatType det = m.determinant(); + if(std::abs(det) > FLOATTYPE_EPSILON) { + tetrahedraCorners[3] = i; + if(det < 0) std::swap(tetrahedraCorners[0], tetrahedraCorners[1]); + n = 4; + break; + } + } + } + if(n != 4) return; + + // Create the initial tetrahedron. + Vertex* tetverts[4]; + for(size_t i = 0; i < 4; i++) { + tetverts[i] = mesh()->createVertex(vecs[tetrahedraCorners[i]]); + } + mesh()->createFace({tetverts[0], tetverts[1], tetverts[3]}); + mesh()->createFace({tetverts[2], tetverts[0], tetverts[3]}); + mesh()->createFace({tetverts[0], tetverts[2], tetverts[1]}); + mesh()->createFace({tetverts[1], tetverts[2], tetverts[3]}); + // Connect opposite half edges. + for(size_t i = 0; i < 4; i++) { + for(Edge* edge = tetverts[i]->edges(); edge != nullptr; edge = edge->nextVertexEdge()) { + if(edge->oppositeEdge()) continue; + for(Edge* oppositeEdge = edge->vertex2()->edges(); oppositeEdge != nullptr; oppositeEdge = oppositeEdge->nextVertexEdge()) { + if(oppositeEdge->oppositeEdge()) continue; + if(oppositeEdge->vertex2() == tetverts[i]) { + edge->linkToOppositeEdge(oppositeEdge); + break; + } + } + OVITO_ASSERT(edge->oppositeEdge()); + } + } + + // Remove 4 points of initial tetrahedron from input list. + for(size_t i = 1; i <= 4; i++) + vecs[tetrahedraCorners[4-i]] = vecs[vecs.size()-i]; + vecs.erase(vecs.end() - 4, vecs.end()); + + // Simplified Quick-hull algorithm. + for(;;) { + // Find the point on the positive side of a face and furthest away from it. + // Also remove points from list which are on the negative side of all faces. + auto furthestPoint = vecs.rend(); + FloatType furthestPointDistance = 0; + size_t remainingPointCount = vecs.size(); + for(auto p = vecs.rbegin(); p != vecs.rend(); ++p) { + bool insideHull = true; + for(int faceIndex = originalFaceCount; faceIndex < mesh()->faceCount(); faceIndex++) { + Face* face = mesh()->face(faceIndex); + Plane3 plane(face->edges()->vertex1()->pos(), + face->edges()->vertex2()->pos(), + face->edges()->nextFaceEdge()->vertex2()->pos(), true); + FloatType signedDistance = plane.pointDistance(*p); + if(signedDistance > FLOATTYPE_EPSILON) { + insideHull = false; + if(signedDistance > furthestPointDistance) { + furthestPointDistance = signedDistance; + furthestPoint = p; + } + } + } + // When point is inside the hull, remove it from the input list. + if(insideHull) { + remainingPointCount--; + *p = vecs[remainingPointCount]; + } + } + if(!remainingPointCount) break; + OVITO_ASSERT(furthestPointDistance > 0 && furthestPoint != vecs.rend()); + + // Kill all faces of the polyhedron that can be seen from the selected point. + for(int faceIndex = originalFaceCount; faceIndex < mesh()->faceCount(); faceIndex++) { + Face* face = mesh()->face(faceIndex); + Plane3 plane(face->edges()->vertex1()->pos(), + face->edges()->vertex2()->pos(), + face->edges()->nextFaceEdge()->vertex2()->pos(), true); + if(plane.pointDistance(*furthestPoint) > FLOATTYPE_EPSILON) { + mesh()->removeFace(faceIndex); + faceIndex--; + } + } + + // Find an edge that borders the newly created hole in the mesh. + Edge* firstBorderEdge = nullptr; + for(int faceIndex = originalFaceCount; faceIndex < mesh()->faceCount() && !firstBorderEdge; faceIndex++) { + Face* face = mesh()->face(faceIndex); + Edge* e = face->edges(); + OVITO_ASSERT(e != nullptr); + do { + if(e->oppositeEdge() == nullptr) { + firstBorderEdge = e; + break; + } + e = e->nextFaceEdge(); + } + while(e != face->edges()); + } + OVITO_ASSERT(firstBorderEdge != nullptr); // If this assert fails, then there was no hole in the mesh. + + // Create new faces that connects the edges at the horizon (i.e. the border of the hole) with + // the selected vertex. + Vertex* vertex = mesh()->createVertex(*furthestPoint); + Edge* borderEdge = firstBorderEdge; + Face* previousFace; + Face* firstFace; + Face* newFace; + do { + newFace = mesh()->createFace({ borderEdge->vertex2(), borderEdge->vertex1(), vertex }); + newFace->edges()->linkToOppositeEdge(borderEdge); + if(borderEdge == firstBorderEdge) + firstFace = newFace; + else + newFace->edges()->nextFaceEdge()->linkToOppositeEdge(previousFace->edges()->prevFaceEdge()); + previousFace = newFace; + // Proceed to next edge along the hole's border. + for(;;) { + borderEdge = borderEdge->nextFaceEdge(); + if(borderEdge->oppositeEdge() == nullptr || borderEdge == firstBorderEdge) break; + borderEdge = borderEdge->oppositeEdge(); + } + } + while(borderEdge != firstBorderEdge); + OVITO_ASSERT(firstFace != newFace); + firstFace->edges()->nextFaceEdge()->linkToOppositeEdge(newFace->edges()->prevFaceEdge()); + + // Remove selected point from the input list as well. + remainingPointCount--; + *furthestPoint = vecs[remainingPointCount]; + vecs.resize(remainingPointCount); + } + + // Delete interior vertices from the mesh that are no longer attached to any of the faces. + for(int vertexIndex = originalVertexCount; vertexIndex < mesh()->vertexCount(); vertexIndex++) { + if(mesh()->vertex(vertexIndex)->numEdges() == 0) { + mesh()->removeVertex(vertexIndex); + vertexIndex--; + } + } +} + +/****************************************************************************** +* Unpacks the results of the computation engine and stores them in the modifier. +******************************************************************************/ +void CoordinationPolyhedraModifier::transferComputationResults(ComputeEngine* engine) +{ + _polyhedraMesh = static_cast(engine)->mesh(); +} + +/****************************************************************************** +* Lets the modifier insert the cached computation results into the +* modification pipeline. +******************************************************************************/ +PipelineStatus CoordinationPolyhedraModifier::applyComputationResults(TimePoint time, TimeInterval& validityInterval) +{ + if(!_polyhedraMesh) + throwException(tr("No computation results available.")); + + // Create the output data object. + OORef meshObj(new SurfaceMesh(dataset(), _polyhedraMesh.data())); + meshObj->addDisplayObject(_surfaceMeshDisplay); + + // Insert output object into the pipeline. + output().addObject(meshObj); + + return PipelineStatus(PipelineStatus::Success); +} + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/CoordinationPolyhedraModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/CoordinationPolyhedraModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/CoordinationPolyhedraModifier.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/CoordinationPolyhedraModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,120 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include +#include +#include +#include + +namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) + +/** + * \brief A modifier that creates coordination polyhedra around atoms. + */ +class OVITO_PARTICLES_EXPORT CoordinationPolyhedraModifier : public AsynchronousParticleModifier +{ +public: + + /// Constructor. + Q_INVOKABLE CoordinationPolyhedraModifier(DataSet* dataset); + +protected: + + /// Resets the modifier's result cache. + virtual void invalidateCachedResults() override; + + /// Is called when the value of a property of this object has changed. + virtual void propertyChanged(const PropertyFieldDescriptor& field) override; + + /// Handles reference events sent by reference targets of this object. + virtual bool referenceEvent(RefTarget* source, ReferenceEvent* event) override; + + /// This virtual method is called by the system when the modifier has been inserted into a PipelineObject. + virtual void initializeModifier(PipelineObject* pipelineObject, ModifierApplication* modApp) override; + + /// Creates a computation engine that will compute the modifier's results. + virtual std::shared_ptr createEngine(TimePoint time, TimeInterval validityInterval) override; + + /// Unpacks the results of the computation engine and stores them in the modifier. + virtual void transferComputationResults(ComputeEngine* engine) override; + + /// Lets the modifier insert the cached computation results into the modification pipeline. + virtual PipelineStatus applyComputationResults(TimePoint time, TimeInterval& validityInterval) override; + +private: + + /// Computation engine that builds the polyhedra. + class ComputePolyhedraEngine : public ComputeEngine + { + public: + + /// Constructor. + ComputePolyhedraEngine(const TimeInterval& validityInterval, ParticleProperty* positions, ParticleProperty* selection, ParticleProperty* particleTypes, + BondsStorage* bonds, const SimulationCell& simCell) : + ComputeEngine(validityInterval), _positions(positions), _selection(selection), _particleTypes(particleTypes), + _bonds(bonds), _simCell(simCell), _mesh(new HalfEdgeMesh<>()) {} + + /// Computes the modifier's results and stores them in this object for later retrieval. + virtual void perform() override; + + /// Returns the generated mesh. + HalfEdgeMesh<>* mesh() { return _mesh.data(); } + + private: + + /// Constructs the convex hull from a set of points and adds the resulting polyhedron to the mesh. + void constructConvexHull(std::vector& vecs); + + private: + + QExplicitlySharedDataPointer _positions; + QExplicitlySharedDataPointer _selection; + QExplicitlySharedDataPointer _particleTypes; + QExplicitlySharedDataPointer _bonds; + QExplicitlySharedDataPointer> _mesh; + SimulationCell _simCell; + }; + +private: + + /// The display object for rendering the computed mesh. + DECLARE_MODIFIABLE_REFERENCE_FIELD(SurfaceMeshDisplay, surfaceMeshDisplay, setSurfaceMeshDisplay); + + /// This stores the cached mesh produced by the modifier. + QExplicitlySharedDataPointer> _polyhedraMesh; + + Q_OBJECT + OVITO_OBJECT + + Q_CLASSINFO("DisplayName", "Coordination polyhedra"); + Q_CLASSINFO("ModifierCategory", "Modification"); +}; + +OVITO_END_INLINE_NAMESPACE +OVITO_END_INLINE_NAMESPACE +} // End of namespace +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/CreateBondsModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/CreateBondsModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/CreateBondsModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/CreateBondsModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,34 +28,34 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, CreateBondsModifier, AsynchronousParticleModifier); -DEFINE_PROPERTY_FIELD(CreateBondsModifier, _cutoffMode, "CutoffMode"); -DEFINE_FLAGS_PROPERTY_FIELD(CreateBondsModifier, _uniformCutoff, "UniformCutoff", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(CreateBondsModifier, _minCutoff, "MinimumCutoff"); -DEFINE_FLAGS_PROPERTY_FIELD(CreateBondsModifier, _onlyIntraMoleculeBonds, "OnlyIntraMoleculeBonds", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_REFERENCE_FIELD(CreateBondsModifier, _bondsDisplay, "BondsDisplay", BondsDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(CreateBondsModifier, _cutoffMode, "Cutoff mode"); -SET_PROPERTY_FIELD_LABEL(CreateBondsModifier, _uniformCutoff, "Cutoff radius"); -SET_PROPERTY_FIELD_LABEL(CreateBondsModifier, _minCutoff, "Lower cutoff"); -SET_PROPERTY_FIELD_LABEL(CreateBondsModifier, _onlyIntraMoleculeBonds, "No bonds between different molecules"); -SET_PROPERTY_FIELD_LABEL(CreateBondsModifier, _bondsDisplay, "Bonds display"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CreateBondsModifier, _uniformCutoff, WorldParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CreateBondsModifier, _minCutoff, WorldParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(CreateBondsModifier, AsynchronousParticleModifier); +DEFINE_PROPERTY_FIELD(CreateBondsModifier, cutoffMode, "CutoffMode"); +DEFINE_FLAGS_PROPERTY_FIELD(CreateBondsModifier, uniformCutoff, "UniformCutoff", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(CreateBondsModifier, minimumCutoff, "MinimumCutoff"); +DEFINE_FLAGS_PROPERTY_FIELD(CreateBondsModifier, onlyIntraMoleculeBonds, "OnlyIntraMoleculeBonds", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_REFERENCE_FIELD(CreateBondsModifier, bondsDisplay, "BondsDisplay", BondsDisplay, PROPERTY_FIELD_ALWAYS_DEEP_COPY|PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(CreateBondsModifier, cutoffMode, "Cutoff mode"); +SET_PROPERTY_FIELD_LABEL(CreateBondsModifier, uniformCutoff, "Cutoff radius"); +SET_PROPERTY_FIELD_LABEL(CreateBondsModifier, minimumCutoff, "Lower cutoff"); +SET_PROPERTY_FIELD_LABEL(CreateBondsModifier, onlyIntraMoleculeBonds, "No bonds between different molecules"); +SET_PROPERTY_FIELD_LABEL(CreateBondsModifier, bondsDisplay, "Bonds display"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CreateBondsModifier, uniformCutoff, WorldParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(CreateBondsModifier, minimumCutoff, WorldParameterUnit, 0); /****************************************************************************** * Constructs the modifier object. ******************************************************************************/ CreateBondsModifier::CreateBondsModifier(DataSet* dataset) : AsynchronousParticleModifier(dataset), - _cutoffMode(UniformCutoff), _uniformCutoff(3.2), _onlyIntraMoleculeBonds(false), _minCutoff(0) + _cutoffMode(UniformCutoff), _uniformCutoff(3.2), _onlyIntraMoleculeBonds(false), _minimumCutoff(0) { - INIT_PROPERTY_FIELD(CreateBondsModifier::_cutoffMode); - INIT_PROPERTY_FIELD(CreateBondsModifier::_uniformCutoff); - INIT_PROPERTY_FIELD(CreateBondsModifier::_onlyIntraMoleculeBonds); - INIT_PROPERTY_FIELD(CreateBondsModifier::_bondsDisplay); - INIT_PROPERTY_FIELD(CreateBondsModifier::_minCutoff); + INIT_PROPERTY_FIELD(cutoffMode); + INIT_PROPERTY_FIELD(uniformCutoff); + INIT_PROPERTY_FIELD(onlyIntraMoleculeBonds); + INIT_PROPERTY_FIELD(bondsDisplay); + INIT_PROPERTY_FIELD(minimumCutoff); // Create the display object for bonds rendering and assign it to the data object. - _bondsDisplay = new BondsDisplay(dataset); + setBondsDisplay(new BondsDisplay(dataset)); } /****************************************************************************** @@ -66,9 +66,9 @@ AsynchronousParticleModifier::propertyChanged(field); // Recompute results when the parameters have been changed. - if(field == PROPERTY_FIELD(CreateBondsModifier::_uniformCutoff) || field == PROPERTY_FIELD(CreateBondsModifier::_cutoffMode) - || field == PROPERTY_FIELD(CreateBondsModifier::_onlyIntraMoleculeBonds) - || field == PROPERTY_FIELD(CreateBondsModifier::_minCutoff)) + if(field == PROPERTY_FIELD(uniformCutoff) || field == PROPERTY_FIELD(cutoffMode) + || field == PROPERTY_FIELD(onlyIntraMoleculeBonds) + || field == PROPERTY_FIELD(minimumCutoff)) invalidateCachedResults(); } @@ -180,7 +180,7 @@ ******************************************************************************/ void CreateBondsModifier::initializeModifier(PipelineObject* pipeline, ModifierApplication* modApp) { - ParticleModifier::initializeModifier(pipeline, modApp); + AsynchronousParticleModifier::initializeModifier(pipeline, modApp); // Adopt the upstream BondsDisplay object if there already is one. PipelineFlowState input = getModifierInput(modApp); @@ -251,14 +251,14 @@ // Prepare the neighbor list. CutoffNeighborFinder neighborFinder; - if(!neighborFinder.prepare(_maxCutoff, _positions.data(), _simCell, nullptr, this)) + if(!neighborFinder.prepare(_maxCutoff, _positions.data(), _simCell, nullptr, *this)) return; FloatType minCutoffSquared = _minCutoff * _minCutoff; // Generate (half) bonds. size_t particleCount = _positions->size(); - setProgressRange(particleCount); + setProgressMaximum(particleCount); if(!_particleTypes) { for(size_t particleIndex = 0; particleIndex < particleCount; particleIndex++) { for(CutoffNeighborFinder::Query neighborQuery(neighborFinder, particleIndex); !neighborQuery.atEnd(); neighborQuery.next()) { diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/CreateBondsModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/CreateBondsModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/CreateBondsModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/CreateBondsModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CREATE_BONDS_MODIFIER_H -#define __OVITO_CREATE_BONDS_MODIFIER_H +#pragma once + #include #include @@ -86,26 +86,6 @@ /// Constructor. Q_INVOKABLE CreateBondsModifier(DataSet* dataset); - /// Returns the mode of choosing the cutoff radius. - CutoffMode cutoffMode() const { return _cutoffMode; } - - /// Sets the mode of choosing the cutoff radius. - void setCutoffMode(CutoffMode mode) { _cutoffMode = mode; } - - /// \brief Returns the uniform cutoff radius used to determine which particles are bonded. - /// \return The uniform cutoff radius. - FloatType uniformCutoff() const { return _uniformCutoff; } - - /// \brief Sets the cutoff radius that is used for generating bonds. - /// \param newCutoff The new cutoff radius. - void setUniformCutoff(FloatType newCutoff) { _uniformCutoff = newCutoff; } - - /// \brief Returns the minimum length of bonds to create. - FloatType minimumCutoff() const { return _minCutoff; } - - /// \brief Sets the minimum length of bonds to create. - void setMinimumCutoff(FloatType cutoff) { _minCutoff = cutoff; } - /// Returns the cutoff radii for pairs of particle types. const PairCutoffsList& pairCutoffs() const { return _pairCutoffs; } @@ -118,15 +98,6 @@ /// Returns the pair-wise cutoff radius for a pair of particle types. FloatType getPairCutoff(const QString& typeA, const QString& typeB) const; - /// \brief Returns the display object that is responsible for rendering the bonds. - BondsDisplay* bondsDisplay() const { return _bondsDisplay; } - - /// Returns whether bonds will only be created between atoms from the same molecule. - bool onlyIntraMoleculeBonds() const { return _onlyIntraMoleculeBonds; } - - /// Sets whether bonds will only be created between atoms from the same molecule. - void setOnlyIntraMoleculeBonds(bool enable) { _onlyIntraMoleculeBonds = enable; } - protected: /// Saves the class' contents to the given stream. @@ -162,39 +133,31 @@ private: /// The mode of choosing the cutoff radius. - PropertyField _cutoffMode; + DECLARE_MODIFIABLE_PROPERTY_FIELD(CutoffMode, cutoffMode, setCutoffMode); /// The cutoff radius for bond generation. - PropertyField _uniformCutoff; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, uniformCutoff, setUniformCutoff); /// The minimum bond length. - PropertyField _minCutoff; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, minimumCutoff, setMinimumCutoff); /// The cutoff radii for pairs of particle types. PairCutoffsList _pairCutoffs; /// If true, bonds will only be created between atoms from the same molecule. - PropertyField _onlyIntraMoleculeBonds; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, onlyIntraMoleculeBonds, setOnlyIntraMoleculeBonds); /// The display object for rendering the bonds. - ReferenceField _bondsDisplay; + DECLARE_MODIFIABLE_REFERENCE_FIELD(BondsDisplay, bondsDisplay, setBondsDisplay); /// This stores the cached results of the modifier, i.e. the list of created bonds. QExplicitlySharedDataPointer _bonds; -private: - Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Create bonds"); Q_CLASSINFO("ModifierCategory", "Modification"); - - DECLARE_PROPERTY_FIELD(_cutoffMode); - DECLARE_PROPERTY_FIELD(_uniformCutoff); - DECLARE_PROPERTY_FIELD(_onlyIntraMoleculeBonds); - DECLARE_PROPERTY_FIELD(_minCutoff); - DECLARE_REFERENCE_FIELD(_bondsDisplay); }; OVITO_END_INLINE_NAMESPACE @@ -205,4 +168,4 @@ Q_DECLARE_METATYPE(Ovito::Particles::CreateBondsModifier::CutoffMode); Q_DECLARE_TYPEINFO(Ovito::Particles::CreateBondsModifier::CutoffMode, Q_PRIMITIVE_TYPE); -#endif // __OVITO_CREATE_BONDS_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/DeleteParticlesModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/DeleteParticlesModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/DeleteParticlesModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/DeleteParticlesModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, DeleteParticlesModifier, ParticleModifier); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(DeleteParticlesModifier, ParticleModifier); /****************************************************************************** * Modifies the particle object. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/DeleteParticlesModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/DeleteParticlesModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/DeleteParticlesModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/DeleteParticlesModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_DELETE_PARTICLES_MODIFIER_H -#define __OVITO_DELETE_PARTICLES_MODIFIER_H +#pragma once + #include #include "../ParticleModifier.h" @@ -60,4 +60,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_DELETE_PARTICLES_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/LoadTrajectoryModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/LoadTrajectoryModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/LoadTrajectoryModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/LoadTrajectoryModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -28,16 +29,16 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, LoadTrajectoryModifier, ParticleModifier); -DEFINE_FLAGS_REFERENCE_FIELD(LoadTrajectoryModifier, _trajectorySource, "TrajectorySource", DataObject, PROPERTY_FIELD_NO_SUB_ANIM); -SET_PROPERTY_FIELD_LABEL(LoadTrajectoryModifier, _trajectorySource, "Trajectory source"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(LoadTrajectoryModifier, ParticleModifier); +DEFINE_FLAGS_REFERENCE_FIELD(LoadTrajectoryModifier, trajectorySource, "TrajectorySource", DataObject, PROPERTY_FIELD_NO_SUB_ANIM); +SET_PROPERTY_FIELD_LABEL(LoadTrajectoryModifier, trajectorySource, "Trajectory source"); /****************************************************************************** * Constructs the modifier object. ******************************************************************************/ LoadTrajectoryModifier::LoadTrajectoryModifier(DataSet* dataset) : ParticleModifier(dataset) { - INIT_PROPERTY_FIELD(LoadTrajectoryModifier::_trajectorySource); + INIT_PROPERTY_FIELD(trajectorySource); // Create the file source object, which will be responsible for loading // and caching the trajectory data. @@ -59,7 +60,7 @@ throwException(tr("No trajectory data has been provided.")); // Get the trajectory frame. - PipelineFlowState trajState = trajectorySource()->evaluate(time); + PipelineFlowState trajState = trajectorySource()->evaluateImmediately(PipelineEvalRequest(time, false)); // Make sure the obtained configuration is valid and ready to use. if(trajState.status().type() == PipelineStatus::Error) { @@ -95,7 +96,7 @@ // Build particle-to-particle index map. std::vector indexToIndexMap(inputParticleCount()); ParticlePropertyObject* identifierProperty = inputStandardProperty(ParticleProperty::IdentifierProperty); - ParticlePropertyObject* trajIdentifierProperty = ParticlePropertyObject::findInState(trajState, ParticleProperty::IdentifierProperty);; + ParticlePropertyObject* trajIdentifierProperty = ParticlePropertyObject::findInState(trajState, ParticleProperty::IdentifierProperty); if(identifierProperty && trajIdentifierProperty) { // Build map of particle identifiers in trajectory dataset. @@ -139,12 +140,40 @@ std::iota(indexToIndexMap.begin(), indexToIndexMap.end(), size_t(0)); } - // Transfer particle positions. - ParticlePropertyObject* outputPosProperty = outputStandardProperty(ParticleProperty::PositionProperty); - for(size_t i = 0; i < inputParticleCount(); i++) { - outputPosProperty->setPoint3(i, trajectoryPosProperty->getPoint3(indexToIndexMap[i])); + // Transfer particle properties from the trajectory file. + for(DataObject* obj : trajState.objects()) { + ParticlePropertyObject* property = dynamic_object_cast(obj); + if(!property) + continue; + if(property->type() == ParticleProperty::IdentifierProperty) + continue; + + // Get or create the output particle property. + ParticlePropertyObject* outputProperty; + if(property->type() != ParticleProperty::UserProperty) { + outputProperty = outputStandardProperty(property->type(), true); + if(outputProperty->dataType() != property->dataType() + || outputProperty->componentCount() != property->componentCount()) + continue; // Types of source property and output property are not compatible. + } + else { + outputProperty = outputCustomProperty(property->name(), + property->dataType(), property->componentCount(), + 0, true); + } + OVITO_ASSERT(outputProperty->stride() == property->stride()); + + // Copy and reorder property data. + std::vector::const_iterator idx = indexToIndexMap.cbegin(); + char* dest = static_cast(outputProperty->data()); + const char* src = static_cast(property->constData()); + size_t stride = outputProperty->stride(); + for(size_t index = 0; index < outputProperty->size(); index++, ++idx, dest += stride) { + memcpy(dest, src + stride * (*idx), stride); + } + + outputProperty->changed(); } - outputPosProperty->changed(); // Transfer box geometry. SimulationCellObject* topologyCell = input().findObject(); @@ -158,6 +187,7 @@ // stored in wrapped coordinates, then it becomes necessary to fix bonds using the minimum image convention. std::array pbc = topologyCell->pbcFlags(); if((pbc[0] || pbc[1] || pbc[2]) && std::abs(simCell.determinant()) > FLOATTYPE_EPSILON) { + ParticlePropertyObject* outputPosProperty = outputStandardProperty(ParticleProperty::PositionProperty); AffineTransformation inverseSimCell = simCell.inverse(); for(DataObject* obj : output().objects()) { diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/LoadTrajectoryModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/LoadTrajectoryModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/LoadTrajectoryModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/LoadTrajectoryModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_LOAD_TRAJECTORY_MODIFIER_H -#define __OVITO_LOAD_TRAJECTORY_MODIFIER_H +#pragma once + #include #include @@ -37,29 +37,19 @@ /// Constructor. Q_INVOKABLE LoadTrajectoryModifier(DataSet* dataset); - /// Returns the data object that provides the particle trajectories. - DataObject* trajectorySource() const { return _trajectorySource; } - - /// Sets the object that will provide the particle trajectories. - void setTrajectorySource(DataObject* refConf) { _trajectorySource = refConf; } - protected: /// Modifies the particle object. virtual PipelineStatus modifyParticles(TimePoint time, TimeInterval& validityInterval) override; /// The source for trajectory data. - ReferenceField _trajectorySource; - -private: + DECLARE_MODIFIABLE_REFERENCE_FIELD(DataObject, trajectorySource, setTrajectorySource); Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Load trajectory"); Q_CLASSINFO("ModifierCategory", "Modification"); - - DECLARE_REFERENCE_FIELD(_trajectorySource); }; OVITO_END_INLINE_NAMESPACE @@ -67,4 +57,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_LOAD_TRAJECTORY_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/ShowPeriodicImagesModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/ShowPeriodicImagesModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/ShowPeriodicImagesModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/ShowPeriodicImagesModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,26 +26,26 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ShowPeriodicImagesModifier, ParticleModifier); -DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, _showImageX, "ShowImageX"); -DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, _showImageY, "ShowImageY"); -DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, _showImageZ, "ShowImageZ"); -DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, _numImagesX, "NumImagesX"); -DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, _numImagesY, "NumImagesY"); -DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, _numImagesZ, "NumImagesZ"); -DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, _adjustBoxSize, "AdjustBoxSize"); -DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, _uniqueIdentifiers, "UniqueIdentifiers"); -SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, _showImageX, "Periodic images X"); -SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, _showImageY, "Periodic images Y"); -SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, _showImageZ, "Periodic images Z"); -SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, _numImagesX, "Number of periodic images - X"); -SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, _numImagesY, "Number of periodic images - Y"); -SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, _numImagesZ, "Number of periodic images - Z"); -SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, _adjustBoxSize, "Adjust simulation box size"); -SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, _uniqueIdentifiers, "Assign unique particle IDs"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ShowPeriodicImagesModifier, _numImagesX, IntegerParameterUnit, 1); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ShowPeriodicImagesModifier, _numImagesY, IntegerParameterUnit, 1); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ShowPeriodicImagesModifier, _numImagesZ, IntegerParameterUnit, 1); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ShowPeriodicImagesModifier, ParticleModifier); +DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, showImageX, "ShowImageX"); +DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, showImageY, "ShowImageY"); +DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, showImageZ, "ShowImageZ"); +DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, numImagesX, "NumImagesX"); +DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, numImagesY, "NumImagesY"); +DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, numImagesZ, "NumImagesZ"); +DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, adjustBoxSize, "AdjustBoxSize"); +DEFINE_PROPERTY_FIELD(ShowPeriodicImagesModifier, uniqueIdentifiers, "UniqueIdentifiers"); +SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, showImageX, "Periodic images X"); +SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, showImageY, "Periodic images Y"); +SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, showImageZ, "Periodic images Z"); +SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, numImagesX, "Number of periodic images - X"); +SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, numImagesY, "Number of periodic images - Y"); +SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, numImagesZ, "Number of periodic images - Z"); +SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, adjustBoxSize, "Adjust simulation box size"); +SET_PROPERTY_FIELD_LABEL(ShowPeriodicImagesModifier, uniqueIdentifiers, "Assign unique particle IDs"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ShowPeriodicImagesModifier, numImagesX, IntegerParameterUnit, 1); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ShowPeriodicImagesModifier, numImagesY, IntegerParameterUnit, 1); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ShowPeriodicImagesModifier, numImagesZ, IntegerParameterUnit, 1); /****************************************************************************** * Constructs the modifier object. @@ -54,14 +54,14 @@ _showImageX(false), _showImageY(false), _showImageZ(false), _numImagesX(3), _numImagesY(3), _numImagesZ(3), _adjustBoxSize(false), _uniqueIdentifiers(true) { - INIT_PROPERTY_FIELD(ShowPeriodicImagesModifier::_showImageX); - INIT_PROPERTY_FIELD(ShowPeriodicImagesModifier::_showImageY); - INIT_PROPERTY_FIELD(ShowPeriodicImagesModifier::_showImageZ); - INIT_PROPERTY_FIELD(ShowPeriodicImagesModifier::_numImagesX); - INIT_PROPERTY_FIELD(ShowPeriodicImagesModifier::_numImagesY); - INIT_PROPERTY_FIELD(ShowPeriodicImagesModifier::_numImagesZ); - INIT_PROPERTY_FIELD(ShowPeriodicImagesModifier::_adjustBoxSize); - INIT_PROPERTY_FIELD(ShowPeriodicImagesModifier::_uniqueIdentifiers); + INIT_PROPERTY_FIELD(showImageX); + INIT_PROPERTY_FIELD(showImageY); + INIT_PROPERTY_FIELD(showImageZ); + INIT_PROPERTY_FIELD(numImagesX); + INIT_PROPERTY_FIELD(numImagesY); + INIT_PROPERTY_FIELD(numImagesZ); + INIT_PROPERTY_FIELD(adjustBoxSize); + INIT_PROPERTY_FIELD(uniqueIdentifiers); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/ShowPeriodicImagesModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/ShowPeriodicImagesModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/ShowPeriodicImagesModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/ShowPeriodicImagesModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SHOW_PERIODIC_IMAGES_MODIFIER_H -#define __OVITO_SHOW_PERIODIC_IMAGES_MODIFIER_H +#pragma once + #include #include "../ParticleModifier.h" @@ -40,54 +40,6 @@ /// \brief Constructs a new instance of this class. Q_INVOKABLE ShowPeriodicImagesModifier(DataSet* dataset); - /// Returns whether periodic images are created in the X direction. - bool showImageX() const { return _showImageX; } - - /// Returns whether periodic images are created in the Y direction. - bool showImageY() const { return _showImageY; } - - /// Returns whether periodic images are created in the Z direction. - bool showImageZ() const { return _showImageZ; } - - /// Controls whether periodic images should be created in the X direction. - void setShowImageX(bool createImages) { _showImageX = createImages; } - - /// Controls whether periodic images should be created in the Y direction. - void setShowImageY(bool createImages) { _showImageY = createImages; } - - /// Controls whether periodic images should be created in the Z direction. - void setShowImageZ(bool createImages) { _showImageZ = createImages; } - - /// Returns the number of periodic images to be created in the X direction. - int numImagesX() const { return _numImagesX; } - - /// Returns the number of periodic images to be created in the Y direction. - int numImagesY() const { return _numImagesY; } - - /// Returns the number of periodic images to be created in the Z direction. - int numImagesZ() const { return _numImagesZ; } - - /// Sets the number of periodic images to be created in the X direction. - void setNumImagesX(int n) { _numImagesX = n; } - - /// Sets the number of periodic images to be created in the Y direction. - void setNumImagesY(int n) { _numImagesY = n; } - - /// Sets the number of periodic images to be created in the Z direction. - void setNumImagesZ(int n) { _numImagesZ = n; } - - /// Returns whether the size of the simulation box is adjusted. - bool adjustBoxSize() const { return _adjustBoxSize; } - - /// Sets whether the size of the simulation box should be adjusted. - void setAdjustBoxSize(bool adjust) { _adjustBoxSize = adjust; } - - /// Returns whether the modifier assigns unique identifiers to particle copies. - bool uniqueIdentifiers() const { return _uniqueIdentifiers; } - - /// Sets whether the the modifier assigns unique identifiers to particle copies. - void setUniqueIdentifiers(bool uniqueIdentifiers) { _uniqueIdentifiers = uniqueIdentifiers; } - protected: /// Modifies the particle object. The time interval passed @@ -97,41 +49,30 @@ private: /// Controls whether the periodic images are shown in the X direction. - PropertyField _showImageX; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, showImageX, setShowImageX); /// Controls whether the periodic images are shown in the Y direction. - PropertyField _showImageY; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, showImageY, setShowImageY); /// Controls whether the periodic images are shown in the Z direction. - PropertyField _showImageZ; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, showImageZ, setShowImageZ); /// Controls the number of periodic images shown in the X direction. - PropertyField _numImagesX; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, numImagesX, setNumImagesX); /// Controls the number of periodic images shown in the Y direction. - PropertyField _numImagesY; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, numImagesY, setNumImagesY); /// Controls the number of periodic images shown in the Z direction. - PropertyField _numImagesZ; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, numImagesZ, setNumImagesZ); /// Controls whether the size of the simulation box is adjusted to the extended system. - PropertyField _adjustBoxSize; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, adjustBoxSize, setAdjustBoxSize); /// Controls whether the modifier assigns unique identifiers to particle copies. - PropertyField _uniqueIdentifiers; - -private: + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, uniqueIdentifiers, setUniqueIdentifiers); Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Show periodic images"); Q_CLASSINFO("ModifierCategory", "Modification"); - - DECLARE_PROPERTY_FIELD(_showImageX); - DECLARE_PROPERTY_FIELD(_showImageY); - DECLARE_PROPERTY_FIELD(_showImageZ); - DECLARE_PROPERTY_FIELD(_numImagesX); - DECLARE_PROPERTY_FIELD(_numImagesY); - DECLARE_PROPERTY_FIELD(_numImagesZ); - DECLARE_PROPERTY_FIELD(_adjustBoxSize); - DECLARE_PROPERTY_FIELD(_uniqueIdentifiers); }; OVITO_END_INLINE_NAMESPACE @@ -139,4 +80,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SHOW_PERIODIC_IMAGES_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/SliceModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/SliceModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/SliceModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/SliceModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -33,24 +33,24 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, SliceModifier, ParticleModifier); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, SliceModifierFunction, RefTarget); -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, SliceParticlesFunction, SliceModifierFunction); -DEFINE_REFERENCE_FIELD(SliceModifier, _normalCtrl, "PlaneNormal", Controller); -DEFINE_REFERENCE_FIELD(SliceModifier, _distanceCtrl, "PlaneDistance", Controller); -DEFINE_REFERENCE_FIELD(SliceModifier, _widthCtrl, "SliceWidth", Controller); -DEFINE_PROPERTY_FIELD(SliceModifier, _createSelection, "CreateSelection"); -DEFINE_PROPERTY_FIELD(SliceModifier, _inverse, "Inverse"); -DEFINE_PROPERTY_FIELD(SliceModifier, _applyToSelection, "ApplyToSelection"); -SET_PROPERTY_FIELD_LABEL(SliceModifier, _normalCtrl, "Normal"); -SET_PROPERTY_FIELD_LABEL(SliceModifier, _distanceCtrl, "Distance"); -SET_PROPERTY_FIELD_LABEL(SliceModifier, _widthCtrl, "Slice width"); -SET_PROPERTY_FIELD_LABEL(SliceModifier, _createSelection, "Create selection (do not delete)"); -SET_PROPERTY_FIELD_LABEL(SliceModifier, _inverse, "Reverse orientation"); -SET_PROPERTY_FIELD_LABEL(SliceModifier, _applyToSelection, "Apply to selection only"); -SET_PROPERTY_FIELD_UNITS(SliceModifier, _normalCtrl, WorldParameterUnit); -SET_PROPERTY_FIELD_UNITS(SliceModifier, _distanceCtrl, WorldParameterUnit); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(SliceModifier, _widthCtrl, WorldParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SliceModifier, ParticleModifier); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SliceModifierFunction, RefTarget); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SliceParticlesFunction, SliceModifierFunction); +DEFINE_REFERENCE_FIELD(SliceModifier, normalController, "PlaneNormal", Controller); +DEFINE_REFERENCE_FIELD(SliceModifier, distanceController, "PlaneDistance", Controller); +DEFINE_REFERENCE_FIELD(SliceModifier, widthController, "SliceWidth", Controller); +DEFINE_PROPERTY_FIELD(SliceModifier, createSelection, "CreateSelection"); +DEFINE_PROPERTY_FIELD(SliceModifier, inverse, "Inverse"); +DEFINE_PROPERTY_FIELD(SliceModifier, applyToSelection, "ApplyToSelection"); +SET_PROPERTY_FIELD_LABEL(SliceModifier, normalController, "Normal"); +SET_PROPERTY_FIELD_LABEL(SliceModifier, distanceController, "Distance"); +SET_PROPERTY_FIELD_LABEL(SliceModifier, widthController, "Slice width"); +SET_PROPERTY_FIELD_LABEL(SliceModifier, createSelection, "Create selection (do not delete)"); +SET_PROPERTY_FIELD_LABEL(SliceModifier, inverse, "Reverse orientation"); +SET_PROPERTY_FIELD_LABEL(SliceModifier, applyToSelection, "Apply to selection only"); +SET_PROPERTY_FIELD_UNITS(SliceModifier, normalController, WorldParameterUnit); +SET_PROPERTY_FIELD_UNITS(SliceModifier, distanceController, WorldParameterUnit); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(SliceModifier, widthController, WorldParameterUnit, 0); /****************************************************************************** * Constructs the modifier object. @@ -60,17 +60,17 @@ _inverse(false), _applyToSelection(false) { - INIT_PROPERTY_FIELD(SliceModifier::_normalCtrl); - INIT_PROPERTY_FIELD(SliceModifier::_distanceCtrl); - INIT_PROPERTY_FIELD(SliceModifier::_widthCtrl); - INIT_PROPERTY_FIELD(SliceModifier::_createSelection); - INIT_PROPERTY_FIELD(SliceModifier::_inverse); - INIT_PROPERTY_FIELD(SliceModifier::_applyToSelection); - - _normalCtrl = ControllerManager::instance().createVector3Controller(dataset); - _distanceCtrl = ControllerManager::instance().createFloatController(dataset); - _widthCtrl = ControllerManager::instance().createFloatController(dataset); - if(_normalCtrl) _normalCtrl->setVector3Value(0, Vector3(1,0,0)); + INIT_PROPERTY_FIELD(normalController); + INIT_PROPERTY_FIELD(distanceController); + INIT_PROPERTY_FIELD(widthController); + INIT_PROPERTY_FIELD(createSelection); + INIT_PROPERTY_FIELD(inverse); + INIT_PROPERTY_FIELD(applyToSelection); + + setNormalController(ControllerManager::createVector3Controller(dataset)); + setDistanceController(ControllerManager::createFloatController(dataset)); + setWidthController(ControllerManager::createFloatController(dataset)); + if(normalController()) normalController()->setVector3Value(0, Vector3(1,0,0)); } /****************************************************************************** @@ -79,9 +79,9 @@ TimeInterval SliceModifier::modifierValidity(TimePoint time) { TimeInterval interval = ParticleModifier::modifierValidity(time); - interval.intersect(_normalCtrl->validityInterval(time)); - interval.intersect(_distanceCtrl->validityInterval(time)); - interval.intersect(_widthCtrl->validityInterval(time)); + if(normalController()) interval.intersect(normalController()->validityInterval(time)); + if(distanceController()) interval.intersect(distanceController()->validityInterval(time)); + if(widthController()) interval.intersect(widthController()->validityInterval(time)); return interval; } @@ -110,10 +110,10 @@ Plane3 SliceModifier::slicingPlane(TimePoint time, TimeInterval& validityInterval) { Plane3 plane; - _normalCtrl->getVector3Value(time, plane.normal, validityInterval); + if(normalController()) normalController()->getVector3Value(time, plane.normal, validityInterval); if(plane.normal == Vector3::Zero()) plane.normal = Vector3(0,0,1); else plane.normal.normalize(); - plane.dist = _distanceCtrl->getFloatValue(time, validityInterval); + if(distanceController()) plane.dist = distanceController()->getFloatValue(time, validityInterval); if(inverse()) return -plane; else @@ -127,7 +127,7 @@ { // Retrieve modifier parameters. FloatType sliceWidth = 0; - if(_widthCtrl) sliceWidth = _widthCtrl->getFloatValue(time, validityInterval); + if(widthController()) sliceWidth = widthController()->getFloatValue(time, validityInterval); Plane3 plane = slicingPlane(time, validityInterval); // Apply all registered and activated slice functions to the input data. @@ -287,7 +287,7 @@ Plane3 plane = slicingPlane(time, interval); FloatType sliceWidth = 0; - if(_widthCtrl) sliceWidth = _widthCtrl->getFloatValue(time, interval); + if(widthController()) sliceWidth = widthController()->getFloatValue(time, interval); ColorA color(0.8f, 0.3f, 0.3f); if(sliceWidth <= 0) { diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/SliceModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/SliceModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/SliceModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/SliceModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SLICE_MODIFIER_H -#define __OVITO_SLICE_MODIFIER_H +#pragma once + #include #include @@ -53,58 +53,22 @@ // Property access functions: /// Returns the plane's distance from the origin. - FloatType distance() const { return _distanceCtrl ? _distanceCtrl->currentFloatValue() : 0.0f; } + FloatType distance() const { return distanceController() ? distanceController()->currentFloatValue() : 0.0f; } /// Sets the plane's distance from the origin. - void setDistance(FloatType newDistance) { if(_distanceCtrl) _distanceCtrl->setCurrentFloatValue(newDistance); } - - /// Returns the controller for the plane distance. - Controller* distanceController() const { return _distanceCtrl; } - - /// Sets the controller for the plane distance. - void setDistanceController(Controller* ctrl) { _distanceCtrl = ctrl; } + void setDistance(FloatType newDistance) { if(distanceController()) distanceController()->setCurrentFloatValue(newDistance); } /// Returns the plane's normal vector. - Vector3 normal() const { return _normalCtrl ? _normalCtrl->currentVector3Value() : Vector3(0,0,1); } + Vector3 normal() const { return normalController() ? normalController()->currentVector3Value() : Vector3(0,0,1); } /// Sets the plane's distance from the origin. - void setNormal(const Vector3& newNormal) { if(_normalCtrl) _normalCtrl->setCurrentVector3Value(newNormal); } - - /// Returns the controller for the plane normal. - Controller* normalController() const { return _normalCtrl; } - - /// Sets the controller for the plane normal. - void setNormalController(Controller* ctrl) { _normalCtrl = ctrl; } + void setNormal(const Vector3& newNormal) { if(normalController()) normalController()->setCurrentVector3Value(newNormal); } /// Returns the slice width. - FloatType sliceWidth() const { return _widthCtrl ? _widthCtrl->currentFloatValue() : 0.0f; } + FloatType sliceWidth() const { return widthController() ? widthController()->currentFloatValue() : 0.0f; } /// Sets the slice width. - void setSliceWidth(FloatType newWidth) { if(_widthCtrl) _widthCtrl->setCurrentFloatValue(newWidth); } - - /// Returns the controller for the slice width. - Controller* sliceWidthController() const { return _widthCtrl; } - - /// Sets the controller for the slice width. - void setSliceWidthController(Controller* ctrl) { _widthCtrl = ctrl; } - - /// Returns whether the plane's orientation should be flipped. - bool inverse() const { return _inverse; } - - /// Sets whether the plane's orientation should be flipped. - void setInverse(bool inverse) { _inverse = inverse; } - - /// Returns whether the atoms are only selected instead of deleted. - bool createSelection() const { return _createSelection; } - - /// Sets whether the atoms are only selected instead of deleted. - void setCreateSelection(bool select) { _createSelection = select; } - - /// Returns whether the modifier is only applied to the currently selected atoms. - bool applyToSelection() const { return _applyToSelection; } - - /// Sets whether the modifier should only be applied to the currently selected atoms. - void setApplyToSelection(bool flag) { _applyToSelection = flag; } + void setSliceWidth(FloatType newWidth) { if(widthController()) widthController()->setCurrentFloatValue(newWidth); } /// Returns the slicing plane. Plane3 slicingPlane(TimePoint time, TimeInterval& validityInterval); @@ -127,37 +91,28 @@ void planeQuadIntersection(const Point3 corners[8], const std::array& quadVerts, const Plane3& plane, QVector& vertices) const; /// This controller stores the normal of the slicing plane. - ReferenceField _normalCtrl; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, normalController, setNormalController); /// This controller stores the distance of the slicing plane from the origin. - ReferenceField _distanceCtrl; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, distanceController, setDistanceController); /// Controls the slice width. - ReferenceField _widthCtrl; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, widthController, setWidthController); /// Controls whether the atoms should only be selected instead of deleted. - PropertyField _createSelection; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, createSelection, setCreateSelection); /// Controls whether the selection/plane orientation should be inverted. - PropertyField _inverse; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, inverse, setInverse); /// Controls whether the modifier should only be applied to the currently selected atoms. - PropertyField _applyToSelection; - -private: + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, applyToSelection, setApplyToSelection); Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Slice"); Q_CLASSINFO("ModifierCategory", "Modification"); - - DECLARE_REFERENCE_FIELD(_normalCtrl); - DECLARE_REFERENCE_FIELD(_distanceCtrl); - DECLARE_REFERENCE_FIELD(_widthCtrl); - DECLARE_PROPERTY_FIELD(_createSelection); - DECLARE_PROPERTY_FIELD(_inverse); - DECLARE_PROPERTY_FIELD(_applyToSelection); }; /** @@ -213,4 +168,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SLICE_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/WrapPeriodicImagesModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/WrapPeriodicImagesModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/WrapPeriodicImagesModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/WrapPeriodicImagesModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Modify) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, WrapPeriodicImagesModifier, ParticleModifier); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(WrapPeriodicImagesModifier, ParticleModifier); /****************************************************************************** * Constructs the modifier object. @@ -70,6 +70,8 @@ // Wrap bonds by adjusting their shift vectors. for(Bond& bond : *bondsObj->modifiableStorage()) { + if(bond.index1 >= posProperty->size() || bond.index2 >= posProperty->size()) + continue; const Point3& p1 = posProperty->getPoint3(bond.index1); const Point3& p2 = posProperty->getPoint3(bond.index2); for(size_t dim = 0; dim < 3; dim++) { diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/WrapPeriodicImagesModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/WrapPeriodicImagesModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/modify/WrapPeriodicImagesModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/modify/WrapPeriodicImagesModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_WRAP_PERIODIC_IMAGES_MODIFIER_H -#define __OVITO_WRAP_PERIODIC_IMAGES_MODIFIER_H +#pragma once + #include #include "../ParticleModifier.h" @@ -61,4 +61,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_WRAP_PERIODIC_IMAGES_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/ParticleModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/ParticleModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/ParticleModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/ParticleModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -32,7 +32,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ParticleModifier, Modifier); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ParticleModifier, Modifier); /****************************************************************************** * This modifies the input object. @@ -81,6 +81,10 @@ status = PipelineStatus(PipelineStatus::Error, ex.messages().join('\n')); state.intersectStateValidity(TimeInterval(time)); } + catch(const std::bad_alloc&) { + status = PipelineStatus(PipelineStatus::Error, tr("Not enough memory to execute this modifier.")); + state.intersectStateValidity(TimeInterval(time)); + } catch(const PipelineStatus& thrown_status) { // Transfer exception message to evaluation status. status = thrown_status; @@ -124,7 +128,7 @@ Modifier::propertyChanged(field); // Clear status when modifier is disabled. - if(field == PROPERTY_FIELD(Modifier::_isEnabled) && !isEnabled()) + if(field == PROPERTY_FIELD(Modifier::isEnabled) && !isEnabled()) setStatus(PipelineStatus(PipelineStatus::Success, tr("Modifier is currently disabled."))); } @@ -167,9 +171,9 @@ } /****************************************************************************** -* Returns the given standard channel from the input object. -* The returned channel may not be modified. If they input object does -* not contain the standard channel then an exception is thrown. +* Returns the given standard particle property from the input object. +* The returned property may not be modified. If they input object does +* not contain the standard property then an exception is thrown. ******************************************************************************/ ParticlePropertyObject* ParticleModifier::expectStandardProperty(ParticleProperty::Type which) const { @@ -182,6 +186,23 @@ } return property; } + +/****************************************************************************** +* Returns the given standard bond property from the input object. +* The returned property may not be modified. If they input object does +* not contain the standard property then an exception is thrown. +******************************************************************************/ +BondPropertyObject* ParticleModifier::expectStandardBondProperty(BondProperty::Type which) const +{ + BondPropertyObject* property = inputStandardBondProperty(which); + if(!property) { + if(which == BondProperty::SelectionProperty) + throwException(tr("No bond selection has been defined. Please select some bonds first.")); + else + throwException(tr("The modifier cannot be evaluated because the input does not contain the required bond property '%1'.").arg(BondProperty::standardPropertyName(which))); + } + return property; +} /****************************************************************************** * Returns the input simulation cell. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/ParticleModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/ParticleModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/ParticleModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/ParticleModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_MODIFIER_H -#define __OVITO_PARTICLE_MODIFIER_H +#pragma once + #include #include @@ -62,11 +62,16 @@ /// The returned property may be NULL if it does not exist. BondPropertyObject* inputStandardBondProperty(BondProperty::Type which) const; - /// Returns the given standard property from the input object. + /// Returns the given standard particle property from the input object. /// The returned property may not be modified. If the input object does /// not contain the standard property then an exception is thrown. ParticlePropertyObject* expectStandardProperty(ParticleProperty::Type which) const; + /// Returns the given standard bond property from the input object. + /// The returned property may not be modified. If the input object does + /// not contain the standard property then an exception is thrown. + BondPropertyObject* expectStandardBondProperty(BondProperty::Type which) const; + /// Returns the property with the given name from the input particles. /// The returned property may not be modified. If the input object does /// not contain a property with the given name and data type, then an exception is thrown. @@ -213,8 +218,6 @@ /// The status returned by the modifier. PipelineStatus _modifierStatus; -private: - Q_OBJECT OVITO_OBJECT }; @@ -223,4 +226,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/properties/ComputeBondLengthsModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/properties/ComputeBondLengthsModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/properties/ComputeBondLengthsModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/properties/ComputeBondLengthsModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Properties) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ComputeBondLengthsModifier, ParticleModifier); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ComputeBondLengthsModifier, ParticleModifier); /****************************************************************************** * Constructs the modifier object. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/properties/ComputeBondLengthsModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/properties/ComputeBondLengthsModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/properties/ComputeBondLengthsModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/properties/ComputeBondLengthsModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COMPUTE_BOND_LENGTHS_MODIFIER_H -#define __OVITO_COMPUTE_BOND_LENGTHS_MODIFIER_H +#pragma once + #include #include "../ParticleModifier.h" @@ -60,4 +60,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_COMPUTE_BOND_LENGTHS_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/properties/ComputePropertyModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/properties/ComputePropertyModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/properties/ComputePropertyModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/properties/ComputePropertyModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,21 +28,21 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Properties) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ComputePropertyModifier, AsynchronousParticleModifier); -DEFINE_PROPERTY_FIELD(ComputePropertyModifier, _expressions, "Expressions"); -DEFINE_PROPERTY_FIELD(ComputePropertyModifier, _outputProperty, "OutputProperty"); -DEFINE_PROPERTY_FIELD(ComputePropertyModifier, _onlySelectedParticles, "OnlySelectedParticles"); -DEFINE_PROPERTY_FIELD(ComputePropertyModifier, _neighborModeEnabled, "NeighborModeEnabled"); -DEFINE_PROPERTY_FIELD(ComputePropertyModifier, _neighborExpressions, "NeighborExpressions"); -DEFINE_FLAGS_PROPERTY_FIELD(ComputePropertyModifier, _cutoff, "Cutoff", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(ComputePropertyModifier, _cachedDisplayObjects, "CachedDisplayObjects", DisplayObject, PROPERTY_FIELD_NEVER_CLONE_TARGET|PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_NO_UNDO|PROPERTY_FIELD_NO_SUB_ANIM); -SET_PROPERTY_FIELD_LABEL(ComputePropertyModifier, _expressions, "Expressions"); -SET_PROPERTY_FIELD_LABEL(ComputePropertyModifier, _outputProperty, "Output property"); -SET_PROPERTY_FIELD_LABEL(ComputePropertyModifier, _onlySelectedParticles, "Compute only for selected particles"); -SET_PROPERTY_FIELD_LABEL(ComputePropertyModifier, _neighborModeEnabled, "Include neighbor terms"); -SET_PROPERTY_FIELD_LABEL(ComputePropertyModifier, _neighborExpressions, "Neighbor expressions"); -SET_PROPERTY_FIELD_LABEL(ComputePropertyModifier, _cutoff, "Cutoff radius"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ComputePropertyModifier, _cutoff, WorldParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ComputePropertyModifier, AsynchronousParticleModifier); +DEFINE_PROPERTY_FIELD(ComputePropertyModifier, expressions, "Expressions"); +DEFINE_PROPERTY_FIELD(ComputePropertyModifier, outputProperty, "OutputProperty"); +DEFINE_PROPERTY_FIELD(ComputePropertyModifier, onlySelectedParticles, "OnlySelectedParticles"); +DEFINE_PROPERTY_FIELD(ComputePropertyModifier, neighborModeEnabled, "NeighborModeEnabled"); +DEFINE_PROPERTY_FIELD(ComputePropertyModifier, neighborExpressions, "NeighborExpressions"); +DEFINE_FLAGS_PROPERTY_FIELD(ComputePropertyModifier, cutoff, "Cutoff", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(ComputePropertyModifier, cachedDisplayObjects, "CachedDisplayObjects", DisplayObject, PROPERTY_FIELD_NEVER_CLONE_TARGET|PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_NO_UNDO|PROPERTY_FIELD_NO_SUB_ANIM); +SET_PROPERTY_FIELD_LABEL(ComputePropertyModifier, expressions, "Expressions"); +SET_PROPERTY_FIELD_LABEL(ComputePropertyModifier, outputProperty, "Output property"); +SET_PROPERTY_FIELD_LABEL(ComputePropertyModifier, onlySelectedParticles, "Compute only for selected particles"); +SET_PROPERTY_FIELD_LABEL(ComputePropertyModifier, neighborModeEnabled, "Include neighbor terms"); +SET_PROPERTY_FIELD_LABEL(ComputePropertyModifier, neighborExpressions, "Neighbor expressions"); +SET_PROPERTY_FIELD_LABEL(ComputePropertyModifier, cutoff, "Cutoff radius"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ComputePropertyModifier, cutoff, WorldParameterUnit, 0); /****************************************************************************** * Constructs a new instance of this class. @@ -51,13 +51,13 @@ _outputProperty(tr("My property")), _expressions(QStringList("0")), _onlySelectedParticles(false), _neighborExpressions(QStringList("0")), _cutoff(3), _neighborModeEnabled(false) { - INIT_PROPERTY_FIELD(ComputePropertyModifier::_expressions); - INIT_PROPERTY_FIELD(ComputePropertyModifier::_onlySelectedParticles); - INIT_PROPERTY_FIELD(ComputePropertyModifier::_outputProperty); - INIT_PROPERTY_FIELD(ComputePropertyModifier::_neighborModeEnabled); - INIT_PROPERTY_FIELD(ComputePropertyModifier::_cutoff); - INIT_PROPERTY_FIELD(ComputePropertyModifier::_neighborExpressions); - INIT_PROPERTY_FIELD(ComputePropertyModifier::_cachedDisplayObjects); + INIT_PROPERTY_FIELD(expressions); + INIT_PROPERTY_FIELD(onlySelectedParticles); + INIT_PROPERTY_FIELD(outputProperty); + INIT_PROPERTY_FIELD(neighborModeEnabled); + INIT_PROPERTY_FIELD(cutoff); + INIT_PROPERTY_FIELD(neighborExpressions); + INIT_PROPERTY_FIELD(cachedDisplayObjects); } /****************************************************************************** @@ -108,7 +108,7 @@ ******************************************************************************/ void ComputePropertyModifier::propertyChanged(const PropertyFieldDescriptor& field) { - if(field == PROPERTY_FIELD(ComputePropertyModifier::_outputProperty)) { + if(field == PROPERTY_FIELD(outputProperty)) { if(outputProperty().type() != ParticleProperty::UserProperty) setPropertyComponentCount(ParticleProperty::standardPropertyComponentCount(outputProperty().type())); else @@ -118,12 +118,12 @@ AsynchronousParticleModifier::propertyChanged(field); // Throw away cached results if parameters change. - if(field == PROPERTY_FIELD(ComputePropertyModifier::_expressions) || - field == PROPERTY_FIELD(ComputePropertyModifier::_neighborExpressions) || - field == PROPERTY_FIELD(ComputePropertyModifier::_onlySelectedParticles) || - field == PROPERTY_FIELD(ComputePropertyModifier::_neighborModeEnabled) || - field == PROPERTY_FIELD(ComputePropertyModifier::_outputProperty) || - field == PROPERTY_FIELD(ComputePropertyModifier::_cutoff)) + if(field == PROPERTY_FIELD(expressions) || + field == PROPERTY_FIELD(neighborExpressions) || + field == PROPERTY_FIELD(onlySelectedParticles) || + field == PROPERTY_FIELD(neighborModeEnabled) || + field == PROPERTY_FIELD(outputProperty) || + field == PROPERTY_FIELD(cutoff)) invalidateCachedResults(); } @@ -291,14 +291,15 @@ CutoffNeighborFinder neighborFinder; if(neighborMode()) { // Prepare the neighbor list. - if(!neighborFinder.prepare(_cutoff, positions(), cell(), nullptr, this)) + if(!neighborFinder.prepare(_cutoff, positions(), cell(), nullptr, *this)) return; } - // Parallelized loop over all particles. - setProgressRange(positions()->size()); setProgressValue(0); - parallelForChunks(positions()->size(), *this, [this, &neighborFinder](size_t startIndex, size_t count, FutureInterfaceBase& futureInterface) { + setProgressMaximum(positions()->size()); + + // Parallelized loop over all particles. + parallelForChunks(positions()->size(), *this, [this, &neighborFinder](size_t startIndex, size_t count, PromiseBase& promise) { ParticleExpressionEvaluator::Worker worker(_evaluator); ParticleExpressionEvaluator::Worker neighborWorker(_neighborEvaluator); @@ -326,10 +327,10 @@ // Update progress indicator. if((particleIndex % 1024) == 0) - futureInterface.incrementProgressValue(1024); + promise.incrementProgressValue(1024); // Stop loop if canceled. - if(futureInterface.isCanceled()) + if(promise.isCanceled()) return; // Skip unselected particles if requested. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/properties/ComputePropertyModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/properties/ComputePropertyModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/properties/ComputePropertyModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/properties/ComputePropertyModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_COMPUTE_PROPERTY_MODIFIER_H -#define __OVITO_COMPUTE_PROPERTY_MODIFIER_H +#pragma once + #include #include @@ -38,15 +38,6 @@ /// \brief Constructs a new instance of this class. Q_INVOKABLE ComputePropertyModifier(DataSet* dataset); - /// \brief Sets the math expressions that are used to calculate the values of the new property's components. - /// \param expressions The mathematical formulas, one for each component of the property to create. - /// \undoable - void setExpressions(const QStringList& expressions) { _expressions = expressions; } - - /// \brief Returns the math expressions that are used to calculate the values of the new property's component. - /// \return The math formulas. - const QStringList& expressions() const { return _expressions; } - /// \brief Sets the math expression that is used to calculate the values of one of the new property's components. /// \param index The property component for which the expression should be set. /// \param expression The math formula. @@ -69,12 +60,6 @@ return expressions()[index]; } - /// \brief Sets the output particle property that receives the computed per-particle values. - void setOutputProperty(const ParticlePropertyReference& prop) { _outputProperty = prop; } - - /// \brief Returns the output particle property that receives the computed per-particle values. - const ParticlePropertyReference& outputProperty() const { return _outputProperty; } - /// \brief Returns the number of vector components of the property to create. /// \return The number of vector components. /// \sa setPropertyComponentCount() @@ -85,36 +70,6 @@ /// \undoable void setPropertyComponentCount(int newComponentCount); - /// \brief Returns whether the math expression is only evaluated for selected particles. - /// \return \c true if the expression is only evaluated for selected particles; \c false if it is calculated for all particles. - bool onlySelectedParticles() const { return _onlySelectedParticles; } - - /// \brief Sets whether the math expression is only evaluated for selected particles. - /// \param enable Specifies the restriction to selected particles. - /// \undoable - void setOnlySelectedParticles(bool enable) { _onlySelectedParticles = enable; } - - /// Returns whether the contributions from neighbor terms are included in the computation. - bool neighborModeEnabled() const { return _neighborModeEnabled; } - - /// Sets whether the contributions from neighbor terms are included in the computation. - void setNeighborModeEnabled(bool enable) { _neighborModeEnabled = enable; } - - /// Returns the cutoff radius used to build the neighbor lists for the computation. - FloatType cutoff() const { return _cutoff; } - - /// \brief Sets the cutoff radius used to build the neighbor lists for the computation. - void setCutoff(FloatType newCutoff) { _cutoff = newCutoff; } - - /// \brief Sets the math expressions that are used to compute the neighbor-terms of the property function. - /// \param expressions The formulas, one for each component of the property to create. - /// \undoable - void setNeighborExpressions(const QStringList& expressions) { _neighborExpressions = expressions; } - - /// \brief Returns the math expressions that are used to compute the neighbor-terms of the property function. - /// \return The math formulas. - const QStringList& neighborExpressions() const { return _neighborExpressions; } - /// \brief Sets the math expression that is used to compute the neighbor-terms of the property function. /// \param index The property component for which the expression should be set. /// \param expression The math formula. @@ -235,22 +190,22 @@ }; /// The math expressions for calculating the property values. One for every vector component. - PropertyField _expressions; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QStringList, expressions, setExpressions); /// Specifies the output property that will receive the computed per-particles values. - PropertyField _outputProperty; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ParticlePropertyReference, outputProperty, setOutputProperty); /// Controls whether the math expression is evaluated and output only for selected particles. - PropertyField _onlySelectedParticles; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, onlySelectedParticles, setOnlySelectedParticles); /// Controls whether the contributions from neighbor terms are included in the computation. - PropertyField _neighborModeEnabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, neighborModeEnabled, setNeighborModeEnabled); /// The math expressions for calculating the neighbor-terms of the property function. - PropertyField _neighborExpressions; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QStringList, neighborExpressions, setNeighborExpressions); /// Controls the cutoff radius for the neighbor lists. - PropertyField _cutoff; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, cutoff, setCutoff); /// The list of input variables during the last evaluation. QStringList _inputVariableNames; @@ -262,7 +217,7 @@ QExplicitlySharedDataPointer _computedProperty; /// The cached display objects that are attached to the output particle property. - VectorReferenceField _cachedDisplayObjects; + DECLARE_VECTOR_REFERENCE_FIELD(DisplayObject, cachedDisplayObjects); private: @@ -272,14 +227,6 @@ Q_CLASSINFO("DisplayName", "Compute property"); Q_CLASSINFO("ModifierCategory", "Modification"); Q_CLASSINFO("ClassNameAlias", "CreateExpressionPropertyModifier"); // This for backward compatibility with files written by Ovito 2.4 and older. - - DECLARE_PROPERTY_FIELD(_expressions); - DECLARE_PROPERTY_FIELD(_outputProperty); - DECLARE_PROPERTY_FIELD(_onlySelectedParticles); - DECLARE_PROPERTY_FIELD(_neighborModeEnabled); - DECLARE_PROPERTY_FIELD(_neighborExpressions); - DECLARE_PROPERTY_FIELD(_cutoff); - DECLARE_VECTOR_REFERENCE_FIELD(_cachedDisplayObjects); }; OVITO_END_INLINE_NAMESPACE @@ -287,4 +234,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_COMPUTE_PROPERTY_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/properties/FreezePropertyModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/properties/FreezePropertyModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/properties/FreezePropertyModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/properties/FreezePropertyModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,21 +22,23 @@ #include #include #include +#include +#include #include "FreezePropertyModifier.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Properties) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, FreezePropertyModifier, ParticleModifier); -DEFINE_PROPERTY_FIELD(FreezePropertyModifier, _sourceProperty, "SourceProperty"); -DEFINE_PROPERTY_FIELD(FreezePropertyModifier, _destinationProperty, "DestinationProperty"); -DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(FreezePropertyModifier, _cachedDisplayObjects, "CachedDisplayObjects", DisplayObject, PROPERTY_FIELD_NEVER_CLONE_TARGET|PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_NO_UNDO|PROPERTY_FIELD_NO_SUB_ANIM); -SET_PROPERTY_FIELD_LABEL(FreezePropertyModifier, _sourceProperty, "Property"); -SET_PROPERTY_FIELD_LABEL(FreezePropertyModifier, _destinationProperty, "Destination property"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(FreezePropertyModifier, ParticleModifier); +DEFINE_PROPERTY_FIELD(FreezePropertyModifier, sourceProperty, "SourceProperty"); +DEFINE_PROPERTY_FIELD(FreezePropertyModifier, destinationProperty, "DestinationProperty"); +DEFINE_FLAGS_VECTOR_REFERENCE_FIELD(FreezePropertyModifier, cachedDisplayObjects, "CachedDisplayObjects", DisplayObject, PROPERTY_FIELD_NEVER_CLONE_TARGET|PROPERTY_FIELD_NO_CHANGE_MESSAGE|PROPERTY_FIELD_NO_UNDO|PROPERTY_FIELD_NO_SUB_ANIM); +SET_PROPERTY_FIELD_LABEL(FreezePropertyModifier, sourceProperty, "Property"); +SET_PROPERTY_FIELD_LABEL(FreezePropertyModifier, destinationProperty, "Destination property"); OVITO_BEGIN_INLINE_NAMESPACE(Internal) - IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, SavedParticleProperty, RefTarget); - DEFINE_REFERENCE_FIELD(SavedParticleProperty, _property, "Property", ParticlePropertyObject); - DEFINE_REFERENCE_FIELD(SavedParticleProperty, _identifiers, "Identifiers", ParticlePropertyObject); + IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SavedParticleProperty, RefTarget); + DEFINE_REFERENCE_FIELD(SavedParticleProperty, property, "Property", ParticlePropertyObject); + DEFINE_REFERENCE_FIELD(SavedParticleProperty, identifiers, "Identifiers", ParticlePropertyObject); OVITO_END_INLINE_NAMESPACE /****************************************************************************** @@ -44,9 +46,9 @@ ******************************************************************************/ FreezePropertyModifier::FreezePropertyModifier(DataSet* dataset) : ParticleModifier(dataset) { - INIT_PROPERTY_FIELD(FreezePropertyModifier::_sourceProperty); - INIT_PROPERTY_FIELD(FreezePropertyModifier::_destinationProperty); - INIT_PROPERTY_FIELD(FreezePropertyModifier::_cachedDisplayObjects); + INIT_PROPERTY_FIELD(sourceProperty); + INIT_PROPERTY_FIELD(destinationProperty); + INIT_PROPERTY_FIELD(cachedDisplayObjects); } /****************************************************************************** @@ -177,7 +179,8 @@ } /****************************************************************************** -* Takes a snapshot of the source property for a specific ModifierApplication. +* Takes a snapshot of the source property for a specific ModifierApplication +* of this modifier. ******************************************************************************/ void FreezePropertyModifier::takePropertySnapshot(ModifierApplication* modApp, const PipelineFlowState& state) { @@ -196,19 +199,27 @@ } /****************************************************************************** -* Takes a snapshot of the source property for all ModifierApplications. +* Takes a snapshot of the source property for every ModifierApplication of +* this modifier. ******************************************************************************/ -void FreezePropertyModifier::takePropertySnapshot(TimePoint time, bool waitUntilReady) +bool FreezePropertyModifier::takePropertySnapshot(TimePoint time, TaskManager& taskManager, bool waitUntilReady) { for(ModifierApplication* modApp : modifierApplications()) { if(PipelineObject* pipelineObj = modApp->pipelineObject()) { + PipelineFlowState state; if(waitUntilReady) { - pipelineObj->waitUntilReady(time, tr("Waiting for pipeline evaluation to complete.")); + Future stateFuture = pipelineObj->evaluateAsync(PipelineEvalRequest(time, false, modApp, false)); + if(!taskManager.waitForTask(stateFuture)) + return false; + state = stateFuture.result(); + } + else { + state = pipelineObj->evaluateImmediately(PipelineEvalRequest(time, false, modApp, false)); } - PipelineFlowState state = pipelineObj->evaluatePipeline(time, modApp, false); takePropertySnapshot(modApp, state); } } + return true; } OVITO_BEGIN_INLINE_NAMESPACE(Internal) diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/properties/FreezePropertyModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/properties/FreezePropertyModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/properties/FreezePropertyModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/properties/FreezePropertyModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_FREEZE_PROPERTY_MODIFIER_H -#define __OVITO_FREEZE_PROPERTY_MODIFIER_H +#pragma once + #include #include "../ParticleModifier.h" @@ -40,23 +40,11 @@ /// Asks the modifier for its validity interval at the given time. virtual TimeInterval modifierValidity(TimePoint time) override { return TimeInterval::infinite(); } - /// Sets the source particle property which should be preserved. - void setSourceProperty(const ParticlePropertyReference& prop) { _sourceProperty = prop; } - - /// Returns the source particle property which is preserved. - const ParticlePropertyReference& sourceProperty() const { return _sourceProperty; } - - /// Sets the particle property to which the stored values should be written. - void setDestinationProperty(const ParticlePropertyReference& prop) { _destinationProperty = prop; } - - /// Returns the particle property to which the stored values will be written - const ParticlePropertyReference& destinationProperty() const { return _destinationProperty; } - - /// Takes a snapshot of the source property for a specific ModifierApplication. + /// Takes a snapshot of the source property for a specific ModifierApplication of this modifier. void takePropertySnapshot(ModifierApplication* modApp, const PipelineFlowState& state); - /// Takes a snapshot of the source property for all ModifierApplications. - void takePropertySnapshot(TimePoint time, bool waitUntilReady); + /// Takes a snapshot of the source property for every ModifierApplication of this modifier. + bool takePropertySnapshot(TimePoint time, TaskManager& taskManager, bool waitUntilReady); protected: @@ -69,23 +57,19 @@ private: /// The particle property that is preserved by this modifier. - PropertyField _sourceProperty; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ParticlePropertyReference, sourceProperty, setSourceProperty); /// The particle property to which the stored values should be written - PropertyField _destinationProperty; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ParticlePropertyReference, destinationProperty, setDestinationProperty); /// The cached display objects that are attached to the output particle property. - VectorReferenceField _cachedDisplayObjects; + DECLARE_VECTOR_REFERENCE_FIELD(DisplayObject, cachedDisplayObjects); Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Freeze property"); Q_CLASSINFO("ModifierCategory", "Modification"); - - DECLARE_PROPERTY_FIELD(_sourceProperty); - DECLARE_PROPERTY_FIELD(_destinationProperty); - DECLARE_VECTOR_REFERENCE_FIELD(_cachedDisplayObjects); }; OVITO_BEGIN_INLINE_NAMESPACE(Internal) @@ -100,8 +84,8 @@ /// Constructor. Q_INVOKABLE SavedParticleProperty(DataSet* dataset) : RefTarget(dataset) { - INIT_PROPERTY_FIELD(SavedParticleProperty::_property); - INIT_PROPERTY_FIELD(SavedParticleProperty::_identifiers); + INIT_PROPERTY_FIELD(property); + INIT_PROPERTY_FIELD(identifiers); } /// Makes a copy of the given source property and, optionally, of the provided @@ -109,25 +93,16 @@ /// values even if the order of particles changes. void reset(ParticlePropertyObject* property, ParticlePropertyObject* identifiers); - /// Returns the stored copy of the particle property. - ParticlePropertyObject* property() const { return _property; } - - /// Returns the particle identifiers, taken at the time when the property values were saved. - ParticlePropertyObject* identifiers() const { return _identifiers; } - private: /// The stored copy of the particle property. - ReferenceField _property; + DECLARE_REFERENCE_FIELD(ParticlePropertyObject, property); /// A copy of the particle identifiers, taken at the time when the property values were saved. - ReferenceField _identifiers; + DECLARE_REFERENCE_FIELD(ParticlePropertyObject, identifiers); Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_property); - DECLARE_REFERENCE_FIELD(_identifiers); }; OVITO_END_INLINE_NAMESPACE @@ -137,4 +112,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_FREEZE_PROPERTY_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/ClearSelectionModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/ClearSelectionModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/ClearSelectionModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/ClearSelectionModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Selection) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ClearSelectionModifier, ParticleModifier); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ClearSelectionModifier, ParticleModifier); /****************************************************************************** * Modifies the particle object. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/ClearSelectionModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/ClearSelectionModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/ClearSelectionModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/ClearSelectionModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CLEAR_SELECTION_MODIFIER_H -#define __OVITO_CLEAR_SELECTION_MODIFIER_H +#pragma once + #include #include "../ParticleModifier.h" @@ -60,4 +60,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CLEAR_SELECTION_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/ExpandSelectionModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/ExpandSelectionModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/ExpandSelectionModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/ExpandSelectionModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,29 +28,29 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Selection) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ExpandSelectionModifier, ParticleModifier); -DEFINE_FLAGS_PROPERTY_FIELD(ExpandSelectionModifier, _mode, "Mode", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ExpandSelectionModifier, _cutoffRange, "Cutoff", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(ExpandSelectionModifier, _numNearestNeighbors, "NumNearestNeighbors", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(ExpandSelectionModifier, _numIterations, "NumIterations"); -SET_PROPERTY_FIELD_LABEL(ExpandSelectionModifier, _mode, "Mode"); -SET_PROPERTY_FIELD_LABEL(ExpandSelectionModifier, _cutoffRange, "Cutoff distance"); -SET_PROPERTY_FIELD_LABEL(ExpandSelectionModifier, _numNearestNeighbors, "N"); -SET_PROPERTY_FIELD_LABEL(ExpandSelectionModifier, _numIterations, "Number of iterations"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ExpandSelectionModifier, _cutoffRange, WorldParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(ExpandSelectionModifier, _numNearestNeighbors, IntegerParameterUnit, 1, ExpandSelectionModifier::MAX_NEAREST_NEIGHBORS); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ExpandSelectionModifier, _numIterations, IntegerParameterUnit, 1); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ExpandSelectionModifier, ParticleModifier); +DEFINE_FLAGS_PROPERTY_FIELD(ExpandSelectionModifier, mode, "Mode", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ExpandSelectionModifier, cutoffRange, "Cutoff", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(ExpandSelectionModifier, numNearestNeighbors, "NumNearestNeighbors", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(ExpandSelectionModifier, numberOfIterations, "NumIterations"); +SET_PROPERTY_FIELD_LABEL(ExpandSelectionModifier, mode, "Mode"); +SET_PROPERTY_FIELD_LABEL(ExpandSelectionModifier, cutoffRange, "Cutoff distance"); +SET_PROPERTY_FIELD_LABEL(ExpandSelectionModifier, numNearestNeighbors, "N"); +SET_PROPERTY_FIELD_LABEL(ExpandSelectionModifier, numberOfIterations, "Number of iterations"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ExpandSelectionModifier, cutoffRange, WorldParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(ExpandSelectionModifier, numNearestNeighbors, IntegerParameterUnit, 1, ExpandSelectionModifier::MAX_NEAREST_NEIGHBORS); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ExpandSelectionModifier, numberOfIterations, IntegerParameterUnit, 1); /****************************************************************************** * Constructs the modifier object. ******************************************************************************/ ExpandSelectionModifier::ExpandSelectionModifier(DataSet* dataset) : AsynchronousParticleModifier(dataset), - _mode(CutoffRange), _cutoffRange(3.2), _numNearestNeighbors(1), _numIterations(1) + _mode(CutoffRange), _cutoffRange(3.2), _numNearestNeighbors(1), _numberOfIterations(1) { - INIT_PROPERTY_FIELD(ExpandSelectionModifier::_mode); - INIT_PROPERTY_FIELD(ExpandSelectionModifier::_cutoffRange); - INIT_PROPERTY_FIELD(ExpandSelectionModifier::_numNearestNeighbors); - INIT_PROPERTY_FIELD(ExpandSelectionModifier::_numIterations); + INIT_PROPERTY_FIELD(mode); + INIT_PROPERTY_FIELD(cutoffRange); + INIT_PROPERTY_FIELD(numNearestNeighbors); + INIT_PROPERTY_FIELD(numberOfIterations); } /****************************************************************************** @@ -117,7 +117,7 @@ // Prepare the neighbor list. NearestNeighborFinder neighFinder(_numNearestNeighbors); - if(!neighFinder.prepare(_positions.data(), _simCell, nullptr, this)) + if(!neighFinder.prepare(_positions.data(), _simCell, nullptr, *this)) return; OVITO_ASSERT(_inputSelection->constDataInt() != _outputSelection->dataInt()); @@ -161,7 +161,7 @@ { // Prepare the neighbor list. CutoffNeighborFinder neighborListBuilder; - if(!neighborListBuilder.prepare(_cutoffRange, _positions.data(), _simCell, nullptr, this)) + if(!neighborListBuilder.prepare(_cutoffRange, _positions.data(), _simCell, nullptr, *this)) return; OVITO_ASSERT(_inputSelection->constDataInt() != _outputSelection->dataInt()); @@ -216,10 +216,10 @@ AsynchronousParticleModifier::propertyChanged(field); // Recompute modifier results when the parameters have been changed. - if(field == PROPERTY_FIELD(ExpandSelectionModifier::_mode) - || field == PROPERTY_FIELD(ExpandSelectionModifier::_cutoffRange) - || field == PROPERTY_FIELD(ExpandSelectionModifier::_numNearestNeighbors) - || field == PROPERTY_FIELD(ExpandSelectionModifier::_numIterations)) + if(field == PROPERTY_FIELD(mode) + || field == PROPERTY_FIELD(cutoffRange) + || field == PROPERTY_FIELD(numNearestNeighbors) + || field == PROPERTY_FIELD(numberOfIterations)) invalidateCachedResults(); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/ExpandSelectionModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/ExpandSelectionModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/ExpandSelectionModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/ExpandSelectionModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_EXPAND_SELECTION_MODIFIER_H -#define __OVITO_EXPAND_SELECTION_MODIFIER_H +#pragma once + #include #include @@ -51,30 +51,6 @@ /// \brief Constructs a new instance of this class. Q_INVOKABLE ExpandSelectionModifier(DataSet* dataset); - /// Returns the mode of expansion. - ExpansionMode mode() const { return _mode; } - - /// Sets the mode of expansion. - void setMode(ExpansionMode mode) { _mode = mode; } - - /// Returns the selection expansion range. - FloatType cutoffRange() const { return _cutoffRange; } - - /// Sets the selection expansion range. - void setCutoffRange(FloatType cutoff) { _cutoffRange = cutoff; } - - /// Returns the number of nearest neighbors to select. - int numNearestNeighbors() const { return _numNearestNeighbors; } - - /// Sets the number of nearest neighbors to select. - void setNumNearestNeighbors(int n) { _numNearestNeighbors = n; } - - /// Returns the number of expansion steps to perform. - int numberOfIterations() const { return _numIterations; } - - /// Sets the number of expansion steps to perform. - void setNumberOfIterations(int n) { _numIterations = n; } - protected: /// Is called when the value of a property of this object has changed. @@ -172,16 +148,16 @@ private: /// The expansion mode. - PropertyField _mode; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ExpansionMode, mode, setMode); /// The selection cutoff range. - PropertyField _cutoffRange; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, cutoffRange, setCutoffRange); /// The number of nearest neighbors to select. - PropertyField _numNearestNeighbors; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, numNearestNeighbors, setNumNearestNeighbors); /// The number of expansion steps to perform. - PropertyField _numIterations; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, numberOfIterations, setNumberOfIterations); /// This stores the cached results of the modifier. QExplicitlySharedDataPointer _outputSelection; @@ -197,11 +173,6 @@ Q_CLASSINFO("DisplayName", "Expand selection"); Q_CLASSINFO("ModifierCategory", "Selection"); - - DECLARE_PROPERTY_FIELD(_mode); - DECLARE_PROPERTY_FIELD(_cutoffRange); - DECLARE_PROPERTY_FIELD(_numNearestNeighbors); - DECLARE_PROPERTY_FIELD(_numIterations); }; OVITO_END_INLINE_NAMESPACE @@ -209,4 +180,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_EXPAND_SELECTION_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/InvertSelectionModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/InvertSelectionModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/InvertSelectionModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/InvertSelectionModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Selection) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, InvertSelectionModifier, ParticleModifier); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(InvertSelectionModifier, ParticleModifier); /****************************************************************************** * Modifies the particle object. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/InvertSelectionModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/InvertSelectionModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/InvertSelectionModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/InvertSelectionModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_INVERT_SELECTION_MODIFIER_H -#define __OVITO_INVERT_SELECTION_MODIFIER_H +#pragma once + #include #include "../ParticleModifier.h" @@ -60,4 +60,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_INVERT_SELECTION_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/ManualSelectionModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/ManualSelectionModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/ManualSelectionModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/ManualSelectionModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Selection) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ManualSelectionModifier, ParticleModifier); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ManualSelectionModifier, ParticleModifier); /****************************************************************************** * This modifies the input object. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/ManualSelectionModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/ManualSelectionModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/ManualSelectionModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/ManualSelectionModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_MANUAL_SELECTION_MODIFIER_H -#define __OVITO_MANUAL_SELECTION_MODIFIER_H +#pragma once + #include #include @@ -81,4 +81,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_MANUAL_SELECTION_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/SelectExpressionModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/SelectExpressionModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/SelectExpressionModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/SelectExpressionModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,9 +29,9 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Selection) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, SelectExpressionModifier, ParticleModifier); -DEFINE_PROPERTY_FIELD(SelectExpressionModifier, _expression, "Expression"); -SET_PROPERTY_FIELD_LABEL(SelectExpressionModifier, _expression, "Boolean expression"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SelectExpressionModifier, ParticleModifier); +DEFINE_PROPERTY_FIELD(SelectExpressionModifier, expression, "Expression"); +SET_PROPERTY_FIELD_LABEL(SelectExpressionModifier, expression, "Boolean expression"); /****************************************************************************** * This modifies the input object. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/SelectExpressionModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/SelectExpressionModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/SelectExpressionModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/SelectExpressionModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SELECT_EXPRESSION_MODIFIER_H -#define __OVITO_SELECT_EXPRESSION_MODIFIER_H +#pragma once + #include #include "../ParticleModifier.h" @@ -36,17 +36,9 @@ /// Constructor. Q_INVOKABLE SelectExpressionModifier(DataSet* dataset) : ParticleModifier(dataset) { - INIT_PROPERTY_FIELD(SelectExpressionModifier::_expression); + INIT_PROPERTY_FIELD(expression); } - /////////////////////////// specific methods /////////////////////////////// - - /// Sets the expression that is used to select particles. - void setExpression(const QString& expression) { _expression = expression; } - - /// Returns the expression that is used to select particles. - const QString& expression() const { return _expression; } - /// \brief Returns the list of available input variables. const QStringList& inputVariableNames() const { return _variableNames; } @@ -62,7 +54,7 @@ virtual PipelineStatus modifyParticles(TimePoint time, TimeInterval& validityInterval) override; /// The expression that is used to select atoms. - PropertyField _expression; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, expression, setExpression); /// The list of input variables during the last evaluation. QStringList _variableNames; @@ -70,15 +62,11 @@ /// Human-readable text listing the input variables during the last evaluation. QString _variableTable; -private: - Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Expression select"); Q_CLASSINFO("ModifierCategory", "Selection"); - - DECLARE_PROPERTY_FIELD(_expression); }; OVITO_END_INLINE_NAMESPACE @@ -86,4 +74,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SELECT_EXPRESSION_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/SelectParticleTypeModifier.cpp ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/SelectParticleTypeModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/SelectParticleTypeModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/SelectParticleTypeModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,11 +28,11 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Modifiers) OVITO_BEGIN_INLINE_NAMESPACE(Selection) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, SelectParticleTypeModifier, ParticleModifier); -DEFINE_PROPERTY_FIELD(SelectParticleTypeModifier, _sourceProperty, "SourceProperty"); -DEFINE_PROPERTY_FIELD(SelectParticleTypeModifier, _selectedParticleTypes, "SelectedParticleTypes"); -SET_PROPERTY_FIELD_LABEL(SelectParticleTypeModifier, _sourceProperty, "Property"); -SET_PROPERTY_FIELD_LABEL(SelectParticleTypeModifier, _selectedParticleTypes, "Selected types"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SelectParticleTypeModifier, ParticleModifier); +DEFINE_PROPERTY_FIELD(SelectParticleTypeModifier, sourceProperty, "SourceProperty"); +DEFINE_PROPERTY_FIELD(SelectParticleTypeModifier, selectedParticleTypes, "SelectedParticleTypes"); +SET_PROPERTY_FIELD_LABEL(SelectParticleTypeModifier, sourceProperty, "Property"); +SET_PROPERTY_FIELD_LABEL(SelectParticleTypeModifier, selectedParticleTypes, "Selected types"); /****************************************************************************** * This modifies the input object. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/SelectParticleTypeModifier.h ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/SelectParticleTypeModifier.h --- ovito-2.8.1+dfsg2/src/plugins/particles/modifier/selection/SelectParticleTypeModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/modifier/selection/SelectParticleTypeModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SELECT_PARTICLE_TYPE_MODIFIER_H -#define __OVITO_SELECT_PARTICLE_TYPE_MODIFIER_H +#pragma once + #include #include "../ParticleModifier.h" @@ -37,26 +37,14 @@ /// Constructor. Q_INVOKABLE SelectParticleTypeModifier(DataSet* dataset) : ParticleModifier(dataset), _sourceProperty(ParticleProperty::ParticleTypeProperty) { - INIT_PROPERTY_FIELD(SelectParticleTypeModifier::_sourceProperty); - INIT_PROPERTY_FIELD(SelectParticleTypeModifier::_selectedParticleTypes); + INIT_PROPERTY_FIELD(sourceProperty); + INIT_PROPERTY_FIELD(selectedParticleTypes); } /// Loads the user-defined default values of this object's parameter fields from the /// application's settings store. virtual void loadUserDefaults() override; - /// Returns the particle type property that is used as source for the selection. - const ParticlePropertyReference& sourceProperty() const { return _sourceProperty; } - - /// Sets the particle type property that is used as source for the selection. - void setSourceProperty(const ParticlePropertyReference& prop) { _sourceProperty = prop; } - - /// Returns the list of particle type identifiers that are selected. - const QSet& selectedParticleTypes() const { return _selectedParticleTypes; } - - /// Sets the list of particle type identifiers to select. - void setSelectedParticleTypes(const QSet& types) { _selectedParticleTypes = types; } - /// Sets a single particle type identifier to be selected. void setSelectedParticleType(int type) { setSelectedParticleTypes(QSet{type}); } @@ -72,21 +60,16 @@ virtual PipelineStatus modifyParticles(TimePoint time, TimeInterval& validityInterval) override; /// The particle type property that is used as source for the selection. - PropertyField _sourceProperty; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ParticlePropertyReference, sourceProperty, setSourceProperty); /// The identifiers of the particle types to select. - PropertyField> _selectedParticleTypes; - -private: + DECLARE_MODIFIABLE_PROPERTY_FIELD(QSet, selectedParticleTypes, setSelectedParticleTypes); Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "Select particle type"); Q_CLASSINFO("ModifierCategory", "Selection"); - - DECLARE_PROPERTY_FIELD(_sourceProperty); - DECLARE_PROPERTY_FIELD(_selectedParticleTypes); }; OVITO_END_INLINE_NAMESPACE @@ -94,4 +77,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_SELECT_PARTICLE_TYPE_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondPropertyObject.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondPropertyObject.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondPropertyObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondPropertyObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,7 +25,7 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, BondPropertyObject, DataObject); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(BondPropertyObject, DataObject); /****************************************************************************** * Constructor. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondPropertyObject.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondPropertyObject.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondPropertyObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondPropertyObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BOND_PROPERTY_OBJECT_H -#define __OVITO_BOND_PROPERTY_OBJECT_H +#pragma once + #include #include @@ -593,4 +593,4 @@ Q_DECLARE_METATYPE(Ovito::Particles::BondPropertyReference); -#endif // __OVITO_BOND_PROPERTY_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondsDisplay.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondsDisplay.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondsDisplay.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondsDisplay.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,19 +30,19 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, BondsDisplay, DisplayObject); -IMPLEMENT_OVITO_OBJECT(Particles, BondPickInfo, ObjectPickInfo); -DEFINE_FLAGS_PROPERTY_FIELD(BondsDisplay, _bondWidth, "BondWidth", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(BondsDisplay, _bondColor, "BondColor", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(BondsDisplay, _useParticleColors, "UseParticleColors", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(BondsDisplay, _shadingMode, "ShadingMode", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(BondsDisplay, _renderingQuality, "RenderingQuality"); -SET_PROPERTY_FIELD_LABEL(BondsDisplay, _bondWidth, "Bond width"); -SET_PROPERTY_FIELD_LABEL(BondsDisplay, _bondColor, "Bond color"); -SET_PROPERTY_FIELD_LABEL(BondsDisplay, _useParticleColors, "Use particle colors"); -SET_PROPERTY_FIELD_LABEL(BondsDisplay, _shadingMode, "Shading mode"); -SET_PROPERTY_FIELD_LABEL(BondsDisplay, _renderingQuality, "RenderingQuality"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(BondsDisplay, _bondWidth, WorldParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(BondsDisplay, DisplayObject); +IMPLEMENT_OVITO_OBJECT(BondPickInfo, ObjectPickInfo); +DEFINE_FLAGS_PROPERTY_FIELD(BondsDisplay, bondWidth, "BondWidth", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(BondsDisplay, bondColor, "BondColor", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(BondsDisplay, useParticleColors, "UseParticleColors", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(BondsDisplay, shadingMode, "ShadingMode", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(BondsDisplay, renderingQuality, "RenderingQuality"); +SET_PROPERTY_FIELD_LABEL(BondsDisplay, bondWidth, "Bond width"); +SET_PROPERTY_FIELD_LABEL(BondsDisplay, bondColor, "Bond color"); +SET_PROPERTY_FIELD_LABEL(BondsDisplay, useParticleColors, "Use particle colors"); +SET_PROPERTY_FIELD_LABEL(BondsDisplay, shadingMode, "Shading mode"); +SET_PROPERTY_FIELD_LABEL(BondsDisplay, renderingQuality, "RenderingQuality"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(BondsDisplay, bondWidth, WorldParameterUnit, 0); /****************************************************************************** * Constructor. @@ -52,11 +52,11 @@ _shadingMode(ArrowPrimitive::NormalShading), _renderingQuality(ArrowPrimitive::HighQuality) { - INIT_PROPERTY_FIELD(BondsDisplay::_bondWidth); - INIT_PROPERTY_FIELD(BondsDisplay::_bondColor); - INIT_PROPERTY_FIELD(BondsDisplay::_useParticleColors); - INIT_PROPERTY_FIELD(BondsDisplay::_shadingMode); - INIT_PROPERTY_FIELD(BondsDisplay::_renderingQuality); + INIT_PROPERTY_FIELD(bondWidth); + INIT_PROPERTY_FIELD(bondColor); + INIT_PROPERTY_FIELD(useParticleColors); + INIT_PROPERTY_FIELD(shadingMode); + INIT_PROPERTY_FIELD(renderingQuality); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondsDisplay.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondsDisplay.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondsDisplay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondsDisplay.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BONDS_DISPLAY_H -#define __OVITO_BONDS_DISPLAY_H +#pragma once + #include #include @@ -51,39 +51,9 @@ /// \brief Computes the display bounding box of the data object. virtual Box3 boundingBox(TimePoint time, DataObject* dataObject, ObjectNode* contextNode, const PipelineFlowState& flowState) override; - /// \brief Returns the display width of bonds. - FloatType bondWidth() const { return _bondWidth; } - - /// \brief Sets the display width of bonds. - void setBondWidth(FloatType newWidth) { _bondWidth = newWidth; } - - /// \brief Returns the selected shading mode for bonds. - ArrowPrimitive::ShadingMode shadingMode() const { return _shadingMode; } - - /// \brief Sets the shading mode for bonds. - void setShadingMode(ArrowPrimitive::ShadingMode mode) { _shadingMode = mode; } - - /// \brief Returns the selected rendering quality mode for bonds. - ArrowPrimitive::RenderingQuality renderingQuality() const { return _renderingQuality; } - - /// \brief Sets the rendering quality mode for bonds. - void setRenderingQuality(ArrowPrimitive::RenderingQuality quality) { _renderingQuality = quality; } - - /// Returns the display color for bonds. - const Color& bondColor() const { return _bondColor; } - - /// Sets the display color for bonds. - void setBondColor(const Color& color) { _bondColor = color; } - /// Returns the display color used for selected bonds. Color selectionBondColor() const { return Color(1,0,0); } - /// Returns whether bonds colors are derived from particle colors. - bool useParticleColors() const { return _useParticleColors; } - - /// Controls whether bonds colors are derived from particle colors. - void setUseParticleColors(bool enable) { _useParticleColors = enable; } - /// Determines the display colors of bonds. void bondColors(std::vector& output, size_t particleCount, BondsObject* bondsObject, BondPropertyObject* bondColorProperty, BondTypeProperty* bondTypeProperty, BondPropertyObject* bondSelectionProperty, @@ -97,19 +67,19 @@ protected: /// Controls the display width of bonds. - PropertyField _bondWidth; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, bondWidth, setBondWidth); /// Controls the color of the bonds. - PropertyField _bondColor; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, bondColor, setBondColor); /// Controls whether bonds colors are derived from particle colors. - PropertyField _useParticleColors; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, useParticleColors, setUseParticleColors); /// Controls the shading mode for bonds. - PropertyField _shadingMode; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ArrowPrimitive::ShadingMode, shadingMode, setShadingMode); /// Controls the rendering quality mode for bonds. - PropertyField _renderingQuality; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ArrowPrimitive::RenderingQuality, renderingQuality, setRenderingQuality); /// The buffered geometry used to render the bonds. std::shared_ptr _buffer; @@ -148,12 +118,6 @@ OVITO_OBJECT Q_CLASSINFO("DisplayName", "Bonds"); - - DECLARE_PROPERTY_FIELD(_bondWidth); - DECLARE_PROPERTY_FIELD(_bondColor); - DECLARE_PROPERTY_FIELD(_useParticleColors); - DECLARE_PROPERTY_FIELD(_shadingMode); - DECLARE_PROPERTY_FIELD(_renderingQuality); }; /** @@ -188,4 +152,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_BONDS_DISPLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondsObject.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondsObject.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondsObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondsObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,7 +25,7 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, BondsObject, DataObject); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(BondsObject, DataObject); /****************************************************************************** * Default constructor. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondsObject.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondsObject.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondsObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondsObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BONDS_OBJECT_H -#define __OVITO_BONDS_OBJECT_H +#pragma once + #include #include @@ -83,4 +83,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_BONDS_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondType.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondType.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondType.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondType.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,26 +24,27 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, BondType, RefTarget); -DEFINE_PROPERTY_FIELD(BondType, _id, "Identifier"); -DEFINE_PROPERTY_FIELD(BondType, _color, "Color"); -DEFINE_PROPERTY_FIELD(BondType, _radius, "Radius"); -DEFINE_PROPERTY_FIELD(BondType, _name, "Name"); -SET_PROPERTY_FIELD_LABEL(BondType, _id, "Id"); -SET_PROPERTY_FIELD_LABEL(BondType, _color, "Color"); -SET_PROPERTY_FIELD_LABEL(BondType, _radius, "Radius"); -SET_PROPERTY_FIELD_LABEL(BondType, _name, "Name"); -SET_PROPERTY_FIELD_UNITS(BondType, _radius, WorldParameterUnit); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(BondType, RefTarget); +DEFINE_PROPERTY_FIELD(BondType, id, "Identifier"); +DEFINE_PROPERTY_FIELD(BondType, color, "Color"); +DEFINE_PROPERTY_FIELD(BondType, radius, "Radius"); +DEFINE_PROPERTY_FIELD(BondType, name, "Name"); +SET_PROPERTY_FIELD_LABEL(BondType, id, "Id"); +SET_PROPERTY_FIELD_LABEL(BondType, color, "Color"); +SET_PROPERTY_FIELD_LABEL(BondType, radius, "Radius"); +SET_PROPERTY_FIELD_LABEL(BondType, name, "Name"); +SET_PROPERTY_FIELD_UNITS(BondType, radius, WorldParameterUnit); +SET_PROPERTY_FIELD_CHANGE_EVENT(BondType, name, ReferenceEvent::TitleChanged); /****************************************************************************** * Constructs a new BondType. ******************************************************************************/ BondType::BondType(DataSet* dataset) : RefTarget(dataset), _color(1,1,1), _radius(0), _id(0) { - INIT_PROPERTY_FIELD(BondType::_id); - INIT_PROPERTY_FIELD(BondType::_color); - INIT_PROPERTY_FIELD(BondType::_radius); - INIT_PROPERTY_FIELD(BondType::_name); + INIT_PROPERTY_FIELD(id); + INIT_PROPERTY_FIELD(color); + INIT_PROPERTY_FIELD(radius); + INIT_PROPERTY_FIELD(name); } } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondType.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondType.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondType.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondType.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BOND_TYPE_H -#define __OVITO_BOND_TYPE_H +#pragma once + #include #include @@ -39,76 +39,30 @@ /// \brief Constructs a new bond type. Q_INVOKABLE BondType(DataSet* dataset); - /// \brief Returns the identifier of the bond type. - /// \return The type identifier. - int id() const { return _id; } - - /// \brief Sets the identifier of the bond type. - /// \param identifier The new identifier. - /// \undoable - void setId(int identifier) { _id = identifier; } - - /// \brief Gets the types's display name. - /// \return The human-readable name of the bond type. - /// \sa setName() - const QString& name() const { return _name; } - - /// \brief Sets the types's display name. - /// \param name The new human-readable name for this bond type. - /// \undoable - /// \sa name() - void setName(const QString& name) { _name = name; } - - /// \brief Returns the display color that is assigned to the bonds of this type. - /// \return The color used for bonds of this type. - /// \sa setColor() - Color color() const { return _color; } - - /// \brief Sets the display color of this bond type. - /// \param color The new color to be used to display bonds of this type. - /// \undoable - void setColor(const Color& color) { _color = color; } - - /// \brief Returns the radius of the bond type. - /// \return The radius in world units. - FloatType radius() const { return _radius; } - - /// \brief Sets the radius of the bond type. - /// \param newRadius The radius in world units to be used to display this kind of bond. - /// \undoable - void setRadius(FloatType newRadius) { _radius = newRadius; } - - // From RefTarget class: - /// Returns the title of this object. virtual QString objectTitle() override { return name(); } protected: /// Stores the identifier of the bond type. - PropertyField _id; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, id, setId); /// The name of this bond type. - PropertyField _name; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, name, setName); /// Stores the color of the bond type. - PropertyField _color; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, color, setColor); /// Stores the radius of the bond type. - PropertyField _radius; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, radius, setRadius); private: Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_id); - DECLARE_PROPERTY_FIELD(_name); - DECLARE_PROPERTY_FIELD(_color); - DECLARE_PROPERTY_FIELD(_radius); }; } // End of namespace } // End of namespace -#endif // __OVITO_BOND_TYPE_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondTypeProperty.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondTypeProperty.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondTypeProperty.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondTypeProperty.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,9 +24,9 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, BondTypeProperty, BondPropertyObject); -DEFINE_VECTOR_REFERENCE_FIELD(BondTypeProperty, _bondTypes, "BondTypes", BondType); -SET_PROPERTY_FIELD_LABEL(BondTypeProperty, _bondTypes, "Bond Types"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(BondTypeProperty, BondPropertyObject); +DEFINE_VECTOR_REFERENCE_FIELD(BondTypeProperty, bondTypes, "BondTypes", BondType); +SET_PROPERTY_FIELD_LABEL(BondTypeProperty, bondTypes, "Bond Types"); /****************************************************************************** * Constructor. @@ -34,7 +34,7 @@ BondTypeProperty::BondTypeProperty(DataSet* dataset, BondProperty* storage) : BondPropertyObject(dataset, storage) { - INIT_PROPERTY_FIELD(BondTypeProperty::_bondTypes); + INIT_PROPERTY_FIELD(bondTypes); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondTypeProperty.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondTypeProperty.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/BondTypeProperty.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/BondTypeProperty.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_BOND_TYPE_PROPERTY_H -#define __OVITO_BOND_TYPE_PROPERTY_H +#pragma once + #include #include "BondPropertyObject.h" @@ -52,12 +52,6 @@ _bondTypes.insert(index, type); } - /// Returns the list of bond types. - const QVector& bondTypes() const { return _bondTypes; } - - /// Replaces the list of bond types. - void setBondTypes(const QVector& types) { _bondTypes = types; } - /// Returns the bond type with the given ID, or NULL if no such type exists. BondType* bondType(int id) const { for(BondType* type : bondTypes()) @@ -117,20 +111,16 @@ /// Returns the default radius for a named bond type. static FloatType getDefaultBondRadius(BondProperty::Type typeClass, const QString& bondTypeName, int bondTypeId, bool userDefaults = true); -protected: +private: /// Contains the bond types. - VectorReferenceField _bondTypes; - -private: + DECLARE_MODIFIABLE_VECTOR_REFERENCE_FIELD(BondType, bondTypes, setBondTypes); Q_OBJECT OVITO_OBJECT - - DECLARE_VECTOR_REFERENCE_FIELD(_bondTypes); }; } // End of namespace } // End of namespace -#endif // __OVITO_BOND_TYPE_PROPERTY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/FieldQuantityObject.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/FieldQuantityObject.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/FieldQuantityObject.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/FieldQuantityObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,127 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include "FieldQuantityObject.h" + +namespace Ovito { namespace Particles { + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(FieldQuantityObject, DataObject); + +/****************************************************************************** +* Constructor. +******************************************************************************/ +FieldQuantityObject::FieldQuantityObject(DataSet* dataset, FieldQuantity* storage) + : DataObjectWithSharedStorage(dataset, storage ? storage : new FieldQuantity()) +{ +} + +/****************************************************************************** +* Factory function that creates a user-defined property object. +******************************************************************************/ +OORef FieldQuantityObject::createFieldQuantity(DataSet* dataset, std::vector shape, int dataType, size_t componentCount, size_t stride, const QString& name, bool initializeMemory) +{ + return createFromStorage(dataset, new FieldQuantity(std::move(shape), dataType, componentCount, stride, name, initializeMemory)); +} + +/****************************************************************************** +* Factory function that creates a property object based on an existing storage. +******************************************************************************/ +OORef FieldQuantityObject::createFromStorage(DataSet* dataset, FieldQuantity* storage) +{ + OORef obj = new FieldQuantityObject(dataset, storage); + return obj; +} + +/****************************************************************************** +* Sets the quantity's name. +******************************************************************************/ +void FieldQuantityObject::setName(const QString& newName) +{ + if(newName == name()) + return; + + // Make the property change undoable. + dataset()->undoStack().pushIfRecording(this, "name"); + + modifiableStorage()->setName(newName); + changed(); + notifyDependents(ReferenceEvent::TitleChanged); +} + +/****************************************************************************** +* Saves the class' contents to the given stream. +******************************************************************************/ +void FieldQuantityObject::saveToStream(ObjectSaveStream& stream) +{ + DataObject::saveToStream(stream); + + stream.beginChunk(0x01); + storage()->saveToStream(stream, !saveWithScene()); + stream.endChunk(); +} + +/****************************************************************************** +* Loads the class' contents from the given stream. +******************************************************************************/ +void FieldQuantityObject::loadFromStream(ObjectLoadStream& stream) +{ + DataObject::loadFromStream(stream); + + stream.expectChunk(0x01); + modifiableStorage()->loadFromStream(stream); + stream.closeChunk(); +} + +/****************************************************************************** +* This helper method returns a specific field quantity (if present) from the +* given pipeline state. +******************************************************************************/ +FieldQuantityObject* FieldQuantityObject::findInState(const PipelineFlowState& state, const QString& name) +{ + for(DataObject* o : state.objects()) { + FieldQuantityObject* fieldQuantity = dynamic_object_cast(o); + if(fieldQuantity && fieldQuantity->name() == name) + return fieldQuantity; + } + return nullptr; +} + +/****************************************************************************** +* This helper method finds the field quantity referenced by this FieldQuantityReference +* in the given pipeline state. +******************************************************************************/ +FieldQuantityObject* FieldQuantityReference::findInState(const PipelineFlowState& state) const +{ + if(isNull()) + return nullptr; + for(DataObject* o : state.objects()) { + if(FieldQuantityObject* fq = dynamic_object_cast(o)) { + if(fq->name() == this->name()) { + return fq; + } + } + } + return nullptr; +} + +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/FieldQuantityObject.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/FieldQuantityObject.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/FieldQuantityObject.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/FieldQuantityObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,215 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include +#include +#include + +namespace Ovito { namespace Particles { + +/** + * \brief Stores a field quantity. + */ +class OVITO_PARTICLES_EXPORT FieldQuantityObject : public DataObjectWithSharedStorage +{ +public: + + /// \brief Creates a field quantity object. + Q_INVOKABLE FieldQuantityObject(DataSet* dataset, FieldQuantity* storage = nullptr); + + /// \brief Factory function that creates a field quantity object. + /// \param shape The number of grid samples along each dimension. + /// \param dataType Specifies the data type (integer, floating-point, ...) of the quantity elements. + /// The data type is specified as an identifier according to the Qt metatype system. + /// \param componentCount The number of components per field value of type \a dataType. + /// \param stride The number of bytes per field value (pass 0 to use the smallest possible stride). + /// \param name The name assigned to the field quantity. + /// \param initializeMemory Controls whether the newly allocated memory is initialized with zeros. + static OORef createFieldQuantity(DataSet* dataset, std::vector shape, int dataType, size_t componentCount, size_t stride, const QString& name, bool initializeMemory); + + /// \brief Factory function that creates a property object based on an existing storage. + static OORef createFromStorage(DataSet* dataset, FieldQuantity* storage); + + /// \brief Gets the quantity's name. + /// \return The name of quantity. + const QString& name() const { return storage()->name(); } + + /// \brief Sets the quantity's name. + /// \param name The new name string. + /// \undoable + void setName(const QString& name); + + /// \brief Returns the data type of the quantity. + /// \return The identifier of the data type used for the elements stored in + /// this property storage according to the Qt meta type system. + int dataType() const { return storage()->dataType(); } + + /// \brief Returns the number of bytes per value. + /// \return Number of bytes used to store a single value of the data type + /// specified by dataType(). + size_t dataTypeSize() const { return storage()->dataTypeSize(); } + + /// \brief Returns the number of bytes used per field element. + size_t stride() const { return storage()->stride(); } + + /// \brief Returns the number of array elements per field value. + /// \return The number of data values stored per particle in this storage object. + size_t componentCount() const { return storage()->componentCount(); } + + /// \brief Returns the human-readable names for the components stored per field value. + /// \return The names of the vector components if this channel contains more than one value per field point. + const QStringList& componentNames() const { return storage()->componentNames(); } + + /// \brief Returns the display name of the property including the name of the given + /// vector component. + QString nameWithComponent(int vectorComponent) const { + if(componentCount() <= 1 || vectorComponent < 0) + return name(); + else if(vectorComponent < componentNames().size()) + return QString("%1.%2").arg(name()).arg(componentNames()[vectorComponent]); + else + return QString("%1.%2").arg(name()).arg(vectorComponent + 1); + } + + //////////////////////////////// from RefTarget ////////////////////////////// + + /// Returns whether this object, when returned as an editable sub-object by another object, + /// should be displayed in the modification stack. + virtual bool isSubObjectEditable() const override { return false; } + + /// \brief Returns the title of this object. + virtual QString objectTitle() override { + return name(); + } + + /// This helper method returns a specific field quantity (if present) from the given pipeline state. + static FieldQuantityObject* findInState(const PipelineFlowState& state, const QString& name); + +protected: + + /// Saves the class' contents to the given stream. + virtual void saveToStream(ObjectSaveStream& stream) override; + + /// Loads the class' contents from the given stream. + virtual void loadFromStream(ObjectLoadStream& stream) override; + +private: + + Q_OBJECT + OVITO_OBJECT +}; + +/** + * \brief A reference to a field quantity. + * + * This class is a reference to a field quantity. For instance, it is used by modifiers + * to store the input quantity selected by the user, which they will act upon. When the modifier + * is evaluated, the reference is resolved by looking up the corresponding FieldQuantityObject + * from the current input dataset, which contains the actual field data. + */ +class OVITO_PARTICLES_EXPORT FieldQuantityReference +{ +public: + + /// \brief Default constructor. Creates a null reference. + FieldQuantityReference() : _vectorComponent(-1) {} + /// \brief Constructs a reference to a field quantity. + FieldQuantityReference(const QString& name, int vectorComponent = -1) : _name(name), _vectorComponent(vectorComponent) {} + /// \brief Constructs a reference based on an existing FieldQuantity. + FieldQuantityReference(FieldQuantity* q, int vectorComponent = -1) : _name(q->name()), _vectorComponent(vectorComponent) {} + /// \brief Constructs a reference based on an existing FieldQuantityObject. + FieldQuantityReference(FieldQuantityObject* q, int vectorComponent = -1) : _name(q->name()), _vectorComponent(vectorComponent) {} + + /// \brief Gets the human-readable name of the referenced field quantity. + /// \return The quantity name. + const QString& name() const { return _name; } + + /// Returns the selected component index. + int vectorComponent() const { return _vectorComponent; } + + /// Selects a component index if the property is a vector quantity. + void setVectorComponent(int index) { _vectorComponent = index; } + + /// \brief Compares two references for equality. + bool operator==(const FieldQuantityReference& other) const { + if(vectorComponent() != other.vectorComponent()) return false; + return name() == other.name(); + } + + /// \brief Compares two references for inequality. + bool operator!=(const FieldQuantityReference& other) const { return !(*this == other); } + + /// \brief Returns true if this reference does not point to any field quantity. + /// \return true if this is a default constructed FieldQuantityReference. + bool isNull() const { return name().isEmpty(); } + + /// \brief This method retrieves the actual quantity from a pipeline state. + /// \return The actual quantity after resolving this reference; or NULL if the quantity does not exist. + FieldQuantityObject* findInState(const PipelineFlowState& state) const; + + /// \brief Returns the display name of the referenced property including the optional vector component. + QString nameWithComponent() const { + if(vectorComponent() < 0) + return name(); + else + return QString("%1.%2").arg(name()).arg(vectorComponent() + 1); + } + +private: + + /// The human-readable name of the quantity. + QString _name; + + /// The zero-based component index if its a vectorial quantity (or zero if scalar). + int _vectorComponent; + + friend SaveStream& operator<<(SaveStream& stream, const FieldQuantityReference& r); + friend LoadStream& operator>>(LoadStream& stream, FieldQuantityReference& r); +}; + +/// Writes a FieldQuantityReference to an output stream. +/// \relates FieldQuantityReference +inline SaveStream& operator<<(SaveStream& stream, const FieldQuantityReference& r) +{ + stream << r.name(); + stream << r.vectorComponent(); + return stream; +} + +/// Reads a FieldQuantityReference from an input stream. +/// \relates FieldQuantityReference +inline LoadStream& operator>>(LoadStream& stream, FieldQuantityReference& r) +{ + stream >> r._name; + stream >> r._vectorComponent; + return stream; +} + +} // End of namespace +} // End of namespace + +Q_DECLARE_METATYPE(Ovito::Particles::FieldQuantityReference); + + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticleDisplay.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticleDisplay.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticleDisplay.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticleDisplay.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,31 +27,27 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ParticleDisplay, DisplayObject); -IMPLEMENT_OVITO_OBJECT(Particles, ParticlePickInfo, ObjectPickInfo); -DEFINE_FLAGS_PROPERTY_FIELD(ParticleDisplay, _defaultParticleRadius, "DefaultParticleRadius", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(ParticleDisplay, _shadingMode, "ShadingMode"); -DEFINE_PROPERTY_FIELD(ParticleDisplay, _renderingQuality, "RenderingQuality"); -DEFINE_PROPERTY_FIELD(ParticleDisplay, _particleShape, "ParticleShape"); -SET_PROPERTY_FIELD_LABEL(ParticleDisplay, _defaultParticleRadius, "Default particle radius"); -SET_PROPERTY_FIELD_LABEL(ParticleDisplay, _shadingMode, "Shading mode"); -SET_PROPERTY_FIELD_LABEL(ParticleDisplay, _renderingQuality, "Rendering quality"); -SET_PROPERTY_FIELD_LABEL(ParticleDisplay, _particleShape, "Shape"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ParticleDisplay, _defaultParticleRadius, WorldParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ParticleDisplay, DisplayObject); +IMPLEMENT_OVITO_OBJECT(ParticlePickInfo, ObjectPickInfo); +DEFINE_FLAGS_PROPERTY_FIELD(ParticleDisplay, defaultParticleRadius, "DefaultParticleRadius", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(ParticleDisplay, renderingQuality, "RenderingQuality"); +DEFINE_PROPERTY_FIELD(ParticleDisplay, particleShape, "ParticleShape"); +SET_PROPERTY_FIELD_LABEL(ParticleDisplay, defaultParticleRadius, "Default particle radius"); +SET_PROPERTY_FIELD_LABEL(ParticleDisplay, renderingQuality, "Rendering quality"); +SET_PROPERTY_FIELD_LABEL(ParticleDisplay, particleShape, "Shape"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ParticleDisplay, defaultParticleRadius, WorldParameterUnit, 0); /****************************************************************************** * Constructor. ******************************************************************************/ ParticleDisplay::ParticleDisplay(DataSet* dataset) : DisplayObject(dataset), _defaultParticleRadius(1.2), - _shadingMode(ParticlePrimitive::NormalShading), _renderingQuality(ParticlePrimitive::AutoQuality), _particleShape(Sphere) { - INIT_PROPERTY_FIELD(ParticleDisplay::_defaultParticleRadius); - INIT_PROPERTY_FIELD(ParticleDisplay::_shadingMode); - INIT_PROPERTY_FIELD(ParticleDisplay::_renderingQuality); - INIT_PROPERTY_FIELD(ParticleDisplay::_particleShape); + INIT_PROPERTY_FIELD(defaultParticleRadius); + INIT_PROPERTY_FIELD(renderingQuality); + INIT_PROPERTY_FIELD(particleShape); } /****************************************************************************** @@ -795,23 +791,6 @@ } /****************************************************************************** -* Loads the data of this class from an input stream. -******************************************************************************/ -void ParticleDisplay::loadFromStream(ObjectLoadStream& stream) -{ - DisplayObject::loadFromStream(stream); - - // This is for backward-compatibility with files written by OVITO 2.5.0. - if(_shadingMode == ParticlePrimitive::FlatShading) { - _shadingMode = ParticlePrimitive::NormalShading; - if(particleShape() == Sphere) - setParticleShape(Circle); - else if(particleShape() == Box) - setParticleShape(Square); - } -} - -/****************************************************************************** * Given an sub-object ID returned by the Viewport::pick() method, looks up the * corresponding particle index. ******************************************************************************/ @@ -822,7 +801,7 @@ return subobjID; } else { - if(subobjID < _particleCount) + if(subobjID < (quint32)_particleCount) return subobjID; else return (subobjID - _particleCount) / 2; diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticleDisplay.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticleDisplay.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticleDisplay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticleDisplay.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_DISPLAY_H -#define __OVITO_PARTICLE_DISPLAY_H +#pragma once + #include #include @@ -68,29 +68,11 @@ /// \brief Returns the display color used for selected particles. Color selectionParticleColor() const { return Color(1,0,0); } - /// \brief Returns the default display radius of particles. - FloatType defaultParticleRadius() const { return _defaultParticleRadius; } - - /// \brief Sets the default display radius of particles. - void setDefaultParticleRadius(FloatType newRadius) { _defaultParticleRadius = newRadius; } - - /// \brief Returns the selected rendering quality mode for particles. - ParticlePrimitive::RenderingQuality renderingQuality() const { return _renderingQuality; } - - /// \brief Returns the actual rendering quality used to render the given particles. - ParticlePrimitive::RenderingQuality effectiveRenderingQuality(SceneRenderer* renderer, ParticlePropertyObject* positionProperty) const; - - /// \brief Sets the rendering quality mode for particles. - void setRenderingQuality(ParticlePrimitive::RenderingQuality quality) { _renderingQuality = quality; } - - /// \brief Returns the display shape of particles. - ParticleShape particleShape() const { return _particleShape; } - /// \brief Returns the actual particle shape used to render the particles. ParticlePrimitive::ParticleShape effectiveParticleShape(ParticlePropertyObject* shapeProperty, ParticlePropertyObject* orientationProperty) const; - /// \brief Sets the display shape of particles. - void setParticleShape(ParticleShape shape) { _particleShape = shape; } + /// \brief Returns the actual rendering quality used to render the particles. + ParticlePrimitive::RenderingQuality effectiveRenderingQuality(SceneRenderer* renderer, ParticlePropertyObject* positionProperty) const; /// \brief Determines the display particle colors. void particleColors(std::vector& output, ParticlePropertyObject* colorProperty, ParticleTypeProperty* typeProperty, ParticlePropertyObject* selectionProperty = nullptr); @@ -117,26 +99,17 @@ Q_PROPERTY(Ovito::ParticlePrimitive::RenderingQuality renderingQuality READ renderingQuality WRITE setRenderingQuality); Q_PROPERTY(Ovito::Particles::ParticleDisplay::ParticleShape particleShape READ particleShape WRITE setParticleShape); - -protected: - - /// Loads the data of this class from an input stream. - virtual void loadFromStream(ObjectLoadStream& stream) override; - + private: /// Controls the default display radius of atomic particles. - PropertyField _defaultParticleRadius; - - /// Controls the shading mode for particles. - /// DEPRECATED: This field is for backward-compatibility with OVITO 2.5.0 - PropertyField _shadingMode; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, defaultParticleRadius, setDefaultParticleRadius); /// Controls the rendering quality mode for particles. - PropertyField _renderingQuality; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ParticlePrimitive::RenderingQuality, renderingQuality, setRenderingQuality); /// Controls the display shape of particles. - PropertyField _particleShape; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ParticleShape, particleShape, setParticleShape); /// The buffered particle geometry used to render the particles. std::shared_ptr _particleBuffer; @@ -209,11 +182,6 @@ OVITO_OBJECT Q_CLASSINFO("DisplayName", "Particles"); - - DECLARE_PROPERTY_FIELD(_defaultParticleRadius); - DECLARE_PROPERTY_FIELD(_shadingMode); - DECLARE_PROPERTY_FIELD(_renderingQuality); - DECLARE_PROPERTY_FIELD(_particleShape); }; /** @@ -262,4 +230,4 @@ Q_DECLARE_METATYPE(Ovito::Particles::ParticleDisplay::ParticleShape); Q_DECLARE_TYPEINFO(Ovito::Particles::ParticleDisplay::ParticleShape, Q_PRIMITIVE_TYPE); -#endif // __OVITO_PARTICLE_DISPLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticlePropertyObject.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticlePropertyObject.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticlePropertyObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticlePropertyObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ParticlePropertyObject, DataObject); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ParticlePropertyObject, DataObject); /****************************************************************************** * Constructor. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticlePropertyObject.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticlePropertyObject.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticlePropertyObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticlePropertyObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_PROPERTY_OBJECT_H -#define __OVITO_PARTICLE_PROPERTY_OBJECT_H +#pragma once + #include #include @@ -116,7 +116,7 @@ /// \brief Returns the number of bytes per value. /// \return Number of bytes used to store a single value of the data type - /// specified by type(). + /// specified by dataType(). size_t dataTypeSize() const { return storage()->dataTypeSize(); } /// \brief Returns the number of bytes used per particle. @@ -601,4 +601,4 @@ Q_DECLARE_METATYPE(Ovito::Particles::ParticlePropertyReference); -#endif // __OVITO_PARTICLE_PROPERTY_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticleType.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticleType.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticleType.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticleType.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,40 +26,31 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ParticleType, RefTarget); -DEFINE_PROPERTY_FIELD(ParticleType, _id, "Identifier"); -DEFINE_PROPERTY_FIELD(ParticleType, _color, "Color"); -DEFINE_PROPERTY_FIELD(ParticleType, _radius, "Radius"); -DEFINE_PROPERTY_FIELD(ParticleType, _name, "Name"); -DEFINE_PROPERTY_FIELD(ParticleType, _enabled, "Enabled"); -SET_PROPERTY_FIELD_LABEL(ParticleType, _id, "Id"); -SET_PROPERTY_FIELD_LABEL(ParticleType, _color, "Color"); -SET_PROPERTY_FIELD_LABEL(ParticleType, _radius, "Radius"); -SET_PROPERTY_FIELD_LABEL(ParticleType, _name, "Name"); -SET_PROPERTY_FIELD_LABEL(ParticleType, _enabled, "Enabled"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ParticleType, _radius, WorldParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ParticleType, RefTarget); +DEFINE_PROPERTY_FIELD(ParticleType, id, "Identifier"); +DEFINE_PROPERTY_FIELD(ParticleType, color, "Color"); +DEFINE_PROPERTY_FIELD(ParticleType, radius, "Radius"); +DEFINE_PROPERTY_FIELD(ParticleType, name, "Name"); +DEFINE_PROPERTY_FIELD(ParticleType, enabled, "Enabled"); +SET_PROPERTY_FIELD_LABEL(ParticleType, id, "Id"); +SET_PROPERTY_FIELD_LABEL(ParticleType, color, "Color"); +SET_PROPERTY_FIELD_LABEL(ParticleType, radius, "Radius"); +SET_PROPERTY_FIELD_LABEL(ParticleType, name, "Name"); +SET_PROPERTY_FIELD_LABEL(ParticleType, enabled, "Enabled"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(ParticleType, radius, WorldParameterUnit, 0); +SET_PROPERTY_FIELD_CHANGE_EVENT(ParticleType, name, ReferenceEvent::TitleChanged); +SET_PROPERTY_FIELD_CHANGE_EVENT(ParticleType, enabled, ReferenceEvent::TargetEnabledOrDisabled); /****************************************************************************** * Constructs a new ParticleType. ******************************************************************************/ ParticleType::ParticleType(DataSet* dataset) : RefTarget(dataset), _color(1,1,1), _radius(0), _id(0), _enabled(true) { - INIT_PROPERTY_FIELD(ParticleType::_id); - INIT_PROPERTY_FIELD(ParticleType::_color); - INIT_PROPERTY_FIELD(ParticleType::_radius); - INIT_PROPERTY_FIELD(ParticleType::_name); - INIT_PROPERTY_FIELD(ParticleType::_enabled); -} - -/****************************************************************************** -* Is called when the value of a property of this object has changed. -******************************************************************************/ -void ParticleType::propertyChanged(const PropertyFieldDescriptor& field) -{ - RefTarget::propertyChanged(field); - - if(field == PROPERTY_FIELD(ParticleType::_enabled)) - notifyDependents(ReferenceEvent::TargetEnabledOrDisabled); + INIT_PROPERTY_FIELD(id); + INIT_PROPERTY_FIELD(color); + INIT_PROPERTY_FIELD(radius); + INIT_PROPERTY_FIELD(name); + INIT_PROPERTY_FIELD(enabled); } } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticleType.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticleType.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticleType.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticleType.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_TYPE_H -#define __OVITO_PARTICLE_TYPE_H +#pragma once + #include #include @@ -39,94 +39,32 @@ /// \brief Constructs a new particle type. Q_INVOKABLE ParticleType(DataSet* dataset); - /// \brief Returns the identifier of the particle type. - /// \return The type identifier. - int id() const { return _id; } - - /// \brief Sets the identifier of the particle type. - /// \param identifier The new identifier. - /// \undoable - void setId(int identifier) { _id = identifier; } - - /// \brief Gets the types's display name. - /// \return The human-readable name of the particle type. - /// \sa setName() - const QString& name() const { return _name; } - - /// \brief Sets the types's display name. - /// \param name The new human-readable name for this particle type. - /// \undoable - /// \sa name() - void setName(const QString& name) { _name = name; } - - /// \brief Returns the display color that is assigned to the particles of this type. - /// \return The color used for particles of this type. - /// \sa setColor() - Color color() const { return _color; } - - /// \brief Sets the display color of this particle type. - /// \param color The new color to be used to display particles of this type. - /// \undoable - void setColor(const Color& color) { _color = color; } - - /// \brief Returns the radius of the particle type. - /// \return The radius in world units. - FloatType radius() const { return _radius; } - - /// \brief Sets the radius of the particle type. - /// \param newRadius The radius in world units to be used to display this kind of particle. - /// \undoable - void setRadius(FloatType newRadius) { _radius = newRadius; } - - /// \brief Returns whether this type is enabled or disabled. - /// This controls, e.g., the search for this structure type by structure identification modifiers. - bool isEnabled() const { return _enabled; } - - /// \brief Sets whether this type is enabled or disabled. - /// This controls, e.g., the search for this structure type by structure identification modifiers. - void setEnabled(bool enabled) { _enabled = enabled; } - - // From RefTarget class: - /// Returns the title of this object. virtual QString objectTitle() override { return name(); } protected: - /// Is called when the value of a property of this object has changed. - virtual void propertyChanged(const PropertyFieldDescriptor& field) override; - -protected: - /// Stores the identifier of the particle type. - PropertyField _id; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, id, setId); /// The name of this particle type. - PropertyField _name; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, name, setName); /// Stores the color of the particle type. - PropertyField _color; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, color, setColor); /// Stores the radius of the particle type. - PropertyField _radius; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, radius, setRadius); /// Stores whether this type is enabled or disabled. /// This controls, e.g., the search for this structure type by structure identification modifiers. - PropertyField _enabled; - -private: + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, enabled, setEnabled); Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_id); - DECLARE_PROPERTY_FIELD(_name); - DECLARE_PROPERTY_FIELD(_color); - DECLARE_PROPERTY_FIELD(_radius); - DECLARE_PROPERTY_FIELD(_enabled); }; } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_TYPE_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticleTypeProperty.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticleTypeProperty.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticleTypeProperty.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticleTypeProperty.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,9 +24,9 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ParticleTypeProperty, ParticlePropertyObject); -DEFINE_VECTOR_REFERENCE_FIELD(ParticleTypeProperty, _particleTypes, "ParticleTypes", ParticleType); -SET_PROPERTY_FIELD_LABEL(ParticleTypeProperty, _particleTypes, "Particle Types"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ParticleTypeProperty, ParticlePropertyObject); +DEFINE_VECTOR_REFERENCE_FIELD(ParticleTypeProperty, particleTypes, "ParticleTypes", ParticleType); +SET_PROPERTY_FIELD_LABEL(ParticleTypeProperty, particleTypes, "Particle Types"); // Define default names, colors, and radii for some predefined particle types. std::array ParticleTypeProperty::_predefinedParticleTypes{{ @@ -84,7 +84,7 @@ ParticleTypeProperty::ParticleTypeProperty(DataSet* dataset, ParticleProperty* storage) : ParticlePropertyObject(dataset, storage) { - INIT_PROPERTY_FIELD(ParticleTypeProperty::_particleTypes); + INIT_PROPERTY_FIELD(particleTypes); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticleTypeProperty.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticleTypeProperty.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/ParticleTypeProperty.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/ParticleTypeProperty.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_TYPE_PROPERTY_H -#define __OVITO_PARTICLE_TYPE_PROPERTY_H +#pragma once + #include #include "ParticlePropertyObject.h" @@ -77,12 +77,6 @@ _particleTypes.insert(index, ptype); } - /// Returns the list of particle types. - const QVector& particleTypes() const { return _particleTypes; } - - /// Replaces the list of particle types. - void setParticleTypes(const QVector& types) { _particleTypes = types; } - /// Returns the particle type with the given ID, or NULL if no such type exists. ParticleType* particleType(int id) const { for(ParticleType* ptype : particleTypes()) @@ -160,11 +154,6 @@ /// Changes the default radius for a named particle type. static void setDefaultParticleRadius(ParticleProperty::Type typeClass, const QString& particleTypeName, FloatType radius); -protected: - - /// Contains the particle types. - VectorReferenceField _particleTypes; - private: /// Data structure that holds the name, color, and radius of a particle type. @@ -176,13 +165,14 @@ /// Contains default names, colors, and radii for the predefined structure types. static std::array _predefinedStructureTypes; + /// Contains the particle types. + DECLARE_MODIFIABLE_VECTOR_REFERENCE_FIELD(ParticleType, particleTypes, setParticleTypes); + Q_OBJECT OVITO_OBJECT - - DECLARE_VECTOR_REFERENCE_FIELD(_particleTypes); }; } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_TYPE_PROPERTY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/SimulationCellDisplay.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/SimulationCellDisplay.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/SimulationCellDisplay.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/SimulationCellDisplay.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,26 +27,26 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, SimulationCellDisplay, DisplayObject); -DEFINE_PROPERTY_FIELD(SimulationCellDisplay, _renderSimulationCell, "RenderSimulationCell"); -DEFINE_PROPERTY_FIELD(SimulationCellDisplay, _simulationCellLineWidth, "SimulationCellLineWidth"); -DEFINE_FLAGS_PROPERTY_FIELD(SimulationCellDisplay, _simulationCellColor, "SimulationCellRenderingColor", PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(SimulationCellDisplay, _simulationCellLineWidth, "Line width"); -SET_PROPERTY_FIELD_LABEL(SimulationCellDisplay, _renderSimulationCell, "Render cell"); -SET_PROPERTY_FIELD_LABEL(SimulationCellDisplay, _simulationCellColor, "Line color"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(SimulationCellDisplay, _simulationCellLineWidth, WorldParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SimulationCellDisplay, DisplayObject); +DEFINE_PROPERTY_FIELD(SimulationCellDisplay, renderCellEnabled, "RenderSimulationCell"); +DEFINE_PROPERTY_FIELD(SimulationCellDisplay, cellLineWidth, "SimulationCellLineWidth"); +DEFINE_FLAGS_PROPERTY_FIELD(SimulationCellDisplay, cellColor, "SimulationCellRenderingColor", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(SimulationCellDisplay, cellLineWidth, "Line width"); +SET_PROPERTY_FIELD_LABEL(SimulationCellDisplay, renderCellEnabled, "Render cell"); +SET_PROPERTY_FIELD_LABEL(SimulationCellDisplay, cellColor, "Line color"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(SimulationCellDisplay, cellLineWidth, WorldParameterUnit, 0); /****************************************************************************** * Constructor. ******************************************************************************/ SimulationCellDisplay::SimulationCellDisplay(DataSet* dataset) : DisplayObject(dataset), - _renderSimulationCell(true), - _simulationCellLineWidth(0.5), - _simulationCellColor(0, 0, 0) + _renderCellEnabled(true), + _cellLineWidth(0.5), + _cellColor(0, 0, 0) { - INIT_PROPERTY_FIELD(SimulationCellDisplay::_renderSimulationCell); - INIT_PROPERTY_FIELD(SimulationCellDisplay::_simulationCellLineWidth); - INIT_PROPERTY_FIELD(SimulationCellDisplay::_simulationCellColor); + INIT_PROPERTY_FIELD(renderCellEnabled); + INIT_PROPERTY_FIELD(cellLineWidth); + INIT_PROPERTY_FIELD(cellColor); } /****************************************************************************** @@ -63,7 +63,7 @@ matrix.translation().z() = 0; } - return Box3(Point3(0), Point3(1)).transformed(matrix).padBox(simulationCellLineWidth()); + return Box3(Point3(0), Point3(1)).transformed(matrix).padBox(cellLineWidth()); } /****************************************************************************** @@ -78,7 +78,7 @@ renderWireframe(cell, renderer, contextNode); } else { - if(!renderSimulationCell()) + if(!renderCellEnabled()) return; // Do nothing if rendering has been disabled by the user. renderSolid(cell, renderer, contextNode); @@ -102,15 +102,15 @@ _wireframeGeometry->setVertexCount(cell->is2D() ? 8 : 24); _wireframePickingGeometry->setVertexCount(_wireframeGeometry->vertexCount(), renderer->defaultLinePickingWidth()); Point3 corners[8]; - corners[0] = cell->origin(); + corners[0] = cell->cellOrigin(); if(cell->is2D()) corners[0].z() = 0; - corners[1] = corners[0] + cell->edgeVector1(); - corners[2] = corners[1] + cell->edgeVector2(); - corners[3] = corners[0] + cell->edgeVector2(); - corners[4] = corners[0] + cell->edgeVector3(); - corners[5] = corners[1] + cell->edgeVector3(); - corners[6] = corners[2] + cell->edgeVector3(); - corners[7] = corners[3] + cell->edgeVector3(); + corners[1] = corners[0] + cell->cellVector1(); + corners[2] = corners[1] + cell->cellVector2(); + corners[3] = corners[0] + cell->cellVector2(); + corners[4] = corners[0] + cell->cellVector3(); + corners[5] = corners[1] + cell->cellVector3(); + corners[6] = corners[2] + cell->cellVector3(); + corners[7] = corners[3] + cell->cellVector3(); Point3 vertices[24] = { corners[0], corners[1], corners[1], corners[2], @@ -143,43 +143,43 @@ ******************************************************************************/ void SimulationCellDisplay::renderSolid(SimulationCellObject* cell, SceneRenderer* renderer, ObjectNode* contextNode) { - if(_solidGeometryCacheHelper.updateState(cell, simulationCellLineWidth(), simulationCellRenderingColor()) + if(_solidGeometryCacheHelper.updateState(cell, cellLineWidth(), cellColor()) || !_edgeGeometry || !_cornerGeometry || !_edgeGeometry->isValid(renderer) || !_cornerGeometry->isValid(renderer)) { _edgeGeometry = renderer->createArrowPrimitive(ArrowPrimitive::CylinderShape, ArrowPrimitive::NormalShading, ArrowPrimitive::HighQuality); _cornerGeometry = renderer->createParticlePrimitive(ParticlePrimitive::NormalShading, ParticlePrimitive::HighQuality); _edgeGeometry->startSetElements(cell->is2D() ? 4 : 12); - ColorA color = (ColorA)simulationCellRenderingColor(); + ColorA color = (ColorA)cellColor(); Point3 corners[8]; - corners[0] = cell->origin(); + corners[0] = cell->cellOrigin(); if(cell->is2D()) corners[0].z() = 0; - corners[1] = corners[0] + cell->edgeVector1(); - corners[2] = corners[1] + cell->edgeVector2(); - corners[3] = corners[0] + cell->edgeVector2(); - corners[4] = corners[0] + cell->edgeVector3(); - corners[5] = corners[1] + cell->edgeVector3(); - corners[6] = corners[2] + cell->edgeVector3(); - corners[7] = corners[3] + cell->edgeVector3(); - _edgeGeometry->setElement(0, corners[0], corners[1] - corners[0], color, simulationCellLineWidth()); - _edgeGeometry->setElement(1, corners[1], corners[2] - corners[1], color, simulationCellLineWidth()); - _edgeGeometry->setElement(2, corners[2], corners[3] - corners[2], color, simulationCellLineWidth()); - _edgeGeometry->setElement(3, corners[3], corners[0] - corners[3], color, simulationCellLineWidth()); + corners[1] = corners[0] + cell->cellVector1(); + corners[2] = corners[1] + cell->cellVector2(); + corners[3] = corners[0] + cell->cellVector2(); + corners[4] = corners[0] + cell->cellVector3(); + corners[5] = corners[1] + cell->cellVector3(); + corners[6] = corners[2] + cell->cellVector3(); + corners[7] = corners[3] + cell->cellVector3(); + _edgeGeometry->setElement(0, corners[0], corners[1] - corners[0], color, cellLineWidth()); + _edgeGeometry->setElement(1, corners[1], corners[2] - corners[1], color, cellLineWidth()); + _edgeGeometry->setElement(2, corners[2], corners[3] - corners[2], color, cellLineWidth()); + _edgeGeometry->setElement(3, corners[3], corners[0] - corners[3], color, cellLineWidth()); if(cell->is2D() == false) { - _edgeGeometry->setElement(4, corners[4], corners[5] - corners[4], color, simulationCellLineWidth()); - _edgeGeometry->setElement(5, corners[5], corners[6] - corners[5], color, simulationCellLineWidth()); - _edgeGeometry->setElement(6, corners[6], corners[7] - corners[6], color, simulationCellLineWidth()); - _edgeGeometry->setElement(7, corners[7], corners[4] - corners[7], color, simulationCellLineWidth()); - _edgeGeometry->setElement(8, corners[0], corners[4] - corners[0], color, simulationCellLineWidth()); - _edgeGeometry->setElement(9, corners[1], corners[5] - corners[1], color, simulationCellLineWidth()); - _edgeGeometry->setElement(10, corners[2], corners[6] - corners[2], color, simulationCellLineWidth()); - _edgeGeometry->setElement(11, corners[3], corners[7] - corners[3], color, simulationCellLineWidth()); + _edgeGeometry->setElement(4, corners[4], corners[5] - corners[4], color, cellLineWidth()); + _edgeGeometry->setElement(5, corners[5], corners[6] - corners[5], color, cellLineWidth()); + _edgeGeometry->setElement(6, corners[6], corners[7] - corners[6], color, cellLineWidth()); + _edgeGeometry->setElement(7, corners[7], corners[4] - corners[7], color, cellLineWidth()); + _edgeGeometry->setElement(8, corners[0], corners[4] - corners[0], color, cellLineWidth()); + _edgeGeometry->setElement(9, corners[1], corners[5] - corners[1], color, cellLineWidth()); + _edgeGeometry->setElement(10, corners[2], corners[6] - corners[2], color, cellLineWidth()); + _edgeGeometry->setElement(11, corners[3], corners[7] - corners[3], color, cellLineWidth()); } _edgeGeometry->endSetElements(); _cornerGeometry->setSize(cell->is2D() ? 4 : 8); _cornerGeometry->setParticlePositions(corners); - _cornerGeometry->setParticleRadius(simulationCellLineWidth()); - _cornerGeometry->setParticleColor(simulationCellRenderingColor()); + _cornerGeometry->setParticleRadius(cellLineWidth()); + _cornerGeometry->setParticleColor(cellColor()); } renderer->beginPickObject(contextNode); _edgeGeometry->render(renderer); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/SimulationCellDisplay.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/SimulationCellDisplay.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/SimulationCellDisplay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/SimulationCellDisplay.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SIMULATION_CELL_DISPLAY_H -#define __OVITO_SIMULATION_CELL_DISPLAY_H +#pragma once + #include #include @@ -45,33 +45,6 @@ /// \brief Lets the display object render the data object. virtual void render(TimePoint time, DataObject* dataObject, const PipelineFlowState& flowState, SceneRenderer* renderer, ObjectNode* contextNode) override; - /// \brief Returns the line width used to render the simulation cell box. - /// \return The line with in world units or zero if the simulation box is not rendered. - FloatType simulationCellLineWidth() const { return _simulationCellLineWidth; } - - /// \brief Sets the line width used to render the simulation cell box. - /// \param newWidth The new line width in world units or zero to not render the box at all. - /// \undoable - void setSimulationCellLineWidth(FloatType newWidth) { _simulationCellLineWidth = newWidth; } - - /// \brief Returns whether the simulation cell is visible. - /// \return The visibility flag. - bool renderSimulationCell() const { return _renderSimulationCell; } - - /// \brief Sets whether the simulation cell is visible. - /// \param on The visibility flag. - /// \undoable - void setRenderSimulationCell(bool on) { _renderSimulationCell = on; } - - /// \brief Returns the color used for rendering the simulation cell. - /// \return The line color - Color simulationCellRenderingColor() const { return _simulationCellColor; } - - /// \brief Sets the color to be used for rendering the simulation cell. - /// \param Color The new line color. - /// \undoable - void setSimulationCellRenderingColor(const Color& color) { _simulationCellColor = color; } - /// \brief Computes the bounding box of the object. virtual Box3 boundingBox(TimePoint time, DataObject* dataObject, ObjectNode* contextNode, const PipelineFlowState& flowState) override; @@ -89,13 +62,13 @@ protected: /// Controls the line width used to render the simulation cell. - PropertyField _simulationCellLineWidth; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, cellLineWidth, setCellLineWidth); /// Controls whether the simulation cell is visible. - PropertyField _renderSimulationCell; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, renderCellEnabled, setRenderCellEnabled); /// Controls the rendering color of the simulation cell. - PropertyField _simulationCellColor; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, cellColor, setCellColor); /// The geometry buffer used to render the simulation cell in wireframe mode. std::shared_ptr _wireframeGeometry; @@ -129,13 +102,9 @@ OVITO_OBJECT Q_CLASSINFO("DisplayName", "Simulation cell"); - - DECLARE_PROPERTY_FIELD(_renderSimulationCell); - DECLARE_PROPERTY_FIELD(_simulationCellLineWidth); - DECLARE_PROPERTY_FIELD(_simulationCellColor); }; } // End of namespace } // End of namespace -#endif // __OVITO_SIMULATION_CELL_DISPLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/SimulationCellObject.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/SimulationCellObject.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/SimulationCellObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/SimulationCellObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,41 +26,41 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, SimulationCellObject, DataObject); -DEFINE_PROPERTY_FIELD(SimulationCellObject, _cellVector1, "CellVector1"); -DEFINE_PROPERTY_FIELD(SimulationCellObject, _cellVector2, "CellVector2"); -DEFINE_PROPERTY_FIELD(SimulationCellObject, _cellVector3, "CellVector3"); -DEFINE_PROPERTY_FIELD(SimulationCellObject, _cellOrigin, "CellTranslation"); -DEFINE_PROPERTY_FIELD(SimulationCellObject, _pbcX, "PeriodicX"); -DEFINE_PROPERTY_FIELD(SimulationCellObject, _pbcY, "PeriodicY"); -DEFINE_PROPERTY_FIELD(SimulationCellObject, _pbcZ, "PeriodicZ"); -DEFINE_PROPERTY_FIELD(SimulationCellObject, _is2D, "Is2D"); -SET_PROPERTY_FIELD_LABEL(SimulationCellObject, _cellVector1, "Cell vector 1"); -SET_PROPERTY_FIELD_LABEL(SimulationCellObject, _cellVector2, "Cell vector 2"); -SET_PROPERTY_FIELD_LABEL(SimulationCellObject, _cellVector3, "Cell vector 3"); -SET_PROPERTY_FIELD_LABEL(SimulationCellObject, _cellOrigin, "Cell origin"); -SET_PROPERTY_FIELD_LABEL(SimulationCellObject, _pbcX, "Periodic boundary conditions (X)"); -SET_PROPERTY_FIELD_LABEL(SimulationCellObject, _pbcY, "Periodic boundary conditions (Y)"); -SET_PROPERTY_FIELD_LABEL(SimulationCellObject, _pbcZ, "Periodic boundary conditions (Z)"); -SET_PROPERTY_FIELD_LABEL(SimulationCellObject, _is2D, "2D"); -SET_PROPERTY_FIELD_UNITS(SimulationCellObject, _cellVector1, WorldParameterUnit); -SET_PROPERTY_FIELD_UNITS(SimulationCellObject, _cellVector2, WorldParameterUnit); -SET_PROPERTY_FIELD_UNITS(SimulationCellObject, _cellVector3, WorldParameterUnit); -SET_PROPERTY_FIELD_UNITS(SimulationCellObject, _cellOrigin, WorldParameterUnit); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SimulationCellObject, DataObject); +DEFINE_PROPERTY_FIELD(SimulationCellObject, cellVector1, "CellVector1"); +DEFINE_PROPERTY_FIELD(SimulationCellObject, cellVector2, "CellVector2"); +DEFINE_PROPERTY_FIELD(SimulationCellObject, cellVector3, "CellVector3"); +DEFINE_PROPERTY_FIELD(SimulationCellObject, cellOrigin, "CellTranslation"); +DEFINE_PROPERTY_FIELD(SimulationCellObject, pbcX, "PeriodicX"); +DEFINE_PROPERTY_FIELD(SimulationCellObject, pbcY, "PeriodicY"); +DEFINE_PROPERTY_FIELD(SimulationCellObject, pbcZ, "PeriodicZ"); +DEFINE_PROPERTY_FIELD(SimulationCellObject, is2D, "Is2D"); +SET_PROPERTY_FIELD_LABEL(SimulationCellObject, cellVector1, "Cell vector 1"); +SET_PROPERTY_FIELD_LABEL(SimulationCellObject, cellVector2, "Cell vector 2"); +SET_PROPERTY_FIELD_LABEL(SimulationCellObject, cellVector3, "Cell vector 3"); +SET_PROPERTY_FIELD_LABEL(SimulationCellObject, cellOrigin, "Cell origin"); +SET_PROPERTY_FIELD_LABEL(SimulationCellObject, pbcX, "Periodic boundary conditions (X)"); +SET_PROPERTY_FIELD_LABEL(SimulationCellObject, pbcY, "Periodic boundary conditions (Y)"); +SET_PROPERTY_FIELD_LABEL(SimulationCellObject, pbcZ, "Periodic boundary conditions (Z)"); +SET_PROPERTY_FIELD_LABEL(SimulationCellObject, is2D, "2D"); +SET_PROPERTY_FIELD_UNITS(SimulationCellObject, cellVector1, WorldParameterUnit); +SET_PROPERTY_FIELD_UNITS(SimulationCellObject, cellVector2, WorldParameterUnit); +SET_PROPERTY_FIELD_UNITS(SimulationCellObject, cellVector3, WorldParameterUnit); +SET_PROPERTY_FIELD_UNITS(SimulationCellObject, cellOrigin, WorldParameterUnit); /****************************************************************************** * Creates the storage for the internal parameters. ******************************************************************************/ void SimulationCellObject::init(DataSet* dataset) { - INIT_PROPERTY_FIELD(SimulationCellObject::_cellVector1); - INIT_PROPERTY_FIELD(SimulationCellObject::_cellVector2); - INIT_PROPERTY_FIELD(SimulationCellObject::_cellVector3); - INIT_PROPERTY_FIELD(SimulationCellObject::_cellOrigin); - INIT_PROPERTY_FIELD(SimulationCellObject::_pbcX); - INIT_PROPERTY_FIELD(SimulationCellObject::_pbcY); - INIT_PROPERTY_FIELD(SimulationCellObject::_pbcZ); - INIT_PROPERTY_FIELD(SimulationCellObject::_is2D); + INIT_PROPERTY_FIELD(cellVector1); + INIT_PROPERTY_FIELD(cellVector2); + INIT_PROPERTY_FIELD(cellVector3); + INIT_PROPERTY_FIELD(cellOrigin); + INIT_PROPERTY_FIELD(pbcX); + INIT_PROPERTY_FIELD(pbcY); + INIT_PROPERTY_FIELD(pbcZ); + INIT_PROPERTY_FIELD(is2D); // Attach a display object. addDisplayObject(new SimulationCellDisplay(dataset)); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/SimulationCellObject.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/SimulationCellObject.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/SimulationCellObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/SimulationCellObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SIMULATION_CELL_OBJECT_H -#define __OVITO_SIMULATION_CELL_OBJECT_H +#pragma once + #include #include @@ -89,15 +89,15 @@ /// \brief Sets the cell geometry to match the given cell data structure. void setData(const SimulationCell& data, bool setBoundaryFlags = true) { - _cellVector1 = data.matrix().column(0); - _cellVector2 = data.matrix().column(1); - _cellVector3 = data.matrix().column(2); - _cellOrigin = Point3::Origin() + data.matrix().column(3); + setCellVector1(data.matrix().column(0)); + setCellVector2(data.matrix().column(1)); + setCellVector3(data.matrix().column(2)); + setCellOrigin(Point3::Origin() + data.matrix().column(3)); if(setBoundaryFlags) { - _pbcX = data.pbcFlags()[0]; - _pbcY = data.pbcFlags()[1]; - _pbcZ = data.pbcFlags()[2]; - _is2D = data.is2D(); + setPbcX(data.pbcFlags()[0]); + setPbcY(data.pbcFlags()[1]); + setPbcZ(data.pbcFlags()[2]); + setIs2D(data.is2D()); } } @@ -116,10 +116,10 @@ /// the fourth matrix column specifies the translation of the cell origin. AffineTransformation cellMatrix() const { return { - _cellVector1.value(), - _cellVector2.value(), - _cellVector3.value(), - _cellOrigin.value() - Point3::Origin() + cellVector1(), + cellVector2(), + cellVector3(), + cellOrigin() - Point3::Origin() }; } @@ -130,10 +130,10 @@ /// /// \undoable void setCellMatrix(const AffineTransformation& shape) { - _cellVector1 = shape.column(0); - _cellVector2 = shape.column(1); - _cellVector3 = shape.column(2); - _cellOrigin = Point3::Origin() + shape.column(3); + setCellVector1(shape.column(0)); + setCellVector2(shape.column(1)); + setCellVector3(shape.column(2)); + setCellOrigin(Point3::Origin() + shape.column(3)); } /// Returns inverse of the simulation cell matrix. @@ -142,43 +142,21 @@ return cellMatrix().inverse(); } - /// Returns the first cell edge vector. - const Vector3& edgeVector1() const { return _cellVector1; } - - /// Returns the second cell edge vector. - const Vector3& edgeVector2() const { return _cellVector2; } - - /// Returns the third cell edge vector. - const Vector3& edgeVector3() const { return _cellVector3; } - - /// Returns the cell origin. - const Point3& origin() const { return _cellOrigin; } - - /// Sets the first cell edge vector. - void setEdgeVector1(const Vector3& v) { _cellVector1 = v; } - - /// Sets the second cell edge vector. - void setEdgeVector2(const Vector3& v) { _cellVector2 = v; } - - /// Sets the third cell edge vector. - void setEdgeVector3(const Vector3& v) { _cellVector3 = v; } - - /// Sets the cell origin. - void setOrigin(const Point3& origin) { _cellOrigin = origin; } - /// Computes the (positive) volume of the three-dimensional cell. FloatType volume3D() const { - return std::abs(edgeVector1().dot(edgeVector2().cross(edgeVector3()))); + return std::abs(cellVector1().dot(cellVector2().cross(cellVector3()))); } /// Computes the (positive) volume of the two-dimensional cell. FloatType volume2D() const { - return edgeVector1().cross(edgeVector2()).length(); + return cellVector1().cross(cellVector2()).length(); } /// \brief Enables or disables periodic boundary conditions in the three spatial directions. void setPBCFlags(const std::array& flags) { - _pbcX = flags[0]; _pbcY = flags[1]; _pbcZ = flags[2]; + setPbcX(flags[0]); + setPbcY(flags[1]); + setPbcZ(flags[2]); } /// \brief Returns the periodic boundary flags in all three spatial directions. @@ -186,30 +164,6 @@ return {{ pbcX(), pbcY(), pbcZ() }}; } - /// \brief Returns whether periodic boundary conditions are enabled in the X direction. - bool pbcX() const { return _pbcX; } - - /// \brief Returns whether periodic boundary conditions are enabled in the X direction. - bool pbcY() const { return _pbcY; } - - /// \brief Returns whether periodic boundary conditions are enabled in the X direction. - bool pbcZ() const { return _pbcZ; } - - /// \brief Sets periodic boundary flag for the X direction. - void setPbcX(bool enable) { _pbcX = enable; } - - /// \brief Sets periodic boundary flag for the Y direction. - void setPbcY(bool enable) { _pbcY = enable; } - - /// \brief Sets periodic boundary flag for the Z direction. - void setPbcZ(bool enable) { _pbcZ = enable; } - - /// Returns whether this is a 2D system. - bool is2D() const { return _is2D; } - - /// Sets whether this is a 2D system. - void set2D(bool is2D) { _is2D = is2D; } - /// \brief Returns the title of this object. virtual QString objectTitle() override { return tr("Simulation cell"); } @@ -219,23 +173,23 @@ void init(DataSet* dataset); /// Stores the first cell edge. - PropertyField _cellVector1; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Vector3, cellVector1, setCellVector1); /// Stores the second cell edge. - PropertyField _cellVector2; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Vector3, cellVector2, setCellVector2); /// Stores the third cell edge. - PropertyField _cellVector3; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Vector3, cellVector3, setCellVector3); /// Stores the cell origin. - PropertyField _cellOrigin; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Point3, cellOrigin, setCellOrigin); /// Specifies periodic boundary condition in the X direction. - PropertyField _pbcX; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, pbcX, setPbcX); /// Specifies periodic boundary condition in the Y direction. - PropertyField _pbcY; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, pbcY, setPbcY); /// Specifies periodic boundary condition in the Z direction. - PropertyField _pbcZ; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, pbcZ, setPbcZ); /// Stores the dimensionality of the system. - PropertyField _is2D; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, is2D, setIs2D); private: @@ -243,18 +197,9 @@ OVITO_OBJECT Q_CLASSINFO("ClassNameAlias", "SimulationCell"); // This for backward compatibility with files written by Ovito 2.4 and older. - - DECLARE_PROPERTY_FIELD(_cellVector1); - DECLARE_PROPERTY_FIELD(_cellVector2); - DECLARE_PROPERTY_FIELD(_cellVector3); - DECLARE_PROPERTY_FIELD(_cellOrigin); - DECLARE_PROPERTY_FIELD(_pbcX); - DECLARE_PROPERTY_FIELD(_pbcY); - DECLARE_PROPERTY_FIELD(_pbcZ); - DECLARE_PROPERTY_FIELD(_is2D); }; } // End of namespace } // End of namespace -#endif // __OVITO_SIMULATION_CELL_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/SurfaceMesh.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/SurfaceMesh.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/SurfaceMesh.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/SurfaceMesh.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,8 +25,8 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, SurfaceMesh, DataObject); -DEFINE_PROPERTY_FIELD(SurfaceMesh, _isCompletelySolid, "IsCompletelySolid"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SurfaceMesh, DataObject); +DEFINE_PROPERTY_FIELD(SurfaceMesh, isCompletelySolid, "IsCompletelySolid"); /****************************************************************************** * Constructs an empty surface mesh object. @@ -34,7 +34,7 @@ SurfaceMesh::SurfaceMesh(DataSet* dataset, HalfEdgeMesh<>* mesh) : DataObjectWithSharedStorage(dataset, mesh ? mesh : new HalfEdgeMesh<>()), _isCompletelySolid(false) { - INIT_PROPERTY_FIELD(SurfaceMesh::_isCompletelySolid); + INIT_PROPERTY_FIELD(isCompletelySolid); } /****************************************************************************** @@ -54,7 +54,7 @@ /****************************************************************************** * Fairs a closed triangle mesh. ******************************************************************************/ -void SurfaceMesh::smoothMesh(HalfEdgeMesh<>& mesh, const SimulationCell& cell, int numIterations, FutureInterfaceBase* progress, FloatType k_PB, FloatType lambda) +bool SurfaceMesh::smoothMesh(HalfEdgeMesh<>& mesh, const SimulationCell& cell, int numIterations, PromiseBase& promise, FloatType k_PB, FloatType lambda) { // This is the implementation of the mesh smoothing algorithm: // @@ -62,15 +62,17 @@ // A Signal Processing Approach To Fair Surface Design // In SIGGRAPH 95 Conference Proceedings, pages 351-358 (1995) - FloatType mu = 1.0f / (k_PB - 1.0f/lambda); - if(progress) progress->setProgressRange(numIterations); + FloatType mu = FloatType(1) / (k_PB - FloatType(1)/lambda); + promise.setProgressMaximum(numIterations); for(int iteration = 0; iteration < numIterations; iteration++) { + if(!promise.setProgressValue(iteration)) + return false; smoothMeshIteration(mesh, lambda, cell); smoothMeshIteration(mesh, mu, cell); - if(progress && !progress->setProgressValue(iteration+1)) - return; } + + return !promise.isCanceled(); } /****************************************************************************** @@ -86,7 +88,7 @@ parallelFor(mesh.vertexCount(), [&mesh, &displacements, prefactor, cell, absoluteToReduced](int index) { HalfEdgeMesh<>::Vertex* vertex = mesh.vertex(index); Vector3 d = Vector3::Zero(); -#if 1 + // Go in positive direction around vertex, facet by facet. HalfEdgeMesh<>::Edge* currentEdge = vertex->edges(); if(currentEdge != nullptr) { @@ -100,13 +102,7 @@ while(currentEdge != vertex->edges()); d *= (prefactor / numManifoldEdges); } -#else - for(HalfEdgeMesh<>::Edge* edge = vertex->edges(); edge != nullptr; edge = edge->nextVertexEdge()) { - d += cell.wrapVector(edge->vertex2()->pos() - vertex->pos()); - } - if(vertex->edges() != nullptr) - d *= (prefactor / vertex->numEdges()); -#endif + displacements[index] = d; }); diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/SurfaceMeshDisplay.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/SurfaceMeshDisplay.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/SurfaceMeshDisplay.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/SurfaceMeshDisplay.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,23 +30,23 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, SurfaceMeshDisplay, AsynchronousDisplayObject); -DEFINE_FLAGS_PROPERTY_FIELD(SurfaceMeshDisplay, _surfaceColor, "SurfaceColor", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(SurfaceMeshDisplay, _capColor, "CapColor", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(SurfaceMeshDisplay, _showCap, "ShowCap", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(SurfaceMeshDisplay, _smoothShading, "SmoothShading"); -DEFINE_PROPERTY_FIELD(SurfaceMeshDisplay, _reverseOrientation, "ReverseOrientation"); -DEFINE_REFERENCE_FIELD(SurfaceMeshDisplay, _surfaceTransparency, "SurfaceTransparency", Controller); -DEFINE_REFERENCE_FIELD(SurfaceMeshDisplay, _capTransparency, "CapTransparency", Controller); -SET_PROPERTY_FIELD_LABEL(SurfaceMeshDisplay, _surfaceColor, "Surface color"); -SET_PROPERTY_FIELD_LABEL(SurfaceMeshDisplay, _capColor, "Cap color"); -SET_PROPERTY_FIELD_LABEL(SurfaceMeshDisplay, _showCap, "Show cap polygons"); -SET_PROPERTY_FIELD_LABEL(SurfaceMeshDisplay, _smoothShading, "Smooth shading"); -SET_PROPERTY_FIELD_LABEL(SurfaceMeshDisplay, _surfaceTransparency, "Surface transparency"); -SET_PROPERTY_FIELD_LABEL(SurfaceMeshDisplay, _capTransparency, "Cap transparency"); -SET_PROPERTY_FIELD_LABEL(SurfaceMeshDisplay, _reverseOrientation, "Inside out"); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(SurfaceMeshDisplay, _surfaceTransparency, PercentParameterUnit, 0, 1); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(SurfaceMeshDisplay, _capTransparency, PercentParameterUnit, 0, 1); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(SurfaceMeshDisplay, AsynchronousDisplayObject); +DEFINE_FLAGS_PROPERTY_FIELD(SurfaceMeshDisplay, surfaceColor, "SurfaceColor", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(SurfaceMeshDisplay, capColor, "CapColor", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(SurfaceMeshDisplay, showCap, "ShowCap", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(SurfaceMeshDisplay, smoothShading, "SmoothShading"); +DEFINE_PROPERTY_FIELD(SurfaceMeshDisplay, reverseOrientation, "ReverseOrientation"); +DEFINE_REFERENCE_FIELD(SurfaceMeshDisplay, surfaceTransparencyController, "SurfaceTransparency", Controller); +DEFINE_REFERENCE_FIELD(SurfaceMeshDisplay, capTransparencyController, "CapTransparency", Controller); +SET_PROPERTY_FIELD_LABEL(SurfaceMeshDisplay, surfaceColor, "Surface color"); +SET_PROPERTY_FIELD_LABEL(SurfaceMeshDisplay, capColor, "Cap color"); +SET_PROPERTY_FIELD_LABEL(SurfaceMeshDisplay, showCap, "Show cap polygons"); +SET_PROPERTY_FIELD_LABEL(SurfaceMeshDisplay, smoothShading, "Smooth shading"); +SET_PROPERTY_FIELD_LABEL(SurfaceMeshDisplay, surfaceTransparencyController, "Surface transparency"); +SET_PROPERTY_FIELD_LABEL(SurfaceMeshDisplay, capTransparencyController, "Cap transparency"); +SET_PROPERTY_FIELD_LABEL(SurfaceMeshDisplay, reverseOrientation, "Inside out"); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(SurfaceMeshDisplay, surfaceTransparencyController, PercentParameterUnit, 0, 1); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(SurfaceMeshDisplay, capTransparencyController, PercentParameterUnit, 0, 1); /****************************************************************************** * Constructor. @@ -54,16 +54,16 @@ SurfaceMeshDisplay::SurfaceMeshDisplay(DataSet* dataset) : AsynchronousDisplayObject(dataset), _surfaceColor(1, 1, 1), _capColor(0.8, 0.8, 1.0), _showCap(true), _smoothShading(true), _trimeshUpdate(true), _reverseOrientation(false) { - INIT_PROPERTY_FIELD(SurfaceMeshDisplay::_surfaceColor); - INIT_PROPERTY_FIELD(SurfaceMeshDisplay::_capColor); - INIT_PROPERTY_FIELD(SurfaceMeshDisplay::_showCap); - INIT_PROPERTY_FIELD(SurfaceMeshDisplay::_smoothShading); - INIT_PROPERTY_FIELD(SurfaceMeshDisplay::_surfaceTransparency); - INIT_PROPERTY_FIELD(SurfaceMeshDisplay::_capTransparency); - INIT_PROPERTY_FIELD(SurfaceMeshDisplay::_reverseOrientation); + INIT_PROPERTY_FIELD(surfaceColor); + INIT_PROPERTY_FIELD(capColor); + INIT_PROPERTY_FIELD(showCap); + INIT_PROPERTY_FIELD(smoothShading); + INIT_PROPERTY_FIELD(surfaceTransparencyController); + INIT_PROPERTY_FIELD(capTransparencyController); + INIT_PROPERTY_FIELD(reverseOrientation); - _surfaceTransparency = ControllerManager::instance().createFloatController(dataset); - _capTransparency = ControllerManager::instance().createFloatController(dataset); + setSurfaceTransparencyController(ControllerManager::createFloatController(dataset)); + setCapTransparencyController(ControllerManager::createFloatController(dataset)); } /****************************************************************************** @@ -155,17 +155,17 @@ FloatType transp_surface = 0; FloatType transp_cap = 0; TimeInterval iv; - if(_surfaceTransparency) transp_surface = _surfaceTransparency->getFloatValue(time, iv); - if(_capTransparency) transp_cap = _capTransparency->getFloatValue(time, iv); - ColorA color_surface(surfaceColor(), 1.0f - transp_surface); - ColorA color_cap(capColor(), 1.0f - transp_cap); + if(surfaceTransparencyController()) transp_surface = surfaceTransparencyController()->getFloatValue(time, iv); + if(capTransparencyController()) transp_cap = capTransparencyController()->getFloatValue(time, iv); + ColorA color_surface(surfaceColor(), FloatType(1) - transp_surface); + ColorA color_cap(capColor(), FloatType(1) - transp_cap); // Do we have to re-create the render primitives from scratch? bool recreateSurfaceBuffer = !_surfaceBuffer || !_surfaceBuffer->isValid(renderer); - bool recreateCapBuffer = _showCap && (!_capBuffer || !_capBuffer->isValid(renderer)); + bool recreateCapBuffer = showCap() && (!_capBuffer || !_capBuffer->isValid(renderer)); // Do we have to update the render primitives? - bool updateContents = _geometryCacheHelper.updateState(color_surface, color_cap, _smoothShading) + bool updateContents = _geometryCacheHelper.updateState(color_surface, color_cap, smoothShading()) || recreateSurfaceBuffer || recreateCapBuffer || _trimeshUpdate; // Re-create the render primitives if necessary. @@ -178,12 +178,12 @@ if(updateContents) { // Assign smoothing group to faces to interpolate normals. - const quint32 smoothingGroup = _smoothShading ? 1 : 0; + const quint32 smoothingGroup = smoothShading() ? 1 : 0; for(auto& face : _surfaceMesh.faces()) face.setSmoothingGroups(smoothingGroup); _surfaceBuffer->setMesh(_surfaceMesh, color_surface); - if(_showCap) + if(showCap()) _capBuffer->setMesh(_capPolygonsMesh, color_cap); // Reset update flag. @@ -193,7 +193,7 @@ // Handle picking of triangles. renderer->beginPickObject(contextNode); _surfaceBuffer->render(renderer); - if(_showCap) + if(showCap()) _capBuffer->render(renderer); else _capBuffer.reset(); @@ -203,8 +203,11 @@ /****************************************************************************** * Generates the final triangle mesh, which will be rendered. ******************************************************************************/ -bool SurfaceMeshDisplay::buildSurfaceMesh(const HalfEdgeMesh<>& input, const SimulationCell& cell, bool reverseOrientation, const QVector& cuttingPlanes, TriMesh& output, FutureInterfaceBase* progress) +bool SurfaceMeshDisplay::buildSurfaceMesh(const HalfEdgeMesh<>& input, const SimulationCell& cell, bool reverseOrientation, const QVector& cuttingPlanes, TriMesh& output, PromiseBase* progress) { + if(cell.is2D()) + throw Exception(tr("Cannot generate surface triangle mesh when simulation cell is two-dimensional.")); + // Convert half-edge mesh to triangle mesh. input.convertToTriMesh(output); @@ -293,14 +296,14 @@ OVITO_ASSERT(z[2] - z[1] == -(z[1] - z[2])); OVITO_ASSERT(z[0] - z[2] == -(z[2] - z[0])); - if(std::abs(zd[0]) < 0.5f && std::abs(zd[1]) < 0.5f && std::abs(zd[2]) < 0.5f) + if(std::abs(zd[0]) < FloatType(0.5) && std::abs(zd[1]) < FloatType(0.5) && std::abs(zd[2]) < FloatType(0.5)) return true; // Face is not crossing the periodic boundary. // Create four new vertices (or use existing ones created during splitting of adjacent faces). int properEdge = -1; int newVertexIndices[3][2]; for(int i = 0; i < 3; i++) { - if(std::abs(zd[i]) < 0.5f) { + if(std::abs(zd[i]) < FloatType(0.5)) { if(properEdge != -1) return false; // The simulation box may be too small or invalid. properEdge = i; @@ -309,7 +312,7 @@ int vi1 = face.vertex(i); int vi2 = face.vertex((i+1)%3); int oi1, oi2; - if(zd[i] <= -0.5f) { + if(zd[i] <= FloatType(-0.5)) { std::swap(vi1, vi2); oi1 = 1; oi2 = 0; } @@ -323,7 +326,7 @@ } else { Vector3 delta = output.vertex(vi2) - output.vertex(vi1); - delta[dim] -= 1.0f; + delta[dim] -= FloatType(1); for(size_t d = dim + 1; d < 3; d++) { if(cell.pbcFlags()[d]) delta[d] -= floor(delta[d] + FloatType(0.5)); @@ -332,14 +335,14 @@ if(delta[dim] != 0) t = output.vertex(vi1)[dim] / (-delta[dim]); else - t = 0.5f; + t = FloatType(0.5); OVITO_ASSERT(std::isfinite(t)); Point3 p = delta * t + output.vertex(vi1); newVertexIndices[i][oi1] = oldVertexCount + (int)newVertices.size(); newVertexIndices[i][oi2] = oldVertexCount + (int)newVertices.size() + 1; newVertexLookupMap.insert(std::make_pair(std::pair(vi1, vi2), std::pair(newVertexIndices[i][oi1], newVertexIndices[i][oi2]))); newVertices.push_back(p); - p[dim] += 1.0f; + p[dim] += FloatType(1); newVertices.push_back(p); } } @@ -361,7 +364,7 @@ /****************************************************************************** * Generates the triangle mesh for the PBC caps. ******************************************************************************/ -void SurfaceMeshDisplay::buildCapMesh(const HalfEdgeMesh<>& input, const SimulationCell& cell, bool isCompletelySolid, bool reverseOrientation, const QVector& cuttingPlanes, TriMesh& output, FutureInterfaceBase* progress) +void SurfaceMeshDisplay::buildCapMesh(const HalfEdgeMesh<>& input, const SimulationCell& cell, bool isCompletelySolid, bool reverseOrientation, const QVector& cuttingPlanes, TriMesh& output, PromiseBase* promise) { // Convert vertex positions to reduced coordinates. std::vector reducedPos(input.vertexCount()); @@ -375,7 +378,7 @@ for(size_t dim = 0; dim < 3; dim++) { if(cell.pbcFlags()[dim] == false) continue; - if(progress && progress->isCanceled()) + if(promise && promise->isCanceled()) return; // Make sure all vertices are located inside the periodic box. @@ -395,6 +398,8 @@ // Find a first edge that crosses the boundary. for(HalfEdgeMesh<>::Vertex* vert : input.vertices()) { + if(promise && promise->isCanceled()) + return; for(HalfEdgeMesh<>::Edge* edge = vert->edges(); edge != nullptr; edge = edge->nextVertexEdge()) { // Skip faces that have already been visited. if(edge->face()->testFlag(1)) continue; @@ -403,6 +408,7 @@ const Point3& v2 = reducedPos[edge->vertex2()->index()]; if(v2[dim] - v1[dim] >= FloatType(0.5)) { std::vector contour = traceContour(edge, reducedPos, cell, dim); + if(contour.empty()) throw Exception(tr("Surface mesh is not a proper manifold.")); clipContour(contour, std::array{{ cell.pbcFlags()[(dim+1)%3], cell.pbcFlags()[(dim+2)%3] }}, openContours, closedContours); } } @@ -417,9 +423,12 @@ CapPolygonTessellator tessellator(output, dim); tessellator.beginPolygon(); for(const auto& contour : closedContours) { + if(promise && promise->isCanceled()) + return; tessellator.beginContour(); - for(const Point2& p : contour) + for(const Point2& p : contour) { tessellator.vertex(p); + } tessellator.endContour(); } @@ -427,20 +436,23 @@ if(!openContours.empty()) { boost::dynamic_bitset<> visitedContours(openContours.size()); for(auto c1 = openContours.begin(); c1 != openContours.end(); ++c1) { + if(promise && promise->isCanceled()) + return; if(!visitedContours.test(c1 - openContours.begin())) { tessellator.beginContour(); auto currentContour = c1; do { - for(const Point2& p : *currentContour) + for(const Point2& p : *currentContour) { tessellator.vertex(p); + } visitedContours.set(currentContour - openContours.begin()); FloatType exitSide = 0; if(currentContour->back().x() == 0) exitSide = currentContour->back().y(); - else if(currentContour->back().y() == 1) exitSide = currentContour->back().x() + 1.0f; - else if(currentContour->back().x() == 1) exitSide = 3.0f - currentContour->back().y(); - else if(currentContour->back().y() == 0) exitSide = 4.0f - currentContour->back().x(); - if(exitSide >= 4.0f) exitSide = 0.0f; + else if(currentContour->back().y() == 1) exitSide = currentContour->back().x() + FloatType(1); + else if(currentContour->back().x() == 1) exitSide = FloatType(3) - currentContour->back().y(); + else if(currentContour->back().y() == 0) exitSide = FloatType(4) - currentContour->back().x(); + if(exitSide >= FloatType(4)) exitSide = 0; // Find the next contour. FloatType entrySide; @@ -448,12 +460,12 @@ for(auto c = openContours.begin(); c != openContours.end(); ++c) { FloatType pos = 0; if(c->front().x() == 0) pos = c->front().y(); - else if(c->front().y() == 1) pos = c->front().x() + 1.0f; - else if(c->front().x() == 1) pos = 3.0f - c->front().y(); - else if(c->front().y() == 0) pos = 4.0f - c->front().x(); - if(pos >= 4.0f) pos = 0.0f; + else if(c->front().y() == 1) pos = c->front().x() + FloatType(1); + else if(c->front().x() == 1) pos = FloatType(3) - c->front().y(); + else if(c->front().y() == 0) pos = FloatType(4) - c->front().x(); + if(pos >= FloatType(4)) pos = 0; FloatType dist = exitSide - pos; - if(dist < 0.0f) dist += 4.0f; + if(dist < 0) dist += FloatType(4); if(dist < closestDist) { closestDist = dist; currentContour = c; @@ -505,7 +517,7 @@ } // Check for early abortion. - if(progress && progress->isCanceled()) + if(promise && promise->isCanceled()) return; // Convert vertex positions back from reduced coordinates to absolute coordinates. @@ -515,9 +527,8 @@ // Clip mesh at cutting planes. for(const Plane3& plane : cuttingPlanes) { - if(progress && progress->isCanceled()) + if(promise && promise->isCanceled()) return; - output.clipAtPlane(plane); } } @@ -532,6 +543,7 @@ std::vector contour; HalfEdgeMesh<>::Edge* edge = firstEdge; do { + OVITO_ASSERT(edge->face() != nullptr); OVITO_ASSERT(!edge->face()->testFlag(1)); // Mark face as visited. @@ -541,9 +553,9 @@ const Point3& v1 = reducedPos[edge->vertex1()->index()]; const Point3& v2 = reducedPos[edge->vertex2()->index()]; Vector3 delta = v2 - v1; - OVITO_ASSERT(delta[dim] >= 0.5f); + OVITO_ASSERT(delta[dim] >= FloatType(0.5)); - delta[dim] -= 1.0f; + delta[dim] -= FloatType(1); if(cell.pbcFlags()[dim1]) { FloatType& c = delta[dim1]; if(FloatType s = floor(c + FloatType(0.5))) @@ -554,26 +566,43 @@ if(FloatType s = floor(c + FloatType(0.5))) c -= s; } - FloatType t; - if(std::abs(delta[dim]) > FloatType(1e-9f)) - t = v1[dim] / delta[dim]; - else - t = FloatType(0.5); - FloatType x = v1[dim1] - delta[dim1] * t; - FloatType y = v1[dim2] - delta[dim2] * t; - OVITO_ASSERT(std::isfinite(x) && std::isfinite(y)); - contour.push_back({x,y}); + if(std::abs(delta[dim]) > FloatType(1e-9f)) { + FloatType t = v1[dim] / delta[dim]; + FloatType x = v1[dim1] - delta[dim1] * t; + FloatType y = v1[dim2] - delta[dim2] * t; + OVITO_ASSERT(std::isfinite(x) && std::isfinite(y)); + if(contour.empty() || std::abs(x - contour.back().x()) > FLOATTYPE_EPSILON || std::abs(y - contour.back().y()) > FLOATTYPE_EPSILON) { + contour.push_back({x,y}); + } + } + else { + FloatType x1 = v1[dim1]; + FloatType y1 = v1[dim2]; + FloatType x2 = v1[dim1] + delta[dim1]; + FloatType y2 = v1[dim2] + delta[dim2]; + if(contour.empty() || std::abs(x1 - contour.back().x()) > FLOATTYPE_EPSILON || std::abs(y1 - contour.back().y()) > FLOATTYPE_EPSILON) { + contour.push_back({x1,y1}); + } + else if(contour.empty() || std::abs(x2 - contour.back().x()) > FLOATTYPE_EPSILON || std::abs(y2 - contour.back().y()) > FLOATTYPE_EPSILON) { + contour.push_back({x2,y2}); + } + } // Find the face edge that crosses the boundary in the reverse direction. for(;;) { edge = edge->nextFaceEdge(); const Point3& v1 = reducedPos[edge->vertex1()->index()]; const Point3& v2 = reducedPos[edge->vertex2()->index()]; - if(v2[dim] - v1[dim] <= -0.5f) + if(v2[dim] - v1[dim] <= FloatType(-0.5)) break; } edge = edge->oppositeEdge(); + if(!edge) { + // Mesh is not closed (not a proper manifold). + contour.clear(); + break; + } } while(edge != firstEdge); @@ -612,43 +641,50 @@ contours.back().push_back(*v1); Vector2 delta = (*v2) - (*v1); - if(std::abs(delta.x()) < 0.5f && std::abs(delta.y()) < 0.5f) + if(std::abs(delta.x()) < FloatType(0.5) && std::abs(delta.y()) < FloatType(0.5)) continue; - FloatType t[2] = { 1.0f, 1.0f }; + FloatType t[2] = { 2, 2 }; Vector2I crossDir(0, 0); for(size_t dim = 0; dim < 2; dim++) { if(pbcFlags[dim]) { - if(delta[dim] >= 0.5f) { - delta[dim] -= 1.0f; + if(delta[dim] >= FloatType(0.5)) { + delta[dim] -= FloatType(1); if(std::abs(delta[dim]) > FLOATTYPE_EPSILON) t[dim] = std::min((*v1)[dim] / -delta[dim], FloatType(1)); else - t[dim] = 0.5f; + t[dim] = FloatType(0.5); crossDir[dim] = -1; + OVITO_ASSERT(t[dim] >= 0 && t[dim] <= 1); } - else if(delta[dim] <= -0.5f) { - delta[dim] += 1.0f; + else if(delta[dim] <= FloatType(-0.5)) { + delta[dim] += FloatType(1); if(std::abs(delta[dim]) > FLOATTYPE_EPSILON) - t[dim] = std::max((1.0f - (*v1)[dim]) / delta[dim], FloatType(0)); + t[dim] = std::max((FloatType(1) - (*v1)[dim]) / delta[dim], FloatType(0)); else - t[dim] = 0.5f; + t[dim] = FloatType(0.5); crossDir[dim] = +1; + OVITO_ASSERT(t[dim] >= 0 && t[dim] <= 1); } - OVITO_ASSERT(t[dim] >= 0 && t[dim] <= 1); } } Point2 base = *v1; if(t[0] < t[1]) { + OVITO_ASSERT(t[0] <= 1); computeContourIntersection(0, t[0], base, delta, crossDir[0], contours); - if(crossDir[1] != 0) + if(crossDir[1] != 0) { + OVITO_ASSERT(t[1] <= 1); computeContourIntersection(1, t[1], base, delta, crossDir[1], contours); + } } else if(t[1] < t[0]) { + OVITO_ASSERT(t[1] <= 1); computeContourIntersection(1, t[1], base, delta, crossDir[1], contours); - if(crossDir[0] != 0) + if(crossDir[0] != 0) { + OVITO_ASSERT(t[0] <= 1); computeContourIntersection(0, t[0], base, delta, crossDir[0], contours); + } } } @@ -659,7 +695,14 @@ auto& firstSegment = contours.front(); auto& lastSegment = contours.back(); firstSegment.insert(firstSegment.begin(), lastSegment.begin(), lastSegment.end()); - openContours.insert(openContours.begin(), std::make_move_iterator(contours.begin()), std::make_move_iterator(contours.end() - 1)); + contours.pop_back(); + for(auto& contour : contours) { + bool isDegenerate = std::all_of(contour.begin(), contour.end(), [&contour](const Point2& p) { + return p.equals(contour.front()); + }); + if(!isDegenerate) + openContours.push_back(std::move(contour)); + } } } @@ -671,12 +714,12 @@ { OVITO_ASSERT(std::isfinite(t)); Point2 intersection = base + t * delta; - intersection[dim] = (crossDir == -1) ? 0.0f : 1.0f; + intersection[dim] = (crossDir == -1) ? 0 : 1; contours.back().push_back(intersection); - intersection[dim] = (crossDir == +1) ? 0.0f : 1.0f; + intersection[dim] = (crossDir == +1) ? 0 : 1; contours.push_back({intersection}); base = intersection; - delta *= (1.0f - t); + delta *= (FloatType(1) - t); } /****************************************************************************** @@ -774,6 +817,7 @@ // Check if any edge is closer to the test point than the closest vertex. for(HalfEdgeMesh<>::Vertex* v : mesh.vertices()) { for(HalfEdgeMesh<>::Edge* edge = v->edges(); edge != nullptr; edge = edge->nextVertexEdge()) { + OVITO_ASSERT_MSG(edge->oppositeEdge() != nullptr, "SurfaceMeshDisplay::isCornerInside3DRegion", "Surface mesh is not fully closed. This should not happen."); const Point3& p1 = reducedPos[edge->vertex1()->index()]; const Point3& p2 = reducedPos[edge->vertex2()->index()]; Vector3 edgeDir = p2 - p1; diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/SurfaceMeshDisplay.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/SurfaceMeshDisplay.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/SurfaceMeshDisplay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/SurfaceMeshDisplay.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SURFACE_MESH_DISPLAY_H -#define __OVITO_SURFACE_MESH_DISPLAY_H +#pragma once + #include #include @@ -49,53 +49,23 @@ /// \brief Computes the bounding box of the object. virtual Box3 boundingBox(TimePoint time, DataObject* dataObject, ObjectNode* contextNode, const PipelineFlowState& flowState) override; - /// Returns the color of the surface. - const Color& surfaceColor() const { return _surfaceColor; } - - /// Sets the color of the surface. - void setSurfaceColor(const Color& color) { _surfaceColor = color; } - - /// Returns the color of the cap polygons. - const Color& capColor() const { return _capColor; } - - /// Sets the color of the cap polygons. - void setCapColor(const Color& color) { _capColor = color; } - - /// Returns whether the cap polygons are rendered. - bool showCap() const { return _showCap; } - - /// Sets whether the cap polygons are rendered. - void setShowCap(bool show) { _showCap = show; } - - /// Returns whether the surface mesh is rendered using smooth shading. - bool smoothShading() const { return _smoothShading; } - - /// Sets whether the surface mesh is rendered using smooth shading. - void setSmoothShading(bool smoothShading) { _smoothShading = smoothShading; } - /// Returns the transparency of the surface mesh. - FloatType surfaceTransparency() const { return _surfaceTransparency ? _surfaceTransparency->currentFloatValue() : 0.0f; } + FloatType surfaceTransparency() const { return surfaceTransparencyController() ? surfaceTransparencyController()->currentFloatValue() : 0.0f; } /// Sets the transparency of the surface mesh. - void setSurfaceTransparency(FloatType transparency) { if(_surfaceTransparency) _surfaceTransparency->setCurrentFloatValue(transparency); } + void setSurfaceTransparency(FloatType transparency) { if(surfaceTransparencyController()) surfaceTransparencyController()->setCurrentFloatValue(transparency); } /// Returns the transparency of the surface cap mesh. - FloatType capTransparency() const { return _capTransparency ? _capTransparency->currentFloatValue() : 0.0f; } + FloatType capTransparency() const { return capTransparencyController() ? capTransparencyController()->currentFloatValue() : 0.0f; } /// Sets the transparency of the surface cap mesh. - void setCapTransparency(FloatType transparency) { if(_capTransparency) _capTransparency->setCurrentFloatValue(transparency); } - - /// Returns whether the mesh' orientation is flipped. - bool reverseOrientation() const { return _reverseOrientation; } - - /// Sets whether the mesh' orientation is flipped. - void setReverseOrientation(bool reverse) { _reverseOrientation = reverse; } + void setCapTransparency(FloatType transparency) { if(capTransparencyController()) capTransparencyController()->setCurrentFloatValue(transparency); } /// Generates the final triangle mesh, which will be rendered. - static bool buildSurfaceMesh(const HalfEdgeMesh<>& input, const SimulationCell& cell, bool reverseOrientation, const QVector& cuttingPlanes, TriMesh& output, FutureInterfaceBase* progress = nullptr); + static bool buildSurfaceMesh(const HalfEdgeMesh<>& input, const SimulationCell& cell, bool reverseOrientation, const QVector& cuttingPlanes, TriMesh& output, PromiseBase* progress = nullptr); /// Generates the triangle mesh for the PBC cap. - static void buildCapMesh(const HalfEdgeMesh<>& input, const SimulationCell& cell, bool isCompletelySolid, bool reverseOrientation, const QVector& cuttingPlanes, TriMesh& output, FutureInterfaceBase* progress = nullptr); + static void buildCapMesh(const HalfEdgeMesh<>& input, const SimulationCell& cell, bool isCompletelySolid, bool reverseOrientation, const QVector& cuttingPlanes, TriMesh& output, PromiseBase* progress = nullptr); protected: @@ -152,25 +122,25 @@ static bool isCornerInside3DRegion(const HalfEdgeMesh<>& mesh, const std::vector& reducedPos, const std::array pbcFlags, bool isCompletelySolid); /// Controls the display color of the surface mesh. - PropertyField _surfaceColor; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, surfaceColor, setSurfaceColor); /// Controls the display color of the cap mesh. - PropertyField _capColor; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, capColor, setCapColor); /// Controls whether the cap mesh is rendered. - PropertyField _showCap; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, showCap, setShowCap); /// Controls whether the surface mesh is rendered using smooth shading. - PropertyField _smoothShading; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, smoothShading, setSmoothShading); /// Controls whether the mesh' orientation is flipped. - PropertyField _reverseOrientation; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, reverseOrientation, setReverseOrientation); /// Controls the transparency of the surface mesh. - ReferenceField _surfaceTransparency; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, surfaceTransparencyController, setSurfaceTransparencyController); /// Controls the transparency of the surface cap mesh. - ReferenceField _capTransparency; + DECLARE_MODIFIABLE_REFERENCE_FIELD(Controller, capTransparencyController, setCapTransparencyController); /// The buffered geometry used to render the surface mesh. std::shared_ptr _surfaceBuffer; @@ -209,17 +179,9 @@ OVITO_OBJECT Q_CLASSINFO("DisplayName", "Surface mesh"); - - DECLARE_PROPERTY_FIELD(_surfaceColor); - DECLARE_PROPERTY_FIELD(_capColor); - DECLARE_PROPERTY_FIELD(_showCap); - DECLARE_PROPERTY_FIELD(_smoothShading); - DECLARE_PROPERTY_FIELD(_reverseOrientation); - DECLARE_REFERENCE_FIELD(_surfaceTransparency); - DECLARE_REFERENCE_FIELD(_capTransparency); }; } // End of namespace } // End of namespace -#endif // __OVITO_SURFACE_MESH_DISPLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/SurfaceMesh.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/SurfaceMesh.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/SurfaceMesh.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/SurfaceMesh.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,14 +19,14 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_SURFACE_MESH_H -#define __OVITO_SURFACE_MESH_H +#pragma once + #include #include #include #include -#include +#include namespace Ovito { namespace Particles { @@ -49,12 +49,6 @@ /// Return false because this object cannot be edited. virtual bool isSubObjectEditable() const override { return false; } - /// Indicates whether the entire simulation cell is part of the solid region. - bool isCompletelySolid() const { return _isCompletelySolid; } - - /// Sets whether the entire simulation cell is part of the solid region. - void setCompletelySolid(bool flag) { _isCompletelySolid = flag; } - /// Returns the planar cuts applied to this mesh. const QVector& cuttingPlanes() const { return _cuttingPlanes; } @@ -65,13 +59,15 @@ } /// Fairs the triangle mesh stored in this object. - void smoothMesh(const SimulationCell& cell, int numIterations, FutureInterfaceBase* progress = nullptr, FloatType k_PB = 0.1f, FloatType lambda = 0.5f) { - smoothMesh(*modifiableStorage(), cell, numIterations, progress, k_PB, lambda); + bool smoothMesh(const SimulationCell& cell, int numIterations, PromiseBase& promise, FloatType k_PB = FloatType(0.1), FloatType lambda = FloatType(0.5)) { + if(!smoothMesh(*modifiableStorage(), cell, numIterations, promise, k_PB, lambda)) + return false; changed(); + return true; } /// Fairs a triangle mesh. - static void smoothMesh(HalfEdgeMesh<>& mesh, const SimulationCell& cell, int numIterations, FutureInterfaceBase* progress = nullptr, FloatType k_PB = 0.1f, FloatType lambda = 0.5f); + static bool smoothMesh(HalfEdgeMesh<>& mesh, const SimulationCell& cell, int numIterations, PromiseBase& promise, FloatType k_PB = FloatType(0.1), FloatType lambda = FloatType(0.5)); protected: @@ -84,18 +80,16 @@ private: /// Indicates that the entire simulation cell is part of the solid region. - PropertyField _isCompletelySolid; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, isCompletelySolid, setIsCompletelySolid); /// The planar cuts applied to this mesh. QVector _cuttingPlanes; Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_isCompletelySolid); }; } // End of namespace } // End of namespace -#endif // __OVITO_SURFACE_MESH_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/TrajectoryDisplay.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/TrajectoryDisplay.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/TrajectoryDisplay.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/TrajectoryDisplay.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,16 +26,16 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, TrajectoryDisplay, DisplayObject); -DEFINE_FLAGS_PROPERTY_FIELD(TrajectoryDisplay, _lineWidth, "LineWidth", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TrajectoryDisplay, _lineColor, "LineColor", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TrajectoryDisplay, _shadingMode, "ShadingMode", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(TrajectoryDisplay, _showUpToCurrentTime, "ShowUpToCurrentTime"); -SET_PROPERTY_FIELD_LABEL(TrajectoryDisplay, _lineWidth, "Line width"); -SET_PROPERTY_FIELD_LABEL(TrajectoryDisplay, _lineColor, "Line color"); -SET_PROPERTY_FIELD_LABEL(TrajectoryDisplay, _shadingMode, "Shading mode"); -SET_PROPERTY_FIELD_LABEL(TrajectoryDisplay, _showUpToCurrentTime, "Show up to current time only"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(TrajectoryDisplay, _lineWidth, WorldParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(TrajectoryDisplay, DisplayObject); +DEFINE_FLAGS_PROPERTY_FIELD(TrajectoryDisplay, lineWidth, "LineWidth", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TrajectoryDisplay, lineColor, "LineColor", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TrajectoryDisplay, shadingMode, "ShadingMode", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(TrajectoryDisplay, showUpToCurrentTime, "ShowUpToCurrentTime"); +SET_PROPERTY_FIELD_LABEL(TrajectoryDisplay, lineWidth, "Line width"); +SET_PROPERTY_FIELD_LABEL(TrajectoryDisplay, lineColor, "Line color"); +SET_PROPERTY_FIELD_LABEL(TrajectoryDisplay, shadingMode, "Shading mode"); +SET_PROPERTY_FIELD_LABEL(TrajectoryDisplay, showUpToCurrentTime, "Show up to current time only"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(TrajectoryDisplay, lineWidth, WorldParameterUnit, 0); /****************************************************************************** * Constructor. @@ -44,10 +44,10 @@ _lineWidth(0.2), _lineColor(0.6, 0.6, 0.6), _shadingMode(ArrowPrimitive::FlatShading), _showUpToCurrentTime(false) { - INIT_PROPERTY_FIELD(TrajectoryDisplay::_lineWidth); - INIT_PROPERTY_FIELD(TrajectoryDisplay::_lineColor); - INIT_PROPERTY_FIELD(TrajectoryDisplay::_shadingMode); - INIT_PROPERTY_FIELD(TrajectoryDisplay::_showUpToCurrentTime); + INIT_PROPERTY_FIELD(lineWidth); + INIT_PROPERTY_FIELD(lineColor); + INIT_PROPERTY_FIELD(shadingMode); + INIT_PROPERTY_FIELD(showUpToCurrentTime); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/TrajectoryDisplay.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/TrajectoryDisplay.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/TrajectoryDisplay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/TrajectoryDisplay.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TRAJECTORY_DISPLAY_H -#define __OVITO_TRAJECTORY_DISPLAY_H +#pragma once + #include #include @@ -46,30 +46,6 @@ /// \brief Computes the display bounding box of the data object. virtual Box3 boundingBox(TimePoint time, DataObject* dataObject, ObjectNode* contextNode, const PipelineFlowState& flowState) override; - /// \brief Returns the display width of trajectory lines. - FloatType lineWidth() const { return _lineWidth; } - - /// \brief Sets the display width of trajectory lines. - void setLineWidth(FloatType newWidth) { _lineWidth = newWidth; } - - /// \brief Returns the selected shading mode for trajectory lines. - ArrowPrimitive::ShadingMode shadingMode() const { return _shadingMode; } - - /// \brief Sets the shading mode for trajectory lines. - void setShadingMode(ArrowPrimitive::ShadingMode mode) { _shadingMode = mode; } - - /// Returns the display color for trajectory lines. - const Color& lineColor() const { return _lineColor; } - - /// Sets the display color for trajectory lines. - void setLineColor(const Color& color) { _lineColor = color; } - - /// Returns the whether the trajectory lines are rendered only up to the current animation time. - bool showUpToCurrentTime() const { return _showUpToCurrentTime; } - - /// Sets the whether the trajectory lines are rendered only up to the current animation time. - void setShowUpToCurrentTime(bool enable) { _showUpToCurrentTime = enable; } - public: Q_PROPERTY(Ovito::ArrowPrimitive::ShadingMode shadingMode READ shadingMode WRITE setShadingMode); @@ -77,16 +53,16 @@ protected: /// Controls the display width of trajectory lines. - PropertyField _lineWidth; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, lineWidth, setLineWidth); /// Controls the color of the trajectory lines. - PropertyField _lineColor; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, lineColor, setLineColor); /// Controls the whether the trajectory lines are rendered only up to the current animation time. - PropertyField _showUpToCurrentTime; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, showUpToCurrentTime, setShowUpToCurrentTime); /// Controls the shading mode for lines. - PropertyField _shadingMode; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ArrowPrimitive::ShadingMode, shadingMode, setShadingMode); /// The buffered geometry used to render the trajectory lines. std::shared_ptr _segmentBuffer; @@ -119,14 +95,9 @@ OVITO_OBJECT Q_CLASSINFO("DisplayName", "Trajectory lines"); - - DECLARE_PROPERTY_FIELD(_lineWidth); - DECLARE_PROPERTY_FIELD(_lineColor); - DECLARE_PROPERTY_FIELD(_shadingMode); - DECLARE_PROPERTY_FIELD(_showUpToCurrentTime); }; } // End of namespace } // End of namespace -#endif // __OVITO_TRAJECTORY_DISPLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/TrajectoryGeneratorObject.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/TrajectoryGeneratorObject.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/TrajectoryGeneratorObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/TrajectoryGeneratorObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,32 +23,34 @@ #include #include #include +#include #include -#include +#include +#include #include #include #include "TrajectoryGeneratorObject.h" namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, TrajectoryGeneratorObject, TrajectoryObject); -DEFINE_FLAGS_REFERENCE_FIELD(TrajectoryGeneratorObject, _source, "ParticleSource", ObjectNode, PROPERTY_FIELD_NEVER_CLONE_TARGET | PROPERTY_FIELD_NO_SUB_ANIM); -DEFINE_PROPERTY_FIELD(TrajectoryGeneratorObject, _onlySelectedParticles, "OnlySelectedParticles"); -DEFINE_PROPERTY_FIELD(TrajectoryGeneratorObject, _useCustomInterval, "UseCustomInterval"); -DEFINE_PROPERTY_FIELD(TrajectoryGeneratorObject, _customIntervalStart, "CustomIntervalStart"); -DEFINE_PROPERTY_FIELD(TrajectoryGeneratorObject, _customIntervalEnd, "CustomIntervalEnd"); -DEFINE_PROPERTY_FIELD(TrajectoryGeneratorObject, _everyNthFrame, "EveryNthFrame"); -DEFINE_PROPERTY_FIELD(TrajectoryGeneratorObject, _unwrapTrajectories, "UnwrapTrajectories"); -SET_PROPERTY_FIELD_LABEL(TrajectoryGeneratorObject, _source, "Source"); -SET_PROPERTY_FIELD_LABEL(TrajectoryGeneratorObject, _onlySelectedParticles, "Only selected particles"); -SET_PROPERTY_FIELD_LABEL(TrajectoryGeneratorObject, _useCustomInterval, "Custom time interval"); -SET_PROPERTY_FIELD_LABEL(TrajectoryGeneratorObject, _customIntervalStart, "Custom interval start"); -SET_PROPERTY_FIELD_LABEL(TrajectoryGeneratorObject, _customIntervalEnd, "Custom interval end"); -SET_PROPERTY_FIELD_LABEL(TrajectoryGeneratorObject, _everyNthFrame, "Every Nth frame"); -SET_PROPERTY_FIELD_LABEL(TrajectoryGeneratorObject, _unwrapTrajectories, "Unwrap trajectories"); -SET_PROPERTY_FIELD_UNITS(TrajectoryGeneratorObject, _customIntervalStart, TimeParameterUnit); -SET_PROPERTY_FIELD_UNITS(TrajectoryGeneratorObject, _customIntervalEnd, TimeParameterUnit); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(TrajectoryGeneratorObject, _everyNthFrame, IntegerParameterUnit, 1); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(TrajectoryGeneratorObject, TrajectoryObject); +DEFINE_FLAGS_REFERENCE_FIELD(TrajectoryGeneratorObject, source, "ParticleSource", ObjectNode, PROPERTY_FIELD_NEVER_CLONE_TARGET | PROPERTY_FIELD_NO_SUB_ANIM); +DEFINE_PROPERTY_FIELD(TrajectoryGeneratorObject, onlySelectedParticles, "OnlySelectedParticles"); +DEFINE_PROPERTY_FIELD(TrajectoryGeneratorObject, useCustomInterval, "UseCustomInterval"); +DEFINE_PROPERTY_FIELD(TrajectoryGeneratorObject, customIntervalStart, "CustomIntervalStart"); +DEFINE_PROPERTY_FIELD(TrajectoryGeneratorObject, customIntervalEnd, "CustomIntervalEnd"); +DEFINE_PROPERTY_FIELD(TrajectoryGeneratorObject, everyNthFrame, "EveryNthFrame"); +DEFINE_PROPERTY_FIELD(TrajectoryGeneratorObject, unwrapTrajectories, "UnwrapTrajectories"); +SET_PROPERTY_FIELD_LABEL(TrajectoryGeneratorObject, source, "Source"); +SET_PROPERTY_FIELD_LABEL(TrajectoryGeneratorObject, onlySelectedParticles, "Only selected particles"); +SET_PROPERTY_FIELD_LABEL(TrajectoryGeneratorObject, useCustomInterval, "Custom time interval"); +SET_PROPERTY_FIELD_LABEL(TrajectoryGeneratorObject, customIntervalStart, "Custom interval start"); +SET_PROPERTY_FIELD_LABEL(TrajectoryGeneratorObject, customIntervalEnd, "Custom interval end"); +SET_PROPERTY_FIELD_LABEL(TrajectoryGeneratorObject, everyNthFrame, "Every Nth frame"); +SET_PROPERTY_FIELD_LABEL(TrajectoryGeneratorObject, unwrapTrajectories, "Unwrap trajectories"); +SET_PROPERTY_FIELD_UNITS(TrajectoryGeneratorObject, customIntervalStart, TimeParameterUnit); +SET_PROPERTY_FIELD_UNITS(TrajectoryGeneratorObject, customIntervalEnd, TimeParameterUnit); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(TrajectoryGeneratorObject, everyNthFrame, IntegerParameterUnit, 1); /****************************************************************************** * Default constructor. @@ -59,33 +61,35 @@ _customIntervalEnd(dataset->animationSettings()->animationInterval().end()), _everyNthFrame(1), _unwrapTrajectories(true) { - INIT_PROPERTY_FIELD(TrajectoryGeneratorObject::_source); - INIT_PROPERTY_FIELD(TrajectoryGeneratorObject::_onlySelectedParticles); - INIT_PROPERTY_FIELD(TrajectoryGeneratorObject::_useCustomInterval); - INIT_PROPERTY_FIELD(TrajectoryGeneratorObject::_customIntervalStart); - INIT_PROPERTY_FIELD(TrajectoryGeneratorObject::_customIntervalEnd); - INIT_PROPERTY_FIELD(TrajectoryGeneratorObject::_everyNthFrame); - INIT_PROPERTY_FIELD(TrajectoryGeneratorObject::_unwrapTrajectories); + INIT_PROPERTY_FIELD(source); + INIT_PROPERTY_FIELD(onlySelectedParticles); + INIT_PROPERTY_FIELD(useCustomInterval); + INIT_PROPERTY_FIELD(customIntervalStart); + INIT_PROPERTY_FIELD(customIntervalEnd); + INIT_PROPERTY_FIELD(everyNthFrame); + INIT_PROPERTY_FIELD(unwrapTrajectories); } /****************************************************************************** * Updates the stored trajectories from the source particle object. ******************************************************************************/ -bool TrajectoryGeneratorObject::generateTrajectories(AbstractProgressDisplay* progressDisplay) +bool TrajectoryGeneratorObject::generateTrajectories(TaskManager& taskManager) { // Suspend viewports while loading simulation frames. ViewportSuspender noVPUpdates(this); + SynchronousTask trajectoryTask(taskManager); + TimePoint currentTime = dataset()->animationSettings()->time(); // Get input particles. if(!source()) throwException(tr("No input particle data object is selected from which trajectory lines can be generated.")); - - if(!source()->waitUntilReady(currentTime, tr("Waiting for input particles to become ready."), progressDisplay)) + Future stateFuture = source()->evaluatePipelineAsync(PipelineEvalRequest(currentTime, false)); + if(!taskManager.waitForTask(stateFuture)) return false; - const PipelineFlowState& state = source()->evalPipeline(currentTime); + const PipelineFlowState& state = stateFuture.result(); ParticlePropertyObject* posProperty = ParticlePropertyObject::findInState(state, ParticleProperty::PositionProperty); ParticlePropertyObject* selectionProperty = ParticlePropertyObject::findInState(state, ParticleProperty::SelectionProperty); ParticlePropertyObject* identifierProperty = ParticlePropertyObject::findInState(state, ParticleProperty::IdentifierProperty); @@ -126,23 +130,34 @@ } } - // Iterate over the simulation frames. - TimeInterval interval = useCustomInterval() ? customInterval() : dataset()->animationSettings()->animationInterval(); + // Determine time interval over which trajectories should be generated. + TimeInterval interval; + if(useCustomInterval()) + interval = customInterval(); + else if(FileSource* fs = dynamic_object_cast(source()->sourceObject())) + interval = TimeInterval(0, dataset()->animationSettings()->frameToTime(fs->numberOfFrames() - 1)); + else + interval = dataset()->animationSettings()->animationInterval(); + + // Generate list of simulation frames at which particle positions should be sampled. QVector sampleTimes; for(TimePoint time = interval.start(); time <= interval.end(); time += everyNthFrame() * dataset()->animationSettings()->ticksPerFrame()) { sampleTimes.push_back(time); } - if(progressDisplay) { - progressDisplay->setMaximum(sampleTimes.size()); - progressDisplay->setValue(0); - } + trajectoryTask.setProgressMaximum(sampleTimes.size()); + trajectoryTask.setProgressValue(0); + // Sample particle positions to generate trajectory points. QVector points; points.reserve(particleCount * sampleTimes.size()); for(TimePoint time : sampleTimes) { - if(!source()->waitUntilReady(time, tr("Loading frame %1.").arg(dataset()->animationSettings()->timeToFrame(time)), progressDisplay)) + trajectoryTask.setProgressText(tr("Loading frame %1").arg(dataset()->animationSettings()->timeToFrame(time))); + + Future stateFuture = source()->evaluatePipelineAsync(PipelineEvalRequest(time, false)); + if(!taskManager.waitForTask(stateFuture)) return false; - const PipelineFlowState& state = source()->evalPipeline(time); + + const PipelineFlowState& state = stateFuture.result(); ParticlePropertyObject* posProperty = ParticlePropertyObject::findInState(state, ParticleProperty::PositionProperty); if(!posProperty) throwException(tr("Input particle set is empty at frame %1.").arg(dataset()->animationSettings()->timeToFrame(time))); @@ -192,19 +207,18 @@ } } - if(progressDisplay) { - progressDisplay->setValue(progressDisplay->value() + 1); - if(progressDisplay->wasCanceled()) return false; - } + trajectoryTask.setProgressValue(trajectoryTask.progressValue() + 1); + if(trajectoryTask.isCanceled()) + return false; } + // Store generated trajectory lines. setTrajectories(particleCount, points, sampleTimes); - // Jump back to current animation time. - if(!source()->waitUntilReady(currentTime, tr("Going back to original frame."), progressDisplay)) - return false; + // Jump back to original animation time. + source()->evaluatePipelineImmediately(PipelineEvalRequest(currentTime, true)); - return true; + return !trajectoryTask.isCanceled(); } } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/TrajectoryGeneratorObject.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/TrajectoryGeneratorObject.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/TrajectoryGeneratorObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/TrajectoryGeneratorObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TRAJECTORY_GENERATOR_OBJECT_H -#define __OVITO_TRAJECTORY_GENERATOR_OBJECT_H +#pragma once + #include #include "TrajectoryObject.h" @@ -37,90 +37,40 @@ /// \brief Constructor. Q_INVOKABLE TrajectoryGeneratorObject(DataSet* dataset); - /// Returns the object node providing the input particle data. - ObjectNode* source() const { return _source; } - - /// Sets the object node providing the input particle data. - void setSource(ObjectNode* source) { _source = source; } - - /// Returns which particles trajectories are created for. - bool onlySelectedParticles() const { return _onlySelectedParticles; } - - /// Controls which particles trajectories are created for. - void setOnlySelectedParticles(bool onlySelected) { _onlySelectedParticles = onlySelected; } - - /// Returns whether the created trajectories span the entire animation interval or a sub-interval. - bool useCustomInterval() { return _useCustomInterval; } - - /// Controls whether the created trajectories span the entire animation interval or a sub-interval. - void setUseCustomInterval(bool customInterval) { _useCustomInterval = customInterval; } - /// Returns the the custom time interval. TimeInterval customInterval() const { return TimeInterval(_customIntervalStart, _customIntervalEnd); } - /// Returns the start of the custom time interval. - TimePoint customIntervalStart() const { return _customIntervalStart; } - - /// Sets the start of the custom time interval. - void setCustomIntervalStart(TimePoint start) { _customIntervalStart = start; } - - /// Returns the end of the custom time interval. - TimePoint customIntervalEnd() const { return _customIntervalEnd; } - - /// Sets the end of the custom time interval. - void setCustomIntervalEnd(TimePoint end) { _customIntervalEnd = end; } - - /// Returns the sampling frequency for creating trajectories. - int everyNthFrame() const { return _everyNthFrame; } - - /// Sets the sampling frequency for creating trajectories. - void setEveryNthFrame(int n) { _everyNthFrame = n; } - - /// Returns whether trajectories are unwrapped when crossing periodic boundaries. - bool unwrapTrajectories() const { return _unwrapTrajectories; } - - /// Sets whether trajectories should be unwrapped when crossing periodic boundaries. - void setUnwrapTrajectories(bool unwrap) { _unwrapTrajectories = unwrap; } - /// Updates the stored trajectories from the source particle object. - bool generateTrajectories(AbstractProgressDisplay* progressDisplay = nullptr); + bool generateTrajectories(TaskManager& taskManager); private: /// The object node providing the input particles. - ReferenceField _source; + DECLARE_MODIFIABLE_REFERENCE_FIELD(ObjectNode, source, setSource); /// Controls which particles trajectories are created for. - PropertyField _onlySelectedParticles; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, onlySelectedParticles, setOnlySelectedParticles); /// Controls whether the created trajectories span the entire animation interval or a sub-interval. - PropertyField _useCustomInterval; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, useCustomInterval, setUseCustomInterval); /// The start of the custom time interval. - PropertyField _customIntervalStart; + DECLARE_MODIFIABLE_PROPERTY_FIELD(TimePoint, customIntervalStart, setCustomIntervalStart); /// The end of the custom time interval. - PropertyField _customIntervalEnd; + DECLARE_MODIFIABLE_PROPERTY_FIELD(TimePoint, customIntervalEnd, setCustomIntervalEnd); /// The sampling frequency for creating trajectories. - PropertyField _everyNthFrame; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, everyNthFrame, setEveryNthFrame); /// Controls whether trajectories are unwrapped when crossing periodic boundaries. - PropertyField _unwrapTrajectories; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, unwrapTrajectories, setUnwrapTrajectories); Q_OBJECT OVITO_OBJECT - - DECLARE_REFERENCE_FIELD(_source); - DECLARE_PROPERTY_FIELD(_onlySelectedParticles); - DECLARE_PROPERTY_FIELD(_useCustomInterval); - DECLARE_PROPERTY_FIELD(_customIntervalStart); - DECLARE_PROPERTY_FIELD(_customIntervalEnd); - DECLARE_PROPERTY_FIELD(_everyNthFrame); - DECLARE_PROPERTY_FIELD(_unwrapTrajectories); }; } // End of namespace } // End of namespace -#endif // __OVITO_TRAJECTORY_GENERATOR_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/TrajectoryObject.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/TrajectoryObject.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/TrajectoryObject.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/TrajectoryObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -25,7 +25,7 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, TrajectoryObject, DataObject); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(TrajectoryObject, DataObject); /****************************************************************************** * Default constructor. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/TrajectoryObject.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/TrajectoryObject.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/TrajectoryObject.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/TrajectoryObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TRAJECTORY_OBJECT_H -#define __OVITO_TRAJECTORY_OBJECT_H +#pragma once + #include #include @@ -81,4 +81,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_TRAJECTORY_OBJECT_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/VectorDisplay.cpp ovito-2.9.0+dfsg1/src/plugins/particles/objects/VectorDisplay.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/VectorDisplay.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/VectorDisplay.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,24 +29,24 @@ namespace Ovito { namespace Particles { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, VectorDisplay, DisplayObject); -IMPLEMENT_OVITO_OBJECT(Particles, VectorPickInfo, ObjectPickInfo); -DEFINE_PROPERTY_FIELD(VectorDisplay, _reverseArrowDirection, "ReverseArrowDirection"); -DEFINE_FLAGS_PROPERTY_FIELD(VectorDisplay, _arrowPosition, "ArrowPosition", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(VectorDisplay, _arrowColor, "ArrowColor", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(VectorDisplay, _arrowWidth, "ArrowWidth", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(VectorDisplay, _scalingFactor, "ScalingFactor", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(VectorDisplay, _shadingMode, "ShadingMode", PROPERTY_FIELD_MEMORIZE); -DEFINE_PROPERTY_FIELD(VectorDisplay, _renderingQuality, "RenderingQuality"); -SET_PROPERTY_FIELD_LABEL(VectorDisplay, _arrowColor, "Arrow color"); -SET_PROPERTY_FIELD_LABEL(VectorDisplay, _arrowWidth, "Arrow width"); -SET_PROPERTY_FIELD_LABEL(VectorDisplay, _scalingFactor, "Scaling factor"); -SET_PROPERTY_FIELD_LABEL(VectorDisplay, _reverseArrowDirection, "Reverse direction"); -SET_PROPERTY_FIELD_LABEL(VectorDisplay, _arrowPosition, "Position"); -SET_PROPERTY_FIELD_LABEL(VectorDisplay, _shadingMode, "Shading mode"); -SET_PROPERTY_FIELD_LABEL(VectorDisplay, _renderingQuality, "RenderingQuality"); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(VectorDisplay, _arrowWidth, WorldParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(VectorDisplay, _scalingFactor, FloatParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(VectorDisplay, DisplayObject); +IMPLEMENT_OVITO_OBJECT(VectorPickInfo, ObjectPickInfo); +DEFINE_PROPERTY_FIELD(VectorDisplay, reverseArrowDirection, "ReverseArrowDirection"); +DEFINE_FLAGS_PROPERTY_FIELD(VectorDisplay, arrowPosition, "ArrowPosition", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(VectorDisplay, arrowColor, "ArrowColor", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(VectorDisplay, arrowWidth, "ArrowWidth", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(VectorDisplay, scalingFactor, "ScalingFactor", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(VectorDisplay, shadingMode, "ShadingMode", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(VectorDisplay, renderingQuality, "RenderingQuality"); +SET_PROPERTY_FIELD_LABEL(VectorDisplay, arrowColor, "Arrow color"); +SET_PROPERTY_FIELD_LABEL(VectorDisplay, arrowWidth, "Arrow width"); +SET_PROPERTY_FIELD_LABEL(VectorDisplay, scalingFactor, "Scaling factor"); +SET_PROPERTY_FIELD_LABEL(VectorDisplay, reverseArrowDirection, "Reverse direction"); +SET_PROPERTY_FIELD_LABEL(VectorDisplay, arrowPosition, "Position"); +SET_PROPERTY_FIELD_LABEL(VectorDisplay, shadingMode, "Shading mode"); +SET_PROPERTY_FIELD_LABEL(VectorDisplay, renderingQuality, "RenderingQuality"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(VectorDisplay, arrowWidth, WorldParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(VectorDisplay, scalingFactor, FloatParameterUnit, 0); /****************************************************************************** * Constructor. @@ -56,13 +56,13 @@ _shadingMode(ArrowPrimitive::FlatShading), _renderingQuality(ArrowPrimitive::LowQuality) { - INIT_PROPERTY_FIELD(VectorDisplay::_arrowColor); - INIT_PROPERTY_FIELD(VectorDisplay::_arrowWidth); - INIT_PROPERTY_FIELD(VectorDisplay::_scalingFactor); - INIT_PROPERTY_FIELD(VectorDisplay::_reverseArrowDirection); - INIT_PROPERTY_FIELD(VectorDisplay::_arrowPosition); - INIT_PROPERTY_FIELD(VectorDisplay::_shadingMode); - INIT_PROPERTY_FIELD(VectorDisplay::_renderingQuality); + INIT_PROPERTY_FIELD(arrowColor); + INIT_PROPERTY_FIELD(arrowWidth); + INIT_PROPERTY_FIELD(scalingFactor); + INIT_PROPERTY_FIELD(reverseArrowDirection); + INIT_PROPERTY_FIELD(arrowPosition); + INIT_PROPERTY_FIELD(shadingMode); + INIT_PROPERTY_FIELD(renderingQuality); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/objects/VectorDisplay.h ovito-2.9.0+dfsg1/src/plugins/particles/objects/VectorDisplay.h --- ovito-2.8.1+dfsg2/src/plugins/particles/objects/VectorDisplay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/objects/VectorDisplay.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_VECTOR_DISPLAY_H -#define __OVITO_VECTOR_DISPLAY_H +#pragma once + #include #include @@ -57,48 +57,6 @@ /// \brief Computes the bounding box of the object. virtual Box3 boundingBox(TimePoint time, DataObject* dataObject, ObjectNode* contextNode, const PipelineFlowState& flowState) override; - /// \brief Returns the selected shading mode for arrows. - ArrowPrimitive::ShadingMode shadingMode() const { return _shadingMode; } - - /// \brief Sets the shading mode for arrows. - void setShadingMode(ArrowPrimitive::ShadingMode mode) { _shadingMode = mode; } - - /// \brief Returns the selected rendering quality mode for arrows. - ArrowPrimitive::RenderingQuality renderingQuality() const { return _renderingQuality; } - - /// \brief Sets the rendering quality mode for arrows. - void setRenderingQuality(ArrowPrimitive::RenderingQuality quality) { _renderingQuality = quality; } - - /// Returns whether the arrow pointing direction is reversed. - bool reverseArrowDirection() const { return _reverseArrowDirection; } - - /// Sets whether the arrow pointing direction should be reversed. - void setReverseArrowDirection(bool reverse) { _reverseArrowDirection = reverse; } - - /// Returns how the arrows are positioned relative to the particles. - ArrowPosition arrowPosition() const { return _arrowPosition; } - - /// Sets how the arrows are positioned relative to the particles. - void setArrowPosition(ArrowPosition posMode) { _arrowPosition = posMode; } - - /// Returns the display color of the arrows. - const Color& arrowColor() const { return _arrowColor; } - - /// Sets the display color of the arrows. - void setArrowColor(const Color& color) { _arrowColor = color; } - - /// Returns the display width of the arrows. - FloatType arrowWidth() const { return _arrowWidth; } - - /// Sets the display width of the arrows. - void setArrowWidth(FloatType width) { _arrowWidth = width; } - - /// Returns the scaling factor that is applied to the vectors. - FloatType scalingFactor() const { return _scalingFactor; } - - /// Sets the scaling factor that is applied to the vectors. - void setScalingFactor(FloatType factor) { _scalingFactor = factor; } - public: Q_PROPERTY(Ovito::ArrowPrimitive::ShadingMode shadingMode READ shadingMode WRITE setShadingMode); @@ -117,26 +75,26 @@ protected: - /// Enables the reversal of the arrow pointing direction. - PropertyField _reverseArrowDirection; + /// Reverses of the arrow pointing direction. + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, reverseArrowDirection, setReverseArrowDirection); /// Controls how the arrows are positioned relative to the particles. - PropertyField _arrowPosition; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ArrowPosition, arrowPosition, setArrowPosition); /// Controls the color of the arrows. - PropertyField _arrowColor; + DECLARE_MODIFIABLE_PROPERTY_FIELD(Color, arrowColor, setArrowColor); /// Controls the width of the arrows in world units. - PropertyField _arrowWidth; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, arrowWidth, setArrowWidth); /// Controls the scaling factor applied to the vectors. - PropertyField _scalingFactor; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, scalingFactor, setScalingFactor); /// Controls the shading mode for arrows. - PropertyField _shadingMode; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ArrowPrimitive::ShadingMode, shadingMode, setShadingMode); /// Controls the rendering quality mode for arrows. - PropertyField _renderingQuality; + DECLARE_MODIFIABLE_PROPERTY_FIELD(ArrowPrimitive::RenderingQuality, renderingQuality, setRenderingQuality); /// The buffered geometry used to render the arrows. std::shared_ptr _buffer; @@ -175,14 +133,6 @@ OVITO_OBJECT Q_CLASSINFO("DisplayName", "Vectors"); - - DECLARE_PROPERTY_FIELD(_reverseArrowDirection); - DECLARE_PROPERTY_FIELD(_arrowPosition); - DECLARE_PROPERTY_FIELD(_arrowColor); - DECLARE_PROPERTY_FIELD(_arrowWidth); - DECLARE_PROPERTY_FIELD(_scalingFactor); - DECLARE_PROPERTY_FIELD(_shadingMode); - DECLARE_PROPERTY_FIELD(_renderingQuality); }; /** @@ -230,4 +180,4 @@ Q_DECLARE_TYPEINFO(Ovito::Particles::VectorDisplay::ArrowPosition, Q_PRIMITIVE_TYPE); -#endif // __OVITO_VECTOR_DISPLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/Particles.h ovito-2.9.0+dfsg1/src/plugins/particles/Particles.h --- ovito-2.8.1+dfsg2/src/plugins/particles/Particles.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/Particles.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLES_H -#define __OVITO_PARTICLES_H +#pragma once + #include @@ -103,5 +103,3 @@ OVITO_END_INLINE_NAMESPACE } } - -#endif diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/resources/python/ovito/data/particles/__init__.py ovito-2.9.0+dfsg1/src/plugins/particles/resources/python/ovito/data/particles/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/particles/resources/python/ovito/data/particles/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/resources/python/ovito/data/particles/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -14,32 +14,36 @@ import ovito.data # Load the native code module -import Particles +import ovito.plugins.Particles # Inject selected classes into parent module. -ovito.data.SimulationCell = Particles.SimulationCell -ovito.data.ParticleProperty = Particles.ParticleProperty -ovito.data.Bonds = Particles.Bonds -ovito.data.SurfaceMesh = Particles.SurfaceMesh -ovito.data.ParticleTypeProperty = Particles.ParticleTypeProperty -ovito.data.ParticleType = Particles.ParticleType -ovito.data.BondProperty = Particles.BondProperty -ovito.data.BondTypeProperty = Particles.BondTypeProperty -ovito.data.BondType = Particles.BondType +ovito.data.SimulationCell = ovito.plugins.Particles.SimulationCell +ovito.data.ParticleProperty = ovito.plugins.Particles.ParticleProperty +ovito.data.Bonds = ovito.plugins.Particles.Bonds +ovito.data.SurfaceMesh = ovito.plugins.Particles.SurfaceMesh +ovito.data.ParticleTypeProperty = ovito.plugins.Particles.ParticleTypeProperty +ovito.data.ParticleType = ovito.plugins.Particles.ParticleType +ovito.data.BondProperty = ovito.plugins.Particles.BondProperty +ovito.data.BondTypeProperty = ovito.plugins.Particles.BondTypeProperty +ovito.data.BondType = ovito.plugins.Particles.BondType +ovito.data.TrajectoryLineGenerator = ovito.plugins.Particles.TrajectoryLineGenerator +ovito.data.__all__ += ['SimulationCell', 'ParticleProperty', 'Bonds', 'SurfaceMesh', 'ParticleTypeProperty', 'ParticleType', + 'BondProperty', 'BondTypeProperty', 'BondType', 'TrajectoryLineGenerator', 'CutoffNeighborFinder', + 'NearestNeighborFinder'] # For backward-compatibility with OVITO 2.5.1: def _ParticleProperty_data_attribute_name(self): - if self.type != Particles.ParticleProperty.Type.User: + if self.type != ovito.data.ParticleProperty.Type.User: return re.sub('\W|^(?=\d)','_', self.name).lower() else: return None -Particles.ParticleProperty._data_attribute_name = property(_ParticleProperty_data_attribute_name) +ovito.data.ParticleProperty._data_attribute_name = property(_ParticleProperty_data_attribute_name) # Access particle and bond properties by their name (not display title). def _ParticleProperty_data_key(self): return self.name -Particles.ParticleProperty._data_key = property(_ParticleProperty_data_key) -Particles.BondProperty._data_key = property(_ParticleProperty_data_key) +ovito.data.ParticleProperty._data_key = property(_ParticleProperty_data_key) +ovito.data.BondProperty._data_key = property(_ParticleProperty_data_key) # Implement the 'particle_properties' attribute of the DataCollection class. def _DataCollection_particle_properties(self): @@ -59,8 +63,6 @@ return sum(isinstance(obj, ovito.data.ParticleProperty) for obj in self._objects) def __getitem__(self, key): - if not isinstance(key, str): - raise TypeError("Property name key is not a string.") for obj in self._objects: if isinstance(obj, ovito.data.ParticleProperty): if obj.name == key: @@ -103,8 +105,6 @@ return sum(isinstance(obj, ovito.data.BondProperty) for obj in self._objects) def __getitem__(self, key): - if not isinstance(key, str): - raise TypeError("Property name key is not a string.") for obj in self._objects: if isinstance(obj, ovito.data.BondProperty): if obj.name == key: @@ -182,7 +182,7 @@ data stored in this particle property, use :py:attr:`.marray` instead. """ return numpy.asarray(self) -Particles.ParticleProperty.array = property(_ParticleProperty_array) +ovito.data.ParticleProperty.array = property(_ParticleProperty_array) # Returns a NumPy array wrapper for a particle property with write access. def _ParticleProperty_marray(self): @@ -225,9 +225,9 @@ # Assume that the data has been changed in the meantime. self.changed() -Particles.ParticleProperty.marray = property(_ParticleProperty_marray, _ParticleProperty_marray_assign) +ovito.data.ParticleProperty.marray = property(_ParticleProperty_marray, _ParticleProperty_marray_assign) # For backward compatibility with OVITO 2.5.1: -Particles.ParticleProperty.mutable_array = property(lambda self: self.marray) +ovito.data.ParticleProperty.mutable_array = property(lambda self: self.marray) # Returns a NumPy array wrapper for a bond property. def _BondProperty_array(self): @@ -243,7 +243,7 @@ data stored in this bond property, use :py:attr:`.marray` instead. """ return numpy.asarray(self) -Particles.BondProperty.array = property(_BondProperty_array) +ovito.data.BondProperty.array = property(_BondProperty_array) # Returns a NumPy array wrapper for a bond property with write access. def _BondProperty_marray(self): @@ -271,7 +271,7 @@ o.__base_property = self return numpy.asarray(o) -Particles.BondProperty.marray = property(_BondProperty_marray, _ParticleProperty_marray_assign) +ovito.data.BondProperty.marray = property(_BondProperty_marray, _ParticleProperty_marray_assign) # Returns a NumPy array wrapper for bonds list. def _Bonds_array(self): @@ -285,7 +285,7 @@ Note that the returned NumPy array is read-only and provides a view of the internal data. """ return numpy.asarray(self) -Particles.Bonds.array = property(_Bonds_array) +ovito.data.Bonds.array = property(_Bonds_array) # Returns a NumPy array wrapper for the bond PBC shift vectors. def _Bonds_pbc_vectors(self): @@ -316,7 +316,7 @@ # Create reference to particle property object to keep it alive. o.__base_property = self return numpy.asarray(o) -Particles.Bonds.pbc_vectors = property(_Bonds_pbc_vectors) +ovito.data.Bonds.pbc_vectors = property(_Bonds_pbc_vectors) def _Bonds_add(self, p1, p2, pbc_shift = (0,0,0)): """ Creates a new half-bond from particle *p1* to particle *p2*. @@ -331,7 +331,7 @@ See :py:attr:`.pbc_vectors` array. """ self.addBond(p1, p2, pbc_shift) -Particles.Bonds.add = _Bonds_add +ovito.data.Bonds.add = _Bonds_add def _Bonds_add_full(self, p1, p2, pbc_shift = (0,0,0)): """ Creates two half-bonds between the particles *p1* and *p2*. This is equivalent to @@ -346,7 +346,7 @@ """ self.addBond(p1, p2, pbc_shift) self.addBond(p2, p1, (-pbc_shift[0], -pbc_shift[1], -pbc_shift[2])) -Particles.Bonds.add_full = _Bonds_add_full +ovito.data.Bonds.add_full = _Bonds_add_full # Implement 'pbc' property of SimulationCell class. def _get_SimulationCell_pbc(self): @@ -357,9 +357,9 @@ self.pbc_x = flags[0] self.pbc_y = flags[1] self.pbc_z = flags[2] -Particles.SimulationCell.pbc = property(_get_SimulationCell_pbc, _set_SimulationCell_pbc) +ovito.data.SimulationCell.pbc = property(_get_SimulationCell_pbc, _set_SimulationCell_pbc) -class CutoffNeighborFinder(Particles.CutoffNeighborFinder): +class CutoffNeighborFinder(ovito.plugins.Particles.CutoffNeighborFinder): """ A utility class that computes particle neighbor lists. @@ -380,13 +380,14 @@ def __init__(self, cutoff, data_collection): """ This is the constructor. """ - super(self.__class__, self).__init__() + super(self.__class__, self).__init__() if not hasattr(data_collection, 'position'): - raise KeyError("Data collection does not contain any particles.") + raise KeyError("DataCollection does not contain any ") if not hasattr(data_collection, 'cell'): - raise KeyError("Data collection does not contain simulation cell information.") + raise KeyError("DataCollection does not contain simulation cell information.") self.particle_count = data_collection.number_of_particles - self.prepare(cutoff, data_collection.position, data_collection.cell) + if not self.prepare(cutoff, data_collection.position, data_collection.cell): + raise RuntimeError("Operation has been canceled by the user.") def find(self, index): """ @@ -409,7 +410,7 @@ if index < 0 or index >= self.particle_count: raise IndexError("Particle index is out of range.") # Construct the C++ neighbor query. - query = Particles.CutoffNeighborFinder.Query(self, int(index)) + query = ovito.plugins.Particles.CutoffNeighborFinder.Query(self, int(index)) # Iterate over neighbors. while not query.at_end: yield query @@ -417,7 +418,7 @@ ovito.data.CutoffNeighborFinder = CutoffNeighborFinder -class NearestNeighborFinder(Particles.NearestNeighborFinder): +class NearestNeighborFinder(ovito.plugins.Particles.NearestNeighborFinder): """ A utility class that finds the *N* nearest neighbors of a particle or a spatial location. @@ -437,7 +438,7 @@ .. literalinclude:: ../example_snippets/nearest_neighbor_finder.py :lines: 19- - If you want to find all neighbor particles within a certain cutoff radius of a central particle, + Note, if you want to find all neighbor particles within a certain cutoff radius of a central particle, use the :py:class:`CutoffNeighborFinder` class instead. """ @@ -447,11 +448,12 @@ if N<=0 or N>30: raise ValueError("The requested number of nearest neighbors is out of range.") if not hasattr(data_collection, 'position'): - raise KeyError("Data collection does not contain any particles.") + raise KeyError("DataCollection does not contain any particles.") if not hasattr(data_collection, 'cell'): - raise KeyError("Data collection does not contain simulation cell information.") + raise KeyError("DataCollection does not contain simulation cell information.") self.particle_count = data_collection.number_of_particles - self.prepare(data_collection.position, data_collection.cell) + if not self.prepare(data_collection.position, data_collection.cell): + raise RuntimeError("Operation has been canceled by the user.") def find(self, index): """ @@ -476,7 +478,7 @@ if index < 0 or index >= self.particle_count: raise IndexError("Particle index is out of range.") # Construct the C++ neighbor query. - query = Particles.NearestNeighborFinder.Query(self) + query = ovito.plugins.Particles.NearestNeighborFinder.Query(self) query.findNeighbors(int(index)) # Iterate over neighbors. for i in range(query.count): @@ -488,7 +490,7 @@ Unlike the :py:meth:`find` method, which queries the nearest neighbors of a physical particle, the :py:meth:`!find_at` method allows searching for neareby particles at arbitrary locations in space. - :param coords: A (x,y,z) coordinate triple specifying the spatial location where the *N* nearest particles should be queried. + :param coords: A (x,y,z) coordinate triplet specifying the spatial location where the *N* nearest particles should be queried. :returns: A Python iterator that visits the *N* nearest neighbors in order of ascending distance. For each visited particle the iterator returns an object with the following attributes: @@ -504,7 +506,7 @@ system contains too few particles and has no periodic boundary conditions. """ # Construct the C++ neighbor query. - query = Particles.NearestNeighborFinder.Query(self) + query = ovito.plugins.Particles.NearestNeighborFinder.Query(self) query.findNeighborsAtLocation(coords, True) # Iterate over neighbors. for i in range(query.count): @@ -899,7 +901,7 @@ return t ovito.data.BondTypeProperty.get_type_by_name = _BondTypeProperty_get_type_by_name -class Enumerator(Particles.Bonds.ParticleBondMap): +class Enumerator(ovito.plugins.Particles.Bonds.ParticleBondMap): """ Utility class that allows efficiently iterating over the bonds of a particle. diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/resources/python/ovito/io/particles/__init__.py ovito-2.9.0+dfsg1/src/plugins/particles/resources/python/ovito/io/particles/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/particles/resources/python/ovito/io/particles/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/resources/python/ovito/io/particles/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -2,9 +2,9 @@ import ovito.io # Load the native code modules -import Particles -from ParticlesImporter import * -from ParticlesExporter import * +import ovito.plugins.Particles +from ovito.plugins.Particles.Importers import * +from ovito.plugins.Particles.Exporters import * # Register export formats. ovito.io.export_file._formatTable["lammps_dump"] = LAMMPSDumpExporter diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/resources/python/ovito/modifiers/particles/__init__.py ovito-2.9.0+dfsg1/src/plugins/particles/resources/python/ovito/modifiers/particles/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/particles/resources/python/ovito/modifiers/particles/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/resources/python/ovito/modifiers/particles/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -5,45 +5,57 @@ import ovito.modifiers # Load the native code modules. -import Particles -import ParticlesModify +import ovito.plugins.Particles +import ovito.plugins.Particles.Modifiers # Inject modifier classes into parent module. -ovito.modifiers.ColorCodingModifier = ParticlesModify.ColorCodingModifier -ovito.modifiers.AssignColorModifier = ParticlesModify.AssignColorModifier -ovito.modifiers.AmbientOcclusionModifier = ParticlesModify.AmbientOcclusionModifier -ovito.modifiers.DeleteSelectedParticlesModifier = ParticlesModify.DeleteSelectedParticlesModifier -ovito.modifiers.ShowPeriodicImagesModifier = ParticlesModify.ShowPeriodicImagesModifier -ovito.modifiers.WrapPeriodicImagesModifier = ParticlesModify.WrapPeriodicImagesModifier -ovito.modifiers.ComputePropertyModifier = ParticlesModify.ComputePropertyModifier -ovito.modifiers.FreezePropertyModifier = ParticlesModify.FreezePropertyModifier -ovito.modifiers.ClearSelectionModifier = ParticlesModify.ClearSelectionModifier -ovito.modifiers.InvertSelectionModifier = ParticlesModify.InvertSelectionModifier -ovito.modifiers.ManualSelectionModifier = ParticlesModify.ManualSelectionModifier -ovito.modifiers.ExpandSelectionModifier = ParticlesModify.ExpandSelectionModifier -ovito.modifiers.SelectExpressionModifier = ParticlesModify.SelectExpressionModifier -ovito.modifiers.SelectParticleTypeModifier = ParticlesModify.SelectParticleTypeModifier -ovito.modifiers.SliceModifier = ParticlesModify.SliceModifier -ovito.modifiers.AffineTransformationModifier = ParticlesModify.AffineTransformationModifier -ovito.modifiers.BinAndReduceModifier = ParticlesModify.BinAndReduceModifier -ovito.modifiers.StructureIdentificationModifier = ParticlesModify.StructureIdentificationModifier -ovito.modifiers.CommonNeighborAnalysisModifier = ParticlesModify.CommonNeighborAnalysisModifier -ovito.modifiers.BondAngleAnalysisModifier = ParticlesModify.BondAngleAnalysisModifier -ovito.modifiers.CreateBondsModifier = ParticlesModify.CreateBondsModifier -ovito.modifiers.CentroSymmetryModifier = ParticlesModify.CentroSymmetryModifier -ovito.modifiers.ClusterAnalysisModifier = ParticlesModify.ClusterAnalysisModifier -ovito.modifiers.CoordinationNumberModifier = ParticlesModify.CoordinationNumberModifier -ovito.modifiers.CalculateDisplacementsModifier = ParticlesModify.CalculateDisplacementsModifier -ovito.modifiers.HistogramModifier = ParticlesModify.HistogramModifier -ovito.modifiers.ScatterPlotModifier = ParticlesModify.ScatterPlotModifier -ovito.modifiers.AtomicStrainModifier = ParticlesModify.AtomicStrainModifier -ovito.modifiers.WignerSeitzAnalysisModifier = ParticlesModify.WignerSeitzAnalysisModifier -ovito.modifiers.VoronoiAnalysisModifier = ParticlesModify.VoronoiAnalysisModifier -ovito.modifiers.IdentifyDiamondModifier = ParticlesModify.IdentifyDiamondModifier -ovito.modifiers.LoadTrajectoryModifier = ParticlesModify.LoadTrajectoryModifier -ovito.modifiers.CombineParticleSetsModifier = ParticlesModify.CombineParticleSetsModifier -ovito.modifiers.ComputeBondLengthsModifier = ParticlesModify.ComputeBondLengthsModifier -ovito.modifiers.PolyhedralTemplateMatchingModifier = ParticlesModify.PolyhedralTemplateMatchingModifier +ovito.modifiers.ColorCodingModifier = ovito.plugins.Particles.Modifiers.ColorCodingModifier +ovito.modifiers.AssignColorModifier = ovito.plugins.Particles.Modifiers.AssignColorModifier +ovito.modifiers.AmbientOcclusionModifier = ovito.plugins.Particles.Modifiers.AmbientOcclusionModifier +ovito.modifiers.DeleteSelectedParticlesModifier = ovito.plugins.Particles.Modifiers.DeleteSelectedParticlesModifier +ovito.modifiers.ShowPeriodicImagesModifier = ovito.plugins.Particles.Modifiers.ShowPeriodicImagesModifier +ovito.modifiers.WrapPeriodicImagesModifier = ovito.plugins.Particles.Modifiers.WrapPeriodicImagesModifier +ovito.modifiers.ComputePropertyModifier = ovito.plugins.Particles.Modifiers.ComputePropertyModifier +ovito.modifiers.FreezePropertyModifier = ovito.plugins.Particles.Modifiers.FreezePropertyModifier +ovito.modifiers.ClearSelectionModifier = ovito.plugins.Particles.Modifiers.ClearSelectionModifier +ovito.modifiers.InvertSelectionModifier = ovito.plugins.Particles.Modifiers.InvertSelectionModifier +ovito.modifiers.ManualSelectionModifier = ovito.plugins.Particles.Modifiers.ManualSelectionModifier +ovito.modifiers.ExpandSelectionModifier = ovito.plugins.Particles.Modifiers.ExpandSelectionModifier +ovito.modifiers.SelectExpressionModifier = ovito.plugins.Particles.Modifiers.SelectExpressionModifier +ovito.modifiers.SelectParticleTypeModifier = ovito.plugins.Particles.Modifiers.SelectParticleTypeModifier +ovito.modifiers.SliceModifier = ovito.plugins.Particles.Modifiers.SliceModifier +ovito.modifiers.AffineTransformationModifier = ovito.plugins.Particles.Modifiers.AffineTransformationModifier +ovito.modifiers.BinAndReduceModifier = ovito.plugins.Particles.Modifiers.BinAndReduceModifier +ovito.modifiers.StructureIdentificationModifier = ovito.plugins.Particles.Modifiers.StructureIdentificationModifier +ovito.modifiers.CommonNeighborAnalysisModifier = ovito.plugins.Particles.Modifiers.CommonNeighborAnalysisModifier +ovito.modifiers.BondAngleAnalysisModifier = ovito.plugins.Particles.Modifiers.BondAngleAnalysisModifier +ovito.modifiers.CreateBondsModifier = ovito.plugins.Particles.Modifiers.CreateBondsModifier +ovito.modifiers.CentroSymmetryModifier = ovito.plugins.Particles.Modifiers.CentroSymmetryModifier +ovito.modifiers.ClusterAnalysisModifier = ovito.plugins.Particles.Modifiers.ClusterAnalysisModifier +ovito.modifiers.CoordinationNumberModifier = ovito.plugins.Particles.Modifiers.CoordinationNumberModifier +ovito.modifiers.CalculateDisplacementsModifier = ovito.plugins.Particles.Modifiers.CalculateDisplacementsModifier +ovito.modifiers.HistogramModifier = ovito.plugins.Particles.Modifiers.HistogramModifier +ovito.modifiers.ScatterPlotModifier = ovito.plugins.Particles.Modifiers.ScatterPlotModifier +ovito.modifiers.AtomicStrainModifier = ovito.plugins.Particles.Modifiers.AtomicStrainModifier +ovito.modifiers.WignerSeitzAnalysisModifier = ovito.plugins.Particles.Modifiers.WignerSeitzAnalysisModifier +ovito.modifiers.VoronoiAnalysisModifier = ovito.plugins.Particles.Modifiers.VoronoiAnalysisModifier +ovito.modifiers.IdentifyDiamondModifier = ovito.plugins.Particles.Modifiers.IdentifyDiamondModifier +ovito.modifiers.LoadTrajectoryModifier = ovito.plugins.Particles.Modifiers.LoadTrajectoryModifier +ovito.modifiers.CombineParticleSetsModifier = ovito.plugins.Particles.Modifiers.CombineParticleSetsModifier +ovito.modifiers.ComputeBondLengthsModifier = ovito.plugins.Particles.Modifiers.ComputeBondLengthsModifier +ovito.modifiers.PolyhedralTemplateMatchingModifier = ovito.plugins.Particles.Modifiers.PolyhedralTemplateMatchingModifier +ovito.modifiers.CreateIsosurfaceModifier = ovito.plugins.Particles.Modifiers.CreateIsosurfaceModifier +ovito.modifiers.CoordinationPolyhedraModifier = ovito.plugins.Particles.Modifiers.CoordinationPolyhedraModifier +ovito.modifiers.__all__ += ['ColorCodingModifier', 'AssignColorModifier', 'AmbientOcclusionModifier', 'DeleteSelectedParticlesModifier', + 'ShowPeriodicImagesModifier', 'WrapPeriodicImagesModifier', 'ComputePropertyModifier', 'FreezePropertyModifier', + 'ClearSelectionModifier', 'InvertSelectionModifier', 'ManualSelectionModifier', 'ExpandSelectionModifier', + 'SelectExpressionModifier', 'SelectParticleTypeModifier', 'SliceModifier', 'AffineTransformationModifier', 'BinAndReduceModifier', + 'StructureIdentificationModifier', 'CommonNeighborAnalysisModifier', 'BondAngleAnalysisModifier', + 'CreateBondsModifier', 'CentroSymmetryModifier', 'ClusterAnalysisModifier', 'CoordinationNumberModifier', + 'CalculateDisplacementsModifier', 'HistogramModifier', 'ScatterPlotModifier', 'AtomicStrainModifier', + 'WignerSeitzAnalysisModifier', 'VoronoiAnalysisModifier', 'IdentifyDiamondModifier', 'LoadTrajectoryModifier', + 'CombineParticleSetsModifier', 'ComputeBondLengthsModifier', 'PolyhedralTemplateMatchingModifier', + 'CreateIsosurfaceModifier', 'CoordinationPolyhedraModifier'] # Implement the 'rdf' attribute of the CoordinationNumberModifier class. def _CoordinationNumberModifier_rdf(self): @@ -97,5 +109,6 @@ time = self.dataset.anim.frameToTime(frame) else: time = self.dataset.anim.time - self._take_snapshot(time, True) + if not self._take_snapshot(time, ovito.task_manager, True): + raise RuntimeError("Operation has been canceled by the user.") ovito.modifiers.FreezePropertyModifier.take_snapshot = _FreezePropertyModifier_take_snapshot diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/resources/python/ovito/vis/particles/__init__.py ovito-2.9.0+dfsg1/src/plugins/particles/resources/python/ovito/vis/particles/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/particles/resources/python/ovito/vis/particles/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/resources/python/ovito/vis/particles/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -2,15 +2,19 @@ import ovito.vis # Load the native code module -import Particles +import ovito.plugins.Particles # Inject selected classes into parent module. -ovito.vis.SimulationCellDisplay = Particles.SimulationCellDisplay -ovito.vis.ParticleDisplay = Particles.ParticleDisplay -ovito.vis.VectorDisplay = Particles.VectorDisplay -ovito.vis.BondsDisplay = Particles.BondsDisplay -ovito.vis.SurfaceMeshDisplay = Particles.SurfaceMeshDisplay +ovito.vis.SimulationCellDisplay = ovito.plugins.Particles.SimulationCellDisplay +ovito.vis.ParticleDisplay = ovito.plugins.Particles.ParticleDisplay +ovito.vis.VectorDisplay = ovito.plugins.Particles.VectorDisplay +ovito.vis.BondsDisplay = ovito.plugins.Particles.BondsDisplay +ovito.vis.SurfaceMeshDisplay = ovito.plugins.Particles.SurfaceMeshDisplay +ovito.vis.TrajectoryLineDisplay = ovito.plugins.Particles.TrajectoryLineDisplay +ovito.vis.__all__ += ['SimulationCellDisplay', 'ParticleDisplay', 'VectorDisplay', 'BondsDisplay', + 'SurfaceMeshDisplay', 'TrajectoryLineDisplay'] # Inject enum types. ovito.vis.VectorDisplay.Shading = ovito.vis.ArrowShadingMode -ovito.vis.BondsDisplay.Shading = ovito.vis.ArrowShadingMode \ No newline at end of file +ovito.vis.BondsDisplay.Shading = ovito.vis.ArrowShadingMode +ovito.vis.TrajectoryLineDisplay.Shading = ovito.vis.ArrowShadingMode diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/scripting/ExporterBinding.cpp ovito-2.9.0+dfsg1/src/plugins/particles/scripting/ExporterBinding.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/scripting/ExporterBinding.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/scripting/ExporterBinding.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -38,12 +38,9 @@ using namespace PyScript; -PYBIND11_PLUGIN(ParticlesExporter) +void defineExportersSubmodule(py::module parentModule) { - py::options options; - options.disable_function_signatures(); - - py::module m("ParticlesExporter"); + py::module m = parentModule.def_submodule("Exporters"); ovito_abstract_class{m} ; @@ -76,12 +73,8 @@ ovito_class{m} ; - - return m.ptr(); } -OVITO_REGISTER_PLUGIN_PYTHON_INTERFACE(ParticlesExporter); - OVITO_END_INLINE_NAMESPACE } // End of namespace } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/scripting/ImporterBinding.cpp ovito-2.9.0+dfsg1/src/plugins/particles/scripting/ImporterBinding.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/scripting/ImporterBinding.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/scripting/ImporterBinding.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -45,12 +45,9 @@ using namespace PyScript; -PYBIND11_PLUGIN(ParticlesImporter) +void defineImportersSubmodule(py::module parentModule) { - py::options options; - options.disable_function_signatures(); - - py::module m("ParticlesImporter"); + py::module m = parentModule.def_submodule("Importers"); ovito_abstract_class(m) .def_property("multiple_frames", &ParticleImporter::isMultiTimestepFile, &ParticleImporter::setMultiTimestepFile) @@ -111,12 +108,8 @@ ovito_class{m} ; - - return m.ptr(); } -OVITO_REGISTER_PLUGIN_PYTHON_INTERFACE(ParticlesImporter); - OVITO_END_INLINE_NAMESPACE } // End of namespace } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/scripting/ModifierBinding.cpp ovito-2.9.0+dfsg1/src/plugins/particles/scripting/ModifierBinding.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/scripting/ModifierBinding.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/scripting/ModifierBinding.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -61,19 +62,18 @@ #include #include #include +#include #include +#include #include "PythonBinding.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Internal) using namespace PyScript; -PYBIND11_PLUGIN(ParticlesModify) +void defineModifiersSubmodule(py::module parentModule) { - py::options options; - options.disable_function_signatures(); - - py::module m("ParticlesModify"); + py::module m = parentModule.def_submodule("Modifiers"); ovito_abstract_class{m} ; @@ -110,15 +110,15 @@ " node.modifiers.append(modifier)\n" "\n" "If, as in the example above, the :py:attr:`.start_value` and :py:attr:`.end_value` parameters are not explicitly set, " - "then the modifier automatically adjusts them to the minimum and maximum values of the property when the modifier " - "is inserted into the modification pipeline.") + "then the modifier automatically adjusts them to the minimum and maximum values of the input property at the time the modifier " + "is inserted into the data pipeline.") .def_property("property", &ColorCodingModifier::sourceParticleProperty, &ColorCodingModifier::setSourceParticleProperty) .def_property("particle_property", &ColorCodingModifier::sourceParticleProperty, &ColorCodingModifier::setSourceParticleProperty, "The name of the input particle property that should be used to color particles. " "This can be one of the :ref:`standard particle properties ` or a custom particle property. " "When using vector properties the component must be included in the name, e.g. ``\"Velocity.X\"``. " "\n\n" - "This field is only used if :py:attr:`.bond_mode` is not set to ``Bonds``. ") + "This field is only used if :py:attr:`.assign_to` is not set to ``Bonds``. ") .def_property("bond_property", &ColorCodingModifier::sourceBondProperty, &ColorCodingModifier::setSourceBondProperty, "The name of the input bond property that should be used to color bonds. " "This can be one of the :ref:`standard bond properties ` or a custom bond property. " @@ -191,7 +191,7 @@ .def("load_image", &ColorCodingImageGradient::loadImage) ; ColorCodingModifier_py.def_static("Custom", [](const QString& filename) { - OORef gradient(new ColorCodingImageGradient(ScriptEngine::activeEngine()->dataset())); + OORef gradient(new ColorCodingImageGradient(ScriptEngine::activeDataset())); gradient->loadImage(filename); return gradient; }); @@ -343,7 +343,7 @@ .def_property("destination_property", &FreezePropertyModifier::destinationProperty, &FreezePropertyModifier::setDestinationProperty, "The name of the output particle property that should be written to by the modifier. " "It can be one of the :ref:`standard particle properties ` or a custom particle property. ") - .def("_take_snapshot", static_cast(&FreezePropertyModifier::takePropertySnapshot)) + .def("_take_snapshot", static_cast(&FreezePropertyModifier::takePropertySnapshot)) ; ovito_class(m, @@ -461,18 +461,15 @@ "The distance of the slicing plane from the origin (along its normal vector)." "\n\n" ":Default: 0.0\n") - .def_property("distance_ctrl", &SliceModifier::distanceController, &SliceModifier::setDistanceController) .def_property("normal", &SliceModifier::normal, &SliceModifier::setNormal, "The normal vector of the slicing plane. Does not have to be a unit vector." "\n\n" ":Default: ``(1,0,0)``\n") - .def_property("normal_ctrl", &SliceModifier::normalController, &SliceModifier::setNormalController) .def_property("slice_width", &SliceModifier::sliceWidth, &SliceModifier::setSliceWidth, "The width of the slab to cut. If zero, the modifier cuts all particles on one " "side of the slicing plane." "\n\n" ":Default: 0.0\n") - .def_property("slice_width_ctrl", &SliceModifier::sliceWidthController, &SliceModifier::setSliceWidthController) .def_property("inverse", &SliceModifier::inverse, &SliceModifier::setInverse, "Reverses the sense of the slicing plane." "\n\n" @@ -503,8 +500,8 @@ " [0, 1,0,0],\n" " [0, 0,1,0]])\n" "\n") - .def_property("transformation", MatrixGetter(), - MatrixSetter(), + .def_property("transformation", MatrixGetter(), + MatrixSetter(), "The 3x4 transformation matrix being applied to particle positions and/or the simulation cell. " "The first three matrix columns define the linear part of the transformation, while the fourth " "column specifies the translation vector. " @@ -544,6 +541,12 @@ "If ``True``, the modifier transforms the surface mesh (if any) that has previously been generated by a :py:class:`ConstructSurfaceModifier`." "\n\n" ":Default: ``True``\n") + .def_property("transform_vector_properties", &AffineTransformationModifier::applyToVectorProperties, &AffineTransformationModifier::setApplyToVectorProperties, + "If ``True``, the modifier applies the transformation to certain standard particle and bond properties that represent vectorial quantities. " + "This option is useful if you are using the AffineTransformationModifier to rotate a particle system and want also to rotate vectorial " + "properties associated with the individual particles or bonds, like e.g. the velocity vectors. See the user manual of OVITO for the list of standard particle properties that are affected by this option. " + "\n\n" + ":Default: ``False``\n") ; auto BinAndReduceModifier_py = ovito_class(m, @@ -916,9 +919,9 @@ ":Default: 12\n") ; - ovito_class(m, + auto ClusterAnalysisModifier_py = ovito_class(m, ":Base class: :py:class:`ovito.modifiers.Modifier`\n\n" - "Groups particles into clusters using a distance cutoff criterion. " + "This modifier groups particles into clusters on the basis of a neighboring criterion. " "\n\n" "**Modifier outputs:**" "\n\n" @@ -932,19 +935,33 @@ "**Example:**" "\n\n" "The following script demonstrates how to apply the `numpy.bincount() `_ " - "function to the generated ``Cluster`` particle property to determine the size (=number of particles) of each cluster " - "found by the modifier. " + "function to the ``Cluster`` particle property generated by the :py:class:`!ClusterAnalysisModifier` to determine the size (=number of particles) of each cluster. " "\n\n" ".. literalinclude:: ../example_snippets/cluster_analysis_modifier.py\n" "\n" ) + .def_property("neighbor_mode", &ClusterAnalysisModifier::neighborMode, &ClusterAnalysisModifier::setNeighborMode, + "Selects the neighboring criterion for the clustering algorithm. Valid values are: " + "\n\n" + " * ``ClusterAnalysisModifier.NeighborMode.CutoffRange``\n" + " * ``ClusterAnalysisModifier.NeighborMode.Bonded``\n" + "\n\n" + "In the first mode (``CutoffRange``), the clustering algorithm treats pairs of particles as neighbors which are within a certain range of " + "each other given by the parameter :py:attr:`.cutoff`. " + "\n\n" + "In the second mode (``Bonded``), particles which are connected by bonds are combined into clusters. " + "Bonds between particles can either be loaded from the input simulation file or dynamically created using for example the " + ":py:class:`CreateBondsModifier` or the :py:class:`VoronoiAnalysisModifier`. " + "\n\n" + ":Default: ``ClusterAnalysisModifier.NeighborMode.CutoffRange``\n") .def_property("cutoff", &ClusterAnalysisModifier::cutoff, &ClusterAnalysisModifier::setCutoff, - "The cutoff distance used by the algorithm to form clusters of connected particles." + "The cutoff distance used by the algorithm to form clusters of connected particles. " + "This parameter is only used when :py:attr:`.neighbor_mode` is set to ``CutoffRange``; otherwise it is ignored. " "\n\n" ":Default: 3.2\n") .def_property("only_selected", &ClusterAnalysisModifier::onlySelectedParticles, &ClusterAnalysisModifier::setOnlySelectedParticles, "Lets the modifier perform the analysis only for selected particles. " - "Particles that are not selected will be assigned cluster ID 0 and treated as if they did not exist." + "In this case, particles which are not selected are treated as if they did not exist and will be assigned cluster ID 0. " "\n\n" ":Default: ``False``\n") .def_property("sort_by_size", &ClusterAnalysisModifier::sortBySize, &ClusterAnalysisModifier::setSortBySize, @@ -953,6 +970,11 @@ ":Default: ``False``\n") ; + py::enum_(ClusterAnalysisModifier_py, "NeighborMode") + .value("CutoffRange", ClusterAnalysisModifier::CutoffRange) + .value("Bonding", ClusterAnalysisModifier::Bonding) + ; + ovito_class(m, ":Base class: :py:class:`ovito.modifiers.Modifier`\n\n" "Computes coordination numbers of particles and the radial distribution function (RDF) of the system." @@ -981,7 +1003,7 @@ })) ; - ovito_class(m, + auto CalculateDisplacementsModifier_py = ovito_class(m, ":Base class: :py:class:`ovito.modifiers.Modifier`\n\n" "Computes the displacement vectors of particles based on a separate reference configuration. " "The modifier requires you to load a reference configuration from an external file::" @@ -997,11 +1019,26 @@ "A :py:class:`~ovito.io.FileSource` that provides the reference positions of particles. " "You can call its :py:meth:`~ovito.io.FileSource.load` function to load a reference simulation file " "as shown in the code example above.") - .def_property("eliminate_cell_deformation", &CalculateDisplacementsModifier::eliminateCellDeformation, &CalculateDisplacementsModifier::setEliminateCellDeformation, - "Boolean flag that controls the elimination of the affine cell deformation prior to calculating the " - "displacement vectors." - "\n\n" - ":Default: ``False``\n") + .def_property("affine_mapping", &CalculateDisplacementsModifier::affineMapping, &CalculateDisplacementsModifier::setAffineMapping, + "Selects the type of affine deformation to be applied to the particle coordinates prior to calculating the displacement vectors. " + "This must be one of the following constants:\n" + " * ``CalculateDisplacementsModifier.AffineMapping.Off``\n" + " * ``CalculateDisplacementsModifier.AffineMapping.ToReference``\n" + " * ``CalculateDisplacementsModifier.AffineMapping.ToCurrent``\n" + "\n\n" + "When affine mapping is turned off (``AffineMapping.Off``), the displacement vectors are simply calculated from the new and old absolute " + "particle positions irrespective of the cell shape in the reference and current configuration. " + "The mode ``AffineMapping.ToReference`` applies an affine transformation to the current configuration such that " + "all particle positions are first mapped to the reference cell before calculating the displacement vectors. Note that this transformation " + "is applied only virtually during the displacement vector calculation. " + "The last option, ``AffineMapping.ToCurrent``, does the reverse: it maps the particle positions of the " + "deformed configuration to the deformed cell before calculating the displacements. " + "\n\n" + ":Default: ``CalculateDisplacementsModifier.AffineMapping.Off``\n") + // For backward compatibility with OVITO 2.8.2: + .def_property("eliminate_cell_deformation", + [](CalculateDisplacementsModifier& mod) { return mod.affineMapping() != CalculateDisplacementsModifier::NO_MAPPING; }, + [](CalculateDisplacementsModifier& mod, bool b) { mod.setAffineMapping(b ? CalculateDisplacementsModifier::TO_REFERENCE_CELL : CalculateDisplacementsModifier::NO_MAPPING); }) .def_property("assume_unwrapped_coordinates", &CalculateDisplacementsModifier::assumeUnwrappedCoordinates, &CalculateDisplacementsModifier::setAssumeUnwrappedCoordinates, "If ``True``, the particle coordinates of the reference and of the current configuration are taken as is. " "If ``False``, the minimum image convention is used to deal with particles that have crossed a periodic boundary. " @@ -1034,7 +1071,13 @@ "\n") ; - ovito_class(m, + py::enum_(CalculateDisplacementsModifier_py, "AffineMapping") + .value("Off", CalculateDisplacementsModifier::NO_MAPPING) + .value("ToReference", CalculateDisplacementsModifier::TO_REFERENCE_CELL) + .value("ToCurrent", CalculateDisplacementsModifier::TO_CURRENT_CELL) + ; + + auto HistogramModifier_py = ovito_class(m, ":Base class: :py:class:`ovito.modifiers.Modifier`\n\n" "Generates a histogram from the values of a particle property. " "\n\n" @@ -1045,24 +1088,33 @@ "Example::" "\n\n" " from ovito.modifiers import *\n" - " modifier = HistogramModifier(bin_count=100, property=\"Potential Energy\")\n" + " modifier = HistogramModifier(bin_count=100, particle_property=\"Potential Energy\")\n" " node.modifiers.append(modifier)\n" " node.compute()\n" " \n" " import numpy\n" " numpy.savetxt(\"histogram.txt\", modifier.histogram)\n" "\n") - .def_property("property", &HistogramModifier::sourceProperty, &HistogramModifier::setSourceProperty, + .def_property("particle_property", &HistogramModifier::sourceParticleProperty, &HistogramModifier::setSourceParticleProperty, "The name of the input particle property for which to compute the histogram. " "This can be one of the :ref:`standard particle properties ` or a custom particle property. " - "For vector properties a specific component name must be included in the string, e.g. ``\"Velocity.X\"``. ") + "When using vector properties the component must be included in the name, e.g. ``\"Velocity.X\"``. " + "\n\n" + "This field is only used if :py:attr:`.source_mode` is set to ``Particles``. ") + // For backward compatibility with OVITO 2.8.1: + .def_property("property", &HistogramModifier::sourceParticleProperty, &HistogramModifier::setSourceParticleProperty) + .def_property("bond_property", &HistogramModifier::sourceBondProperty, &HistogramModifier::setSourceBondProperty, + "The name of the input bond property for which to compute the histogram. " + "This can be one of the :ref:`standard bond properties ` or a custom bond property. " + "\n\n" + "This field is only used if :py:attr:`.source_mode` is set to ``Bonds``. ") .def_property("bin_count", &HistogramModifier::numberOfBins, &HistogramModifier::setNumberOfBins, "The number of histogram bins." "\n\n" ":Default: 200\n") .def_property("fix_xrange", &HistogramModifier::fixXAxisRange, &HistogramModifier::setFixXAxisRange, "Controls how the value range of the histogram is determined. If false, the range is chosen automatically by the modifier to include " - "all particle property values. If true, the range is specified manually using the :py:attr:`.xrange_start` and :py:attr:`.xrange_end` attributes." + "all input values. If true, the range is specified manually using the :py:attr:`.xrange_start` and :py:attr:`.xrange_end` attributes." "\n\n" ":Default: ``False``\n") .def_property("xrange_start", &HistogramModifier::xAxisRangeStart, &HistogramModifier::setXAxisRangeStart, @@ -1074,10 +1126,20 @@ "\n\n" ":Default: 0.0\n") .def_property("only_selected", &HistogramModifier::onlySelected, &HistogramModifier::setOnlySelected, - "If ``True``, the histogram is computed only on the basis of currently selected particles. " - "You can use this to restrict histogram calculation to a subset of particles. " + "If ``True``, the histogram is computed only on the basis of currently selected particles or bonds. " + "You can use this to restrict histogram calculation to a subset of particles/bonds. " "\n\n" ":Default: ``False``\n") + .def_property("source_mode", &HistogramModifier::dataSourceType, &HistogramModifier::setDataSourceType, + "Determines where this modifier takes its input values from. " + "This must be one of the following constants:\n" + " * ``HistogramModifier.SourceMode.Particles``\n" + " * ``HistogramModifier.SourceMode.Bonds``\n" + "\n" + "If this is set to ``Bonds``, then the histogram is computed from the bond property selected by :py:attr:`.bond_property`. " + "Otherwise it is computed from the particle property selected by :py:attr:`.particle_property`. " + "\n\n" + ":Default: ``HistogramModifier.SourceMode.Particles``\n") .def_property_readonly("_histogram_data", py::cpp_function([](HistogramModifier& mod) { py::array_t array((size_t)mod.histogramData().size(), mod.histogramData().data(), py::cast(&mod)); // Mark array as read-only. @@ -1086,6 +1148,12 @@ })) ; + py::enum_(HistogramModifier_py, "SourceMode") + .value("Particles", HistogramModifier::Particles) + .value("Bonds", HistogramModifier::Bonds) + ; + + ovito_class{m} ; @@ -1190,7 +1258,7 @@ ovito_class(m, ":Base class: :py:class:`ovito.modifiers.Modifier`\n\n" "Performs the Wigner-Seitz cell analysis to identify point defects in crystals. " - "The modifier requires loading a reference configuration from an external file::" + "The modifier requires loading a reference configuration from an external data file::" "\n\n" " from ovito.modifiers import *\n" " \n" @@ -1226,21 +1294,6 @@ "Boolean flag that controls the elimination of the affine cell deformation prior to performing the analysis." "\n\n" ":Default: ``False``\n") - .def_property("use_frame_offset", &WignerSeitzAnalysisModifier::useReferenceFrameOffset, &WignerSeitzAnalysisModifier::setUseReferenceFrameOffset, - "Determines whether a sliding reference configuration is taken at a constant time offset (specified by :py:attr:`.frame_offset`) " - "relative to the current frame. If ``False``, a constant reference configuration is used (set by the :py:attr:`.reference_frame` parameter) " - "irrespective of the current frame." - "\n\n" - ":Default: ``False``\n") - .def_property("reference_frame", &WignerSeitzAnalysisModifier::referenceFrameNumber, &WignerSeitzAnalysisModifier::setReferenceFrameNumber, - "The frame number to use as reference configuration if the reference data comprises multiple " - "simulation frames. Only used if ``use_frame_offset==False``." - "\n\n" - ":Default: 0\n") - .def_property("frame_offset", &WignerSeitzAnalysisModifier::referenceFrameOffset, &WignerSeitzAnalysisModifier::setReferenceFrameOffset, - "The relative frame offset when using a sliding reference configuration (``use_frame_offset==True``)." - "\n\n" - ":Default: -1\n") .def_property("per_type_occupancies", &WignerSeitzAnalysisModifier::perTypeOccupancy, &WignerSeitzAnalysisModifier::setPerTypeOccupancy, "A parameter flag that controls whether occupancy numbers are determined per particle type. " "\n\n" @@ -1251,6 +1304,10 @@ "the property component ``Occupancy.1`` contains the number of particles of type 1 that occupy a site. " "\n\n" ":Default: ``False``\n") + // For backward compatibility with OVITO 2.8.2: + .def_property("use_frame_offset", &WignerSeitzAnalysisModifier::useReferenceFrameOffset, &WignerSeitzAnalysisModifier::setUseReferenceFrameOffset) + .def_property("reference_frame", &WignerSeitzAnalysisModifier::referenceFrameNumber, &WignerSeitzAnalysisModifier::setReferenceFrameNumber) + .def_property("frame_offset", &WignerSeitzAnalysisModifier::referenceFrameOffset, &WignerSeitzAnalysisModifier::setReferenceFrameOffset) .def_property_readonly("vacancy_count", &WignerSeitzAnalysisModifier::vacancyCount) .def_property_readonly("interstitial_count", &WignerSeitzAnalysisModifier::interstitialCount) ; @@ -1287,13 +1344,27 @@ "\n\n" ":Default: ``False``\n") .def_property("face_threshold", &VoronoiAnalysisModifier::faceThreshold, &VoronoiAnalysisModifier::setFaceThreshold, - "Specifies a minimum area for faces of a Voronoi cell. The modifier will ignore any Voronoi cell faces with an area smaller than this " - "threshold when computing the coordination number and the Voronoi index of particles." + "Specifies a minimum area for individual Voronoi faces in terms of an absolute area. The algorithm will ignore any face of a Voronoi polyhedron with an area smaller than this " + "threshold when computing the coordination number and the Voronoi index of a particle. " + "The threshold parameter is an absolute area given in units of length squared (in whatever units your input data is given). " + "\n\n" + "Note that this absolute area threshold and the :py:attr:`.relative_face_threshold` are applied simultaneously. " + "\n\n" + ":Default: 0.0\n") + .def_property("relative_face_threshold", &VoronoiAnalysisModifier::relativeFaceThreshold, &VoronoiAnalysisModifier::setRelativeFaceThreshold, + "Specifies a minimum area for Voronoi faces in terms of a fraction of total area of the Voronoi polyhedron surface. The algorithm will ignore any face of a Voronoi polyhedron with an area smaller than this " + "threshold when computing the coordination number and the Voronoi index of particles. " + "The threshold parameter is specified as a fraction of the total surface area of the Voronoi polyhedron the faces belong to. " + "For example, a threshold value of 0.01 would remove those faces from the analysis with an area less than 1% of the total area " + "of the polyhedron surface. " + "\n\n" + "Note that this relative threshold and the absolute :py:attr:`.face_threshold` are applied simultaneously. " "\n\n" ":Default: 0.0\n") .def_property("edge_threshold", &VoronoiAnalysisModifier::edgeThreshold, &VoronoiAnalysisModifier::setEdgeThreshold, "Specifies the minimum length an edge must have to be considered in the Voronoi index calculation. Edges that are shorter " - "than this threshold will be ignored when counting the number of edges of a Voronoi face." + "than this threshold will be ignored when counting the number of edges of a Voronoi face. " + "The threshold parameter is an absolute value in units of length of your input data. " "\n\n" ":Default: 0.0\n") .def_property("compute_indices", &VoronoiAnalysisModifier::computeIndices, &VoronoiAnalysisModifier::setComputeIndices, @@ -1477,10 +1548,34 @@ .value("B2", PolyhedralTemplateMatchingModifier::ALLOY_B2) ; - return m.ptr(); -} + ovito_class(m, + ":Base class: :py:class:`ovito.modifiers.Modifier`\n\n" + "Generates an isosurface from a scalar field defined on a structured data grid." + "\n\n" + "**Modifier outputs:**" + "\n\n" + " * :py:attr:`DataCollection.surface ` (:py:class:`~ovito.data.SurfaceMesh`):\n" + " The isosurface mesh generted by the modifier.\n" + ) + .def_property("isolevel", &CreateIsosurfaceModifier::isolevel, &CreateIsosurfaceModifier::setIsolevel, + "The value at which to create the isosurface." + "\n\n" + ":Default: 0.0\n") + .def_property("field_quantity", &CreateIsosurfaceModifier::sourceQuantity, &CreateIsosurfaceModifier::setSourceQuantity, + "The name of the field quantity for which the isosurface should be constructed.") + .def_property_readonly("mesh_display", &CreateIsosurfaceModifier::surfaceMeshDisplay, + "The :py:class:`~ovito.vis.SurfaceMeshDisplay` controlling the visual representation of the generated isosurface.\n") + ; -OVITO_REGISTER_PLUGIN_PYTHON_INTERFACE(ParticlesModify); + ovito_class(m, + ":Base class: :py:class:`ovito.modifiers.Modifier`\n\n" + "Constructs coordination polyhedra around currently selected particles. " + "A coordination polyhedron is the convex hull spanned by the bonded neighbors of a particle. ") + .def_property_readonly("polyhedra_display", &CoordinationPolyhedraModifier::surfaceMeshDisplay, + "A :py:class:`~ovito.vis.SurfaceMeshDisplay` instance controlling the visual representation of the generated polyhedra.\n") + ; + +} OVITO_END_INLINE_NAMESPACE } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/scripting/PythonBinding.h ovito-2.9.0+dfsg1/src/plugins/particles/scripting/PythonBinding.h --- ovito-2.8.1+dfsg2/src/plugins/particles/scripting/PythonBinding.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/scripting/PythonBinding.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,13 +19,14 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLES_PYTHON_BINDING_H -#define __OVITO_PARTICLES_PYTHON_BINDING_H +#pragma once + #include #include #include #include +#include #include #include @@ -176,6 +177,52 @@ } }; + /// Automatic Python string <--> FieldQuantityReference conversion + template<> struct type_caster { + public: + PYBIND11_TYPE_CASTER(Ovito::Particles::FieldQuantityReference, _("FieldQuantityReference")); + + bool load(handle src, bool) { + using namespace Ovito; + using namespace Ovito::Particles; + + QString str; + try { + str = src.cast(); + } + catch(const cast_error&) { + return false; + } + + QStringList parts = str.split(QChar('.')); + if(parts.length() > 2) + throw Exception("Too many dots in field quantity name string."); + else if(parts.length() == 0 || parts[0].isEmpty()) + throw Exception("Field quantity name string is empty."); + QString name = parts[0]; + + // Determine vector component. + int component = -1; + if(parts.length() == 2) { + // Try to convert component to integer. + bool ok; + component = parts[1].toInt(&ok); + if(!ok) { + // Assume its not a vector quantity. + component = -1; + name = parts.join(QChar('.')); + } + } + value = FieldQuantityReference(name, component); + return true; + } + + static handle cast(const Ovito::Particles::FieldQuantityReference& src, return_value_policy /* policy */, handle /* parent */) { + object s = pybind11::cast(src.nameWithComponent()); + return s.release(); + } + }; + /// Automatic Python string list <--> InputColumnMapping conversion template<> struct type_caster { public: @@ -238,4 +285,4 @@ }} // namespace pybind11::detail -#endif // __OVITO_PARTICLES_PYTHON_BINDING_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/scripting/PythonInterface.cpp ovito-2.9.0+dfsg1/src/plugins/particles/scripting/PythonInterface.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/scripting/PythonInterface.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/scripting/PythonInterface.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -33,16 +33,26 @@ #include #include #include +#include #include +#include +#include +#include #include #include #include +#include +#include #include "PythonBinding.h" namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Internal) using namespace PyScript; +void defineModifiersSubmodule(py::module parentModule); // Defined in ModifierBinding.cpp +void defineImportersSubmodule(py::module parentModule); // Defined in ImporterBinding.cpp +void defineExportersSubmodule(py::module parentModule); // Defined in ExporterBinding.cpp + template py::dict PropertyObject__array_interface__(PropertyClass& p) { @@ -60,25 +70,25 @@ if(p.dataType() == qMetaTypeId()) { OVITO_STATIC_ASSERT(sizeof(int) == 4); #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - ai["typestr"] = py::cast("i4"); + ai["typestr"] = py::bytes(">i4"); #endif } else if(p.dataType() == qMetaTypeId()) { #ifdef FLOATTYPE_FLOAT OVITO_STATIC_ASSERT(sizeof(FloatType) == 4); #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - ai["typestr"] = py::cast("f4"); + ai["typestr"] = py::bytes(">f4"); #endif #else OVITO_STATIC_ASSERT(sizeof(FloatType) == 8); #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - ai["typestr"] = py::cast("f8"); + ai["typestr"] = py::bytes(">f8"); #endif #endif } @@ -99,9 +109,9 @@ ai["shape"] = py::make_tuple(p.storage()->size(), 2); OVITO_STATIC_ASSERT(sizeof(unsigned int) == 4); #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - ai["typestr"] = py::cast("u4"); + ai["typestr"] = py::bytes(">u4"); #endif const unsigned int* data; if(!p.storage()->empty()) { @@ -123,9 +133,9 @@ ai["shape"] = py::make_tuple(p.storage()->size(), 3); OVITO_STATIC_ASSERT(sizeof(int8_t) == 1); #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - ai["typestr"] = py::cast("i1"); + ai["typestr"] = py::bytes(">i1"); #endif const int8_t* data; if(!p.storage()->empty()) { @@ -143,6 +153,9 @@ PYBIND11_PLUGIN(Particles) { + // Register the classes of this plugin with the global PluginManager. + PluginManager::instance().registerLoadedPluginClasses(); + py::options options; options.disable_function_signatures(); @@ -167,8 +180,8 @@ "ParticleProperty") .def_static("createUserProperty", &ParticlePropertyObject::createUserProperty) .def_static("createStandardProperty", &ParticlePropertyObject::createStandardProperty) - .def_static("findInState", (ParticlePropertyObject* (*)(const PipelineFlowState&, ParticleProperty::Type))&ParticlePropertyObject::findInState) - .def_static("findInState", (ParticlePropertyObject* (*)(const PipelineFlowState&, const QString&))&ParticlePropertyObject::findInState) + //.def_static("findInState", (ParticlePropertyObject* (*)(const PipelineFlowState&, ParticleProperty::Type))&ParticlePropertyObject::findInState) + //.def_static("findInState", (ParticlePropertyObject* (*)(const PipelineFlowState&, const QString&))&ParticlePropertyObject::findInState) .def("changed", &ParticlePropertyObject::changed, "Informs the particle property object that its internal data has changed. " "This function must be called after each direct modification of the per-particle data " @@ -373,7 +386,7 @@ .def_property("pbc_x", &SimulationCellObject::pbcX, &SimulationCellObject::setPbcX) .def_property("pbc_y", &SimulationCellObject::pbcY, &SimulationCellObject::setPbcY) .def_property("pbc_z", &SimulationCellObject::pbcZ, &SimulationCellObject::setPbcZ) - .def_property("is2D", &SimulationCellObject::is2D, &SimulationCellObject::set2D, + .def_property("is2D", &SimulationCellObject::is2D, &SimulationCellObject::setIs2D, "Specifies whether the system is two-dimensional (true) or three-dimensional (false). " "For two-dimensional systems the PBC flag in the third direction (z) and the third cell vector are ignored. " "\n\n" @@ -382,10 +395,10 @@ MatrixSetter(), "A 3x4 matrix containing the three edge vectors of the cell (matrix columns 0 to 2) " "and the cell origin (matrix column 3).") - .def_property("vector1", &SimulationCellObject::edgeVector1, &SimulationCellObject::setEdgeVector1) - .def_property("vector2", &SimulationCellObject::edgeVector2, &SimulationCellObject::setEdgeVector2) - .def_property("vector3", &SimulationCellObject::edgeVector3, &SimulationCellObject::setEdgeVector3) - .def_property("origin", &SimulationCellObject::origin, &SimulationCellObject::setOrigin) + .def_property("vector1", &SimulationCellObject::cellVector1, &SimulationCellObject::setCellVector1) + .def_property("vector2", &SimulationCellObject::cellVector2, &SimulationCellObject::setCellVector2) + .def_property("vector3", &SimulationCellObject::cellVector3, &SimulationCellObject::setCellVector3) + .def_property("origin", &SimulationCellObject::cellOrigin, &SimulationCellObject::setCellOrigin) .def_property_readonly("volume", &SimulationCellObject::volume3D, "Returns the volume of the three-dimensional simulation cell.\n" "It is the absolute value of the determinant of the cell matrix.") @@ -583,16 +596,16 @@ "The following script demonstrates how to change the line width of the simulation cell:" "\n\n" ".. literalinclude:: ../example_snippets/simulation_cell_display.py\n") - .def_property("line_width", &SimulationCellDisplay::simulationCellLineWidth, &SimulationCellDisplay::setSimulationCellLineWidth, + .def_property("line_width", &SimulationCellDisplay::cellLineWidth, &SimulationCellDisplay::setCellLineWidth, "The width of the simulation cell line (in simulation units of length)." "\n\n" ":Default: 0.14% of the simulation box diameter\n") - .def_property("render_cell", &SimulationCellDisplay::renderSimulationCell, &SimulationCellDisplay::setRenderSimulationCell, + .def_property("render_cell", &SimulationCellDisplay::renderCellEnabled, &SimulationCellDisplay::setRenderCellEnabled, "Boolean flag controlling the cell's visibility in rendered images. " "If ``False``, the cell will only be visible in the interactive viewports. " "\n\n" ":Default: ``True``\n") - .def_property("rendering_color", &SimulationCellDisplay::simulationCellRenderingColor, &SimulationCellDisplay::setSimulationCellRenderingColor, + .def_property("rendering_color", &SimulationCellDisplay::cellColor, &SimulationCellDisplay::setCellColor, "The line color used when rendering the cell." "\n\n" ":Default: ``(0, 0, 0)``\n") @@ -661,7 +674,7 @@ ":Base class: :py:class:`ovito.data.DataObject`\n\n" "This data object stores the surface mesh computed by a :py:class:`~ovito.modifiers.ConstructSurfaceModifier`. " "\n\n" - "Currently, no direct script access to the vertices and faces of the mesh is possible. But you can export the mesh to a VTK text file, " + "Currently, no direct access to the stored vertices and faces of the mesh is possible. But you can export the mesh to a geometry file, " "which can be further processed by external tools such as ParaView. " "\n\n" "The visual appearance of the surface mesh within Ovito is controlled by its attached :py:class:`~ovito.vis.SurfaceMeshDisplay` instance, which is " @@ -669,9 +682,12 @@ "of the :py:class:`~ovito.modifiers.ConstructSurfaceModifier` that created the surface mesh." "\n\n" "Example:\n\n" - ".. literalinclude:: ../example_snippets/surface_mesh.py" + ".. literalinclude:: ../example_snippets/surface_mesh.py\n" + " :lines: 4-\n" ) - .def_property("is_completely_solid", &SurfaceMesh::isCompletelySolid, &SurfaceMesh::setCompletelySolid) + .def_property("is_completely_solid", &SurfaceMesh::isCompletelySolid, &SurfaceMesh::setIsCompletelySolid) + + // For backward compatibility with Ovito 2.8.2: .def("export_vtk", [](SurfaceMesh& mesh, const QString& filename, SimulationCellObject* simCellObj) { if(!simCellObj) throw Exception("A simulation cell is required to generate non-periodic mesh for export."); @@ -707,7 +723,8 @@ auto CutoffNeighborFinder_py = py::class_(m, "CutoffNeighborFinder") .def(py::init<>()) .def("prepare", [](CutoffNeighborFinder& finder, FloatType cutoff, ParticlePropertyObject& positions, SimulationCellObject& cell) { - finder.prepare(cutoff, positions.storage(), cell.data()); + SynchronousTask task(ScriptEngine::activeTaskManager()); + return finder.prepare(cutoff, positions.storage(), cell.data(), nullptr, task.promise()); }) ; @@ -725,7 +742,8 @@ auto NearestNeighborFinder_py = py::class_(m, "NearestNeighborFinder") .def(py::init()) .def("prepare", [](NearestNeighborFinder& finder, ParticlePropertyObject& positions, SimulationCellObject& cell) { - finder.prepare(positions.storage(), cell.data()); + SynchronousTask task(ScriptEngine::activeTaskManager()); + return finder.prepare(positions.storage(), cell.data(), nullptr, task.promise()); }) ; @@ -775,8 +793,8 @@ "BondProperty") .def_static("createUserProperty", &BondPropertyObject::createUserProperty) .def_static("createStandardProperty", &BondPropertyObject::createStandardProperty) - .def_static("findInState", (BondPropertyObject* (*)(const PipelineFlowState&, BondProperty::Type))&BondPropertyObject::findInState) - .def_static("findInState", (BondPropertyObject* (*)(const PipelineFlowState&, const QString&))&BondPropertyObject::findInState) + //.def_static("findInState", (BondPropertyObject* (*)(const PipelineFlowState&, BondProperty::Type))&BondPropertyObject::findInState) + //.def_static("findInState", (BondPropertyObject* (*)(const PipelineFlowState&, const QString&))&BondPropertyObject::findInState) .def("changed", &BondPropertyObject::changed, "Informs the bond property object that its stored data has changed. " "This function must be called after each direct modification of the per-bond data " @@ -859,6 +877,116 @@ "The display name of this bond type.") ; + ovito_abstract_class, DataObject>(m, nullptr, "DataObjectWithSharedFieldQuantityStorage"); + auto FieldQuantityObject_py = ovito_abstract_class>(m) + .def("changed", &FieldQuantityObject::changed, + "Informs the object that its stored data has changed. " + "This function must be called after each direct modification of the field data " + "through the :py:attr:`.marray` attribute.\n\n" + "Calling this method on an input field quantity is necessary to invalidate data caches down the data " + "pipeline. Forgetting to call this method may result in an incomplete re-evaluation of the data pipeline. " + "See :py:attr:`.marray` for more information.") + .def_property("name", &FieldQuantityObject::name, &FieldQuantityObject::setName, + "The human-readable name of the field quantitz.") + .def_property_readonly("components", &FieldQuantityObject::componentCount, + "The number of vector components (if this is a vector quantity); otherwise 1 (= scalar quantity).") + ; + + ovito_class{m}; + + ovito_class(m, + ":Base class: :py:class:`ovito.data.DataObject`\n\n" + "Data object that generates and stores the trajectory lines from a set of moving particles. " + "\n\n" + "The visual appearance of the trajectory lines is controlled by the attached :py:class:`~ovito.vis.TrajectoryLineDisplay` instance, which is " + "accessible through the :py:attr:`~DataObject.display` attribute." + "\n\n" + "**Usage example:**" + "\n\n" + ".. literalinclude:: ../example_snippets/trajectory_lines.py", + "TrajectoryLineGenerator") + .def_property("source_node", &TrajectoryGeneratorObject::source, &TrajectoryGeneratorObject::setSource, + "The :py:class:`~ovito.ObjectNode` that serves as source for particle trajectory data. ") + .def_property("only_selected", &TrajectoryGeneratorObject::onlySelectedParticles, &TrajectoryGeneratorObject::setOnlySelectedParticles, + "Controls whether trajectory lines should only by generated for currently selected particles." + "\n\n" + ":Default: ``True``\n") + .def_property("unwrap_trajectories", &TrajectoryGeneratorObject::unwrapTrajectories, &TrajectoryGeneratorObject::setUnwrapTrajectories, + "Controls whether trajectory lines should be automatically unwrapped at the box boundaries when the particles cross a periodic boundary." + "\n\n" + ":Default: ``True``\n") + .def_property("sampling_frequency", &TrajectoryGeneratorObject::everyNthFrame, &TrajectoryGeneratorObject::setEveryNthFrame, + "Length of animation frame interval at which the particle positions should be sampled when generating the trajectory lines." + "\n\n" + ":Default: 1\n") + .def_property("frame_interval", [](TrajectoryGeneratorObject& tgo) -> py::object { + if(tgo.useCustomInterval()) return py::make_tuple( + tgo.dataset()->animationSettings()->timeToFrame(tgo.customIntervalStart()), + tgo.dataset()->animationSettings()->timeToFrame(tgo.customIntervalEnd())); + else + return py::none(); + }, + [](TrajectoryGeneratorObject& tgo, py::object arg) { + if(py::isinstance(arg)) { + tgo.setUseCustomInterval(false); + return; + } + else if(py::isinstance(arg)) { + py::tuple tup = py::reinterpret_borrow(arg); + if(tup.size() == 2) { + int a = tup[0].cast(); + int b = tup[1].cast(); + tgo.setCustomIntervalStart(tgo.dataset()->animationSettings()->frameToTime(a)); + tgo.setCustomIntervalEnd(tgo.dataset()->animationSettings()->frameToTime(b)); + tgo.setUseCustomInterval(true); + return; + } + } + throw py::value_error("Tuple of two integers or None expected."); + }, + "The animation frame interval over which the particle positions are sampled to generate the trajectory lines. " + "Set this to a tuple of two integers to specify the first and the last animation frame; or use ``None`` to generate trajectory lines " + "over the entire input sequence." + "\n\n" + ":Default: ``None``\n") + .def("generate", [](TrajectoryGeneratorObject& obj) { + return obj.generateTrajectories(ScriptEngine::activeTaskManager()); + }, + "Generates the trajectory lines by sampling the positions of the particles in the :py:attr:`.source_node` at regular time intervals. " + "The trajectory line data is cached by the :py:class:`!TrajectoryLineGenerator`.") + ; + + ovito_class(m, + ":Base class: :py:class:`ovito.vis.Display`\n\n" + "Controls the visual appearance of particle trajectory lines. An instance of this class is attached to every :py:class:`~ovito.data.TrajectoryLineGenerator` data object.", + "TrajectoryLineDisplay") + .def_property("width", &TrajectoryDisplay::lineWidth, &TrajectoryDisplay::setLineWidth, + "The display width of trajectory lines." + "\n\n" + ":Default: 0.2\n") + .def_property("color", &TrajectoryDisplay::lineColor, &TrajectoryDisplay::setLineColor, + "The display color of trajectory lines." + "\n\n" + ":Default: ``(0.6, 0.6, 0.6)``\n") + .def_property("shading", &TrajectoryDisplay::shadingMode, &TrajectoryDisplay::setShadingMode, + "The shading style used for trajectory lines.\n" + "Possible values:" + "\n\n" + " * ``TrajectoryLineDisplay.Shading.Normal`` \n" + " * ``TrajectoryLineDisplay.Shading.Flat`` (default)\n" + "\n") + .def_property("upto_current_time", &TrajectoryDisplay::showUpToCurrentTime, &TrajectoryDisplay::setShowUpToCurrentTime, + "If ``True``, trajectory lines are only rendered up to the particle positions at the current animation time. " + "Otherwise, the complete trajectory lines are displayed." + "\n\n" + ":Default: ``False``\n") + ; + + // Register submodules. + defineModifiersSubmodule(m); // Defined in ModifierBinding.cpp + defineImportersSubmodule(m); // Defined in ImporterBinding.cpp + defineExportersSubmodule(m); // Defined in ExporterBinding.cpp + return m.ptr(); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/util/CapPolygonTessellator.h ovito-2.9.0+dfsg1/src/plugins/particles/util/CapPolygonTessellator.h --- ovito-2.8.1+dfsg2/src/plugins/particles/util/CapPolygonTessellator.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/util/CapPolygonTessellator.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CAP_POLY_TESSELLATOR_H -#define __OVITO_CAP_POLY_TESSELLATOR_H +#pragma once + #include #include @@ -150,11 +150,11 @@ tessellator->mesh.addVertex(p); } - static void errorData(int errno, void* polygon_data) { - if(errno == GLU_TESS_NEED_COMBINE_CALLBACK) + static void errorData(int errnum, void* polygon_data) { + if(errnum == GLU_TESS_NEED_COMBINE_CALLBACK) qDebug() << "ERROR: Could not tessellate cap polygon. It contains overlapping contours."; else - qDebug() << "ERROR: Could not tessellate cap polygon. Error code: " << errno; + qDebug() << "ERROR: Could not tessellate cap polygon. Error code: " << errnum; } private: @@ -171,4 +171,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CAP_POLY_TESSELLATOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/util/CutoffNeighborFinder.cpp ovito-2.9.0+dfsg1/src/plugins/particles/util/CutoffNeighborFinder.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/util/CutoffNeighborFinder.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/util/CutoffNeighborFinder.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,8 +27,9 @@ /****************************************************************************** * Initialization function. ******************************************************************************/ -bool CutoffNeighborFinder::prepare(FloatType cutoffRadius, ParticleProperty* positions, const SimulationCell& cellData, ParticleProperty* selectionProperty, FutureInterfaceBase* progress) +bool CutoffNeighborFinder::prepare(FloatType cutoffRadius, ParticleProperty* positions, const SimulationCell& cellData, ParticleProperty* selectionProperty, PromiseBase& promise) { + promise.setProgressMaximum(0); OVITO_CHECK_POINTER(positions); _cutoffRadius = cutoffRadius; @@ -128,7 +129,7 @@ for(int ix = -stencilRadiusX; ix <= stencilRadiusX; ix++) { for(int iy = -stencilRadiusY; iy <= stencilRadiusY; iy++) { for(int iz = -stencilRadiusZ; iz <= stencilRadiusZ; iz++) { - if(progress && progress->isCanceled()) + if(promise.isCanceled()) return false; if(std::abs(ix) < stencilRadius && std::abs(iy) < stencilRadius && std::abs(iz) < stencilRadius) continue; @@ -160,7 +161,7 @@ const Point3* p = positions->constDataPoint3(); for(size_t pindex = 0; pindex < particles.size(); pindex++, ++p) { - if(progress && progress->isCanceled()) + if(promise.isCanceled()) return false; NeighborListParticle& a = particles[pindex]; @@ -203,7 +204,7 @@ bins[binIndex] = &a; } - return (!progress || !progress->isCanceled()); + return !promise.isCanceled(); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/util/CutoffNeighborFinder.h ovito-2.9.0+dfsg1/src/plugins/particles/util/CutoffNeighborFinder.h --- ovito-2.8.1+dfsg2/src/plugins/particles/util/CutoffNeighborFinder.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/util/CutoffNeighborFinder.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,13 +19,13 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_CUTOFF_NEIGHBOR_FINDER_H -#define __OVITO_CUTOFF_NEIGHBOR_FINDER_H +#pragma once + #include #include #include -#include +#include namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Util) @@ -76,11 +76,11 @@ /// \param positions The ParticleProperty containing the particle coordinates. /// \param simCell The input simulation cell geometry and boundary conditions. /// \param selectionProperty Determines which particles are included in the neighbor search (optional). - /// \param progress An optional callback object that will be used to the report progress. + /// \param promis A callback object that will be used to the report progress. /// \return \c false when the operation has been canceled by the user;s /// \c true on success. /// \throw Exception on error. - bool prepare(FloatType cutoffRadius, ParticleProperty* positions, const SimulationCell& simCell, ParticleProperty* selectionProperty = nullptr, FutureInterfaceBase* progress = nullptr); + bool prepare(FloatType cutoffRadius, ParticleProperty* positions, const SimulationCell& simCell, ParticleProperty* selectionProperty, PromiseBase& promise); /// Returns the cutoff radius set via prepare(). FloatType cutoffRadius() const { return _cutoffRadius; } @@ -89,7 +89,7 @@ FloatType cutoffRadiusSquared() const { return _cutoffRadiusSquared; } /// \brief An iterator class that returns all neighbors of a central particle. - class Query + class OVITO_PARTICLES_EXPORT Query { public: @@ -177,4 +177,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_CUTOFF_NEIGHBOR_FINDER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/util/NearestNeighborFinder.cpp ovito-2.9.0+dfsg1/src/plugins/particles/util/NearestNeighborFinder.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/util/NearestNeighborFinder.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/util/NearestNeighborFinder.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,8 +29,9 @@ /****************************************************************************** * Prepares the neighbor list builder. ******************************************************************************/ -bool NearestNeighborFinder::prepare(ParticleProperty* posProperty, const SimulationCell& cellData, ParticleProperty* selectionProperty, FutureInterfaceBase* progress) +bool NearestNeighborFinder::prepare(ParticleProperty* posProperty, const SimulationCell& cellData, ParticleProperty* selectionProperty, PromiseBase& promise) { + promise.setProgressMaximum(0); OVITO_CHECK_POINTER(posProperty); simCell = cellData; @@ -110,7 +111,7 @@ const int* sel = selectionProperty ? selectionProperty->constDataInt() : nullptr; atoms.resize(posProperty->size()); for(NeighborListAtom& a : atoms) { - if(progress && progress->isCanceled()) + if(promise.isCanceled()) return false; a.pos = *p; // Wrap atomic positions back into simulation box. @@ -131,7 +132,7 @@ root->convertToAbsoluteCoordinates(simCell); - return (!progress || !progress->isCanceled()); + return !promise.isCanceled(); } /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/util/NearestNeighborFinder.h ovito-2.9.0+dfsg1/src/plugins/particles/util/NearestNeighborFinder.h --- ovito-2.8.1+dfsg2/src/plugins/particles/util/NearestNeighborFinder.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/util/NearestNeighborFinder.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,15 +19,15 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_NEAREST_NEIGHBOR_FINDER_H -#define __OVITO_NEAREST_NEIGHBOR_FINDER_H +#pragma once + #include #include #include #include #include -#include +#include namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Util) @@ -65,7 +65,7 @@ Point3 pos; }; - struct TreeNode { + struct OVITO_PARTICLES_EXPORT TreeNode { /// Constructor for a leaf node. TreeNode() : splitDim(-1), atoms(nullptr), numAtoms(0) {} @@ -113,10 +113,11 @@ /// \param posProperty The positions of the particles. /// \param cellData The simulation cell data. /// \param selectionProperty Determines which particles are included in the neighbor search (optional). + /// \param promis A callback object that will be used to the report progress. /// \return \c false when the operation has been canceled by the user; /// \c true on success. /// \throw Exception on error. - bool prepare(ParticleProperty* posProperty, const SimulationCell& cellData, ParticleProperty* selectionProperty = nullptr, FutureInterfaceBase* progress = nullptr); + bool prepare(ParticleProperty* posProperty, const SimulationCell& cellData, ParticleProperty* selectionProperty, PromiseBase& promise); /// Returns the coordinates of the i-th input particle. const Point3& particlePos(size_t index) const { @@ -323,4 +324,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_NEAREST_NEIGHBOR_FINDER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/util/ParticleExpressionEvaluator.cpp ovito-2.9.0+dfsg1/src/plugins/particles/util/ParticleExpressionEvaluator.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/util/ParticleExpressionEvaluator.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/util/ParticleExpressionEvaluator.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -222,7 +222,8 @@ OVITO_ASSERT(!_inputVariables.empty()); // Determine the number of parallel threads to use. - size_t nthreads = Application::instance().idealThreadCount(); + size_t nthreads = Application::instance()->idealThreadCount(); + if(maxThreadCount() != 0 && nthreads > maxThreadCount()) nthreads = maxThreadCount(); if(_particleCount == 0) return; else if(_particleCount < 100) diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/util/ParticleExpressionEvaluator.h ovito-2.9.0+dfsg1/src/plugins/particles/util/ParticleExpressionEvaluator.h --- ovito-2.8.1+dfsg2/src/plugins/particles/util/ParticleExpressionEvaluator.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/util/ParticleExpressionEvaluator.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_EXPRESSION_EVALUATOR_H -#define __OVITO_PARTICLE_EXPRESSION_EVALUATOR_H +#pragma once + #include #include @@ -53,6 +53,12 @@ /// Initializes the parser object and evaluates the expressions for every particle. void evaluate(const std::function& callback, const std::function& filter = std::function()); + /// Returns the maximum number of threads used to evaluate the expression (or 0 if all processor cores are used). + size_t maxThreadCount() const { return _maxThreadCount; } + + /// Sets The maximum number of threads used to evaluate the expression (or 0 if all processor cores should be used). + void setMaxThreadCount(size_t count) { _maxThreadCount = count; } + /// Returns the list of expressions. const std::vector& expression() const { return _expressions; } @@ -200,6 +206,9 @@ /// List of characters allowed in variable names. static QByteArray _validVariableNameChars; + + /// The maximum number of threads used to evaluate the expression. + size_t _maxThreadCount = 0; }; OVITO_END_INLINE_NAMESPACE @@ -207,4 +216,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_EXPRESSION_EVALUATOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/util/ParticleSelectionSet.cpp ovito-2.9.0+dfsg1/src/plugins/particles/util/ParticleSelectionSet.cpp --- ovito-2.8.1+dfsg2/src/plugins/particles/util/ParticleSelectionSet.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/util/ParticleSelectionSet.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,8 +26,8 @@ namespace Ovito { namespace Particles { OVITO_BEGIN_INLINE_NAMESPACE(Util) -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Particles, ParticleSelectionSet, RefTarget); -DEFINE_PROPERTY_FIELD(ParticleSelectionSet, _useIdentifiers, "UseIdentifiers"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(ParticleSelectionSet, RefTarget); +DEFINE_PROPERTY_FIELD(ParticleSelectionSet, useIdentifiers, "UseIdentifiers"); /* Undo record that can restore an old particle selection state. */ class ReplaceSelectionOperation : public UndoableOperation diff -Nru ovito-2.8.1+dfsg2/src/plugins/particles/util/ParticleSelectionSet.h ovito-2.9.0+dfsg1/src/plugins/particles/util/ParticleSelectionSet.h --- ovito-2.8.1+dfsg2/src/plugins/particles/util/ParticleSelectionSet.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/particles/util/ParticleSelectionSet.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PARTICLE_SELECTION_SET_H -#define __OVITO_PARTICLE_SELECTION_SET_H +#pragma once + #include #include @@ -54,7 +54,7 @@ /// Constructor. Q_INVOKABLE ParticleSelectionSet(DataSet* dataset) : RefTarget(dataset), _useIdentifiers(true) { - INIT_PROPERTY_FIELD(ParticleSelectionSet::_useIdentifiers); + INIT_PROPERTY_FIELD(useIdentifiers); } /// Returns the stored selection set as a bit array. @@ -84,9 +84,6 @@ /// Copies the stored selection set into the given output selection particle property. PipelineStatus applySelection(ParticlePropertyObject* outputSelectionProperty, ParticlePropertyObject* identifierProperty); - /// Returns true if this object tries to store identifiers of selected particle when available. - bool useIdentifiers() const { return _useIdentifiers; } - protected: /// Saves the class' contents to the given stream. @@ -110,13 +107,11 @@ QSet _selectedIdentifiers; /// Controls whether the object should store the identifiers of selected particles (when available). - PropertyField _useIdentifiers; + DECLARE_PROPERTY_FIELD(bool, useIdentifiers); Q_OBJECT OVITO_OBJECT - DECLARE_PROPERTY_FIELD(_useIdentifiers); - friend class ReplaceSelectionOperation; }; @@ -124,4 +119,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_PARTICLE_SELECTION_SET_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/povray/exporter/POVRayExporter.cpp ovito-2.9.0+dfsg1/src/plugins/povray/exporter/POVRayExporter.cpp --- ovito-2.8.1+dfsg2/src/plugins/povray/exporter/POVRayExporter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/povray/exporter/POVRayExporter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,7 +22,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -30,7 +31,7 @@ namespace Ovito { namespace POVRay { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(POVRay, POVRayExporter, FileExporter); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(POVRayExporter, FileExporter); /****************************************************************************** * Constructs a new instance of the class. @@ -99,27 +100,40 @@ /****************************************************************************** * Exports a single animation frame to the current output file. *****************************************************************************/ -bool POVRayExporter::exportFrame(int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) +bool POVRayExporter::exportFrame(int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) { - if(!FileExporter::exportFrame(frameNumber, time, filePath, progressDisplay)) + if(!FileExporter::exportFrame(frameNumber, time, filePath, taskManager)) return false; - if(progressDisplay) - progressDisplay->setStatusText(tr("Exporting frame %1 to file '%2'.").arg(frameNumber).arg(filePath)); + // Wait until the scene is ready. + Future sceneReadyFuture = dataset()->makeSceneReady(); + if(!taskManager.waitForTask(sceneReadyFuture)) + return false; Viewport* vp = dataset()->viewportConfig()->activeViewport(); if(!vp) throwException(tr("POV-Ray exporter requires an active viewport.")); + SynchronousTask exportTask(taskManager); + exportTask.setProgressText(tr("Writing data to POV-Ray file")); + OVITO_ASSERT(_renderer); Box3 boundingBox = _renderer->sceneBoundingBox(time); ViewProjectionParameters projParams = vp->projectionParameters(time, _renderer->renderSettings()->outputImageAspectRatio(), boundingBox); - _renderer->beginFrame(time, projParams, vp); - for(SceneNode* node : outputData()) { - _renderer->renderNode(node); + try { + _renderer->_exportTask = &exportTask; + _renderer->beginFrame(time, projParams, vp); + for(SceneNode* node : outputData()) { + _renderer->renderNode(node); + if(exportTask.isCanceled()) break; + } + _renderer->endFrame(!exportTask.isCanceled()); + } + catch(...) { + _renderer->endFrame(false); + throw; } - _renderer->endFrame(); - return true; + return !exportTask.isCanceled(); } OVITO_END_INLINE_NAMESPACE diff -Nru ovito-2.8.1+dfsg2/src/plugins/povray/exporter/POVRayExporter.h ovito-2.9.0+dfsg1/src/plugins/povray/exporter/POVRayExporter.h --- ovito-2.8.1+dfsg2/src/plugins/povray/exporter/POVRayExporter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/povray/exporter/POVRayExporter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_POVRAY_EXPORTER_H -#define __OVITO_POVRAY_EXPORTER_H +#pragma once + #include #include @@ -51,7 +51,14 @@ QFile& outputFile() { return _outputFile; } /// \brief Returns the file filter that specifies the files that can be exported by this service. - virtual QString fileFilter() override { return QStringLiteral("*.pov"); } + virtual QString fileFilter() override { +#ifndef Q_OS_WIN + return QStringLiteral("*.pov"); +#else + // Workaround for bug in Windows file selection dialog (https://bugreports.qt.io/browse/QTBUG-45759) + return QStringLiteral("*"); +#endif + } /// \brief Returns the filter description that is displayed in the drop-down box of the file dialog. virtual QString fileFilterDescription() override { return tr("POV-Ray scene"); } @@ -59,7 +66,7 @@ protected: /// \brief Exports a single animation frame to the current output file. - virtual bool exportFrame(int frameNumber, TimePoint time, const QString& filePath, AbstractProgressDisplay* progressDisplay) override; + virtual bool exportFrame(int frameNumber, TimePoint time, const QString& filePath, TaskManager& taskManager) override; private: @@ -76,4 +83,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_POVRAY_EXPORTER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/povray/gui/POVRayRendererEditor.cpp ovito-2.9.0+dfsg1/src/plugins/povray/gui/POVRayRendererEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/povray/gui/POVRayRendererEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/povray/gui/POVRayRendererEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -36,7 +36,7 @@ namespace Ovito { namespace POVRay { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(POVRayGui, POVRayRendererEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(POVRayRendererEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(POVRayRenderer, POVRayRendererEditor); /** @@ -116,12 +116,12 @@ layout->setColumnStretch(1, 1); // Quality level - IntegerParameterUI* qualityLevelUI = new IntegerParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_qualityLevel)); + IntegerParameterUI* qualityLevelUI = new IntegerParameterUI(this, PROPERTY_FIELD(POVRayRenderer::qualityLevel)); layout->addWidget(qualityLevelUI->label(), 0, 0); layout->addLayout(qualityLevelUI->createFieldLayout(), 0, 1); // Antialiasing - BooleanGroupBoxParameterUI* enableAntialiasingUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_enableAntialiasing)); + BooleanGroupBoxParameterUI* enableAntialiasingUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(POVRayRenderer::antialiasingEnabled)); QGroupBox* aaGroupBox = enableAntialiasingUI->groupBox(); mainLayout->addWidget(aaGroupBox); @@ -131,26 +131,26 @@ layout->setColumnStretch(1, 1); // Sampling Method - IntegerRadioButtonParameterUI* samplingMethodUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_samplingMethod)); + IntegerRadioButtonParameterUI* samplingMethodUI = new IntegerRadioButtonParameterUI(this, PROPERTY_FIELD(POVRayRenderer::samplingMethod)); layout->addWidget(samplingMethodUI->addRadioButton(1, tr("Non-recursive sampling")), 1, 0, 1, 2); layout->addWidget(samplingMethodUI->addRadioButton(2, tr("Recursive sampling")), 2, 0, 1, 2); // AA Threshold - FloatParameterUI* AAThresholdUI = new FloatParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_AAThreshold)); + FloatParameterUI* AAThresholdUI = new FloatParameterUI(this, PROPERTY_FIELD(POVRayRenderer::AAThreshold)); layout->addWidget(AAThresholdUI->label(), 3, 0); layout->addLayout(AAThresholdUI->createFieldLayout(), 3, 1); // AA Depth - IntegerParameterUI* AADepthUI = new IntegerParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_antialiasDepth)); + IntegerParameterUI* AADepthUI = new IntegerParameterUI(this, PROPERTY_FIELD(POVRayRenderer::antialiasDepth)); layout->addWidget(AADepthUI->label(), 4, 0); layout->addLayout(AADepthUI->createFieldLayout(), 4, 1); // Jitter - BooleanParameterUI* enableJitterUI = new BooleanParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_enableJitter)); + BooleanParameterUI* enableJitterUI = new BooleanParameterUI(this, PROPERTY_FIELD(POVRayRenderer::jitterEnabled)); layout->addWidget(enableJitterUI->checkBox(), 5, 0, 1, 2); // Radiosity - BooleanGroupBoxParameterUI* enableRadiosityUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_enableRadiosity)); + BooleanGroupBoxParameterUI* enableRadiosityUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(POVRayRenderer::radiosityEnabled)); QGroupBox* radiosityGroupBox = enableRadiosityUI->groupBox(); mainLayout->addWidget(radiosityGroupBox); @@ -160,22 +160,22 @@ layout->setColumnStretch(1, 1); // Ray count - IntegerParameterUI* radiosityRayCountUI = new IntegerParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_radiosityRayCount)); + IntegerParameterUI* radiosityRayCountUI = new IntegerParameterUI(this, PROPERTY_FIELD(POVRayRenderer::radiosityRayCount)); layout->addWidget(radiosityRayCountUI->label(), 0, 0); layout->addLayout(radiosityRayCountUI->createFieldLayout(), 0, 1); // Recursion limit - IntegerParameterUI* radiosityRecursionLimitUI = new IntegerParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_radiosityRecursionLimit)); + IntegerParameterUI* radiosityRecursionLimitUI = new IntegerParameterUI(this, PROPERTY_FIELD(POVRayRenderer::radiosityRecursionLimit)); layout->addWidget(radiosityRecursionLimitUI->label(), 1, 0); layout->addLayout(radiosityRecursionLimitUI->createFieldLayout(), 1, 1); // Error bound - FloatParameterUI* radiosityErrorBoundUI = new FloatParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_radiosityErrorBound)); + FloatParameterUI* radiosityErrorBoundUI = new FloatParameterUI(this, PROPERTY_FIELD(POVRayRenderer::radiosityErrorBound)); layout->addWidget(radiosityErrorBoundUI->label(), 2, 0); layout->addLayout(radiosityErrorBoundUI->createFieldLayout(), 2, 1); // Focal blur - BooleanGroupBoxParameterUI* enableDepthOfFieldUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_depthOfFieldEnabled)); + BooleanGroupBoxParameterUI* enableDepthOfFieldUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(POVRayRenderer::depthOfFieldEnabled)); QGroupBox* dofGroupBox = enableDepthOfFieldUI->groupBox(); mainLayout->addWidget(dofGroupBox); @@ -185,7 +185,7 @@ layout->setColumnStretch(1, 1); // Focal length - FloatParameterUI* focalLengthUI = new FloatParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_dofFocalLength)); + FloatParameterUI* focalLengthUI = new FloatParameterUI(this, PROPERTY_FIELD(POVRayRenderer::dofFocalLength)); layout->addWidget(focalLengthUI->label(), 0, 0); layout->addLayout(focalLengthUI->createFieldLayout(), 0, 1); @@ -195,15 +195,31 @@ layout->addWidget(modeAction->createPushButton(), 0, 2); // Aperture - FloatParameterUI* apertureUI = new FloatParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_dofAperture)); + FloatParameterUI* apertureUI = new FloatParameterUI(this, PROPERTY_FIELD(POVRayRenderer::dofAperture)); layout->addWidget(apertureUI->label(), 1, 0); layout->addLayout(apertureUI->createFieldLayout(), 1, 1); // Sample count - IntegerParameterUI* dofSampleCountUI = new IntegerParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_dofSampleCount)); + IntegerParameterUI* dofSampleCountUI = new IntegerParameterUI(this, PROPERTY_FIELD(POVRayRenderer::dofSampleCount)); layout->addWidget(dofSampleCountUI->label(), 2, 0); layout->addLayout(dofSampleCountUI->createFieldLayout(), 2, 1); + // Omnidiretional stereo + BooleanGroupBoxParameterUI* enableODSUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(POVRayRenderer::odsEnabled)); + QGroupBox* odsGroupBox = enableODSUI->groupBox(); + mainLayout->addWidget(odsGroupBox); + + layout = new QGridLayout(enableODSUI->childContainer()); + layout->setContentsMargins(4,4,4,4); + layout->setSpacing(2); + layout->setColumnStretch(1, 1); + layout->addWidget(new QLabel(tr("(Requires POV-Ray 3.7.1 or later)")), 0, 0, 1, 2); + + // Interpupillary distance + FloatParameterUI* interpupillaryDistanceUI = new FloatParameterUI(this, PROPERTY_FIELD(POVRayRenderer::interpupillaryDistance)); + layout->addWidget(interpupillaryDistanceUI->label(), 1, 0); + layout->addLayout(interpupillaryDistanceUI->createFieldLayout(), 1, 1); + // Preferences group QGroupBox* settingsGroupBox = new QGroupBox(tr("Settings")); mainLayout->addWidget(settingsGroupBox); @@ -215,7 +231,7 @@ // POV-Ray executable path layout->addWidget(new QLabel(tr("POV-Ray executable:")), 0, 0, 1, 2); - StringParameterUI* povrayExecutablePUI = new StringParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_povrayExecutable)); + StringParameterUI* povrayExecutablePUI = new StringParameterUI(this, PROPERTY_FIELD(POVRayRenderer::povrayExecutable)); layout->addWidget(new QLabel(tr("POV-Ray executable:")), 0, 0); static_cast(povrayExecutablePUI->textBox())->setPlaceholderText(QStringLiteral("povray")); layout->addWidget(povrayExecutablePUI->textBox(), 1, 0); @@ -228,17 +244,18 @@ if(!path.isEmpty()) { UndoableTransaction::handleExceptions(renderer->dataset()->undoStack(), tr("Set executable path"), [renderer, &path]() { renderer->setPovrayExecutable(path); + PROPERTY_FIELD(POVRayRenderer::povrayExecutable).memorizeDefaultValue(renderer); }); } } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } }); layout->addWidget(selectExecutablePathButton, 1, 1); // Show POV-Ray window - BooleanParameterUI* povrayDisplayEnabledUI = new BooleanParameterUI(this, PROPERTY_FIELD(POVRayRenderer::_povrayDisplayEnabled)); + BooleanParameterUI* povrayDisplayEnabledUI = new BooleanParameterUI(this, PROPERTY_FIELD(POVRayRenderer::povrayDisplayEnabled)); layout->addWidget(povrayDisplayEnabledUI->checkBox(), 2, 0, 1, 2); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/povray/gui/POVRayRendererEditor.h ovito-2.9.0+dfsg1/src/plugins/povray/gui/POVRayRendererEditor.h --- ovito-2.8.1+dfsg2/src/plugins/povray/gui/POVRayRendererEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/povray/gui/POVRayRendererEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_POVRAY_RENDERER_EDITOR_H -#define __OVITO_POVRAY_RENDERER_EDITOR_H +#pragma once + #include #include @@ -53,4 +53,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_POVRAY_RENDERER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/povray/renderer/POVRayRenderer.cpp ovito-2.9.0+dfsg1/src/plugins/povray/renderer/POVRayRenderer.cpp --- ovito-2.8.1+dfsg2/src/plugins/povray/renderer/POVRayRenderer.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/povray/renderer/POVRayRenderer.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,7 +23,8 @@ #include #include #include -#include +#include +#include #include "POVRayRenderer.h" #include @@ -31,75 +32,83 @@ namespace Ovito { namespace POVRay { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(POVRay, POVRayRenderer, NonInteractiveSceneRenderer); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _qualityLevel, "QualityLevel", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _enableAntialiasing, "EnableAntialiasing", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _samplingMethod, "SamplingMethod", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _AAThreshold, "AAThreshold", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _antialiasDepth, "AntialiasDepth", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _enableJitter, "EnableJitter", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _povrayDisplayEnabled, "ShowPOVRayDisplay", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _enableRadiosity, "EnableRadiosity", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _radiosityRayCount, "RadiosityRayCount", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _radiosityRecursionLimit, "RadiosityRecursionLimit", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _radiosityErrorBound, "RadiosityErrorBound", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _povrayExecutable, "ExecutablePath", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _depthOfFieldEnabled, "DepthOfFieldEnabled", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _dofFocalLength, "DOFFocalLength", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _dofAperture, "DOFAperture", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, _dofSampleCount, "DOFSampleCount", PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _qualityLevel, "Quality level"); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _enableAntialiasing, "Anti-aliasing"); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _samplingMethod, "Sampling method"); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _AAThreshold, "Anti-aliasing threshold"); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _antialiasDepth, "Anti-aliasing depth"); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _enableJitter, "Enable jitter"); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _povrayDisplayEnabled, "Show POV-Ray window"); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _enableRadiosity, "Radiosity"); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _radiosityRayCount, "Ray count"); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _radiosityRecursionLimit, "Recursion limit"); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _radiosityErrorBound, "Error bound"); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _povrayExecutable, "POV-Ray executable path"); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _depthOfFieldEnabled, "Focal blur"); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _dofFocalLength, "Focal length"); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _dofAperture, "Aperture"); -SET_PROPERTY_FIELD_LABEL(POVRayRenderer, _dofSampleCount, "Blur samples"); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, _qualityLevel, IntegerParameterUnit, 0, 11); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, _samplingMethod, IntegerParameterUnit, 1, 2); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, _AAThreshold, FloatParameterUnit, 0, 1); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, _antialiasDepth, IntegerParameterUnit, 1, 9); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, _radiosityRayCount, IntegerParameterUnit, 1, 1600); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, _radiosityRecursionLimit, IntegerParameterUnit, 1, 20); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, _radiosityErrorBound, FloatParameterUnit, FloatType(1e-5), 100); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(POVRayRenderer, _dofFocalLength, WorldParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, _dofAperture, FloatParameterUnit, 0, 1); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(POVRayRenderer, _dofSampleCount, IntegerParameterUnit, 0); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(POVRayRenderer, NonInteractiveSceneRenderer); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, qualityLevel, "QualityLevel", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, antialiasingEnabled, "EnableAntialiasing", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, samplingMethod, "SamplingMethod", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, AAThreshold, "AAThreshold", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, antialiasDepth, "AntialiasDepth", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, jitterEnabled, "EnableJitter", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, povrayDisplayEnabled, "ShowPOVRayDisplay", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, radiosityEnabled, "EnableRadiosity", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, radiosityRayCount, "RadiosityRayCount", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, radiosityRecursionLimit, "RadiosityRecursionLimit", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, radiosityErrorBound, "RadiosityErrorBound", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, povrayExecutable, "ExecutablePath", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, depthOfFieldEnabled, "DepthOfFieldEnabled", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, dofFocalLength, "DOFFocalLength", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, dofAperture, "DOFAperture", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, dofSampleCount, "DOFSampleCount", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, odsEnabled, "ODSEnabled", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(POVRayRenderer, interpupillaryDistance, "InterpupillaryDistance", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, qualityLevel, "Quality level"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, antialiasingEnabled, "Anti-aliasing"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, samplingMethod, "Sampling method"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, AAThreshold, "Anti-aliasing threshold"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, antialiasDepth, "Anti-aliasing depth"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, jitterEnabled, "Enable jitter"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, povrayDisplayEnabled, "Show POV-Ray window"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, radiosityEnabled, "Radiosity"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, radiosityRayCount, "Ray count"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, radiosityRecursionLimit, "Recursion limit"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, radiosityErrorBound, "Error bound"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, povrayExecutable, "POV-Ray executable path"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, depthOfFieldEnabled, "Focal blur"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, dofFocalLength, "Focal length"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, dofAperture, "Aperture"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, dofSampleCount, "Blur samples"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, odsEnabled, "Omni­directional stereo projection"); +SET_PROPERTY_FIELD_LABEL(POVRayRenderer, interpupillaryDistance, "Interpupillary distance"); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, qualityLevel, IntegerParameterUnit, 0, 11); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, samplingMethod, IntegerParameterUnit, 1, 2); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, AAThreshold, FloatParameterUnit, 0, 1); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, antialiasDepth, IntegerParameterUnit, 1, 9); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, radiosityRayCount, IntegerParameterUnit, 1, 1600); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, radiosityRecursionLimit, IntegerParameterUnit, 1, 20); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, radiosityErrorBound, FloatParameterUnit, FloatType(1e-5), 100); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(POVRayRenderer, dofFocalLength, WorldParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(POVRayRenderer, dofAperture, FloatParameterUnit, 0, 1); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(POVRayRenderer, dofSampleCount, IntegerParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(POVRayRenderer, interpupillaryDistance, WorldParameterUnit, 0); /****************************************************************************** * Constructor. ******************************************************************************/ POVRayRenderer::POVRayRenderer(DataSet* dataset) : NonInteractiveSceneRenderer(dataset), - _qualityLevel(9), _enableAntialiasing(true), _samplingMethod(1), _AAThreshold(0.3f), - _antialiasDepth(3), _enableJitter(true), _povrayDisplayEnabled(true), _enableRadiosity(false), + _qualityLevel(9), _antialiasingEnabled(true), _samplingMethod(1), _AAThreshold(0.3f), + _antialiasDepth(3), _jitterEnabled(true), _povrayDisplayEnabled(true), _radiosityEnabled(false), _radiosityRayCount(50), _radiosityRecursionLimit(2), _radiosityErrorBound(0.8f), - _depthOfFieldEnabled(false), _dofFocalLength(40), _dofAperture(1.0f), _dofSampleCount(80) + _depthOfFieldEnabled(false), _dofFocalLength(40), _dofAperture(1.0f), _dofSampleCount(80), + _odsEnabled(false), _interpupillaryDistance(0.5) { - INIT_PROPERTY_FIELD(POVRayRenderer::_qualityLevel); - INIT_PROPERTY_FIELD(POVRayRenderer::_enableAntialiasing); - INIT_PROPERTY_FIELD(POVRayRenderer::_samplingMethod); - INIT_PROPERTY_FIELD(POVRayRenderer::_AAThreshold); - INIT_PROPERTY_FIELD(POVRayRenderer::_antialiasDepth); - INIT_PROPERTY_FIELD(POVRayRenderer::_enableJitter); - INIT_PROPERTY_FIELD(POVRayRenderer::_povrayDisplayEnabled); - INIT_PROPERTY_FIELD(POVRayRenderer::_enableRadiosity); - INIT_PROPERTY_FIELD(POVRayRenderer::_radiosityRayCount); - INIT_PROPERTY_FIELD(POVRayRenderer::_radiosityRecursionLimit); - INIT_PROPERTY_FIELD(POVRayRenderer::_radiosityErrorBound); - INIT_PROPERTY_FIELD(POVRayRenderer::_povrayExecutable); - INIT_PROPERTY_FIELD(POVRayRenderer::_depthOfFieldEnabled); - INIT_PROPERTY_FIELD(POVRayRenderer::_dofFocalLength); - INIT_PROPERTY_FIELD(POVRayRenderer::_dofAperture); - INIT_PROPERTY_FIELD(POVRayRenderer::_dofSampleCount); + INIT_PROPERTY_FIELD(qualityLevel); + INIT_PROPERTY_FIELD(antialiasingEnabled); + INIT_PROPERTY_FIELD(samplingMethod); + INIT_PROPERTY_FIELD(AAThreshold); + INIT_PROPERTY_FIELD(antialiasDepth); + INIT_PROPERTY_FIELD(jitterEnabled); + INIT_PROPERTY_FIELD(povrayDisplayEnabled); + INIT_PROPERTY_FIELD(radiosityEnabled); + INIT_PROPERTY_FIELD(radiosityRayCount); + INIT_PROPERTY_FIELD(radiosityRecursionLimit); + INIT_PROPERTY_FIELD(radiosityErrorBound); + INIT_PROPERTY_FIELD(povrayExecutable); + INIT_PROPERTY_FIELD(depthOfFieldEnabled); + INIT_PROPERTY_FIELD(dofFocalLength); + INIT_PROPERTY_FIELD(dofAperture); + INIT_PROPERTY_FIELD(dofSampleCount); + INIT_PROPERTY_FIELD(odsEnabled); + INIT_PROPERTY_FIELD(interpupillaryDistance); } /****************************************************************************** @@ -139,13 +148,13 @@ _outputStream << "#version 3.5;\n"; _outputStream << "#include \"transforms.inc\"\n"; - if(_enableRadiosity) { + if(radiosityEnabled()) { _outputStream << "global_settings {\n"; _outputStream << "radiosity {\n"; - _outputStream << "count " << _radiosityRayCount.value() << "\n"; + _outputStream << "count " << radiosityRayCount() << "\n"; _outputStream << "always_sample on\n"; - _outputStream << "recursion_limit " << _radiosityRecursionLimit.value() << "\n"; - _outputStream << "error_bound " << _radiosityErrorBound.value() << "\n"; + _outputStream << "recursion_limit " << radiosityRecursionLimit() << "\n"; + _outputStream << "error_bound " << radiosityErrorBound() << "\n"; _outputStream << "}\n"; _outputStream << "}\n"; } @@ -156,70 +165,123 @@ renderSettings()->backgroundColorController()->getColorValue(time, backgroundColor, iv); _outputStream << "background { color "; write(backgroundColor); _outputStream << "}\n"; + // Create a white sphere around the scene to be independent of background color. + if(radiosityEnabled()) { + FloatType skySphereRadius = params.boundingBox.size().length() * 10; + _outputStream << "sphere { "; write(params.boundingBox.center()); _outputStream << ", " << skySphereRadius << "\n"; + _outputStream << " texture {\n"; + _outputStream << " pigment { color rgb 1.0 }\n"; + _outputStream << " finish { emission 0.8 }\n"; + _outputStream << " }\n"; + _outputStream << " no_image\n"; + _outputStream << " no_shadow\n"; + _outputStream << "}\n"; + } + // Write camera. _outputStream << "camera {\n"; - // Write projection transformation - if(projParams().isPerspective) { - _outputStream << " perspective\n"; - - Point3 p0 = projParams().inverseProjectionMatrix * Point3(0,0,0); - Point3 px = projParams().inverseProjectionMatrix * Point3(1,0,0); - Point3 py = projParams().inverseProjectionMatrix * Point3(0,1,0); - Point3 lookat = projParams().inverseProjectionMatrix * Point3(0,0,0); - Vector3 direction = (lookat - Point3::Origin()).normalized(); - Vector3 right = px - p0; - Vector3 up = right.cross(direction).normalized(); - right = direction.cross(up).normalized() * (up.length() / projParams().aspectRatio); - - _outputStream << " location <0, 0, 0>\n"; - _outputStream << " direction "; write(direction); _outputStream << "\n"; - _outputStream << " right "; write(right); _outputStream << "\n"; - _outputStream << " up "; write(up); _outputStream << "\n"; - _outputStream << " angle " << (atan(tan(projParams().fieldOfView * 0.5) / projParams().aspectRatio) * 2.0 * 180.0 / FLOATTYPE_PI) << "\n"; - - if(depthOfFieldEnabled()) { - _outputStream << " aperture " << dofAperture() << "\n"; - _outputStream << " focal_point "; write(p0 + dofFocalLength() * direction); _outputStream << "\n"; - _outputStream << " blur_samples " << dofSampleCount() << "\n"; - } + if(!odsEnabled()) { + // Write projection transformation + if(projParams().isPerspective) { + _outputStream << " perspective\n"; + + Point3 p0 = projParams().inverseProjectionMatrix * Point3(0,0,0); + Point3 px = projParams().inverseProjectionMatrix * Point3(1,0,0); + Point3 py = projParams().inverseProjectionMatrix * Point3(0,1,0); + Point3 lookat = projParams().inverseProjectionMatrix * Point3(0,0,0); + Vector3 direction = (lookat - Point3::Origin()).normalized(); + Vector3 right = px - p0; + Vector3 up = right.cross(direction).normalized(); + right = direction.cross(up).normalized() * (up.length() / projParams().aspectRatio); + + _outputStream << " location <0, 0, 0>\n"; + _outputStream << " direction "; write(direction); _outputStream << "\n"; + _outputStream << " right "; write(right); _outputStream << "\n"; + _outputStream << " up "; write(up); _outputStream << "\n"; + _outputStream << " angle " << (atan(tan(projParams().fieldOfView * 0.5) / projParams().aspectRatio) * 2.0 * 180.0 / FLOATTYPE_PI) << "\n"; + + if(depthOfFieldEnabled()) { + _outputStream << " aperture " << dofAperture() << "\n"; + _outputStream << " focal_point "; write(p0 + dofFocalLength() * direction); _outputStream << "\n"; + _outputStream << " blur_samples " << dofSampleCount() << "\n"; + } + } + else { + _outputStream << " orthographic\n"; + + Point3 px = projParams().inverseProjectionMatrix * Point3(1,0,0); + Point3 py = projParams().inverseProjectionMatrix * Point3(0,1,0); + Vector3 direction = projParams().inverseProjectionMatrix * Point3(0,0,1) - Point3::Origin(); + Vector3 up = (py - Point3::Origin()) * 2; + Vector3 right = px - Point3::Origin(); + + right = direction.cross(up).normalized() * (up.length() / projParams().aspectRatio); + + _outputStream << " location "; write(-(direction*2)); _outputStream << "\n"; + _outputStream << " direction "; write(direction); _outputStream << "\n"; + _outputStream << " right "; write(right); _outputStream << "\n"; + _outputStream << " up "; write(up); _outputStream << "\n"; + _outputStream << " sky "; write(up); _outputStream << "\n"; + _outputStream << " look_at "; write(-direction); _outputStream << "\n"; + } + // Write camera transformation. + Rotation rot(projParams().viewMatrix); + _outputStream << " Axis_Rotate_Trans("; write(rot.axis()); _outputStream << ", " << (rot.angle() * 180.0f / FLOATTYPE_PI) << ")\n"; + _outputStream << " translate "; write(projParams().inverseViewMatrix.translation()); _outputStream << "\n"; } else { - _outputStream << " orthographic\n"; - - Point3 px = projParams().inverseProjectionMatrix * Point3(1,0,0); - Point3 py = projParams().inverseProjectionMatrix * Point3(0,1,0); - Vector3 direction = projParams().inverseProjectionMatrix * Point3(0,0,1) - Point3::Origin(); - Vector3 up = (py - Point3::Origin()) * 2; - Vector3 right = px - Point3::Origin(); - - right = direction.cross(up).normalized() * (up.length() / projParams().aspectRatio); - - _outputStream << " location "; write(-(direction*2)); _outputStream << "\n"; - _outputStream << " direction "; write(direction); _outputStream << "\n"; - _outputStream << " right "; write(right); _outputStream << "\n"; - _outputStream << " up "; write(up); _outputStream << "\n"; - _outputStream << " sky "; write(up); _outputStream << "\n"; - _outputStream << " look_at "; write(-direction); _outputStream << "\n"; - } - // Write camera transformation. - Rotation rot(projParams().viewMatrix); - _outputStream << " Axis_Rotate_Trans("; write(rot.axis()); _outputStream << ", " << (rot.angle() * 180.0f / FLOATTYPE_PI) << ")\n"; - _outputStream << " translate "; write(projParams().inverseViewMatrix.translation()); _outputStream << "\n"; + if(!projParams().isPerspective) + throwException(tr("Omni­directional stereo projection requires a perspective viewport camera.")); + if(depthOfFieldEnabled()) + throwException(tr("Depth of field does not work with omni­directional stereo projection.")); + + const AffineTransformation& camTM = projParams().inverseViewMatrix * AffineTransformation::rotationY(FLOATTYPE_PI); + + _outputStream << " // ODS Top/Bottom\n"; + _outputStream << " #declare odsIPD = " << interpupillaryDistance() << "; // Interpupillary distance\n"; + _outputStream << " #declare odsVerticalModulation = 0.2; // Use 0.0001 if you don't care about Zenith & Nadir zones.\n"; + _outputStream << " #declare odsHandedness = -1; // -1 for left-handed or 1 for right-handed\n"; + _outputStream << " #declare odsAngle = 0; // Rotation, clockwise, in degree.\n"; + _outputStream << " #declare odslocx = function(x,y) { cos(((x+0.5+odsAngle/360)) * 2 * pi - pi)*(odsIPD/2*pow(sin(select(y, 1-2*(y+0.5), 1-2*y)*pi), odsVerticalModulation))*select(-y,-1,+1) }\n"; + _outputStream << " #declare odslocy = function(x,y) { 0 }\n"; + _outputStream << " #declare odslocz = function(x,y) { sin(((x+0.5+odsAngle/360)) * 2 * pi - pi)*(odsIPD/2*pow(sin(select(y, 1-2*(y+0.5), 1-2*y)*pi), odsVerticalModulation))*select(-y,-1,+1) * odsHandedness }\n"; + _outputStream << " #declare odsdirx = function(x,y) { sin(((x+0.5+odsAngle/360)) * 2 * pi - pi) * cos(pi / 2 -select(y, 1-2*(y+0.5), 1-2*y) * pi) }\n"; + _outputStream << " #declare odsdiry = function(x,y) { sin(pi / 2 - select(y, 1-2*(y+0.5), 1-2*y) * pi) }\n"; + _outputStream << " #declare odsdirz = function(x,y) { -cos(((x+0.5+odsAngle/360)) * 2 * pi - pi) * cos(pi / 2 -select(y, 1-2*(y+0.5), 1-2*y) * pi) * odsHandedness }\n"; + _outputStream << " user_defined\n"; + _outputStream << " location {\n"; + _outputStream << " function { " << camTM(0,0) << "*odslocx(x,y) + " << camTM(0,1) << "*odslocy(x,y) + " << camTM(0,2) << "*odslocz(x,y) + " << camTM(0,3) << " }\n"; + _outputStream << " function { " << camTM(2,0) << "*odslocx(x,y) + " << camTM(2,1) << "*odslocy(x,y) + " << camTM(2,2) << "*odslocz(x,y) + " << camTM(2,3) << " }\n"; + _outputStream << " function { " << camTM(1,0) << "*odslocx(x,y) + " << camTM(1,1) << "*odslocy(x,y) + " << camTM(1,2) << "*odslocz(x,y) + " << camTM(1,3) << " }\n"; + _outputStream << " }\n"; + _outputStream << " direction {\n"; + _outputStream << " function { " << camTM(0,0) << "*odsdirx(x,y) + " << camTM(0,1) << "*odsdiry(x,y) + " << camTM(0,2) << "*odsdirz(x,y) }\n"; + _outputStream << " function { " << camTM(2,0) << "*odsdirx(x,y) + " << camTM(2,1) << "*odsdiry(x,y) + " << camTM(2,2) << "*odsdirz(x,y) }\n"; + _outputStream << " function { " << camTM(1,0) << "*odsdirx(x,y) + " << camTM(1,1) << "*odsdiry(x,y) + " << camTM(1,2) << "*odsdirz(x,y) }\n"; + _outputStream << " }\n"; + } _outputStream << "}\n"; Vector3 viewingDirection = projParams().inverseViewMatrix.column(2); Vector3 screen_x = projParams().inverseViewMatrix.column(0).normalized(); Vector3 screen_y = projParams().inverseViewMatrix.column(1).normalized(); // Write a light source. - _outputStream << "light_source {\n"; - _outputStream << " <0, 0, 0>\n"; - if(!_enableRadiosity) + _outputStream << "light_source {\n"; + if(!odsEnabled()) { // Create parallel light for normal cameras. + _outputStream << " <0, 0, 0>\n"; + } + else { // Create point light for panoramic camera. + _outputStream << " "; write(projParams().inverseViewMatrix.translation() + Vector3(7, 0, 10) * interpupillaryDistance()); _outputStream << "\n"; + } + if(!radiosityEnabled()) _outputStream << " color <1.5, 1.5, 1.5>\n"; else - _outputStream << " color <0.5, 0.5, 0.5>\n"; - _outputStream << " parallel\n"; + _outputStream << " color <0.25, 0.25, 0.25>\n"; _outputStream << " shadowless\n"; - _outputStream << " point_at "; write(projParams().inverseViewMatrix * Vector3(0,0,-1)); _outputStream << "\n"; + if(!odsEnabled()) { + _outputStream << " parallel\n"; + _outputStream << " point_at "; write(projParams().inverseViewMatrix * Vector3(0,0,-1)); _outputStream << "\n"; + } _outputStream << "}\n"; // Define macro for particle primitives in the POV-Ray file to reduce file size. @@ -250,14 +312,21 @@ _outputStream << " texture { pigment { color particleColor } }\n"; _outputStream << "}\n"; _outputStream << "#end\n"; + + _outputStream << "#macro CYL(base, dir, cylRadius, cylColor) // Macro for cylinders\n"; + _outputStream << "cylinder { base, base + dir, cylRadius\n"; + _outputStream << " texture { pigment { color cylColor } }\n"; + _outputStream << "}\n"; + _outputStream << "#end\n"; } /****************************************************************************** * Renders a single animation frame into the given frame buffer. ******************************************************************************/ -bool POVRayRenderer::renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, AbstractProgressDisplay* progress) +bool POVRayRenderer::renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, TaskManager& taskManager) { - if(progress) progress->setStatusText(tr("Writing scene to temporary POV-Ray file.")); + SynchronousTask renderTask(taskManager); + renderTask.setProgressText(tr("Writing scene to temporary POV-Ray file")); // Export Ovito data objects to POV-Ray scene. renderScene(); @@ -274,10 +343,9 @@ _imageFile->close(); // Start POV-Ray sub-process. - if(progress) { - progress->setStatusText(tr("Starting external POV-Ray program.")); - if(progress->wasCanceled()) return false; - } + renderTask.setProgressText(tr("Starting external POV-Ray program.")); + if(renderTask.isCanceled()) + return false; // Specify POV-Ray options: QStringList parameters; @@ -295,31 +363,33 @@ else parameters << "Output_Alpha=off"; // No alpha channel - if(_povrayDisplayEnabled) + if(povrayDisplayEnabled()) parameters << "Display=on"; else parameters << "Display=off"; +#ifdef Q_OS_WIN + // Let the Windows version of POV-Ray exit automatically after rendering is done. + parameters << "/EXIT"; +#endif + // Pass quality settings to POV-Ray. - if(_qualityLevel) - parameters << QString("+Q%1").arg(_qualityLevel); - if(_enableAntialiasing) { - if(_enableAntialiasing) { - if(_AAThreshold) - parameters << QString("+A%1").arg(_AAThreshold); - else - parameters << "+A"; - } - else { - parameters << "-A"; - } + if(qualityLevel()) + parameters << QString("+Q%1").arg(qualityLevel()); + if(antialiasingEnabled()) { + if(AAThreshold()) + parameters << QString("+A%1").arg(AAThreshold()); + else + parameters << "+A"; } - if(_samplingMethod) - parameters << QString("+AM%1").arg(_samplingMethod); - if(_antialiasDepth) - parameters << QString("+R%1").arg(_antialiasDepth); - if(_enableJitter) - parameters << (_enableJitter ? "+J" : "-J"); + else { + parameters << "-A"; + } + if(samplingMethod()) + parameters << QString("+AM%1").arg(samplingMethod()); + if(antialiasingEnabled() && antialiasDepth()) + parameters << QString("+R%1").arg(antialiasDepth()); + parameters << (jitterEnabled() ? "+J" : "-J"); QProcess povrayProcess; QString executablePath = povrayExecutable().isEmpty() ? QString("povray") : povrayExecutable(); @@ -335,30 +405,26 @@ } // Wait until POV-Ray has finished rendering. - if(progress) { - progress->setStatusText(tr("Waiting for external POV-Ray program...")); - if(progress->wasCanceled()) return false; - } + renderTask.setProgressText(tr("Waiting for external POV-Ray program...")); + if(renderTask.isCanceled()) + return false; while(!povrayProcess.waitForFinished(100)) { - if(progress) { - QCoreApplication::processEvents(); - if(progress->wasCanceled()) - return false; - } + renderTask.setProgressValue(0); + if(renderTask.isCanceled()) + return false; } OVITO_ASSERT(povrayProcess.exitStatus() == QProcess::NormalExit); - //qDebug() << "POV-Ray console output:"; - //std::cout << povrayProcess.readAllStandardError().constData(); - //qDebug() << "POV-Ray program returned with exit code" << povrayProcess.exitCode(); + qDebug() << "POV-Ray console output:"; + std::cout << povrayProcess.readAllStandardError().constData(); + qDebug() << "POV-Ray program returned with exit code" << povrayProcess.exitCode(); if(povrayProcess.exitCode() != 0) throwException(tr("POV-Ray program returned with error code %1.").arg(povrayProcess.exitCode())); // Get rendered image from POV-Ray process. - if(progress) { - progress->setStatusText(tr("Getting rendered image from POV-Ray.")); - if(progress->wasCanceled()) return false; - } + renderTask.setProgressText(tr("Getting rendered image from POV-Ray.")); + if(renderTask.isCanceled()) + return false; QImage povrayImage; if(!povrayImage.load(_imageFile->fileName(), "PNG")) { @@ -395,21 +461,22 @@ QRectF boundingRect; painter.drawText(pos, std::get<4>(textCall) | Qt::TextSingleLine | Qt::TextDontClip, std::get<0>(textCall), &boundingRect); frameBuffer->update(boundingRect.toAlignedRect()); - } + } } - return (!progress || progress->wasCanceled() == false); + return !renderTask.isCanceled(); } /****************************************************************************** * This method is called after renderFrame() has been called. ******************************************************************************/ -void POVRayRenderer::endFrame() +void POVRayRenderer::endFrame(bool renderSuccessful) { _sceneFile.reset(); _imageFile.reset(); _outputStream.setDevice(nullptr); - NonInteractiveSceneRenderer::endFrame(); + _exportTask = nullptr; + NonInteractiveSceneRenderer::endFrame(renderSuccessful); } /****************************************************************************** @@ -453,6 +520,7 @@ _outputStream << "SPRTCLE("; write(tm * (*p)); _outputStream << ", " << (*r) << ", "; write(*c); _outputStream << ")\n"; + if(_exportTask && _exportTask->isCanceled()) return; } } } @@ -463,6 +531,7 @@ _outputStream << "DPRTCLE("; write(tm * (*p)); _outputStream << ", " << (*r) << ", "; write(*c); _outputStream << ")\n"; + if(_exportTask && _exportTask->isCanceled()) return; } } } @@ -475,6 +544,7 @@ _outputStream << "CPRTCLE("; write(tm * (*p)); _outputStream << ", " << (*r) << ", "; write(*c); _outputStream << ")\n"; + if(_exportTask && _exportTask->isCanceled()) return; } } } @@ -485,6 +555,7 @@ _outputStream << "SQPRTCLE("; write(tm * (*p)); _outputStream << ", " << (*r) << ", "; write(*c); _outputStream << ")\n"; + if(_exportTask && _exportTask->isCanceled()) return; } } } @@ -532,6 +603,7 @@ 0,0,s.z(),0)); _outputStream << "\n"; _outputStream << "}\n"; } + if(_exportTask && _exportTask->isCanceled()) return; } } else throwException(tr("Particle shape not supported by POV-Ray renderer: %1").arg(particleBuffer.particleShape())); @@ -545,15 +617,12 @@ const AffineTransformation tm = modelTM(); if(arrowBuffer.shape() == ArrowPrimitive::CylinderShape) { for(const DefaultArrowPrimitive::ArrowElement& element : arrowBuffer.elements()) { - _outputStream << "cylinder { "; - write(tm * element.pos); // base point - _outputStream << ", "; - write(tm * (element.pos + element.dir)); // cap point - _outputStream << ", " << element.width << "\n"; - _outputStream << " texture { pigment { color "; - write(element.color); - _outputStream << " } }\n"; - _outputStream << "}\n"; + if(element.dir.isZero() || element.width <= 0) continue; + _outputStream << "CYL("; write(tm * element.pos); + _outputStream << ", "; write(tm * element.dir); + _outputStream << ", " << element.width << ", "; write(element.color); + _outputStream << ")\n"; + if(_exportTask && _exportTask->isCanceled()) return; } } else if(arrowBuffer.shape() == ArrowPrimitive::ArrowShape) { @@ -561,7 +630,7 @@ FloatType arrowHeadRadius = element.width * FloatType(2.5); FloatType arrowHeadLength = arrowHeadRadius * FloatType(1.8); FloatType length = element.dir.length(); - if(length == 0) + if(length == 0 || element.width <= 0) continue; if(length > arrowHeadLength) { @@ -605,6 +674,7 @@ _outputStream << " } }\n"; _outputStream << "}\n"; } + if(_exportTask && _exportTask->isCanceled()) return; } } else throwException(tr("Arrow shape not supported by POV-Ray renderer: %1").arg(arrowBuffer.shape())); @@ -655,7 +725,7 @@ Vector3 d2 = mesh.vertex(face->vertex(2)) - p0; *faceNormal = d2.cross(d1); if(*faceNormal != Vector3::Zero()) { - faceNormal->normalize(); + //faceNormal->normalize(); allMask |= face->smoothingGroups(); } } @@ -717,6 +787,7 @@ ++rv; write(rv->pos); _outputStream << ", "; write(rv->normal); _outputStream << " }\n"; ++rv; + if(_exportTask && _exportTask->isCanceled()) return; } // Write material diff -Nru ovito-2.8.1+dfsg2/src/plugins/povray/renderer/POVRayRenderer.h ovito-2.9.0+dfsg1/src/plugins/povray/renderer/POVRayRenderer.h --- ovito-2.8.1+dfsg2/src/plugins/povray/renderer/POVRayRenderer.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/povray/renderer/POVRayRenderer.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_POVRAY_RENDERER_H -#define __OVITO_POVRAY_RENDERER_H +#pragma once + #include #include @@ -56,10 +56,10 @@ /// Renders a single animation frame into the given frame buffer. /// Throws an exception on error. Returns false when the operation has been aborted by the user. - virtual bool renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, AbstractProgressDisplay* progress) override; + virtual bool renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, TaskManager& taskManager) override; /// This method is called after renderFrame() has been called. - virtual void endFrame() override; + virtual void endFrame(bool renderSuccessful) override; /// Finishes the rendering pass. This is called after all animation frames have been rendered /// or when the rendering operation has been aborted. @@ -88,66 +88,6 @@ _outputStream.setDevice(device); } - /// Returns the path to the external POV-Ray executable. - const QString& povrayExecutable() const { return _povrayExecutable; } - - ///Sets the path to the external POV-Ray executable. - void setPovrayExecutable(const QString& path) { _povrayExecutable = path; } - - /// Returns the POV-Ray quality level to use for rendering (0 <= level <= 11). - int qualityLevel() const { return _qualityLevel; } - - /// Sets the POV-Ray quality level to use for rendering (0 <= level <= 11). - void setQualityLevel(int level) { _qualityLevel = level; } - - /// Returns whether anti-aliasing is turned on. - bool antialiasingEnabled() const { return _enableAntialiasing; } - - /// Turns anti-aliasing on/off - void setAntialiasingEnabled(bool enable) { _enableAntialiasing = enable; } - - /// Returns whether the POV-Ray rendering window is shown. - bool povrayDisplayEnabled() const { return _povrayDisplayEnabled; } - - /// Turns the POV-Ray rendering window on or off. - void setPovrayDisplayEnabled(bool enable) { _povrayDisplayEnabled = enable; } - - /// Returns whether radiosity is turned on. - bool radiosityEnabled() const { return _enableRadiosity; } - - /// Turns radiosity on or off. - void setRadiosityEnabled(bool enable) { _enableRadiosity = enable; } - - /// Returns the number of rays that are sent out whenever a new radiosity value has to be calculated. - int radiosityRayCount() const { return _radiosityRayCount; } - - /// Sets the number of rays that are sent out whenever a new radiosity value has to be calculated. - void setRadiosityRayCount(int count) { _radiosityRayCount = count; } - - /// Returns whether depth-of-field rendering is enabled. - bool depthOfFieldEnabled() const { return _depthOfFieldEnabled; } - - /// Enables/disables depth-of-field rendering. - void setDepthOfFieldEnabled(bool enabled) { _depthOfFieldEnabled = enabled; } - - /// Returns the camera's focal length, which is used for depth-of-field rendering. - FloatType dofFocalLength() const { return _dofFocalLength; } - - /// Sets the camera's focal length, which is used for depth-of-field rendering. - void setDofFocalLength(FloatType length) { _dofFocalLength = length; } - - /// Returns the camera's aperture, which is used for depth-of-field rendering. - FloatType dofAperture() const { return _dofAperture; } - - /// Sets the camera's aperture, which is used for depth-of-field rendering. - void setDofAperture(FloatType aperture) { _dofAperture = aperture; } - - /// Returns the number of sampling rays used for focal blur. - int dofSampleCount() const { return _dofSampleCount; } - - /// Sets the number of sampling rays used for focal blur. - void setDofSampleCount(int count) { _dofSampleCount = count; } - private: /// Writes a 3d vector to the output stream in POV-Ray format. @@ -197,81 +137,73 @@ /// The temporary file for receiving the rendered image from POV-Ray. std::unique_ptr _imageFile; + /// This is used by the POVRayExporter class to make the export process interruptable. + SynchronousTask* _exportTask = nullptr; + /// The POV-Ray quality level to use for rendering (0 <= level <= 11). /// See POV-Ray documentation for details. - PropertyField _qualityLevel; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, qualityLevel, setQualityLevel); /// Turns anti-aliasing on/off - PropertyField _enableAntialiasing; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, antialiasingEnabled, setAntialiasingEnabled); /// Controls the AA sampling method (only 1 or 2 are valid). - PropertyField _samplingMethod; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, samplingMethod, setSamplingMethod); /// Controls the anti-aliasing threshold. - PropertyField _AAThreshold; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, AAThreshold, setAAThreshold); /// Controls the number of AA samples. - PropertyField _antialiasDepth; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, antialiasDepth, setAntialiasDepth); /// Turns on AA-jitter. - PropertyField _enableJitter; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, jitterEnabled, setJitterEnabled); /// Shows or supresses the POV-Ray rendering window. - PropertyField _povrayDisplayEnabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, povrayDisplayEnabled, setPovrayDisplayEnabled); /// Turns on radiosity. - PropertyField _enableRadiosity; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, radiosityEnabled, setRadiosityEnabled); /// Controls the number of rays that are sent out whenever a new radiosity value has to be calculated. - PropertyField _radiosityRayCount; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, radiosityRayCount, setRadiosityRayCount); /// Determines how many recursion levels are used to calculate the diffuse inter-reflection. - PropertyField _radiosityRecursionLimit; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, radiosityRecursionLimit, setRadiosityRecursionLimit); /// Controls the fraction of error tolerated for the radiosity calculation. - PropertyField _radiosityErrorBound; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, radiosityErrorBound, setRadiosityErrorBound); /// Enables depth-of-field rendering. - PropertyField _depthOfFieldEnabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, depthOfFieldEnabled, setDepthOfFieldEnabled); /// Controls the camera's focal length, which is used for depth-of-field rendering. - PropertyField _dofFocalLength; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, dofFocalLength, setDofFocalLength); /// Controls the camera's aperture, which is used for depth-of-field rendering. - PropertyField _dofAperture; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, dofAperture, setDofAperture); /// Controls the number of sampling rays used for focal blur. - PropertyField _dofSampleCount; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, dofSampleCount, setDofSampleCount); /// Path to the external POV-Ray executable. - PropertyField _povrayExecutable; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, povrayExecutable, setPovrayExecutable); + + /// Enables omni­directional stereo projection. + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, odsEnabled, setODSEnabled); + + /// The interpupillary distance for stereo projection. + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, interpupillaryDistance, setInterpupillaryDistance); Q_OBJECT OVITO_OBJECT Q_CLASSINFO("DisplayName", "POV-Ray renderer"); - DECLARE_PROPERTY_FIELD(_qualityLevel); - DECLARE_PROPERTY_FIELD(_enableAntialiasing); - DECLARE_PROPERTY_FIELD(_samplingMethod); - DECLARE_PROPERTY_FIELD(_AAThreshold); - DECLARE_PROPERTY_FIELD(_antialiasDepth); - DECLARE_PROPERTY_FIELD(_enableJitter); - DECLARE_PROPERTY_FIELD(_povrayDisplayEnabled); - DECLARE_PROPERTY_FIELD(_enableRadiosity); - DECLARE_PROPERTY_FIELD(_radiosityRayCount); - DECLARE_PROPERTY_FIELD(_radiosityRecursionLimit); - DECLARE_PROPERTY_FIELD(_radiosityErrorBound); - DECLARE_PROPERTY_FIELD(_depthOfFieldEnabled); - DECLARE_PROPERTY_FIELD(_dofFocalLength); - DECLARE_PROPERTY_FIELD(_dofAperture); - DECLARE_PROPERTY_FIELD(_dofSampleCount); - DECLARE_PROPERTY_FIELD(_povrayExecutable); - friend class POVRayExporter; }; } // End of namespace } // End of namespace -#endif // __OVITO_POVRAY_RENDERER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/povray/resources/python/ovito/io/povray/__init__.py ovito-2.9.0+dfsg1/src/plugins/povray/resources/python/ovito/io/povray/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/povray/resources/python/ovito/io/povray/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/povray/resources/python/ovito/io/povray/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -2,7 +2,7 @@ import ovito.io # Load the native code module -import POVRay +import ovito.plugins.POVRay # Register export formats. -ovito.io.export_file._formatTable["povray"] = POVRay.POVRayExporter +ovito.io.export_file._formatTable["povray"] = ovito.plugins.POVRay.POVRayExporter diff -Nru ovito-2.8.1+dfsg2/src/plugins/povray/resources/python/ovito/vis/povray/__init__.py ovito-2.9.0+dfsg1/src/plugins/povray/resources/python/ovito/vis/povray/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/povray/resources/python/ovito/vis/povray/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/povray/resources/python/ovito/vis/povray/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -2,7 +2,8 @@ import ovito.vis # Load the native code module -import POVRay +import ovito.plugins.POVRay # Inject POVRayRenderer class into parent module. -ovito.vis.POVRayRenderer = POVRay.POVRayRenderer \ No newline at end of file +ovito.vis.POVRayRenderer = ovito.plugins.POVRay.POVRayRenderer +ovito.vis.__all__ += ['POVRayRenderer'] \ No newline at end of file diff -Nru ovito-2.8.1+dfsg2/src/plugins/povray/scripting/PythonInterface.cpp ovito-2.9.0+dfsg1/src/plugins/povray/scripting/PythonInterface.cpp --- ovito-2.8.1+dfsg2/src/plugins/povray/scripting/PythonInterface.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/povray/scripting/PythonInterface.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,6 +23,7 @@ #include #include #include +#include namespace Ovito { namespace POVRay { OVITO_BEGIN_INLINE_NAMESPACE(Internal) @@ -31,6 +32,9 @@ PYBIND11_PLUGIN(POVRay) { + // Register the classes of this plugin with the global PluginManager. + PluginManager::instance().registerLoadedPluginClasses(); + py::options options; options.disable_function_signatures(); @@ -89,7 +93,17 @@ .def_property("blur_samples", &POVRayRenderer::dofSampleCount, &POVRayRenderer::setDofSampleCount, "Controls the maximum number of rays to use for each pixel to compute focus blur (depth-of-field)." "\n\n" - ":Default: 1.0") + ":Default: 1.0") + .def_property("omni_stereo", &POVRayRenderer::odsEnabled, &POVRayRenderer::setODSEnabled, + "This flag enables `omni­directional stereo projection `_ for stereoscopic 360-degree VR videos and images. " + "Note that this requires POV-Ray 3.7.1 or newer. The eye separation distance is controlled by the :py:attr:`.interpupillary_distance` parameter. " + "\n\n" + ":Default: ``False``") + .def_property("interpupillary_distance", &POVRayRenderer::interpupillaryDistance, &POVRayRenderer::setInterpupillaryDistance, + "Controls interpupillary distance (eye separation) for stereoscopic rendering. This setting is only used " + "if the :py:attr:`.omni_stereo` option has been set. " + "\n\n" + ":Default: 0.5") ; ovito_class{m} diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/AnimationBinding.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/AnimationBinding.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/AnimationBinding.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/AnimationBinding.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -35,14 +35,11 @@ using namespace Ovito; namespace py = pybind11; -PYBIND11_PLUGIN(PyScriptAnimation) +void defineAnimationSubmodule(py::module parentModule) { - py::options options; - options.disable_function_signatures(); + py::module m = parentModule.def_submodule("Animation"); - py::module m("PyScriptAnimation"); - - py::object TimeInterval_py = py::class_(m, "TimeInterval") + py::class_(m, "TimeInterval", py::metaclass()) .def(py::init<>()) .def(py::init()) .def(py::init()) @@ -58,13 +55,14 @@ .def("intersect", &TimeInterval::intersect) .def_static("time_to_seconds", &TimeToSeconds) .def_static("seconds_to_time", &TimeFromSeconds) - .def_property_readonly_static("infinite", &TimeInterval::infinite) - .def_property_readonly_static("empty", &TimeInterval::empty) + .def_property_readonly_static("infinite", [](py::object /*self*/) { return TimeInterval::infinite(); }) + .def_property_readonly_static("empty", [](py::object /*self*/) { return TimeInterval::empty(); }) + .def_property_readonly_static("TimeNegativeInfinity", [](py::object /*self*/) { return TimeNegativeInfinity(); }) + .def_property_readonly_static("TimePositiveInfinity", [](py::object /*self*/) { return TimePositiveInfinity(); }) + .def("__str__", [](TimeInterval& iv) { return py::str("({},{})").format(iv.start(), iv.end()); }) .def(py::self == TimeInterval()) .def(py::self != TimeInterval()) ; - py::setattr(TimeInterval_py, "TimeNegativeInfinity", py::cast(TimeNegativeInfinity())); - py::setattr(TimeInterval_py, "TimePositiveInfinity", py::cast(TimePositiveInfinity())); ovito_class(m, "Stores animation-related settings of the current :py:attr:`~ovito.DataSet`. You can access " @@ -73,9 +71,11 @@ "Animation settings comprise the animation length (number of frames) and the current animation time. " "For example, to step through each animation frame and perform some action::" "\n\n" + " from ovito import dataset\n" + " \n" " for frame in range(0, dataset.anim.last_frame + 1):\n" " dataset.anim.current_frame = frame # Jump to the animation frame.\n" - " performSomething()\n" + " perform_something()\n" "\n") .def_property("time", &AnimationSettings::time, &AnimationSettings::setTime) //.def_property("animation_interval", &AnimationSettings::animationInterval, &AnimationSettings::setAnimationInterval) @@ -86,11 +86,12 @@ //.def_property("ticks_per_frame", &AnimationSettings::ticksPerFrame, &AnimationSettings::setTicksPerFrame) .def_property("current_frame", &AnimationSettings::currentFrame, &AnimationSettings::setCurrentFrame, "The current animation frame. This parameter controls the position of the time slider in OVITO's main window " - "and determines which animation frame is shown in the viewports." + "and determines which animation frame is shown in the viewports. It also affects various other functions that operate " + "on the current animation frame." "\n\n" ":Default: 0\n") .def_property("last_frame", &AnimationSettings::lastFrame, &AnimationSettings::setLastFrame, - "The index of the last animation frame. You can change this property to set a new animation length." + "The index of the last animation frame. You can set this property to change the animation length. " "\n\n" ":Default: 0\n") .def_property("first_frame", &AnimationSettings::firstFrame, &AnimationSettings::setFirstFrame, @@ -174,10 +175,6 @@ ovito_class{m} ; - - return m.ptr(); } -OVITO_REGISTER_PLUGIN_PYTHON_INTERFACE(PyScriptAnimation); - }; diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/AppBinding.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/AppBinding.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/AppBinding.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/AppBinding.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,19 +30,16 @@ #include #include #include -#include +#include #include "PythonBinding.h" namespace PyScript { using namespace Ovito; -PYBIND11_PLUGIN(PyScriptApp) +void defineAppSubmodule(py::module parentModule) { - py::options options; - options.disable_function_signatures(); - - py::module m("PyScriptApp"); + py::module m = parentModule.def_submodule("App"); py::class_>(m, "OvitoObject") .def("__str__", [](py::object& pyobj) { @@ -120,21 +117,9 @@ .def("clone", static_cast (CloneHelper::*)(RefTarget*, bool)>(&CloneHelper::cloneObject)) ; - py::class_(m, "AbstractProgressDisplay") - .def_property_readonly("canceled", &AbstractProgressDisplay::wasCanceled) + py::class_(m, "TaskManager") + //.def_property_readonly("canceled", &AbstractProgressDisplay::wasCanceled) ; - - // Let scripts access the current progress display. - m.def("get_progress_display", []() -> AbstractProgressDisplay* { - if(ScriptEngine::activeEngine()) - return ScriptEngine::activeEngine()->progressDisplay(); - else - return nullptr; - }, py::return_value_policy::reference); - - return m.ptr(); } -OVITO_REGISTER_PLUGIN_PYTHON_INTERFACE(PyScriptApp); - }; diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/FileIOBinding.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/FileIOBinding.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/FileIOBinding.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/FileIOBinding.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -26,19 +26,16 @@ #include #include #include -#include +#include #include "PythonBinding.h" namespace PyScript { using namespace Ovito; -PYBIND11_PLUGIN(PyScriptFileIO) +void defineIOSubmodule(py::module parentModule) { - py::options options; - options.disable_function_signatures(); - - py::module m("PyScriptFileIO"); + py::module m = parentModule.def_submodule("IO"); ovito_abstract_class{m} // These are needed by ovito.io.import_file(): @@ -57,11 +54,12 @@ .value("ResetScene", FileImporter::ResetScene) ; - py::class_(m, "FileManager") - .def_property_readonly_static("instance", py::cpp_function(&FileManager::instance, py::return_value_policy::reference)) + //py::class_(m, "FileManager", py::metaclass()) + //.def_property_readonly_static("instance", py::cpp_function( + // [](py::object /*self*/) { return Application::instance()->fileManager(); }, py::return_value_policy::reference)) //.def("removeFromCache", &FileManager::removeFromCache) //.def("urlFromUserInput", &FileManager::urlFromUserInput) - ; + //; ovito_abstract_class{m} //.def("requestReload", &FileSourceImporter::requestReload) @@ -121,9 +119,15 @@ .def_property_readonly("num_frames", &FileSource::numberOfFrames, "The total number of frames the imported file or file sequence contains (read-only).") .def_property_readonly("loaded_frame", &FileSource::loadedFrameIndex, - "The zero-based frame index that is currently loaded into memory by the :py:class:`!FileSource` (read-only). " + "The zero-based frame index that is currently loaded and kept in memory by the :py:class:`!FileSource` (read-only). " "\n\n" - "The content of this frame is accessible through the inherited :py:class:`~ovito.data.DataCollection` interface.") + "The data of this frame is accessible through the inherited :py:class:`~ovito.data.DataCollection` interface.") + .def_property_readonly("loaded_file", [](FileSource& fs) -> QUrl { + if(fs.loadedFrameIndex() < 0) return QUrl(); + const FileSourceImporter::Frame& frameInfo = fs.frames()[fs.loadedFrameIndex()]; + return frameInfo.sourceFile; + }, + "The path or URL of the data file that is currently loaded and kept in memory by the :py:class:`!FileSource` (read-only). ") .def_property("adjust_animation_interval", &FileSource::adjustAnimationIntervalEnabled, &FileSource::setAdjustAnimationIntervalEnabled, "A flag that controls whether the animation length in OVITO is automatically adjusted to match the number of frames in the " "loaded file or file sequence." @@ -141,10 +145,6 @@ //.def("animationTimeToInputFrame", &FileSource::animationTimeToInputFrame) //.def("inputFrameToAnimationTime", &FileSource::inputFrameToAnimationTime) ; - - return m.ptr(); } -OVITO_REGISTER_PLUGIN_PYTHON_INTERFACE(PyScriptFileIO); - }; diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/PythonBinding.h ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/PythonBinding.h --- ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/PythonBinding.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/PythonBinding.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,14 +19,15 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PYSCRIPT_BINDING_H -#define __OVITO_PYSCRIPT_BINDING_H +#pragma once + #include #include #include +#include -PYBIND11_DECLARE_HOLDER_TYPE(T, Ovito::OORef); +PYBIND11_DECLARE_HOLDER_TYPE(T, Ovito::OORef, true); namespace pybind11 { namespace detail { @@ -72,7 +73,7 @@ if(!src) return false; try { QString str = src.cast(); - value = Ovito::FileManager::instance().urlFromUserInput(str); + value = Ovito::Application::instance()->fileManager()->urlFromUserInput(str); return true; } catch(const cast_error&) {} @@ -321,8 +322,13 @@ using namespace Ovito; namespace py = pybind11; -/// \brief Adds the initXXX() function of a plugin to an internal list so that the scripting engine can discover and register all internal modules. +/// Registers the initXXX() function of a plugin so that the scripting engine can discover and load all internal modules. /// Use the OVITO_REGISTER_PLUGIN_PYTHON_INTERFACE macro to create an instance of this structure on application startup. +/// +/// This helper class makes our internal script modules available by registering their initXXX functions with the Python interpreter. +/// This is required for static builds where all Ovito plugins are linked into the main executable file. +/// On Windows this is also needed, because OVITO plugins have an .dll extension and the Python interpreter +/// only looks for modules that have a .pyd extension. struct OVITO_PYSCRIPT_EXPORT PythonPluginRegistration { #if PY_MAJOR_VERSION >= 3 @@ -332,18 +338,19 @@ #endif /// The identifier of the plugin to register. - const char* _moduleName; + std::string _moduleName; /// The initXXX() function to be registered with the Python interpreter. InitFuncPointer _initFunc; /// Next structure in linked list. PythonPluginRegistration* _next; - PythonPluginRegistration(const char* moduleName, InitFuncPointer initFunc) : _moduleName(moduleName), _initFunc(initFunc) { + PythonPluginRegistration(const char* moduleName, InitFuncPointer initFunc) : _initFunc(initFunc) { _next = linkedlist; linkedlist = this; + _moduleName = std::string("ovito.plugins.") + moduleName; } - /// The initXXX() functions for each of the registered plugins. + /// Head of linked list of initXXX() functions. static PythonPluginRegistration* linkedlist; }; @@ -400,9 +407,7 @@ /// Constructs the object instance in place and passes the current DataSet to the C++ constructor. static void constructInstance(OvitoObjectClass& instance) { - ScriptEngine* engine = ScriptEngine::activeEngine(); - if(!engine) throw Exception("Invalid interpreter state. There is no active script engine."); - DataSet* dataset = engine->dataset(); + DataSet* dataset = ScriptEngine::activeDataset(); if(!dataset) throw Exception("Invalid interpreter state. There is no active dataset."); new (&instance) OvitoObjectClass(dataset); } @@ -780,6 +785,4 @@ }); } -}; // End of namespace - -#endif +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/PythonInterface.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/PythonInterface.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/PythonInterface.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/PythonInterface.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -20,11 +20,19 @@ /////////////////////////////////////////////////////////////////////////////// #include -#include +#include +#include #include "PythonBinding.h" namespace PyScript { +void defineAppSubmodule(py::module parentModule); // Defined in AppBinding.cpp +void defineSceneSubmodule(py::module parentModule); // Defined in SceneBinding.cpp +void defineIOSubmodule(py::module parentModule); // Defined in FileIOBinding.cpp +void defineViewportSubmodule(py::module parentModule); // Defined in ViewportBinding.cpp +void defineAnimationSubmodule(py::module parentModule); // Defined in AnimationBinding.cpp +void defineRenderingSubmodule(py::module parentModule); // Defined in RenderingBinding.cpp + using namespace Ovito; PYBIND11_PLUGIN(PyScript) @@ -34,13 +42,63 @@ py::module m("PyScript"); + // Register Ovito-to-Python exception translator. + py::register_exception_translator([](std::exception_ptr p) { + try { + if(p) std::rethrow_exception(p); + } + catch(const Exception& ex) { + PyErr_SetString(PyExc_RuntimeError, ex.messages().join(QChar('\n')).toUtf8().constData()); + } + }); + + // Initialize an ad-hoc environment when this module has been imported by an external Python interpreter and is not running as a standalone app. + // Otherwise an environment is already provided by the StandaloneApplication class. + if(!Application::instance()) { + try { + AdhocApplication* app = new AdhocApplication(); // This will leak, but it doesn't matter because this Python module will never be unloaded. + if(!app->initialize()) + throw Exception("Application object could not be initialized."); + OVITO_ASSERT(Application::instance() == app); + + // Create a global QCoreApplication object if there isn't one already. + // This application object is needed for event processing (e.g. QEventLoop). + if(!QCoreApplication::instance()) { + static int argc = 1; + static char* argv[] = { const_cast("") }; + app->createQtApplication(argc, argv); + } + } + catch(const Exception& ex) { + ex.logError(); + throw std::runtime_error("Error during OVITO runtime environment initialization."); + } + } + OVITO_ASSERT(QCoreApplication::instance() != nullptr); + + // Register submodules. + defineAppSubmodule(m); + defineSceneSubmodule(m); + defineAnimationSubmodule(m); + defineIOSubmodule(m); + defineViewportSubmodule(m); + defineRenderingSubmodule(m); + // Make Ovito program version number available to script. m.attr("version") = py::make_tuple(Application::applicationVersionMajor(), Application::applicationVersionMinor(), Application::applicationVersionRevision()); m.attr("version_string") = py::cast(QCoreApplication::applicationVersion()); // Make environment information available to the script. - m.attr("gui_mode") = py::cast(Application::instance().guiMode()); - m.attr("headless_mode") = py::cast(Application::instance().headlessMode()); + m.attr("gui_mode") = py::cast(Application::instance()->guiMode()); + m.attr("headless_mode") = py::cast(Application::instance()->headlessMode()); + + // Add an attribute to the ovito module that provides access to the active dataset. + DataSet* activeDataset = Application::instance()->datasetContainer()->currentSet(); + m.attr("dataset") = py::cast(activeDataset, py::return_value_policy::reference); + + // Add an attribute to the ovito module that provides access to the global task manager. + TaskManager* activeTaskManager = &Application::instance()->datasetContainer()->taskManager(); + m.attr("task_manager") = py::cast(activeTaskManager, py::return_value_policy::reference); return m.ptr(); } diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/RenderingBinding.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/RenderingBinding.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/RenderingBinding.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/RenderingBinding.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,18 +28,16 @@ #include #include #include +#include #include "PythonBinding.h" namespace PyScript { using namespace Ovito; -PYBIND11_PLUGIN(PyScriptRendering) +void defineRenderingSubmodule(py::module parentModule) { - py::options options; - options.disable_function_signatures(); - - py::module m("PyScriptRendering"); + py::module m = parentModule.def_submodule("Rendering"); py::class_>(m, "FrameBuffer") .def(py::init<>()) @@ -123,6 +121,19 @@ ovito_abstract_class{m} ; + ovito_class(m, + "The standard OpenGL-based renderer." + "\n\n" + "This is the default built-in rendering engine that is also used by OVITO to render the contents of the interactive viewports. " + "Since it accelerates the generation of images by using the computer's graphics hardware, it is very fast.", + "OpenGLRenderer") + .def_property("antialiasing_level", &StandardSceneRenderer::antialiasingLevel, &StandardSceneRenderer::setAntialiasingLevel, + "A positive integer controlling the level of supersampling. If 1, no supersampling is performed. For larger values, " + "the image in rendered at a higher resolution and then scaled back to the output size to reduce aliasing artifacts." + "\n\n" + ":Default: 3") + ; + ovito_abstract_class(m, "Abstract base class for display setting objects that control the visual appearance of data. " ":py:class:`DataObjects ` may be associated with an instance of this class, which can be accessed via " @@ -174,11 +185,6 @@ .value("CylinderShape", ArrowPrimitive::CylinderShape) .value("ArrowShape", ArrowPrimitive::ArrowShape) ; - - return m.ptr(); } -OVITO_REGISTER_PLUGIN_PYTHON_INTERFACE(PyScriptRendering); - - }; diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/SceneBinding.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/SceneBinding.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/SceneBinding.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/SceneBinding.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include "PythonBinding.h" @@ -38,12 +38,9 @@ using namespace Ovito; -PYBIND11_PLUGIN(PyScriptScene) +void defineSceneSubmodule(py::module parentModule) { - py::options options; - options.disable_function_signatures(); - - py::module m("PyScriptScene"); + py::module m = parentModule.def_submodule("Scene"); auto PipelineStatus_py = py::class_(m, "PipelineStatus") .def(py::init<>()) @@ -82,13 +79,16 @@ "displaying the data in the viewports and in rendered images. " "The :py:attr:`.display` attribute provides access to the attached display object and " "allows controlling the visual appearance of the data.") - .def("evaluate", &DataObject::evaluate) + //.def("evaluate", &DataObject::evaluate) //.def("objectValidity", &DataObject::objectValidity) //.def("addDisplayObject", &DataObject::addDisplayObject) //.def("setDisplayObject", &DataObject::setDisplayObject) //.def_property("saveWithScene", &DataObject::saveWithScene, &DataObject::setSaveWithScene) // Required by FileSource.load(): - .def("wait_until_ready", &DataObject::waitUntilReady, py::arg("time"), py::arg("message"), py::arg("progress_display") = (AbstractProgressDisplay*)nullptr) + .def("wait_until_ready", [](DataObject* obj, TimePoint time) { + Future future = obj->evaluateAsync(PipelineEvalRequest(time, false)); + return ScriptEngine::activeTaskManager().waitForTask(future); + }) .def_property("display", &DataObject::displayObject, &DataObject::setDisplayObject, "The :py:class:`~ovito.vis.Display` object associated with this data object, which is responsible for " "displaying the data. If this field is ``None``, the data is non-visual and doesn't appear in the viewports or rendered images.") @@ -276,7 +276,7 @@ PipelineObject_py, "modifier_applications", "PipelineObjectModifierApplicationList"); auto SceneNode_py = ovito_abstract_class(m) - .def_property("name", &SceneNode::name, &SceneNode::setName) + .def_property("name", &SceneNode::nodeName, &SceneNode::setNodeName) .def_property("display_color", &SceneNode::displayColor, &SceneNode::setDisplayColor) .def_property_readonly("parent_node", &SceneNode::parentNode) .def_property_readonly("lookat_node", &SceneNode::lookatTargetNode) @@ -330,10 +330,14 @@ .def_property("source", &ObjectNode::sourceObject, &ObjectNode::setSourceObject, "The object that provides or generates the data that enters the node's modification pipeline. " "This typically is a :py:class:`~ovito.io.FileSource` instance if the node was created by a call to :py:func:`~ovito.io.import_file`.") - //.def_property_readonly("displayObjects", &ObjectNode::displayObjects) // Required by ObjectNode.wait() and ObjectNode.compute(): - .def("eval_pipeline", &ObjectNode::evalPipeline) - .def("wait_until_ready", &ObjectNode::waitUntilReady, py::arg("time"), py::arg("message"), py::arg("progress_display") = (AbstractProgressDisplay*)nullptr) + .def("eval_pipeline", [](ObjectNode* node, TimePoint time) { + return node->evaluatePipelineImmediately(PipelineEvalRequest(time, false)); + }) + .def("wait_until_ready", [](ObjectNode* node, TimePoint time) { + Future future = node->evaluatePipelineAsync(PipelineEvalRequest(time, false)); + return ScriptEngine::activeTaskManager().waitForTask(future); + }) // Required by ObjectNode.modifiers sequence: .def("apply_modifier", &ObjectNode::applyModifier) ; @@ -392,10 +396,6 @@ ovito_class{m} ; - - return m.ptr(); } -OVITO_REGISTER_PLUGIN_PYTHON_INTERFACE(PyScriptScene); - }; diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/ViewportBinding.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/ViewportBinding.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/binding/ViewportBinding.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/binding/ViewportBinding.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -33,12 +33,9 @@ using namespace Ovito; -PYBIND11_PLUGIN(PyScriptViewport) +void defineViewportSubmodule(py::module parentModule) { - py::options options; - options.disable_function_signatures(); - - py::module m("PyScriptViewport"); + py::module m = parentModule.def_submodule("Viewport"); auto Viewport_py = ovito_class(m, "A viewport defines the view on the three-dimensional scene. " @@ -305,10 +302,6 @@ "The output text generated when compiling/running the Python function. " "Contain the error message when the most recent execution of the custom rendering function failed.") ; - - return m.ptr(); } -OVITO_REGISTER_PLUGIN_PYTHON_INTERFACE(PyScriptViewport); - }; diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/CMakeLists.txt ovito-2.9.0+dfsg1/src/plugins/pyscript/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/plugins/pyscript/CMakeLists.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -19,7 +19,8 @@ # ############################################################################### -SET(Python_ADDITIONAL_VERSIONS "3.4" "3.5" "3.6") +SET(Python_ADDITIONAL_VERSIONS 3.4 3.5 3.6 3.7) +FIND_PACKAGE(PythonInterp REQUIRED) FIND_PACKAGE(PythonLibs REQUIRED) IF(MSVC) @@ -30,6 +31,7 @@ SET(SourceFiles engine/ScriptEngine.cpp engine/ScriptAutostarter.cpp + engine/AdhocApplication.cpp binding/PythonInterface.cpp binding/ViewportBinding.cpp binding/AnimationBinding.cpp @@ -43,7 +45,7 @@ OVITO_STANDARD_PLUGIN(PyScript SOURCES PyScript.cpp ${SourceFiles} - LIB_DEPENDENCIES ${PYTHON_LIBRARIES} + LIB_DEPENDENCIES ${PYTHON_LIBRARIES} OpenGLRenderer PYTHON_WRAPPERS "${CMAKE_CURRENT_SOURCE_DIR}/python/" ) @@ -54,8 +56,8 @@ ADD_PRECOMPILED_HEADER(PyScript plugins/pyscript/PyScript.h) # Install the Python source files that belong to the plugin and which provide the scripting interface. -INSTALL(DIRECTORY "${OVITO_PLUGIN_PYTHON_DIRECTORY}/" - DESTINATION "${OVITO_RELATIVE_PLUGIN_PYTHON_DIRECTORY}/" +INSTALL(DIRECTORY "${OVITO_PYTHON_DIRECTORY}/" + DESTINATION "${OVITO_RELATIVE_PYTHON_DIRECTORY}/" REGEX "__pycache__" EXCLUDE) # Build corresponding GUI plugin. @@ -63,52 +65,55 @@ ADD_SUBDIRECTORY(gui) ENDIF() -# Build the script launcher executable. -ADD_EXECUTABLE(ovitos launcher/Main.cpp) -TARGET_LINK_LIBRARIES(ovitos Core Gui) -TARGET_LINK_LIBRARIES(ovitos Qt5::Core Qt5::Gui) -IF(APPLE) - SET_TARGET_PROPERTIES(ovitos PROPERTIES OUTPUT_NAME "ovitos.exe") - SET_TARGET_PROPERTIES(ovitos PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OVITO_LIBRARY_DIRECTORY}") - INSTALL(TARGETS ovitos DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}") - SET(OVITOS_EXECUTABLE "${OVITO_LIBRARY_DIRECTORY}/ovitos.exe") - - # Install the launch helper script. - INSTALL(PROGRAMS "resources/ovitos" DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}") -ELSE() - SET_TARGET_PROPERTIES(ovitos PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OVITO_BINARY_DIRECTORY}") - INSTALL(TARGETS ovitos DESTINATION "${OVITO_RELATIVE_BINARY_DIRECTORY}") - GET_PROPERTY(OVITOS_EXECUTABLE TARGET ovitos PROPERTY LOCATION) -ENDIF() -SET(OVITOS_EXECUTABLE "${OVITOS_EXECUTABLE}" PARENT_SCOPE) -IF(APPLE) - SET_TARGET_PROPERTIES(ovitos PROPERTIES MACOSX_RPATH TRUE) - SET_TARGET_PROPERTIES(ovitos PROPERTIES INSTALL_RPATH "@executable_path/") -ELSEIF(UNIX) - SET_TARGET_PROPERTIES(ovitos PROPERTIES INSTALL_RPATH "$ORIGIN/../lib/ovito/") +IF(OVITO_BUILD_GUI) + # Build the script launcher executable. + ADD_EXECUTABLE(ovitos launcher/Main.cpp) + TARGET_LINK_LIBRARIES(ovitos Core Gui) + TARGET_LINK_LIBRARIES(ovitos Qt5::Core Qt5::Gui) + IF(APPLE) + SET_TARGET_PROPERTIES(ovitos PROPERTIES OUTPUT_NAME "ovitos.exe") + SET_TARGET_PROPERTIES(ovitos PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OVITO_LIBRARY_DIRECTORY}") + INSTALL(TARGETS ovitos DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}") + SET(OVITOS_EXECUTABLE "${OVITO_LIBRARY_DIRECTORY}/ovitos.exe") + + # Install the launch helper script. + INSTALL(PROGRAMS "resources/ovitos" DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}") + ELSE() + SET_TARGET_PROPERTIES(ovitos PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${OVITO_BINARY_DIRECTORY}") + INSTALL(TARGETS ovitos DESTINATION "${OVITO_RELATIVE_BINARY_DIRECTORY}") + GET_PROPERTY(OVITOS_EXECUTABLE TARGET ovitos PROPERTY LOCATION) + ENDIF() + SET(OVITOS_EXECUTABLE "${OVITOS_EXECUTABLE}" PARENT_SCOPE) + IF(APPLE) + SET_TARGET_PROPERTIES(ovitos PROPERTIES MACOSX_RPATH TRUE) + SET_TARGET_PROPERTIES(ovitos PROPERTIES INSTALL_RPATH "@executable_path/") + ELSEIF(UNIX) + SET_TARGET_PROPERTIES(ovitos PROPERTIES INSTALL_RPATH "$ORIGIN/../lib/ovito/") + ENDIF() + # Build the script launcher together with PyScript plugin. + ADD_DEPENDENCIES(PyScript ovitos) ENDIF() -# Build the script launcher together with PyScript plugin. -ADD_DEPENDENCIES(PyScript ovitos) # Install standard Python packages. IF(APPLE) - STRING(REGEX MATCH "[0-9]+\\.[0-9]+" PYTHON_MAJORMINOR_VERSION ${PYTHONLIBS_VERSION_STRING}) - LIST(GET PYTHON_LIBRARIES 0 PYTHON_FIRST_LIBRARY) - GET_FILENAME_COMPONENT(PYTHON_LIBRARY_PATH "${PYTHON_FIRST_LIBRARY}" PATH) - INSTALL(DIRECTORY "${PYTHON_LIBRARY_PATH}/python${PYTHON_MAJORMINOR_VERSION}" - DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}/../Frameworks/Python.framework/Versions/${PYTHON_MAJORMINOR_VERSION}/lib/" - PATTERN "*.pyc" EXCLUDE - PATTERN "*.pyo" EXCLUDE - PATTERN "__pycache__" EXCLUDE - PATTERN "test" EXCLUDE - PATTERN "*.exe" EXCLUDE - PATTERN "sphinx" EXCLUDE) - - # Install Python header files. - INSTALL(DIRECTORY "${PYTHON_INCLUDE_PATH}" DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}/../Frameworks/Python.framework/Versions/${PYTHON_MAJORMINOR_VERSION}/include/") - + IF(OVITO_REDISTRIBUTABLE_PACKAGE) + STRING(REGEX MATCH "[0-9]+\\.[0-9]+" PYTHON_MAJORMINOR_VERSION ${PYTHONLIBS_VERSION_STRING}) + LIST(GET PYTHON_LIBRARIES 0 PYTHON_FIRST_LIBRARY) + GET_FILENAME_COMPONENT(PYTHON_LIBRARY_PATH "${PYTHON_FIRST_LIBRARY}" PATH) + INSTALL(DIRECTORY "${PYTHON_LIBRARY_PATH}/python${PYTHON_MAJORMINOR_VERSION}" + DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}/../Frameworks/Python.framework/Versions/${PYTHON_MAJORMINOR_VERSION}/lib/" + PATTERN "*.pyc" EXCLUDE + PATTERN "*.pyo" EXCLUDE + PATTERN "__pycache__" EXCLUDE + PATTERN "test" EXCLUDE + PATTERN "*.exe" EXCLUDE + PATTERN "sphinx" EXCLUDE) + + # Install Python header files. + INSTALL(DIRECTORY "${PYTHON_INCLUDE_PATH}" DESTINATION "${OVITO_RELATIVE_LIBRARY_DIRECTORY}/../Frameworks/Python.framework/Versions/${PYTHON_MAJORMINOR_VERSION}/include/") + ENDIF() ELSEIF(UNIX) - IF(OVITO_MONOLITHIC_BUILD) + IF(OVITO_REDISTRIBUTABLE_PACKAGE) # Install standard Python packages. STRING(REGEX MATCH "[0-9]+\\.[0-9]+" PYTHON_MAJORMINOR_VERSION ${PYTHONLIBS_VERSION_STRING}) @@ -163,6 +168,7 @@ PATTERN "*.pyc" EXCLUDE PATTERN "*.pyo" EXCLUDE PATTERN "__pycache__" EXCLUDE) + # Also install the compiled modules that are shipped with Python. INSTALL(DIRECTORY "${PYTHON_LIBRARY_PATH}/../DLLs" DESTINATION "${OVITO_RELATIVE_BINARY_DIRECTORY}") @@ -178,7 +184,10 @@ SET(PYTHON_TEST_SCRIPTS_DIR "${CMAKE_SOURCE_DIR}/tests/scripts/test_suite") FILE(GLOB_RECURSE PYTHON_TEST_SCRIPTS RELATIVE "${PYTHON_TEST_SCRIPTS_DIR}" "${PYTHON_TEST_SCRIPTS_DIR}/*.py") FOREACH(test_script ${PYTHON_TEST_SCRIPTS}) + # Run each test case both with 'ovitos' and a second time with the system Python interpreter. ADD_TEST(NAME "${test_script}" WORKING_DIRECTORY "${PYTHON_TEST_SCRIPTS_DIR}" COMMAND "${OVITOS_EXECUTABLE}" "${test_script}") + ADD_TEST(NAME "${test_script}_extern" WORKING_DIRECTORY "${PYTHON_TEST_SCRIPTS_DIR}" COMMAND "${PYTHON_EXECUTABLE}" "${test_script}") + SET_PROPERTY(TEST "${test_script}_extern" PROPERTY ENVIRONMENT "PYTHONPATH=${OVITO_PYTHON_DIRECTORY}") ENDFOREACH() # Also test example snippets that are part of user documentation. @@ -186,6 +195,8 @@ FILE(GLOB_RECURSE PYTHON_EXAMPLE_SNIPPETS RELATIVE "${PYTHON_EXAMPLE_SNIPPETS_DIR}" "${PYTHON_EXAMPLE_SNIPPETS_DIR}/*.py") FOREACH(test_script ${PYTHON_EXAMPLE_SNIPPETS}) ADD_TEST(NAME "snippet_${test_script}" WORKING_DIRECTORY "${PYTHON_EXAMPLE_SNIPPETS_DIR}" COMMAND "${OVITOS_EXECUTABLE}" "${test_script}") + ADD_TEST(NAME "snippet_${test_script}_extern" WORKING_DIRECTORY "${PYTHON_EXAMPLE_SNIPPETS_DIR}" COMMAND "${PYTHON_EXECUTABLE}" "${test_script}") + SET_PROPERTY(TEST "snippet_${test_script}_extern" PROPERTY ENVIRONMENT "PYTHONPATH=${OVITO_PYTHON_DIRECTORY}") ENDFOREACH() # Propagate list of plugins to parent scope. diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/engine/AdhocApplication.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/engine/AdhocApplication.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/engine/AdhocApplication.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/engine/AdhocApplication.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,65 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "AdhocApplication.h" + +namespace PyScript { + +/****************************************************************************** +* Initializes the application object. +******************************************************************************/ +bool AdhocApplication::initialize() +{ + if(!Application::initialize()) + return false; + + // Initialize application state. + PluginManager::initialize(); + + // Create a DataSetContainer and a default DataSet. + _datasetContainer = new DataSetContainer(); + _datasetContainer->setParent(this); + _datasetContainer->setCurrentSet(new DataSet()); + // Do not record operations for undo. + _datasetContainer->currentSet()->undoStack().suspend(); + +#if defined(Q_OS_LINUX) + // On Unix/Linux, use headless mode if no X server is available. + if(!qEnvironmentVariableIsEmpty("DISPLAY")) + _headlessMode = false; +#elif defined(Q_OS_OSX) || defined(Q_OS_WIN) + // On Windows and macOS, there is always an OpenGL implementation available for background rendering. + _headlessMode = false; +#endif + + // Set the global default OpenGL surface format. + // This will let Qt use core profile contexts. + QSurfaceFormat::setDefaultFormat(OpenGLSceneRenderer::getDefaultSurfaceFormat()); + + return true; +} + +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/engine/AdhocApplication.h ovito-2.9.0+dfsg1/src/plugins/pyscript/engine/AdhocApplication.h --- ovito-2.8.1+dfsg2/src/plugins/pyscript/engine/AdhocApplication.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/engine/AdhocApplication.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include + +namespace PyScript { + +using namespace Ovito; + +/** + * \brief The application object that is created when the OVITO Python module is loaded by an external interpreter. + */ +class AdhocApplication : public Application +{ +public: + + /// \brief Initializes the application object. + bool initialize(); + +private: + + Q_OBJECT +}; + +} // End of namespace + + diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/engine/ScriptAutostarter.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/engine/ScriptAutostarter.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/engine/ScriptAutostarter.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/engine/ScriptAutostarter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -21,13 +21,14 @@ #include #include +#include #include #include "ScriptAutostarter.h" #include "ScriptEngine.h" namespace PyScript { -IMPLEMENT_OVITO_OBJECT(PyScript, ScriptAutostarter, AutoStartObject); +IMPLEMENT_OVITO_OBJECT(ScriptAutostarter, AutoStartObject); /****************************************************************************** * Destructor, which is called at program exit. @@ -60,22 +61,22 @@ void ScriptAutostarter::applicationStarted() { // Execute the script commands and files passed on the command line. - QStringList scriptCommands = Application::instance().cmdLineParser().values("exec"); - QStringList scriptFiles = Application::instance().cmdLineParser().values("script"); + QStringList scriptCommands = StandaloneApplication::instance()->cmdLineParser().values("exec"); + QStringList scriptFiles = StandaloneApplication::instance()->cmdLineParser().values("script"); - if((!scriptCommands.empty() || !scriptFiles.empty()) && Application::instance().datasetContainer()) { + if((!scriptCommands.empty() || !scriptFiles.empty()) && Application::instance()->datasetContainer()) { // Get the current dataset. - DataSet* dataset = Application::instance().datasetContainer()->currentSet(); + DataSet* dataset = Application::instance()->datasetContainer()->currentSet(); // Suppress undo recording. Actions performed by startup scripts cannot be undone. UndoSuspender noUndo(dataset); // Set up script engine. - ScriptEngine engine(dataset); + ScriptEngine engine(dataset, Application::instance()->datasetContainer()->taskManager(), false); // Pass command line parameters to the script. - QStringList scriptArguments = Application::instance().cmdLineParser().values("scriptarg"); + QStringList scriptArguments = StandaloneApplication::instance()->cmdLineParser().values("scriptarg"); // Execute script commands. for(int index = scriptCommands.size() - 1; index >= 0; index--) { diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/engine/ScriptAutostarter.h ovito-2.9.0+dfsg1/src/plugins/pyscript/engine/ScriptAutostarter.h --- ovito-2.8.1+dfsg2/src/plugins/pyscript/engine/ScriptAutostarter.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/engine/ScriptAutostarter.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PYSCRIPT_AUTOSTARTER_OBJECT_H -#define __OVITO_PYSCRIPT_AUTOSTARTER_OBJECT_H +#pragma once + #include #include @@ -55,6 +55,4 @@ OVITO_OBJECT }; -}; // End of namespace - -#endif +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/engine/ScriptEngine.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/engine/ScriptEngine.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/engine/ScriptEngine.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/engine/ScriptEngine.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "ScriptEngine.h" namespace PyScript { @@ -31,43 +31,71 @@ /// Points to the script engine that is currently active (i.e. which is executing a script). ScriptEngine* ScriptEngine::_activeEngine = nullptr; -/// Head of linked list containing all initXXX functions. +/// Head of linked list containing all initXXX functions. PythonPluginRegistration* PythonPluginRegistration::linkedlist = nullptr; /****************************************************************************** -* Initializes the scripting engine and sets up the environment. +* Sets the dataset that is currently active in the Python interpreter. ******************************************************************************/ -ScriptEngine::ScriptEngine(DataSet* dataset, QObject* parent, bool redirectOutputToConsole) - : QObject(parent), _dataset(dataset) +void ScriptEngine::setActiveDataset(DataSet* dataset) { - try { - // Initialize the underlying Python interpreter if it isn't initialized already. - initializeInterpreter(); - } - catch(Exception& ex) { - ex.setContext(dataset); - throw; - } + OVITO_ASSERT(dataset); + OVITO_ASSERT(dataset->container()); - // Install default signal handlers for Python script output, which forward the script output to the host application's stdout/stderr. - if(redirectOutputToConsole) { - connect(this, &ScriptEngine::scriptOutput, [](const QString& str) { std::cout << str.toLocal8Bit().constData(); }); - connect(this, &ScriptEngine::scriptError, [](const QString& str) { std::cerr << str.toLocal8Bit().constData(); }); - } + // Add an attribute to the ovito module that provides access to the active dataset. + py::module ovito_module = py::module::import("ovito"); + py::setattr(ovito_module, "dataset", py::cast(dataset, py::return_value_policy::reference)); + + // Add an attribute to the ovito module that provides access to the global task manager. + py::setattr(ovito_module, "task_manager", py::cast(&dataset->container()->taskManager(), py::return_value_policy::reference)); +} + +/****************************************************************************** +* Returns the dataset that is currently active in the Python interpreter. +******************************************************************************/ +DataSet* ScriptEngine::activeDataset() +{ + // Read the ovito module's attribute that provides access to the active dataset. + py::module ovito_module = py::module::import("ovito"); + return py::cast(py::getattr(ovito_module, "dataset", py::none())); +} + +/****************************************************************************** +* Returns the task manager that is currently active in the Python interpreter. +******************************************************************************/ +TaskManager& ScriptEngine::activeTaskManager() +{ + // Read the ovito module's attribute that provides access to the active dataset. + py::module ovito_module = py::module::import("ovito"); + TaskManager* taskManager = py::cast(py::getattr(ovito_module, "task_manager", py::none())); + if(!taskManager) throw Exception(tr("Invalid OVITO context state: There is no active task manager. This should not happen. Please contact the developer.")); + return *taskManager; +} - // Initialize state of the script engine. +/****************************************************************************** +* Initializes the scripting engine and sets up the environment. +******************************************************************************/ +ScriptEngine::ScriptEngine(DataSet* dataset, TaskManager& taskManager, bool privateContext, QObject* parent) + : QObject(parent), _dataset(dataset), _taskManager(&taskManager) +{ try { + // Initialize our embedded Python interpreter if it isn't running already. + if(!Py_IsInitialized()) + initializeEmbeddedInterpreter(); + // Import the main module and get a reference to the main namespace. - // Make a local copy of the global main namespace for this engine. + // Make a local copy of the global main namespace for this execution context. // The original namespace dictionary is not touched. py::object main_module = py::module::import("__main__"); - _mainNamespace = main_module.attr("__dict__").attr("copy")(); - - // Add a reference to the current dataset to the namespace. - PyObject* mod = PyImport_ImportModule("ovito"); - if(!mod) throw py::error_already_set(); - py::module ovito_module = py::reinterpret_steal(mod); - py::setattr(ovito_module, "dataset", py::cast(dataset, py::return_value_policy::reference)); + if(privateContext) { + _mainNamespace = py::getattr(main_module, "__dict__").attr("copy")(); + } + else { + _mainNamespace = py::getattr(main_module, "__dict__"); + } + + // Add the 'dataset' attribute to the ovito module that provides access to the active dataset. + setActiveDataset(dataset); } catch(py::error_already_set& ex) { ex.restore(); @@ -75,6 +103,10 @@ PyErr_PrintEx(0); throw Exception(tr("Failed to initialize Python interpreter."), dataset); } + catch(Exception& ex) { + ex.setContext(dataset); + throw; + } catch(const std::exception& ex) { throw Exception(tr("Failed to initialize Python interpreter. %1").arg(ex.what()), dataset); } @@ -85,9 +117,13 @@ ******************************************************************************/ ScriptEngine::~ScriptEngine() { + if(_activeEngine == this) { + qWarning() << "Deleting active script engine."; + _activeEngine = nullptr; + } try { // Explicitly release all objects created by Python scripts. - _mainNamespace.clear(); + if(_mainNamespace) _mainNamespace.clear(); } catch(py::error_already_set& ex) { ex.restore(); @@ -96,9 +132,9 @@ } /****************************************************************************** -* Initializes the Python interpreter and sets up the global namespace. +* Initializes the embedded Python interpreter and sets up the global namespace. ******************************************************************************/ -void ScriptEngine::initializeInterpreter() +void ScriptEngine::initializeEmbeddedInterpreter() { // This is a one-time global initialization. static bool isInterpreterInitialized = false; @@ -122,17 +158,17 @@ // On Windows this is needed, because OVITO plugins have an .dll extension and the Python interpreter // only looks for modules that have a .pyd extension. for(PythonPluginRegistration* r = PythonPluginRegistration::linkedlist; r != nullptr; r = r->_next) { - // Note: "const_cast" is for backward compatibility with Python 2.6. - PyImport_AppendInittab(const_cast(r->_moduleName), r->_initFunc); + // Note: const_cast<> is for backward compatibility with Python 2.6. + PyImport_AppendInittab(const_cast(r->_moduleName.c_str()), r->_initFunc); } // Initialize the Python interpreter. Py_Initialize(); - py::object sys_module = py::module::import("sys"); + py::module sys_module = py::module::import("sys"); // Install output redirection (don't do this in console mode as it interferes with the interactive interpreter). - if(Application::instance().guiMode()) { + if(Application::instance()->guiMode()) { // Register the output redirector class. py::class_(sys_module, "__StdOutStreamRedirectorHelper") .def("write", &InterpreterStdOutputRedirector::write) @@ -145,26 +181,22 @@ sys_module.attr("stderr") = py::cast(new InterpreterStdErrorRedirector(), py::return_value_policy::take_ownership); } - // Install Ovito to Python exception translator. - py::register_exception_translator([](std::exception_ptr p) { - try { - if(p) std::rethrow_exception(p); - } - catch(const Exception& ex) { - PyErr_SetString(PyExc_RuntimeError, ex.messages().join(QChar('\n')).toUtf8().constData()); - } - }); + // Determine path where Python source files are located. + QDir prefixDir(QCoreApplication::applicationDirPath()); +#if defined(Q_OS_WIN) + QString pythonModulePath = prefixDir.absolutePath() + QStringLiteral("/plugins/python"); +#elif defined(Q_OS_MAC) + QString pythonModulePath = prefixDir.absolutePath() + QStringLiteral("/../Resources/python"); +#else + QString pythonModulePath = prefixDir.absolutePath() + QStringLiteral("/../lib/ovito/plugins/python"); +#endif - // Prepend directories containing OVITO's Python modules to sys.path. + // Prepend directory containing OVITO's Python source files to sys.path. py::object sys_path = sys_module.attr("path"); - - for(const QDir& pluginDir : PluginManager::instance().pluginDirs()) { - py::object path = py::cast(QDir::toNativeSeparators(pluginDir.absolutePath() + "/python")); - PyList_Insert(sys_path.ptr(), 0, path.ptr()); - } + PyList_Insert(sys_path.ptr(), 0, py::cast(QDir::toNativeSeparators(pythonModulePath)).ptr()); // Prepend current directory to sys.path. - sys_path.attr("insert")(0, ""); + PyList_Insert(sys_path.ptr(), 0, py::str().ptr()); } catch(const Exception&) { throw; @@ -190,15 +222,11 @@ ******************************************************************************/ int ScriptEngine::executeCommands(const QString& commands, const QStringList& scriptArguments) { - if(QThread::currentThread() != QCoreApplication::instance()->thread()) - throw Exception(tr("Can run Python scripts only from the main thread.")); - - if(!_mainNamespace) - throw Exception(tr("Python script engine is not initialized."), dataset()); + if(QCoreApplication::instance() && QThread::currentThread() != QCoreApplication::instance()->thread()) + throw Exception(tr("Can run Python scripts only from the main thread."), dataset()); - // Remember the script engine that was active so we can restore it later. - ScriptEngine* previousEngine = _activeEngine; - _activeEngine = this; + // Activate this engine. + ActiveScriptEngineSetter engineSetter(this); try { // Pass command line parameters to the script. @@ -213,23 +241,19 @@ if(!result) throw py::error_already_set(); Py_XDECREF(result); - _activeEngine = previousEngine; return 0; } catch(py::error_already_set& ex) { - return handlePythonException(ex, previousEngine); + return handlePythonException(ex); } catch(Exception& ex) { - _activeEngine = previousEngine; ex.setContext(dataset()); throw; } catch(const std::exception& ex) { - _activeEngine = previousEngine; throw Exception(tr("Script execution error: %1").arg(ex.what()), dataset()); } catch(...) { - _activeEngine = previousEngine; throw Exception(tr("Unhandled exception thrown by Python interpreter."), dataset()); } } @@ -240,34 +264,26 @@ ******************************************************************************/ void ScriptEngine::execute(const std::function& func) { - if(QThread::currentThread() != QCoreApplication::instance()->thread()) - throw Exception(tr("Can run Python scripts only from the main thread.")); - - if(!_mainNamespace) - throw Exception(tr("Python script engine is not initialized."), dataset()); + if(QCoreApplication::instance() && QThread::currentThread() != QCoreApplication::instance()->thread()) + throw Exception(tr("Can run Python scripts only from the main thread."), dataset()); - // Remember the script engine that was active so we can restore it later. - ScriptEngine* previousEngine = _activeEngine; - _activeEngine = this; + // Activate this engine. + ActiveScriptEngineSetter engineSetter(this); try { func(); - _activeEngine = previousEngine; } catch(py::error_already_set& ex) { - handlePythonException(ex, previousEngine); + handlePythonException(ex); } catch(Exception& ex) { - _activeEngine = previousEngine; ex.setContext(dataset()); throw; } catch(const std::exception& ex) { - _activeEngine = previousEngine; throw Exception(tr("Script execution error: %1").arg(ex.what()), dataset()); } catch(...) { - _activeEngine = previousEngine; throw Exception(tr("Unhandled exception thrown by Python interpreter."), dataset()); } } @@ -290,14 +306,10 @@ int ScriptEngine::executeFile(const QString& filename, const QStringList& scriptArguments) { if(QThread::currentThread() != QCoreApplication::instance()->thread()) - throw Exception(tr("Can run Python scripts only from the main thread.")); - - if(!_mainNamespace) - throw Exception(tr("Python script engine is not initialized."), dataset()); + throw Exception(tr("Can run Python scripts only from the main thread."), dataset()); - // Remember the script engine that was active so we can restore it later. - ScriptEngine* previousEngine = _activeEngine; - _activeEngine = this; + // Activate this engine. + ActiveScriptEngineSetter engineSetter(this); try { // Pass command line parameters to the script. @@ -311,23 +323,19 @@ _mainNamespace["__file__"] = nativeFilename; py::eval_file(nativeFilename, _mainNamespace, _mainNamespace); - _activeEngine = previousEngine; return 0; } catch(py::error_already_set& ex) { - return handlePythonException(ex, previousEngine, filename); + return handlePythonException(ex, filename); } catch(Exception& ex) { - _activeEngine = previousEngine; ex.setContext(dataset()); throw; } catch(const std::exception& ex) { - _activeEngine = previousEngine; throw Exception(tr("Script execution error: %1").arg(ex.what()), dataset()); } catch(...) { - _activeEngine = previousEngine; throw Exception(tr("Unhandled exception thrown by Python interpreter."), dataset()); } } @@ -335,13 +343,12 @@ /****************************************************************************** * Handles an exception raised by the Python side. ******************************************************************************/ -int ScriptEngine::handlePythonException(py::error_already_set& ex, ScriptEngine* previousEngine, const QString& filename) +int ScriptEngine::handlePythonException(py::error_already_set& ex, const QString& filename) { ex.restore(); // Handle calls to sys.exit() if(PyErr_ExceptionMatches(PyExc_SystemExit)) { - _activeEngine = previousEngine; return handleSystemExit(); } @@ -351,7 +358,7 @@ tr("The Python script '%1' has exited with an error.").arg(filename), dataset()); // Retrieve Python error message and traceback. - if(Application::instance().guiMode()) { + if(Application::instance()->guiMode()) { PyObject* extype; PyObject* value; PyObject* traceback; @@ -387,8 +394,6 @@ // Print error message to the console. PyErr_PrintEx(0); } - // Deactivate script engine. - _activeEngine = previousEngine; // Raise C++ exception. throw exception; @@ -404,10 +409,13 @@ int exitcode = 0; PyErr_Fetch(&exception, &value, &tb); + #if PY_MAJOR_VERSION < 3 if(Py_FlushLine()) PyErr_Clear(); #endif + + // Interpret sys.exit() argument. if(value && value != Py_None) { #ifdef PyExceptionInstance_Check if(PyExceptionInstance_Check(value)) { // Python 2.6 or newer @@ -432,8 +440,14 @@ exitcode = (int)PyInt_AsLong(value); #endif else { + // Send sys.exit() argument to stderr. py::str s(value); - Q_EMIT scriptError(s.cast() + QChar('\n')); + try { + auto write = py::module::import("sys").attr("stderr").attr("write"); + write(s); + write("\n"); + } + catch(const py::error_already_set&) {} exitcode = 1; } } diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/engine/ScriptEngine.h ovito-2.9.0+dfsg1/src/plugins/pyscript/engine/ScriptEngine.h --- ovito-2.8.1+dfsg2/src/plugins/pyscript/engine/ScriptEngine.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/engine/ScriptEngine.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PYSCRIPT_ENGINE_H -#define __OVITO_PYSCRIPT_ENGINE_H +#pragma once + #include #include @@ -39,20 +39,27 @@ /// \brief Initializes the scripting engine and sets up the environment. /// \param dataset The engine will execute scripts in the context of this dataset. - /// \param parent The owner of this QObject. - /// \param redirectOutputToConsole Controls whether the Python script output should be forwarded to the terminal. - ScriptEngine(DataSet* dataset, QObject* parent = nullptr, bool redirectOutputToConsole = true); + /// \param taskManager The engine will execute scripts in the context of this task manager. + /// \param privateContext If true, then changes made by the script will not be visible on the global scope. + /// \param parent The owner of this engine object. + ScriptEngine(DataSet* dataset, TaskManager& taskManager, bool privateContext, QObject* parent = nullptr); /// \brief Destructor virtual ~ScriptEngine(); - /// \brief Returns the dataset that provides the context for the script. + /// \brief Returns the dataset that provides the context for the script execution. DataSet* dataset() const { return _dataset; } + /// \brief Returns the task manager that provides the context for the script execution. + TaskManager& taskManager() const { OVITO_ASSERT(_taskManager); return *_taskManager; } + /// \brief Returns the script engine that is currently active (i.e. which is executing a script). /// \return The active script engine or NULL if no script is currently being executed. static ScriptEngine* activeEngine() { return _activeEngine; } + /// \brief Returns the task manager providing the context for the currently running script. + static TaskManager& activeTaskManager(); + /// \brief Executes a Python script consisting of one or more statements. /// \param script The script commands. /// \param scriptArguments An optional list of command line arguments that will be passed to the script via sys.argv. @@ -62,9 +69,8 @@ int executeCommands(const QString& commands, const QStringList& scriptArguments = QStringList()); /// \brief Executes a Python script file. - /// \param scriptFile The script file path. + /// \param file The script file path. /// \param scriptArguments An optional list of command line arguments that will be passed to the script via sys.argv. - /// \param progressDisplay An optional progress display, which will be used to show the script execution status. /// \return The exit code returned by the Python script. /// \throw Exception on error. int executeFile(const QString& file, const QStringList& scriptArguments = QStringList()); @@ -83,14 +89,11 @@ /// \brief Provides access to the global namespace the script will be executed in by this script engine. py::dict& mainNamespace() { return _mainNamespace; } - /// Returns the progress display that has been registered with the engine, which - /// is responsible for showing the progress of long-running operations - /// performed by a script. - AbstractProgressDisplay* progressDisplay() const { return _progressDisplay; } - - /// Sets the progress display which will be used to show the progress of long-running operations - /// performed by a script. - void setProgressDisplay(AbstractProgressDisplay* progressDisplay) { _progressDisplay = progressDisplay; } + /// \brief Returns the dataset that is currently active in the Python interpreter. + static DataSet* activeDataset(); + + /// \brief Sets the dataset that is currently active in the Python interpreter. + static void setActiveDataset(DataSet* dataset); Q_SIGNALS: @@ -102,15 +105,15 @@ private: - /// Initializes the Python interpreter and sets up the global namespace. - void initializeInterpreter(); + /// Initializes the embedded Python interpreter and sets up the global namespace. + void initializeEmbeddedInterpreter(); /// Handles a call to sys.exit() in the Python interpreter. /// Returns the program exit code. int handleSystemExit(); /// Handles an exception raised by the Python side. - int handlePythonException(py::error_already_set& ex, ScriptEngine* previousEngine, const QString& filename = QString()); + int handlePythonException(py::error_already_set& ex, const QString& filename = QString()); /// This helper class redirects Python script write calls to the sys.stdout stream to this script engine. struct InterpreterStdOutputRedirector { @@ -134,23 +137,32 @@ } }; + /// This helper class is used to make a script engine the active one as long as a script execution + /// is in progress. Uses RAII pattern to ensure that the old state is restored when the helper object goes out of scope. + struct ActiveScriptEngineSetter { + ActiveScriptEngineSetter(ScriptEngine* engine) : _previousEngine(ScriptEngine::_activeEngine) { + ScriptEngine::_activeEngine = engine; + } + ~ActiveScriptEngineSetter() { + ScriptEngine::_activeEngine = _previousEngine; + } + private: + QPointer _previousEngine; + }; + /// The dataset that provides the context for the script execution. QPointer _dataset; + /// The task manager that provides the context for the script execution. + TaskManager* _taskManager; + /// The namespace (scope) the script will be executed in by this script engine. py::dict _mainNamespace; - /// The progress display that has been registered with the engine, which - /// is responsible for showing the progress of long-running operations - /// performed by a script. - AbstractProgressDisplay* _progressDisplay = nullptr; - /// The script engine that is currently active (i.e. which is executing a script). static ScriptEngine* _activeEngine; Q_OBJECT }; -}; // End of namespace - -#endif +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/extensions/PythonScriptModifier.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/extensions/PythonScriptModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/extensions/PythonScriptModifier.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/extensions/PythonScriptModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -28,9 +28,9 @@ namespace PyScript { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(PyScript, PythonScriptModifier, Modifier); -DEFINE_PROPERTY_FIELD(PythonScriptModifier, _script, "Script"); -SET_PROPERTY_FIELD_LABEL(PythonScriptModifier, _script, "Script"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(PythonScriptModifier, Modifier); +DEFINE_PROPERTY_FIELD(PythonScriptModifier, script, "Script"); +SET_PROPERTY_FIELD_LABEL(PythonScriptModifier, script, "Script"); /****************************************************************************** * Constructor. @@ -39,7 +39,15 @@ _scriptExecutionQueued(false), _computingInterval(TimeInterval::empty()) { - INIT_PROPERTY_FIELD(PythonScriptModifier::_script); + INIT_PROPERTY_FIELD(script); +} + +/****************************************************************************** +* Loads the default values of this object's parameter fields. +******************************************************************************/ +void PythonScriptModifier::loadUserDefaults() +{ + Modifier::loadUserDefaults(); // Load example script. setScript("from ovito.data import *\n\n" @@ -65,7 +73,7 @@ Modifier::propertyChanged(field); // Recompute results when script has been changed. - if(field == PROPERTY_FIELD(PythonScriptModifier::_script)) { + if(field == PROPERTY_FIELD(script)) { _modifyScriptFunction = py::object(); invalidateCachedResults(false); } @@ -150,7 +158,7 @@ _scriptExecutionQueued = false; do { - if(!_generatorObject) { + if(!_generatorObject || _generatorObject.is_none()) { // Check if an evaluation request is still pending. _computingInterval = _inputCache.stateValidity(); @@ -173,7 +181,7 @@ // Initialize local script engine if there is no active engine to re-use. if(!_scriptEngine) { - _scriptEngine.reset(new ScriptEngine(dataset(), nullptr, false)); + _scriptEngine.reset(new ScriptEngine(dataset(), dataset()->container()->taskManager(), true)); connect(_scriptEngine.get(), &ScriptEngine::scriptOutput, this, &PythonScriptModifier::onScriptOutput); connect(_scriptEngine.get(), &ScriptEngine::scriptError, this, &PythonScriptModifier::onScriptOutput); _mainNamespacePrototype = _scriptEngine->mainNamespace(); @@ -192,10 +200,7 @@ int animationFrame = dataset()->animationSettings()->timeToFrame(_computingInterval.start()); // Construct progress callback object. - _runningTask = std::make_shared(); - // Register background task so user/system can cancel it. - dataset()->container()->taskManager().registerTask(_runningTask); - _runningTask->reportStarted(); + _runningTask.reset(new SynchronousTask(dataset()->container()->taskManager())); _runningTask->setProgressText(tr("Running modifier script")); // Make sure the actions of the modify() function are not recorded on the undo stack. @@ -210,15 +215,12 @@ OORef inputDataCollection = new CompoundObject(dataset()); inputDataCollection->setDataObjects(_outputCache); - ScriptEngine* engine = ScriptEngine::activeEngine(); - if(!engine) engine = _scriptEngine.get(); - - engine->execute([this,animationFrame,&inputDataCollection,engine]() { + _scriptEngine->execute([this,animationFrame,&inputDataCollection]() { // Prepare arguments to be passed to the script function. py::tuple arguments = py::make_tuple(animationFrame, inputDataCollection.get(), _dataCollection.get()); // Execute modify() script function. - _generatorObject = engine->callObject(_modifyScriptFunction, arguments); + _generatorObject = _scriptEngine->callObject(_modifyScriptFunction, arguments); }); } catch(const Exception& ex) { @@ -245,35 +247,28 @@ // Perform one computation step by calling the generator object. bool exhausted = false; try { - // Make sure the actions of the modify() function are not recorded on the undo stack. - UndoSuspender noUndo(dataset()); - - // Get script engine to execute the script. - ScriptEngine* engine = ScriptEngine::activeEngine(); - if(!engine) engine = _scriptEngine.get(); - - if(_runningTask->isCanceled()) { - _outputCache.setStateValidity(TimeInterval::empty()); - throwException(tr("Modifier script execution has been canceled by the user.")); - } - // Measure how long the script is running. QTime time; time.start(); do { - engine->execute([this, &exhausted]() { - py::handle item = PyIter_Next(_generatorObject.ptr()); + _scriptEngine->execute([this, &exhausted]() { + py::handle item; + { + // Make sure the actions of the modify() function are not recorded on the undo stack. + UndoSuspender noUndo(dataset()); + item = PyIter_Next(_generatorObject.ptr()); + } if(item) { py::object itemObj = py::reinterpret_steal(item); if(PyFloat_Check(itemObj.ptr())) { double progressValue = itemObj.cast(); if(progressValue >= 0.0 && progressValue <= 1.0) { - _runningTask->setProgressRange(100); + _runningTask->setProgressMaximum(100); _runningTask->setProgressValue((int)(progressValue * 100.0)); } else { - _runningTask->setProgressRange(0); + _runningTask->setProgressMaximum(0); _runningTask->setProgressValue(0); } } @@ -296,6 +291,11 @@ } while(!exhausted && time.elapsed() < 30); + if(!_runningTask || _runningTask->isCanceled()) { + _outputCache.setStateValidity(TimeInterval::empty()); + throwException(tr("Modifier script execution has been canceled by the user.")); + } + if(!exhausted) { // Keep calling this method in GUI mode. Otherwise stay in the outer while loop. if(ScriptEngine::activeEngine() == nullptr) @@ -343,10 +343,7 @@ setStatus(_outputCache.status()); // Signal completion of background task. - if(_runningTask) { - _runningTask->reportFinished(); - _runningTask.reset(); - } + _runningTask.reset(); // Notify pipeline system that the evaluation request was satisfied or not satisfied. notifyDependents(ReferenceEvent::PendingStateChanged); @@ -407,7 +404,6 @@ _dataCollection.reset(); if(_runningTask) { _runningTask->cancel(); - _runningTask->reportFinished(); _runningTask.reset(); } // Discard active generator object. diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/extensions/PythonScriptModifier.h ovito-2.9.0+dfsg1/src/plugins/pyscript/extensions/PythonScriptModifier.h --- ovito-2.8.1+dfsg2/src/plugins/pyscript/extensions/PythonScriptModifier.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/extensions/PythonScriptModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,11 +19,11 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PYTHON_SCRIPT_MODIFIER_H -#define __OVITO_PYTHON_SCRIPT_MODIFIER_H +#pragma once + #include -#include +#include #include #include #include @@ -39,21 +39,6 @@ { public: - // A helper class that provides the progress callback interface for Python scripts. - class ProgressHelper : public FutureInterface - { - public: - - virtual void cancel() override { - FutureInterface::cancel(); - // Since this task runs in the main application thread, canceling it - // means immediate termination. - reportFinished(); - } - }; - -public: - /// \brief Constructor. Q_INVOKABLE PythonScriptModifier(DataSet* dataset); @@ -66,12 +51,6 @@ /// Sets the status returned by the modifier and generates a ReferenceEvent::ObjectStatusChanged event. void setStatus(const PipelineStatus& status); - /// Returns the Python script. - const QString& script() const { return _script; } - - /// Sets the Python script. - void setScript(const QString& script) { _script = script; } - /// Returns the Python script function executed by the modifier. py::object scriptFunction() { if(_modifyScriptFunction) @@ -98,6 +77,9 @@ /// Returns whether the modifier can be applied to the given input data. virtual bool isApplicableTo(const PipelineFlowState& input) override { return true; } + /// Loads the default values of this object's parameter fields. + virtual void loadUserDefaults() override; + protected: /// This method is called by the system when the upstream modification pipeline has changed. @@ -127,7 +109,7 @@ private: /// The Python script. - PropertyField _script; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, script, setScript); /// The Python engine. std::unique_ptr _scriptEngine; @@ -154,7 +136,7 @@ bool _scriptExecutionQueued; /// The running script task. - std::shared_ptr _runningTask; + std::unique_ptr _runningTask; /// The generator object returned by the script function. py::object _generatorObject; @@ -170,10 +152,8 @@ Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_script); }; } // End of namespace -#endif // __OVITO_PYTHON_SCRIPT_MODIFIER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/extensions/PythonViewportOverlay.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/extensions/PythonViewportOverlay.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/extensions/PythonViewportOverlay.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/extensions/PythonViewportOverlay.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -23,24 +23,29 @@ #include #include #include +#include #include "PythonViewportOverlay.h" namespace PyScript { -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(PyScript, PythonViewportOverlay, ViewportOverlay); -DEFINE_PROPERTY_FIELD(PythonViewportOverlay, _script, "Script"); -SET_PROPERTY_FIELD_LABEL(PythonViewportOverlay, _script, "Script"); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(PythonViewportOverlay, ViewportOverlay); +DEFINE_PROPERTY_FIELD(PythonViewportOverlay, script, "Script"); +SET_PROPERTY_FIELD_LABEL(PythonViewportOverlay, script, "Script"); /****************************************************************************** * Constructor. ******************************************************************************/ -PythonViewportOverlay::PythonViewportOverlay(DataSet* dataset) : ViewportOverlay(dataset), - _scriptEngine(dataset, nullptr, false) +PythonViewportOverlay::PythonViewportOverlay(DataSet* dataset) : ViewportOverlay(dataset) { - INIT_PROPERTY_FIELD(PythonViewportOverlay::_script); + INIT_PROPERTY_FIELD(script); +} - connect(&_scriptEngine, &ScriptEngine::scriptOutput, this, &PythonViewportOverlay::onScriptOutput); - connect(&_scriptEngine, &ScriptEngine::scriptError, this, &PythonViewportOverlay::onScriptOutput); +/****************************************************************************** +* Loads the default values of this object's parameter fields. +******************************************************************************/ +void PythonViewportOverlay::loadUserDefaults() +{ + ViewportOverlay::loadUserDefaults(); // Load example script. setScript("import ovito\n" @@ -61,7 +66,7 @@ "\n" "\t# Print to the log window:\n" "\tprint(text1)\n" - "\tprint(text2)\n"); + "\tprint(text2)\n"); } /****************************************************************************** @@ -70,7 +75,7 @@ void PythonViewportOverlay::propertyChanged(const PropertyFieldDescriptor& field) { ViewportOverlay::propertyChanged(field); - if(field == PROPERTY_FIELD(PythonViewportOverlay::_script)) { + if(field == PROPERTY_FIELD(script)) { compileScript(); } } @@ -80,15 +85,26 @@ ******************************************************************************/ void PythonViewportOverlay::compileScript() { + // Cannot execute scripts during file loading. + if(isBeingLoaded()) return; + _scriptOutput.clear(); _overlayScriptFunction = py::function(); try { - _scriptEngine.executeCommands(script()); + + // Initialize a local script engine. + if(!_scriptEngine) { + _scriptEngine.reset(new ScriptEngine(dataset(), dataset()->container()->taskManager(), true)); + connect(_scriptEngine.get(), &ScriptEngine::scriptOutput, this, &PythonViewportOverlay::onScriptOutput); + connect(_scriptEngine.get(), &ScriptEngine::scriptError, this, &PythonViewportOverlay::onScriptOutput); + } + + _scriptEngine->executeCommands(script()); // Extract the render() function defined by the script. - _scriptEngine.execute([this]() { + _scriptEngine->execute([this]() { try { - _overlayScriptFunction = py::function(_scriptEngine.mainNamespace()["render"]); + _overlayScriptFunction = py::function(_scriptEngine->mainNamespace()["render"]); if(!py::isinstance(_overlayScriptFunction)) { _overlayScriptFunction = py::function(); throwException(tr("Invalid Python script. It does not define a callable function render().")); @@ -119,19 +135,25 @@ ******************************************************************************/ void PythonViewportOverlay::render(Viewport* viewport, QPainter& painter, const ViewProjectionParameters& projParams, RenderSettings* renderSettings) { + // When the overlay was loaded from a scene file, the script is not compiled yet. + // Let's do it now. + if(!_scriptEngine) + compileScript(); + if(!compilationSucessful()) return; + // This object instance may be deleted while this method is being executed. + // This is to detect this situation. + QPointer thisPointer(this); + _scriptOutput.clear(); try { // Enable antialiasing for the QPainter by default. painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::TextAntialiasing); - ScriptEngine* engine = ScriptEngine::activeEngine(); - if(!engine) engine = &_scriptEngine; - - engine->execute([this,engine,viewport,&painter,&projParams,renderSettings]() { + _scriptEngine->execute([this,viewport,&painter,&projParams,renderSettings]() { // Pass viewport, QPainter, and other information to the Python script function. // The QPainter pointer has to be converted to the representation used by PyQt. @@ -154,13 +176,15 @@ py::tuple arguments = py::make_tuple(sip_painter); // Execute render() script function. - engine->callObject(_overlayScriptFunction, arguments, kwargs); + _scriptEngine->callObject(_overlayScriptFunction, arguments, kwargs); }); } catch(const Exception& ex) { _scriptOutput += ex.messages().join('\n'); } - notifyDependents(ReferenceEvent::ObjectStatusChanged); + + if(thisPointer) + thisPointer->notifyDependents(ReferenceEvent::ObjectStatusChanged); } } // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/extensions/PythonViewportOverlay.h ovito-2.9.0+dfsg1/src/plugins/pyscript/extensions/PythonViewportOverlay.h --- ovito-2.8.1+dfsg2/src/plugins/pyscript/extensions/PythonViewportOverlay.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/extensions/PythonViewportOverlay.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PYTHON_VIEWPORT_OVERLAY_H -#define __OVITO_PYTHON_VIEWPORT_OVERLAY_H +#pragma once + #include #include @@ -43,12 +43,6 @@ /// \brief This method asks the overlay to paint its contents over the given viewport. virtual void render(Viewport* viewport, QPainter& painter, const ViewProjectionParameters& projParams, RenderSettings* renderSettings) override; - /// Returns the Python script that renders the overlay. - const QString& script() const { return _script; } - - /// Sets the Python script that renders the overlay. - void setScript(const QString& script) { _script = script; } - /// Returns the output generated by the script. const QString& scriptOutput() const { return _scriptOutput; } @@ -71,17 +65,14 @@ return (bool)_overlayScriptFunction; } + /// Loads the default values of this object's parameter fields. + virtual void loadUserDefaults() override; + protected: /// Is called when the value of a property of this object has changed. virtual void propertyChanged(const PropertyFieldDescriptor& field) override; - /// This method is called once for this object after they have been completely loaded from a stream. - virtual void loadFromStreamComplete() override { - ViewportOverlay::loadFromStreamComplete(); - compileScript(); - } - private Q_SLOTS: /// Is called when the script generates some output. @@ -93,10 +84,10 @@ void compileScript(); /// The Python script. - PropertyField _script; + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, script, setScript); /// The Python engine. - ScriptEngine _scriptEngine; + std::unique_ptr _scriptEngine; /// The output generated by the script. QString _scriptOutput; @@ -108,10 +99,8 @@ Q_OBJECT OVITO_OBJECT - - DECLARE_PROPERTY_FIELD(_script); }; } // End of namespace -#endif // __OVITO_PYTHON_VIEWPORT_OVERLAY_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/CMakeLists.txt ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/CMakeLists.txt 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -37,7 +37,6 @@ PLUGIN_DEPENDENCIES PyScript PRIVATE_LIB_DEPENDENCIES ${QScintilla_LIBRARIES} GUI_PLUGIN - PYTHON_WRAPPERS "${CMAKE_CURRENT_SOURCE_DIR}/python/" ) # Add QScintilla include directory. @@ -50,7 +49,7 @@ IF(APPLE) # Nothing to do. ELSEIF(UNIX) - IF(OVITO_MONOLITHIC_BUILD) + IF(OVITO_REDISTRIBUTABLE_PACKAGE) # Install a copy of the QScintilla2 library. CONFIGURE_FILE("${QScintilla_LIBRARIES}" "${OVITO_LIBRARY_DIRECTORY}" COPYONLY) GET_FILENAME_COMPONENT(real_qscintilla_lib "${QScintilla_LIBRARIES}" REALPATH) diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/GUIBinding.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/GUIBinding.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/GUIBinding.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/GUIBinding.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -20,33 +20,36 @@ /////////////////////////////////////////////////////////////////////////////// #include -#include #include #include #include #include +#include namespace PyScript { using namespace Ovito; -PYBIND11_PLUGIN(PyScriptGUI) +PYBIND11_PLUGIN(PyScriptGui) { + // Register the classes of this plugin with the global PluginManager. + PluginManager::instance().registerLoadedPluginClasses(); + py::options options; options.disable_function_signatures(); - py::module m("PyScriptGUI"); + py::module m("PyScriptGui"); py::class_(m, "MainWindow") .def_property_readonly("frame_buffer_window", &MainWindow::frameBufferWindow, py::return_value_policy::reference) ; py::class_(m, "GuiDataSetContainer") - .def("fileNew", &GuiDataSetContainer::fileNew) - .def("fileLoad", &GuiDataSetContainer::fileLoad) - .def("fileSave", &GuiDataSetContainer::fileSave) - .def("fileSaveAs", &GuiDataSetContainer::fileSaveAs) - .def("askForSaveChanges", &GuiDataSetContainer::askForSaveChanges) + //.def("fileNew", &GuiDataSetContainer::fileNew) + //.def("fileLoad", &GuiDataSetContainer::fileLoad) + //.def("fileSave", &GuiDataSetContainer::fileSave) + //.def("fileSaveAs", &GuiDataSetContainer::fileSaveAs) + //.def("askForSaveChanges", &GuiDataSetContainer::askForSaveChanges) .def_property_readonly("window", &GuiDataSetContainer::mainWindow, py::return_value_policy::reference) ; @@ -56,22 +59,9 @@ .def("show_and_activate", &FrameBufferWindow::showAndActivateWindow) ; - ovito_class(m, - "The standard OpenGL-based renderer." - "\n\n" - "This is the default built-in rendering engine that is also used by OVITO to render the contents of the interactive viewports. " - "Since it accelerates the generation of images by using the computer's graphics hardware, it is very fast.", - "OpenGLRenderer") - .def_property("antialiasing_level", &StandardSceneRenderer::antialiasingLevel, &StandardSceneRenderer::setAntialiasingLevel, - "A positive integer controlling the level of supersampling. If 1, no supersampling is performed. For larger values, " - "the image in rendered at a higher resolution and then scaled back to the output size to reduce aliasing artifacts." - "\n\n" - ":Default: 3") - ; - return m.ptr(); } -OVITO_REGISTER_PLUGIN_PYTHON_INTERFACE(PyScriptGUI); +OVITO_REGISTER_PLUGIN_PYTHON_INTERFACE(PyScriptGui); }; diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/ObjectScriptEditor.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/ObjectScriptEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/ObjectScriptEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/ObjectScriptEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -38,11 +38,7 @@ * Constructs the editor frame. ******************************************************************************/ ObjectScriptEditor::ObjectScriptEditor(QWidget* parentWidget, RefTarget* scriptableObject) : -#if !defined(Q_OS_MAC) || QT_VERSION >= QT_VERSION_CHECK(5, 3, 1) QMainWindow(parentWidget, (Qt::WindowFlags)(Qt::Tool | Qt::CustomizeWindowHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint)) -#else - QMainWindow(parentWidget, (Qt::WindowFlags)(Qt::Window | Qt::CustomizeWindowHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint)) -#endif { // Create the central editor component. QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont); @@ -91,6 +87,9 @@ // Disable context menu in toolbar. setContextMenuPolicy(Qt::NoContextMenu); + // Delete window when it is being closed by the user. + setAttribute(Qt::WA_DeleteOnClose); + // Make the input widget active. _codeEditor->setFocus(); diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/ObjectScriptEditor.h ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/ObjectScriptEditor.h --- ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/ObjectScriptEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/ObjectScriptEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_OBJECT_SCRIPT_EDITOR_H -#define __OVITO_OBJECT_SCRIPT_EDITOR_H +#pragma once + #include #include @@ -113,4 +113,4 @@ }; -#endif // __OVITO_OBJECT_SCRIPT_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/python/ovito/vis/gui/__init__.py ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/python/ovito/vis/gui/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/python/ovito/vis/gui/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/python/ovito/vis/gui/__init__.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -# Load dependencies -import ovito -import ovito.vis - -# Load the native modules. -import PyScriptGUI - -# Inject selected classes into parent module. -ovito.vis.OpenGLRenderer = PyScriptGUI.OpenGLRenderer \ No newline at end of file diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/PythonScriptModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/PythonScriptModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/PythonScriptModifierEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/PythonScriptModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -29,7 +29,7 @@ namespace PyScript { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(PyScriptGui, PythonScriptModifierEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(PythonScriptModifierEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(PythonScriptModifier, PythonScriptModifierEditor); /****************************************************************************** @@ -50,7 +50,7 @@ sublayout->setContentsMargins(0,0,0,0); sublayout->setSpacing(10); - StringParameterUI* namePUI = new StringParameterUI(this, PROPERTY_FIELD(Modifier::_title)); + StringParameterUI* namePUI = new StringParameterUI(this, PROPERTY_FIELD(Modifier::title)); layout->addWidget(new QLabel(tr("User-defined modifier name:")), row++, 0); static_cast(namePUI->textBox())->setPlaceholderText(PythonScriptModifier::OOType.displayName()); sublayout->addWidget(namePUI->textBox(), 1); diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/PythonScriptModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/PythonScriptModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/PythonScriptModifierEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/PythonScriptModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PYTHON_SCRIPT_MODIFIER_EDITOR_H -#define __OVITO_PYTHON_SCRIPT_MODIFIER_EDITOR_H +#pragma once + #include #include @@ -68,4 +68,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_PYTHON_SCRIPT_MODIFIER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/PythonViewportOverlayEditor.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/PythonViewportOverlayEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/PythonViewportOverlayEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/PythonViewportOverlayEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -27,7 +27,7 @@ namespace PyScript { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(PyScriptGui, PythonViewportOverlayEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(PythonViewportOverlayEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(PythonViewportOverlay, PythonViewportOverlayEditor); /****************************************************************************** diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/PythonViewportOverlayEditor.h ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/PythonViewportOverlayEditor.h --- ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/PythonViewportOverlayEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/PythonViewportOverlayEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PYTHON_VIEWPORT_OVERLAY_EDITOR_H -#define __OVITO_PYTHON_VIEWPORT_OVERLAY_EDITOR_H +#pragma once + #include #include @@ -68,4 +68,4 @@ OVITO_END_INLINE_NAMESPACE } // End of namespace -#endif // __OVITO_PYTHON_VIEWPORT_OVERLAY_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/RunScriptAction.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/RunScriptAction.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/RunScriptAction.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/RunScriptAction.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include #include @@ -30,7 +30,7 @@ namespace PyScript { -IMPLEMENT_OVITO_OBJECT(PyScriptGui, RunScriptAction, GuiAutoStartObject); +IMPLEMENT_OVITO_OBJECT(RunScriptAction, GuiAutoStartObject); /****************************************************************************** * Is called when a new main window is created. @@ -52,23 +52,15 @@ // Keep undo records so that script actions can be undone. dataset->undoStack().beginCompoundOperation(tr("Script actions")); try { - ScriptEngine engine(dataset); - // Show a progress dialog while script is running. - QProgressDialog progressDialog(actionManager.mainWindow()); - progressDialog.setWindowModality(Qt::WindowModal); - progressDialog.setAutoClose(false); - progressDialog.setAutoReset(false); - progressDialog.setMinimumDuration(0); - progressDialog.setValue(0); - progressDialog.setLabelText(tr("Running script")); - ProgressDialogAdapter progressDisplay(&progressDialog); - engine.setProgressDisplay(&progressDisplay); + ProgressDialog progressDialog(actionManager.mainWindow(), tr("Script execution")); + + ScriptEngine engine(dataset, progressDialog.taskManager(), true); engine.executeFile(scriptFile); } catch(const Exception& ex) { - ex.showError(); + ex.reportError(); } dataset->undoStack().endCompoundOperation(); }); diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/RunScriptAction.h ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/RunScriptAction.h --- ovito-2.8.1+dfsg2/src/plugins/pyscript/gui/RunScriptAction.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/gui/RunScriptAction.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PYSCRIPT_AUTOSTARTER_OBJECT_H -#define __OVITO_PYSCRIPT_AUTOSTARTER_OBJECT_H +#pragma once + #include #include @@ -49,6 +49,4 @@ OVITO_OBJECT }; -}; // End of namespace - -#endif +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/launcher/Main.cpp ovito-2.9.0+dfsg1/src/plugins/pyscript/launcher/Main.cpp --- ovito-2.8.1+dfsg2/src/plugins/pyscript/launcher/Main.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/launcher/Main.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -66,7 +66,7 @@ execMode = true; break; } - else if(strcmp(*argv, "-nt") == 0) { + else if(strcmp(*argv, "-nt") == 0 || strcmp(*argv, "--nthreads") == 0) { if(argc >= 2) { newargv.push_back("--nthreads"); newargv.push_back(argv[1]); @@ -77,7 +77,7 @@ } else if(strcmp(*argv, "-h") == 0 || strcmp(*argv, "--help") == 0) { std::cout << "OVITO Script Interpreter" << std::endl << std::endl; - std::cout << "Usage: ovitos [-g|--gui] [-v|--version] [-nt ] [-o FILE] [-c command | -m module-name | script-file] [arguments]" << std::endl; + std::cout << "Usage: ovitos [-g|--gui] [-v|--version] [-nt|--nthreads ] [-o FILE] [-c command | -m module-name | script-file] [arguments]" << std::endl; return 0; } else if(strcmp(*argv, "-v") == 0 || strcmp(*argv, "--version") == 0) { diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/PyScript.h ovito-2.9.0+dfsg1/src/plugins/pyscript/PyScript.h --- ovito-2.8.1+dfsg2/src/plugins/pyscript/PyScript.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/PyScript.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_PYSCRIPT_H -#define __OVITO_PYSCRIPT_H +#pragma once + #include @@ -45,5 +45,3 @@ #else # define OVITO_PYSCRIPT_EXPORT Q_DECL_IMPORT #endif - -#endif diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/python/ovito/anim/__init__.py ovito-2.9.0+dfsg1/src/plugins/pyscript/python/ovito/anim/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/pyscript/python/ovito/anim/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/python/ovito/anim/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,5 +1,4 @@ # Load the native module. -from PyScriptAnimation import * +from ..plugins.PyScript.Animation import * -# Add __str__ method to TimeInterval class: -TimeInterval.__str__ = lambda self: str((self.start,self.end)) \ No newline at end of file +__all__ = ['AnimationSettings'] diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/python/ovito/data/__init__.py ovito-2.9.0+dfsg1/src/plugins/pyscript/python/ovito/data/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/pyscript/python/ovito/data/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/python/ovito/data/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -16,6 +16,7 @@ * :py:class:`ParticleTypeProperty` * :py:class:`SimulationCell` * :py:class:`SurfaceMesh` + * :py:class:`TrajectoryLineGenerator` **Auxiliary classes:** @@ -37,9 +38,11 @@ import collections # Load the native module. -from PyScriptScene import DataCollection -from PyScriptScene import DataObject -from PyScriptApp import CloneHelper +from ..plugins.PyScript.Scene import DataCollection +from ..plugins.PyScript.Scene import DataObject +from ..plugins.PyScript.App import CloneHelper + +__all__ = ['DataCollection', 'DataObject'] # Give the DataCollection class a dict-like interface. DataCollection.__len__ = lambda self: len(self.objects) @@ -71,12 +74,28 @@ raise AttributeError("DataCollection does not have an attribute named '%s'." % name) DataCollection.__getattr__ = _DataCollection__getattr__ +def _DataCollection_get(self, key, default=None): + try: return self[key] + except KeyError: return default +DataCollection.get = _DataCollection_get + +def _DataCollection_keys(self): + return collections.KeysView(self) +DataCollection.keys = _DataCollection_keys + +def _DataCollection_items(self): + return collections.ItemsView(self) +DataCollection.items = _DataCollection_items + +def _DataCollection_values(self): + return collections.ValuesView(self) +DataCollection.values = _DataCollection_values + def _DataCollection__str__(self): return "DataCollection(" + str(list(self.keys())) + ")" DataCollection.__str__ = _DataCollection__str__ -# Mix in base class collections.Mapping: -DataCollection.__bases__ = DataCollection.__bases__ + (collections.Mapping, ) +collections.Mapping.register(DataCollection) # Implement the 'attributes' property of the DataCollection class. def _DataCollection_attributes(self): @@ -163,21 +182,15 @@ return len(self._data_collection.attribute_names) def __getitem__(self, key): - if not isinstance(key, str): - raise TypeError("Attribute key is not a string.") v = self._data_collection.get_attribute(key) if v is not None: return v raise KeyError("DataCollection contains no attribute named '%s'." % key) def __setitem__(self, key, value): - if not isinstance(key, str): - raise TypeError("Attribute key is not a string.") self._data_collection.set_attribute(key, value) def __delitem__(self, key): - if not isinstance(key, str): - raise TypeError("Attribute key is not a string.") v = self._data_collection.get_attribute(key) if v is None: raise KeyError("DataCollection contains no attribute named '%s'." % key) @@ -245,32 +258,41 @@ which will allow you to use all modules installed in the system's Python interpreter. :return: A new `ASE Atoms object `_ that contains the - contains the converted particle data from this :py:class:`!DataCollection`. + converted particle data from this :py:class:`!DataCollection`. """ from ase.atoms import Atoms + from ase.data import chemical_symbols # Extract basic dat: pbc, cell, positions, particle types pbc = self.cell.pbc cell_matrix = np.array(self.cell.matrix) cell, origin = cell_matrix[:, :3].T, cell_matrix[:, 3] info = {'cell_origin': origin } - positions = np.array(self.position) - type_names = dict([(t.id, t.name) for t in - self.particle_type.type_list]) - symbols = [type_names[id] for id in np.array(self.particle_type)] - + positions = np.array(self.particle_properties.position) + if 'Particle Type' in self.particle_properties: + # ASE only accepts chemical symbols as atom type names. + # If our atom type names are not chemical symbols, pass the numerical atom type to ASE instead. + type_names = {} + for t in self.particle_properties.particle_type.type_list: + if t.name in chemical_symbols: + type_names[t.id] = t.name + else: + type_names[t.id] = t.id + symbols = [type_names[id] for id in np.array(self.particle_properties.particle_type)] + else: + symbols = None + # construct ase.Atoms object atoms = Atoms(symbols, - positions, + positions=positions, cell=cell, pbc=pbc, info=info) # Convert any other particle properties to additional arrays - for name, prop in self.items(): - if name in ['Simulation cell', - 'Position', + for name, prop in self.particle_properties.items(): + if name in ['Position', 'Particle Type']: continue if not isinstance(prop, ParticleProperty): diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/python/ovito/__init__.py ovito-2.9.0+dfsg1/src/plugins/pyscript/python/ovito/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/pyscript/python/ovito/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/python/ovito/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,7 @@ import os.path +import sys +import pkgutil +import importlib try: # Python 3.x import collections.abc as collections @@ -6,32 +9,40 @@ # Python 2.x import collections +# Allow OVITO plugins and C++ extension modules to be spread over several installation directories. +_package_source_path = __path__ # Make a copy of the original path, which will be used below to automatically import all submodules. +__path__ = pkgutil.extend_path(__path__, __name__) + # Load the native module with the core bindings -from PyScript import * -from PyScriptApp import * +import ovito.plugins.PyScript +from .plugins.PyScript import (version, version_string, gui_mode, headless_mode, dataset, task_manager) +from .plugins.PyScript.App import (DataSet) -# Load sub-modules (in the right order because there are dependencies between them) +# Load sub-modules (in the right order because there are dependencies among them) import ovito.anim import ovito.data import ovito.vis import ovito.io import ovito.modifiers -from PyScriptScene import ObjectNode -from PyScriptScene import SceneRoot -from PyScriptScene import PipelineObject -from PyScriptScene import PipelineStatus - -# Load all OVITO modules packages. This is required -# to make all Python bindings available. -import pkgutil -import importlib -for _, _name, _ in pkgutil.walk_packages(__path__, __name__ + '.'): - if _name == "ovito.linalg": continue # For backward compatibility with OVITO 2.7.1 +# Load the bindings for the GUI classes when running in gui mode. +if ovito.gui_mode: + import ovito.plugins.PyScriptGui + +from .plugins.PyScript.Scene import (ObjectNode, SceneRoot, PipelineObject, PipelineStatus) + +__all__ = ['version', 'version_string', 'gui_mode', 'headless_mode', 'dataset', 'task_manager', + 'DataSet', 'ObjectNode'] + +# Load the whole OVITO package. This is required to make all Python bindings available. +for _, _name, _ in pkgutil.walk_packages(_package_source_path, __name__ + '.'): + if _name.startswith("ovito.linalg"): continue # For backward compatibility with OVITO 2.7.1. The old 'ovito.linalg' module has been deprecated but may still be present in some existing OVITO installations. + if _name.startswith("ovito.plugins"): continue # Do not load C++ plugin modules at this point, only Python modules try: + #print("Loading submodule ", _name) importlib.import_module(_name) except: - print("Error while loading submodule %s:" % _name, sys.exc_info()[0]) + print("Error while loading OVITO submodule %s:" % _name, sys.exc_info()[0]) raise def _DataSet_scene_nodes(self): @@ -146,17 +157,15 @@ return ObjectNodeModifierList(self) ObjectNode.modifiers = property(_get_ObjectNode_modifiers) -def _ObjectNode_wait(self, signalError = True, msgText = None, time = None): +def _ObjectNode_wait(self, signalError = True, time = None): # Blocks script execution until the node's modification pipeline is ready. # - # :param str msgText: An optional text that will be shown to the user while waiting for the operation to finish. # :param signalError: If ``True``, the function raises an exception when the modification pipeline could not be successfully evaluated. # This may be the case if the input file could not be loaded, or if one of the modifiers reported an error. # :returns: ``True`` if the pipeline evaluation is complete, ``False`` if the operation has been canceled by the user. # - if not msgText: msgText = "Data pipeline is being evaluated. Waiting for operation for complete." if time is None: time = self.dataset.anim.time - if not self.wait_until_ready(time, msgText, ovito.get_progress_display()): + if not self.wait_until_ready(time): return False if signalError: state = self.eval_pipeline(time) @@ -180,7 +189,7 @@ have been computed and their output fields are up to date. This function raises a ``RuntimeError`` when the modification pipeline could not be successfully evaluated for some reason. - This may happen due to invalid modifier parameters for example. + This may happen due to invalid modifier parameters, for example. :returns: A reference to the node's internal :py:class:`~ovito.data.DataCollection` containing the output of the modification pipeline. It is also accessible via the :py:attr:`.output` attribute after calling :py:meth:`.compute`. @@ -192,16 +201,22 @@ if not self.wait(time = time): raise RuntimeError("Operation has been canceled by the user.") - + state = self.eval_pipeline(time) assert(state.status.type != PipelineStatus.Type.Error) assert(state.status.type != PipelineStatus.Type.Pending) - + self.__output = ovito.data.DataCollection() self.__output.set_data_objects(state) - + + # Wait for worker threads to finish. + # This is to avoid warning messages 'QThreadStorage: Thread exited after QThreadStorage destroyed' + # during Python program exit. + import PyQt5.QtCore + PyQt5.QtCore.QThreadPool.globalInstance().waitForDone(0) + return self.__output - + ObjectNode.compute = _ObjectNode_compute def _ObjectNode_output(self): diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/python/ovito/io/__init__.py ovito-2.9.0+dfsg1/src/plugins/pyscript/python/ovito/io/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/pyscript/python/ovito/io/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/python/ovito/io/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -6,15 +6,17 @@ * :py:func:`import_file` * :py:func:`export_file` -In addition, it contains the :py:class:`FileSource` class, which is a data source object -that reads its input data from an external file. +In addition, the module contains the :py:class:`FileSource` class, which is a data source for OVITO's +data pipeline system reading its input data from an external file. """ import ovito.data -import PyScriptScene +import ovito.plugins.PyScript.Scene # Load the native module. -from PyScriptFileIO import * +from ..plugins.PyScript.IO import * + +__all__ = ['import_file', 'export_file', 'FileSource'] def import_file(location, **params): """ This high-level function imports external data from a file. @@ -157,18 +159,18 @@ raise RuntimeError("Operation has been canceled by the user.") # Block execution until data has been loaded. - if not self.wait_until_ready(self.dataset.anim.time, "Script is waiting for I/O operation to finish.", ovito.get_progress_display()): + if not self.wait_until_ready(self.dataset.anim.time): raise RuntimeError("Operation has been canceled by the user.") # Raise Python error if loading failed. - if self.status.type == PyScriptScene.PipelineStatus.Type.Error: + if self.status.type == ovito.plugins.PyScript.Scene.PipelineStatus.Type.Error: raise RuntimeError(self.status.text) FileSource.load = _FileSource_load # Implement the 'sourceUrl' property of FileSource, which returns or sets the currently loaded file path. def _get_FileSource_source_path(self, _originalGetterMethod = FileSource.source_path): - """ The path or URL of the loaded file. """ + """ The path or URL of the imported file or file sequence. Unlike the path return by :py:attr:`.loaded_file`, the source path may contain a '*' wildcard character when a file sequence has been imported. """ return _originalGetterMethod.__get__(self) def _set_FileSource_source_path(self, url): """ Sets the URL of the file referenced by this FileSource. """ @@ -176,7 +178,8 @@ FileSource.source_path = property(_get_FileSource_source_path, _set_FileSource_source_path) def export_file(node, file, format, **params): - """ High-level function that exports the output of a modification pipeline to a file. + """ High-level function that exports the results of the data pipeline to a file. + See the :ref:`file_output_overview` section for an overview. :param node: The object node that provides the data to be exported. :type node: :py:class:`~ovito.scene.ObjectNode` @@ -190,68 +193,72 @@ * ``"vasp"`` -- POSCAR format * ``"xyz"`` -- XYZ format * ``"fhi-aims"`` -- FHI-aims format - * ``"ca"`` -- Text-based format for storing dislocation lines (Crystal Analysis Tool) + * ``"ca"`` -- `Text-based format for storing dislocation lines <../../particles.modifiers.dislocation_analysis.html#particles.modifiers.dislocation_analysis.fileformat>`_ * ``"povray"`` -- POV-Ray scene format - The function evaluates the modification pipeline of the given object node to obtain the data to be exported. + The function first evaluates the modification pipeline of the given :py:class:`~ovito.ObjectNode` to obtain the data to be exported. This means it is not necessary to call :py:meth:`ObjectNode.compute() ` before calling - :py:func:`!export_file` (but it doesn't hurt either). + :py:func:`!export_file`, but it doesn't hurt either. + + The ``format`` parameter determines the type of file written by the export function; the filename suffix is ignored. + However, for files that end in ``.gz``, automatic gzip compression is activated if the file format is text-based. - Depending on the selected export format, additional keyword arguments must be provided to the function: + Depending on the selected format, additional keyword arguments must be provided: **File columns** - When writing files in the *lammps_dump*, *xyz*, or *imd* formats, you must specify the particle properties to be exported + When writing files in one of the formats *lammps_dump*, *xyz*, or *imd*, you must specify the set of particle properties to be exported using the ``columns`` keyword parameter:: - export_file(node, "output.xyz", "xyz", columns = + export_file(node, "output.xyz", "xyz", columns= ["Particle Identifier", "Particle Type", "Position.X", "Position.Y", "Position.Z"] ) - See the list of :ref:`particle properties ` for valid names. For vector properties, the component must be appended to - the property base name as demonstrated for the ``Position`` property in the example above. - - **Exporting multiple simulation frames** - - By default, only the current animation frame (:py:attr:`~ovito.anim.AnimationSettings.current_frame`) is exported. - To export a specific frame, pass the ``frame`` keyword parameter to the function. - You can export all animation frames by passing ``multiple_frames=True`` to :py:func:`!export_file`. Further - control is possible using the keyword arguments ``start_frame``, ``end_frame``, and ``every_nth_frame``. - - The *lammps_dump* and *xyz* file formats can store multiple frames per file. For all other file formats, or - if you explicitly want to generate one file per frame, you have to pass wildcard filename to :py:func:`!export_file`. - This filename must contain exactly one ``*`` character as in the following example. It will be replaced by OVITO with the + See the list of standard :ref:`particle properties ` for valid names. Additionaly, user-defined properties + can be listed if they exist in the output data. For vector properties, the component name must be appended to the base name as + demonstrated for the ``Position`` property in the example above. + + **Exporting several simulation frames** + + By default, only the current animation frame (given by the :py:attr:`~ovito.anim.AnimationSettings.current_frame` global variable) is exported. + To export a different frame, pass the ``frame`` keyword parameter to the :py:func:`!export_file` function. + Alternatively, you can export all frames of the current animation sequence at once by passing ``multiple_frames=True``. Refined + control of the exported frames is possible using the keyword arguments ``start_frame``, ``end_frame``, and ``every_nth_frame``. + + The *lammps_dump* and *xyz* file formats can store multiple frames in a single output file. For all other formats, or + if you intentionally want to generate one file per frame, you must pass a wildcard filename to :py:func:`!export_file`. + This filename must contain exactly one ``*`` character as in the following example, which will be replaced with the animation frame number:: - export_file(node, "output.*.dump", "lammps_dump", multiple_frames = True) + export_file(node, "output.*.dump", "lammps_dump", multiple_frames=True) - The above line is equivalent to the following Python loop:: + The above call is equivalent to the following Python loop:: for i in range(node.source.num_frames): - export_file(node, "output.%i.dump" % i, "lammps_dump", frame = i) + export_file(node, "output.%i.dump" % i, "lammps_dump", frame=i) **LAMMPS atom style** When writing files in the *lammps_data* format, the LAMMPS atom style "atomic" is used by default. If you want to create - a data file with a different atom style, it must be explicitly selected using the ``atom_style`` keyword parameter:: + a data file with a different atom style, the style can be selected using the ``atom_style`` keyword parameter:: - export_file(node, "output.data", "lammps_data", atom_tyle = "bond") + export_file(node, "output.data", "lammps_data", atom_tyle="bond") - The following LAMMPS atom styles are currently supported by OVITO: - ``angle``, ``atomic``, ``body``, ``bond``, ``charge``, ``dipole``, ``full``, ``molecular``. + The following `LAMMPS atom styles `_ are currently supported by OVITO: + ``angle``, ``atomic``, ``bond``, ``charge``, ``dipole``, ``full``, ``molecular``, ``sphere``. **Global attributes** The *txt* file format allows you to export global quantities computed by OVITO's data pipeline to a text file. - For example, to write out the number of FCC atoms identified by the :py:class:`~ovito.modifiers.CommonNeighborAnalysisModifier` - as a function of simulation time one would do the following:: + For example, to write out the number of FCC atoms identified by a :py:class:`~ovito.modifiers.CommonNeighborAnalysisModifier` + as a function of simulation time, one would do the following:: export_file(node, "data.txt", "txt", - columns = ["Timestep", "CommonNeighborAnalysis.counts.FCC"], - multiple_frames = True) + columns=["Timestep", "CommonNeighborAnalysis.counts.FCC"], + multiple_frames=True) - See the documentation of an analysis modifier to find out which global quantities it - outputs. From a script you can determine which :py:attr:`~ovito.data.DataCollection.attributes` are available for export as follows:: + See the documentation of each analysis modifier to find out which global quantities it + computes. At runtime, you can determine which :py:attr:`~ovito.data.DataCollection.attributes` are available for export as follows:: print(node.compute().attributes) @@ -295,7 +302,7 @@ raise ValueError("Invalid node parameter.") # Export data. - if not exporter.export_nodes(ovito.get_progress_display()): + if not exporter.export_nodes(ovito.task_manager): raise RuntimeError("Operation has been canceled by the user.") # This is the table of export formats used by the export_file() function diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/python/ovito/modifiers/__init__.py ovito-2.9.0+dfsg1/src/plugins/pyscript/python/ovito/modifiers/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/pyscript/python/ovito/modifiers/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/python/ovito/modifiers/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -32,7 +32,9 @@ :py:class:`ComputePropertyModifier` :guilabel:`Compute property` :py:class:`ConstructSurfaceModifier` :guilabel:`Construct surface mesh` :py:class:`CoordinationNumberModifier` :guilabel:`Coordination analysis` +:py:class:`CoordinationPolyhedraModifier` :guilabel:`Coordination polyhedra` :py:class:`CreateBondsModifier` :guilabel:`Create bonds` +:py:class:`CreateIsosurfaceModifier` :guilabel:`Create isosurface` :py:class:`DeleteSelectedParticlesModifier` :guilabel:`Delete selected particles` :py:class:`DislocationAnalysisModifier` :guilabel:`Dislocation analysis (DXA)` :py:class:`ElasticStrainModifier` :guilabel:`Elastic strain calculation` @@ -51,6 +53,7 @@ :py:class:`ShowPeriodicImagesModifier` :guilabel:`Show periodic images` :py:class:`SliceModifier` :guilabel:`Slice` :py:class:`VoronoiAnalysisModifier` :guilabel:`Voronoi analysis` +:py:class:`VoroTopModifier` :guilabel:`VoroTop analysis` :py:class:`WignerSeitzAnalysisModifier` :guilabel:`Wigner-Seitz defect analysis` :py:class:`WrapPeriodicImagesModifier` :guilabel:`Wrap at periodic boundaries` ============================================== ========================================= @@ -60,5 +63,7 @@ """ # Load the native module. -from PyScriptScene import Modifier -from PyScriptScene import PythonScriptModifier +from ..plugins.PyScript.Scene import Modifier +from ..plugins.PyScript.Scene import PythonScriptModifier + +__all__ = ['Modifier', 'PythonScriptModifier'] diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/python/ovito/plugins/__init__.py ovito-2.9.0+dfsg1/src/plugins/pyscript/python/ovito/plugins/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/pyscript/python/ovito/plugins/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/python/ovito/plugins/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,38 @@ +import sys + +# This is the ovito.plugins Python package. It contains the native C++ plugin libraries of OVITO. + +# Our C++ extension modules are, however, located in a different directory of the OVITO installation. +# For the time being, we use hardcoded relative paths to find them. + +# Platform-dependent paths where this Python module is located: + + # Linux: lib/ovito/plugins/python/ovito/plugins/ + # Windows: plugins/python/ovito/plugins/ + # macOS: Ovito.app/Contents/Resources/python/ovito/plugins/ + +# Platform-dependent paths where the native C++ plugins are located: + + # Linux: lib/ovito/plugins/ + # Windows: plugins/ + # macOS: Ovito.app/Contents/PlugIns/ + +if sys.platform.startswith('darwin'): # macOS + __path__[0] += "/../../../../PlugIns" +elif sys.platform.startswith('win32'): # Windows + __path__[0] += "\\..\\..\\.." +else: + __path__[0] += "/../../.." + +# On Windows, extension modules for the Python interpreter have a .pyd file extension. +# Our OVITO plugins, however, have the standard .dll extension. We therefore need to implement +# a custom file entry finder and hook it into the import machinery of Python. +# It specifically handles the OVITO plugin path and allows to load extension modules with .dll +# extension instead of .pyd. +if sys.platform.startswith('win32'): + import importlib.machinery + def OVITOPluginFinderHook(path): + if path == __path__[0]: + return importlib.machinery.FileFinder(path, (importlib.machinery.ExtensionFileLoader, ['.dll'])) + raise ImportError() + sys.path_hooks.insert(0, OVITOPluginFinderHook) diff -Nru ovito-2.8.1+dfsg2/src/plugins/pyscript/python/ovito/vis/__init__.py ovito-2.9.0+dfsg1/src/plugins/pyscript/python/ovito/vis/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/pyscript/python/ovito/vis/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/pyscript/python/ovito/vis/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -21,6 +21,7 @@ * :py:class:`ParticleDisplay` * :py:class:`SimulationCellDisplay` * :py:class:`SurfaceMeshDisplay` + * :py:class:`TrajectoryLineDisplay` * :py:class:`VectorDisplay` **Viewport overlays:** @@ -33,12 +34,14 @@ import sip import PyQt5.QtGui +import ovito # Load the native modules. -from PyScriptRendering import * -from PyScriptViewport import * +from ..plugins.PyScript.Rendering import * +from ..plugins.PyScript.Viewport import * -import ovito +__all__ = ['RenderSettings', 'Viewport', 'ViewportConfiguration', 'OpenGLRenderer', 'Display', + 'CoordinateTripodOverlay', 'PythonViewportOverlay', 'TextLabelOverlay'] def _get_RenderSettings_custom_range(self): """ @@ -116,7 +119,7 @@ else: # Create a temporary off-screen frame buffer. fb = FrameBuffer(settings.size[0], settings.size[1]) - if not self.dataset.render_scene(settings, self, fb, ovito.get_progress_display()): + if not self.dataset.render_scene(settings, self, fb, ovito.task_manager): return None return fb.image Viewport.render = _Viewport_render diff -Nru ovito-2.8.1+dfsg2/src/plugins/tachyon/gui/TachyonRendererEditor.cpp ovito-2.9.0+dfsg1/src/plugins/tachyon/gui/TachyonRendererEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/tachyon/gui/TachyonRendererEditor.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/tachyon/gui/TachyonRendererEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -34,7 +34,7 @@ namespace Ovito { namespace Tachyon { OVITO_BEGIN_INLINE_NAMESPACE(Internal) -IMPLEMENT_OVITO_OBJECT(TachyonGui, TachyonRendererEditor, PropertiesEditor); +IMPLEMENT_OVITO_OBJECT(TachyonRendererEditor, PropertiesEditor); SET_OVITO_OBJECT_EDITOR(TachyonRenderer, TachyonRendererEditor); /** @@ -106,7 +106,7 @@ mainLayout->setContentsMargins(4,4,4,4); // Antialiasing - BooleanGroupBoxParameterUI* enableAntialiasingUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(TachyonRenderer::_antialiasingEnabled)); + BooleanGroupBoxParameterUI* enableAntialiasingUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(TachyonRenderer::antialiasingEnabled)); QGroupBox* aaGroupBox = enableAntialiasingUI->groupBox(); mainLayout->addWidget(aaGroupBox); @@ -115,11 +115,11 @@ layout->setSpacing(4); layout->setColumnStretch(1, 1); - IntegerParameterUI* aaSamplesUI = new IntegerParameterUI(this, PROPERTY_FIELD(TachyonRenderer::_antialiasingSamples)); + IntegerParameterUI* aaSamplesUI = new IntegerParameterUI(this, PROPERTY_FIELD(TachyonRenderer::antialiasingSamples)); layout->addWidget(aaSamplesUI->label(), 0, 0); layout->addLayout(aaSamplesUI->createFieldLayout(), 0, 1); - BooleanGroupBoxParameterUI* enableDirectLightUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(TachyonRenderer::_directLightSourceEnabled)); + BooleanGroupBoxParameterUI* enableDirectLightUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(TachyonRenderer::directLightSourceEnabled)); QGroupBox* lightsGroupBox = enableDirectLightUI->groupBox(); mainLayout->addWidget(lightsGroupBox); @@ -129,17 +129,17 @@ layout->setColumnStretch(1, 1); // Default light brightness. - FloatParameterUI* defaultLightIntensityUI = new FloatParameterUI(this, PROPERTY_FIELD(TachyonRenderer::_defaultLightSourceIntensity)); + FloatParameterUI* defaultLightIntensityUI = new FloatParameterUI(this, PROPERTY_FIELD(TachyonRenderer::defaultLightSourceIntensity)); defaultLightIntensityUI->label()->setText(tr("Brightness:")); layout->addWidget(defaultLightIntensityUI->label(), 0, 0); layout->addLayout(defaultLightIntensityUI->createFieldLayout(), 0, 1); // Shadows. - BooleanParameterUI* enableShadowsUI = new BooleanParameterUI(this, PROPERTY_FIELD(TachyonRenderer::_shadowsEnabled)); + BooleanParameterUI* enableShadowsUI = new BooleanParameterUI(this, PROPERTY_FIELD(TachyonRenderer::shadowsEnabled)); layout->addWidget(enableShadowsUI->checkBox(), 1, 0, 1, 2); // Ambient occlusion. - BooleanGroupBoxParameterUI* enableAmbientOcclusionUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(TachyonRenderer::_ambientOcclusionEnabled)); + BooleanGroupBoxParameterUI* enableAmbientOcclusionUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(TachyonRenderer::ambientOcclusionEnabled)); QGroupBox* aoGroupBox = enableAmbientOcclusionUI->groupBox(); mainLayout->addWidget(aoGroupBox); @@ -149,19 +149,19 @@ layout->setColumnStretch(1, 1); // Ambient occlusion brightness. - FloatParameterUI* aoBrightnessUI = new FloatParameterUI(this, PROPERTY_FIELD(TachyonRenderer::_ambientOcclusionBrightness)); + FloatParameterUI* aoBrightnessUI = new FloatParameterUI(this, PROPERTY_FIELD(TachyonRenderer::ambientOcclusionBrightness)); aoBrightnessUI->label()->setText(tr("Brightness:")); layout->addWidget(aoBrightnessUI->label(), 0, 0); layout->addLayout(aoBrightnessUI->createFieldLayout(), 0, 1); // Ambient occlusion samples. - IntegerParameterUI* aoSamplesUI = new IntegerParameterUI(this, PROPERTY_FIELD(TachyonRenderer::_ambientOcclusionSamples)); + IntegerParameterUI* aoSamplesUI = new IntegerParameterUI(this, PROPERTY_FIELD(TachyonRenderer::ambientOcclusionSamples)); aoSamplesUI->label()->setText(tr("Sample count:")); layout->addWidget(aoSamplesUI->label(), 1, 0); layout->addLayout(aoSamplesUI->createFieldLayout(), 1, 1); // Depth of field - BooleanGroupBoxParameterUI* enableDepthOfFieldUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(TachyonRenderer::_depthOfFieldEnabled)); + BooleanGroupBoxParameterUI* enableDepthOfFieldUI = new BooleanGroupBoxParameterUI(this, PROPERTY_FIELD(TachyonRenderer::depthOfFieldEnabled)); QGroupBox* dofGroupBox = enableDepthOfFieldUI->groupBox(); mainLayout->addWidget(dofGroupBox); @@ -171,7 +171,7 @@ layout->setColumnStretch(1, 1); // Focal length - FloatParameterUI* focalLengthUI = new FloatParameterUI(this, PROPERTY_FIELD(TachyonRenderer::_dofFocalLength)); + FloatParameterUI* focalLengthUI = new FloatParameterUI(this, PROPERTY_FIELD(TachyonRenderer::dofFocalLength)); layout->addWidget(focalLengthUI->label(), 0, 0); layout->addLayout(focalLengthUI->createFieldLayout(), 0, 1); @@ -181,7 +181,7 @@ layout->addWidget(modeAction->createPushButton(), 0, 2); // Aperture - FloatParameterUI* apertureUI = new FloatParameterUI(this, PROPERTY_FIELD(TachyonRenderer::_dofAperture)); + FloatParameterUI* apertureUI = new FloatParameterUI(this, PROPERTY_FIELD(TachyonRenderer::dofAperture)); layout->addWidget(apertureUI->label(), 1, 0); layout->addLayout(apertureUI->createFieldLayout(), 1, 1, 1, 2); diff -Nru ovito-2.8.1+dfsg2/src/plugins/tachyon/gui/TachyonRendererEditor.h ovito-2.9.0+dfsg1/src/plugins/tachyon/gui/TachyonRendererEditor.h --- ovito-2.8.1+dfsg2/src/plugins/tachyon/gui/TachyonRendererEditor.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/tachyon/gui/TachyonRendererEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TACHYON_RENDERER_EDITOR_H -#define __OVITO_TACHYON_RENDERER_EDITOR_H +#pragma once + #include #include @@ -53,4 +53,4 @@ } // End of namespace } // End of namespace -#endif // __OVITO_TACHYON_RENDERER_EDITOR_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/tachyon/renderer/TachyonRenderer.cpp ovito-2.9.0+dfsg1/src/plugins/tachyon/renderer/TachyonRenderer.cpp --- ovito-2.8.1+dfsg2/src/plugins/tachyon/renderer/TachyonRenderer.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/tachyon/renderer/TachyonRenderer.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include "TachyonRenderer.h" extern "C" { @@ -54,35 +54,35 @@ return rt_vector(p.x(), p.y(), -p.z()); } -IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(Tachyon, TachyonRenderer, NonInteractiveSceneRenderer); -DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, _antialiasingEnabled, "EnableAntialiasing", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, _directLightSourceEnabled, "EnableDirectLightSource", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, _shadowsEnabled, "EnableShadows", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, _antialiasingSamples, "AntialiasingSamples", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, _defaultLightSourceIntensity, "DefaultLightSourceIntensity", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, _ambientOcclusionEnabled, "EnableAmbientOcclusion", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, _ambientOcclusionSamples, "AmbientOcclusionSamples", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, _ambientOcclusionBrightness, "AmbientOcclusionBrightness", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, _depthOfFieldEnabled, "DepthOfFieldEnabled", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, _dofFocalLength, "DOFFocalLength", PROPERTY_FIELD_MEMORIZE); -DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, _dofAperture, "DOFAperture", PROPERTY_FIELD_MEMORIZE); -SET_PROPERTY_FIELD_LABEL(TachyonRenderer, _antialiasingEnabled, "Enable anti-aliasing"); -SET_PROPERTY_FIELD_LABEL(TachyonRenderer, _antialiasingSamples, "Anti-aliasing samples"); -SET_PROPERTY_FIELD_LABEL(TachyonRenderer, _directLightSourceEnabled, "Direct light"); -SET_PROPERTY_FIELD_LABEL(TachyonRenderer, _shadowsEnabled, "Shadows"); -SET_PROPERTY_FIELD_LABEL(TachyonRenderer, _defaultLightSourceIntensity, "Direct light intensity"); -SET_PROPERTY_FIELD_LABEL(TachyonRenderer, _ambientOcclusionEnabled, "Ambient occlusion"); -SET_PROPERTY_FIELD_LABEL(TachyonRenderer, _ambientOcclusionSamples, "Ambient occlusion samples"); -SET_PROPERTY_FIELD_LABEL(TachyonRenderer, _ambientOcclusionBrightness, "Ambient occlusion brightness"); -SET_PROPERTY_FIELD_LABEL(TachyonRenderer, _depthOfFieldEnabled, "Depth of field"); -SET_PROPERTY_FIELD_LABEL(TachyonRenderer, _dofFocalLength, "Focal length"); -SET_PROPERTY_FIELD_LABEL(TachyonRenderer, _dofAperture, "Aperture"); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(TachyonRenderer, _antialiasingSamples, IntegerParameterUnit, 1, 500); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(TachyonRenderer, _defaultLightSourceIntensity, FloatParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(TachyonRenderer, _ambientOcclusionBrightness, FloatParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(TachyonRenderer, _dofFocalLength, WorldParameterUnit, 0); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(TachyonRenderer, _dofAperture, FloatParameterUnit, 0, 1); -SET_PROPERTY_FIELD_UNITS_AND_RANGE(TachyonRenderer, _ambientOcclusionSamples, IntegerParameterUnit, 1, 100); +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(TachyonRenderer, NonInteractiveSceneRenderer); +DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, antialiasingEnabled, "EnableAntialiasing", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, directLightSourceEnabled, "EnableDirectLightSource", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, shadowsEnabled, "EnableShadows", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, antialiasingSamples, "AntialiasingSamples", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, defaultLightSourceIntensity, "DefaultLightSourceIntensity", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, ambientOcclusionEnabled, "EnableAmbientOcclusion", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, ambientOcclusionSamples, "AmbientOcclusionSamples", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, ambientOcclusionBrightness, "AmbientOcclusionBrightness", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, depthOfFieldEnabled, "DepthOfFieldEnabled", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, dofFocalLength, "DOFFocalLength", PROPERTY_FIELD_MEMORIZE); +DEFINE_FLAGS_PROPERTY_FIELD(TachyonRenderer, dofAperture, "DOFAperture", PROPERTY_FIELD_MEMORIZE); +SET_PROPERTY_FIELD_LABEL(TachyonRenderer, antialiasingEnabled, "Enable anti-aliasing"); +SET_PROPERTY_FIELD_LABEL(TachyonRenderer, antialiasingSamples, "Anti-aliasing samples"); +SET_PROPERTY_FIELD_LABEL(TachyonRenderer, directLightSourceEnabled, "Direct light"); +SET_PROPERTY_FIELD_LABEL(TachyonRenderer, shadowsEnabled, "Shadows"); +SET_PROPERTY_FIELD_LABEL(TachyonRenderer, defaultLightSourceIntensity, "Direct light intensity"); +SET_PROPERTY_FIELD_LABEL(TachyonRenderer, ambientOcclusionEnabled, "Ambient occlusion"); +SET_PROPERTY_FIELD_LABEL(TachyonRenderer, ambientOcclusionSamples, "Ambient occlusion samples"); +SET_PROPERTY_FIELD_LABEL(TachyonRenderer, ambientOcclusionBrightness, "Ambient occlusion brightness"); +SET_PROPERTY_FIELD_LABEL(TachyonRenderer, depthOfFieldEnabled, "Depth of field"); +SET_PROPERTY_FIELD_LABEL(TachyonRenderer, dofFocalLength, "Focal length"); +SET_PROPERTY_FIELD_LABEL(TachyonRenderer, dofAperture, "Aperture"); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(TachyonRenderer, antialiasingSamples, IntegerParameterUnit, 1, 500); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(TachyonRenderer, defaultLightSourceIntensity, FloatParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(TachyonRenderer, ambientOcclusionBrightness, FloatParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(TachyonRenderer, dofFocalLength, WorldParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(TachyonRenderer, dofAperture, FloatParameterUnit, 0, 1); +SET_PROPERTY_FIELD_UNITS_AND_RANGE(TachyonRenderer, ambientOcclusionSamples, IntegerParameterUnit, 1, 100); /****************************************************************************** * Default constructor. @@ -93,17 +93,17 @@ _defaultLightSourceIntensity(0.90f), _ambientOcclusionBrightness(0.80f), _depthOfFieldEnabled(false), _dofFocalLength(40), _dofAperture(1e-2f) { - INIT_PROPERTY_FIELD(TachyonRenderer::_antialiasingEnabled); - INIT_PROPERTY_FIELD(TachyonRenderer::_antialiasingSamples); - INIT_PROPERTY_FIELD(TachyonRenderer::_directLightSourceEnabled); - INIT_PROPERTY_FIELD(TachyonRenderer::_shadowsEnabled); - INIT_PROPERTY_FIELD(TachyonRenderer::_defaultLightSourceIntensity); - INIT_PROPERTY_FIELD(TachyonRenderer::_ambientOcclusionEnabled); - INIT_PROPERTY_FIELD(TachyonRenderer::_ambientOcclusionSamples); - INIT_PROPERTY_FIELD(TachyonRenderer::_ambientOcclusionBrightness); - INIT_PROPERTY_FIELD(TachyonRenderer::_depthOfFieldEnabled); - INIT_PROPERTY_FIELD(TachyonRenderer::_dofFocalLength); - INIT_PROPERTY_FIELD(TachyonRenderer::_dofAperture); + INIT_PROPERTY_FIELD(antialiasingEnabled); + INIT_PROPERTY_FIELD(antialiasingSamples); + INIT_PROPERTY_FIELD(directLightSourceEnabled); + INIT_PROPERTY_FIELD(shadowsEnabled); + INIT_PROPERTY_FIELD(defaultLightSourceIntensity); + INIT_PROPERTY_FIELD(ambientOcclusionEnabled); + INIT_PROPERTY_FIELD(ambientOcclusionSamples); + INIT_PROPERTY_FIELD(ambientOcclusionBrightness); + INIT_PROPERTY_FIELD(depthOfFieldEnabled); + INIT_PROPERTY_FIELD(dofFocalLength); + INIT_PROPERTY_FIELD(dofAperture); } /****************************************************************************** @@ -122,16 +122,16 @@ /****************************************************************************** * Renders a single animation frame into the given frame buffer. ******************************************************************************/ -bool TachyonRenderer::renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, AbstractProgressDisplay* progress) +bool TachyonRenderer::renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, TaskManager& taskManager) { - if(progress) progress->setStatusText(tr("Preparing scene")); + SynchronousTask renderTask(taskManager); + renderTask.setProgressText(tr("Handing scene data to Tachyon renderer")); // Create new scene and set up parameters. _rtscene = rt_newscene(); rt_resolution(_rtscene, renderSettings()->outputImageWidth(), renderSettings()->outputImageHeight()); if(antialiasingEnabled()) rt_aa_maxsamples(_rtscene, antialiasingSamples()); - //rt_normal_fixup_mode(_rtscene, 2); // Create Tachyon frame buffer. QImage img(renderSettings()->outputImageWidth(), renderSettings()->outputImageHeight(), QImage::Format_RGBA8888); @@ -183,7 +183,7 @@ p0 = projParams().inverseViewMatrix * p0; direction = (projParams().inverseViewMatrix * direction).normalized(); up = (projParams().inverseViewMatrix * up).normalized(); - p0 += direction * projParams().znear; + p0 += direction * (projParams().znear - FloatType(1e-9)); rt_camera_position(_rtscene, tvec(p0), tvec(direction), tvec(up)); rt_camera_zoom(_rtscene, 0.5 / projParams().fieldOfView); @@ -233,10 +233,8 @@ renderModifiers(true); // Render scene. - if(progress) { - progress->setMaximum(renderSettings()->outputImageWidth() * renderSettings()->outputImageHeight()); - progress->setStatusText(tr("Rendering scene")); - } + renderTask.setProgressMaximum(renderSettings()->outputImageWidth() * renderSettings()->outputImageHeight()); + renderTask.setProgressText(tr("Rendering image")); scenedef * scene = (scenedef *)_rtscene; @@ -244,7 +242,7 @@ /* since the last frame rendered, or when rendering the scene the */ /* first time, various setup, initialization and memory allocation */ /* routines need to be run in order to prepare for rendering. */ - if (scene->scenecheck) + if(scene->scenecheck) rendercheck(scene); camera_init(scene); /* Initialize all aspects of camera system */ @@ -253,11 +251,14 @@ if(frameBuffer->image().format() != QImage::Format_ARGB32) frameBuffer->image() = frameBuffer->image().convertToFormat(QImage::Format_ARGB32); - int tileSize = scene->numthreads * 8; - for(int ystart = 0; ystart < scene->vres; ystart += tileSize) { - for(int xstart = 0; xstart < scene->hres; xstart += tileSize) { - int xstop = std::min(scene->hres, xstart + tileSize); - int ystop = std::min(scene->vres, ystart + tileSize); + int tileHeight = 16; + int tileWidth = scene->numthreads * 4; + QTime renderTime; + renderTime.start(); + for(int ystart = 0; ystart < scene->vres; ystart += tileHeight) { + for(int xstart = 0; xstart < scene->hres; ) { + int xstop = std::min(scene->hres, xstart + tileWidth); + int ystop = std::min(scene->vres, ystart + tileHeight); for(int thr = 0; thr < scene->numthreads; thr++) { thr_parms* parms = &((thr_parms *) scene->threadparms)[thr]; parms->startx = 1 + xstart; @@ -290,14 +291,19 @@ } frameBuffer->update(QRect(xstart, frameBuffer->image().height() - ystop, xstop - xstart, ystop - ystart)); - if(progress) { - progress->setValue(progress->value() + (xstop - xstart) * (ystop - ystart)); - if(progress->wasCanceled()) - break; - } + renderTask.setProgressValue(renderTask.progressValue() + (xstop - xstart) * (ystop - ystart)); + if(renderTask.isCanceled()) + break; + + xstart += tileWidth; + + // Auto-adjust tile size to maintain constant update interval of about 50 ms. + // We furthermore limit the maximum tile width to 100px and the minimum width to 1px. + int elapsedTime = renderTime.restart(); + tileWidth = std::max(1, std::min(100, (tileWidth + tileWidth * 50 / std::max(1, elapsedTime)) / 2)); } - if(progress && progress->wasCanceled()) + if(renderTask.isCanceled()) break; } @@ -320,7 +326,7 @@ // Clean up. rt_deletescene(_rtscene); - return (!progress || progress->wasCanceled() == false); + return !renderTask.isCanceled(); } /****************************************************************************** @@ -571,7 +577,7 @@ Vector3 d2 = mesh.vertex(face->vertex(2)) - p0; *faceNormal = normalTM * (Vector_3)d2.cross(d1); if(*faceNormal != Vector_3::Zero()) { - faceNormal->normalize(); + //faceNormal->normalize(); allMask |= face->smoothingGroups(); } } diff -Nru ovito-2.8.1+dfsg2/src/plugins/tachyon/renderer/TachyonRenderer.h ovito-2.9.0+dfsg1/src/plugins/tachyon/renderer/TachyonRenderer.h --- ovito-2.8.1+dfsg2/src/plugins/tachyon/renderer/TachyonRenderer.h 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/tachyon/renderer/TachyonRenderer.h 2017-07-27 16:52:45.000000000 +0000 @@ -19,8 +19,8 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef __OVITO_TACHYON_RENDERER_H -#define __OVITO_TACHYON_RENDERER_H +#pragma once + #include #include @@ -51,7 +51,7 @@ /// Renders a single animation frame into the given frame buffer. /// Throws an exception on error. Returns false when the operation has been aborted by the user. - virtual bool renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, AbstractProgressDisplay* progress) override; + virtual bool renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask stereoTask, TaskManager& taskManager) override; /// Finishes the rendering pass. This is called after all animation frames have been rendered /// or when the rendering operation has been aborted. @@ -75,72 +75,6 @@ /// Renders the triangle mesh stored in the given buffer. virtual void renderMesh(const DefaultMeshPrimitive& meshBuffer) override; - /// Returns whether anti-aliasing is enabled. - bool antialiasingEnabled() const { return _antialiasingEnabled; } - - /// Enables/disables anti-aliasing. - void setAntialiasingEnabled(bool on) { _antialiasingEnabled = on; } - - /// Returns the quality level of anti-aliasing. - int antialiasingSamples() const { return _antialiasingSamples; } - - /// Sets the quality level of anti-aliasing. - void setAntialiasingSamples(int sampleCount) { _antialiasingSamples = sampleCount; } - - /// Returns whether the default direct light source is enabled. - bool directLightSourceEnabled() const { return _directLightSourceEnabled; } - - /// Enables/disables the default direct light source. - void setDirectLightSourceEnabled(bool on) { _directLightSourceEnabled = on; } - - /// Returns the brightness of the default direct light source. - FloatType defaultLightSourceIntensity() const { return _defaultLightSourceIntensity; } - - /// Sets the brightness of the default direct light source. - void setDefaultLightSourceIntensity(FloatType brightness) { _defaultLightSourceIntensity = brightness; } - - /// Returns whether the calculation of shadows is enabled. - bool shadowsEnabled() const { return _shadowsEnabled; } - - /// Enables/disables the calculation of shadows. - void setShadowsEnabled(bool on) { _shadowsEnabled = on; } - - /// Returns whether the calculation of ambient occlusion is enabled. - bool ambientOcclusionEnabled() const { return _ambientOcclusionEnabled; } - - /// Enables/disables the calculation of ambient occlusion. - void setAmbientOcclusionEnabled(bool on) { _ambientOcclusionEnabled = on; } - - /// Returns the brightness of the ambient occlusion sky light source. - FloatType ambientOcclusionBrightness() const { return _ambientOcclusionBrightness; } - - /// Sets the brightness of the ambient occlusion sky light source. - void setAmbientOcclusionBrightness(FloatType brightness) { _ambientOcclusionBrightness = brightness; } - - /// Returns the number of AO samples to compute. - int ambientOcclusionSamples() const { return _ambientOcclusionSamples; } - - /// Sets the number of AO samples to compute. - void setAmbientOcclusionSamples(int sampleCount) { _ambientOcclusionSamples = sampleCount; } - - /// Returns whether depth-of-field rendering is enabled. - bool depthOfFieldEnabled() const { return _depthOfFieldEnabled; } - - /// Enables/disables depth-of-field rendering. - void setDepthOfFieldEnabled(bool enabled) { _depthOfFieldEnabled = enabled; } - - /// Returns the camera's focal length, which is used for depth-of-field rendering. - FloatType dofFocalLength() const { return _dofFocalLength; } - - /// Sets the camera's focal length, which is used for depth-of-field rendering. - void setDofFocalLength(FloatType length) { _dofFocalLength = length; } - - /// Returns the camera's aperture, which is used for depth-of-field rendering. - FloatType dofAperture() const { return _dofAperture; } - - /// Sets the camera's aperture, which is used for depth-of-field rendering. - void setDofAperture(FloatType aperture) { _dofAperture = aperture; } - private: /// Creates a texture with the given color. @@ -149,37 +83,37 @@ private: /// Controls anti-aliasing. - PropertyField _antialiasingEnabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, antialiasingEnabled, setAntialiasingEnabled); /// Controls quality of anti-aliasing. - PropertyField _antialiasingSamples; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, antialiasingSamples, setAntialiasingSamples); /// Enables direct light source. - PropertyField _directLightSourceEnabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, directLightSourceEnabled, setDirectLightSourceEnabled); /// Enables shadows for the direct light source. - PropertyField _shadowsEnabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, shadowsEnabled, setShadowsEnabled); /// Controls the brightness of the default direct light source. - PropertyField _defaultLightSourceIntensity; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, defaultLightSourceIntensity, setDefaultLightSourceIntensity); /// Enables ambient occlusion lighting. - PropertyField _ambientOcclusionEnabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, ambientOcclusionEnabled, setAmbientOcclusionEnabled); /// Controls quality of ambient occlusion. - PropertyField _ambientOcclusionSamples; + DECLARE_MODIFIABLE_PROPERTY_FIELD(int, ambientOcclusionSamples, setAmbientOcclusionSamples); /// Controls the brightness of the sky light source used for ambient occlusion. - PropertyField _ambientOcclusionBrightness; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, ambientOcclusionBrightness, setAmbientOcclusionBrightness); /// Enables depth-of-field rendering. - PropertyField _depthOfFieldEnabled; + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, depthOfFieldEnabled, setDepthOfFieldEnabled); /// Controls the camera's focal length, which is used for depth-of-field rendering. - PropertyField _dofFocalLength; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, dofFocalLength, setDofFocalLength); /// Controls the camera's aperture, which is used for depth-of-field rendering. - PropertyField _dofAperture; + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, dofAperture, setDofAperture); /// The Tachyon internal scene handle. SceneHandle _rtscene; @@ -194,21 +128,9 @@ OVITO_OBJECT Q_CLASSINFO("DisplayName", "Tachyon renderer"); - - DECLARE_PROPERTY_FIELD(_antialiasingEnabled); - DECLARE_PROPERTY_FIELD(_antialiasingSamples); - DECLARE_PROPERTY_FIELD(_directLightSourceEnabled); - DECLARE_PROPERTY_FIELD(_shadowsEnabled); - DECLARE_PROPERTY_FIELD(_defaultLightSourceIntensity); - DECLARE_PROPERTY_FIELD(_ambientOcclusionEnabled); - DECLARE_PROPERTY_FIELD(_ambientOcclusionSamples); - DECLARE_PROPERTY_FIELD(_ambientOcclusionBrightness); - DECLARE_PROPERTY_FIELD(_depthOfFieldEnabled); - DECLARE_PROPERTY_FIELD(_dofFocalLength); - DECLARE_PROPERTY_FIELD(_dofAperture); }; } // End of namespace } // End of namespace -#endif // __OVITO_TACHYON_RENDERER_H + diff -Nru ovito-2.8.1+dfsg2/src/plugins/tachyon/resources/python/ovito/vis/tachyon/__init__.py ovito-2.9.0+dfsg1/src/plugins/tachyon/resources/python/ovito/vis/tachyon/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/tachyon/resources/python/ovito/vis/tachyon/__init__.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/tachyon/resources/python/ovito/vis/tachyon/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -2,7 +2,8 @@ import ovito.vis # Load the native code module -import Tachyon +import ovito.plugins.Tachyon # Inject TachyonRenderer class into parent module. -ovito.vis.TachyonRenderer = Tachyon.TachyonRenderer \ No newline at end of file +ovito.vis.TachyonRenderer = ovito.plugins.Tachyon.TachyonRenderer +ovito.vis.__all__ += ['TachyonRenderer'] diff -Nru ovito-2.8.1+dfsg2/src/plugins/tachyon/scripting/PythonInterface.cpp ovito-2.9.0+dfsg1/src/plugins/tachyon/scripting/PythonInterface.cpp --- ovito-2.8.1+dfsg2/src/plugins/tachyon/scripting/PythonInterface.cpp 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/tachyon/scripting/PythonInterface.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -22,6 +22,7 @@ #include #include #include +#include namespace Ovito { namespace Tachyon { OVITO_BEGIN_INLINE_NAMESPACE(Internal) @@ -30,6 +31,9 @@ PYBIND11_PLUGIN(Tachyon) { + // Register the classes of this plugin with the global PluginManager. + PluginManager::instance().registerLoadedPluginClasses(); + py::options options; options.disable_function_signatures(); diff -Nru ovito-2.8.1+dfsg2/src/plugins/vorotop/CMakeLists.txt ovito-2.9.0+dfsg1/src/plugins/vorotop/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/plugins/vorotop/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vorotop/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,45 @@ +############################################################################### +# +# Copyright (2017) Alexander Stukowski +# +# This file is part of OVITO (Open Visualization Tool). +# +# OVITO is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# OVITO is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################### + +SET(SourceFiles + VoroTopModifier.cpp + Filter.cpp +) + +IF(OVITO_BUILD_PLUGIN_PYSCRIPT) + LIST(APPEND SourceFiles PythonInterface.cpp) +ENDIF() + +OVITO_STANDARD_PLUGIN(VoroTop + SOURCES ${SourceFiles} + PLUGIN_DEPENDENCIES Particles + LIB_DEPENDENCIES VoroPlusPlus + OPTIONAL_PLUGIN_DEPENDENCIES PyScript + PYTHON_WRAPPERS "${CMAKE_CURRENT_SOURCE_DIR}/resources/python/" +) + +# Build corresponding GUI plugin. +IF(OVITO_BUILD_GUI) + ADD_SUBDIRECTORY(gui) +ENDIF() + +# Propagate list of plugins to parent scope. +SET(OVITO_PLUGIN_LIST ${OVITO_PLUGIN_LIST} PARENT_SCOPE) diff -Nru ovito-2.8.1+dfsg2/src/plugins/vorotop/Filter.cpp ovito-2.9.0+dfsg1/src/plugins/vorotop/Filter.cpp --- ovito-2.8.1+dfsg2/src/plugins/vorotop/Filter.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vorotop/Filter.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,118 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "Filter.h" + +namespace Ovito { namespace VoroTop { + +/****************************************************************************** +* Loads the filter definition from the given input stream. +******************************************************************************/ +bool Filter::load(CompressedTextReader& stream, bool readHeaderOnly, PromiseBase& promise) +{ + // Parse comment lines starting with '#': + _filterDescription.clear(); + const char* line; + while(!stream.eof()) { + line = stream.readLineTrimLeft(); + if(line[0] != '#') break; + _filterDescription += QString::fromUtf8(line + 1).trimmed() + QChar('\n'); + if(promise.isCanceled()) return false; + } + + // Create the default "Other" structure type. + _structureTypeLabels.clear(); + _structureTypeLabels.push_back("Other"); + _structureTypeDescriptions.clear(); + _structureTypeDescriptions.push_back(QString()); + + // Parse list of structure types (lines starting with '*'). + while(!stream.eof()) { + if(line[0] != '*') break; + int typeId; + int stringLength; + if(sscanf(line, "* %i%n", &typeId, &stringLength) != 1) + throw Exception(QString("Invalid structure type definition in line %1 of VoroTop filter definition file").arg(stream.lineNumber())); + if(typeId != _structureTypeLabels.size()) + throw Exception(QString("Invalid structure type definition in line %1 of VoroTop filter definition file: Type IDs must start at 1 and form a consecutive sequence.").arg(stream.lineNumber())); + QStringList columns = QString::fromUtf8(line + stringLength).trimmed().split(QChar('\t'), QString::SkipEmptyParts); + if(columns.empty()) + throw Exception(QString("Invalid structure type definition in line %1 of VoroTop filter definition file: Type label is missing.").arg(stream.lineNumber())); + _structureTypeLabels.push_back(columns[0]); + _structureTypeDescriptions.push_back(columns.size() >= 2 ? columns[1] : QString()); + + line = stream.readLineTrimLeft(); + if(promise.isCanceled()) return false; + } + if(_structureTypeLabels.size() <= 1) + throw Exception(QString("Invalid filter definition file")); + + if(readHeaderOnly) + return !promise.isCanceled(); + + promise.setProgressMaximum(stream.underlyingSize()); + + // Parse Weinberg vector list. + for(;;) { + + // Parse structure type the current Weinberg code will be mapped to. + int typeId; + int stringLength; + if(sscanf(line, "%i (%n", &typeId, &stringLength) != 1 || typeId <= 0 || typeId >= _structureTypeLabels.size()) + throw Exception(QString("Invalid Weinberg vector in line %1 of VoroTop filter definition file").arg(stream.lineNumber())); + line += stringLength; + + // Parse Weinberg code sequence. + WeinbergVector wvector; + for(;;) { + const char* s = line; + while(*s != '\0' && *s != ')' && *s != ',') + ++s; + int label; + if(*s == '\0' || !parseInt(line, s, label)) + throw Exception(QString("Invalid Weinberg vector in line %1 of VoroTop filter definition file").arg(stream.lineNumber())); + wvector.push_back(label); + if(label > maximumVertices) maximumVertices = label; + + if(*s == ')') break; + line = s + 1; + } + int edges = (wvector.size()-1)/2; + if(edges > maximumEdges) maximumEdges = edges; + + _entries.emplace(std::move(wvector), typeId); + if(stream.eof()) break; + + line = stream.readNonEmptyLine(); + + // Update progress indicator. + promise.setProgressValueIntermittent(stream.underlyingByteOffset()); + if(promise.isCanceled()) return false; + } + + return !promise.isCanceled(); +} + +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/vorotop/Filter.h ovito-2.9.0+dfsg1/src/plugins/vorotop/Filter.h --- ovito-2.8.1+dfsg2/src/plugins/vorotop/Filter.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vorotop/Filter.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,90 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include + +namespace Ovito { namespace VoroTop { + +/** + * A filter is a specification of topological types, recorded with Weinberg codes. + */ +class OVITO_VOROTOP_EXPORT Filter +{ +public: + + /// Data type holding a single Weinberg vector. + using WeinbergVector = std::vector; + + /// Maximum edges and vertices of type in Filter + int maximumEdges; + int maximumVertices; + +public: + + /// Loads the filter definition from the given input stream. + bool load(CompressedTextReader& stream, bool readHeaderOnly, PromiseBase& promise); + + /// Returns the comment text loaded from the filter definition file. + const QString& filterDescription() const { return _filterDescription; } + + /// Returns the number of Weinberg vectors of this filter. + size_t size() const { return _entries.size(); } + + /// Looks up the structure type associated with the given Weinberg vector. + /// Return 0 if Weinberg vector is not in filter. + int findType(const WeinbergVector& wvector) const { + auto iter = _entries.find(wvector); + if(iter != _entries.end()) + return iter->second; + else + return 0; + } + + /// Returns the number of structure types defined in this filter (including the "other" type). + int structureTypeCount() const { return _structureTypeLabels.size(); } + + /// Returns the name of the structure type with the given index. + const QString& structureTypeLabel(int index) const { return _structureTypeLabels[index]; } + + /// Returns the description string of the structure type with the given index. + const QString& structureTypeDescription(int index) const { return _structureTypeDescriptions[index]; } + +private: + + /// Names of the structures types this filter maps to, e.g. "FCC", "FCC-HCP", "BCC", etc. + QStringList _structureTypeLabels; + + /// Descriptions strings of the structures types. + QStringList _structureTypeDescriptions; + + /// Mapping from Weinberg vectors to structure types. + std::map _entries; + + /// Comment text loaded from the filter definition file. + QString _filterDescription; +}; + +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/vorotop/gui/CMakeLists.txt ovito-2.9.0+dfsg1/src/plugins/vorotop/gui/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/plugins/vorotop/gui/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vorotop/gui/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,30 @@ +############################################################################### +# +# Copyright (2017) Alexander Stukowski +# +# This file is part of OVITO (Open Visualization Tool). +# +# OVITO is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# OVITO is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################### + +SET(SourceFiles + VoroTopModifierEditor.cpp +) + +OVITO_STANDARD_PLUGIN(VoroTopGui + SOURCES ${SourceFiles} + PLUGIN_DEPENDENCIES VoroTop ParticlesGui + GUI_PLUGIN +) diff -Nru ovito-2.8.1+dfsg2/src/plugins/vorotop/gui/VoroTopModifierEditor.cpp ovito-2.9.0+dfsg1/src/plugins/vorotop/gui/VoroTopModifierEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/vorotop/gui/VoroTopModifierEditor.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vorotop/gui/VoroTopModifierEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,113 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "VoroTopModifierEditor.h" + +namespace Ovito { namespace VoroTop { + +IMPLEMENT_OVITO_OBJECT(VoroTopModifierEditor, ParticleModifierEditor); +SET_OVITO_OBJECT_EDITOR(VoroTopModifier, VoroTopModifierEditor); + +/****************************************************************************** +* Sets up the UI widgets of the editor. +******************************************************************************/ +void VoroTopModifierEditor::createUI(const RolloutInsertionParameters& rolloutParams) +{ + // Create a rollout. + QWidget* rollout = createRollout(tr("VoroTop analysis"), rolloutParams, "particles.modifiers.vorotop_analysis.html"); + + // Create the rollout contents. + QVBoxLayout* layout = new QVBoxLayout(rollout); + layout->setContentsMargins(4,4,4,4); + layout->setSpacing(4); + + QGridLayout* gridlayout = new QGridLayout(); + QGridLayout* sublayout; + gridlayout->setContentsMargins(4,4,4,4); + gridlayout->setSpacing(4); + gridlayout->setColumnStretch(1, 1); + int row = 0; + + // Filter filename. + gridlayout->addWidget(new QLabel(tr("Filter:")), row++, 0, 1, 2); + FilenameParameterUI* fileFileUI = new FilenameParameterUI(this, PROPERTY_FIELD(VoroTopModifier::filterFile)); + gridlayout->addWidget(fileFileUI->selectorWidget(), row++, 0, 1, 2); + connect(fileFileUI, &FilenameParameterUI::showSelectionDialog, this, &VoroTopModifierEditor::onLoadFilter); + + QLabel* label = new QLabel(tr("Filter definition files are available for download on the VoroTop website.")); + label->setWordWrap(true); + label->setOpenExternalLinks(true); + gridlayout->addWidget(label, row++, 0, 1, 2); + + // Atomic radii. + BooleanParameterUI* useRadiiPUI = new BooleanParameterUI(this, PROPERTY_FIELD(VoroTopModifier::useRadii)); + gridlayout->addWidget(useRadiiPUI->checkBox(), row++, 0, 1, 2); + + // Only selected particles. + BooleanParameterUI* onlySelectedPUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::onlySelectedParticles)); + gridlayout->addWidget(onlySelectedPUI->checkBox(), row++, 0, 1, 2); + + layout->addLayout(gridlayout); + + // Status label. + layout->addSpacing(6); + layout->addWidget(statusLabel()); + + StructureListParameterUI* structureTypesPUI = new StructureListParameterUI(this, false); + layout->addSpacing(10); + layout->addWidget(new QLabel(tr("Structure types:"))); + layout->addWidget(structureTypesPUI->tableWidget()); + label = new QLabel(tr("

    Double-click to change colors.

    ")); + label->setWordWrap(true); + layout->addWidget(label); +} + +/****************************************************************************** +* Is called when the user presses the 'Load filter' button. +******************************************************************************/ +void VoroTopModifierEditor::onLoadFilter() +{ + VoroTopModifier* mod = static_object_cast(editObject()); + if(!mod) return; + + undoableTransaction(tr("Load VoroTop filter"), [this, mod]() { + + HistoryFileDialog fileDialog(QStringLiteral("vorotop_filter"), container(), tr("Pick VoroTop filter file"), + QString(), tr("VoroTop filter definition file (*)")); + fileDialog.setFileMode(QFileDialog::ExistingFile); + + if(fileDialog.exec()) { + QStringList selectedFiles = fileDialog.selectedFiles(); + if(!selectedFiles.empty()) { + mod->loadFilterDefinition(selectedFiles.front()); + } + } + }); +} + + +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/vorotop/gui/VoroTopModifierEditor.h ovito-2.9.0+dfsg1/src/plugins/vorotop/gui/VoroTopModifierEditor.h --- ovito-2.8.1+dfsg2/src/plugins/vorotop/gui/VoroTopModifierEditor.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vorotop/gui/VoroTopModifierEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include +#include + +namespace Ovito { namespace VoroTop { + +/** + * A properties editor for the VoroTopModifier class. + */ +class VoroTopModifierEditor : public ParticleModifierEditor +{ +public: + + /// Default constructor. + Q_INVOKABLE VoroTopModifierEditor() {} + +protected: + + /// Creates the user interface controls for the editor. + virtual void createUI(const RolloutInsertionParameters& rolloutParams) override; + +private Q_SLOTS: + + /// Is called when the user presses the 'Load filter' button. + void onLoadFilter(); + +private: + + Q_OBJECT + OVITO_OBJECT +}; + +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/vorotop/PythonInterface.cpp ovito-2.9.0+dfsg1/src/plugins/vorotop/PythonInterface.cpp --- ovito-2.8.1+dfsg2/src/plugins/vorotop/PythonInterface.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vorotop/PythonInterface.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,103 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +namespace Ovito { namespace VoroTop { + +using namespace PyScript; + +PYBIND11_PLUGIN(VoroTop) +{ + // Register the classes of this plugin with the global PluginManager. + PluginManager::instance().registerLoadedPluginClasses(); + + py::options options; + options.disable_function_signatures(); + + py::module m("VoroTop"); + + auto VoroTopModifier_py = ovito_class(m, + ":Base class: :py:class:`ovito.modifiers.Modifier`\n\n" + "This modifier uses the Voronoi cell topology of particles to characterize their local environments " + "[`Lazar, Han, Srolovitz, PNAS 112:43 (2015) `_]. " + "\n\n" + "The Voronoi cell of a particle is the region of space closer to it than to any other particle. " + "The topology of the Voronoi cell is the manner in which its faces are connected, and describes " + "the manner in which a particle's neighbors are arranged. The topology of a Voronoi cell can be " + "completely described in a vector of integers called a *Weinberg vector* " + "[`Weinberg, IEEE Trans. Circuit Theory 13:2 (1966) `_]. " + "\n\n" + "This modifier requires loading a *filter*, which specifies structure types and associated " + "Weinberg vectors. Filters for several common structures can be obtained from the " + "`VoroTop `_ website. " + "The modifier calculates the Voronoi cell topology of each particle, uses the provided " + "filter to determine the structure type, and stores the results in the ``Structure Type`` particle property. " + "This allows the user to subsequently select particles of a certain structural type, e.g. by using the " + ":py:class:SelectParticleTypeModifier`. " + "\n\n" + "This method is well-suited for analyzing finite-temperature systems, including those heated to " + "their bulk melting temperatures. This robust behavior relieves the need to quench a sample " + "(such as by energy minimization) prior to analysis. " + "Further information about the Voronoi topology approach for local structure analysis, as well " + "as additional filters, can be found on the `VoroTop webpage `_. " + "\n\n" + "**Modifier outputs:**" + "\n\n" + " * ``Structure Type`` (:py:class:`~ovito.data.ParticleProperty`):\n" + " This output particle property contains the integer structure type computed by the modifier for each particle.\n" + " * ``Color`` (:py:class:`~ovito.data.ParticleProperty`):\n" + " The modifier assigns a color to each particle based on its identified structure type. " + "\n\n" + ) + .def_property("only_selected", &VoroTopModifier::onlySelectedParticles, &VoroTopModifier::setOnlySelectedParticles, + "Lets the modifier take into account only selected particles. Particles that are currently not selected will be treated as if they did not exist." + "\n\n" + ":Default: ``False``\n") + .def_property("use_radii", &VoroTopModifier::useRadii, &VoroTopModifier::setUseRadii, + "If ``True``, the modifier computes the poly-disperse Voronoi tessellation, which takes into account the radii of particles. " + "Otherwise a mono-disperse Voronoi tessellation is computed, which is independent of the particle sizes. " + "\n\n" + ":Default: ``False``\n") + .def_property("filter_file", &VoroTopModifier::filterFile, &VoroTopModifier::loadFilterDefinition, + "Path to the filter definition file used by the modifier. " + "Filters files are available from the `VoroTop `_ website. " + "\n\n" + ":Default: ``''``\n") + ; + expose_subobject_list( + VoroTopModifier_py, "structures", "VoroTopStructureTypeList", + "A list of :py:class:`~ovito.data.ParticleType` instances managed by this modifier, one for each structural type loaded from the :py:attr:`.filter_file`. "); + + return m.ptr(); +} + +OVITO_REGISTER_PLUGIN_PYTHON_INTERFACE(VoroTop); + +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/vorotop/resources/python/ovito/modifiers/vorotop/__init__.py ovito-2.9.0+dfsg1/src/plugins/vorotop/resources/python/ovito/modifiers/vorotop/__init__.py --- ovito-2.8.1+dfsg2/src/plugins/vorotop/resources/python/ovito/modifiers/vorotop/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vorotop/resources/python/ovito/modifiers/vorotop/__init__.py 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,11 @@ +# Load dependencies +import ovito.modifiers +import ovito.modifiers.particles + +# Load the native code modules. +import ovito.plugins.Particles +import ovito.plugins.VoroTop + +# Inject modifier classes into parent module. +ovito.modifiers.VoroTopModifier = ovito.plugins.VoroTop.VoroTopModifier +ovito.modifiers.__all__ += ['VoroTopModifier'] diff -Nru ovito-2.8.1+dfsg2/src/plugins/vorotop/VoroTopModifier.cpp ovito-2.9.0+dfsg1/src/plugins/vorotop/VoroTopModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/vorotop/VoroTopModifier.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vorotop/VoroTopModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,588 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// Copyright (2017) Emanuel A. Lazar +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include "VoroTopModifier.h" +#include "Filter.h" + +#include + +namespace Ovito { namespace VoroTop { + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(VoroTopModifier, StructureIdentificationModifier); +DEFINE_PROPERTY_FIELD(VoroTopModifier, useRadii, "UseRadii"); +DEFINE_PROPERTY_FIELD(VoroTopModifier, filterFile, "FilterFile"); +SET_PROPERTY_FIELD_LABEL(VoroTopModifier, useRadii, "Use particle radii"); +SET_PROPERTY_FIELD_LABEL(VoroTopModifier, filterFile, "Filter file"); + +/****************************************************************************** + * Constructs the modifier object. + ******************************************************************************/ +VoroTopModifier::VoroTopModifier(DataSet* dataset) : StructureIdentificationModifier(dataset), + _useRadii(false) +{ + INIT_PROPERTY_FIELD(useRadii); + INIT_PROPERTY_FIELD(filterFile); +} + +/****************************************************************************** + * Loads a new filter definition into the modifier. + ******************************************************************************/ +void VoroTopModifier::loadFilterDefinition(const QString& filepath) +{ + // Open filter file for reading. + QFile file(filepath); + CompressedTextReader stream(file, filepath); + + // Load filter file header (i.e. list of structure types). + std::shared_ptr filter = std::make_shared(); + SynchronousTask loadTask(dataset()->container()->taskManager()); + if(!filter->load(stream, true, loadTask.promise())) + return; + + // Rebuild structure types list. + setStructureTypes(QVector()); + for(int i = 0; i < filter->structureTypeCount(); i++) { + OORef stype(new ParticleType(dataset())); + stype->setId(i); + stype->setName(filter->structureTypeLabel(i)); + stype->setColor(ParticleTypeProperty::getDefaultParticleColor(ParticleProperty::StructureTypeProperty, stype->name(), i)); + addStructureType(stype); + } + + // Filter file was successfully loaded. Accept it as the new filter. + setFilterFile(filepath); +} + +/****************************************************************************** + * Unpacks the results of the computation engine and stores them in the modifier. + ******************************************************************************/ +void VoroTopModifier::transferComputationResults(ComputeEngine* engine) +{ + StructureIdentificationModifier::transferComputationResults(engine); + + // Cache loaded filter definition for future use. + _filter = static_cast(engine)->filter(); +} + +/****************************************************************************** + * Lets the modifier insert the cached computation results into the modification pipeline. + ******************************************************************************/ +PipelineStatus VoroTopModifier::applyComputationResults(TimePoint time, TimeInterval& validityInterval) +{ + // Base class implementation of this method does the heavy work, but override this + // to report the number of loaded Weinberg vectors to the user below. + + PipelineStatus status = StructureIdentificationModifier::applyComputationResults(time, validityInterval); + if(status.type() != PipelineStatus::Success) + return status; + + return PipelineStatus(PipelineStatus::Success, tr("%1 Weinberg vectors loaded").arg(filter() ? filter()->size() : 0)); +} + +/****************************************************************************** + * Creates and initializes a computation engine that will compute the modifier's results. + ******************************************************************************/ +std::shared_ptr VoroTopModifier::createEngine(TimePoint time, TimeInterval validityInterval) +{ + // Get the current positions. + ParticlePropertyObject* posProperty = expectStandardProperty(ParticleProperty::PositionProperty); + + // Get simulation cell. + SimulationCellObject* inputCell = expectSimulationCell(); + + // Get selection particle property. + ParticlePropertyObject* selectionProperty = nullptr; + if(onlySelectedParticles()) + selectionProperty = expectStandardProperty(ParticleProperty::SelectionProperty); + + // Get particle radii. + std::vector radii; + if(useRadii()) + radii = std::move(inputParticleRadii(time, validityInterval)); + + // Create engine object. Pass all relevant modifier parameters to the engine as well as the input data. + return std::make_shared( + validityInterval, + posProperty->storage(), + selectionProperty ? selectionProperty->storage() : nullptr, + std::move(radii), + inputCell->data(), + filterFile(), + filter(), + getTypesToIdentify(structureTypes().size())); +} + +/****************************************************************************** + * Processes a single Voronoi cell. + ******************************************************************************/ +void VoroTopModifier::VoroTopAnalysisEngine::processCell(voro::voronoicell_neighbor& vcell, size_t particleIndex, QMutex* mutex) +{ + const int max_epf = 256; // MAXIMUM EDGES PER FACE + const int max_epc = 512; // MAXIMUM EDGES PER CELL + const int max_vpc = 512; // MAXIMUM VERTICES PER CELL + + int edge_count = vcell.number_of_edges(); + int vertex_count = vcell.p; // TOTAL NUMBER OF VERTICES + int* vertex_degrees = vcell.nu; // VERTEX DEGREE ARRAY + int** ed = vcell.ed; // EDGE CONNECTIONS ARRAY + + // TOO MANY VERTICES OR EDGES + if(vertex_count > filter()->maximumVertices || + edge_count > filter()->maximumEdges || + vertex_count >= max_vpc || + edge_count >= max_epc) + { + structures()->setInt(particleIndex, 0); // structureType OTHER + return; + } + + int face_count = 0; + int max_face_edges = 3; // EVERY CONVEX POLYHEDRON MUST HAVE AT LEAST ONE FACE WITH 3 OR MORE EDGES + int min_face_edges = 5; // EVERY CONVEX POLYHEDRON MUST HAVE AT LEAST ONE FACE WITH 5 OR FEWER EDGES + int pvector[max_epf] = {}; // RECORDS NUMBER OF FACES WITH EACH NUMBER OF EDGES, NO FACE IN FILTER HAS MORE THAN max_epf-1 EDGES + int origins[2*max_epc] = {}; // NO VORONOI CELL IN FILTER HAS MORE THAN max_epc EDGES + int origin_c = 0; + + // DETERMINE VERTICES ON FACES WITH MINIMAL EDGES + for(int i=0;i= 0) + { + int face[max_epf]={}; // NO SINGLE FACE WILL HAVE MORE THAN max_epf EDGES + int face_c=0; + + ed[i][j]=-1-k; // INDICATE THAT WE HAVE CHECKED THIS VERTEX + int l=vcell.cycle_up(ed[i][vertex_degrees[i]+j],k); + face[face_c++]=k; + do { + int m=ed[k][l]; + ed[k][l]=-1-m; + l=vcell.cycle_up(ed[k][vertex_degrees[k]+l],m); + k=m; + + face[face_c++]=m; + } while (k!=i); + + // KEEP TRACK OF MINIMAL AND MAXIMAL FACE EDGES + if(face_c>max_face_edges) + max_face_edges = face_c; + if(face_ccanonical_code[current_code_length]) break; + if(vertices_temp_labels[next]canonical_code[current_code_length]) break; + if(vertices_temp_labels[next]4 && orientation==0) { chirality=0; symmetry_counter = 48; finished=1; } + else if(chirality==-1 && orientation==1) { chirality=0; symmetry_counter *= 2; finished=1; } + else symmetry_counter++; + } + } + } + } + } + + canonical_code.push_back(1); + + int structureType = filter()->findType(canonical_code); + structures()->setInt(particleIndex, structureType); +} + + +/****************************************************************************** + * Performs the actual computation. This method is executed in a worker thread. + ******************************************************************************/ +void VoroTopModifier::VoroTopAnalysisEngine::perform() +{ + if(positions()->size() == 0) + return; // Nothing to do when there are zero particles. + + if(!filter()) { + setProgressText(tr("Loading VoroTop filter file")); + if(_filterFile.isEmpty()) + throw Exception(tr("No filter file selected")); + + // Open filter file for reading. + QFile file(_filterFile); + CompressedTextReader stream(file, _filterFile); + + // Parse filter definition. + _filter = std::make_shared(); + if(!_filter->load(stream, false, *this)) + return; + } + + setProgressText(tr("Performing VoroTop analysis")); + + // Decide whether to use Voro++ container class or our own implementation. + if(cell().isAxisAligned()) { + // Use Voro++ container. + double ax = cell().matrix()(0,3); + double ay = cell().matrix()(1,3); + double az = cell().matrix()(2,3); + double bx = ax + cell().matrix()(0,0); + double by = ay + cell().matrix()(1,1); + double bz = az + cell().matrix()(2,2); + if(ax > bx) std::swap(ax,bx); + if(ay > by) std::swap(ay,by); + if(az > bz) std::swap(az,bz); + double volumePerCell = (bx - ax) * (by - ay) * (bz - az) * voro::optimal_particles / positions()->size(); + double cellSize = pow(volumePerCell, 1.0/3.0); + int nx = (int)std::ceil((bx - ax) / cellSize); + int ny = (int)std::ceil((by - ay) / cellSize); + int nz = (int)std::ceil((bz - az) / cellSize); + + if(_radii.empty()) { + voro::container voroContainer(ax, bx, ay, by, az, bz, nx, ny, nz, + cell().pbcFlags()[0], cell().pbcFlags()[1], cell().pbcFlags()[2], (int)std::ceil(voro::optimal_particles)); + + // Insert particles into Voro++ container. + size_t count = 0; + for(size_t index = 0; index < positions()->size(); index++) { + // Skip unselected particles (if requested). + if(selection() && selection()->getInt(index) == 0) { + structures()->setInt(index, 0); + continue; + } + const Point3& p = positions()->getPoint3(index); + voroContainer.put(index, p.x(), p.y(), p.z()); + count++; + } + if(!count) return; + + setProgressMaximum(count); + setProgressValue(0); + voro::c_loop_all cl(voroContainer); + voro::voronoicell_neighbor v; + if(cl.start()) { + do { + if(!incrementProgressValue()) + return; + if(!voroContainer.compute_cell(v,cl)) + continue; + processCell(v, cl.pid(), nullptr); + count--; + } + while(cl.inc()); + } + if(count) + throw Exception(tr("Could not compute Voronoi cell for some particles.")); + } + else { + voro::container_poly voroContainer(ax, bx, ay, by, az, bz, nx, ny, nz, + cell().pbcFlags()[0], cell().pbcFlags()[1], cell().pbcFlags()[2], (int)std::ceil(voro::optimal_particles)); + + // Insert particles into Voro++ container. + size_t count = 0; + for(size_t index = 0; index < positions()->size(); index++) { + structures()->setInt(index, 0); + // Skip unselected particles (if requested). + if(selection() && selection()->getInt(index) == 0) { + continue; + } + const Point3& p = positions()->getPoint3(index); + voroContainer.put(index, p.x(), p.y(), p.z(), _radii[index]); + count++; + } + + if(!count) return; + setProgressMaximum(count); + setProgressValue(0); + voro::c_loop_all cl(voroContainer); + voro::voronoicell_neighbor v; + if(cl.start()) { + do { + if(!incrementProgressValue()) + return; + if(!voroContainer.compute_cell(v,cl)) + continue; + processCell(v, cl.pid(), nullptr); + count--; + } + while(cl.inc()); + } + if(count) + throw Exception(tr("Could not compute Voronoi cell for some particles.")); + } + } + else { + // Prepare the nearest neighbor list generator. + NearestNeighborFinder nearestNeighborFinder; + if(!nearestNeighborFinder.prepare(positions(), cell(), selection(), *this)) + return; + + // Squared particle radii (input was just radii). + for(auto& r : _radii) + r = r*r; + + // This is the size we use to initialize Voronoi cells. Must be larger than the simulation box. + double boxDiameter = sqrt( + cell().matrix().column(0).squaredLength() + + cell().matrix().column(1).squaredLength() + + cell().matrix().column(2).squaredLength()); + + // The normal vectors of the three cell planes. + std::array planeNormals; + planeNormals[0] = cell().cellNormalVector(0); + planeNormals[1] = cell().cellNormalVector(1); + planeNormals[2] = cell().cellNormalVector(2); + + Point3 corner1 = Point3::Origin() + cell().matrix().column(3); + Point3 corner2 = corner1 + cell().matrix().column(0) + cell().matrix().column(1) + cell().matrix().column(2); + + QMutex mutex; + + // Perform analysis, particle-wise parallel. + parallelFor(positions()->size(), *this, + [&nearestNeighborFinder, this, boxDiameter, + planeNormals, corner1, corner2, &mutex](size_t index) { + + // Reset structure type. + structures()->setInt(index, 0); + + // Skip unselected particles (if requested). + if(selection() && selection()->getInt(index) == 0) + return; + + // Build Voronoi cell. + voro::voronoicell_neighbor v; + + // Initialize the Voronoi cell to be a cube larger than the simulation cell, centered at the origin. + v.init(-boxDiameter, boxDiameter, -boxDiameter, boxDiameter, -boxDiameter, boxDiameter); + + // Cut Voronoi cell at simulation cell boundaries in non-periodic directions. + bool skipParticle = false; + for(size_t dim = 0; dim < 3; dim++) { + if(!cell().pbcFlags()[dim]) { + double r; + r = 2 * planeNormals[dim].dot(corner2 - positions()->getPoint3(index)); + if(r <= 0) skipParticle = true; + v.nplane(planeNormals[dim].x() * r, planeNormals[dim].y() * r, planeNormals[dim].z() * r, r*r, -1); + r = 2 * planeNormals[dim].dot(positions()->getPoint3(index) - corner1); + if(r <= 0) skipParticle = true; + v.nplane(-planeNormals[dim].x() * r, -planeNormals[dim].y() * r, -planeNormals[dim].z() * r, r*r, -1); + } + } + // Skip particles that are located outside of non-periodic box boundaries. + if(skipParticle) + return; + + // This function will be called for every neighbor particle. + int nvisits = 0; + auto visitFunc = [this, &v, &nvisits, index](const NearestNeighborFinder::Neighbor& n, FloatType& mrs) { + // Skip unselected particles (if requested). + OVITO_ASSERT(!selection() || selection()->getInt(n.index)); + FloatType rs = n.distanceSq; + if(!_radii.empty()) + rs += _radii[index] - _radii[n.index]; + v.nplane(n.delta.x(), n.delta.y(), n.delta.z(), rs, n.index); + if(nvisits == 0) { + mrs = v.max_radius_squared(); + nvisits = 100; + } + nvisits--; + }; + + // Visit all neighbors of the current particles. + nearestNeighborFinder.visitNeighbors(nearestNeighborFinder.particlePos(index), visitFunc); + + processCell(v, index, &mutex); + }); + } +} + +/****************************************************************************** + * Is called when the value of a property of this object has changed. + ******************************************************************************/ +void VoroTopModifier::propertyChanged(const PropertyFieldDescriptor& field) +{ + StructureIdentificationModifier::propertyChanged(field); + + // Throw away loaded filter definition whenever a new filter file has been selected. + if(field == PROPERTY_FIELD(VoroTopModifier::filterFile)) + _filter.reset(); + + // Recompute modifier results when the parameters change. + if(field == PROPERTY_FIELD(VoroTopModifier::useRadii) || + field == PROPERTY_FIELD(VoroTopModifier::filterFile)) + invalidateCachedResults(); +} + +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/vorotop/VoroTopModifier.h ovito-2.9.0+dfsg1/src/plugins/vorotop/VoroTopModifier.h --- ovito-2.8.1+dfsg2/src/plugins/vorotop/VoroTopModifier.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vorotop/VoroTopModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,121 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include +#include +#include "Filter.h" + +namespace voro { + class voronoicell_neighbor; // Defined by Voro++ +} + +namespace Ovito { namespace VoroTop { + +/** + * \brief This analysis modifier performs the Voronoi topology analysis developed by Emanuel A. Lazar. + */ +class OVITO_VOROTOP_EXPORT VoroTopModifier : public StructureIdentificationModifier +{ +public: + + /// Constructor. + Q_INVOKABLE VoroTopModifier(DataSet* dataset); + + /// Loads a new filter definition into the modifier. + void loadFilterDefinition(const QString& filepath); + + /// Returns the VoroTop filter definition cached from the last analysis run. + const std::shared_ptr& filter() const { return _filter; } + +protected: + + /// Is called when the value of a property of this object has changed. + virtual void propertyChanged(const PropertyFieldDescriptor& field) override; + + /// Creates a computation engine that will compute the modifier's results. + virtual std::shared_ptr createEngine(TimePoint time, TimeInterval validityInterval) override; + + /// Unpacks the results of the computation engine and stores them in the modifier. + virtual void transferComputationResults(ComputeEngine* engine) override; + + /// Lets the modifier insert the cached computation results into the modification pipeline. + virtual PipelineStatus applyComputationResults(TimePoint time, TimeInterval& validityInterval) override; + +private: + + /// Compute engine that performs the actual analysis in a background thread. + class VoroTopAnalysisEngine : public StructureIdentificationEngine + { + public: + + /// Constructor. + VoroTopAnalysisEngine(const TimeInterval& validityInterval, ParticleProperty* positions, ParticleProperty* selection, + std::vector&& radii, const SimulationCell& simCell, const QString& filterFile, const std::shared_ptr& filter, const QVector& typesToIdentify) : + StructureIdentificationEngine(validityInterval, positions, simCell, typesToIdentify, selection), + _filterFile(filterFile), + _filter(filter), + _radii(std::move(radii)) {} + + /// Computes the modifier's results and stores them in this object for later retrieval. + virtual void perform() override; + + /// Processes a single Voronoi cell. + void processCell(voro::voronoicell_neighbor& vcell, size_t particleIndex, QMutex* mutex); + + /// Returns the VoroTop filter definition. + const std::shared_ptr& filter() const { return _filter; } + + private: + + /// The path of the external file containing the filter definition. + QString _filterFile; + + /// The VoroTop filter definition. + std::shared_ptr _filter; + + /// The per-particle radii. + std::vector _radii; + }; + +private: + + /// Controls whether the weighted Voronoi tessellation is computed, which takes into account particle radii. + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, useRadii, setUseRadii); + + /// The external file path of the loaded filter file. + DECLARE_MODIFIABLE_PROPERTY_FIELD(QString, filterFile, setFilterFile); + + /// The VoroTop filter definition cached from the last analysis run. + std::shared_ptr _filter; + + Q_OBJECT + OVITO_OBJECT + + Q_CLASSINFO("DisplayName", "VoroTop analysis"); + Q_CLASSINFO("ModifierCategory", "Analysis"); +}; + +} // End of namespace +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/vorotop/VoroTopPlugin.h ovito-2.9.0+dfsg1/src/plugins/vorotop/VoroTopPlugin.h --- ovito-2.8.1+dfsg2/src/plugins/vorotop/VoroTopPlugin.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vorotop/VoroTopPlugin.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,37 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include + +#ifdef VoroTop_EXPORTS // This is defined by CMake when building the plugin library. +# define OVITO_VOROTOP_EXPORT Q_DECL_EXPORT +#else +# define OVITO_VOROTOP_EXPORT Q_DECL_IMPORT +#endif + +namespace Ovito { + namespace VoroTop { + using namespace Ovito::Particles; + } +} diff -Nru ovito-2.8.1+dfsg2/src/plugins/vr/CMakeLists.txt ovito-2.9.0+dfsg1/src/plugins/vr/CMakeLists.txt --- ovito-2.8.1+dfsg2/src/plugins/vr/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vr/CMakeLists.txt 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,54 @@ +############################################################################### +# +# Copyright (2016) Alexander Stukowski +# +# This file is part of OVITO (Open Visualization Tool). +# +# OVITO is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# OVITO is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################### + +# Locate the OpenVR library. +FIND_PACKAGE(OpenVR REQUIRED) + +SET(SourceFiles + StartVRAction.cpp + VRWindow.cpp + VRRenderingWidget.cpp + VRSceneRenderer.cpp + VRCacheModifier.cpp + VRSettingsObject.cpp + VRSettingsObjectEditor.cpp +) + +OVITO_STANDARD_PLUGIN(VRPlugin + SOURCES ${SourceFiles} + GUI_PLUGIN +) + +# Link to OpenVR library. +TARGET_INCLUDE_DIRECTORIES(VRPlugin PRIVATE ${OpenVR_INCLUDE_DIRS}) +TARGET_LINK_LIBRARIES(VRPlugin PRIVATE ${OpenVR_LIBRARIES}) + +IF(WIN32) + # Determine location of OpenVR DLL. + LIST(GET OpenVR_LIBRARIES 0 OpenVR_FIRST_LIBRARY) + GET_FILENAME_COMPONENT(OPENVR_LIBRARY_PATH "${OpenVR_FIRST_LIBRARY}" PATH) + + # Deploy OpenVR DLL. + OVITO_INSTALL_DLL("${OPENVR_LIBRARY_PATH}/../../bin/win64/openvr_api.dll") +ENDIF() + +# Propagate list of plugins to parent scope. +SET(OVITO_PLUGIN_LIST ${OVITO_PLUGIN_LIST} PARENT_SCOPE) \ No newline at end of file diff -Nru ovito-2.8.1+dfsg2/src/plugins/vr/StartVRAction.cpp ovito-2.9.0+dfsg1/src/plugins/vr/StartVRAction.cpp --- ovito-2.8.1+dfsg2/src/plugins/vr/StartVRAction.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vr/StartVRAction.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "StartVRAction.h" +#include "VRWindow.h" + +namespace VRPlugin { + +IMPLEMENT_OVITO_OBJECT(StartVRAction, GuiAutoStartObject); + +/****************************************************************************** +* Is called when a new main window is created. +******************************************************************************/ +void StartVRAction::registerActions(ActionManager& actionManager) +{ + // Register an action, which allows the user to run a Python script file. + QAction* startVRAction = actionManager.createCommandAction("StartVR", tr("Start VR module...")); + + connect(startVRAction, &QAction::triggered, [&actionManager]() { + try { + VRWindow* window = new VRWindow(actionManager.mainWindow(), &actionManager.mainWindow()->datasetContainer()); + window->show(); + } + catch(const Exception& ex) { + ex.reportError(); + } + }); +} + +/****************************************************************************** +* Is called when the main menu is created. +******************************************************************************/ +void StartVRAction::addActionsToMenu(ActionManager& actionManager, QMenuBar* menuBar) +{ + QAction* startVRAction = actionManager.findAction("StartVR"); + if(!startVRAction) return; + + QMenu* vrMenu = menuBar->addMenu(tr("&Virtual Reality")); + vrMenu->setObjectName(QStringLiteral("VRMenu")); + vrMenu->addAction(startVRAction); +} + +/****************************************************************************** +* Registers plugin-specific command line options. +******************************************************************************/ +void StartVRAction::registerCommandLineOptions(QCommandLineParser& cmdLineParser) +{ + // Register the --vr command line option. + cmdLineParser.addOption(QCommandLineOption("vr", tr("Invokes the virtual reality module."))); +} + +/****************************************************************************** +* Is called after the application has been completely initialized. +******************************************************************************/ +void StartVRAction::applicationStarted() +{ + // Handle the --vr command line option. + if(StandaloneApplication::instance()->cmdLineParser().isSet("vr")) { + + // Trigger the 'Start VR' command action, which has been registered by registerActions() above. + GuiDataSetContainer* container = qobject_cast(StandaloneApplication::instance()->datasetContainer()); + container->mainWindow()->actionManager()->findAction("StartVR")->trigger(); + } +} + + +}; diff -Nru ovito-2.8.1+dfsg2/src/plugins/vr/StartVRAction.h ovito-2.9.0+dfsg1/src/plugins/vr/StartVRAction.h --- ovito-2.8.1+dfsg2/src/plugins/vr/StartVRAction.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vr/StartVRAction.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include + +namespace VRPlugin { + +using namespace Ovito; + +/** + * \brief An auto-start object that is automatically invoked on application startup. + */ +class StartVRAction : public GuiAutoStartObject +{ +public: + + /// \brief Default constructor. + Q_INVOKABLE StartVRAction() {} + + /// \brief Is called when a new main window is created. + virtual void registerActions(ActionManager& actionManager) override; + + /// \brief Is called when the main menu is created. + virtual void addActionsToMenu(ActionManager& actionManager, QMenuBar* menuBar) override; + + /// \brief Registers plugin-specific command line options. + virtual void registerCommandLineOptions(QCommandLineParser& cmdLineParser) override; + + /// \brief Is called after the application has been completely initialized. + virtual void applicationStarted() override; + +private: + + Q_OBJECT + OVITO_OBJECT +}; + +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/vr/VRCacheModifier.cpp ovito-2.9.0+dfsg1/src/plugins/vr/VRCacheModifier.cpp --- ovito-2.8.1+dfsg2/src/plugins/vr/VRCacheModifier.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vr/VRCacheModifier.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include "VRCacheModifier.h" + +namespace VRPlugin { + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(VRCacheModifier, Modifier); + +/****************************************************************************** +* This modifies the input object in a specific way. +******************************************************************************/ +PipelineStatus VRCacheModifier::modifyObject(TimePoint time, ModifierApplication* modApp, PipelineFlowState& state) +{ + if(state.status().type() != PipelineStatus::Pending) { + _cache = state; + _cache.cloneObjectsIfNeeded(false); + } + else { + TimeInterval stateValidity = state.stateValidity(); + state = _cache; + state.setStatus(PipelineStatus::Pending); + state.setStateValidity(stateValidity); + } + return PipelineStatus(); +} + +}; diff -Nru ovito-2.8.1+dfsg2/src/plugins/vr/VRCacheModifier.h ovito-2.9.0+dfsg1/src/plugins/vr/VRCacheModifier.h --- ovito-2.8.1+dfsg2/src/plugins/vr/VRCacheModifier.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vr/VRCacheModifier.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,64 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include + +namespace VRPlugin { + +using namespace Ovito; + +/** + * \brief A modifier that caches the results of the data pipeline. + */ +class VRCacheModifier : public Modifier +{ +public: + + /// \brief Default constructor. + Q_INVOKABLE VRCacheModifier(DataSet* dataset) : Modifier(dataset) {} + + /// \brief This modifies the input object in a specific way. + virtual PipelineStatus modifyObject(TimePoint time, ModifierApplication* modApp, PipelineFlowState& state) override; + + /// \brief Asks the modifier for its validity interval at the given time. + virtual TimeInterval modifierValidity(TimePoint time) override { return TimeInterval::infinite(); } + + /// Asks the modifier whether it can be applied to the given input data. + virtual bool isApplicableTo(const PipelineFlowState& input) override { return true; } + +private: + + /// The cached state. + PipelineFlowState _cache; + + Q_OBJECT + OVITO_OBJECT + + Q_CLASSINFO("DisplayName", "VR Display Cache"); + Q_CLASSINFO("ModifierCategory", "VR"); + +}; + +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/vr/VRRenderingWidget.cpp ovito-2.9.0+dfsg1/src/plugins/vr/VRRenderingWidget.cpp --- ovito-2.8.1+dfsg2/src/plugins/vr/VRRenderingWidget.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vr/VRRenderingWidget.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,365 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include "VRWindow.h" + +namespace VRPlugin { + +/****************************************************************************** +* Constructor. +******************************************************************************/ +VRRenderingWidget::VRRenderingWidget(QWidget *parent, DataSet* dataset) : QOpenGLWidget(parent) +{ + _sceneRenderer = new VRSceneRenderer(dataset); + + // Create a settings object, or use stored one if there is one. + _settings = dataset->findGlobalObject(); + if(!_settings) { + _settings = new VRSettingsObject(dataset); + dataset->addGlobalObject(_settings); + _settings->recenter(); + } + + // Initialize VR headset. + vr::EVRInitError eError = vr::VRInitError_None; + _hmd = vr::VR_Init(&eError, vr::VRApplication_Scene); + if(eError != vr::VRInitError_None) + dataset->throwException(tr("Cannot start virtual reality headset. OpenVR initialization error: %1").arg(vr::VR_GetVRInitErrorAsEnglishDescription(eError))); + + // Get the proper rendering resolution of the hmd. + _hmd->GetRecommendedRenderTargetSize(&_hmdRenderWidth, &_hmdRenderHeight); + + // Initialize the compositor. + vr::IVRCompositor* compositor = vr::VRCompositor(); + if(!compositor) + dataset->throwException(tr("OpenVR Compositor initialization failed.")); + + // Get dimensions of play area. + vr::IVRChaperone* chaperone = vr::VRChaperone(); + chaperone->GetPlayAreaRect(&_playAreaRect); + _playAreaMesh.setVertexCount(4); + _playAreaMesh.setFaceCount(2); + for(int i = 0; i < 4; i++) { + _playAreaMesh.vertices()[i].x() = _playAreaRect.vCorners[i].v[0]; + _playAreaMesh.vertices()[i].y() = _playAreaRect.vCorners[i].v[1]; + _playAreaMesh.vertices()[i].z() = _playAreaRect.vCorners[i].v[2]; + } + _playAreaMesh.faces()[0].setVertices(0,1,2); + _playAreaMesh.faces()[1].setVertices(0,2,3); +} + +/****************************************************************************** +* Destructor. +******************************************************************************/ +VRRenderingWidget::~VRRenderingWidget() +{ + cleanup(); + + // Shutdown VR headset. + if(_hmd) { + vr::VR_Shutdown(); + } +} + +/****************************************************************************** +* Called when the GL context is destroyed. +******************************************************************************/ +void VRRenderingWidget::cleanup() +{ + makeCurrent(); + _floorMesh.reset(); + _eyeBuffer.reset(); + doneCurrent(); +} + +/****************************************************************************** +* Called when the GL context is initialized. +******************************************************************************/ +void VRRenderingWidget::initializeGL() +{ + connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &VRRenderingWidget::cleanup); + initializeOpenGLFunctions(); +} + +/****************************************************************************** +* Computes the projection and transformation matrices for each of the two eyes. +******************************************************************************/ +ViewProjectionParameters VRRenderingWidget::projectionParameters(int eye, FloatType aspectRatio, const AffineTransformation& bodyToWorldTM, const Box3& sceneBoundingBox) +{ + OVITO_ASSERT(aspectRatio > FLOATTYPE_EPSILON); + OVITO_ASSERT(!sceneBoundingBox.isEmpty()); + + AffineTransformation headToBodyTM = fromOpenVRMatrix(_trackedDevicePose[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking); + AffineTransformation eyeToHeadTM = fromOpenVRMatrix(_hmd->GetEyeToHeadTransform(eye ? vr::Eye_Right : vr::Eye_Left)); + + ViewProjectionParameters params; + params.aspectRatio = aspectRatio; + params.validityInterval.setInfinite(); + params.boundingBox = sceneBoundingBox; + params.inverseViewMatrix = bodyToWorldTM * headToBodyTM * eyeToHeadTM; + params.viewMatrix = params.inverseViewMatrix.inverse(); + params.fieldOfView = 0; + params.isPerspective = true; + + // Transform scene bounding box to camera space. + Box3 bb = sceneBoundingBox.transformed(params.viewMatrix).centerScale(FloatType(1.01)); + + // Compute near/far plane distances. + if(bb.minc.z() < 0) { + params.zfar = -bb.minc.z(); + params.znear = std::max(-bb.maxc.z(), params.zfar * FloatType(1e-4)); + } + else { + params.zfar = std::max(sceneBoundingBox.size().length(), FloatType(1)); + params.znear = params.zfar * FloatType(1e-4); + } + params.zfar = std::max(params.zfar, params.znear * FloatType(1.01)); + + // Compute projection matrix. + params.projectionMatrix = fromOpenVRMatrix(_hmd->GetProjectionMatrix(eye ? vr::Eye_Right : vr::Eye_Left, params.znear, params.zfar)); + params.inverseProjectionMatrix = params.projectionMatrix.inverse(); + + return params; +} + +/****************************************************************************** +* Called when the VR window contents are rendered. +******************************************************************************/ +void VRRenderingWidget::paintGL() +{ + // Queue up another repaint event. + update(); + + // Clear background of VR window. + glViewport(0, 0, _windowWidth, _windowHeight); + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + vr::IVRCompositor* compositor = vr::VRCompositor(); + if(!compositor) return; + + // Choose between seated and standing mode. + compositor->SetTrackingSpace(settings()->flyingMode() ? vr::TrackingUniverseSeated : vr::TrackingUniverseStanding); + + // Request camera position from VR headset. + compositor->WaitGetPoses(_trackedDevicePose, vr::k_unMaxTrackedDeviceCount, nullptr, 0); + if(!_trackedDevicePose[vr::k_unTrackedDeviceIndex_Hmd].bPoseIsValid) + return; + + // Measure time since last frame. + FloatType elapsedTime = _time.elapsed(); + _time.restart(); + + bool accelerating = false; + bool playAnimation = false; + + // Process SteamVR controller state. + std::vector controllerTMs; + for(vr::TrackedDeviceIndex_t unTrackedDevice = vr::k_unTrackedDeviceIndex_Hmd + 1; unTrackedDevice < vr::k_unMaxTrackedDeviceCount; unTrackedDevice++) { + if(!_hmd->IsTrackedDeviceConnected(unTrackedDevice)) + continue; + if(_hmd->GetTrackedDeviceClass(unTrackedDevice) != vr::TrackedDeviceClass_Controller) + continue; + if(!_trackedDevicePose[unTrackedDevice].bPoseIsValid) + continue; + + AffineTransformation controllerTM = fromOpenVRMatrix(_trackedDevicePose[unTrackedDevice].mDeviceToAbsoluteTracking); + controllerTMs.push_back(controllerTM); + + vr::VRControllerState_t state; + if(_hmd->GetControllerState(unTrackedDevice, &state, sizeof(state))) { + if(state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_SteamVR_Touchpad)) { + _currentSpeed += elapsedTime * FloatType(1e-6); + _currentSpeed = std::min(_currentSpeed, FloatType(0.001)); + accelerating = true; + if(settings()->flyingMode()) { + AffineTransformation tm = settings()->viewerTM(); + FloatType factor = _currentSpeed * settings()->movementSpeed() * elapsedTime; + tm.translation() += controllerTM * Vector3(state.rAxis[0].x * factor, 0, -state.rAxis[0].y * factor); + settings()->setViewerTM(tm); + } + else { + if(std::abs(state.rAxis[0].x) > std::abs(state.rAxis[0].y)) { + settings()->setRotationZ(settings()->rotationZ() + state.rAxis[0].x * elapsedTime * _currentSpeed * 2); + } + else { + AffineTransformation tm = AffineTransformation::rotationX(FLOATTYPE_PI/2) * settings()->viewerTM() * controllerTM; + Vector3 dir = tm.column(2); + Vector3 translation = settings()->translation(); + if(dir.z()*dir.z() >= dir.x()*dir.x() + dir.y()*dir.y()) { + translation.z() -= FloatType(0.5) * state.rAxis[0].y * elapsedTime * std::copysign(_currentSpeed, dir.z()) * settings()->movementSpeed(); + } + else { + translation -= (FloatType(0.5) * state.rAxis[0].y * elapsedTime * _currentSpeed * settings()->movementSpeed()) * Vector3(dir.x(), dir.y(), 0).normalized(); + } + settings()->setTranslation(translation); + } + } + } + + if(state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_SteamVR_Trigger)) { + playAnimation = true; + } + } + } + if(!accelerating) + _currentSpeed = 0; + + dataset()->animationSettings()->setAnimationPlayback(playAnimation); + + // Compute model transformation. + AffineTransformation transformationTM = + AffineTransformation::translation(settings()->translation()) * + AffineTransformation::scaling(std::max(settings()->scaleFactor(), FloatType(1e-6))) * + AffineTransformation::rotationZ(settings()->rotationZ()) * + AffineTransformation::translation(-settings()->modelCenter()); + + // Compute viewer position in scene space. + AffineTransformation bodyToWorldTM = + ViewportSettings::getSettings().coordinateSystemOrientation() * + transformationTM.inverse() * + AffineTransformation::rotationX(FLOATTYPE_PI/2) * + settings()->viewerTM(); + + // Allocate framebuffers for both eyes. + _renderResolution = QSize(_hmdRenderWidth, _hmdRenderHeight) * (settings()->supersamplingEnabled() ? 2 : 1); + if(!_eyeBuffer || _eyeBuffer->size() != _renderResolution) + _eyeBuffer.reset(new QOpenGLFramebufferObject(_renderResolution, QOpenGLFramebufferObject::Depth)); + + FloatType aspectRatio = (FloatType)_renderResolution.height() / _renderResolution.width(); + try { + for(int eye = 0; eye < 2; eye++) { + + // Set up the renderer. + TimePoint time = dataset()->animationSettings()->time(); + _sceneRenderer->startRender(dataset(), dataset()->renderSettings()); + + // Render to an offscreen buffer, one for each eye. + if(!_eyeBuffer->bind()) + dataset()->throwException(tr("Failed to bind OpenGL framebuffer object for offscreen rendering.")); + + // Request scene bounding box. + Box3 boundingBox = _sceneRenderer->sceneBoundingBox(time); + + // Add ground geometry to bounding box. + AffineTransformation bodyToFloorTM; + if(settings()->showFloor()) { + if(settings()->flyingMode()) + bodyToFloorTM = bodyToWorldTM * fromOpenVRMatrix(_hmd->GetSeatedZeroPoseToStandingAbsoluteTrackingPose()).inverse(); + else + bodyToFloorTM = bodyToWorldTM; + boundingBox.addBox(_playAreaMesh.boundingBox().transformed(bodyToFloorTM)); + } + + // Add controller geometry to bounding box. + for(const AffineTransformation& controllerTM : controllerTMs) + boundingBox.addBox((bodyToWorldTM * controllerTM) * Box3(Point3::Origin(), _controllerSize)); + + // Set up projection. + ViewProjectionParameters projParams = projectionParameters(eye, aspectRatio, bodyToWorldTM, boundingBox); + + // Set up the renderer. + _sceneRenderer->beginFrame(time, projParams, nullptr); + _sceneRenderer->setRenderingViewport(0, 0, _renderResolution.width(), _renderResolution.height()); + + // Call the viewport renderer to render the scene objects. + _sceneRenderer->renderFrame(nullptr, SceneRenderer::NonStereoscopic, dataset()->container()->taskManager()); + + // Render floor rectangle. + if(settings()->showFloor()) { + if(!_floorMesh || !_floorMesh->isValid(_sceneRenderer)) { + _floorMesh = _sceneRenderer->createMeshPrimitive(); + _floorMesh->setMesh(_playAreaMesh, ColorA(1.0f,1.0f,0.7f,0.8f)); + _floorMesh->setCullFaces(false); + } + _sceneRenderer->setWorldTransform(bodyToFloorTM); + _floorMesh->render(_sceneRenderer); + } + + // Render VR controllers. + for(const AffineTransformation& controllerTM : controllerTMs) { + if(!_controllerGeometry || !_controllerGeometry->isValid(_sceneRenderer)) { + _controllerGeometry = _sceneRenderer->createArrowPrimitive(ArrowPrimitive::ArrowShape, ArrowPrimitive::NormalShading, ArrowPrimitive::HighQuality); + _controllerGeometry->startSetElements(1); + _controllerGeometry->setElement(0, Point3(0,0,_controllerSize), Vector3(0,0,-_controllerSize), ColorA(1.0f, 0.0f, 0.0f, 1.0f), 0.02f); + _controllerGeometry->endSetElements(); + } + _sceneRenderer->setWorldTransform(bodyToWorldTM * controllerTM); + _controllerGeometry->render(_sceneRenderer); + } + + // Cleanup + _sceneRenderer->endFrame(true); + _sceneRenderer->endRender(); + + // Submit rendered image to VR compositor. + const vr::Texture_t tex = { reinterpret_cast(intptr_t(_eyeBuffer->texture())), vr::TextureType_OpenGL, vr::ColorSpace_Gamma }; + compositor->Submit(vr::EVREye(eye), &tex); + } + } + catch(const Exception& ex) { + ex.logError(); + ex.reportError(); + } + + // Tell the compositor to begin work immediately instead of waiting for the next WaitGetPoses() call + compositor->PostPresentHandoff(); + + // Switch back to the screen framebuffer. + if(!QOpenGLFramebufferObject::bindDefault()) + dataset()->throwException(tr("Failed to release OpenGL framebuffer object after offscreen rendering.")); + + // Mirror right eye on screen. + FloatType windowAspectRatio = (FloatType)_windowHeight / _windowWidth; + int blitWidth, blitHeight; + if(aspectRatio > windowAspectRatio) { + blitWidth = _renderResolution.width(); + blitHeight = _renderResolution.height() * (windowAspectRatio / aspectRatio); + } + else { + blitWidth = _renderResolution.width() * (aspectRatio / windowAspectRatio); + blitHeight = _renderResolution.height(); + } + QOpenGLFramebufferObject::blitFramebuffer( + nullptr, QRect(0,0,_windowWidth,_windowHeight), + _eyeBuffer.get(), + QRect((_renderResolution.width() - blitWidth)/2, (_renderResolution.height() - blitHeight)/2, blitWidth, blitHeight), + GL_COLOR_BUFFER_BIT, GL_LINEAR); +} + +/****************************************************************************** +* Called when the VR display window is resized. +******************************************************************************/ +void VRRenderingWidget::resizeGL(int w, int h) +{ + _windowWidth = w; + _windowHeight = h; +} + +}; + diff -Nru ovito-2.8.1+dfsg2/src/plugins/vr/VRRenderingWidget.h ovito-2.9.0+dfsg1/src/plugins/vr/VRRenderingWidget.h --- ovito-2.8.1+dfsg2/src/plugins/vr/VRRenderingWidget.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vr/VRRenderingWidget.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,139 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include +#include "VRSceneRenderer.h" +#include "VRSettingsObject.h" + +#include + +namespace VRPlugin { + +using namespace Ovito; + +class VRRenderingWidget : public QOpenGLWidget, protected QOpenGLFunctions +{ + Q_OBJECT + +public: + + /// Constructor. + VRRenderingWidget(QWidget* parent, DataSet* dataset); + + /// Destructor. + ~VRRenderingWidget(); + + /// Returns the dataset that is being shown in the VR window. + DataSet* dataset() const { return _sceneRenderer->dataset(); } + + /// Returns the settings object. + VRSettingsObject* settings() const { return _settings; } + + // From QWidget: + QSize minimumSizeHint() const override { return QSize(50, 50); } + QSize sizeHint() const override { return QSize(500, 500); } + +public Q_SLOTS: + + /// Called when the GL context is destroyed. + void cleanup(); + +protected: + + /// Called when the GL context is initialized. + void initializeGL() override; + + /// Called when the VR window contents are rendered. + void paintGL() override; + + /// Called when the VR display window is resized. + void resizeGL(int width, int height) override; + +private: + + /// Computes the projection and transformation matrices for each of the two eyes. + ViewProjectionParameters projectionParameters(int eye, FloatType aspectRatio, const AffineTransformation& bodyToWorldTM, const Box3& sceneBoundingBox); + + /// Converts a transformation matrix from the OpenVR format to OVITO's internal format. + static AffineTransformation fromOpenVRMatrix(const vr::HmdMatrix34_t& tm) { + AffineTransformation tm_out; + for(size_t r = 0; r < 3; ++r) + for(size_t c = 0; c < 4; ++c) + tm_out(r,c) = static_cast(tm.m[r][c]); + return tm_out; + } + + /// Converts a transformation matrix from the OpenVR format to OVITO's internal format. + static Matrix4 fromOpenVRMatrix(const vr::HmdMatrix44_t& tm) { + Matrix4 tm_out; + for(size_t r = 0; r < 4; ++r) + for(size_t c = 0; c < 4; ++c) + tm_out(r,c) = static_cast(tm.m[r][c]); + return tm_out; + } + + /// This is the OpenGL scene renderer. + OORef _sceneRenderer; + + /// VR Headset interface. + vr::IVRSystem* _hmd = nullptr; + vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; + + /// Corner positions of the VR play area. + vr::HmdQuad_t _playAreaRect; + TriMesh _playAreaMesh; + + /// Floor geometry. + std::shared_ptr _floorMesh; + + /// Controller geometry. + std::shared_ptr _controllerGeometry; + FloatType _controllerSize = 0.2f; + + // Current size of VR monitor window. + int _windowWidth; + int _windowHeight; + + // Preferred rendering resolution of the VR headset. + uint32_t _hmdRenderWidth = 800; + uint32_t _hmdRenderHeight = 600; + + /// Rendering resolution. + QSize _renderResolution; + + // GL framebuffer into which the each eye's view is rendered. + std::unique_ptr _eyeBuffer; + + /// Used for time measurements. + QTime _time; + + /// For smooth acceleration. + FloatType _currentSpeed = 0; + + /// The settings object. + OORef _settings; +}; + +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/vr/VRSceneRenderer.cpp ovito-2.9.0+dfsg1/src/plugins/vr/VRSceneRenderer.cpp --- ovito-2.8.1+dfsg2/src/plugins/vr/VRSceneRenderer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vr/VRSceneRenderer.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,67 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2013) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "VRSceneRenderer.h" + +namespace VRPlugin { + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(VRSceneRenderer, OpenGLSceneRenderer); + +/****************************************************************************** +* This method is called just before renderFrame() is called. +******************************************************************************/ +void VRSceneRenderer::beginFrame(TimePoint time, const ViewProjectionParameters& params, Viewport* vp) +{ + OpenGLSceneRenderer::beginFrame(time, params, vp); + + // Set viewport background color. + setClearColor(ColorA(renderSettings()->backgroundColor())); +} + +/****************************************************************************** +* Returns the final size of the rendered image in pixels. +******************************************************************************/ +QSize VRSceneRenderer::outputSize() const +{ +#if 0 + return viewport()->windowSize(); +#endif + return OpenGLSceneRenderer::outputSize(); +} + +/****************************************************************************** +* Returns the device pixel ratio of the output device we are rendering to. +******************************************************************************/ +qreal VRSceneRenderer::devicePixelRatio() const +{ +#if 0 + if(viewport()) { + if(QWidget* vpWidget = ViewportsPanel::viewportWidget(viewport())) + return vpWidget->devicePixelRatio(); + } +#endif + return OpenGLSceneRenderer::devicePixelRatio(); +} + +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/vr/VRSceneRenderer.h ovito-2.9.0+dfsg1/src/plugins/vr/VRSceneRenderer.h --- ovito-2.8.1+dfsg2/src/plugins/vr/VRSceneRenderer.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vr/VRSceneRenderer.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include + +namespace VRPlugin { + +using namespace Ovito; + +class VRSceneRenderer : public OpenGLSceneRenderer +{ +public: + + /// Standard constructor. + VRSceneRenderer(DataSet* dataset) : OpenGLSceneRenderer(dataset) {} + + /// This method is called just before renderFrame() is called. + virtual void beginFrame(TimePoint time, const ViewProjectionParameters& params, Viewport* vp) override; + + /// Returns whether this renderer is rendering an interactive viewport. + /// \return true if rendering a real-time viewport; false if rendering an output image. + virtual bool isInteractive() const override { return false; } + + /// Returns the final size of the rendered image in pixels. + virtual QSize outputSize() const override; + + /// Returns the device pixel ratio of the output device we are rendering to. + qreal devicePixelRatio() const; + +private: + + Q_OBJECT + OVITO_OBJECT +}; + +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/vr/VRSettingsObject.cpp ovito-2.9.0+dfsg1/src/plugins/vr/VRSettingsObject.cpp --- ovito-2.8.1+dfsg2/src/plugins/vr/VRSettingsObject.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vr/VRSettingsObject.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,95 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "VRSettingsObject.h" + +namespace VRPlugin { + +IMPLEMENT_SERIALIZABLE_OVITO_OBJECT(VRSettingsObject, RefTarget); +DEFINE_PROPERTY_FIELD(VRSettingsObject, supersamplingEnabled, "SupersamplingEnabled"); +DEFINE_FLAGS_PROPERTY_FIELD(VRSettingsObject, scaleFactor, "ScaleFactor", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(VRSettingsObject, showFloor, "ShowFloor"); +DEFINE_FLAGS_PROPERTY_FIELD(VRSettingsObject, flyingMode, "FlyingMode", PROPERTY_FIELD_MEMORIZE); +DEFINE_PROPERTY_FIELD(VRSettingsObject, viewerTM, "ViewerTM"); +DEFINE_PROPERTY_FIELD(VRSettingsObject, translation, "Translation"); +DEFINE_PROPERTY_FIELD(VRSettingsObject, rotationZ, "RotationZ"); +DEFINE_PROPERTY_FIELD(VRSettingsObject, modelCenter, "ModelCenter"); +DEFINE_PROPERTY_FIELD(VRSettingsObject, movementSpeed, "MovementSpeed"); +SET_PROPERTY_FIELD_LABEL(VRSettingsObject, supersamplingEnabled, "Supersampling"); +SET_PROPERTY_FIELD_LABEL(VRSettingsObject, scaleFactor, "Scale factor"); +SET_PROPERTY_FIELD_LABEL(VRSettingsObject, translation, "Position"); +SET_PROPERTY_FIELD_LABEL(VRSettingsObject, rotationZ, "Rotation angle"); +SET_PROPERTY_FIELD_LABEL(VRSettingsObject, showFloor, "Show floor rectangle"); +SET_PROPERTY_FIELD_LABEL(VRSettingsObject, flyingMode, "Fly mode"); +SET_PROPERTY_FIELD_LABEL(VRSettingsObject, viewerTM, "Viewer transformation"); +SET_PROPERTY_FIELD_LABEL(VRSettingsObject, modelCenter, "Center of rotation"); +SET_PROPERTY_FIELD_LABEL(VRSettingsObject, movementSpeed, "Speed"); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(VRSettingsObject, scaleFactor, PercentParameterUnit, 0); +SET_PROPERTY_FIELD_UNITS(VRSettingsObject, rotationZ, AngleParameterUnit); +SET_PROPERTY_FIELD_UNITS(VRSettingsObject, modelCenter, WorldParameterUnit); +SET_PROPERTY_FIELD_UNITS_AND_MINIMUM(VRSettingsObject, movementSpeed, FloatParameterUnit, 0); + +/****************************************************************************** +* Adjusts the transformation to bring the model into the center of the +* playing area. +******************************************************************************/ +void VRSettingsObject::recenter() +{ + // Reset model position to center of scene bounding box. + const Box3& bbox = dataset()->sceneRoot()->worldBoundingBox(dataset()->animationSettings()->time()); + if(!bbox.isEmpty()) { + setModelCenter(bbox.center() - Point3::Origin()); + } + setRotationZ(0); + if(flyingMode() == false) { + FloatType height = bbox.size(ViewportSettings::getSettings().upDirection()) * scaleFactor() / FloatType(1.9); + setTranslation(Vector3(0, 0, height)); + setViewerTM(AffineTransformation::Identity()); + } + else { + FloatType offset = bbox.size().length() * scaleFactor() / 2; + setTranslation(Vector3(0, 0, 0)); + setViewerTM(AffineTransformation::translation( + (ViewportSettings::getSettings().coordinateSystemOrientation() * + AffineTransformation::rotationX(FLOATTYPE_PI/2)).inverse() * + Vector3(0, -offset, 0))); + } +} + +/****************************************************************************** +* Computes the apparent model size in meters. +******************************************************************************/ +Vector3 VRSettingsObject::apparentModelSize() +{ + const Box3& bbox = dataset()->sceneRoot()->worldBoundingBox(dataset()->animationSettings()->time()); + if(!bbox.isEmpty()) + return bbox.size() * scaleFactor(); + else + return Vector3::Zero(); +} + + +}; diff -Nru ovito-2.8.1+dfsg2/src/plugins/vr/VRSettingsObjectEditor.cpp ovito-2.9.0+dfsg1/src/plugins/vr/VRSettingsObjectEditor.cpp --- ovito-2.8.1+dfsg2/src/plugins/vr/VRSettingsObjectEditor.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vr/VRSettingsObjectEditor.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,155 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "VRSettingsObject.h" +#include "VRSettingsObjectEditor.h" + +namespace VRPlugin { + +IMPLEMENT_OVITO_OBJECT(VRSettingsObjectEditor, PropertiesEditor); +SET_OVITO_OBJECT_EDITOR(VRSettingsObject, VRSettingsObjectEditor); + +/****************************************************************************** +* Creates the UI controls for the editor. +******************************************************************************/ +void VRSettingsObjectEditor::createUI(const RolloutInsertionParameters& rolloutParams) +{ + // Create the rollout. + QWidget* rollout = createRollout(tr("Settings"), rolloutParams); + QVBoxLayout* mainLayout = new QVBoxLayout(rollout); + mainLayout->setContentsMargins(4,4,4,4); + + // Model size group box. + QGroupBox* sizeGroupBox = new QGroupBox(tr("Model size")); + mainLayout->addWidget(sizeGroupBox); + QGridLayout* layout = new QGridLayout(sizeGroupBox); + layout->setContentsMargins(4,4,4,4); + layout->setSpacing(2); + layout->setColumnStretch(0, 1); + int row = 0; + + // Apparent model size. + layout->addWidget(new QLabel(tr("Apparent size:")), row, 0); + QLabel* modelSizeLabel = new QLabel(); + layout->addWidget(modelSizeLabel, row++, 1); + connect(this, &PropertiesEditor::contentsChanged, this, [modelSizeLabel](RefTarget* editObject) { + if(editObject) { + Vector3 modelSize = static_object_cast(editObject)->apparentModelSize(); + modelSizeLabel->setText(tr("%1 x %2 x %3 m").arg(modelSize.x(), 0, 'f', 2).arg(modelSize.y(), 0, 'f', 2).arg(modelSize.z(), 0, 'f', 2)); + } + else modelSizeLabel->setText(QString()); + }); + + // Scale factor + FloatParameterUI* scaleFactorUI = new FloatParameterUI(this, PROPERTY_FIELD(VRSettingsObject::scaleFactor)); + layout->addWidget(scaleFactorUI->label(), row, 0); + layout->addLayout(scaleFactorUI->createFieldLayout(), row++, 1); + + // Model transformation group box. + QGroupBox* transformationGroupBox = new QGroupBox(tr("Model transformation")); + mainLayout->addWidget(transformationGroupBox); + layout = new QGridLayout(transformationGroupBox); + layout->setContentsMargins(4,4,4,4); + layout->setSpacing(2); + layout->setColumnStretch(0, 1); + row = 0; + + // Rotation + FloatParameterUI* rotationUI = new FloatParameterUI(this, PROPERTY_FIELD(VRSettingsObject::rotationZ)); + layout->addWidget(rotationUI->label(), row, 0); + layout->addLayout(rotationUI->createFieldLayout(), row++, 1); + + // Translation + Vector3ParameterUI* translationXUI = new Vector3ParameterUI(this, PROPERTY_FIELD(VRSettingsObject::translation), 0); + layout->addWidget(translationXUI->label(), row, 0); + layout->addLayout(translationXUI->createFieldLayout(), row++, 1); + Vector3ParameterUI* translationYUI = new Vector3ParameterUI(this, PROPERTY_FIELD(VRSettingsObject::translation), 1); + layout->addWidget(translationYUI->label(), row, 0); + layout->addLayout(translationYUI->createFieldLayout(), row++, 1); + Vector3ParameterUI* translationZUI = new Vector3ParameterUI(this, PROPERTY_FIELD(VRSettingsObject::translation), 2); + layout->addWidget(translationZUI->label(), row, 0); + layout->addLayout(translationZUI->createFieldLayout(), row++, 1); + + // Model center + Vector3ParameterUI* modelCenterXUI = new Vector3ParameterUI(this, PROPERTY_FIELD(VRSettingsObject::modelCenter), 0); + layout->addWidget(modelCenterXUI->label(), row, 0); + layout->addLayout(modelCenterXUI->createFieldLayout(), row++, 1); + Vector3ParameterUI* modelCenterYUI = new Vector3ParameterUI(this, PROPERTY_FIELD(VRSettingsObject::modelCenter), 1); + layout->addWidget(modelCenterYUI->label(), row, 0); + layout->addLayout(modelCenterYUI->createFieldLayout(), row++, 1); + Vector3ParameterUI* modelCenterZUI = new Vector3ParameterUI(this, PROPERTY_FIELD(VRSettingsObject::modelCenter), 2); + layout->addWidget(modelCenterZUI->label(), row, 0); + layout->addLayout(modelCenterZUI->createFieldLayout(), row++, 1); + + // Recenter action. + QPushButton* recenterBtn = new QPushButton(tr("Reset"), rollout); + connect(recenterBtn, &QPushButton::clicked, this, [this]() { + VRSettingsObject* settings = static_object_cast(editObject()); + if(settings) settings->recenter(); + }); + layout->addWidget(recenterBtn, row++, 0, 1, 2); + + // Navigation mode group box. + QGroupBox* navigationGroupBox = new QGroupBox(tr("Navigation")); + mainLayout->addWidget(navigationGroupBox); + layout = new QGridLayout(navigationGroupBox); + layout->setContentsMargins(4,4,4,4); + layout->setSpacing(2); + layout->setColumnStretch(0, 1); + row = 0; + + // Speed + FloatParameterUI* speedUI = new FloatParameterUI(this, PROPERTY_FIELD(VRSettingsObject::movementSpeed)); + layout->addWidget(speedUI->label(), row, 0); + layout->addLayout(speedUI->createFieldLayout(), row++, 1); + + // Flying mode + BooleanParameterUI* flyingModeUI = new BooleanParameterUI(this, PROPERTY_FIELD(VRSettingsObject::flyingMode)); + layout->addWidget(flyingModeUI->checkBox(), row++, 0, 1, 2); + + // Show floor + BooleanParameterUI* showFloorUI = new BooleanParameterUI(this, PROPERTY_FIELD(VRSettingsObject::showFloor)); + layout->addWidget(showFloorUI->checkBox(), row++, 0, 1, 2); + + // Performance group box. + QGroupBox* performanceGroupBox = new QGroupBox(tr("Performance")); + mainLayout->addWidget(performanceGroupBox); + layout = new QGridLayout(performanceGroupBox); + layout->setContentsMargins(4,4,4,4); + layout->setSpacing(2); + layout->setColumnStretch(0, 1); + row = 0; + + // Supersampling + BooleanParameterUI* supersamplingEnabledUI = new BooleanParameterUI(this, PROPERTY_FIELD(VRSettingsObject::supersamplingEnabled)); + layout->addWidget(supersamplingEnabledUI->checkBox(), row++, 0, 1, 2); + + // Disable viewport rendering. + QCheckBox* disableViewportsBox = new QCheckBox(tr("Disable main viewports")); + connect(disableViewportsBox, &QCheckBox::toggled, this, &VRSettingsObjectEditor::disableViewportRendering); + layout->addWidget(disableViewportsBox, row++, 0, 1, 2); +} + +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/vr/VRSettingsObjectEditor.h ovito-2.9.0+dfsg1/src/plugins/vr/VRSettingsObjectEditor.h --- ovito-2.8.1+dfsg2/src/plugins/vr/VRSettingsObjectEditor.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vr/VRSettingsObjectEditor.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,63 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include +#include + +namespace VRPlugin { + +using namespace Ovito; +/* + * \brief The UI component for the VRSettingsObject class. + */ +class VRSettingsObjectEditor : public PropertiesEditor +{ +public: + + /// Default constructor. + Q_INVOKABLE VRSettingsObjectEditor() {} + +protected: + + /// Creates the user interface controls for the editor. + virtual void createUI(const RolloutInsertionParameters& rolloutParams) override; + +private Q_SLOTS: + + /// Disables rendering of the normal viewports. + void disableViewportRendering(bool disable) { + _viewportSuspender.reset(disable ? new ViewportSuspender(dataset()) : nullptr); + } + +private: + + /// Used to disable viewport rendering. + std::unique_ptr _viewportSuspender; + + Q_OBJECT + OVITO_OBJECT +}; + +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/vr/VRSettingsObject.h ovito-2.9.0+dfsg1/src/plugins/vr/VRSettingsObject.h --- ovito-2.8.1+dfsg2/src/plugins/vr/VRSettingsObject.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vr/VRSettingsObject.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,97 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include + +namespace VRPlugin { + +using namespace Ovito; + +/** + * \brief An object that stores the current VR settings. + */ +class VRSettingsObject : public RefTarget +{ +public: + + /// \brief Default constructor. + Q_INVOKABLE VRSettingsObject(DataSet* dataset) : RefTarget(dataset), + _supersamplingEnabled(true), _scaleFactor(1e-1), _showFloor(false), _flyingMode(false), + _translation(Vector3::Zero()), + _rotationZ(0), + _modelCenter(Vector3::Zero()), + _viewerTM(AffineTransformation::Identity()), + _movementSpeed(4) { + INIT_PROPERTY_FIELD(supersamplingEnabled); + INIT_PROPERTY_FIELD(scaleFactor); + INIT_PROPERTY_FIELD(translation); + INIT_PROPERTY_FIELD(rotationZ); + INIT_PROPERTY_FIELD(modelCenter); + INIT_PROPERTY_FIELD(showFloor); + INIT_PROPERTY_FIELD(flyingMode); + INIT_PROPERTY_FIELD(viewerTM); + INIT_PROPERTY_FIELD(movementSpeed); + } + + /// Adjusts the transformation to bring the model into the center of the playing area. + void recenter(); + + /// Computes the apparent model size in meters. + Vector3 apparentModelSize(); + +private: + + /// Enables supersampling. + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, supersamplingEnabled, setSupersamplingEnabled); + + /// The scaling applied to the model. + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, scaleFactor, setScaleFactor); + + /// The translation applied to the model. + DECLARE_MODIFIABLE_PROPERTY_FIELD(Vector3, translation, setTranslation); + + /// The rotation angle around vertical axis applied to the model. + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, rotationZ, setRotationZ); + + /// The center point of the model, around which it is being rotated. + DECLARE_MODIFIABLE_PROPERTY_FIELD(Vector3, modelCenter, setModelCenter); + + /// Enables the display of the floor rectangle. + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, showFloor, setShowFloor); + + /// Activates the flying mode. + DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, flyingMode, setFlyingMode); + + /// Current flying position. + DECLARE_MODIFIABLE_PROPERTY_FIELD(AffineTransformation, viewerTM, setViewerTM); + + /// The speed of motion when navigating. + DECLARE_MODIFIABLE_PROPERTY_FIELD(FloatType, movementSpeed, setMovementSpeed); + + Q_OBJECT + OVITO_OBJECT +}; + +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/src/plugins/vr/VRWindow.cpp ovito-2.9.0+dfsg1/src/plugins/vr/VRWindow.cpp --- ovito-2.8.1+dfsg2/src/plugins/vr/VRWindow.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vr/VRWindow.cpp 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,67 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "VRWindow.h" + +namespace VRPlugin { + +/****************************************************************************** +* Constructor. +******************************************************************************/ +VRWindow::VRWindow(QWidget* parentWidget, GuiDataSetContainer* datasetContainer) : QMainWindow(parentWidget) +{ + // Use a default window size. + resize(800, 600); + + // Set title. + setWindowTitle(tr("Ovito - Virtual Reality Module")); + + // Create the widget for rendering. + _glWidget = new VRRenderingWidget(this, datasetContainer->currentSet()); + setCentralWidget(_glWidget); + + // Create settings panel. + PropertiesPanel* propPanel = new PropertiesPanel(this, datasetContainer->mainWindow()); + propPanel->setEditObject(_glWidget->settings()); + QDockWidget* dockWidget = new QDockWidget(tr("Settings"), this); + dockWidget->setObjectName("SettingsPanel"); + dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + dockWidget->setFeatures(QDockWidget::DockWidgetClosable); + dockWidget->setWidget(propPanel); + dockWidget->setTitleBarWidget(new QWidget()); + addDockWidget(Qt::LeftDockWidgetArea, dockWidget); + + // Close the VR window immediately when OVITO is closed or if another DataSet is loaded. + connect(datasetContainer, &DataSetContainer::dataSetChanged, this, [this] { + delete this; + }); + + // Delete window when it is being closed by the user. + setAttribute(Qt::WA_DeleteOnClose); +} + +}; + diff -Nru ovito-2.8.1+dfsg2/src/plugins/vr/VRWindow.h ovito-2.9.0+dfsg1/src/plugins/vr/VRWindow.h --- ovito-2.8.1+dfsg2/src/plugins/vr/VRWindow.h 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/src/plugins/vr/VRWindow.h 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,51 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (2017) Alexander Stukowski +// +// This file is part of OVITO (Open Visualization Tool). +// +// OVITO is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// OVITO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + + +#include +#include +#include "VRRenderingWidget.h" + +namespace VRPlugin { + +using namespace Ovito; + +/** + * \brief A window that renders the scene for VR visualization. + */ +class VRWindow : public QMainWindow +{ + Q_OBJECT + +public: + + /// Constructor. + VRWindow(QWidget* parentWidget, GuiDataSetContainer* datasetContainer); + +private: + + /// The OpenGL widget used for rendering. + VRRenderingWidget* _glWidget; +}; + +} // End of namespace diff -Nru ovito-2.8.1+dfsg2/tests/files/CASTEP/quartz_alpha.castep ovito-2.9.0+dfsg1/tests/files/CASTEP/quartz_alpha.castep --- ovito-2.8.1+dfsg2/tests/files/CASTEP/quartz_alpha.castep 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/files/CASTEP/quartz_alpha.castep 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,4533 @@ + +-------------------------------------------------+ + | | + | CCC AA SSS TTTTT EEEEE PPPP | + | C A A S T E P P | + | C AAAA SS T EEE PPPP | + | C A A S T E P | + | CCC A A SSS T EEEEE P | + | | + +-------------------------------------------------+ + | | + | Welcome to Academic Release CASTEP version 17.2 | + | Ab Initio Total Energy Program | + | | + | Authors: | + | M. Segall, M. Probert, C. Pickard, P. Hasnip, | + | S. Clark, K. Refson, J. R. Yates, M. Payne | + | | + | Contributors: | + | P. Lindan, P. Haynes, J. White, V. Milman, | + | N. Govind, M. Gibson, P. Tulip, V. Cocula, | + | B. Montanari, D. Quigley, M. Glover, | + | L. Bernasconi, A. Perlov, M. Plummer, | + | E. McNellis, J. Meyer, J. Gale, D. Jochym | + | J. Aarons, B. Walker, R. Gillen, D. Jones | + | T. Green, I. J. Bush, C. J. Armstrong, | + | E. J. Higgins, E. L. Brown, M. S. McFly, | + | J. Wilkins, B-C. Shih | + | | + | Copyright (c) 2000 - 2016 | + | | + | Distributed under the terms of an | + | Agreement between the United Kingdom | + | Car-Parrinello (UKCP) Consortium, | + | Daresbury Laboratory and Accelrys, Inc. | + | | + | Please cite | + | | + | "First principles methods using CASTEP" | + | | + | Zeitschrift fuer Kristallographie | + | 220(5-6) pp. 567-570 (2005) | + | | + | S. J. Clark, M. D. Segall, C. J. Pickard, | + | P. J. Hasnip, M. J. Probert, K. Refson, | + | M. C. Payne | + | | + | in all publications arising from | + | your use of CASTEP | + | | + +-------------------------------------------------+ + + + Compiled for linux_x86_64_gfortran4.9 on Thu, 13 Apr 2017 17:36:26 +0100 + from code version dcaebbd29535+ Fri, 28 Oct 2016 15:46:39 +0100 + Compiler: GNU Fortran 4.9.2; Optimisation: fast + MATHLIBS: default (LAPACK version 3.5.0) + FFT Lib : default + Fundamental constants values: CODATA 2010 + + Run started: Thu, 20 Apr 2017 14:24:03 +0100 + + Pseudo atomic calculation performed for O 2s2 2p4 + + Converged in 25 iterations to a total energy of -429.5309 eV + + + Pseudo atomic calculation performed for Si 3s2 3p2 + + Converged in 16 iterations to a total energy of -101.9015 eV + + Calculation not parallelised. + + ************************************ Title ************************************ + + + ***************************** General Parameters ****************************** + + output verbosity : normal (1) + write checkpoint data to : quartz_alpha.check + type of calculation : geometry optimization + stress calculation : on + density difference calculation : off + electron localisation func (ELF) calculation : off + Hirshfeld analysis : off + unlimited duration calculation + timing information : on + memory usage estimate : on + write final potential to formatted file : off + write final density to formatted file : off + write BibTeX reference list : on + write OTFG pseudopotential files : on + write electrostatic potential file : on + write bands file : on + checkpoint writing : both castep_bin and check files + + output length unit : A + output mass unit : amu + output time unit : ps + output charge unit : e + output spin unit : hbar/2 + output energy unit : eV + output force unit : eV/A + output velocity unit : A/ps + output pressure unit : GPa + output inv_length unit : 1/A + output frequency unit : cm-1 + output force constant unit : eV/A**2 + output volume unit : A**3 + output IR intensity unit : (D/A)**2/amu + output dipole unit : D + output efield unit : eV/A/e + output entropy unit : J/mol/K + + wavefunctions paging : none + random number generator seed : randomised (142403362) + data distribution : optimal for this architecture + optimization strategy : maximize speed(+++) + + *********************** Exchange-Correlation Parameters *********************** + + using functional : Perdew Burke Ernzerhof + relativistic treatment : Koelling-Harmon + DFT+D: Semi-empirical dispersion correction : off + + ************************* Pseudopotential Parameters ************************** + + pseudopotential representation : reciprocal space + representation : reciprocal space + spin-orbit coupling : off + + **************************** Basis Set Parameters ***************************** + + basis set accuracy : FINE + plane wave basis set cut-off : 340.0000 eV + size of standard grid : 2.0000 + size of fine gmax : 18.8933 1/A + largest prime factor in FFT : 5 + finite basis set correction : automatic + number of sample energies : 3 + sample spacing : 5.0000 eV + + **************************** Electronic Parameters **************************** + + number of electrons : 48.00 + net charge of system : 0.000 + treating system as non-spin-polarized + number of bands : 29 + + ********************* Electronic Minimization Parameters ********************** + + Method: Treating system as metallic with density mixing treatment of electrons, + and number of SD steps : 1 + and number of CG steps : 4 + + total energy / atom convergence tol. : 0.1000E-05 eV + eigen-energy convergence tolerance : 0.3103E-06 eV + max force / atom convergence tol. : ignored + convergence tolerance window : 3 cycles + max. number of SCF cycles : 100 + number of fixed-spin iterations : 10 + smearing scheme : Gaussian + smearing width : 0.1000 eV + Fermi energy convergence tolerance : 0.2721E-13 eV + periodic dipole correction : NONE + + ************************** Density Mixing Parameters ************************** + + density-mixing scheme : Pulay + max. length of mixing history : 20 + charge density mixing amplitude : 0.5000 + charge density mixing g-vector : 1.500 1/A + + ********************** Geometry Optimization Parameters *********************** + + optimization method : BFGS + variable cell method : fixed basis quality + max. number of steps : 100 + estimated bulk modulus : 500.0 GPa + estimated : 1668. cm-1 + geom line minimiser : on + with line minimiser tolerance : 0.4000 + total energy convergence tolerance : 0.1000E-04 eV/atom + max ionic |force| tolerance : 0.3000E-01 eV/A + max ionic |displacement| tolerance : 0.1000E-02 A + max |stress component| tolerance : 0.5000E-01 GPa + convergence tolerance window : 2 steps + backup results every : 5 steps + write geom trajectory file : on + + ******************************************************************************* + + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.2521812 -2.4549980 0.0000000 1.4776382 0.0000000 0.0000000 + 0.0000000 4.9099959 0.0000000 0.7388191 1.2796722 0.0000000 + 0.0000000 0.0000000 5.4020000 0.0000000 0.0000000 1.1631220 + + Lattice parameters(A) Cell Angles + a = 4.909996 alpha = 90.000000 + b = 4.909996 beta = 90.000000 + c = 5.402000 gamma = 120.000000 + + Current cell volume = 112.783994 A**3 + density = 1.598213 AMU/A**3 + = 2.653896 g/cm^3 + + ------------------------------- + Cell Contents + ------------------------------- + Total number of ions in cell = 9 + Total number of species in cell = 2 + Max number of any one species = 6 + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x----------------------------------------------------------x + x O 1 0.150179 0.414589 0.116499 x + x O 2 -0.414589 -0.264410 0.783166 x + x O 3 0.264410 -0.150179 0.449833 x + x O 4 0.414589 0.150179 -0.116499 x + x O 5 -0.264410 -0.414589 0.216834 x + x O 6 -0.150179 0.264410 0.550167 x + x Si 1 0.480781 0.480781 0.000000 x + x Si 2 -0.480781 -0.000000 0.666667 x + x Si 3 0.000000 -0.480781 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + + No user defined ionic velocities + + ------------------------------- + Details of Species + ------------------------------- + + Mass of species in AMU + O 15.9989996 + Si 28.0849991 + + Electric Quadrupole Moment (Barn) + O -0.0255800 Isotope 17 + Si 1.0000000 No Isotope Defined + + Files used for pseudopotentials: + O O_00PBE.usp + Si Si_00PBE.usp + + ------------------------------- + k-Points For BZ Sampling + ------------------------------- + MP grid size for SCF calculation is 6 6 6 + with an offset of 0.083 0.083 0.000 + Number of kpoints used = 30 + + ------------------------------- + Symmetry and Constraints + ------------------------------- + + Maximum deviation from symmetry = 0.376003E-14 ANG + + Number of symmetry operations = 6 + There are no ionic constraints specified or generated for this cell + Point group of crystal = 19: D3, 32, 3 2 + Space group of crystal = 154: P3_221, P 32 2" + + Set iprint > 1 for details on symmetry rotations/translations + + Centre of mass is NOT constrained + + Number of cell constraints= 4 + Cell constraints are: 1 1 3 0 0 0 + + External pressure/stress (GPa) + 0.00000 0.00000 0.00000 + 0.00000 0.00000 + 0.00000 + ++---------------- MEMORY AND SCRATCH DISK ESTIMATES PER PROCESS --------------+ +| Memory Disk | +| Baseline code, static data and system overhead 42.0 MB 0.0 MB | +| BLAS internal memory storage 0.0 MB 0.0 MB | +| Model and support data 60.9 MB 0.0 MB | +| Electronic energy minimisation requirements 49.5 MB 0.0 MB | +| Force calculation requirements 3.7 MB 0.0 MB | +| Stress calculation requirements 4.7 MB 0.0 MB | +| ----------------------------- | +| Approx. total storage required per process 152.4 MB 0.0 MB | +| | +| Requirements will fluctuate during execution and may exceed these estimates | ++-----------------------------------------------------------------------------+ +Calculating finite basis set correction with 3 cut-off energies. +Calculating total energy with cut-off of 330.000 eV. +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.28192807E+003 0.00000000E+000 1.60 <-- SCF + 1 -2.83492571E+003 6.93479141E+000 3.14991745E+002 9.39 <-- SCF + 2 -2.96245604E+003 -1.16870354E+000 1.41700363E+001 14.08 <-- SCF + 3 -2.96431080E+003 -9.10930714E-001 2.06085194E-001 18.69 <-- SCF + 4 -2.95490662E+003 2.12338179E+000 -1.04490910E+000 24.80 <-- SCF + 5 -2.95504332E+003 2.08116622E+000 1.51892957E-002 31.21 <-- SCF + 6 -2.95510494E+003 2.32518740E+000 6.84608428E-003 37.89 <-- SCF + 7 -2.95511371E+003 2.32661252E+000 9.74664000E-004 44.24 <-- SCF + 8 -2.95511548E+003 2.34369940E+000 1.96640058E-004 50.84 <-- SCF + 9 -2.95511568E+003 2.34407303E+000 2.19948473E-005 55.52 <-- SCF + 10 -2.95511569E+003 2.34490692E+000 1.43112390E-006 59.85 <-- SCF + 11 -2.95511569E+003 2.34517476E+000 1.97723353E-007 64.05 <-- SCF + 12 -2.95511569E+003 2.34468946E+000 2.90716257E-008 68.60 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.115693930 eV +Final free energy (E-TS) = -2955.115693930 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.115693930 eV + +Calculating total energy with cut-off of 335.000 eV. +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95512354E+003 0.00000000E+000 70.08 <-- SCF + 1 -2.95520033E+003 2.34121098E+000 9.40409937E-003 75.90 <-- SCF + 2 -2.95520040E+003 2.34120954E+000 7.64787700E-006 83.05 <-- SCF + 3 -2.95520032E+003 2.34614126E+000 -8.89622609E-006 90.09 <-- SCF + 4 -2.95520041E+003 2.34422033E+000 1.04334341E-005 94.10 <-- SCF + 5 -2.95520041E+003 2.34451897E+000 2.47763668E-008 98.05 <-- SCF + 6 -2.95520041E+003 2.34483303E+000 2.22025543E-008 101.21 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.200413913 eV +Final free energy (E-TS) = -2955.200413913 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.200413913 eV + +Calculating total energy with cut-off of 340.000 eV. +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95520830E+003 0.00000000E+000 102.19 <-- SCF + 1 -2.95527259E+003 2.34189956E+000 8.02008067E-003 106.41 <-- SCF + 2 -2.95527265E+003 2.34189824E+000 6.59467001E-006 111.51 <-- SCF + 3 -2.95527258E+003 2.34650517E+000 -8.37066850E-006 116.53 <-- SCF + 4 -2.95527266E+003 2.34470479E+000 9.23676886E-006 121.33 <-- SCF + 5 -2.95527266E+003 2.34503570E+000 -8.92174521E-009 126.15 <-- SCF + 6 -2.95527266E+003 2.34532320E+000 4.02662902E-008 130.79 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.272662068 eV +Final free energy (E-TS) = -2955.272662068 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.272662068 eV + + For future reference: finite basis dEtot/dlog(Ecut) = -5.188226eV + Total energy corrected for finite basis set = -2955.271518 eV + ++---------------- MEMORY AND SCRATCH DISK ESTIMATES PER PROCESS --------------+ +| Memory Disk | +| Model and support data 71.1 MB 0.0 MB | +| Electronic energy minimisation requirements 49.5 MB 0.0 MB | +| Geometry minimisation requirements 72.5 MB 0.0 MB | +| ----------------------------- | +| Approx. total storage required per process 193.2 MB 0.0 MB | +| | +| Requirements will fluctuate during execution and may exceed these estimates | ++-----------------------------------------------------------------------------+ + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 -0.00577 -0.14789 -0.01184 * + * O 2 0.13097 0.06895 -0.01184 * + * O 3 -0.12519 0.07895 -0.01184 * + * O 4 -0.13097 0.06895 0.01184 * + * O 5 0.12519 0.07895 0.01184 * + * O 6 0.00577 -0.14789 0.01184 * + * Si 1 -0.70685 -0.40810 0.00000 * + * Si 2 0.70685 -0.40810 0.00000 * + * Si 3 0.00000 0.81620 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -5.825075 0.000000 0.000000 * + * y 0.000000 -5.825075 -0.000000 * + * z 0.000000 -0.000000 -6.303052 * + * * + * Pressure: 5.9844 * + * * + ************************************************* + BFGS: finished iteration 0 with enthalpy= -2.95527152E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 0.000000E+000 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 8.162030E-001 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 0.000000E+000 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 6.303052E+000 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 1 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.314508 | -2955.271518 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 1 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + ++---------------- MEMORY AND SCRATCH DISK ESTIMATES PER PROCESS --------------+ +| Memory Disk | +| Model and support data 71.8 MB 0.0 MB | +| Electronic energy minimisation requirements 50.5 MB 0.0 MB | +| Geometry minimisation requirements 74.0 MB 0.0 MB | +| ----------------------------- | +| Approx. total storage required per process 196.3 MB 0.0 MB | +| | +| Requirements will fluctuate during execution and may exceed these estimates | ++-----------------------------------------------------------------------------+ + + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.2686940 -2.4645316 0.0000000 1.4719222 0.0000000 -0.0000000 + -0.0000000 4.9290633 -0.0000000 0.7359611 1.2747220 0.0000000 + 0.0000000 -0.0000000 5.4246994 -0.0000000 0.0000000 1.1582550 + + Lattice parameters(A) Cell Angles + a = 4.929063 alpha = 90.000000 + b = 4.929063 beta = 90.000000 + c = 5.424699 gamma = 120.000000 + + Current cell volume = 114.139272 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.150173 0.414439 0.116489 x + x O 2 -0.414439 -0.264266 0.783155 x + x O 3 0.264266 -0.150173 0.449822 x + x O 4 0.414439 0.150173 -0.116489 x + x O 5 -0.264266 -0.414439 0.216845 x + x O 6 -0.150173 0.264266 0.550178 x + x Si 1 0.479969 0.479969 0.000000 x + x Si 2 -0.479969 0.000000 0.666667 x + x Si 3 0.000000 -0.479969 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95520064E+003 0.00000000E+000 136.41 <-- SCF + 1 -2.95541320E+003 1.96923581E+000 1.57423589E-002 143.32 <-- SCF + 2 -2.95541421E+003 1.96922658E+000 1.12113169E-004 148.95 <-- SCF + 3 -2.95531278E+003 2.26662185E+000 -1.12699585E-002 154.08 <-- SCF + 4 -2.95531364E+003 2.24409306E+000 9.58366849E-005 159.24 <-- SCF + 5 -2.95531349E+003 2.24484146E+000 -1.71302945E-005 164.51 <-- SCF + 6 -2.95531351E+003 2.24600755E+000 2.92771453E-006 168.23 <-- SCF + 7 -2.95531354E+003 2.24649740E+000 2.71831812E-006 171.65 <-- SCF + 8 -2.95531354E+003 2.24649591E+000 8.23850611E-007 174.90 <-- SCF + 9 -2.95531355E+003 2.24658378E+000 7.66132340E-008 178.10 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.313545454 eV +Final free energy (E-TS) = -2955.313545454 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.313545454 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.00910 -0.03896 0.12690 * + * O 2 0.02919 0.02736 0.12690 * + * O 3 -0.03829 0.01160 0.12690 * + * O 4 -0.02919 0.02736 -0.12690 * + * O 5 0.03829 0.01160 -0.12690 * + * O 6 -0.00910 -0.03896 -0.12690 * + * Si 1 -0.55120 -0.31823 0.00000 * + * Si 2 0.55120 -0.31823 0.00000 * + * Si 3 0.00000 0.63647 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -3.608277 0.000000 -0.000000 * + * y 0.000000 -3.608277 0.000000 * + * z -0.000000 0.000000 -3.486442 * + * * + * Pressure: 3.5677 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.314508 | -2955.271518 | <-- min BFGS + | trial step | 1.000000 | 0.196479 | -2955.314134 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: improving iteration 1 with line minimization (lambda= 2.664669) +-------------------------------------------------------------------------------- + ++---------------- MEMORY AND SCRATCH DISK ESTIMATES PER PROCESS --------------+ +| Memory Disk | +| Model and support data 71.9 MB 0.0 MB | +| Electronic energy minimisation requirements 50.7 MB 0.0 MB | +| Geometry minimisation requirements 74.2 MB 0.0 MB | +| ----------------------------- | +| Approx. total storage required per process 196.8 MB 0.0 MB | +| | +| Requirements will fluctuate during execution and may exceed these estimates | ++-----------------------------------------------------------------------------+ + + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.2961825 -2.4804021 0.0000000 1.4625043 0.0000000 -0.0000000 + -0.0000000 4.9608042 -0.0000000 0.7312521 1.2665659 0.0000000 + 0.0000000 -0.0000000 5.4624864 -0.0000000 0.0000000 1.1502427 + + Lattice parameters(A) Cell Angles + a = 4.960804 alpha = 90.000000 + b = 4.960804 beta = 90.000000 + c = 5.462486 gamma = 120.000000 + + Current cell volume = 116.419350 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.150162 0.414188 0.116471 x + x O 2 -0.414188 -0.264027 0.783138 x + x O 3 0.264027 -0.150162 0.449804 x + x O 4 0.414188 0.150162 -0.116471 x + x O 5 -0.264027 -0.414188 0.216862 x + x O 6 -0.150162 0.264027 0.550196 x + x Si 1 0.478619 0.478619 0.000000 x + x Si 2 -0.478619 0.000000 0.666667 x + x Si 3 0.000000 -0.478619 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95504511E+003 0.00000000E+000 182.01 <-- SCF + 1 -2.95561049E+003 1.62295998E+000 3.29286667E-002 186.59 <-- SCF + 2 -2.95561323E+003 1.62293073E+000 3.04194054E-004 192.91 <-- SCF + 3 -2.95533352E+003 2.11996172E+000 -3.10782881E-002 198.03 <-- SCF + 4 -2.95533566E+003 2.07969185E+000 2.37786410E-004 203.17 <-- SCF + 5 -2.95533518E+003 2.08129537E+000 -5.41404973E-005 209.67 <-- SCF + 6 -2.95533524E+003 2.08331813E+000 6.72473659E-006 215.08 <-- SCF + 7 -2.95533529E+003 2.08413785E+000 6.20297263E-006 220.41 <-- SCF + 8 -2.95533531E+003 2.08413230E+000 1.71437939E-006 225.18 <-- SCF + 9 -2.95533531E+003 2.08430510E+000 2.49493407E-007 229.84 <-- SCF + 10 -2.95533531E+003 2.08430987E+000 1.05351699E-007 234.50 <-- SCF + 11 -2.95533531E+003 2.08430519E+000 2.11116390E-008 239.18 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.335312857 eV +Final free energy (E-TS) = -2955.335312857 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.335312857 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.04104 0.12895 0.33687 * + * O 2 -0.13219 -0.02893 0.33687 * + * O 3 0.09115 -0.10001 0.33687 * + * O 4 0.13219 -0.02893 -0.33687 * + * O 5 -0.09115 -0.10001 -0.33687 * + * O 6 -0.04104 0.12895 -0.33687 * + * Si 1 -0.31331 -0.18089 0.00000 * + * Si 2 0.31331 -0.18089 -0.00000 * + * Si 3 0.00000 0.36178 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -0.200281 0.000000 0.000000 * + * y 0.000000 -0.200281 -0.000000 * + * z 0.000000 -0.000000 0.861334 * + * * + * Pressure: -0.1536 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.314508 | -2955.271518 | <-- min BFGS + | trial step | 1.000000 | 0.196479 | -2955.314134 | <-- min BFGS + | line step | 2.664669 | 0.011349 | -2955.334965 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 1 with enthalpy= -2.95533496E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 7.049681E-003 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 3.630303E-001 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 1.072614E-002 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 8.613342E-001 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 2 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.144172 | -2955.334965 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 2 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.2996301 -2.4823926 0.0000000 1.4613316 0.0000000 -0.0000000 + -0.0000000 4.9647852 -0.0000000 0.7306658 1.2655503 0.0000000 + 0.0000000 -0.0000000 5.4631135 -0.0000000 0.0000000 1.1501107 + + Lattice parameters(A) Cell Angles + a = 4.964785 alpha = 90.000000 + b = 4.964785 beta = 90.000000 + c = 5.463113 gamma = 120.000000 + + Current cell volume = 116.619665 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.150210 0.414321 0.116788 x + x O 2 -0.414321 -0.264112 0.783455 x + x O 3 0.264112 -0.150210 0.450122 x + x O 4 0.414321 0.150210 -0.116788 x + x O 5 -0.264112 -0.414321 0.216545 x + x O 6 -0.150210 0.264112 0.549878 x + x Si 1 0.478102 0.478102 0.000000 x + x Si 2 -0.478102 0.000000 0.666667 x + x Si 3 0.000000 -0.478102 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95533353E+003 0.00000000E+000 244.49 <-- SCF + 1 -2.95534617E+003 2.02707252E+000 1.24534775E-003 249.84 <-- SCF + 2 -2.95534626E+003 2.02706943E+000 9.15152627E-006 255.19 <-- SCF + 3 -2.95534165E+003 2.06704966E+000 -5.11756920E-004 260.21 <-- SCF + 4 -2.95534121E+003 2.06591137E+000 -4.91318749E-005 265.36 <-- SCF + 5 -2.95534112E+003 2.06852105E+000 -9.26195693E-006 271.64 <-- SCF + 6 -2.95534113E+003 2.06922515E+000 1.22431089E-006 276.37 <-- SCF + 7 -2.95534114E+003 2.06949719E+000 5.67795342E-007 281.07 <-- SCF + 8 -2.95534114E+003 2.06957644E+000 2.39720842E-007 285.39 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.341142110 eV +Final free energy (E-TS) = -2955.341142110 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.341142110 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.05244 0.12399 0.32514 * + * O 2 -0.13360 -0.01658 0.32514 * + * O 3 0.08116 -0.10741 0.32514 * + * O 4 0.13360 -0.01658 -0.32514 * + * O 5 -0.08116 -0.10741 -0.32514 * + * O 6 -0.05244 0.12399 -0.32514 * + * Si 1 -0.28688 -0.16563 0.00000 * + * Si 2 0.28688 -0.16563 0.00000 * + * Si 3 0.00000 0.33126 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 0.029012 0.000000 -0.000000 * + * y 0.000000 0.029012 -0.000000 * + * z -0.000000 -0.000000 0.992790 * + * * + * Pressure: -0.3503 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.144172 | -2955.334965 | <-- min BFGS + | trial step | 1.000000 | 0.130953 | -2955.340489 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: improving iteration 2 with line minimization (lambda= 10.906353) +-------------------------------------------------------------------------------- + ++---------------- MEMORY AND SCRATCH DISK ESTIMATES PER PROCESS --------------+ +| Memory Disk | +| Model and support data 75.8 MB 0.0 MB | +| Electronic energy minimisation requirements 52.0 MB 0.0 MB | +| Geometry minimisation requirements 76.1 MB 0.0 MB | +| ----------------------------- | +| Approx. total storage required per process 203.8 MB 0.0 MB | +| | +| Requirements will fluctuate during execution and may exceed these estimates | ++-----------------------------------------------------------------------------+ + + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3337841 -2.5021114 0.0000000 1.4498150 0.0000000 -0.0000000 + -0.0000000 5.0042228 -0.0000000 0.7249075 1.2555766 0.0000000 + 0.0000000 -0.0000000 5.4693259 -0.0000000 0.0000000 1.1488043 + + Lattice parameters(A) Cell Angles + a = 5.004223 alpha = 90.000000 + b = 5.004223 beta = 90.000000 + c = 5.469326 gamma = 120.000000 + + Current cell volume = 118.614483 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.150688 0.415640 0.119934 x + x O 2 -0.415640 -0.264953 0.786600 x + x O 3 0.264953 -0.150688 0.453267 x + x O 4 0.415640 0.150688 -0.119934 x + x O 5 -0.264953 -0.415640 0.213400 x + x O 6 -0.150688 0.264953 0.546733 x + x Si 1 0.472982 0.472982 0.000000 x + x Si 2 -0.472982 0.000000 0.666667 x + x Si 3 0.000000 -0.472982 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95406523E+003 0.00000000E+000 291.26 <-- SCF + 1 -2.95586754E+003 1.48649087E+000 5.85613974E-002 296.73 <-- SCF + 2 -2.95587540E+003 1.48631226E+000 8.72577719E-004 303.88 <-- SCF + 3 -2.95541076E+003 1.91081430E+000 -5.16263004E-002 310.05 <-- SCF + 4 -2.95536474E+003 1.89550949E+000 -5.11337385E-003 316.22 <-- SCF + 5 -2.95535532E+003 1.92176329E+000 -1.04601980E-003 322.13 <-- SCF + 6 -2.95535545E+003 1.92802418E+000 1.39213812E-005 328.09 <-- SCF + 7 -2.95535551E+003 1.93263290E+000 6.98009821E-006 333.03 <-- SCF + 8 -2.95535553E+003 1.93200561E+000 1.91429918E-006 337.10 <-- SCF + 9 -2.95535553E+003 1.93176710E+000 2.26568503E-007 340.88 <-- SCF + 10 -2.95535553E+003 1.93197570E+000 -4.53073158E-008 344.63 <-- SCF + 11 -2.95535553E+003 1.93203081E+000 7.41195107E-009 348.31 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.355530891 eV +Final free energy (E-TS) = -2955.355530891 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.355530891 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.16177 0.07401 0.20512 * + * O 2 -0.14498 0.10310 0.20512 * + * O 3 -0.01679 -0.17710 0.20512 * + * O 4 0.14498 0.10310 -0.20512 * + * O 5 0.01679 -0.17710 -0.20512 * + * O 6 -0.16177 0.07401 -0.20512 * + * Si 1 0.01502 0.00867 0.00000 * + * Si 2 -0.01502 0.00867 0.00000 * + * Si 3 -0.00000 -0.01735 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 2.411348 -0.000000 -0.000000 * + * y -0.000000 2.411348 0.000000 * + * z -0.000000 0.000000 2.319757 * + * * + * Pressure: -2.3808 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.144172 | -2955.334965 | <-- min BFGS + | trial step | 1.000000 | 0.130953 | -2955.340489 | <-- min BFGS + | line step | 10.906353 | -0.012288 | -2955.354347 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 2 with enthalpy= -2.95535435E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 2.153581E-003 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 2.715153E-001 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 2.820743E-002 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 2.411348E+000 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 3 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.142947 | -2955.354347 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 3 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3248962 -2.4969800 0.0000000 1.4527945 0.0000000 -0.0000000 + -0.0000000 4.9939599 -0.0000000 0.7263972 1.2581569 0.0000000 + 0.0000000 -0.0000000 5.4514530 -0.0000000 0.0000000 1.1525708 + + Lattice parameters(A) Cell Angles + a = 4.993960 alpha = 90.000000 + b = 4.993960 beta = 90.000000 + c = 5.451453 gamma = 120.000000 + + Current cell volume = 117.742434 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.150943 0.416082 0.120621 x + x O 2 -0.416082 -0.265140 0.787287 x + x O 3 0.265140 -0.150943 0.453954 x + x O 4 0.416082 0.150943 -0.120621 x + x O 5 -0.265140 -0.416082 0.212713 x + x O 6 -0.150943 0.265140 0.546046 x + x Si 1 0.472558 0.472558 0.000000 x + x Si 2 -0.472558 0.000000 0.666667 x + x Si 3 0.000000 -0.472558 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95528358E+003 0.00000000E+000 352.76 <-- SCF + 1 -2.95542933E+003 2.14682687E+000 8.33099398E-003 357.83 <-- SCF + 2 -2.95542998E+003 2.14681748E+000 7.29915589E-005 363.82 <-- SCF + 3 -2.95537368E+003 1.96477530E+000 -6.25596912E-003 370.00 <-- SCF + 4 -2.95537112E+003 1.98645889E+000 -2.84131124E-004 376.32 <-- SCF + 5 -2.95537047E+003 1.98980124E+000 -7.25963893E-005 384.56 <-- SCF + 6 -2.95537047E+003 1.99081686E+000 2.96958235E-007 389.05 <-- SCF + 7 -2.95537047E+003 1.99088393E+000 -9.16159190E-008 392.92 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.370470365 eV +Final free energy (E-TS) = -2955.370470365 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.370470365 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.14010 -0.00418 0.10198 * + * O 2 -0.06643 0.12342 0.10198 * + * O 3 -0.07367 -0.11924 0.10198 * + * O 4 0.06643 0.12342 -0.10198 * + * O 5 0.07367 -0.11924 -0.10198 * + * O 6 -0.14010 -0.00418 -0.10198 * + * Si 1 -0.01314 -0.00759 0.00000 * + * Si 2 0.01314 -0.00759 0.00000 * + * Si 3 0.00000 0.01518 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 1.069579 -0.000000 0.000000 * + * y -0.000000 1.069579 0.000000 * + * z 0.000000 0.000000 0.508370 * + * * + * Pressure: -0.8825 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.142947 | -2955.354347 | <-- min BFGS + | trial step | 1.000000 | 0.057498 | -2955.372321 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: improving iteration 3 with line minimization (lambda= 1.672899) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3189155 -2.4935270 0.0000000 1.4548063 0.0000000 -0.0000000 + -0.0000000 4.9870540 -0.0000000 0.7274031 1.2598992 0.0000000 + 0.0000000 -0.0000000 5.4394263 -0.0000000 0.0000000 1.1551191 + + Lattice parameters(A) Cell Angles + a = 4.987054 alpha = 90.000000 + b = 4.987054 beta = 90.000000 + c = 5.439426 gamma = 120.000000 + + Current cell volume = 117.157979 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.151114 0.416380 0.121083 x + x O 2 -0.416380 -0.265265 0.787750 x + x O 3 0.265265 -0.151114 0.454416 x + x O 4 0.416380 0.151114 -0.121083 x + x O 5 -0.265265 -0.416380 0.212250 x + x O 6 -0.151114 0.265265 0.545584 x + x Si 1 0.472273 0.472273 0.000000 x + x Si 2 -0.472273 0.000000 0.666667 x + x Si 3 0.000000 -0.472273 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95535349E+003 0.00000000E+000 397.13 <-- SCF + 1 -2.95541070E+003 2.13514836E+000 4.26408150E-003 402.44 <-- SCF + 2 -2.95541099E+003 2.13514354E+000 3.28177189E-005 409.29 <-- SCF + 3 -2.95538540E+003 2.01209041E+000 -2.84329348E-003 415.80 <-- SCF + 4 -2.95538411E+003 2.02641621E+000 -1.43383852E-004 422.64 <-- SCF + 5 -2.95538377E+003 2.02869650E+000 -3.75921827E-005 430.16 <-- SCF + 6 -2.95538376E+003 2.02938512E+000 -1.80179183E-006 435.52 <-- SCF + 7 -2.95538375E+003 2.02939039E+000 -5.73888914E-007 440.21 <-- SCF + 8 -2.95538375E+003 2.02940721E+000 -3.11452370E-007 444.82 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.383750202 eV +Final free energy (E-TS) = -2955.383750202 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.383750202 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.12356 -0.06224 0.02580 * + * O 2 -0.00788 0.13813 0.02580 * + * O 3 -0.11568 -0.07589 0.02580 * + * O 4 0.00788 0.13813 -0.02580 * + * O 5 0.11568 -0.07589 -0.02580 * + * O 6 -0.12356 -0.06224 -0.02580 * + * Si 1 -0.10983 -0.06341 0.00000 * + * Si 2 0.10983 -0.06341 0.00000 * + * Si 3 0.00000 0.12682 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -0.044747 0.000000 0.000000 * + * y 0.000000 -0.044747 -0.000000 * + * z 0.000000 -0.000000 -0.745573 * + * * + * Pressure: 0.2784 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.142947 | -2955.354347 | <-- min BFGS + | trial step | 1.000000 | 0.057498 | -2955.372321 | <-- min BFGS + | line step | 1.672899 | -0.002329 | -2955.386565 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 3 with enthalpy= -2.95538656E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 3.579778E-003 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 1.407356E-001 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 7.025866E-003 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 7.455727E-001 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 4 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.037847 | -2955.386565 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 4 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3231517 -2.4959728 0.0000000 1.4533807 0.0000000 -0.0000000 + -0.0000000 4.9919456 -0.0000000 0.7266904 1.2586646 0.0000000 + 0.0000000 -0.0000000 5.4394696 -0.0000000 0.0000000 1.1551099 + + Lattice parameters(A) Cell Angles + a = 4.991946 alpha = 90.000000 + b = 4.991946 beta = 90.000000 + c = 5.439470 gamma = 120.000000 + + Current cell volume = 117.388860 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.151421 0.416733 0.121838 x + x O 2 -0.416733 -0.265312 0.788505 x + x O 3 0.265312 -0.151421 0.455171 x + x O 4 0.416733 0.151421 -0.121838 x + x O 5 -0.265312 -0.416733 0.211495 x + x O 6 -0.151421 0.265312 0.544829 x + x Si 1 0.471104 0.471104 0.000000 x + x Si 2 -0.471104 0.000000 0.666667 x + x Si 3 0.000000 -0.471104 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95530634E+003 0.00000000E+000 450.14 <-- SCF + 1 -2.95539635E+003 1.96292942E+000 1.08697944E-003 455.03 <-- SCF + 2 -2.95539668E+003 1.96292147E+000 3.68593264E-005 461.33 <-- SCF + 3 -2.95537879E+003 2.00573182E+000 -1.98785621E-003 469.02 <-- SCF + 4 -2.95537576E+003 2.00942703E+000 -3.36368227E-004 477.87 <-- SCF + 5 -2.95537567E+003 2.01378651E+000 -9.95348897E-006 486.47 <-- SCF + 6 -2.95537568E+003 2.01551729E+000 1.28412377E-006 492.68 <-- SCF + 7 -2.95537569E+003 2.01591637E+000 8.93322324E-007 498.89 <-- SCF + 8 -2.95537569E+003 2.01607396E+000 2.09739319E-007 504.45 <-- SCF + 9 -2.95537569E+003 2.01606813E+000 -1.07759575E-009 509.85 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.375693345 eV +Final free energy (E-TS) = -2955.375693345 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.375693345 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.10854 -0.06789 0.01020 * + * O 2 0.00452 0.12794 0.01020 * + * O 3 -0.11306 -0.06005 0.01020 * + * O 4 -0.00452 0.12794 -0.01020 * + * O 5 0.11306 -0.06005 -0.01020 * + * O 6 -0.10854 -0.06789 -0.01020 * + * Si 1 0.04426 0.02555 -0.00000 * + * Si 2 -0.04426 0.02555 -0.00000 * + * Si 3 -0.00000 -0.05111 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 0.197734 -0.000000 0.000000 * + * y -0.000000 0.197734 -0.000000 * + * z 0.000000 -0.000000 -0.672323 * + * * + * Pressure: 0.0923 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.037847 | -2955.386565 | <-- min BFGS + | trial step | 1.000000 | -0.005013 | -2955.377031 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 4 with enthalpy= -2.95537703E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 1.059270E-003 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 1.284279E-001 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 5.836208E-003 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 6.723232E-001 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 5 ... +================================================================================ + +Writing analysis data to quartz_alpha.castep_bin + +Writing model to quartz_alpha.check + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.040740 | -2955.377031 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 5 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3224290 -2.4955555 0.0000000 1.4536237 0.0000000 -0.0000000 + -0.0000000 4.9911111 -0.0000000 0.7268119 1.2588751 0.0000000 + 0.0000000 -0.0000000 5.4434462 -0.0000000 0.0000000 1.1542661 + + Lattice parameters(A) Cell Angles + a = 4.991111 alpha = 90.000000 + b = 4.991111 beta = 90.000000 + c = 5.443446 gamma = 120.000000 + + Current cell volume = 117.435401 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.151545 0.416672 0.121734 x + x O 2 -0.416672 -0.265126 0.788401 x + x O 3 0.265126 -0.151545 0.455067 x + x O 4 0.416672 0.151545 -0.121734 x + x O 5 -0.265126 -0.416672 0.211599 x + x O 6 -0.151545 0.265126 0.544933 x + x Si 1 0.471262 0.471262 0.000000 x + x Si 2 -0.471262 0.000000 0.666667 x + x Si 3 0.000000 -0.471262 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95537462E+003 0.00000000E+000 516.67 <-- SCF + 1 -2.95537765E+003 2.00269991E+000 6.90666565E-005 523.59 <-- SCF + 2 -2.95537768E+003 2.00269890E+000 3.37610680E-006 529.38 <-- SCF + 3 -2.95537643E+003 2.01358751E+000 -1.39756015E-004 535.21 <-- SCF + 4 -2.95537622E+003 2.01187689E+000 -2.29498931E-005 541.11 <-- SCF + 5 -2.95537621E+003 2.01225874E+000 -1.02667540E-006 544.94 <-- SCF + 6 -2.95537621E+003 2.01215474E+000 2.75554467E-007 548.57 <-- SCF + 7 -2.95537621E+003 2.01217743E+000 1.47310347E-007 552.20 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.376213691 eV +Final free energy (E-TS) = -2955.376213691 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.376213691 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.08508 -0.04498 0.04283 * + * O 2 -0.00359 0.09617 0.04283 * + * O 3 -0.08149 -0.05119 0.04283 * + * O 4 0.00359 0.09617 -0.04283 * + * O 5 0.08149 -0.05119 -0.04283 * + * O 6 -0.08508 -0.04498 -0.04283 * + * Si 1 0.06961 0.04019 -0.00000 * + * Si 2 -0.06961 0.04019 0.00000 * + * Si 3 -0.00000 -0.08037 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 0.214353 -0.000000 0.000000 * + * y -0.000000 0.214353 0.000000 * + * z 0.000000 0.000000 -0.453395 * + * * + * Pressure: 0.0082 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.040740 | -2955.377031 | <-- min BFGS + | trial step | 1.000000 | 0.029026 | -2955.377775 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: improving iteration 5 with line minimization (lambda= 3.477927) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3206381 -2.4945216 0.0000000 1.4542262 0.0000000 -0.0000000 + -0.0000000 4.9890431 -0.0000000 0.7271131 1.2593969 0.0000000 + 0.0000000 -0.0000000 5.4532997 -0.0000000 0.0000000 1.1521805 + + Lattice parameters(A) Cell Angles + a = 4.989043 alpha = 90.000000 + b = 4.989043 beta = 90.000000 + c = 5.453300 gamma = 120.000000 + + Current cell volume = 117.550509 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.151855 0.416520 0.121477 x + x O 2 -0.416520 -0.264666 0.788143 x + x O 3 0.264666 -0.151855 0.454810 x + x O 4 0.416520 0.151855 -0.121477 x + x O 5 -0.264666 -0.416520 0.211857 x + x O 6 -0.151855 0.264666 0.545190 x + x Si 1 0.471654 0.471654 0.000000 x + x Si 2 -0.471654 0.000000 0.666667 x + x Si 3 0.000000 -0.471654 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95535173E+003 0.00000000E+000 556.44 <-- SCF + 1 -2.95538433E+003 1.97893655E+000 7.28437225E-004 561.38 <-- SCF + 2 -2.95538451E+003 1.97893003E+000 2.00362221E-005 567.66 <-- SCF + 3 -2.95537678E+003 2.00613644E+000 -8.58696572E-004 573.57 <-- SCF + 4 -2.95537552E+003 2.00178692E+000 -1.40736444E-004 579.54 <-- SCF + 5 -2.95537546E+003 2.00276740E+000 -5.68912312E-006 585.26 <-- SCF + 6 -2.95537547E+003 2.00233167E+000 6.62559576E-007 589.57 <-- SCF + 7 -2.95537547E+003 2.00264083E+000 4.04506544E-007 593.95 <-- SCF + 8 -2.95537548E+003 2.00253691E+000 1.10468818E-007 599.37 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.375475417 eV +Final free energy (E-TS) = -2955.375475417 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.375475417 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.02964 0.00985 0.12069 * + * O 2 -0.02334 0.02074 0.12069 * + * O 3 -0.00629 -0.03059 0.12069 * + * O 4 0.02334 0.02074 -0.12069 * + * O 5 0.00629 -0.03059 -0.12069 * + * O 6 -0.02964 0.00985 -0.12069 * + * Si 1 0.13127 0.07579 -0.00000 * + * Si 2 -0.13127 0.07579 0.00000 * + * Si 3 -0.00000 -0.15158 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 0.232650 0.000000 -0.000000 * + * y 0.000000 0.232650 -0.000000 * + * z -0.000000 -0.000000 0.124596 * + * * + * Pressure: -0.1966 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.040740 | -2955.377031 | <-- min BFGS + | trial step | 1.000000 | 0.029026 | -2955.377775 | <-- min BFGS + | line step | 3.477927 | -0.000067 | -2955.378460 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 5 with enthalpy= -2.95537846E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 1.587576E-004 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 1.515755E-001 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 3.463016E-003 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 2.326500E-001 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 6 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.041800 | -2955.378460 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 6 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3181964 -2.4931118 0.0000000 1.4550485 0.0000000 -0.0000000 + -0.0000000 4.9862237 -0.0000000 0.7275243 1.2601090 0.0000000 + 0.0000000 -0.0000000 5.4551026 -0.0000000 0.0000000 1.1517997 + + Lattice parameters(A) Cell Angles + a = 4.986224 alpha = 90.000000 + b = 4.986224 beta = 90.000000 + c = 5.455103 gamma = 120.000000 + + Current cell volume = 117.456505 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.152137 0.416591 0.121676 x + x O 2 -0.416591 -0.264454 0.788343 x + x O 3 0.264454 -0.152137 0.455010 x + x O 4 0.416591 0.152137 -0.121676 x + x O 5 -0.264454 -0.416591 0.211657 x + x O 6 -0.152137 0.264454 0.544990 x + x Si 1 0.471781 0.471781 0.000000 x + x Si 2 -0.471781 0.000000 0.666667 x + x Si 3 0.000000 -0.471781 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95538684E+003 0.00000000E+000 604.85 <-- SCF + 1 -2.95539085E+003 2.02221084E+000 1.37624097E-003 609.92 <-- SCF + 2 -2.95539090E+003 2.02220915E+000 6.35574155E-006 615.11 <-- SCF + 3 -2.95538781E+003 2.00046999E+000 -3.43619240E-004 620.04 <-- SCF + 4 -2.95538732E+003 2.00540909E+000 -5.41577732E-005 625.12 <-- SCF + 5 -2.95538726E+003 2.00600151E+000 -7.17525948E-006 629.85 <-- SCF + 6 -2.95538726E+003 2.00662270E+000 -4.51481427E-007 632.99 <-- SCF + 7 -2.95538726E+003 2.00662474E+000 1.44351513E-007 636.03 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.387256348 eV +Final free energy (E-TS) = -2955.387256348 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.387256348 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.01045 0.00994 0.12117 * + * O 2 -0.01383 0.00408 0.12117 * + * O 3 0.00338 -0.01402 0.12117 * + * O 4 0.01383 0.00408 -0.12117 * + * O 5 -0.00338 -0.01402 -0.12117 * + * O 6 -0.01045 0.00994 -0.12117 * + * Si 1 0.06650 0.03839 0.00000 * + * Si 2 -0.06650 0.03839 -0.00000 * + * Si 3 -0.00000 -0.07679 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -0.228095 0.000000 0.000000 * + * y 0.000000 -0.228095 -0.000000 * + * z 0.000000 -0.000000 -0.093861 * + * * + * Pressure: 0.1834 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.041800 | -2955.378460 | <-- min BFGS + | trial step | 1.000000 | 0.024080 | -2955.389540 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: improving iteration 6 with line minimization (lambda= 2.358938) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3148783 -2.4911961 0.0000000 1.4561675 0.0000000 -0.0000000 + -0.0000000 4.9823922 -0.0000000 0.7280837 1.2610780 0.0000000 + 0.0000000 -0.0000000 5.4575527 -0.0000000 0.0000000 1.1512826 + + Lattice parameters(A) Cell Angles + a = 4.982392 alpha = 90.000000 + b = 4.982392 beta = 90.000000 + c = 5.457553 gamma = 120.000000 + + Current cell volume = 117.328738 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.152521 0.416687 0.121948 x + x O 2 -0.416687 -0.264166 0.788614 x + x O 3 0.264166 -0.152521 0.455281 x + x O 4 0.416687 0.152521 -0.121948 x + x O 5 -0.264166 -0.416687 0.211386 x + x O 6 -0.152521 0.264166 0.544719 x + x Si 1 0.471954 0.471954 0.000000 x + x Si 2 -0.471954 0.000000 0.666667 x + x Si 3 0.000000 -0.471954 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95537942E+003 0.00000000E+000 639.85 <-- SCF + 1 -2.95539579E+003 2.03577957E+000 6.94830524E-004 643.96 <-- SCF + 2 -2.95539590E+003 2.03577767E+000 1.14504630E-005 649.13 <-- SCF + 3 -2.95539031E+003 2.00629513E+000 -6.20864442E-004 654.09 <-- SCF + 4 -2.95538947E+003 2.01295711E+000 -9.31012606E-005 659.21 <-- SCF + 5 -2.95538938E+003 2.01372512E+000 -1.01670253E-005 664.09 <-- SCF + 6 -2.95538938E+003 2.01466425E+000 2.78544667E-007 668.42 <-- SCF + 7 -2.95538938E+003 2.01454445E+000 3.65744677E-007 673.27 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.389384858 eV +Final free energy (E-TS) = -2955.389384858 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.389384858 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 -0.01559 0.00698 0.12072 * + * O 2 0.00175 -0.01700 0.12072 * + * O 3 0.01384 0.01001 0.12072 * + * O 4 -0.00175 -0.01700 -0.12072 * + * O 5 -0.01384 0.01001 -0.12072 * + * O 6 0.01559 0.00698 -0.12072 * + * Si 1 0.07814 0.04512 0.00000 * + * Si 2 -0.07814 0.04512 0.00000 * + * Si 3 -0.00000 -0.09023 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -0.629802 0.000000 0.000000 * + * y 0.000000 -0.629802 0.000000 * + * z 0.000000 0.000000 -0.345627 * + * * + * Pressure: 0.5351 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.041800 | -2955.378460 | <-- min BFGS + | trial step | 1.000000 | 0.024080 | -2955.389540 | <-- min BFGS + | line step | 2.358938 | 0.011463 | -2955.390891 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: improving iteration 6 with quad minimization (lambda= 3.593562) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3118637 -2.4894556 0.0000000 1.4571855 0.0000000 -0.0000000 + -0.0000000 4.9789113 -0.0000000 0.7285928 1.2619597 0.0000000 + 0.0000000 -0.0000000 5.4597787 -0.0000000 0.0000000 1.1508132 + + Lattice parameters(A) Cell Angles + a = 4.978911 alpha = 90.000000 + b = 4.978911 beta = 90.000000 + c = 5.459779 gamma = 120.000000 + + Current cell volume = 117.212640 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.152869 0.416774 0.122194 x + x O 2 -0.416774 -0.263904 0.788861 x + x O 3 0.263904 -0.152869 0.455528 x + x O 4 0.416774 0.152869 -0.122194 x + x O 5 -0.263904 -0.416774 0.211139 x + x O 6 -0.152869 0.263904 0.544472 x + x Si 1 0.472110 0.472110 0.000000 x + x Si 2 -0.472110 0.000000 0.666667 x + x Si 3 0.000000 -0.472110 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95538387E+003 0.00000000E+000 678.40 <-- SCF + 1 -2.95539529E+003 2.04143820E+000 4.88656121E-004 682.54 <-- SCF + 2 -2.95539537E+003 2.04143657E+000 9.33630592E-006 688.24 <-- SCF + 3 -2.95539077E+003 2.01456434E+000 -5.11045039E-004 695.98 <-- SCF + 4 -2.95539008E+003 2.02050951E+000 -7.69958754E-005 703.19 <-- SCF + 5 -2.95539001E+003 2.02125444E+000 -8.39482117E-006 710.31 <-- SCF + 6 -2.95539001E+003 2.02207009E+000 2.12436573E-007 715.01 <-- SCF + 7 -2.95539001E+003 2.02195892E+000 3.05918735E-007 719.55 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.390009690 eV +Final free energy (E-TS) = -2955.390009690 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.390009690 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 -0.03956 0.00426 0.11972 * + * O 2 0.01609 -0.03639 0.11972 * + * O 3 0.02347 0.03213 0.11972 * + * O 4 -0.01609 -0.03639 -0.11972 * + * O 5 -0.02347 0.03213 -0.11972 * + * O 6 0.03956 0.00426 -0.11972 * + * Si 1 0.08887 0.05131 0.00000 * + * Si 2 -0.08887 0.05131 0.00000 * + * Si 3 -0.00000 -0.10262 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -0.983212 0.000000 0.000000 * + * y 0.000000 -0.983212 0.000000 * + * z 0.000000 0.000000 -0.554767 * + * * + * Pressure: 0.8404 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.041800 | -2955.378460 | <-- min BFGS + | trial step | 1.000000 | 0.024080 | -2955.389540 | <-- min BFGS + | line step | 2.358938 | 0.011463 | -2955.390891 | <-- min BFGS + | quad step | 3.593562 | -0.000019 | -2955.391777 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 6 with enthalpy= -2.95539178E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 1.479667E-003 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 1.261584E-001 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 6.008435E-003 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 9.832118E-001 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 7 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.040510 | -2955.391777 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 7 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3129954 -2.4901090 0.0000000 1.4568032 0.0000000 -0.0000000 + -0.0000000 4.9802181 -0.0000000 0.7284016 1.2616285 0.0000000 + 0.0000000 -0.0000000 5.4673826 -0.0000000 0.0000000 1.1492127 + + Lattice parameters(A) Cell Angles + a = 4.980218 alpha = 90.000000 + b = 4.980218 beta = 90.000000 + c = 5.467383 gamma = 120.000000 + + Current cell volume = 117.437507 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.153607 0.417108 0.123218 x + x O 2 -0.417108 -0.263501 0.789885 x + x O 3 0.263501 -0.153607 0.456552 x + x O 4 0.417108 0.153607 -0.123218 x + x O 5 -0.263501 -0.417108 0.210115 x + x O 6 -0.153607 0.263501 0.543448 x + x Si 1 0.471857 0.471857 0.000000 x + x Si 2 -0.471857 0.000000 0.666667 x + x Si 3 0.000000 -0.471857 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95524563E+003 0.00000000E+000 724.85 <-- SCF + 1 -2.95544010E+003 1.95195272E+000 5.36965932E-003 731.32 <-- SCF + 2 -2.95544076E+003 1.95193736E+000 7.27744216E-005 738.68 <-- SCF + 3 -2.95540106E+003 1.99136864E+000 -4.41084123E-003 745.88 <-- SCF + 4 -2.95539351E+003 1.99953183E+000 -8.38939987E-004 752.20 <-- SCF + 5 -2.95539349E+003 2.00396208E+000 -2.69523523E-006 757.98 <-- SCF + 6 -2.95539352E+003 2.00617934E+000 3.27975892E-006 763.04 <-- SCF + 7 -2.95539353E+003 2.00648729E+000 2.00526678E-006 766.97 <-- SCF + 8 -2.95539354E+003 2.00675995E+000 3.23639815E-007 770.45 <-- SCF + 9 -2.95539354E+003 2.00675569E+000 4.84252110E-009 773.56 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.393537449 eV +Final free energy (E-TS) = -2955.393537449 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.393537449 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 -0.03475 -0.01702 0.08532 * + * O 2 0.03211 -0.02158 0.08532 * + * O 3 0.00264 0.03860 0.08532 * + * O 4 -0.03211 -0.02158 -0.08532 * + * O 5 -0.00264 0.03860 -0.08532 * + * O 6 0.03475 -0.01702 -0.08532 * + * Si 1 0.10726 0.06193 0.00000 * + * Si 2 -0.10726 0.06193 0.00000 * + * Si 3 -0.00000 -0.12386 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -1.045217 0.000000 0.000000 * + * y 0.000000 -1.045217 -0.000000 * + * z 0.000000 -0.000000 -0.632610 * + * * + * Pressure: 0.9077 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.040510 | -2955.391777 | <-- min BFGS + | trial step | 1.000000 | 0.029744 | -2955.393756 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: improving iteration 7 with line minimization (lambda= 3.762959) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3161223 -2.4919144 0.0000000 1.4557478 0.0000000 -0.0000000 + -0.0000000 4.9838287 -0.0000000 0.7278739 1.2607145 0.0000000 + 0.0000000 -0.0000000 5.4883920 -0.0000000 0.0000000 1.1448135 + + Lattice parameters(A) Cell Angles + a = 4.983829 alpha = 90.000000 + b = 4.983829 beta = 90.000000 + c = 5.488392 gamma = 120.000000 + + Current cell volume = 118.059780 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.155646 0.418031 0.126047 x + x O 2 -0.418031 -0.262385 0.792714 x + x O 3 0.262385 -0.155646 0.459381 x + x O 4 0.418031 0.155646 -0.126047 x + x O 5 -0.262385 -0.418031 0.207286 x + x O 6 -0.155646 0.262385 0.540619 x + x Si 1 0.471156 0.471156 0.000000 x + x Si 2 -0.471156 0.000000 0.666667 x + x Si 3 0.000000 -0.471156 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95422422E+003 0.00000000E+000 777.54 <-- SCF + 1 -2.95575353E+003 1.80484818E+000 3.99748466E-002 781.75 <-- SCF + 2 -2.95575873E+003 1.80478756E+000 5.78310143E-004 787.02 <-- SCF + 3 -2.95545027E+003 1.92860241E+000 -3.42743364E-002 791.97 <-- SCF + 4 -2.95539284E+003 1.94508672E+000 -6.38050646E-003 797.09 <-- SCF + 5 -2.95539227E+003 1.95856689E+000 -6.30493628E-005 802.40 <-- SCF + 6 -2.95539246E+003 1.96471755E+000 2.07249367E-005 807.39 <-- SCF + 7 -2.95539254E+003 1.96694064E+000 9.41436313E-006 811.13 <-- SCF + 8 -2.95539255E+003 1.96676422E+000 9.28239391E-007 814.48 <-- SCF + 9 -2.95539255E+003 1.96663755E+000 5.54381767E-008 817.74 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.392553721 eV +Final free energy (E-TS) = -2955.392553721 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.392553721 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 -0.01566 -0.07712 -0.00919 * + * O 2 0.07462 0.02500 -0.00919 * + * O 3 -0.05896 0.05212 -0.00919 * + * O 4 -0.07462 0.02500 0.00919 * + * O 5 0.05896 0.05212 0.00919 * + * O 6 0.01566 -0.07712 0.00919 * + * Si 1 0.15576 0.08993 -0.00000 * + * Si 2 -0.15576 0.08993 0.00000 * + * Si 3 -0.00000 -0.17985 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -1.162788 0.000000 0.000000 * + * y 0.000000 -1.162788 -0.000000 * + * z 0.000000 -0.000000 -0.738218 * + * * + * Pressure: 1.0213 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.040510 | -2955.391777 | <-- min BFGS + | trial step | 1.000000 | 0.029744 | -2955.393756 | <-- min BFGS + | line step | 3.762959 | -0.000084 | -2955.394986 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 7 with enthalpy= -2.95539499E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 3.565046E-004 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 1.798516E-001 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 2.431630E-002 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 1.162788E+000 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 8 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.040344 | -2955.394986 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 8 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + ++---------------- MEMORY AND SCRATCH DISK ESTIMATES PER PROCESS --------------+ +| Memory Disk | +| Model and support data 75.8 MB 0.0 MB | +| Electronic energy minimisation requirements 52.0 MB 0.0 MB | +| Geometry minimisation requirements 76.1 MB 0.0 MB | +| ----------------------------- | +| Approx. total storage required per process 203.9 MB 0.0 MB | +| | +| Requirements will fluctuate during execution and may exceed these estimates | ++-----------------------------------------------------------------------------+ + + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3203958 -2.4943817 0.0000000 1.4543078 0.0000000 -0.0000000 + -0.0000000 4.9887633 -0.0000000 0.7271539 1.2594675 0.0000000 + 0.0000000 -0.0000000 5.5108089 -0.0000000 0.0000000 1.1401566 + + Lattice parameters(A) Cell Angles + a = 4.988763 alpha = 90.000000 + b = 4.988763 beta = 90.000000 + c = 5.510809 gamma = 120.000000 + + Current cell volume = 118.776845 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.156592 0.418061 0.126818 x + x O 2 -0.418061 -0.261468 0.793485 x + x O 3 0.261468 -0.156592 0.460152 x + x O 4 0.418061 0.156592 -0.126818 x + x O 5 -0.261468 -0.418061 0.206515 x + x O 6 -0.156592 0.261468 0.539848 x + x Si 1 0.471844 0.471844 0.000000 x + x Si 2 -0.471844 0.000000 0.666667 x + x Si 3 -0.000000 -0.471844 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95519652E+003 0.00000000E+000 822.48 <-- SCF + 1 -2.95544743E+003 1.77147980E+000 5.82707838E-003 828.65 <-- SCF + 2 -2.95544831E+003 1.77146501E+000 9.76718751E-005 835.70 <-- SCF + 3 -2.95539041E+003 1.91611370E+000 -6.43351153E-003 844.09 <-- SCF + 4 -2.95538480E+003 1.90903616E+000 -6.22537464E-004 852.93 <-- SCF + 5 -2.95538369E+003 1.91633788E+000 -1.24030301E-004 859.67 <-- SCF + 6 -2.95538372E+003 1.91836415E+000 4.08521761E-006 865.01 <-- SCF + 7 -2.95538374E+003 1.91905814E+000 1.72255593E-006 870.33 <-- SCF + 8 -2.95538375E+003 1.91935519E+000 6.34820122E-007 876.16 <-- SCF + 9 -2.95538375E+003 1.91924816E+000 6.11385207E-009 882.24 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.383745930 eV +Final free energy (E-TS) = -2955.383745930 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.383745930 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.00875 -0.06033 0.01157 * + * O 2 0.04788 0.03774 0.01157 * + * O 3 -0.05662 0.02259 0.01157 * + * O 4 -0.04788 0.03774 -0.01157 * + * O 5 0.05662 0.02259 -0.01157 * + * O 6 -0.00875 -0.06033 -0.01157 * + * Si 1 0.22123 0.12773 0.00000 * + * Si 2 -0.22123 0.12773 0.00000 * + * Si 3 -0.00000 -0.25546 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -0.310952 0.000000 0.000000 * + * y 0.000000 -0.310952 0.000000 * + * z 0.000000 0.000000 0.228640 * + * * + * Pressure: 0.1311 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.040344 | -2955.394986 | <-- min BFGS + | trial step | 1.000000 | 0.024227 | -2955.386478 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: improving iteration 8 with line minimization (lambda= 2.503266) +-------------------------------------------------------------------------------- + ++---------------- MEMORY AND SCRATCH DISK ESTIMATES PER PROCESS --------------+ +| Memory Disk | +| Model and support data 75.9 MB 0.0 MB | +| Electronic energy minimisation requirements 52.2 MB 0.0 MB | +| Geometry minimisation requirements 76.3 MB 0.0 MB | +| ----------------------------- | +| Approx. total storage required per process 204.4 MB 0.0 MB | +| | +| Requirements will fluctuate during execution and may exceed these estimates | ++-----------------------------------------------------------------------------+ + + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3268200 -2.4980907 0.0000000 1.4521485 0.0000000 -0.0000000 + -0.0000000 4.9961814 -0.0000000 0.7260743 1.2575975 0.0000000 + 0.0000000 -0.0000000 5.5445075 -0.0000000 0.0000000 1.1332270 + + Lattice parameters(A) Cell Angles + a = 4.996181 alpha = 90.000000 + b = 4.996181 beta = 90.000000 + c = 5.544507 gamma = 120.000000 + + Current cell volume = 119.858819 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.158014 0.418105 0.127977 x + x O 2 -0.418105 -0.260090 0.794644 x + x O 3 0.260090 -0.158014 0.461310 x + x O 4 0.418105 0.158014 -0.127977 x + x O 5 -0.260090 -0.418105 0.205356 x + x O 6 -0.158014 0.260090 0.538690 x + x Si 1 0.472879 0.472879 0.000000 x + x Si 2 -0.472879 0.000000 0.666667 x + x Si 3 -0.000000 -0.472879 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95496332E+003 0.00000000E+000 888.32 <-- SCF + 1 -2.95552819E+003 1.62566816E+000 1.57453944E-002 896.94 <-- SCF + 2 -2.95553021E+003 1.62561506E+000 2.24992509E-004 907.78 <-- SCF + 3 -2.95539748E+003 1.84447458E+000 -1.47484003E-002 915.32 <-- SCF + 4 -2.95538476E+003 1.83268579E+000 -1.41301024E-003 923.36 <-- SCF + 5 -2.95538221E+003 1.84345409E+000 -2.82760635E-004 932.86 <-- SCF + 6 -2.95538229E+003 1.84649487E+000 7.87708398E-006 943.94 <-- SCF + 7 -2.95538231E+003 1.84792531E+000 3.16914943E-006 952.46 <-- SCF + 8 -2.95538232E+003 1.84798497E+000 1.01736906E-006 960.11 <-- SCF + 9 -2.95538232E+003 1.84785394E+000 7.25459975E-008 967.23 <-- SCF + 10 -2.95538232E+003 1.84789266E+000 -2.89034554E-010 973.09 <-- SCF + 11 -2.95538232E+003 1.84790656E+000 6.91715072E-009 978.14 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.382323622 eV +Final free energy (E-TS) = -2955.382323622 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.382323622 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.04905 -0.03192 0.04032 * + * O 2 0.00312 0.05844 0.04032 * + * O 3 -0.05217 -0.02652 0.04032 * + * O 4 -0.00312 0.05844 -0.04032 * + * O 5 0.05217 -0.02652 -0.04032 * + * O 6 -0.04905 -0.03192 -0.04032 * + * Si 1 0.21265 0.12278 -0.00000 * + * Si 2 -0.21265 0.12278 0.00000 * + * Si 3 -0.00000 -0.24555 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 0.644249 -0.000000 -0.000000 * + * y -0.000000 0.644249 0.000000 * + * z -0.000000 0.000000 1.648983 * + * * + * Pressure: -0.9792 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.040344 | -2955.394986 | <-- min BFGS + | trial step | 1.000000 | 0.024227 | -2955.386478 | <-- min BFGS + | line step | 2.503266 | -0.004856 | -2955.383141 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 8 with enthalpy= -2.95538314E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 1.316098E-003 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 2.455524E-001 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 1.581928E-002 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 1.648983E+000 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 9 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.046797 | -2955.383141 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 9 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + ++---------------- MEMORY AND SCRATCH DISK ESTIMATES PER PROCESS --------------+ +| Memory Disk | +| Model and support data 76.0 MB 0.0 MB | +| Electronic energy minimisation requirements 52.4 MB 0.0 MB | +| Geometry minimisation requirements 76.6 MB 0.0 MB | +| ----------------------------- | +| Approx. total storage required per process 205.0 MB 0.0 MB | +| | +| Requirements will fluctuate during execution and may exceed these estimates | ++-----------------------------------------------------------------------------+ + + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3227565 -2.4957446 0.0000000 1.4535136 0.0000000 -0.0000000 + -0.0000000 4.9914892 -0.0000000 0.7267568 1.2587797 0.0000000 + 0.0000000 -0.0000000 5.5549810 -0.0000000 0.0000000 1.1310903 + + Lattice parameters(A) Cell Angles + a = 4.991489 alpha = 90.000000 + b = 4.991489 beta = 90.000000 + c = 5.554981 gamma = 120.000000 + + Current cell volume = 119.859783 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.158849 0.418018 0.128345 x + x O 2 -0.418018 -0.259169 0.795011 x + x O 3 0.259169 -0.158849 0.461678 x + x O 4 0.418018 0.158849 -0.128345 x + x O 5 -0.259169 -0.418018 0.204989 x + x O 6 -0.158849 0.259169 0.538322 x + x Si 1 0.474275 0.474275 0.000000 x + x Si 2 -0.474275 0.000000 0.666667 x + x Si 3 -0.000000 -0.474275 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95529859E+003 0.00000000E+000 985.11 <-- SCF + 1 -2.95540822E+003 1.84317251E+000 2.78605182E-003 991.70 <-- SCF + 2 -2.95540867E+003 1.84315535E+000 5.00558984E-005 1001.06 <-- SCF + 3 -2.95538979E+003 1.84017787E+000 -2.09761946E-003 1007.80 <-- SCF + 4 -2.95538624E+003 1.84547129E+000 -3.93843152E-004 1015.68 <-- SCF + 5 -2.95538625E+003 1.84600874E+000 2.66201641E-007 1021.13 <-- SCF + 6 -2.95538625E+003 1.84676934E+000 5.42367133E-007 1026.74 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.386250058 eV +Final free energy (E-TS) = -2955.386250058 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.386250058 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.05484 -0.04380 0.04186 * + * O 2 0.01052 0.06939 0.04186 * + * O 3 -0.06535 -0.02559 0.04186 * + * O 4 -0.01052 0.06939 -0.04186 * + * O 5 0.06535 -0.02559 -0.04186 * + * O 6 -0.05484 -0.04380 -0.04186 * + * Si 1 0.14021 0.08095 -0.00000 * + * Si 2 -0.14021 0.08095 0.00000 * + * Si 3 -0.00000 -0.16190 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 0.379926 -0.000000 0.000000 * + * y -0.000000 0.379926 0.000000 * + * z 0.000000 0.000000 1.589273 * + * * + * Pressure: -0.7830 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.046797 | -2955.383141 | <-- min BFGS + | trial step | 1.000000 | 0.032857 | -2955.388232 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: improving iteration 9 with line minimization (lambda= 3.357142) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3131782 -2.4902146 0.0000000 1.4567414 0.0000000 -0.0000000 + -0.0000000 4.9804291 -0.0000000 0.7283707 1.2615751 0.0000000 + 0.0000000 -0.0000000 5.5796687 -0.0000000 0.0000000 1.1260857 + + Lattice parameters(A) Cell Angles + a = 4.980429 alpha = 90.000000 + b = 4.980429 beta = 90.000000 + c = 5.579669 gamma = 120.000000 + + Current cell volume = 119.859532 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.160816 0.417815 0.129211 x + x O 2 -0.417815 -0.256999 0.795878 x + x O 3 0.256999 -0.160816 0.462544 x + x O 4 0.417815 0.160816 -0.129211 x + x O 5 -0.256999 -0.417815 0.204122 x + x O 6 -0.160816 0.256999 0.537456 x + x Si 1 0.477567 0.477567 0.000000 x + x Si 2 -0.477567 0.000000 0.666667 x + x Si 3 -0.000000 -0.477567 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95490304E+003 0.00000000E+000 1031.32 <-- SCF + 1 -2.95551525E+003 1.83778834E+000 1.41130721E-002 1036.58 <-- SCF + 2 -2.95551774E+003 1.83772183E+000 2.76753496E-004 1044.61 <-- SCF + 3 -2.95541395E+003 1.83298392E+000 -1.15327582E-002 1052.04 <-- SCF + 4 -2.95539403E+003 1.84253442E+000 -2.21262211E-003 1058.57 <-- SCF + 5 -2.95539405E+003 1.84451638E+000 1.55039394E-006 1065.66 <-- SCF + 6 -2.95539406E+003 1.84622927E+000 1.47146985E-006 1071.47 <-- SCF + 7 -2.95539410E+003 1.84677420E+000 4.04980884E-006 1076.75 <-- SCF + 8 -2.95539409E+003 1.84662499E+000 -1.74031628E-007 1081.62 <-- SCF + 9 -2.95539409E+003 1.84651055E+000 -2.13627042E-007 1086.27 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.394091795 eV +Final free energy (E-TS) = -2955.394091795 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.394091795 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.07348 -0.05512 0.02878 * + * O 2 0.01099 0.09120 0.02878 * + * O 3 -0.08447 -0.03608 0.02878 * + * O 4 -0.01099 0.09120 -0.02878 * + * O 5 0.08447 -0.03608 -0.02878 * + * O 6 -0.07348 -0.05512 -0.02878 * + * Si 1 -0.07647 -0.04415 -0.00000 * + * Si 2 0.07647 -0.04415 0.00000 * + * Si 3 0.00000 0.08829 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -0.297915 0.000000 -0.000000 * + * y 0.000000 -0.297915 0.000000 * + * z -0.000000 0.000000 1.409466 * + * * + * Pressure: -0.2712 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.046797 | -2955.383141 | <-- min BFGS + | trial step | 1.000000 | 0.032857 | -2955.388232 | <-- min BFGS + | line step | 3.357142 | -0.011963 | -2955.395606 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 9 with enthalpy= -2.95539561E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 1.385038E-003 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 9.625902E-002 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 2.334718E-002 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 1.409466E+000 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 10 ... +================================================================================ + +Writing analysis data to quartz_alpha.castep_bin + +Writing model to quartz_alpha.check + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.044137 | -2955.395606 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 10 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3149171 -2.4912186 0.0000000 1.4561543 0.0000000 -0.0000000 + -0.0000000 4.9824371 -0.0000000 0.7280772 1.2610667 0.0000000 + 0.0000000 -0.0000000 5.5696645 -0.0000000 0.0000000 1.1281084 + + Lattice parameters(A) Cell Angles + a = 4.982437 alpha = 90.000000 + b = 4.982437 beta = 90.000000 + c = 5.569664 gamma = 120.000000 + + Current cell volume = 119.741121 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.161020 0.418160 0.129893 x + x O 2 -0.418160 -0.257140 0.796559 x + x O 3 0.257140 -0.161020 0.463226 x + x O 4 0.418160 0.161020 -0.129893 x + x O 5 -0.257140 -0.418160 0.203441 x + x O 6 -0.161020 0.257140 0.536774 x + x Si 1 0.476566 0.476566 0.000000 x + x Si 2 -0.476566 0.000000 0.666667 x + x Si 3 -0.000000 -0.476566 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95535051E+003 0.00000000E+000 1094.11 <-- SCF + 1 -2.95541558E+003 1.87186472E+000 2.21955782E-003 1100.10 <-- SCF + 2 -2.95541589E+003 1.87185767E+000 3.43492830E-005 1105.81 <-- SCF + 3 -2.95540031E+003 1.84303846E+000 -1.73091644E-003 1111.55 <-- SCF + 4 -2.95539765E+003 1.85355173E+000 -2.96263875E-004 1119.05 <-- SCF + 5 -2.95539757E+003 1.85392256E+000 -8.92234838E-006 1125.15 <-- SCF + 6 -2.95539758E+003 1.85604560E+000 1.12841960E-006 1128.93 <-- SCF + 7 -2.95539759E+003 1.85569771E+000 1.25124244E-006 1134.73 <-- SCF + 8 -2.95539759E+003 1.85601086E+000 2.15817766E-007 1140.54 <-- SCF + 9 -2.95539759E+003 1.85606594E+000 2.27201698E-009 1146.15 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.397589938 eV +Final free energy (E-TS) = -2955.397589938 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.397589938 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.06958 -0.08666 -0.02024 * + * O 2 0.04026 0.10359 -0.02024 * + * O 3 -0.10984 -0.01693 -0.02024 * + * O 4 -0.04026 0.10359 0.02024 * + * O 5 0.10984 -0.01693 0.02024 * + * O 6 -0.06958 -0.08666 0.02024 * + * Si 1 -0.04009 -0.02315 0.00000 * + * Si 2 0.04009 -0.02315 0.00000 * + * Si 3 0.00000 0.04629 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -0.594430 0.000000 0.000000 * + * y 0.000000 -0.594430 0.000000 * + * z 0.000000 0.000000 0.810842 * + * * + * Pressure: 0.1260 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.044137 | -2955.395606 | <-- min BFGS + | trial step | 1.000000 | 0.015478 | -2955.398952 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: improving iteration 10 with line minimization (lambda= 1.540070) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3158563 -2.4917608 0.0000000 1.4558375 0.0000000 -0.0000000 + -0.0000000 4.9835216 -0.0000000 0.7279187 1.2607922 0.0000000 + 0.0000000 -0.0000000 5.5642615 -0.0000000 0.0000000 1.1292038 + + Lattice parameters(A) Cell Angles + a = 4.983522 alpha = 90.000000 + b = 4.983522 beta = 90.000000 + c = 5.564261 gamma = 120.000000 + + Current cell volume = 119.677043 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.161130 0.418346 0.130261 x + x O 2 -0.418346 -0.257216 0.796927 x + x O 3 0.257216 -0.161130 0.463594 x + x O 4 0.418346 0.161130 -0.130261 x + x O 5 -0.257216 -0.418346 0.203073 x + x O 6 -0.161130 0.257216 0.536406 x + x Si 1 0.476026 0.476026 0.000000 x + x Si 2 -0.476026 0.000000 0.666667 x + x Si 3 -0.000000 -0.476026 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95539192E+003 0.00000000E+000 1151.90 <-- SCF + 1 -2.95540365E+003 1.87013950E+000 5.21467988E-004 1159.44 <-- SCF + 2 -2.95540374E+003 1.87013738E+000 1.01399916E-005 1169.60 <-- SCF + 3 -2.95539921E+003 1.85441518E+000 -5.03399987E-004 1178.97 <-- SCF + 4 -2.95539842E+003 1.85993708E+000 -8.74821632E-005 1186.19 <-- SCF + 5 -2.95539839E+003 1.86013457E+000 -2.68520719E-006 1193.80 <-- SCF + 6 -2.95539840E+003 1.86109947E+000 5.85387823E-007 1199.23 <-- SCF + 7 -2.95539841E+003 1.86122724E+000 7.45550261E-007 1203.92 <-- SCF + 8 -2.95539841E+003 1.86126063E+000 1.15884939E-008 1208.67 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.398406390 eV +Final free energy (E-TS) = -2955.398406390 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.398406390 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.06764 -0.10378 -0.04618 * + * O 2 0.05606 0.11047 -0.04618 * + * O 3 -0.12369 -0.00669 -0.04618 * + * O 4 -0.05606 0.11047 0.04618 * + * O 5 0.12369 -0.00669 0.04618 * + * O 6 -0.06764 -0.10378 0.04618 * + * Si 1 -0.02125 -0.01227 0.00000 * + * Si 2 0.02125 -0.01227 0.00000 * + * Si 3 0.00000 0.02453 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -0.767182 0.000000 -0.000000 * + * y 0.000000 -0.767182 0.000000 * + * z -0.000000 0.000000 0.498027 * + * * + * Pressure: 0.3454 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.044137 | -2955.395606 | <-- min BFGS + | trial step | 1.000000 | 0.015478 | -2955.398952 | <-- min BFGS + | line step | 1.540070 | 0.000533 | -2955.399606 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 10 with enthalpy= -2.95539961E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 4.443620E-004 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 1.322012E-001 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 7.678975E-003 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 7.671818E-001 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 11 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.032507 | -2955.399606 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 11 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3197259 -2.4939949 0.0000000 1.4545333 0.0000000 -0.0000000 + -0.0000000 4.9879899 -0.0000000 0.7272667 1.2596628 0.0000000 + 0.0000000 -0.0000000 5.5650863 -0.0000000 0.0000000 1.1290365 + + Lattice parameters(A) Cell Angles + a = 4.987990 alpha = 90.000000 + b = 4.987990 beta = 90.000000 + c = 5.565086 gamma = 120.000000 + + Current cell volume = 119.909518 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.161610 0.418378 0.130662 x + x O 2 -0.418378 -0.256768 0.797329 x + x O 3 0.256768 -0.161610 0.463996 x + x O 4 0.418378 0.161610 -0.130662 x + x O 5 -0.256768 -0.418378 0.202671 x + x O 6 -0.161610 0.256768 0.536004 x + x Si 1 0.475996 0.475996 0.000000 x + x Si 2 -0.475996 0.000000 0.666667 x + x Si 3 -0.000000 -0.475996 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95536475E+003 0.00000000E+000 1214.70 <-- SCF + 1 -2.95541003E+003 1.79881306E+000 1.15821750E-003 1221.68 <-- SCF + 2 -2.95541020E+003 1.79880657E+000 1.91188347E-005 1232.75 <-- SCF + 3 -2.95539924E+003 1.84343050E+000 -1.21758080E-003 1240.16 <-- SCF + 4 -2.95539777E+003 1.84211443E+000 -1.63271545E-004 1245.99 <-- SCF + 5 -2.95539765E+003 1.84526015E+000 -1.34850932E-005 1253.28 <-- SCF + 6 -2.95539767E+003 1.84626024E+000 2.47122993E-006 1258.62 <-- SCF + 7 -2.95539768E+003 1.84654574E+000 1.10031266E-006 1264.16 <-- SCF + 8 -2.95539769E+003 1.84666022E+000 3.74477199E-007 1269.77 <-- SCF + 9 -2.95539769E+003 1.84663450E+000 -2.62887390E-008 1275.71 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.397687844 eV +Final free energy (E-TS) = -2955.397687844 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.397687844 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.06529 -0.09328 -0.03971 * + * O 2 0.04814 0.10318 -0.03971 * + * O 3 -0.11342 -0.00990 -0.03971 * + * O 4 -0.04814 0.10318 0.03971 * + * O 5 0.11342 -0.00990 0.03971 * + * O 6 -0.06529 -0.09328 0.03971 * + * Si 1 0.00170 0.00098 0.00000 * + * Si 2 -0.00170 0.00098 -0.00000 * + * Si 3 0.00000 -0.00197 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -0.558077 0.000000 -0.000000 * + * y 0.000000 -0.558077 0.000000 * + * z -0.000000 0.000000 0.682690 * + * * + * Pressure: 0.1445 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.032507 | -2955.399606 | <-- min BFGS + | trial step | 1.000000 | 0.026915 | -2955.400312 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: improving iteration 11 with line minimization (lambda= 5.813255) +-------------------------------------------------------------------------------- + ++---------------- MEMORY AND SCRATCH DISK ESTIMATES PER PROCESS --------------+ +| Memory Disk | +| Model and support data 76.2 MB 0.0 MB | +| Electronic energy minimisation requirements 52.6 MB 0.0 MB | +| Geometry minimisation requirements 77.0 MB 0.0 MB | +| ----------------------------- | +| Approx. total storage required per process 205.7 MB 0.0 MB | +| | +| Requirements will fluctuate during execution and may exceed these estimates | ++-----------------------------------------------------------------------------+ + + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3383515 -2.5047484 0.0000000 1.4482887 0.0000000 0.0000000 + -0.0000000 5.0094968 -0.0000000 0.7241443 1.2542548 0.0000000 + -0.0000000 -0.0000000 5.5690564 0.0000000 0.0000000 1.1282316 + + Lattice parameters(A) Cell Angles + a = 5.009497 alpha = 90.000000 + b = 5.009497 beta = 90.000000 + c = 5.569056 gamma = 120.000000 + + Current cell volume = 121.032068 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.163922 0.418531 0.132596 x + x O 2 -0.418531 -0.254609 0.799262 x + x O 3 0.254609 -0.163922 0.465929 x + x O 4 0.418531 0.163922 -0.132596 x + x O 5 -0.254609 -0.418531 0.200738 x + x O 6 -0.163922 0.254609 0.534071 x + x Si 1 0.475853 0.475853 0.000000 x + x Si 2 -0.475853 0.000000 0.666667 x + x Si 3 -0.000000 -0.475853 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95444070E+003 0.00000000E+000 1280.96 <-- SCF + 1 -2.95568698E+003 1.53414436E+000 3.18517250E-002 1289.07 <-- SCF + 2 -2.95569112E+003 1.53400845E+000 4.60454976E-004 1296.48 <-- SCF + 3 -2.95542863E+003 1.76423940E+000 -2.91657855E-002 1303.67 <-- SCF + 4 -2.95539450E+003 1.75434979E+000 -3.79200425E-003 1310.87 <-- SCF + 5 -2.95539122E+003 1.76966992E+000 -3.64206920E-004 1319.88 <-- SCF + 6 -2.95539137E+003 1.77440843E+000 1.65605172E-005 1328.11 <-- SCF + 7 -2.95539142E+003 1.77666756E+000 5.53651116E-006 1333.66 <-- SCF + 8 -2.95539143E+003 1.77654289E+000 8.50063128E-007 1338.95 <-- SCF + 9 -2.95539143E+003 1.77630989E+000 8.04430385E-008 1343.61 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.391431089 eV +Final free energy (E-TS) = -2955.391431089 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.391431089 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.05191 -0.04380 -0.00434 * + * O 2 0.01198 0.06685 -0.00434 * + * O 3 -0.06389 -0.02305 -0.00434 * + * O 4 -0.01198 0.06685 0.00434 * + * O 5 0.06389 -0.02305 0.00434 * + * O 6 -0.05191 -0.04380 0.00434 * + * Si 1 0.17063 0.09852 0.00000 * + * Si 2 -0.17063 0.09852 0.00000 * + * Si 3 -0.00000 -0.19703 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 0.468946 -0.000000 0.000000 * + * y -0.000000 0.468946 0.000000 * + * z 0.000000 0.000000 1.525602 * + * * + * Pressure: -0.8212 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.032507 | -2955.399606 | <-- min BFGS + | trial step | 1.000000 | 0.026915 | -2955.400312 | <-- min BFGS + | line step | 5.813255 | -0.000456 | -2955.393540 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 11 with enthalpy= -2.95539354E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 6.739604E-004 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 1.970308E-001 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 1.877933E-002 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 1.525602E+000 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 12 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.031617 | -2955.393540 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 12 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + ++---------------- MEMORY AND SCRATCH DISK ESTIMATES PER PROCESS --------------+ +| Memory Disk | +| Model and support data 76.4 MB 0.0 MB | +| Electronic energy minimisation requirements 53.0 MB 0.0 MB | +| Geometry minimisation requirements 77.6 MB 0.0 MB | +| ----------------------------- | +| Approx. total storage required per process 207.0 MB 0.0 MB | +| | +| Requirements will fluctuate during execution and may exceed these estimates | ++-----------------------------------------------------------------------------+ + + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3504995 -2.5117621 0.0000000 1.4442446 0.0000000 0.0000000 + -0.0000000 5.0235241 -0.0000000 0.7221223 1.2507525 0.0000000 + -0.0000000 -0.0000000 5.5723506 0.0000000 0.0000000 1.1275646 + + Lattice parameters(A) Cell Angles + a = 5.023524 alpha = 90.000000 + b = 5.023524 beta = 90.000000 + c = 5.572351 gamma = 120.000000 + + Current cell volume = 121.782827 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.167440 0.418354 0.134719 x + x O 2 -0.418354 -0.250914 0.801385 x + x O 3 0.250914 -0.167440 0.468052 x + x O 4 0.418354 0.167440 -0.134719 x + x O 5 -0.250914 -0.418354 0.198615 x + x O 6 -0.167440 0.250914 0.531948 x + x Si 1 0.478174 0.478174 0.000000 x + x Si 2 -0.478174 0.000000 0.666667 x + x Si 3 -0.000000 -0.478174 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95368931E+003 0.00000000E+000 1349.69 <-- SCF + 1 -2.95587568E+003 1.55350455E+000 5.35714059E-002 1357.19 <-- SCF + 2 -2.95588331E+003 1.55333041E+000 8.47666075E-004 1366.20 <-- SCF + 3 -2.95546903E+003 1.71448746E+000 -4.60315832E-002 1373.75 <-- SCF + 4 -2.95540105E+003 1.70868717E+000 -7.55303688E-003 1381.37 <-- SCF + 5 -2.95539962E+003 1.72267821E+000 -1.58398479E-004 1390.58 <-- SCF + 6 -2.95539988E+003 1.72704104E+000 2.80498784E-005 1398.00 <-- SCF + 7 -2.95539997E+003 1.73022727E+000 1.06300365E-005 1404.82 <-- SCF + 8 -2.95539997E+003 1.72933696E+000 1.28370356E-007 1412.34 <-- SCF + 9 -2.95539997E+003 1.72881107E+000 6.50489731E-008 1417.62 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.399974274 eV +Final free energy (E-TS) = -2955.399974274 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.399974274 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.03787 -0.00376 0.02881 * + * O 2 -0.01567 0.03468 0.02881 * + * O 3 -0.02219 -0.03091 0.02881 * + * O 4 0.01567 0.03468 -0.02881 * + * O 5 0.02219 -0.03091 -0.02881 * + * O 6 -0.03787 -0.00376 -0.02881 * + * Si 1 0.13130 0.07581 0.00000 * + * Si 2 -0.13130 0.07581 0.00000 * + * Si 3 -0.00000 -0.15162 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 0.631794 -0.000000 -0.000000 * + * y -0.000000 0.631794 0.000000 * + * z -0.000000 0.000000 1.653839 * + * * + * Pressure: -0.9725 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.031617 | -2955.393540 | <-- min BFGS + | trial step | 1.000000 | 0.021509 | -2955.398778 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: improving iteration 12 with line minimization (lambda= 3.127693) +-------------------------------------------------------------------------------- + ++---------------- MEMORY AND SCRATCH DISK ESTIMATES PER PROCESS --------------+ +| Memory Disk | +| Model and support data 77.0 MB 0.0 MB | +| Electronic energy minimisation requirements 53.8 MB 0.0 MB | +| Geometry minimisation requirements 78.8 MB 0.0 MB | +| ----------------------------- | +| Approx. total storage required per process 209.6 MB 0.0 MB | +| | +| Requirements will fluctuate during execution and may exceed these estimates | ++-----------------------------------------------------------------------------+ + + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3763468 -2.5266850 0.0000000 1.4357147 0.0000000 -0.0000000 + -0.0000000 5.0533700 -0.0000000 0.7178573 1.2433654 0.0000000 + 0.0000000 -0.0000000 5.5793597 -0.0000000 0.0000000 1.1261481 + + Lattice parameters(A) Cell Angles + a = 5.053370 alpha = 90.000000 + b = 5.053370 beta = 90.000000 + c = 5.579360 gamma = 120.000000 + + Current cell volume = 123.389211 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.174926 0.417978 0.139236 x + x O 2 -0.417978 -0.243052 0.805902 x + x O 3 0.243052 -0.174926 0.472569 x + x O 4 0.417978 0.174926 -0.139236 x + x O 5 -0.243052 -0.417978 0.194098 x + x O 6 -0.174926 0.243052 0.527431 x + x Si 1 0.483113 0.483113 0.000000 x + x Si 2 -0.483113 0.000000 0.666667 x + x Si 3 -0.000000 -0.483113 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.94758632E+003 0.00000000E+000 1423.90 <-- SCF + 1 -2.95767442E+003 1.19397663E+000 2.52848793E-001 1431.66 <-- SCF + 2 -2.95772071E+003 1.19485060E+000 5.14347879E-003 1440.48 <-- SCF + 3 -2.95573223E+003 1.63036694E+000 -2.20942150E-001 1449.09 <-- SCF + 4 -2.95541210E+003 1.58685282E+000 -3.55701172E-002 1455.26 <-- SCF + 5 -2.95539710E+003 1.61744401E+000 -1.66610007E-003 1461.40 <-- SCF + 6 -2.95539837E+003 1.62588528E+000 1.40408467E-004 1469.18 <-- SCF + 7 -2.95539878E+003 1.63398343E+000 4.61953327E-005 1477.73 <-- SCF + 8 -2.95539878E+003 1.63103664E+000 -4.33180173E-008 1484.68 <-- SCF + 9 -2.95539879E+003 1.63080088E+000 5.13955986E-007 1490.65 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.398786483 eV +Final free energy (E-TS) = -2955.398786483 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.398786483 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.00588 0.08845 0.11079 * + * O 2 -0.07954 -0.03913 0.11079 * + * O 3 0.07366 -0.04932 0.11079 * + * O 4 0.07954 -0.03913 -0.11079 * + * O 5 -0.07366 -0.04932 -0.11079 * + * O 6 -0.00588 0.08845 -0.11079 * + * Si 1 0.07388 0.04265 0.00000 * + * Si 2 -0.07388 0.04265 0.00000 * + * Si 3 -0.00000 -0.08531 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 1.349273 -0.000000 -0.000000 * + * y -0.000000 1.349273 0.000000 * + * z -0.000000 0.000000 2.189717 * + * * + * Pressure: -1.6294 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.031617 | -2955.393540 | <-- min BFGS + | trial step | 1.000000 | 0.021509 | -2955.398778 | <-- min BFGS + | line step | 3.127693 | -0.001517 | -2955.398330 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 12 with enthalpy= -2.95539833E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 5.321888E-004 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 1.418949E-001 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 6.802729E-002 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 2.189717E+000 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 13 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.060666 | -2955.398330 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 13 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3770720 -2.5271037 0.0000000 1.4354768 0.0000000 -0.0000000 + -0.0000000 5.0542074 -0.0000000 0.7177384 1.2431594 0.0000000 + 0.0000000 -0.0000000 5.5458965 -0.0000000 0.0000000 1.1329431 + + Lattice parameters(A) Cell Angles + a = 5.054207 alpha = 90.000000 + b = 5.054207 beta = 90.000000 + c = 5.545897 gamma = 120.000000 + + Current cell volume = 122.689817 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.176384 0.418063 0.140313 x + x O 2 -0.418063 -0.241679 0.806980 x + x O 3 0.241679 -0.176384 0.473647 x + x O 4 0.418063 0.176384 -0.140313 x + x O 5 -0.241679 -0.418063 0.193020 x + x O 6 -0.176384 0.241679 0.526353 x + x Si 1 0.483782 0.483782 0.000000 x + x Si 2 -0.483782 0.000000 0.666667 x + x Si 3 -0.000000 -0.483782 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95506037E+003 0.00000000E+000 1496.39 <-- SCF + 1 -2.95551447E+003 1.79418647E+000 1.29048388E-002 1501.43 <-- SCF + 2 -2.95551608E+003 1.79414368E+000 1.78200763E-004 1507.71 <-- SCF + 3 -2.95542202E+003 1.65315013E+000 -1.04503384E-002 1513.68 <-- SCF + 4 -2.95541077E+003 1.67375533E+000 -1.25038090E-003 1519.86 <-- SCF + 5 -2.95540979E+003 1.67333564E+000 -1.08610977E-004 1525.86 <-- SCF + 6 -2.95540985E+003 1.67560866E+000 6.50114733E-006 1530.64 <-- SCF + 7 -2.95540986E+003 1.67514487E+000 7.75513825E-007 1535.82 <-- SCF + 8 -2.95540986E+003 1.67542342E+000 -3.00693470E-008 1540.43 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.409858235 eV +Final free energy (E-TS) = -2955.409858235 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.409858235 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 -0.01559 0.04349 0.06071 * + * O 2 -0.02987 -0.03525 0.06071 * + * O 3 0.04546 -0.00825 0.06071 * + * O 4 0.02987 -0.03525 -0.06071 * + * O 5 -0.04546 -0.00825 -0.06071 * + * O 6 0.01559 0.04349 -0.06071 * + * Si 1 0.04144 0.02392 -0.00000 * + * Si 2 -0.04144 0.02392 0.00000 * + * Si 3 -0.00000 -0.04785 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 0.266765 -0.000000 -0.000000 * + * y -0.000000 0.266765 0.000000 * + * z -0.000000 0.000000 0.514563 * + * * + * Pressure: -0.3494 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.060666 | -2955.398330 | <-- min BFGS + | trial step | 1.000000 | 0.016291 | -2955.410146 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 13 with enthalpy= -2.95541015E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 1.312940E-003 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 7.628888E-002 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 9.332267E-003 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 5.145628E-001 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 14 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.009925 | -2955.410146 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 14 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3838824 -2.5310357 0.0000000 1.4332468 0.0000000 -0.0000000 + -0.0000000 5.0620714 -0.0000000 0.7166234 1.2412281 0.0000000 + 0.0000000 -0.0000000 5.5438674 -0.0000000 0.0000000 1.1333578 + + Lattice parameters(A) Cell Angles + a = 5.062071 alpha = 90.000000 + b = 5.062071 beta = 90.000000 + c = 5.543867 gamma = 120.000000 + + Current cell volume = 123.026875 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.179667 0.418429 0.143135 x + x O 2 -0.418429 -0.238762 0.809802 x + x O 3 0.238762 -0.179667 0.476468 x + x O 4 0.418429 0.179667 -0.143135 x + x O 5 -0.238762 -0.418429 0.190198 x + x O 6 -0.179667 0.238762 0.523532 x + x Si 1 0.485152 0.485152 0.000000 x + x Si 2 -0.485152 0.000000 0.666667 x + x Si 3 -0.000000 -0.485152 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95361905E+003 0.00000000E+000 1544.97 <-- SCF + 1 -2.95590205E+003 1.56140031E+000 5.46558310E-002 1549.89 <-- SCF + 2 -2.95590964E+003 1.56125616E+000 8.44043233E-004 1556.10 <-- SCF + 3 -2.95548674E+003 1.63945794E+000 -4.69893482E-002 1561.84 <-- SCF + 4 -2.95541075E+003 1.64419407E+000 -8.44298109E-003 1569.25 <-- SCF + 5 -2.95541094E+003 1.65433712E+000 2.07242878E-005 1578.86 <-- SCF + 6 -2.95541127E+003 1.65857732E+000 3.66022382E-005 1587.11 <-- SCF + 7 -2.95541136E+003 1.66070341E+000 1.03934465E-005 1592.35 <-- SCF + 8 -2.95541137E+003 1.66043238E+000 2.36506531E-007 1598.04 <-- SCF + 9 -2.95541137E+003 1.66025603E+000 -3.59776481E-008 1603.50 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.411365285 eV +Final free energy (E-TS) = -2955.411365285 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.411365285 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.01014 0.00487 0.01039 * + * O 2 -0.00929 0.00634 0.01039 * + * O 3 -0.00085 -0.01122 0.01039 * + * O 4 0.00929 0.00634 -0.01039 * + * O 5 0.00085 -0.01122 -0.01039 * + * O 6 -0.01014 0.00487 -0.01039 * + * Si 1 0.00610 0.00352 -0.00000 * + * Si 2 -0.00610 0.00352 0.00000 * + * Si 3 0.00000 -0.00705 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 0.052014 -0.000000 -0.000000 * + * y -0.000000 0.052014 0.000000 * + * z -0.000000 0.000000 0.032338 * + * * + * Pressure: -0.0455 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.009925 | -2955.410146 | <-- min BFGS + | trial step | 1.000000 | 0.005293 | -2955.410917 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: improving iteration 14 with line minimization (lambda= 2.142765) +-------------------------------------------------------------------------------- + ++---------------- MEMORY AND SCRATCH DISK ESTIMATES PER PROCESS --------------+ +| Memory Disk | +| Model and support data 77.1 MB 0.0 MB | +| Electronic energy minimisation requirements 54.0 MB 0.0 MB | +| Geometry minimisation requirements 79.0 MB 0.0 MB | +| ----------------------------- | +| Approx. total storage required per process 210.1 MB 0.0 MB | +| | +| Requirements will fluctuate during execution and may exceed these estimates | ++-----------------------------------------------------------------------------+ + + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3916650 -2.5355290 0.0000000 1.4307069 0.0000000 -0.0000000 + -0.0000000 5.0710580 -0.0000000 0.7153534 1.2390285 0.0000000 + 0.0000000 -0.0000000 5.5415487 -0.0000000 0.0000000 1.1338320 + + Lattice parameters(A) Cell Angles + a = 5.071058 alpha = 90.000000 + b = 5.071058 beta = 90.000000 + c = 5.541549 gamma = 120.000000 + + Current cell volume = 123.412439 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.183419 0.418847 0.146359 x + x O 2 -0.418847 -0.235428 0.813026 x + x O 3 0.235428 -0.183419 0.479692 x + x O 4 0.418847 0.183419 -0.146359 x + x O 5 -0.235428 -0.418847 0.186974 x + x O 6 -0.183419 0.235428 0.520308 x + x Si 1 0.486719 0.486719 0.000000 x + x Si 2 -0.486719 0.000000 0.666667 x + x Si 3 -0.000000 -0.486719 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95306707E+003 0.00000000E+000 1609.50 <-- SCF + 1 -2.95605136E+003 1.52403971E+000 7.11602807E-002 1616.60 <-- SCF + 2 -2.95606157E+003 1.52390758E+000 1.13446147E-003 1622.90 <-- SCF + 3 -2.95550943E+003 1.62411501E+000 -6.13486240E-002 1628.67 <-- SCF + 4 -2.95540999E+003 1.62471751E+000 -1.10491547E-002 1637.26 <-- SCF + 5 -2.95541011E+003 1.63646015E+000 1.38306999E-005 1646.78 <-- SCF + 6 -2.95541057E+003 1.64100660E+000 5.10791501E-005 1654.35 <-- SCF + 7 -2.95541069E+003 1.64382580E+000 1.32913761E-005 1659.07 <-- SCF + 8 -2.95541070E+003 1.64325992E+000 2.36720546E-007 1664.59 <-- SCF + 9 -2.95541070E+003 1.64299060E+000 -2.01544349E-008 1669.37 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.410695382 eV +Final free energy (E-TS) = -2955.410695382 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.410695382 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.03915 -0.03574 -0.04454 * + * O 2 0.01138 0.05177 -0.04454 * + * O 3 -0.05052 -0.01603 -0.04454 * + * O 4 -0.01138 0.05177 0.04454 * + * O 5 0.05052 -0.01603 0.04454 * + * O 6 -0.03915 -0.03574 0.04454 * + * Si 1 -0.02780 -0.01605 0.00000 * + * Si 2 0.02780 -0.01605 0.00000 * + * Si 3 0.00000 0.03210 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -0.135471 0.000000 0.000000 * + * y 0.000000 -0.135471 0.000000 * + * z 0.000000 0.000000 -0.391378 * + * * + * Pressure: 0.2208 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.009925 | -2955.410146 | <-- min BFGS + | trial step | 1.000000 | 0.005293 | -2955.410917 | <-- min BFGS + | line step | 2.142765 | 0.000436 | -2955.409893 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 14 with enthalpy= -2.95540989E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 2.807077E-005 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 6.923798E-002 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 4.763556E-002 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 3.913777E-001 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 15 ... +================================================================================ + +Writing analysis data to quartz_alpha.castep_bin + +Writing model to quartz_alpha.check + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.004278 | -2955.409893 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 15 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + ++---------------- MEMORY AND SCRATCH DISK ESTIMATES PER PROCESS --------------+ +| Memory Disk | +| Model and support data 77.3 MB 0.0 MB | +| Electronic energy minimisation requirements 54.3 MB 0.0 MB | +| Geometry minimisation requirements 79.5 MB 0.0 MB | +| ----------------------------- | +| Approx. total storage required per process 211.2 MB 0.0 MB | +| | +| Requirements will fluctuate during execution and may exceed these estimates | ++-----------------------------------------------------------------------------+ + + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.4020784 -2.5415412 0.0000000 1.4273224 0.0000000 0.0000000 + -0.0000000 5.0830823 -0.0000000 0.7136612 1.2360975 0.0000000 + -0.0000000 -0.0000000 5.5498527 0.0000000 0.0000000 1.1321355 + + Lattice parameters(A) Cell Angles + a = 5.083082 alpha = 90.000000 + b = 5.083082 beta = 90.000000 + c = 5.549853 gamma = 120.000000 + + Current cell volume = 124.184208 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.187877 0.419079 0.149628 x + x O 2 -0.419079 -0.231202 0.816294 x + x O 3 0.231202 -0.187877 0.482961 x + x O 4 0.419079 0.187877 -0.149628 x + x O 5 -0.231202 -0.419079 0.183706 x + x O 6 -0.187877 0.231202 0.517039 x + x Si 1 0.488853 0.488853 0.000000 x + x Si 2 -0.488853 0.000000 0.666667 x + x Si 3 -0.000000 -0.488853 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95243892E+003 0.00000000E+000 1677.57 <-- SCF + 1 -2.95622724E+003 1.39953538E+000 9.08164328E-002 1682.57 <-- SCF + 2 -2.95624097E+003 1.39945960E+000 1.52506803E-003 1689.62 <-- SCF + 3 -2.95553114E+003 1.59626341E+000 -7.88699576E-002 1697.76 <-- SCF + 4 -2.95540966E+003 1.57944137E+000 -1.34971734E-002 1704.17 <-- SCF + 5 -2.95540767E+003 1.59500886E+000 -2.21824453E-004 1713.48 <-- SCF + 6 -2.95540826E+003 1.59918208E+000 6.62978053E-005 1721.66 <-- SCF + 7 -2.95540840E+003 1.60367074E+000 1.56586746E-005 1729.10 <-- SCF + 8 -2.95540840E+003 1.60209851E+000 -1.46814773E-007 1735.11 <-- SCF + 9 -2.95540840E+003 1.60159025E+000 5.69490879E-008 1738.97 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.408403166 eV +Final free energy (E-TS) = -2955.408403166 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.408403166 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.02395 -0.01074 -0.02038 * + * O 2 -0.00267 0.02612 -0.02038 * + * O 3 -0.02128 -0.01537 -0.02038 * + * O 4 0.00267 0.02612 0.02038 * + * O 5 0.02128 -0.01537 0.02038 * + * O 6 -0.02395 -0.01074 0.02038 * + * Si 1 -0.00391 -0.00226 0.00000 * + * Si 2 0.00391 -0.00226 0.00000 * + * Si 3 0.00000 0.00451 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 0.176914 -0.000000 0.000000 * + * y -0.000000 0.176914 0.000000 * + * z 0.000000 0.000000 -0.038924 * + * * + * Pressure: -0.1050 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.004278 | -2955.409893 | <-- min BFGS + | trial step | 1.000000 | 0.001181 | -2955.407043 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 15 with enthalpy= -2.95540704E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 3.166820E-004 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 3.323458E-002 | 3.000000E-002 | eV/A | No | <-- BFGS + | |dR|max | 2.858612E-002 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 1.769137E-001 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 16 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.002452 | -2955.407043 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 16 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.4045945 -2.5429938 0.0000000 1.4265071 0.0000000 0.0000000 + -0.0000000 5.0859877 -0.0000000 0.7132535 1.2353914 0.0000000 + -0.0000000 -0.0000000 5.5569372 0.0000000 0.0000000 1.1306922 + + Lattice parameters(A) Cell Angles + a = 5.085988 alpha = 90.000000 + b = 5.085988 beta = 90.000000 + c = 5.556937 gamma = 120.000000 + + Current cell volume = 124.484915 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.190505 0.419202 0.151429 x + x O 2 -0.419202 -0.228697 0.818096 x + x O 3 0.228697 -0.190505 0.484763 x + x O 4 0.419202 0.190505 -0.151429 x + x O 5 -0.228697 -0.419202 0.181904 x + x O 6 -0.190505 0.228697 0.515237 x + x Si 1 0.490343 0.490343 0.000000 x + x Si 2 -0.490343 0.000000 0.666667 x + x Si 3 -0.000000 -0.490343 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95443433E+003 0.00000000E+000 1743.46 <-- SCF + 1 -2.95566472E+003 1.51446512E+000 2.86307030E-002 1748.47 <-- SCF + 2 -2.95566873E+003 1.51436054E+000 4.45207455E-004 1754.71 <-- SCF + 3 -2.95544451E+003 1.58267070E+000 -2.49128913E-002 1760.64 <-- SCF + 4 -2.95540655E+003 1.57794428E+000 -4.21737713E-003 1768.77 <-- SCF + 5 -2.95540664E+003 1.58476978E+000 9.59740278E-006 1776.76 <-- SCF + 6 -2.95540685E+003 1.58653566E+000 2.35609672E-005 1783.33 <-- SCF + 7 -2.95540689E+003 1.58851191E+000 4.66171824E-006 1788.85 <-- SCF + 8 -2.95540690E+003 1.58793860E+000 2.02954719E-007 1792.91 <-- SCF + 9 -2.95540690E+003 1.58759217E+000 4.38521318E-008 1797.34 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.406896701 eV +Final free energy (E-TS) = -2955.406896701 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.406896701 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 0.00822 0.00015 0.00015 * + * O 2 -0.00424 0.00704 0.00015 * + * O 3 -0.00398 -0.00719 0.00015 * + * O 4 0.00424 0.00704 -0.00015 * + * O 5 0.00398 -0.00719 -0.00015 * + * O 6 -0.00822 0.00015 -0.00015 * + * Si 1 -0.00817 -0.00472 -0.00000 * + * Si 2 0.00817 -0.00472 -0.00000 * + * Si 3 0.00000 0.00944 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 0.228517 -0.000000 0.000000 * + * y -0.000000 0.228517 0.000000 * + * z 0.000000 0.000000 0.089144 * + * * + * Pressure: -0.1821 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.002452 | -2955.407043 | <-- min BFGS + | trial step | 1.000000 | 0.000277 | -2955.405979 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 16 with enthalpy= -2.95540598E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 1.182568E-004 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 9.435018E-003 | 3.000000E-002 | eV/A | Yes | <-- BFGS + | |dR|max | 1.645984E-002 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 2.285167E-001 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 17 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.005151 | -2955.405979 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 17 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.4018247 -2.5413947 0.0000000 1.4274047 0.0000000 0.0000000 + -0.0000000 5.0827894 -0.0000000 0.7137024 1.2361687 0.0000000 + -0.0000000 -0.0000000 5.5608506 0.0000000 0.0000000 1.1298965 + + Lattice parameters(A) Cell Angles + a = 5.082789 alpha = 90.000000 + b = 5.082789 beta = 90.000000 + c = 5.560851 gamma = 120.000000 + + Current cell volume = 124.415956 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.190806 0.419255 0.151607 x + x O 2 -0.419255 -0.228449 0.818274 x + x O 3 0.228449 -0.190806 0.484940 x + x O 4 0.419255 0.190806 -0.151607 x + x O 5 -0.228449 -0.419255 0.181726 x + x O 6 -0.190806 0.228449 0.515060 x + x Si 1 0.490529 0.490529 0.000000 x + x Si 2 -0.490529 0.000000 0.666667 x + x Si 3 -0.000000 -0.490529 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95539942E+003 0.00000000E+000 1803.90 <-- SCF + 1 -2.95541031E+003 1.60630899E+000 4.80707272E-004 1811.01 <-- SCF + 2 -2.95541036E+003 1.60630705E+000 6.28485612E-006 1820.55 <-- SCF + 3 -2.95540768E+003 1.59097712E+000 -2.97478515E-004 1826.89 <-- SCF + 4 -2.95540728E+003 1.59327608E+000 -4.52853169E-005 1833.85 <-- SCF + 5 -2.95540727E+003 1.59291858E+000 -9.29190881E-007 1838.67 <-- SCF + 6 -2.95540727E+003 1.59315174E+000 3.27451144E-007 1843.65 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.407271649 eV +Final free energy (E-TS) = -2955.407271649 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.407271649 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 -0.00966 -0.00003 0.00025 * + * O 2 0.00486 -0.00835 0.00025 * + * O 3 0.00480 0.00838 0.00025 * + * O 4 -0.00486 -0.00835 -0.00025 * + * O 5 -0.00480 0.00838 -0.00025 * + * O 6 0.00966 -0.00003 -0.00025 * + * Si 1 -0.00705 -0.00407 -0.00000 * + * Si 2 0.00705 -0.00407 0.00000 * + * Si 3 0.00000 0.00814 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 0.063420 -0.000000 0.000000 * + * y -0.000000 0.063420 0.000000 * + * z 0.000000 0.000000 0.046304 * + * * + * Pressure: -0.0577 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.005151 | -2955.405979 | <-- min BFGS + | trial step | 1.000000 | -0.001486 | -2955.406495 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 17 with enthalpy= -2.95540649E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 5.728945E-005 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 9.660453E-003 | 3.000000E-002 | eV/A | Yes | <-- BFGS + | |dR|max | 1.723963E-003 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 6.342034E-002 | 5.000000E-002 | GPa | No | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 18 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.003542 | -2955.406495 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 18 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3738118 -2.5252214 0.0000000 1.4365468 0.0000000 0.0000000 + -0.0000000 5.0504428 -0.0000000 0.7182734 1.2440860 0.0000000 + -0.0000000 -0.0000000 5.5788838 0.0000000 0.0000000 1.1262442 + + Lattice parameters(A) Cell Angles + a = 5.050443 alpha = 90.000000 + b = 5.050443 beta = 90.000000 + c = 5.578884 gamma = 120.000000 + + Current cell volume = 123.235794 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.187352 0.419205 0.148617 x + x O 2 -0.419205 -0.231853 0.815283 x + x O 3 0.231853 -0.187352 0.481950 x + x O 4 0.419205 0.187352 -0.148617 x + x O 5 -0.231853 -0.419205 0.184717 x + x O 6 -0.187352 0.231853 0.518050 x + x Si 1 0.489170 0.489170 0.000000 x + x Si 2 -0.489170 0.000000 0.666667 x + x Si 3 -0.000000 -0.489170 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95322956E+003 0.00000000E+000 1849.22 <-- SCF + 1 -2.95598278E+003 1.83417157E+000 6.40312241E-002 1854.39 <-- SCF + 2 -2.95599205E+003 1.83393603E+000 1.02994008E-003 1860.91 <-- SCF + 3 -2.95549603E+003 1.68005259E+000 -5.51127210E-002 1867.10 <-- SCF + 4 -2.95540737E+003 1.68381348E+000 -9.85161565E-003 1873.26 <-- SCF + 5 -2.95540695E+003 1.67128130E+000 -4.63331334E-005 1881.36 <-- SCF + 6 -2.95540740E+003 1.66821296E+000 5.02369708E-005 1889.60 <-- SCF + 7 -2.95540748E+003 1.66532428E+000 8.70572568E-006 1896.68 <-- SCF + 8 -2.95540748E+003 1.66605252E+000 1.84170910E-008 1900.85 <-- SCF + 9 -2.95540748E+003 1.66654794E+000 2.14299594E-007 1904.91 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.407481643 eV +Final free energy (E-TS) = -2955.407481643 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.407481643 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 -0.08197 -0.02113 0.03911 * + * O 2 0.05928 -0.06042 0.03911 * + * O 3 0.02268 0.08155 0.03911 * + * O 4 -0.05928 -0.06042 -0.03911 * + * O 5 -0.02268 0.08155 -0.03911 * + * O 6 0.08197 -0.02113 -0.03911 * + * Si 1 0.02142 0.01237 -0.00000 * + * Si 2 -0.02142 0.01237 0.00000 * + * Si 3 -0.00000 -0.02474 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -1.303751 0.000000 -0.000000 * + * y 0.000000 -1.303751 0.000000 * + * z -0.000000 0.000000 -0.512532 * + * * + * Pressure: 1.0400 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.003542 | -2955.406495 | <-- min BFGS + | trial step | 1.000000 | -0.022270 | -2955.407540 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: improving iteration 18 with line minimization (lambda= 0.137223) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.3979807 -2.5391753 0.0000000 1.4286523 0.0000000 0.0000000 + -0.0000000 5.0783507 -0.0000000 0.7143262 1.2372492 0.0000000 + -0.0000000 -0.0000000 5.5633251 0.0000000 0.0000000 1.1293939 + + Lattice parameters(A) Cell Angles + a = 5.078351 alpha = 90.000000 + b = 5.078351 beta = 90.000000 + c = 5.563325 gamma = 120.000000 + + Current cell volume = 124.254020 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.190332 0.419248 0.151197 x + x O 2 -0.419248 -0.228916 0.817863 x + x O 3 0.228916 -0.190332 0.484530 x + x O 4 0.419248 0.190332 -0.151197 x + x O 5 -0.228916 -0.419248 0.182137 x + x O 6 -0.190332 0.228916 0.515470 x + x Si 1 0.490343 0.490343 0.000000 x + x Si 2 -0.490343 0.000000 0.666667 x + x Si 3 -0.000000 -0.490343 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95374235E+003 0.00000000E+000 1910.59 <-- SCF + 1 -2.95587957E+003 1.37394625E+000 5.24473595E-002 1917.72 <-- SCF + 2 -2.95588703E+003 1.37380568E+000 8.28968553E-004 1925.10 <-- SCF + 3 -2.95547046E+003 1.60365817E+000 -4.62847350E-002 1933.10 <-- SCF + 4 -2.95540987E+003 1.58436601E+000 -6.73293948E-003 1939.91 <-- SCF + 5 -2.95540686E+003 1.59791641E+000 -3.34504017E-004 1946.53 <-- SCF + 6 -2.95540724E+003 1.60101978E+000 4.26736632E-005 1954.80 <-- SCF + 7 -2.95540731E+003 1.60414366E+000 7.86168265E-006 1962.58 <-- SCF + 8 -2.95540732E+003 1.60339553E+000 3.83975424E-007 1967.67 <-- SCF + 9 -2.95540732E+003 1.60286486E+000 9.74160309E-008 1973.10 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.407316799 eV +Final free energy (E-TS) = -2955.407316799 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.407316799 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 -0.01278 -0.00582 0.00846 * + * O 2 0.01143 -0.00816 0.00846 * + * O 3 0.00135 0.01398 0.00846 * + * O 4 -0.01143 -0.00816 -0.00846 * + * O 5 -0.00135 0.01398 -0.00846 * + * O 6 0.01278 -0.00582 -0.00846 * + * Si 1 -0.00350 -0.00202 0.00000 * + * Si 2 0.00350 -0.00202 0.00000 * + * Si 3 0.00000 0.00404 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -0.142869 0.000000 0.000000 * + * y 0.000000 -0.142869 0.000000 * + * z 0.000000 0.000000 -0.071278 * + * * + * Pressure: 0.1190 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.003542 | -2955.406495 | <-- min BFGS + | trial step | 1.000000 | -0.022270 | -2955.407540 | <-- min BFGS + | line step | 0.137223 | -0.002601 | -2955.407241 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: improving iteration 18 with quad minimization (lambda= 0.060234) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.4001374 -2.5404205 0.0000000 1.4279521 0.0000000 0.0000000 + -0.0000000 5.0808410 -0.0000000 0.7139760 1.2366428 0.0000000 + -0.0000000 -0.0000000 5.5619368 0.0000000 0.0000000 1.1296758 + + Lattice parameters(A) Cell Angles + a = 5.080841 alpha = 90.000000 + b = 5.080841 beta = 90.000000 + c = 5.561937 gamma = 120.000000 + + Current cell volume = 124.344874 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.190598 0.419252 0.151427 x + x O 2 -0.419252 -0.228654 0.818094 x + x O 3 0.228654 -0.190598 0.484760 x + x O 4 0.419252 0.190598 -0.151427 x + x O 5 -0.228654 -0.419252 0.181906 x + x O 6 -0.190598 0.228654 0.515240 x + x Si 1 0.490447 0.490447 0.000000 x + x Si 2 -0.490447 0.000000 0.666667 x + x Si 3 -0.000000 -0.490447 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95539667E+003 0.00000000E+000 1979.12 <-- SCF + 1 -2.95541207E+003 1.58052205E+000 5.36817698E-004 1985.70 <-- SCF + 2 -2.95541213E+003 1.58052014E+000 6.43100534E-006 1993.97 <-- SCF + 3 -2.95540895E+003 1.59740501E+000 -3.52913819E-004 1999.63 <-- SCF + 4 -2.95540850E+003 1.59613204E+000 -5.08181605E-005 2007.95 <-- SCF + 5 -2.95540848E+003 1.59729433E+000 -1.28244494E-006 2012.56 <-- SCF + 6 -2.95540849E+003 1.59755514E+000 6.27146248E-007 2016.26 <-- SCF + 7 -2.95540849E+003 1.59776887E+000 1.12884557E-007 2020.13 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.408491489 eV +Final free energy (E-TS) = -2955.408491489 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.408491489 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 -0.00857 -0.00356 0.00512 * + * O 2 0.00736 -0.00564 0.00512 * + * O 3 0.00120 0.00920 0.00512 * + * O 4 -0.00736 -0.00564 -0.00512 * + * O 5 -0.00120 0.00920 -0.00512 * + * O 6 0.00857 -0.00356 -0.00512 * + * Si 1 -0.00528 -0.00305 -0.00000 * + * Si 2 0.00528 -0.00305 0.00000 * + * Si 3 0.00000 0.00609 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x -0.025551 -0.000000 -0.000000 * + * y -0.000000 -0.025551 -0.000000 * + * z -0.000000 -0.000000 0.003548 * + * * + * Pressure: 0.0159 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.003542 | -2955.406495 | <-- min BFGS + | trial step | 1.000000 | -0.022270 | -2955.407540 | <-- min BFGS + | line step | 0.137223 | -0.002601 | -2955.407241 | <-- min BFGS + | quad step | 0.060234 | -0.000110 | -2955.406606 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 18 with enthalpy= -2.95540661E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 1.233413E-005 | 1.000000E-005 | eV | No | <-- BFGS + | |F|max | 1.059609E-002 | 3.000000E-002 | eV/A | Yes | <-- BFGS + | |dR|max | 1.450796E-003 | 1.000000E-003 | A | No | <-- BFGS + | Smax | 2.555126E-002 | 5.000000E-002 | GPa | Yes | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + +================================================================================ + Starting BFGS iteration 19 ... +================================================================================ + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.002479 | -2955.406606 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + +-------------------------------------------------------------------------------- + BFGS: starting iteration 19 with trial guess (lambda= 1.000000) +-------------------------------------------------------------------------------- + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.4008353 -2.5408235 0.0000000 1.4277256 0.0000000 -0.0000000 + -0.0000000 5.0816469 -0.0000000 0.7138628 1.2364466 0.0000000 + 0.0000000 -0.0000000 5.5608470 -0.0000000 0.0000000 1.1298972 + + Lattice parameters(A) Cell Angles + a = 5.081647 alpha = 90.000000 + b = 5.081647 beta = 90.000000 + c = 5.560847 gamma = 120.000000 + + Current cell volume = 124.359954 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.190511 0.419256 0.151420 x + x O 2 -0.419256 -0.228745 0.818087 x + x O 3 0.228745 -0.190511 0.484753 x + x O 4 0.419256 0.190511 -0.151420 x + x O 5 -0.228745 -0.419256 0.181913 x + x O 6 -0.190511 0.228745 0.515247 x + x Si 1 0.490324 0.490324 0.000000 x + x Si 2 -0.490324 0.000000 0.666667 x + x Si 3 -0.000000 -0.490324 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +------------------------------------------------------------------------ <-- SCF +SCF loop Energy Fermi Energy gain Timer <-- SCF + energy per atom (sec) <-- SCF +------------------------------------------------------------------------ <-- SCF +Initial -2.95541170E+003 0.00000000E+000 2024.62 <-- SCF + 1 -2.95540812E+003 1.59313462E+000 1.68236279E-004 2030.84 <-- SCF + 2 -2.95540812E+003 1.59313449E+000 4.30031771E-007 2036.70 <-- SCF + 3 -2.95540796E+003 1.59674321E+000 -1.85800092E-005 2042.57 <-- SCF + 4 -2.95540793E+003 1.59639355E+000 -2.64089098E-006 2046.32 <-- SCF + 5 -2.95540793E+003 1.59654783E+000 -1.88965954E-010 2051.51 <-- SCF + 6 -2.95540793E+003 1.59642691E+000 6.54306001E-008 2055.24 <-- SCF +------------------------------------------------------------------------ <-- SCF + +Final energy, E = -2955.407933218 eV +Final free energy (E-TS) = -2955.407933218 eV +(energies not corrected for finite basis set) + +NB est. 0K energy (E-0.5TS) = -2955.407933218 eV + + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 -0.00450 -0.00447 0.00238 * + * O 2 0.00612 -0.00166 0.00238 * + * O 3 -0.00162 0.00614 0.00238 * + * O 4 -0.00612 -0.00166 -0.00238 * + * O 5 0.00162 0.00614 -0.00238 * + * O 6 0.00450 -0.00447 -0.00238 * + * Si 1 -0.00178 -0.00103 -0.00000 * + * Si 2 0.00178 -0.00103 0.00000 * + * Si 3 0.00000 0.00206 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 0.007391 0.000000 -0.000000 * + * y 0.000000 0.007391 0.000000 * + * z -0.000000 0.000000 0.009632 * + * * + * Pressure: -0.0081 * + * * + ************************************************* + + +------------+-------------+-------------+-----------------+ <-- min BFGS + | Step | lambda | F.delta' | enthalpy | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + | previous | 0.000000 | 0.002479 | -2955.406606 | <-- min BFGS + | trial step | 1.000000 | 0.000535 | -2955.406685 | <-- min BFGS + +------------+-------------+-------------+-----------------+ <-- min BFGS + + BFGS: finished iteration 19 with enthalpy= -2.95540668E+003 eV + + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | Parameter | value | tolerance | units | OK? | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + | dE/ion | 8.807743E-006 | 1.000000E-005 | eV | Yes | <-- BFGS + | |F|max | 6.778713E-003 | 3.000000E-002 | eV/A | Yes | <-- BFGS + | |dR|max | 6.264132E-004 | 1.000000E-003 | A | Yes | <-- BFGS + | Smax | 9.631693E-003 | 5.000000E-002 | GPa | Yes | <-- BFGS + +-----------+-----------------+-----------------+------------+-----+ <-- BFGS + + BFGS: Geometry optimization completed successfully. + +================================================================================ + BFGS: Final Configuration: +================================================================================ + + ------------------------------- + Unit Cell + ------------------------------- + Real Lattice(A) Reciprocal Lattice(1/A) + 4.4008353 -2.5408235 0.0000000 1.4277256 0.0000000 -0.0000000 + -0.0000000 5.0816469 -0.0000000 0.7138628 1.2364466 0.0000000 + 0.0000000 -0.0000000 5.5608470 -0.0000000 0.0000000 1.1298972 + + Lattice parameters(A) Cell Angles + a = 5.081647 alpha = 90.000000 + b = 5.081647 beta = 90.000000 + c = 5.560847 gamma = 120.000000 + + Current cell volume = 124.359954 A**3 + + ------------------------------- + Cell Contents + ------------------------------- + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + x Element Atom Fractional coordinates of atoms x + x Number u v w x + x---------------------------------------------------------------x + x O 1 0.190511 0.419256 0.151420 x + x O 2 -0.419256 -0.228745 0.818087 x + x O 3 0.228745 -0.190511 0.484753 x + x O 4 0.419256 0.190511 -0.151420 x + x O 5 -0.228745 -0.419256 0.181913 x + x O 6 -0.190511 0.228745 0.515247 x + x Si 1 0.490324 0.490324 0.000000 x + x Si 2 -0.490324 0.000000 0.666667 x + x Si 3 -0.000000 -0.490324 0.333333 x + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + + BFGS: Final Enthalpy = -2.95540668E+003 eV + BFGS: Final unchanged from initial value + BFGS: Final bulk modulus = 313.57313 GPa + + ******************************** Symmetrised Forces ******************************** + * * + * Cartesian components (eV/A) * + * -------------------------------------------------------------------------------- * + * x y z * + * * + * O 1 -0.00450 -0.00447 0.00238 * + * O 2 0.00612 -0.00166 0.00238 * + * O 3 -0.00162 0.00614 0.00238 * + * O 4 -0.00612 -0.00166 -0.00238 * + * O 5 0.00162 0.00614 -0.00238 * + * O 6 0.00450 -0.00447 -0.00238 * + * Si 1 -0.00178 -0.00103 -0.00000 * + * Si 2 0.00178 -0.00103 0.00000 * + * Si 3 0.00000 0.00206 0.00000 * + * * + ************************************************************************************ + + *********** Symmetrised Stress Tensor *********** + * * + * Cartesian components (GPa) * + * --------------------------------------------- * + * x y z * + * * + * x 0.007391 0.000000 -0.000000 * + * y 0.000000 0.007391 0.000000 * + * z -0.000000 0.000000 0.009632 * + * * + * Pressure: -0.0081 * + * * + ************************************************* + +Writing analysis data to quartz_alpha.castep_bin + +Writing model to quartz_alpha.check + + A BibTeX formatted list of references used in this run has been written to + quartz_alpha.bib + +Initialisation time = 0.71 s +Calculation time = 2058.86 s +Finalisation time = 2.49 s +Total time = 2062.06 s +Peak Memory Use = 292808 kB diff -Nru ovito-2.8.1+dfsg2/tests/files/CASTEP/quartz_alpha.geom ovito-2.9.0+dfsg1/tests/files/CASTEP/quartz_alpha.geom --- ovito-2.8.1+dfsg2/tests/files/CASTEP/quartz_alpha.geom 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/files/CASTEP/quartz_alpha.geom 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,544 @@ + BEGIN header + + END header + + 0 F F F F <-- c + -1.0860422968943938E+002 -1.0860422968943938E+002 <-- E + 8.0354578804424115E+000 -4.6392737703353273E+000 0.0000000000000000E+000 <-- h + 0.0000000000000000E+000 9.2785475406706510E+000 0.0000000000000000E+000 <-- h + 0.0000000000000000E+000 0.0000000000000000E+000 1.0208300540485364E+001 <-- h + -1.9799028528790381E-004 2.3716922523120409E-020 5.2939559203393771E-023 <-- S + 2.3716922523120409E-020 -1.9799028528790397E-004 -4.2351647362715017E-022 <-- S + 5.2939559203393771E-023 -4.2351647362715017E-022 -2.1423639877913352E-004 <-- S + O 1 1.2067602077283508E+000 3.1500600708916457E+000 1.1892613437881627E+000 <-- R + O 2 -3.3314121487033512E+000 -5.2994503927688441E-001 7.9947950374450727E+000 <-- R + O 3 2.1246519409749993E+000 -2.6201150316147612E+000 4.5920281906166185E+000 <-- R + O 4 3.3314121487033512E+000 -5.2994503927688597E-001 -1.1892613437881627E+000 <-- R + O 5 -2.1246519409749993E+000 -2.6201150316147608E+000 2.2135055030402926E+000 <-- R + O 6 -1.2067602077283508E+000 3.1500600708916466E+000 5.6162723498687477E+000 <-- R + Si 1 3.8632932089749068E+000 2.2304733741601162E+000 0.0000000000000000E+000 <-- R + Si 2 -3.8632932089749068E+000 2.2304733741601162E+000 6.8055336936569102E+000 <-- R + Si 3 0.0000000000000000E+000 -4.4609467483202314E+000 3.4027668468284555E+000 <-- R + O 1 -1.1229024131537955E-004 -2.8760609512440412E-003 -2.3016409085382014E-004 <-- F + O 2 2.5468869672674635E-003 1.3407842740458178E-003 -2.3016409085382006E-004 <-- F + O 3 -2.4345967259520899E-003 1.5352766771982225E-003 -2.3016409085382006E-004 <-- F + O 4 -2.5468869672674640E-003 1.3407842740458175E-003 2.3016409085382014E-004 <-- F + O 5 2.4345967259520886E-003 1.5352766771982225E-003 2.3016409085382020E-004 <-- F + O 6 1.1229024131538129E-004 -2.8760609512440412E-003 2.3016409085382014E-004 <-- F + Si 1 -1.3746093360251220E-002 -7.9363107018467650E-003 0.0000000000000000E+000 <-- F + Si 2 1.3746093360251219E-002 -7.9363107018467650E-003 0.0000000000000000E+000 <-- F + Si 3 1.1564823173178713E-018 1.5872621403693530E-002 0.0000000000000000E+000 <-- F + + 1 F F F F <-- c + -1.0860656132857910E+002 -1.0860656132857910E+002 <-- E + 8.1186082425952328E+000 -4.6872806543074734E+000 3.7712638214812431E-036 <-- h + -8.0418282246430295E-018 9.3745613086149433E+000 -6.2001547604716219E-036 <-- h + 8.5267983640466100E-037 -6.8214386912372880E-036 1.0322603201648580E+001 <-- h + -6.8074158098864542E-006 2.1175823681357508E-021 2.6469779601696886E-022 <-- S + 2.1175823681357508E-021 -6.8074158098864499E-006 -4.2351647362715017E-022 <-- S + 2.6469779601696886E-022 -4.2351647362715017E-022 2.9276157663869138E-005 <-- S + O 1 1.2191042832507626E+000 3.1789839198613103E+000 1.2022833717902701E+000 <-- R + O 2 -3.3626329744475107E+000 -5.3371668077307433E-001 8.0840188395559895E+000 <-- R + O 3 2.1435286911967473E+000 -2.6452672390882355E+000 4.6431511056731312E+000 <-- R + O 4 3.3626329744475107E+000 -5.3371668077307566E-001 -1.2022833717902701E+000 <-- R + O 5 -2.1435286911967473E+000 -2.6452672390882355E+000 2.2385843620925905E+000 <-- R + O 6 -1.2191042832507626E+000 3.1789839198613108E+000 5.6794520959754502E+000 <-- R + Si 1 3.8857164198064393E+000 2.2434194209697971E+000 -1.1625122338132443E-036 <-- R + Si 2 -3.8857164198064393E+000 2.2434194209697971E+000 6.8817354677657203E+000 <-- R + Si 3 3.8489680797517231E-018 -4.4868388419395924E+000 3.4408677338828606E+000 <-- R + O 1 7.9801557061782850E-004 2.5075879961216374E-003 6.5510437297171082E-003 <-- F + O 2 -2.5706426921751663E-003 -5.6269224129024565E-004 6.5510437297171082E-003 <-- F + O 3 1.7726271215573375E-003 -1.9448957548313928E-003 6.5510437297171065E-003 <-- F + O 4 2.5706426921751663E-003 -5.6269224129024554E-004 -6.5510437297171082E-003 <-- F + O 5 -1.7726271215573388E-003 -1.9448957548313928E-003 -6.5510437297171091E-003 <-- F + O 6 -7.9801557061782698E-004 2.5075879961216374E-003 -6.5510437297171082E-003 <-- F + Si 1 -6.0928692488027396E-003 -3.5177197009334544E-003 7.2280144832366958E-020 <-- F + Si 2 6.0928692488027387E-003 -3.5177197009334548E-003 -1.4456028966473392E-019 <-- F + Si 3 1.0119220276531375E-018 7.0354394018669088E-003 0.0000000000000000E+000 <-- F + + 2 F F F F <-- c + -1.0860727361242684E+002 -1.0860727361242684E+002 <-- E + 8.1896650606651207E+000 -4.7283053273478819E+000 4.7330898497628753E-035 <-- h + -1.4899075949515041E-017 9.4566106546957602E+000 -8.2330897857585390E-035 <-- h + 7.8326292169450059E-036 -9.0580831257721415E-035 1.0335528122295734E+001 <-- h + 8.1960068943645072E-005 -1.4399560103323106E-020 -7.9409338805090657E-023 <-- S + -1.4399560103323106E-020 8.1960068943645085E-005 0.0000000000000000E+000 <-- S + -7.9409338805090657E-023 0.0000000000000000E+000 7.8846932884607030E-005 <-- S + O 1 1.2340824604173632E+000 3.2180521035842178E+000 1.2395762883282304E+000 <-- R + O 2 -3.4039561026145662E+000 -5.4027929070586800E-001 8.1299283698587210E+000 <-- R + O 3 2.1698736421972020E+000 -2.6777728128783491E+000 4.6847523290934765E+000 <-- R + O 4 3.4039561026145662E+000 -5.4027929070586933E-001 -1.2395762883282304E+000 <-- R + O 5 -2.1698736421972020E+000 -2.6777728128783496E+000 2.2055997524370152E+000 <-- R + O 6 -1.2340824604173632E+000 3.2180521035842182E+000 5.6507757932022589E+000 <-- R + Si 1 3.8735626391807414E+000 2.2364024324538789E+000 -1.6554363198959362E-035 <-- R + Si 2 -3.8735626391807414E+000 2.2364024324538789E+000 6.8903520815304908E+000 <-- R + Si 3 7.0469919745009314E-018 -4.4728048649077561E+000 3.4451760407652459E+000 <-- R + O 1 3.1459984400587439E-003 1.4392575341275356E-003 3.9888636304691860E-003 <-- F + O 2 -2.8194328071719666E-003 2.0048858022933187E-003 3.9888636304691860E-003 <-- F + O 3 -3.2656563288677729E-004 -3.4441433364208567E-003 3.9888636304691860E-003 <-- F + O 4 2.8194328071719670E-003 2.0048858022933187E-003 -3.9888636304691860E-003 <-- F + O 5 3.2656563288677539E-004 -3.4441433364208554E-003 -3.9888636304691860E-003 <-- F + O 6 -3.1459984400587430E-003 1.4392575341275356E-003 -3.9888636304691860E-003 <-- F + Si 1 2.9216976735687032E-004 1.6868429383255938E-004 0.0000000000000000E+000 <-- F + Si 2 -2.9216976735687027E-004 1.6868429383255944E-004 0.0000000000000000E+000 <-- F + Si 3 -7.2280144832366958E-020 -3.3736858766511877E-004 0.0000000000000000E+000 <-- F + + 3 F F F F <-- c + -1.0860845760234196E+002 -1.0860845760234196E+002 <-- E + 8.1615673951297580E+000 -4.7120831325874404E+000 4.4533161868712977E-035 <-- h + -1.2234474047325388E-017 9.4241662651748772E+000 -7.6735424599753850E-035 <-- h + 7.8326292169450059E-036 -8.4424665927768864E-035 1.0279025991290801E+001 <-- h + -1.5209257338688569E-006 0.0000000000000000E+000 0.0000000000000000E+000 <-- S + 0.0000000000000000E+000 -1.5209257338688536E-006 -4.2351647362715017E-022 <-- S + 0.0000000000000000E+000 -4.2351647362715017E-022 -2.5341504003799839E-005 <-- S + O 1 1.2333290258160070E+000 3.2119680404360023E+000 1.2446148294691999E+000 <-- R + O 2 -3.3983104320693047E+000 -5.3788975263662486E-001 8.0972988236630670E+000 <-- R + O 3 2.1649814062532968E+000 -2.6740782877993774E+000 4.6709568265661350E+000 <-- R + O 4 3.3983104320693047E+000 -5.3788975263662597E-001 -1.2446148294691999E+000 <-- R + O 5 -2.1649814062532968E+000 -2.6740782877993774E+000 2.1817271676277348E+000 <-- R + O 6 -1.2333290258160070E+000 3.2119680404360031E+000 5.6080691647246681E+000 <-- R + Si 1 3.8544908990967763E+000 2.2253913581824865E+000 -1.5208270987407195E-035 <-- R + Si 2 -3.8544908990967763E+000 2.2253913581824873E+000 6.8526839941938684E+000 <-- R + Si 3 5.7780162299207064E-018 -4.4507827163649729E+000 3.4263419970969347E+000 <-- R + O 1 2.4028685671850080E-003 -1.2103269281721037E-003 5.0179560835109094E-004 <-- F + O 2 -1.5326041691107826E-004 2.6861086852233841E-003 5.0179560835109105E-004 <-- F + O 3 -2.2496081502739310E-003 -1.4757817570512806E-003 5.0179560835109094E-004 <-- F + O 4 1.5326041691107926E-004 2.6861086852233841E-003 -5.0179560835109094E-004 <-- F + O 5 2.2496081502739293E-003 -1.4757817570512806E-003 -5.0179560835109094E-004 <-- F + O 6 -2.4028685671850084E-003 -1.2103269281721035E-003 -5.0179560835109094E-004 <-- F + Si 1 -2.1358824412781416E-003 -1.2331523024293298E-003 0.0000000000000000E+000 <-- F + Si 2 2.1358824412781407E-003 -1.2331523024293296E-003 0.0000000000000000E+000 <-- F + Si 3 5.0596101382656877E-019 2.4663046048586600E-003 0.0000000000000000E+000 <-- F + + 4 F F F F <-- c + -1.0860810725528238E+002 -1.0860810725528238E+002 <-- E + 8.1695728009517179E+000 -4.7167050557937200E+000 4.3621644921330386E-035 <-- h + -1.2988960652408274E-017 9.4334101115874365E+000 -7.4408623486603036E-035 <-- h + 8.1526238733939834E-036 -8.1864708676177045E-035 1.0279107901166116E+001 <-- h + 6.7208503964861990E-006 -2.5410988417629010E-021 1.5881867761018131E-022 <-- S + -2.5410988417629010E-021 6.7208503964861939E-006 -2.1175823681357508E-022 <-- S + 1.5881867761018131E-022 -2.1175823681357508E-022 -2.2851803761379090E-005 <-- S + O 1 1.2370421924102046E+000 3.2170063123286385E+000 1.2523849308507755E+000 <-- R + O 2 -3.4045302868166001E+000 -5.3719319198388438E-001 8.1051235316281858E+000 <-- R + O 3 2.1674880944063948E+000 -2.6798131203447539E+000 4.6787542312394814E+000 <-- R + O 4 3.4045302868166001E+000 -5.3719319198388549E-001 -1.2523849308507755E+000 <-- R + O 5 -2.1674880944063948E+000 -2.6798131203447539E+000 2.1739843695379308E+000 <-- R + O 6 -1.2370421924102049E+000 3.2170063123286390E+000 5.6003536699266352E+000 <-- R + Si 1 3.8487203885514925E+000 2.2220597523658054E+000 -1.4503876150324418E-035 <-- R + Si 2 -3.8487203885514925E+000 2.2220597523658054E+000 6.8527386007774114E+000 <-- R + Si 3 6.1191544413672542E-018 -4.4441195047316091E+000 3.4263693003887061E+000 <-- R + O 1 2.1107717430123309E-003 -1.3202070626866984E-003 1.9832171160683956E-004 <-- F + O 2 8.7946983036150950E-005 2.4880854823823868E-003 1.9832171160683954E-004 <-- F + O 3 -2.1987187260484810E-003 -1.1678784196956886E-003 1.9832171160683956E-004 <-- F + O 4 -8.7946983036149500E-005 2.4880854823823868E-003 -1.9832171160683956E-004 <-- F + O 5 2.1987187260484806E-003 -1.1678784196956879E-003 -1.9832171160683962E-004 <-- F + O 6 -2.1107717430123318E-003 -1.3202070626866988E-003 -1.9832171160683956E-004 <-- F + Si 1 8.6072027007568885E-004 4.9693707962516641E-004 -7.2280144832366958E-020 <-- F + Si 2 -8.6072027007568863E-004 4.9693707962516619E-004 -1.4456028966473392E-019 <-- F + Si 3 -7.2280144832366958E-020 -9.9387415925033282E-004 0.0000000000000000E+000 <-- F + + 5 F F F F <-- c + -1.0860815976339164E+002 -1.0860815976339164E+002 <-- E + 8.1648226974143583E+000 -4.7139625822377473E+000 5.3737201803219600E-035 <-- h + -1.2515173903087493E-017 9.4279251644754911E+000 -9.4639737250381464E-035 <-- h + 8.1526238733939834E-036 -1.0412307278587611E-034 1.0305242879750493E+001 <-- h + 7.9076124017194951E-006 0.0000000000000000E+000 -1.0587911840678754E-022 <-- S + 0.0000000000000000E+000 7.9076124017194951E-006 -2.1175823681357508E-022 <-- S + -1.0587911840678754E-022 -2.1175823681357508E-022 4.2349311409532549E-006 <-- S + O 1 1.2398652902333662E+000 3.2110850599037577E+000 1.2518450616118471E+000 <-- R + O 2 -3.4008138807060138E+000 -5.3178769133921766E-001 8.1220069814455087E+000 <-- R + O 3 2.1609485904726471E+000 -2.6792973685645403E+000 4.6869260215286781E+000 <-- R + O 4 3.4008138807060138E+000 -5.3178769133921877E-001 -1.2518450616118471E+000 <-- R + O 5 -2.1609485904726471E+000 -2.6792973685645398E+000 2.1832358983049849E+000 <-- R + O 6 -1.2398652902333662E+000 3.2110850599037586E+000 5.6183168582218146E+000 <-- R + Si 1 3.8509715042395269E+000 2.2233594346142693E+000 -1.9291845554472285E-035 <-- R + Si 2 -3.8509715042395269E+000 2.2233594346142693E+000 6.8701619198336630E+000 <-- R + Si 3 5.9028321688669031E-018 -4.4467188692285369E+000 3.4350809599168319E+000 <-- R + O 1 5.7631749216946070E-004 1.9146588598406016E-004 2.3470159045082908E-003 <-- F + O 2 -4.5397306730502081E-004 4.0337264587206193E-004 2.3470159045082904E-003 <-- F + O 3 -1.2234442486443943E-004 -5.9483853185612195E-004 2.3470159045082908E-003 <-- F + O 4 4.5397306730501994E-004 4.0337264587206187E-004 -2.3470159045082908E-003 <-- F + O 5 1.2234442486443926E-004 -5.9483853185612195E-004 -2.3470159045082908E-003 <-- F + O 6 -5.7631749216945950E-004 1.9146588598406046E-004 -2.3470159045082904E-003 <-- F + Si 1 2.5527608829473132E-003 1.4738371829463781E-003 -3.6140072416183479E-020 <-- F + Si 2 -2.5527608829473128E-003 1.4738371829463781E-003 0.0000000000000000E+000 <-- F + Si 3 -6.5052130349130266E-019 -2.9476743658927562E-003 0.0000000000000000E+000 <-- F + + 6 F F F F <-- c + -1.0860864915412303E+002 -1.0860864915412303E+002 <-- E + 8.1482414071666582E+000 -4.7043893698497259E+000 4.8963840870916287E-035 <-- h + -1.1008899057966167E-017 9.4087787396994482E+000 -8.4187855909960299E-035 <-- h + 8.7275842616919905E-036 -9.2623865019915970E-035 1.0317486467217371E+001 <-- h + -3.3418692981355246E-005 7.6232965252887031E-021 1.0587911840678754E-022 <-- S + 7.6232965252887031E-021 -3.3418692981355233E-005 0.0000000000000000E+000 <-- S + 1.0587911840678754E-022 0.0000000000000000E+000 -1.8856155913602894E-005 <-- S + O 1 1.2456162852971384E+000 3.2021748537904782E+000 1.2607375748508010E+000 <-- R + O 2 -3.3959729133908447E+000 -5.2235208046031234E-001 8.1390618863290491E+000 <-- R + O 3 2.1503566280937059E+000 -2.6798227733301663E+000 4.6998997305899257E+000 <-- R + O 4 3.3959729133908447E+000 -5.2235208046031323E-001 -1.2607375748508010E+000 <-- R + O 5 -2.1503566280937059E+000 -2.6798227733301658E+000 2.1784245808883238E+000 <-- R + O 6 -1.2456162852971384E+000 3.2021748537904795E+000 5.6175867366274463E+000 <-- R + Si 1 3.8468696827178990E+000 2.2209912468545894E+000 -1.6629624576183881E-035 <-- R + Si 2 -3.8468696827178990E+000 2.2209912468545894E+000 6.8783243114782486E+000 <-- R + Si 3 5.1974159711252022E-018 -4.4419824937091770E+000 3.4391621557391248E+000 <-- R + O 1 -7.6927642969683806E-004 8.2848637329089044E-005 2.3281921969331341E-003 <-- F + O 2 3.1288919025250435E-004 -7.0763724931460076E-004 2.3281921969331341E-003 <-- F + O 3 4.5638723944433512E-004 6.2478861198551146E-004 2.3281921969331341E-003 <-- F + O 4 -3.1288919025250511E-004 -7.0763724931460076E-004 -2.3281921969331341E-003 <-- F + O 5 -4.5638723944433512E-004 6.2478861198551146E-004 -2.3281921969331341E-003 <-- F + O 6 7.6927642969683784E-004 8.2848637329089342E-005 -2.3281921969331336E-003 <-- F + Si 1 1.7283157202837591E-003 9.9784354635049045E-004 0.0000000000000000E+000 <-- F + Si 2 -1.7283157202837584E-003 9.9784354635049067E-004 0.0000000000000000E+000 <-- F + Si 3 -5.7824115865893567E-019 -1.9956870927009809E-003 0.0000000000000000E+000 <-- F + + 7 F F F F <-- c + -1.0860876706584290E+002 -1.0860876706584290E+002 <-- E + 8.1562890443371110E+000 -4.7090356753364286E+000 6.0201671235997154E-035 <-- h + -1.1797538544915527E-017 9.4180713506728537E+000 -1.1045482740615277E-034 <-- h + 6.3193307235694886E-036 -1.2152290747738600E-034 1.0371557726415102E+001 <-- h + -3.9522367623791759E-005 1.0164395367051604E-020 1.3234889800848443E-023 <-- S + 1.0164395367051604E-020 -3.9522367623791765E-005 -2.1175823681357508E-022 <-- S + 1.3234889800848443E-023 -2.1175823681357508E-022 -2.5091519721476387E-005 <-- S + O 1 1.2694954940743253E+000 3.2041048694086438E+000 1.3073074099281441E+000 <-- R + O 2 -3.4095839603344693E+000 -5.0263708684607877E-001 8.2216792275382122E+000 <-- R + O 3 2.1400884662601438E+000 -2.7014677825625650E+000 4.7644933187331784E+000 <-- R + O 4 3.4095839603344693E+000 -5.0263708684607988E-001 -1.3073074099281441E+000 <-- R + O 5 -2.1400884662601438E+000 -2.7014677825625646E+000 2.1498784988768906E+000 <-- R + O 6 -1.2694954940743253E+000 3.2041048694086447E+000 5.6070644076819232E+000 <-- R + Si 1 3.8428864188329608E+000 2.2186915083783671E+000 -1.8783552232786308E-035 <-- R + Si 2 -3.8428864188329608E+000 2.2186915083783680E+000 6.9143718176100686E+000 <-- R + Si 3 5.5584838157974952E-018 -4.4373830167567343E+000 3.4571859088050347E+000 <-- R + O 1 -3.0445908282045734E-004 -1.4998200243685599E-003 -1.7881355573176128E-004 <-- F + O 2 1.4511117836179990E-003 4.8624071204885340E-004 -1.7881355573176128E-004 <-- F + O 3 -1.1466527007975404E-003 1.0135793123197071E-003 -1.7881355573176128E-004 <-- F + O 4 -1.4511117836179981E-003 4.8624071204885340E-004 1.7881355573176136E-004 <-- F + O 5 1.1466527007975397E-003 1.0135793123197071E-003 1.7881355573176131E-004 <-- F + O 6 3.0445908282045767E-004 -1.4998200243685601E-003 1.7881355573176136E-004 <-- F + Si 1 3.0289734261687395E-003 1.7487786229667438E-003 -1.0842021724855044E-019 <-- F + Si 2 -3.0289734261687387E-003 1.7487786229667443E-003 1.4456028966473392E-019 <-- F + Si 3 -7.9508159315603655E-019 -3.4975572459334876E-003 0.0000000000000000E+000 <-- F + + 8 F F F F <-- c + -1.0860833177458578E+002 -1.0860833177458578E+002 <-- E + 8.1765047691429711E+000 -4.7207072294949546E+000 4.5640163499530885E-035 <-- h + -1.3791146249718951E-017 9.4414144589899056E+000 -8.1331811933220232E-035 <-- h + 6.3193307235694886E-036 -8.9481632343561299E-035 1.0477600615740828E+001 <-- h + 2.1897584364305626E-005 -8.4703294725430034E-022 -3.5072457972248373E-022 <-- S + -8.4703294725430034E-022 2.1897584364305623E-005 0.0000000000000000E+000 <-- S + -3.5072457972248373E-022 0.0000000000000000E+000 5.6047805352332288E-005 <-- S + O 1 1.2920044334221457E+000 3.2015598018874512E+000 1.3408922622837418E+000 <-- R + O 2 -3.4186343368806802E+000 -4.8187123979802671E-001 8.3259593394442941E+000 <-- R + O 3 2.1266299034585341E+000 -2.7196885620894240E+000 4.8334258008640187E+000 <-- R + O 4 3.4186343368806802E+000 -4.8187123979802782E-001 -1.3408922622837418E+000 <-- R + O 5 -2.1266299034585341E+000 -2.7196885620894240E+000 2.1516412762965351E+000 <-- R + O 6 -1.2920044334221457E+000 3.2015598018874516E+000 5.6441748148768101E+000 <-- R + Si 1 3.8664983290517378E+000 2.2323238510992596E+000 -1.1934266138163496E-035 <-- R + Si 2 -3.8664983290517378E+000 2.2323238510992596E+000 6.9850670771605525E+000 <-- R + Si 3 6.5215450165799410E-018 -4.4646477021985183E+000 3.4925335385802772E+000 <-- R + O 1 9.5395238377531338E-004 -6.2078897036281933E-004 7.8402604396268782E-004 <-- F + O 2 6.0642826835730308E-005 1.1365414835315531E-003 7.8402604396268782E-004 <-- F + O 3 -1.0145952106110437E-003 -5.1575251316873392E-004 7.8402604396268793E-004 <-- F + O 4 -6.0642826835730308E-005 1.1365414835315529E-003 -7.8402604396268782E-004 <-- F + O 5 1.0145952106110432E-003 -5.1575251316873392E-004 -7.8402604396268782E-004 <-- F + O 6 -9.5395238377531284E-004 -6.2078897036281966E-004 -7.8402604396268772E-004 <-- F + Si 1 4.1354747656936674E-003 2.3876174692001434E-003 -7.2280144832366958E-020 <-- F + Si 2 -4.1354747656936674E-003 2.3876174692001434E-003 0.0000000000000000E+000 <-- F + Si 3 -8.6736173798840355E-019 -4.7752349384002869E-003 0.0000000000000000E+000 <-- F + + 9 F F F F <-- c + -1.0860878986752721E+002 -1.0860878986752721E+002 <-- E + 8.1507254702117677E+000 -4.7058235443175045E+000 3.8805185958096654E-035 <-- h + -1.1539662652283420E-017 9.4116470886350054E+000 -6.7661856850351780E-035 <-- h + 6.3193307235694886E-036 -7.4441885093339176E-035 1.0544045766128212E+001 <-- h + -1.0125909768367543E-005 1.6940658945086007E-021 -3.3087224502121107E-024 <-- S + 1.6940658945086007E-021 -1.0125909768367546E-005 0.0000000000000000E+000 <-- S + -3.3087224502121107E-024 0.0000000000000000E+000 4.7906772762198766E-005 <-- S + O 1 1.3107694985197487E+000 3.1755532715331154E+000 1.3624071265090649E+000 <-- R + O 2 -3.4054945534783361E+000 -4.5261695154266590E-001 8.3917709705945391E+000 <-- R + O 3 2.0947250549585865E+000 -2.7229363199904491E+000 4.8770890485518033E+000 <-- R + O 4 3.4054945534783361E+000 -4.5261695154266723E-001 -1.3624071265090649E+000 <-- R + O 5 -2.0947250549585865E+000 -2.7229363199904495E+000 2.1522747955336734E+000 <-- R + O 6 -1.3107694985197487E+000 3.1755532715331163E+000 5.6669567175764097E+000 <-- R + Si 1 3.8925166881347999E+000 2.2473455577197372E+000 -8.8060715687895105E-036 <-- R + Si 2 -3.8925166881347999E+000 2.2473455577197381E+000 7.0293638440854753E+000 <-- R + Si 3 5.5109609093841872E-018 -4.4946911154394744E+000 3.5146819220427385E+000 <-- R + O 1 1.4290406883741133E-003 -1.0718351640769178E-003 5.5961731022879458E-004 <-- F + O 2 2.1371613657301600E-004 1.7735031212120428E-003 5.5961731022879458E-004 <-- F + O 3 -1.6427568249471290E-003 -7.0166795713512539E-004 5.5961731022879458E-004 <-- F + O 4 -2.1371613657301556E-004 1.7735031212120424E-003 -5.5961731022879469E-004 <-- F + O 5 1.6427568249471293E-003 -7.0166795713512539E-004 -5.5961731022879447E-004 <-- F + O 6 -1.4290406883741130E-003 -1.0718351640769178E-003 -5.5961731022879447E-004 <-- F + Si 1 -1.4870126085590491E-003 -8.5852712983993469E-004 -7.2280144832366958E-020 <-- F + Si 2 1.4870126085590489E-003 -8.5852712983993469E-004 0.0000000000000000E+000 <-- F + Si 3 2.8912057932946783E-019 1.7170542596798694E-003 0.0000000000000000E+000 <-- F + + 10 F F F F <-- c + -1.0860893683755813E+002 -1.0860893683755813E+002 <-- E + 8.1557863904734109E+000 -4.7087454679929115E+000 3.8260276643099434E-035 <-- h + -1.2023813690751295E-017 9.4174909359858194E+000 -6.6765997466513090E-035 <-- h + 6.1961271484388808E-036 -7.3456256492294324E-035 1.0514930309250568E+001 <-- h + -2.6075981536412983E-005 2.5410988417629010E-021 -3.3087224502121107E-024 <-- S + 2.5410988417629010E-021 -2.6075981536412983E-005 2.1175823681357508E-022 <-- S + -3.3087224502121107E-024 2.1175823681357508E-022 1.6927603909568453E-005 <-- S + O 1 1.3141392763372595E+000 3.1810525559129319E+000 1.3696808471871598E+000 <-- R + O 2 -3.4119419623626475E+000 -4.5244828053750030E-001 8.3796343866875382E+000 <-- R + O 3 2.0978026860253869E+000 -2.7286042753754312E+000 4.8746576169373501E+000 <-- R + O 4 3.4119419623626475E+000 -4.5244828053750163E-001 -1.3696808471871598E+000 <-- R + O 5 -2.0978026860253869E+000 -2.7286042753754312E+000 2.1352959225630306E+000 <-- R + O 6 -1.3141392763372595E+000 3.1810525559129323E+000 5.6402726923132196E+000 <-- R + Si 1 3.8823665836618972E+000 2.2414853921700040E+000 -8.6082830631910618E-036 <-- R + Si 2 -3.8823665836618972E+000 2.2414853921700049E+000 7.0099535395003798E+000 <-- R + Si 3 5.7236482475406784E-018 -4.4829707843400080E+000 3.5049767697501903E+000 <-- R + O 1 1.3153279644133181E-003 -2.0181935538799286E-003 -8.9797538515071218E-004 <-- F + O 2 1.0901429052073569E-003 2.1482042084299733E-003 -8.9797538515071218E-004 <-- F + O 3 -2.4054708696206752E-003 -1.3001065455004422E-004 -8.9797538515071218E-004 <-- F + O 4 -1.0901429052073554E-003 2.1482042084299733E-003 8.9797538515071218E-004 <-- F + O 5 2.4054708696206761E-003 -1.3001065455004365E-004 8.9797538515071218E-004 <-- F + O 6 -1.3153279644133192E-003 -2.0181935538799291E-003 8.9797538515071218E-004 <-- F + Si 1 -4.1319832908185940E-004 -2.3856016652411521E-004 1.0842021724855044E-019 <-- F + Si 2 4.1319832908185929E-004 -2.3856016652411513E-004 1.4456028966473392E-019 <-- F + Si 3 7.2280144832366958E-020 4.7712033304823026E-004 0.0000000000000000E+000 <-- F + + 11 F F F F <-- c + -1.0860871392924969E+002 -1.0860871392924969E+002 <-- E + 8.1982961728422836E+000 -4.7332885022867721E+000 2.7330863465704346E-035 <-- h + -1.6166168962954560E-017 9.4665770045735407E+000 -5.6621280850239250E-035 <-- h + -1.2447153370933420E-036 -6.2294992763995980E-035 1.0523991352319298E+001 <-- h + 1.5939162271611009E-005 -5.0821976835258020E-021 0.0000000000000000E+000 <-- S + -5.0821976835258020E-021 1.5939162271611009E-005 0.0000000000000000E+000 <-- S + 0.0000000000000000E+000 0.0000000000000000E+000 5.1854172060033771E-005 <-- S + O 1 1.3438812147705546E+000 3.1861697965490761E+000 1.3954359481515677E+000 <-- R + O 2 -3.4312445919674741E+000 -4.2924962661454602E-001 8.4114301830310989E+000 <-- R + O 3 2.0873633771969184E+000 -2.7569201699345292E+000 4.9034330655913347E+000 <-- R + O 4 3.4312445919674741E+000 -4.2924962661454757E-001 -1.3954359481515677E+000 <-- R + O 5 -2.0873633771969184E+000 -2.7569201699345296E+000 2.1125611692881994E+000 <-- R + O 6 -1.3438812147705546E+000 3.1861697965490765E+000 5.6205582867279649E+000 <-- R + Si 1 3.9011804928405933E+000 2.2523476076988338E+000 -8.9724639241321474E-036 <-- R + Si 2 -3.9011804928405933E+000 2.2523476076988338E+000 7.0159942348795328E+000 <-- R + Si 3 7.6927134214984694E-018 -4.5046952153976658E+000 3.5079971174397668E+000 <-- R + O 1 1.0094159535653947E-003 -8.5185484962823461E-004 -8.4386400894439120E-005 <-- F + O 2 2.3301996333232838E-004 1.3001072835870427E-003 -8.4386400894439093E-005 <-- F + O 3 -1.2424359168977225E-003 -4.4825243395880780E-004 -8.4386400894439120E-005 <-- F + O 4 -2.3301996333232708E-004 1.3001072835870430E-003 8.4386400894439120E-005 <-- F + O 5 1.2424359168977217E-003 -4.4825243395880780E-004 8.4386400894439161E-005 <-- F + O 6 -1.0094159535653947E-003 -8.5185484962823493E-004 8.4386400894439120E-005 <-- F + Si 1 3.3182970003321076E-003 1.9158196663928704E-003 7.2280144832366958E-020 <-- F + Si 2 -3.3182970003321072E-003 1.9158196663928704E-003 0.0000000000000000E+000 <-- F + Si 3 -7.2280144832366965E-019 -3.8316393327857399E-003 0.0000000000000000E+000 <-- F + + 12 F F F F <-- c + -1.0860888994746995E+002 -1.0860888994746995E+002 <-- E + 8.2700968653283855E+000 -4.7747426514216249E+000 4.4371223215663641E-035 <-- h + -2.2458976110592697E-017 9.5494853028432463E+000 -8.7550741668513064E-035 <-- h + 7.5697493256384700E-037 -9.6323727348168211E-035 1.0543461843566707E+001 <-- h + 4.5860876758099795E-005 -8.4703294725430034E-021 -1.0587911840678754E-022 <-- S + -8.4703294725430034E-021 4.5860876758099795E-005 0.0000000000000000E+000 <-- S + -1.0587911840678754E-022 0.0000000000000000E+000 7.4426983251820602E-005 <-- S + O 1 1.4466513226154183E+000 3.1562480711634118E+000 1.4680242288248808E+000 <-- R + O 2 -3.4567166715808590E+000 -3.2528723977839497E-001 8.4969987912026852E+000 <-- R + O 3 2.0100653489654392E+000 -2.8309608313850152E+000 4.9825115100137838E+000 <-- R + O 4 3.4567166715808590E+000 -3.2528723977839707E-001 -1.4680242288248808E+000 <-- R + O 5 -2.0100653489654396E+000 -2.8309608313850161E+000 2.0464630523640222E+000 <-- R + O 6 -1.4466513226154183E+000 3.1562480711634122E+000 5.5609503335529249E+000 <-- R + Si 1 3.9953892167519709E+000 2.3067390398090790E+000 -1.5885932025926805E-035 <-- R + Si 2 -3.9953892167519709E+000 2.3067390398090790E+000 7.0289745623778055E+000 <-- R + Si 3 1.0850217649535249E-017 -4.6134780796181563E+000 3.5144872811889032E+000 <-- R + O 1 1.1440777704245595E-004 1.7201463119509259E-003 2.1546195372120209E-003 <-- F + O 2 -1.5468942928968431E-003 -7.6099311466619024E-004 2.1546195372120209E-003 <-- F + O 3 1.4324865158543852E-003 -9.5915319728473566E-004 2.1546195372120209E-003 <-- F + O 4 1.5468942928968440E-003 -7.6099311466619024E-004 -2.1546195372120209E-003 <-- F + O 5 -1.4324865158543852E-003 -9.5915319728473566E-004 -2.1546195372120209E-003 <-- F + O 6 -1.1440777704245567E-004 1.7201463119509268E-003 -2.1546195372120214E-003 <-- F + Si 1 1.4367443918177575E-003 8.2950476137266750E-004 0.0000000000000000E+000 <-- F + Si 2 -1.4367443918177573E-003 8.2950476137266761E-004 0.0000000000000000E+000 <-- F + Si 3 -4.3368086899420177E-019 -1.6590095227453350E-003 0.0000000000000000E+000 <-- F + + 13 F F F F <-- c + -1.0860932419451655E+002 -1.0860932419451655E+002 <-- E + 8.2714673834872361E+000 -4.7755339204495666E+000 4.3867455997278015E-035 <-- h + -2.2595202858732664E-017 9.5510678408991296E+000 -8.7550741668513064E-035 <-- h + 1.1698561966589218E-037 -9.6323727348168211E-035 1.0480225557401495E+001 <-- h + 9.0671669201670718E-006 -1.6940658945086007E-021 -1.0587911840678754E-022 <-- S + -1.6940658945086007E-021 9.0671669201670718E-006 0.0000000000000000E+000 <-- S + -1.0587911840678754E-022 0.0000000000000000E+000 1.7489635504514743E-005 <-- S + O 1 1.4589551079882708E+000 3.1506198056895438E+000 1.4705167679772149E+000 <-- R + O 2 -3.4579943433876728E+000 -3.1181771634585886E-001 8.4573338062448773E+000 <-- R + O 3 1.9990392353994002E+000 -2.8388020893436829E+000 4.9639252871110466E+000 <-- R + O 4 3.4579943433876728E+000 -3.1181771634586108E-001 -1.4705167679772149E+000 <-- R + O 5 -1.9990392353994004E+000 -2.8388020893436838E+000 2.0228917511566178E+000 <-- R + O 6 -1.4589551079882708E+000 3.1506198056895438E+000 5.5163002702904498E+000 <-- R + Si 1 4.0015862461222076E+000 2.3103168963841605E+000 -1.6188375699791126E-035 <-- R + Si 2 -4.0015862461222076E+000 2.3103168963841614E+000 6.9868170382676640E+000 <-- R + Si 3 1.0931150277924002E-017 -4.6206337927683210E+000 3.4934085191338324E+000 <-- R + O 1 -3.0314481976899632E-004 8.4577016491134069E-004 1.1805902047420564E-003 <-- F + O 2 -5.8088603869167494E-004 -6.8541619740127675E-004 1.1805902047420564E-003 <-- F + O 3 8.8403085846067294E-004 -1.6035396751006362E-004 1.1805902047420564E-003 <-- F + O 4 5.8088603869167635E-004 -6.8541619740127675E-004 -1.1805902047420564E-003 <-- F + O 5 -8.8403085846067327E-004 -1.6035396751006362E-004 -1.1805902047420564E-003 <-- F + O 6 3.0314481976899686E-004 8.4577016491134069E-004 -1.1805902047420564E-003 <-- F + Si 1 8.0578469517311551E-004 4.6522001066707868E-004 -3.6140072416183479E-020 <-- F + Si 2 -8.0578469517311518E-004 4.6522001066707868E-004 0.0000000000000000E+000 <-- F + Si 3 -2.1684043449710089E-019 -9.3044002133415747E-004 0.0000000000000000E+000 <-- F + + 14 F F F F <-- c + -1.0860931491028184E+002 -1.0860931491028184E+002 <-- E + 8.2990441367506431E+000 -4.7914553663695711E+000 3.9251707869791728E-035 <-- h + -2.5110049571454626E-017 9.5829107327391387E+000 -7.8319245413540500E-035 <-- h + 1.1698561966589218E-037 -8.6167192847908092E-035 1.0472009313344342E+001 <-- h + -4.6045712681725274E-006 0.0000000000000000E+000 1.0587911840678754E-022 <-- S + 0.0000000000000000E+000 -4.6045712681725223E-006 1.0587911840678754E-022 <-- S + 1.0587911840678754E-022 1.0587911840678754E-022 -1.3302657886259908E-005 <-- S + O 1 1.5222054135153888E+000 3.1349272712142890E+000 1.5326731679754566E+000 <-- R + O 2 -3.4760293626458978E+000 -2.4919507772461999E-001 8.5140127102050176E+000 <-- R + O 3 1.9538239491305074E+000 -2.8857321934896674E+000 5.0233429390902380E+000 <-- R + O 4 3.4760293626458978E+000 -2.4919507772462204E-001 -1.5326731679754566E+000 <-- R + O 5 -1.9538239491305076E+000 -2.8857321934896683E+000 1.9579966031393252E+000 <-- R + O 6 -1.5222054135153888E+000 3.1349272712142895E+000 5.4486663742541062E+000 <-- R + Si 1 4.0392993565513899E+000 2.3320905708424271E+000 -1.4073967341726021E-035 <-- R + Si 2 -4.0392993565513899E+000 2.3320905708424280E+000 6.9813395422295628E+000 <-- R + Si 3 1.2221528817734699E-017 -4.6641811416848542E+000 3.4906697711147818E+000 <-- R + O 1 7.6129161765497251E-004 -6.9500234790899112E-004 -8.6624097393478688E-004 <-- F + O 2 2.2124388015152952E-004 1.0067990545318531E-003 -8.6624097393478688E-004 <-- F + O 3 -9.8253549780650444E-004 -3.1179670662286166E-004 -8.6624097393478688E-004 <-- F + O 4 -2.2124388015152836E-004 1.0067990545318531E-003 8.6624097393478688E-004 <-- F + O 5 9.8253549780650466E-004 -3.1179670662286166E-004 8.6624097393478688E-004 <-- F + O 6 -7.6129161765497359E-004 -6.9500234790899112E-004 8.6624097393478688E-004 <-- F + Si 1 -5.4062577643451063E-004 -3.1213043755531510E-004 1.0842021724855044E-019 <-- F + Si 2 5.4062577643451042E-004 -3.1213043755531510E-004 0.0000000000000000E+000 <-- F + Si 3 1.4456028966473392E-019 6.2426087511063008E-004 0.0000000000000000E+000 <-- F + + 15 F F F F <-- c + -1.0860921016964220E+002 -1.0860921016964220E+002 <-- E + 8.3187225926507740E+000 -4.8028167281807486E+000 4.0744925095462023E-035 <-- h + -2.6786686471638818E-017 9.6056334563614918E+000 -8.1809447083266699E-035 <-- h + -2.0300903678308514E-037 -9.0007128725295821E-035 1.0487701615494355E+001 <-- h + 6.0131736573555937E-006 -8.4703294725430034E-022 3.1763735522036263E-022 <-- S + -8.4703294725430034E-022 6.0131736573555954E-006 0.0000000000000000E+000 <-- S + 3.1763735522036263E-022 0.0000000000000000E+000 -1.3230035511181269E-006 <-- S + O 1 1.5628956853872282E+000 3.1231797675038599E+000 1.5692518613327135E+000 <-- R + O 2 -3.4862008619375340E+000 -2.0808251674149744E-001 8.5610529383289489E+000 <-- R + O 3 1.9233051765503044E+000 -2.9150972507623614E+000 5.0651523998308328E+000 <-- R + O 4 3.4862008619375340E+000 -2.0808251674149972E-001 -1.5692518613327135E+000 <-- R + O 5 -1.9233051765503046E+000 -2.9150972507623614E+000 1.9266486771654059E+000 <-- R + O 6 -1.5628956853872282E+000 3.1231797675038604E+000 5.4225492156635253E+000 <-- R + Si 1 4.0666320589567375E+000 2.3478711139338340E+000 -1.4468671975835087E-035 <-- R + Si 2 -4.0666320589567375E+000 2.3478711139338357E+000 6.9918010769962375E+000 <-- R + Si 3 1.3094750635755715E-017 -4.6957422278676688E+000 3.4959005384981197E+000 <-- R + O 1 4.6582365391683423E-004 -2.0895535241959116E-004 -3.9631073810466921E-004 <-- F + O 2 -5.1951183506322142E-005 5.0789279418546481E-004 -3.9631073810466921E-004 <-- F + O 3 -4.1387247041051265E-004 -2.9893744176587414E-004 -3.9631073810466921E-004 <-- F + O 4 5.1951183506322142E-005 5.0789279418546470E-004 3.9631073810466921E-004 <-- F + O 5 4.1387247041051238E-004 -2.9893744176587414E-004 3.9631073810466921E-004 <-- F + O 6 -4.6582365391683391E-004 -2.0895535241959146E-004 3.9631073810466921E-004 <-- F + Si 1 -7.6013938646407052E-005 -4.3886667939666792E-005 0.0000000000000000E+000 <-- F + Si 2 7.6013938646407012E-005 -4.3886667939666826E-005 0.0000000000000000E+000 <-- F + Si 3 0.0000000000000000E+000 8.7773335879333611E-005 0.0000000000000000E+000 <-- F + + 16 F T F F <-- c + -1.0860917105692589E+002 -1.0860917105692589E+002 <-- E + 8.3234773732681333E+000 -4.8055619020501181E+000 4.7132266823066417E-035 <-- h + -2.7289677541694077E-017 9.6111238041002327E+000 -9.4584130538475487E-035 <-- h + -2.0300903678308514E-037 -1.0406189402651574E-034 1.0501089373342689E+001 <-- h + 7.7671246209675239E-006 -1.6940658945086007E-021 1.0587911840678754E-022 <-- S + -1.6940658945086007E-021 7.7671246209675239E-006 0.0000000000000000E+000 <-- S + 1.0587911840678754E-022 0.0000000000000000E+000 3.0299502205573100E-006 <-- S + O 1 1.5856647164690609E+000 3.1135159968337538E+000 1.5901725286499284E+000 <-- R + O 2 -3.4892163065817914E+000 -1.8353207207001981E-001 8.5908987775450534E+000 <-- R + O 3 1.9035515901127291E+000 -2.9299839247637327E+000 5.0905356530974917E+000 <-- R + O 4 3.4892163065817914E+000 -1.8353207207002170E-001 -1.5901725286499284E+000 <-- R + O 5 -1.9035515901127293E+000 -2.9299839247637331E+000 1.9101905957976353E+000 <-- R + O 6 -1.5856647164690609E+000 3.1135159968337547E+000 5.4105537202451988E+000 <-- R + Si 1 4.0813574672235804E+000 2.3563728323606234E+000 -1.7325512069014792E-035 <-- R + Si 2 -4.0813574672235804E+000 2.3563728323606243E+000 7.0007262488951270E+000 <-- R + Si 3 1.3381297769922920E-017 -4.7127456647212469E+000 3.5003631244475639E+000 <-- R + O 1 1.5982236987842693E-004 2.8966683106217486E-006 2.9657110728030975E-006 <-- F + O 2 -8.2419773282548195E-005 1.3696189825243956E-004 2.9657110728030611E-006 <-- F + O 3 -7.7402596595877303E-005 -1.3985856656306117E-004 2.9657110728030251E-006 <-- F + O 4 8.2419773282548479E-005 1.3696189825243956E-004 -2.9657110728030975E-006 <-- F + O 5 7.7402596595877872E-005 -1.3985856656306117E-004 -2.9657110728030975E-006 <-- F + O 6 -1.5982236987842750E-004 2.8966683106220379E-006 -2.9657110728030611E-006 <-- F + Si 1 -1.5889998835605631E-004 -9.1740951051597473E-005 -1.4456028966473392E-019 <-- F + Si 2 1.5889998835605620E-004 -9.1740951051597487E-005 -2.8912057932946783E-019 <-- F + Si 3 7.2280144832366958E-020 1.8348190210319489E-004 0.0000000000000000E+000 <-- F + + 17 F T F F <-- c + -1.0860919000506324E+002 -1.0860919000506324E+002 <-- E + 8.3182431714999616E+000 -4.8025399342502704E+000 4.7297175157613861E-035 <-- h + -2.6786686471638818E-017 9.6050798685005372E+000 -9.5165830816763196E-035 <-- h + -3.6300636500757382E-037 -1.0470188333941370E-034 1.0508484576182394E+001 <-- h + 2.1556135749437036E-006 -1.6940658945086007E-021 0.0000000000000000E+000 <-- S + -1.6940658945086007E-021 2.1556135749437074E-006 5.2939559203393771E-023 <-- S + 0.0000000000000000E+000 5.2939559203393771E-023 1.5738430019447186E-006 <-- S + O 1 1.5871692765071364E+000 3.1106274827410734E+000 1.5931602312579856E+000 <-- R + O 2 -3.4874670600173787E+000 -1.8078482780918731E-001 8.5988166153795795E+000 <-- R + O 3 1.9002977835102406E+000 -2.9298426549318841E+000 5.0959884233187838E+000 <-- R + O 4 3.4874670600173787E+000 -1.8078482780918920E-001 -1.5931602312579856E+000 <-- R + O 5 -1.9002977835102408E+000 -2.9298426549318850E+000 1.9096679608028133E+000 <-- R + O 6 -1.5871692765071364E+000 3.1106274827410734E+000 5.4124961528636115E+000 <-- R + Si 1 4.0803414328510073E+000 2.3557862246421122E+000 -1.7534621053883232E-035 <-- R + Si 2 -4.0803414328510081E+000 2.3557862246421131E+000 7.0056563841215969E+000 <-- R + Si 3 1.3139652737431149E-017 -4.7115724492842244E+000 3.5028281920607989E+000 <-- R + O 1 -1.8780234396997540E-004 -6.1473515858712774E-007 4.8474277240922086E-006 <-- F + O 2 9.4433548248923360E-005 -1.6233423318896782E-004 4.8474277240922086E-006 <-- F + O 3 9.3368795721052340E-005 1.6294896834755505E-004 4.8474277240922086E-006 <-- F + O 4 -9.4433548248923360E-005 -1.6233423318896782E-004 -4.8474277240922086E-006 <-- F + O 5 -9.3368795721051188E-005 1.6294896834755505E-004 -4.8474277240922450E-006 <-- F + O 6 1.8780234396997483E-004 -6.1473515858683858E-007 -4.8474277240922086E-006 <-- F + Si 1 -1.3702468430679346E-004 -7.9111238370150680E-005 -7.2280144832366958E-020 <-- F + Si 2 1.3702468430679341E-004 -7.9111238370150680E-005 0.0000000000000000E+000 <-- F + Si 3 3.6140072416183479E-020 1.5822247674030131E-004 0.0000000000000000E+000 <-- F + + 18 F T F T <-- c + -1.0860919408450093E+002 -1.0860919408450093E+002 <-- E + 8.3150545661636261E+000 -4.8006989921009975E+000 4.7476746291239808E-035 <-- h + -2.6503911847063623E-017 9.6013979842019914E+000 -9.5524973084015079E-035 <-- h + -3.6300636500757382E-037 -1.0509701330828312E-034 1.0510537235611940E+001 <-- h + -8.6846973706597544E-007 -2.5410988417629010E-021 -3.1763735522036263E-022 <-- S + -2.5410988417629010E-021 -8.6846973706597036E-007 -1.0587911840678754E-022 <-- S + -3.1763735522036263E-022 -1.0587911840678754E-022 1.2060797631823481E-007 <-- S + O 1 1.5848311289459500E+000 3.1104046153301397E+000 1.5915781686942827E+000 <-- R + O 2 -3.4861049773972415E+000 -1.8269828928950513E-001 8.5986029924355751E+000 <-- R + O 3 1.9012738484512903E+000 -2.9277063260406337E+000 5.0950905805649302E+000 <-- R + O 4 3.4861049773972415E+000 -1.8269828928950652E-001 -1.5915781686942827E+000 <-- R + O 5 -1.9012738484512905E+000 -2.9277063260406342E+000 1.9119342431763648E+000 <-- R + O 6 -1.5848311289459500E+000 3.1104046153301401E+000 5.4154466550470124E+000 <-- R + Si 1 4.0780967960639165E+000 2.3544902829888525E+000 -1.7617611989688198E-035 <-- R + Si 2 -4.0780967960639165E+000 2.3544902829888534E+000 7.0070248237412942E+000 <-- R + Si 3 1.2998774346773627E-017 -4.7089805659777051E+000 3.5035124118706475E+000 <-- R + O 1 -1.6656510295704063E-004 -6.9199791829149232E-005 9.9642619174592870E-005 <-- F + O 2 1.4321132913915850E-004 -1.0964971463019331E-004 9.9642619174592897E-005 <-- F + O 3 2.3353773817882718E-005 1.7884950645934267E-004 9.9642619174592897E-005 <-- F + O 4 -1.4321132913915793E-004 -1.0964971463019331E-004 -9.9642619174592870E-005 <-- F + O 5 -2.3353773817883009E-005 1.7884950645934207E-004 -9.9642619174592829E-005 <-- F + O 6 1.6656510295704036E-004 -6.9199791829149232E-005 -9.9642619174592829E-005 <-- F + Si 1 -1.0262670228834898E-004 -5.9251554192221897E-005 -1.4456028966473392E-019 <-- F + Si 2 1.0262670228834897E-004 -5.9251554192221864E-005 2.8912057932946783E-019 <-- F + Si 3 3.6140072416183479E-020 1.1850310838444379E-004 0.0000000000000000E+000 <-- F + + 19 T T T T <-- c + -1.0860919699760818E+002 -1.0860919699760818E+002 <-- E + 8.3163735417656959E+000 -4.8014605030199089E+000 4.4266953710425227E-035 <-- h + -2.6629659614577436E-017 9.6029210060398125E+000 -8.7090319048843426E-035 <-- h + 9.1697226078833539E-037 -9.5817168271262776E-035 1.0508477786534472E+001 <-- h + 2.5122992486880757E-007 1.6940658945086007E-021 -1.0587911840678754E-022 <-- S + 1.6940658945086007E-021 2.5122992486881095E-007 0.0000000000000000E+000 <-- S + -1.0587911840678754E-022 0.0000000000000000E+000 3.2737462575714517E-007 <-- S + O 1 1.5843640530015122E+000 3.1113511018071991E+000 1.5911934818664528E+000 <-- R + O 2 -3.4866911207584939E+000 -1.8357603216141394E-001 8.5968453395561006E+000 <-- R + O 3 1.9023270677569803E+000 -2.9277750696457843E+000 5.0940194107112777E+000 <-- R + O 4 3.4866911207584939E+000 -1.8357603216141594E-001 -1.5911934818664528E+000 <-- R + O 5 -1.9023270677569806E+000 -2.9277750696457843E+000 1.9116324469783721E+000 <-- R + O 6 -1.5843640530015122E+000 3.1113511018071995E+000 5.4144583758231972E+000 <-- R + Si 1 4.0777185272238610E+000 2.3542718893722205E+000 -1.5050978875204956E-035 <-- R + Si 2 -4.0777185272238610E+000 2.3542718893722223E+000 7.0056518576896494E+000 <-- R + Si 3 1.3057164380446103E-017 -4.7085437787444420E+000 3.5028259288448251E+000 <-- R + O 1 -8.7565752911091213E-005 -8.6982320674438014E-005 4.6304898497363800E-005 <-- F + O 2 1.1911177583973434E-004 -3.2343006185297282E-005 4.6304898497363800E-005 <-- F + O 3 -3.1546022928643135E-005 1.1932532685973544E-004 4.6304898497363800E-005 <-- F + O 4 -1.1911177583973376E-004 -3.2343006185297282E-005 -4.6304898497363800E-005 <-- F + O 5 3.1546022928641976E-005 1.1932532685973486E-004 -4.6304898497363800E-005 <-- F + O 6 8.7565752911091213E-005 -8.6982320674438313E-005 -4.6304898497363800E-005 <-- F + Si 1 -3.4621480552521129E-005 -1.9988721116741470E-005 -7.2280144832366958E-020 <-- F + Si 2 3.4621480552521149E-005 -1.9988721116741450E-005 0.0000000000000000E+000 <-- F + Si 3 0.0000000000000000E+000 3.9977442233482920E-005 0.0000000000000000E+000 <-- F + diff -Nru ovito-2.8.1+dfsg2/tests/files/CASTEP/test.cell ovito-2.9.0+dfsg1/tests/files/CASTEP/test.cell --- ovito-2.8.1+dfsg2/tests/files/CASTEP/test.cell 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/files/CASTEP/test.cell 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,43 @@ +%BLOCK LATTICE_CART # H-Vector +#Optional Units + 21.222673600000000 0.000000000000000 0.000000000000000 # R1x R1y R1z + 0.000000000000000 21.222673600000000 0.000000000000000 # R2x R2y R2z + 0.000000000000000 0.000000000000000 54.330044416000000 # R3x R3y R3z +%ENDBLOCK LATTICE_CART + + %BLOCK LATTICE_ABC +21.222673600000000 21.222673600000000 54.330044416000000 # ABC side lengths + 90 90 70 # alpha, beta, gamma angles +%ENDBLOCK LATTICE_ABC + +# Instructions to castep (Can be ignored entirely I suspect) +fix_all_cell : T +kpoints_mp_spacing = 0.05 A + +%BLOCK POSITIONS_ABS # Absolute positions entry +ANG # Optional units +8 16.3714250871232 3.47831211661269 47.6388648058143 +Ar:Tag 19.9938383532128 5.9346589870918 45.475551097258 # Loads default Ar params, but can be overridden +Ar 3.08848186950762 1.29619245696072 48.6152300340142 +Cu 3.65016616503122 13.4336977167168 0.676108172722509 +%ENDBLOCK POSITIONS_ABS + +#%BLOCK POSITIONS_FRAC # Fractional coordinates +#Ar:Tag 0.942098 0.279637669548468 0.837024 # Loads default Ar params, but can be overridden +#Ar 0.145527464056537 0.061075832451229 0.894813 SPIN= 4 # Optional spin stated any of these ways +#Ar 0.171993700408756 0.632988 0.012444461991336 SPIN : 1 +#Ar 0.771412 0.163896037896596 0.876842 SPIN 4 +#%ENDBLOCK positions_frac + +%block species_mass +# ME Optional units +Ar:Tag 150.0 +#Ar defaults to CODATA numbers +%ENDBLOCK SpEcIeS_MASs # Case insensitive + +%block ionic_velocities +1 1 1 +1 2 3 +0 1 2 +5 6 7 +%endblock ionic_velocities diff -Nru ovito-2.8.1+dfsg2/tests/files/CASTEP/test.md ovito-2.9.0+dfsg1/tests/files/CASTEP/test.md --- ovito-2.8.1+dfsg2/tests/files/CASTEP/test.md 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/files/CASTEP/test.md 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,178 @@ + BEGIN header + + END header + + 0.0000000000000000E+000 + -9.3242199142955485E+001 -9.3242156391002169E+001 4.2751953321648325E-005 <-- E + 3.1668113571591354E-006 <-- T + 3.7447310299409951E-008 <-- P + 8.0354578804424115E+000 -4.6392737703353273E+000 0.0000000000000000E+000 <-- h + 0.0000000000000000E+000 9.2785475406706510E+000 0.0000000000000000E+000 <-- h + 0.0000000000000000E+000 0.0000000000000000E+000 1.0208300540485364E+001 <-- h + O 1 1.2067602077283508E+000 3.1500600708916462E+000 1.1892613437881625E+000 <-- R + O 2 -3.3314121487033508E+000 -5.2994503927688474E-001 7.9947950374450727E+000 <-- R + O 3 2.1246519409749989E+000 -2.6201150316147608E+000 4.5920281906166185E+000 <-- R + O 4 3.3314121487033508E+000 -5.2994503927688563E-001 -1.1892613437881625E+000 <-- R + O 5 -2.1246519409749989E+000 -2.6201150316147608E+000 2.2135055030402926E+000 <-- R + O 6 -1.2067602077283508E+000 3.1500600708916462E+000 5.6162723498687477E+000 <-- R + Si 1 -3.8632932089749059E+000 2.2304733741601157E+000 6.8055336936569102E+000 <-- R + Si 2 0.0000000000000000E+000 -4.4609467483202314E+000 3.4027668468284551E+000 <-- R + Si:A 1 3.8632932089749059E+000 2.2304733741601166E+000 0.0000000000000000E+000 <-- R + O 1 -1.7991647012660077E-005 7.2036504790911134E-006 1.3107416739416073E-005 <-- V + O 2 6.8628924959420533E-007 -1.8077621588297798E-005 -8.3759199134074968E-006 <-- V + O 3 1.6085053062754405E-005 -6.6451419978520388E-006 -9.4227463062470266E-006 <-- V + O 4 1.6872856489345305E-005 -1.5862094653151939E-005 1.5158107051004894E-006 <-- V + O 5 -2.7090381724192341E-006 6.9729186170561844E-006 4.9685338148326224E-006 <-- V + O 6 3.1023648216572327E-007 1.1405013883234403E-006 2.0858871762104831E-005 <-- V + Si 1 4.6302291735588495E-006 -6.2726062753409069E-006 9.3436783121737655E-006 <-- V + Si 2 4.5739530214384551E-006 3.3402362423237756E-006 3.5334098957474989E-006 <-- V + Si:A 1 2.1118507580911164E-005 5.1259416846957625E-005 -1.2175824330684770E-005 <-- V + O 1 -1.0419905178750073E-001 -9.9282394744334243E-002 -1.2811738035374434E-001 <-- F + O 2 1.3823902998031354E-001 -3.5715937515915161E-002 -1.2693222312261590E-001 <-- F + O 3 -3.6891816702468938E-002 1.3839224780473272E-001 -1.2912196518252056E-001 <-- F + O 4 -1.3806651865829617E-001 -4.0633382283957714E-002 1.2811905068418045E-001 <-- F + O 5 3.8134757368206984E-002 1.3763832946631807E-001 1.2689299636395712E-001 <-- F + O 6 1.0134396501533093E-001 -1.0118829504008880E-001 1.2915991701672819E-001 <-- F + Si 1 1.8046884428063618E-002 -9.4092479056024844E-003 1.0781918998238934E-003 <-- F + Si 2 8.9054428826912868E-004 2.0312588713250465E-002 -1.0764520281849191E-003 <-- F + Si:A 1 -1.7497793931918353E-002 -1.0113908494402815E-002 -2.1352776239432524E-006 <-- F + + 2.0670686716130454E+001 + -9.3243982446804779E+001 -9.3242211852685713E+001 1.7705941190624417E-003 <-- E + 1.3115511993055124E-004 <-- T + 1.5508996019900523E-006 <-- P + 8.0354578804424115E+000 -4.6392737703353273E+000 0.0000000000000000E+000 <-- h + 0.0000000000000000E+000 9.2785475406706510E+000 0.0000000000000000E+000 <-- h + 0.0000000000000000E+000 0.0000000000000000E+000 1.0208300540485364E+001 <-- h + O 1 1.2056250161323123E+000 3.1494816995065005E+000 1.1885937816709320E+000 <-- R + O 2 -3.3303853168400441E+000 -5.3058034697178491E-001 7.9936920816679180E+000 <-- R + O 3 2.1247141855282399E+000 -2.6192386230996227E+000 4.5908875556472584E+000 <-- R + O 4 3.3307495401420799E+000 -5.3057057238866068E-001 -1.1882914972819347E+000 <-- R + O 5 -2.1244285891708610E+000 -2.6189626511316648E+000 2.2145377384581342E+000 <-- R + O 6 -1.2060114174679968E+000 3.1493424087124491E+000 5.6176496554141648E+000 <-- R + Si 1 -3.8631221898446788E+000 2.2303044505684162E+000 6.8057313331669027E+000 <-- R + Si 2 9.8262964867279758E-005 -4.4607929395129560E+000 3.4028353928350574E+000 <-- R + Si:A 1 3.8616790388793820E+000 2.2303476129907844E+000 -2.5193290023608437E-004 <-- R + O 1 -9.2081228674930271E-005 -6.3233752038665116E-005 -7.7577768541441214E-005 <-- V + O 2 9.8605611134163277E-005 -4.3477333369266380E-005 -9.8060723231410191E-005 <-- V + O 3 -9.9013044897541524E-006 9.1440177447589763E-005 -1.0072038049373945E-004 <-- V + O 4 -8.0973773174126365E-005 -4.4748783216565211E-005 9.2258016669601175E-005 <-- V + O 5 2.4046075349091329E-005 1.0451095139183988E-004 9.4429622676116642E-005 <-- V + O 6 7.2261696467594593E-005 -7.0378576454143638E-005 1.1212854610383459E-004 <-- V + Si 1 1.1779697220315277E-005 -1.0025270995524918E-005 9.6959768290929870E-006 <-- V + Si 2 4.8612875069927977E-006 1.1445626152612783E-005 3.2001188694496583E-006 <-- V + Si:A 1 -1.6699860614063502E-004 -6.1075030161167923E-005 -9.5953865183149151E-006 <-- V + O 1 -1.0486779171999656E-001 -9.9478687162996279E-002 -1.2777913052122949E-001 <-- F + O 2 1.3807085172639577E-001 -3.5957264692911849E-002 -1.2614139829093249E-001 <-- F + O 3 -3.6436789369642966E-002 1.3838604775049584E-001 -1.2850276114254849E-001 <-- F + O 4 -1.3803823929320475E-001 -4.0879411577751941E-002 1.2793836181928828E-001 <-- F + O 5 3.7363133241094360E-002 1.3759562619440566E-001 1.2554934499288409E-001 <-- F + O 6 1.0168950186912341E-001 -1.0062507088293626E-001 1.2838591189027737E-001 <-- F + Si 1 1.7367796704273915E-002 -9.1794671698055691E-003 6.6690851303129834E-004 <-- F + Si 2 5.3275869283138475E-004 1.9837223447443077E-002 -5.7449533508954287E-004 <-- F + Si:A 1 -1.5681221850874571E-002 -9.6989959059426631E-003 4.5725807431890915E-004 <-- F + + 4.1341373432260909E+001 + -9.3249000144689646E+001 -9.3242228262498514E+001 6.7718821911243524E-003 <-- E + 5.0162090304624828E-004 <-- T + 5.9316301132297504E-006 <-- P + 8.0354578804424115E+000 -4.6392737703353273E+000 0.0000000000000000E+000 <-- h + 0.0000000000000000E+000 9.2785475406706510E+000 0.0000000000000000E+000 <-- h + 0.0000000000000000E+000 0.0000000000000000E+000 1.0208300540485364E+001 <-- h + O 1 1.2029534432675988E+000 3.1474459007350939E+000 1.1860541722888494E+000 <-- R + O 2 -3.3273356573109374E+000 -5.3174245195154191E-001 7.9907410724669248E+000 <-- R + O 3 2.1242426074486209E+000 -2.6163347690921874E+000 4.5878642717543885E+000 <-- R + O 4 3.3280645817083401E+000 -5.3179501543448149E-001 -1.1854472706689052E+000 <-- R + O 5 -2.1236578431944122E+000 -2.6157944053455102E+000 2.2174093533344137E+000 <-- R + O 6 -1.2037728099498350E+000 3.1471505238808248E+000 5.6209078979656422E+000 <-- R + Si 1 -3.8628062201132018E+000 2.2300589156881299E+000 6.8059345386557926E+000 <-- R + Si 2 2.0097230218817387E-004 -4.4604735704152896E+000 3.4028991441376650E+000 <-- R + Si:A 1 3.8563892572357790E+000 2.2279484485308361E+000 -3.9668645728053867E-004 <-- R + O 1 -1.6744718385210074E-004 -1.3323602555873043E-004 -1.6741445220381211E-004 <-- V + O 2 1.9633534210505794E-004 -6.9945316392036507E-005 -1.8638626339306775E-004 <-- V + O 3 -3.5177359611152602E-005 1.8966501555924394E-004 -1.9137842661360184E-004 <-- V + O 4 -1.7894485716790713E-004 -7.4768353947809877E-005 1.8226052900594000E-004 <-- V + O 5 4.9495439210326962E-005 2.0238341800869373E-004 1.8217783374621519E-004 <-- V + O 6 1.4478409401164622E-004 -1.4128181134685829E-004 2.0264078033204177E-004 <-- V + Si 1 1.8355349489729965E-005 -1.3594142831070229E-005 9.9277097288855268E-006 <-- V + Si 2 4.9441884957091092E-006 1.9012078228406490E-005 3.0349128866416705E-006 <-- V + Si:A 1 -3.0742135042002296E-004 -1.5261624481761475E-004 -2.5473555106663677E-006 <-- V + O 1 -1.0780073742142918E-001 -9.8054542676272838E-002 -1.2572306861506316E-001 <-- F + O 2 1.3770404013436877E-001 -3.8730397734510508E-002 -1.2309663853410371E-001 <-- F + O 3 -3.4887477038562931E-002 1.3878594320023865E-001 -1.2731716813218757E-001 <-- F + O 4 -1.3841770533548875E-001 -4.3830162365320391E-002 1.2603177459849077E-001 <-- F + O 5 3.4450177785492392E-002 1.3858203877274142E-001 1.2205957788482966E-001 <-- F + O 6 1.0295504326065352E-001 -9.9450502239638222E-002 1.2702256369218151E-001 <-- F + Si 1 1.5204504736265200E-002 -8.4988352201684977E-003 4.8097363713062429E-004 <-- F + Si 2 -1.2211106677819208E-004 1.7642975892550799E-002 -2.4384767505282394E-004 <-- F + Si:A 1 -9.0857350545208698E-003 -6.4465176296204223E-003 7.8583314377477572E-004 <-- F + + 6.2012060148391363E+001 + -9.3257128335407970E+001 -9.3242244817077420E+001 1.4883518330546628E-002 <-- E + 1.1024828392997503E-003 <-- T + 1.3036778111111741E-005 <-- P + 8.0354578804424115E+000 -4.6392737703353273E+000 0.0000000000000000E+000 <-- h + 0.0000000000000000E+000 9.2785475406706510E+000 0.0000000000000000E+000 <-- h + 0.0000000000000000E+000 0.0000000000000000E+000 1.0208300540485364E+001 <-- h + O 1 1.1987025195745020E+000 3.1439735392192469E+000 1.1816726382844165E+000 <-- R + O 2 -3.3222685441441282E+000 -5.3347198241658611E-001 7.9859866175503411E+000 <-- R + O 3 2.1232599051681942E+000 -2.6113976108643522E+000 4.5829757086457477E+000 <-- R + O 4 3.3233517139781186E+000 -5.3366159883013276E-001 -1.1807565966903388E+000 <-- R + O 5 -2.1223823797352734E+000 -2.6105958426712701E+000 2.2220692203141170E+000 <-- R + O 6 -1.2000258441704097E+000 3.1435016245903720E+000 5.6260271035864760E+000 <-- R + Si 1 -3.8623633544869436E+000 2.2297424500331449E+000 6.8061417583221306E+000 <-- R + Si 2 3.0266250778787830E-004 -4.4600069540871914E+000 3.4029608603020387E+000 <-- R + Si:A 1 3.8489698180306173E+000 2.2240382478219507E+000 -3.5724407566727030E-004 <-- R + O 1 -2.4548276293393943E-004 -2.0184848346898281E-004 -2.5536800322025741E-004 <-- V + O 2 2.9347974711015139E-004 -9.8874830902351943E-005 -2.7184481860344521E-004 <-- V + O 3 -5.9015555620564826E-005 2.8827049974454515E-004 -2.8094051051780970E-004 <-- V + O 4 -2.7705690440885176E-004 -1.0764292581247288E-004 2.7045635671808034E-004 <-- V + O 5 7.2389873655565414E-005 3.0093464791000515E-004 2.6684897914676961E-004 <-- V + O 6 2.1844134583780161E-004 -2.1109379135380839E-004 2.9195015187915397E-004 <-- V + Si 1 2.3820484074386016E-005 -1.6761394528779029E-005 1.0066445787512066E-005 <-- V + Si 2 4.7558352734435164E-006 2.5436052819657280E-005 3.0177500609360602E-006 <-- V + Si:A 1 -3.5499034553515622E-004 -1.9493541406456492E-004 6.8029897255088947E-006 <-- V + O 1 -1.1240096751312403E-001 -9.5556889305835363E-002 -1.2246528491221749E-001 <-- F + O 2 1.3641917210629947E-001 -4.2903242882413248E-002 -1.1805130680033825E-001 <-- F + O 3 -3.2379421799101832E-002 1.3946015926962504E-001 -1.2541016221177265E-001 <-- F + O 4 -1.3843601102404623E-001 -4.8935686991681840E-002 1.2284023812739737E-001 <-- F + O 5 3.0153603690477416E-002 1.3951096832735477E-001 1.1686644528737154E-001 <-- F + O 6 1.0489184688548386E-001 -9.7545755150409863E-002 1.2499165998242039E-001 <-- F + Si 1 1.1866879791246881E-002 -7.1900535484301547E-003 2.0625137677027173E-004 <-- F + Si 2 -8.1089111788231946E-004 1.4177994599736198E-002 1.5883211924936190E-004 <-- F + Si:A 1 6.9578898064681378E-004 -1.0174943179455359E-003 8.6332703111944794E-004 <-- F + + 8.2682746864521818E+001 + -9.3268206401361454E+001 -9.3242254425685189E+001 2.5951975676264259E-002 <-- E + 1.9223685686121674E-003 <-- T + 2.2731866278018702E-005 <-- P + 8.0354578804424115E+000 -4.6392737703353273E+000 0.0000000000000000E+000 <-- h + 0.0000000000000000E+000 9.2785475406706510E+000 0.0000000000000000E+000 <-- h + 0.0000000000000000E+000 0.0000000000000000E+000 1.0208300540485364E+001 <-- h + O 1 1.1928048486939633E+000 3.1391012072032658E+000 1.1754969083050697E+000 <-- R + O 2 -3.3152028014908512E+000 -5.3583007325892762E-001 7.9795026343054154E+000 <-- R + O 3 2.1218028233253987E+000 -2.6044172707127435E+000 4.5762498051968219E+000 <-- R + O 4 3.3166106687611876E+000 -5.3624512182783612E-001 -1.1742662334286942E+000 <-- R + O 5 -2.1206651463949036E+000 -2.6033533536875568E+000 2.2284412566313376E+000 <-- R + O 6 -1.1947421446985089E+000 3.1384236166232347E+000 5.6329775182180839E+000 <-- R + Si 1 -3.8618214485857463E+000 2.2293659766176712E+000 6.8063506993502294E+000 <-- R + Si 2 3.9758506420992096E-004 -4.4594220090570298E+000 3.4030239020698603E+000 <-- R + Si:A 1 3.8417134687961627E+000 2.2198895507828214E+000 -1.1544151858244141E-004 <-- R + O 1 -3.2685819893433441E-004 -2.6876186614226599E-004 -3.4078483054927227E-004 <-- V + O 2 3.8954508805515468E-004 -1.3100401021887538E-004 -3.5379363464936602E-004 <-- V + O 3 -8.0769260925643070E-005 3.8751120404065546E-004 -3.6910909110375953E-004 <-- V + O 4 -3.7527947939475779E-004 -1.4423511898715104E-004 3.5610904188202721E-004 <-- V + O 5 9.2050751644306435E-005 4.0012255782430198E-004 3.4800734303965794E-004 <-- V + O 6 2.9374652216685148E-004 -2.7936691664038937E-004 3.7974332385677699E-004 <-- V + Si 1 2.7729936261243689E-005 -1.9268133538769577E-005 1.0077761814288654E-005 <-- V + Si 2 4.3029197935966771E-006 3.0210217129787349E-005 3.2211022689976550E-006 <-- V + Si:A 1 -2.8695236382430211E-004 -1.7095327317467410E-004 1.5653148990424518E-005 <-- V + O 1 -1.1722518453076974E-001 -9.3260072405214542E-002 -1.1856491220112500E-001 <-- F + O 2 1.3465912461556084E-001 -4.7759249110203864E-002 -1.1319281572683768E-001 <-- F + O 3 -2.9005436917694607E-002 1.4057841469919674E-001 -1.2338496425643256E-001 <-- F + O 4 -1.3872959381212244E-001 -5.4320589429465618E-002 1.1885550536857312E-001 <-- F + O 5 2.5325690556710089E-002 1.4037862984064539E-001 1.1214717015809991E-001 <-- F + O 6 1.0760517579520210E-001 -9.5108144086359342E-002 1.2274413410723004E-001 <-- F + Si 1 7.4984774205385596E-003 -5.2270049152526588E-003 -1.5019776867565793E-004 <-- F + Si 2 -1.4326124817949204E-003 9.4706888562796371E-003 8.4846710342852453E-004 <-- F + Si:A 1 1.1304359354370130E-002 5.2473265503742358E-003 6.9761321573930568E-004 <-- F Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/tests/files/.DS_Store and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/tests/files/.DS_Store differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/tests/files/GSD/E.gsd and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/tests/files/GSD/E.gsd differ diff -Nru ovito-2.8.1+dfsg2/tests/files/LAMMPS/bond_types.0.data ovito-2.9.0+dfsg1/tests/files/LAMMPS/bond_types.0.data --- ovito-2.8.1+dfsg2/tests/files/LAMMPS/bond_types.0.data 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/files/LAMMPS/bond_types.0.data 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,62 @@ +# LAMMPS data file written by OVITO +16 atoms +32 bonds +2 atom types +2 bond types +0.0 5.0900002 xlo xhi +0.0 6.7399998 ylo yhi +0.0 4.5300002 zlo zhi + +Atoms # bond + +1 1 1 0.18324 1.685 3.8505 +2 1 1 4.9067602 5.0549998 0.6795001 +3 1 1 2.3617599 5.0549998 1.5855 +4 1 1 2.72824 1.685 2.9444998 +5 1 1 0.94674 0.42462 1.4858399 +6 1 1 4.14326 6.3153796 3.0441597 +7 1 1 3.4917403 2.9453798 0.77916 +8 1 1 1.59826 3.7946203 3.75084 +9 1 1 4.14326 3.7946203 3.0441597 +10 1 1 0.94674 2.9453798 1.4858399 +11 1 1 1.59826 6.3153796 3.75084 +12 1 1 3.4917403 0.42462 0.77916 +13 1 2 4.5300999 1.685 2.0385001 +14 1 2 0.5599001 5.0549998 2.4915002 +15 1 2 3.1048999 5.0549998 4.3035002 +16 1 2 1.9851 1.685 0.2265 + +Bonds + +1 1 1 13 +2 1 1 16 +3 1 2 15 +4 2 2 14 +5 1 3 14 +6 1 3 15 +7 1 4 13 +8 1 4 16 +9 2 5 16 +10 1 5 13 +11 1 5 14 +12 1 6 15 +13 2 6 13 +14 1 6 14 +15 1 7 13 +16 1 7 16 +17 1 7 15 +18 1 8 14 +19 1 8 16 +20 1 8 15 +21 1 9 15 +22 1 9 13 +23 1 9 14 +24 1 10 16 +25 1 10 13 +26 1 10 14 +27 1 11 14 +28 1 11 16 +29 1 11 15 +30 1 12 13 +31 1 12 16 +32 1 12 15 diff -Nru ovito-2.8.1+dfsg2/tests/files/LAMMPS/bond_types.1.data ovito-2.9.0+dfsg1/tests/files/LAMMPS/bond_types.1.data --- ovito-2.8.1+dfsg2/tests/files/LAMMPS/bond_types.1.data 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/files/LAMMPS/bond_types.1.data 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,62 @@ +# LAMMPS data file written by OVITO +16 atoms +32 bonds +2 atom types +2 bond types +0.0 5.0900002 xlo xhi +0.0 6.7399998 ylo yhi +0.0 4.5300002 zlo zhi + +Atoms # bond + +1 1 1 0.18324 1.685 3.8505 +2 1 1 4.9067602 5.0549998 0.6795001 +3 1 1 2.3617599 5.0549998 1.5855 +4 1 1 2.72824 1.685 2.9444998 +5 1 1 0.94674 0.42462 1.4858399 +6 1 1 4.14326 6.3153796 3.0441597 +7 1 1 3.4917403 2.9453798 0.77916 +8 1 1 1.59826 3.7946203 3.75084 +9 1 1 4.14326 3.7946203 3.0441597 +10 1 1 0.94674 2.9453798 1.4858399 +11 1 1 1.59826 6.3153796 3.75084 +12 1 1 3.4917403 0.42462 0.77916 +13 1 2 4.5300999 1.685 2.0385001 +14 1 2 0.5599001 5.0549998 2.4915002 +15 1 2 3.1048999 5.0549998 4.3035002 +16 1 2 1.9851 1.685 0.2265 + +Bonds + +1 1 1 13 +2 1 1 16 +3 1 2 15 +4 1 2 14 +5 1 3 14 +6 1 3 15 +7 1 4 13 +8 1 4 16 +9 1 5 16 +10 1 5 13 +11 1 5 14 +12 1 6 15 +13 1 6 13 +14 1 6 14 +15 1 7 13 +16 1 7 16 +17 1 7 15 +18 1 8 14 +19 1 8 16 +20 1 8 15 +21 1 9 15 +22 1 9 13 +23 1 9 14 +24 1 10 16 +25 1 10 13 +26 1 10 14 +27 1 11 14 +28 1 11 16 +29 1 11 15 +30 1 12 13 +31 1 12 16 +32 1 12 15 diff -Nru ovito-2.8.1+dfsg2/tests/files/LAMMPS/bond_types.2.data ovito-2.9.0+dfsg1/tests/files/LAMMPS/bond_types.2.data --- ovito-2.8.1+dfsg2/tests/files/LAMMPS/bond_types.2.data 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/files/LAMMPS/bond_types.2.data 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,30 @@ +# LAMMPS data file written by OVITO +16 atoms +0 bonds +2 atom types +2 bond types +0.0 5.0900002 xlo xhi +0.0 6.7399998 ylo yhi +0.0 4.5300002 zlo zhi + +Atoms # bond + +1 1 1 0.18324 1.685 3.8505 +2 1 1 4.9067602 5.0549998 0.6795001 +3 1 1 2.3617599 5.0549998 1.5855 +4 1 1 2.72824 1.685 2.9444998 +5 1 1 0.94674 0.42462 1.4858399 +6 1 1 4.14326 6.3153796 3.0441597 +7 1 1 3.4917403 2.9453798 0.77916 +8 1 1 1.59826 3.7946203 3.75084 +9 1 1 4.14326 3.7946203 3.0441597 +10 1 1 0.94674 2.9453798 1.4858399 +11 1 1 1.59826 6.3153796 3.75084 +12 1 1 3.4917403 0.42462 0.77916 +13 1 2 4.5300999 1.685 2.0385001 +14 1 2 0.5599001 5.0549998 2.4915002 +15 1 2 3.1048999 5.0549998 4.3035002 +16 1 2 1.9851 1.685 0.2265 + +Bonds + diff -Nru ovito-2.8.1+dfsg2/tests/files/LAMMPS/bond_types.3.data ovito-2.9.0+dfsg1/tests/files/LAMMPS/bond_types.3.data --- ovito-2.8.1+dfsg2/tests/files/LAMMPS/bond_types.3.data 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/files/LAMMPS/bond_types.3.data 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,62 @@ +# LAMMPS data file written by OVITO +16 atoms +32 bonds +2 atom types +2 bond types +0.0 5.0900002 xlo xhi +0.0 6.7399998 ylo yhi +0.0 4.5300002 zlo zhi + +Atoms # bond + +1 1 1 0.18324 1.685 3.8505 +2 1 1 4.9067602 5.0549998 0.6795001 +3 1 1 2.3617599 5.0549998 1.5855 +4 1 1 2.72824 1.685 2.9444998 +5 1 1 0.94674 0.42462 1.4858399 +6 1 1 4.14326 6.3153796 3.0441597 +7 1 1 3.4917403 2.9453798 0.77916 +8 1 1 1.59826 3.7946203 3.75084 +9 1 1 4.14326 3.7946203 3.0441597 +10 1 1 0.94674 2.9453798 1.4858399 +11 1 1 1.59826 6.3153796 3.75084 +12 1 1 3.4917403 0.42462 0.77916 +13 1 2 4.5300999 1.685 2.0385001 +14 1 2 0.5599001 5.0549998 2.4915002 +15 1 2 3.1048999 5.0549998 4.3035002 +16 1 2 1.9851 1.685 0.2265 + +Bonds + +1 1 1 13 +2 1 1 16 +3 1 2 15 +4 1 2 14 +5 1 3 14 +6 1 3 15 +7 1 4 13 +8 1 4 16 +9 1 5 16 +10 1 5 13 +11 1 5 14 +12 1 6 15 +13 1 6 13 +14 1 6 14 +15 1 7 13 +16 1 7 16 +17 1 7 15 +18 1 8 14 +19 1 8 16 +20 1 8 15 +21 1 9 15 +22 1 9 13 +23 1 9 14 +24 1 10 16 +25 1 10 13 +26 1 10 14 +27 2 11 14 +28 2 11 16 +29 2 11 15 +30 2 12 13 +31 2 12 16 +32 2 12 15 diff -Nru ovito-2.8.1+dfsg2/tests/files/LAMMPS/very_small_fp_number.dump ovito-2.9.0+dfsg1/tests/files/LAMMPS/very_small_fp_number.dump --- ovito-2.8.1+dfsg2/tests/files/LAMMPS/very_small_fp_number.dump 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/files/LAMMPS/very_small_fp_number.dump 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,14 @@ +ITEM: TIMESTEP +1 +ITEM: NUMBER OF ATOMS +5 +ITEM: BOX BOUNDS ff ff ff +-20 20 +-20 20 +-8.00066 8.00066 +ITEM: ATOMS id x y z radius f_fixEleph[1] f_fixEleph[2] f_fixEleph[3] +2326 -6.3494 -7.8912 -7.14365 1.25 0.277993 0.945923 6.69514e-204 +1564 -5.46345 -7.91925 -7.6051 1.25 -0.0159838 0.923502 0.680096 +4034 -4.52814 -7.96294 -7.95474 1.25 -0.114299 0.888722 0.916042 +2927 -4.69315 -7.72346 -6.99839 1.25 0.105174 0.79217 0.391069 +1605 -3.70769 -7.73025 -7.37291 1.25 -0.0128596 0.789221 0.561434 \ No newline at end of file Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/tests/files/POSCAR/CHGCAR.nospin.gz and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/tests/files/POSCAR/CHGCAR.nospin.gz differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/tests/files/VoroTop/FCC-BCC-ICOS-both-HCP.gz and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/tests/files/VoroTop/FCC-BCC-ICOS-both-HCP.gz differ Binary files /tmp/tmpAMvXIk/pQBo0jpj8y/ovito-2.8.1+dfsg2/tests/files/VoroTop/FCC.gz and /tmp/tmpAMvXIk/qVyFngmAii/ovito-2.9.0+dfsg1/tests/files/VoroTop/FCC.gz differ diff -Nru ovito-2.8.1+dfsg2/tests/files/VTK/box_a.vtk ovito-2.9.0+dfsg1/tests/files/VTK/box_a.vtk --- ovito-2.8.1+dfsg2/tests/files/VTK/box_a.vtk 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/files/VTK/box_a.vtk 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,55 @@ +# vtk DataFile Version 4.1 +vtk output +ASCII +DATASET POLYDATA +POINTS 24 float +-789.885 -220.352 -432.073 -789.885 -220.352 432.073 -789.885 220.352 -432.073 +-789.885 220.352 432.073 789.885 -220.352 -432.073 789.885 -220.352 432.073 +789.885 220.352 -432.073 789.885 220.352 432.073 -789.885 -220.352 -432.073 +-789.885 -220.352 432.073 789.885 -220.352 -432.073 789.885 -220.352 432.073 +-789.885 220.352 -432.073 -789.885 220.352 432.073 789.885 220.352 -432.073 +789.885 220.352 432.073 -789.885 -220.352 -432.073 789.885 -220.352 -432.073 +-789.885 220.352 -432.073 789.885 220.352 -432.073 -789.885 -220.352 432.073 +789.885 -220.352 432.073 -789.885 220.352 432.073 789.885 220.352 432.073 + +METADATA +INFORMATION 1 +NAME L2_NORM_RANGE LOCATION vtkDataArray +DATA 2 926.909 926.909 + +POLYGONS 6 30 +4 0 1 3 2 +4 4 6 7 5 +4 8 10 11 9 +4 12 13 15 14 +4 16 18 19 17 +4 20 21 23 22 + +POINT_DATA 24 +NORMALS Normals float +-1 0 0 -1 0 0 -1 0 0 +-1 0 0 1 0 0 1 0 0 +1 0 0 1 0 0 0 -1 0 +0 -1 0 0 -1 0 0 -1 0 +0 1 0 0 1 0 0 1 0 +0 1 0 0 0 -1 0 0 -1 +0 0 -1 0 0 -1 0 0 1 +0 0 1 0 0 1 0 0 1 + +METADATA +INFORMATION 1 +NAME L2_NORM_RANGE LOCATION vtkDataArray +DATA 2 1 1 + +TEXTURE_COORDINATES TCoords 2 float +-431.573 -219.852 432.573 -219.852 -431.573 220.852 432.573 220.852 431.573 +-219.852 -432.573 -219.852 431.573 220.852 -432.573 220.852 789.385 431.573 +789.385 -432.573 -790.385 431.573 -790.385 -432.573 -789.385 431.573 -789.385 +-432.573 790.385 431.573 790.385 -432.573 789.385 -219.852 -790.385 -219.852 +789.385 220.852 -790.385 220.852 -789.385 -219.852 790.385 -219.852 -789.385 +220.852 790.385 220.852 +METADATA +INFORMATION 1 +NAME L2_NORM_RANGE LOCATION vtkDataArray +DATA 2 484.345 901.015 + diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/affine_transformation_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/affine_transformation_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/affine_transformation_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/affine_transformation_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * import numpy as np diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/ambient_occlusion_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/ambient_occlusion_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/ambient_occlusion_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/ambient_occlusion_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,7 +1,6 @@ -from ovito import * +import ovito from ovito.io import * from ovito.modifiers import * -import numpy as np node = import_file("../../files/CFG/shear.void.120.cfg") @@ -18,4 +17,4 @@ modifier.sample_count = 30 if not ovito.headless_mode: # Ambient occlusion modifier requires OpenGL support. - node.compute() \ No newline at end of file + node.compute() diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/assign_color_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/assign_color_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/assign_color_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/assign_color_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/atomic_strain_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/atomic_strain_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/atomic_strain_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/atomic_strain_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * import numpy as np @@ -14,7 +13,7 @@ # Calculate the atomic strain. modifier = AtomicStrainModifier() node.modifiers.append(modifier) -print(type(modifier.reference)) +print("Loading reference configuration") modifier.reference.load("../../files/CFG/shear.void.120.cfg") print("Parameter defaults:") diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/avi_output.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/avi_output.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/avi_output.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/avi_output.py 2017-07-27 16:52:45.000000000 +0000 @@ -4,16 +4,19 @@ import os import os.path -import_file("../../files/LAMMPS/animation.dump.gz", multiple_frames = True) +node = import_file("../../files/LAMMPS/animation.dump.gz", multiple_frames = True) +node.add_to_scene() vp = ovito.dataset.viewports.active_vp -if os.path.isfile("movie.avi"): - os.remove("movie.avi") -assert(not os.path.isfile("movie.avi")) +output_file = "_movie.avi" + +if os.path.isfile(output_file): + os.remove(output_file) +assert(not os.path.isfile(output_file)) settings = RenderSettings( - filename = "movie.avi", + filename = output_file, size = (64, 64), range = RenderSettings.Range.ANIMATION ) @@ -21,5 +24,5 @@ settings.renderer = TachyonRenderer(ambient_occlusion = False, antialiasing = False) vp.render(settings) -assert(os.path.isfile("movie.avi")) -os.remove("movie.avi") +assert(os.path.isfile(output_file)) +os.remove(output_file) diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/binandreduce_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/binandreduce_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/binandreduce_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/binandreduce_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * import numpy diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/bond_angle_analysis_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/bond_angle_analysis_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/bond_angle_analysis_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/bond_angle_analysis_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import BondAngleAnalysisModifier diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/bond_properties.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/bond_properties.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/bond_properties.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/bond_properties.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.data import * import numpy diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/bonds_pbc_vectors.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/bonds_pbc_vectors.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/bonds_pbc_vectors.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/bonds_pbc_vectors.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * import numpy diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/centrosymmetry_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/centrosymmetry_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/centrosymmetry_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/centrosymmetry_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * import numpy as np diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/cluster_analysis_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/cluster_analysis_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/cluster_analysis_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/cluster_analysis_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * import numpy as np @@ -25,6 +24,8 @@ print(" cutoff: {}".format(modifier.cutoff)) modifier.cutoff = 2.8 +print(" neighbor_mode: {}".format(modifier.neighbor_mode)) +modifier.neighbor_mode = ClusterAnalysisModifier.NeighborMode.CutoffRange print(" sort_by_size: {}".format(modifier.sort_by_size)) modifier.sort_by_size = False @@ -39,4 +40,9 @@ modifier.sort_by_size = True node.compute() print(node.output.attributes['ClusterAnalysis.largest_size']) -assert(node.output.attributes['ClusterAnalysis.largest_size'] >= 1) \ No newline at end of file +assert(node.output.attributes['ClusterAnalysis.largest_size'] >= 1) + +node.modifiers.insert(2, VoronoiAnalysisModifier(generate_bonds=True)) +modifier.neighbor_mode = ClusterAnalysisModifier.NeighborMode.Bonding +node.compute() +assert(node.output.attributes['ClusterAnalysis.largest_size'] == node.output.number_of_particles) \ No newline at end of file diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/color_coding_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/color_coding_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/color_coding_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/color_coding_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * @@ -29,3 +28,16 @@ modifier.gradient = ColorCodingModifier.Custom("../../../doc/manual/images/modifiers/color_coding_custom_map.png") print(node.compute().particle_properties.color.array) + +modifier.particle_property = "Position.X" +node.compute() + +modifier = ColorCodingModifier( + particle_property = "Position.Z", + bond_property = "Length", + start_value = 0.0, + end_value = 0.0, + only_selected = True, + gradient = ColorCodingModifier.Grayscale(), + assign_to = ColorCodingModifier.AssignmentMode.Bonds +) diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/common_neighbor_analysis_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/common_neighbor_analysis_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/common_neighbor_analysis_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/common_neighbor_analysis_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.data import * from ovito.modifiers import * diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/construct_surface_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/construct_surface_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/construct_surface_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/construct_surface_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,8 +1,12 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * import numpy as np +import sys +import os + +if "ovito.plugins.CrystalAnalysis" not in sys.modules: sys.exit() + node = import_file("../../files/CFG/lammps_dumpi-42-1100-510000.cfg") modifier = ConstructSurfaceModifier() @@ -32,3 +36,11 @@ print(" solid_volume= {}".format(node.output.attributes['ConstructSurfaceMesh.solid_volume'])) print(" surface_area= {}".format(node.output.attributes['ConstructSurfaceMesh.surface_area'])) print(node.output) + +surface_mesh = node.output.surface + +# Backward compatibility with Ovito 2.8.2: +surface_mesh.export_vtk("_surface_mesh.vtk", node.output.cell) +surface_mesh.export_cap_vtk("_surfacecap_mesh.vtk", node.output.cell) +os.remove("_surface_mesh.vtk") +os.remove("_surfacecap_mesh.vtk") diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/coordination_number_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/coordination_number_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/coordination_number_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/coordination_number_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * import numpy as np diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/create_bonds_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/create_bonds_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/create_bonds_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/create_bonds_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.data import * from ovito.modifiers import * diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/create_new_particle_property.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/create_new_particle_property.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/create_new_particle_property.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/create_new_particle_property.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,4 @@ -from ovito import * +import ovito from ovito.data import * # The number of particles we are going to create. @@ -47,11 +47,11 @@ data.add(bonds) # Create a node and insert it into the scene. -node = ObjectNode() +node = ovito.ObjectNode() node.source = data node.add_to_scene() # Select the new node and adjust cameras of all viewports to show it. -dataset.selected_node = node -for vp in dataset.viewports: +ovito.dataset.selected_node = node +for vp in ovito.dataset.viewports: vp.zoom_all() diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/data_collection.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/data_collection.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/data_collection.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/data_collection.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.data import * diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/dataset.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/dataset.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/dataset.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/dataset.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,4 @@ -from ovito import * +import ovito print(ovito.dataset) assert(isinstance(ovito.dataset, ovito.DataSet)) @@ -9,14 +9,14 @@ assert(len(scene_nodes) == 0) assert(ovito.dataset.selected_node is None) -o1 = ObjectNode() +o1 = ovito.ObjectNode() o1.add_to_scene() assert(len(scene_nodes) == 1) assert(o1 in scene_nodes) assert(scene_nodes[0] == o1) assert(ovito.dataset.selected_node == o1) -o2 = ObjectNode() +o2 = ovito.ObjectNode() scene_nodes.append(o2) assert(len(scene_nodes) == 2) assert(scene_nodes[1] == o2) @@ -28,5 +28,3 @@ del scene_nodes[0] assert(len(scene_nodes) == 0) - -ovito.dataset.save("../../files/output.ovito") \ No newline at end of file diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/dislocation_analysis_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/dislocation_analysis_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/dislocation_analysis_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/dislocation_analysis_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,8 +1,10 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * import numpy as np +import sys +if "ovito.plugins.CrystalAnalysis" not in sys.modules: sys.exit() + node = import_file("../../files/LAMMPS/frank_read.dump.gz") modifier = DislocationAnalysisModifier() diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/elastic_strain_calculation_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/elastic_strain_calculation_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/elastic_strain_calculation_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/elastic_strain_calculation_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,8 +1,10 @@ -from ovito import * from ovito.io import * from ovito.data import * from ovito.modifiers import * +import sys +if "ovito.plugins.CrystalAnalysis" not in sys.modules: sys.exit() + import numpy node = import_file("../../files/CFG/fcc_coherent_twin.0.cfg") diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/expand_selection_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/expand_selection_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/expand_selection_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/expand_selection_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * import numpy as np diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/export_file.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/export_file.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/export_file.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/export_file.py 2017-07-27 16:52:45.000000000 +0000 @@ -9,22 +9,22 @@ node1 = import_file(test_data_dir + "LAMMPS/class2.data", atom_style = "full") print(node1.source) -export_file(node1, "test.data", "lammps_data", atom_style = "full") -export_file(node1, "test.data", "lammps_data", atom_style = "bond") -export_file(node1, "test.data", "lammps_dump", columns = ["Particle Identifier", "Particle Type", "Position.X", "Position.Y", "Position.Z"]) -export_file(node1, "test.data", "fhi-aims") -export_file(node1, "test.data", "imd") -export_file(node1, "test.data", "vasp") -export_file(node1, "test.data", "povray") -export_file(node1, "test.data", "xyz", columns = ["Position.X", "Position.Y", "Position.Z"]) +export_file(node1, "_export_file_test.data", "lammps_data", atom_style = "full") +export_file(node1, "_export_file_test.data", "lammps_data", atom_style = "bond") +export_file(node1, "_export_file_test.data", "lammps_dump", columns = ["Particle Identifier", "Particle Type", "Position.X", "Position.Y", "Position.Z"]) +export_file(node1, "_export_file_test.data", "fhi-aims") +export_file(node1, "_export_file_test.data", "imd") +export_file(node1, "_export_file_test.data", "vasp") +export_file(node1, "_export_file_test.data", "povray") +export_file(node1, "_export_file_test.data", "xyz", columns = ["Position.X", "Position.Y", "Position.Z"]) ovito.dataset.anim.last_frame = 7 -export_file(node1, "test.dump", "lammps_dump", columns = ["Position.X", "Position.Y", "Position.Z"], multiple_frames = True) -export_file(node1, "test.*.dump", "lammps_dump", columns = ["Position.X", "Position.Y", "Position.Z"], multiple_frames = True, start_frame = 1, end_frame = 5, every_nth_frame = 2) -os.remove("test.data") -os.remove("test.dump") -os.remove("test.1.dump") -os.remove("test.3.dump") -os.remove("test.5.dump") +export_file(node1, "_export_file_test.dump", "lammps_dump", columns = ["Position.X", "Position.Y", "Position.Z"], multiple_frames = True) +export_file(node1, "_export_file_test.*.dump", "lammps_dump", columns = ["Position.X", "Position.Y", "Position.Z"], multiple_frames = True, start_frame = 1, end_frame = 5, every_nth_frame = 2) +os.remove("_export_file_test.data") +os.remove("_export_file_test.dump") +os.remove("_export_file_test.1.dump") +os.remove("_export_file_test.3.dump") +os.remove("_export_file_test.5.dump") for i in range(ovito.dataset.anim.last_frame + 1): - export_file(node1, "test.%i.dump" % i, "lammps_dump", columns = ["Position.X", "Position.Y", "Position.Z"], frame = i) - os.remove("test.%i.dump" % i) \ No newline at end of file + export_file(node1, "_export_file_test.%i.dump" % i, "lammps_dump", columns = ["Position.X", "Position.Y", "Position.Z"], frame = i) + os.remove("_export_file_test.%i.dump" % i) \ No newline at end of file diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/export_file_text.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/export_file_text.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/export_file_text.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/export_file_text.py 2017-07-27 16:52:45.000000000 +0000 @@ -6,5 +6,5 @@ test_data_dir = "../../files/" node = import_file(test_data_dir + "LAMMPS/animation1.dump", multiple_frames = True) -export_file(node, "test.data", "txt", columns = ["Timestep", "SourceFrame"], multiple_frames = True) -os.remove("test.data") \ No newline at end of file +export_file(node, "_export_file_text.data", "txt", columns = ["Timestep", "SourceFrame"], multiple_frames = True) +os.remove("_export_file_text.data") \ No newline at end of file diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/file_source.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/file_source.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/file_source.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/file_source.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * from ovito.data import * @@ -7,9 +6,12 @@ node = import_file("../../files/CFG/shear.void.120.cfg") file_source = node.source -print(file_source.source_path) +print("source_path:", file_source.source_path) +print("loaded_file:", file_source.loaded_file) +print("num_frames:", file_source.num_frames) print(file_source) assert(isinstance(file_source, DataCollection)) assert(file_source.loaded_frame == 0) -assert(file_source.num_frames == True) +assert(file_source.num_frames == 1) assert(file_source.adjust_animation_interval == True) +assert(file_source.loaded_file.endswith("/shear.void.120.cfg")) \ No newline at end of file diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/freeze_property_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/freeze_property_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/freeze_property_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/freeze_property_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/global_namespace.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/global_namespace.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/global_namespace.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/global_namespace.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,11 +1,6 @@ -from ovito import * +import ovito assert(len(ovito.version) == 3) print("version_string=", ovito.version_string) print("gui_mode=", ovito.gui_mode) print("headless_mode=", ovito.headless_mode) - -# Progress display -progress = ovito.get_progress_display() -if progress is not None: - print(progress.canceled) \ No newline at end of file diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/histogram_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/histogram_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/histogram_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/histogram_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * import numpy @@ -22,8 +21,14 @@ print(" xrange_end: {}".format(modifier.xrange_end)) modifier.xrange_end = 50 -print(" property: {}".format(modifier.property)) -modifier.property = "Position.X" +print(" particle_property: {}".format(modifier.particle_property)) +modifier.particle_property = "Position.X" + +print(" bond_property: {}".format(modifier.bond_property)) +modifier.bond_property = "Length" + +print(" source_mode: {}".format(modifier.source_mode)) +modifier.source_mode = HistogramModifier.SourceMode.Particles node.compute() @@ -38,4 +43,3 @@ print(" xrange_end: {}".format(modifier.xrange_end)) #numpy.savetxt("histogram.txt", modifier.histogram) - diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/import_file.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/import_file.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/import_file.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/import_file.py 2017-07-27 16:52:45.000000000 +0000 @@ -7,10 +7,13 @@ assert(len(ovito.dataset.scene_nodes) == 0) import_file(test_data_dir + "CFG/fcc_coherent_twin.0.cfg") import_file(test_data_dir + "CFG/shear.void.120.cfg") +import_file(test_data_dir + "LAMMPS/very_small_fp_number.dump") import_file(test_data_dir + "Parcas/movie.0000000.parcas") import_file(test_data_dir + "IMD/nw2.imd.gz") import_file(test_data_dir + "FHI-aims/3_geometry.in.next_step") import_file(test_data_dir + "GSD/test.gsd") +node = import_file(test_data_dir + "GSD/E.gsd") +assert(node.source.num_frames == 5) import_file(test_data_dir + "GSD/triblock.gsd") import_file(test_data_dir + "PDB/SiShuffle.pdb") import_file(test_data_dir + "PDB/trjconv_gromacs.pdb") @@ -20,8 +23,14 @@ import_file(test_data_dir + "LAMMPS/atom_style_sphere.data.gz") import_file(test_data_dir + "LAMMPS/class2.data", atom_style = "full") import_file(test_data_dir + "LAMMPS/bonds.data.gz", atom_style = "bond") +import_file(test_data_dir + "CASTEP/test.cell") +node = import_file(test_data_dir + "CASTEP/quartz_alpha.geom") +assert(node.source.num_frames == 20) +node = import_file(test_data_dir + "CASTEP/test.md") +assert(node.source.num_frames == 5) import_file(test_data_dir + "VTK/mesh_test.vtk") import_file(test_data_dir + "VTK/ThomsonTet_Gr1_rotmatNonRand_unstructGrid.vtk") +import_file(test_data_dir + "VTK/box_a.vtk") node = import_file(test_data_dir + "LAMMPS/multi_sequence_*.dump") assert(ovito.dataset.anim.last_frame == 2) node = import_file(test_data_dir + "LAMMPS/shear.void.dump.bin", diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/isosurface_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/isosurface_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/isosurface_modifier.py 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/isosurface_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,22 @@ +from ovito.io import * +from ovito.modifiers import * + +node = import_file("../../files/POSCAR/CHGCAR.nospin.gz") + +modifier = CreateIsosurfaceModifier() +node.modifiers.append(modifier) + +print("Parameter defaults:") + +print(" isolevel: {}".format(modifier.isolevel)) +modifier.isolevel = 0.02 + +print(" field_quantity: {}".format(modifier.field_quantity)) +modifier.field_quantity = "Charge density" + +print(" mesh_display: {}".format(modifier.mesh_display)) + +node.compute() +print("Output:") + +print(node.output.surface) diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/mutable_particle_property.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/mutable_particle_property.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/mutable_particle_property.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/mutable_particle_property.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * from ovito.data import * diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/object_node.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/object_node.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/object_node.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/object_node.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/opengl_renderer.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/opengl_renderer.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/opengl_renderer.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/opengl_renderer.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,5 +1,4 @@ -# Import OVITO modules. -from ovito import * +import ovito from ovito.io import * from ovito.vis import OpenGLRenderer, RenderSettings @@ -15,4 +14,4 @@ renderer.antialiasing_level = 2 settings = RenderSettings(size = (100,100), renderer = renderer) - dataset.viewports.active_vp.render(settings) + ovito.dataset.viewports.active_vp.render(settings) diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/ovito_object.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/ovito_object.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/ovito_object.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/ovito_object.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,9 +1,9 @@ -from ovito import * +import ovito -o1 = ObjectNode() +o1 = ovito.ObjectNode() print(str(o1)) print(repr(o1)) assert(o1 == o1) -o2 = ObjectNode() +o2 = ovito.ObjectNode() assert(o1 != o2) assert(ovito.dataset.anim == ovito.dataset.anim) \ No newline at end of file diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/particle_properties.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/particle_properties.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/particle_properties.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/particle_properties.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * node = import_file("../../files/CFG/shear.void.120.cfg") diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/particle_type.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/particle_type.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/particle_type.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/particle_type.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * node = import_file("../../files/CFG/shear.void.120.cfg") diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/povray_exporter.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/povray_exporter.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/povray_exporter.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/povray_exporter.py 2017-07-27 16:52:45.000000000 +0000 @@ -3,12 +3,16 @@ from ovito.vis import * import os +import sys +if "ovito.plugins.POVRay" not in sys.modules: sys.exit() + test_data_dir = "../../files/" node1 = import_file(test_data_dir + "LAMMPS/class2.data", atom_style = "full") node1.add_to_scene() node1.source.particle_properties.position.display.shape = ParticleDisplay.Shape.Square node1.source.particle_properties.position.display.radius = 0.3 -export_file(node1, "test.pov", "povray") -export_file(None, "test.pov", "povray") -os.remove("test.pov") +export_file(node1, "_povray_export_test.pov", "povray") +export_file(None, "_povray_export_test.pov", "povray") +assert(os.path.isfile("_povray_export_test.pov")) +os.remove("_povray_export_test.pov") diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/povray_renderer.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/povray_renderer.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/povray_renderer.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/povray_renderer.py 2017-07-27 16:52:45.000000000 +0000 @@ -2,6 +2,9 @@ from ovito.io import import_file from ovito.vis import * +import sys +if "ovito.plugins.POVRay" not in sys.modules: sys.exit() + test_data_dir = "../../files/" node1 = import_file(test_data_dir + "LAMMPS/class2.data", atom_style = "full") node1.add_to_scene() diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/python_data_plot_overlay.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/python_data_plot_overlay.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/python_data_plot_overlay.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/python_data_plot_overlay.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,4 @@ -from ovito import * +import ovito from ovito.io import * from ovito.modifiers import * from ovito.vis import * @@ -15,7 +15,7 @@ node.modifiers.append(CoordinationNumberModifier()) node.modifiers.append(HistogramModifier()) node.add_to_scene() -vp = dataset.viewports.active_vp +vp = ovito.dataset.viewports.active_vp def render(painter, **args): @@ -64,4 +64,6 @@ vp.overlays.append(overlay) if ovito.headless_mode: ovito.dataset.render_settings.renderer = TachyonRenderer(ambient_occlusion = False, antialiasing = False) +else: + ovito.dataset.render_settings.renderer = OpenGLRenderer() vp.render() diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/python_script_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/python_script_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/python_script_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/python_script_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * from ovito.data import * diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/python_viewport_overlay.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/python_viewport_overlay.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/python_viewport_overlay.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/python_viewport_overlay.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,4 @@ -from ovito import * +import ovito from ovito.io import * from ovito.modifiers import * from ovito.vis import * @@ -8,9 +8,9 @@ node = import_file("../../files/CFG/fcc_coherent_twin.0.cfg") node.modifiers.append(CommonNeighborAnalysisModifier()) -vp = dataset.viewports.active_vp +vp = ovito.dataset.viewports.active_vp -new_overlay = ovito.vis.PythonViewportOverlay() +new_overlay = PythonViewportOverlay() new_overlay.script = """ def render(painter, **args): painter.drawText(10, 10, "Hello world") @@ -21,7 +21,7 @@ assert(vp.overlays[0] == new_overlay) assert(new_overlay.output == "") -overlay2 = ovito.vis.PythonViewportOverlay() +overlay2 = PythonViewportOverlay() overlay2.script = "This is an intentionally invalid Python script." vp.overlays.append(overlay2) diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/render_settings.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/render_settings.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/render_settings.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/render_settings.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,4 @@ -from ovito import * +import ovito from ovito.io import * from ovito.vis import * @@ -7,6 +7,7 @@ node.add_to_scene() settings = RenderSettings(size = (20,20)) -settings.renderer = TachyonRenderer(ambient_occlusion = False, antialiasing = False) +if ovito.headless_mode: + settings.renderer = TachyonRenderer(ambient_occlusion = False, antialiasing = False) settings.background_color = (0.8,0.8,1.0) -dataset.viewports.active_vp.render(settings) +ovito.dataset.viewports.active_vp.render(settings) diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/render_to_qimage.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/render_to_qimage.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/render_to_qimage.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/render_to_qimage.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,5 +1,4 @@ -# Import OVITO modules. -from ovito import * +import ovito from ovito.io import * from ovito.vis import * @@ -11,7 +10,7 @@ settings = RenderSettings(size = (100,100)) if ovito.headless_mode: settings.renderer = TachyonRenderer(ambient_occlusion = False, antialiasing = False) -img = dataset.viewports.active_vp.render(settings) +img = ovito.dataset.viewports.active_vp.render(settings) assert(img.width() == 100) painter = QPainter(img) painter.eraseRect(20, 10, 40, 50) diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/save_scene.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/save_scene.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/save_scene.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/save_scene.py 2017-07-27 16:52:45.000000000 +0000 @@ -3,11 +3,14 @@ import os import os.path -import_file("../../files/LAMMPS/animation.dump.gz") +node = import_file("../../files/LAMMPS/animation.dump.gz") +node.add_to_scene() -if os.path.isfile("scene.ovito"): os.remove("scene.ovito") +output_test_file = "_save_scene.ovito" -ovito.dataset.save("scene.ovito") -assert(os.path.isfile("scene.ovito")) +if os.path.isfile(output_test_file): os.remove(output_test_file) -os.remove("scene.ovito") +ovito.dataset.save(output_test_file) +assert(os.path.isfile(output_test_file)) + +os.remove(output_test_file) diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/simulation_cell.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/simulation_cell.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/simulation_cell.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/simulation_cell.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import import_file node = import_file("../../files/LAMMPS/animation.dump.gz") diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/system_exit.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/system_exit.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/system_exit.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/system_exit.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,4 @@ -from ovito import * import sys -sys.exit(2) \ No newline at end of file +sys.exit(0) +assert(False) diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/trajectory_lines.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/trajectory_lines.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/trajectory_lines.py 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/trajectory_lines.py 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,36 @@ +import ovito +from ovito.io import * +from ovito.data import * +from ovito.vis import * + +node = import_file("../../files/LAMMPS/animation.dump.gz", multiple_frames = True) +node.add_to_scene() +node.source.particle_properties.position.display.radius = 0.1 +print(node.source.num_frames) + +traj_node = ovito.ObjectNode() +traj_node.add_to_scene() +traj_node.source = TrajectoryLineGenerator() + +print(traj_node.source.source_node) +print(traj_node.source.only_selected) +print(traj_node.source.unwrap_trajectories) +print(traj_node.source.sampling_frequency) +print(traj_node.source.frame_interval) + +traj_node.source.sampling_frequency = 2 +traj_node.source.frame_interval = (0, 9) +assert(traj_node.source.frame_interval == (0, 9)) + +traj_node.source.source_node = node +traj_node.source.only_selected = False +assert(traj_node.source.generate()) + +dis = traj_node.source.display +print(dis.width) +print(dis.color) +print(dis.shading) +print(dis.upto_current_time) +assert(dis.shading == TrajectoryLineDisplay.Shading.Flat) + +dis.shading = TrajectoryLineDisplay.Shading.Normal \ No newline at end of file diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/viewport.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/viewport.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/viewport.py 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/viewport.py 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,29 @@ +from ovito.io import * +from ovito.vis import * +from PyQt5 import QtCore + +# Import a data file. +node = import_file("../../files/CFG/shear.void.120.cfg") +node.add_to_scene() + +settings = RenderSettings(size = (20,20)) +settings.renderer = TachyonRenderer(ambient_occlusion = False, antialiasing = False) + +vp = Viewport() +vp.type = Viewport.Type.PERSPECTIVE +vp.camera_pos = (350, -450, 450) +vp.camera_dir = (-100, -50, -50) +print(vp.fov) +print(vp.title) +print(vp.type) +vp.zoom_all() + +overlay = TextLabelOverlay( + text = 'Some text', + alignment = QtCore.Qt.AlignHCenter ^ QtCore.Qt.AlignBottom, + offset_y = 0.1, + font_size = 0.03, + text_color = (0,0,0)) + +vp.overlays.append(overlay) +vp.render(settings) diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/voronoi_analysis_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/voronoi_analysis_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/voronoi_analysis_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/voronoi_analysis_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,4 +1,3 @@ -from ovito import * from ovito.io import * from ovito.modifiers import * import numpy as np @@ -22,6 +21,9 @@ print(" face_threshold: {}".format(modifier.face_threshold)) modifier.face_threshold = 0.04 +print(" relative_face_threshold: {}".format(modifier.relative_face_threshold)) +modifier.relative_face_threshold = 0.01 + print(" only_selected: {}".format(modifier.only_selected)) modifier.only_selected = False diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/vorotop_analysis_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/vorotop_analysis_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/vorotop_analysis_modifier.py 1970-01-01 00:00:00.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/vorotop_analysis_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -0,0 +1,29 @@ +from ovito.io import * +from ovito.data import * +from ovito.modifiers import * + +import numpy + +node = import_file("../../files/CFG/fcc_coherent_twin.0.cfg") +modifier = VoroTopModifier() + +print("Parameter defaults:") +print(" only_selected: {}".format(modifier.only_selected)) +print(" use_radii: {}".format(modifier.use_radii)) +print(" filter_file: {}".format(modifier.filter_file)) + +modifier.use_radii = True +modifier.filter_file = "../../files/VoroTop/FCC-BCC-ICOS-both-HCP.gz" + +node.modifiers.append(modifier) + +modifier.structures[4].color = (1,0,0) +assert(modifier.structures[4].name == "FCC-HCP") + +node.compute() + +print("Computed structure types:") +print(node.output.structure_type.array) + +assert(node.output.particle_properties.structure_type.array[0] == 4) +assert((node.output.particle_properties.color.array[0] == (1,0,0)).all()) diff -Nru ovito-2.8.1+dfsg2/tests/scripts/test_suite/wigner_seitz_modifier.py ovito-2.9.0+dfsg1/tests/scripts/test_suite/wigner_seitz_modifier.py --- ovito-2.8.1+dfsg2/tests/scripts/test_suite/wigner_seitz_modifier.py 2016-12-17 13:59:02.000000000 +0000 +++ ovito-2.9.0+dfsg1/tests/scripts/test_suite/wigner_seitz_modifier.py 2017-07-27 16:52:45.000000000 +0000 @@ -1,7 +1,8 @@ -from ovito import * +import ovito from ovito.io import * from ovito.modifiers import * import numpy as np +import os node = import_file("../../files/NetCDF/sheared_aSi.nc") @@ -9,7 +10,7 @@ node.modifiers.append(modifier) modifier.reference.load("../../files/NetCDF/sheared_aSi.nc") -dataset.anim.current_frame = 4 +ovito.dataset.anim.current_frame = 4 print("Parameter defaults:") @@ -25,6 +26,9 @@ print(" use_frame_offset: {}".format(modifier.use_frame_offset)) modifier.use_frame_offset = False +print(" per_type_occupancies: {}".format(modifier.per_type_occupancies)) +modifier.per_type_occupancies = False + node.compute() print("Output:") @@ -32,7 +36,19 @@ print(" interstitial_count= {}".format(modifier.interstitial_count)) print(" vacancy_count= {}".format(node.output.attributes['WignerSeitz.vacancy_count'])) print(" interstitial_count= {}".format(node.output.attributes['WignerSeitz.interstitial_count'])) -print(node.output["Occupancy"].array) +print(node.output.particle_properties["Occupancy"].array) assert(node.output.attributes['WignerSeitz.vacancy_count'] == 970) assert(modifier.vacancy_count == 970) + +node.source.load('../../files/CFG/shear.void.120.cfg') +print(len(node.source.particle_properties.particle_type.type_list)) +modifier.per_type_occupancies = True +node.compute() +print("number_of_particles: %i" % node.output.number_of_particles) +print("occupancy.shape=%s" % str(node.output.particle_properties["Occupancy"].array.shape)) +#assert(node.output["Occupancy"].array.shape == (node.output.number_of_particles, 3)) +print(node.output.particle_properties["Occupancy"].array) + +export_file(node, "_output.dump", "lammps_dump", columns = [ "Particle Identifier", "Particle Type", "Position.X", "Position.Y", "Position.Z", "Occupancy","Occupancy.1"]) +os.remove("_output.dump") \ No newline at end of file
    (") << - (p1.particleIndex+1) << QStringLiteral(" - ") << (p2.particleIndex+1) << - QStringLiteral("):Distance = ") << delta.length() << QStringLiteral("
    (") << + p1.particleIndex << QStringLiteral(" - ") << p2.particleIndex << + QStringLiteral("):Distance = ") << delta.length() << QStringLiteral("
        [") << delta.x() << QStringLiteral(", ") << delta.y() << QStringLiteral(", ") << delta.z() << QStringLiteral("]
    (") << - (p2.particleIndex+1) << QStringLiteral(" - ") << (p1.particleIndex+1) << QStringLiteral(" - ") << (p3.particleIndex+1) << - QStringLiteral("):") << (angle * 180.0f / FLOATTYPE_PI) << QStringLiteral("
    ") << qRadiansToDegrees(angle) << QStringLiteral("