abort handled properly in eigensolver, ui improvements + ellipsoidDistance implementation

Use of Geometric Tools Engine for ellipsoidDistance computation
This commit is contained in:
Paul Leroy
2024-03-26 17:24:03 +01:00
parent 625e72b899
commit 14649ea696
8 changed files with 575 additions and 317 deletions
+1
View File
@@ -21,6 +21,7 @@ if ( PLUGIN_G3POINT )
C:/opt/eigen-3.4.0
C:/Users/PaulLeroy/miniconda3/envs/env_4_CloudCompare/include
C:/opt/open3d-devel-windows-amd64-0.18.0/include
C:/opt/GeometricTools/GTE
)
# Find installed Open3D, which exports Open3D::Open3D
+1
View File
@@ -34,6 +34,7 @@ public:
void segmentAndClusterAndClean();
void getBorders();
int cluster();
void fit();
bool processNewStacks(std::vector<std::vector<int>>& stacks, int pointCount);
bool merge(XXb& condition);
bool keep(Xb& condition);
+17
View File
@@ -22,6 +22,14 @@ public:
void emitSegmentClusterClean(){emit segmentClusterClean();}
void emitGetBorders(){emit getBorders();}
void emitAllClicked(bool state){emit allClicked(state);}
void emitOnlyOneClicked(bool state){emit onlyOneClicked(state);}
void emitOnlyOneChanged(int idx){emit onlyOneChanged(idx);}
void emitFit(){emit fit();}
void emitTransparencyChanged(double transparency){emit transparencyChanged(transparency);}
void emitSignals();
double getMaxAngle1();
double getMaxAngle2();
double getMinFlatness();
@@ -34,6 +42,8 @@ public:
void enableCluster(bool state);
void enableClean(bool state);
void setOnlyOneMax(int idx);
signals:
void segment();
void cluster();
@@ -42,6 +52,13 @@ signals:
void segmentClusterClean();
void getBorders();
void allClicked(bool state);
void onlyOneClicked(bool state);
void onlyOneChanged(int idx);
void transparencyChanged(double transparency);
void fit();
private:
Ui::qG3PointDialog *ui;
};
+23 -2
View File
@@ -12,10 +12,14 @@
#include <ccMainAppInterface.h>
#include <ccColorTypes.h>
#include <set>
class ccPointCloud;
class GrainsAsEllipsoids : public ccHObject
class GrainsAsEllipsoids : public QObject, public ccHObject
{
Q_OBJECT
public:
typedef Eigen::Array<bool, Eigen::Dynamic, Eigen::Dynamic> Xb;
@@ -54,11 +58,13 @@ public:
enum Method{
DIRECT = 0};
double ellipsoidDistance(const Eigen::ArrayXd& p, int idx);
bool explicitToImplicit(const Eigen::Array3f& center, const Eigen::Array3f& radii, const Eigen::Matrix3f &rotationMatrix, Eigen::ArrayXd& parameters);
bool implicitToExplicit(const Eigen::ArrayXd& parameters, Eigen::Array3f& center, Eigen::Array3f& radii, Eigen::Matrix3f& rotationMatrix);
Eigen::ArrayXd directFit(const Eigen::ArrayX3d& xyz);
bool directFit(const Eigen::ArrayX3d& xyz, Eigen::ArrayXd &parameters);
bool fitEllipsoidToGrain(const int grainIndex, Eigen::Array3f& center, Eigen::Array3f& radii, Eigen::Matrix3f& rotationMatrix, const Method& method=DIRECT);
@@ -71,6 +77,8 @@ public:
void setUniformValueColor(const ccColor::Rgba &color);
void drawEllipsoid(CC_DRAW_CONTEXT &context, int idx);
bool drawEllipsoids(CC_DRAW_CONTEXT &context);
bool initProgram(QOpenGLContext* context);
@@ -81,6 +89,14 @@ public:
// from ccHObject
void draw(CC_DRAW_CONTEXT& context);
void setOnlyOne(int i){m_onlyOne = i;}
void showOnlyOne(bool state){m_showAll =!state;}
void showAll(bool state);
void setTransparency(double transparency){m_transparency = transparency;}
ccPointCloud* m_cloud;
ccMainAppInterface* m_app;
Eigen::ArrayXi m_localMaximumIndexes;
@@ -98,6 +114,11 @@ public:
std::vector<Eigen::Array3f> m_center;
std::vector<Eigen::Array3f> m_radii;
std::vector<Eigen::Matrix3f> m_rotationMatrix;
std::set<int> m_fitNotOK;
double m_transparency = 1.0;
int m_onlyOne;
bool m_showAll{true};
};
#endif // GRAINSASELLIPSOIDS_H
+23 -8
View File
@@ -957,6 +957,27 @@ int G3PointAction::cluster()
return 0;
}
void G3PointAction::fit()
{
// plot display grains as ellipsoids
m_grainsAsEllipsoids = new GrainsAsEllipsoids(m_cloud, m_app, m_stacks);
m_grainsAsEllipsoids->setLocalMaximumIndexes(m_localMaximumIndexes);
m_grainColors.reset(new RGBAColorsTableType(getRandomColors(m_localMaximumIndexes.size())));
m_grainsAsEllipsoids->setGrainColorsTable(*m_grainColors);
m_grainsAsEllipsoids->setName("grains as ellipsoids");
// add connections with the dialog
connect(m_dlg, &G3PointDialog::onlyOneClicked, m_grainsAsEllipsoids, &GrainsAsEllipsoids::showOnlyOne);
connect(m_dlg, &G3PointDialog::allClicked, m_grainsAsEllipsoids, &GrainsAsEllipsoids::showAll);
connect(m_dlg, &G3PointDialog::onlyOneChanged, m_grainsAsEllipsoids, &GrainsAsEllipsoids::setOnlyOne);
connect(m_dlg, &G3PointDialog::transparencyChanged, m_grainsAsEllipsoids, &GrainsAsEllipsoids::setTransparency);
m_dlg->setOnlyOneMax(m_stacks.size());
m_dlg->emitSignals(); // force to send parameters to m_grainsAsEllipsoids
m_app->addToDB(m_grainsAsEllipsoids);
}
bool G3PointAction::cleanLabels()
{
ccLog::Print("[cleanLabels]");
@@ -1640,14 +1661,6 @@ void G3PointAction::segment()
m_app->dispToConsole( "[G3Point] initial segmentation: " + QString::number(nLabels) + " labels", ccMainAppInterface::STD_CONSOLE_MESSAGE );
// plot display grains as ellipsoids
m_grainsAsEllipsoids = new GrainsAsEllipsoids(m_cloud, m_app, m_stacks);
m_grainsAsEllipsoids->setLocalMaximumIndexes(m_localMaximumIndexes);
m_grainColors.reset(new RGBAColorsTableType(getRandomColors(m_localMaximumIndexes.size())));
m_grainsAsEllipsoids->setGrainColorsTable(*m_grainColors);
m_grainsAsEllipsoids->setName("grains as ellipsoids");
m_app->addToDB(m_grainsAsEllipsoids);
m_dlg->enableCluster(true);
m_dlg->enableClean(true);
}
@@ -1735,6 +1748,8 @@ void G3PointAction::showDlg()
connect(m_dlg, &G3PointDialog::segmentClusterClean, s_g3PointAction, &G3Point::G3PointAction::segmentAndClusterAndClean);
connect(m_dlg, &G3PointDialog::getBorders, s_g3PointAction, &G3Point::G3PointAction::getBorders);
connect(m_dlg, &G3PointDialog::fit, s_g3PointAction, &G3Point::G3PointAction::fit);
connect(m_dlg, &QDialog::finished, s_g3PointAction, &G3Point::G3PointAction::clean);
connect(m_dlg, &QDialog::finished, s_g3PointAction, &G3Point::G3PointAction::resetDlg); // dialog is defined with Qt::WA_DeleteOnClose
}
+18
View File
@@ -18,6 +18,13 @@ G3PointDialog::G3PointDialog(QString cloudName, QWidget *parent)
connect(this->ui->pushButtonClean, &QPushButton::clicked, this, &G3PointDialog::emitClean);
connect(this->ui->pushButtonSegmentClusterClean, &QPushButton::clicked, this, &G3PointDialog::emitSegmentClusterClean);
connect(this->ui->pushButtonGetBorders, &QPushButton::clicked, this, &G3PointDialog::emitGetBorders);
connect(this->ui->radioButtonAll, &QRadioButton::clicked, this, &G3PointDialog::emitAllClicked);
connect(this->ui->radioButtonOnlyOne, &QRadioButton::clicked, this, &::G3PointDialog::emitOnlyOneClicked);
connect(this->ui->spinBoxOnlyOne, qOverload<int>(&QSpinBox::valueChanged), this, &::G3PointDialog::emitOnlyOneChanged);
connect(this->ui->pushButtonFit, &QPushButton::clicked, this, &G3PointDialog::emitFit);
connect(this->ui->doubleSpinBoxTransparency, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &G3PointDialog::emitTransparencyChanged);
}
G3PointDialog::~G3PointDialog()
@@ -74,3 +81,14 @@ void G3PointDialog::enableClean(bool state)
{
this->ui->pushButtonClean->setEnabled(state);
}
void G3PointDialog::emitSignals()
{
emit allClicked(this->ui->radioButtonAll->isChecked());
emit emitOnlyOneChanged(this->ui->spinBoxOnlyOne->value());
}
void G3PointDialog::setOnlyOneMax(int max)
{
this->ui->spinBoxOnlyOne->setMaximum(max);
}
+171 -115
View File
@@ -8,7 +8,10 @@
#include <iostream>
#include <random>
std::vector<int> indexes;
// from GeometricTools/GTE
#include <Mathematics/DistPointHyperellipsoid.h>
#include <Mathematics/Vector2.h>
#include <Mathematics/Vector3.h>
GrainsAsEllipsoids::GrainsAsEllipsoids(ccPointCloud *cloud, ccMainAppInterface *app, const std::vector<std::vector<int> >& stacks)
: m_cloud(cloud)
@@ -24,18 +27,16 @@ GrainsAsEllipsoids::GrainsAsEllipsoids(ccPointCloud *cloud, ccMainAppInterface *
// fit all ellipsoids
std::cout << "[GrainsAsEllipsoids::GrainsAsEllipsoids] fit " << stacks.size() << " ellipsoids" << std::endl;
indexes.push_back(268);
indexes.push_back(351);
lockVisibility(false);
for (int idx : indexes)
for (int idx = 0; idx < m_stacks.size(); idx++)
{
fitEllipsoidToGrain(idx, m_center[idx], m_radii[idx], m_rotationMatrix[idx]);
std::cout << "grain " << idx << " stack size " << m_stacks[idx].size() << std::endl;
std::cout << "center " << std::endl << m_center[idx] << std::endl;
std::cout << "radii " << std::endl << m_radii[idx] << std::endl;
std::cout << "rotation matrix " << std::endl << m_rotationMatrix[idx] << std::endl;
if (!fitEllipsoidToGrain(idx, m_center[idx], m_radii[idx], m_rotationMatrix[idx]))
{
m_fitNotOK.insert(idx);
ccLog::Warning("[GrainsAsEllipsoids::GrainsAsEllipsoids] fit not possible for grain " + QString::number(idx)
+ " of size " + QString::number(m_stacks[idx].size()));
}
}
}
@@ -187,6 +188,67 @@ void GrainsAsEllipsoids::buildInterleavedVertices()
// ELLIPSOID FITTING
double GrainsAsEllipsoids::ellipsoidDistance(const Eigen::ArrayXd& p, int idx)
{
// Compute the mean distance between the points of the grain and the ellipsoid
// GTE Geometric Tools Engine
// center
gte::Vector3<double> center = {m_center[idx](0), m_center[idx](1), m_center[idx](2)};
// axis
std::array<gte::Vector3<double>, 3> axis;
axis[0] = {m_rotationMatrix[idx](0, 0), m_rotationMatrix[idx](1, 0), m_rotationMatrix[idx](2, 0)};
axis[1] = {m_rotationMatrix[idx](0, 1), m_rotationMatrix[idx](1, 1), m_rotationMatrix[idx](2, 1)};
axis[2] = {m_rotationMatrix[idx](0, 2), m_rotationMatrix[idx](1, 2), m_rotationMatrix[idx](2, 2)};
// extent
gte::Vector3<double> extent = {m_radii[idx](0), m_radii[idx](1), m_radii[idx](2)};
// create the ellipsoid
gte::Ellipsoid3<double> ellipsoid(center, axis, extent);
gte::DCPQuery<double, gte::Vector3<double>, gte::Ellipsoid3<double>> query;
std::vector<int> stack = m_stacks[idx];
double sum_a = 0; // distances with respect to the ellipsoid
double sum_b = 0; // distances with respect to the mean
//compute gravity center
size_t count = m_cloud->size();
CCVector3 mean(0, 0, 0);
for (int index : m_stacks[idx])
{
const CCVector3* P = m_cloud->getPoint(index);
mean.x += P->x;
mean.y += P->y;
mean.z += P->z;
}
mean.x = mean.x / count;
mean.y = mean.y / count;
mean.z = mean.z / count;
for (int index : stack)
{
const CCVector3 *P = m_cloud->getPoint(index);
gte::Vector3<double> P_gte = {P->x, P->y, P->z};
auto result = query(P_gte, ellipsoid);
sum_a = sum_a + pow(result.distance, 2);
CCVector3 P_minus_min = *P - CCVector3(mean.x, mean.y, mean.z);
sum_b = sum_b + P_minus_min.norm2d();
}
double r2 = 1 - sum_a / sum_b;
// in Matlab
// d = (x-xp).^2 + (y-yp).^2 + (z-zp).^2;
// r2 = 1 - sum((x-xp).^2 + (y-yp).^2 + (z-zp).^2)./sum((x-mean(x)).^2 + (y-mean(y)).^2 + (z-mean(z)).^2);
return r2;
}
bool GrainsAsEllipsoids::explicitToImplicit(const Eigen::Array3f& center,
const Eigen::Array3f& radii,
const Eigen::Matrix3f& rotationMatrix,
@@ -301,7 +363,7 @@ bool GrainsAsEllipsoids::implicitToExplicit(const Eigen::ArrayXd& parameters,
Eigen::EigenSolver<Eigen::MatrixXd> eigensolver(s.block(0, 0, 3, 3));
if (eigensolver.info() != Eigen::Success)
{
abort();
return false;
}
radii = (-s(3, 3) / eigensolver.eigenvalues().array().real()).sqrt().cast<float>();
@@ -310,10 +372,8 @@ bool GrainsAsEllipsoids::implicitToExplicit(const Eigen::ArrayXd& parameters,
return true;
}
Eigen::ArrayXd GrainsAsEllipsoids::directFit(const Eigen::ArrayX3d& xyz)
bool GrainsAsEllipsoids::directFit(const Eigen::ArrayX3d& xyz, Eigen::ArrayXd& parameters)
{
std::cout << "[GrainsAsEllipsoids::directFit]" << std::endl;
Eigen::MatrixXd d(xyz.rows(), 10);
d << xyz(Eigen::all, 0).pow(2).matrix()
@@ -345,11 +405,13 @@ Eigen::ArrayXd GrainsAsEllipsoids::directFit(const Eigen::ArrayX3d& xyz)
Eigen::GeneralizedEigenSolver<Eigen::MatrixXd> eigensolver(s, c);
if (eigensolver.info() != Eigen::Success)
{
abort();
return false;
}
Eigen::ArrayXd eigenValues(10);
Eigen::VectorXd eigenValuesAsAMatrix(10);
eigenValues = eigensolver.eigenvalues().real();
eigenValuesAsAMatrix = eigensolver.eigenvalues().real().matrix();
Xb condition = (eigenValues > 0) && (!eigenValues.isInf());
int flt = condition.count();
@@ -381,10 +443,10 @@ Eigen::ArrayXd GrainsAsEllipsoids::directFit(const Eigen::ArrayX3d& xyz)
break;
case 0: // degenerate case
// # single positive eigenvalue becomes near-zero negative eigenvalue due to round-off error
eigenValue = finiteValues.abs().minCoeff();
eigenValue = eigenValues.abs().minCoeff();
for (k = 0; k < 10; k++)
{
if (eigenValues(k) == eigenValue)
if (abs(eigenValues(k)) == eigenValue)
{
v = eigensolver.eigenvectors()(Eigen::all, k).real();
break;
@@ -405,14 +467,14 @@ Eigen::ArrayXd GrainsAsEllipsoids::directFit(const Eigen::ArrayX3d& xyz)
break;
}
Eigen::ArrayXd p(10);
parameters.resize(10);
p << v(0), v(1), v(2)
parameters << v(0), v(1), v(2)
, 2 * v(5), 2 * v(4), 2* v(3)
, 2 * v(6), 2 * v(7), 2 * v(8)
, v(9);
return p;
return true;
}
bool GrainsAsEllipsoids::fitEllipsoidToGrain(const int grainIndex,
@@ -453,9 +515,15 @@ bool GrainsAsEllipsoids::fitEllipsoidToGrain(const int grainIndex,
// The constraint confines the class of ellipsoids to fit to those whose smallest radius is at least half of the
// largest radius.
p = directFit(scale * (grainPoints.cast<double>().rowwise() - means)); // Ellipsoid fit
if(!directFit(scale * (grainPoints.cast<double>().rowwise() - means), p)) // Ellipsoid fit
{
return false;
}
implicitToExplicit(p, center, radii, rotationMatrix); // Get the explicit parameters
if (!implicitToExplicit(p, center, radii, rotationMatrix)) // Get the explicit parameters
{
return false;
}
break;
default:
@@ -558,62 +626,27 @@ bool GrainsAsEllipsoids::initProgram(QOpenGLContext* context)
return true;
}
bool GrainsAsEllipsoids::drawEllipsoids(CC_DRAW_CONTEXT& context)
void GrainsAsEllipsoids::drawEllipsoid(CC_DRAW_CONTEXT& context, int idx)
{
QOpenGLFunctions_2_1* glFunc = context.glFunctions<QOpenGLFunctions_2_1>();
assert(glFunc != nullptr);
CCVector3f color;
// set uniforms
QVector4D lightPosition(0, 0, 1, 0);
QVector4D lightAmbient(0.3f, 0.3f, 0.3f, 1); // grey
QVector4D lightDiffuse(0.7f, 0.7f, 0.7f, 1); // light grey
QVector4D lightSpecular(1.0f, 1.0f, 1.0f, 1); // RGB white
// QVector4D materialAmbient(0.5f, 0.5f, 0.5f, 1);
QVector4D materialDiffuse(0.7f, 0.7f, 0.7f, 1);
QVector4D materialSpecular(0.4f, 0.4f, 0.4f, 1);
QVector4D materialAmbient(color.x, color.y, color.z, 1);
// QVector4D materialDiffuse(color.r / ccColor::MAX, color.g / ccColor::MAX, color.b / ccColor::MAX, 1);
// QVector4D materialSpecular(color.r / ccColor::MAX, color.g / ccColor::MAX, color.b / ccColor::MAX, 1);
float materialShininess = 16;
m_program->setUniformValue("lightPosition", lightPosition);
m_program->setUniformValue("lightAmbient", lightAmbient);
m_program->setUniformValue("lightDiffuse", lightDiffuse);
m_program->setUniformValue("lightSpecular", lightSpecular);
m_program->setUniformValue("materialDiffuse", materialDiffuse);
m_program->setUniformValue("materialSpecular", materialSpecular);
m_program->setUniformValue("materialShininess", materialShininess);
m_program->setAttributeArray("vertexPosition", static_cast<GLfloat*>(vertices.data()), 3);
m_program->setAttributeArray("vertexNormal", static_cast<GLfloat*>(normals.data()), 3);
m_program->setAttributeArray("vertexTexCoord", static_cast<GLfloat*>(texCoords.data()), 2);
m_program->enableAttributeArray("vertexPosition");
m_program->enableAttributeArray("vertexNormal");
m_program->enableAttributeArray("vertexTexCoord");
QMatrix4x4 projection;
QMatrix4x4 modelView;
//generate random colors
std::mt19937 gen(42); // to seed mersenne twister.
std::uniform_real_distribution<> dis(0.5, 1.0);
std::uniform_real_distribution<> dis2(-1., 1.0);
for (int idx : indexes)
if (!m_fitNotOK.count(idx))
{
QMatrix4x4 projection;
QMatrix4x4 modelView;
Eigen::Matrix3f rotation(m_rotationMatrix[idx].transpose());
QMatrix4x4 matrixFromFit(rotation(0, 0), rotation(0, 1), rotation(0, 2), m_center[idx](0),
rotation(1, 0), rotation(1, 1), rotation(1, 2), m_center[idx](1),
rotation(2, 0), rotation(2, 1), rotation(2, 2), m_center[idx](2),
0, 0, 0, 1);
CCVector3f color;
color = m_grainColors[idx];
glFunc->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glFunc->glEnable( GL_BLEND );
m_program->setUniformValue("materialAmbient", color.x, color.y, color.z, 0.5);
glFunc->glEnable(GL_BLEND);
m_program->setUniformValue("materialAmbient", color.x, color.y, color.z, 1.);
// prepare translation, rotation and scaling
glFunc->glPushMatrix(); // save the current matrix
@@ -643,9 +676,61 @@ bool GrainsAsEllipsoids::drawEllipsoids(CC_DRAW_CONTEXT& context)
glFunc->glPopMatrix();
}
}
if (false)
{ // Matlab 22.36920946, 17.15421478, -11.2193826
bool GrainsAsEllipsoids::drawEllipsoids(CC_DRAW_CONTEXT& context)
{
QOpenGLFunctions_2_1* glFunc = context.glFunctions<QOpenGLFunctions_2_1>();
assert(glFunc != nullptr);
CCVector3f color;
// set uniforms
QVector4D lightPosition(0, 0, 1, 0);
QVector4D lightAmbient(0.3f, 0.3f, 0.3f, 1); // grey
QVector4D lightDiffuse(0.7f, 0.7f, 0.7f, 1); // light grey
QVector4D lightSpecular(1.0f, 1.0f, 1.0f, 1); // RGB white
// QVector4D materialAmbient(0.5f, 0.5f, 0.5f, 1);
QVector4D materialDiffuse(0.7f, 0.7f, 0.7f, m_transparency);
QVector4D materialSpecular(0.4f, 0.4f, 0.4f, 1);
QVector4D materialAmbient(color.x, color.y, color.z, 1);
// QVector4D materialDiffuse(color.r / ccColor::MAX, color.g / ccColor::MAX, color.b / ccColor::MAX, 1);
// QVector4D materialSpecular(color.r / ccColor::MAX, color.g / ccColor::MAX, color.b / ccColor::MAX, 1);
float materialShininess = 16;
m_program->setUniformValue("lightPosition", lightPosition);
m_program->setUniformValue("lightAmbient", lightAmbient);
m_program->setUniformValue("lightDiffuse", lightDiffuse);
m_program->setUniformValue("lightSpecular", lightSpecular);
m_program->setUniformValue("materialDiffuse", materialDiffuse);
m_program->setUniformValue("materialSpecular", materialSpecular);
m_program->setUniformValue("materialShininess", materialShininess);
m_program->setAttributeArray("vertexPosition", static_cast<GLfloat*>(vertices.data()), 3);
m_program->setAttributeArray("vertexNormal", static_cast<GLfloat*>(normals.data()), 3);
m_program->setAttributeArray("vertexTexCoord", static_cast<GLfloat*>(texCoords.data()), 2);
m_program->enableAttributeArray("vertexPosition");
m_program->enableAttributeArray("vertexNormal");
m_program->enableAttributeArray("vertexTexCoord");
QMatrix4x4 projection;
QMatrix4x4 modelView;
if (m_showAll)
{
for (int idx = 0; idx < m_stacks.size(); idx++)
{
drawEllipsoid(context, idx);
}
}
else
{
drawEllipsoid(context, m_onlyOne);
}
if (false) // Matlab fit of grain 351
{
Eigen::Matrix3f rotation;
rotation << -0.1424, -0.8175, -0.5580,
-0.9102, -0.1133, 0.3983,
@@ -690,44 +775,6 @@ bool GrainsAsEllipsoids::drawEllipsoids(CC_DRAW_CONTEXT& context)
glFunc->glPopMatrix();
}
// for (int k = 1; k < m_localMaximumIndexes.size(); k++)
// {
// if (k==indexOfGrainToFit)
// continue;
// const CCVector3f* center = m_cloud->getPoint(m_localMaximumIndexes[k]);
// CCVector3f color = m_grainColors[k];
// m_program->setUniformValue("materialAmbient", color.x, color.y, color.z, 1);
// // prepare translation, rotation and scaling
// glFunc->glPushMatrix(); // save the current matrix
// // translate
// glFunc->glTranslatef(center->x, center->y, center->z);
// // rotate
// glFunc->glRotatef(90, static_cast<float>(dis2(gen)), static_cast<float>(dis2(gen)), static_cast<float>(dis2(gen)));
// // scale
// glFunc->glScalef(static_cast<float>(dis(gen)), static_cast<float>(dis(gen)), static_cast<float>(dis(gen)));
// // get matrices
// glFunc->glGetFloatv(GL_PROJECTION_MATRIX, projection.data());
// glFunc->glGetFloatv(GL_MODELVIEW_MATRIX, modelView.data());
// m_program->setUniformValue("modelViewProjectionMatrix", projection * modelView);
// // draw triangles
// m_program->setUniformValue("drawLines", 0);
// glFunc->glEnable(GL_POLYGON_OFFSET_FILL);
// glFunc->glPolygonOffset(1.0, 1.0f); // move polygon backward
// glFunc->glDrawElements(GL_TRIANGLES, (unsigned int)indices.size(), GL_UNSIGNED_INT, indices.data());
// glFunc->glDisable(GL_POLYGON_OFFSET_FILL);
// // draw lines
// m_program->setUniformValue("drawLines", 1);
// glFunc->glDisable(GL_LIGHTING);
// glFunc->glDisable(GL_TEXTURE_2D);
// glFunc->glDrawElements(GL_LINES, (unsigned int)lineIndices.size(), GL_UNSIGNED_INT, lineIndices.data());
// glFunc->glPopMatrix();
// }
m_program->disableAttributeArray("vertexPosition");
m_program->disableAttributeArray("vertexNormal");
m_program->disableAttributeArray("vertexTexCoord");
@@ -756,18 +803,18 @@ void GrainsAsEllipsoids::drawGrains(CC_DRAW_CONTEXT& context)
// set uniforms
m_program->setUniformValue("modelViewProjectionMatrix", projectionModelView);
// get the coordinates of the local maxima
std::vector<CCVector3> semiAxisLengths(m_localMaximumIndexes.size(), CCVector3(1, 1, 1));
std::vector<CCVector3f> centers(m_localMaximumIndexes.size());
// initialize the vector containing the centers of the grains
for (int index = 0; index < m_localMaximumIndexes.size(); index++)
{
centers[index] = *m_cloud->getPoint(m_localMaximumIndexes[index]);
}
if (false)
{
// get the coordinates of the local maxima
std::vector<CCVector3> semiAxisLengths(m_localMaximumIndexes.size(), CCVector3(1, 1, 1));
std::vector<CCVector3f> centers(m_localMaximumIndexes.size());
// initialize the vector containing the centers of the grains
for (int index = 0; index < m_localMaximumIndexes.size(); index++)
{
centers[index] = *m_cloud->getPoint(m_localMaximumIndexes[index]);
}
m_program->setAttributeArray("vertexIn", static_cast<GLfloat*>(vertices.data()), 3);
m_program->setAttributeArray("semiAxisLengths", static_cast<GLfloat*>(semiAxisLengths.front().u), 3);
@@ -801,3 +848,12 @@ void GrainsAsEllipsoids::draw(CC_DRAW_CONTEXT& context)
{
drawGrains(context);
}
void GrainsAsEllipsoids::showAll(bool state)
{
m_showAll = state;
ccLog::Warning("[GrainsAsEllipsoids::showAll] changed " + QString::number(m_showAll));
}
+321 -192
View File
@@ -6,206 +6,335 @@
<rect>
<x>0</x>
<y>0</y>
<width>281</width>
<height>459</height>
<width>303</width>
<height>509</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="16" column="0" colspan="2">
<widget class="QLabel" name="labelCloud">
<property name="text">
<string>-</string>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QPushButton" name="pushButtonSegmentCluster">
<property name="text">
<string>Segment + Cluster</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Min points per grain</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Point size</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Min flatness</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Max angle 1</string>
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QRadioButton" name="radioButtonG3Point">
<property name="text">
<string>G3Point</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSpinBox" name="spinBoxPointSize">
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>3</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Radius factor</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxkNN">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
<property name="value">
<number>20</number>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="spinBoxNMin">
<property name="maximum">
<number>1000000000</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxRadiusFactor">
<property name="value">
<double>0.600000000000000</double>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QPushButton" name="pushButtonClean">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Clean</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QPushButton" name="pushButtonCluster">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Cluster</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxMinFlatness">
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxMaxAngle1">
<property name="frame">
<bool>true</bool>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::UpDownArrows</enum>
</property>
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="value">
<double>60.000000000000000</double>
</property>
</widget>
</item>
<item row="15" column="1">
<widget class="QRadioButton" name="radioButtonSteepestSlope">
<property name="text">
<string>steepest slope</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>kNN</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Max angle 2</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxMaxAngle2">
<property name="value">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QPushButton" name="pushButtonSegmentClusterClean">
<property name="text">
<string>Segment + Cluster + Clean</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QPushButton" name="pushButtonSegment">
<property name="text">
<string>Segment</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QPushButton" name="pushButtonGetBorders">
<property name="text">
<string>Get borders</string>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Segmentation</string>
</attribute>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>kNN</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxkNN">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
<property name="value">
<number>20</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Radius factor</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxRadiusFactor">
<property name="value">
<double>0.600000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Max angle 1</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxMaxAngle1">
<property name="frame">
<bool>true</bool>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::UpDownArrows</enum>
</property>
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="value">
<double>60.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Max angle 2</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxMaxAngle2">
<property name="value">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Min points per grain</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="spinBoxNMin">
<property name="maximum">
<number>1000000000</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Min flatness</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxMinFlatness">
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Point size</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSpinBox" name="spinBoxPointSize">
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>3</number>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QPushButton" name="pushButtonSegment">
<property name="text">
<string>Segment</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QPushButton" name="pushButtonCluster">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Cluster</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QPushButton" name="pushButtonClean">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Clean</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QPushButton" name="pushButtonSegmentCluster">
<property name="text">
<string>Segment + Cluster</string>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QPushButton" name="pushButtonSegmentClusterClean">
<property name="text">
<string>Segment + Cluster + Clean</string>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QPushButton" name="pushButtonGetBorders">
<property name="text">
<string>Get borders</string>
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QRadioButton" name="radioButtonG3Point">
<property name="text">
<string>G3Point</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QRadioButton" name="radioButtonSteepestSlope">
<property name="text">
<string>steepest slope</string>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel" name="labelCloud">
<property name="text">
<string>-</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Fitting</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Fit ellipsoids</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QPushButton" name="pushButtonFit">
<property name="text">
<string>Run</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="radioButtonDirect">
<property name="text">
<string>Direct</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Show</string>
</property>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QRadioButton" name="radioButtonAll">
<property name="text">
<string>All</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="radioButtonOnlyOne">
<property name="text">
<string>Only one</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBoxOnlyOne"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Transparency</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxTransparency">
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxWireframes">
<property name="text">
<string>Wireframes</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="checkBoxSurfaces">
<property name="text">
<string>Surfaces</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>