Added the wheel control for the hopDist parameter.

Added the ctrl and shift modifiers for selection.
Added the plane fitting selection.
This commit is contained in:
Manuele Sabbadin msabbadin 2012-02-01 02:18:16 +00:00
parent 810e38942f
commit 6ea33748be
6 changed files with 259 additions and 43 deletions

View File

@ -1,6 +1,8 @@
#ifndef CONNECTEDCOMPONENT_H
#define CONNECTEDCOMPONENT_H
#include <QTime>
#include "knnGraph.h"
#include <vector>
@ -10,6 +12,8 @@
#include <vcg/complex/allocate.h>
#include <vcg/complex/algorithms/update/flag.h>
#include <vcg/space/fitting3.h>
using namespace std;
using namespace vcg;
@ -18,11 +22,13 @@ template <typename _MyMeshType, typename _MyVertexType>
class ComponentFinder {
public:
static std::vector<_MyVertexType*> &FindComponent(_MyMeshType& m, _MyVertexType& v, int numOfNeighbours, int numOfHop);
static std::vector<_MyVertexType*> &FindComponent(_MyMeshType& m, _MyVertexType& v, int numOfNeighbours, float dim, float maxHopDist, vector<_MyVertexType*> &borderVect, vector<_MyVertexType*> &notReachableVect);
static std::vector<_MyVertexType*> &FindComponent(_MyMeshType& m, _MyVertexType& v, int numOfNeighbours, float dim, float maxHopDist, vector<_MyVertexType*> &borderVect, vector<_MyVertexType*> &notReachableVect, bool fitting = false, float planeDim = 0.0, float distanceFromPlane = 0.0);
static void DeletePerVertexAttribute(_MyMeshType& m);
static void Dijkstra(_MyMeshType& m, _MyVertexType& v, int numOfNeighbours, float maxHopDist, vector<_MyVertexType*> &notReachableVect);
// static void DijkstraMod(_MyMeshType& m, _MyVertexType& v, int numOfNeighbours, float maxHopDist, vector<_MyVertexType*> &notReachableVect, bool fitting = false, float planeDim = 0.0, float distanceFromPlane = 0.0);
};
@ -102,8 +108,9 @@ public:
* maximum distance we want between two vertex (with the Shortest Path we also compute the geodesic distance)
**/
template <typename _MyMeshType, typename _MyVertexType>
std::vector<_MyVertexType*> &ComponentFinder<_MyMeshType, _MyVertexType>::FindComponent(_MyMeshType& m, _MyVertexType& v, int numOfNeighbours, float dim, float maxHopDist, vector<_MyVertexType*> &borderVect, vector<_MyVertexType*> &notReachableVect) {
std::vector<_MyVertexType*> &ComponentFinder<_MyMeshType, _MyVertexType>::FindComponent(_MyMeshType& m, _MyVertexType& v, int numOfNeighbours, float dim, float maxHopDist, vector<_MyVertexType*> &borderVect, vector<_MyVertexType*> &notReachableVect, bool fitting, float planeDim, float distanceFromPlane) {
vector<_MyVertexType*> *resultVect = new vector<_MyVertexType*>();
vector<typename _MyMeshType::CoordType> pointToFit = vector<typename _MyMeshType::CoordType>();
tri::UpdateFlags<_MyMeshType>::VertexClearV(m);
@ -115,12 +122,31 @@ std::vector<_MyVertexType*> &ComponentFinder<_MyMeshType, _MyVertexType>::FindCo
else return *resultVect;
for (typename _MyMeshType::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++) {
if (distFromCenter[vi] < dim) resultVect->push_back(&*vi);
if (fitting) {
if (distFromCenter[vi] < planeDim) {
pointToFit.push_back(vi->cP());
}
}
else if (distFromCenter[vi] < dim) resultVect->push_back(&*vi);
}
typename vector<_MyVertexType*>::iterator it;
for (it = notReachableVect.begin(); it != notReachableVect.end(); it++) {
if (distFromCenter[*it] < dim) borderVect.push_back(*it);
if (fitting) {
Plane3<typename _MyMeshType::ScalarType> fittingPlane = Plane3<typename _MyMeshType::ScalarType>();
vcg::PlaneFittingPoints(pointToFit, fittingPlane);
for (typename _MyMeshType::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++) {
if (distFromCenter[vi] < dim && math::Abs(vcg::SignedDistancePlanePoint<typename _MyMeshType::ScalarType>(fittingPlane, vi->cP())) < distanceFromPlane) resultVect->push_back(&*vi);
}
for (it = notReachableVect.begin(); it != notReachableVect.end(); it++) {
if (distFromCenter[*it] < dim && math::Abs(vcg::SignedDistancePlanePoint<typename _MyMeshType::ScalarType>(fittingPlane, (*it)->cP())) < distanceFromPlane) borderVect.push_back(*it);
}
}
else {
for (it = notReachableVect.begin(); it != notReachableVect.end(); it++) {
if (distFromCenter[*it] < dim) borderVect.push_back(*it);
}
}
return *resultVect;
@ -140,13 +166,15 @@ void ComponentFinder<_MyMeshType, _MyVertexType>::Dijkstra(_MyMeshType& m, _MyVe
}
else distFromCenter = vcg::tri::Allocator<_MyMeshType>::template GetPerVertexAttribute<float>(m, std::string("DistParam"));
//QTime t;
//t.start();
if (!hasKNNGraph) {
KNNTree<_MyMeshType, _MyVertexType>::MakeKNNTree(m, numOfNeighbours);
}
//printf("KNNGraph Creation: %d ms\n", t.elapsed());
typename _MyMeshType::template PerVertexAttributeHandle<vector<_MyVertexType*>* > neighboursVect = vcg::tri::Allocator<_MyMeshType>::template GetPerVertexAttribute<vector<_MyVertexType*>* >(m,"KNNGraph");
typename vector<_MyVertexType*>::iterator it;
typedef priority_queue<_MyVertexType*, vector<_MyVertexType*>, Compare<_MyMeshType, _MyVertexType> > VertPriorityQueue;
@ -174,12 +202,16 @@ void ComponentFinder<_MyMeshType, _MyVertexType>::Dijkstra(_MyMeshType& m, _MyVe
for (it = neighboursVect[element]->begin(); it != neighboursVect[element]->end(); it++) {
distance = vcg::Distance((*it)->P(), element->P());
if (distFromCenter[*element] + distance < distFromCenter[*it]) distFromCenter[*it] = distFromCenter[*element] + distance;
if (!((*it)->IsV()) && distance <= maxHopDist) {
prQueue.push(*it);
(*it)->SetV();
if (distance <= maxHopDist) {
if (distFromCenter[*element] + distance < distFromCenter[*it])
distFromCenter[*it] = distFromCenter[*element] + distance;
if (!(*it)->IsV()) {
prQueue.push(*it);
(*it)->SetV();
}
}
else if (distance > maxHopDist) notReachableVect.push_back(*it);
else if (distance > maxHopDist) notReachableVect.push_back(element);
}
}
}

View File

@ -29,6 +29,7 @@
#include "edit_point.h"
#include <wrap/gl/pick.h>
#include <wrap/qt/gl_label.h>
#include <vcg/space/fitting3.h>
#include "connectedComponent.h"
@ -36,10 +37,10 @@
using namespace std;
using namespace vcg;
EditPointPlugin::EditPointPlugin() {}
EditPointPlugin::EditPointPlugin(int _editType) : editType(_editType){}
const QString EditPointPlugin::Info() {
return tr("Select a region of the mesh");
return tr("Select a region of the point cloud thought to be in the same connected component.");
}
void EditPointPlugin::Decorate(MeshModel &m, GLArea * gla, QPainter *p)
@ -53,7 +54,11 @@ void EditPointPlugin::Decorate(MeshModel &m, GLArea * gla, QPainter *p)
if(NewSel.size() > 0) {
startingVertex = NewSel.front();
//timer.start();
ComponentFinder<CMeshO, CVertexO>::Dijkstra(m.cm, *startingVertex, 6, this->maxHop, this->NotReachableVector);
//printf("ComponentFinder in Decorate::Dijkstra: %d ms\n", timer.elapsed());
ComponentVector.push_back(startingVertex);
}
@ -74,13 +79,41 @@ void EditPointPlugin::Decorate(MeshModel &m, GLArea * gla, QPainter *p)
glDepthFunc(GL_LEQUAL);
glPointSize(6.f);
tri::UpdateSelection<CMeshO>::VertexClear(m.cm);
switch (composingSelMode) {
case SMSub:
for(vector<CMeshO::VertexPointer>::iterator vi = OldComponentVector.begin(); vi != OldComponentVector.end(); ++vi) {
(*vi)->SetS();
}
for(vector<CMeshO::VertexPointer>::iterator vi = ComponentVector.begin(); vi != ComponentVector.end(); ++vi) {
(*vi)->ClearS();
}
break;
case SMAdd:
for(vector<CMeshO::VertexPointer>::iterator vi = OldComponentVector.begin(); vi != OldComponentVector.end(); ++vi) {
(*vi)->SetS();
}
for(vector<CMeshO::VertexPointer>::iterator vi = ComponentVector.begin(); vi != ComponentVector.end(); ++vi) {
(*vi)->SetS();
}
break;
case SMClear:
for(vector<CMeshO::VertexPointer>::iterator vi = ComponentVector.begin(); vi != ComponentVector.end(); ++vi) {
(*vi)->SetS();
}
break;
}
glBegin(GL_POINTS);
glColor4f(1,0,0,.6f);
for(vector<CMeshO::VertexPointer>::iterator vi = ComponentVector.begin(); vi != ComponentVector.end(); ++vi)
{
glVertex((*vi)->cP());
for (CMeshO::VertexIterator vi = m.cm.vert.begin(); vi != m.cm.vert.end(); vi++) {
if (vi->IsS()) glVertex(vi->cP());
}
glEnd();
glBegin(GL_POINTS);
@ -88,10 +121,11 @@ void EditPointPlugin::Decorate(MeshModel &m, GLArea * gla, QPainter *p)
for(vector<CMeshO::VertexPointer>::iterator vi = BorderVector.begin(); vi != BorderVector.end(); ++vi)
{
glVertex((*vi)->cP());
if ((*vi)->IsS()) glVertex((*vi)->cP());
}
glEnd();
glPopAttrib();
glPopMatrix();
}
@ -100,7 +134,13 @@ void EditPointPlugin::Decorate(MeshModel &m, GLArea * gla, QPainter *p)
bool EditPointPlugin::StartEdit(MeshModel &m, GLArea *gla ) {
BorderVector = std::vector<CVertexO*>();
NotReachableVector = std::vector<CVertexO*>();
OldComponentVector = std::vector<CVertexO*>();
composingSelMode = SMClear;
this->maxHop = m.cm.bbox.Diag() / 100.0;
this->planeDist = m.cm.bbox.Diag() / 100.0;
this->fittingRadiusPerc = 0.1;
return true;
}
@ -119,6 +159,21 @@ void EditPointPlugin::mousePressEvent(QMouseEvent *ev, MeshModel &m, GLArea *gla
this->isMousePressed = true;
this->dist = 0.0;
this->startingClick = vcg::Point2f(ev->x(), ev->y());
this->fittingRadius = 0.0;
OldComponentVector.clear();
if (ev->modifiers() & Qt::ControlModifier || ev->modifiers() & Qt::ShiftModifier)
{
for (CMeshO::VertexIterator vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi) {
if (vi->IsS()) OldComponentVector.push_back(&*vi);
}
}
composingSelMode = SMClear;
if(ev->modifiers() & Qt::ControlModifier) composingSelMode = SMAdd;
if(ev->modifiers() & Qt::ShiftModifier) composingSelMode = SMSub;
BorderVector.clear();
ComponentVector.clear();
@ -135,45 +190,147 @@ void EditPointPlugin::mouseMoveEvent(QMouseEvent *ev, MeshModel &m, GLArea *gla
this->dist = (perim * distFromCenter) / gla->width();
BorderVector.clear();
ComponentVector = ComponentFinder<CMeshO, CVertexO>::FindComponent(m.cm, *startingVertex, 6, this->dist, this->maxHop, BorderVector, NotReachableVector);
}
if (editType == SELECT_DEFAULT_MODE)
ComponentVector = ComponentFinder<CMeshO, CVertexO>::FindComponent(m.cm, *startingVertex, 6, this->dist, this->maxHop, BorderVector, NotReachableVector);
else if (editType == SELECT_FITTING_PLANE_MODE) {
this->fittingRadius = dist * fittingRadiusPerc;
ComponentVector = ComponentFinder<CMeshO, CVertexO>::FindComponent(m.cm, *startingVertex, 6, this->dist, this->maxHop, BorderVector, NotReachableVector, true, fittingRadius, planeDist);
}
gla->update();
}
}
void EditPointPlugin::mouseReleaseEvent(QMouseEvent *ev, MeshModel &m, GLArea *gla) {
this->isMousePressed = false;
gla->update();
}
void EditPointPlugin::keyPressEvent(QKeyEvent *ev, MeshModel &m, GLArea *gla) {
bool hopDistModified = false;
bool parameterModified = false;
int keyPressed = ev->key();
if (startingVertex != NULL) {
switch (keyPressed) {
case Qt::Key_A:
this->maxHop *= 1.2;
switch (keyPressed) {
case Qt::Key_A:
if (startingVertex != NULL) {
this->maxHop *= 1.2;
hopDistModified = true;
break;
case Qt::Key_Z:
this->maxHop /= 1.2;
hopDistModified = true;
break;
default: break;
hopDistModified = true;
parameterModified = true;
}
break;
case Qt::Key_Z:
if (startingVertex != NULL) {
this->maxHop /= 1.2;
hopDistModified = true;
parameterModified = true;
}
break;
case Qt::Key_S:
if (startingVertex != NULL && editType == SELECT_FITTING_PLANE_MODE) {
this->fittingRadiusPerc *= 1.2;
this->fittingRadius = (dist * fittingRadiusPerc);
parameterModified = true;
}
break;
case Qt::Key_X:
if (startingVertex != NULL && editType == SELECT_FITTING_PLANE_MODE) {
this->fittingRadiusPerc /= 1.2;
this->fittingRadius = (dist * fittingRadiusPerc);
parameterModified = true;
}
break;
case Qt::Key_D:
if (startingVertex != NULL && editType == SELECT_FITTING_PLANE_MODE) {
this->planeDist *= 1.2;
parameterModified = true;
}
break;
case Qt::Key_C:
if (startingVertex != NULL && editType == SELECT_FITTING_PLANE_MODE) {
this->planeDist /= 1.2;
parameterModified = true;
}
break;
default: break;
}
if (hopDistModified) {
//timer.restart();
ComponentFinder<CMeshO, CVertexO>::Dijkstra(m.cm, *startingVertex, 6, this->maxHop, this->NotReachableVector);
//printf("ComponentFinder in ChangeHop::Dijkstra: %d ms\n", timer.elapsed());
}
if (parameterModified) {
//printf("fittingRadius: %f\n", fittingRadius);
//printf("planeDist: %f\n", planeDist);
BorderVector.clear();
ComponentVector = ComponentFinder<CMeshO, CVertexO>::FindComponent(m.cm, *startingVertex, 6, this->dist, this->maxHop, BorderVector, NotReachableVector);
if (editType == SELECT_DEFAULT_MODE)
ComponentVector = ComponentFinder<CMeshO, CVertexO>::FindComponent(m.cm, *startingVertex, 6, this->dist, this->maxHop, BorderVector, NotReachableVector);
else if (editType == SELECT_FITTING_PLANE_MODE)
ComponentVector = ComponentFinder<CMeshO, CVertexO>::FindComponent(m.cm, *startingVertex, 6, this->dist, this->maxHop, BorderVector, NotReachableVector, true, fittingRadius, planeDist);
}
gla->update();
return;
}
void EditPointPlugin::keyReleaseEvent(QKeyEvent *ev, MeshModel &m, GLArea *gla) {}
void EditPointPlugin::wheelEvent(QWheelEvent* ev, MeshModel &m, GLArea *gla) {
bool hopDistModified = false;
int wheelDirection = ev->delta();
if (startingVertex != NULL) {
if (wheelDirection > 0) {
this->maxHop *= pow(1.2, wheelDirection / 120.f);
hopDistModified = true;
}
else if (wheelDirection < 0) {
this->maxHop /= pow(1.2, (-1*wheelDirection) / 120.f);
hopDistModified = true;
}
}
if (hopDistModified) {
//timer.restart();
ComponentFinder<CMeshO, CVertexO>::Dijkstra(m.cm, *startingVertex, 6, this->maxHop, this->NotReachableVector);
//printf("ComponentFinder in ChangeHop::Dijkstra: %d ms\n", timer.elapsed());
BorderVector.clear();
if (editType == SELECT_DEFAULT_MODE)
ComponentVector = ComponentFinder<CMeshO, CVertexO>::FindComponent(m.cm, *startingVertex, 6, this->dist, this->maxHop, BorderVector, NotReachableVector);
else if (editType == SELECT_FITTING_PLANE_MODE)
ComponentVector = ComponentFinder<CMeshO, CVertexO>::FindComponent(m.cm, *startingVertex, 6, this->dist, this->maxHop, BorderVector, NotReachableVector, true, fittingRadius, planeDist);
}
gla->update();
return;
}

View File

@ -33,7 +33,9 @@ class EditPointPlugin : public QObject, public MeshEditInterface
Q_INTERFACES(MeshEditInterface)
public:
EditPointPlugin();
enum {SELECT_DEFAULT_MODE, SELECT_FITTING_PLANE_MODE};
EditPointPlugin(int _editType);
virtual ~EditPointPlugin() {}
static const QString Info();
@ -45,9 +47,16 @@ public:
void mouseMoveEvent(QMouseEvent *, MeshModel &, GLArea * );
void mouseReleaseEvent(QMouseEvent *, MeshModel &/*m*/, GLArea * );
void keyPressEvent(QKeyEvent *, MeshModel &/*m*/, GLArea *);
void keyReleaseEvent(QKeyEvent *, MeshModel &/*m*/, GLArea *);
void wheelEvent(QWheelEvent*, MeshModel &/*m*/, GLArea * );
private:
private:
typedef enum {SMAdd, SMClear,SMSub} ComposingSelMode; // How the selection are composed
ComposingSelMode composingSelMode;
int editType;
bool isMousePressed;
bool haveToPick;
@ -56,12 +65,17 @@ private:
float dist;
float maxHop;
float fittingRadiusPerc;
float fittingRadius;
float planeDist;
std::vector<CMeshO::VertexPointer> ComponentVector;
std::vector<CMeshO::VertexPointer> BorderVector;
std::vector<CMeshO::VertexPointer> NotReachableVector;
std::vector<CMeshO::VertexPointer> OldComponentVector;
QPoint cur;
//QTime timer;
};
#endif

View File

@ -26,12 +26,14 @@
PointEditFactory::PointEditFactory()
{
editPoint = new QAction(QIcon(":/images/icon_info.png"),"Point", this);
editPoint = new QAction(QIcon(":/images/select_vertex.png"),"Point", this);
editPointFittingPlane = new QAction(QIcon(":/images/select_vertex.png"),"PointFitting", this);
actionList << editPoint;
actionList << editPointFittingPlane;
foreach(QAction *editAction, actionList)
editAction->setCheckable(true);
editAction->setCheckable(true);
}
//gets a list of actions available from this plugin
@ -44,9 +46,11 @@ QList<QAction *> PointEditFactory::actions() const
MeshEditInterface* PointEditFactory::getMeshEditInterface(QAction *action)
{
if(action == editPoint)
{
return new EditPointPlugin();
} else assert(0); //should never be asked for an action that isn't here
return new EditPointPlugin(EditPointPlugin::SELECT_DEFAULT_MODE);
else if (action == editPointFittingPlane)
return new EditPointPlugin(EditPointPlugin::SELECT_FITTING_PLANE_MODE);
assert(0); //should never be asked for an action that isn't here
}
QString PointEditFactory::getEditToolDescription(QAction *)

View File

@ -50,6 +50,7 @@ private:
QList <QAction *> actionList;
QAction *editPoint;
QAction *editPointFittingPlane;
};
#endif

View File

@ -1,6 +1,8 @@
#ifndef KNNGRAPH_H
#define KNNGRAPH_H
#include <QTime>
#include <Vector>
#include <vcg/complex/complex.h>
@ -48,7 +50,10 @@ void KNNTree<_MyMeshType, _MyVertexType>::MakeKNNTree(_MyMeshType& m, int numOfN
}
ConstDataWrapper<typename _MyMeshType::CoordType> DW(&(input[0]), input.size());
//QTime t2;
//t2.start();
KdTree<float> tree(DW);
//printf("KdTree Creation: %d ms\n", t2.elapsed());
tree.setMaxNofNeighbors(neighboursVectSize);
@ -56,6 +61,8 @@ void KNNTree<_MyMeshType, _MyVertexType>::MakeKNNTree(_MyMeshType& m, int numOfN
//If the number of the found vertices is less than the required we exclude the point with
//the highest value (inserted by the doQueryK function of the vcg library). Moreover
//we have to exclude the queryPoint!
//t2.restart();
int neightId = -1;
for (int j = 0; j < m.vn; j++) {
tree.doQueryK(m.vert[j].cP());
@ -67,6 +74,7 @@ void KNNTree<_MyMeshType, _MyVertexType>::MakeKNNTree(_MyMeshType& m, int numOfN
kNeighboursVect[m.vert[j]]->push_back(&(m.vert[neightId]));
}
}
//printf("KdTree Creation (knn-query): %d ms\n", t2.elapsed());
return;
}