diff --git a/.github/actions/1_build/action.yml b/.github/actions/1_build/action.yml index e0d0f7b0a..569b4a46e 100644 --- a/.github/actions/1_build/action.yml +++ b/.github/actions/1_build/action.yml @@ -53,4 +53,4 @@ runs: - name: Configure and Build shell: bash run: | - bash scripts/${{ runner.os }}/1_build.sh ${{ steps.envs.outputs.build_option }} ${{ steps.envs.outputs.nightly }} --ccache \ No newline at end of file + bash scripts/${{ runner.os }}/1_build.sh ${{ steps.envs.outputs.build_option }} ${{ steps.envs.outputs.nightly }} --use_brew_llvm --ccache \ No newline at end of file diff --git a/.github/workflows/CreateRelease.yml b/.github/workflows/CreateRelease.yml index ae51d0a20..4b2eec98e 100644 --- a/.github/workflows/CreateRelease.yml +++ b/.github/workflows/CreateRelease.yml @@ -128,7 +128,6 @@ jobs: read -a strarrd <<< "$STR_VERSION" ML_VERSION_D=${strarrd[1]} #get the meshlab version from the string echo "ml_version_d=$ML_VERSION_D" >> $GITHUB_OUTPUT - #access to this variable using ${{steps.envs.outputs.ml_version}} or ${{steps.envs.outputs.ml_version_d}} - name: Create MeshLab Portable Linux Archive run: | cd meshlab_linux_portable @@ -148,27 +147,6 @@ jobs: with: name: MeshLab_macOS_packages_double path: meshlab_macos_dmg_double - - name: Download MacOS Portable - uses: actions/download-artifact@v3 - with: - name: MeshLab_macOS_portable - path: meshlab_macos_portable - - name: Download MacOS Portable-d - uses: actions/download-artifact@v3 - with: - name: MeshLab_macOS_portable_double - path: meshlab_macos_portable_double - - name: Change Permissions - run: | - chmod +x meshlab_macos_portable/MeshLab*.app/Contents/MacOS/meshlab - chmod +x meshlab_macos_portable_double/MeshLab*.app/Contents/MacOS/meshlab - - name: Create MeshLab Portable MacOS - run: | - cd meshlab_macos_portable - tar -cvzf ../MeshLab${{steps.envs.outputs.ml_version}}-macos.tar.gz * - cd ../meshlab_macos_portable_double - tar -cvzf ../MeshLab${{steps.envs.outputs.ml_version_d}}-macos.tar.gz * - cd .. #Download Windows Packages - name: Download Windows ZIP @@ -211,8 +189,6 @@ jobs: MeshLab${{steps.envs.outputs.ml_version_d}}-linux.tar.gz meshlab_linux_appimage/MeshLab${{steps.envs.outputs.ml_version}}-linux.AppImage meshlab_linux_appimage_double/MeshLab${{steps.envs.outputs.ml_version_d}}-linux.AppImage - MeshLab${{steps.envs.outputs.ml_version}}-macos.tar.gz - MeshLab${{steps.envs.outputs.ml_version_d}}-macos.tar.gz meshlab_macos_dmg/MeshLab${{steps.envs.outputs.ml_version}}-macos.dmg meshlab_macos_dmg_double/MeshLab${{steps.envs.outputs.ml_version_d}}-macos.dmg MeshLab${{steps.envs.outputs.ml_version}}-windows.zip diff --git a/resources/privacy.txt b/resources/privacy.txt index 57b1204d9..5c76e07f2 100644 --- a/resources/privacy.txt +++ b/resources/privacy.txt @@ -2,8 +2,8 @@ Privacy Disclaimer Please read it carefully. -MeshLab will automatically check for the availability of updated versions and will notify the need of upgrading the software to the users. For this reason, from time to time, MeshLab will issue a http network connection. If you prefer that MeshLab does not communicate in any way with its developers, simply use a plain firewall and prevent any MeshLab access to the network. This will not limit in any way the normal behaviour of MeshLab. When using MeshLab some aggregated statistical data about only the specific usage of MeshLab are collected: the number and size of the opened/saved meshes; nothing more. Periodically this information is sent back to the developers. This data will be used for statistical analysis only. -Paranoids can also look at the sources for seeing what is transmitted. +MeshLab will automatically check for the availability of updated versions and will notify the need of upgrading the software to the users. For this reason, from time to time, MeshLab will issue a http network connection. If you prefer that MeshLab does not communicate in any way with its developers, simply use a plain firewall and prevent any MeshLab access to the network, or disable the update check in the system preferences. This will not limit in any way the normal behaviour of MeshLab apart from getting notified when new releases are distributed. +Important: when using MeshLab the following aggregated statistical data are collected: the number of opened meshes, the number of saved meshes, and the total sum of the number of vertices opened by the user. This statistically aggregated information (three integers) is sent back to the developer when checking for updates. Disabling the check for updates also disable this data collection. We would like to remark that the kind of aggregated information collected by MeshLab is probably by far less sensitive than the information that is silently collected by most web sites when you surf them: ip address, visited pages, frequency of return. We would also like to stress that we really need this information in order to assess how diffusely MeshLab is used and what is its impact on the 3D community. diff --git a/sample/TextureSingle.ply b/sample/TextureSingle.ply new file mode 100644 index 000000000..a5ecc7cd5 --- /dev/null +++ b/sample/TextureSingle.ply @@ -0,0 +1,19 @@ +ply +format ascii 1.0 +comment VCGLIB generated +comment TextureFile TextureDouble_A.png +element vertex 4 +property float x +property float y +property float z +element face 2 +property list uchar int vertex_indices +property list uchar float texcoord +property int texnumber +end_header +0 0 0 +1 0 0 +1 1 0 +0 1 0 +3 0 1 2 6 0 0 2 0 2 2 0 +3 0 2 3 6 0 0 2 2 0 2 0 diff --git a/scripts/Linux/0_setup_env.sh b/scripts/Linux/0_setup_env.sh index f61a4bb0d..2462b807c 100644 --- a/scripts/Linux/0_setup_env.sh +++ b/scripts/Linux/0_setup_env.sh @@ -5,7 +5,8 @@ # Run this script if you never installed any of the MeshLab dependencies. DONT_INSTALL_QT=false -DONT_INSTALL_CGAL_BOOST=false +DONT_INSTALL_CGAL_BOOST=true +DONT_INSTALL_EMBREE=true #checking for parameters for i in "$@" @@ -19,6 +20,10 @@ case $i in DONT_INSTALL_CGAL_BOOST=true shift # past argument=value ;; + --dont_install_embree) + DONT_INSTALL_EMBREE=true + shift # past argument=value + ;; *) # unknown option ;; @@ -30,7 +35,7 @@ echo "=== installing mesa packages..." sudo apt-get install -y mesa-common-dev libglu1-mesa-dev echo "=== installing cmake, patchelf, gmp, mpfr and xcerces-c..." -sudo apt-get install -y cmake ninja-build patchelf libgmp-dev libmpfr-dev libxerces-c-dev +sudo apt-get install -y cmake ninja-build patchelf libgmp-dev libmpfr-dev libxerces-c-dev libtbb-dev if [ "$DONT_INSTALL_QT" = false ] ; then echo "=== installing qt packages..." @@ -50,3 +55,10 @@ if [ "$DONT_INSTALL_CGAL_BOOST" = false ] ; then else echo "=== jumping installation of cgal and boost packages..." fi + +if [ "$DONT_INSTALL_EMBREE" = false ] ; then + echo "=== installing embree..." + sudo apt-get install -y libembree-dev +else + echo "=== jumping installation of embree package..." +fi diff --git a/scripts/macOS/0_setup_env.sh b/scripts/macOS/0_setup_env.sh index 6bc5d3d8c..3dbf3c8f0 100644 --- a/scripts/macOS/0_setup_env.sh +++ b/scripts/macOS/0_setup_env.sh @@ -22,7 +22,7 @@ case $i in esac done -brew install coreutils node cmake ninja libomp cgal xerces-c +brew install coreutils node cmake ninja llvm libomp cgal xerces-c tbb embree npm install -g appdmg if [ "$DONT_INSTALL_QT" = false ] ; then diff --git a/scripts/macOS/1_build.sh b/scripts/macOS/1_build.sh index daa31b451..30e8312b5 100644 --- a/scripts/macOS/1_build.sh +++ b/scripts/macOS/1_build.sh @@ -7,6 +7,7 @@ BUILD_PATH=$SOURCE_PATH/build INSTALL_PATH=$SOURCE_PATH/install DOUBLE_PRECISION_OPTION="" NIGHTLY_OPTION="" +USE_BREW_LLVM=false QT_DIR="" CCACHE="" @@ -38,6 +39,14 @@ case $i in QT_DIR=${i#*=} shift # past argument=value ;; + --use_brew_llvm) + USE_BREW_LLVM=true + shift # past argument=value + ;; + --use_brew_qt) + QT_DIR=$(brew --prefix qt5) + shift # past argument=value + ;; --ccache) CCACHE="-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" shift # past argument=value @@ -65,6 +74,20 @@ then export Qt5_DIR=$QT_DIR fi +if [ "$USE_BREW_LLVM" = true ] ; then + BREW_PATH="$(brew --prefix)" + LLVM_PATH="$(brew --prefix llvm)" + export SDKROOT=$(xcrun --sdk macosx --show-sdk-path) + export LIBRARY_PATH="$LIBRARY_PATH:$SDKROOT/usr/lib" + export PATH="$LLVM_PATH/bin:$PATH" + export CC="$LLVM_PATH/bin/clang" + export CXX="$LLVM_PATH/bin/clang++" + export COMPILER=${CXX} + export CFLAGS="-I $BREW_PATH/include -I $LLVM_PATH/include" + export CXXFLAGS="-I $BREW_PATH/include -I $LLVM_PATH/include" + export LDFLAGS="-L $LIBRARY_PATH -L $BREW_PATH/lib -L $LLVM_PATH/lib" +fi + BUILD_PATH=$(realpath $BUILD_PATH) INSTALL_PATH=$(realpath $INSTALL_PATH) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8eb53d613..b7c6a5867 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -104,6 +104,7 @@ set(EXTERNAL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external) add_subdirectory(${EXTERNAL_DIR}) add_subdirectory(common) +add_subdirectory(common_gui) if (NOT MESHLAB_BUILD_ONLY_LIBRARIES) add_subdirectory(meshlab) @@ -147,7 +148,10 @@ if(NOT DEFINED MESHLAB_PLUGINS) # it may be already defined in parent directory meshlabplugins/filter_color_projection meshlabplugins/filter_colorproc meshlabplugins/filter_create + meshlabplugins/filter_cubization + meshlabplugins/filter_developability meshlabplugins/filter_dirt + meshlabplugins/filter_embree meshlabplugins/filter_fractal meshlabplugins/filter_func meshlabplugins/filter_img_patch_param @@ -157,6 +161,7 @@ if(NOT DEFINED MESHLAB_PLUGINS) # it may be already defined in parent directory meshlabplugins/filter_layer meshlabplugins/filter_measure meshlabplugins/filter_mesh_booleans + meshlabplugins/filter_mesh_alpha_wrap meshlabplugins/filter_meshing meshlabplugins/filter_mls meshlabplugins/filter_mutualglobal diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index c4ddb0d19..0e640fdd4 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -41,6 +41,8 @@ else() endif() set(HEADERS + filter_history/filter.h + filter_history/filter_history.h ml_document/helpers/mesh_document_state_data.h ml_document/helpers/mesh_model_state_data.h ml_document/base_types.h @@ -53,9 +55,34 @@ set(HEADERS ml_shared_data_context/ml_plugin_gl_context.h ml_shared_data_context/ml_scene_gl_shared_data_context.h ml_shared_data_context/ml_shared_data_context.h - parameters/rich_parameter.h + parameters/rich_parameters.h + parameters/values.h parameters/rich_parameter_list.h - parameters/value.h + parameters/rich_parameter/rich_bool.h + parameters/rich_parameter/rich_color.h + parameters/rich_parameter/rich_direction.h + parameters/rich_parameter/rich_dynamic_float.h + parameters/rich_parameter/rich_enum.h + parameters/rich_parameter/rich_file_open.h + parameters/rich_parameter/rich_file_save.h + parameters/rich_parameter/rich_float.h + parameters/rich_parameter/rich_int.h + parameters/rich_parameter/rich_matrix44.h + parameters/rich_parameter/rich_mesh.h + parameters/rich_parameter/rich_parameter.h + parameters/rich_parameter/rich_percentage.h + parameters/rich_parameter/rich_position.h + parameters/rich_parameter/rich_shot.h + parameters/rich_parameter/rich_string.h + parameters/value/bool_value.h + parameters/value/color_value.h + parameters/value/float_value.h + parameters/value/int_value.h + parameters/value/matrix44_value.h + parameters/value/point3_value.h + parameters/value/shot_value.h + parameters/value/string_value.h + parameters/value/value.h plugins/containers/generic_container_iterator.h plugins/containers/decorate_plugin_container.h plugins/containers/edit_plugin_container.h @@ -89,6 +116,8 @@ set(HEADERS mlexception.h) set(SOURCES + filter_history/filter.cpp + filter_history/filter_history.cpp ml_document/helpers/mesh_document_state_data.cpp ml_document/cmesh.cpp ml_document/mesh_document.cpp @@ -99,9 +128,32 @@ set(SOURCES ml_shared_data_context/ml_plugin_gl_context.cpp ml_shared_data_context/ml_scene_gl_shared_data_context.cpp ml_shared_data_context/ml_shared_data_context.cpp - parameters/rich_parameter.cpp + parameters/rich_parameters.cpp parameters/rich_parameter_list.cpp - parameters/value.cpp + parameters/rich_parameter/rich_bool.cpp + parameters/rich_parameter/rich_color.cpp + parameters/rich_parameter/rich_direction.cpp + parameters/rich_parameter/rich_dynamic_float.cpp + parameters/rich_parameter/rich_enum.cpp + parameters/rich_parameter/rich_file_open.cpp + parameters/rich_parameter/rich_file_save.cpp + parameters/rich_parameter/rich_float.cpp + parameters/rich_parameter/rich_int.cpp + parameters/rich_parameter/rich_matrix44.cpp + parameters/rich_parameter/rich_mesh.cpp + parameters/rich_parameter/rich_parameter.cpp + parameters/rich_parameter/rich_percentage.cpp + parameters/rich_parameter/rich_position.cpp + parameters/rich_parameter/rich_shot.cpp + parameters/rich_parameter/rich_string.cpp + parameters/value/bool_value.cpp + parameters/value/color_value.cpp + parameters/value/float_value.cpp + parameters/value/int_value.cpp + parameters/value/matrix44_value.cpp + parameters/value/point3_value.cpp + parameters/value/shot_value.cpp + parameters/value/string_value.cpp plugins/containers/decorate_plugin_container.cpp plugins/containers/edit_plugin_container.cpp plugins/containers/filter_plugin_container.cpp diff --git a/src/common/filter_history/filter.cpp b/src/common/filter_history/filter.cpp new file mode 100644 index 000000000..f77c6f4d5 --- /dev/null +++ b/src/common/filter_history/filter.cpp @@ -0,0 +1,136 @@ +/***************************************************************************** + * MeshLab o o * + * An extendible mesh processor o o * + * _ O _ * + * Copyright(C) 2005-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "filter.h" + +Filter::Filter() +{ +} + +Filter::Filter( + const FilterPlugin* plugin, + const QAction* filter, + const RichParameterList& paramList) : + plugin(plugin), + filter(filter), + paramList(paramList) +{ +} + +void Filter::setParameterValue(const std::string ¶meter, const Value &value) +{ + RichParameter& rp = paramList.getParameterByName(QString::fromStdString(parameter)); + rp.setValue(value); +} + +/** + * @brief returns a string containing a pymeshlab python call of the filter with the current + * parameters set. + * @param meshSetName: the name of the MeshSet object. + * @return + */ +std::string Filter::pyMeshLabCall(std::string meshSetName) const +{ + bool first = true; + std::string call = meshSetName + "." + plugin->pythonFilterName(filter).toStdString() + "("; + for (const RichParameter& p : paramList) { + // parameter must be added only if its value is not default + if (!p.isValueDefault()) { + if (!p.isOfType()) { // RichShot not yet supported by pymeshlab + // if it is not the first parameter we are adding, we put the comma after the last + // parameter, because we are going to add another one + if (first) { + first = false; + } + else { + call += ", "; + } + call += p.pythonName().toStdString() + " = "; + if (p.isOfType()) { + if (p.value().getBool()) { + call += "True"; + } + else { + call += "False"; + } + } + else if (p.isOfType()) { + QColor c = p.value().getColor(); + call += "pymeshlab.Color("; + call += std::to_string(c.red()) + ", "; + call += std::to_string(c.green()) + ", "; + call += std::to_string(c.blue()) + ", "; + call += std::to_string(c.alpha()) + ")"; + } + else if (p.isOfType() || p.isOfType()) { + Point3m pp = p.value().getPoint3(); + call += "numpy.array(["; + call += std::to_string(pp[0]) + ", "; + call += std::to_string(pp[1]) + ", "; + call += std::to_string(pp[2]) + "])"; + } + else if (p.isOfType() || p.isOfType()) { + call += std::to_string(p.value().getFloat()); + } + else if ( + p.isOfType() || p.isOfType() || p.isOfType()) { + call += std::to_string(p.value().getInt()); + } + else if ( + p.isOfType() || p.isOfType() || + p.isOfType()) { + call += "'" + p.value().getString().toStdString() + "'"; + } + else if (p.isOfType()) { + Matrix44m m = p.value().getMatrix44(); + call += "numpy.array(["; + bool firstRow = true; + for (unsigned int i = 0; i < 4 ; i++) { + if (firstRow) + firstRow = false; + else + call += ", "; + call += "["; + bool firstCol = true; + for (unsigned int j = 0; j < 4 ; j++) { + if (firstCol) + firstCol = false; + else + call += ", "; + call += std::to_string(m.ElementAt(i,j)); + } + call += "]"; + } + call += "])"; + } + else if (p.isOfType()) { + const RichPercentage& rp = dynamic_cast(p); + float per = (p.value().getFloat() / (rp.max - rp.min) ) * 100; + call += "pymeshlab.PercentageValue(" + std::to_string(per) + ")"; + } + } + } + } + call += ")"; + return call; +} diff --git a/src/common/filter_history/filter.h b/src/common/filter_history/filter.h new file mode 100644 index 000000000..5acc728a7 --- /dev/null +++ b/src/common/filter_history/filter.h @@ -0,0 +1,49 @@ +/***************************************************************************** + * MeshLab o o * + * An extendible mesh processor o o * + * _ O _ * + * Copyright(C) 2005-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef FILTER_H +#define FILTER_H + +#include +#include + +class Filter +{ +public: + Filter(); + Filter( + const FilterPlugin* plugin, + const QAction* filter, + const RichParameterList& paramList); + + void setParameterValue(const std::string& parameter, const Value& value); + + std::string pyMeshLabCall(std::string meshSetName = "ms") const; + +private: + const FilterPlugin* plugin; + const QAction* filter; + RichParameterList paramList; +}; + +#endif // FILTER_H diff --git a/src/common/filter_history/filter_history.cpp b/src/common/filter_history/filter_history.cpp new file mode 100644 index 000000000..ef2d395fd --- /dev/null +++ b/src/common/filter_history/filter_history.cpp @@ -0,0 +1,44 @@ +/***************************************************************************** + * MeshLab o o * + * An extendible mesh processor o o * + * _ O _ * + * Copyright(C) 2005-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "filter_history.h" + +FilterHistory::iterator FilterHistory::begin() +{ + return history.begin(); +} + +FilterHistory::iterator FilterHistory::end() +{ + return history.end(); +} + +FilterHistory::const_iterator FilterHistory::begin() const +{ + return history.begin(); +} + +FilterHistory::const_iterator FilterHistory::end() const +{ + return history.end(); +} diff --git a/src/common/filter_history/filter_history.h b/src/common/filter_history/filter_history.h new file mode 100644 index 000000000..4df36ebfc --- /dev/null +++ b/src/common/filter_history/filter_history.h @@ -0,0 +1,45 @@ +/***************************************************************************** + * MeshLab o o * + * An extendible mesh processor o o * + * _ O _ * + * Copyright(C) 2005-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_FILTER_HISTORY_H +#define MESHLAB_FILTER_HISTORY_H + +#include + +#include "filter.h" + +class FilterHistory +{ + using iterator = std::list::iterator; + using const_iterator = std::list::const_iterator; + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + +private: + std::list history; +}; + +#endif // MESHLAB_FILTER_HISTORY_H diff --git a/src/common/parameters/rich_parameter.cpp b/src/common/parameters/rich_parameter.cpp deleted file mode 100644 index 5e2d7f575..000000000 --- a/src/common/parameters/rich_parameter.cpp +++ /dev/null @@ -1,900 +0,0 @@ -/**************************************************************************** -* MeshLab o o * -* A versatile mesh processing toolbox o o * -* _ O _ * -* Copyright(C) 2004-2021 \/)\/ * -* Visual Computing Lab /\/| * -* ISTI - Italian National Research Council | * -* \ * -* All rights reserved. * -* * -* This program 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. * -* * -* This program 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 (http://www.gnu.org/licenses/gpl.txt) * -* for more details. * -* * -****************************************************************************/ - -#include "rich_parameter.h" -#include "../ml_document/mesh_document.h" -#include "../python/python_utils.h" - -/**** RichParameter Class ****/ - -RichParameter::RichParameter(const RichParameter& rp) : - pName(rp.pName), - val(rp.value().clone()), - fieldDesc(rp.fieldDesc), - tooltip(rp.tooltip), - advanced(rp.advanced), - pCategory(rp.pCategory) -{ -} - -RichParameter::RichParameter(RichParameter&& rp) : - pName(std::move(rp.pName)), - fieldDesc(std::move(rp.fieldDesc)), - tooltip(std::move(rp.tooltip)), - pCategory(std::move(rp.pCategory)) -{ - val = rp.val; - rp.val = nullptr; - advanced = rp.advanced; -} - -RichParameter::RichParameter( - const QString& nm, - const Value& v, - const QString& desc, - const QString& tltip, - bool isAdvanced, - const QString& category) : - pName(nm), - val(v.clone()), - fieldDesc(desc), - tooltip(tltip), - advanced(isAdvanced), - pCategory(category) -{ -} - -RichParameter::~RichParameter() -{ - delete val; -} - -const QString& RichParameter::name() const -{ - return pName; -} - -const Value& RichParameter::value() const -{ - return *val; -} - -const QString& RichParameter::fieldDescription() const -{ - return fieldDesc; -} - -const QString& RichParameter::toolTip() const -{ - return tooltip; -} - -bool RichParameter::isAdvanced() const -{ - return advanced; -} - -const QString& RichParameter::category() const -{ - return pCategory; -} - -void RichParameter::setName(const QString& newName) -{ - pName = newName; -} - -void RichParameter::setValue(const Value& ov) -{ - assert(val->typeName() == ov.typeName()); - delete val; - val = ov.clone(); -} - -QDomElement RichParameter::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const -{ - QDomElement parElem = doc.createElement("Param"); - parElem.setAttribute("name", pName); - parElem.setAttribute("type", stringType()); - if (saveDescriptionAndTooltip) { - parElem.setAttribute("description", fieldDesc); - parElem.setAttribute("tooltip",tooltip); - } - val->fillToXMLElement(parElem); - return parElem; -} - -/** - * @brief returns the name of the parameter used in python (for pymeshlab) - */ -QString RichParameter::pythonName() const -{ - return pymeshlab::computePythonName(pName); -} - -/** - * @brief returns the type if the parameter (as a string) used in python - * (for pymeshlab) - */ -QString RichParameter::pythonType() const -{ - return pymeshlab::computePythonTypeString(*this); -} - -RichParameter& RichParameter::operator=(const RichParameter& rp) -{ - if (&rp != this){ - delete val; - val = rp.value().clone(); - pName = rp.pName; - fieldDesc = rp.fieldDesc; - tooltip = rp.tooltip; - } - return *this; -} - -RichParameter& RichParameter::operator=(RichParameter&& rp) -{ - assert(&rp != this); - val = rp.val; - rp.val = nullptr; - pName = std::move(rp.pName); - fieldDesc = std::move(rp.fieldDesc); - tooltip = std::move(rp.tooltip); - return *this; -} - -/**** RichBool Class ****/ - -RichBool::RichBool( - const QString& nm, - const bool defval, - const QString& desc, - const QString& tltip, - bool hidden, - const QString& category) : - RichParameter(nm, BoolValue(defval), desc, tltip, hidden, category) -{ -} - -RichBool::~RichBool() -{ -} - -QString RichBool::stringType() const -{ - return "RichBool"; -} - -RichBool* RichBool::clone() const -{ - return new RichBool(*this); -} - -bool RichBool::operator==( const RichParameter& rb ) -{ - return (rb.value().isBool() && (pName == rb.name()) && (value().getBool() == rb.value().getBool())); -} - -/**** RichInt Class ****/ - -RichInt::RichInt( - const QString& nm, - const int defval, - const QString& desc, - const QString& tltip, - bool hidden, - const QString& category) : - RichParameter(nm, IntValue(defval),desc, tltip, hidden, category) -{ -} - -RichInt::~RichInt() -{ -} - -QString RichInt::stringType() const -{ - return "RichInt"; -} - -RichInt* RichInt::clone() const -{ - return new RichInt(*this); -} - -bool RichInt::operator==( const RichParameter& rb ) -{ - return (rb.value().isInt() &&(pName == rb.name()) && (value().getInt() == rb.value().getInt())); -} - -/**** RichFloat Class ****/ - -RichFloat::RichFloat( - const QString& nm, - const Scalarm defval, - const QString& desc, - const QString& tltip, - bool hidden, - const QString& category) : - RichParameter(nm, FloatValue(defval),desc, tltip, hidden, category) -{ -} - -RichFloat::~RichFloat() -{ -} - -QString RichFloat::stringType() const -{ - return "RichFloat"; -} - -RichFloat* RichFloat::clone() const -{ - return new RichFloat(*this); -} - -bool RichFloat::operator==( const RichParameter& rb ) -{ - return (rb.value().isFloat() &&(pName == rb.name()) && (value().getFloat() == rb.value().getFloat())); -} - -/**** RichString Class ****/ - -RichString::RichString( - const QString& nm, - const QString& defval, - const QString& desc, - const QString& tltip, - bool hidden, - const QString& category) : - RichParameter(nm, StringValue(defval),desc,tltip, hidden, category) -{ -} - -RichString::~RichString() -{ -} - -QString RichString::stringType() const -{ - return "RichString"; -} - -RichString* RichString::clone() const -{ - return new RichString(*this); -} - -bool RichString::operator==( const RichParameter& rb ) -{ - return (rb.value().isString() &&(pName == rb.name()) && (value().getString() == rb.value().getString())); -} - -/**** RichMatrix44f Class ****/ - -RichMatrix44f::RichMatrix44f( - const QString& nm, - const Matrix44m& defval, - const QString& desc, - const QString& tltip, - bool hidden, - const QString& category) : - RichParameter(nm, Matrix44fValue(defval),desc, tltip, hidden, category) -{ -} - -RichMatrix44f::~RichMatrix44f() -{ -} - -QString RichMatrix44f::stringType() const -{ - return "RichMatrix44f"; -} - -RichMatrix44f* RichMatrix44f::clone() const -{ - return new RichMatrix44f(*this); -} - -bool RichMatrix44f::operator==( const RichParameter& rb ) -{ - return (rb.value().isMatrix44f() &&(pName == rb.name()) && (value().getMatrix44f() == rb.value().getMatrix44f())); -} - -/**** RichPosition Class ****/ - -RichPosition::RichPosition( - const QString& nm, - const Point3m& defval, - const QString& desc, - const QString& tltip, - bool hidden, - const QString& category) : - RichParameter(nm, Point3fValue(defval),desc, tltip, hidden, category) -{ -} - -RichPosition::~RichPosition() -{ -} - -QString RichPosition::stringType() const -{ - return "RichPosition"; -} - -RichPosition* RichPosition::clone() const -{ - return new RichPosition(*this); -} - -bool RichPosition::operator==( const RichParameter& rb ) -{ - return (rb.value().isPoint3f() &&(pName == rb.name()) && (value().getPoint3f() == rb.value().getPoint3f())); -} - -/**** RichDirection Class ****/ - -RichDirection::RichDirection( - const QString& nm, - const Point3m& defval, - const QString& desc, - const QString& tltip, - bool hidden, - const QString& category) : - RichParameter(nm, Point3fValue(defval), desc, tltip, hidden, category) -{ -} - -RichDirection::~RichDirection() -{ -} - -QString RichDirection::stringType() const -{ - return "RichDirection"; -} - -RichDirection* RichDirection::clone() const -{ - return new RichDirection(*this); -} - -bool RichDirection::operator==(const RichParameter& rb) -{ - return (rb.value().isPoint3f() &&(pName == rb.name()) && (value().getPoint3f() == rb.value().getPoint3f())); -} - -/**** RichShotf Class ****/ - -RichShotf::RichShotf( - const QString& nm, - const Shotm& defval, - const QString& desc, - const QString& tltip, - bool hidden, - const QString& category) : - RichParameter(nm, ShotfValue(defval),desc, tltip, hidden, category) -{ -} - -RichShotf::~RichShotf() -{ -} - -QString RichShotf::stringType() const -{ - return "RichShotf"; -} - -RichShotf* RichShotf::clone() const -{ - return new RichShotf(*this); -} - -bool RichShotf::operator==( const RichParameter& rb ) -{ - return (rb.value().isShotf() &&(pName == rb.name()) ); - // TODO REAL TEST OF EQUALITY // && (value().getShotf() == rb.value().getShotf())); -} - -/**** RichColor Class ****/ - -RichColor::RichColor( - const QString& nm, - const QColor& defval, - const QString& desc, - const QString& tltip, - bool hidden, - const QString& category) : - RichParameter(nm, ColorValue(defval),desc, tltip, hidden, category) -{ -} - -RichColor::~RichColor() -{ -} - -QString RichColor::stringType() const -{ - return "RichColor"; -} - -RichColor* RichColor::clone() const -{ - return new RichColor(*this); -} - -bool RichColor::operator==( const RichParameter& rb ) -{ - return (rb.value().isColor() &&(pName == rb.name()) && (value().getColor() == rb.value().getColor())); -} - -/**** RichAbsPerc Class ****/ - -RichAbsPerc::RichAbsPerc( - const QString& nm, - const Scalarm defval, - const Scalarm minval, - const Scalarm maxval, - const QString& desc, - const QString& tltip, - bool hidden, - const QString& category) : - RichParameter(nm, FloatValue(defval), desc, tltip, hidden, category), min(minval), max(maxval) -{ -} - -RichAbsPerc::~RichAbsPerc() -{ -} - -QString RichAbsPerc::stringType() const -{ - return "RichAbsPerc"; -} - -QDomElement RichAbsPerc::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const -{ - QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); - parElem.setAttribute("min",QString::number(min)); - parElem.setAttribute("max",QString::number(max)); - return parElem; -} - -RichAbsPerc* RichAbsPerc::clone() const -{ - return new RichAbsPerc(*this); -} - -bool RichAbsPerc::operator==( const RichParameter& rb ) -{ - return (rb.isOfType() &&(pName == rb.name()) && (value().getFloat() == rb.value().getFloat())); -} - -/**** RichEnum Class ****/ - -RichEnum::RichEnum( - const QString& nm, - const int defval, - const QStringList& values, - const QString& desc, - const QString& tltip, - bool hidden, - const QString& category) : - RichParameter(nm, IntValue(defval),desc, tltip, hidden, category), enumvalues(values) -{ -} - -RichEnum::~RichEnum() -{ -} - -QString RichEnum::stringType() const -{ - return "RichEnum"; -} - -QDomElement RichEnum::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const -{ - QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); - parElem.setAttribute("enum_cardinality", enumvalues.size()); - for(int ii = 0; ii < enumvalues.size(); ++ii) - parElem.setAttribute(QString("enum_val")+QString::number(ii), enumvalues.at(ii)); - return parElem; -} - -RichEnum* RichEnum::clone() const -{ - return new RichEnum(*this); -} - -bool RichEnum::operator==( const RichParameter& rb ) -{ - return (rb.isOfType() &&(pName == rb.name()) && (value().getInt() == rb.value().getInt())); -} - -/**** RichDynamicFloat Class ****/ - -RichDynamicFloat::RichDynamicFloat( - const QString& nm, - const Scalarm defval, - const Scalarm minval, - const Scalarm maxval, - const QString& desc, - const QString& tltip, - bool hidden, - const QString& category) : - RichParameter(nm, FloatValue(defval),desc, tltip, hidden, category), min(minval), max(maxval) -{ -} - -RichDynamicFloat::~RichDynamicFloat() -{ -} - -QString RichDynamicFloat::stringType() const -{ - return "RichDynamicFloat"; -} - -QDomElement RichDynamicFloat::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const -{ - QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); - parElem.setAttribute("min",QString::number(min)); - parElem.setAttribute("max",QString::number(max)); - return parElem; -} - -RichDynamicFloat* RichDynamicFloat::clone() const -{ - return new RichDynamicFloat(*this); -} - -bool RichDynamicFloat::operator==( const RichParameter& rb ) -{ - return (rb.isOfType() &&(pName == rb.name()) && (value().getFloat() == rb.value().getFloat())); -} - -/**** RichOpenFile Class ****/ - -RichOpenFile::RichOpenFile( - const QString& nm, - const QString& directorydefval, - const QStringList& exts, - const QString& desc, - const QString& tltip, - bool hidden, - const QString& category) : - RichParameter(nm, StringValue(directorydefval), desc, tltip, hidden, category), exts(exts) -{ -} - -RichOpenFile::~RichOpenFile() -{ -} - -QString RichOpenFile::stringType() const -{ - return "RichOpenFile"; -} - -QDomElement RichOpenFile::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const -{ - QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); - parElem.setAttribute("exts_cardinality", exts.size()); - for(int ii = 0; ii < exts.size(); ++ii) - parElem.setAttribute(QString("ext_val")+QString::number(ii), exts[ii]); - return parElem; -} - -RichOpenFile* RichOpenFile::clone() const -{ - return new RichOpenFile(*this); -} - -bool RichOpenFile::operator==( const RichParameter& rb ) -{ - return (rb.isOfType() &&(pName == rb.name()) && (value().getString() == rb.value().getString())); -} - -/**** RichSaveFile Class ****/ - -RichSaveFile::RichSaveFile( - const QString& nm, - const QString& filedefval, - const QString& ext, - const QString& desc, - const QString& tltip, - bool hidden, - const QString& category) : - RichParameter(nm, StringValue(filedefval), desc, tltip, hidden, category), ext(ext) -{ -} - -RichSaveFile::~RichSaveFile() -{ -} - -QString RichSaveFile::stringType() const -{ - return "RichSaveFile"; -} - -QDomElement RichSaveFile::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const -{ - QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); - parElem.setAttribute("ext", ext); - return parElem; -} - -RichSaveFile* RichSaveFile::clone() const -{ - return new RichSaveFile(*this); -} - -bool RichSaveFile::operator==( const RichParameter& rb ) -{ - return (rb.isOfType() &&(pName == rb.name()) && (value().getString() == rb.value().getString())); -} - -/**** RichMesh Class ****/ - -RichMesh::RichMesh( - const QString& nm, - unsigned int meshind, - const MeshDocument* doc, - const QString& desc, - const QString& tltip, - bool hidden, - const QString& category): - RichParameter(nm,IntValue(meshind), desc, tltip, hidden, category), meshdoc(doc) -{ -} - -RichMesh::~RichMesh() -{ -} - -QString RichMesh::stringType() const -{ - return "RichMesh"; -} - -RichMesh* RichMesh::clone() const -{ - return new RichMesh(*this); -} - -bool RichMesh::operator==( const RichParameter& rb ) -{ - return (rb.isOfType() &&(pName == rb.name()) && (value().getInt() == rb.value().getInt())); -} - -/**** RichParameterAdapter Class ****/ - -bool RichParameterAdapter::create( const QDomElement& np,RichParameter*& par ) -{ - QString name=np.attribute("name"); - QString type=np.attribute("type"); - QString desc=np.attribute("description"); - QString tooltip=np.attribute("tooltip"); - - // qDebug(" Reading Param with name %s : %s", qUtf8Printable(name), qUtf8Printable(type)); - - bool corrconv = false; - if(type=="RichBool") { - QString val = np.attribute("value").toLower(); - if ((val != QString("true")) && (val != QString("false"))) - return false; - par = new RichBool(name,np.attribute("value")!=QString("false"),desc,tooltip); - return true; - } - - if(type=="RichInt") { - int val = np.attribute("value").toInt(&corrconv); - if (!corrconv) - return false; - par = new RichInt(name,val,desc,tooltip); - return true; - } - - if(type=="RichFloat") { - float val = np.attribute("value").toFloat(&corrconv); - if (!corrconv) - return false; - par = new RichFloat(name,val,desc,tooltip); - return true; - } - - if(type=="RichString") { - par = new RichString(name,np.attribute("value"),desc,tooltip); - return true; - } - - if(type=="RichAbsPerc") { - float val = np.attribute("value").toFloat(&corrconv); - if ((!corrconv) && (val >= 0.0f) && (val <= 100.0f)) - return false; - float min = np.attribute("min").toFloat(&corrconv); - if (!corrconv) - return false; - float max = np.attribute("max").toFloat(&corrconv); - if (!corrconv) - return false; - par = new RichAbsPerc(name,val,min,max,desc,tooltip); - return true; - } - - if(type=="RichColor") { - unsigned int r = np.attribute("r").toUInt(&corrconv); - if ((!corrconv) && (r <= 255)) - return false; - unsigned int g = np.attribute("g").toUInt(&corrconv); - if ((!corrconv) && (g <= 255)) - return false; - unsigned int b = np.attribute("b").toUInt(&corrconv); - if ((!corrconv) && (b <= 255)) - return false; - unsigned int a = np.attribute("a").toUInt(&corrconv); - if ((!corrconv) && (a <= 255)) - return false; - QColor col(r,g,b,a); - par= new RichColor(name,col,desc,tooltip); - return true; - } - - if(type=="RichMatrix44f") { - Matrix44m mm; - for(int i=0;i<16;++i) - { - Scalarm val = np.attribute(QString("val")+QString::number(i)).toFloat(&corrconv); - if (!corrconv) - return false; - mm.V()[i]=val; - } - par = new RichMatrix44f(name,mm,desc,tooltip); - return true; - } - - if(type=="RichEnum") { - QStringList list; - int enum_card = np.attribute(QString("enum_cardinality")).toUInt(&corrconv); - if (!corrconv) - return false; - - for(int i=0;i=0) && (val < enum_card)) - return false; - par = new RichEnum(name,val,list,desc,tooltip); - return true; - } - - if(type == "RichMesh") { - int val = np.attribute("value").toInt(&corrconv); - - if (!corrconv) - return false; - - par = new RichMesh(name, val, nullptr, desc,tooltip); - return true; - } - - if(type == "RichDynamicFloat") { - float min = np.attribute("min").toFloat(&corrconv); - if (!corrconv) - return false; - float max = np.attribute("max").toFloat(&corrconv); - if (!corrconv) - return false; - - float val = np.attribute("value").toFloat(&corrconv); - if ((!corrconv) && (val >= min) && (val <= max)) - return false; - - par = new RichDynamicFloat(name, val, min, max, desc, tooltip); - return true; - } - - if(type == "RichOpenFile") { - QStringList list; - int exts_card = np.attribute(QString("exts_cardinality")).toUInt(&corrconv); - if (!corrconv) - return false; - - for(int i=0;i - -class MeshDocument; - -/** - * @brief The RichParameter class - * - * The RichParameter class is a representation of a MeshLab parameter that contains - * a value of a certain type (see the Value class and its specializations) plus - * some other decorators, like a parameter description and a tooltip. - * - * All these decorators allow MeshLab to automatically design GUI interfaces for - * every RichParameter spcialization. - * - * Every specialization must implement the following member functions: - * - QString stringType() const : returns a string representation of the type of the RichParameter - * - RichParameter* clone() const : returns a *new* object which is a clone of the RichParameter - * - bool operator==(const RichParameter& rp): returns true if the two RichParameter are the same - */ -class RichParameter -{ -public: - RichParameter(const RichParameter& rp); - RichParameter(RichParameter&& rp); - RichParameter( - const QString& nm, - const Value& v, - const QString& desc = QString(), - const QString& tltip = QString(), - bool isAdvanced = false, - const QString& category = QString()); - virtual ~RichParameter(); - - const QString& name() const; - const Value& value() const; - const QString& fieldDescription() const; - const QString& toolTip() const; - bool isAdvanced() const; - const QString& category() const; - - template - bool isOfType() const - { - const RichParam* t = dynamic_cast(this); - return (t != nullptr); - } - - virtual QString stringType() const = 0; - - void setName(const QString& newName); - void setValue(const Value& ov); - - virtual QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; - - //python names of paraeter - QString pythonName() const; - QString pythonType() const; - - virtual RichParameter* clone() const = 0; - RichParameter& operator=(const RichParameter& rp); - RichParameter& operator=(RichParameter&& rp); - virtual bool operator==(const RichParameter& rp) = 0; - -protected: - QString pName; - Value* val; - QString fieldDesc; - QString tooltip; - bool advanced; - QString pCategory; -}; - - -class RichBool : public RichParameter -{ -public: - RichBool( - const QString& nm, - const bool defval, - const QString& desc = QString(), - const QString& tltip = QString(), - bool hidden = false, - const QString& category = QString()); - ~RichBool(); - - QString stringType() const; - - RichBool* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichInt : public RichParameter -{ -public: - RichInt( - const QString& nm, - const int defval, - const QString& desc = QString(), - const QString& tltip = QString(), - bool hidden = false, - const QString& category = QString()); - ~RichInt(); - - QString stringType() const; - - RichInt* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichFloat : public RichParameter -{ -public: - RichFloat( - const QString& nm, - const Scalarm defval, - const QString& desc = QString(), - const QString& tltip = QString(), - bool hidden = false, - const QString& category = QString()); - ~RichFloat(); - - QString stringType() const; - - RichFloat* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichString : public RichParameter -{ -public: - RichString( - const QString& nm, - const QString& defval, - const QString& desc = QString(), - const QString& tltip = QString(), - bool hidden = false, - const QString& category = QString()); - ~RichString(); - - QString stringType() const; - - RichString* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichMatrix44f : public RichParameter -{ -public: - RichMatrix44f( - const QString& nm, - const Matrix44m& defval, - const QString& desc = QString(), - const QString& tltip = QString(), - bool hidden = false, - const QString& category = QString()); - ~RichMatrix44f(); - - QString stringType() const; - - RichMatrix44f* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichPosition : public RichParameter -{ -public: - RichPosition( - const QString& nm, - const Point3m& defval, - const QString& desc = QString(), - const QString& tltip = QString(), - bool hidden = false, - const QString& category = QString()); - ~RichPosition(); - - QString stringType() const; - - RichPosition* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichDirection : public RichParameter -{ -public: - RichDirection( - const QString& nm, - const Point3m& defval, - const QString& desc = QString(), - const QString& tltip = QString(), - bool hidden = false, - const QString& category = QString()); - ~RichDirection(); - - QString stringType() const; - - RichDirection* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichShotf : public RichParameter -{ -public: - RichShotf( - const QString& nm, - const Shotm& defval, - const QString& desc = QString(), - const QString& tltip = QString(), - bool hidden = false, - const QString& category = QString()); - ~RichShotf(); - - QString stringType() const; - - RichShotf* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichColor : public RichParameter -{ -public: - RichColor( - const QString& nm, - const QColor& defval, - const QString& desc = QString(), - const QString& tltip = QString(), - bool hidden = false, - const QString& category = QString()); - ~RichColor(); - - QString stringType() const; - - RichColor* clone() const; - bool operator==(const RichParameter& rb); -}; - -class RichAbsPerc : public RichParameter -{ -public: - RichAbsPerc( - const QString& nm, - const Scalarm defval, - const Scalarm minval, - const Scalarm maxval, - const QString& desc = QString(), - const QString& tltip = QString(), - bool hidden = false, - const QString& category = QString()); - ~RichAbsPerc(); - - QString stringType() const; - QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; - - RichAbsPerc* clone() const; - bool operator==(const RichParameter& rb); - Scalarm min; - Scalarm max; -}; - -class RichEnum : public RichParameter -{ -public: - RichEnum( - const QString& nm, - const int defval, - const QStringList& values, - const QString& desc = QString(), - const QString& tltip = QString(), - bool hidden = false, - const QString& category = QString()); - ~RichEnum(); - - QString stringType() const; - QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; - - RichEnum* clone() const; - bool operator==(const RichParameter& rb); - QStringList enumvalues; -}; - -class RichDynamicFloat : public RichParameter -{ -public: - RichDynamicFloat( - const QString& nm, - const Scalarm defval, - const Scalarm minval, - const Scalarm maxval, - const QString& desc = QString(), - const QString& tltip = QString(), - bool hidden = false, - const QString& category = QString()); - ~RichDynamicFloat(); - - QString stringType() const; - QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; - - RichDynamicFloat* clone() const; - bool operator==(const RichParameter& rb); - Scalarm min; - Scalarm max; -}; - -class RichOpenFile : public RichParameter -{ -public: - RichOpenFile( - const QString& nm, - const QString& directorydefval, - const QStringList& exts, - const QString& desc = QString(), - const QString& tltip = QString(), - bool hidden = false, - const QString& category = QString()); - ~RichOpenFile(); - - QString stringType() const; - QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; - - RichOpenFile* clone() const; - bool operator==(const RichParameter& rb); - QStringList exts; -}; - -class RichSaveFile : public RichParameter -{ -public: - RichSaveFile( - const QString& nm, - const QString& filedefval, - const QString& ext, - const QString& desc = QString(), - const QString& tltip = QString(), - bool hidden = false, - const QString& category = QString()); - ~RichSaveFile(); - - QString stringType() const; - QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; - - RichSaveFile* clone() const; - bool operator==(const RichParameter& rb); - QString ext; -}; - -class RichMesh : public RichParameter -{ -public: - RichMesh( - const QString& nm, - unsigned int meshindex, - const MeshDocument* doc, - const QString& desc = QString(), - const QString& tltip = QString(), - bool hidden = false, - const QString& category = QString()); - ~RichMesh(); - - QString stringType() const; - - RichMesh* clone() const; - bool operator==(const RichParameter& rb); - const MeshDocument* meshdoc; -}; - -class RichParameterAdapter -{ -public: - static bool create(const QDomElement& np, RichParameter*& par); -}; - -#endif // MESHLAB_RICH_PARAMETER_H diff --git a/src/common/parameters/rich_parameter/rich_bool.cpp b/src/common/parameters/rich_parameter/rich_bool.cpp new file mode 100644 index 000000000..e68135e7c --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_bool.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_bool.h" + +RichBool::RichBool( + const QString& nm, + const bool defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, BoolValue(defval), desc, tltip, hidden, category) +{ +} + +RichBool::~RichBool() +{ +} + +QString RichBool::stringType() const +{ + return "RichBool"; +} + +RichBool* RichBool::clone() const +{ + return new RichBool(*this); +} + +bool RichBool::operator==( const RichParameter& rb ) +{ + return (rb.value().isBool() && (pName == rb.name()) && (value().getBool() == rb.value().getBool())); +} diff --git a/src/common/parameters/rich_parameter/rich_bool.h b/src/common/parameters/rich_parameter/rich_bool.h new file mode 100644 index 000000000..ea51f70db --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_bool.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_BOOL_H +#define MESHLAB_RICH_BOOL_H + +#include "rich_parameter.h" + +class RichBool : public RichParameter +{ +public: + RichBool( + const QString& nm, + const bool defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichBool(); + + QString stringType() const; + + RichBool* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_BOOL_H diff --git a/src/common/parameters/rich_parameter/rich_color.cpp b/src/common/parameters/rich_parameter/rich_color.cpp new file mode 100644 index 000000000..263ad923f --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_color.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_color.h" + +RichColor::RichColor( + const QString& nm, + const QColor& defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, ColorValue(defval),desc, tltip, hidden, category) +{ +} + +RichColor::~RichColor() +{ +} + +QString RichColor::stringType() const +{ + return "RichColor"; +} + +RichColor* RichColor::clone() const +{ + return new RichColor(*this); +} + +bool RichColor::operator==( const RichParameter& rb ) +{ + return (rb.value().isColor() &&(pName == rb.name()) && (value().getColor() == rb.value().getColor())); +} diff --git a/src/common/parameters/rich_parameter/rich_color.h b/src/common/parameters/rich_parameter/rich_color.h new file mode 100644 index 000000000..2c247e806 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_color.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_COLOR_H +#define MESHLAB_RICH_COLOR_H + +#include "rich_parameter.h" + +class RichColor : public RichParameter +{ +public: + RichColor( + const QString& nm, + const QColor& defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichColor(); + + QString stringType() const; + + RichColor* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_COLOR_H diff --git a/src/common/parameters/rich_parameter/rich_direction.cpp b/src/common/parameters/rich_parameter/rich_direction.cpp new file mode 100644 index 000000000..0fc89ee6e --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_direction.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_direction.h" + +RichDirection::RichDirection( + const QString& nm, + const Point3m& defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, Point3Value(defval), desc, tltip, hidden, category) +{ +} + +RichDirection::~RichDirection() +{ +} + +QString RichDirection::stringType() const +{ + return "RichDirection"; +} + +RichDirection* RichDirection::clone() const +{ + return new RichDirection(*this); +} + +bool RichDirection::operator==(const RichParameter& rb) +{ + return (rb.value().isPoint3() &&(pName == rb.name()) && (value().getPoint3() == rb.value().getPoint3())); +} diff --git a/src/common/parameters/rich_parameter/rich_direction.h b/src/common/parameters/rich_parameter/rich_direction.h new file mode 100644 index 000000000..40e0daa2a --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_direction.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_DIRECTION_H +#define MESHLAB_RICH_DIRECTION_H + +#include "rich_parameter.h" + +class RichDirection : public RichParameter +{ +public: + RichDirection( + const QString& nm, + const Point3m& defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichDirection(); + + QString stringType() const; + + RichDirection* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_DIRECTION_H diff --git a/src/common/parameters/rich_parameter/rich_dynamic_float.cpp b/src/common/parameters/rich_parameter/rich_dynamic_float.cpp new file mode 100644 index 000000000..44c1ccf6c --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_dynamic_float.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_dynamic_float.h" + +RichDynamicFloat::RichDynamicFloat( + const QString& nm, + const Scalarm defval, + const Scalarm minval, + const Scalarm maxval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, FloatValue(defval),desc, tltip, hidden, category), min(minval), max(maxval) +{ +} + +RichDynamicFloat::~RichDynamicFloat() +{ +} + +QString RichDynamicFloat::stringType() const +{ + return "RichDynamicFloat"; +} + +QDomElement RichDynamicFloat::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const +{ + QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); + parElem.setAttribute("min",QString::number(min)); + parElem.setAttribute("max",QString::number(max)); + return parElem; +} + +RichDynamicFloat* RichDynamicFloat::clone() const +{ + return new RichDynamicFloat(*this); +} + +bool RichDynamicFloat::operator==( const RichParameter& rb ) +{ + return (rb.isOfType() &&(pName == rb.name()) && (value().getFloat() == rb.value().getFloat())); +} diff --git a/src/common/parameters/rich_parameter/rich_dynamic_float.h b/src/common/parameters/rich_parameter/rich_dynamic_float.h new file mode 100644 index 000000000..521076100 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_dynamic_float.h @@ -0,0 +1,52 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_DYNAMIC_FLOAT_H +#define MESHLAB_RICH_DYNAMIC_FLOAT_H + +#include "rich_parameter.h" + +class RichDynamicFloat : public RichParameter +{ +public: + RichDynamicFloat( + const QString& nm, + const Scalarm defval, + const Scalarm minval, + const Scalarm maxval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichDynamicFloat(); + + QString stringType() const; + QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; + + RichDynamicFloat* clone() const; + bool operator==(const RichParameter& rb); + Scalarm min; + Scalarm max; +}; + +#endif // MESHLAB_RICH_DYNAMIC_FLOAT_H diff --git a/src/common/parameters/rich_parameter/rich_enum.cpp b/src/common/parameters/rich_parameter/rich_enum.cpp new file mode 100644 index 000000000..48a14f632 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_enum.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_enum.h" + +RichEnum::RichEnum( + const QString& nm, + const int defval, + const QStringList& values, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, IntValue(defval),desc, tltip, hidden, category), enumvalues(values) +{ +} + +RichEnum::~RichEnum() +{ +} + +QString RichEnum::stringType() const +{ + return "RichEnum"; +} + +QDomElement RichEnum::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const +{ + QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); + parElem.setAttribute("enum_cardinality", enumvalues.size()); + for(int ii = 0; ii < enumvalues.size(); ++ii) + parElem.setAttribute(QString("enum_val")+QString::number(ii), enumvalues.at(ii)); + return parElem; +} + +RichEnum* RichEnum::clone() const +{ + return new RichEnum(*this); +} + +bool RichEnum::operator==( const RichParameter& rb ) +{ + return (rb.isOfType() &&(pName == rb.name()) && (value().getInt() == rb.value().getInt())); +} + diff --git a/src/common/parameters/rich_parameter/rich_enum.h b/src/common/parameters/rich_parameter/rich_enum.h new file mode 100644 index 000000000..b9090a463 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_enum.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_ENUM_H +#define MESHLAB_RICH_ENUM_H + +#include "rich_parameter.h" + +class RichEnum : public RichParameter +{ +public: + RichEnum( + const QString& nm, + const int defval, + const QStringList& values, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichEnum(); + + QString stringType() const; + QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; + + RichEnum* clone() const; + bool operator==(const RichParameter& rb); + QStringList enumvalues; +}; + +#endif // MESHLAB_RICH_ENUM_H diff --git a/src/common/parameters/rich_parameter/rich_file_open.cpp b/src/common/parameters/rich_parameter/rich_file_open.cpp new file mode 100644 index 000000000..a811f190e --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_file_open.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_file_open.h" + +RichFileOpen::RichFileOpen( + const QString& nm, + const QString& directorydefval, + const QStringList& exts, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, StringValue(directorydefval), desc, tltip, hidden, category), exts(exts) +{ +} + +RichFileOpen::~RichFileOpen() +{ +} + +QString RichFileOpen::stringType() const +{ + return "RichOpenFile"; +} + +QDomElement RichFileOpen::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const +{ + QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); + parElem.setAttribute("exts_cardinality", exts.size()); + for(int ii = 0; ii < exts.size(); ++ii) + parElem.setAttribute(QString("ext_val")+QString::number(ii), exts[ii]); + return parElem; +} + +RichFileOpen* RichFileOpen::clone() const +{ + return new RichFileOpen(*this); +} + +bool RichFileOpen::operator==( const RichParameter& rb ) +{ + return (rb.isOfType() &&(pName == rb.name()) && (value().getString() == rb.value().getString())); +} diff --git a/src/common/parameters/rich_parameter/rich_file_open.h b/src/common/parameters/rich_parameter/rich_file_open.h new file mode 100644 index 000000000..e65535542 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_file_open.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_FILE_OPEN_H +#define MESHLAB_RICH_FILE_OPEN_H + +#include "rich_parameter.h" + +class RichFileOpen : public RichParameter +{ +public: + RichFileOpen( + const QString& nm, + const QString& directorydefval, + const QStringList& exts, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichFileOpen(); + + QString stringType() const; + QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; + + RichFileOpen* clone() const; + bool operator==(const RichParameter& rb); + QStringList exts; +}; + +#endif // MESHLAB_RICH_FILE_OPEN_H diff --git a/src/common/parameters/rich_parameter/rich_file_save.cpp b/src/common/parameters/rich_parameter/rich_file_save.cpp new file mode 100644 index 000000000..c5fd62854 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_file_save.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_file_save.h" + +RichFileSave::RichFileSave( + const QString& nm, + const QString& filedefval, + const QString& ext, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, StringValue(filedefval), desc, tltip, hidden, category), ext(ext) +{ +} + +RichFileSave::~RichFileSave() +{ +} + +QString RichFileSave::stringType() const +{ + return "RichSaveFile"; +} + +QDomElement RichFileSave::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const +{ + QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); + parElem.setAttribute("ext", ext); + return parElem; +} + +RichFileSave* RichFileSave::clone() const +{ + return new RichFileSave(*this); +} + +bool RichFileSave::operator==( const RichParameter& rb ) +{ + return (rb.isOfType() &&(pName == rb.name()) && (value().getString() == rb.value().getString())); +} diff --git a/src/common/parameters/rich_parameter/rich_file_save.h b/src/common/parameters/rich_parameter/rich_file_save.h new file mode 100644 index 000000000..09faf757c --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_file_save.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_FILE_SAVE_H +#define MESHLAB_RICH_FILE_SAVE_H + +#include "rich_parameter.h" + +class RichFileSave : public RichParameter +{ +public: + RichFileSave( + const QString& nm, + const QString& filedefval, + const QString& ext, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichFileSave(); + + QString stringType() const; + QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; + + RichFileSave* clone() const; + bool operator==(const RichParameter& rb); + QString ext; +}; + +#endif // MESHLAB_RICH_FILE_SAVE_H diff --git a/src/common/parameters/rich_parameter/rich_float.cpp b/src/common/parameters/rich_parameter/rich_float.cpp new file mode 100644 index 000000000..14dedb117 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_float.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_float.h" + +RichFloat::RichFloat( + const QString& nm, + const Scalarm defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, FloatValue(defval),desc, tltip, hidden, category) +{ +} + +RichFloat::~RichFloat() +{ +} + +QString RichFloat::stringType() const +{ + return "RichFloat"; +} + +RichFloat* RichFloat::clone() const +{ + return new RichFloat(*this); +} + +bool RichFloat::operator==( const RichParameter& rb ) +{ + return (rb.value().isFloat() &&(pName == rb.name()) && (value().getFloat() == rb.value().getFloat())); +} + diff --git a/src/common/parameters/rich_parameter/rich_float.h b/src/common/parameters/rich_parameter/rich_float.h new file mode 100644 index 000000000..0ae4eecdb --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_float.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_FLOAT_H +#define MESHLAB_RICH_FLOAT_H + +#include "rich_parameter.h" + +class RichFloat : public RichParameter +{ +public: + RichFloat( + const QString& nm, + const Scalarm defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichFloat(); + + QString stringType() const; + + RichFloat* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_FLOAT_H diff --git a/src/common/parameters/rich_parameter/rich_int.cpp b/src/common/parameters/rich_parameter/rich_int.cpp new file mode 100644 index 000000000..6b5b4aa40 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_int.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_int.h" + +RichInt::RichInt( + const QString& nm, + const int defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, IntValue(defval),desc, tltip, hidden, category) +{ +} + +RichInt::~RichInt() +{ +} + +QString RichInt::stringType() const +{ + return "RichInt"; +} + +RichInt* RichInt::clone() const +{ + return new RichInt(*this); +} + +bool RichInt::operator==( const RichParameter& rb ) +{ + return (rb.value().isInt() &&(pName == rb.name()) && (value().getInt() == rb.value().getInt())); +} + diff --git a/src/common/parameters/rich_parameter/rich_int.h b/src/common/parameters/rich_parameter/rich_int.h new file mode 100644 index 000000000..ed5f3320a --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_int.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_INT_H +#define MESHLAB_RICH_INT_H + +#include "rich_parameter.h" + +class RichInt : public RichParameter +{ +public: + RichInt( + const QString& nm, + const int defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichInt(); + + QString stringType() const; + + RichInt* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_INT_H diff --git a/src/common/parameters/rich_parameter/rich_matrix44.cpp b/src/common/parameters/rich_parameter/rich_matrix44.cpp new file mode 100644 index 000000000..3b324d0a2 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_matrix44.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_matrix44.h" + +RichMatrix44::RichMatrix44( + const QString& nm, + const Matrix44m& defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, Matrix44Value(defval),desc, tltip, hidden, category) +{ +} + +RichMatrix44::~RichMatrix44() +{ +} + +QString RichMatrix44::stringType() const +{ + return "RichMatrix44f"; +} + +RichMatrix44* RichMatrix44::clone() const +{ + return new RichMatrix44(*this); +} + +bool RichMatrix44::operator==( const RichParameter& rb ) +{ + return (rb.value().isMatrix44() &&(pName == rb.name()) && (value().getMatrix44() == rb.value().getMatrix44())); +} + diff --git a/src/common/parameters/rich_parameter/rich_matrix44.h b/src/common/parameters/rich_parameter/rich_matrix44.h new file mode 100644 index 000000000..997de4be3 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_matrix44.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_MATRIX44_H +#define MESHLAB_RICH_MATRIX44_H + +#include "rich_parameter.h" + +class RichMatrix44 : public RichParameter +{ +public: + RichMatrix44( + const QString& nm, + const Matrix44m& defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichMatrix44(); + + QString stringType() const; + + RichMatrix44* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_MATRIX44_H diff --git a/src/common/parameters/rich_parameter/rich_mesh.cpp b/src/common/parameters/rich_parameter/rich_mesh.cpp new file mode 100644 index 000000000..6d2c9e604 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_mesh.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_mesh.h" + +RichMesh::RichMesh( + const QString& nm, + unsigned int meshind, + const MeshDocument* doc, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category): + RichParameter(nm,IntValue(meshind), desc, tltip, hidden, category), meshdoc(doc) +{ +} + +RichMesh::~RichMesh() +{ +} + +QString RichMesh::stringType() const +{ + return "RichMesh"; +} + +RichMesh* RichMesh::clone() const +{ + return new RichMesh(*this); +} + +bool RichMesh::operator==( const RichParameter& rb ) +{ + return (rb.isOfType() &&(pName == rb.name()) && (value().getInt() == rb.value().getInt())); +} + diff --git a/src/common/parameters/rich_parameter/rich_mesh.h b/src/common/parameters/rich_parameter/rich_mesh.h new file mode 100644 index 000000000..48b1f106b --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_mesh.h @@ -0,0 +1,49 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_MESH_H +#define MESHLAB_RICH_MESH_H + +#include "rich_parameter.h" + +class RichMesh : public RichParameter +{ +public: + RichMesh( + const QString& nm, + unsigned int meshindex, + const MeshDocument* doc, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichMesh(); + + QString stringType() const; + + RichMesh* clone() const; + bool operator==(const RichParameter& rb); + const MeshDocument* meshdoc; +}; + +#endif // MESHLAB_RICH_MESH_H diff --git a/src/common/parameters/rich_parameter/rich_parameter.cpp b/src/common/parameters/rich_parameter/rich_parameter.cpp new file mode 100644 index 000000000..3010c5909 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_parameter.cpp @@ -0,0 +1,186 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_parameter.h" + +#include +#include + +RichParameter::RichParameter(const RichParameter& rp) : + pName(rp.pName), + val(rp.value().clone()), + fieldDesc(rp.fieldDesc), + tooltip(rp.tooltip), + advanced(rp.advanced), + defaultValue(rp.defaultValue), + pCategory(rp.pCategory) +{ +} + +RichParameter::RichParameter(RichParameter&& rp) +{ + swap(rp); +} + +RichParameter::RichParameter( + const QString& nm, + const Value& v, + const QString& desc, + const QString& tltip, + bool isAdvanced, + const QString& category) : + pName(nm), + val(v.clone()), + fieldDesc(desc), + tooltip(tltip), + advanced(isAdvanced), + defaultValue(true), + pCategory(category) +{ +} + +RichParameter::~RichParameter() +{ + delete val; +} + +const QString& RichParameter::name() const +{ + return pName; +} + +const Value& RichParameter::value() const +{ + return *val; +} + +const QString& RichParameter::fieldDescription() const +{ + return fieldDesc; +} + +const QString& RichParameter::toolTip() const +{ + return tooltip; +} + +bool RichParameter::isAdvanced() const +{ + return advanced; +} + +bool RichParameter::isValueDefault() const +{ + return defaultValue; +} + +const QString& RichParameter::category() const +{ + return pCategory; +} + +void RichParameter::setName(const QString& newName) +{ + pName = newName; +} + +void RichParameter::setValue(const Value& ov, bool isDefault) +{ + assert(val->typeName() == ov.typeName()); + delete val; + val = ov.clone(); + defaultValue = isDefault; +} + +void RichParameter::setDefaultValue(bool isDefault) +{ + defaultValue = isDefault; +} + +QDomElement RichParameter::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const +{ + QDomElement parElem = doc.createElement("Param"); + parElem.setAttribute("name", pName); + parElem.setAttribute("type", stringType()); + if (saveDescriptionAndTooltip) { + parElem.setAttribute("description", fieldDesc); + parElem.setAttribute("tooltip",tooltip); + } + val->fillToXMLElement(parElem); + return parElem; +} + +/** + * @brief returns the name of the parameter used in python (for pymeshlab) + */ +QString RichParameter::pythonName() const +{ + return pymeshlab::computePythonName(pName); +} + +/** + * @brief returns the type if the parameter (as a string) used in python + * (for pymeshlab) + */ +QString RichParameter::pythonType() const +{ + return pymeshlab::computePythonTypeString(*this); +} + +RichParameter& RichParameter::operator=(const RichParameter& rp) +{ + if (&rp != this){ + delete val; + val = rp.value().clone(); + pName = rp.pName; + fieldDesc = rp.fieldDesc; + tooltip = rp.tooltip; + advanced = rp.advanced; + defaultValue = rp.defaultValue; + pCategory = rp.pCategory; + } + return *this; +} + +RichParameter& RichParameter::operator=(RichParameter&& rp) +{ + ::swap(*this, rp); + return *this; +} + +void RichParameter::swap(RichParameter &rp) +{ + ::swap(*this, rp); +} + +void swap(RichParameter &rp1, RichParameter &rp2) +{ + using std::swap; + swap(rp1.pName, rp2.pName); + swap(rp1.val, rp2.val); + swap(rp1.fieldDesc, rp2.fieldDesc); + swap(rp1.tooltip, rp2.tooltip); + swap(rp1.advanced, rp2.advanced); + swap(rp1.defaultValue, rp2.defaultValue); + swap(rp1.pCategory, rp2.pCategory); +} diff --git a/src/common/parameters/rich_parameter/rich_parameter.h b/src/common/parameters/rich_parameter/rich_parameter.h new file mode 100644 index 000000000..6621495c9 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_parameter.h @@ -0,0 +1,109 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_PARAMETER_H +#define MESHLAB_RICH_PARAMETER_H + +#include + +#include + +class MeshDocument; + +/** + * @brief The RichParameter class + * + * The RichParameter class is a representation of a MeshLab parameter that contains + * a value of a certain type (see the Value class and its specializations) plus + * some other decorators, like a parameter description and a tooltip. + * + * All these decorators allow MeshLab to automatically design GUI interfaces for + * every RichParameter spcialization. + * + * Every specialization must implement the following member functions: + * - QString stringType() const : returns a string representation of the type of the RichParameter + * - RichParameter* clone() const : returns a *new* object which is a clone of the RichParameter + * - bool operator==(const RichParameter& rp): returns true if the two RichParameter are the same + */ +class RichParameter +{ +public: + RichParameter(const RichParameter& rp); + RichParameter(RichParameter&& rp); + RichParameter( + const QString& nm, + const Value& v, + const QString& desc = QString(), + const QString& tltip = QString(), + bool isAdvanced = false, + const QString& category = QString()); + virtual ~RichParameter(); + + const QString& name() const; + const Value& value() const; + const QString& fieldDescription() const; + const QString& toolTip() const; + bool isAdvanced() const; + bool isValueDefault() const; + const QString& category() const; + + template + bool isOfType() const + { + const RichParam* t = dynamic_cast(this); + return (t != nullptr); + } + + void setName(const QString& newName); + void setValue(const Value& ov, bool isDefault = false); + void setDefaultValue(bool isDefault = true); + + virtual QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; + + //python names of paraeter + QString pythonName() const; + QString pythonType() const; + + RichParameter& operator=(const RichParameter& rp); + RichParameter& operator=(RichParameter&& rp); + + virtual RichParameter* clone() const = 0; + virtual QString stringType() const = 0; + virtual bool operator==(const RichParameter& rp) = 0; + + friend void swap(RichParameter& rp1, RichParameter& rp2); + void swap(RichParameter& rp); + +protected: + QString pName; + Value* val; + QString fieldDesc; + QString tooltip; + bool advanced; + bool defaultValue; + QString pCategory; +}; + +void swap(RichParameter& rp1, RichParameter& rp2); + +#endif // MESHLAB_RICH_PARAMETER_H diff --git a/src/common/parameters/rich_parameter/rich_percentage.cpp b/src/common/parameters/rich_parameter/rich_percentage.cpp new file mode 100644 index 000000000..689fcd224 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_percentage.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_percentage.h" + +RichPercentage::RichPercentage( + const QString& nm, + const Scalarm defval, + const Scalarm minval, + const Scalarm maxval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, FloatValue(defval), desc, tltip, hidden, category), min(minval), max(maxval) +{ +} + +RichPercentage::~RichPercentage() +{ +} + +QString RichPercentage::stringType() const +{ + return "RichAbsPerc"; +} + +QDomElement RichPercentage::fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip) const +{ + QDomElement parElem = RichParameter::fillToXMLDocument(doc, saveDescriptionAndTooltip); + parElem.setAttribute("min",QString::number(min)); + parElem.setAttribute("max",QString::number(max)); + return parElem; +} + +RichPercentage* RichPercentage::clone() const +{ + return new RichPercentage(*this); +} + +bool RichPercentage::operator==( const RichParameter& rb ) +{ + return (rb.isOfType() &&(pName == rb.name()) && (value().getFloat() == rb.value().getFloat())); +} diff --git a/src/common/parameters/rich_parameter/rich_percentage.h b/src/common/parameters/rich_parameter/rich_percentage.h new file mode 100644 index 000000000..23b8659b1 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_percentage.h @@ -0,0 +1,52 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_PERCENTAGE_H +#define MESHLAB_RICH_PERCENTAGE_H + +#include "rich_parameter.h" + +class RichPercentage : public RichParameter +{ +public: + RichPercentage( + const QString& nm, + const Scalarm defval, + const Scalarm minval, + const Scalarm maxval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichPercentage(); + + QString stringType() const; + QDomElement fillToXMLDocument(QDomDocument& doc, bool saveDescriptionAndTooltip = true) const; + + RichPercentage* clone() const; + bool operator==(const RichParameter& rb); + Scalarm min; + Scalarm max; +}; + +#endif // MESHLAB_RICH_PERCENTAGE_H diff --git a/src/common/parameters/rich_parameter/rich_position.cpp b/src/common/parameters/rich_parameter/rich_position.cpp new file mode 100644 index 000000000..cb23a4f16 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_position.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_position.h" + +RichPosition::RichPosition( + const QString& nm, + const Point3m& defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, Point3Value(defval),desc, tltip, hidden, category) +{ +} + +RichPosition::~RichPosition() +{ +} + +QString RichPosition::stringType() const +{ + return "RichPosition"; +} + +RichPosition* RichPosition::clone() const +{ + return new RichPosition(*this); +} + +bool RichPosition::operator==( const RichParameter& rb ) +{ + return (rb.value().isPoint3() &&(pName == rb.name()) && (value().getPoint3() == rb.value().getPoint3())); +} + diff --git a/src/common/parameters/rich_parameter/rich_position.h b/src/common/parameters/rich_parameter/rich_position.h new file mode 100644 index 000000000..3daa6db0c --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_position.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_POSITION_H +#define MESHLAB_RICH_POSITION_H + +#include "rich_parameter.h" + +class RichPosition : public RichParameter +{ +public: + RichPosition( + const QString& nm, + const Point3m& defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichPosition(); + + QString stringType() const; + + RichPosition* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_POSITION_H diff --git a/src/common/parameters/rich_parameter/rich_shot.cpp b/src/common/parameters/rich_parameter/rich_shot.cpp new file mode 100644 index 000000000..c6144000a --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_shot.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_shot.h" + +RichShot::RichShot( + const QString& nm, + const Shotm& defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, ShotValue(defval),desc, tltip, hidden, category) +{ +} + +RichShot::~RichShot() +{ +} + +QString RichShot::stringType() const +{ + return "RichShotf"; +} + +RichShot* RichShot::clone() const +{ + return new RichShot(*this); +} + +bool RichShot::operator==( const RichParameter& rb ) +{ + return (rb.value().isShot() &&(pName == rb.name()) ); + // TODO REAL TEST OF EQUALITY // && (value().getShotf() == rb.value().getShotf())); +} + diff --git a/src/common/parameters/rich_parameter/rich_shot.h b/src/common/parameters/rich_parameter/rich_shot.h new file mode 100644 index 000000000..a6b9a4a0e --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_shot.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_SHOT_H +#define MESHLAB_RICH_SHOT_H + +#include "rich_parameter.h" + +class RichShot : public RichParameter +{ +public: + RichShot( + const QString& nm, + const Shotm& defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichShot(); + + QString stringType() const; + + RichShot* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_SHOT_H diff --git a/src/common/parameters/rich_parameter/rich_string.cpp b/src/common/parameters/rich_parameter/rich_string.cpp new file mode 100644 index 000000000..fec0ea3df --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_string.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_string.h" + +RichString::RichString( + const QString& nm, + const QString& defval, + const QString& desc, + const QString& tltip, + bool hidden, + const QString& category) : + RichParameter(nm, StringValue(defval),desc,tltip, hidden, category) +{ +} + +RichString::~RichString() +{ +} + +QString RichString::stringType() const +{ + return "RichString"; +} + +RichString* RichString::clone() const +{ + return new RichString(*this); +} + +bool RichString::operator==( const RichParameter& rb ) +{ + return (rb.value().isString() &&(pName == rb.name()) && (value().getString() == rb.value().getString())); +} + diff --git a/src/common/parameters/rich_parameter/rich_string.h b/src/common/parameters/rich_parameter/rich_string.h new file mode 100644 index 000000000..f02771a67 --- /dev/null +++ b/src/common/parameters/rich_parameter/rich_string.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_STRING_H +#define MESHLAB_RICH_STRING_H + +#include "rich_parameter.h" + +class RichString : public RichParameter +{ +public: + RichString( + const QString& nm, + const QString& defval, + const QString& desc = QString(), + const QString& tltip = QString(), + bool hidden = false, + const QString& category = QString()); + ~RichString(); + + QString stringType() const; + + RichString* clone() const; + bool operator==(const RichParameter& rb); +}; + +#endif // MESHLAB_RICH_STRING_H diff --git a/src/common/parameters/rich_parameter_list.cpp b/src/common/parameters/rich_parameter_list.cpp index 344b3643a..7b249849e 100644 --- a/src/common/parameters/rich_parameter_list.cpp +++ b/src/common/parameters/rich_parameter_list.cpp @@ -152,7 +152,7 @@ QString RichParameterList::getString(const QString& name) const */ Matrix44m RichParameterList::getMatrix44(const QString& name) const { - return getParameterByName(name).value().getMatrix44f(); + return getParameterByName(name).value().getMatrix44(); } /** @@ -161,7 +161,7 @@ Matrix44m RichParameterList::getMatrix44(const QString& name) const */ Point3m RichParameterList::getPoint3m(const QString& name) const { - return getParameterByName(name).value().getPoint3f(); + return getParameterByName(name).value().getPoint3(); } /** @@ -170,7 +170,7 @@ Point3m RichParameterList::getPoint3m(const QString& name) const */ Shot RichParameterList::getShotf(const QString& name) const { - return Shot::Construct(getParameterByName(name).value().getShotf()); + return Shot::Construct(getParameterByName(name).value().getShot()); } /** @@ -335,6 +335,13 @@ void RichParameterList::setValue(const QString& name,const Value& newval) getParameterByName(name).setValue(newval); } +void RichParameterList::setAllValuesAsDefault() +{ + for (auto& p : paramList) { + p->setDefaultValue(); + } +} + /** * @brief adds a RichParameter to the list. * @return a reference to the added parameter diff --git a/src/common/parameters/rich_parameter_list.h b/src/common/parameters/rich_parameter_list.h index 13bb2af3f..4c3177614 100644 --- a/src/common/parameters/rich_parameter_list.h +++ b/src/common/parameters/rich_parameter_list.h @@ -24,7 +24,7 @@ #ifndef MESHLAB_RICH_PARAMETER_LIST_H #define MESHLAB_RICH_PARAMETER_LIST_H -#include "rich_parameter.h" +#include "rich_parameters.h" /** * @brief The RichParameterList class @@ -123,6 +123,7 @@ public: unsigned int numberAdvancedParameters() const; void setValue(const QString& name, const Value& val); + void setAllValuesAsDefault(); RichParameter& addParam(const RichParameter& pd); void join(const RichParameterList& rps); diff --git a/src/common/parameters/rich_parameters.cpp b/src/common/parameters/rich_parameters.cpp new file mode 100644 index 000000000..43580fcd1 --- /dev/null +++ b/src/common/parameters/rich_parameters.cpp @@ -0,0 +1,227 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_parameters.h" + +bool RichParameterAdapter::create( const QDomElement& np,RichParameter*& par ) +{ + QString name=np.attribute("name"); + QString type=np.attribute("type"); + QString desc=np.attribute("description"); + QString tooltip=np.attribute("tooltip"); + + // qDebug(" Reading Param with name %s : %s", qUtf8Printable(name), qUtf8Printable(type)); + + bool corrconv = false; + if(type=="RichBool") { + QString val = np.attribute("value").toLower(); + if ((val != QString("true")) && (val != QString("false"))) + return false; + par = new RichBool(name,np.attribute("value")!=QString("false"),desc,tooltip); + return true; + } + + if(type=="RichInt") { + int val = np.attribute("value").toInt(&corrconv); + if (!corrconv) + return false; + par = new RichInt(name,val,desc,tooltip); + return true; + } + + if(type=="RichFloat") { + float val = np.attribute("value").toFloat(&corrconv); + if (!corrconv) + return false; + par = new RichFloat(name,val,desc,tooltip); + return true; + } + + if(type=="RichString") { + par = new RichString(name,np.attribute("value"),desc,tooltip); + return true; + } + + if(type=="RichAbsPerc") { + float val = np.attribute("value").toFloat(&corrconv); + if ((!corrconv) && (val >= 0.0f) && (val <= 100.0f)) + return false; + float min = np.attribute("min").toFloat(&corrconv); + if (!corrconv) + return false; + float max = np.attribute("max").toFloat(&corrconv); + if (!corrconv) + return false; + par = new RichPercentage(name,val,min,max,desc,tooltip); + return true; + } + + if(type=="RichColor") { + unsigned int r = np.attribute("r").toUInt(&corrconv); + if ((!corrconv) && (r <= 255)) + return false; + unsigned int g = np.attribute("g").toUInt(&corrconv); + if ((!corrconv) && (g <= 255)) + return false; + unsigned int b = np.attribute("b").toUInt(&corrconv); + if ((!corrconv) && (b <= 255)) + return false; + unsigned int a = np.attribute("a").toUInt(&corrconv); + if ((!corrconv) && (a <= 255)) + return false; + QColor col(r,g,b,a); + par= new RichColor(name,col,desc,tooltip); + return true; + } + + if(type=="RichMatrix44f") { + Matrix44m mm; + for(int i=0;i<16;++i) + { + Scalarm val = np.attribute(QString("val")+QString::number(i)).toFloat(&corrconv); + if (!corrconv) + return false; + mm.V()[i]=val; + } + par = new RichMatrix44(name,mm,desc,tooltip); + return true; + } + + if(type=="RichEnum") { + QStringList list; + int enum_card = np.attribute(QString("enum_cardinality")).toUInt(&corrconv); + if (!corrconv) + return false; + + for(int i=0;i=0) && (val < enum_card)) + return false; + par = new RichEnum(name,val,list,desc,tooltip); + return true; + } + + if(type == "RichMesh") { + int val = np.attribute("value").toInt(&corrconv); + + if (!corrconv) + return false; + + par = new RichMesh(name, val, nullptr, desc,tooltip); + return true; + } + + if(type == "RichDynamicFloat") { + float min = np.attribute("min").toFloat(&corrconv); + if (!corrconv) + return false; + float max = np.attribute("max").toFloat(&corrconv); + if (!corrconv) + return false; + + float val = np.attribute("value").toFloat(&corrconv); + if ((!corrconv) && (val >= min) && (val <= max)) + return false; + + par = new RichDynamicFloat(name, val, min, max, desc, tooltip); + return true; + } + + if(type == "RichOpenFile") { + QStringList list; + int exts_card = np.attribute(QString("exts_cardinality")).toUInt(&corrconv); + if (!corrconv) + return false; + + for(int i=0;i -#include -#include "../ml_document/cmesh.h" -class MeshModel; -class MeshDocument; -class QDomElement; - -/** - * @brief The Value class - * - * Represents a generic parameter value for meshlab. - * Specializations inherit from this class, depending on the type of the - * value. Value class is an attribute of the RichParameter class. - */ -class Value -{ -public: - virtual ~Value() {} - - virtual bool getBool() const { assert(0); return bool(); } - virtual int getInt() const { assert(0); return int(); } - virtual Scalarm getFloat() const { assert(0); return Scalarm(); } - virtual QString getString() const { assert(0); return QString(); } - virtual Matrix44m getMatrix44f() const { assert(0); return Matrix44m(); } - virtual Point3m getPoint3f() const { assert(0); return Point3m(); } - virtual Shotm getShotf() const { assert(0); return Shotm(); } - virtual QColor getColor() const { assert(0); return QColor(); } - - virtual bool isBool() const { return false; } - virtual bool isInt() const { return false; } - virtual bool isFloat() const { return false; } - virtual bool isString() const { return false; } - virtual bool isMatrix44f() const { return false; } - virtual bool isPoint3f() const { return false; } - virtual bool isShotf() const { return false; } - virtual bool isColor() const { return false; } - - virtual QString typeName() const = 0; - virtual void set(const Value& p) = 0; - virtual Value* clone() const = 0; - virtual void fillToXMLElement(QDomElement& element) const = 0; -}; - -class BoolValue : public Value -{ -public: - BoolValue(const bool val) : pval(val) {}; - ~BoolValue() {} - - inline bool getBool() const { return pval; } - inline bool isBool() const { return true; } - inline QString typeName() const { return QString("Bool"); } - inline void set(const Value& p) { pval = p.getBool(); } - inline BoolValue* clone() const {return new BoolValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - bool pval; -}; - -class IntValue : public Value -{ -public: - IntValue(const int val) : pval(val) {} - ~IntValue() {} - - inline int getInt() const { return pval; } - inline bool isInt() const { return true; } - inline QString typeName() const { return QString("Int"); } - inline void set(const Value& p) { pval = p.getInt(); } - inline IntValue* clone() const {return new IntValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - int pval; -}; - -class FloatValue : public Value -{ -public: - FloatValue(const float val) :pval(val) {} - ~FloatValue() {} - - inline Scalarm getFloat() const { return pval; } - inline bool isFloat() const { return true; } - inline QString typeName() const { return QString("Float"); } - inline void set(const Value& p) { pval = p.getFloat(); } - inline FloatValue* clone() const {return new FloatValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - Scalarm pval; -}; - -class StringValue : public Value -{ -public: - StringValue(const QString& val) :pval(val) {} - ~StringValue() {} - - inline QString getString() const { return pval; } - inline bool isString() const { return true; } - inline QString typeName() const { return QString("String"); } - inline void set(const Value& p) { pval = p.getString(); } - inline StringValue* clone() const {return new StringValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - QString pval; -}; - -class Matrix44fValue : public Value -{ -public: - Matrix44fValue(const Matrix44m& val) :pval(val) {} - //Matrix44fValue(const vcg::Matrix44d& val) :pval(vcg::Matrix44f::Construct(val)) {} - ~Matrix44fValue() {} - - inline Matrix44m getMatrix44f() const { return pval; } - inline bool isMatrix44f() const { return true; } - inline QString typeName() const { return QString("Matrix44f"); } - inline void set(const Value& p) { pval = p.getMatrix44f(); } - inline Matrix44fValue* clone() const {return new Matrix44fValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - Matrix44m pval; -}; - -class Point3fValue : public Value -{ -public: - Point3fValue(const Point3m& val) : pval(val) {} - ~Point3fValue() {} - - inline Point3m getPoint3f() const { return pval; } - inline bool isPoint3f() const { return true; } - inline QString typeName() const { return QString("Point3f"); } - inline void set(const Value& p) { pval = p.getPoint3f(); } - inline Point3fValue* clone() const {return new Point3fValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - Point3m pval; -}; - -class ShotfValue : public Value -{ -public: - ShotfValue(const Shotm& val) : pval(val) {} - ~ShotfValue() {} - - inline Shotm getShotf() const { return pval; } - inline bool isShotf() const { return true; } - inline QString typeName() const { return QString("Shotf"); } - inline void set(const Value& p) { pval = p.getShotf(); } - inline ShotfValue* clone() const {return new ShotfValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - Shotm pval; -}; - -class ColorValue : public Value -{ -public: - ColorValue(QColor val) :pval(val) {} - ~ColorValue() {} - - inline QColor getColor() const { return pval; } - inline bool isColor() const { return true; } - inline QString typeName() const { return QString("Color"); } - inline void set(const Value& p) { pval = p.getColor(); } - inline ColorValue* clone() const {return new ColorValue(*this);} - void fillToXMLElement(QDomElement& element) const; - -private: - QColor pval; -}; - -#endif //MESHLAB_VALUE_H diff --git a/src/common/parameters/value/bool_value.cpp b/src/common/parameters/value/bool_value.cpp new file mode 100644 index 000000000..833fc4f47 --- /dev/null +++ b/src/common/parameters/value/bool_value.cpp @@ -0,0 +1,69 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "bool_value.h" + +#include + +BoolValue::BoolValue(const bool val) : pval(val) +{ +} + +bool BoolValue::getBool() const +{ + return pval; +} + +bool BoolValue::isBool() const +{ + return true; +} + +QString BoolValue::typeName() const +{ + return QString("Bool"); +} + +void BoolValue::set(const Value &p) +{ + pval = p.getBool(); +} + +BoolValue *BoolValue::clone() const +{ + return new BoolValue(*this); +} + +bool BoolValue::operator==(const Value &p) const +{ + if (p.isBool()) + return pval == p.getBool(); + else + return false; +} + +void BoolValue::fillToXMLElement(QDomElement& element) const +{ + QString v = pval ? "true" : "false"; + element.setAttribute("value", v); +} diff --git a/src/common/parameters/value/bool_value.h b/src/common/parameters/value/bool_value.h new file mode 100644 index 000000000..b5c934128 --- /dev/null +++ b/src/common/parameters/value/bool_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_BOOL_VALUE_H +#define MESHLAB_BOOL_VALUE_H + +#include "value.h" + +class BoolValue : public Value +{ +public: + BoolValue(const bool val); + ~BoolValue() {} + + bool getBool() const; + bool isBool() const; + QString typeName() const; + void set(const Value& p); + BoolValue* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + bool pval; +}; + +#endif // MESHLAB_BOOL_VALUE_H diff --git a/src/common/parameters/value/color_value.cpp b/src/common/parameters/value/color_value.cpp new file mode 100644 index 000000000..f40b3decb --- /dev/null +++ b/src/common/parameters/value/color_value.cpp @@ -0,0 +1,71 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "color_value.h" + +#include + +ColorValue::ColorValue(QColor val) : pval(val) +{ +} + +QColor ColorValue::getColor() const +{ + return pval; +} + +bool ColorValue::isColor() const +{ + return true; +} + +QString ColorValue::typeName() const +{ + return QString("Color"); +} + +void ColorValue::set(const Value& p) +{ + pval = p.getColor(); +} + +ColorValue* ColorValue::clone() const +{ + return new ColorValue(*this); +} + +bool ColorValue::operator==(const Value& p) const +{ + if (p.isColor()) + return pval == p.getColor(); + else + return false; +} + +void ColorValue::fillToXMLElement(QDomElement& element) const +{ + element.setAttribute("r", QString::number(pval.red())); + element.setAttribute("g", QString::number(pval.green())); + element.setAttribute("b", QString::number(pval.blue())); + element.setAttribute("a", QString::number(pval.alpha())); +} diff --git a/src/common/parameters/value/color_value.h b/src/common/parameters/value/color_value.h new file mode 100644 index 000000000..c497c8e2a --- /dev/null +++ b/src/common/parameters/value/color_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_COLOR_VALUE_H +#define MESHLAB_COLOR_VALUE_H + +#include "value.h" + +class ColorValue : public Value +{ +public: + ColorValue(QColor val); + ~ColorValue() {} + + QColor getColor() const; + bool isColor() const; + QString typeName() const; + void set(const Value& p); + ColorValue* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + QColor pval; +}; + +#endif // MESHLAB_COLOR_VALUE_H diff --git a/src/common/parameters/value/float_value.cpp b/src/common/parameters/value/float_value.cpp new file mode 100644 index 000000000..406642fda --- /dev/null +++ b/src/common/parameters/value/float_value.cpp @@ -0,0 +1,68 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "float_value.h" + +#include + +FloatValue::FloatValue(const float val) : pval(val) +{ +} + +Scalarm FloatValue::getFloat() const +{ + return pval; +} + +bool FloatValue::isFloat() const +{ + return true; +} + +QString FloatValue::typeName() const +{ + return QString("Float"); +} + +void FloatValue::set(const Value& p) +{ + pval = p.getFloat(); +} + +FloatValue* FloatValue::clone() const +{ + return new FloatValue(*this); +} + +bool FloatValue::operator==(const Value& p) const +{ + if (p.isFloat()) + return pval == p.getFloat(); + else + return false; +} + +void FloatValue::fillToXMLElement(QDomElement& element) const +{ + element.setAttribute("value", QString::number(pval)); +} diff --git a/src/common/parameters/value/float_value.h b/src/common/parameters/value/float_value.h new file mode 100644 index 000000000..93530b568 --- /dev/null +++ b/src/common/parameters/value/float_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_FLOAT_VALUE_H +#define MESHLAB_FLOAT_VALUE_H + +#include "value.h" + +class FloatValue : public Value +{ +public: + FloatValue(const float val); + ~FloatValue() {} + + Scalarm getFloat() const; + bool isFloat() const; + QString typeName() const; + void set(const Value& p); + FloatValue* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + Scalarm pval; +}; + +#endif // MESHLAB_FLOAT_VALUE_H diff --git a/src/common/parameters/value/int_value.cpp b/src/common/parameters/value/int_value.cpp new file mode 100644 index 000000000..43ccf594f --- /dev/null +++ b/src/common/parameters/value/int_value.cpp @@ -0,0 +1,63 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "int_value.h" + +#include + +IntValue::IntValue(const int val) : pval(val) +{ +} + +int IntValue::getInt() const +{ + return pval; +} + +QString IntValue::typeName() const +{ + return QString("Int"); +} + +void IntValue::set(const Value& p) +{ + pval = p.getInt(); +} + +IntValue* IntValue::clone() const +{ + return new IntValue(*this); +} + +bool IntValue::operator==(const Value& p) const +{ + if (p.isInt()) + return pval == p.getInt(); + else + return false; +} + +void IntValue::fillToXMLElement(QDomElement& element) const +{ + element.setAttribute("value", QString::number(pval)); +} diff --git a/src/common/parameters/value/int_value.h b/src/common/parameters/value/int_value.h new file mode 100644 index 000000000..8d3479bda --- /dev/null +++ b/src/common/parameters/value/int_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_INT_VALUE_H +#define MESHLAB_INT_VALUE_H + +#include "value.h" + +class IntValue : public Value +{ +public: + IntValue(const int val); + ~IntValue() {} + + int getInt() const; + inline bool isInt() const { return true; } + QString typeName() const; + void set(const Value& p); + IntValue* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + int pval; +}; + +#endif // MESHLAB_INT_VALUE_H diff --git a/src/common/parameters/value/matrix44_value.cpp b/src/common/parameters/value/matrix44_value.cpp new file mode 100644 index 000000000..202cb4d8e --- /dev/null +++ b/src/common/parameters/value/matrix44_value.cpp @@ -0,0 +1,69 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "matrix44_value.h" + +#include + +Matrix44Value::Matrix44Value(const Matrix44m& val) : pval(val) +{ +} + +Matrix44m Matrix44Value::getMatrix44() const +{ + return pval; +} + +bool Matrix44Value::isMatrix44() const +{ + return true; +} + +QString Matrix44Value::typeName() const +{ + return QString("Matrix44"); +} + +void Matrix44Value::set(const Value& p) +{ + pval = p.getMatrix44(); +} + +Matrix44Value* Matrix44Value::clone() const +{ + return new Matrix44Value(*this); +} + +bool Matrix44Value::operator==(const Value& p) const +{ + if (p.isMatrix44()) + return pval == p.getMatrix44(); + else + return false; +} + +void Matrix44Value::fillToXMLElement(QDomElement& element) const +{ + for (unsigned int ii = 0; ii < 16; ++ii) + element.setAttribute(QString("val") + QString::number(ii), QString::number(pval.V()[ii])); +} diff --git a/src/common/parameters/value/matrix44_value.h b/src/common/parameters/value/matrix44_value.h new file mode 100644 index 000000000..b5e75695b --- /dev/null +++ b/src/common/parameters/value/matrix44_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_MATRIX44_VALUE_H +#define MESHLAB_MATRIX44_VALUE_H + +#include "value.h" + +class Matrix44Value : public Value +{ +public: + Matrix44Value(const Matrix44m& val); + ~Matrix44Value() {} + + Matrix44m getMatrix44() const; + bool isMatrix44() const; + QString typeName() const; + void set(const Value& p); + Matrix44Value* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + Matrix44m pval; +}; + +#endif // MESHLAB_MATRIX44_VALUE_H diff --git a/src/common/parameters/value/point3_value.cpp b/src/common/parameters/value/point3_value.cpp new file mode 100644 index 000000000..e8cb906c6 --- /dev/null +++ b/src/common/parameters/value/point3_value.cpp @@ -0,0 +1,70 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "point3_value.h" + +#include + +Point3Value::Point3Value(const Point3m& val) : pval(val) +{ +} + +Point3m Point3Value::getPoint3() const +{ + return pval; +} + +bool Point3Value::isPoint3() const +{ + return true; +} + +QString Point3Value::typeName() const +{ + return QString("Point3"); +} + +void Point3Value::set(const Value& p) +{ + pval = p.getPoint3(); +} + +Point3Value* Point3Value::clone() const +{ + return new Point3Value(*this); +} + +bool Point3Value::operator==(const Value& p) const +{ + if (p.isPoint3()) + return pval == p.getPoint3(); + else + return false; +} + +void Point3Value::fillToXMLElement(QDomElement& element) const +{ + element.setAttribute("x", QString::number(pval.X())); + element.setAttribute("y", QString::number(pval.Y())); + element.setAttribute("z", QString::number(pval.Z())); +} diff --git a/src/common/parameters/value/point3_value.h b/src/common/parameters/value/point3_value.h new file mode 100644 index 000000000..bdfab998e --- /dev/null +++ b/src/common/parameters/value/point3_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_POINT3_VALUE_H +#define MESHLAB_POINT3_VALUE_H + +#include "value.h" + +class Point3Value : public Value +{ +public: + Point3Value(const Point3m& val); + ~Point3Value() {} + + Point3m getPoint3() const; + bool isPoint3() const; + QString typeName() const; + void set(const Value& p); + Point3Value* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + Point3m pval; +}; + +#endif // MESHLAB_POINT3_VALUE_H diff --git a/src/common/parameters/value/shot_value.cpp b/src/common/parameters/value/shot_value.cpp new file mode 100644 index 000000000..379db5236 --- /dev/null +++ b/src/common/parameters/value/shot_value.cpp @@ -0,0 +1,69 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "shot_value.h" + +#include + +ShotValue::ShotValue(const Shotm& val) : pval(val) +{ +} + +Shotm ShotValue::getShot() const +{ + return pval; +} + +bool ShotValue::isShot() const +{ + return true; +} + +QString ShotValue::typeName() const +{ + return QString("Shot"); +} + +void ShotValue::set(const Value& p) +{ + pval = p.getShot(); +} + +ShotValue* ShotValue::clone() const +{ + return new ShotValue(*this); +} + +bool ShotValue::operator==(const Value& p) const +{ + if (p.isShot()) + return pval == p.getShot(); + else + return false; +} + +void ShotValue::fillToXMLElement(QDomElement&) const +{ + assert(0); + // TODO!!! +} diff --git a/src/common/parameters/value/shot_value.h b/src/common/parameters/value/shot_value.h new file mode 100644 index 000000000..c6b3f8e43 --- /dev/null +++ b/src/common/parameters/value/shot_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_SHOT_VALUE_H +#define MESHLAB_SHOT_VALUE_H + +#include "value.h" + +class ShotValue : public Value +{ +public: + ShotValue(const Shotm& val); + ~ShotValue() {} + + Shotm getShot() const; + bool isShot() const; + QString typeName() const; + void set(const Value& p); + ShotValue* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + Shotm pval; +}; + +#endif // MESHLAB_SHOT_VALUE_H diff --git a/src/common/parameters/value/string_value.cpp b/src/common/parameters/value/string_value.cpp new file mode 100644 index 000000000..c5005678e --- /dev/null +++ b/src/common/parameters/value/string_value.cpp @@ -0,0 +1,68 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "string_value.h" + +#include + +StringValue::StringValue(const QString& val) : pval(val) +{ +} + +QString StringValue::getString() const +{ + return pval; +} + +bool StringValue::isString() const +{ + return true; +} + +QString StringValue::typeName() const +{ + return QString("String"); +} + +void StringValue::set(const Value& p) +{ + pval = p.getString(); +} + +StringValue* StringValue::clone() const +{ + return new StringValue(*this); +} + +bool StringValue::operator==(const Value& p) const +{ + if (p.isString()) + return pval == p.getString(); + else + return false; +} + +void StringValue::fillToXMLElement(QDomElement& element) const +{ + element.setAttribute("value", pval); +} diff --git a/src/common/parameters/value/string_value.h b/src/common/parameters/value/string_value.h new file mode 100644 index 000000000..a814d1703 --- /dev/null +++ b/src/common/parameters/value/string_value.h @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_STRING_VALUE_H +#define MESHLAB_STRING_VALUE_H + +#include "value.h" + +class StringValue : public Value +{ +public: + StringValue(const QString& val); + ~StringValue() {} + + QString getString() const; + bool isString() const; + QString typeName() const; + void set(const Value& p); + StringValue* clone() const; + bool operator==(const Value& p) const; + void fillToXMLElement(QDomElement& element) const; + +private: + QString pval; +}; + +#endif // MESHLAB_STRING_VALUE_H diff --git a/src/common/parameters/value/value.h b/src/common/parameters/value/value.h new file mode 100644 index 000000000..3aad13b68 --- /dev/null +++ b/src/common/parameters/value/value.h @@ -0,0 +1,110 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_VALUE_H +#define MESHLAB_VALUE_H + +#include "../../ml_document/cmesh.h" +#include +#include +class MeshModel; +class MeshDocument; +class QDomElement; + +/** + * @brief The Value class + * + * Represents a generic parameter value for meshlab. + * Specializations inherit from this class, depending on the type of the + * value. Value class is an attribute of the RichParameter class. + */ +class Value +{ +public: + virtual ~Value() {} + + virtual bool getBool() const + { + assert(0); + return bool(); + } + virtual int getInt() const + { + assert(0); + return int(); + } + virtual Scalarm getFloat() const + { + assert(0); + return Scalarm(); + } + virtual QString getString() const + { + assert(0); + return QString(); + } + virtual Matrix44m getMatrix44() const + { + assert(0); + return Matrix44m(); + } + virtual Point3m getPoint3() const + { + assert(0); + return Point3m(); + } + virtual Shotm getShot() const + { + assert(0); + return Shotm(); + } + virtual QColor getColor() const + { + assert(0); + return QColor(); + } + + virtual bool isBool() const { return false; } + virtual bool isInt() const { return false; } + virtual bool isFloat() const { return false; } + virtual bool isString() const { return false; } + virtual bool isMatrix44() const { return false; } + virtual bool isPoint3() const { return false; } + virtual bool isShot() const { return false; } + virtual bool isColor() const { return false; } + + virtual QString typeName() const = 0; + virtual void set(const Value& p) = 0; + virtual Value* clone() const = 0; + virtual bool operator==(const Value& p) const = 0; + virtual void fillToXMLElement(QDomElement& element) const = 0; + + template + bool isOfType() const + { + const Val* t = dynamic_cast(this); + return (t != nullptr); + } +}; + +#endif //MESHLAB_VALUE_H diff --git a/src/common/parameters/values.h b/src/common/parameters/values.h new file mode 100644 index 000000000..43c41dafa --- /dev/null +++ b/src/common/parameters/values.h @@ -0,0 +1,36 @@ +/***************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_VALUES_H +#define MESHLAB_VALUES_H + +#include "value/bool_value.h" +#include "value/color_value.h" +#include "value/float_value.h" +#include "value/int_value.h" +#include "value/matrix44_value.h" +#include "value/point3_value.h" +#include "value/shot_value.h" +#include "value/string_value.h" + +#endif // MESHLAB_VALUES_H diff --git a/src/common/python/function.cpp b/src/common/python/function.cpp index 0f867c1cb..5679f9b0f 100644 --- a/src/common/python/function.cpp +++ b/src/common/python/function.cpp @@ -23,7 +23,7 @@ #include "function.h" #include -#include "../parameters/rich_parameter.h" +#include pymeshlab::Function::Function() { diff --git a/src/common/python/function_parameter.cpp b/src/common/python/function_parameter.cpp index c8d32eb4b..685b812ba 100644 --- a/src/common/python/function_parameter.cpp +++ b/src/common/python/function_parameter.cpp @@ -120,8 +120,8 @@ void pymeshlab::FunctionParameter::printDefaultValue(std::ostream& o) const o << "'" << ren->enumvalues.at(ren->value().getInt()).toStdString() << "'"; return; } - if (parameter->isOfType()) { - RichAbsPerc* rabs = dynamic_cast(parameter); + if (parameter->isOfType()) { + RichPercentage* rabs = dynamic_cast(parameter); float abs = parameter->value().getFloat(); float perc = (abs - rabs->min) / (rabs->max - rabs->min) * 100; o << perc << "%"; @@ -133,8 +133,8 @@ void pymeshlab::FunctionParameter::printDefaultValue(std::ostream& o) const " [min: " << rdyn->min << "; max: " << rdyn->max << "]"; return; } - if (parameter->isOfType()){ - const MESHLAB_SCALAR* v = parameter->value().getMatrix44f().V(); + if (parameter->isOfType()){ + const MESHLAB_SCALAR* v = parameter->value().getMatrix44().V(); o << "[[" << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << "]," << "[" << v[4] << ", " << v[5] << ", " << v[6] << ", " << v[7] << "]," << "[" << v[8] << ", " << v[9] << ", " << v[10] << ", " << v[11] << "]," @@ -142,12 +142,12 @@ void pymeshlab::FunctionParameter::printDefaultValue(std::ostream& o) const return; } if (parameter->isOfType() || parameter->isOfType()) { - o << "[" << parameter->value().getPoint3f().X() << ", " - << parameter->value().getPoint3f().Y() << ", " - << parameter->value().getPoint3f().Z() << "]"; + o << "[" << parameter->value().getPoint3().X() << ", " + << parameter->value().getPoint3().Y() << ", " + << parameter->value().getPoint3().Z() << "]"; return; } - if (parameter->isOfType()) { + if (parameter->isOfType()) { o << "None"; return; } @@ -165,7 +165,7 @@ void pymeshlab::FunctionParameter::printDefaultValue(std::ostream& o) const o << rm->value().getInt(); return; } - if (parameter->isOfType() || parameter->isOfType()){ + if (parameter->isOfType() || parameter->isOfType()){ o << "'" << parameter->value().getString().toStdString() << "'"; return; } diff --git a/src/common/python/function_set.cpp b/src/common/python/function_set.cpp index a9d9e8bae..f7fbf522a 100644 --- a/src/common/python/function_set.cpp +++ b/src/common/python/function_set.cpp @@ -62,14 +62,6 @@ void pymeshlab::FunctionSet::loadFilterPlugin(FilterPlugin* fp) f.addParameter(par); } filterSet.insert(f); - - // Just for actual PyMeshLab version; this portion of code will be removed soon - QString oldPythonFilterName = computePythonName(fp->filterName(act)); - f.setPythonFunctionName(oldPythonFilterName); - f.setDeprecated("You should use '" + pythonFilterName.toStdString() + - "' instead of '" + oldPythonFilterName.toStdString() + "'. See " - "https://pymeshlab.readthedocs.io/en/latest/index.html#filters-renaming"); - filterSet.insert(f); } } @@ -85,7 +77,7 @@ void pymeshlab::FunctionSet::loadIOPlugin(IOPlugin* iop) //filename parameter QString sv = "file_name." + inputFormat; QStringList sl(inputFormat); - RichOpenFile of("file_name", sv, sl, "File Name", "The name of the file to load"); + RichFileOpen of("file_name", sv, sl, "File Name", "The name of the file to load"); FunctionParameter par(of); f.addParameter(par); @@ -125,7 +117,7 @@ void pymeshlab::FunctionSet::loadIOPlugin(IOPlugin* iop) } //filename parameter QString sv = "file_name." + outputFormat; - RichSaveFile of("file_name", sv, outputFormat, "File Name", "The name of the file to save"); + RichFileSave of("file_name", sv, outputFormat, "File Name", "The name of the file to save"); FunctionParameter par(of); f.addParameter(par); @@ -150,7 +142,7 @@ void pymeshlab::FunctionSet::loadIOPlugin(IOPlugin* iop) //filename parameter QString sv = "file_name." + inputImageFormat; QStringList sl(inputImageFormat); - RichOpenFile of("file_name", sv, sl, "File Name", "The name of the file to load"); + RichFileOpen of("file_name", sv, sl, "File Name", "The name of the file to load"); FunctionParameter par(of); f.addParameter(par); diff --git a/src/common/python/python_utils.cpp b/src/common/python/python_utils.cpp index ed6e452ba..20429a91c 100644 --- a/src/common/python/python_utils.cpp +++ b/src/common/python/python_utils.cpp @@ -24,13 +24,14 @@ #include "python_utils.h" #include -#include "../parameters/rich_parameter.h" + +#include QString pymeshlab::computePythonTypeString(const RichParameter& par) { if (par.isOfType()) return PYTHON_TYPE_ENUM; - if (par.isOfType()) + if (par.isOfType()) return PYTHON_TYPE_ABSPERC; if (par.isOfType()) return PYTHON_TYPE_DYNAMIC_FLOAT; @@ -42,30 +43,31 @@ QString pymeshlab::computePythonTypeString(const RichParameter& par) return PYTHON_TYPE_FLOAT; if (par.isOfType()) return PYTHON_TYPE_STRING; - if (par.isOfType()) + if (par.isOfType()) return PYTHON_TYPE_MATRIX44F; if (par.isOfType()) return PYTHON_TYPE_POINT3F; if (par.isOfType()) return PYTHON_TYPE_POINT3F; - if (par.isOfType()) + if (par.isOfType()) return PYTHON_TYPE_SHOTF; if (par.isOfType()) return PYTHON_TYPE_COLOR; if (par.isOfType()) return PYTHON_TYPE_MESH; - if (par.isOfType() || par.isOfType()) + if (par.isOfType() || par.isOfType()) return PYTHON_TYPE_FILENAME; return "still_unsupported"; } QString pymeshlab::computePythonName(const QString& name) { + static const QRegularExpression rgexp("[().,'\":+]+"); QString pythonName = name.toLower(); pythonName.replace(' ', '_'); pythonName.replace('/', '_'); pythonName.replace('-', '_'); - pythonName.remove(QRegularExpression("[().,'\":+]+")); + pythonName.remove(rgexp); if (pythonKeywords.contains(pythonName)) pythonName += "_"; diff --git a/src/common/utilities/eigen_mesh_conversions.cpp b/src/common/utilities/eigen_mesh_conversions.cpp index f2946e7b2..6870dee09 100644 --- a/src/common/utilities/eigen_mesh_conversions.cpp +++ b/src/common/utilities/eigen_mesh_conversions.cpp @@ -74,18 +74,20 @@ class PolyMesh : * The only matrix required to be non-empty is the 'vertices' matrix. * Other matrices may be empty. * - * If normals and quality matrices are give, their sizes must be coherent with + * If normals and quality matrices are given, their sizes must be coherent with * the sizes of vertex and face matrices. If this requirement is not satisfied, * a MLException will be thrown. * - * @param vertices: #V*3 matrix of scalars (vertex coordinates) - * @param faces: #F*3 matrix of integers (vertex indices composing the faces) - * @param vertexNormals: #V*3 matrix of scalars (vertex normals) - * @param faceNormals: #F*3 matrix of scalars (face normals) + * @param vertices: #V×3 matrix of scalars (vertex coordinates) + * @param faces: #F×3 matrix of integers (vertex indices composing the faces) + * @param vertexNormals: #V×3 matrix of scalars (vertex normals) + * @param faceNormals: #F×3 matrix of scalars (face normals) * @param vertexQuality: #V vector of scalars (vertex quality) * @param faceQuality: #F vector of scalars (face quality) * @param vertexColor: #V*4 vector of scalars (RGBA vertex colors in interval [0-1]) * @param faceColor: #F*4 vector of scalars (RGBA face colors in interval [0-1]) + * @param vertexTexCoords: #V×2 matrix of scalars (vertex texture coordinates) + * @param wedgeTexCoords: #F*3×2 matrix scalars (texture coordinates for each face edge) * @return a CMeshO made of the given components */ CMeshO meshlab::meshFromMatrices( @@ -97,16 +99,19 @@ CMeshO meshlab::meshFromMatrices( const EigenVectorXm& vertexQuality, const EigenVectorXm& faceQuality, const EigenMatrixX4m& vertexColor, - const EigenMatrixX4m& faceColor) + const EigenMatrixX4m& faceColor, + const EigenMatrixX2m& vertexTexCoords, + const EigenMatrixX2m& wedgeTexCoords) { CMeshO m; if (vertices.rows() > 0) { // add vertices and their associated normals and quality if any std::vector ivp(vertices.rows()); - bool hasVNormals = vertexNormals.rows() > 0; - bool hasVQuality = vertexQuality.rows() > 0; - bool hasVColors = vertexColor.rows() > 0; + bool hasVNormals = vertexNormals.rows() > 0; + bool hasVQuality = vertexQuality.rows() > 0; + bool hasVColors = vertexColor.rows() > 0; + bool hasVTexCoords = vertexTexCoords.rows() > 0; if (hasVNormals && (vertices.rows() != vertexNormals.rows())) { throw MLException( "Error while creating mesh: the number of vertex normals " @@ -122,6 +127,14 @@ CMeshO meshlab::meshFromMatrices( "Error while creating mesh: the number of vertex colors " "is different from the number of vertices."); } + if (hasVTexCoords) { + if ((vertices.rows() != vertexTexCoords.rows())) { + throw MLException( + "Error while creating mesh: the number of vertex texture coordinates " + "is different from the number of vertices."); + } + m.vert.EnableTexCoord(); + } CMeshO::VertexIterator vi = vcg::tri::Allocator::AddVertices(m, vertices.rows()); for (unsigned int i = 0; i < vertices.rows(); ++i, ++vi) { ivp[i] = &*vi; @@ -134,19 +147,25 @@ CMeshO meshlab::meshFromMatrices( vi->Q() = vertexQuality(i); } if (hasVColors) { - vi->C() = CMeshO::VertexType::ColorType( + vi->C().Construct(CMeshO::VertexType::ColorType( vertexColor(i, 0) * 255, vertexColor(i, 1) * 255, vertexColor(i, 2) * 255, - vertexColor(i, 3) * 255); + vertexColor(i, 3) * 255)); + } + if (hasVTexCoords) { + vi->T() = CMeshO::VertexType::TexCoordType( + vertexTexCoords(i, 0), + vertexTexCoords(i, 1)); } } // add faces and their associated normals and quality if any - bool hasFNormals = faceNormals.rows() > 0; - bool hasFQuality = faceQuality.rows() > 0; - bool hasFColors = faceColor.rows() > 0; + bool hasFNormals = faceNormals.rows() > 0; + bool hasFQuality = faceQuality.rows() > 0; + bool hasFColors = faceColor.rows() > 0; + bool hasFWedgeTexCoords = wedgeTexCoords.rows() > 0; if (hasFNormals && (faces.rows() != faceNormals.rows())) { throw MLException( "Error while creating mesh: the number of face normals " @@ -168,6 +187,15 @@ CMeshO meshlab::meshFromMatrices( } m.face.EnableColor(); } + if (hasFWedgeTexCoords) { + if (faces.rows() * 3 != wedgeTexCoords.rows()) { + throw MLException( + "Error while creating mesh: the number of wedge texture coords " + "is different from three times the number of faces (a texture coordinate for " + "each edge of a face."); + } + m.face.EnableWedgeTexCoord(); + } CMeshO::FaceIterator fi = vcg::tri::Allocator::AddFaces(m, faces.rows()); for (unsigned int i = 0; i < faces.rows(); ++i, ++fi) { for (unsigned int j = 0; j < 3; j++) { @@ -190,11 +218,17 @@ CMeshO meshlab::meshFromMatrices( fi->Q() = faceQuality(i); } if (hasFColors) { - fi->C() = CMeshO::FaceType::ColorType( + fi->C().Construct(CMeshO::FaceType::ColorType( faceColor(i, 0) * 255, faceColor(i, 1) * 255, faceColor(i, 2) * 255, - faceColor(i, 3) * 255); + faceColor(i, 3) * 255)); + } + if (hasFWedgeTexCoords) { + for (uint j = 0; j < 3; j++) { + fi->WT(j).U() = wedgeTexCoords(i*3 + j, 0); + fi->WT(j).V() = wedgeTexCoords(i*3 + j, 1); + } } } @@ -241,14 +275,15 @@ CMeshO meshlab::meshFromMatrices( * called 'poly_birth_faces', which stores for each triangle of the mesh, the id * of its polygonal birth face of the polygon mesh given in input. * - * @param vertices: #V*3 matrix of scalars (vertex coordinates) + * @param vertices: #V×3 matrix of scalars (vertex coordinates) * @param faces: #F list of vector of integers (vertex indices composing the faces) - * @param vertexNormals: #V*3 matrix of scalars (vertex normals) - * @param faceNormals: #F*3 matrix of scalars (face normals) + * @param vertexNormals: #V×3 matrix of scalars (vertex normals) + * @param faceNormals: #F×3 matrix of scalars (face normals) * @param vertexQuality: #V vector of scalars (vertex quality) * @param faceQuality: #F vector of scalars (face quality) * @param vertexColor: #V*4 vector of scalars (RGBA vertex colors in interval [0-1]) * @param faceColor: #F*4 vector of scalars (RGBA face colors in interval [0-1]) + * @param vertexTexCoords: #V×2 matrix of scalars (vertex texture coordinates) * @return a CMeshO made of the given components */ CMeshO meshlab::polyMeshFromMatrices( @@ -259,7 +294,8 @@ CMeshO meshlab::polyMeshFromMatrices( const EigenVectorXm& vertexQuality, const EigenVectorXm& faceQuality, const EigenMatrixX4m& vertexColor, - const EigenMatrixX4m& faceColor) + const EigenMatrixX4m& faceColor, + const EigenMatrixX2m& vertexTexCoords) { PolyMesh pm; CMeshO m; @@ -267,9 +303,10 @@ CMeshO meshlab::polyMeshFromMatrices( // add vertices and their associated normals and quality if any std::vector ivp(vertices.rows()); - bool hasVNormals = vertexNormals.rows() > 0; - bool hasVQuality = vertexQuality.rows() > 0; - bool hasVColors = vertexColor.rows() > 0; + bool hasVNormals = vertexNormals.rows() > 0; + bool hasVQuality = vertexQuality.rows() > 0; + bool hasVColors = vertexColor.rows() > 0; + bool hasVTexCoords = vertexTexCoords.rows() > 0; if (hasVNormals && (vertices.rows() != vertexNormals.rows())) { throw MLException( "Error while creating mesh: the number of vertex normals " @@ -285,6 +322,14 @@ CMeshO meshlab::polyMeshFromMatrices( "Error while creating mesh: the number of vertex colors " "is different from the number of vertices."); } + if (hasVTexCoords) { + if ((vertices.rows() != vertexTexCoords.rows())) { + throw MLException( + "Error while creating mesh: the number of vertex texture coordinates " + "is different from the number of vertices."); + } + m.vert.EnableTexCoord(); + } PolyMesh::VertexIterator vi = vcg::tri::Allocator::AddVertices(pm, vertices.rows()); for (unsigned int i = 0; i < vertices.rows(); ++i, ++vi) { @@ -298,11 +343,16 @@ CMeshO meshlab::polyMeshFromMatrices( vi->Q() = vertexQuality(i); } if (hasVColors) { - vi->C() = CMeshO::VertexType::ColorType( + vi->C().Construct(CMeshO::VertexType::ColorType( vertexColor(i, 0) * 255, vertexColor(i, 1) * 255, vertexColor(i, 2) * 255, - vertexColor(i, 3) * 255); + vertexColor(i, 3) * 255)); + } + if (hasVTexCoords) { + vi->T() = CMeshO::VertexType::TexCoordType( + vertexTexCoords(i, 0), + vertexTexCoords(i, 1)); } } @@ -353,11 +403,11 @@ CMeshO meshlab::polyMeshFromMatrices( fi->Q() = faceQuality(i); } if (hasFColors) { - fi->C() = CMeshO::FaceType::ColorType( + fi->C().Construct(CMeshO::FaceType::ColorType( faceColor(i, 0) * 255, faceColor(i, 1) * 255, faceColor(i, 2) * 255, - faceColor(i, 3) * 255); + faceColor(i, 3) * 255)); } } diff --git a/src/common/utilities/eigen_mesh_conversions.h b/src/common/utilities/eigen_mesh_conversions.h index 823d6b588..70eeacc72 100644 --- a/src/common/utilities/eigen_mesh_conversions.h +++ b/src/common/utilities/eigen_mesh_conversions.h @@ -43,25 +43,28 @@ namespace meshlab { // From eigen to CMeshO CMeshO meshFromMatrices( const EigenMatrixX3m& vertices, - const Eigen::MatrixX3i& faces = Eigen::MatrixX3i(), - const Eigen::MatrixX2i& edges = Eigen::MatrixX2i(), - const EigenMatrixX3m& vertexNormals = EigenMatrixX3m(), - const EigenMatrixX3m& faceNormals = EigenMatrixX3m(), - const EigenVectorXm& vertexQuality = EigenVectorXm(), - const EigenVectorXm& faceQuality = EigenVectorXm(), - const EigenMatrixX4m& vertexColor = EigenMatrixX4m(), - const EigenMatrixX4m& faceColor = EigenMatrixX4m()); + const Eigen::MatrixX3i& faces = Eigen::MatrixX3i(), + const Eigen::MatrixX2i& edges = Eigen::MatrixX2i(), + const EigenMatrixX3m& vertexNormals = EigenMatrixX3m(), + const EigenMatrixX3m& faceNormals = EigenMatrixX3m(), + const EigenVectorXm& vertexQuality = EigenVectorXm(), + const EigenVectorXm& faceQuality = EigenVectorXm(), + const EigenMatrixX4m& vertexColor = EigenMatrixX4m(), + const EigenMatrixX4m& faceColor = EigenMatrixX4m(), + const EigenMatrixX2m& vertexTexCoords = EigenMatrixX2m(), + const EigenMatrixX2m& wedgeTexCoords = EigenMatrixX2m()); // From eigen to polygonal CMeshO CMeshO polyMeshFromMatrices( const EigenMatrixX3m& vertices, const std::list& faces, - const EigenMatrixX3m& vertexNormals = EigenMatrixX3m(), - const EigenMatrixX3m& faceNormals = EigenMatrixX3m(), - const EigenVectorXm& vertexQuality = EigenVectorXm(), - const EigenVectorXm& faceQuality = EigenVectorXm(), - const EigenMatrixX4m& vertexColor = EigenMatrixX4m(), - const EigenMatrixX4m& faceColor = EigenMatrixX4m()); + const EigenMatrixX3m& vertexNormals = EigenMatrixX3m(), + const EigenMatrixX3m& faceNormals = EigenMatrixX3m(), + const EigenVectorXm& vertexQuality = EigenVectorXm(), + const EigenVectorXm& faceQuality = EigenVectorXm(), + const EigenMatrixX4m& vertexColor = EigenMatrixX4m(), + const EigenMatrixX4m& faceColor = EigenMatrixX4m(), + const EigenMatrixX2m& vertexTexCoords = EigenMatrixX2m()); void addVertexScalarAttribute( CMeshO& mesh, diff --git a/src/common_gui/CMakeLists.txt b/src/common_gui/CMakeLists.txt new file mode 100644 index 000000000..1af96d5be --- /dev/null +++ b/src/common_gui/CMakeLists.txt @@ -0,0 +1,85 @@ +set(HEADERS + gui_utils/clickable_label.h + gui_utils/vertical_scroll_area.h + + rich_parameter/widgets/bool_widget.h + rich_parameter/widgets/color_widget.h + rich_parameter/widgets/combo_widget.h + rich_parameter/widgets/direction_widget.h + rich_parameter/widgets/dynamic_float_widget.h + rich_parameter/widgets/enum_widget.h + rich_parameter/widgets/float_widget.h + rich_parameter/widgets/int_widget.h + rich_parameter/widgets/io_file_widget.h + rich_parameter/widgets/line_edit_widget.h + rich_parameter/widgets/matrix44_widget.h + rich_parameter/widgets/mesh_widget.h + rich_parameter/widgets/open_file_widget.h + rich_parameter/widgets/percentage_widget.h + rich_parameter/widgets/point3_widget.h + rich_parameter/widgets/position_widget.h + rich_parameter/widgets/rich_parameter_widget.h + rich_parameter/widgets/rich_parameter_widgets.h + rich_parameter/widgets/save_file_widget.h + rich_parameter/widgets/shot_widget.h + rich_parameter/widgets/string_widget.h + + rich_parameter/richparameterlistdialog.h + rich_parameter/rich_parameter_list_frame.h +) + +set(SOURCES + gui_utils/clickable_label.cpp + gui_utils/vertical_scroll_area.cpp + + rich_parameter/widgets/bool_widget.cpp + rich_parameter/widgets/color_widget.cpp + rich_parameter/widgets/combo_widget.cpp + rich_parameter/widgets/direction_widget.cpp + rich_parameter/widgets/dynamic_float_widget.cpp + rich_parameter/widgets/enum_widget.cpp + rich_parameter/widgets/float_widget.cpp + rich_parameter/widgets/int_widget.cpp + rich_parameter/widgets/io_file_widget.cpp + rich_parameter/widgets/line_edit_widget.cpp + rich_parameter/widgets/matrix44_widget.cpp + rich_parameter/widgets/mesh_widget.cpp + rich_parameter/widgets/open_file_widget.cpp + rich_parameter/widgets/percentage_widget.cpp + rich_parameter/widgets/point3_widget.cpp + rich_parameter/widgets/position_widget.cpp + rich_parameter/widgets/rich_parameter_widget.cpp + rich_parameter/widgets/save_file_widget.cpp + rich_parameter/widgets/shot_widget.cpp + rich_parameter/widgets/string_widget.cpp + + rich_parameter/richparameterlistdialog.cpp + rich_parameter/rich_parameter_list_frame.cpp +) + +set(RESOURCES ) + +set(TARGET_TYPE SHARED) +add_library(meshlab-common-gui ${TARGET_TYPE} ${SOURCES} ${HEADERS} ${RESOURCES}) + +target_link_libraries( + meshlab-common-gui + PUBLIC + meshlab-common +) + +set_property(TARGET meshlab-common-gui PROPERTY FOLDER Core) + +set_property(TARGET meshlab-common-gui + PROPERTY RUNTIME_OUTPUT_DIRECTORY ${MESHLAB_LIB_OUTPUT_DIR}) + +set_property(TARGET meshlab-common-gui + PROPERTY LIBRARY_OUTPUT_DIRECTORY ${MESHLAB_LIB_OUTPUT_DIR}) + +set_target_properties(meshlab-common-gui PROPERTIES + INSTALL_RPATH "${MESHLAB_LIB_INSTALL_DIR}:${INSTALL_RPATH}") + +set_target_properties(meshlab-common-gui PROPERTIES + INSTALL_RPATH "$ORIGIN") + +install(TARGETS meshlab-common-gui DESTINATION ${MESHLAB_LIB_INSTALL_DIR}) diff --git a/src/meshlab/gui_utils/clickable_label.cpp b/src/common_gui/gui_utils/clickable_label.cpp similarity index 100% rename from src/meshlab/gui_utils/clickable_label.cpp rename to src/common_gui/gui_utils/clickable_label.cpp diff --git a/src/meshlab/gui_utils/clickable_label.h b/src/common_gui/gui_utils/clickable_label.h similarity index 100% rename from src/meshlab/gui_utils/clickable_label.h rename to src/common_gui/gui_utils/clickable_label.h diff --git a/src/meshlab/gui_utils/vertical_scroll_area.cpp b/src/common_gui/gui_utils/vertical_scroll_area.cpp similarity index 100% rename from src/meshlab/gui_utils/vertical_scroll_area.cpp rename to src/common_gui/gui_utils/vertical_scroll_area.cpp diff --git a/src/meshlab/gui_utils/vertical_scroll_area.h b/src/common_gui/gui_utils/vertical_scroll_area.h similarity index 100% rename from src/meshlab/gui_utils/vertical_scroll_area.h rename to src/common_gui/gui_utils/vertical_scroll_area.h diff --git a/src/meshlab/rich_parameter_gui/richparameterlistframe.cpp b/src/common_gui/rich_parameter/rich_parameter_list_frame.cpp similarity index 62% rename from src/meshlab/rich_parameter_gui/richparameterlistframe.cpp rename to src/common_gui/rich_parameter/rich_parameter_list_frame.cpp index 437e89e35..51cfe5b7f 100644 --- a/src/meshlab/rich_parameter_gui/richparameterlistframe.cpp +++ b/src/common_gui/rich_parameter/rich_parameter_list_frame.cpp @@ -1,8 +1,8 @@ /***************************************************************************** - * VCGLib o o * + * MeshLab o o * * Visual and Computer Graphics Library o o * * _ O _ * - * Copyright(C) 2004-2021 \/)\/ * + * Copyright(C) 2004-2022 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -21,7 +21,7 @@ * * ****************************************************************************/ -#include "richparameterlistframe.h" +#include "rich_parameter_list_frame.h" #include #include @@ -40,32 +40,36 @@ RichParameterListFrame::RichParameterListFrame(QWidget* parent) : } RichParameterListFrame::RichParameterListFrame( - const RichParameterList& curParSet, - const RichParameterList& defParSet, + const RichParameterList& parameterList, + const RichParameterList& defaultValuesList, QWidget* p, QWidget* gla) : QFrame(p), isHelpVisible(false), gla(gla) { - loadFrameContent(curParSet, defParSet); + loadFrameContent(parameterList, defaultValuesList); } RichParameterListFrame::RichParameterListFrame( - const RichParameterList& curParSet, + const RichParameterList& parameterList, QWidget* p, QWidget* gla) : QFrame(p), isHelpVisible(false), gla(gla) { - loadFrameContent(curParSet); + loadFrameContent(parameterList, parameterList); } RichParameterListFrame::RichParameterListFrame( - const RichParameter& curPar, - const RichParameter& defPar, + const RichParameter& parameter, + const RichParameter& defaultValue, QWidget* p, QWidget* gla) : QFrame(p), isHelpVisible(false), gla(gla) { - loadFrameContent(curPar, defPar); + RichParameterList crpl; + crpl.addParam(parameter); + RichParameterList drpl; + drpl.addParam(defaultValue); + loadFrameContent(crpl, drpl); } RichParameterListFrame::~RichParameterListFrame() @@ -91,14 +95,15 @@ void RichParameterListFrame::writeValuesOnParameterList(RichParameterList& curPa { assert(curParSet.size() == (unsigned int) stdfieldwidgets.size()); for (auto& p : stdfieldwidgets) { - curParSet.setValue(p.first, (p.second)->widgetValue()); + curParSet.setValue(p.first, *(p.second)->getWidgetValue()); } } void RichParameterListFrame::resetValues() { for (auto& p : stdfieldwidgets) { - p.second->resetValue(); + p.second->resetWidgetToDefaultValue(); + rpl.getParameterByName(p.first).setValue(*p.second->getWidgetValue(), true); } } @@ -117,6 +122,16 @@ unsigned int RichParameterListFrame::size() const return stdfieldwidgets.size(); } +RichParameterList RichParameterListFrame::currentRichParameterList() const +{ + for (const auto& w : *this) { + if (w.second->hasBeenChanged()) { + rpl.getParameterByName(w.first).setValue(*w.second->getWidgetValue()); + } + } + return rpl; +} + RichParameterListFrame::iterator RichParameterListFrame::begin() { return stdfieldwidgets.begin(); @@ -127,6 +142,16 @@ RichParameterListFrame::iterator RichParameterListFrame::end() return stdfieldwidgets.end(); } +RichParameterListFrame::const_iterator RichParameterListFrame::begin() const +{ + return stdfieldwidgets.begin(); +} + +RichParameterListFrame::const_iterator RichParameterListFrame::end() const +{ + return stdfieldwidgets.end(); +} + void RichParameterListFrame::toggleAdvancedParameters() { if (areAdvancedParametersVisible) { @@ -175,7 +200,7 @@ void RichParameterListFrame::loadFrameContent( // put the parameter widgets into the grid layout for (const RichParameter* fpi : p.second) { const RichParameter& defrp = defParSet.getParameterByName(fpi->name()); - RichParameterWidget* wd = createWidgetFromRichParameter(this, *fpi, defrp); + RichParameterWidget* wd = createWidgetFromRichParameter(this, *fpi, defrp.value()); stdfieldwidgets[fpi->name()] = wd; wd->addWidgetToGridLayout(glay, i++); } @@ -195,95 +220,86 @@ void RichParameterListFrame::loadFrameContent( QSpacerItem* spacer = new QSpacerItem(40, 20, QSizePolicy::Minimum, QSizePolicy::Expanding); glay->addItem(spacer, i++, 0); setLayout(glay); -} - -/* creates widgets for the standard parameters */ -void RichParameterListFrame::loadFrameContent(const RichParameterList& curParSet) -{ - loadFrameContent(curParSet, curParSet); -} - -void RichParameterListFrame::loadFrameContent( - const RichParameter& curPar, - const RichParameter& defPar) -{ - RichParameterList crpl; - crpl.addParam(curPar); - RichParameterList drpl; - drpl.addParam(defPar); - loadFrameContent(crpl, drpl); + rpl = curParSet; + rpl.setAllValuesAsDefault(); } RichParameterWidget* RichParameterListFrame::createWidgetFromRichParameter( - QWidget* parent, - const RichParameter& pd, - const RichParameter& def) + RichParameterListFrame* parent, + const RichParameter& pd, + const Value& defaultValue) { - if (pd.isOfType()) { - return new AbsPercWidget(parent, (const RichAbsPerc&) pd, (const RichAbsPerc&) def); + RichParameterWidget* w = nullptr; + if (pd.isOfType() && defaultValue.isOfType()) { + w = new PercentageWidget( + parent, (const RichPercentage&) pd, (const FloatValue&) defaultValue); } - else if (pd.isOfType()) { - return new DynamicFloatWidget( - parent, (const RichDynamicFloat&) pd, (const RichDynamicFloat&) def); + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new DynamicFloatWidget( + parent, (const RichDynamicFloat&) pd, (const FloatValue&) defaultValue); } - else if (pd.isOfType()) { - return new EnumWidget(parent, (const RichEnum&) pd, (const RichEnum&) def); + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new EnumWidget(parent, (const RichEnum&) pd, (const IntValue&) defaultValue); } - else if (pd.isOfType()) { - return new BoolWidget(parent, (const RichBool&) pd, (const RichBool&) def); + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new BoolWidget(parent, (const RichBool&) pd, (const BoolValue&) defaultValue); } - else if (pd.isOfType()) { - return new IntWidget(parent, (const RichInt&) pd, (const RichInt&) def); + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new IntWidget(parent, (const RichInt&) pd, (const IntValue&) defaultValue); } - else if (pd.isOfType()) { - return new FloatWidget(parent, (const RichFloat&) pd, (const RichFloat&) def); + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new FloatWidget(parent, (const RichFloat&) pd, (const FloatValue&) defaultValue); } - else if (pd.isOfType()) { - return new StringWidget(parent, (const RichString&) pd, (const RichString&) def); + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new StringWidget(parent, (const RichString&) pd, (const StringValue&) defaultValue); } - else if (pd.isOfType()) { - return new Matrix44fWidget( + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new Matrix44Widget( parent, - (const RichMatrix44f&) pd, - (const RichMatrix44f&) def, + (const RichMatrix44&) pd, + (const Matrix44Value&) defaultValue, reinterpret_cast(parent)->gla); } - else if (pd.isOfType()) { - return new PositionWidget( + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new PositionWidget( parent, (const RichPosition&) pd, - (const RichPosition&) def, + (const Point3Value&) defaultValue, reinterpret_cast(parent)->gla); } - else if (pd.isOfType()) { - return new DirectionWidget( + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new DirectionWidget( parent, (const RichDirection&) pd, - (const RichDirection&) def, + (const Point3Value&) defaultValue, reinterpret_cast(parent)->gla); } - else if (pd.isOfType()) { - return new ShotfWidget( + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new ShotWidget( parent, - (const RichShotf&) pd, - (const RichShotf&) def, + (const RichShot&) pd, + (const ShotValue&) defaultValue, reinterpret_cast(parent)->gla); } - else if (pd.isOfType()) { - return new ColorWidget(parent, (const RichColor&) pd, (const RichColor&) def); + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new ColorWidget(parent, (const RichColor&) pd, (const ColorValue&) defaultValue); } - else if (pd.isOfType()) { - return new OpenFileWidget(parent, (const RichOpenFile&) pd, (const RichOpenFile&) def); + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new OpenFileWidget( + parent, (const RichFileOpen&) pd, (const StringValue&) defaultValue); } - else if (pd.isOfType()) { - return new SaveFileWidget(parent, (const RichSaveFile&) pd, (const RichSaveFile&) def); + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new SaveFileWidget( + parent, (const RichFileSave&) pd, (const StringValue&) defaultValue); } - else if (pd.isOfType()) { - return new MeshWidget(parent, (const RichMesh&) pd, (const RichMesh&) def); + else if (pd.isOfType() && defaultValue.isOfType()) { + w = new MeshWidget(parent, (const RichMesh&) pd, (const IntValue&) defaultValue); } else { std::cerr << "RichParameter type not supported for widget creation.\n"; assert(0); return nullptr; } + connect(w, SIGNAL(parameterChanged()), parent, SIGNAL(parameterChanged())); + return w; } diff --git a/src/meshlab/rich_parameter_gui/richparameterlistframe.h b/src/common_gui/rich_parameter/rich_parameter_list_frame.h similarity index 79% rename from src/meshlab/rich_parameter_gui/richparameterlistframe.h rename to src/common_gui/rich_parameter/rich_parameter_list_frame.h index 530a7c9a6..087599abb 100644 --- a/src/meshlab/rich_parameter_gui/richparameterlistframe.h +++ b/src/common_gui/rich_parameter/rich_parameter_list_frame.h @@ -1,8 +1,8 @@ /***************************************************************************** - * VCGLib o o * + * MeshLab o o * * Visual and Computer Graphics Library o o * * _ O _ * - * Copyright(C) 2004-2021 \/)\/ * + * Copyright(C) 2004-2022 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -21,10 +21,10 @@ * * ****************************************************************************/ -#ifndef RICHPARAMETERLISTFRAME_H -#define RICHPARAMETERLISTFRAME_H +#ifndef RICH_PARAMETER_LIST_FRAME_H +#define RICH_PARAMETER_LIST_FRAME_H -#include "richparameterwidgets.h" +#include "widgets/rich_parameter_widgets.h" #include @@ -49,14 +49,15 @@ class RichParameterListFrame : public QFrame Q_OBJECT public: typedef std::map::iterator iterator; + typedef std::map::const_iterator const_iterator; RichParameterListFrame(QWidget* parent); RichParameterListFrame( - const RichParameterList& curParSet, - const RichParameterList& defParSet, + const RichParameterList& parameterList, + const RichParameterList& defaultValuesList, QWidget* p, QWidget* gla = 0); - RichParameterListFrame(const RichParameterList& curParSet, QWidget* p, QWidget* gla = 0); + RichParameterListFrame(const RichParameterList& parameterList, QWidget* p, QWidget* gla = 0); RichParameterListFrame( const RichParameter& curPar, const RichParameter& defPar, @@ -79,8 +80,12 @@ public: unsigned int size() const; + RichParameterList currentRichParameterList() const; + iterator begin(); iterator end(); + const_iterator begin() const; + const_iterator end() const; signals: void parameterChanged(); @@ -90,14 +95,15 @@ public slots: private: void loadFrameContent(const RichParameterList& curParSet, const RichParameterList& defParSet); - void loadFrameContent(const RichParameterList& curParSet); - - void loadFrameContent(const RichParameter& curPar, const RichParameter& defPar); static RichParameterWidget* createWidgetFromRichParameter( - QWidget* parent, + RichParameterListFrame *parent, const RichParameter& pd, - const RichParameter& def); + const Value& defaultValue); + + mutable RichParameterList rpl; // a list containing all the parameters in the frame. + // the list does not contain updated values. + // it is updated just when someone asks a list containing the current values of the frame std::map stdfieldwidgets; bool isHelpVisible; @@ -108,4 +114,4 @@ private: QPushButton* showHiddenFramePushButton; }; -#endif // RICHPARAMETERLISTFRAME_H +#endif // RICH_PARAMETER_LIST_FRAME_H diff --git a/src/meshlab/rich_parameter_gui/richparameterlistdialog.cpp b/src/common_gui/rich_parameter/richparameterlistdialog.cpp similarity index 100% rename from src/meshlab/rich_parameter_gui/richparameterlistdialog.cpp rename to src/common_gui/rich_parameter/richparameterlistdialog.cpp diff --git a/src/meshlab/rich_parameter_gui/richparameterlistdialog.h b/src/common_gui/rich_parameter/richparameterlistdialog.h similarity index 96% rename from src/meshlab/rich_parameter_gui/richparameterlistdialog.h rename to src/common_gui/rich_parameter/richparameterlistdialog.h index 6265586cc..de8160073 100644 --- a/src/meshlab/rich_parameter_gui/richparameterlistdialog.h +++ b/src/common_gui/rich_parameter/richparameterlistdialog.h @@ -26,8 +26,8 @@ #include -#include "../../common/parameters/rich_parameter_list.h" -#include "richparameterlistframe.h" +#include +#include "rich_parameter_list_frame.h" /** * @brief This class provide a modal dialog box for asking a generic parameter list diff --git a/src/common_gui/rich_parameter/widgets/bool_widget.cpp b/src/common_gui/rich_parameter/widgets/bool_widget.cpp new file mode 100644 index 000000000..ec5e801a0 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/bool_widget.cpp @@ -0,0 +1,58 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "bool_widget.h" + +BoolWidget::BoolWidget(QWidget* p, const RichBool& param, const BoolValue& defaultValue) : + RichParameterWidget(p, param, defaultValue) +{ + cb = new QCheckBox("", this); + cb->setToolTip(param.toolTip()); + cb->setChecked(param.value().getBool()); + widgets.push_back(cb); + + connect(cb, SIGNAL(stateChanged(int)), this, SLOT(setParameterChanged())); + connect(descriptionLabel, SIGNAL(clicked()), cb, SLOT(toggle())); +} + +BoolWidget::~BoolWidget() +{ +} + +void BoolWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addWidget(cb, r, 1); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr BoolWidget::getWidgetValue() const +{ + return std::make_shared(cb->isChecked()); +} + +void BoolWidget::setWidgetValue(const Value& nv) +{ + cb->setChecked(nv.getBool()); +} diff --git a/src/common_gui/rich_parameter/widgets/bool_widget.h b/src/common_gui/rich_parameter/widgets/bool_widget.h new file mode 100644 index 000000000..80beb3daa --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/bool_widget.h @@ -0,0 +1,43 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_BOOL_WIDGET_H +#define MESHLAB_BOOL_WIDGET_H + +#include "rich_parameter_widget.h" + +class BoolWidget : public RichParameterWidget +{ +public: + BoolWidget(QWidget* p, const RichBool& param, const BoolValue& defaultValue); + ~BoolWidget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + +private: + QCheckBox* cb; +}; + +#endif // MESHLAB_BOOL_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/color_widget.cpp b/src/common_gui/rich_parameter/widgets/color_widget.cpp new file mode 100644 index 000000000..20ef45764 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/color_widget.cpp @@ -0,0 +1,102 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "color_widget.h" + +#include + +ColorWidget::ColorWidget(QWidget* p, const RichColor& param, const ColorValue& defaultValue) : + RichParameterWidget(p, param, defaultValue), pickcol(defaultValue.getColor()) +{ + colorLabel = new QLabel(this); + colorButton = new QPushButton(this); + colorButton->setAutoFillBackground(true); + colorButton->setFlat(true); + colorButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + QColor cl = param.value().getColor(); + pickcol = cl; + updateColorInfo(cl); + + vlay = new QHBoxLayout(); + QFontMetrics met(colorLabel->font()); + QColor black(Qt::black); + QString blackname = "(" + black.name() + ")"; + QSize sz = met.size(Qt::TextSingleLine, blackname); + colorLabel->setMaximumWidth(sz.width()); + colorLabel->setMinimumWidth(sz.width()); + vlay->addWidget(colorLabel, 0, Qt::AlignRight); + vlay->addWidget(colorButton); + widgets.push_back(colorLabel); + widgets.push_back(colorButton); + + connect(colorButton, SIGNAL(clicked()), this, SLOT(pickColor())); + connect(this, SIGNAL(dialogParamChanged()), this, SLOT(setParameterChanged())); +} + +ColorWidget::~ColorWidget() +{ + delete colorButton; + delete colorLabel; +} + +void ColorWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addLayout(vlay, r, 1); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr ColorWidget::getWidgetValue() const +{ + return std::make_shared(pickcol); +} + +void ColorWidget::setWidgetValue(const Value& nv) +{ + QColor cl = nv.getColor(); + pickcol = cl; + updateColorInfo(cl); +} + +void ColorWidget::updateColorInfo(const ColorValue& newColor) +{ + QColor col = newColor.getColor(); + colorLabel->setText("(" + col.name() + ")"); + QPalette palette(col); + colorButton->setPalette(palette); +} + +void ColorWidget::pickColor() +{ + QColor tmp = pickcol; + auto dialogParam = QColorDialog::DontUseNativeDialog | QColorDialog::ShowAlphaChannel; + pickcol = QColorDialog::getColor(pickcol, this->parentWidget(), "Pick a Color", dialogParam); + if (pickcol.isValid()) { + updateColorInfo(ColorValue(pickcol)); + emit dialogParamChanged(); + } + else { + pickcol = tmp; + } +} diff --git a/src/common_gui/rich_parameter/widgets/color_widget.h b/src/common_gui/rich_parameter/widgets/color_widget.h new file mode 100644 index 000000000..62f41fcf7 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/color_widget.h @@ -0,0 +1,56 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_COLOR_WIDGET_H +#define MESHLAB_COLOR_WIDGET_H + +#include "rich_parameter_widget.h" + +class ColorWidget : public RichParameterWidget +{ + Q_OBJECT +public: + ColorWidget(QWidget* p, const RichColor& param, const ColorValue& defaultValue); + ~ColorWidget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + +private: + void updateColorInfo(const ColorValue& newColor); +private slots: + void pickColor(); +signals: + void dialogParamChanged(); + +protected: + QHBoxLayout* vlay; + +private: + QPushButton* colorButton; + QLabel* colorLabel; + QColor pickcol; +}; + +#endif // MESHLAB_COLOR_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/combo_widget.cpp b/src/common_gui/rich_parameter/widgets/combo_widget.cpp new file mode 100644 index 000000000..7f4f9ce3d --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/combo_widget.cpp @@ -0,0 +1,71 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "combo_widget.h" + +ComboWidget::ComboWidget(QWidget* p, const RichParameter& param, const Value& defaultValue) : + RichParameterWidget(p, param, defaultValue), enumCombo(new QComboBox(this)) +{ +} + +ComboWidget::ComboWidget( + QWidget* p, + const RichParameter& rpar, + const Value& defaultValue, + const QStringList& values, + int defaultEnum) : + RichParameterWidget(p, rpar, defaultValue), enumCombo(new QComboBox(this)) +{ + init(defaultEnum, values); +} + +ComboWidget::~ComboWidget() +{ +} + +void ComboWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addWidget(enumCombo, r, 1); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +void ComboWidget::setIndex(int newEnum) +{ + enumCombo->setCurrentIndex(newEnum); +} + +int ComboWidget::getIndex() +{ + return enumCombo->currentIndex(); +} + +void ComboWidget::init(int defaultEnum, QStringList values) +{ + enumCombo->addItems(values); + widgets.push_back(enumCombo); + setIndex(defaultEnum); + connect(enumCombo, SIGNAL(activated(int)), this, SIGNAL(dialogParamChanged())); + connect(this, SIGNAL(dialogParamChanged()), this, SLOT(setParameterChanged())); +} diff --git a/src/common_gui/rich_parameter/widgets/combo_widget.h b/src/common_gui/rich_parameter/widgets/combo_widget.h new file mode 100644 index 000000000..4bf48d837 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/combo_widget.h @@ -0,0 +1,59 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_COMBO_WIDGET_H +#define MESHLAB_COMBO_WIDGET_H + +#include "rich_parameter_widget.h" + +class ComboWidget : public RichParameterWidget +{ + Q_OBJECT +protected: + QComboBox* enumCombo; + +public: + ComboWidget(QWidget* p, const RichParameter& param, const Value& defaultValue); + ComboWidget( + QWidget* p, + const RichParameter& rpar, + const Value& defaultValue, + const QStringList& values, + int defaultEnum); + ~ComboWidget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + virtual std::shared_ptr getWidgetValue() const = 0; + virtual void setWidgetValue(const Value& nv) = 0; + + int getIndex(); + void setIndex(int newEnum); + +signals: + void dialogParamChanged(); + +protected: + void init(int newEnum, QStringList values); +}; + +#endif // MESHLAB_COMBO_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/direction_widget.cpp b/src/common_gui/rich_parameter/widgets/direction_widget.cpp new file mode 100644 index 000000000..2463ec02c --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/direction_widget.cpp @@ -0,0 +1,67 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "direction_widget.h" + +DirectionWidget::DirectionWidget( + QWidget* p, + const RichDirection& param, + const Point3Value& defaultValue, + QWidget* gla) : + Point3Widget(p, param, defaultValue, gla) +{ + // if we have a connection to the current glarea we can setup the additional + // button for getting the current view direction. + if (gla) { + QStringList names; + names << "View Dir."; + names << "Raster Camera Dir."; + + getPoint3Combo->addItems(names); + + connect( + gla, SIGNAL(transmitViewDir(QString, Point3m)), this, SLOT(setValue(QString, Point3m))); + connect( + gla, SIGNAL(transmitShot(QString, Shotm)), this, SLOT(setShotValue(QString, Shotm))); + connect(this, SIGNAL(askViewDir(QString)), gla, SLOT(sendViewDir(QString))); + connect(this, SIGNAL(askCameraDir(QString)), gla, SLOT(sendRasterShot(QString))); + + connect(getPoint3Button, SIGNAL(clicked()), this, SLOT(getPoint())); + } +} + +DirectionWidget::~DirectionWidget() +{ + this->disconnect(); +} + +void DirectionWidget::getPoint() +{ + int index = getPoint3Combo->currentIndex(); + switch (index) { + case 0: emit askViewDir(paramName); break; + case 1: emit askCameraDir(paramName); break; + + default: assert(0); + } +} diff --git a/src/common_gui/rich_parameter/widgets/direction_widget.h b/src/common_gui/rich_parameter/widgets/direction_widget.h new file mode 100644 index 000000000..06adb03aa --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/direction_widget.h @@ -0,0 +1,48 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_DIRECTION_WIDGET_H +#define MESHLAB_DIRECTION_WIDGET_H + +#include "point3_widget.h" + +class DirectionWidget : public Point3Widget +{ + Q_OBJECT +public: + DirectionWidget( + QWidget* p, + const RichDirection& param, + const Point3Value& defaultValue, + QWidget* gla); + ~DirectionWidget(); + +public slots: + void getPoint(); + +signals: + void askViewDir(QString); + void askCameraDir(QString); +}; + +#endif // MESHLAB_DIRECTION_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/dynamic_float_widget.cpp b/src/common_gui/rich_parameter/widgets/dynamic_float_widget.cpp new file mode 100644 index 000000000..dbb08fdce --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/dynamic_float_widget.cpp @@ -0,0 +1,117 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "dynamic_float_widget.h" + +DynamicFloatWidget::DynamicFloatWidget( + QWidget* p, + const RichDynamicFloat& param, + const FloatValue& defaultValue) : + RichParameterWidget(p, param, defaultValue) +{ + int numbdecimaldigit = 4; + minVal = param.min; + maxVal = param.max; + valueLE = new QLineEdit(this); + valueLE->setAlignment(Qt::AlignRight); + + valueSlider = new QSlider(Qt::Horizontal, this); + valueSlider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + valueSlider->setMinimum(0); + valueSlider->setMaximum(100); + valueSlider->setValue(floatToInt(param.value().getFloat())); + QFontMetrics fm(valueLE->font()); + QSize sz = fm.size(Qt::TextSingleLine, QString::number(0)); + valueLE->setValidator(new QDoubleValidator(param.min, param.max, numbdecimaldigit, valueLE)); + valueLE->setText(QString::number(param.value().getFloat())); + valueLE->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + + hlay = new QHBoxLayout(); + hlay->addWidget(valueLE); + hlay->addWidget(valueSlider); + widgets.push_back(valueLE); + widgets.push_back(valueSlider); + int maxlenghtplusdot = 8; // numbmaxvaluedigit + numbdecimaldigit + 1; + valueLE->setMaxLength(maxlenghtplusdot); + valueLE->setMaximumWidth(sz.width() * maxlenghtplusdot); + + connect(valueLE, SIGNAL(textChanged(const QString&)), this, SLOT(setValueFromTextBox())); + connect(valueSlider, SIGNAL(valueChanged(int)), this, SLOT(setValue(int))); + connect(this, SIGNAL(dialogParamChanged()), this, SLOT(setParameterChanged())); +} + +DynamicFloatWidget::~DynamicFloatWidget() +{ +} + +void DynamicFloatWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addLayout(hlay, r, 1); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr DynamicFloatWidget::getWidgetValue() const +{ + return std::make_shared(valueLE->text().toFloat()); +} + +void DynamicFloatWidget::setWidgetValue(const Value& nv) +{ + valueLE->setText(QString::number(nv.getFloat())); +} + +float DynamicFloatWidget::getValue() +{ + return float(valueLE->text().toDouble()); +} + +void DynamicFloatWidget::setValue(int newVal) +{ + if (floatToInt(float(valueLE->text().toDouble())) != newVal) { + valueLE->setText(QString::number(intToFloat(newVal))); + } +} + +void DynamicFloatWidget::setValueFromTextBox() +{ + float newValLE = float(valueLE->text().toDouble()); + valueSlider->setValue(floatToInt(newValLE)); + emit dialogParamChanged(); +} + +void DynamicFloatWidget::setValue(float newVal) +{ + if (QString::number(intToFloat(newVal)) != valueLE->text()) + valueLE->setText(QString::number(intToFloat(newVal))); +} + +float DynamicFloatWidget::intToFloat(int val) +{ + return minVal + float(val) / 100.0f * (maxVal - minVal); +} +int DynamicFloatWidget::floatToInt(float val) +{ + return int(100.0f * (val - minVal) / (maxVal - minVal)); +} diff --git a/src/common_gui/rich_parameter/widgets/dynamic_float_widget.h b/src/common_gui/rich_parameter/widgets/dynamic_float_widget.h new file mode 100644 index 000000000..ae6caa253 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/dynamic_float_widget.h @@ -0,0 +1,63 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_DYNAMIC_FLOAT_WIDGET_H +#define MESHLAB_DYNAMIC_FLOAT_WIDGET_H + +#include "rich_parameter_widget.h" + +class DynamicFloatWidget : public RichParameterWidget +{ + Q_OBJECT + +public: + DynamicFloatWidget(QWidget* p, const RichDynamicFloat& param, const FloatValue& defaultValue); + ~DynamicFloatWidget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + + float getValue(); + +public slots: + void setValue(int newv); + void setValueFromTextBox(); + void setValue(float newValue); + +signals: + // void valueChanged(int mask); + void dialogParamChanged(); + +private: + QLineEdit* valueLE; + QSlider* valueSlider; + float minVal; + float maxVal; + QHBoxLayout* hlay; + + float intToFloat(int val); + int floatToInt(float val); +}; + +#endif // MESHLAB_DYNAMIC_FLOAT_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/enum_widget.cpp b/src/common_gui/rich_parameter/widgets/enum_widget.cpp new file mode 100644 index 000000000..8c5155674 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/enum_widget.cpp @@ -0,0 +1,43 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "enum_widget.h" + +EnumWidget::EnumWidget(QWidget* p, const RichEnum& param, const IntValue& defaultValue) : + ComboWidget(p, param, defaultValue, param.enumvalues, param.value().getInt()) +{ +} + +EnumWidget::~EnumWidget() +{ +} + +std::shared_ptr EnumWidget::getWidgetValue() const +{ + return std::make_shared(enumCombo->currentIndex()); +} + +void EnumWidget::setWidgetValue(const Value& nv) +{ + enumCombo->setCurrentIndex(nv.getInt()); +} diff --git a/src/common_gui/rich_parameter/widgets/enum_widget.h b/src/common_gui/rich_parameter/widgets/enum_widget.h new file mode 100644 index 000000000..65ebdb752 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/enum_widget.h @@ -0,0 +1,39 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_ENUM_WIDGET_H +#define MESHLAB_ENUM_WIDGET_H + +#include "combo_widget.h" + +class EnumWidget : public ComboWidget +{ +public: + EnumWidget(QWidget* p, const RichEnum& param, const IntValue& defaultValue); + ~EnumWidget();; + + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); +}; + +#endif // MESHLAB_ENUM_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/float_widget.cpp b/src/common_gui/rich_parameter/widgets/float_widget.cpp new file mode 100644 index 000000000..9bb6049ab --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/float_widget.cpp @@ -0,0 +1,44 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "float_widget.h" + +FloatWidget::FloatWidget(QWidget* p, const RichFloat& param, const FloatValue& defaultValue) : + LineEditWidget(p, param, defaultValue) +{ + lned->setText(QString::number(param.value().getFloat(), 'g', 3)); +} + +FloatWidget::~FloatWidget() +{ +} + +std::shared_ptr FloatWidget::getWidgetValue() const +{ + return std::make_shared(lned->text().toFloat()); +} + +void FloatWidget::setWidgetValue(const Value& nv) +{ + lned->setText(QString::number(nv.getFloat(), 'g', 3)); +} diff --git a/src/common_gui/rich_parameter/widgets/float_widget.h b/src/common_gui/rich_parameter/widgets/float_widget.h new file mode 100644 index 000000000..610f06385 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/float_widget.h @@ -0,0 +1,39 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_FLOAT_WIDGET_H +#define MESHLAB_FLOAT_WIDGET_H + +#include "line_edit_widget.h" + +class FloatWidget : public LineEditWidget +{ +public: + FloatWidget(QWidget* p, const RichFloat& param, const FloatValue& defaultValue); + ~FloatWidget(); + + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); +}; + +#endif // MESHLAB_FLOAT_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/int_widget.cpp b/src/common_gui/rich_parameter/widgets/int_widget.cpp new file mode 100644 index 000000000..280002313 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/int_widget.cpp @@ -0,0 +1,44 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "int_widget.h" + +IntWidget::IntWidget(QWidget* p, const RichInt& param, const IntValue& defaultValue) : + LineEditWidget(p, param, defaultValue) +{ + lned->setText(QString::number(param.value().getInt())); +} + +IntWidget::~IntWidget() +{ +} + +std::shared_ptr IntWidget::getWidgetValue() const +{ + return std::make_shared(lned->text().toInt()); +} + +void IntWidget::setWidgetValue(const Value& nv) +{ + lned->setText(QString::number(nv.getInt())); +} diff --git a/src/common_gui/rich_parameter/widgets/int_widget.h b/src/common_gui/rich_parameter/widgets/int_widget.h new file mode 100644 index 000000000..2434594e8 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/int_widget.h @@ -0,0 +1,39 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_INT_WIDGET_H +#define MESHLAB_INT_WIDGET_H + +#include "line_edit_widget.h" + +class IntWidget : public LineEditWidget +{ +public: + IntWidget(QWidget* p, const RichInt& param, const IntValue& defaultValue); + ~IntWidget(); + + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); +}; + +#endif // MESHLAB_INT_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/io_file_widget.cpp b/src/common_gui/rich_parameter/widgets/io_file_widget.cpp new file mode 100644 index 000000000..3f8af8aab --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/io_file_widget.cpp @@ -0,0 +1,76 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "io_file_widget.h" + +#include + +IOFileWidget::IOFileWidget( + QWidget* p, + const RichParameter& param, + const StringValue& defaultValue) : + RichParameterWidget(p, param, defaultValue) +{ + filename = new QLineEdit(this); + filename->setText(param.value().getString()); + browse = new QPushButton(this); + browse->setText("..."); + hlay = new QHBoxLayout(); + hlay->addWidget(filename, 2); + hlay->addWidget(browse); + widgets.push_back(filename); + widgets.push_back(browse); + + connect(browse, SIGNAL(clicked()), this, SLOT(selectFile())); + connect(this, SIGNAL(dialogParamChanged()), this, SLOT(setParameterChanged())); +} + +IOFileWidget::~IOFileWidget() +{ + delete filename; + delete browse; +} + +void IOFileWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addLayout(hlay, r, 1, Qt::AlignTop); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr IOFileWidget::getWidgetValue() const +{ + return std::make_shared(filename->text()); +} + +void IOFileWidget::setWidgetValue(const Value& nv) +{ + QString fle = nv.getString(); + updateFileName(fle); +} + +void IOFileWidget::updateFileName(const StringValue& file) +{ + filename->setText(file.getString()); +} diff --git a/src/common_gui/rich_parameter/widgets/io_file_widget.h b/src/common_gui/rich_parameter/widgets/io_file_widget.h new file mode 100644 index 000000000..8313fea94 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/io_file_widget.h @@ -0,0 +1,56 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_IO_FILE_WIDGET_H +#define MESHLAB_IO_FILE_WIDGET_H + +#include "rich_parameter_widget.h" + +class IOFileWidget : public RichParameterWidget +{ + Q_OBJECT + +protected: + IOFileWidget(QWidget* p, const RichParameter& param, const StringValue& defaultValue); + ~IOFileWidget(); + +public: + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + +protected slots: + virtual void selectFile() = 0; + +signals: + void dialogParamChanged(); + +protected: + void updateFileName(const StringValue& file); + + QLineEdit* filename; + QPushButton* browse; + QHBoxLayout* hlay; +}; + +#endif // MESHLAB_IO_FILE_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/line_edit_widget.cpp b/src/common_gui/rich_parameter/widgets/line_edit_widget.cpp new file mode 100644 index 000000000..ee9baaaf7 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/line_edit_widget.cpp @@ -0,0 +1,56 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "line_edit_widget.h" + +LineEditWidget::LineEditWidget(QWidget* p, const RichParameter& param, const Value& defaultValue) : + RichParameterWidget(p, param, defaultValue) +{ + lned = new QLineEdit(this); + + connect(lned, SIGNAL(editingFinished()), this, SLOT(changeChecker())); + connect(this, SIGNAL(lineEditChanged()), this, SLOT(setParameterChanged())); + lned->setAlignment(Qt::AlignLeft); + widgets.push_back(lned); +} + +LineEditWidget::~LineEditWidget() +{ +} + +void LineEditWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addWidget(lned, r, 1); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +void LineEditWidget::changeChecker() +{ + if (lned->text() != this->lastVal) { + this->lastVal = lned->text(); + if (!this->lastVal.isEmpty()) + emit lineEditChanged(); + } +} diff --git a/src/common_gui/rich_parameter/widgets/line_edit_widget.h b/src/common_gui/rich_parameter/widgets/line_edit_widget.h new file mode 100644 index 000000000..f3f934b75 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/line_edit_widget.h @@ -0,0 +1,51 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_LINE_EDIT_WIDGET_H +#define MESHLAB_LINE_EDIT_WIDGET_H + +#include "rich_parameter_widget.h" + +class LineEditWidget : public RichParameterWidget +{ + Q_OBJECT + +public: + LineEditWidget(QWidget* p, const RichParameter& param, const Value& defaultValue); + ~LineEditWidget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const = 0; + virtual void setWidgetValue(const Value& nv) = 0; + +private slots: + void changeChecker(); +signals: + void lineEditChanged(); + +protected: + QLineEdit* lned; + QString lastVal; +}; + +#endif // MESHLAB_LINE_EDIT_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/matrix44_widget.cpp b/src/common_gui/rich_parameter/widgets/matrix44_widget.cpp new file mode 100644 index 000000000..46054d8dd --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/matrix44_widget.cpp @@ -0,0 +1,180 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "matrix44_widget.h" + +#include +#include + +Matrix44Widget::Matrix44Widget( + QWidget* p, + const RichMatrix44& param, + const Matrix44Value& defaultValue, + QWidget* gla) : + RichParameterWidget(p, param, defaultValue) +{ + valid = false; + m.SetIdentity(); + paramName = param.name(); + + vlay = new QVBoxLayout(); + lay44 = new QGridLayout(); + + for (int i = 0; i < 16; ++i) { + coordSB[i] = new QLineEdit(p); + QFont baseFont = coordSB[i]->font(); + if (baseFont.pixelSize() != -1) + baseFont.setPixelSize(baseFont.pixelSize() * 3 / 4); + else + baseFont.setPointSize(baseFont.pointSize() * 3 / 4); + coordSB[i]->setFont(baseFont); + coordSB[i]->setMinimumWidth(coordSB[i]->sizeHint().width() / 4); + coordSB[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + coordSB[i]->setValidator(new QDoubleValidator(p)); + lay44->addWidget(coordSB[i], i / 4, i % 4); + widgets.push_back(coordSB[i]); + connect( + coordSB[i], + SIGNAL(textChanged(const QString&)), + this, + SLOT(invalidateMatrix(const QString&))); + connect(coordSB[i], SIGNAL(editingFinished()), this, SLOT(setParameterChanged())); + } + this->setValue(paramName, param.value().getMatrix44()); + + QLabel* headerL = new QLabel("Matrix:", this); + vlay->addWidget(headerL, 0, Qt::AlignTop); + widgets.push_back(headerL); + + vlay->addLayout(lay44); + + QPushButton* getMatrixButton = new QPushButton("Read from current layer"); + vlay->addWidget(getMatrixButton); + widgets.push_back(getMatrixButton); + + QPushButton* pasteMatrixButton = new QPushButton("Paste from clipboard"); + vlay->addWidget(pasteMatrixButton); + widgets.push_back(pasteMatrixButton); + + // gridLay->addLayout(vlay,row,1,Qt::AlignTop); + + connect( + gla, SIGNAL(transmitMatrix(QString, Matrix44m)), this, SLOT(setValue(QString, Matrix44m))); + connect(getMatrixButton, SIGNAL(clicked()), this, SLOT(getMatrix())); + connect(pasteMatrixButton, SIGNAL(clicked()), this, SLOT(pasteMatrix())); + connect(this, SIGNAL(askMeshMatrix(QString)), gla, SLOT(sendMeshMatrix(QString))); +} + +Matrix44Widget::~Matrix44Widget() +{ +} + +void Matrix44Widget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addLayout(vlay, r, 1, Qt::AlignTop); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr Matrix44Widget::getWidgetValue() const +{ + if (!valid) { + Matrix44m tempM; + for (unsigned int i = 0; i < 16; ++i) + tempM[i / 4][i % 4] = coordSB[i]->text().toFloat(); + return std::make_shared(tempM); + } + else { + return std::make_shared(m); + } +} + +void Matrix44Widget::setWidgetValue(const Value& nv) +{ + valid = true; + m = nv.getMatrix44(); + for (unsigned int ii = 0; ii < 16; ++ii) + coordSB[ii]->setText(QString::number(nv.getMatrix44()[ii / 4][ii % 4], 'g', 3)); +} + +Matrix44m Matrix44Widget::getValue() +{ + if (!valid) { + Scalarm val[16]; + for (unsigned int i = 0; i < 16; ++i) + val[i] = coordSB[i]->text().toFloat(); + return Matrix44m(val); + } + return m; +} + +void Matrix44Widget::setValue(QString name, Matrix44m newVal) +{ + if (name == paramName) { + for (int i = 0; i < 16; ++i) + coordSB[i]->setText(QString::number(newVal[i / 4][i % 4], 'g', 4)); + valid = true; + m = newVal; + } +} + +void Matrix44Widget::getMatrix() +{ + emit askMeshMatrix(QString("TransformMatrix")); +} + +void Matrix44Widget::pasteMatrix() +{ + QClipboard* clipboard = QApplication::clipboard(); + QString shotString = clipboard->text().trimmed(); + if (shotString.contains(' ')) { + QStringList list1 = shotString.split(" "); + if (list1.size() != 16) + return; + valid = false; + int id = 0; + for (QStringList::iterator i = list1.begin(); i != list1.end(); ++i, ++id) { + bool ok = true; + (*i).toFloat(&ok); + if (!ok) + return; + } + id = 0; + for (QStringList::iterator i = list1.begin(); i != list1.end(); ++i, ++id) { + coordSB[id]->setText(*i); + } + } + else { + QByteArray value = QByteArray::fromBase64(shotString.toLocal8Bit()); + memcpy(m.V(), value.data(), sizeof(Matrix44m::ScalarType) * 16); + int id = 0; + for (int i = 0; i < 16; ++i, ++id) + coordSB[id]->setText(QString::number(m.V()[i])); + } +} + +void Matrix44Widget::invalidateMatrix(const QString& /*s*/) +{ + valid = false; +} diff --git a/src/common_gui/rich_parameter/widgets/matrix44_widget.h b/src/common_gui/rich_parameter/widgets/matrix44_widget.h new file mode 100644 index 000000000..6d363a6b5 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/matrix44_widget.h @@ -0,0 +1,65 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_MATRIX44_WIDGET_H +#define MESHLAB_MATRIX44_WIDGET_H + +#include "rich_parameter_widget.h" + +class Matrix44Widget : public RichParameterWidget +{ + Q_OBJECT + +public: + Matrix44Widget( + QWidget* p, + const RichMatrix44& param, + const Matrix44Value& defaultValue, + QWidget* gla); + ~Matrix44Widget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + + Matrix44m getValue(); + +public slots: + void setValue(QString name, Matrix44m val); + void getMatrix(); + void pasteMatrix(); + void invalidateMatrix(const QString& s); +signals: + void askMeshMatrix(QString); + +private: + QString paramName; + QLineEdit* coordSB[16]; + QPushButton* getPoint3Button; + QGridLayout* lay44; + QVBoxLayout* vlay; + Matrix44m m; + bool valid; +}; + +#endif // MESHLAB_MATRIX44_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/mesh_widget.cpp b/src/common_gui/rich_parameter/widgets/mesh_widget.cpp new file mode 100644 index 000000000..2f154dd25 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/mesh_widget.cpp @@ -0,0 +1,73 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "mesh_widget.h" + +#include + +MeshWidget::MeshWidget(QWidget* p, const RichMesh& param, const IntValue& defaultValue) : + ComboWidget(p, param, defaultValue) +{ + md = param.meshdoc; + + QStringList meshNames; + + if (md) { + int currentmeshindex = -1; + unsigned int i = 0; + for (const MeshModel& mm : md->meshIterator()) { + QString shortName = mm.label(); + meshNames.push_back(shortName); + if (mm.id() == (unsigned int) param.value().getInt()) { + currentmeshindex = i; + } + ++i; + } + + init(currentmeshindex, meshNames); + } +} + +MeshWidget::~MeshWidget() +{ +} + +std::shared_ptr MeshWidget::getWidgetValue() const +{ + auto it = md->meshBegin(); + std::advance(it, enumCombo->currentIndex()); + return std::make_shared((*it).id()); +} + +void MeshWidget::setWidgetValue(const Value& nv) +{ + int meshindex = -1; + unsigned int i = 0; + for (const MeshModel& mm : md->meshIterator()) { + if (mm.id() == (unsigned int) nv.getInt()) { + meshindex = i; + } + ++i; + } + enumCombo->setCurrentIndex(meshindex); +} diff --git a/src/common_gui/rich_parameter/widgets/mesh_widget.h b/src/common_gui/rich_parameter/widgets/mesh_widget.h new file mode 100644 index 000000000..32fe4f287 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/mesh_widget.h @@ -0,0 +1,43 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_MESH_WIDGET_H +#define MESHLAB_MESH_WIDGET_H + +#include "combo_widget.h" + +class MeshWidget : public ComboWidget +{ +public: + MeshWidget(QWidget* p, const RichMesh& param, const IntValue& defaultValue); + ~MeshWidget(); + ; + + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + +private: + const MeshDocument* md; +}; + +#endif // MESHLAB_MESH_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/open_file_widget.cpp b/src/common_gui/rich_parameter/widgets/open_file_widget.cpp new file mode 100644 index 000000000..eade04c6a --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/open_file_widget.cpp @@ -0,0 +1,50 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "open_file_widget.h" + +#include + +OpenFileWidget::OpenFileWidget( + QWidget* p, + const RichFileOpen& param, + const StringValue& defaultValue) : + IOFileWidget(p, param, defaultValue), extensions(param.exts.join(";;")) +{ +} + +OpenFileWidget::~OpenFileWidget() +{ +} + +void OpenFileWidget::selectFile() +{ + QString path = QDir::homePath(); + if (!filename->text().isEmpty()) + path = filename->text(); + QString fl = QFileDialog::getOpenFileName(this, tr("Open"), path, extensions); + if (!fl.isEmpty()) { + updateFileName(fl); + emit dialogParamChanged(); + } +} diff --git a/src/common_gui/rich_parameter/widgets/open_file_widget.h b/src/common_gui/rich_parameter/widgets/open_file_widget.h new file mode 100644 index 000000000..1d979d573 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/open_file_widget.h @@ -0,0 +1,43 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_OPEN_FILE_WIDGET_H +#define MESHLAB_OPEN_FILE_WIDGET_H + +#include "io_file_widget.h" + +class OpenFileWidget : public IOFileWidget +{ + Q_OBJECT +public: + OpenFileWidget(QWidget* p, const RichFileOpen& param, const StringValue& defaultValue); + ~OpenFileWidget(); + +protected slots: + void selectFile(); + +private: + QString extensions; +}; + +#endif // MESHLAB_OPEN_FILE_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/percentage_widget.cpp b/src/common_gui/rich_parameter/widgets/percentage_widget.cpp new file mode 100644 index 000000000..5bc8b8d31 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/percentage_widget.cpp @@ -0,0 +1,121 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "percentage_widget.h" + +PercentageWidget::PercentageWidget( + QWidget* p, + const RichPercentage& param, + const FloatValue& defaultValue) : + RichParameterWidget(p, param, defaultValue), m_min(param.min), m_max(param.max) +{ + descriptionLabel->setText(descriptionLabel->text() + " (abs and %)"); + + absSB = new QDoubleSpinBox(this); + percSB = new QDoubleSpinBox(this); + + absSB->setMinimum(m_min - (m_max - m_min)); + absSB->setMaximum(m_max * 2); + absSB->setAlignment(Qt::AlignRight); + + int decimals = 7 - ceil(log10(fabs(m_max - m_min))); + absSB->setDecimals(decimals); + absSB->setSingleStep((m_max - m_min) / 100.0); + float initVal = param.value().getFloat(); + absSB->setValue(initVal); + absSB->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + + percSB->setMinimum(-200); + percSB->setMaximum(200); + percSB->setAlignment(Qt::AlignRight); + percSB->setSingleStep(0.5); + percSB->setValue((100 * (initVal - m_min)) / (m_max - m_min)); + percSB->setDecimals(3); + percSB->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + QLabel* absLab = new QLabel(" world unit"); + QLabel* percLab = new QLabel( + " perc on" + QString("(%1 .. %2)").arg(m_min).arg(m_max) + ""); + + vlay = new QGridLayout(); + vlay->addWidget(absLab, 0, 0, Qt::AlignHCenter); + vlay->addWidget(percLab, 0, 1, Qt::AlignHCenter); + + vlay->addWidget(absSB, 1, 0, Qt::AlignTop); + vlay->addWidget(percSB, 1, 1, Qt::AlignTop); + + widgets.push_back(absLab); + widgets.push_back(percLab); + widgets.push_back(absSB); + widgets.push_back(percSB); + + connect(absSB, SIGNAL(valueChanged(double)), this, SLOT(on_absSB_valueChanged(double))); + connect(percSB, SIGNAL(valueChanged(double)), this, SLOT(on_percSB_valueChanged(double))); + connect(this, SIGNAL(dialogParamChanged()), this, SLOT(setParameterChanged())); +} + +PercentageWidget::~PercentageWidget() +{ + delete absSB; + delete percSB; +} + +void PercentageWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addLayout(vlay, r, 1, Qt::AlignTop); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr PercentageWidget::getWidgetValue() const +{ + return std::make_shared(absSB->value()); +} + +void PercentageWidget::setWidgetValue(const Value& nv) +{ + setValue(nv.getFloat(), m_min, m_max); +} + +void PercentageWidget::setValue(float val, float minV, float maxV) +{ + absSB->setValue(val); + m_min = minV; + m_max = maxV; +} + +void PercentageWidget::on_absSB_valueChanged(double newv) +{ + disconnect(percSB, SIGNAL(valueChanged(double)), this, SLOT(on_percSB_valueChanged(double))); + percSB->setValue((100 * (newv - m_min)) / (m_max - m_min)); + connect(percSB, SIGNAL(valueChanged(double)), this, SLOT(on_percSB_valueChanged(double))); + emit dialogParamChanged(); +} + +void PercentageWidget::on_percSB_valueChanged(double newv) +{ + disconnect(absSB, SIGNAL(valueChanged(double)), this, SLOT(on_absSB_valueChanged(double))); + absSB->setValue((m_max - m_min) * 0.01 * newv + m_min); + connect(absSB, SIGNAL(valueChanged(double)), this, SLOT(on_absSB_valueChanged(double))); + emit dialogParamChanged(); +} diff --git a/src/common_gui/rich_parameter/widgets/percentage_widget.h b/src/common_gui/rich_parameter/widgets/percentage_widget.h new file mode 100644 index 000000000..89d13f6b5 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/percentage_widget.h @@ -0,0 +1,58 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_PERCENTAGE_WIDGET_H +#define MESHLAB_PERCENTAGE_WIDGET_H + +#include "rich_parameter_widget.h" + +class PercentageWidget : public RichParameterWidget +{ + Q_OBJECT +public: + PercentageWidget(QWidget* p, const RichPercentage& param, const FloatValue& defaultValue); + ~PercentageWidget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + +private: + void setValue(float val, float minV, float maxV); + +public slots: + + void on_absSB_valueChanged(double newv); + void on_percSB_valueChanged(double newv); +signals: + void dialogParamChanged(); + +protected: + QDoubleSpinBox* absSB; + QDoubleSpinBox* percSB; + float m_min; + float m_max; + QGridLayout* vlay; +}; + +#endif // MESHLAB_PERCENTAGE_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/point3_widget.cpp b/src/common_gui/rich_parameter/widgets/point3_widget.cpp new file mode 100644 index 000000000..2e36c5432 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/point3_widget.cpp @@ -0,0 +1,119 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "point3_widget.h" + +Point3Widget::Point3Widget( + QWidget* p, + const RichParameter& param, + const Point3Value& defaultValue, + QWidget* gla) : + RichParameterWidget(p, param, defaultValue) +{ + assert(param.value().isPoint3()); + + paramName = param.name(); + + vlay = new QHBoxLayout(); + vlay->setSpacing(0); + const Point3Value& p3v = param.value().getPoint3(); + for (unsigned int i = 0; i < 3; ++i) { + coordSB[i] = new QLineEdit(this); + QFont baseFont = coordSB[i]->font(); + if (baseFont.pixelSize() != -1) + baseFont.setPixelSize(baseFont.pixelSize() * 3 / 4); + else + baseFont.setPointSize(baseFont.pointSize() * 3 / 4); + coordSB[i]->setFont(baseFont); + coordSB[i]->setMinimumWidth(coordSB[i]->sizeHint().width() / 4); + coordSB[i]->setValidator(new QDoubleValidator()); + coordSB[i]->setAlignment(Qt::AlignRight); + coordSB[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + vlay->addWidget(coordSB[i]); + widgets.push_back(coordSB[i]); + } + setValue(paramName, param.value().getPoint3()); + // connects must be made AFTER setValue + for (unsigned int i = 0; i < 3 ; i++) { + connect(coordSB[i], SIGNAL(textChanged(QString)), this, SLOT(setParameterChanged())); + } + // if we have a connection to the current glarea we can setup the additional + // button for getting the current view direction. + if (gla) { + getPoint3Combo = new QComboBox(this); + getPoint3Combo->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + vlay->addWidget(getPoint3Combo); + widgets.push_back(getPoint3Combo); + + getPoint3Button = new QPushButton("Get", this); + getPoint3Button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + + vlay->addWidget(getPoint3Button); + widgets.push_back(getPoint3Button); + } +} + +Point3Widget::~Point3Widget() +{ + this->disconnect(); +} + +void Point3Widget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addLayout(vlay, r, 1); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr Point3Widget::getWidgetValue() const +{ + return std::make_shared(Point3m( + coordSB[0]->text().toFloat(), coordSB[1]->text().toFloat(), coordSB[2]->text().toFloat())); +} + +void Point3Widget::setWidgetValue(const Value& nv) +{ + for (unsigned int ii = 0; ii < 3; ++ii) + coordSB[ii]->setText(QString::number(nv.getPoint3()[ii], 'g', 3)); +} + +vcg::Point3f Point3Widget::getValue() +{ + return vcg::Point3f( + coordSB[0]->text().toFloat(), coordSB[1]->text().toFloat(), coordSB[2]->text().toFloat()); +} + +void Point3Widget::setValue(QString name, Point3m newVal) +{ + if (name == paramName) { + for (int i = 0; i < 3; ++i) + coordSB[i]->setText(QString::number(newVal[i], 'g', 4)); + } +} + +void Point3Widget::setShotValue(QString name, Shotm newValShot) +{ + vcg::Point3f p = newValShot.GetViewPoint(); + setValue(name, p); +} diff --git a/src/common_gui/rich_parameter/widgets/point3_widget.h b/src/common_gui/rich_parameter/widgets/point3_widget.h new file mode 100644 index 000000000..b35ac1ed8 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/point3_widget.h @@ -0,0 +1,58 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_POINT3_WIDGET_H +#define MESHLAB_POINT3_WIDGET_H + +#include "rich_parameter_widget.h" + +class Point3Widget : public RichParameterWidget +{ + Q_OBJECT +public: + Point3Widget( + QWidget* p, + const RichParameter& rpf, + const Point3Value& defaultValue, + QWidget* gla); + ~Point3Widget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + + vcg::Point3f getValue(); + +public slots: + void setValue(QString name, Point3m val); + void setShotValue(QString name, Shotm val); + +protected: + QString paramName; + QLineEdit* coordSB[3]; + QComboBox* getPoint3Combo; + QPushButton* getPoint3Button; + QHBoxLayout* vlay; +}; + +#endif // MESHLAB_POINT3_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/position_widget.cpp b/src/common_gui/rich_parameter/widgets/position_widget.cpp new file mode 100644 index 000000000..93ff03324 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/position_widget.cpp @@ -0,0 +1,85 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "position_widget.h" + +PositionWidget::PositionWidget( + QWidget* p, + const RichPosition& param, + const Point3Value& defaultValue, + QWidget* gla) : + Point3Widget(p, param, defaultValue, gla) +{ + // if we have a connection to the current glarea we can setup the additional + // button for getting the current view direction. + if (gla) { + QStringList names; + names << "View Pos."; + names << "Surf. Pos."; + names << "Raster Camera Pos."; + names << "Trackball Center"; + + getPoint3Combo->addItems(names); + + connect( + gla, + SIGNAL(transmitSurfacePos(QString, Point3m)), + this, + SLOT(setValue(QString, Point3m))); + connect( + gla, + SIGNAL(transmitCameraPos(QString, Point3m)), + this, + SLOT(setValue(QString, Point3m))); + connect( + gla, SIGNAL(transmitShot(QString, Shotm)), this, SLOT(setShotValue(QString, Shotm))); + connect( + gla, + SIGNAL(transmitTrackballPos(QString, Point3m)), + this, + SLOT(setValue(QString, Point3m))); + connect(this, SIGNAL(askViewPos(QString)), gla, SLOT(sendViewerShot(QString))); + connect(this, SIGNAL(askSurfacePos(QString)), gla, SLOT(sendSurfacePos(QString))); + connect(this, SIGNAL(askCameraPos(QString)), gla, SLOT(sendRasterShot(QString))); + connect(this, SIGNAL(askTrackballPos(QString)), gla, SLOT(sendTrackballPos(QString))); + + connect(getPoint3Button, SIGNAL(clicked()), this, SLOT(getPoint())); + } +} + +PositionWidget::~PositionWidget() +{ + this->disconnect(); +} + +void PositionWidget::getPoint() +{ + int index = getPoint3Combo->currentIndex(); + switch (index) { + case 0: emit askViewPos(paramName); break; + case 1: emit askSurfacePos(paramName); break; + case 2: emit askCameraPos(paramName); break; + case 3: emit askTrackballPos(paramName); break; + default: assert(0); + } +} diff --git a/src/common_gui/rich_parameter/widgets/position_widget.h b/src/common_gui/rich_parameter/widgets/position_widget.h new file mode 100644 index 000000000..8e75ff845 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/position_widget.h @@ -0,0 +1,50 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_POSITION_WIDGET_H +#define MESHLAB_POSITION_WIDGET_H + +#include "point3_widget.h" + +class PositionWidget : public Point3Widget +{ + Q_OBJECT +public: + PositionWidget( + QWidget* p, + const RichPosition& param, + const Point3Value& defaultValue, + QWidget* gla); + ~PositionWidget(); + +public slots: + void getPoint(); + +signals: + void askViewPos(QString); + void askSurfacePos(QString); + void askCameraPos(QString); + void askTrackballPos(QString); +}; + +#endif // MESHLAB_POSITION_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/rich_parameter_widget.cpp b/src/common_gui/rich_parameter/widgets/rich_parameter_widget.cpp new file mode 100644 index 000000000..49bec051d --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/rich_parameter_widget.cpp @@ -0,0 +1,93 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "rich_parameter_widget.h" + +#include "../rich_parameter_list_frame.h" + +RichParameterWidget::RichParameterWidget( + QWidget* p, + const RichParameter& param, + const Value& defaultValue) : + QWidget(p), defaultValue(defaultValue.clone()), visible(true), helpVisible(false) +{ + descriptionLabel = new ClickableLabel(param.fieldDescription(), this); + descriptionLabel->setToolTip(param.toolTip()); + descriptionLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + + helpLabel = new QLabel("" + param.toolTip() + "", this); + helpLabel->setTextFormat(Qt::RichText); + helpLabel->setWordWrap(true); + helpLabel->setVisible(false); + helpLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + helpLabel->setMinimumWidth(250); +} + +RichParameterWidget::~RichParameterWidget() +{ + delete defaultValue; +} + +void RichParameterWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != NULL) { + lay->addWidget(descriptionLabel, r, 0, 1, 1, Qt::AlignRight); + lay->addWidget(helpLabel, r, 2); + } +} + +void RichParameterWidget::setVisible(bool b) +{ + visible = b; + descriptionLabel->setVisible(b); + for (QWidget* w : widgets) + w->setVisible(b); + if (b && helpVisible) + helpLabel->setVisible(true); + else if (!b) + helpLabel->setVisible(false); + QWidget::setVisible(b); +} + +void RichParameterWidget::resetWidgetToDefaultValue() +{ + setWidgetValue(*defaultValue); + parameterValueChanged = false; +} + +void RichParameterWidget::setHelpVisible(bool b) +{ + helpVisible = b; + helpLabel->setVisible(visible && helpVisible); +} + +bool RichParameterWidget::hasBeenChanged() const +{ + return parameterValueChanged; +} + +void RichParameterWidget::setParameterChanged() +{ + parameterValueChanged = true; + emit parameterChanged(); +} diff --git a/src/common_gui/rich_parameter/widgets/rich_parameter_widget.h b/src/common_gui/rich_parameter/widgets/rich_parameter_widget.h new file mode 100644 index 000000000..310b3f9c2 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/rich_parameter_widget.h @@ -0,0 +1,82 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_PARAMETER_WIDGET_H +#define MESHLAB_RICH_PARAMETER_WIDGET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "../../gui_utils/clickable_label.h" + +class RichParameterWidget : public QWidget +{ + Q_OBJECT +public: + RichParameterWidget(QWidget* p, const RichParameter& param, const Value& defaultValue); + virtual ~RichParameterWidget(); + + virtual std::shared_ptr getWidgetValue() const = 0; + virtual void setWidgetValue(const Value& nv) = 0; + + virtual void addWidgetToGridLayout(QGridLayout* lay, const int r) = 0; + + void setVisible(bool b); + + void resetWidgetToDefaultValue(); + void setHelpVisible(bool b); + + bool hasBeenChanged() const; + +signals: + void parameterChanged(); + +protected slots: + void setParameterChanged(); + +protected: + ClickableLabel* descriptionLabel; + QLabel* helpLabel; + std::vector widgets; // will contain all the other widgets of this widget + + Value* defaultValue; + + bool parameterValueChanged = false; + + bool visible; + bool helpVisible; +}; + +#endif // MESHLAB_RICH_PARAMETER_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/rich_parameter_widgets.h b/src/common_gui/rich_parameter/widgets/rich_parameter_widgets.h new file mode 100644 index 000000000..6f1e0fc10 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/rich_parameter_widgets.h @@ -0,0 +1,43 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_RICH_PARAMETER_WIDGETS_H +#define MESHLAB_RICH_PARAMETER_WIDGETS_H + +#include "bool_widget.h" +#include "color_widget.h" +#include "direction_widget.h" +#include "dynamic_float_widget.h" +#include "enum_widget.h" +#include "float_widget.h" +#include "int_widget.h" +#include "matrix44_widget.h" +#include "mesh_widget.h" +#include "open_file_widget.h" +#include "percentage_widget.h" +#include "position_widget.h" +#include "save_file_widget.h" +#include "shot_widget.h" +#include "string_widget.h" + +#endif // MESHLAB_RICH_PARAMETER_WIDGETS_H diff --git a/src/common_gui/rich_parameter/widgets/save_file_widget.cpp b/src/common_gui/rich_parameter/widgets/save_file_widget.cpp new file mode 100644 index 000000000..7f3ebec33 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/save_file_widget.cpp @@ -0,0 +1,47 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "save_file_widget.h" + +#include + +SaveFileWidget::SaveFileWidget( + QWidget* p, + const RichFileSave& param, + const StringValue& defaultValue) : + IOFileWidget(p, param, defaultValue), extension(param.ext) +{ +} + +SaveFileWidget::~SaveFileWidget() +{ +} + +void SaveFileWidget::selectFile() +{ + QString fl = QFileDialog::getSaveFileName(this, tr("Save"), filename->text(), extension); + if (!fl.isEmpty()) { + updateFileName(fl); + emit dialogParamChanged(); + } +} diff --git a/src/common_gui/rich_parameter/widgets/save_file_widget.h b/src/common_gui/rich_parameter/widgets/save_file_widget.h new file mode 100644 index 000000000..fc2b58267 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/save_file_widget.h @@ -0,0 +1,43 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_SAVE_FILE_WIDGET_H +#define MESHLAB_SAVE_FILE_WIDGET_H + +#include "io_file_widget.h" + +class SaveFileWidget : public IOFileWidget +{ + Q_OBJECT +public: + SaveFileWidget(QWidget* p, const RichFileSave& param, const StringValue& defaultValue); + ~SaveFileWidget(); + +protected slots: + void selectFile(); + +private: + QString extension; +}; + +#endif // MESHLAB_SAVE_FILE_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/shot_widget.cpp b/src/common_gui/rich_parameter/widgets/shot_widget.cpp new file mode 100644 index 000000000..a4d53c31e --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/shot_widget.cpp @@ -0,0 +1,128 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "shot_widget.h" + +#include + +ShotWidget::ShotWidget( + QWidget* p, + const RichShot& param, + const ShotValue& defaultValue, + QWidget* gla) : + RichParameterWidget(p, param, defaultValue) +{ + paramName = param.name(); + + hlay = new QHBoxLayout(); + + this->setShotValue(paramName, param.value().getShot()); + // if we have a connection to the current glarea we can setup the additional + // button for getting the current view direction. + if (gla) { + getShotButton = new QPushButton("Get shot", this); + getShotButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + hlay->addWidget(getShotButton); + widgets.push_back(getShotButton); + + QStringList names; + names << "Current Trackball"; + names << "Current Mesh"; + names << "Current Raster"; + names << "From File"; + + getShotCombo = new QComboBox(this); + getShotCombo->addItems(names); + hlay->addWidget(getShotCombo); + widgets.push_back(getShotCombo); + connect(getShotCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(getShot())); + connect(getShotButton, SIGNAL(clicked()), this, SLOT(getShot())); + connect( + gla, SIGNAL(transmitShot(QString, Shotm)), this, SLOT(setShotValue(QString, Shotm))); + connect(this, SIGNAL(askViewerShot(QString)), gla, SLOT(sendViewerShot(QString))); + connect(this, SIGNAL(askMeshShot(QString)), gla, SLOT(sendMeshShot(QString))); + connect(this, SIGNAL(askRasterShot(QString)), gla, SLOT(sendRasterShot(QString))); + } +} + +ShotWidget::~ShotWidget() +{ +} + +void ShotWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) +{ + if (lay != nullptr) { + lay->addLayout(hlay, r, 1); + } + RichParameterWidget::addWidgetToGridLayout(lay, r); +} + +std::shared_ptr ShotWidget::getWidgetValue() const +{ + return std::make_shared(curShot); +} + +void ShotWidget::setWidgetValue(const Value& nv) +{ + curShot = nv.getShot(); +} + +Shotm ShotWidget::getValue() +{ + return curShot; +} + +void ShotWidget::getShot() +{ + int index = getShotCombo->currentIndex(); + switch (index) { + case 0: emit askViewerShot(paramName); break; + case 1: emit askMeshShot(paramName); break; + case 2: emit askRasterShot(paramName); break; + case 3: { + QString filename = QFileDialog::getOpenFileName( + this, tr("Load xml camera"), "./", tr("Xml Files (*.xml)")); + QFile qf(filename); + QFileInfo qfInfo(filename); + + if (!qf.open(QIODevice::ReadOnly)) + return; + + QDomDocument doc("XmlDocument"); // It represents the XML document + if (!doc.setContent(&qf)) + return; + qf.close(); + + QString type = doc.doctype().name(); + + } break; + default: assert(0); + } +} + +void ShotWidget::setShotValue(QString name, Shotm newVal) +{ + if (name == paramName) { + curShot = newVal; + } +} diff --git a/src/common_gui/rich_parameter/widgets/shot_widget.h b/src/common_gui/rich_parameter/widgets/shot_widget.h new file mode 100644 index 000000000..d8e3f7e15 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/shot_widget.h @@ -0,0 +1,60 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_SHOT_WIDGET_H +#define MESHLAB_SHOT_WIDGET_H + +#include "rich_parameter_widget.h" + +class ShotWidget : public RichParameterWidget +{ + Q_OBJECT + +public: + ShotWidget(QWidget* p, const RichShot& param, const ShotValue& defaultValue, QWidget* gla); + ~ShotWidget(); + + void addWidgetToGridLayout(QGridLayout* lay, const int r); + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); + + Shotm getValue(); + +public slots: + void getShot(); + void setShotValue(QString name, Shotm val); +signals: + void askRasterShot(QString); + void askMeshShot(QString); + void askViewerShot(QString); + +private: + QString paramName; + Shotm curShot; + QLineEdit* shotLE; + QPushButton* getShotButton; + QComboBox* getShotCombo; + QHBoxLayout* hlay; +}; + +#endif // MESHLAB_SHOT_WIDGET_H diff --git a/src/common_gui/rich_parameter/widgets/string_widget.cpp b/src/common_gui/rich_parameter/widgets/string_widget.cpp new file mode 100644 index 000000000..7d32dc21a --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/string_widget.cpp @@ -0,0 +1,44 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "string_widget.h" + +StringWidget::StringWidget(QWidget* p, const RichString& param, const StringValue& defaultValue) : + LineEditWidget(p, param, defaultValue) +{ + lned->setText(param.value().getString()); +} + +StringWidget::~StringWidget() +{ +} + +std::shared_ptr StringWidget::getWidgetValue() const +{ + return std::make_shared(lned->text()); +} + +void StringWidget::setWidgetValue(const Value& nv) +{ + lned->setText(nv.getString()); +} diff --git a/src/common_gui/rich_parameter/widgets/string_widget.h b/src/common_gui/rich_parameter/widgets/string_widget.h new file mode 100644 index 000000000..981bc7629 --- /dev/null +++ b/src/common_gui/rich_parameter/widgets/string_widget.h @@ -0,0 +1,39 @@ +/***************************************************************************** + * MeshLab o o * + * Visual and Computer Graphics Library o o * + * _ O _ * + * Copyright(C) 2004-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_STRING_WIDGET_H +#define MESHLAB_STRING_WIDGET_H + +#include "line_edit_widget.h" + +class StringWidget : public LineEditWidget +{ +public: + StringWidget(QWidget* p, const RichString& param, const StringValue& defaultValue); + ~StringWidget(); + + std::shared_ptr getWidgetValue() const; + void setWidgetValue(const Value& nv); +}; + +#endif // MESHLAB_STRING_WIDGET_H diff --git a/src/external/CMakeLists.txt b/src/external/CMakeLists.txt index 16f840bc5..d82d49ecd 100644 --- a/src/external/CMakeLists.txt +++ b/src/external/CMakeLists.txt @@ -46,6 +46,9 @@ if ((NOT MESHLAB_BUILD_MINI) AND MESHLAB_ALLOW_OPTIONAL_EXTERNAL_LIBRARIES) # cgal - optional for filter_mesh_booleans include(${CMAKE_CURRENT_SOURCE_DIR}/cgal.cmake) + # embree - optional for filter_embree + include(${CMAKE_CURRENT_SOURCE_DIR}/embree.cmake) + # levmar - optional, for several plugins include(${CMAKE_CURRENT_SOURCE_DIR}/levmar.cmake) diff --git a/src/external/cgal.cmake b/src/external/cgal.cmake index 4317336c4..48a1e0a56 100644 --- a/src/external/cgal.cmake +++ b/src/external/cgal.cmake @@ -13,7 +13,7 @@ if(MESHLAB_ALLOW_SYSTEM_CGAL AND TARGET CGAL::CGAL) add_library(external-cgal INTERFACE) target_link_libraries(external-cgal INTERFACE CGAL::CGAL Threads::Threads) elseif(MESHLAB_ALLOW_DOWNLOAD_SOURCE_CGAL) - set(CGAL_DIR "${MESHLAB_EXTERNAL_DOWNLOAD_DIR}/CGAL-5.2.1") + set(CGAL_DIR "${MESHLAB_EXTERNAL_DOWNLOAD_DIR}/CGAL-5.6") set(CGAL_CHECK "${CGAL_DIR}/include/CGAL/version.h") set(CGAL_WIN_CHECK "${CGAL_DIR}/auxiliary/gmp/lib/libmpfr-4.lib") @@ -21,9 +21,10 @@ elseif(MESHLAB_ALLOW_DOWNLOAD_SOURCE_CGAL) if (NOT EXISTS ${CGAL_CHECK}) set(CGAL_LINK - https://github.com/CGAL/cgal/releases/download/v5.2.1/CGAL-5.2.1.zip - https://www.meshlab.net/data/libs/CGAL-5.2.1.zip) - set(CGAL_MD5 1a999ab90ea4cf28f6aa17ea2af24876) + https://github.com/CGAL/cgal/releases/download/v5.6/CGAL-5.6.zip + https://www.meshlab.net/data/libs/CGAL-5.6.zip + ) + set(CGAL_MD5 6d1d067b88e20f7080d07d5108b4c772) download_and_unzip( NAME "CGAL" LINK ${CGAL_LINK} @@ -37,8 +38,9 @@ elseif(MESHLAB_ALLOW_DOWNLOAD_SOURCE_CGAL) if (WIN32 AND NOT EXISTS ${CGAL_WIN_CHECK}) set(CGAL_AUX_LINK - https://github.com/CGAL/cgal/releases/download/v5.2.1/CGAL-5.2.1-win64-auxiliary-libraries-gmp-mpfr.zip - https://www.meshlab.net/data/libs/CGAL-5.2.1-win64-auxiliary-libraries-gmp-mpfr.zip) + https://github.com/CGAL/cgal/releases/download/v5.6/CGAL-5.6-win64-auxiliary-libraries-gmp-mpfr.zip + https://www.meshlab.net/data/libs/CGAL-5.6-win64-auxiliary-libraries-gmp-mpfr.zip + ) set(CGAL_AUX_MD5 247f4dca741c6b9a9be76286414070fa) download_and_unzip( NAME "CGAL auxiliary libraries" diff --git a/src/external/embree.cmake b/src/external/embree.cmake new file mode 100644 index 000000000..652bd1902 --- /dev/null +++ b/src/external/embree.cmake @@ -0,0 +1,135 @@ +# Copyright 2019, 2021, Collabora, Ltd. +# Copyright 2019, 2021, Visual Computing Lab, ISTI - Italian National Research Council +# SPDX-License-Identifier: BSL-1.0 +option(MESHLAB_ALLOW_DOWNLOAD_SOURCE_EMBREE "Allow download and use of embree source (linux only)" ON) +option(MESHLAB_ALLOW_DOWNLOAD_DLL_EMBREE "Allow download and use of embree dll (windows only)" ON) +option(MESHLAB_ALLOW_SYSTEM_EMBREE "Allow use of system-provided embree" ON) + +set(EMBREE_MAJOR 4) +set(EMBREE_MINOR 3.0) +set(EMBREE_VER "${EMBREE_MAJOR}.${EMBREE_MINOR}") + +# looking for embree for the filter_embree +find_package(embree ${EMBREE_MAJOR}) +find_package(TBB) + +if(MESHLAB_ALLOW_SYSTEM_EMBREE AND TARGET embree AND TBB_FOUND) + message(STATUS "- embree - using system-provided library") + add_library(external-embree INTERFACE) + target_link_libraries(external-embree INTERFACE embree) +elseif(MESHLAB_ALLOW_DOWNLOAD_DLL_EMBREE AND WIN32) + set(EMBREE_WIN_DIR "${MESHLAB_EXTERNAL_DOWNLOAD_DIR}/embree-${EMBREE_VER}.x64.windows") + set(EMBREE_WIN_CHECK "${EMBREE_WIN_DIR}/lib/embree${EMBREE_MAJOR}.lib") + set(TBB_WIN_DIR "${MESHLAB_EXTERNAL_DOWNLOAD_DIR}/oneapi-tbb-2021.6.0") + set(TBB_WIN_CHECK "${TBB_WIN_DIR}/lib/cmake/tbb/TBBConfig.cmake") + + if (NOT EXISTS ${TBB_WIN_CHECK}) + set(TBB_WIN_LINK https://github.com/oneapi-src/oneTBB/releases/download/v2021.6.0/oneapi-tbb-2021.6.0-win.zip) + #set(TBB_WIN_MD5 ) + download_and_unzip( + NAME "TBB" + LINK ${TBB_WIN_LINK} + #MD5 ${TBB_WIN_MD5} + DIR ${MESHLAB_EXTERNAL_DOWNLOAD_DIR}) + if (NOT download_and_unzip_SUCCESS) + message(STATUS "- TBB - download failed.") + endif() + endif() + + if(NOT EXISTS ${EMBREE_WIN_CHECK}) + set(EMBREE_WIN_LINK https://github.com/embree/embree/releases/download/v${EMBREE_VER}/embree-${EMBREE_VER}.x64.windows.zip) + #set(EMBREE_WIN_MD5 ) + download_and_unzip( + NAME "embree dll" + LINK ${EMBREE_WIN_LINK} + #MD5 ${EMBREE_WIN_MD5} + DIR ${EMBREE_WIN_DIR}) + if (NOT download_and_unzip_SUCCESS) + message(STATUS "- embree dll - download failed.") + endif() + endif() + + if (EXISTS ${TBB_WIN_CHECK} AND EXISTS ${EMBREE_WIN_CHECK}) + message(STATUS "- embree - using downloaded dll") + + set(TBB_DIR "${TBB_WIN_DIR}/lib/cmake/tbb") + set(embree_DIR "${EMBREE_WIN_DIR}/lib/cmake/embree-${EMBREE_VER}") + find_package(embree) + + add_library(external-embree INTERFACE) + target_link_libraries(external-embree INTERFACE embree) + + if (DEFINED MESHLAB_LIB_OUTPUT_DIR) + file( + COPY + ${EMBREE_WIN_DIR}/bin/embree${EMBREE_MAJOR}.dll + ${EMBREE_WIN_DIR}/bin/tbb12.dll + DESTINATION + ${MESHLAB_LIB_OUTPUT_DIR}) + endif() + if (DEFINED MESHLAB_LIB_INSTALL_DIR) + install( + FILES + ${EMBREE_WIN_DIR}/bin/embree${EMBREE_MAJOR}.dll + ${EMBREE_WIN_DIR}/bin/tbb12.dll + DESTINATION + ${MESHLAB_LIB_INSTALL_DIR}) + endif() + endif() +elseif(MESHLAB_ALLOW_DOWNLOAD_SOURCE_EMBREE AND (UNIX AND NOT APPLE) AND TBB_FOUND) + set(EMBREE_SRC_DIR "${MESHLAB_EXTERNAL_DOWNLOAD_DIR}/embree-${EMBREE_VER}") + set(EMBREE_CHECK "${EMBREE_SRC_DIR}/CMakeLists.txt") + set(ISPC_DIR "${MESHLAB_EXTERNAL_DOWNLOAD_DIR}/ispc-v1.18.1-linux") + set(ISPC_CHECK "${ISPC_DIR}/bin/ispc") + + if (NOT EXISTS ${ISPC_CHECK}) + set(ISPC_LINK + https://github.com/ispc/ispc/releases/download/v1.18.1/ispc-v1.18.1-linux.tar.gz) + #set(ISPC_MD5 ) + download_and_unzip( + NAME "embree ispc" + LINK ${ISPC_LINK} + #MD5 ${ISPC_MD5} + DIR ${MESHLAB_EXTERNAL_DOWNLOAD_DIR}) + if (NOT download_and_unzip_SUCCESS) + message(STATUS "- embree ispc - download failed.") + endif() + endif() + + if (NOT EXISTS ${EMBREE_CHECK}) + set(EMBREE_LINK + https://github.com/embree/embree/archive/refs/tags/v${EMBREE_VER}.zip) + #set(EMBREE_MD5 ) + download_and_unzip( + NAME "embree" + LINK ${EMBREE_LINK} + #MD5 ${EMBREE_MD5} + DIR ${MESHLAB_EXTERNAL_DOWNLOAD_DIR}) + if (NOT download_and_unzip_SUCCESS) + message(STATUS "- embree - download failed.") + endif() + endif() + + if (EXISTS ${EMBREE_CHECK}) + message(STATUS "- embree - using downloaded source") + + if (EXISTS ${ISPC_CHECK}) + set(EMBREE_ISPC_EXECUTABLE ${ISPC_CHECK}) + else() + set(EMBREE_ISPC_SUPPORT OFF) + endif() + + set(EMBREE_TUTORIALS OFF) + + set(MESSAGE_QUIET ON) + add_subdirectory(${EMBREE_SRC_DIR} EXCLUDE_FROM_ALL) + unset(MESSAGE_QUIET) + + add_library(external-embree INTERFACE) + target_link_libraries(external-embree INTERFACE embree) + + install(TARGETS embree DESTINATION ${MESHLAB_LIB_INSTALL_DIR}) + endif() +else() + message(STATUS "- embree - skipping embree library") +endif() diff --git a/src/external/muparser.cmake b/src/external/muparser.cmake index bea9a9b45..d13f50bd4 100644 --- a/src/external/muparser.cmake +++ b/src/external/muparser.cmake @@ -35,14 +35,14 @@ elseif(MESHLAB_ALLOW_DOWNLOAD_SOURCE_MUPARSER) set(ENABLE_SAMPLES OFF) set(MESSAGE_QUIET ON) - if(NOT OPENMP_FOUND) + if(NOT OpenMP_CXX_FOUND) set(ENABLE_OPENMP OFF) endif() add_subdirectory(${MUPARSER_DIR} EXCLUDE_FROM_ALL) - if (APPLE AND OPENMP_FOUND) + if (APPLE AND OpenMP_CXX_FOUND) target_link_libraries(muparser PRIVATE OpenMP::OpenMP_CXX) endif() - if(NOT OPENMP_FOUND) + if(NOT OpenMP_CXX_FOUND) unset(ENABLE_OPENMP) endif() unset(MESSAGE_QUIET) diff --git a/src/external/qhull.cmake b/src/external/qhull.cmake index c8a1174d9..80fad05f6 100644 --- a/src/external/qhull.cmake +++ b/src/external/qhull.cmake @@ -33,6 +33,12 @@ elseif(MESHLAB_ALLOW_DOWNLOAD_SOURCE_QHULL) if (EXISTS ${QHULL_CHECK}) message(STATUS "- qhull - using downloaded source") + # remove target uninstall to avoid duplicates + # todo - make PR to Qhull to solve this + file(READ "${QHULL_DIR}/CMakeLists.txt" FILE_CONTENTS) + string(REPLACE "uninstall" "qhull-uninstall" FILE_CONTENTS "${FILE_CONTENTS}") + file(WRITE "${QHULL_DIR}/CMakeLists.txt" "${FILE_CONTENTS}") + set(MESSAGE_QUIET ON) add_subdirectory(${QHULL_DIR} EXCLUDE_FROM_ALL) unset(MESSAGE_QUIET) diff --git a/src/meshlab/CMakeLists.txt b/src/meshlab/CMakeLists.txt index bbc3ed912..000d5dc2d 100644 --- a/src/meshlab/CMakeLists.txt +++ b/src/meshlab/CMakeLists.txt @@ -22,11 +22,6 @@ set(SOURCES dialogs/save_mesh_attributes_dialog.cpp dialogs/save_snapshot_dialog.cpp dialogs/setting_dialog.cpp - gui_utils/clickable_label.cpp - gui_utils/vertical_scroll_area.cpp - rich_parameter_gui/richparameterlistdialog.cpp - rich_parameter_gui/richparameterlistframe.cpp - rich_parameter_gui/richparameterwidgets.cpp ${VCGDIR}/wrap/gui/trackball.cpp ${VCGDIR}/wrap/gui/trackmode.cpp ${VCGDIR}/wrap/gui/coordinateframe.cpp) @@ -51,11 +46,6 @@ set(HEADERS dialogs/save_mesh_attributes_dialog.h dialogs/save_snapshot_dialog.h dialogs/setting_dialog.h - gui_utils/clickable_label.h - gui_utils/vertical_scroll_area.h - rich_parameter_gui/richparameterlistdialog.h - rich_parameter_gui/richparameterlistframe.h - rich_parameter_gui/richparameterwidgets.h ${VCGDIR}/wrap/gui/trackball.h ${VCGDIR}/wrap/gui/trackmode.h ${VCGDIR}/wrap/gl/trimesh.h) @@ -86,7 +76,7 @@ target_compile_definitions(meshlab PUBLIC QT_DISABLE_DEPRECATED_BEFORE=0x000000) target_include_directories(meshlab PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries( meshlab - PUBLIC meshlab-common OpenGL::GLU Qt5::Network + PUBLIC meshlab-common meshlab-common-gui OpenGL::GLU Qt5::Network ) set_property(TARGET meshlab PROPERTY FOLDER Core) diff --git a/src/meshlab/dialogs/filter_dock_dialog.cpp b/src/meshlab/dialogs/filter_dock_dialog.cpp index 74745f78f..7c06504db 100644 --- a/src/meshlab/dialogs/filter_dock_dialog.cpp +++ b/src/meshlab/dialogs/filter_dock_dialog.cpp @@ -23,6 +23,11 @@ #include "filter_dock_dialog.h" #include "ui_filter_dock_dialog.h" +#include +#include + +#include + #include "../mainwindow.h" FilterDockDialog::FilterDockDialog( @@ -47,14 +52,15 @@ FilterDockDialog::FilterDockDialog( ui->setupUi(this); this->setWindowTitle(plugin->filterName(filter)); + ui->pymeshlabFilterLabel->setText(plugin->pythonFilterName(filter)); ui->filterInfoLabel->setText(plugin->filterInfo(filter)); ui->parameterFrame->initParams(rpl, rpl, (QWidget*) glArea); // by default, the previewCheckBox is visible when the dialog is constructed. // now, we check if the filter is previewable: - // - if it is previewable, we set all data structures necessary to make the preview available // - if it is not previewable, we set the previewCheckBox non visible + // - if it is previewable, we set all data structures necessary to make the preview available if (!isFilterPreviewable(plugin, filter)) { ui->previewCheckBox->setVisible(false); } @@ -255,3 +261,21 @@ void FilterDockDialog::updateRenderingData(MainWindow* mw, MeshModel* mesh) } } } + +void FilterDockDialog::on_copyToClipBoardPushButton_clicked() +{ + QSettings settings; + QString meshSetName = settings.value(MainWindowSetting::meshSetNameParam(), "").toString(); + QDomDocument doc; + doc.setContent(meshSetName); + RichParameter* s; + RichParameterAdapter::create(doc.firstChild().toElement(), s); + + RichParameterList rpl = ui->parameterFrame->currentRichParameterList(); + + Filter f(plugin, filter, rpl); + + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(QString::fromStdString(f.pyMeshLabCall(s->value().getString().toStdString()))); +} + diff --git a/src/meshlab/dialogs/filter_dock_dialog.h b/src/meshlab/dialogs/filter_dock_dialog.h index 9576d08e5..09c0d3b01 100644 --- a/src/meshlab/dialogs/filter_dock_dialog.h +++ b/src/meshlab/dialogs/filter_dock_dialog.h @@ -62,6 +62,8 @@ private slots: void applyDynamic(); void changeCurrentMesh(int meshId); + void on_copyToClipBoardPushButton_clicked(); + private: bool isPreviewable() const; diff --git a/src/meshlab/dialogs/filter_dock_dialog.ui b/src/meshlab/dialogs/filter_dock_dialog.ui index cfc838d38..2edaefdde 100644 --- a/src/meshlab/dialogs/filter_dock_dialog.ui +++ b/src/meshlab/dialogs/filter_dock_dialog.ui @@ -27,100 +27,7 @@ - - - - - true - - - - Filter Description - - - Qt::RichText - - - true - - - true - - - - - - - QFrame::NoFrame - - - QFrame::Plain - - - QAbstractScrollArea::AdjustToContentsOnFirstShow - - - true - - - - - 0 - 0 - 382 - 388 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - - - - - - Qt::NoFocus - - - Preview - - - true - - - - + QFrame::NoFrame @@ -187,6 +94,154 @@ + + + + + true + + + + Filter Description + + + Qt::RichText + + + true + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + QAbstractScrollArea::AdjustToContentsOnFirstShow + + + true + + + + + 0 + 0 + 382 + 292 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + + + + + Qt::NoFocus + + + Preview + + + true + + + + + + + QFrame::StyledPanel + + + QFrame::Plain + + + + + + + Ubuntu Mono + + + + IBeamCursor + + + TextLabel + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + true + + + + PyMeshLab Filter + + + + + + + Copy the PyMeshLab filter call of the current filter with the current parameters, leaving as default the unchanged ones. You can set the name of the MeshSet object going to Tools -> Options. + + + Copy PyMeshLab call to clipboard + + + + + + @@ -194,13 +249,13 @@ RichParameterListFrame QFrame -
rich_parameter_gui/richparameterlistframe.h
+
common_gui/rich_parameter/rich_parameter_list_frame.h
1
VerticalScrollArea QScrollArea -
gui_utils/vertical_scroll_area.h
+
common_gui/gui_utils/vertical_scroll_area.h
1
diff --git a/src/meshlab/dialogs/filter_script_dialog.cpp b/src/meshlab/dialogs/filter_script_dialog.cpp index 15238cfac..b09980a98 100644 --- a/src/meshlab/dialogs/filter_script_dialog.cpp +++ b/src/meshlab/dialogs/filter_script_dialog.cpp @@ -28,7 +28,7 @@ #include "mainwindow.h" #include #include -#include "rich_parameter_gui/richparameterlistdialog.h" +#include FilterScriptDialog::FilterScriptDialog(FilterScript& fs, QWidget * parent): QDialog(parent), diff --git a/src/meshlab/dialogs/options_dialog.cpp b/src/meshlab/dialogs/options_dialog.cpp index cbcb79984..aa8207873 100644 --- a/src/meshlab/dialogs/options_dialog.cpp +++ b/src/meshlab/dialogs/options_dialog.cpp @@ -126,7 +126,7 @@ QTableWidgetItem* MeshLabOptionsDialog::createQTableWidgetItemFromRichParameter( else if (pd.isOfType()){ return new QTableWidgetItem(pd.value().getString()); } - else if (pd.isOfType()){ + else if (pd.isOfType()){ return new QTableWidgetItem(QString::number(pd.value().getFloat())); } else if (pd.isOfType()){ @@ -135,16 +135,16 @@ QTableWidgetItem* MeshLabOptionsDialog::createQTableWidgetItemFromRichParameter( else if (pd.isOfType()){ return new QTableWidgetItem(QString::number(pd.value().getInt())); } - else if (pd.isOfType()){ + else if (pd.isOfType()){ assert(0); return nullptr; } else if (pd.isOfType() || pd.isOfType()){ - vcg::Point3f pp = pd.value().getPoint3f(); + vcg::Point3f pp = pd.value().getPoint3(); QString pst = "P3(" + QString::number(pp.X()) + "," + QString::number(pp.Y()) + "," + QString::number(pp.Z()) + ")"; return new QTableWidgetItem(pst); } - else if (pd.isOfType()){ + else if (pd.isOfType()){ assert(0); /// return new QTableWidgetItem(QString("TODO")); } @@ -154,10 +154,10 @@ QTableWidgetItem* MeshLabOptionsDialog::createQTableWidgetItemFromRichParameter( QIcon ic(pix); return new QTableWidgetItem(ic,""); } - else if (pd.isOfType()){ + else if (pd.isOfType()){ new QTableWidgetItem(pd.value().getString()); } - else if (pd.isOfType()){ + else if (pd.isOfType()){ assert(0); return nullptr; } diff --git a/src/meshlab/dialogs/save_mesh_attributes_dialog.h b/src/meshlab/dialogs/save_mesh_attributes_dialog.h index b1f041b5d..b7dccd6eb 100644 --- a/src/meshlab/dialogs/save_mesh_attributes_dialog.h +++ b/src/meshlab/dialogs/save_mesh_attributes_dialog.h @@ -29,7 +29,7 @@ #include -#include "rich_parameter_gui/richparameterlistframe.h" +#include #include #include "glarea.h" // diff --git a/src/meshlab/dialogs/save_mesh_attributes_dialog.ui b/src/meshlab/dialogs/save_mesh_attributes_dialog.ui index 855e65ff0..23d1080d9 100644 --- a/src/meshlab/dialogs/save_mesh_attributes_dialog.ui +++ b/src/meshlab/dialogs/save_mesh_attributes_dialog.ui @@ -452,7 +452,7 @@ VerticalScrollArea QScrollArea -
gui_utils/vertical_scroll_area.h
+
common_gui/gui_utils/vertical_scroll_area.h
1
diff --git a/src/meshlab/dialogs/save_snapshot_dialog.cpp b/src/meshlab/dialogs/save_snapshot_dialog.cpp index 4968136c9..58fdab572 100644 --- a/src/meshlab/dialogs/save_snapshot_dialog.cpp +++ b/src/meshlab/dialogs/save_snapshot_dialog.cpp @@ -44,6 +44,7 @@ void SaveSnapshotDialog::setValues(const SnapshotSetting& ss) ui->counterSpinBox->setValue(settings.counter); ui->backgroundComboBox->setCurrentIndex(settings.background); ui->alllayersCheckBox->setChecked(settings.snapAllLayers); + ui->useLayerNameCheckBox->setChecked(settings.useLayerName); ui->tiledSaveCheckBox->setChecked(settings.tiledSave); ui->addToRastersCheckBox->setChecked(settings.addToRasters); } @@ -56,6 +57,7 @@ SnapshotSetting SaveSnapshotDialog::getValues() settings.resolution=ui->resolutionSpinBox->value(); settings.background = ui->backgroundComboBox->currentIndex(); settings.snapAllLayers=ui->alllayersCheckBox->isChecked(); + settings.useLayerName=ui->useLayerNameCheckBox->isChecked(); settings.tiledSave=ui->tiledSaveCheckBox->isChecked(); settings.addToRasters=ui->addToRastersCheckBox->isChecked(); return settings; @@ -80,3 +82,23 @@ void SaveSnapshotDialog::on_browseDir_clicked() ui->outDirLineEdit->setText(selection.at(0)); } } + +void SaveSnapshotDialog::on_alllayersCheckBox_stateChanged(int arg1) +{ + if (arg1 == Qt::Checked) + ui->useLayerNameCheckBox->setEnabled(true); + else { + ui->useLayerNameCheckBox->setEnabled(false); + ui->useLayerNameCheckBox->setChecked(false); + } +} + + +void SaveSnapshotDialog::on_useLayerNameCheckBox_stateChanged(int arg1) +{ + if (arg1 == Qt::Checked) + ui->baseNameLineEdit->setEnabled(false); + else + ui->baseNameLineEdit->setEnabled(true); +} + diff --git a/src/meshlab/dialogs/save_snapshot_dialog.h b/src/meshlab/dialogs/save_snapshot_dialog.h index 70cb374f1..684cfac46 100644 --- a/src/meshlab/dialogs/save_snapshot_dialog.h +++ b/src/meshlab/dialogs/save_snapshot_dialog.h @@ -45,6 +45,10 @@ public: private slots: void on_browseDir_clicked(); + void on_alllayersCheckBox_stateChanged(int arg1); + + void on_useLayerNameCheckBox_stateChanged(int arg1); + private: Ui::SaveSnapShotDialog* ui; SnapshotSetting settings; diff --git a/src/meshlab/dialogs/save_snapshot_dialog.ui b/src/meshlab/dialogs/save_snapshot_dialog.ui index 8db45652f..7195d68cf 100644 --- a/src/meshlab/dialogs/save_snapshot_dialog.ui +++ b/src/meshlab/dialogs/save_snapshot_dialog.ui @@ -120,10 +120,38 @@ - - - Snap All Layers + + + + 10 + 0 + + + QFrame::NoFrame + + + QFrame::Plain + + + + + + Snap All Layers + + + + + + + false + + + Use Layer Name + + + + diff --git a/src/meshlab/dialogs/setting_dialog.cpp b/src/meshlab/dialogs/setting_dialog.cpp index fd28d5ce8..aa656f3aa 100644 --- a/src/meshlab/dialogs/setting_dialog.cpp +++ b/src/meshlab/dialogs/setting_dialog.cpp @@ -44,14 +44,16 @@ SettingDialog::SettingDialog( applybut = new QPushButton("Apply",this); loadbut = new QPushButton("Load",this); closebut = new QPushButton("Close",this); - + helpLabel = new QLabel(currentParam.toolTip(),this); + helpLabel->setWordWrap(true); QGridLayout* dialoglayout = new QGridLayout(parent); - - dialoglayout->addWidget(savebut,1,0); - dialoglayout->addWidget(resetbut,1,1); - dialoglayout->addWidget(loadbut,1,2); - dialoglayout->addWidget(applybut,1,3); - dialoglayout->addWidget(closebut,1,4); + + dialoglayout->addWidget(helpLabel,1,0,1,5); + dialoglayout->addWidget(savebut,2,0); + dialoglayout->addWidget(resetbut,2,1); + dialoglayout->addWidget(loadbut,2,2); + dialoglayout->addWidget(applybut,2,3); + dialoglayout->addWidget(closebut,2,4); dialoglayout->addWidget(&frame,0,0,1,5); @@ -86,7 +88,7 @@ void SettingDialog::save() void SettingDialog::apply() { assert(frame.size() == 1); - currentParameter->setValue(frame.begin()->second->widgetValue()); + currentParameter->setValue(*frame.begin()->second->getWidgetValue()); emit applySettingSignal(*currentParameter); } @@ -95,7 +97,7 @@ void SettingDialog::reset() qDebug("resetting the value of param %s to the hardwired default", qUtf8Printable(currentParameter->name())); assert(frame.size() == 1); - frame.begin()->second->setValue(defaultParameter.value()); + frame.begin()->second->resetWidgetToDefaultValue(); apply(); } diff --git a/src/meshlab/dialogs/setting_dialog.h b/src/meshlab/dialogs/setting_dialog.h index 3bbebd0e9..5988dd0e4 100644 --- a/src/meshlab/dialogs/setting_dialog.h +++ b/src/meshlab/dialogs/setting_dialog.h @@ -25,8 +25,8 @@ #define MESHLAB_SETTING_DIALOG_H #include -#include -#include "../rich_parameter_gui/richparameterlistframe.h" +#include +#include /** * @brief This class describes a dialog to load, save, modify and reset a @@ -61,6 +61,7 @@ private: QPushButton* resetbut; QPushButton* closebut; QPushButton* loadbut; + QLabel *helpLabel; }; #endif // MESHLAB_SETTING_DIALOG_H diff --git a/src/meshlab/glarea.cpp b/src/meshlab/glarea.cpp index b72553810..d10ce079c 100644 --- a/src/meshlab/glarea.cpp +++ b/src/meshlab/glarea.cpp @@ -72,7 +72,7 @@ GLArea::GLArea(QWidget *parent, MultiViewer_Container *mvcont, RichParameterList takeSnapTile=false; activeDefaultTrackball=true; infoAreaVisible = true; - trackBallVisible = true; + trackBallVisible = glas.startupShowTrackball; currentShader = NULL; lastFilterRef = NULL; //lastEditRef = NULL; @@ -202,7 +202,7 @@ void GLArea::pasteTile() tileBuffer.format()); uchar* snapPtr = snapBuffer.bits() + (tileBuffer.bytesPerLine() * tileCol) + - ((totalCols * tileRow) * tileBuffer.byteCount()); + ((totalCols * tileRow) * tileBuffer.sizeInBytes()); uchar* tilePtr = tileBuffer.bits(); for (int y = 0; y < tileBuffer.height(); y++) { @@ -219,11 +219,14 @@ void GLArea::pasteTile() if (tileRow >= totalRows) { if (ss.snapAllLayers) { - outfile = QString("%1/%2%3_L%4.png") + QString lname = ss.basename; + if (ss.useLayerName) { + lname = md()->getMesh(snapshotCounter)->label(); + } + outfile = QString("%1/%2%3.png") .arg(ss.outdir) - .arg(ss.basename) - .arg(ss.counter, 2, 10, QChar('0')) - .arg(snapshotCounter, 2, 10, QChar('0')); + .arg(lname) + .arg(ss.counter, 2, 10, QChar('0')); } else { outfile = QString("%1/%2%3.png") @@ -1882,7 +1885,7 @@ void GLArea::loadRaster(int id) //load his shot or a default shot if (rm.shot.IsValid()) { - fov = (rm.shot.Intrinsics.cameraType == 0) ? rm.shot.GetFovFromFocal() : 5.0; + fov = (rm.shot.Intrinsics.cameraType == vcg::Camera::PERSPECTIVE) ? rm.shot.GetFovFromFocal() : 5.0; // this code seems useless, and if the camera translation is[0 0 0] (or even just with a small z), there is a division by zero //float cameraDist = getCameraDistance(); @@ -2128,7 +2131,7 @@ void GLArea::loadShotFromTextAlignFile(const QDomDocument &doc) // The shot loaded from TextAlign doesn't have a scale. Trackball needs it. // The scale factor is computed as the ratio between cameraDistance and the z coordinate of the translation // introduced by the shot. - fov = (shot.Intrinsics.cameraType == 0) ? shot.GetFovFromFocal() : 5.0; + fov = (shot.Intrinsics.cameraType == vcg::Camera::PERSPECTIVE) ? shot.GetFovFromFocal() : 5.0; // float cameraDist = getCameraDistance(); @@ -2166,7 +2169,7 @@ void GLArea::loadViewFromViewStateFile(const QDomDocument &doc) trackball.track.sca = attr.namedItem("TrackScale").nodeValue().section(' ',0,0).toFloat(); nearPlane = attr.namedItem("NearPlane").nodeValue().section(' ',0,0).toFloat(); farPlane = attr.namedItem("FarPlane").nodeValue().section(' ',0,0).toFloat(); - fov = (shot.Intrinsics.cameraType == 0) ? shot.GetFovFromFocal() : 5.0; + fov = (shot.Intrinsics.cameraType == vcg::Camera::PERSPECTIVE) ? shot.GetFovFromFocal() : 5.0; clipRatioNear = nearPlane/getCameraDistance(); clipRatioFar = farPlane/getCameraDistance(); } @@ -2242,9 +2245,9 @@ QPair GLArea::shotFromTrackball() // in MeshLab, fov < 5.0 means orthographic camera if (fov > 5.0) - shot.Intrinsics.cameraType = 0; //perspective + shot.Intrinsics.cameraType = vcg::Camera::PERSPECTIVE; //perspective else - shot.Intrinsics.cameraType = 1; //orthographic + shot.Intrinsics.cameraType = vcg::Camera::ORTHO; //orthographic float cameraDist = getCameraDistance(); @@ -2279,7 +2282,7 @@ void GLArea::loadShot(const QPair &shotAndScale){ Shotm shot = shotAndScale.first; - fov = (shot.Intrinsics.cameraType == 0) ? shot.GetFovFromFocal() : 5.0; + fov = (shot.Intrinsics.cameraType == vcg::Camera::PERSPECTIVE) ? shot.GetFovFromFocal() : 5.0; float cameraDist = getCameraDistance(); @@ -2473,10 +2476,28 @@ void GLArea::setupTextureEnv( GLuint textid ) glPushAttrib(GL_ENABLE_BIT); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,textid); - if(glas.textureMagFilter == 0 ) + switch(glas.textureWrapST) + { + case 0: + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + break; + case 1: + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT ); + break; + case 2: + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + break; + default: assert(0); break; + } + + if(glas.textureMagFilter == 0 ) glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); else glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + if(glas.textureMinFilter == 0 ) glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); else diff --git a/src/meshlab/glarea_setting.cpp b/src/meshlab/glarea_setting.cpp index ed4dcea4d..0c6b0d72a 100644 --- a/src/meshlab/glarea_setting.cpp +++ b/src/meshlab/glarea_setting.cpp @@ -17,14 +17,18 @@ void GLAreaSetting::initGlobalParameterList(RichParameterList& defaultGlobalPara QStringList textureMinFilterModes = (QStringList() << "Nearest" << "MipMap"); QStringList textureMagFilterModes = (QStringList() << "Nearest" << "Linear"); + QStringList textureWrapSTModes = (QStringList() << "Repeat" << "Mirrored Repeat" << "Clamp to Edge"); + defaultGlobalParamSet.addParam(RichEnum(textureMinFilterParam() , 1,textureMinFilterModes,"MeshLab Texture Minification Filtering","MeshLab GLarea's BackGround Color(top corner)")); defaultGlobalParamSet.addParam(RichEnum(textureMagFilterParam() , 1,textureMagFilterModes,"MeshLab Texture Magnification Filtering","MeshLab GLarea's BackGround Color(top corner)")); - + defaultGlobalParamSet.addParam(RichEnum(textureWrapSTParam() , 0,textureWrapSTModes,"MeshLab Texture Clamping","MeshLab Texture Clamping")); + defaultGlobalParamSet.addParam(RichBool(pointDistanceAttenuationParam() , true,"Perspective Varying Point Size","If true the size of the points is drawn with a size proprtional to the distance from the observer.")); defaultGlobalParamSet.addParam(RichBool(pointSmoothParam() , false,"Antialiased Point","If true the points are drawn with small circles instead of fast squared dots.")); defaultGlobalParamSet.addParam(RichFloat(pointSizeParam() , 2.0, "Point Size","The base size of points when drawn")); defaultGlobalParamSet.addParam(RichBool(wheelDirectionParam(), false, "Wheel Direction", "If true, inverts the direction of the mouse wheel for zooming in/out in the MeshLab canvas.")); + defaultGlobalParamSet.addParam(RichBool(showTrackballParam(), true, "Show Trackball", "If true, show the trackball on startup.")); defaultGlobalParamSet.addParam(RichInt(matrixDecimalPrecisionParam(), 2, "Rotation Matrix Precision", "Number of decimal values shown in the rotation matrix")); } @@ -44,11 +48,13 @@ void GLAreaSetting::updateGlobalParameterSet( const RichParameterList& rps ) textureMinFilter = rps.getEnum(this->textureMinFilterParam()); textureMagFilter = rps.getEnum(this->textureMagFilterParam()); + textureWrapST = rps.getEnum(this->textureWrapSTParam()); pointDistanceAttenuation = rps.getBool(this->pointDistanceAttenuationParam()); pointSmooth = rps.getBool(this->pointSmoothParam()); pointSize = rps.getFloat(this->pointSizeParam()); wheelDirection = rps.getBool(this->wheelDirectionParam()); + startupShowTrackball = rps.getBool(showTrackballParam()); matrixDecimalPrecision = rps.getInt(this->matrixDecimalPrecisionParam()); currentGlobalParamSet=&rps; } diff --git a/src/meshlab/glarea_setting.h b/src/meshlab/glarea_setting.h index f03ab315e..da468408d 100644 --- a/src/meshlab/glarea_setting.h +++ b/src/meshlab/glarea_setting.h @@ -57,9 +57,11 @@ public: int textureMagFilter; int textureMinFilter; + int textureWrapST; inline static QString textureMinFilterParam() {return "MeshLab::Appearance::textureMinFilter";} inline static QString textureMagFilterParam() {return "MeshLab::Appearance::textureMagFilter";} - + inline static QString textureWrapSTParam() {return "MeshLab::Appearance::textureWrapST";} + bool pointDistanceAttenuation; inline static QString pointDistanceAttenuationParam() {return "MeshLab::Appearance::pointDistanceAttenuation";} bool pointSmooth; @@ -68,6 +70,8 @@ public: inline static QString pointSizeParam() {return "MeshLab::Appearance::pointSize";} bool wheelDirection; inline static QString wheelDirectionParam() {return "MeshLab::Appearance::wheelDirection";} + bool startupShowTrackball; + inline static QString showTrackballParam() {return "MeshLab::Appearance::showTrackball";} int matrixDecimalPrecision; inline static QString matrixDecimalPrecisionParam() {return "MeshLab::Appearance::matrixDecimalPrecision";} diff --git a/src/meshlab/layerDialog.cpp b/src/meshlab/layerDialog.cpp index dd6e6c3af..f79208e79 100644 --- a/src/meshlab/layerDialog.cpp +++ b/src/meshlab/layerDialog.cpp @@ -34,10 +34,11 @@ $Log: stdpardialog.cpp,v $ #include #include +#include + #include "mainwindow.h" #include "ui_layerDialog.h" #include "layerDialog.h" -#include "rich_parameter_gui/richparameterlistframe.h" #include "../common/mlexception.h" using namespace std; @@ -81,18 +82,31 @@ LayerDialog::LayerDialog(QWidget *parent ) // The following connection is used to associate the click with the switch between raster and mesh view. connect(ui->rasterTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem * , int )) , this, SLOT(rasterItemClicked(QTreeWidgetItem * , int ) ) ); - // state buttons + // state and animation buttons isRecording = false; viewState[0] = viewState[1] = viewState[2] = viewState[3] = ""; connect(ui->bW1, SIGNAL(clicked()), this, SLOT(clickW1())); connect(ui->bW2, SIGNAL(clicked()), this, SLOT(clickW2())); connect(ui->bW3, SIGNAL(clicked()), this, SLOT(clickW3())); connect(ui->bW4, SIGNAL(clicked()), this, SLOT(clickW4())); + connect(ui->animSlower, SIGNAL(clicked()), this, SLOT(clickAnimSlower())); + connect(ui->animStepBackward, SIGNAL(clicked()), this, SLOT(clickAnimStepBackward())); + connect(ui->animPlay, SIGNAL(clicked()), this, SLOT(clickAnimPlay())); + connect(ui->animStepForward, SIGNAL(clicked()), this, SLOT(clickAnimStepForward())); + connect(ui->animFaster, SIGNAL(clicked()), this, SLOT(clickAnimFaster())); connect(ui->bV1, SIGNAL(clicked()), this, SLOT(clickV1())); connect(ui->bV2, SIGNAL(clicked()), this, SLOT(clickV2())); connect(ui->bV3, SIGNAL(clicked()), this, SLOT(clickV3())); connect(ui->bV4, SIGNAL(clicked()), this, SLOT(clickV4())); + animIndex = -1; + animMsecDelay = 500; + animTimer = new QTimer(this); + resetAnim(); + connect(animTimer, SIGNAL(timeout()), this, SLOT(updateAnim())); + // Make wide enough to accommodate alternate text ("||") from clickAnimPlay() + ui->animPlay->setMinimumSize(ui->animPlay->size().width() + 6, ui->animPlay->size().height()); + this->setContextMenuPolicy(Qt::CustomContextMenu); ui->meshTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu); ui->rasterTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu); @@ -218,6 +232,61 @@ void LayerDialog::clickW4() mw->meshDoc()->Log.log(0, "No View to Restore"); } +void LayerDialog::clickAnimSlower() +{ + if (animMsecDelay < 3000) + { + animMsecDelay = int(animMsecDelay * 1.2); + } +} + +void LayerDialog::clickAnimStepBackward() +{ + pauseAnim(); + stepAnim(-1); +} + +void LayerDialog::clickAnimPlay() +{ + if (!animTimer->isActive() && startAnim()) + { + ui->animPlay->setText(tr("||")); + ui->animPlay->setToolTip(tr("Pause animation")); + stepAnim(1); + animTimer->start(animMsecDelay); + } + else + { + pauseAnim(); + } +} + +void LayerDialog::clickAnimStepForward() +{ + pauseAnim(); + stepAnim(1); +} + +void LayerDialog::clickAnimFaster() +{ + if (animMsecDelay > 10) + { + animMsecDelay = int(animMsecDelay / 1.2f); + } +} + +void LayerDialog::updateAnim() +{ + if (stepAnim(1) > 1) + { + animTimer->start(animMsecDelay); // Restart in case animMsecDelay changed + } + else + { + pauseAnim(); + } +} + void LayerDialog::clickV1() { MeshDocument *md = mw->meshDoc(); @@ -405,6 +474,13 @@ void LayerDialog::meshItemClicked (QTreeWidgetItem * item , int col) mw->GLA()->meshSetVisibility(*md->getMesh(clickedId), !md->getMesh(clickedId)->isVisible()); } updatePerMeshItemVisibility(); + + // If not animating, or a mesh in the animation set was clicked, reset the animation + if (!ui->animPlay->isChecked() || + std::find(animMeshIDs.begin(), animMeshIDs.end(), clickedId) != animMeshIDs.end()) + { + resetAnim(); + } } break; case 1 : @@ -567,11 +643,10 @@ void LayerDialog::showContextMenu(const QPoint& pos) } } -void LayerDialog::updateLog(const GLLogStream &log) +void LayerDialog::updateLog(GLLogStream &log) { const QList< pair > &logStringList=log.logStringList(); - ui->logPlainTextEdit->clear(); - //ui->logPlainTextEdit->setFont(QFont("Courier",10)); + //ui->logPlainTextEdit->clear(); pair logElem; #ifdef __APPLE__ @@ -600,6 +675,7 @@ void LayerDialog::updateLog(const GLLogStream &log) logText += "
"; } ui->logPlainTextEdit->appendHtml(logText); + log.clear(); } void LayerDialog::updateTable() @@ -675,6 +751,28 @@ void LayerDialog::updateTable(const MLSceneGLSharedDataContext::PerMeshRendering } _docitem->addChildren(itms); + // Delete any animation IDs no longer in the layer dialog + for (auto animIter = animMeshIDs.begin(); animIter != animMeshIDs.end(); ) + { + bool foundInMeshList = false; + for(MeshModel& m : md->meshIterator()) + { + if (m.id() == *animIter) + { + foundInMeshList = true; + break; + } + } + if (foundInMeshList) + { + ++animIter; + } + else + { + animIter = animMeshIDs.erase(animIter); + } + } + updateTreeWidgetSizes(ui->meshTreeWidget); updatePerMeshItemVisibility(); updatePerMeshItemSelectionStatus(); @@ -860,6 +958,114 @@ void LayerDialog::actionActivated(MLRenderingAction* ract) _tabw->switchTab(ract->meshId(),ract->text()); } +bool LayerDialog::startAnim() +{ + if (animMeshIDs.size() > 1) + { + return true; + } + + MeshDocument *md = mw->meshDoc(); + bool canAnimate = md->meshNumber() > 1; + + if (canAnimate) + { + int visibleCount = 0; + for(MeshModel& m : md->meshIterator()) + { + if (m.isVisible()) + { + ++visibleCount; + } + } + // If fewer than two meshes were visible select all meshes, else select only the visible ones + animIndex = -1; + animMeshIDs.clear(); + for(MeshModel& m : md->meshIterator()) + { + if (m.isVisible() && animIndex < 0) + { + animIndex = animMeshIDs.size(); // Remember first visible mesh + } + if (m.isVisible() || visibleCount < 2) + { + animMeshIDs.push_back(m.id()); + } + } + if (animIndex >= 0) + { + --animIndex; + } + ui->animStepBackward->setEnabled(true); + ui->animStepForward->setEnabled(true); + } + return canAnimate; +} + +// Advance the animation by the specified offset (1 = forward, -1 = backward) +int LayerDialog::stepAnim(int offset) +{ + bool foundVisible = false; + int animatingCount = 0; + MeshDocument *md = mw->meshDoc(); + + if (md->meshNumber() > 1) + { + MeshModel* lastMP = nullptr; + + while (!foundVisible && animMeshIDs.size() > 1) + { + animIndex = (animMeshIDs.size() + animIndex + offset) % animMeshIDs.size(); + animatingCount = 0; + for (const auto& id : animMeshIDs) + { + for(MeshModel& m : md->meshIterator()) + { + if (m.id() == id) + { + bool makeVisible = m.id() == animMeshIDs[animIndex]; + mw->GLA()->meshSetVisibility(m, makeVisible); + foundVisible |= makeVisible; + ++animatingCount; + lastMP = &m; + } + } + } + if (!foundVisible) + { + // The mesh being animated to was deleted; remove it from the list and try again + animMeshIDs.erase(animMeshIDs.begin() + animIndex); + animIndex -= offset; + } + } + if (animMeshIDs.size() == 1 && lastMP != nullptr) + { + mw->GLA()->meshSetVisibility(*lastMP, true); + } + updatePerMeshItemVisibility(); + updatePerMeshItemSelectionStatus(); + mw->GLA()->update(); + } + return animatingCount; +} + +void LayerDialog::pauseAnim() +{ + animTimer->stop(); + ui->animPlay->setChecked(false); + ui->animPlay->setText(tr(">")); + ui->animPlay->setToolTip(tr("Resume animation")); +} + +void LayerDialog::resetAnim() +{ + pauseAnim(); + animMeshIDs.clear(); + ui->animStepBackward->setEnabled(false); + ui->animStepForward->setEnabled(false); + ui->animPlay->setToolTip(tr("Animate visible meshes, or all if < 2 are visible")); +} + LayerDialog::~LayerDialog() { delete ui; @@ -1288,7 +1494,7 @@ void DecoratorParamsTreeWidget::save() void DecoratorParamsTreeWidget::reset() { for(auto& p : *frame) - p.second->resetValue(); + p.second->resetWidgetToDefaultValue(); apply(); } @@ -1298,7 +1504,7 @@ void DecoratorParamsTreeWidget::apply() for(auto& p : *frame) { current.setValue( p.first, - p.second->widgetValue()); + *p.second->getWidgetValue()); } mainWin->updateCustomSettings(); if (mainWin->GLA()) @@ -1329,3 +1535,9 @@ DecoratorParamItem::DecoratorParamItem( QAction* action): QTreeWidgetItem(), act(action) { } + +void LayerDialog::on_cleanLogPushButton_clicked() +{ + ui->logPlainTextEdit->clear(); +} + diff --git a/src/meshlab/layerDialog.h b/src/meshlab/layerDialog.h index ae4030417..0996c0791 100644 --- a/src/meshlab/layerDialog.h +++ b/src/meshlab/layerDialog.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include "ml_render_gui.h" @@ -113,7 +114,7 @@ class LayerDialog : public QDockWidget public: LayerDialog(QWidget *parent = 0); ~LayerDialog(); - void updateLog(const GLLogStream& Log); + void updateLog(GLLogStream& Log); void updateDecoratorParsView(); void updateRenderingParametersTab(int meshid,const MLRenderingData& dt); void reset(); @@ -140,6 +141,12 @@ public slots: void clickW2(); void clickW3(); void clickW4(); + void clickAnimSlower(); + void clickAnimStepBackward(); + void clickAnimPlay(); + void clickAnimStepForward(); + void clickAnimFaster(); + void updateAnim(); void clickV1(); void clickV2(); void clickV3(); @@ -148,6 +155,8 @@ public slots: private slots: /*WARNING!!! ADDED just to avoid usual mac strange behavior. Please, avoid to use it if it's not absolutely necessary*/ void updateTable(); + void on_cleanLogPushButton_clicked(); + private: Ui::layerDialog* ui; MainWindow *mw; @@ -175,6 +184,16 @@ private: QString viewState[4]; QMap visibilityState[4]; + int animIndex; + std::vector animMeshIDs; + int animMsecDelay; + QTimer* animTimer; + + bool startAnim(); + int stepAnim(int offset); + void pauseAnim(); + void resetAnim(); + QTreeWidgetItem* _docitem; int _previd; QGroupBox* _renderingtabcontainer; diff --git a/src/meshlab/mainwindow.h b/src/meshlab/mainwindow.h index 428b34451..5656b2d29 100644 --- a/src/meshlab/mainwindow.h +++ b/src/meshlab/mainwindow.h @@ -67,10 +67,10 @@ class MainWindowSetting { public: static void initGlobalParameterList(RichParameterList& gbllist); - void updateGlobalParameterList(const RichParameterList& rpl ); + void updateGlobalParameterList(const RichParameterList& rpl); std::ptrdiff_t maxgpumem; - inline static QString maximumDedicatedGPUMem() {return "MeshLab::System::maxGPUMemDedicatedToGeometry";} + inline static QString maximumDedicatedGPUMem() {return "MeshLab::System::maxGPUMemDedicatedToGeometry"; } //bool permeshtoolbar; //inline static QString perMeshRenderingToolBar() {return "MeshLab::GUI::perMeshToolBar";} @@ -79,19 +79,28 @@ public: inline static QString highPrecisionRendering() {return "MeshLab::System::highPrecisionRendering";} size_t perbatchprimitives; - inline static QString perBatchPrimitives() {return "MeshLab::System::perBatchPrimitives";} + inline static QString perBatchPrimitives() {return "MeshLab::System::perBatchPrimitives"; } size_t minpolygonpersmoothrendering; inline static QString minFaceNumberPerSmoothRendering() { return "MeshLab::System::minFaceNumberPerSmoothRendering"; } std::ptrdiff_t maxTextureMemory; - inline static QString maxTextureMemoryParam() {return "MeshLab::System::maxTextureMemory";} + inline static QString maxTextureMemoryParam() {return "MeshLab::System::maxTextureMemory"; } int startupWindowWidth; - inline static QString startupWindowWidthParam() {return "MeshLab::System::startupWindowWidth";} - + inline static QString startupWindowWidthParam() {return "MeshLab::System::startupWindowWidth"; } + int startupWindowHeight; - inline static QString startupWindowHeightParam() {return "MeshLab::System::startupWindowHeight";} + inline static QString startupWindowHeightParam() {return "MeshLab::System::startupWindowHeight"; } + + QString meshSetName; + inline static QString meshSetNameParam() {return "MeshLab::System::meshSetName"; } + + bool checkForUpdate; + inline static QString checkForUpdateParam() {return "MeshLab::System::checkForUpdate"; } + + bool sendAnonymousData; + inline static QString sendAnonymousDataParam() {return "MeshLab::System::sendAnonymousData"; } }; class MainWindow : public QMainWindow @@ -238,7 +247,7 @@ private slots: void dropEvent ( QDropEvent * event ); void dragEnterEvent(QDragEnterEvent *); - void connectionDone(QNetworkReply *reply); + void checkForUpdatesConnectionDone(QNetworkReply *reply); ///////////Solt Wrapper for QMdiArea ////////////////// void wrapSetActiveSubWindow(QWidget* window); void switchCurrentContainer(QMdiSubWindow *); @@ -354,7 +363,6 @@ public: return _qsb; } - void setHandleMenu(QPoint point, Qt::Orientation orientation, QSplitter *origin); QMenu* meshLayerMenu() { return filterMenuMeshLayer; } QMenu* rasterLayerMenu() { return filterMenuRasterLayer; } diff --git a/src/meshlab/mainwindow_Init.cpp b/src/meshlab/mainwindow_Init.cpp index 9b05ed676..014a48bfd 100644 --- a/src/meshlab/mainwindow_Init.cpp +++ b/src/meshlab/mainwindow_Init.cpp @@ -1,26 +1,25 @@ -/**************************************************************************** -* MeshLab o o * -* An extendible mesh processor o o * -* _ O _ * -* Copyright(C) 2005, 2006 \/)\/ * -* Visual Computing Lab /\/| * -* ISTI - Italian National Research Council | * -* \ * -* All rights reserved. * -* * -* This program 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. * -* * -* This program 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 (http://www.gnu.org/licenses/gpl.txt) * -* for more details. * -* * -****************************************************************************/ - +/***************************************************************************** + * MeshLab o o * + * An extendible mesh processor o o * + * _ O _ * + * Copyright(C) 2005-2022 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ #include #include @@ -103,7 +102,7 @@ MainWindow::MainWindow() : // Quando si passa da una finestra all'altra aggiorna lo stato delle toolbar e dei menu connect(mdiarea, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(switchCurrentContainer(QMdiSubWindow *))); //httpReq = new QNetworkAccessManager(this); - connect(&httpReq, SIGNAL(finished(QNetworkReply*)), this, SLOT(connectionDone(QNetworkReply*))); + connect(&httpReq, SIGNAL(finished(QNetworkReply*)), this, SLOT(checkForUpdatesConnectionDone(QNetworkReply*))); QIcon icon; icon.addPixmap(QPixmap(":images/eye48.png")); @@ -962,7 +961,6 @@ void MainWindow::loadMeshLabSettings() QDomDocument doc; doc.setContent(settings.value(klist.at(ii)).toString()); - QString st = settings.value(klist.at(ii)).toString(); QDomElement docElem = doc.firstChild().toElement(); if (!docElem.isNull()) @@ -1073,54 +1071,54 @@ void MainWindow::saveRecentProjectList(const QString &projName) void MainWindow::checkForUpdates(bool verboseFlag) { - verboseCheckingFlag = verboseFlag; - - bool checkForMonthlyAndBetasVal = false; - const QString checkForMonthlyAndBetasVar("checkForMonthlyAndBetas"); - - QString urlCheck = "https://www.meshlab.net/ML_VERSION"; QSettings settings; - if (settings.contains(checkForMonthlyAndBetasVar)) - checkForMonthlyAndBetasVal = settings.value(checkForMonthlyAndBetasVar).toBool(); - if (checkForMonthlyAndBetasVal){ - urlCheck = "https://raw.githubusercontent.com/cnr-isti-vclab/meshlab/master/ML_VERSION"; + + // if the user has chosen to do not send anonymous data, skip + if (mwsettings.sendAnonymousData) { + int totalKV = settings.value("totalKV", 0).toInt(); + int loadedMeshCounter = settings.value("loadedMeshCounter", 0).toInt(); + int savedMeshCounter = settings.value("savedMeshCounter", 0).toInt(); + QString UID = settings.value("UID", QString("")).toString(); + if (UID.isEmpty()) { + UID = QUuid::createUuid().toString(); + settings.setValue("UID", UID); + } + + QString baseCommand("/~cignoni/meshlab_latest.php"); + + #ifdef Q_OS_WIN + QString OS = "Win"; + #elif defined( Q_OS_OSX) + QString OS = "Mac"; + #else + QString OS = "Lin"; + #endif + QString message = baseCommand + QString("?code=%1&count=%2&scount=%3&totkv=%4&ver=%5&os=%6").arg(UID).arg(loadedMeshCounter).arg(savedMeshCounter).arg(totalKV).arg(MeshLabApplication::appVer()).arg(OS); + + QNetworkAccessManager stats; + QNetworkRequest statreq(MeshLabApplication::organizationHost() + message); + stats.get(statreq); } - int totalKV = settings.value("totalKV", 0).toInt(); - int loadedMeshCounter = settings.value("loadedMeshCounter", 0).toInt(); - int savedMeshCounter = settings.value("savedMeshCounter", 0).toInt(); - QString UID = settings.value("UID", QString("")).toString(); - if (UID.isEmpty()) { - UID = QUuid::createUuid().toString(); - settings.setValue("UID", UID); + + // if the user has chosen to do not check for updates in the settings skip the check + if(mwsettings.checkForUpdate) { + verboseCheckingFlag = verboseFlag; + const QString urlCheck = "https://www.meshlab.net/ML_VERSION"; + + QNetworkRequest request(urlCheck); + httpReq.get(request); } - QString baseCommand("/~cignoni/meshlab_latest.php"); - - #ifdef Q_OS_WIN - QString OS = "Win"; - #elif defined( Q_OS_OSX) - QString OS = "Mac"; - #else - QString OS = "Lin"; - #endif - QString message = baseCommand + QString("?code=%1&count=%2&scount=%3&totkv=%4&ver=%5&os=%6").arg(UID).arg(loadedMeshCounter).arg(savedMeshCounter).arg(totalKV).arg(MeshLabApplication::appVer()).arg(OS); - - QNetworkAccessManager stats; - QNetworkRequest statreq(MeshLabApplication::organizationHost() + message); - stats.get(statreq); - - QNetworkRequest request(urlCheck); - httpReq.get(request); } -void MainWindow::connectionDone(QNetworkReply *reply) +void MainWindow::checkForUpdatesConnectionDone(QNetworkReply *reply) { + qDebug() << QSslSocket::sslLibraryBuildVersionString(); + qDebug() << QSslSocket::sslLibraryVersionString(); QSettings settings; QSettings::setDefaultFormat(QSettings::NativeFormat); bool dontRemindMeAboutUpgradeVal = false; - bool checkForMonthlyAndBetasVal = false; const QString dontRemindMeAboutUpgradeVar("dontRemindMeAboutUpgrade"); - const QString checkForMonthlyAndBetasVar("checkForMonthlyAndBetas"); // Check if the user specified not to be reminded to upgrade if (settings.contains(dontRemindMeAboutUpgradeVar)) @@ -1129,13 +1127,10 @@ void MainWindow::connectionDone(QNetworkReply *reply) if (dontRemindMeAboutUpgradeVal) return; } - - if (settings.contains(checkForMonthlyAndBetasVar)){ - checkForMonthlyAndBetasVal = settings.value(checkForMonthlyAndBetasVar).toBool();; - } QByteArray ddata = reply->readAll(); QString onlineVersion = QString::fromStdString(ddata.toStdString()); + std::cerr << "Online version: " << onlineVersion.toStdString() << "\n"; QStringList splitOnlineVersion = onlineVersion.split("."); @@ -1173,29 +1168,21 @@ void MainWindow::connectionDone(QNetworkReply *reply) dontShowCheckBox.blockSignals(true); msgBox.addButton(&dontShowCheckBox, QMessageBox::ResetRole); dontShowCheckBox.setChecked(dontRemindMeAboutUpgradeVal); - QCheckBox checkMonthlysCheckBox("Check for Monthly and Beta versions."); - checkMonthlysCheckBox.blockSignals(true); - msgBox.addButton(&checkMonthlysCheckBox, QMessageBox::ResetRole); - checkMonthlysCheckBox.setChecked(checkForMonthlyAndBetasVal); if (newVersionAvailable){ QString message = "
You are using an old version of MeshLab.
" "A new MeshLab version is available: " + onlineVersion + "

" "Please, upgrade to the new version!

"; - if (checkForMonthlyAndBetasVal){ - message += - " Download
"; - } - else { - message += - " Download"; - } + + message += + " Download"; msgBox.setText(message); } else if (verboseCheckingFlag && !newVersionAvailable) { msgBox.setText("
Your MeshLab version is the most recent one: " + onlineVersion + ".
"); + dontShowCheckBox.setVisible(false); } reply->deleteLater(); @@ -1206,16 +1193,6 @@ void MainWindow::connectionDone(QNetworkReply *reply) settings.setValue(dontRemindMeAboutUpgradeVar, true); else if (userReply == QMessageBox::Ok && dontShowCheckBox.checkState() == Qt::Unchecked) settings.setValue(dontRemindMeAboutUpgradeVar, false); - if (userReply == QMessageBox::Ok && checkMonthlysCheckBox.checkState() == Qt::Checked) { - settings.setValue(checkForMonthlyAndBetasVar, true); - if (!checkForMonthlyAndBetasVal) { - //the user changed the states: he now wants to check for betas - //need to check again with properly set - checkForUpdates(false); - } - } - else if (userReply == QMessageBox::Ok && checkMonthlysCheckBox.checkState() == Qt::Unchecked) - settings.setValue(checkForMonthlyAndBetasVar, false); } } @@ -1301,6 +1278,9 @@ void MainWindowSetting::initGlobalParameterList(RichParameterList& gbllist) gbllist.addParam(RichInt(startupWindowWidthParam(), 0, "Startup Window Width (in pixels)", "Window width on startup")); gbllist.addParam(RichInt(startupWindowHeightParam(), 0, "Startup Window Height (in pixels)", "Window height on startup")); + gbllist.addParam(RichString(meshSetNameParam(), "ms", "Name of the MeshSet object.", "Set the MeshSet name object in the PyMeshLab call copied in the clipboard from the filter dock dialog.")); + gbllist.addParam(RichBool(checkForUpdateParam(), true, "Automatic online check for updated version of MeshLab", "If true, MeshLab periodically will check online if a new version has been released")); + gbllist.addParam(RichBool(sendAnonymousDataParam(), true, "Send anonymous and aggregate statistics", "If true, MeshLab periodically will send a few aggregated statistic of usage (number of opened and saved mesh and total number of vertices loaded)")); } void MainWindowSetting::updateGlobalParameterList(const RichParameterList& rpl) @@ -1314,6 +1294,9 @@ void MainWindowSetting::updateGlobalParameterList(const RichParameterList& rpl) maxTextureMemory = (std::ptrdiff_t) rpl.getInt(this->maxTextureMemoryParam()) * (float)(1024 * 1024); startupWindowWidth = rpl.getInt(startupWindowWidthParam()); startupWindowHeight = rpl.getInt(startupWindowHeightParam()); + meshSetName = rpl.getString(meshSetNameParam()); + checkForUpdate = rpl.getBool(checkForUpdateParam()); + sendAnonymousData = rpl.getBool(sendAnonymousDataParam()); } void MainWindow::defaultPerViewRenderingData(MLRenderingData& dt) const diff --git a/src/meshlab/mainwindow_RunTime.cpp b/src/meshlab/mainwindow_RunTime.cpp index 419f35898..65d1e099b 100644 --- a/src/meshlab/mainwindow_RunTime.cpp +++ b/src/meshlab/mainwindow_RunTime.cpp @@ -48,7 +48,7 @@ #include #include -#include "rich_parameter_gui/richparameterlistdialog.h" +#include #include #include "dialogs/about_dialog.h" @@ -344,7 +344,7 @@ void MainWindow::updateMenus() showInfoPaneAct->setEnabled(activeDoc); windowsMenu->setEnabled(activeDoc); preferencesMenu->setEnabled(activeDoc); - + showToolbarStandardAct->setChecked(mainToolBar->isVisible()); if(activeDoc && GLA()) { @@ -485,97 +485,6 @@ void MainWindow::setUnsplit() } } -//set the split/unsplit menu that appears right clicking on a splitter's handle -void MainWindow::setHandleMenu(QPoint point, Qt::Orientation orientation, QSplitter *origin) -{ - MultiViewer_Container *mvc = currentViewContainer(); - int epsilon =10; - splitMenu->clear(); - unSplitMenu->clear(); - //the viewer to split/unsplit is chosen through picking - - //Vertical handle allows to split horizontally - if(orientation == Qt::Vertical) - { - splitUpAct->setData(point); - splitDownAct->setData(point); - - //check if the viewer on the top is splittable according to its size - int pickingId = mvc->getViewerByPicking(QPoint(point.x(), point.y()-epsilon)); - if(pickingId>=0) - splitUpAct->setEnabled(mvc->getViewer(pickingId)->size().width()/2 > mvc->getViewer(pickingId)->minimumSizeHint().width()); - - //the viewer on top can be closed only if the splitter over the handle that originated the event has one child - bool unSplittabilityUp = true; - Splitter * upSplitter = qobject_cast(origin->widget(0)); - if(upSplitter) - unSplittabilityUp = !(upSplitter->count()>1); - unsplitUpAct->setEnabled(unSplittabilityUp); - - //check if the viewer below is splittable according to its size - pickingId = mvc->getViewerByPicking(QPoint(point.x(), point.y()+epsilon)); - if(pickingId>=0) - splitDownAct->setEnabled(mvc->getViewer(pickingId)->size().width()/2 > mvc->getViewer(pickingId)->minimumSizeHint().width()); - - //the viewer below can be closed only if the splitter ounder the handle that originated the event has one child - bool unSplittabilityDown = true; - Splitter * downSplitter = qobject_cast(origin->widget(1)); - if(downSplitter) - unSplittabilityDown = !(downSplitter->count()>1); - unsplitDownAct->setEnabled(unSplittabilityDown); - - splitMenu->addAction(splitUpAct); - splitMenu->addAction(splitDownAct); - - unsplitUpAct->setData(point); - unsplitDownAct->setData(point); - - unSplitMenu->addAction(unsplitUpAct); - unSplitMenu->addAction(unsplitDownAct); - } - //Horizontal handle allows to split vertically - else if (orientation == Qt::Horizontal) - { - splitRightAct->setData(point); - splitLeftAct->setData(point); - - //check if the viewer on the right is splittable according to its size - int pickingId =mvc->getViewerByPicking(QPoint(point.x()+epsilon, point.y())); - if(pickingId>=0) - splitRightAct->setEnabled(mvc->getViewer(pickingId)->size().height()/2 > mvc->getViewer(pickingId)->minimumSizeHint().height()); - - //the viewer on the right can be closed only if the splitter on the right the handle that originated the event has one child - bool unSplittabilityRight = true; - Splitter * rightSplitter = qobject_cast(origin->widget(1)); - if(rightSplitter) - unSplittabilityRight = !(rightSplitter->count()>1); - unsplitRightAct->setEnabled(unSplittabilityRight); - - //check if the viewer on the left is splittable according to its size - pickingId =mvc->getViewerByPicking(QPoint(point.x()-epsilon, point.y())); - if(pickingId>=0) - splitLeftAct->setEnabled(mvc->getViewer(pickingId)->size().height()/2 > mvc->getViewer(pickingId)->minimumSizeHint().height()); - - //the viewer on the left can be closed only if the splitter on the left of the handle that originated the event has one child - bool unSplittabilityLeft = true; - Splitter * leftSplitter = qobject_cast(origin->widget(0)); - if(leftSplitter) - unSplittabilityLeft = !(leftSplitter->count()>1); - unsplitLeftAct->setEnabled(unSplittabilityLeft); - - splitMenu->addAction(splitRightAct); - splitMenu->addAction(splitLeftAct); - - unsplitRightAct->setData(point); - unsplitLeftAct->setData(point); - - unSplitMenu->addAction(unsplitRightAct); - unSplitMenu->addAction(unsplitLeftAct); - } - handleMenu->popup(point); -} - - void MainWindow::splitFromHandle(QAction *qa ) { MultiViewer_Container *mvc = currentViewContainer(); @@ -2782,6 +2691,44 @@ void MainWindow::showEvent(QShowEvent * event) QWidget::showEvent(event); QSettings settings; QSettings::setDefaultFormat(QSettings::NativeFormat); + + const QString informativeSettingString = "informativeShown"; + QVariant informativeShown = settings.value(informativeSettingString); + if (!informativeShown.isValid()) { + // the user never agreed or declined the informative about sending anonymous data... + + QMessageBox::StandardButton reply; + reply = QMessageBox::question( + this, + "Send Anonymous Statistics", + "MeshLab will send periodically some few aggregate statistics of usage (number of " + "opened and saved mesh and total number of vertices loaded).
" + "We really need this information in order to assess how diffusely MeshLab is used and " + "what is its impact on the 3D community.
" + "Do you allow MeshLab to periodically send aggregated statistics?
" + "You can always change this setting in the MeshLab options.", + QMessageBox::Yes | QMessageBox::No, // buttons to show + QMessageBox::Yes); + + mwsettings.sendAnonymousData = (reply == QMessageBox::Yes); + + informativeShown.setValue(true); + settings.setValue(informativeSettingString, informativeShown); + + // TODO: manage of settings in meshlab needs to be completely remade. + // It was thinked to actually save the values of the settings **exclusively from the + // GUI settings dialog**. A proper class that manages settings **outside GUI and + // MainWindow** is needed. + // Right now, the only way to actually save a setting is outside the dialog is + // doing the following mess: + RichBool& p = dynamic_cast(currentGlobalParams.getParameterByName(mwsettings.sendAnonymousDataParam())); + p.setValue(BoolValue(mwsettings.sendAnonymousData)); + QDomDocument doc("MeshLabSettings"); + doc.appendChild(p.fillToXMLDocument(doc)); + QString docstring = doc.toString(); + settings.setValue(p.name(),QVariant(docstring)); + } + const QString versioncheckeddatestring("lastTimeMeshLabVersionCheckedOnStart"); QDate today = QDate::currentDate(); QString todayStr = today.toString(); diff --git a/src/meshlab/multiViewer_Container.cpp b/src/meshlab/multiViewer_Container.cpp index acdc79621..83bece793 100644 --- a/src/meshlab/multiViewer_Container.cpp +++ b/src/meshlab/multiViewer_Container.cpp @@ -24,7 +24,6 @@ #include "glarea.h" #include #include -#include "mainwindow.h" #include using namespace vcg; @@ -34,7 +33,7 @@ Splitter::Splitter(Qt::Orientation orientation, QWidget *parent):QSplitter(orien QSplitterHandle *Splitter::createHandle() { - return new SplitterHandle(orientation(), this); + return new QSplitterHandle(orientation(), this); } MultiViewer_Container *Splitter::getRootContainer() @@ -49,19 +48,6 @@ MultiViewer_Container *Splitter::getRootContainer() return mvc; } -SplitterHandle::SplitterHandle(Qt::Orientation orientation, QSplitter *parent):QSplitterHandle(orientation, parent){} - -void SplitterHandle::mousePressEvent ( QMouseEvent * e ) -{ - QSplitterHandle::mousePressEvent(e); - - if(e->button()== Qt::RightButton) - { - MainWindow *window = qobject_cast(QApplication::activeWindow()); - if (window) window->setHandleMenu(mapToGlobal(e->pos()), orientation(), splitter()); - } -} - MultiViewer_Container::MultiViewer_Container(vcg::QtThreadSafeMemoryInfo& meminfo, bool highprec,size_t perbatchprimitives, size_t minfacespersmoothrendering,QWidget *parent) : Splitter(parent),meshDoc() { @@ -106,9 +92,7 @@ void MultiViewer_Container::addView(GLArea* viewer,Qt::Orientation orient) { MLRenderingData dt; - MainWindow *window = qobject_cast(QApplication::activeWindow()); - if ((window != NULL) && (scenecontext != NULL)) - { + if (scenecontext != nullptr) { //window->defaultPerViewRenderingData(dt); scenecontext->addView(viewer->context(),dt); } diff --git a/src/meshlab/multiViewer_Container.h b/src/meshlab/multiViewer_Container.h index 35594a7a4..91edddcf7 100644 --- a/src/meshlab/multiViewer_Container.h +++ b/src/meshlab/multiViewer_Container.h @@ -38,7 +38,6 @@ class GLArea; class RichParameterList; class MultiViewer_Container; -class MainWindow; class Splitter : public QSplitter { @@ -56,18 +55,6 @@ protected: QSplitterHandle *createHandle(); }; -class SplitterHandle : public QSplitterHandle -{ - Q_OBJECT - -public: - SplitterHandle(Qt::Orientation orientation, QSplitter *parent); - ~SplitterHandle() {} - -protected: - void mousePressEvent ( QMouseEvent * e ); -}; - class MultiViewer_Container : public Splitter { Q_OBJECT diff --git a/src/meshlab/rich_parameter_gui/richparameterwidgets.cpp b/src/meshlab/rich_parameter_gui/richparameterwidgets.cpp deleted file mode 100644 index edb6020bc..000000000 --- a/src/meshlab/rich_parameter_gui/richparameterwidgets.cpp +++ /dev/null @@ -1,1378 +0,0 @@ -/***************************************************************************** - * MeshLab o o * - * Visual and Computer Graphics Library o o * - * _ O _ * - * Copyright(C) 2004-2021 \/)\/ * - * Visual Computing Lab /\/| * - * ISTI - Italian National Research Council | * - * \ * - * All rights reserved. * - * * - * This program 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. * - * * - * This program 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 (http://www.gnu.org/licenses/gpl.txt) * - * for more details. * - * * - ****************************************************************************/ - -#include "richparameterwidgets.h" - -#include -#include -#include -#include -#include - -/******************************************/ -// MeshLabWidget Implementation -/******************************************/ -RichParameterWidget::RichParameterWidget( - QWidget* p, - const RichParameter& rpar, - const RichParameter& defaultParam) : - QWidget(p), - parameter(rpar.clone()), - defaultParameter(defaultParam.clone()), - visible(true), - helpVisible(false) -{ - if (parameter != nullptr) { - descriptionLabel = new ClickableLabel(parameter->fieldDescription(), this); - descriptionLabel->setToolTip(parameter->toolTip()); - descriptionLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); - - helpLabel = new QLabel("" + rpar.toolTip() + "", this); - helpLabel->setTextFormat(Qt::RichText); - helpLabel->setWordWrap(true); - helpLabel->setVisible(false); - helpLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); - helpLabel->setMinimumWidth(250); - } -} - -RichParameterWidget::~RichParameterWidget() -{ - delete parameter; - delete defaultParameter; -} - -void RichParameterWidget::resetValue() -{ - parameter->setValue(defaultParameter->value()); - resetWidgetValue(); -} - -void RichParameterWidget::setValue(const Value& v) -{ - parameter->setValue(v); - resetWidgetValue(); -} - -void RichParameterWidget::setHelpVisible(bool b) -{ - helpVisible = b; - helpLabel->setVisible(visible && helpVisible); -} - -void RichParameterWidget::setVisible(bool b) -{ - visible = b; - descriptionLabel->setVisible(b); - for (QWidget* w : widgets) - w->setVisible(b); - if (b && helpVisible) - helpLabel->setVisible(true); - else if (!b) - helpLabel->setVisible(false); - QWidget::setVisible(b); -} - -const Value& RichParameterWidget::widgetValue() -{ - collectWidgetValue(); - return parameter->value(); -} - -const RichParameter& RichParameterWidget::richParameter() const -{ - return *parameter; -} - -QString RichParameterWidget::parameterName() const -{ - return parameter->name(); -} - -void RichParameterWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) -{ - if (lay != NULL) { - lay->addWidget(descriptionLabel, r, 0, 1, 1, Qt::AlignRight); - lay->addWidget(helpLabel, r, 2); - } -} - -/******************************************/ -// BoolWidget Implementation -/******************************************/ - -BoolWidget::BoolWidget(QWidget* p, const RichBool& rb, const RichBool& rdef) : - RichParameterWidget(p, rb, rdef) -{ - cb = new QCheckBox("", this); - cb->setToolTip(parameter->toolTip()); - cb->setChecked(parameter->value().getBool()); - widgets.push_back(cb); - - connect(cb, SIGNAL(stateChanged(int)), p, SIGNAL(parameterChanged())); - connect(descriptionLabel, SIGNAL(clicked()), cb, SLOT(toggle())); -} - -BoolWidget::~BoolWidget() -{ -} - -void BoolWidget::collectWidgetValue() -{ - parameter->setValue(BoolValue(cb->isChecked())); -} - -void BoolWidget::resetWidgetValue() -{ - cb->setChecked(parameter->value().getBool()); -} - -void BoolWidget::setWidgetValue(const Value& nv) -{ - cb->setChecked(nv.getBool()); -} - -void BoolWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) -{ - if (lay != nullptr) { - lay->addWidget(cb, r, 1); - } - RichParameterWidget::addWidgetToGridLayout(lay, r); -} - -/******************************************/ -// LineEditWidget Implementation -/******************************************/ - -LineEditWidget::LineEditWidget(QWidget* p, const RichParameter& rpar, const RichParameter& rdef) : - RichParameterWidget(p, rpar, rdef) -{ - lned = new QLineEdit(this); - - connect(lned, SIGNAL(editingFinished()), this, SLOT(changeChecker())); - connect(this, SIGNAL(lineEditChanged()), p, SIGNAL(parameterChanged())); - lned->setAlignment(Qt::AlignLeft); - widgets.push_back(lned); -} - -LineEditWidget::~LineEditWidget() -{ -} - -void LineEditWidget::changeChecker() -{ - if (lned->text() != this->lastVal) { - this->lastVal = lned->text(); - if (!this->lastVal.isEmpty()) - emit lineEditChanged(); - } -} - -void LineEditWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) -{ - if (lay != nullptr) { - lay->addWidget(lned, r, 1); - } - RichParameterWidget::addWidgetToGridLayout(lay, r); -} - -/******************************************/ -// IntWidget Implementation -/******************************************/ - -IntWidget::IntWidget(QWidget* p, const RichInt& rpar, const RichInt& rdef) : - LineEditWidget(p, rpar, rdef) -{ - lned->setText(QString::number(parameter->value().getInt())); -} - -void IntWidget::collectWidgetValue() -{ - parameter->setValue(IntValue(lned->text().toInt())); -} - -void IntWidget::resetWidgetValue() -{ - lned->setText(QString::number(parameter->value().getInt())); -} - -void IntWidget::setWidgetValue(const Value& nv) -{ - lned->setText(QString::number(nv.getInt())); -} - -/******************************************/ -// FloatWidget Implementation -/******************************************/ - -FloatWidget::FloatWidget(QWidget* p, const RichFloat& rpar, const RichFloat& rdef) : - LineEditWidget(p, rpar, rdef) -{ - lned->setText(QString::number(parameter->value().getFloat(), 'g', 3)); -} - -void FloatWidget::collectWidgetValue() -{ - parameter->setValue(FloatValue(lned->text().toFloat())); -} - -void FloatWidget::resetWidgetValue() -{ - lned->setText(QString::number(parameter->value().getFloat(), 'g', 3)); -} - -void FloatWidget::setWidgetValue(const Value& nv) -{ - lned->setText(QString::number(nv.getFloat(), 'g', 3)); -} - -/******************************************/ -// StringWidget Implementation -/******************************************/ - -StringWidget::StringWidget(QWidget* p, const RichString& rpar, const RichString& rdef) : - LineEditWidget(p, rpar, rdef) -{ - lned->setText(parameter->value().getString()); -} - -void StringWidget::collectWidgetValue() -{ - parameter->setValue(StringValue(lned->text())); -} - -void StringWidget::resetWidgetValue() -{ - lned->setText(parameter->value().getString()); -} - -void StringWidget::setWidgetValue(const Value& nv) -{ - lned->setText(nv.getString()); -} - -/******************************************/ -// ColorWidget Implementation -/******************************************/ - -ColorWidget::ColorWidget(QWidget* p, const RichColor& newColor, const RichColor& rdef) : - RichParameterWidget(p, newColor, rdef), pickcol() -{ - colorLabel = new QLabel(this); - colorButton = new QPushButton(this); - colorButton->setAutoFillBackground(true); - colorButton->setFlat(true); - colorButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - initWidgetValue(); - - vlay = new QHBoxLayout(); - QFontMetrics met(colorLabel->font()); - QColor black(Qt::black); - QString blackname = "(" + black.name() + ")"; - QSize sz = met.size(Qt::TextSingleLine, blackname); - colorLabel->setMaximumWidth(sz.width()); - colorLabel->setMinimumWidth(sz.width()); - vlay->addWidget(colorLabel, 0, Qt::AlignRight); - vlay->addWidget(colorButton); - widgets.push_back(colorLabel); - widgets.push_back(colorButton); - - pickcol = parameter->value().getColor(); - connect(colorButton, SIGNAL(clicked()), this, SLOT(pickColor())); - connect(this, SIGNAL(dialogParamChanged()), p, SIGNAL(parameterChanged())); -} - -ColorWidget::~ColorWidget() -{ - delete colorButton; - delete colorLabel; -} - -void ColorWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) -{ - if (lay != nullptr) { - lay->addLayout(vlay, r, 1); - } - RichParameterWidget::addWidgetToGridLayout(lay, r); -} - -void ColorWidget::collectWidgetValue() -{ - parameter->setValue(ColorValue(pickcol)); -} - -void ColorWidget::resetWidgetValue() -{ - QColor cl = parameter->value().getColor(); - pickcol = cl; - updateColorInfo(cl); -} - -void ColorWidget::setWidgetValue(const Value& nv) -{ - QColor cl = nv.getColor(); - pickcol = cl; - updateColorInfo(cl); -} - -void ColorWidget::initWidgetValue() -{ - QColor cl = parameter->value().getColor(); - pickcol = cl; - updateColorInfo(cl); -} - -void ColorWidget::updateColorInfo(const ColorValue& newColor) -{ - QColor col = newColor.getColor(); - colorLabel->setText("(" + col.name() + ")"); - QPalette palette(col); - colorButton->setPalette(palette); -} - -void ColorWidget::pickColor() -{ - pickcol = QColorDialog::getColor( - pickcol, - this->parentWidget(), - "Pick a Color", - QColorDialog::DontUseNativeDialog | QColorDialog::ShowAlphaChannel); - if (pickcol.isValid()) { - collectWidgetValue(); - updateColorInfo(ColorValue(pickcol)); - } - emit dialogParamChanged(); -} - -/******************************************/ -// AbsPercWidget Implementation -/******************************************/ - -AbsPercWidget::AbsPercWidget(QWidget* p, const RichAbsPerc& rabs, const RichAbsPerc& rdef) : - RichParameterWidget(p, rabs, rdef) - -{ - m_min = rabs.min; - m_max = rabs.max; - - descriptionLabel->setText(descriptionLabel->text() + " (abs and %)"); - - absSB = new QDoubleSpinBox(this); - percSB = new QDoubleSpinBox(this); - - absSB->setMinimum(m_min - (m_max - m_min)); - absSB->setMaximum(m_max * 2); - absSB->setAlignment(Qt::AlignRight); - - int decimals = 7 - ceil(log10(fabs(m_max - m_min))); - absSB->setDecimals(decimals); - absSB->setSingleStep((m_max - m_min) / 100.0); - float initVal = parameter->value().getFloat(); - absSB->setValue(initVal); - absSB->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - - percSB->setMinimum(-200); - percSB->setMaximum(200); - percSB->setAlignment(Qt::AlignRight); - percSB->setSingleStep(0.5); - percSB->setValue((100 * (initVal - m_min)) / (m_max - m_min)); - percSB->setDecimals(3); - percSB->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - QLabel* absLab = new QLabel(" world unit"); - QLabel* percLab = new QLabel( - " perc on" + QString("(%1 .. %2)").arg(m_min).arg(m_max) + ""); - - vlay = new QGridLayout(); - vlay->addWidget(absLab, 0, 0, Qt::AlignHCenter); - vlay->addWidget(percLab, 0, 1, Qt::AlignHCenter); - - vlay->addWidget(absSB, 1, 0, Qt::AlignTop); - vlay->addWidget(percSB, 1, 1, Qt::AlignTop); - - widgets.push_back(absLab); - widgets.push_back(percLab); - widgets.push_back(absSB); - widgets.push_back(percSB); - - connect(absSB, SIGNAL(valueChanged(double)), this, SLOT(on_absSB_valueChanged(double))); - connect(percSB, SIGNAL(valueChanged(double)), this, SLOT(on_percSB_valueChanged(double))); - connect(this, SIGNAL(dialogParamChanged()), p, SIGNAL(parameterChanged())); -} - -AbsPercWidget::~AbsPercWidget() -{ - delete absSB; - delete percSB; -} - -void AbsPercWidget::on_absSB_valueChanged(double newv) -{ - disconnect(percSB, SIGNAL(valueChanged(double)), this, SLOT(on_percSB_valueChanged(double))); - percSB->setValue((100 * (newv - m_min)) / (m_max - m_min)); - connect(percSB, SIGNAL(valueChanged(double)), this, SLOT(on_percSB_valueChanged(double))); - emit dialogParamChanged(); -} - -void AbsPercWidget::on_percSB_valueChanged(double newv) -{ - disconnect(absSB, SIGNAL(valueChanged(double)), this, SLOT(on_absSB_valueChanged(double))); - absSB->setValue((m_max - m_min) * 0.01 * newv + m_min); - connect(absSB, SIGNAL(valueChanged(double)), this, SLOT(on_absSB_valueChanged(double))); - emit dialogParamChanged(); -} - -void AbsPercWidget::setValue(float val, float minV, float maxV) -{ - absSB->setValue(val); - m_min = minV; - m_max = maxV; -} - -void AbsPercWidget::collectWidgetValue() -{ - parameter->setValue(FloatValue(absSB->value())); -} - -void AbsPercWidget::resetWidgetValue() -{ - RichAbsPerc* ap = reinterpret_cast(parameter); - setValue(parameter->value().getFloat(), ap->min, ap->max); -} - -void AbsPercWidget::setWidgetValue(const Value& nv) -{ - RichAbsPerc* ap = reinterpret_cast(parameter); - setValue(nv.getFloat(), ap->min, ap->max); -} - -void AbsPercWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) -{ - if (lay != nullptr) { - lay->addLayout(vlay, r, 1, Qt::AlignTop); - } - RichParameterWidget::addWidgetToGridLayout(lay, r); -} - -/******************************************/ -// PositionWidget Implementation -/******************************************/ - -PositionWidget::PositionWidget( - QWidget* p, - const RichPosition& rpf, - const RichPosition& rdef, - QWidget* gla_curr) : - RichParameterWidget(p, rpf, rdef) -{ - paramName = rpf.name(); - - vlay = new QHBoxLayout(); - vlay->setSpacing(0); - for (int i = 0; i < 3; ++i) { - coordSB[i] = new QLineEdit(this); - QFont baseFont = coordSB[i]->font(); - if (baseFont.pixelSize() != -1) - baseFont.setPixelSize(baseFont.pixelSize() * 3 / 4); - else - baseFont.setPointSize(baseFont.pointSize() * 3 / 4); - coordSB[i]->setFont(baseFont); - coordSB[i]->setMinimumWidth(coordSB[i]->sizeHint().width() / 4); - coordSB[i]->setValidator(new QDoubleValidator()); - coordSB[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - vlay->addWidget(coordSB[i]); - widgets.push_back(coordSB[i]); - connect(coordSB[i], SIGNAL(textChanged(QString)), p, SIGNAL(parameterChanged())); - } - this->setValue(paramName, parameter->value().getPoint3f()); - // if we have a connection to the current glarea we can setup the additional - // button for getting the current view direction. - if (gla_curr) { - QStringList names; - names << "View Pos."; - names << "Surf. Pos."; - names << "Raster Camera Pos."; - names << "Trackball Center"; - - getPoint3Combo = new QComboBox(this); - getPoint3Combo->addItems(names); - getPoint3Combo->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - vlay->addWidget(getPoint3Combo); - widgets.push_back(getPoint3Combo); - - connect( - gla_curr, - SIGNAL(transmitSurfacePos(QString, Point3m)), - this, - SLOT(setValue(QString, Point3m))); - connect( - gla_curr, - SIGNAL(transmitCameraPos(QString, Point3m)), - this, - SLOT(setValue(QString, Point3m))); - connect( - gla_curr, - SIGNAL(transmitShot(QString, Shotm)), - this, - SLOT(setShotValue(QString, Shotm))); - connect( - gla_curr, - SIGNAL(transmitTrackballPos(QString, Point3m)), - this, - SLOT(setValue(QString, Point3m))); - connect(this, SIGNAL(askViewPos(QString)), gla_curr, SLOT(sendViewerShot(QString))); - connect(this, SIGNAL(askSurfacePos(QString)), gla_curr, SLOT(sendSurfacePos(QString))); - connect(this, SIGNAL(askCameraPos(QString)), gla_curr, SLOT(sendRasterShot(QString))); - connect(this, SIGNAL(askTrackballPos(QString)), gla_curr, SLOT(sendTrackballPos(QString))); - - getPoint3Button = new QPushButton("Get", this); - getPoint3Button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - connect(getPoint3Button, SIGNAL(clicked()), this, SLOT(getPoint())); - - vlay->addWidget(getPoint3Button); - widgets.push_back(getPoint3Button); - } -} - -PositionWidget::~PositionWidget() -{ - this->disconnect(); -} - -void PositionWidget::getPoint() -{ - int index = getPoint3Combo->currentIndex(); - switch (index) { - case 0: emit askViewPos(paramName); break; - case 1: emit askSurfacePos(paramName); break; - case 2: emit askCameraPos(paramName); break; - case 3: emit askTrackballPos(paramName); break; - default: assert(0); - } -} - -void PositionWidget::setValue(QString name, Point3m newVal) -{ - if (name == paramName) { - for (int i = 0; i < 3; ++i) - coordSB[i]->setText(QString::number(newVal[i], 'g', 4)); - } -} - -void PositionWidget::setShotValue(QString name, Shotm newValShot) -{ - vcg::Point3f p = newValShot.GetViewPoint(); - setValue(name, p); -} - -vcg::Point3f PositionWidget::getValue() -{ - return vcg::Point3f( - coordSB[0]->text().toFloat(), coordSB[1]->text().toFloat(), coordSB[2]->text().toFloat()); -} - -void PositionWidget::collectWidgetValue() -{ - parameter->setValue(Point3fValue(vcg::Point3f( - coordSB[0]->text().toFloat(), coordSB[1]->text().toFloat(), coordSB[2]->text().toFloat()))); -} - -void PositionWidget::resetWidgetValue() -{ - for (unsigned int ii = 0; ii < 3; ++ii) - coordSB[ii]->setText(QString::number(parameter->value().getPoint3f()[ii], 'g', 3)); -} - -void PositionWidget::setWidgetValue(const Value& nv) -{ - for (unsigned int ii = 0; ii < 3; ++ii) - coordSB[ii]->setText(QString::number(nv.getPoint3f()[ii], 'g', 3)); -} - -void PositionWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) -{ - if (lay != nullptr) { - lay->addLayout(vlay, r, 1); - } - RichParameterWidget::addWidgetToGridLayout(lay, r); -} - -/******************************************/ -// DirectionWidget Implementation -/******************************************/ - -DirectionWidget::DirectionWidget( - QWidget* p, - const RichDirection& rpf, - const RichDirection& rdef, - QWidget* gla_curr) : - RichParameterWidget(p, rpf, rdef) -{ - paramName = rpf.name(); - - vlay = new QHBoxLayout(); - vlay->setSpacing(0); - for (int i = 0; i < 3; ++i) { - coordSB[i] = new QLineEdit(this); - QFont baseFont = coordSB[i]->font(); - if (baseFont.pixelSize() != -1) - baseFont.setPixelSize(baseFont.pixelSize() * 3 / 4); - else - baseFont.setPointSize(baseFont.pointSize() * 3 / 4); - coordSB[i]->setFont(baseFont); - coordSB[i]->setMinimumWidth(coordSB[i]->sizeHint().width() / 4); - coordSB[i]->setValidator(new QDoubleValidator()); - coordSB[i]->setAlignment(Qt::AlignRight); - coordSB[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - vlay->addWidget(coordSB[i]); - widgets.push_back(coordSB[i]); - connect(coordSB[i], SIGNAL(textChanged(QString)), p, SIGNAL(parameterChanged())); - } - this->setValue(paramName, parameter->value().getPoint3f()); - // if we have a connection to the current glarea we can setup the additional - // button for getting the current view direction. - if (gla_curr) { - QStringList names; - names << "View Dir."; - names << "Raster Camera Dir."; - - getPoint3Combo = new QComboBox(this); - getPoint3Combo->addItems(names); - getPoint3Combo->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - vlay->addWidget(getPoint3Combo); - widgets.push_back(getPoint3Combo); - - connect( - gla_curr, - SIGNAL(transmitViewDir(QString, Point3m)), - this, - SLOT(setValue(QString, Point3m))); - connect( - gla_curr, - SIGNAL(transmitShot(QString, Shotm)), - this, - SLOT(setShotValue(QString, Shotm))); - connect(this, SIGNAL(askViewDir(QString)), gla_curr, SLOT(sendViewDir(QString))); - connect(this, SIGNAL(askCameraDir(QString)), gla_curr, SLOT(sendRasterShot(QString))); - - getPoint3Button = new QPushButton("Get", this); - getPoint3Button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - connect(getPoint3Button, SIGNAL(clicked()), this, SLOT(getPoint())); - - vlay->addWidget(getPoint3Button); - widgets.push_back(getPoint3Button); - } -} - -DirectionWidget::~DirectionWidget() -{ - this->disconnect(); -} - -void DirectionWidget::getPoint() -{ - int index = getPoint3Combo->currentIndex(); - switch (index) { - case 0: emit askViewDir(paramName); break; - case 1: emit askCameraDir(paramName); break; - - default: assert(0); - } -} - -void DirectionWidget::setValue(QString name, Point3m newVal) -{ - if (name == paramName) { - for (int i = 0; i < 3; ++i) - coordSB[i]->setText(QString::number(newVal[i], 'g', 4)); - } -} - -void DirectionWidget::setShotValue(QString name, Shotm newValShot) -{ - vcg::Point3f p = newValShot.GetViewDir(); - setValue(name, p); -} - -vcg::Point3f DirectionWidget::getValue() -{ - return vcg::Point3f( - coordSB[0]->text().toFloat(), coordSB[1]->text().toFloat(), coordSB[2]->text().toFloat()); -} - -void DirectionWidget::collectWidgetValue() -{ - parameter->setValue(Point3fValue(vcg::Point3f( - coordSB[0]->text().toFloat(), coordSB[1]->text().toFloat(), coordSB[2]->text().toFloat()))); -} - -void DirectionWidget::resetWidgetValue() -{ - for (unsigned int ii = 0; ii < 3; ++ii) - coordSB[ii]->setText(QString::number(parameter->value().getPoint3f()[ii], 'g', 3)); -} - -void DirectionWidget::setWidgetValue(const Value& nv) -{ - for (unsigned int ii = 0; ii < 3; ++ii) - coordSB[ii]->setText(QString::number(nv.getPoint3f()[ii], 'g', 3)); -} - -void DirectionWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) -{ - if (lay != nullptr) { - lay->addLayout(vlay, r, 1); - } - RichParameterWidget::addWidgetToGridLayout(lay, r); -} - -/******************************************/ -// Matrix44fWidget Implementation -/******************************************/ - -Matrix44fWidget::Matrix44fWidget( - QWidget* p, - const RichMatrix44f& rpf, - const RichMatrix44f& rdef, - QWidget* gla_curr) : - RichParameterWidget(p, rpf, rdef) -{ - valid = false; - m.SetIdentity(); - paramName = rpf.name(); - - vlay = new QVBoxLayout(); - lay44 = new QGridLayout(); - - for (int i = 0; i < 16; ++i) { - coordSB[i] = new QLineEdit(p); - QFont baseFont = coordSB[i]->font(); - if (baseFont.pixelSize() != -1) - baseFont.setPixelSize(baseFont.pixelSize() * 3 / 4); - else - baseFont.setPointSize(baseFont.pointSize() * 3 / 4); - coordSB[i]->setFont(baseFont); - coordSB[i]->setMinimumWidth(coordSB[i]->sizeHint().width() / 4); - coordSB[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - coordSB[i]->setValidator(new QDoubleValidator(p)); - lay44->addWidget(coordSB[i], i / 4, i % 4); - widgets.push_back(coordSB[i]); - connect( - coordSB[i], - SIGNAL(textChanged(const QString&)), - this, - SLOT(invalidateMatrix(const QString&))); - } - this->setValue(paramName, parameter->value().getMatrix44f()); - - QLabel* headerL = new QLabel("Matrix:", this); - vlay->addWidget(headerL, 0, Qt::AlignTop); - widgets.push_back(headerL); - - vlay->addLayout(lay44); - - QPushButton* getMatrixButton = new QPushButton("Read from current layer"); - vlay->addWidget(getMatrixButton); - widgets.push_back(getMatrixButton); - - QPushButton* pasteMatrixButton = new QPushButton("Paste from clipboard"); - vlay->addWidget(pasteMatrixButton); - widgets.push_back(pasteMatrixButton); - - // gridLay->addLayout(vlay,row,1,Qt::AlignTop); - - connect( - gla_curr, - SIGNAL(transmitMatrix(QString, Matrix44m)), - this, - SLOT(setValue(QString, Matrix44m))); - connect(getMatrixButton, SIGNAL(clicked()), this, SLOT(getMatrix())); - connect(pasteMatrixButton, SIGNAL(clicked()), this, SLOT(pasteMatrix())); - connect(this, SIGNAL(askMeshMatrix(QString)), gla_curr, SLOT(sendMeshMatrix(QString))); -} - -Matrix44fWidget::~Matrix44fWidget() -{ -} - -void Matrix44fWidget::setValue(QString name, Matrix44m newVal) -{ - if (name == paramName) { - for (int i = 0; i < 16; ++i) - coordSB[i]->setText(QString::number(newVal[i / 4][i % 4], 'g', 4)); - valid = true; - m = newVal; - } -} - -Matrix44m Matrix44fWidget::getValue() -{ - if (!valid) { - Scalarm val[16]; - for (unsigned int i = 0; i < 16; ++i) - val[i] = coordSB[i]->text().toFloat(); - return Matrix44m(val); - } - return m; -} - -void Matrix44fWidget::getMatrix() -{ - emit askMeshMatrix(QString("TransformMatrix")); -} - -void Matrix44fWidget::pasteMatrix() -{ - QClipboard* clipboard = QApplication::clipboard(); - QString shotString = clipboard->text().trimmed(); - if (shotString.contains(' ')) { - QStringList list1 = shotString.split(" "); - if (list1.size() != 16) - return; - valid = false; - int id = 0; - for (QStringList::iterator i = list1.begin(); i != list1.end(); ++i, ++id) { - bool ok = true; - (*i).toFloat(&ok); - if (!ok) - return; - } - id = 0; - for (QStringList::iterator i = list1.begin(); i != list1.end(); ++i, ++id) { - coordSB[id]->setText(*i); - } - } - else { - QByteArray value = QByteArray::fromBase64(shotString.toLocal8Bit()); - memcpy(m.V(), value.data(), sizeof(Matrix44m::ScalarType) * 16); - int id = 0; - for (int i = 0; i < 16; ++i, ++id) - coordSB[id]->setText(QString::number(m.V()[i])); - } -} - -void Matrix44fWidget::collectWidgetValue() -{ - if (!valid) { - Matrix44m tempM; - for (unsigned int i = 0; i < 16; ++i) - tempM[i / 4][i % 4] = coordSB[i]->text().toFloat(); - parameter->setValue(Matrix44fValue(tempM)); - } - else { - parameter->setValue(Matrix44fValue(m)); - } -} - -void Matrix44fWidget::resetWidgetValue() -{ - valid = false; - vcg::Matrix44f m; - m.SetIdentity(); - for (unsigned int ii = 0; ii < 16; ++ii) { - coordSB[ii]->setText( - QString::number(parameter->value().getMatrix44f()[ii / 4][ii % 4], 'g', 3)); - } -} - -void Matrix44fWidget::setWidgetValue(const Value& nv) -{ - valid = true; - m = nv.getMatrix44f(); - for (unsigned int ii = 0; ii < 16; ++ii) - coordSB[ii]->setText(QString::number(nv.getMatrix44f()[ii / 4][ii % 4], 'g', 3)); -} - -void Matrix44fWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) -{ - if (lay != nullptr) { - lay->addLayout(vlay, r, 1, Qt::AlignTop); - } - RichParameterWidget::addWidgetToGridLayout(lay, r); -} - -void Matrix44fWidget::invalidateMatrix(const QString& /*s*/) -{ - valid = false; -} - -/******************************************/ -// ShotfWidget Implementation -/******************************************/ - -ShotfWidget::ShotfWidget( - QWidget* p, - const RichShotf& rpf, - const RichShotf& rdef, - QWidget* gla_curr) : - RichParameterWidget(p, rpf, rdef) -{ - paramName = rpf.name(); - - hlay = new QHBoxLayout(); - - this->setShotValue(paramName, parameter->value().getShotf()); - // if we have a connection to the current glarea we can setup the additional - // button for getting the current view direction. - if (gla_curr) { - getShotButton = new QPushButton("Get shot", this); - getShotButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - hlay->addWidget(getShotButton); - widgets.push_back(getShotButton); - - QStringList names; - names << "Current Trackball"; - names << "Current Mesh"; - names << "Current Raster"; - names << "From File"; - - getShotCombo = new QComboBox(this); - getShotCombo->addItems(names); - hlay->addWidget(getShotCombo); - widgets.push_back(getShotCombo); - connect(getShotCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(getShot())); - connect(getShotButton, SIGNAL(clicked()), this, SLOT(getShot())); - connect( - gla_curr, - SIGNAL(transmitShot(QString, Shotm)), - this, - SLOT(setShotValue(QString, Shotm))); - connect(this, SIGNAL(askViewerShot(QString)), gla_curr, SLOT(sendViewerShot(QString))); - connect(this, SIGNAL(askMeshShot(QString)), gla_curr, SLOT(sendMeshShot(QString))); - connect(this, SIGNAL(askRasterShot(QString)), gla_curr, SLOT(sendRasterShot(QString))); - } -} - -void ShotfWidget::getShot() -{ - int index = getShotCombo->currentIndex(); - switch (index) { - case 0: emit askViewerShot(paramName); break; - case 1: emit askMeshShot(paramName); break; - case 2: emit askRasterShot(paramName); break; - case 3: { - QString filename = QFileDialog::getOpenFileName( - this, tr("Load xml camera"), "./", tr("Xml Files (*.xml)")); - QFile qf(filename); - QFileInfo qfInfo(filename); - - if (!qf.open(QIODevice::ReadOnly)) - return; - - QDomDocument doc("XmlDocument"); // It represents the XML document - if (!doc.setContent(&qf)) - return; - qf.close(); - - QString type = doc.doctype().name(); - - } break; - default: assert(0); - } -} - -ShotfWidget::~ShotfWidget() -{ -} - -void ShotfWidget::setShotValue(QString name, Shotm newVal) -{ - if (name == paramName) { - curShot = newVal; - } -} - -Shotm ShotfWidget::getValue() -{ - return curShot; -} - -void ShotfWidget::collectWidgetValue() -{ - parameter->setValue(ShotfValue(curShot)); -} - -void ShotfWidget::resetWidgetValue() -{ - curShot = parameter->value().getShotf(); -} - -void ShotfWidget::setWidgetValue(const Value& nv) -{ - curShot = nv.getShotf(); -} - -void ShotfWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) -{ - if (lay != nullptr) { - lay->addLayout(hlay, r, 1); - } - RichParameterWidget::addWidgetToGridLayout(lay, r); -} - -/******************************************/ -// DynamicFloatWidget Implementation -/******************************************/ - -DynamicFloatWidget::DynamicFloatWidget( - QWidget* p, - const RichDynamicFloat& rdf, - const RichDynamicFloat& rdef) : - RichParameterWidget(p, rdf, rdef) -{ - int numbdecimaldigit = 4; - minVal = rdf.min; - maxVal = rdf.max; - valueLE = new QLineEdit(this); - valueLE->setAlignment(Qt::AlignRight); - - valueSlider = new QSlider(Qt::Horizontal, this); - valueSlider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - valueSlider->setMinimum(0); - valueSlider->setMaximum(100); - valueSlider->setValue(floatToInt(parameter->value().getFloat())); - RichDynamicFloat* dfd = reinterpret_cast(parameter); - QFontMetrics fm(valueLE->font()); - QSize sz = fm.size(Qt::TextSingleLine, QString::number(0)); - valueLE->setValidator(new QDoubleValidator(dfd->min, dfd->max, numbdecimaldigit, valueLE)); - valueLE->setText(QString::number(parameter->value().getFloat())); - valueLE->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - - hlay = new QHBoxLayout(); - hlay->addWidget(valueLE); - hlay->addWidget(valueSlider); - widgets.push_back(valueLE); - widgets.push_back(valueSlider); - int maxlenghtplusdot = 8; // numbmaxvaluedigit + numbdecimaldigit + 1; - valueLE->setMaxLength(maxlenghtplusdot); - valueLE->setMaximumWidth(sz.width() * maxlenghtplusdot); - - connect(valueLE, SIGNAL(textChanged(const QString&)), this, SLOT(setValue())); - connect(valueSlider, SIGNAL(valueChanged(int)), this, SLOT(setValue(int))); - connect(this, SIGNAL(dialogParamChanged()), p, SIGNAL(parameterChanged())); -} - -DynamicFloatWidget::~DynamicFloatWidget() -{ -} - -float DynamicFloatWidget::getValue() -{ - return float(valueLE->text().toDouble()); -} - -void DynamicFloatWidget::setValue(float newVal) -{ - if (QString::number(intToFloat(newVal)) != valueLE->text()) - valueLE->setText(QString::number(intToFloat(newVal))); -} - -void DynamicFloatWidget::setValue(int newVal) -{ - if (floatToInt(float(valueLE->text().toDouble())) != newVal) { - valueLE->setText(QString::number(intToFloat(newVal))); - } -} - -void DynamicFloatWidget::setValue() -{ - float newValLE = float(valueLE->text().toDouble()); - valueSlider->setValue(floatToInt(newValLE)); - emit dialogParamChanged(); -} - -float DynamicFloatWidget::intToFloat(int val) -{ - return minVal + float(val) / 100.0f * (maxVal - minVal); -} -int DynamicFloatWidget::floatToInt(float val) -{ - return int(100.0f * (val - minVal) / (maxVal - minVal)); -} - -void DynamicFloatWidget::collectWidgetValue() -{ - parameter->setValue(FloatValue(valueLE->text().toFloat())); -} - -void DynamicFloatWidget::resetWidgetValue() -{ - valueLE->setText(QString::number(parameter->value().getFloat())); -} - -void DynamicFloatWidget::setWidgetValue(const Value& nv) -{ - valueLE->setText(QString::number(nv.getFloat())); -} - -void DynamicFloatWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) -{ - if (lay != nullptr) { - lay->addLayout(hlay, r, 1); - } - RichParameterWidget::addWidgetToGridLayout(lay, r); -} - -/******************************************/ -// ComboWidget Implementation -/******************************************/ - -ComboWidget::ComboWidget(QWidget* p, const RichParameter& rpar, const RichParameter& rdef) : - RichParameterWidget(p, rpar, rdef) -{ -} - -void ComboWidget::init(QWidget* p, int defaultEnum, QStringList values) -{ - enumCombo = new QComboBox(this); - enumCombo->addItems(values); - widgets.push_back(enumCombo); - setIndex(defaultEnum); - connect(enumCombo, SIGNAL(activated(int)), this, SIGNAL(dialogParamChanged())); - connect(this, SIGNAL(dialogParamChanged()), p, SIGNAL(parameterChanged())); -} - -void ComboWidget::setIndex(int newEnum) -{ - enumCombo->setCurrentIndex(newEnum); -} - -int ComboWidget::getIndex() -{ - return enumCombo->currentIndex(); -} - -ComboWidget::~ComboWidget() -{ - delete enumCombo; -} - -void ComboWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) -{ - if (lay != nullptr) { - lay->addWidget(enumCombo, r, 1); - } - RichParameterWidget::addWidgetToGridLayout(lay, r); -} - -/******************************************/ -// EnumWidget Implementation -/******************************************/ - -EnumWidget::EnumWidget(QWidget* p, const RichEnum& rpar, const RichEnum& rdef) : - ComboWidget(p, rpar, rdef) -{ - init(p, rpar.value().getInt(), rpar.enumvalues); -} - -int EnumWidget::getSize() -{ - return enumCombo->count(); -} - -void EnumWidget::collectWidgetValue() -{ - parameter->setValue(IntValue(enumCombo->currentIndex())); -} - -void EnumWidget::resetWidgetValue() -{ - enumCombo->setCurrentIndex(parameter->value().getInt()); -} - -void EnumWidget::setWidgetValue(const Value& nv) -{ - enumCombo->setCurrentIndex(nv.getInt()); -} - -/******************************************/ -// MeshWidget Implementation -/******************************************/ - -MeshWidget::MeshWidget(QWidget* p, const RichMesh& rpar, const RichMesh& rdef) : - ComboWidget(p, rpar, rdef) -{ - md = ((RichMesh*) parameter)->meshdoc; - - QStringList meshNames; - - // make the default mesh Index be 0 - // defaultMeshIndex = -1; - int currentmeshindex = -1; - unsigned int i = 0; - for (const MeshModel& mm : md->meshIterator()) { - QString shortName = mm.label(); - meshNames.push_back(shortName); - if (mm.id() == (unsigned int) parameter->value().getInt()) { - currentmeshindex = i; - } - ++i; - } - - init(p, currentmeshindex, meshNames); -} - -void MeshWidget::collectWidgetValue() -{ - auto it = md->meshBegin(); - std::advance(it, enumCombo->currentIndex()); - parameter->setValue(IntValue((*it).id())); -} - -void MeshWidget::resetWidgetValue() -{ - int meshindex = -1; - unsigned int i = 0; - for (const MeshModel& mm : md->meshIterator()) { - if (mm.id() == (unsigned int) parameter->value().getInt()) { - meshindex = i; - } - ++i; - } - enumCombo->setCurrentIndex(meshindex); -} - -void MeshWidget::setWidgetValue(const Value& nv) -{ - int meshindex = -1; - unsigned int i = 0; - for (const MeshModel& mm : md->meshIterator()) { - if (mm.id() == (unsigned int) nv.getInt()) { - meshindex = i; - } - ++i; - } - enumCombo->setCurrentIndex(meshindex); -} - -/******************************************/ -// IOFileWidget Implementation -/******************************************/ - -IOFileWidget::IOFileWidget(QWidget* p, const RichParameter& rpar, const RichParameter& rdef) : - RichParameterWidget(p, rpar, rdef) -{ - filename = new QLineEdit(this); - filename->setText(tr("")); - browse = new QPushButton(this); - browse->setText("..."); - hlay = new QHBoxLayout(); - hlay->addWidget(filename, 2); - hlay->addWidget(browse); - widgets.push_back(filename); - widgets.push_back(browse); - - connect(browse, SIGNAL(clicked()), this, SLOT(selectFile())); - connect(this, SIGNAL(dialogParamChanged()), p, SIGNAL(parameterChanged())); -} - -IOFileWidget::~IOFileWidget() -{ - delete filename; - delete browse; -} - -void IOFileWidget::collectWidgetValue() -{ - parameter->setValue(StringValue(filename->text())); -} - -void IOFileWidget::resetWidgetValue() -{ - QString fle = parameter->value().getString(); - updateFileName(fle); -} - -void IOFileWidget::setWidgetValue(const Value& nv) -{ - QString fle = nv.getString(); - updateFileName(fle); -} - -void IOFileWidget::updateFileName(const StringValue& file) -{ - filename->setText(file.getString()); -} - -void IOFileWidget::addWidgetToGridLayout(QGridLayout* lay, const int r) -{ - if (lay != nullptr) { - lay->addLayout(hlay, r, 1, Qt::AlignTop); - } - RichParameterWidget::addWidgetToGridLayout(lay, r); -} - -/******************************************/ -// SaveFileWidget Implementation -/******************************************/ - -SaveFileWidget::SaveFileWidget(QWidget* p, const RichSaveFile& rpar, const RichSaveFile& rdef) : - IOFileWidget(p, rpar, rdef) -{ - filename->setText(parameter->value().getString()); - QString tmp = parameter->value().getString(); -} - -SaveFileWidget::~SaveFileWidget() -{ -} - -void SaveFileWidget::selectFile() -{ - RichSaveFile* dec = reinterpret_cast(parameter); - QString ext; - QString fl = - QFileDialog::getSaveFileName(this, tr("Save"), parameter->value().getString(), dec->ext); - collectWidgetValue(); - updateFileName(fl); - StringValue fileName(fl); - parameter->setValue(fileName); - emit dialogParamChanged(); -} - -/******************************************/ -// OpenFileWidget Implementation -/******************************************/ - -OpenFileWidget::OpenFileWidget(QWidget* p, const RichOpenFile& rdf, const RichOpenFile& rdef) : - IOFileWidget(p, rdf, rdef) -{ -} - -void OpenFileWidget::selectFile() -{ - RichOpenFile* dec = reinterpret_cast(parameter); - QString ext; - QString path = QDir::homePath(); - if (!parameter->value().getString().isEmpty()) - path = parameter->value().getString(); - QString fl = QFileDialog::getOpenFileName(this, tr("Open"), path, dec->exts.join(";;")); - collectWidgetValue(); - updateFileName(fl); - StringValue fileName(fl); - parameter->setValue(fileName); - emit dialogParamChanged(); -} - -OpenFileWidget::~OpenFileWidget() -{ -} diff --git a/src/meshlab/rich_parameter_gui/richparameterwidgets.h b/src/meshlab/rich_parameter_gui/richparameterwidgets.h deleted file mode 100644 index 50d930333..000000000 --- a/src/meshlab/rich_parameter_gui/richparameterwidgets.h +++ /dev/null @@ -1,480 +0,0 @@ -/***************************************************************************** - * MeshLab o o * - * Visual and Computer Graphics Library o o * - * _ O _ * - * Copyright(C) 2004-2021 \/)\/ * - * Visual Computing Lab /\/| * - * ISTI - Italian National Research Council | * - * \ * - * All rights reserved. * - * * - * This program 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. * - * * - * This program 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 (http://www.gnu.org/licenses/gpl.txt) * - * for more details. * - * * - ****************************************************************************/ - -#ifndef RICHPARAMETERLISTWIDGETS_H -#define RICHPARAMETERLISTWIDGETS_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "../gui_utils/clickable_label.h" - -class RichParameterWidget : public QWidget -{ - Q_OBJECT -public: - RichParameterWidget(QWidget* p, const RichParameter& rpar, const RichParameter& defaultValue); - - // this one is called by resetValue to reset the values inside the widgets. - virtual void resetWidgetValue() = 0; - // bring the values from the Qt widgets to the parameter (e.g. from the checkBox to the - // parameter). - virtual void collectWidgetValue() = 0; - virtual void setWidgetValue(const Value& nv) = 0; - virtual ~RichParameterWidget(); - - virtual void addWidgetToGridLayout(QGridLayout* lay, const int r) = 0; - // called when the user press the 'default' button to reset the parameter values to its default. - // It just set the parameter value and then it calls the specialized resetWidgetValue() to - // update also the widget. - void resetValue(); - void setValue(const Value& v); - void setHelpVisible(bool b); - void setVisible(bool b); - // update the parameter with the current widget values and return it. - const Value& widgetValue(); - const RichParameter& richParameter() const; - - QString parameterName() const; - -signals: - void parameterChanged(); - -protected: - ClickableLabel* descriptionLabel; - QLabel* helpLabel; - std::vector widgets; //will contain all the other widgets of this widget - - RichParameter* parameter; - RichParameter* defaultParameter; - - bool visible; - bool helpVisible; -}; - -class BoolWidget : public RichParameterWidget -{ -public: - BoolWidget(QWidget* p, const RichBool& rb, const RichBool& rdef); - ~BoolWidget(); - - void addWidgetToGridLayout(QGridLayout* lay, const int r); - void collectWidgetValue(); - void resetWidgetValue(); - void setWidgetValue(const Value& nv); - -private: - QCheckBox* cb; -}; - -class LineEditWidget : public RichParameterWidget -{ - Q_OBJECT -protected: - QLineEdit* lned; - QString lastVal; - -private slots: - void changeChecker(); -signals: - void lineEditChanged(); - -public: - LineEditWidget(QWidget* p, const RichParameter& rpar, const RichParameter& rdef); - ~LineEditWidget(); - void addWidgetToGridLayout(QGridLayout* lay, const int r); - virtual void collectWidgetValue() = 0; - virtual void resetWidgetValue() = 0; - virtual void setWidgetValue(const Value& nv) = 0; -}; - -class IntWidget : public LineEditWidget -{ -public: - IntWidget(QWidget* p, const RichInt& rpar, const RichInt& rdef); - ~IntWidget() {} - void collectWidgetValue(); - void resetWidgetValue(); - void setWidgetValue(const Value& nv); -}; - -class FloatWidget : public LineEditWidget -{ -public: - FloatWidget(QWidget* p, const RichFloat& rpar, const RichFloat& rdef); - ~FloatWidget() {} - void collectWidgetValue(); - void resetWidgetValue(); - void setWidgetValue(const Value& nv); -}; - -class StringWidget : public LineEditWidget -{ -public: - StringWidget(QWidget* p, const RichString& rpar, const RichString& rdef); - ~StringWidget() {} - void collectWidgetValue(); - void resetWidgetValue(); - void setWidgetValue(const Value& nv); -}; - -class ColorWidget : public RichParameterWidget -{ - Q_OBJECT -public: - ColorWidget(QWidget* p, const RichColor& newColor, const RichColor& rdef); - ~ColorWidget(); - - void addWidgetToGridLayout(QGridLayout* lay, const int r); - void collectWidgetValue(); - void resetWidgetValue(); - void setWidgetValue(const Value& nv); - void initWidgetValue(); - -private: - void updateColorInfo(const ColorValue& newColor); -private slots: - void pickColor(); -signals: - void dialogParamChanged(); - -protected: - QHBoxLayout* vlay; - -private: - QPushButton* colorButton; - QLabel* colorLabel; - QColor pickcol; -}; - -class AbsPercWidget : public RichParameterWidget -{ - Q_OBJECT -public: - AbsPercWidget(QWidget* p, const RichAbsPerc& rabs, const RichAbsPerc& rdef); - ~AbsPercWidget(); - - void addWidgetToGridLayout(QGridLayout* lay, const int r); - void collectWidgetValue(); - void resetWidgetValue(); - void setWidgetValue(const Value& nv); - -private: - void setValue(float val, float minV, float maxV); - -public slots: - - void on_absSB_valueChanged(double newv); - void on_percSB_valueChanged(double newv); -signals: - void dialogParamChanged(); - -protected: - QDoubleSpinBox* absSB; - QDoubleSpinBox* percSB; - float m_min; - float m_max; - QGridLayout* vlay; -}; - -class PositionWidget : public RichParameterWidget -{ - Q_OBJECT -public: - PositionWidget(QWidget* p, const RichPosition& rpf, const RichPosition& rdef, QWidget* gla); - ~PositionWidget(); - QString paramName; - vcg::Point3f getValue(); - - void addWidgetToGridLayout(QGridLayout* lay, const int r); - void collectWidgetValue(); - void resetWidgetValue(); - void setWidgetValue(const Value& nv); - -public slots: - void getPoint(); - void setValue(QString name, Point3m val); - void setShotValue(QString name, Shotm val); -signals: - void askViewPos(QString); - void askSurfacePos(QString); - void askCameraPos(QString); - void askTrackballPos(QString); - -protected: - QLineEdit* coordSB[3]; - QComboBox* getPoint3Combo; - QPushButton* getPoint3Button; - QHBoxLayout* vlay; -}; - -class DirectionWidget : public RichParameterWidget -{ - Q_OBJECT -public: - DirectionWidget(QWidget* p, const RichDirection& rpf, const RichDirection& rdef, QWidget* gla); - ~DirectionWidget(); - QString paramName; - vcg::Point3f getValue(); - - void addWidgetToGridLayout(QGridLayout* lay, const int r); - void collectWidgetValue(); - void resetWidgetValue(); - void setWidgetValue(const Value& nv); - -public slots: - void getPoint(); - void setValue(QString name, Point3m val); - void setShotValue(QString name, Shotm val); -signals: - void askViewDir(QString); - void askCameraDir(QString); - -protected: - QLineEdit* coordSB[3]; - QComboBox* getPoint3Combo; - QPushButton* getPoint3Button; - QHBoxLayout* vlay; -}; - -class Matrix44fWidget : public RichParameterWidget -{ - Q_OBJECT - -public: - Matrix44fWidget( - QWidget* p, - const RichMatrix44f& rpf, - const RichMatrix44f& rdef, - QWidget* gla_curr); - ~Matrix44fWidget(); - QString paramName; - Matrix44m getValue(); - - void addWidgetToGridLayout(QGridLayout* lay, const int r); - void collectWidgetValue(); - void resetWidgetValue(); - void setWidgetValue(const Value& nv); - -public slots: - void setValue(QString name, Matrix44m val); - void getMatrix(); - void pasteMatrix(); - void invalidateMatrix(const QString& s); -signals: - void askMeshMatrix(QString); - -protected: - QLineEdit* coordSB[16]; - QPushButton* getPoint3Button; - QGridLayout* lay44; - QVBoxLayout* vlay; - Matrix44m m; - bool valid; -}; - -class ShotfWidget : public RichParameterWidget -{ - Q_OBJECT - -public: - ShotfWidget(QWidget* p, const RichShotf& rpf, const RichShotf& rdef, QWidget* gla); - ~ShotfWidget(); - QString paramName; - Shotm getValue(); - - void addWidgetToGridLayout(QGridLayout* lay, const int r); - void collectWidgetValue(); - void resetWidgetValue(); - void setWidgetValue(const Value& nv); - -public slots: - void getShot(); - void setShotValue(QString name, Shotm val); -signals: - void askRasterShot(QString); - void askMeshShot(QString); - void askViewerShot(QString); - -protected: - Shotm curShot; - QLineEdit* shotLE; - QPushButton* getShotButton; - QComboBox* getShotCombo; - QHBoxLayout* hlay; -}; - -class DynamicFloatWidget : public RichParameterWidget -{ - Q_OBJECT - -public: - DynamicFloatWidget(QWidget* p, const RichDynamicFloat& rdf, const RichDynamicFloat& rdef); - ~DynamicFloatWidget(); - - float getValue(); - void setValue(float val, float minV, float maxV); - - void addWidgetToGridLayout(QGridLayout* lay, const int r); - void collectWidgetValue(); - void resetWidgetValue(); - void setWidgetValue(const Value& nv); - -public slots: - void setValue(int newv); - void setValue(); - void setValue(float newValue); - -signals: - // void valueChanged(int mask); - void dialogParamChanged(); - -protected: - QLineEdit* valueLE; - QSlider* valueSlider; - float minVal; - float maxVal; - QHBoxLayout* hlay; - -private: - float intToFloat(int val); - int floatToInt(float val); -}; - -class ComboWidget : public RichParameterWidget -{ - Q_OBJECT -protected: - QComboBox* enumCombo; - -public: - ComboWidget(QWidget* p, const RichParameter& rpar, const RichParameter& rdef); - ~ComboWidget(); - void init(QWidget* p, int newEnum, QStringList values); - void addWidgetToGridLayout(QGridLayout* lay, const int r); - virtual void collectWidgetValue() = 0; - virtual void resetWidgetValue() = 0; - virtual void setWidgetValue(const Value& nv) = 0; - - int getIndex(); - void setIndex(int newEnum); - -signals: - void dialogParamChanged(); -}; - -class EnumWidget : public ComboWidget -{ - Q_OBJECT - -public: - EnumWidget(QWidget* p, const RichEnum& rpar, const RichEnum& rdef); - ~EnumWidget() {}; - - void collectWidgetValue(); - void resetWidgetValue(); - void setWidgetValue(const Value& nv); - - // returns the number of items in the list - int getSize(); -}; - -class MeshWidget : public ComboWidget -{ -private: - const MeshDocument* md; - -public: - MeshWidget(QWidget* p, const RichMesh& defaultMesh, const RichMesh& rdef); - ~MeshWidget() {}; - - void collectWidgetValue(); - void resetWidgetValue(); - void setWidgetValue(const Value& nv); -}; - -class IOFileWidget : public RichParameterWidget -{ - Q_OBJECT - -protected: - IOFileWidget(QWidget* p, const RichParameter& rpar, const RichParameter& rdef); - ~IOFileWidget(); - - void updateFileName(const StringValue& file); - -public: - void addWidgetToGridLayout(QGridLayout* lay, const int r); - void collectWidgetValue(); - void resetWidgetValue(); - void setWidgetValue(const Value& nv); - -protected slots: - virtual void selectFile() = 0; - -signals: - void dialogParamChanged(); - -protected: - QLineEdit* filename; - QPushButton* browse; - QHBoxLayout* hlay; -}; - -class SaveFileWidget : public IOFileWidget -{ - Q_OBJECT -public: - SaveFileWidget(QWidget* p, const RichSaveFile& rpar, const RichSaveFile& rdef); - ~SaveFileWidget(); - -protected slots: - void selectFile(); -}; - -class OpenFileWidget : public IOFileWidget -{ - Q_OBJECT -public: - OpenFileWidget(QWidget* p, const RichOpenFile& rdf, const RichOpenFile& rdef); - ~OpenFileWidget(); - - /*void collectWidgetValue(); - void resetWidgetValue(); - void setWidgetValue(const Value& nv);*/ - -protected slots: - void selectFile(); -}; - -#endif // RICHPARAMETERLISTWIDGETS_H diff --git a/src/meshlab/snapshotsetting.h b/src/meshlab/snapshotsetting.h index 9638ba896..a9ad8eb4f 100644 --- a/src/meshlab/snapshotsetting.h +++ b/src/meshlab/snapshotsetting.h @@ -33,6 +33,7 @@ public: int resolution; int background; bool snapAllLayers; + bool useLayerName; bool tiledSave; // if true all the tiles are saved as separated files and not joined. bool addToRasters; @@ -44,9 +45,10 @@ public: resolution=1; background=0; snapAllLayers=false; + useLayerName=false; tiledSave=false; addToRasters=false; }; }; -#endif \ No newline at end of file +#endif diff --git a/src/meshlab/ui/layerDialog.ui b/src/meshlab/ui/layerDialog.ui index 061fc8327..121b3000b 100644 --- a/src/meshlab/ui/layerDialog.ui +++ b/src/meshlab/ui/layerDialog.ui @@ -72,7 +72,6 @@ 9 - 75 false true @@ -90,7 +89,6 @@ 9 - 75 true @@ -107,7 +105,6 @@ 9 - 75 true @@ -124,7 +121,6 @@ 9 - 75 true @@ -143,7 +139,105 @@ - 40 + 1 + 20 + + + +
+ + + + + 9 + 75 + true + + + + Decrease animation speed + + + - + + + + + + + + 9 + 75 + true + + + + Animate one step backward + + + -1 + + + + + + + + 9 + 75 + true + + + + > + + + true + + + + + + + + 9 + 75 + true + + + + Animate one step forward + + + +1 + + + + + + + + 9 + 75 + true + + + + Increase animation speed + + + + + + + + + + + Qt::Horizontal + + + + 1 20 @@ -154,7 +248,6 @@ 9 - 75 true @@ -171,7 +264,6 @@ 9 - 75 true @@ -188,7 +280,6 @@ 9 - 75 true @@ -205,7 +296,6 @@ 9 - 75 true @@ -303,6 +393,46 @@ + + + + QFrame::NoFrame + + + QFrame::Plain + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Clean Log + + + + + + diff --git a/src/meshlabplugins/decorate_base/decorate_base.cpp b/src/meshlabplugins/decorate_base/decorate_base.cpp index 11faed1c5..c44764428 100644 --- a/src/meshlabplugins/decorate_base/decorate_base.cpp +++ b/src/meshlabplugins/decorate_base/decorate_base.cpp @@ -635,9 +635,27 @@ bool DecorateBasePlugin::startDecorate(const QAction * action, MeshModel &m, con vector *CVp = &cvH(); CVp->clear(); float NormalLen=rm->getFloat(CurvatureLength()); + bool curvScale =rm->getBool(CurvatureScaling()); float LineLen = m.cm.bbox.Diag()*NormalLen; + float scale1,scale2; if (rm->getBool(this->ShowPerVertexCurvature()) && m.hasDataMask(MeshModel::MM_VERTCURVDIR)) { + if(curvScale) // get range of curvature values + { + auto minmaxPD = tri::Stat::ComputePerVertexCurvatureDirMinMax(m.cm); + scale1=minmaxPD.first.second; + scale2=minmaxPD.second.second; + for(CMeshO::VertexIterator vi=m.cm.vert.begin();vi!=m.cm.vert.end();++vi) + if(!(*vi).IsD()) + { + CVp->push_back(make_pair((*vi).P(), Color4b::Green)); + CVp->push_back(make_pair((*vi).P() +Point3m::Construct((*vi).PD1()*scale1*LineLen*0.25), Color4b::Green)); + CVp->push_back(make_pair((*vi).P(), Color4b::Red)); + CVp->push_back(make_pair((*vi).P()+Point3m::Construct((*vi).PD2()*scale2*LineLen*0.25), Color4b::Red)); + } + } + else + { for(CMeshO::VertexIterator vi=m.cm.vert.begin();vi!=m.cm.vert.end();++vi) if(!(*vi).IsD()) { @@ -650,6 +668,7 @@ bool DecorateBasePlugin::startDecorate(const QAction * action, MeshModel &m, con CVp->push_back(make_pair((*vi).P()+Point3m::Construct((*vi).PD2()/Norm((*vi).PD2())*LineLen*0.25), Color4b::Red)); } + } } if (rm->getBool(this->ShowPerFaceCurvature()) && m.hasDataMask(MeshModel::MM_FACECURVDIR)) { @@ -819,8 +838,8 @@ void DecorateBasePlugin::DisplayCamera(QString who, const Shotm &ls, int cameraS } const char *typeBuf; - if(ls.Intrinsics.cameraType == Camera::PERSPECTIVE) typeBuf="Persp"; - if(ls.Intrinsics.cameraType == Camera::ORTHO) typeBuf="Ortho"; + if(ls.Intrinsics.cameraType == Camera::PERSPECTIVE) typeBuf="Persp"; + if(ls.Intrinsics.cameraType == Camera::ORTHO) typeBuf="Ortho"; Point3m vp = ls.GetViewPoint(); Point3m ax0 = ls.Axis(0); @@ -869,7 +888,7 @@ void DecorateBasePlugin::DrawCamera(const MeshModel* m, const Shotm &ls, vcg::Co glDepthFunc(GL_ALWAYS); glDisable(GL_LIGHTING); - if (ls.Intrinsics.cameraType == Camera::PERSPECTIVE) + if (ls.Intrinsics.cameraType == Camera::PERSPECTIVE) { // draw scale float drawscale = 1.0; @@ -1154,7 +1173,8 @@ void DecorateBasePlugin::initGlobalParameterList(const QAction* action, RichPara case DP_SHOW_CURVATURE : { - parset.addParam(RichFloat(CurvatureLength(),0.05f,"Vector Length","The length of the normal expressed as a percentage of the bbox of the mesh")); + parset.addParam(RichFloat(CurvatureLength(),0.05f,"Vector Length","The max length of the curvature vectors expressed as a percentage of the bbox of the mesh")); + parset.addParam(RichBool(CurvatureScaling(),false,"Vector Scaling","The length of the curvature vectors is proportional to the curvature along that direction.")); parset.addParam(RichBool(ShowPerVertexCurvature(),true,"Per Vertex","")); parset.addParam(RichBool(ShowPerFaceCurvature(),true,"Per Face","")); } break; diff --git a/src/meshlabplugins/decorate_base/decorate_base.h b/src/meshlabplugins/decorate_base/decorate_base.h index 1e7d366d8..9f1be42fa 100644 --- a/src/meshlabplugins/decorate_base/decorate_base.h +++ b/src/meshlabplugins/decorate_base/decorate_base.h @@ -136,6 +136,7 @@ public: inline QString ShowPerVertexCurvature() const { return "MeshLab::Decoration::ShowPerVertexCurvature" ; } inline QString ShowPerFaceCurvature() const { return "MeshLab::Decoration::ShowPerFaceCurvature" ; } inline QString CurvatureLength() const { return "MeshLab::Decoration::CurvatureLength" ; } + inline QString CurvatureScaling() const { return "MeshLab::Decoration::CurvatureScaling" ; } inline QString TextureStyleParam() const { return "MeshLab::Decoration::TextureStyle" ; } inline QString TextureFaceColorParam() const { return "MeshLab::Decoration::TextureFaceColor" ; } diff --git a/src/meshlabplugins/edit_align/CMakeLists.txt b/src/meshlabplugins/edit_align/CMakeLists.txt index 237163c11..7eda7ec54 100644 --- a/src/meshlabplugins/edit_align/CMakeLists.txt +++ b/src/meshlabplugins/edit_align/CMakeLists.txt @@ -7,16 +7,11 @@ if(TARGET external-newuoa) set(SOURCES align/align_parameter.cpp - alignDialog.cpp AlignPairDialog.cpp AlignPairWidget.cpp edit_align_factory.cpp edit_align.cpp - ../../meshlab/gui_utils/clickable_label.cpp - ../../meshlab/rich_parameter_gui/richparameterwidgets.cpp - ../../meshlab/rich_parameter_gui/richparameterlistframe.cpp - ../../meshlab/rich_parameter_gui/richparameterlistdialog.cpp ${VCGDIR}/wrap/gui/trackball.cpp ${VCGDIR}/wrap/gui/trackmode.cpp ${VCGDIR}/wrap/ply/plylib.cpp) @@ -29,9 +24,6 @@ if(TARGET external-newuoa) AlignPairWidget.h edit_align_factory.h edit_align.h - ../../meshlab/rich_parameter_gui/richparameterwidgets.h - ../../meshlab/rich_parameter_gui/richparameterlistframe.h - ../../meshlab/rich_parameter_gui/richparameterlistdialog.h ${VCGDIR}/wrap/gui/trackball.h ${VCGDIR}/wrap/gui/trackmode.h ${VCGDIR}/wrap/gl/trimesh.h) @@ -42,7 +34,7 @@ if(TARGET external-newuoa) add_meshlab_plugin(edit_align ${SOURCES} ${HEADERS} ${RESOURCES} ${UI}) - target_link_libraries(edit_align PRIVATE external-newuoa OpenGL::GLU) + target_link_libraries(edit_align PRIVATE meshlab-common-gui external-newuoa OpenGL::GLU) if(OpenMP_CXX_FOUND) target_link_libraries(edit_align PRIVATE OpenMP::OpenMP_CXX) endif() diff --git a/src/meshlabplugins/edit_align/edit_align.cpp b/src/meshlabplugins/edit_align/edit_align.cpp index 9d190e767..53fc038e2 100644 --- a/src/meshlabplugins/edit_align/edit_align.cpp +++ b/src/meshlabplugins/edit_align/edit_align.cpp @@ -27,8 +27,8 @@ $Log: meshedit.cpp,v $ #include "edit_align.h" #include +#include #include -#include #include #include "AlignPairWidget.h" #include "AlignPairDialog.h" diff --git a/src/meshlabplugins/edit_pickpoints/CMakeLists.txt b/src/meshlabplugins/edit_pickpoints/CMakeLists.txt index d7770e0e4..792404e3a 100644 --- a/src/meshlabplugins/edit_pickpoints/CMakeLists.txt +++ b/src/meshlabplugins/edit_pickpoints/CMakeLists.txt @@ -7,11 +7,7 @@ set(SOURCES editpickpoints.cpp pickPointsTemplate.cpp pickedPoints.cpp - pickpointsDialog.cpp - ../../meshlab/gui_utils/clickable_label.cpp - ../../meshlab/rich_parameter_gui/richparameterwidgets.cpp - ../../meshlab/rich_parameter_gui/richparameterlistframe.cpp - ../../meshlab/rich_parameter_gui/richparameterlistdialog.cpp) + pickpointsDialog.cpp) set(HEADERS edit_pickpoints_factory.h @@ -26,4 +22,4 @@ set(UI pickpointsDialog.ui) add_meshlab_plugin(edit_pickpoints ${SOURCES} ${HEADERS} ${RESOURCES} ${UI}) -target_link_libraries(edit_pickpoints PRIVATE OpenGL::GLU) +target_link_libraries(edit_pickpoints PRIVATE meshlab-common-gui OpenGL::GLU) diff --git a/src/meshlabplugins/edit_pickpoints/pickpointsDialog.cpp b/src/meshlabplugins/edit_pickpoints/pickpointsDialog.cpp index bb721a7bb..6eed5e815 100644 --- a/src/meshlabplugins/edit_pickpoints/pickpointsDialog.cpp +++ b/src/meshlabplugins/edit_pickpoints/pickpointsDialog.cpp @@ -30,8 +30,8 @@ #include #include -#include -#include +#include +#include #include "editpickpoints.h" #include "pickpointsDialog.h" diff --git a/src/meshlabplugins/edit_point/edit_point.cpp b/src/meshlabplugins/edit_point/edit_point.cpp index 72d0b7843..79578604e 100644 --- a/src/meshlabplugins/edit_point/edit_point.cpp +++ b/src/meshlabplugins/edit_point/edit_point.cpp @@ -51,11 +51,19 @@ const QString EditPointPlugin::info() { void EditPointPlugin::decorate(MeshModel &m, GLArea * gla, QPainter* /*p*/) { - this->realTimeLog("Point Selection",m.shortName(), - "" - "" - "" - "
Hop Thr:%8.3f (Wheel to change it)
Radius: %8.3f (Drag or Alt+Wheel to change it)
",this->maxHop,this->dist); + const char *methodName = (editType==SELECT_FITTING_PLANE_MODE)?"Fitting Plane":"Point Cluster Selection"; + char keyInstrutionBuf[1024]=""; + if(editType==SELECT_FITTING_PLANE_MODE) + snprintf(keyInstrutionBuf,1024, + " PlaneDist: %9.4f (C / D to decrease/increase)" + " Radius Perc: %9.4f (S / X to decrease/increase)", + this->planeDist); + this->realTimeLog("Point Selection",m.shortName(), "%s" + "" + "" + "" + "%s" + "
Hop Thr:%9.4f (Wheel to change it)
Radius: %9.4f (Drag or Alt+Wheel to change it)
",methodName,this->maxHop,this->dist,keyInstrutionBuf); /* When the user first click we have to find the point under the mouse pointer. At the same time we need to compute the Dijkstra algorithm over the knn-graph in order diff --git a/src/meshlabplugins/filter_ao/filter_ao.cpp b/src/meshlabplugins/filter_ao/filter_ao.cpp index 4fc51bcaa..3f5006f15 100644 --- a/src/meshlabplugins/filter_ao/filter_ao.cpp +++ b/src/meshlabplugins/filter_ao/filter_ao.cpp @@ -83,7 +83,7 @@ QString AmbientOcclusionPlugin::filterName(ActionIDType filterId) const QString AmbientOcclusionPlugin::pythonFilterName(ActionIDType f) const { switch (f) { - case FP_AMBIENT_OCCLUSION: return QString("compute_scalar_ambient_occlusion"); + case FP_AMBIENT_OCCLUSION: return QString("compute_scalar_ambient_occlusion_gpu"); default: assert(0); return QString(); } } diff --git a/src/meshlabplugins/filter_camera/filter_camera.cpp b/src/meshlabplugins/filter_camera/filter_camera.cpp index 76d2d0da4..65f604fc8 100644 --- a/src/meshlabplugins/filter_camera/filter_camera.cpp +++ b/src/meshlabplugins/filter_camera/filter_camera.cpp @@ -172,7 +172,7 @@ RichParameterList FilterCameraPlugin::initParameterList(const QAction *action, c behaviour.push_back("The matrix is the transformation to apply to the extrinsics"); behaviour.push_back("The matrix represent the new extrinsics"); - parlst.addParam(RichMatrix44f("TransformMatrix",Matrix44m::Identity(),"")); + parlst.addParam(RichMatrix44("TransformMatrix",Matrix44m::Identity(),"")); parlst.addParam(RichEnum("camera", 0, shotType, tr("Camera type"), tr("Choose the camera to scale"))); parlst.addParam(RichEnum("behaviour", 0, behaviour, tr("Matrix semantic"), tr("What the matrix is used for"))); parlst.addParam(RichBool ("toallRaster", false, "Apply to all active Raster layers", "Apply the same scaling to all the active Raster layers: it is taken into account only if 'Raster Camera' is selected")); @@ -180,11 +180,11 @@ RichParameterList FilterCameraPlugin::initParameterList(const QAction *action, c } break; case FP_SET_RASTER_CAMERA : - parlst.addParam(RichShotf ("Shot", defShot, "New shot", "This filter allows one to set a shot for the current raster.")); + parlst.addParam(RichShot ("Shot", defShot, "New shot", "This filter allows one to set a shot for the current raster.")); break; case FP_SET_MESH_CAMERA : - parlst.addParam(RichShotf ("Shot", defShot, "New shot", "This filter allows one to set a shot for the current mesh.")); + parlst.addParam(RichShot ("Shot", defShot, "New shot", "This filter allows one to set a shot for the current mesh.")); break; case FP_QUALITY_FROM_CAMERA : parlst.addParam(RichBool ("Depth", true, "Depth", "Use depth as a factor.")); diff --git a/src/meshlabplugins/filter_clean/cleanfilter.cpp b/src/meshlabplugins/filter_clean/cleanfilter.cpp index 7e081cf9a..e30574dfe 100644 --- a/src/meshlabplugins/filter_clean/cleanfilter.cpp +++ b/src/meshlabplugins/filter_clean/cleanfilter.cpp @@ -268,7 +268,7 @@ RichParameterList CleanFilter::initParameterList(const QAction* action, const Me pair qualityRange; switch (ID(action)) { case FP_BALL_PIVOTING: - parlst.addParam(RichAbsPerc( + parlst.addParam(RichPercentage( "BallRadius", 0.0f, 0.0f, @@ -297,7 +297,7 @@ RichParameterList CleanFilter::initParameterList(const QAction* action, const Me "Useful if you run the algorithm multiple times with an increasing ball radius.")); break; case FP_REMOVE_ISOLATED_DIAMETER: - parlst.addParam(RichAbsPerc( + parlst.addParam(RichPercentage( "MinComponentDiag", md.mm()->cm.bbox.Diag() / 10.0f, 0.0f, @@ -326,7 +326,7 @@ RichParameterList CleanFilter::initParameterList(const QAction* action, const Me break; case FP_REMOVE_WRT_Q: qualityRange = tri::Stat::ComputePerVertexQualityMinMax(md.mm()->cm); - parlst.addParam(RichAbsPerc( + parlst.addParam(RichPercentage( "MaxQualityThr", (float) 1.0, qualityRange.first, @@ -334,7 +334,7 @@ RichParameterList CleanFilter::initParameterList(const QAction* action, const Me "Delete all vertices with quality under:")); break; case FP_MERGE_CLOSE_VERTEX: - parlst.addParam(RichAbsPerc( + parlst.addParam(RichPercentage( "Threshold", md.mm()->cm.bbox.Diag() / 10000.0f, 0.0f, diff --git a/src/meshlabplugins/filter_colorproc/filter_colorproc.cpp b/src/meshlabplugins/filter_colorproc/filter_colorproc.cpp index d7a443f52..4dbf6e8cb 100644 --- a/src/meshlabplugins/filter_colorproc/filter_colorproc.cpp +++ b/src/meshlabplugins/filter_colorproc/filter_colorproc.cpp @@ -22,6 +22,7 @@ ****************************************************************************/ #include +#include #include "filter_colorproc.h" #include @@ -87,7 +88,7 @@ FilterColorProc::~FilterColorProc() QString FilterColorProc::pluginName() const { - return "FilterColorProc"; + return "FilterColorProc"; } QString FilterColorProc::pythonFilterName(ActionIDType f) const @@ -229,6 +230,8 @@ int FilterColorProc::getRequirements(const QAction *action) RichParameterList FilterColorProc::initParameterList(const QAction *a, const MeshDocument& md) { + QStringList colorMaps = (QStringList() << "RGB" << "Viridis" << "Plasma" << "Cividis" << "Turbo" << "RdPu"); + RichParameterList par; switch(ID(a)) { @@ -399,6 +402,9 @@ RichParameterList FilterColorProc::initParameterList(const QAction *a, const Mes par.addParam(RichFloat("maxVal", minmax.second, "Max", "The value that will be mapped with the upper end of the scale (blue)")); par.addParam(RichDynamicFloat("perc", 0, 0, 100, "Percentile Crop [0..100]", "If not zero this value will be used for a percentile cropping of the quality values.
If this parameter is set to a value P then the two values V_min,V_max for which P% of the vertices have a quality lower or greater than V_min,V_max are used as min/max values for clamping.

The automated percentile cropping is very useful for automatically discarding outliers.")); par.addParam(RichBool("zeroSym", false, "Zero Symmetric", "If true the min max range will be enlarged to be symmetric (so that green is always Zero)")); + par.addParam(RichEnum("colorMap", 0, colorMaps, "Color Map", + "The color map to use. RGB is the VCGLib default, other colormaps are sampled from Matplotlib " + "https://matplotlib.org")); break; } case CP_MAP_FQUALITY_INTO_COLOR: @@ -409,6 +415,9 @@ RichParameterList FilterColorProc::initParameterList(const QAction *a, const Mes par.addParam(RichFloat("maxVal", minmax.second, "Max", "The value that will be mapped with the upper end of the scale (blue)")); par.addParam(RichDynamicFloat("perc", 0, 0, 100, "Percentile Crop [0..100]", "If not zero this value will be used for a percentile cropping of the quality values.
If this parameter is set to a value P then the two values V_min,V_max for which P% of the faces have a quality lower or greater than V_min,V_max are used as min/max values for clamping.

The automated percentile cropping is very useful for automatically discarding outliers.")); par.addParam(RichBool("zeroSym", false, "Zero Symmetric", "If true the min max range will be enlarged to be symmetric (so that green is always Zero)")); + par.addParam(RichEnum("colorMap", 0, colorMaps, "Color Map", + "The color map to use. RGB is the VCGLib default, other colormaps are sampled from Matplotlib " + "https://matplotlib.org")); break; } case CP_FACE_TO_VERTEX_QUALITY: @@ -629,13 +638,15 @@ std::map FilterColorProc::applyFilter(const QAction *filt PercHi = max(math::Abs(PercLo), PercHi); } + ColorMap cmap = vcg::ColorMapEnums[par.getEnum("colorMap")]; + if (usePerc) { - tri::UpdateColor::PerVertexQualityRamp(m->cm, PercLo, PercHi); + tri::UpdateColor::PerVertexQualityRamp(m->cm, PercLo, PercHi, cmap); log("Quality Range: %f %f; Used (%f %f) percentile (%f %f) ", H.MinV(), H.MaxV(), PercLo, PercHi, par.getDynamicFloat("perc"), 100 - par.getDynamicFloat("perc")); } else { - tri::UpdateColor::PerVertexQualityRamp(m->cm, RangeMin, RangeMax); + tri::UpdateColor::PerVertexQualityRamp(m->cm, RangeMin, RangeMax, cmap); log("Quality Range: %f %f; Used (%f %f)", H.MinV(), H.MaxV(), RangeMin, RangeMax); } break; @@ -695,13 +706,15 @@ std::map FilterColorProc::applyFilter(const QAction *filt PercHi = max(math::Abs(PercLo), PercHi); } + ColorMap cmap = vcg::ColorMapEnums[par.getEnum("colorMap")]; + if (usePerc){ - tri::UpdateColor::PerFaceQualityRamp(m->cm, PercLo, PercHi); + tri::UpdateColor::PerFaceQualityRamp(m->cm, PercLo, PercHi, false, cmap); log("Quality Range: %f %f; Used (%f %f) percentile (%f %f) ", H.MinV(), H.MaxV(), PercLo, PercHi, perc, 100 - perc); } else { - tri::UpdateColor::PerFaceQualityRamp(m->cm, RangeMin, RangeMax); + tri::UpdateColor::PerFaceQualityRamp(m->cm, RangeMin, RangeMax, false, cmap); log("Quality Range: %f %f; Used (%f %f)", H.MinV(), H.MaxV(), RangeMin, RangeMax); } break; @@ -1071,7 +1084,7 @@ int FilterColorProc::getPreConditions(const QAction* filter ) const case CP_COLOURISATION: case CP_SCATTER_PER_MESH: case CP_PERLIN_COLOR: - case CP_COLOR_NOISE: + case CP_COLOR_NOISE: case CP_MESH_TO_FACE: return MeshModel::MM_NONE; case CP_THRESHOLDING: case CP_CONTR_BRIGHT: @@ -1079,7 +1092,7 @@ int FilterColorProc::getPreConditions(const QAction* filter ) const case CP_EQUALIZE: case CP_DESATURATION: case CP_WHITE_BAL: - case CP_LEVELS: + case CP_LEVELS: case CP_VERTEX_SMOOTH: case CP_VERTEX_TO_FACE: return MeshModel::MM_VERTCOLOR; case CP_TRIANGLE_QUALITY: @@ -1103,8 +1116,8 @@ int FilterColorProc::getPreConditions(const QAction* filter ) const FilterPlugin::FilterArity FilterColorProc::filterArity(const QAction* act ) const { - switch(ID(act)) - { + switch(ID(act)) + { case CP_FILLING: case CP_COLOURISATION: case CP_PERLIN_COLOR: @@ -1135,7 +1148,7 @@ FilterPlugin::FilterArity FilterColorProc::filterArity(const QAction* act ) cons case CP_SCATTER_PER_MESH: return FilterPlugin::VARIABLE; default: assert(0); - } + } return FilterPlugin::SINGLE_MESH; } diff --git a/src/meshlabplugins/filter_cubization/CMakeLists.txt b/src/meshlabplugins/filter_cubization/CMakeLists.txt new file mode 100644 index 000000000..a8fef1247 --- /dev/null +++ b/src/meshlabplugins/filter_cubization/CMakeLists.txt @@ -0,0 +1,34 @@ +# Copyright 2019-2020, Collabora, Ltd. +# SPDX-License-Identifier: BSL-1.0 + +if (TARGET external-libigl AND TARGET Threads::Threads) + set(SOURCES + filter_cubization.cpp + CubicStylizationFiles/src/cube_style_precomputation.cpp + CubicStylizationFiles/src/cube_style_single_iteration.cpp + CubicStylizationFiles/src/fit_rotations_l1.cpp + CubicStylizationFiles/src/normalize_unitbox.cpp + CubicStylizationFiles/src/orthogonal_procrustes.cpp + CubicStylizationFiles/src/shrinkage.cpp) + + set(HEADERS + filter_cubization.h + curvdata.h + curvedgeflip.h + CubicStylizationFiles/conversionMeshes.h + CubicStylizationFiles/cubic_stylizing.h + CubicStylizationFiles/src/cube_style_data.h + CubicStylizationFiles/src/cube_style_precomputation.h + CubicStylizationFiles/src/cube_style_single_iteration.h + CubicStylizationFiles/src/fit_rotations_l1.h + CubicStylizationFiles/src/normalize_unitbox.h + CubicStylizationFiles/src/orthogonal_procrustes.h + CubicStylizationFiles/src/shrinkage.h) + + add_meshlab_plugin(filter_cubization ${SOURCES} ${HEADERS}) + target_link_libraries(filter_cubization PRIVATE external-libigl Threads::Threads) + +else() + message( + STATUS "Skipping filter_cubization - don't know about libigl or Threads::Threads on this system.") +endif() diff --git a/src/meshlabplugins/filter_cubization/CubicStylizationFiles/README.md b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/README.md new file mode 100644 index 000000000..8a8694e26 --- /dev/null +++ b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/README.md @@ -0,0 +1,18 @@ +# Cubic Stylization filter + +Cubic stylization is a 3D stylization tool. Unlike image stylization (2D to 2D) and non-photorealistic rendering (3D to 2D), cubic stylization is a 3D to 3D stylization algorithm which takes a manifold triangle mesh as the input and outputs a cubified triangle mesh. + +This is a MeshLab filter based on "[Cubic Stylization](https://www.dgp.toronto.edu/projects/cubic-stylization/)" by [Hsueh-Ti Derek Liu](https://www.dgp.toronto.edu/~hsuehtil/) and [Alec Jacobson](https://www.cs.toronto.edu/~jacobson/). + +The folder `/src` contains the original C++ implementation of Cubic stylization performed by [Hsueh-Ti Derek Liu](https://www.dgp.toronto.edu/~hsuehtil/) and [Alec Jacobson](https://www.cs.toronto.edu/~jacobson/). +Their code is licensed under [MPL2](https://www.mozilla.org/en-US/MPL/2.0/). + +## Bibtex +``` +@article{Liu:CubicStyle:2019, + title = {Cubic Stylization}, + author = {Hsueh-Ti Derek Liu and Alec Jacobson}, + year = {2019}, + journal = {ACM Transactions on Graphics}, +} +``` diff --git a/src/meshlabplugins/filter_cubization/CubicStylizationFiles/conversionMeshes.h b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/conversionMeshes.h new file mode 100644 index 000000000..eec4666f2 --- /dev/null +++ b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/conversionMeshes.h @@ -0,0 +1,48 @@ +#ifndef CONVERSIONMESHES_H +#define CONVERSIONMESHES_H + +#include +#include +#include + +namespace vcg{ +namespace tri{ + template + void Mesh2Matrix(MeshType& convertingMesh, Eigen::MatrixXd &output_vertexes, Eigen::MatrixXi &output_faces){ + + typedef typename MeshType::ScalarType ScalarType; + typedef typename Eigen::Matrix MatrixXm; + + MatrixXm temp_verts; + //convert mesh in matrix + vcg::tri::MeshToMatrix< MeshType >::GetTriMeshData( convertingMesh, temp_verts, output_faces); + output_vertexes = temp_verts.template cast(); + } + + template + void Matrix2Mesh(MeshType& convertedMesh, Eigen::MatrixXd vertexes, Eigen::MatrixXi faces){ + typedef typename MeshType::VertexPointer VertexPointer; + typedef typename MeshType::FaceIterator FaceIterator; + + //reconvert V and F matrixes in a mesh + convertedMesh.Clear(); + + Allocator::AddVertices(convertedMesh,vertexes.rows()); + Allocator::AddFaces(convertedMesh,faces.rows()); + std::vector ivp; + + int i; + for (i=0; i < vertexes.rows(); i++){ + for (int j = 0; j < 3; j++) + convertedMesh.vert[i].P()[j] = vertexes(i,j); + ivp.push_back(&convertedMesh.vert[i]); + } + + FaceIterator fi; + for (i=0,fi=convertedMesh.face.begin();fi!=convertedMesh.face.end();i++,fi++) + for (int j = 0; j < 3; j++) + (*fi).V(j) = ivp[faces(i, j)]; + } +}} + +#endif // CONVERSIONMESHES_H diff --git a/src/meshlabplugins/filter_cubization/CubicStylizationFiles/cubic_stylizing.h b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/cubic_stylizing.h new file mode 100644 index 000000000..feff6fbce --- /dev/null +++ b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/cubic_stylizing.h @@ -0,0 +1,53 @@ +#ifndef CUBIC_STYLIZING_H +#define CUBIC_STYLIZING_H + +#include +#include +#include +#include + +#include +#include + +#include + +#include + +namespace vcg{ +namespace tri{ + +template +class Cubization{ + public: + static void Init(MeshType& m, Eigen::MatrixXd& V, Eigen::MatrixXd& U, Eigen::MatrixXi& F, cube_style_data& data){ + + // check requirements + vcg::tri::VertexVectorHasPerVertexTexCoord( m.vert ); + vcg::tri::VertexVectorHasPerVertexFlags( m.vert ); + + Mesh2Matrix(m, V, F); + + //normalize_unitbox(V); + U = V; + + data.bc.resize(1,3); + data.bc << V.row(F(0,0)); + + data.b.resize(1); + data.b << F(0,0); + + // precomputation ARAP and initialize ADMM parameters + cube_style_precomputation(V,F,data); + } + + static double Stylize(Eigen::MatrixXd &V, Eigen::MatrixXd &U, Eigen::MatrixXi &F, cube_style_data& data, Eigen::VectorXd& energy_verts, double& energyCubic) + { + // apply cubic stylization + cube_style_single_iteration(V,U,data, energy_verts); + energyCubic = data.objVal; + + return data.reldV; + } +}; +}} +#endif // CUBIC_STYLIZING_H diff --git a/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/LICENSE.MPL2 b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/LICENSE.MPL2 new file mode 100644 index 000000000..f4bbcd200 --- /dev/null +++ b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/LICENSE.MPL2 @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. \ No newline at end of file diff --git a/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/cube_style_data.h b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/cube_style_data.h new file mode 100644 index 000000000..f60eacccf --- /dev/null +++ b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/cube_style_data.h @@ -0,0 +1,78 @@ +#ifndef CUBE_STYLE_DATA_H +#define CUBE_STYLE_DATA_H + +#include +#include +#include +#include + +struct cube_style_data +{ + // user should tune these + double lambda = 0.0; + double rhoInit = 1e-3; + double ABSTOL = 1e-6; + double RELTOL = 1e-3; + + // usually these don't need to tune + double mu = 10; + double tao = 2; + double maxIter_ADMM = 100; + double objVal = 0; + double reldV = std::numeric_limits::max(); + + std::vector objHis; + std::vector hEList; + std::vector dVList, UHis; + std::vector WVecList; + + Eigen::SparseMatrix K, L; + Eigen::MatrixXd N, VA, zAll, uAll; + Eigen::VectorXd rhoAll, objValVec; + + // bool useBc = false; + Eigen::MatrixXd bc; + Eigen::VectorXi b; + + igl::min_quad_with_fixed_data solver_data; + + // for plane constraints + Eigen::VectorXi bx, by, bz; + igl::min_quad_with_fixed_data solver_data_x, solver_data_y, solver_data_z; + double xPlane = 0.0; + double yPlane = 0.0; + double zPlane = 0.0; + // for plane constraints + + void reset() + { + // user should tune these + ABSTOL = 1e-5; + rhoInit = 1e-3; + RELTOL = 1e-3; + + // usually these don't need to tune + double mu = 10; + double tao = 2; + double maxIter_ADMM = 100; + double objVal = 0; + double reldV = std::numeric_limits::max(); + + objHis.clear(); + hEList.clear(); + dVList.clear(); + UHis.clear(); + WVecList.clear(); + K = Eigen::SparseMatrix(); + L = Eigen::SparseMatrix(); + N = Eigen::MatrixXd(); + VA = Eigen::MatrixXd(); + zAll =Eigen::MatrixXd(); + uAll = Eigen::MatrixXd(); + rhoAll = Eigen::VectorXd(); + objValVec = Eigen::VectorXd(); + + igl::min_quad_with_fixed_data solver_data; + } +}; +#endif // CUBE_STYLE_DATA_H diff --git a/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/cube_style_precomputation.cpp b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/cube_style_precomputation.cpp new file mode 100644 index 000000000..1e648ad84 --- /dev/null +++ b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/cube_style_precomputation.cpp @@ -0,0 +1,70 @@ +#include "cube_style_precomputation.h" + +void cube_style_precomputation( + const Eigen::MatrixXd & V, + const Eigen::MatrixXi & F, + cube_style_data & data) +{ + using namespace Eigen; + using namespace std; + + data.reset(); + + igl::per_vertex_normals(V,F, data.N); + + igl::cotmatrix(V,F,data.L); + + SparseMatrix M; + igl::massmatrix(V,F,igl::MASSMATRIX_TYPE_BARYCENTRIC,M); + data.VA = M.diagonal(); + + vector> adjFList, VI; + igl::vertex_triangle_adjacency(V.rows(),F,adjFList,VI); + + igl::arap_rhs(V,F,V.cols(),igl::ARAP_ENERGY_TYPE_SPOKES_AND_RIMS, data.K); + + data.hEList.resize(V.rows()); + data.WVecList.resize(V.rows()); + data.dVList.resize(V.rows()); + vector adjF; + for (int ii=0; ii(),false,data.solver_data); + + data.zAll.resize(3, V.rows()); data.zAll.setRandom(); + data.uAll.resize(3, V.rows()); data.uAll.setRandom(); + data.rhoAll.resize(V.rows()); data.rhoAll.setConstant(data.rhoInit); +} diff --git a/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/cube_style_precomputation.h b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/cube_style_precomputation.h new file mode 100644 index 000000000..f299f8d8d --- /dev/null +++ b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/cube_style_precomputation.h @@ -0,0 +1,24 @@ +#ifndef CUBE_STYLE_PRECOMPUTATION_H +#define CUBE_STYLE_PRECOMPUTATION_H + +#include +#include +#include +#include + +// include libigl functions +#include +#include +#include +#include +#include +#include +#include +#include + +#include +void cube_style_precomputation( + const Eigen::MatrixXd & V, + const Eigen::MatrixXi & F, + cube_style_data & data); +#endif diff --git a/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/cube_style_single_iteration.cpp b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/cube_style_single_iteration.cpp new file mode 100644 index 000000000..06bc6428a --- /dev/null +++ b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/cube_style_single_iteration.cpp @@ -0,0 +1,41 @@ +#include "cube_style_single_iteration.h" + +void cube_style_single_iteration( + const Eigen::MatrixXd & V, + Eigen::MatrixXd & U, + cube_style_data & data, + Eigen::VectorXd & energyVects) +{ + using namespace Eigen; + using namespace std; + + // local step + MatrixXd RAll(3,V.rows()*3); + { + fit_rotations_l1(V, U, RAll, data, energyVects); + } + + //R.setZero(); + //R = RAll; + + // global step + MatrixXd Upre = U; + { + VectorXd Rcol; + igl::columnize(RAll, V.rows(), 2, Rcol); + VectorXd Bcol = data.K * Rcol; + for(int dim=0; dim +#include +#include +#include + +// include libigl functions +#include +#include +#include + +// include cube flow functions +#include +#include + +void cube_style_single_iteration( + const Eigen::MatrixXd & V, + Eigen::MatrixXd & U, + cube_style_data & data, + Eigen::VectorXd & energyVects); +#endif // CUBE_STYLE_SINGLE_ITERATION_H diff --git a/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/fit_rotations_l1.cpp b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/fit_rotations_l1.cpp new file mode 100644 index 000000000..af71ad15f --- /dev/null +++ b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/fit_rotations_l1.cpp @@ -0,0 +1,100 @@ +#include "fit_rotations_l1.h" + +void fit_rotations_l1( + const Eigen::MatrixXd & V, + Eigen::MatrixXd & U, + Eigen::MatrixXd & RAll, + cube_style_data & data, + Eigen::VectorXd & energy_vects) +{ + using namespace Eigen; + using namespace std; + + data.objValVec.setZero(V.rows()); + igl::parallel_for( + V.rows(), + [&data, &RAll, &U](const int ii) + { + // warm start parameters + VectorXd z = data.zAll.col(ii); + VectorXd u = data.uAll.col(ii); + VectorXd n = data.N.row(ii).transpose(); + double rho = data.rhoAll(ii); + Matrix3d R; + + // get energy parameters + // Note: dVn = [dV n], dUn = [dU z-u] + MatrixXi hE = data.hEList[ii]; + MatrixXd dU(3,hE.rows()); + { + MatrixXd U_hE0, U_hE1; + igl::slice(U,hE.col(0),1,U_hE0); + igl::slice(U,hE.col(1),1,U_hE1); + dU = (U_hE1 - U_hE0).transpose(); + } + + // Note: + // S = [dV n] * [W 0; 0 rho] * [dU (z-u)]' + // = dV * W * dU' + n * rho * (z-u)' + // = Spre + n * rho * (z-u)' + MatrixXd dV = data.dVList[ii]; + VectorXd WVec = data.WVecList[ii]; + Matrix3d Spre = dV * WVec.asDiagonal() * dU.transpose(); + + // ADMM + for (int k=0; k data.mu * s_norm) + { + rho = data.tao * rho; + u = u / data.tao; + } + else if (s_norm > data.mu * r_norm) + { + rho = rho / data.tao; + u = u * data.tao; + } + + // stopping criteria + double nz = double(z.size()); + double eps_pri = sqrt(2.0*nz)*data.ABSTOL + data.RELTOL*max( (R*n).norm(),z.norm() ); + double eps_dual = sqrt(1.0*nz)*data.ABSTOL + data.RELTOL* ((rho*u).norm()); + if ( (r_norm +#include +#include +#include +#include +#include +#include +#include +#include + +void fit_rotations_l1( + const Eigen::MatrixXd & V, + Eigen::MatrixXd & U, + Eigen::MatrixXd & RAll, + cube_style_data & data, + Eigen::VectorXd & energy_vects); +#endif // FIT_ROTATIONS_L1_H diff --git a/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/normalize_unitbox.cpp b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/normalize_unitbox.cpp new file mode 100644 index 000000000..91c4d03c1 --- /dev/null +++ b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/normalize_unitbox.cpp @@ -0,0 +1,8 @@ +#include "normalize_unitbox.h" + +void normalize_unitbox( + Eigen::MatrixXd & V) +{ + V = V.rowwise() - V.colwise().minCoeff(); + V /= V.maxCoeff(); +} diff --git a/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/normalize_unitbox.h b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/normalize_unitbox.h new file mode 100644 index 000000000..97a619353 --- /dev/null +++ b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/normalize_unitbox.h @@ -0,0 +1,15 @@ +#ifndef NORMALIZE_UNITBOX_H +#define NORMALIZE_UNITBOX_H + +#include +#include + +// Inputs: +// V a matrix of vertex positions +// Outputs: +// V a matrix of vertex positions (in a unit box) +void normalize_unitbox( + Eigen::MatrixXd & V); + +#endif // NORMALIZE_UNITBOX_H + diff --git a/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/orthogonal_procrustes.cpp b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/orthogonal_procrustes.cpp new file mode 100644 index 000000000..bbe3fc846 --- /dev/null +++ b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/orthogonal_procrustes.cpp @@ -0,0 +1,34 @@ +#include "orthogonal_procrustes.h" + +void orthogonal_procrustes( + const Eigen::Matrix3d & S, + Eigen::Matrix3d & R) +{ + using namespace Eigen; + using namespace std; + + // using svd3x3 which has problems for double precision + // Matrix3d SU, SV; + // Matrix SS; + // igl::svd3x3(S, SU, SS, SV); + // R = SV * SU.transpose(); + // if (R.determinant() < 0) + // { + // SU.col(2) = -SU.col(2); + // R = SV * SU.transpose(); + // } + + // using Eigen svd + JacobiSVD svd; + svd.compute(S, Eigen::ComputeFullU | Eigen::ComputeFullV ); + Matrix3d SU = svd.matrixU(); + Matrix3d SV = svd.matrixV(); + R = SV * SU.transpose(); + if (R.determinant() < 0) + { + SU.col(2) = -SU.col(2); + R = SV * SU.transpose(); + } + + assert(R.determinant() > 0); +} diff --git a/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/orthogonal_procrustes.h b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/orthogonal_procrustes.h new file mode 100644 index 000000000..e81315abb --- /dev/null +++ b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/orthogonal_procrustes.h @@ -0,0 +1,12 @@ +#ifndef ORTHOGONAL_PROCRUSTES_H +#define ORTHOGONAL_PROCRUSTES_H + +#include +#include +#include +#include + +void orthogonal_procrustes( + const Eigen::Matrix3d & S, + Eigen::Matrix3d & R); +#endif // ORTHOGONAL_PROCRUSTES_H diff --git a/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/shrinkage.cpp b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/shrinkage.cpp new file mode 100644 index 000000000..5ab44bbeb --- /dev/null +++ b/src/meshlabplugins/filter_cubization/CubicStylizationFiles/src/shrinkage.cpp @@ -0,0 +1,32 @@ +#include "shrinkage.h" + +void shrinkage( + const Eigen::VectorXd & x, + const double & k, + Eigen::VectorXd & z) +{ + using namespace Eigen; + using namespace std; + + VectorXd tmp1 = x.array() - k; + VectorXd posMax = tmp1.array().max(0.0); + + VectorXd tmp2 = -x.array() - k; + VectorXd negMax = tmp2.array().max(0.0); + + // VectorXd posMax = x.array() - k; + // for (int ii=0; ii +#include + +void shrinkage( + const Eigen::VectorXd & x, + const double & k, + Eigen::VectorXd & z); +#endif // SHRINKAGE_H diff --git a/src/meshlabplugins/filter_cubization/curvdata.h b/src/meshlabplugins/filter_cubization/curvdata.h new file mode 100644 index 000000000..cb1d4a42f --- /dev/null +++ b/src/meshlabplugins/filter_cubization/curvdata.h @@ -0,0 +1,93 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +#ifndef __CURVDATA +#define __CURVDATA + +namespace vcg +{ +class CurvData +{ +public: + CurvData() + { + A = 0; // area + H = 0; // absolute mean curvature + K = 0; // gaussian curvature + } + + virtual ~CurvData() {} + + friend const CurvData operator+(const CurvData &lhs, const CurvData &rhs) + { + CurvData result; + result.A = lhs.A + rhs.A; + result.H = lhs.H + rhs.H; + result.K = lhs.K + rhs.K; + return result; + } + + friend CurvData &operator+=(CurvData &lhs, const CurvData &rhs) + { + lhs.A += rhs.A; + lhs.H += rhs.H; + lhs.K += rhs.K; + return lhs; + } + + float A; + float H; + float K; +}; + + +class NSMCEval +{ +public: + float operator() (const CurvData& c) + { + return (powf(c.H / 4.0, 2.0f) / c.A); + } +}; + +class MeanCEval +{ +public: + float operator() (const CurvData& c) + { + return (c.H / 4.0); + } +}; + +class AbsCEval +{ +public: + float operator() (const CurvData& c) + { + float k = 2 * M_PI - c.K; + if(k > 0) return 2.0 * (c.H / 4.0); + else return 2.0 * math::Sqrt(powf(c.H / 4.0, 2.0) - (c.A * k)); + } +}; + +} //end namespace vcg +#endif // __CURVDATA diff --git a/src/meshlabplugins/filter_cubization/curvedgeflip.h b/src/meshlabplugins/filter_cubization/curvedgeflip.h new file mode 100644 index 000000000..ebc988fb9 --- /dev/null +++ b/src/meshlabplugins/filter_cubization/curvedgeflip.h @@ -0,0 +1,339 @@ +/**************************************************************************** + * MeshLab o o * + * A versatile mesh processing toolbox o o * + * _ O _ * + * Copyright(C) 2005 \/)\/ * + * Visual Computing Lab /\/| * + * ISTI - Italian National Research Council | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef __CURVEDGEFLIP +#define __CURVEDGEFLIP + +#include +#include +#include +#include + +#include + +#include "curvdata.h" + +namespace vcg +{ +namespace tri +{ + +/* + * This flip happens only if decreases the curvature of the surface + * Edge flip optimization based on the paper + * "optimizing 3d triangulations using discrete curvature analysis" + * http://www2.in.tu-clausthal.de/~hormann/papers/Dyn.2001.OTU.pdf + */ +template +class CurvEdgeFlip : public TopoEdgeFlip +{ +protected: + typedef typename TRIMESH_TYPE::FaceType FaceType; + typedef typename TRIMESH_TYPE::FacePointer FacePointer; + typedef typename TRIMESH_TYPE::FaceIterator FaceIterator; + typedef typename TRIMESH_TYPE::VertexIterator VertexIterator; + typedef typename TRIMESH_TYPE::VertexType VertexType; + typedef typename TRIMESH_TYPE::ScalarType ScalarType; + typedef typename TRIMESH_TYPE::VertexPointer VertexPointer; + typedef typename TRIMESH_TYPE::CoordType CoordType; + typedef vcg::face::Pos PosType; + typedef vcg::face::VFIterator VFIteratorType; + typedef typename LocalOptimization::HeapElem HeapElem; + typedef typename LocalOptimization::HeapType HeapType; + typedef TriEdgeFlip Parent; + typedef typename vcg::Triangle3 TriangleType; + + typedef typename TRIMESH_TYPE::VertContainer VertContainer; + + // New curvature precomputed for the vertices of the faces + // adjacent to edge to be flipped + ScalarType _cv0, _cv1, _cv2, _cv3; + + + static CurvData FaceCurv(VertexPointer v0, + VertexPointer v1, + VertexPointer v2, + CoordType fNormal) + { + CurvData res; + + float ang0 = math::Abs(Angle(v1->P() - v0->P(), v2->P() - v0->P())); + float ang1 = math::Abs(Angle(v0->P() - v1->P(), v2->P() - v1->P())); + float ang2 = M_PI - ang0 - ang1; + + float s01 = SquaredDistance(v1->P(), v0->P()); + float s02 = SquaredDistance(v2->P(), v0->P()); + + // voronoi cell of vertex + if (ang0 >= M_PI/2) { + TriangleType triangle(v0->P(), v1->P(), v2->P()); + res.A += (0.5f * DoubleArea(triangle) - + (s01 * tan(ang1) + s02 * tan(ang2)) / 8.0 ); + } else if (ang1 >= M_PI/2) + res.A += (s01 * tan(ang0)) / 8.0; + else if (ang2 >= M_PI/2) + res.A += (s02 * tan(ang0) / 8.0); + else // non obctuse triangle + res.A += ((s02 / tan(ang1)) + (s01 / tan(ang2))) / 8.0; + + res.K += ang0; + + ang1 = math::Abs(Angle(fNormal, v1->N())); + ang2 = math::Abs(Angle(fNormal, v2->N())); + res.H += ( (math::Sqrt(s01) / 2.0) * ang1 + + (math::Sqrt(s02) / 2.0) * ang2 ); + + return res; + } + + /* Compute vertex curvature walking around a verte with VF adjacency + * f1, f2 --> this faces are to be ignored + * */ + static CurvData Curvature(VertexPointer v, FacePointer f1 = NULL, FacePointer f2 = NULL) + { + CurvData curv; + VFIteratorType vfi(v); + + while (!vfi.End()) { + if (vfi.F() != f1 && vfi.F() != f2 && !vfi.F()->IsD()) { + int i = vfi.I(); + curv += FaceCurv(vfi.F()->V0(i), + vfi.F()->V1(i), + vfi.F()->V2(i), + vfi.F()->N()); + } + ++vfi; + } + + return curv; + } + +public: + CurvEdgeFlip() {} + + CurvEdgeFlip(PosType pos, int mark,BaseParameterClass *pp) + { + this->_pos = pos; + this->_localMark = mark; + this->_priority = ComputePriority(pp); + } + + + CurvEdgeFlip(CurvEdgeFlip &par) + { + this->_pos = par.GetPos(); + this->_localMark = par.GetMark(); + this->_priority = par.Priority(); + } + + // temporary empty (flip is already done in constructor) + void Execute(TRIMESH_TYPE& m, BaseParameterClass *) + { + int i = this->_pos.E(); + FacePointer f1 = this->_pos.F(); + int j = f1->FFi(i); + FacePointer f2 = f1->FFp(i); + VertexPointer v0 = f1->V0(i), v1 = f1->V1(i), + v2 = f1->V2(i), v3 = f2->V2(j); + + // save precomputed curvature in vertex quality + v0->Q() = _cv0; + v1->Q() = _cv1; + v2->Q() = _cv2; + v3->Q() = _cv3; + + CoordType n1 = Normal(v0->P(), v3->P(), v2->P()); + CoordType n2 = Normal(v1->P(), v2->P(), v3->P()); + + // compute and update normals on vertices after flip + v0->N() = v0->N() - f1->N() - f2->N() + n1; + v1->N() = v1->N() - f1->N() - f2->N() + n2; + v2->N() = v2->N() - f1->N() + n1 + n2; + v3->N() = v3->N() - f2->N() + n1 + n2; + + // fix VF adjacency - detach + assert(f1->V1(i) == v1); + vcg::face::VFDetach(*f1, (i + 1) % 3); // detach v1 from f1 + assert(f2->V1(j) == v0); + vcg::face::VFDetach(*f2, (j + 1) % 3); // detach v0 from f2 + + // do the flip + vcg::face::FlipEdge(*this->_pos.F(), this->_pos.E()); + + // fix VF adjacency - append + assert(f2->V1(j) == v2); + vcg::face::VFAppend(f2, (j + 1) % 3); // attach v2 with f2 + assert(f1->V1(i) == v3); + vcg::face::VFAppend(f1, (i + 1) % 3); // attach v3 with f1 + + // update face normals after the flip + f1->N() = n1; + f2->N() = n2; + + // avoid texture coordinates swap after flip + if (tri::HasPerWedgeTexCoord(m)) { + f2->WT((j + 1) % 3) = f1->WT((i + 2) % 3); + f1->WT((i + 1) % 3) = f2->WT((j + 2) % 3); + } + } + + + virtual bool IsFeasible(BaseParameterClass *_pp) + { + PlanarEdgeFlipParameter *pp=(PlanarEdgeFlipParameter *)_pp; + // First the flip must be topologically correct. + if(!vcg::face::CheckFlipEdge(*this->_pos.F(), this->_pos.E())) + return false; + + // then the angle between the involved normals must be greater??? + if (math::ToDeg(Angle(this->_pos.FFlip()->cN(), this->_pos.F()->cN()) ) <= pp->CoplanarAngleThresholdDeg ) + return false; + + CoordType v0, v1, v2, v3; + int i = this->_pos.E(); + FacePointer f = this->_pos.F(); + v0 = f->P0(i); + v1 = f->P1(i); + v2 = f->P2(i); + v3 = f->FFp(i)->P2(f->FFi(i)); + + // Take the parallelogram formed by the adjacent faces of edge + // If a corner of the parallelogram on extreme of edge to flip is >= 180 + // the flip will produce two identical faces - avoid this + if( (Angle(v2 - v0, v1 - v0) + Angle(v3 - v0, v1 - v0) >= M_PI) || + (Angle(v2 - v1, v0 - v1) + Angle(v3 - v1, v0 - v1) >= M_PI)) + return false; + + // if any of two faces adj to edge in non writable, the flip is unfeasible + if (!this->_pos.F()->IsW() || !this->_pos.F()->FFp(i)->IsW()) + return false; + + return true; + } + + + ScalarType ComputePriority(BaseParameterClass *pp) + { + /* + 1 + /|\ + / | \ + 2 | 3 + \ | / + \|/ + 0 + */ + + if(!this->IsFeasible(pp)) + return std::numeric_limits::infinity(); + + VertexPointer v0, v1, v2, v3; + int i = this->_pos.E(); + + FacePointer f1 = this->_pos.F(); + v0 = f1->V0(i); + v1 = f1->V1(i); + v2 = f1->V2(i); + + FacePointer f2 = this->_pos.F()->FFp(i); + v3 = f2->V2(f1->FFi(i)); + + // save sum of curvatures of vertices + float cbefore = v0->Q() + v1->Q() + v2->Q() + v3->Q(); + + // saving current vertex normals + CoordType nv0orig = v0->N(); + CoordType nv1orig = v1->N(); + CoordType nv2orig = v2->N(); + CoordType nv3orig = v3->N(); + + CurvData cd0, cd1, cd2, cd3; + CoordType n1 = Normal(v0->P(), v3->P(), v2->P()); + CoordType n2 = Normal(v1->P(), v2->P(), v3->P()); + + // new vertex normal after the flip + // set this now to evaluate new curvatures + v0->N() = nv0orig - f1->N() - f2->N() + n1; + v1->N() = nv1orig - f1->N() - f2->N() + n2; + v2->N() = nv2orig - f1->N() + n1 + n2; + v3->N() = nv3orig - f2->N() + n1 + n2; + + cd0 = FaceCurv(v0, v3, v2, n1) + Curvature(v0, f1, f2); + cd1 = FaceCurv(v1, v2, v3, n2) + Curvature(v1, f1, f2); + cd2 = FaceCurv(v2, v0, v3, n1) + FaceCurv(v2, v3, v1, n2) + Curvature(v2, f1, f2); + cd3 = FaceCurv(v3, v2, v0, n1) + FaceCurv(v3, v1, v2, n2) + Curvature(v3, f1, f2); + + // restore original pervertex normals after computation + v0->N() = nv0orig; + v1->N() = nv1orig; + v2->N() = nv2orig; + v3->N() = nv3orig; + + CURVEVAL curveval; + + _cv0 = curveval(cd0); + _cv1 = curveval(cd1); + _cv2 = curveval(cd2); + _cv3 = curveval(cd3); + float cafter = _cv0 + _cv1 + _cv2 + _cv3; + + // The priority of an edge flip is **how much we lower the overall curvature**. + // If after the flip the sum of the curvature is decreased it is a good move; + // good flips have: cafter < cbefore + // Since the local optimization is designed to make the minimum cost move we put inside + // negative values (the more negative the better). + this->_priority = (cafter - cbefore); + //qDebug("computed curvature change, %f->%f (priority = %f)", cbefore,cafter,this->_priority); + return this->_priority; + } + + + static void Init(TRIMESH_TYPE &m, HeapType &heap, BaseParameterClass *pp) + { + CURVEVAL curveval; + heap.clear(); + + // comuputing edge flip priority require non normalized vertex normals AND non normalized face normals. + vcg::tri::UpdateNormal::PerVertexPerFace(m); + + VertexIterator vi; + for (vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if (!(*vi).IsD() && (*vi).IsW()) + (*vi).Q() = curveval(Curvature(&(*vi))); + + FaceIterator fi; + for (fi = m.face.begin(); fi != m.face.end(); ++fi) + if (!(*fi).IsD()) + for (unsigned int i = 0; i < 3; i++) + if ((*fi).V1(i) - (*fi).V0(i) > 0) { + PosType newpos(&*fi, i); + TopoEdgeFlip::Insert(heap, newpos, tri::IMark(m),pp); + } + } +}; // end CurvEdgeFlip class + + +}; // namespace tri +}; // namespace vcg + +#endif // __CURVEDGEFLIP diff --git a/src/meshlabplugins/filter_cubization/filter_cubization.cpp b/src/meshlabplugins/filter_cubization/filter_cubization.cpp new file mode 100644 index 000000000..908d2a857 --- /dev/null +++ b/src/meshlabplugins/filter_cubization/filter_cubization.cpp @@ -0,0 +1,354 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include +#include +#include + +#include "filter_cubization.h" + +#include +#include + +#include +#include + +#include +#include + +#include "curvedgeflip.h" +#include "curvdata.h" + +using namespace std; +using namespace vcg; + +// forward declarations +class MeanCEFlip; +typedef Histogram Histogramm; + +class MeanCEFlip : public vcg::tri::CurvEdgeFlip +{ +public: + MeanCEFlip(PosType pos, int mark,BaseParameterClass *_pp) : + vcg::tri::CurvEdgeFlip(pos, mark,_pp) {} +}; + + +// Constructor usually performs only two simple tasks of filling the two lists +// - typeList: with all the possible id of the filtering actions +// - actionList with the corresponding actions. If you want to add icons to +// your filtering actions you can do here by construction the QActions accordingly +CubizationPlugin::CubizationPlugin() +{ + typeList = { + FP_CUBIZATION + }; + + for(ActionIDType tt: types()) + actionList.push_back(new QAction(filterName(tt), this)); + + cubic_ApplyEdgeFlip = false; + cubic_ApplyColorize = false; +} + +QString CubizationPlugin::pluginName() const +{ + return "FilterCubization"; +} + +QString CubizationPlugin::pythonFilterName(ActionIDType f) const +{ + switch (f) { + case FP_CUBIZATION: return tr("apply_coord_cubic_stylization"); + default: assert(0); return QString(); + } +} + +QString CubizationPlugin::filterName(ActionIDType filterId) const +{ + switch (filterId) { + case FP_CUBIZATION: return tr("Cubic stylization"); + default: assert(0); return QString(); + } +} + +FilterPlugin::FilterArity CubizationPlugin::filterArity(const QAction*) const +{ + return SINGLE_MESH; +} + +int CubizationPlugin::getPreConditions(const QAction*) const +{ + return MeshModel::MM_VERTCOORD | MeshModel::MM_FACEVERT; +} + +int CubizationPlugin::getRequirements(const QAction *action) +{ + switch (ID(action)) { + case FP_CUBIZATION: + return MeshModel::MM_VERTCOORD | + MeshModel::MM_FACEFACETOPO | + MeshModel::MM_VERTFACETOPO | + MeshModel::MM_VERTMARK; + } + + return 0; +} + +QString CubizationPlugin::filterInfo(ActionIDType filterId) const +{ + switch(filterId) { + case FP_CUBIZATION: + return tr("Turn a mesh into a cube's style maintaining its original shape." + "
For all detailed about cubic stylization see:
" + "
Hsueh-Ti Derek Liu and Alec Jacobson.
" + "Cubic Stylization (pdf)
" + "in ACM Transactions on Graphics, 2019

"); + default : assert(0); + } + return {}; +} + + CubizationPlugin::FilterClass CubizationPlugin::getClass(const QAction *action) const +{ + switch(ID(action)) { + case FP_CUBIZATION: return FilterPlugin::Remeshing; + } + return FilterPlugin::Generic; +} + +int CubizationPlugin::postCondition(const QAction *a) const +{ + switch(ID(a)) + { + case FP_CUBIZATION : return MeshModel::MM_ALL | + MeshModel::MM_VERTQUALITY; + default : assert(0); + } + return {}; +} + +// This function define the needed parameters for each filter. +// Return true if the filter has some parameters +// it is called every time, so you can set the default value of parameters according to the mesh +// For each parameter you need to define, +// - the name of the parameter, +// - the string shown in the dialog +// - the default value +// - a possibly long string describing the meaning of that parameter (shown as a popup help in the dialog) +RichParameterList CubizationPlugin::initParameterList(const QAction *action, const MeshModel &m) +{ + RichParameterList parlst; + if (ID(action) == FP_CUBIZATION) { + parlst.addParam(RichFloat("lcubeness", 0.2f, + tr("Cubeness parameter (λ)"), + tr("Control the cubeness of the mesh. Generally, the higher the cubeness parameter, the more cubic the mesh is. λ ∈ [0, 1] "))); + + + parlst.addParam(RichBool("applyef", cubic_ApplyEdgeFlip, tr("Apply edge flipping"), tr("Apply edge flip optimization on cubic stylization."))); + parlst.addParam(RichBool("applycol", cubic_ApplyColorize, tr("Colorize by vertex Quality"), tr("Color vertices depending on their cubization energy."))); + } + return parlst; +} + +void Freeze(MeshModel &m) +{ + tri::UpdatePosition::Matrix(m.cm, m.cm.Tr,true); + tri::UpdateBounding::Box(m.cm); + m.cm.shot.ApplyRigidTransformation(m.cm.Tr); + m.cm.Tr.SetIdentity(); +} + +void ApplyTransform(MeshModel &m, const Matrix44m &tr, bool freeze, + bool invertFlag=false, bool composeFlage=true) +{ + if(invertFlag) m.cm.Tr = Inverse(m.cm.Tr); + if(composeFlage) m.cm.Tr = tr * m.cm.Tr; + else m.cm.Tr=tr; + if(freeze) Freeze(m); +} + +std::map CubizationPlugin::applyFilter( + const QAction* filter, + const RichParameterList& par, + MeshDocument& md, + unsigned int&, + vcg::CallBackPos*) +{ + if (ID(filter) == FP_CUBIZATION) { + // get bounding box + Box3m bbox = md.mm()->cm.bbox; + Matrix44m transfM, prevScaleTran, scaleTran, trTran, trTranInv, prevTransfM; + Point3m tranVec = Point3m(0, 0, 0); + float maxSide = max(bbox.DimX(), max(bbox.DimY(), bbox.DimZ())); + + if (maxSide >= 1.0) { + // compute unit box scale + scaleTran.SetScale(1.0 / maxSide, 1.0 / maxSide, 1.0 / maxSide); + + // reverse scale computation + prevScaleTran.SetScale( + 1.0 / (1.0 / maxSide), 1.0 / (1.0 / maxSide), 1.0 / (1.0 / maxSide)); + + // compute translate + trTran.SetTranslate(tranVec); + trTranInv.SetTranslate(-tranVec); + + transfM = trTran * scaleTran * trTranInv; + prevTransfM = trTran * prevScaleTran * trTranInv; + } + + MeshModel& m = *(md.mm()); + + if (maxSide >= 1.0) { + // apply transform + ApplyTransform(m, transfM, true); + } + + double energyTotal = 0.f; + time_t start = clock(); + + bool isColorizing = par.getBool("applycol"); + + m = ComputeCubicStylization(md, par, energyTotal, isColorizing); + + m.updateDataMask(MeshModel::MM_VERTQUALITY); + + if (isColorizing) { + m.updateDataMask(MeshModel::MM_FACEFACETOPO); + m.updateDataMask(MeshModel::MM_VERTCOLOR); + + Histogramm H; + vcg::tri::Stat::ComputePerVertexQualityHistogram(m.cm, H); + vcg::tri::UpdateColor::PerVertexQualityRamp( + m.cm, H.Percentile(0.01f), H.Percentile(0.99f)); + } + + if (maxSide >= 1.0) { + // re-apply transform to get previous mesh scale + ApplyTransform(m, prevTransfM, true); + } + m.updateBoxAndNormals(); + + log("cubic stylization performed in %.2f sec. with cubic energy equal to %.5f", + (clock() - start) / (float) CLOCKS_PER_SEC, + energyTotal); + } + else { + wrongActionCalled(filter); + } + return std::map(); +} + +MeshModel CubizationPlugin::ComputeCubicStylization( + MeshDocument& md, + const RichParameterList& par, + double& totalEnergy, + bool isColorizing){ + + MeshModel &m=*(md.mm()); + + float limit = -std::numeric_limits::epsilon(); + + int delvert = tri::Clean::RemoveUnreferencedVertex(m.cm); + if (delvert) + log( "Pre-Curvature Cleaning: Removed %d unreferenced vertices", + delvert); + + + tri::Allocator::CompactVertexVector(m.cm); + tri::Allocator::CompactFaceVector(m.cm); + m.updateDataMask(MeshModel::MM_FACEFACETOPO); + vcg::tri::UpdateFlags::FaceBorderFromFF(m.cm); + + bool isApplyEdgeFlip = par.getBool("applyef"); + + if ( tri::Clean::CountNonManifoldEdgeFF(m.cm) >0 && isApplyEdgeFlip) { + throw MLException("Mesh has some not 2-manifold faces, edge flips requires manifoldness"); + } + + Eigen::MatrixXd verts; + Eigen::MatrixXi faces; + Eigen::MatrixXd u_verts; + Eigen::VectorXd energy_verts; + + + float lambda = par.getFloat("lcubeness"); + cube_style_data data; + + data.lambda = lambda; + + vcg::tri::Cubization::Init(m.cm, verts, u_verts, faces, data); + + // apply cubic stylization + int maxIter = 1000; + double stopReldV = 1e-3; // stopping criteria for relative displacement + double reldV = 0; + + for (int iter=0; iter::Stylize(verts, u_verts, faces, data, energy_verts, totalEnergy); + + //apply Edge Flips + if((iter%30 == 0 || reldV < stopReldV) && isApplyEdgeFlip){ + Matrix2Mesh(m.cm, u_verts, faces); + + vcg::tri::PlanarEdgeFlipParameter pp; + float limit = -std::numeric_limits::epsilon(); + + vcg::LocalOptimization optimiz(m.cm,&pp); + float pthr = 10; + + // VF adjacency needed for edge flips based on vertex curvature + vcg::tri::UpdateTopology::VertexFace(m.cm); + vcg::tri::UpdateTopology::TestVertexFace(m.cm); + + pp.CoplanarAngleThresholdDeg = pthr; + optimiz.Init(); + + // stop when flips become harmful + optimiz.SetTargetMetric(limit); + optimiz.DoOptimization(); + optimiz.h.clear(); + + Mesh2Matrix(m.cm, u_verts, faces); + + log( "Iteration %d: %d curvature edge flips performed", iter, optimiz.nPerformedOps); + } + + if (reldV < stopReldV) break; + } + + Matrix2Mesh(m.cm, u_verts, faces); + + if(isColorizing){ + assert(energy_verts.size() == m.cm.vert.size()); + for(int i = 0; i < energy_verts.size(); i++){ + m.cm.vert[i].Q() = energy_verts[i]; + } + } + + return m; +} + +MESHLAB_PLUGIN_NAME_EXPORTER(CubizationPlugin) diff --git a/src/meshlabplugins/filter_cubization/filter_cubization.h b/src/meshlabplugins/filter_cubization/filter_cubization.h new file mode 100644 index 000000000..8475a5fdb --- /dev/null +++ b/src/meshlabplugins/filter_cubization/filter_cubization.h @@ -0,0 +1,73 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef FILTER_CUBIZATION_H +#define FILTER_CUBIZATION_H + +#include +#include + +class CubizationPlugin : public QObject, public FilterPlugin +{ + Q_OBJECT + MESHLAB_PLUGIN_IID_EXPORTER(FILTER_PLUGIN_IID) + Q_INTERFACES(FilterPlugin) + +public: + enum { + // mesh improvement by edge flipping + FP_CUBIZATION + }; + + CubizationPlugin(); + + QString pythonFilterName(ActionIDType f) const; + QString pluginName() const; + QString filterName(ActionIDType filter) const; + QString filterInfo(ActionIDType filter) const; + RichParameterList initParameterList(const QAction*, const MeshModel &/*m*/); + std::map applyFilter( + const QAction* action, + const RichParameterList & parameters, + MeshDocument &md, + unsigned int& postConditionMask, + vcg::CallBackPos * cb); + int getPreConditions(const QAction *) const; + int getRequirements(const QAction*); + FilterClass getClass(const QAction *) const; + int postCondition(const QAction* ) const; + FilterArity filterArity(const QAction*) const; + +private: + MeshModel ComputeCubicStylization( + MeshDocument& md, + const RichParameterList& par, + double& totalEnergy, + bool isColorizing); + +protected: + bool cubic_ApplyEdgeFlip; + bool cubic_ApplyColorize; +}; + +#endif // FILTER_CUBIZATION_H diff --git a/src/meshlabplugins/filter_developability/CMakeLists.txt b/src/meshlabplugins/filter_developability/CMakeLists.txt new file mode 100644 index 000000000..d24c43fbf --- /dev/null +++ b/src/meshlabplugins/filter_developability/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright 2019-2020, Collabora, Ltd. +# SPDX-License-Identifier: BSL-1.0 + + +set(SOURCES + filter_developability.cpp) + +set(HEADERS + filter_developability.h + remeshing.h + mesh_utils.h + energy.h + energy_grad.h + opt.h) + +add_meshlab_plugin(filter_developability ${SOURCES} ${HEADERS}) diff --git a/src/meshlabplugins/filter_developability/energy.h b/src/meshlabplugins/filter_developability/energy.h new file mode 100644 index 000000000..c85d06b9f --- /dev/null +++ b/src/meshlabplugins/filter_developability/energy.h @@ -0,0 +1,133 @@ +#ifndef FILTERDEVELOPABILITY_ENERGY_H +#define FILTERDEVELOPABILITY_ENERGY_H + +#include + +#define FILTERDEVELOPABILITY_AVOID_BRANCHING + + +template +struct StarPartitioning +{ + Star* star; + int rBegin; // index of the starting face within star for the first region + int rSize; // cardinality of the first region +}; + + +/* + * Compute the combinatorial energy of a mesh + * as defined in section 4.1.1 of the paper "Developability of Triangle Meshes" by Stein et al. 2018 + */ +template +double combinatorialEnergy(MeshType& m, + StarVertAttrHandle& vAttrStar) +{ + using VertexIterator = typename MeshType::VertexIterator; + + double totEnergy = 0.0; + + for(VertexIterator vIter = m.vert.begin(); vIter != m.vert.end(); vIter++) + totEnergy += localCombinatorialEnergy(&(*vIter), m, vAttrStar); + + return totEnergy; +} + + +/* + * Compute the combinatorial energy of a vertex star + * as defined in section 4.1.1 of the paper "Developability of Triangle Meshes" by Stein et al. 2018 + */ +template +double localCombinatorialEnergy(typename MeshType::VertexPointer v, + MeshType& m, + StarVertAttrHandle& vAttrStar, + StarPartitioning* outP = nullptr) +{ + double energy = -1.0; + StarPartitioning currP = { + &(vAttrStar[v]), // star of faces around v + 0, // rBegin + 0 // rSize + }; + + if(outP != nullptr) + outP->star = currP.star; + + if(currP.star->size() <= 3 || v->IsB()) + energy = 0.0; + else + { + // consider all possible cardinalities of a region resulting from a partitioning of the star + for(currP.rSize = 2; currP.rSize <= (currP.star->size() - 2); currP.rSize++) + { + // consider all possible regions having rSize faces and not crossing the vector boundaries. + // rBegin is the index of the first face in the region + for(currP.rBegin = 0; currP.rBegin < (currP.star->size() - currP.rSize); currP.rBegin++) + { + double currRegionEnergy = regionNormalDeviation(currP, 0, m); + double otherRegionEnergy = regionNormalDeviation(currP, 1, m); + + double currPartitioningEnergy; + #ifdef FILTERDEVELOPABILITY_AVOID_BRANCHING + currPartitioningEnergy = std::max(currRegionEnergy, otherRegionEnergy); + #else + currPartitioningEnergy = currRegionEnergy + otherRegionEnergy; + #endif + + if(energy < 0 || currPartitioningEnergy < energy) + { + energy = currPartitioningEnergy; + if(outP != nullptr) + { + outP->rBegin = currP.rBegin; + outP->rSize = currP.rSize; + } + } + } + } + } + + return energy; +} + + +/* + * Compute the normal deviation of a region of a vertex star + * as defined in equation 1 of the paper "Developability of Triangle Meshes" by Stein et al. 2018 + */ +template +double regionNormalDeviation(const StarPartitioning& partitioning, + bool region, + MeshType& m) +{ + // compute the begin index and the cardinality of the desired region + int rBegin = region ? (partitioning.rBegin + partitioning.rSize) : partitioning.rBegin; + int rSize = region ? (partitioning.star->size() - partitioning.rSize) : partitioning.rSize; + int starSize = partitioning.star->size(); + + vcg::Point3d normDiff; + normDiff.SetZero(); + + double currRegionNormalDev; + double regionNormalDev = 0.0; + + // iterate through each pair of faces within the region + for(int i = rBegin; i < (rBegin + rSize - 1); i++) + for(int j = i+1; j < (rBegin + rSize); j++) + { + normDiff = ( partitioning.star->at(i % starSize)->N() - partitioning.star->at(j % starSize)->N() ); + currRegionNormalDev = normDiff.SquaredNorm(); + + #ifdef FILTERDEVELOPABILITY_AVOID_BRANCHING + regionNormalDev = std::max(regionNormalDev, currRegionNormalDev); + #else + regionNormalDev += ( currRegionNormalDev / std::pow(rSize, 2) ); + #endif + } + + return regionNormalDev; +} + + +#endif diff --git a/src/meshlabplugins/filter_developability/energy_grad.h b/src/meshlabplugins/filter_developability/energy_grad.h new file mode 100644 index 000000000..af9adf628 --- /dev/null +++ b/src/meshlabplugins/filter_developability/energy_grad.h @@ -0,0 +1,116 @@ +#ifndef FILTERDEVELOPABILITY_ENERGYGRAD_H +#define FILTERDEVELOPABILITY_ENERGYGRAD_H + +#include "mesh_utils.h" +#include "energy.h" + +#include + + +/* + * Compute the combinatorial energy of a mesh and its gradient + * as defined in section B.2 of the paper "Developability of Triangle Meshes" by Stein et al. 2018 + */ +template +double combinatorialEnergyGrad(MeshType& m, + AreaFaceAttrHandle& fAttrArea, + StarVertAttrHandle& vAttrStar, + GradientVertAttrHandle& vAttrGrad) +{ + using VertexIterator = typename MeshType::VertexIterator; + + // reset the gradient associated with each vertex + for(VertexIterator vIter = m.vert.begin(); vIter != m.vert.end(); vIter++) + vAttrGrad[vIter].SetZero(); + + double currEnergy; + double totEnergy = 0.0; + StarPartitioning currPart; + for(VertexIterator vIter = m.vert.begin(); vIter != m.vert.end(); vIter++) + { + currEnergy = localCombinatorialEnergy(&(*vIter), m, vAttrStar, &currPart); + totEnergy += currEnergy; + + if(currPart.star->size() <= 3 || vIter->IsB()) + continue; + + regionNormalDeviationGrad(&(*vIter), currPart, 0, m, fAttrArea, vAttrStar, vAttrGrad); + regionNormalDeviationGrad(&(*vIter), currPart, 1, m, fAttrArea, vAttrStar, vAttrGrad); + } + + return totEnergy; +} + + +/* + * Compute the gradient of the normal deviation of a region + * as defined in section B.2 of the paper "Developability of Triangle Meshes" by Stein et al. 2018 + */ +template +void regionNormalDeviationGrad(typename MeshType::VertexPointer v, + StarPartitioning& partitioning, + bool region, + MeshType& m, + AreaFaceAttrHandle& fAttrArea, + StarVertAttrHandle& vAttrStar, + GradientVertAttrHandle& vAttrGrad) +{ + using FacePointer = typename MeshType::FacePointer; + using VertexPointer = typename MeshType::VertexPointer; + + // compute the begin index and the cardinality of the desired region + int rBegin = region ? (partitioning.rBegin + partitioning.rSize) : partitioning.rBegin; + int rSize = region ? (partitioning.star->size() - partitioning.rSize) : partitioning.rSize; + int starSize = partitioning.star->size(); + + FacePointer faceA, faceB; + vcg::Point3d normalDiff; + + int faceA_vIndex, faceB_vIndex; + VertexPointer vertA, vertB; + + // iterate through each pair of faces within the region + for(int i = rBegin; i < (rBegin + rSize - 1); i++) + for(int j = i+1; j < (rBegin + rSize); j++) + { + faceA = vAttrStar[v][i % starSize]; + faceB = vAttrStar[v][j % starSize]; + + normalDiff = faceA->N() - faceB->N(); + + for(faceA_vIndex = 0; faceA_vIndex < 3; faceA_vIndex++) + { + vertA = faceA->V(faceA_vIndex); + vAttrGrad[vertA] += (faceNormalGrad(faceA, faceA_vIndex, m, fAttrArea).transpose() * normalDiff * 2/std::pow(rSize, 2)); + } + + for(faceB_vIndex = 0; faceB_vIndex < 3; faceB_vIndex++) + { + vertB = faceB->V(faceB_vIndex); + vAttrGrad[vertB] -= (faceNormalGrad(faceB, faceB_vIndex, m, fAttrArea).transpose() * normalDiff* 2/std::pow(rSize, 2)); + } + } +} + + +/* + * Compute the gradient of the normal of a face wrt one of its vertices + * as defined in section B.1 of the paper "Developability of Triangle Meshes" by Stein et al. 2018 + */ +template +vcg::Matrix33d faceNormalGrad(typename MeshType::FacePointer f, + int vIndex, + MeshType& m, + AreaFaceAttrHandle& fAttrArea) +{ + vcg::Point3d oppositeEdge = f->V2(vIndex)->P() - f->V1(vIndex)->P(); + vcg::Matrix33d grad; + + grad.ExternalProduct(oppositeEdge ^ f->N(), f->N()); + grad /= fAttrArea[f]; + + return grad; +} + + +#endif diff --git a/src/meshlabplugins/filter_developability/filter_developability.cpp b/src/meshlabplugins/filter_developability/filter_developability.cpp new file mode 100644 index 000000000..02c246a73 --- /dev/null +++ b/src/meshlabplugins/filter_developability/filter_developability.cpp @@ -0,0 +1,239 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include "filter_developability.h" +#include "remeshing.h" +#include "opt.h" +#include "energy.h" + +FilterDevelopabilityPlugin::FilterDevelopabilityPlugin() +{ + typeList = {FP_MAKE_DEVELOPABLE}; + + for(ActionIDType tt : types()) + actionList.push_back(new QAction(filterName(tt), this)); +} + +FilterDevelopabilityPlugin::~FilterDevelopabilityPlugin() +{ +} + +QString FilterDevelopabilityPlugin::pluginName() const +{ + return "FilterDevelopability"; +} + +QString FilterDevelopabilityPlugin::filterName(ActionIDType filterId) const +{ + switch(filterId) { + case FP_MAKE_DEVELOPABLE : + return "Make mesh developable"; + default : + assert(0); + return QString(); + } +} + +QString FilterDevelopabilityPlugin::pythonFilterName(ActionIDType f) const +{ + switch(f) { + case FP_MAKE_DEVELOPABLE : + return "apply_coord_developability_of_mesh"; + default : + assert(0); + return QString(); + } +} + + QString FilterDevelopabilityPlugin::filterInfo(ActionIDType filterId) const +{ + switch(filterId) { + case FP_MAKE_DEVELOPABLE : + return "The filter improves the developability of the current two-manifold triangular mesh " + "by applying an optimization process that encourages each vertex star to form an hinge or a flat piece. " + "The resulting mesh is similar to the initial, but it is comprised of one or more developable pieces held toghether by highly regular seam curves, " + "i.e. path of edges which vertex stars did not form an hinge or a flat spot.
" + "Since small interior angles can have a negative impact on the outcome, an automatic remeshing that runs along the optimization can be enabled.
" + "When the obtained design is satisfactory, one may want to refine the quality of the seams and the developability of the surfaces " + "by alternating between regular midpoint subdivisions and further optimization rounds.
" + "For more details see:
" + "Oded Stein, Eitan Grinspun and Keenan Crane
" + "'Developability of triangle meshes'
" + "ACM Transactions on Graphics, Volume 37, Issue 4"; + default : + assert(0); + return "Unknown Filter"; + } +} + +FilterDevelopabilityPlugin::FilterClass FilterDevelopabilityPlugin::getClass(const QAction *a) const +{ + switch(ID(a)) { + case FP_MAKE_DEVELOPABLE : + return FilterPlugin::Remeshing; + default : + assert(0); + return FilterPlugin::Generic; + } +} + +FilterPlugin::FilterArity FilterDevelopabilityPlugin::filterArity(const QAction*) const +{ + return SINGLE_MESH; +} + +int FilterDevelopabilityPlugin::getPreConditions(const QAction*) const +{ + return MeshModel::MM_NONE; +} + +int FilterDevelopabilityPlugin::postCondition(const QAction*) const +{ + return MeshModel::MM_ALL; +} + +RichParameterList FilterDevelopabilityPlugin::initParameterList(const QAction *action,const MeshModel &m) +{ + RichParameterList parlst; + QList optMethodsList{ "[F] Fixed stepsize", "[B] Backtracking line search" }; + switch(ID(action)) { + case FP_MAKE_DEVELOPABLE : + + parlst.addParam(RichEnum("OptMethod", 1, optMethodsList, "Gradient method", "The gradient method optimization algorithm to use")); + parlst.addParam(RichInt("MaxFunEvals", 400, "Max function evaluations", "The maximum number of function evaluation. Once reached, the optimization stops")); + parlst.addParam(RichFloat("Eps", 1e-5, "Stop threshold", "Optimization stops when the squared norm of the gradient is less than or equal to the accuracy")); + parlst.addParam(RichFloat("StepSize", 0.01, "Initial step size", "The initial step size of the opt method, fixed when using [F] optimizer")); + parlst.addParam(RichFloat("MinStepSize", 1e-10, "Min step size (B only)", "The minimum step size for the backtracking line search opt method")); + parlst.addParam(RichFloat("Tau", 0.8, "Tau (B only)", "Scaling factor of the step size for the backtracking line search opt method")); + parlst.addParam(RichFloat("M1", 1e-4, "Armijo constant (B only)", "The constant of the Armijo condition of the backtracking line search opt method")); + parlst.addParam(RichBool("EdgeFlips", true, "Apply edge flips", "Whether or not to apply edge flips when necessary during optimization")); + parlst.addParam(RichBool("EdgeCollapses", true, "Apply edge collapses", "Whether or not to apply edge collapses when necessary during optimization")); + parlst.addParam(RichFloat("AngleThreshold", 18, "Post-processing angle threshold (deg)", "The maximum angle under which an edge flip or an edge collapse must be performed during optimization")); + break; + default : + assert(0); + } + return parlst; +} + +std::map FilterDevelopabilityPlugin::applyFilter(const QAction * action, const RichParameterList & parameters, MeshDocument &md, unsigned int& /*postConditionMask*/, vcg::CallBackPos *cb) +{ + switch(ID(action)) { + case FP_MAKE_DEVELOPABLE : + makeDevelopable(md, + cb, + parameters.getEnum("OptMethod"), + parameters.getInt("MaxFunEvals"), + parameters.getFloat("Eps"), + parameters.getFloat("StepSize"), + parameters.getFloat("MinStepSize"), + parameters.getFloat("Tau"), + parameters.getFloat("M1"), + parameters.getBool("EdgeFlips"), + parameters.getBool("EdgeCollapses"), + parameters.getFloat("AngleThreshold")); + break; + default : + wrongActionCalled(action); + } + return std::map(); +} + +void FilterDevelopabilityPlugin::makeDevelopable(MeshDocument &md, + vcg::CallBackPos *cb, + int optMethod, + int maxFunEval, + double eps, + double initialStepSize, + double minStepSize, + double tau, + double m1, + bool doEdgeFlip, + bool doEdgeCollapse, + double angleThreshold) +{ + // Get the current mesh, update FF topology and check 2-manifold precondition + + md.mm()->updateDataMask(MeshModel::MM_FACEFACETOPO); + CMeshO &m = md.mm()->cm; + + if(vcg::tri::Clean::CountNonManifoldEdgeFF(m) > 0) + throw MLException("non possible developability optimization because of non manifold edges"); + if(vcg::tri::Clean::CountNonManifoldVertexFF(m) > 0) + throw MLException("non possible developability optimization because of non manifold verties"); + + // Apply an initial remeshing if necessary + + MeshPostProcessing postProcessing(doEdgeFlip, doEdgeCollapse, vcg::math::ToRad(angleThreshold)); + if(postProcessing.process(m)) + log("An initial remeshing has been applied"); + + // Temporarily move the mesh to origin and scale the diagonal of the bounding box to unit + + double boundingBoxDiag; + vcg::Point3d boundingBoxCenter; + + vcg::tri::UpdateBounding::Box(m); + boundingBoxDiag = m.bbox.Diag(); + boundingBoxCenter = m.bbox.Center(); + vcg::tri::UpdatePosition::Translate(m, -boundingBoxCenter); + vcg::tri::UpdatePosition::Scale(m, 1.0 / boundingBoxDiag); + + // Proceed to the actual optimization + + vcg::tri::UpdateFlags::VertexBorderFromFaceAdj(m); + Optimizer* opt; + + if(optMethod == 0) + opt = new FixedStepOpt(m, maxFunEval, eps, initialStepSize); + else + opt = new BacktrackingOpt(m, maxFunEval, eps, initialStepSize, minStepSize, tau, m1); + + while(opt->step()) + { + if(optMethod == 0) + log("[F] nFunEvals:%d gradSqNorm:%f energy:%f", opt->getNFunEval(), opt->getGradientSqNorm(), opt->getEnergy()); + else + log("[B] nFunEvals:%d stepSize:%f gradSqNorm:%f energy:%f", opt->getNFunEval(), opt->getStepSize(), opt->getGradientSqNorm(), opt->getEnergy()); + + if(optMethod == 1 || (opt->getNFunEval() % 10 == 0)) + cb(100 * opt->getNFunEval() / maxFunEval, "Optimizing developability energy..."); + + if(postProcessing.process(m)) + { + log("Remeshing applied"); + opt->reset(); + } + } + + delete opt; + + // Reset original position and scale of the mesh + + vcg::tri::UpdatePosition::Scale(m, boundingBoxDiag); + vcg::tri::UpdatePosition::Translate(m, boundingBoxCenter); + + md.mm()->updateBoxAndNormals(); +} + +MESHLAB_PLUGIN_NAME_EXPORTER(FilterDevelopabilityPlugin) diff --git a/src/meshlabplugins/filter_developability/filter_developability.h b/src/meshlabplugins/filter_developability/filter_developability.h new file mode 100644 index 000000000..3a9f68ccd --- /dev/null +++ b/src/meshlabplugins/filter_developability/filter_developability.h @@ -0,0 +1,73 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef FILTERDEVELOPABILITY_PLUGIN_H +#define FILTERDEVELOPABILITY_PLUGIN_H + +#include + +class FilterDevelopabilityPlugin : public QObject, public FilterPlugin +{ + Q_OBJECT + MESHLAB_PLUGIN_IID_EXPORTER(FILTER_PLUGIN_IID) + Q_INTERFACES(FilterPlugin) + +public: + enum { FP_MAKE_DEVELOPABLE } ; + + FilterDevelopabilityPlugin(); + virtual ~FilterDevelopabilityPlugin(); + + QString pluginName() const; + + QString filterName(ActionIDType filter) const; + QString pythonFilterName(ActionIDType f) const; + QString filterInfo(ActionIDType filter) const; + FilterClass getClass(const QAction* a) const; + FilterArity filterArity(const QAction*) const; + int getPreConditions(const QAction *) const; + int postCondition(const QAction* ) const; + RichParameterList initParameterList(const QAction*, const MeshModel &/*m*/); + std::map applyFilter( + const QAction* action, + const RichParameterList & parameters, + MeshDocument &md, + unsigned int& postConditionMask, + vcg::CallBackPos * cb); + +private: + void makeDevelopable(MeshDocument &md, + vcg::CallBackPos *cb, + int optMethod, + int maxFunEval, + double eps, + double initialStepSize, + double minStepSize, + double tau, + double m1, + bool doEdgeFlip, + bool doEdgeCollapse, + double angleThreshold); +}; + +#endif diff --git a/src/meshlabplugins/filter_developability/mesh_utils.h b/src/meshlabplugins/filter_developability/mesh_utils.h new file mode 100644 index 000000000..2e013e88a --- /dev/null +++ b/src/meshlabplugins/filter_developability/mesh_utils.h @@ -0,0 +1,74 @@ +#ifndef FILTERDEVELOPABILITY_MESHUTILS_H +#define FILTERDEVELOPABILITY_MESHUTILS_H + +#include +#include +#include +#include +#include +#include + + +template +using Star = std::vector; + +template +using StarVertAttrHandle = typename MeshType:: template PerVertexAttributeHandle>; + +template +using AreaFaceAttrHandle = typename MeshType:: template PerFaceAttributeHandle; + +template +using GradientVertAttrHandle = typename MeshType:: template PerVertexAttributeHandle; + + +template +void updateFaceStars(MeshType& m, StarVertAttrHandle& stars) +{ + using VertexPointer = typename MeshType::VertexPointer; + using VertexIterator = typename MeshType::VertexIterator; + using FaceIterator = typename MeshType::FaceIterator; + using FaceType = typename MeshType::FaceType; + + int vIndex; + VertexPointer v; + std::vector> currStarPos; + + for(VertexIterator vIter = m.vert.begin(); vIter != m.vert.end(); vIter++) + stars[vIter].clear(); + + vcg::tri::UpdateFlags::VertexClearV(m); + for(FaceIterator fIter = m.face.begin(); fIter != m.face.end(); fIter++) + { + for(vIndex = 0; vIndex < 3; vIndex++) + { + v = fIter->V(vIndex); + if(v->IsV()) + continue; + v->SetV(); + + vcg::face::VFOrderedStarFF(vcg::face::Pos(&(*fIter), v), currStarPos); + for(vcg::face::Pos p : currStarPos) + stars[v].push_back(p.F()); + } + } +} + +template +void updateNormalsAndAreas(MeshType& m, AreaFaceAttrHandle& areas) +{ + using FaceIterator = typename MeshType::FaceIterator; + + vcg::tri::UpdateNormal::PerFace(m); + double currNorm; + + for(FaceIterator fIter = m.face.begin(); fIter != m.face.end(); fIter++) + { + currNorm = fIter->N().Norm(); + areas[fIter] = currNorm / 2.0; + fIter->N().Normalize(); + } +} + + +#endif diff --git a/src/meshlabplugins/filter_developability/opt.h b/src/meshlabplugins/filter_developability/opt.h new file mode 100644 index 000000000..3520e07cb --- /dev/null +++ b/src/meshlabplugins/filter_developability/opt.h @@ -0,0 +1,234 @@ +#ifndef FILTERDEVELOPABILITY_OPT_H +#define FILTERDEVELOPABILITY_OPT_H + +#include "mesh_utils.h" +#include "energy.h" +#include "energy_grad.h" + +#include +#include + +#include +#include + + +/* + * Gradient method optimizer interface + */ +template +class Optimizer +{ +public: + Optimizer(MeshType& m, + double stepSize) : + m(m), + stepSize(stepSize), + nFunEval(0) + { + vAttrStar = vcg::tri::Allocator:: template GetPerVertexAttribute>(m, std::string("Star")); + vAttrGrad = vcg::tri::Allocator:: template GetPerVertexAttribute(m, std::string("Gradient")); + fAttrArea = vcg::tri::Allocator:: template GetPerFaceAttribute(m, std::string("Area")); + } + + virtual ~Optimizer() {} + + /* + * Routine that must be called when the mesh geometry and/or topology changes + */ + virtual void reset() = 0; + + /* + * Perform an optimization step; returns true iff another step can be performed + */ + virtual bool step() = 0; + + void updateGradientSqNorm() + { + gradSqNorm = 0.0; + + for(size_t v = 0; v < m.VN(); v++) + for(int i = 0; i < 3; i++) + gradSqNorm += std::pow(vAttrGrad[v][i], 2); + } + + double getGradientSqNorm() { return gradSqNorm; } + double getStepSize() { return stepSize; } + double getEnergy() { return energy; } + int getNFunEval() { return nFunEval; } + +protected: + MeshType& m; + AreaFaceAttrHandle fAttrArea; + StarVertAttrHandle vAttrStar; + GradientVertAttrHandle vAttrGrad; + double stepSize; + double gradSqNorm; + double energy; + int nFunEval; +}; + + +/* + * Gradient method optimization with fixed step size + */ +template +class FixedStepOpt : public Optimizer +{ + using Optimizer::m; + using Optimizer::fAttrArea; + using Optimizer::vAttrStar; + using Optimizer::vAttrGrad; + using Optimizer::stepSize; + using Optimizer::gradSqNorm; + using Optimizer::energy; + using Optimizer::nFunEval; + using Optimizer::updateGradientSqNorm; + +public: + FixedStepOpt(MeshType& m, + int maxFunEval, + double eps, + double stepSize) : + Optimizer(m, stepSize), + maxFunEval(maxFunEval), + eps(eps) + { + reset(); + } + + void reset() override + { + updateFaceStars(m, vAttrStar); + updateNormalsAndAreas(m, fAttrArea); + energy = combinatorialEnergyGrad(m, fAttrArea, vAttrStar, vAttrGrad); + updateGradientSqNorm(); + } + + bool step() override + { + if(nFunEval >= maxFunEval || gradSqNorm <= eps) + return false; + + for(size_t v = 0; v < m.VN(); v++) + m.vert[v].P() -= (vAttrGrad[v] * stepSize); + + updateNormalsAndAreas(m, fAttrArea); + energy = combinatorialEnergyGrad(m, fAttrArea, vAttrStar, vAttrGrad); + updateGradientSqNorm(); + nFunEval++; + + return true; + } + +private: + int maxFunEval; + double eps; +}; + + +/* + * Gradient method optimization with backtracking line search (Armijo condition) + */ +template +class BacktrackingOpt : public Optimizer +{ + using Optimizer::m; + using Optimizer::fAttrArea; + using Optimizer::vAttrStar; + using Optimizer::vAttrGrad; + using Optimizer::stepSize; + using Optimizer::gradSqNorm; + using Optimizer::energy; + using Optimizer::nFunEval; + using Optimizer::updateGradientSqNorm; + +public: + BacktrackingOpt(MeshType& m, + int maxFunEval, + double eps, + double initialStepSize, + double minStepSize, + double tau, + double armijoM1) : + Optimizer(m, initialStepSize), + maxFunEval(maxFunEval), + eps(eps), + initialStepSize(initialStepSize), + minStepSize(minStepSize), + tau(tau), + armijoM1(armijoM1) + { + reset(); + } + + void reset() override + { + tmpVP.clear(); + tmpVP.reserve(m.vert.size()); + for(size_t v = 0; v < m.vert.size(); v++) + tmpVP.push_back(m.vert[v].cP()); + + updateFaceStars(m, vAttrStar); + updateNormalsAndAreas(m, fAttrArea); + energy = combinatorialEnergyGrad(m, fAttrArea, vAttrStar, vAttrGrad); + updateGradientSqNorm(); + } + + bool step() override + { + if(nFunEval >= maxFunEval || gradSqNorm <= eps) + return false; + + double LS_energy, LS_stepSize; + // compute the current tomography deriv as the dot prod between grad and search direction -grad + // == minus the squared l2 norm of the gradient + double tomographyDeriv = -(gradSqNorm); + + for(LS_stepSize = initialStepSize; LS_stepSize > minStepSize; LS_stepSize *= tau) + { + for(size_t v = 0; v < m.vert.size(); v++) + m.vert[v].P() = tmpVP[v] - vAttrGrad[v] * LS_stepSize; + + updateNormalsAndAreas(m, fAttrArea); + LS_energy = combinatorialEnergy(m, vAttrStar); + nFunEval++; + + // check Armijo condition + if(LS_energy <= energy + armijoM1 * LS_stepSize * tomographyDeriv) + break; + + if(nFunEval >= maxFunEval) + { + for(size_t v = 0; v < m.vert.size(); v++) + m.vert[v].P() = tmpVP[v]; + + updateNormalsAndAreas(m, fAttrArea); + + return false; + } + } + + for(size_t v = 0; v < m.vert.size(); v++) + tmpVP[v] = m.vert[v].cP(); + + stepSize = LS_stepSize; + energy = LS_energy; + combinatorialEnergyGrad(m, fAttrArea, vAttrStar, vAttrGrad); + updateGradientSqNorm(); + nFunEval++; + + return true; + } + +private: + std::vector tmpVP; + int maxFunEval; + double eps; + double initialStepSize; + double minStepSize; + double tau; + double armijoM1; +}; + + +#endif diff --git a/src/meshlabplugins/filter_developability/remeshing.h b/src/meshlabplugins/filter_developability/remeshing.h new file mode 100644 index 000000000..92ef4df0a --- /dev/null +++ b/src/meshlabplugins/filter_developability/remeshing.h @@ -0,0 +1,98 @@ +#ifndef FILTERDEVELOPABILITY_REMESHING_H +#define FILTERDEVELOPABILITY_REMESHING_H + +#include "mesh_utils.h" + + +/* + * To improve numerical stability of the energy optimization, meshes should not present + * small interior angles; + * this class implements a post-processing phase that can be applied between iterations + * in order to get rid of these angles by means of edge flipping and/or edge collapsing + */ +template +class MeshPostProcessing +{ +public: + MeshPostProcessing(bool doEdgeFlipping, + bool doEdgeCollapsing, + double angleThreshold) : + doEdgeFlipping(doEdgeFlipping), + doEdgeCollapsing(doEdgeCollapsing), + angleThreshold(angleThreshold) // the radiants under which the angle is considered to be small + {} + + /* + * Perform the post-processing on a mesh + */ + bool process(MeshType& m) + { + typedef typename MeshType::FaceType FaceType; + typedef typename MeshType::FaceIterator FaceIterator; + + double faceAngles[3]; + int edgeToFlip; + int edgeToCollapse; + bool meshModified = false; + + for(FaceIterator fIter = m.face.begin(); fIter != m.face.end(); fIter++) + { + if(fIter->IsD()) + continue; + + faceAngles[0] = vcg::face::WedgeAngleRad(*fIter, 0); + faceAngles[1] = vcg::face::WedgeAngleRad(*fIter, 1); + faceAngles[2] = vcg::face::WedgeAngleRad(*fIter, 2); + + edgeToFlip = -1; + edgeToCollapse = -1; + for(int i = 0; i < 2; i++) + if(faceAngles[i] < angleThreshold) + { + if(faceAngles[(i+1)%3] < angleThreshold) + { + edgeToFlip = i; + break; + } + else if(faceAngles[(i-1)%3] < angleThreshold) + { + edgeToFlip = (i-1)%3; + break; + } + else + { + edgeToCollapse = (i+1)%3; + break; + } + } + + if(doEdgeFlipping && edgeToFlip >= 0 && vcg::face::CheckFlipEdge(*fIter, edgeToFlip)) + { + vcg::face::FlipEdge(*fIter, edgeToFlip); + meshModified = true; + } + else if(doEdgeCollapsing && edgeToCollapse >= 0 && vcg::face::FFLinkCondition(*fIter, edgeToCollapse)) + { + vcg::face::FFEdgeCollapse(m, *fIter, edgeToCollapse); + meshModified = true; + } + } + + if(meshModified) + { + vcg::tri::Allocator::CompactFaceVector(m); + vcg::tri::Allocator::CompactVertexVector(m); + vcg::tri::UpdateFlags::VertexBorderFromFaceAdj(m); + } + + return meshModified; + } + +private: + bool doEdgeFlipping; + bool doEdgeCollapsing; + double angleThreshold; +}; + + +#endif diff --git a/src/meshlabplugins/filter_embree/CMakeLists.txt b/src/meshlabplugins/filter_embree/CMakeLists.txt new file mode 100644 index 000000000..c16a5330a --- /dev/null +++ b/src/meshlabplugins/filter_embree/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright 2019-2020, Collabora, Ltd. +# SPDX-License-Identifier: BSL-1.0 + +if (TARGET external-embree) + set(SOURCES filter_embree.cpp) + + set(HEADERS filter_embree.h) + + add_meshlab_plugin(filter_embree ${SOURCES} ${HEADERS}) + + target_link_libraries(filter_embree PRIVATE external-embree) + if(OpenMP_CXX_FOUND) + target_link_libraries(filter_embree PRIVATE OpenMP::OpenMP_CXX) + endif() +else() + message( + STATUS "Skipping filter_embree - don't know about embree or omp on this system.") +endif() diff --git a/src/meshlabplugins/filter_embree/filter_embree.cpp b/src/meshlabplugins/filter_embree/filter_embree.cpp new file mode 100644 index 000000000..72a7a8f0c --- /dev/null +++ b/src/meshlabplugins/filter_embree/filter_embree.cpp @@ -0,0 +1,323 @@ +/**************************************************************************** +* MeshLab o o * +* A versatile mesh processing toolbox o o * +* _ O _ * +* Copyright(C) 2005 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program 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. * +* * +* This program 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 (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#include "filter_embree.h" +#include +#include +/** + * @brief Constructor usually performs only two simple tasks of filling the two lists + * - typeList: with all the possible id of the filtering actions + * - actionList with the corresponding actions. If you want to add icons to + * your filtering actions you can do here by construction the QActions accordingly + */ +FilterEmbreePlugin::FilterEmbreePlugin() +{ + typeList = { + FP_OBSCURANCE, + FP_AMBIENT_OCCLUSION, + FP_SDF, + //FP_SELECT_VISIBLE_FACES, + FP_ANALYZE_NORMALS + }; + + for(ActionIDType tt : types()) + actionList.push_back(new QAction(filterName(tt), this)); + +} + +FilterEmbreePlugin::~FilterEmbreePlugin() +{ +} + +QString FilterEmbreePlugin::pluginName() const +{ + return "FilterEmbree"; +} + +/** + * @brief ST() must return the very short string describing each filtering action + * (this string is used also to define the menu entry) + * @param filterId: the id of the filter + * @return the name of the filter + */ +QString FilterEmbreePlugin::filterName(ActionIDType filterId) const +{ + switch(filterId) { + case FP_OBSCURANCE : + return QString("Compute Obscurance"); + case FP_AMBIENT_OCCLUSION: + return QString("Compute Ambient occlusion"); + case FP_SDF: + return QString("Compute Shape-Diameter Function"); + case FP_SELECT_VISIBLE_FACES: + return QString("Select Visible Faces "); + case FP_ANALYZE_NORMALS: + return QString("Reorient face normals by geometry"); + default : + assert(0); + return QString(); + } +} + +/** + * @brief FilterSamplePlugin::pythonFilterName if you want that your filter should have a different + * name on pymeshlab, use this function to return its python name. + * @param f + * @return + */ +QString FilterEmbreePlugin::pythonFilterName(ActionIDType f) const +{ + switch(f) { + case FP_OBSCURANCE : + return QString("compute_scalar_by_volumetric_obscurance"); + case FP_AMBIENT_OCCLUSION: + return QString("compute_scalar_ambient_occlusion"); + case FP_SDF: + return QString("compute_scalar_by_shape_diameter_function_per_vertex"); + case FP_SELECT_VISIBLE_FACES: + return QString("compute_selection_by_visibility_per_face"); + case FP_ANALYZE_NORMALS: + return QString("meshing_re_orient_faces_by_geometry"); + default : + assert(0); + return QString(); + } +} + + +/** + * @brief // Info() must return the longer string describing each filtering action + * (this string is used in the About plugin dialog) + * @param filterId: the id of the filter + * @return an info string of the filter + * + */ + QString FilterEmbreePlugin::filterInfo(ActionIDType filterId) const +{ + switch(filterId) { + case FP_OBSCURANCE: + return QString("Compute ambient Obscurance.
" + "Ambient obscurance is a computer graphics technique used to simulate the effect of global ambient light in a 3D scene, making the mesh appear more realistic.
" + "This filter requires two values:" + "
    " + "
  • the number of rays(defined by the user), which will be shot from the barycenter of each face in order to compute how many time it is visible from these directions;" + "
  • the tau value which represent the T spatial decay;
  • " + "
" + "The resulting values for the obscurance are saved into face quality and mapped on the mesh into a gray shade.
" + "For further details see the reference paper: Iones Krupkin Sbert Zhukov Fast, Realistic Lighting for Video Games IEEECG&A 2003
" + "This filter uses Embree3 library by INTEL."); + + + case FP_AMBIENT_OCCLUSION: + return QString("Compute Ambient Occlusion." + "This filter is a shading technique used in computer graphics to simulate the way light interacts with surfaces in a realistic manner." + "The parameter for the number of rays is defined by the user; this parameter represents the number of rays that will be shot from the barycenter of each face." + "The higher the number of rays, the longer the time to compute, but the better the results." + "These results are saved into face quality and mapped into a gray shade on the mesh." + "This filter uses the Embree3 library by INTEL."); + + + case FP_SDF: + return QString("Compute Shape-Diameter Function
" + "The SDF defines the distance between a point in 3D space and the nearest point on the object's surface." + "This filter can be used to find out the thickness of the mesh
" + "Given a face, a set of rays are shot inward, and an average of the distance to hit a face is saved in the face quality. The face quality is then mapped into a color ramp." + "This filter requires two values:" + "
    " + "
  • the number of rays which will be shot from the barycenter of each face
  • " + "
  • the cone amplitude (in degrees) of the cone which we value as valid for the shooting angle
  • " + "
" + "
" + "For further details see the reference paper: Shapira Shamir Cohen-Or, Consistent Mesh Partitioning and Skeletonisation using the shaper diameter function, Visual Comput. J. (2008)
" + "This filter uses Embree3 library by INTEL."); + + + case FP_SELECT_VISIBLE_FACES: + return QString("Select visible face
" + "This filter displays all visible faces from a given direction, selecting the face is is visible from the point given." + "This filter utilizes the Embree3 library by INTEL."); + + case FP_ANALYZE_NORMALS: + return QString("Reorient face normals by geometry." + "Given the input mesh, this filter uses raytracing to determine if any faces are pointing inward and corrects their orientation. The number of rays is defined by the user; the higher the number, the higher the precision, but at the cost of computation time." + "This filter requires two values:" + "
    " + "
  • the number of rays to be shot from the barycenter of each face
  • " + "
  • Parity Sampling: If selected, the normal analysis will be performed using the Parity Sampling algorithm. It is suggested to use this algotirhm when the standard one (visibility sampling) faild to riorient all faces because it is used to reorient faces invisible from the outside
  • " + "
" + " For further details, see the reference paper: Kenshi Takayama, Alec Jacobson, Ladislav Kavan, Olga Sorkine-Hornung. " + "
" + " A Simple Method for Correcting Facet Orientations in Polygon Meshes Based on Ray Casting. Journal of Computer Graphics Techniques 3(4), 2014. " + + "This filter uses the Embree3 library by Intel."); + default : + assert(0); + return QString("Unknown Filter"); + } +} + + /** + * @brief The FilterClass describes in which generic class of filters it fits. + * This choice affect the submenu in which each filter will be placed + * More than a single class can be chosen. + * @param a: the action of the filter + * @return the class od the filter + */ +FilterEmbreePlugin::FilterClass FilterEmbreePlugin::getClass(const QAction *a) const +{ + return FilterPlugin::Quality; + /* + switch(ID(a)) { + default : + return FilterPlugin::Generic; + } + */ +} + +/** + * @brief FilterSamplePlugin::filterArity + * @return + */ +FilterEmbreePlugin::FilterArity FilterEmbreePlugin::filterArity(const QAction*) const +{ + return SINGLE_MESH; +} + +/** + * @brief FilterSamplePlugin::getPreConditions + * @return + */ +int FilterEmbreePlugin::getPreConditions(const QAction*) const +{ + return MeshModel::MM_NONE; +} + +/** + * @brief FilterSamplePlugin::postCondition + * @return + */ +int FilterEmbreePlugin::postCondition(const QAction* act) const +{ + switch(ID(act)) { + case FP_ANALYZE_NORMALS: + return MeshModel::MM_GEOMETRY_AND_TOPOLOGY_CHANGE; + case FP_SELECT_VISIBLE_FACES: + return MeshModel::MM_FACEFLAGSELECT; + } + + return MeshModel::MM_VERTQUALITY | MeshModel::MM_FACEQUALITY; +} + +/** + * @brief This function define the needed parameters for each filter. Return true if the filter has some parameters + * it is called every time, so you can set the default value of parameters according to the mesh + * For each parameter you need to define, + * - the name of the parameter, + * - the default value + * - the string shown in the dialog + * - a possibly long string describing the meaning of that parameter (shown as a popup help in the dialog) + * @param action + * @param m + * @param parlst + */ +RichParameterList FilterEmbreePlugin::initParameterList(const QAction *action,const MeshModel &m) +{ + RichParameterList parlst; + switch(ID(action)) { + case FP_OBSCURANCE : + parlst.addParam(RichInt("Rays", 64, "Number of rays", "The number of rays shoot from the barycenter of the face. The higher the number the higher the definition of the ambient obscurance but at the cost of the calculation time ")); + parlst.addParam(RichFloat("TAU",0.1f,"Tau value", "The value to control spatial decay, the higher the value, the grater the influence that the distance (where the ray hits another face) has on the result ")); + break; + case FP_AMBIENT_OCCLUSION: + parlst.addParam(RichInt("Rays", 64, "Number of rays", "The number of rays shoot from the barycenter of the face. The higher the number the higher the definition of the ambient occlusion but at the cost of the calculation time ")); + break; + case FP_SDF: + parlst.addParam(RichInt("Rays", 64, "Number of rays", "The number of rays shoot from the barycenter of the face. The higher the number the higher the definition of the SDF but at the cost of the calculation time")); + parlst.addParam(RichFloat("cone_amplitude",90.0f,"Cone amplitude ", "The value for the angle (in degrees) of the cone for which we consider a ray shooting direction as a valid direction")); + + break; + case FP_SELECT_VISIBLE_FACES: + parlst.addParam(RichDirection("dir", Point3f(1.0f, 1.0f, 0.0f), "Direction", "This values indicates the direction of the shadows")); + parlst.addParam(RichBool("incrementalSelection", false, "don't clean selection", "If checked, any previous selection of the faces will not be reset")); + break; + case FP_ANALYZE_NORMALS: + parlst.addParam(RichInt("Rays", 64, "Number of rays", "The number of rays shoot from the barycenter of the face. The higher the number the higher the definition of the normal analysis but at the cost of the calculation time")); + parlst.addParam(RichBool("parity_sampling", false, "Parity Sampling", "If checked, the normal analysis will be performed using the parity sampling algorithm. This algorithm is slower than the visibility sampling but works better with some models")); + break; + default : + break; + } + return parlst; +} + +/** + * @brief The Real Core Function doing the actual mesh processing. + * @param action + * @param md: an object containing all the meshes and rasters of MeshLab + * @param par: the set of parameters of each filter + * @param cb: callback object to tell MeshLab the percentage of execution of the filter + * @return true if the filter has been applied correctly, false otherwise + */ +std::map FilterEmbreePlugin::applyFilter(const QAction * action, const RichParameterList & parameters, MeshDocument &md, unsigned int& /*postConditionMask*/, vcg::CallBackPos *cb) +{ + + MeshModel *m = md.mm(); + EmbreeAdaptor adaptor = EmbreeAdaptor(m->cm); + + switch(ID(action)) { + case FP_OBSCURANCE: + m->updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY | MeshModel::MM_FACEQUALITY | MeshModel::MM_FACECOLOR); + adaptor.computeObscurance(m->cm, parameters.getInt("Rays"), parameters.getFloat("TAU")); + tri::UpdateQuality::VertexFromFace(m->cm); + tri::UpdateColor::PerVertexQualityGray(m->cm); + break; + case FP_AMBIENT_OCCLUSION: + m->updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY | MeshModel::MM_FACEQUALITY | MeshModel::MM_FACECOLOR); + adaptor.computeAmbientOcclusion(m->cm,parameters.getInt("Rays")); + tri::UpdateQuality::VertexFromFace(m->cm); + tri::UpdateColor::PerVertexQualityGray(m->cm); + break; + case FP_SDF: + m->updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY | MeshModel::MM_FACEQUALITY | MeshModel::MM_FACECOLOR); + adaptor.computeSDF(m->cm,parameters.getInt("Rays"), parameters.getFloat("cone_amplitude")); + tri::UpdateQuality::VertexFromFace(m->cm); + tri::UpdateColor::PerVertexQualityRamp(m->cm); + break; + case FP_SELECT_VISIBLE_FACES: + m->updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY | MeshModel::MM_FACEQUALITY | MeshModel::MM_FACECOLOR); + adaptor.selectVisibleFaces(m->cm,parameters.getPoint3m("dir"), parameters.getBool("incrementalSelection")); + break; + case FP_ANALYZE_NORMALS: + adaptor.computeNormalAnalysis(m->cm,parameters.getInt("Rays"), parameters.getBool("parity_sampling")); + //tri::UpdateNormal::PerVertexNormalizedPerFace(m->cm); + m->updateBoxAndNormals(); + break; + default : + wrongActionCalled(action); + } + + return std::map(); + +} + +MESHLAB_PLUGIN_NAME_EXPORTER(FilterEmbreePlugin) diff --git a/src/common/parameters/value.cpp b/src/meshlabplugins/filter_embree/filter_embree.h similarity index 53% rename from src/common/parameters/value.cpp rename to src/meshlabplugins/filter_embree/filter_embree.h index e5dff7899..276dbe7f8 100644 --- a/src/common/parameters/value.cpp +++ b/src/meshlabplugins/filter_embree/filter_embree.h @@ -2,13 +2,13 @@ * MeshLab o o * * A versatile mesh processing toolbox o o * * _ O _ * -* Copyright(C) 2004-2021 \/)\/ * +* Copyright(C) 2005 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * -* This program is free software; you can redistribute it and/or modify * +* This program 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. * @@ -21,55 +21,56 @@ * * ****************************************************************************/ -#include "value.h" +/**************************************************************************** +History +$Log: sampleplugins.h,v $ -#include "../ml_document/mesh_document.h" +Revision 0 +Created filter for Embree By Paolo Fasano p.fasano99@hotmail.com -void BoolValue::fillToXMLElement(QDomElement& element) const +****************************************************************************/ + +#ifndef FILTEREMBREE_PLUGIN_H +#define FILTEREMBREE_PLUGIN_H + +#include +#include + +class FilterEmbreePlugin : public QObject, public FilterPlugin { - QString v = pval ? "true" : "false"; - element.setAttribute("value", v); -} + Q_OBJECT + MESHLAB_PLUGIN_IID_EXPORTER(FILTER_PLUGIN_IID) + Q_INTERFACES(FilterPlugin) -void IntValue::fillToXMLElement(QDomElement& element) const -{ - element.setAttribute("value", QString::number(pval)); -} +public: + enum { + FP_OBSCURANCE, + FP_AMBIENT_OCCLUSION, + FP_SDF, + FP_SELECT_VISIBLE_FACES, + FP_ANALYZE_NORMALS + } ; -void FloatValue::fillToXMLElement(QDomElement& element) const -{ - element.setAttribute("value", QString::number(pval)); -} + FilterEmbreePlugin(); + ~FilterEmbreePlugin(); -void StringValue::fillToXMLElement(QDomElement& element) const -{ - element.setAttribute("value", pval); -} + QString pluginName() const; -void Matrix44fValue::fillToXMLElement(QDomElement& element) const -{ - for(unsigned int ii = 0;ii < 16;++ii) - element.setAttribute(QString("val")+QString::number(ii),QString::number(pval.V()[ii])); -} + QString filterName(ActionIDType filter) const; + QString pythonFilterName(ActionIDType f) const; + QString filterInfo(ActionIDType filter) const; + FilterClass getClass(const QAction* a) const; + FilterArity filterArity(const QAction*) const; + int getPreConditions(const QAction *) const; + int postCondition(const QAction* ) const; + RichParameterList initParameterList(const QAction*, const MeshModel &/*m*/); + std::map applyFilter( + const QAction* action, + const RichParameterList & parameters, + MeshDocument &md, + unsigned int& postConditionMask, + vcg::CallBackPos * cb); -void Point3fValue::fillToXMLElement(QDomElement& element) const -{ - element.setAttribute("x",QString::number(pval.X())); - element.setAttribute("y",QString::number(pval.Y())); - element.setAttribute("z",QString::number(pval.Z())); -} - -void ShotfValue::fillToXMLElement(QDomElement&) const -{ - assert(0); - //TODO!!! -} - -void ColorValue::fillToXMLElement(QDomElement& element) const -{ - element.setAttribute("r",QString::number(pval.red())); - element.setAttribute("g",QString::number(pval.green())); - element.setAttribute("b",QString::number(pval.blue())); - element.setAttribute("a",QString::number(pval.alpha())); -} +}; +#endif diff --git a/src/meshlabplugins/filter_fractal/filter_fractal.cpp b/src/meshlabplugins/filter_fractal/filter_fractal.cpp index 1a6c33f30..33d683888 100644 --- a/src/meshlabplugins/filter_fractal/filter_fractal.cpp +++ b/src/meshlabplugins/filter_fractal/filter_fractal.cpp @@ -213,7 +213,7 @@ void FilterFractal::initParameterSetForFractalDisplacement(const QAction *filter par.addParam(RichDynamicFloat("maxHeight", 0.2f, 0.0f, 1.0f, "Max height:", "Defines the maximum perturbation height as a fraction of the terrain's side.")); } else { float diag = md.mm()->cm.bbox.Diag(); - par.addParam(RichAbsPerc("maxHeight", 0.02 * diag, 0, 0.5*diag, "Max height:", "Defines the maximum height for the perturbation.")); + par.addParam(RichPercentage("maxHeight", 0.02 * diag, 0, 0.5*diag, "Max height:", "Defines the maximum height for the perturbation.")); } par.addParam(RichDynamicFloat("scale", 1.0f, 0.0f, 10.0f, "Scale factor:", "Scales the fractal perturbation in and out. Values larger than 1 mean zoom out; values smaller than one mean zoom in.")); diff --git a/src/meshlabplugins/filter_func/filter_func.cpp b/src/meshlabplugins/filter_func/filter_func.cpp index dde18d949..530f15e60 100644 --- a/src/meshlabplugins/filter_func/filter_func.cpp +++ b/src/meshlabplugins/filter_func/filter_func.cpp @@ -22,17 +22,33 @@ ****************************************************************************/ #include "filter_func.h" +#include #include - #include #include #include "muParser.h" #include "string_conversion.h" +#include + using namespace mu; using namespace vcg; +std::random_device randomDev; +std::default_random_engine rndEngine(randomDev()); +//Function to generate a random double number in [0..1) interval +double ML_Rnd() { return std::generate_canonical(rndEngine); } +//Function to generate a random integer number in [0..a) interval +double ML_RandInt(const double a) { return std::floor(a*ML_Rnd()); } + +//Add rnd() and randint() custom functions to a mu::Parser +void setCustomFunctions(mu::Parser& p) +{ + p.DefineFun("rnd", ML_Rnd); + p.DefineFun("randInt", ML_RandInt); +} + // Constructor FilterFunctionPlugin::FilterFunctionPlugin() { @@ -46,6 +62,7 @@ FilterFunctionPlugin::FilterFunctionPlugin() FF_VERT_COLOR, FF_VERT_QUALITY, FF_VERT_NORMAL, + FF_FACE_NORMAL, FF_FACE_QUALITY, FF_DEF_VERT_SCALAR_ATTRIB, FF_DEF_FACE_SCALAR_ATTRIB, @@ -82,6 +99,7 @@ QString FilterFunctionPlugin::filterName(ActionIDType filterId) const case FF_VERT_TEXTURE_FUNC: return QString("Per Vertex Texture Function"); case FF_WEDGE_TEXTURE_FUNC: return QString("Per Wedge Texture Function"); case FF_VERT_NORMAL: return QString("Per Vertex Normal Function"); + case FF_FACE_NORMAL: return QString("Per Face Normal Function"); case FF_DEF_VERT_SCALAR_ATTRIB: return QString("Define New Per Vertex Custom Scalar Attribute"); case FF_DEF_FACE_SCALAR_ATTRIB: return QString("Define New Per Face Custom Scalar Attribute"); case FF_DEF_VERT_POINT_ATTRIB: return QString("Define New Per Vertex Custom Point Attribute"); @@ -107,6 +125,7 @@ QString FilterFunctionPlugin::pythonFilterName(ActionIDType f) const case FF_VERT_TEXTURE_FUNC: return QString("compute_texcoord_by_function_per_vertex"); case FF_WEDGE_TEXTURE_FUNC: return QString("compute_texcoord_by_function_per_wedge"); case FF_VERT_NORMAL: return QString("compute_normal_by_function_per_vertex"); + case FF_FACE_NORMAL: return QString("compute_normal_by_function_per_face"); case FF_DEF_VERT_SCALAR_ATTRIB: return QString("compute_new_custom_scalar_attribute_per_vertex"); case FF_DEF_FACE_SCALAR_ATTRIB: return QString("compute_new_custom_scalar_attribute_per_face"); case FF_DEF_VERT_POINT_ATTRIB: return QString("compute_new_custom_point_attribute_per_vertex"); @@ -120,29 +139,47 @@ QString FilterFunctionPlugin::pythonFilterName(ActionIDType f) const } const QString PossibleOperators( - "
It's possible to use parenthesis (), and predefined operators:
" + "
It's possible to use any of the predefined muparser built-in " + "operators and " + "functions, like: " "&& (logic and), || (logic or), <, <=, >, >=, " - "!= (not equal), == (equal), _?_:_ (c/c++ ternary operator)

"); + "!= (not equal), == (equal), _?_:_ (c/c++ ternary operator), and " + "rnd() (random value in [0..1]), and these values:" ); const QString PerVertexAttributeString( - "It's possible to use the following per-vertex variables in the expression:
" + "
  • Per-vertex variables:
    " "x,y,z (position), nx,ny,nz (normal), r,g,b,a (color), q " "(quality), vi (vertex index), vtu,vtv,ti (texture coords and texture " - "index), vsel (is the vertex selected? 1 yes, 0 no) " - "and all custom vertex attributes already defined by user.
    "); + "index), vsel ( 1 if selected, 0 if not selected)." + "
  • Bounding Box variables:
    " + "xmin,ymin,zmin (min coordinates), xmax,ymax,zmax (max coordinates), " + "xmid,ymid,zmid (midpoint coordinates), xdim,ydim,zdim (dimensions), " + "bbdiag (diagonal length)" + "
  • User-defined attributes:
    " + "All user defined custom vertex attributes are available. " + "Point3 attribute are available as 3 variables with _x, _y, _z appended to the attribute name." + "
"); const QString PerFaceAttributeString( - "It's possible to use the following per-face variables, or variables associated to the three " - "vertex of every face:
" - "x0,y0,z0 for the first vertex position, x1,y1,z1 for the second vertex " - "position, x2,y2,z2 for the third vertex position, " - "nx0,ny0,nz0 nx1,ny1,nz1 nx2,ny2,nz2 for vertex normals, r0,g0,b0,a0 r1,g1,b1,a1 " - "r2,g2,b2,a2 for vertex colors, vi0, vi1, vi2 for vertex indices, " - "q0,q1,q2 for vertex quality, wtu0,wtv0 wtu1,wtv1 wtu2,wtv2 for per-wedge " - "texture coords, ti for face texture index, vsel0,vsel1,vsel2 for vertex " - "selection (1 yes, 0 no) " - "fi for face index, fr,fg,fb,fa for face color, fq for face quality, " - "fnx,fny,fnz for face normal, fsel face selection (1 yes, 0 no).
"); + "
  • Per-face variables:
    " + "fi (face index), fr,fg,fb,fa (face color), fq (face quality), " + "fnx,fny,fnz (face normal), fsel ( 1 if face is selected, 0 if not selected)." + "
  • Per-vertex variables:
    " + "x0,y0,z0 (first vertex position), x1,y1,z1 (second vertex position)," + "x2,y2,z2 (third vertex position), " + "nx0,ny0,nz0 nx1,ny1,nz1 nx2,ny2,nz2 (vertex normals), r0,g0,b0,a0 r1,g1,b1,a1 " + "r2,g2,b2,a2 (vertex colors), vi0, vi1, vi2 (vertex indices), " + "q0,q1,q2 (vertex quality), wtu0,wtv0 wtu1,wtv1 wtu2,wtv2 (per-wedge texture coords), " + "ti (face texture index), vsel0,vsel1,vsel2 (1 if vertex is selected, 0 if not)." + "
  • Bounding Box variables:
    " + "xmin,ymin,zmin (min coordinates), xmax,ymax,zmax (max coordinates), " + "xmid,ymid,zmid (midpoint coordinates), xdim,ydim,zdim (dimensions), " + "bbdiag (diagonal length)." + "
  • User-defined attributes:
    " + "All user defined custom face scalar attributes are available. " + "Point3 attribute are available as 3 variables with _x, _y, _z appended to the attribute name." + "
"); + // long string describing each filtering action QString FilterFunctionPlugin::filterInfo(ActionIDType filterId) const @@ -185,11 +222,15 @@ QString FilterFunctionPlugin::filterInfo(ActionIDType filterId) const return tr("Texture function using muparser to generate new texture coords for every " "vertex
") + PerVertexAttributeString; - + case FF_VERT_NORMAL: return tr("Normal function using muparser to generate new Normal for every vertex
") + PerVertexAttributeString; - + + case FF_FACE_NORMAL: + return tr("Normal function using muparser to generate new Normal for every face
") + + PerFaceAttributeString; + case FF_FACE_QUALITY: return tr("Quality function using muparser to generate new Quality for every face
" "Insert three function each one for quality of the three vertex of a face
") + @@ -262,6 +303,7 @@ FilterFunctionPlugin::FilterClass FilterFunctionPlugin::getClass(const QAction* case FF_VERT_TEXTURE_FUNC: return FilterPlugin::Texture; case FF_VERT_COLOR: return FilterPlugin::VertexColoring; case FF_VERT_NORMAL: return FilterPlugin::Normal; + case FF_FACE_NORMAL: return FilterPlugin::Normal; case FF_FACE_COLOR: return FilterPlugin::FaceColoring; case FF_WEDGE_TEXTURE_FUNC: return FilterPlugin::Texture; case FF_ISOSURFACE: return FilterPlugin::MeshCreation; @@ -288,6 +330,7 @@ int FilterFunctionPlugin::postCondition(const QAction* action) const return MeshModel::MM_VERTCOORD + MeshModel::MM_VERTNORMAL + MeshModel::MM_FACENORMAL; case FF_VERT_COLOR: return MeshModel::MM_VERTCOLOR; case FF_VERT_NORMAL: return MeshModel::MM_VERTNORMAL; + case FF_FACE_NORMAL: return MeshModel::MM_FACENORMAL; case FF_VERT_TEXTURE_FUNC: return MeshModel::MM_VERTTEXCOORD; case FF_WEDGE_TEXTURE_FUNC: return MeshModel::MM_WEDGTEXCOORD; case FF_VERT_QUALITY: return MeshModel::MM_VERTQUALITY + MeshModel::MM_VERTCOLOR; @@ -317,6 +360,7 @@ int FilterFunctionPlugin::getRequirements(const QAction* action) case FF_GEOM_FUNC: case FF_VERT_COLOR: case FF_VERT_NORMAL: + case FF_FACE_NORMAL: case FF_VERT_QUALITY: case FF_VERT_TEXTURE_FUNC: case FF_DEF_VERT_SCALAR_ATTRIB: @@ -379,7 +423,7 @@ RichParameterList FilterFunctionPlugin::initParameterList(const QAction* action, "only on selection", "if checked, only affects selected vertices")); break; - + case FF_VERT_NORMAL: parlst.addParam(RichString( "x", "-nx", "func nx = ", "insert function to generate new x for the normal")); @@ -393,7 +437,21 @@ RichParameterList FilterFunctionPlugin::initParameterList(const QAction* action, "only on selection", "if checked, only affects selected vertices")); break; - + + case FF_FACE_NORMAL: + parlst.addParam(RichString( + "x", "-fnx", "func nx = ", "insert function to generate new x for the normal")); + parlst.addParam(RichString( + "y", "-fny", "func ny = ", "insert function to generate new y for the normal")); + parlst.addParam(RichString( + "z", "-fnz", "func nz = ", "insert function to generate new z for the normal")); + parlst.addParam(RichBool( + "onselected", + false, + "only on selection", + "if checked, only affects selected vertices")); + break; + case FF_VERT_COLOR: parlst.addParam(RichString( "x", "255", "func r = ", "function to generate Red component. Expected Range 0-255")); @@ -667,6 +725,24 @@ std::map FilterFunctionPlugin::applyFilter( md.addNewMesh("", this->filterName(ID(filter))); MeshModel& m = *(md.mm()); Q_UNUSED(cb); + + //Set values to parser variables related to BBox + const auto &bbox = m.cm.bbox; + xmin = bbox.min.X(); + ymin = bbox.min.Y(); + zmin = bbox.min.Z(); + xmax = bbox.max.X(); + ymax = bbox.max.Y(); + zmax = bbox.max.Z(); + xdim = bbox.DimX(); + ydim = bbox.DimY(); + zdim = bbox.DimZ(); + bbdiag = bbox.Diag(); + auto bbCenter = bbox.Center(); + xmid = bbCenter.X(); + ymid = bbCenter.Y(); + zmid = bbCenter.Z(); + switch (ID(filter)) { case FF_VERT_SELECTION: { std::string expr = par.getString("condSelect").toStdString(); @@ -674,7 +750,9 @@ std::map FilterFunctionPlugin::applyFilter( // muparser initialization and explicitly define parser variables Parser p; + setPerVertexVariables(p, m.cm); + setCustomFunctions(p); // set expression inserted by user as string (required by muparser) p.SetExpr(wexpr); @@ -720,7 +798,8 @@ std::map FilterFunctionPlugin::applyFilter( // muparser initialization and explicitly define parser variables Parser p; setPerFaceVariables(p, m.cm); - + setCustomFunctions(p); + // set expression inserted by user as string (required by muparser) p.SetExpr(conversion::fromStringToWString(select.toStdString())); @@ -788,12 +867,16 @@ std::map FilterFunctionPlugin::applyFilter( // muparser initialization and explicitly define parser variables // function for x,y and z must use different parser and variables Parser p1, p2, p3, p4; - setPerVertexVariables(p1, m.cm); setPerVertexVariables(p2, m.cm); setPerVertexVariables(p3, m.cm); setPerVertexVariables(p4, m.cm); + setCustomFunctions(p1); + setCustomFunctions(p2); + setCustomFunctions(p3); + setCustomFunctions(p4); + p1.SetExpr(conversion::fromStringToWString(func_x)); p2.SetExpr(conversion::fromStringToWString(func_y)); p3.SetExpr(conversion::fromStringToWString(func_z)); @@ -889,6 +972,9 @@ std::map FilterFunctionPlugin::applyFilter( Parser p; setPerVertexVariables(p, m.cm); + //Add rnd() and randInt() internal functions + setCustomFunctions(p); + // set expression to calc with parser p.SetExpr(conversion::fromStringToWString(func_q)); @@ -948,6 +1034,8 @@ std::map FilterFunctionPlugin::applyFilter( Parser pu, pv; setPerVertexVariables(pu, m.cm); setPerVertexVariables(pv, m.cm); + setCustomFunctions(pu); + setCustomFunctions(pv); // set expression to calc with parser #ifdef _UNICODE @@ -1006,6 +1094,12 @@ std::map FilterFunctionPlugin::applyFilter( setPerFaceVariables(pv1, m.cm); setPerFaceVariables(pu2, m.cm); setPerFaceVariables(pv2, m.cm); + setCustomFunctions(pu0); + setCustomFunctions(pv0); + setCustomFunctions(pu1); + setCustomFunctions(pv1); + setCustomFunctions(pu2); + setCustomFunctions(pv2); // set expression to calc with parser pu0.SetExpr(conversion::fromStringToWString(func_u0)); @@ -1038,6 +1132,75 @@ std::map FilterFunctionPlugin::applyFilter( } log("%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC); + } break; + case FF_FACE_NORMAL: { + std::string func_nx = par.getString("x").toStdString(); + std::string func_ny = par.getString("y").toStdString(); + std::string func_nz = par.getString("z").toStdString(); + bool onSelected = par.getBool("onselected"); + if (onSelected && m.cm.sfn == 0) // if no selection, fail + { + log("Cannot apply only on selection: there is no selection"); + throw MLException("Cannot apply only on selection: there is no selection"); + } + m.updateDataMask(MeshModel::MM_FACENORMAL); + Parser p_nx, p_ny, p_nz; + + setPerFaceVariables(p_nx, m.cm); + setPerFaceVariables(p_ny, m.cm); + setPerFaceVariables(p_nz, m.cm); + setCustomFunctions(p_nx); + setCustomFunctions(p_ny); + setCustomFunctions(p_nz); + + p_nx.SetExpr(conversion::fromStringToWString(func_nx)); + p_ny.SetExpr(conversion::fromStringToWString(func_ny)); + p_nz.SetExpr(conversion::fromStringToWString(func_nz)); + + + double nx = 0, ny = 0, nz = 0; + errorMsg = ""; + + time_t start = clock(); + + // every parser variables is related to face attributes. + for (CMeshO::FaceIterator fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi) + if (!(*fi).IsD()) + if ((!onSelected) || ((*fi).IsS())) { + setAttributes(fi, m.cm); + + // evaluate functions to generate new color + // in case of fail, error dialog contains details of parser's error + try { + nx = p_nx.Eval(); + } + catch (Parser::exception_type& e) { + showParserError("func nx: ", e); + } + try { + ny = p_ny.Eval(); + } + catch (Parser::exception_type& e) { + showParserError("func ny: ", e); + } + try { + nz = p_nz.Eval(); + } + catch (Parser::exception_type& e) { + showParserError("func nz: ", e); + } + + if (errorMsg != "") + throw MLException(errorMsg); + + // set new color for this iteration + (*fi).N() = Point3m(nx,ny,nz); + } + + // if succeeded log stream contains number of vertices processed and time elapsed + log("%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC); + + } break; case FF_FACE_COLOR: { std::string func_r = par.getString("r").toStdString(); @@ -1062,6 +1225,10 @@ std::map FilterFunctionPlugin::applyFilter( setPerFaceVariables(p2, m.cm); setPerFaceVariables(p3, m.cm); setPerFaceVariables(p4, m.cm); + setCustomFunctions(p1); + setCustomFunctions(p2); + setCustomFunctions(p3); + setCustomFunctions(p4); p1.SetExpr(conversion::fromStringToWString(func_r)); p2.SetExpr(conversion::fromStringToWString(func_g)); @@ -1135,6 +1302,7 @@ std::map FilterFunctionPlugin::applyFilter( // muparser initialization and define custom variables Parser pf; setPerFaceVariables(pf, m.cm); + setCustomFunctions(pf); // set expression to calc with parser pf.SetExpr(conversion::fromStringToWString(func_q)); @@ -1194,6 +1362,7 @@ std::map FilterFunctionPlugin::applyFilter( Parser p; setPerVertexVariables(p, m.cm); + setCustomFunctions(p); p.SetExpr(conversion::fromStringToWString(expr)); @@ -1246,6 +1415,7 @@ std::map FilterFunctionPlugin::applyFilter( h = tri::Allocator::AddPerFaceAttribute(m.cm, name); Parser p; setPerFaceVariables(p, m.cm); + setCustomFunctions(p); p.SetExpr(conversion::fromStringToWString(expr)); time_t start = clock(); @@ -1292,6 +1462,10 @@ std::map FilterFunctionPlugin::applyFilter( setPerVertexVariables(p_x, m.cm); setPerVertexVariables(p_y, m.cm); setPerVertexVariables(p_z, m.cm); + setCustomFunctions(p_x); + setCustomFunctions(p_y); + setCustomFunctions(p_z); + p_x.SetExpr(conversion::fromStringToWString(x_expr)); p_y.SetExpr(conversion::fromStringToWString(y_expr)); p_z.SetExpr(conversion::fromStringToWString(z_expr)); @@ -1351,6 +1525,9 @@ std::map FilterFunctionPlugin::applyFilter( setPerFaceVariables(p_x, m.cm); setPerFaceVariables(p_y, m.cm); setPerFaceVariables(p_z, m.cm); + setCustomFunctions(p_x); + setCustomFunctions(p_y); + setCustomFunctions(p_z); p_x.SetExpr(conversion::fromStringToWString(x_expr)); p_y.SetExpr(conversion::fromStringToWString(y_expr)); p_z.SetExpr(conversion::fromStringToWString(z_expr)); @@ -1432,6 +1609,8 @@ std::map FilterFunctionPlugin::applyFilter( Parser p; double x, y, z; + setCustomFunctions(p); + p.DefineVar(conversion::fromStringToWString("x"), &x); p.DefineVar(conversion::fromStringToWString("y"), &y); p.DefineVar(conversion::fromStringToWString("z"), &z); @@ -1659,6 +1838,22 @@ void FilterFunctionPlugin::setAttributes(CMeshO::FaceIterator& fi, CMeshO& m) // set variables to explicit value obtained through attribute's handler for (int i = 0; i < (int) f_attrValue.size(); i++) f_attrValue[i] = f_handlers[i][fi]; + + for (int i = 0; i < (int) f3_handlers.size(); i++) { + f3_attrValue[i * 3 + 0] = f3_handlers[i][fi].X(); + f3_attrValue[i * 3 + 1] = f3_handlers[i][fi].Y(); + f3_attrValue[i * 3 + 2] = f3_handlers[i][fi].Z(); + } + +} + + // Generate a random double in [0.0, 1.0] interval +double FilterFunctionPlugin::random() +{ + std::random_device rd; // Seed for the random number engine + std::mt19937 gen(rd()); // Mersenne Twister engine + std::uniform_real_distribution dis(0.0, 1.0); + return dis(gen); // Generate a random double in [0.0, 1.0] } // Function explicitly define parser variables to perform per-vertex filter action @@ -1683,16 +1878,32 @@ void FilterFunctionPlugin::setPerVertexVariables(Parser& p, CMeshO& m) p.DefineVar(conversion::fromStringToWString("ti"), &ti); p.DefineVar(conversion::fromStringToWString("vsel"), &vsel); + //Add tokens related to mesh bounding box + p.DefineVar(conversion::fromStringToWString("xmin"), &xmin); + p.DefineVar(conversion::fromStringToWString("ymin"), &ymin); + p.DefineVar(conversion::fromStringToWString("zmin"), &zmin); + p.DefineVar(conversion::fromStringToWString("xmax"), &xmax); + p.DefineVar(conversion::fromStringToWString("ymax"), &ymax); + p.DefineVar(conversion::fromStringToWString("zmax"), &zmax); + p.DefineVar(conversion::fromStringToWString("bbdiag"), &bbdiag); + p.DefineVar(conversion::fromStringToWString("xdim"), &xdim); + p.DefineVar(conversion::fromStringToWString("ydim"), &ydim); + p.DefineVar(conversion::fromStringToWString("zdim"), &zdim); + p.DefineVar(conversion::fromStringToWString("xmid"), &xmid); + p.DefineVar(conversion::fromStringToWString("ymid"), &ymid); + p.DefineVar(conversion::fromStringToWString("zmid"), &zmid); + + //Add function rnd() + p.DefineFun("rnd", random); + // define var for user-defined attributes (if any exists) // if vector is empty, code won't be executed v_handlers.clear(); v_attrNames.clear(); v_attrValue.clear(); - v3_handlers.clear(); - v3_attrNames.clear(); - v3_attrValue.clear(); std::vector AllVertexAttribName; tri::Allocator::GetAllPerVertexAttribute(m, AllVertexAttribName); + v_attrValue.reserve(AllVertexAttribName.size()); for (int i = 0; i < (int) AllVertexAttribName.size(); i++) { CMeshO::PerVertexAttributeHandle hh = tri::Allocator::GetPerVertexAttribute(m, AllVertexAttribName[i]); @@ -1703,7 +1914,11 @@ void FilterFunctionPlugin::setPerVertexVariables(Parser& p, CMeshO& m) qDebug("Adding custom per vertex float variable %s", v_attrNames.back().c_str()); } AllVertexAttribName.clear(); + v3_handlers.clear(); + v3_attrNames.clear(); + v3_attrValue.clear(); tri::Allocator::GetAllPerVertexAttribute(m, AllVertexAttribName); + v3_attrValue.reserve(AllVertexAttribName.size()); for (int i = 0; i < (int) AllVertexAttribName.size(); i++) { CMeshO::PerVertexAttributeHandle hh3 = tri::Allocator::GetPerVertexAttribute(m, AllVertexAttribName[i]); @@ -1809,13 +2024,33 @@ void FilterFunctionPlugin::setPerFaceVariables(Parser& p, CMeshO& m) p.DefineVar(conversion::fromStringToWString("vsel2"), &vsel2); p.DefineVar(conversion::fromStringToWString("fsel"), &fsel); + //Add tokens related to mesh bounding box + p.DefineVar(conversion::fromStringToWString("xmin"), &xmin); + p.DefineVar(conversion::fromStringToWString("ymin"), &ymin); + p.DefineVar(conversion::fromStringToWString("zmin"), &zmin); + p.DefineVar(conversion::fromStringToWString("xmax"), &xmax); + p.DefineVar(conversion::fromStringToWString("ymax"), &ymax); + p.DefineVar(conversion::fromStringToWString("zmax"), &zmax); + p.DefineVar(conversion::fromStringToWString("bbdiag"), &bbdiag); + p.DefineVar(conversion::fromStringToWString("xdim"), &xdim); + p.DefineVar(conversion::fromStringToWString("ydim"), &ydim); + p.DefineVar(conversion::fromStringToWString("zdim"), &zdim); + p.DefineVar(conversion::fromStringToWString("xmid"), &xmid); + p.DefineVar(conversion::fromStringToWString("ymid"), &ymid); + p.DefineVar(conversion::fromStringToWString("zmid"), &zmid); + + //Add function rnd() + p.DefineFun("rnd", random); + // define var for user-defined attributes (if any exists) // if vector is empty, code won't be executed - std::vector AllFaceAttribName; - tri::Allocator::GetAllPerFaceAttribute(m, AllFaceAttribName); f_handlers.clear(); f_attrNames.clear(); f_attrValue.clear(); + std::vector AllFaceAttribName; + tri::Allocator::GetAllPerFaceAttribute(m, AllFaceAttribName); + f_attrValue.reserve(AllFaceAttribName.size()); + qDebug("Searching for Scalar Face Attributes (%lu)",AllFaceAttribName.size()); for (int i = 0; i < (int) AllFaceAttribName.size(); i++) { CMeshO::PerFaceAttributeHandle hh = tri::Allocator::GetPerFaceAttribute(m, AllFaceAttribName[i]); @@ -1824,6 +2059,32 @@ void FilterFunctionPlugin::setPerFaceVariables(Parser& p, CMeshO& m) f_attrValue.push_back(0); p.DefineVar(conversion::fromStringToWString(f_attrNames.back()), &f_attrValue.back()); } + AllFaceAttribName.clear(); + f3_handlers.clear(); + f3_attrNames.clear(); + f3_attrValue.clear(); + tri::Allocator::GetAllPerFaceAttribute(m, AllFaceAttribName); + f3_attrValue.reserve(AllFaceAttribName.size()); + qDebug("Searching for Point3 Face Attributes (%lu)",AllFaceAttribName.size()); + for (int i = 0; i < (int) AllFaceAttribName.size(); i++) { + CMeshO::PerFaceAttributeHandle hh3 = + tri::Allocator::GetPerFaceAttribute(m, AllFaceAttribName[i]); + + f3_handlers.push_back(hh3); + + f3_attrValue.push_back(0); + f3_attrNames.push_back(AllFaceAttribName[i] + "_x"); + p.DefineVar(conversion::fromStringToWString(f3_attrNames.back()), &f3_attrValue.back()); + + f3_attrValue.push_back(0); + f3_attrNames.push_back(AllFaceAttribName[i] + "_y"); + p.DefineVar(conversion::fromStringToWString(f3_attrNames.back()), &f3_attrValue.back()); + + f3_attrValue.push_back(0); + f3_attrNames.push_back(AllFaceAttribName[i] + "_z"); + p.DefineVar(conversion::fromStringToWString(f3_attrNames.back()), &f3_attrValue.back()); + qDebug("Adding custom per face Point3f variable %s", f3_attrNames.back().c_str()); + } } void FilterFunctionPlugin::checkAttributeName(const std::string &name) const @@ -1853,6 +2114,7 @@ FilterPlugin::FilterArity FilterFunctionPlugin::filterArity(const QAction* filte case FF_VERT_TEXTURE_FUNC: case FF_WEDGE_TEXTURE_FUNC: case FF_VERT_NORMAL: + case FF_FACE_NORMAL: case FF_DEF_VERT_SCALAR_ATTRIB: case FF_DEF_FACE_SCALAR_ATTRIB: case FF_REFINE: return FilterPlugin::SINGLE_MESH; diff --git a/src/meshlabplugins/filter_func/filter_func.h b/src/meshlabplugins/filter_func/filter_func.h index 26fee7f6f..c1ca56608 100644 --- a/src/meshlabplugins/filter_func/filter_func.h +++ b/src/meshlabplugins/filter_func/filter_func.h @@ -37,25 +37,38 @@ class FilterFunctionPlugin : public QObject, public FilterPlugin Q_INTERFACES(FilterPlugin) protected: + // These variables are used to store the actual values that can be used in side functions double x, y, z, nx, ny, nz, r, g, b, a, q, vtu, vtv, vsel; double x0, y0, z0, x1, y1, z1, x2, y2, z2, nx0, ny0, nz0, nx1, ny1, nz1, nx2, ny2, nz2, r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2, q0, q1, q2, wtu0, wtv0, wtu1, wtv1, wtu2, wtv2, vsel0, vsel1, vsel2; double fr, fg, fb, fa, fnx, fny, fnz, fq, fsel; double v, f, v0i, v1i, v2i, ti; + + //Bounding Box of the mesh + double xmin, ymin, zmin, xmax, ymax, zmax, xdim, ydim, zdim, bbdiag, xmid, ymid, zmid; + std::vector v_attrNames; // names of the per vertex attributes std::vector v_attrValue; // values of the per vertex attributes std::vector v3_attrNames; // names of the per vertex attributes There are // 3x (one foreach coord _x, _y, _z) std::vector v3_attrValue; // values of the per vertex attributes. There are 3x // (one foreach coord _x, _y, _z) - std::vector f_attrNames; - std::vector f_attrValue; + std::vector f_attrNames; // names of the per face attributes + std::vector f_attrValue; // values of the per face attributes + std::vector f3_attrNames; // names of the per face attributes + std::vector f3_attrValue; // values of the per face attributes + std::vector> v_handlers; std::vector> v3_handlers; std::vector> f_handlers; + std::vector> f3_handlers; + QString errorMsg; + // Generate a random double in [0.0, 1.0] interval + static double random(); + public: enum { FF_VERT_SELECTION, @@ -66,6 +79,7 @@ public: FF_FACE_COLOR, FF_VERT_COLOR, FF_VERT_NORMAL, + FF_FACE_NORMAL, FF_VERT_QUALITY, FF_FACE_QUALITY, FF_DEF_VERT_SCALAR_ATTRIB, diff --git a/src/meshlabplugins/filter_geodesic/filter_geodesic.cpp b/src/meshlabplugins/filter_geodesic/filter_geodesic.cpp index 47e2ff04f..dd600f699 100644 --- a/src/meshlabplugins/filter_geodesic/filter_geodesic.cpp +++ b/src/meshlabplugins/filter_geodesic/filter_geodesic.cpp @@ -44,7 +44,8 @@ FilterGeodesic::FilterGeodesic() typeList = { FP_QUALITY_BORDER_GEODESIC, FP_QUALITY_POINT_GEODESIC, - FP_QUALITY_SELECTED_GEODESIC + FP_QUALITY_SELECTED_GEODESIC, + FP_QUALITY_SELECTED_GEODESIC_HEAT }; for(ActionIDType tt : types()) @@ -67,6 +68,8 @@ QString FilterGeodesic::filterName(ActionIDType filter) const return QString("Colorize by geodesic distance from a given point"); case FP_QUALITY_SELECTED_GEODESIC: return QString("Colorize by geodesic distance from the selected points"); + case FP_QUALITY_SELECTED_GEODESIC_HEAT: + return QString("Colorize by approximated geodesic distance from the selected points"); default: assert(0); return QString(); } } @@ -79,6 +82,8 @@ QString FilterGeodesic::pythonFilterName(ActionIDType f) const return QString("compute_scalar_by_geodesic_distance_from_given_point_per_vertex"); case FP_QUALITY_SELECTED_GEODESIC: return QString("compute_scalar_by_geodesic_distance_from_selection_per_vertex"); + case FP_QUALITY_SELECTED_GEODESIC_HEAT: + return QString("compute_scalar_by_heat_geodesic_distance_from_selection_per_vertex"); default: assert(0); return QString(); } } @@ -87,9 +92,10 @@ QString FilterGeodesic::filterInfo(ActionIDType filterId) const { switch(filterId) { - case FP_QUALITY_BORDER_GEODESIC : return tr("Store in the quality field the geodesic distance from borders and color the mesh accordingly."); - case FP_QUALITY_POINT_GEODESIC : return tr("Store in the quality field the geodesic distance from a given point on the mesh surface and color the mesh accordingly."); - case FP_QUALITY_SELECTED_GEODESIC : return tr("Store in the quality field the geodesic distance from the selected points on the mesh surface and color the mesh accordingly."); + case FP_QUALITY_BORDER_GEODESIC : return tr("Store in the quality field the geodesic distance from borders and color the mesh accordingly."); + case FP_QUALITY_POINT_GEODESIC : return tr("Store in the quality field the geodesic distance from a given point on the mesh surface and color the mesh accordingly."); + case FP_QUALITY_SELECTED_GEODESIC : return tr("Store in the quality field the geodesic distance from the selected points on the mesh surface and color the mesh accordingly."); + case FP_QUALITY_SELECTED_GEODESIC_HEAT : return tr("Store in the quality field the approximated geodesic distance, computed via heat method (Crane et al.), from the selected points on the mesh surface and color the mesh accordingly. As this implementation does not use intrinsic triangulation it is very sensitive to trinagulation. First run takes longer as factorization has to be build. "); default : assert(0); } return QString("error!"); @@ -99,9 +105,10 @@ FilterGeodesic::FilterClass FilterGeodesic::getClass(const QAction *a) const { switch(ID(a)) { - case FP_QUALITY_BORDER_GEODESIC : - case FP_QUALITY_SELECTED_GEODESIC : - case FP_QUALITY_POINT_GEODESIC : return FilterGeodesic::FilterClass(FilterPlugin::VertexColoring + FilterPlugin::Quality); + case FP_QUALITY_BORDER_GEODESIC : + case FP_QUALITY_SELECTED_GEODESIC : + case FP_QUALITY_POINT_GEODESIC : + case FP_QUALITY_SELECTED_GEODESIC_HEAT : return FilterGeodesic::FilterClass(FilterPlugin::VertexColoring + FilterPlugin::Quality); default : assert(0); } return FilterPlugin::Generic; @@ -111,15 +118,16 @@ int FilterGeodesic::getRequirements(const QAction *action) { switch(ID(action)) { - case FP_QUALITY_BORDER_GEODESIC : - case FP_QUALITY_SELECTED_GEODESIC: - case FP_QUALITY_POINT_GEODESIC : return MeshModel::MM_VERTFACETOPO; + case FP_QUALITY_BORDER_GEODESIC : + case FP_QUALITY_SELECTED_GEODESIC : + case FP_QUALITY_POINT_GEODESIC : return MeshModel::MM_VERTFACETOPO; + case FP_QUALITY_SELECTED_GEODESIC_HEAT : return MeshModel::MM_VERTFACETOPO + MeshModel::MM_FACEFACETOPO; default: assert(0); } return 0; } -std::map FilterGeodesic::applyFilter(const QAction *filter, const RichParameterList & par, MeshDocument &md, unsigned int& /*postConditionMask*/, vcg::CallBackPos * /*cb*/) +std::map FilterGeodesic::applyFilter(const QAction *filter, const RichParameterList & par, MeshDocument &md, unsigned int& /*postConditionMask*/, vcg::CallBackPos *cb) { MeshModel &m=*(md.mm()); CMeshO::VertexIterator vi; @@ -236,7 +244,60 @@ std::map FilterGeodesic::applyFilter(const QAction *filte else log("Warning: no vertices are selected! aborting geodesic computation."); } - break; + break; + case FP_QUALITY_SELECTED_GEODESIC_HEAT: + { + m.updateDataMask(MeshModel::MM_FACEFACETOPO); + m.updateDataMask(MeshModel::MM_VERTFACETOPO); + m.updateDataMask(MeshModel::MM_FACEQUALITY); + m.updateDataMask(MeshModel::MM_FACENORMAL); + m.updateDataMask(MeshModel::MM_VERTQUALITY); + m.updateDataMask(MeshModel::MM_VERTCOLOR); + + std::vector seedVec; + ForEachVertex(m.cm, [&seedVec] (CMeshO::VertexType & v) { + if (v.IsS()) seedVec.push_back(&v); + }); + + float param_m = par.getFloat("m"); + + if (seedVec.size() > 0){ + // cache factorizations to reduce runtime on successive computations + std::pair::GeodesicHeatCache> cache; + if (!vcg::tri::HasPerMeshAttribute(m.cm, "GeodesicHeatCache")){ + cb(20, "Building Cache: Computing Factorizations..."); + cache = std::make_pair(param_m, tri::GeodesicHeat::BuildCache(m.cm, param_m)); + // save cache for next compute + auto GeodesicHeatCacheHandle = tri::Allocator::GetPerMeshAttribute::GeodesicHeatCache>>(m.cm, std::string("GeodesicHeatCache")); + GeodesicHeatCacheHandle() = cache; + } + else { + cb(10, "Recovering Cache..."); + // recover cache + auto GeodesicHeatCacheHandle = vcg::tri::Allocator::GetPerMeshAttribute::GeodesicHeatCache>>(m.cm, std::string("GeodesicHeatCache")); + // if m has changed rebuild everything + if (std::get<0>(GeodesicHeatCacheHandle()) != param_m){ + cb(20, "Parameter Changed: Rebuilding Factorizations..."); + GeodesicHeatCacheHandle() = std::make_pair(param_m, tri::GeodesicHeat::BuildCache(m.cm, param_m)); + } + cache = GeodesicHeatCacheHandle(); + } + cb(80, "Computing Geodesic Distance..."); + + if (tri::GeodesicHeat::ComputeFromCache(m.cm, seedVec, std::get<1>(cache))){ + tri::UpdateColor::PerVertexQualityRamp(m.cm); + } + else{ + log("Warning: heat method has failed. The mesh is most likely badly conditioned (e.g. angles ~ 0deg) or has disconnected components"); + // delete cache as its most likely useless after failure + auto GeodesicHeatCacheHandle = vcg::tri::Allocator::GetPerMeshAttribute::GeodesicHeatCache>>(m.cm, std::string("GeodesicHeatCache")); + tri::Allocator::DeletePerMeshAttribute::GeodesicHeatCache>>(m.cm, GeodesicHeatCacheHandle); + } + } + else + log("Warning: no vertices are selected! aborting geodesic computation."); + } + break; default: wrongActionCalled(filter); break; @@ -251,11 +312,14 @@ RichParameterList FilterGeodesic::initParameterList(const QAction *action, const { case FP_QUALITY_POINT_GEODESIC : parlst.addParam(RichPosition("startPoint",m.cm.bbox.min,"Starting point","The starting point from which geodesic distance has to be computed. If it is not a surface vertex, the closest vertex to the specified point is used as starting seed point.")); - parlst.addParam(RichAbsPerc("maxDistance",m.cm.bbox.Diag(),0,m.cm.bbox.Diag()*2,"Max Distance","If not zero it indicates a cut off value to be used during geodesic distance computation.")); + parlst.addParam(RichPercentage("maxDistance",m.cm.bbox.Diag(),0,m.cm.bbox.Diag()*2,"Max Distance","If not zero it indicates a cut off value to be used during geodesic distance computation.")); break; case FP_QUALITY_SELECTED_GEODESIC : - parlst.addParam(RichAbsPerc("maxDistance",m.cm.bbox.Diag(),0,m.cm.bbox.Diag()*2,"Max Distance","If not zero it indicates a cut off value to be used during geodesic distance computation.")); - break; + parlst.addParam(RichPercentage("maxDistance",m.cm.bbox.Diag(),0,m.cm.bbox.Diag()*2,"Max Distance","If not zero it indicates a cut off value to be used during geodesic distance computation.")); + break; + case FP_QUALITY_SELECTED_GEODESIC_HEAT : + parlst.addParam(RichFloat("m", 1.0, tr("Euler Step"), tr("Multiplier used in backward Euler timestep. Changing this value will reset the cache."))); + break; default: break; // do not add any parameter for the other filters } return parlst; @@ -265,10 +329,11 @@ int FilterGeodesic::postCondition(const QAction * filter) const { switch (ID(filter)) { - case FP_QUALITY_BORDER_GEODESIC : - case FP_QUALITY_SELECTED_GEODESIC : - case FP_QUALITY_POINT_GEODESIC : return MeshModel::MM_VERTCOLOR + MeshModel::MM_VERTQUALITY; - default : return MeshModel::MM_ALL; + case FP_QUALITY_BORDER_GEODESIC : + case FP_QUALITY_SELECTED_GEODESIC : + case FP_QUALITY_POINT_GEODESIC : return MeshModel::MM_VERTCOLOR + MeshModel::MM_VERTQUALITY; + case FP_QUALITY_SELECTED_GEODESIC_HEAT : return MeshModel::MM_VERTCOLOR + MeshModel::MM_VERTQUALITY + MeshModel::MM_FACEQUALITY; + default : return MeshModel::MM_ALL; } } MESHLAB_PLUGIN_NAME_EXPORTER(FilterGeodesic) diff --git a/src/meshlabplugins/filter_geodesic/filter_geodesic.h b/src/meshlabplugins/filter_geodesic/filter_geodesic.h index 6fe6d24c2..498b43aba 100644 --- a/src/meshlabplugins/filter_geodesic/filter_geodesic.h +++ b/src/meshlabplugins/filter_geodesic/filter_geodesic.h @@ -26,6 +26,7 @@ #include #include #include +#include class FilterGeodesic : public QObject, public FilterPlugin @@ -42,7 +43,8 @@ class FilterGeodesic : public QObject, public FilterPlugin enum { FP_QUALITY_BORDER_GEODESIC, FP_QUALITY_POINT_GEODESIC, - FP_QUALITY_SELECTED_GEODESIC + FP_QUALITY_SELECTED_GEODESIC, + FP_QUALITY_SELECTED_GEODESIC_HEAT } ; diff --git a/src/meshlabplugins/filter_io_nxs/filter_io_nxs.cpp b/src/meshlabplugins/filter_io_nxs/filter_io_nxs.cpp index e1fb68a20..425d57215 100644 --- a/src/meshlabplugins/filter_io_nxs/filter_io_nxs.cpp +++ b/src/meshlabplugins/filter_io_nxs/filter_io_nxs.cpp @@ -153,18 +153,23 @@ QString FilterIONXSPlugin::pythonFilterName(ActionIDType f) const QString FilterIONXSPlugin::filterInfo(ActionIDType filter) const { QString commonDescription = - "Nexus is a collection " - "of tools for streaming visualization of large 3D models in OpenGL.
"; + " Nexus is set of c++/javascript libraries and tools " + "for the creation and efficient visualization of multiresolution 3D models. " + "Nexus it is tailored for the processing and the streaming visualization of very large unstructured 3d models" + "like the ones coming from 3D scanning. " + "
"; switch(filter) { case FP_NXS_BUILDER : return commonDescription + - "This filter is the equivalent of calling " - "nxsbuild: " - "it creates a nxs file starting from a obj, ply or stl."; + "This filter is the equivalent of calling " + "nxsbuild: " + "it creates a nxs file starting from a file containing a 3D object, without the need of loading it before. " + "It supports only the following 3D formats: obj, ply or stl."; case FP_NXS_COMPRESS: return commonDescription + - "This filter is the equivalent of calling nxscompress, which" - "creates a nxz (compressed nexus) file starting from a nxs."; + "This filter is the equivalent of calling nxscompress, which " + "creates a .nxz (compressed nexus) file starting from a file .nxs (uncompressed nxs). " + "It is useful for exploring different lossy compression settings without the need of recreating the whole multiresolution structure."; default : assert(0); return "Unknown Filter"; @@ -203,13 +208,13 @@ RichParameterList FilterIONXSPlugin::initParameterList(const QAction* action, co RichParameterList params; switch(ID(action)) { case FP_NXS_BUILDER : - params.addParam(RichOpenFile("input_file", "", {"*.ply *.obj *.stl", "*.ply", "*.obj", "*.stl"}, "Input File", "The input file from which create the .nxs file.")); - params.addParam(RichSaveFile("output_file", "", "*.nxs", "Output File", "The name of the output nxs file.")); + params.addParam(RichFileOpen("input_file", "", {"*.ply *.obj *.stl", "*.ply", "*.obj", "*.stl"}, "Input File", "The input file from which create the .nxs file.")); + params.addParam(RichFileSave("output_file", "", "*.nxs", "Output File", "The name of the output nxs file.")); params.join(nxsParameters()); break; case FP_NXS_COMPRESS: - params.addParam(RichOpenFile("input_file", "", {"*.nxs"}, "Input File", "The input nxs file to compress into an nxz file.")); - params.addParam(RichSaveFile("output_file", "", "*.nxz", "Output File", "The name of the output nxz file.")); + params.addParam(RichFileOpen("input_file", "", {"*.nxs"}, "Input File", "The input nxs file to compress into an nxz file.")); + params.addParam(RichFileSave("output_file", "", "*.nxz", "Output File", "The name of the output nxz file.")); params.join(nxzParameters(false)); break; default : diff --git a/src/meshlabplugins/filter_layer/filter_layer.cpp b/src/meshlabplugins/filter_layer/filter_layer.cpp index 8ca389fdc..9a4c5e50d 100644 --- a/src/meshlabplugins/filter_layer/filter_layer.cpp +++ b/src/meshlabplugins/filter_layer/filter_layer.cpp @@ -212,7 +212,7 @@ FilterLayerPlugin::initParameterList(const QAction* action, const MeshDocument& "Name of the output file, it will be saved in the same folder as the project file.")); break; case FP_IMPORT_CAMERAS: - parlst.addParam(RichOpenFile( + parlst.addParam(RichFileOpen( "ImportFile", "", QStringList( diff --git a/src/meshlabplugins/filter_mesh_alpha_wrap/CMakeLists.txt b/src/meshlabplugins/filter_mesh_alpha_wrap/CMakeLists.txt new file mode 100644 index 000000000..e528ddf9d --- /dev/null +++ b/src/meshlabplugins/filter_mesh_alpha_wrap/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright 2023, PTC + +if (TARGET external-boost AND TARGET external-cgal AND TARGET external-libigl) + set(SOURCES filter_mesh_alpha_wrap.cpp) + + set(HEADERS filter_mesh_alpha_wrap.h) + + add_meshlab_plugin(filter_mesh_alpha_wrap ${SOURCES} ${HEADERS}) + + target_link_libraries(filter_mesh_alpha_wrap PRIVATE external-boost external-cgal external-libigl) +else() + message( + STATUS "Skipping filter_mesh_alpha_wrap - don't know about boost, cgal or libigl on this system.") +endif() diff --git a/src/meshlabplugins/filter_mesh_alpha_wrap/filter_mesh_alpha_wrap.cpp b/src/meshlabplugins/filter_mesh_alpha_wrap/filter_mesh_alpha_wrap.cpp new file mode 100644 index 000000000..d8b14291f --- /dev/null +++ b/src/meshlabplugins/filter_mesh_alpha_wrap/filter_mesh_alpha_wrap.cpp @@ -0,0 +1,319 @@ +/***************************************************************************** + * MeshLab - Alpha Wrap plugin o o * + * by PTC, based on CGAL o o * + * _ O _ * + * Copyright(C) 2023 \/)\/ * + * PTC /\/| * + * Lex van der Sluijs | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#include "filter_mesh_alpha_wrap.h" + +#include + +#include +#include +#include +#include "CGAL/alpha_wrap_3.h" +#include "qdebug.h" + + +namespace PMP = CGAL::Polygon_mesh_processing; +using K = CGAL::Exact_predicates_inexact_constructions_kernel; +using Point_3 = K::Point_3; +using CgalMesh = CGAL::Surface_mesh; + +typedef CgalMesh::Vertex_index vertex_descriptor; +typedef CgalMesh::Face_index face_descriptor; + +typedef boost::graph_traits::vertex_descriptor boost_vertex_descriptor; + +/** + * @brief + * Constructor usually performs only two simple tasks of filling the two lists + * - typeList: with all the possible id of the filtering actions + * - actionList with the corresponding actions. + * If you want to add icons to your filtering actions you can do here by construction the QActions + * accordingly + */ +FilterMeshAlphaWrap::FilterMeshAlphaWrap() +{ + typeList = {MESH_ALPHA_WRAP}; + + for (const ActionIDType& tt : typeList) + actionList.push_back(new QAction(filterName(tt), this)); +} + +QString FilterMeshAlphaWrap::pluginName() const +{ + return "FilterMeshAlphaWrap"; +} + +QString FilterMeshAlphaWrap::vendor() const +{ + return "PTC"; +} + +/** + * @brief ST() must return the very short string describing each filtering action + * (this string is used also to define the menu entry) + * @param filterId: the id of the filter + * @return the name of the filter + */ +QString FilterMeshAlphaWrap::filterName(ActionIDType filterId) const +{ + switch (filterId) { + case MESH_ALPHA_WRAP: return "Alpha Wrap"; + default: assert(0); return QString(); + } +} + +QString FilterMeshAlphaWrap::pythonFilterName(ActionIDType f) const +{ + switch (f) { + case MESH_ALPHA_WRAP: return "generate_alpha_wrap"; + default: assert(0); return QString(); + } +} + +/** + * @brief // Info() must return the longer string describing each filtering action + * (this string is used in the About plugin dialog) + * @param filterId: the id of the filter + * @return an info string of the filter + */ +QString FilterMeshAlphaWrap::filterInfo(ActionIDType filterId) const +{ + QString description = + "This filter extecutes an Alpha Wrap based on the input mesh.
" + "The filter uses the original code provided in CGAL " + "3D Alpha Wrapping.
" + "
" + "Alpha: this is the size of the 'ball', specified as the fraction of the length of the largest diagonal of the bounding box. So, if this value is 0.02 then the size of the ball is 2% of the largest diagonal. Note that the run-time and memory consumption will increase with a smaller ball size.

" + "Offset: the offset distance that is added to the surface, always larger than 0, as a fraction of the length of the largest diagonal. A value of 0.001 means that the surface will be offset by a thousandth of this length.

" + "The implementation is based on the following paper:
" + "Cédric Portaneri, Mael Rouxel-Labbé, Michael Hemmer, David Cohen-Steiner, Pierre Alliez, " + "\"Alpha Wrapping with an Offset\" (2022)

This plugin is contributed by Lex van der Sluijs at PTC.
"; + switch (filterId) { + case MESH_ALPHA_WRAP: return description; + default: assert(0); return "Unknown Filter"; + } +} + +/** + * @brief The FilterClass describes in which generic class of filters it fits. + * This choice affect the submenu in which each filter will be placed + * More than a single class can be chosen. + * @param a: the action of the filter + * @return the class od the filter + */ +FilterMeshAlphaWrap::FilterClass FilterMeshAlphaWrap::getClass(const QAction* a) const +{ + switch (ID(a)) { + case MESH_ALPHA_WRAP: + return FilterPlugin::FilterClass( + FilterPlugin::FilterClass(FilterPlugin::Layer + FilterPlugin::Remeshing)); + default: assert(0); return FilterPlugin::Generic; + } +} + +/** + * @brief FilterSamplePlugin::filterArity + * @return + */ +FilterPlugin::FilterArity FilterMeshAlphaWrap::filterArity(const QAction*) const +{ + return FIXED; +} + +/** + * @brief FilterSamplePlugin::getPreConditions + * @return + */ +// int FilterMeshBooleans::getPreConditions(const QAction*) const +//{ +// return MeshModel::MM_NONE; +//} + +/** + * @brief FilterSamplePlugin::postCondition + * @return + */ +// int FilterMeshBooleans::postCondition(const QAction*) const +//{ +// return MeshModel::MM_VERTCOORD | MeshModel::MM_FACENORMAL | MeshModel::MM_VERTNORMAL; +//} + +/** + * @brief This function define the needed parameters for each filter. Return true if the filter has + * some parameters it is called every time, so you can set the default value of parameters according + * to the mesh For each parameter you need to define, + * - the name of the parameter, + * - the default value + * - the string shown in the dialog + * - a possibly long string describing the meaning of that parameter (shown as a popup help in the + * dialog) + * @param action + * @param m + * @param parlst + */ +RichParameterList +FilterMeshAlphaWrap::initParameterList(const QAction* action, const MeshDocument& md) +{ + RichParameterList parlst; + switch (ID(action)) { + case MESH_ALPHA_WRAP: + { + parlst.addParam(RichFloat( + "Alpha fraction", + 0.02, + tr("Alpha: the size of the ball (fraction)"), + tr(""))); + parlst.addParam(RichFloat( + "Offset fraction", + 0.001, + tr("Offset added to the surface (fraction)"), + tr(""))); + } break; + default: assert(0); + } + return parlst; +} + + + +/** + * @brief The Real Core Function doing the actual mesh processing. + * @param action + * @param md: an object containing all the meshes and rasters of MeshLab + * @param par: the set of parameters of each filter + * @param cb: callback object to tell MeshLab the percentage of execution of the filter + * @return true if the filter has been applied correctly, false otherwise + */ +std::map FilterMeshAlphaWrap::applyFilter( + const QAction* action, + const RichParameterList& par, + MeshDocument& md, + unsigned int& /*postConditionMask*/, + vcg::CallBackPos*) +{ + float alpha_fraction = par.getFloat("Alpha fraction"); + float offset_fraction = par.getFloat("Offset fraction"); + + CgalMesh inputMesh; + CgalMesh wrapResult; + + // ------- initialize the CGAL input mesh based on the contents of the MeshDocument ---------- + // 'cm' is 'current mesh' or 'compute mesh' ? + CMeshO& m = md.mm()->cm; + + // note: coding guided from these pages: + // http://vcglib.net/platonic_8h_source.html to read from VCGlib mesh + // https://doc.cgal.org/latest/Surface_mesh/index.html#Chapter_3D_Surface_mesh to write to CGAL mesh + + for (auto vi = m.vert.begin(); vi != m.vert.end(); ++vi){ + vertex_descriptor vertex = inputMesh.add_vertex(K::Point_3((*vi).P().X(), (*vi).P().Y(), (*vi).P().Z())); + } + + bool meshContainsQuads = false; + for (auto fi = m.face.begin(); fi != m.face.end(); ++fi) + { + vertex_descriptor u( (*fi).V(0)->Index() ); + vertex_descriptor v( (*fi).V(1)->Index() ); + vertex_descriptor w( (*fi).V(2)->Index() ); + + //qDebug() << "m.face (*fi).VN() " << (*fi).VN(); + if ( (*fi).VN() == 4) + { + meshContainsQuads = true; + vertex_descriptor x( (*fi).V(3)->Index() ); + face_descriptor face = inputMesh.add_face(u, v, w, x); + } + else + face_descriptor face = inputMesh.add_face(u, v, w); + } + + CGAL::Bbox_3 bbox = CGAL::Polygon_mesh_processing::bbox(inputMesh); + const double diag_length = std::sqrt(CGAL::square(bbox.xmax() - bbox.xmin()) + + CGAL::square(bbox.ymax() - bbox.ymin()) + + CGAL::square(bbox.zmax() - bbox.zmin())); + + switch (ID(action)) { + case MESH_ALPHA_WRAP: + + { + if(meshContainsQuads) + { + qDebug() << "Input mesh contains quads, triangulating first"; + CGAL::Polygon_mesh_processing::triangulate_faces(inputMesh); + } + + CGAL::alpha_wrap_3(inputMesh, diag_length * alpha_fraction, diag_length * offset_fraction, wrapResult); + + // making a nice label that has the used parameter doesn't work, since it will be interpreted + // as a file name and the UI will manipulate the string based on where the dots are. + // QString newName = QString::asprintf("Alpha Wrap a=%.4f, o=%.4f").arg(alpha_fraction, offset_fraction); + QString newName = "Alpha wrap"; + MeshModel* mesh = md.addNewMesh("", newName, true); + + EigenMatrixX3m VR; + Eigen::MatrixX3i FR; + + + VR.resize(wrapResult.num_vertices(), Eigen::NoChange); + FR.resize(wrapResult.num_faces(), Eigen::NoChange); + + // --------- copy results from wrap into Eigen matrices -------------- + // 'rvi' = result vertex iterator, vi = vertex index + int vi = 0; + for(auto rvi = wrapResult.vertices().begin(); rvi != wrapResult.vertices().end(); ++rvi) + { + VR(vi, 0) = wrapResult.point(*rvi).x(); + VR(vi, 1) = wrapResult.point(*rvi).y(); + VR(vi, 2) = wrapResult.point(*rvi).z(); + ++vi; + } + + int faceIndex = 0; + for(auto rfi = wrapResult.faces().begin(); rfi != wrapResult.faces().end(); ++rfi) + { + // qDebug() << "vertices around face " << *rfi; + CGAL::Vertex_around_face_iterator vbegin, vend; + int i = 0; + for(boost::tie(vbegin, vend) = vertices_around_face(wrapResult.halfedge( *rfi), wrapResult); vbegin != vend; ++vbegin) + { + // qDebug() << *vbegin << " vbegin->idx() " << vbegin->idx(); + FR(faceIndex, i) = vbegin->idx(); + ++i; + } + + ++faceIndex; + } + + + // ------------- then initialize the new mesh using these Eigen matrices ---------- + mesh->cm = meshlab::meshFromMatrices(VR, FR); + } + break; + + default: wrongActionCalled(action); + } + return std::map(); +} + + +MESHLAB_PLUGIN_NAME_EXPORTER(FilterMeshAlphaWrap) diff --git a/src/meshlabplugins/filter_mesh_alpha_wrap/filter_mesh_alpha_wrap.h b/src/meshlabplugins/filter_mesh_alpha_wrap/filter_mesh_alpha_wrap.h new file mode 100644 index 000000000..363bf981a --- /dev/null +++ b/src/meshlabplugins/filter_mesh_alpha_wrap/filter_mesh_alpha_wrap.h @@ -0,0 +1,73 @@ +/***************************************************************************** + * MeshLab - Alpha Wrap plugin o o * + * by PTC, based on CGAL o o * + * _ O _ * + * Copyright(C) 2023 \/)\/ * + * PTC /\/| * + * Lex van der Sluijs | * + * \ * + * All rights reserved. * + * * + * This program 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. * + * * + * This program 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 (http://www.gnu.org/licenses/gpl.txt) * + * for more details. * + * * + ****************************************************************************/ + +#ifndef MESHLAB_FILTER_MESH_ALPHAWRAP_H +#define MESHLAB_FILTER_MESH_ALPHAWRAP_H + +// from meshlab common, include the abstract class file of filter plugins +#include + +/** + * @brief The FilterMeshAlphaWrap class + * This Meshlab plugin implements the Alpha Wrap algorithm from CGAL. + * + * It is very useful for making scaled-down CAD models 3D printable. + * It is also able to robustly make a watertight mesh based on a mesh with degenerate geometries. + * + */ +class FilterMeshAlphaWrap : public QObject, public FilterPlugin +{ + Q_OBJECT + MESHLAB_PLUGIN_IID_EXPORTER(FILTER_PLUGIN_IID) + Q_INTERFACES(FilterPlugin) + +public: + // enum used to give an ID to every filter implemented in the plugin + enum FilterIds { MESH_ALPHA_WRAP }; + + FilterMeshAlphaWrap(); + + QString pluginName() const; + QString vendor() const; + + QString filterName(ActionIDType filter) const; + QString pythonFilterName(ActionIDType f) const; + + QString filterInfo(ActionIDType filter) const; + FilterClass getClass(const QAction* a) const; + FilterArity filterArity(const QAction*) const; + // int getPreConditions(const QAction *) const; + // int postCondition(const QAction* ) const; + RichParameterList initParameterList(const QAction*, const MeshDocument& /*m*/); + std::map applyFilter( + const QAction* action, + const RichParameterList& params, + MeshDocument& md, + unsigned int& postConditionMask, + vcg::CallBackPos* cb); + +private: + +}; + +#endif // MESHLAB_FILTER_MESH_ALPHAWRAP_H diff --git a/src/meshlabplugins/filter_meshing/meshfilter.cpp b/src/meshlabplugins/filter_meshing/meshfilter.cpp index 0ffc638b8..f9c547b7c 100644 --- a/src/meshlabplugins/filter_meshing/meshfilter.cpp +++ b/src/meshlabplugins/filter_meshing/meshfilter.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include "quadric_simp.h" @@ -42,6 +43,28 @@ using namespace std; using namespace vcg; using namespace vcg::tri; +// Polygonal mesh used by doo sabin refinement +class PEdge; +class PFace; +class PVertex; +struct PUsedTypes : public UsedTypes ::AsVertexType, + Use ::AsEdgeType, + Use ::AsFaceType> {}; + +class PVertex : public Vertex {}; +class PEdge : public Edge< PUsedTypes, edge::VertexRef, edge::BitFlags> {}; +class PFace :public vcg::Face< + PUsedTypes, + face::PolyInfo, // this is necessary if you use component in vcg/simplex/face/component_polygon.h + face::PFVAdj, // Pointer to the vertices (just like FVAdj ) + face::PFFAdj, // Pointer to the vertices (just like FVAdj ) + face::Color4b, + face::BitFlags, // bit flags + face::Normal3f, // normal + face::WedgeTexCoord2f + > {}; +class PMesh : public tri::TriMesh< vector, vector, vector > {}; + ExtraMeshFilterPlugin::ExtraMeshFilterPlugin(void) { @@ -73,6 +96,7 @@ ExtraMeshFilterPlugin::ExtraMeshFilterPlugin(void) FP_CYLINDER_UNWRAP, FP_REFINE_CATMULL, FP_REFINE_HALF_CATMULL, + FP_REFINE_DOOSABIN, FP_QUAD_DOMINANT, FP_MAKE_PURE_TRI, FP_QUAD_PAIRING, @@ -101,7 +125,7 @@ ExtraMeshFilterPlugin::ExtraMeshFilterPlugin(void) lastqtex_QualityThr = 0.3f; lastqtex_extratw = 1.0; - lastisor_Iterations = 3; + lastisor_Iterations = 10; lastisor_RemeshingAdaptivity = false; lastisor_SelectedOnly = false; lastisor_RefineFlag = true; @@ -135,6 +159,7 @@ ExtraMeshFilterPlugin::FilterClass ExtraMeshFilterPlugin::getClass(const QAction case FP_REFINE_LS3_LOOP : return FilterPlugin::Remeshing; case FP_REFINE_CATMULL : case FP_REFINE_HALF_CATMULL : + case FP_REFINE_DOOSABIN : case FP_QUAD_DOMINANT : case FP_MAKE_PURE_TRI : case FP_QUAD_PAIRING : return FilterClass(Remeshing+Polygonal); @@ -186,6 +211,7 @@ int ExtraMeshFilterPlugin::getPreConditions(const QAction *filter) const case FP_CLOSE_HOLES : case FP_CYLINDER_UNWRAP : case FP_REFINE_HALF_CATMULL : + case FP_REFINE_DOOSABIN : case FP_QUAD_DOMINANT : case FP_QUAD_PAIRING : case FP_FAUX_CREASE : @@ -230,12 +256,13 @@ QString ExtraMeshFilterPlugin::pythonFilterName(ActionIDType f) const case FP_BUTTERFLY_SS: return tr("meshing_surface_subdivision_butterfly"); case FP_MIDPOINT: return tr("meshing_surface_subdivision_midpoint"); case FP_REFINE_CATMULL: return tr("meshing_surface_subdivision_catmull_clark"); + case FP_REFINE_DOOSABIN: return tr("meshing_surface_subdivision_doo_sabin"); case FP_QUADRIC_SIMPLIFICATION: return tr("meshing_decimation_quadric_edge_collapse"); case FP_QUADRIC_TEXCOORD_SIMPLIFICATION: return tr("meshing_decimation_quadric_edge_collapse_with_texture"); case FP_EXPLICIT_ISOTROPIC_REMESHING: return tr("meshing_isotropic_explicit_remeshing"); case FP_CLUSTERING: return tr("meshing_decimation_clustering"); - case FP_REORIENT: return tr("meshing_re_orient_faces_coherentely"); + case FP_REORIENT: return tr("meshing_re_orient_faces_coherently"); case FP_INVERT_FACES: return tr("meshing_invert_face_orientation"); case FP_SCALE: return tr("compute_matrix_from_scaling_or_normalization"); case FP_CENTER: return tr("compute_matrix_from_translation"); @@ -275,12 +302,13 @@ QString ExtraMeshFilterPlugin::filterName(ActionIDType filter) const case FP_BUTTERFLY_SS: return tr("Subdivision Surfaces: Butterfly Subdivision"); case FP_MIDPOINT: return tr("Subdivision Surfaces: Midpoint"); case FP_REFINE_CATMULL: return tr("Subdivision Surfaces: Catmull-Clark"); + case FP_REFINE_DOOSABIN: return tr("Subdivision Surfaces: Doo Sabin"); case FP_QUADRIC_SIMPLIFICATION: return tr("Simplification: Quadric Edge Collapse Decimation"); case FP_QUADRIC_TEXCOORD_SIMPLIFICATION: return tr("Simplification: Quadric Edge Collapse Decimation (with texture)"); case FP_EXPLICIT_ISOTROPIC_REMESHING: return tr("Remeshing: Isotropic Explicit Remeshing"); case FP_CLUSTERING: return tr("Simplification: Clustering Decimation"); - case FP_REORIENT: return tr("Re-Orient all faces coherentely"); + case FP_REORIENT: return tr("Re-Orient all faces coherently"); case FP_INVERT_FACES: return tr("Invert Faces Orientation"); case FP_SCALE: return tr("Transform: Scale, Normalize"); case FP_CENTER: return tr("Transform: Translate, Center, set Origin"); @@ -332,6 +360,7 @@ QString ExtraMeshFilterPlugin::filterInfo(ActionIDType filterID) const case FP_MIDPOINT : return tr("Apply a plain subdivision scheme where every edge is split on its midpoint. Useful to uniformly refine a mesh substituting each triangle with four smaller triangles."); case FP_REFINE_CATMULL : return tr("Apply the Catmull-Clark Subdivision Surfaces. Note that position of the new vertices is simply linearly interpolated. " "If the mesh is triangle based (no faux edges) it generates a quad mesh, otherwise it honores it the faux-edge bits"); + case FP_REFINE_DOOSABIN : return tr("Apply the DooSabin Subdivision Surfaces. It is a Dual approximating refinement scheme that creates a new face for each vertex, edge and face. On a pure quad mesh it will add non quad face for each extraordinarhy vertex in the mesh (e.g. in a cube it will add a triangular face for each corner. On the other hand after a refinement step all the vertices will have degree 4."); case FP_REFINE_HALF_CATMULL : return tr("Convert a tri mesh into a quad mesh by applying a 4-8 subdivision scheme." "It introduces less overhead than the plain Catmull-Clark Subdivision Surfaces" "(it adds only a single vertex for each triangle instead of four)." @@ -381,7 +410,7 @@ QString ExtraMeshFilterPlugin::filterInfo(ActionIDType filterID) const case FP_NORMAL_EXTRAPOLATION : return tr("Compute the normals of the vertices of a mesh without exploiting the triangle connectivity, useful for dataset with no faces"); case FP_NORMAL_SMOOTH_POINTCLOUD : return tr("Smooth the normals of the vertices of a mesh without exploiting the triangle connectivity, useful for dataset with no faces"); case FP_COMPUTE_PRINC_CURV_DIR : return tr("Compute the principal directions of curvature with different algorithms"); - case FP_CLOSE_HOLES : return tr("Close holes smaller than a given threshold"); + case FP_CLOSE_HOLES : return tr("Close holes whose boundary is composed by a number of edges smaller than a given trheshold"); case FP_CYLINDER_UNWRAP : return tr("Unwrap the geometry of current mesh along a clylindrical equatorial projection. The cylindrical projection axis is centered on the origin and directed along the vertical Y axis."); case FP_QUAD_PAIRING : return tr("Convert a tri-mesh into a quad mesh by pairing triangles."); case FP_QUAD_DOMINANT : return tr("Convert a tri-mesh into a quad-dominant mesh by pairing suitable triangles."); @@ -393,7 +422,7 @@ QString ExtraMeshFilterPlugin::filterInfo(ActionIDType filterID) const "vertices are duplicated whenever two or more selected wedge or face attributes do not match.
" "This is particularly useful for GPU-friendly mesh layout, where a single index must be used to access all required vertex attributes."); case FP_SLICE_WITH_A_PLANE : return tr("Compute the polyline representing a planar section (a slice) of a mesh; if the resulting polyline is closed the result is filled and also a triangular mesh representing the section is saved"); - case FP_PERIMETER_POLYLINE : return tr("Create a new Layer with the perimeter polyline(s) of the selection borders"); + case FP_PERIMETER_POLYLINE : return tr("Create a new Layer with an edge mesh (polyline) composed by the selected edges of the current mesh. It can be used to convert the boundary edges of a mesh into a polyline by selecting all the faces of the mesh."); case FP_FAUX_EXTRACT : return tr("Create a new Layer with an edge mesh composed only by the selected edges of the current mesh"); default : assert(0); @@ -427,7 +456,7 @@ RichParameterList ExtraMeshFilterPlugin::initParameterList(const QAction * actio curvColorMethods << "Mean Curvature"<<"Gaussian Curvature"<<"Min Curvature"<<"Max Curvature" << "Shape Index"<< "CurvedNess" <<"None"; parlst.addParam(RichEnum("Method", 3, curvCalcMethods, tr("Method:"), tr("Choose a method"))); parlst.addParam(RichEnum("CurvColorMethod", 0, curvColorMethods, tr("Quality/Color Mapping"), QString("Choose the curvature that is mapped into quality and visualized as per vertex color."))); - parlst.addParam(RichAbsPerc("Scale",maxVal*0.1,0,maxVal,"Curvature Scale","This parameter is used only for scale dependent methods: 'Scale Dependent Quadric Fitting' and 'PCA'." + parlst.addParam(RichPercentage("Scale",maxVal*0.1,0,maxVal,"Curvature Scale","This parameter is used only for scale dependent methods: 'Scale Dependent Quadric Fitting' and 'PCA'." " It specifies the scale at which the curvature is computed. e.g. for SDQF it specify how large is the patch where we fit the quadric used to compute curvature dirs.")); parlst.addParam(RichBool("Autoclean",true,"Remove Unreferenced Vertices","If selected, before starting the filter will remove any unreference vertex (for which curvature values are not defined)")); break; @@ -467,10 +496,10 @@ RichParameterList ExtraMeshFilterPlugin::initParameterList(const QAction * actio parlst.addParam(RichBool ("Adaptive", lastisor_RemeshingAdaptivity, "Adaptive remeshing", "Toggles adaptive isotropic remeshing." )); parlst.addParam(RichBool ("SelectedOnly", lastisor_SelectedOnly, "Remesh only selected faces", "If checked the remeshing operations will be applied only to the selected faces.")); maxVal = m.cm.bbox.Diag(); - parlst.addParam(RichAbsPerc("TargetLen",maxVal*0.01,0,maxVal,"Target Length", "Sets the target length for the remeshed mesh edges.")); + parlst.addParam(RichPercentage("TargetLen",maxVal*0.01,0,maxVal,"Target Length", "Sets the target length for the remeshed mesh edges.")); parlst.addParam(RichFloat ("FeatureDeg", lastisor_FeatureDeg, "Crease Angle", "Minimum angle between faces of the original to consider the shared edge as a feature to be preserved.")); parlst.addParam(RichBool ("CheckSurfDist", lastisor_CheckSurfDist, "Check Surface Distance", "If toggled each local operation must deviate from original mesh by [Max. surface distance]")); - parlst.addParam(RichAbsPerc ("MaxSurfDist", maxVal*0.01,0,maxVal, "Max. Surface Distance", "Maximal surface deviation allowed for each local operation")); + parlst.addParam(RichPercentage ("MaxSurfDist", maxVal*0.01,0,maxVal, "Max. Surface Distance", "Maximal surface deviation allowed for each local operation")); parlst.addParam(RichBool ("SplitFlag", lastisor_RefineFlag, "Refine Step", "If checked the remeshing operations will include a refine step.")); parlst.addParam(RichBool ("CollapseFlag", lastisor_CollapseFlag, "Collapse Step", "If checked the remeshing operations will include a collapse step.")); parlst.addParam(RichBool ("SwapFlag", lastisor_SwapFlag, "Edge-Swap Step", "If checked the remeshing operations will include a edge-swap step, aimed at improving the vertex valence of the resulting mesh.")); @@ -483,6 +512,9 @@ RichParameterList ExtraMeshFilterPlugin::initParameterList(const QAction * actio parlst.addParam(RichBool("Selected",m.cm.sfn>0,"Close holes with selected faces","Only the holes with at least one of the boundary faces selected are closed")); parlst.addParam(RichBool("NewFaceSelected",true,"Select the newly created faces","After closing a hole the faces that have been created are left selected. Any previous selection is lost. Useful for example for smoothing the newly created holes.")); parlst.addParam(RichBool("SelfIntersection",true,"Prevent creation of selfIntersecting faces","When closing an holes it tries to prevent the creation of faces that intersect faces adjacent to the boundary of the hole. It is an heuristic, non intersetcting hole filling can be NP-complete.")); + parlst.addParam(RichBool("RefineHole",false,"Refine Filled Hole","After closing the hole it will refine the newly created triangles to make the surface more smooth and the triangulation more evenly spaced")); + maxVal = m.cm.bbox.Diag(); + parlst.addParam(RichPercentage("RefineHoleEdgeLen",maxVal*0.03,0,maxVal,"Hole Refinement Edge Len", "The target edge lenght of the triangulation inside the filled hole.")); break; case FP_LOOP_SS: @@ -494,16 +526,32 @@ RichParameterList ExtraMeshFilterPlugin::initParameterList(const QAction * actio case FP_MIDPOINT: parlst.addParam(RichInt("Iterations", 3, "Iterations", "Number of time the model is subdivided.")); maxVal = m.cm.bbox.Diag(); - parlst.addParam(RichAbsPerc("Threshold",maxVal*0.01,0,maxVal,"Edge Threshold", "All the edges longer than this threshold will be refined.
Setting this value to zero will force an uniform refinement.")); + parlst.addParam(RichPercentage("Threshold",maxVal*0.01,0,maxVal,"Edge Threshold", "All the edges longer than this threshold will be refined.
Setting this value to zero will force an uniform refinement.")); parlst.addParam(RichBool ("Selected",m.cm.sfn>0,"Affect only selected faces","If selected the filter affect only the selected faces")); break; - + + case FP_REFINE_DOOSABIN: + parlst.addParam(RichInt("Iterations", 2, "Iterations", "Number of times the model is subdivided.")); + break; + case FP_CLUSTERING: // TODO implement selection maxVal = m.cm.bbox.Diag(); - parlst.addParam(RichAbsPerc("Threshold",maxVal*0.01,0,maxVal,"Cell Size", "The size of the cell of the clustering grid. Smaller the cell finer the resulting mesh. For obtaining a very coarse mesh use larger values.")); - //parlst.addParam(RichBool ("Selected",m.cm.sfn>0,"Affect only selected faces","If selected the filter affect only the selected faces")); + parlst.addParam(RichPercentage( + "Threshold", + maxVal * 0.01, + 0, + maxVal, + "Cell Size", + "The size of the cell of the clustering grid. Smaller the cell finer the resulting " + "mesh. For obtaining a very coarse mesh use larger values.")); + //TODO: implement selection on clustering algorithm +// parlst.addParam(RichBool( +// "Selected", +// m.cm.sfn > 0, +// "Affect only selected points/faces", +// "If selected the filter affect only the selected points/faces")); break; case FP_CYLINDER_UNWRAP: @@ -539,7 +587,7 @@ RichParameterList ExtraMeshFilterPlugin::initParameterList(const QAction * actio case FP_SET_TRANSFORM_MATRIX: { Matrix44m mat; mat.SetIdentity(); - parlst.addParam(RichMatrix44f("TransformMatrix", mat, "")); + parlst.addParam(RichMatrix44("TransformMatrix", mat, "")); parlst.addParam(RichBool("compose", false, "Compose with current", "If selected, the new matrix will be composed with the current one (matrix=new*old)")); parlst.addParam(RichBool("Freeze", true, "Freeze Matrix", "The transformation is explicitly applied, and the vertex coordinates are actually changed")); parlst.addParam(RichBool ("allLayers",false,"Apply to all visible Layers","If selected, the filter will be applied to all visible mesh layers")); @@ -701,7 +749,6 @@ RichParameterList ExtraMeshFilterPlugin::initParameterList(const QAction * actio parlst.addParam(RichEnum ("level", 0, opt, tr("Optimize For:"), tr("Choose any of three different greedy strategies."))); } break; - default: break; } @@ -770,7 +817,7 @@ std::map ExtraMeshFilterPlugin::applyFilter( throw MLException("Mesh has some not 2 manifoldfaces, subdivision surfaces require manifoldness"); // text } - bool selected = par.getBool("Selected"); + bool selected = par.getBool("Selected"); Scalarm threshold = par.getAbsPerc("Threshold"); int iterations = par.getInt("Iterations"); @@ -856,14 +903,17 @@ std::map ExtraMeshFilterPlugin::applyFilter( { // TODO implement selection Scalarm threshold = par.getAbsPerc("Threshold"); - vcg::tri::Clustering > ClusteringGrid; - ClusteringGrid.Init(m.cm.bbox,100000,threshold); - if(m.cm.FN() ==0) + vcg::tri::Clustering> ClusteringGrid( + m.cm.bbox, 100000, threshold); + if(m.cm.FN() == 0) { ClusteringGrid.AddPointSet(m.cm); - else + ClusteringGrid.ExtractPointSet(m.cm); + } + else { ClusteringGrid.AddMesh(m.cm); + ClusteringGrid.ExtractMesh(m.cm); + } - ClusteringGrid.ExtractMesh(m.cm); m.updateBoxAndNormals(); m.clearDataMask(MeshModel::MM_FACEFACETOPO); } break; @@ -1095,8 +1145,13 @@ std::map ExtraMeshFilterPlugin::applyFilter( float errorSum = 0; for (size_t i = 0; i < selected_pts.size(); ++i) errorSum += fabs(SignedDistancePlanePoint(plane, selected_pts[i])); - log("Fitting Plane avg error is %f", errorSum / float(selected_pts.size())); - log("Fitting Plane normal is [%f, %f, %f]", plane.Direction().X(), plane.Direction().Y(), plane.Direction().Z()); + float fpAvgError = errorSum / float(selected_pts.size()); + Point3m fpNormal(plane.Direction().X(), plane.Direction().Y(), plane.Direction().Z()); + log("Fitting Plane avg error is %f", fpAvgError); + log("Fitting Plane normal is [%f, %f, %f]", fpNormal.X(), fpNormal.Y(), fpNormal.Z()); + outputValues["fitting_plane_avg_error"] = QVariant::fromValue(fpAvgError); + outputValues["fitting_plane_normal"] = QVariant::fromValue(fpNormal); + Matrix44m tr1; // translation matrix the centroid of selected points tr1.SetTranslate(-selBox.Center()); @@ -1151,6 +1206,8 @@ std::map ExtraMeshFilterPlugin::applyFilter( log("Rotation axis is [%f, %f, %f]", rotAxis.X(), rotAxis.Y(), rotAxis.Z()); log("Rotation angle is %f", -angleRad); + outputValues["rotation_axis"] = QVariant::fromValue(rotAxis); + outputValues["rotation_angle"] = QVariant::fromValue(-angleRad); Matrix44m transfM; if (par.getBool("ToOrigin")) @@ -1424,6 +1481,8 @@ std::map ExtraMeshFilterPlugin::applyFilter( bool SelectedFlag = par.getBool("Selected"); bool SelfIntersectionFlag = par.getBool("SelfIntersection"); bool NewFaceSelectedFlag = par.getBool("NewFaceSelected"); + bool RefineHoleFlag = par.getBool("RefineHole"); + float RefineHoleEdgeLen = par.getAbsPerc("RefineHoleEdgeLen"); int holeCnt; if( SelfIntersectionFlag ) holeCnt = tri::Hole::EarCuttingIntersectionFill >(m.cm,MaxHoleSize,SelectedFlag,cb); @@ -1442,6 +1501,44 @@ std::map ExtraMeshFilterPlugin::applyFilter( for(size_t i=OriginalSize;i::Params params; + params.SetFeatureAngleDeg(181.0f); + params.adapt = false; + params.selectedOnly = true; + params.splitFlag = true; + params.collapseFlag = true; + params.swapFlag = true; + params.smoothFlag = true; + params.projectFlag = false; + params.surfDistCheck= false; + + // Refinement and smoothing can be tricky. Usually it is good to + // 1) start with large tris to get fast convergence to the min surf + // 2) switch a bit to small tri to unfold bad things at the boundary + // 3) go for the desired edge len + // Rinse and repeat. + + for(int k=0;k<3;k++) + { + params.SetTargetLen(RefineHoleEdgeLen*3.0); params.iter = 5; + tri::IsotropicRemeshing::Do(m.cm, params); + + params.SetTargetLen(RefineHoleEdgeLen/3.0); params.iter = 3; + tri::IsotropicRemeshing::Do(m.cm, params); + + params.SetTargetLen(RefineHoleEdgeLen ); params.iter = 2; + tri::IsotropicRemeshing::Do(m.cm, params); + } + + } + } break; case FP_CYLINDER_UNWRAP: @@ -1570,7 +1667,23 @@ std::map ExtraMeshFilterPlugin::applyFilter( m.clearDataMask(MeshModel::MM_FACEFACETOPO); m.updateDataMask(MeshModel::MM_POLYGONAL); } break; - + + case FP_REFINE_DOOSABIN : + { + PMesh baseIn, refinedOut; + m.updateDataMask(MeshModel::MM_FACEFACETOPO); + tri::PolygonSupport::ImportFromTriMesh(baseIn,m.cm); + tri::Clean::RemoveUnreferencedVertex(baseIn); + tri::Allocator::CompactEveryVector(baseIn); + tri::DooSabin::Refine(baseIn, refinedOut); + m.cm.Clear(); + tri::PolygonSupport::ImportFromPolyMesh(m.cm,refinedOut); + m.updateDataMask(MeshModel::MM_FACEFACETOPO); + tri::UpdateTopology::FaceFace(m.cm); + tri::UpdateNormal::PerBitPolygonFaceNormalized(m.cm); + tri::UpdateNormal::PerVertexFromCurrentFaceNormal(m.cm); + } break; + case FP_QUAD_PAIRING : { m.updateDataMask(MeshModel::MM_FACEQUALITY | MeshModel::MM_FACEFACETOPO ); diff --git a/src/meshlabplugins/filter_meshing/meshfilter.h b/src/meshlabplugins/filter_meshing/meshfilter.h index 7b75a3349..637cab618 100644 --- a/src/meshlabplugins/filter_meshing/meshfilter.h +++ b/src/meshlabplugins/filter_meshing/meshfilter.h @@ -69,6 +69,7 @@ public: FP_CLOSE_HOLES, FP_CYLINDER_UNWRAP, FP_REFINE_CATMULL, + FP_REFINE_DOOSABIN, FP_REFINE_HALF_CATMULL, FP_QUAD_DOMINANT, FP_MAKE_PURE_TRI, diff --git a/src/meshlabplugins/filter_mutualinfo/filter_mutualinfo.cpp b/src/meshlabplugins/filter_mutualinfo/filter_mutualinfo.cpp index bd8e3ad39..4ed14171a 100644 --- a/src/meshlabplugins/filter_mutualinfo/filter_mutualinfo.cpp +++ b/src/meshlabplugins/filter_mutualinfo/filter_mutualinfo.cpp @@ -114,7 +114,7 @@ RichParameterList FilterMutualInfoPlugin::initParameterList(const QAction *actio switch(ID(action)) { case FP_IMAGE_MUTUALINFO: parlst.addParam(RichEnum("Rendering Mode", 0, rendList, tr("Rendering mode:"), "Rendering modes")); - parlst.addParam(RichShotf("Shot", Shotm(), "Starting shot", "If the point of view has been set by hand, it must be retrieved from current trackball")); + parlst.addParam(RichShot("Shot", Shotm(), "Starting shot", "If the point of view has been set by hand, it must be retrieved from current trackball")); parlst.addParam(RichBool("Estimate Focal", false, "Estimate focal length", "Estimate focal length: if not checked, only extrinsic parameters are estimated")); parlst.addParam(RichBool("Fine", true, "Fine Alignment", "Fine alignment: the perturbations applied to reach the alignment are smaller")); parlst.addParam(RichInt("NumOfIterations", 100, "Max iterations", "Maximum number of iterations")); diff --git a/src/meshlabplugins/filter_plymc/filter_plymc.cpp b/src/meshlabplugins/filter_plymc/filter_plymc.cpp index 0f0811106..e5031ab1d 100644 --- a/src/meshlabplugins/filter_plymc/filter_plymc.cpp +++ b/src/meshlabplugins/filter_plymc/filter_plymc.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include using namespace vcg; @@ -112,7 +113,7 @@ RichParameterList PlyMCPlugin::initParameterList(const QAction *action,const Mes switch(ID(action)) { case FP_PLYMC : - parlst.addParam(RichAbsPerc("voxSize",m.cm.bbox.Diag()/100.0,0,m.cm.bbox.Diag(),"Voxel Side", "VoxelSide")); + parlst.addParam(RichPercentage("voxSize",m.cm.bbox.Diag()/100.0,0,m.cm.bbox.Diag(),"Voxel Side", "VoxelSide")); parlst.addParam( RichInt("subdiv",1,"SubVol Splitting","The level of recursive splitting of the subvolume reconstruction process. A value of '3' means that a 3x3x3 regular space subdivision is created and the reconstruction process generate 8 matching meshes. It is useful for reconsruction objects at a very high resolution. Default value (1) means no splitting.")); parlst.addParam( RichFloat("geodesic",2.0,"Geodesic Weighting","The influence of each range map is weighted with its geodesic distance from the borders. In this way when two (or more ) range maps overlaps their contribution blends smoothly hiding possible misalignments. ")); parlst.addParam( RichBool("openResult",true,"Show Result","if not checked the result is only saved into the current directory")); @@ -142,13 +143,21 @@ std::map PlyMCPlugin::applyFilter( case FP_PLYMC: { srand(time(NULL)); - - //check if folder is writable - QTemporaryFile file("./_tmp_XXXXXX.tmp"); - if (!file.open()) - { - log("ERROR - current folder is not writable. VCG Merging needs to save intermediate files in the current working folder. Project and meshes must be in a write-enabled folder. Please save your data in a suitable folder before applying."); - throw MLException("current folder is not writable.
VCG Merging needs to save intermediate files in the current working folder.
Project and meshes must be in a write-enabled folder.
Please save your data in a suitable folder before applying."); + + QDir currDir = QDir::current(); + + //Using tmp dir + QTemporaryDir tmpdir; + QTemporaryFile file(tmpdir.path()); + if (!file.open()) { + log("ERROR - tmp folder is not writable. VCG Merging needs to save intermediate files " + "in the tmp folder."); + throw MLException( + "tmp folder is not writable.
VCG Merging needs to save intermediate files in " + "the tmp folder."); + } + else { + QDir::setCurrent(tmpdir.path()); } tri::PlyMC > pmc; @@ -170,10 +179,8 @@ std::map PlyMCPlugin::applyFilter( p.FullyPreprocessedFlag=true; p.MergeColor=p.VertSplatFlag=par.getBool("mergeColor"); p.SimplificationFlag = par.getBool("simplification"); - for(MeshModel& mm: md.meshIterator()) - { - if(mm.isVisible()) - { + for(MeshModel& mm: md.meshIterator()) { + if(mm.isVisible()) { SMesh sm; mm.updateDataMask(MeshModel::MM_FACEQUALITY); tri::Append::Mesh(sm, mm.cm/*,false,p.VertSplatFlag*/); // note the last parameter of the append to prevent removal of unreferenced vertices... @@ -189,8 +196,7 @@ std::map PlyMCPlugin::applyFilter( QString mshTmpPath=QString("__TMP")+QString(mm.shortName())+QString(".vmi"); qDebug("Saving tmp file %s",qUtf8Printable(mshTmpPath)); int retVal = tri::io::ExporterVMI::Save(sm,qUtf8Printable(mshTmpPath) ); - if(retVal!=0) - { + if(retVal!=0) { qDebug("Failed to write vmi temp file %s",qUtf8Printable(mshTmpPath)); log("ERROR - Failed to write vmi temp file %s", qUtf8Printable(mshTmpPath)); @@ -201,14 +207,12 @@ std::map PlyMCPlugin::applyFilter( } } - if(pmc.Process(cb)==false) - { + if(pmc.Process(cb)==false) { throw MLException(pmc.errorMessage.c_str()); } - if(par.getBool("openResult")) - { + if(par.getBool("openResult")) { for(size_t i=0;i PlyMCPlugin::applyFilter( for(int i=0;i MetroMeshGrid; + typedef GridStaticPtr FaceMeshGrid; typedef GridStaticPtr VertexMeshGrid; public: - - LocalRedetailSampler():m(0) {} - - CMeshO *m; /// the source mesh for which we search the closest points (e.g. the mesh from which we take colors etc). - CallBackPos *cb; - int sampleNum; // the expected number of samples. Used only for the callback - int sampleCnt; - MetroMeshGrid unifGridFace; + CMeshO *m=0; /// the source mesh for which we search the closest points (e.g. the mesh from which we take colors etc). + CallBackPos *cb=0; + int sampleNum=0; // the expected number of samples. Used only for the callback + int sampleCnt=0; + FaceMeshGrid unifGridFace; VertexMeshGrid unifGridVert; - bool useVertexSampling; + + bool useVertexSampling=false; // Parameters typedef tri::FaceTmark MarkerFace; MarkerFace markerFunctor; - bool coordFlag; - bool colorFlag; - bool normalFlag; - bool qualityFlag; - bool selectionFlag; - bool storeDistanceAsQualityFlag; - float dist_upper_bound; - void init(CMeshO *_m, CallBackPos *_cb=0, int targetSz=0) - { - coordFlag=false; - colorFlag=false; - qualityFlag=false; - selectionFlag=false; - storeDistanceAsQualityFlag=false; - m=_m; - tri::UpdateNormal::PerFaceNormalized(*m); - if(m->fn==0) useVertexSampling = true; - else useVertexSampling = false; + // what data has to be resampled + bool coordFlag=false; + bool colorFlag=false; + bool normalFlag=false; + bool qualityFlag=false; + bool selectionFlag=false; + + bool storeDistanceAsQualityFlag=false; + bool storeBarycentricCoordsAsAttributesFlag=false; - if(useVertexSampling) unifGridVert.Set(m->vert.begin(),m->vert.end()); - else unifGridFace.Set(m->face.begin(),m->face.end()); - markerFunctor.SetMesh(m); - // sampleNum and sampleCnt are used only for the progress callback. - cb=_cb; - sampleNum = targetSz; - sampleCnt = 0; + CMeshO::PerVertexAttributeHandle PerVertBaricentricCoordsHandle; + CMeshO::PerVertexAttributeHandle PerVertNearestFaceIndex; + CMeshO::PerVertexAttributeHandle PerVertNearestVertexIndex; + float dist_upper_bound; + void init(CMeshO *_m_src, CMeshO* _m_trg=0, CallBackPos *_cb=0) + { + m=_m_src; + tri::UpdateNormal::PerFaceNormalized(*m); + if(m->fn==0) useVertexSampling = true; + + if(useVertexSampling) unifGridVert.Set(m->vert.begin(),m->vert.end()); + else unifGridFace.Set(m->face.begin(),m->face.end()); + markerFunctor.SetMesh(m); + // sampleNum and sampleCnt are used only for the progress callback. + cb=_cb; + sampleNum = _m_trg->vn; + sampleCnt = 0; + if(storeBarycentricCoordsAsAttributesFlag) + { + if(useVertexSampling==false){ + qDebug("adding attribute to target mesh\n"); + PerVertBaricentricCoordsHandle = vcg::tri::Allocator:: GetPerVertexAttribute (*_m_trg,std::string("BarycentricCoords")); + PerVertNearestFaceIndex = vcg::tri::Allocator:: GetPerVertexAttribute (*_m_trg,std::string("NearestFaceIndex")); + } else { + PerVertNearestVertexIndex = vcg::tri::Allocator:: GetPerVertexAttribute (*_m_trg,std::string("NearestVertexIndex")); + } + } } // this function is called for each vertex of the target mesh. @@ -193,8 +203,14 @@ public: nearestV = tri::GetClosestVertex(*m,unifGridVert,startPt,dist_upper_bound,dist); //(PDistFunct,markerFunctor,startPt,dist_upper_bound,dist,closestPt); if(cb) cb(sampleCnt++*100/sampleNum,"Resampling Vertex attributes"); if(storeDistanceAsQualityFlag) p.Q() = dist; - if(dist == dist_upper_bound) return ; - + if(dist == dist_upper_bound) + { + if(storeBarycentricCoordsAsAttributesFlag) + PerVertNearestVertexIndex[p]=-1; + return ; + } + if(storeBarycentricCoordsAsAttributesFlag) + PerVertNearestVertexIndex[p]=tri::Index(*m,nearestV); if(coordFlag) p.P()=nearestV->P(); if(colorFlag) p.C() = nearestV->C(); if(normalFlag) p.N() = nearestV->N(); @@ -208,12 +224,21 @@ public: dist=dist_upper_bound; if(cb) cb(sampleCnt++*100/sampleNum,"Resampling Vertex attributes"); nearestF = unifGridFace.GetClosest(PDistFunct,markerFunctor,startPt,dist_upper_bound,dist,closestPt); + + if(!nearestF && storeBarycentricCoordsAsAttributesFlag){ + PerVertBaricentricCoordsHandle[p]=Point3f(0,0,0); + PerVertNearestFaceIndex[p]=-1; + } if(dist == dist_upper_bound) return ; Point3m interp; InterpolationParameters(*nearestF,(*nearestF).cN(),closestPt, interp); interp[2]=1.0-interp[1]-interp[0]; - + if(storeBarycentricCoordsAsAttributesFlag) + { + PerVertBaricentricCoordsHandle[p]=interp; + PerVertNearestFaceIndex[p]=tri::Index(*m,nearestF); + } if(coordFlag) p.P()=closestPt; if(colorFlag) p.C().lerp(nearestF->V(0)->C(),nearestF->V(1)->C(),nearestF->V(2)->C(),interp); if(normalFlag) p.N() = nearestF->V(0)->N()*interp[0] + nearestF->V(1)->N()*interp[1] + nearestF->V(2)->N()*interp[2]; @@ -223,6 +248,7 @@ public: if (nearestF->IsS()) p.SetS(); else if (nearestF->V(0)->IsS() || nearestF->V(1)->IsS() || nearestF->V(2)->IsS()) p.SetS(); } + } } }; // end class RedetailSampler @@ -580,7 +606,7 @@ RichParameterList FilterDocSampling::initParameterList(const QAction *action, co break; case FP_CLUSTERED_SAMPLING :{ float maxVal = md.mm()->cm.bbox.Diag(); - parlst.addParam(RichAbsPerc("Threshold",maxVal*0.01,0,maxVal,"Cell Size", "The size of the cell of the clustering grid. Smaller the cell finer the resulting mesh. For obtaining a very coarse mesh use larger values.")); + parlst.addParam(RichPercentage("Threshold",maxVal*0.01,0,maxVal,"Cell Size", "The size of the cell of the clustering grid. Smaller the cell finer the resulting mesh. For obtaining a very coarse mesh use larger values.")); parlst.addParam(RichEnum("Sampling", 1, QStringList() << "Average" << "Closest to center", @@ -603,7 +629,7 @@ RichParameterList FilterDocSampling::initParameterList(const QAction *action, co case FP_POINTCLOUD_SIMPLIFICATION : parlst.addParam(RichInt("SampleNum", 1000, "Number of samples", "The desired number of samples. The ray of the disk is calculated according to the sampling density.")); - parlst.addParam(RichAbsPerc("Radius", 0, 0, md.mm()->cm.bbox.Diag(), "Explicit Radius", "If not zero this parameter override the previous parameter to allow exact radius specification")); + parlst.addParam(RichPercentage("Radius", 0, 0, md.mm()->cm.bbox.Diag(), "Explicit Radius", "If not zero this parameter override the previous parameter to allow exact radius specification")); parlst.addParam(RichBool("BestSampleFlag", true, "Best Sample Heuristic", "If true it will use a simple heuristic for choosing the samples. At a small cost (it can slow a bit the process) it usually improve the maximality of the generated sampling. ")); parlst.addParam(RichInt("BestSamplePool", 10, "Best Sample Pool Size", "Used only if the Best Sample Flag is true. It control the number of attempt that it makes to get the best sample. It is reasonable that it is smaller than the Montecarlo oversampling factor.")); parlst.addParam(RichBool("ExactNumFlag", false, "Precise sample number", "If requested it will try to do a dicotomic search for the best poisson disk radius that will generate the requested number of samples with the below specified tolerance. Obviously it will takes much longer.")); @@ -612,7 +638,7 @@ RichParameterList FilterDocSampling::initParameterList(const QAction *action, co case FP_POISSONDISK_SAMPLING : parlst.addParam(RichInt("SampleNum", 1000, "Number of samples", "The desired number of samples. The ray of the disk is calculated according to the sampling density.")); - parlst.addParam(RichAbsPerc("Radius", 0, 0, md.mm()->cm.bbox.Diag(), "Explicit Radius", "If not zero this parameter override the previous parameter to allow exact radius specification")); + parlst.addParam(RichPercentage("Radius", 0, 0, md.mm()->cm.bbox.Diag(), "Explicit Radius", "If not zero this parameter override the previous parameter to allow exact radius specification")); parlst.addParam(RichInt("MontecarloRate", 20, "MonterCarlo OverSampling", "The over-sampling rate that is used to generate the initial Montecarlo samples (e.g. if this parameter is K means thatK x poisson sample points will be used). The generated Poisson-disk samples are a subset of these initial Montecarlo samples. Larger this number slows the process but make it a bit more accurate.")); parlst.addParam(RichBool("SaveMontecarlo", false, "Save Montecarlo", "If true, it will generate an additional Layer with the montecarlo sampling that was pruned to build the poisson distribution.")); parlst.addParam(RichBool("ApproximateGeodesicDistance", false, "Approximate Geodesic Distance", "If true Poisson Disc distances are computed using an approximate geodesic distance, e.g. an euclidean distance weighted by a function of the difference between the normals of the two points.")); @@ -664,7 +690,7 @@ RichParameterList FilterDocSampling::initParameterList(const QAction *action, co parlst.addParam(RichBool("SampleFace", false, "Sample Faces", "See the above comment.")); parlst.addParam(RichInt("SampleNum", md.mm()->cm.vn, "Number of samples", "The desired number of samples. It can be smaller or larger than the mesh size, and according to the chosen sampling strategy it will try to adapt.")); - parlst.addParam(RichAbsPerc("MaxDist", md.mm()->cm.bbox.Diag() / 2.0, 0.0f, md.bbox().Diag(), + parlst.addParam(RichPercentage("MaxDist", md.mm()->cm.bbox.Diag() / 2.0, 0.0f, md.bbox().Diag(), tr("Max Distance"), tr("Sample points for which we do not find anything within this distance are rejected and not considered neither for averaging nor for max."))); } break; @@ -686,7 +712,7 @@ RichParameterList FilterDocSampling::initParameterList(const QAction *action, co parlst.addParam(RichBool("SignedDist", true, "Compute Signed Distance", "If TRUE, the distance is signed; if FALSE, it will compute the distance absolute value.")); - parlst.addParam(RichAbsPerc("MaxDist", md.mm()->cm.bbox.Diag(), 0.0f, md.bbox().Diag(), + parlst.addParam(RichPercentage("MaxDist", md.mm()->cm.bbox.Diag(), 0.0f, md.bbox().Diag(), tr("Max Distance [abs]"), tr("Search is interrupted when nothing is found within this distance range [+maxDistance -maxDistance]."))); } break; @@ -703,6 +729,9 @@ RichParameterList FilterDocSampling::initParameterList(const QAction *action, co "The mesh that contains the source data that we want to transfer.")); parlst.addParam(RichMesh ("TargetMesh", vertexMesh->id(),&md, "Target Mesh", "The mesh whose vertices will receive the data from the source.")); + parlst.addParam(RichBool ("VertexSampling", false, "Vertex Sampling", + "if enabled for each vertex of the target mesh we search the closest vertex in the source mesh and directly copy the found attributes, otherwise we search for the closest point on the source surface that usually falls inside a face and attribute are therefore interpolated")); + parlst.addParam(RichBool ("GeomTransfer", false, "Transfer Geometry", "if enabled, the position of each vertex of the target mesh will be snapped onto the corresponding closest point on the source mesh")); parlst.addParam(RichBool ("NormalTransfer", false, "Transfer Normal", @@ -715,7 +744,9 @@ RichParameterList FilterDocSampling::initParameterList(const QAction *action, co "if enabled, each vertex of the target mesh will be selected if the corresponding closest point on the source mesh falls in a selected face")); parlst.addParam(RichBool ("QualityDistance", false, "Store dist. as quality", "if enabled, we store the distance of the transferred value as in the vertex quality")); - parlst.addParam(RichAbsPerc("UpperBound", md.mm()->cm.bbox.Diag()/50.0, 0.0f, md.mm()->cm.bbox.Diag(), + parlst.addParam(RichBool ("SaveBarycentric", false, "Save barycentric coords", + "if enabled, we store as per vertex attributes of the target mesh, the index of the closest face and the barycentric coordinates of its position inside that face of the src mesh. If vertex sampling is enabled or if source mesh is a point cloud, only the index of the corresponding closest vertex on the src is saved.")); + parlst.addParam(RichPercentage("UpperBound", md.mm()->cm.bbox.Diag()/50.0, 0.0f, md.mm()->cm.bbox.Diag(), tr("Max Dist Search"), tr("Sample points for which we do not find anything within this distance are rejected and not considered for recovering attributes."))); parlst.addParam(RichBool ("onSelected", false, "Only on selection", "If checked, only transfer to selected vertices on TARGET mesh")); @@ -723,10 +754,10 @@ RichParameterList FilterDocSampling::initParameterList(const QAction *action, co case FP_UNIFORM_MESH_RESAMPLING : { - parlst.addParam(RichAbsPerc("CellSize", md.mm()->cm.bbox.Diag()/50.0, 0.0f, md.mm()->cm.bbox.Diag(), + parlst.addParam(RichPercentage("CellSize", md.mm()->cm.bbox.Diag()/50.0, 0.0f, md.mm()->cm.bbox.Diag(), tr("Precision"), tr("Size of the cell, the default is 1/50 of the box diag. Smaller cells give better precision at a higher computational cost. Remember that halving the cell size means that you build a volume 8 times larger."))); - parlst.addParam(RichAbsPerc("Offset", 0.0, -md.mm()->cm.bbox.Diag()/5.0f, md.mm()->cm.bbox.Diag()/5.0f, + parlst.addParam(RichPercentage("Offset", 0.0, -md.mm()->cm.bbox.Diag()/5.0f, md.mm()->cm.bbox.Diag()/5.0f, tr("Offset"), tr("Offset of the created surface (i.e. distance of the created surface from the original one).
" "If offset is zero, the created surface passes on the original mesh itself. " "Values greater than zero mean an external surface, and lower than zero mean an internal surface.
" @@ -781,10 +812,10 @@ RichParameterList FilterDocSampling::initParameterList(const QAction *action, co } break; case FP_REGULAR_RECURSIVE_SAMPLING : { - parlst.addParam(RichAbsPerc("CellSize", md.mm()->cm.bbox.Diag()/50.0, 0.0f, md.mm()->cm.bbox.Diag(), + parlst.addParam(RichPercentage("CellSize", md.mm()->cm.bbox.Diag()/50.0, 0.0f, md.mm()->cm.bbox.Diag(), tr("Precision"), tr("Size of the cell, the default is 1/50 of the box diag. Smaller cells give better precision at a higher computational cost. Remember that halving the cell size means that you build a volume 8 times larger."))); - parlst.addParam(RichAbsPerc("Offset", 0.0, -md.mm()->cm.bbox.Diag()/5.0f, md.mm()->cm.bbox.Diag()/5.0f, + parlst.addParam(RichPercentage("Offset", 0.0, -md.mm()->cm.bbox.Diag()/5.0f, md.mm()->cm.bbox.Diag()/5.0f, tr("Offset"), tr("Offset of the created surface (i.e. distance of the created surface from the original one).
" "If offset is zero, the created surface passes on the original mesh itself. " "Values greater than zero mean an external surface, and lower than zero mean an internal surface.
" @@ -967,9 +998,9 @@ std::map FilterDocSampling::applyFilter( { case 0 : { - tri::Clustering > ClusteringGrid; - ClusteringGrid.Init(curMM->cm.bbox,100000,threshold); - ClusteringGrid.AddPointSet(curMM->cm,selected); + tri::Clustering> ClusteringGrid( + curMM->cm.bbox, 100000, threshold); + ClusteringGrid.AddPointSet(curMM->cm, selected); ClusteringGrid.ExtractPointSet(mm->cm); ClusteringGrid.SelectPointSet(curMM->cm); tri::UpdateSelection::FaceFromVertexLoose(curMM->cm); @@ -978,8 +1009,8 @@ std::map FilterDocSampling::applyFilter( case 1 : { - vcg::tri::Clustering > ClusteringGrid; - ClusteringGrid.Init(curMM->cm.bbox,100000,threshold); + vcg::tri::Clustering> ClusteringGrid( + curMM->cm.bbox, 100000, threshold); ClusteringGrid.AddPointSet(curMM->cm,selected); ClusteringGrid.SelectPointSet(curMM->cm); tri::UpdateSelection::FaceFromVertexLoose(curMM->cm); @@ -1259,12 +1290,14 @@ std::map FilterDocSampling::applyFilter( bool qualityT = par.getBool("QualityTransfer"); bool selectionT = par.getBool("SelectionTransfer"); bool distquality = par.getBool("QualityDistance"); - + bool vertSampling = par.getBool("VertexSampling"); + bool saveBarycentric = par.getBool("SaveBarycentric"); + if (srcMesh == trgMesh){ log("Vertex Attribute Transfer: cannot compute, it is the same mesh"); throw MLException("Cannot compute, it is the same mesh"); } - if (!colorT && !geomT && !qualityT && !normalT && !selectionT) + if (!colorT && !geomT && !qualityT && !normalT && !selectionT && !saveBarycentric) { log("Vertex Attribute Transfer: you have to choose at least one attribute to be sampled"); throw MLException("You have to choose at least one attribute to be sampled"); @@ -1291,8 +1324,7 @@ std::map FilterDocSampling::applyFilter( tri::UpdateNormal::PerFaceNormalized(srcMesh->cm); LocalRedetailSampler rs; - rs.init(&(srcMesh->cm),cb,trgMesh->cm.vn); - + rs.useVertexSampling = vertSampling; rs.dist_upper_bound = upperbound; rs.colorFlag = colorT; rs.coordFlag = geomT; @@ -1300,7 +1332,9 @@ std::map FilterDocSampling::applyFilter( rs.qualityFlag = qualityT; rs.selectionFlag = selectionT; rs.storeDistanceAsQualityFlag = distquality; - + rs.storeBarycentricCoordsAsAttributesFlag = saveBarycentric; + rs.init(&(srcMesh->cm),&(trgMesh->cm),cb); + qDebug("apply: using vertex sampling %s\n",rs.useVertexSampling?"True":"False"); if(rs.colorFlag) trgMesh->updateDataMask(MeshModel::MM_VERTCOLOR); if(rs.qualityFlag || rs.storeDistanceAsQualityFlag) trgMesh->updateDataMask(MeshModel::MM_VERTQUALITY); @@ -1390,7 +1424,6 @@ std::map FilterDocSampling::applyFilter( typedef vcg::SpatialHashTable SampleSHT; SampleSHT sht; tri::EmptyTMark markerFunctor; - typedef vcg::vertex::PointDistanceFunctor VDistFunct; tri::UpdateColor::PerVertexConstant(mmM->cm, Color4b::LightGray); tri::UpdateQuality::VertexConstant(mmM->cm, std::numeric_limits::max()); bool approximateGeodeticFlag = par.getBool("ApproximateGeodetic"); diff --git a/src/meshlabplugins/filter_sdfgpu/filter_sdfgpu.cpp b/src/meshlabplugins/filter_sdfgpu/filter_sdfgpu.cpp index 2aaea4de7..1e32c37a2 100644 --- a/src/meshlabplugins/filter_sdfgpu/filter_sdfgpu.cpp +++ b/src/meshlabplugins/filter_sdfgpu/filter_sdfgpu.cpp @@ -110,9 +110,9 @@ QString SdfGpuPlugin::filterName(ActionIDType filterId) const QString SdfGpuPlugin::pythonFilterName(ActionIDType f) const { switch (f) { - case SDF_SDF: return QString("compute_scalar_by_shape_diameter_function_per_vertex"); + case SDF_SDF: return QString("compute_scalar_by_shape_diameter_function_per_vertex_gpu"); case SDF_DEPTH_COMPLEXITY: return QString("get_depth_complexity"); - case SDF_OBSCURANCE: return QString("compute_scalar_by_volumetric_obscurance"); + case SDF_OBSCURANCE: return QString("compute_scalar_by_volumetric_obscurance_gpu"); default: assert(0); return QString(); } diff --git a/src/meshlabplugins/filter_texture/filter_texture.cpp b/src/meshlabplugins/filter_texture/filter_texture.cpp index b655f1979..04745b37c 100644 --- a/src/meshlabplugins/filter_texture/filter_texture.cpp +++ b/src/meshlabplugins/filter_texture/filter_texture.cpp @@ -243,7 +243,7 @@ RichParameterList FilterTexturePlugin::initParameterList(const QAction *action, parlst.addParam(RichEnum("method", 1, QStringList("Basic") << "Space-optimizing", "Method", "Choose space optimizing to map smaller faces into smaller triangles in parametrizazion domain")); break; case FP_SET_TEXTURE : - parlst.addParam(RichOpenFile("textName", "", QStringList{"*.png", "*.jpg", "*.jpeg", "*.dds"},"Texture file", "Sets the given input image as unique texture of the mesh.")); + parlst.addParam(RichFileOpen("textName", "", QStringList{"*.png", "*.jpg", "*.jpeg", "*.dds"},"Texture file", "Sets the given input image as unique texture of the mesh.")); parlst.addParam(RichBool("use_dummy_texture", false, "Use dummy texture", "If checked, the filter will set a dummy texture instead of loading an image. The 'Texture File' parameter will be ignored.")); break; case FP_COLOR_TO_TEXTURE : { @@ -261,7 +261,7 @@ RichParameterList FilterTexturePlugin::initParameterList(const QAction *action, "The mesh whose texture will be filled according to source mesh data")); parlst.addParam(RichEnum("AttributeEnum", 0, QStringList("Vertex Color") << "Vertex Normal" << "Vertex Quality"<< "Texture Color", "Color Data Source", "Choose what attribute has to be transferred onto the target texture. You can choose between Per vertex attributes (color,normal,quality) or to transfer color information from source mesh texture")); - parlst.addParam(RichAbsPerc("upperBound", md.mm()->cm.bbox.Diag()/50.0, 0.0f, md.mm()->cm.bbox.Diag(), + parlst.addParam(RichPercentage("upperBound", md.mm()->cm.bbox.Diag()/50.0, 0.0f, md.mm()->cm.bbox.Diag(), tr("Max Dist Search"), tr("Sample points for which we do not find anything within this distance are rejected and not considered for recovering data"))); parlst.addParam(RichString("textName", trgFileName, "Texture file", "The texture file to be created")); parlst.addParam(RichInt("textW", 1024, "Texture width (px)", "The texture width")); @@ -275,7 +275,7 @@ RichParameterList FilterTexturePlugin::initParameterList(const QAction *action, "The mesh with associated texture that we want to sample from")); parlst.addParam(RichMesh ("targetMesh",trg->id(),&md, "Target Mesh", "The mesh whose vertex color will be filled according to source mesh texture")); - parlst.addParam(RichAbsPerc("upperBound", md.mm()->cm.bbox.Diag()/50.0, 0.0f, md.mm()->cm.bbox.Diag(), + parlst.addParam(RichPercentage("upperBound", md.mm()->cm.bbox.Diag()/50.0, 0.0f, md.mm()->cm.bbox.Diag(), tr("Max Dist Search"), tr("Sample points for which we do not find anything within this distance are rejected and not considered for recovering color"))); } break; diff --git a/src/meshlabplugins/filter_unsharp/filter_unsharp.cpp b/src/meshlabplugins/filter_unsharp/filter_unsharp.cpp index c7982efab..b729d31b2 100644 --- a/src/meshlabplugins/filter_unsharp/filter_unsharp.cpp +++ b/src/meshlabplugins/filter_unsharp/filter_unsharp.cpp @@ -606,7 +606,7 @@ RichParameterList FilterUnsharp::initParameterList(const QAction* action, const Point3f(0, 0, 0), "Viewpoint", "The position of the view point that is used to get the constraint direction.")); - parlst.addParam(RichAbsPerc( + parlst.addParam(RichPercentage( "delta", 1.0, 0, @@ -680,7 +680,7 @@ RichParameterList FilterUnsharp::initParameterList(const QAction* action, const "The number of times that the whole algorithm (normal smoothing + vertex fitting) is " "iterated.")); float maxVal = md.mm()->cm.bbox.Diag() / 10; - parlst.addParam(RichAbsPerc("delta", maxVal * 0.01, 0, maxVal, "delta", "")); + parlst.addParam(RichPercentage("delta", maxVal * 0.01, 0, maxVal, "delta", "")); parlst.addParam(RichBool( "Selected", md.mm()->cm.sfn > 0, diff --git a/src/meshlabplugins/filter_voronoi/filter_voronoi.cpp b/src/meshlabplugins/filter_voronoi/filter_voronoi.cpp index 0ce84aa01..a8986db14 100644 --- a/src/meshlabplugins/filter_voronoi/filter_voronoi.cpp +++ b/src/meshlabplugins/filter_voronoi/filter_voronoi.cpp @@ -181,13 +181,13 @@ RichParameterList FilterVoronoiPlugin::initParameterList(const QAction* action, "")); break; case VOLUME_SAMPLING: - par.addParam(RichAbsPerc("sampleSurfRadius", m.cm.bbox.Diag() / 500.0, 0, m.cm.bbox.Diag(),"Surface Sampling Radius", "Surface Sampling is used only as an optimization.")); + par.addParam(RichPercentage("sampleSurfRadius", m.cm.bbox.Diag() / 500.0, 0, m.cm.bbox.Diag(),"Surface Sampling Radius", "Surface Sampling is used only as an optimization.")); par.addParam(RichInt("sampleVolNum", 200000, "Volume Sample Num.", "Number of volumetric samples scattered inside the mesh and used for choosing the voronoi seeds and performing the Lloyd relaxation for having a centroidal voronoi diagram.")); par.addParam(RichBool("poissonFiltering", true, "Poisson Filtering", "If true the base montecarlo sampling of the volume is filtered to get a poisson disk volumetric distribution.")); - par.addParam(RichAbsPerc("poissonRadius", m.cm.bbox.Diag() / 100.0, 0, m.cm.bbox.Diag(), "Poisson Radius", "Number of voxel per side in the volumetric representation.")); + par.addParam(RichPercentage("poissonRadius", m.cm.bbox.Diag() / 100.0, 0, m.cm.bbox.Diag(), "Poisson Radius", "Number of voxel per side in the volumetric representation.")); break; case VORONOI_SCAFFOLDING: - par.addParam(RichAbsPerc("sampleSurfRadius", m.cm.bbox.Diag() / 100.0, 0, m.cm.bbox.Diag(), "Surface Sampling Radius", "Surface Sampling is used only as an optimization.")); + par.addParam(RichPercentage("sampleSurfRadius", m.cm.bbox.Diag() / 100.0, 0, m.cm.bbox.Diag(), "Surface Sampling Radius", "Surface Sampling is used only as an optimization.")); par.addParam(RichInt("sampleVolNum", 100000, "Volume Sample Num.", "Number of volumetric samples scattered inside the mesh and used for choosing the voronoi seeds and performing the Lloyd relaxation for having a centroidal voronoi diagram.")); par.addParam(RichInt("voxelRes", 50, "Volume Side Resolution", "Number of voxel per side in the volumetric representation.")); par.addParam(RichFloat("isoThr", 1, "Width of the entity (in voxel)", "Number of voxel per side in the volumetric representation.")); @@ -198,14 +198,14 @@ RichParameterList FilterVoronoiPlugin::initParameterList(const QAction* action, break; case BUILD_SHELL: par.addParam(RichBool("edgeCylFlag", true, "Edge -> Cyl.", "If True all the edges are converted into cylinders.")); - par.addParam(RichAbsPerc("edgeCylRadius", m.cm.bbox.Diag() / 100.0, 0, m.cm.bbox.Diag(), "Edge Cylinder Rad.", "The radius of the cylinder replacing each edge.")); + par.addParam(RichPercentage("edgeCylRadius", m.cm.bbox.Diag() / 100.0, 0, m.cm.bbox.Diag(), "Edge Cylinder Rad.", "The radius of the cylinder replacing each edge.")); par.addParam(RichBool("vertCylFlag", false, "Vertex -> Cyl.", "If True all the vertices are converted into cylinders.")); - par.addParam(RichAbsPerc("vertCylRadius", m.cm.bbox.Diag() / 100.0, 0, m.cm.bbox.Diag(), "Vertex Cylinder Rad.", "The radius of the cylinder replacing each vertex.")); + par.addParam(RichPercentage("vertCylRadius", m.cm.bbox.Diag() / 100.0, 0, m.cm.bbox.Diag(), "Vertex Cylinder Rad.", "The radius of the cylinder replacing each vertex.")); par.addParam(RichBool("vertSphFlag", true, "Vertex -> Sph.", "If True all the vertices are converted into sphere.")); - par.addParam(RichAbsPerc("vertSphRadius", m.cm.bbox.Diag() / 100.0, 0, m.cm.bbox.Diag(), "Vertex Sphere Rad.", "The radius of the sphere replacing each vertex.")); + par.addParam(RichPercentage("vertSphRadius", m.cm.bbox.Diag() / 100.0, 0, m.cm.bbox.Diag(), "Vertex Sphere Rad.", "The radius of the sphere replacing each vertex.")); par.addParam(RichBool("faceExtFlag", true, "Face -> Prism", "If True all the faces are converted into prism.")); - par.addParam(RichAbsPerc("faceExtHeight", m.cm.bbox.Diag() / 200.0, 0, m.cm.bbox.Diag(), "Face Prism Height", "The Height of the prism that is substituted with each face.")); - par.addParam(RichAbsPerc("faceExtInset", m.cm.bbox.Diag() / 200.0, 0, m.cm.bbox.Diag(), "Face Prism Inset", "The inset radius of each prism, e.g. how much it is moved toward the inside each vertex on the border of the prism.")); + par.addParam(RichPercentage("faceExtHeight", m.cm.bbox.Diag() / 200.0, 0, m.cm.bbox.Diag(), "Face Prism Height", "The Height of the prism that is substituted with each face.")); + par.addParam(RichPercentage("faceExtInset", m.cm.bbox.Diag() / 200.0, 0, m.cm.bbox.Diag(), "Face Prism Inset", "The inset radius of each prism, e.g. how much it is moved toward the inside each vertex on the border of the prism.")); par.addParam(RichBool("edgeFauxFlag", true, "Ignore faux edges", "If true only the Non-Faux edges will be considered for conversion.")); par.addParam(RichInt("cylinderSideNum", 16, "Cylinder Side", "Number of sides of the cylinder (both edge and vertex).")); break; diff --git a/src/meshlabplugins/io_u3d/io_u3d.cpp b/src/meshlabplugins/io_u3d/io_u3d.cpp index 9df0b0fdb..0c90d3bcf 100644 --- a/src/meshlabplugins/io_u3d/io_u3d.cpp +++ b/src/meshlabplugins/io_u3d/io_u3d.cpp @@ -296,19 +296,19 @@ void U3DIOPlugin::saveLatex(const QString& file,const vcg::tri::io::u3dparameter std::string u3d_final = vcg::tri::io::QtUtilityFunctions::fileNameFromTrimmedPath(file_trim).toStdString(); latex.write(0,"\\documentclass[a4paper]{article}"); - latex.write(0,"\\usepackage[3D]{movie15}"); + latex.write(0,"\\usepackage[3Dmenu]{media9}"); latex.write(0,"\\usepackage{hyperref}"); latex.write(0,"\\usepackage[UKenglish]{babel}"); latex.write(0,"\\begin{document}"); - latex.write(0,"\\includemovie["); - latex.write(1,"poster,"); - latex.write(1,"toolbar, %same as `controls\'"); + latex.write(0,"\\includemedia["); + latex.write(1,"width=\\linewidth,height=\\linewidth,"); + latex.write(1,"3Dmenu,'"); QString u3d_text = QString::fromStdString(u3d_final); substituteChar(u3d_text,QChar('_'),QString("")); latex.write(1,"label=" + u3d_text.toStdString() + ","); - latex.write(1,"text=(" + u3d_text.toStdString() + "),"); + latex.write(1,"activate=pageopen,"); std::string cam_string; typename vcg::tri::io::u3dparametersclasses::Movie15Parameters::CameraParameters* cam = mov_par._campar; if (cam != NULL) { @@ -319,8 +319,8 @@ void U3DIOPlugin::saveLatex(const QString& file,const vcg::tri::io::u3dparameter ", 3Dcoo=" + TextUtility::nmbToStr(-cam->_obj_pos.X()) + " " + TextUtility::nmbToStr(cam->_obj_pos.Z()) + " " + TextUtility::nmbToStr(cam->_obj_pos.Y()) + ","; latex.write(1,cam_string); } - latex.write(1,"3Dlights=CAD,"); - latex.write(0,"]{\\linewidth}{\\linewidth}{" + u3d_final + "}"); + latex.write(1,"3Dlights=CAD"); + latex.write(0,"]{}{" + u3d_final + "}"); latex.write(0,"\\end{document}"); } diff --git a/src/vcglib b/src/vcglib index 59807bd57..6ac9e0c64 160000 --- a/src/vcglib +++ b/src/vcglib @@ -1 +1 @@ -Subproject commit 59807bd573c6fe7020e0892d99853e5a34d77ae4 +Subproject commit 6ac9e0c647a63e0e037813a1e92bd050d13efc85