Commit 14197aad authored by Jan Möbius's avatar Jan Möbius

Merge branch 'Plugin-AlignMeshes' into 'master'

Plugin align meshes



See merge request !45
parents 113cddc9 2e465b40
Pipeline #299 passed with stage
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openflipper.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenFlipper. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
\*===========================================================================*/
#include <Eigen/Dense>
namespace align{
template< class MeshT >
void moveToCOG(MeshT& _mesh) {
ACG::Vec3d mean(0.0);
for (typename MeshT::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it) {
mean += _mesh.point(*v_it);
}
mean /= (double)_mesh.n_vertices();
for (TriMesh::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it) {
_mesh.set_point(*v_it, _mesh.point(*v_it) - mean);
}
}
template< class MeshT >
void rotate(MeshT& _mesh) {
using namespace Eigen;
Matrix3Xd data = Matrix3Xd::Zero(3, _mesh.n_vertices());
size_t i(0);
for (typename MeshT::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it, ++i) {
const ACG::Vec3d tmp = _mesh.point(*v_it);
data.col(i) = Vector3d(tmp[0], tmp[1], tmp[2]);
}
Matrix3d covar = (data * data.transpose()) / (double)_mesh.n_vertices();
JacobiSVD<Matrix3d> svd(covar, ComputeThinU | ComputeThinV);
const Matrix3d& u = svd.matrixU();
Eigen::Vector3d v0 = u.col(0);
Eigen::Vector3d v1 = u.col(1);
Eigen::Vector3d v2 = v0.cross(v1);
v0.normalize();
v1.normalize();
v2.normalize();
Matrix3d trans;
trans.col(0) = v0;
trans.col(1) = v1;
trans.col(2) = v2;
Matrix3d invTrans = trans.inverse();
ACG::Matrix4x4d mat;
mat.identity();
for (i = 0; i < 3; ++i) {
for (size_t j = 0; j < 3; ++j) {
mat(i,j) = invTrans(i,j);
}
}
for (typename MeshT::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it, ++i) {
const ACG::Vec4d tmp(_mesh.point(*v_it)[0], _mesh.point(*v_it)[1], _mesh.point(*v_it)[2], 1.0);
const ACG::Vec4d res = mat * tmp;
_mesh.set_point(*v_it, ACG::Vec3d(res[0], res[1],res[2]));
}
}
template< class MeshT >
void moveCenterOfBBToOrigin(MeshT& _mesh) {
ACG::Vec3d min(DBL_MAX);
ACG::Vec3d max(-DBL_MAX);
for (typename MeshT::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it) {
min.minimize(_mesh.point(*v_it));
max.maximize(_mesh.point(*v_it));
}
const ACG::Vec3d diag = max - min;
const ACG::Vec3d center = min + 0.5*diag;
for (typename MeshT::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it) {
_mesh.point(*v_it) -= center;
}
}
template< class MeshT >
void scaleToUnitCubeNonUniform(MeshT& _mesh) {
ACG::Vec3d min(DBL_MAX);
ACG::Vec3d max(-DBL_MAX);
for (typename MeshT::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it) {
min.minimize(_mesh.point(*v_it));
max.maximize(_mesh.point(*v_it));
}
const ACG::Vec3d diagonal = max - min;
const double maxDiag = std::max(std::max(diagonal[0],diagonal[1]),diagonal[2]);
OpenMesh::MPropHandleT<ACG::Vec3d> origDiagonal;
if (!_mesh.get_property_handle(origDiagonal, "origDiagonal"))
_mesh.add_property(origDiagonal, "origDiagonal");
_mesh.mproperty(origDiagonal).set_persistent(true);
_mesh.property(origDiagonal) = diagonal;
for (typename MeshT::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it) {
_mesh.point(*v_it)[0] /= diagonal[0];
_mesh.point(*v_it)[1] /= diagonal[1];
_mesh.point(*v_it)[2] /= diagonal[2];
}
}
template< class MeshT >
void scaleToUnitCubeUniform(MeshT& _mesh) {
ACG::Vec3d min(DBL_MAX);
ACG::Vec3d max(-DBL_MAX);
for (typename MeshT::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it) {
min.minimize(_mesh.point(*v_it));
max.maximize(_mesh.point(*v_it));
}
const ACG::Vec3d diagonal = max - min;
const double maxDiag = std::max(std::max(diagonal[0],diagonal[1]),diagonal[2]);
OpenMesh::MPropHandleT<ACG::Vec3d> origDiagonal;
if (!_mesh.get_property_handle(origDiagonal, "origDiagonal"))
_mesh.add_property(origDiagonal, "origDiagonal");
_mesh.mproperty(origDiagonal).set_persistent(true);
_mesh.property(origDiagonal) = diagonal;
for (typename MeshT::VertexIter v_it = _mesh.vertices_begin(); v_it != _mesh.vertices_end(); ++v_it) {
_mesh.point(*v_it)[0] /= maxDiag;
_mesh.point(*v_it)[1] /= maxDiag;
_mesh.point(*v_it)[2] /= maxDiag;
}
}
} // namespace align
#define ALIGNT_CC
namespace align{
/** \brief Move Mesh into center of gravity
*
* @param _mesh Mesh to modify
*/
template< class MeshT >
void moveToCOG(MeshT& _mesh);
/** \brief Rotate a mesh such that its largest PCA axis is aligned to x and second largest aligned to y
*
* @param _mesh Mesh to modify
*/
template< class MeshT >
void rotate(MeshT& _mesh);
/** \brief Move mesh such that its bounding box center is in the origin
*
* @param _mesh Mesh to modify
*/
template< class MeshT >
void moveCenterOfBBToOrigin(MeshT& _mesh);
/** \brief Scale mesh such that it has length 1 on each separate axis
*
* @param _mesh Mesh to modify
*/
template< class MeshT >
void scaleToUnitCubeNonUniform(MeshT& _mesh);
/** \brief Scale mesh such that it has length 1 on the largest axis (keeps ratios of axis)
*
* @param _mesh Mesh to modify
*/
template< class MeshT >
void scaleToUnitCubeUniform(MeshT& _mesh);
} // namespace align
#if defined(INCLUDE_TEMPLATES) && !defined(ALIGNT_CC)
#define MALIGNT_TEMPLATES
#include "AlignT.cc"
#endif
include (plugin)
openflipper_plugin(DIRS Widgets DEPS OpenMesh EIGEN3)
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openflipper.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenFlipper. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
\*===========================================================================*/
#include "PluginAlignMeshes.hh"
#include <ObjectTypes/TriangleMesh/TriangleMesh.hh>
#include <ObjectTypes/PolyMesh/PolyMesh.hh>
#include "AlignT.hh"
PluginAlignMeshes::PluginAlignMeshes() :
toolBox_(0) {
}
PluginAlignMeshes::~PluginAlignMeshes() {
}
void PluginAlignMeshes::initializePlugin() {
toolBox_ = new AlignMeshesToolbox();
emit addToolbox("Align Meshes", toolBox_);
connect(toolBox_->alignMeshesButton, SIGNAL(pressed()), SLOT(alignMeshes()));
connect(toolBox_->scaleToUnitCubeUniformButton, SIGNAL(pressed()), SLOT(scaleToUnitCubeUniform()));
connect(toolBox_->scaleToUnitCubeNonUniformButton, SIGNAL(pressed()), SLOT(scaleToUnitCubeNonUniform()));
}
void PluginAlignMeshes::scaleToUnitCubeNonUniform() {
for (PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_TRIANGLE_MESH | DATA_POLY_MESH ); o_it
!= PluginFunctions::objectsEnd(); ++o_it) {
if(o_it->dataType() == DATA_TRIANGLE_MESH){
TriMesh& mesh = * PluginFunctions::triMesh(*o_it);
align::moveToCOG( mesh );
align::scaleToUnitCubeNonUniform( mesh );
align::moveToCOG( mesh );
emit log(LOGINFO,"Moved Triangle mesh scaleToUnitCubeNonUniform");
} else if(o_it->dataType() == DATA_POLY_MESH) {
PolyMesh& mesh = * PluginFunctions::polyMesh(*o_it);
align::moveToCOG( mesh );
align::scaleToUnitCubeNonUniform( mesh );
align::moveToCOG( mesh );
emit log(LOGINFO,"Moved poly mesh scaleToUnitCubeNonUniform");
}
emit updatedObject(o_it->id(), UPDATE_GEOMETRY);
}
}
void PluginAlignMeshes::scaleToUnitCubeUniform() {
for (PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_TRIANGLE_MESH); o_it
!= PluginFunctions::objectsEnd(); ++o_it) {
if(o_it->dataType() == DATA_TRIANGLE_MESH){
TriMesh& mesh = * PluginFunctions::triMesh(*o_it);
align::moveToCOG( mesh );
align::scaleToUnitCubeUniform( mesh );
align::moveToCOG( mesh );
emit log(LOGINFO,"Moved Triangle mesh scaleToUnitCubeUniform");
} else if(o_it->dataType() == DATA_POLY_MESH) {
PolyMesh& mesh = * PluginFunctions::polyMesh(*o_it);
align::moveToCOG( mesh );
align::scaleToUnitCubeUniform( mesh );
align::moveToCOG( mesh );
emit log(LOGINFO,"Moved poly mesh scaleToUnitCubeUniform");
}
emit updatedObject(o_it->id(), UPDATE_GEOMETRY);
}
}
void PluginAlignMeshes::alignMeshes() {
for (PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DATA_TRIANGLE_MESH); o_it
!= PluginFunctions::objectsEnd(); ++o_it) {
if(o_it->dataType() == DATA_TRIANGLE_MESH) {
TriMesh& mesh = * PluginFunctions::triMesh(*o_it);
align::moveToCOG( mesh );
align::rotate( mesh );
emit log(LOGINFO,"Moved Triangle mesh alignMeshes");
} else if(o_it->dataType() == DATA_POLY_MESH) {
PolyMesh& mesh = * PluginFunctions::polyMesh(*o_it);
align::moveToCOG( mesh );
align::rotate( mesh );
emit log(LOGINFO,"Moved Poly mesh alignMeshes");
}
emit updatedObject(o_it->id(), UPDATE_GEOMETRY);
}
}
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2(pluginalignmeshes, PluginAlignMeshes)
#endif
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openflipper.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenFlipper. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
\*===========================================================================*/
#pragma once
#include <QObject>
#include <OpenFlipper/BasePlugin/BaseInterface.hh>
#include <OpenFlipper/BasePlugin/LoggingInterface.hh>
#include <OpenFlipper/BasePlugin/ToolboxInterface.hh>
#include <OpenFlipper/common/Types.hh>
#include "Widgets/AlignMeshesToolbox.hh"
class PluginAlignMeshes : public QObject, BaseInterface, LoggingInterface, ToolboxInterface {
Q_OBJECT
Q_INTERFACES(BaseInterface)
Q_INTERFACES(ToolboxInterface)
Q_INTERFACES(LoggingInterface)
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA(IID "org.OpenFlipper.Plugins.Plugin-AlignMeshes")
#endif
public:
PluginAlignMeshes();
~PluginAlignMeshes();
// BaseInterface
QString name() { return QString("PluginAlignMeshes"); }
QString description() { return tr("Aligns meshes"); }
signals:
// BaseInterface
void updatedObject(int, const UpdateType);
// LoggingInterface
void log(Logtype _type, QString _message);
void log(QString _message);
// ToolboxInterface
void addToolbox(QString _name, QWidget* _widget);
public slots:
// BaseInterface
QString version() { return QString("1.0"); }
void alignMeshes();
void scaleToUnitCubeUniform();
void scaleToUnitCubeNonUniform();
private slots:
// BaseInterface
void initializePlugin();
private:
AlignMeshesToolbox* toolBox_;
};
#include "AlignMeshesToolbox.hh"
AlignMeshesToolbox::AlignMeshesToolbox(QWidget *parent)
: QWidget(parent)
{
setupUi(this);
}
#ifndef ALIGN_MESHES_TOOLBOX_HH
#define ALIGN_MESHES_TOOLBOX_HH
#include "ui_AlignMeshesToolbox.hh"
#include <QtGui>
class AlignMeshesToolbox : public QWidget, public Ui::AlignMeshesToolbox
{
Q_OBJECT
public:
AlignMeshesToolbox(QWidget *parent = 0);
};
#endif // ALIGN_MESHES_TOOLBOX_HH
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AlignMeshesToolbox</class>
<widget class="QWidget" name="AlignMeshesToolbox">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>385</width>
<height>118</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QPushButton" name="scaleToUnitCubeUniformButton">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Scale meshes &lt;span style=&quot; color:#000000;&quot;&gt;such that their biggest boundingbox axis size is 1.0. The aspect ratio of the mesh is kept.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="statusTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Scale meshes &lt;span style=&quot; color:#000000;&quot;&gt;such that their biggest boundingbox axis size is 1.0. The aspect ratio of the mesh is kept.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Scale meshes &lt;span style=&quot; color:#000000;&quot;&gt;such that their biggest boundingbox axis size is 1.0. The aspect ratio of the mesh is kept.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Scale Meshes to Unit Cube Uniformly</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="alignMeshesButton">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Aligns meshes with the unit axis. The plugin analyses the meshes (&lt;span style=&quot; font-weight:600;&quot;&gt;which are marked as target meshes&lt;/span&gt;) and aligns the mesh such that the direction of the biggest extend of the mesh is aligned with the x axis and the second largest is aligned to the y axis.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#aa0000;&quot;&gt;If you want to align meshes to each other, select both meshes as target.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="statusTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Aligns meshes with the unit axis. The plugin analyses the meshes (&lt;span style=&quot; font-weight:600;&quot;&gt;which are marked as target meshes&lt;/span&gt;) and aligns the mesh such that the direction of the biggest extend of the mesh is aligned with the x axis and the second largest is aligned to the y axis.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#aa0000;&quot;&gt;If you want to align meshes to each other, select both meshes as target.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Aligns meshes with the unit axis. The plugin analyses the meshes (&lt;span style=&quot; font-weight:600;&quot;&gt;which are marked as target meshes&lt;/span&gt;) and aligns the mesh such that the direction of the biggest extend of the mesh is aligned with the x axis and the second largest is aligned to the y axis.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; color:#aa0000;&quot;&gt;If you want to align meshes to each other, select both meshes as target.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Align Meshes with default axis</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="scaleToUnitCubeNonUniformButton">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Scale meshes such that their boundingbox axis sizes are all 1.0. The aspect ratio of the mesh is &lt;span style=&quot; font-weight:600;&quot;&gt;not&lt;/span&gt; kept.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="statusTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Scale meshes such that their boundingbox axis sizes are all 1.0. The aspect ratio of the mesh is &lt;span style=&quot; font-weight:600;&quot;&gt;not&lt;/span&gt; kept.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Scale meshes such that their boundingbox axis sizes are all 1.0. The aspect ratio of the mesh is &lt;span style=&quot; font-weight:600;&quot;&gt;not&lt;/span&gt; kept.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Scale Meshes to Unit Cube Non-Uniformly</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment