Cleaned up a bit the edit point interface. Now it uses the RealTimeLog to show the current hop and radius

This commit is contained in:
Paolo Cignoni cignoni 2012-07-12 06:47:31 +00:00
parent 44a14687c6
commit 2ecc484f7f
3 changed files with 113 additions and 100 deletions

View File

@ -14,22 +14,17 @@
#include <vcg/space/fitting3.h>
namespace vcg {
namespace tri {
using namespace std;
using namespace vcg;
template <typename _MyMeshType, typename _MyVertexType>
template <typename _MyMeshType>
class ComponentFinder {
typedef typename _MyMeshType::VertexType VertexType;
typedef typename _MyMeshType::VertexIterator VertexIterator;
typedef typename _MyMeshType::CoordType CoordType;
public:
static std::vector<_MyVertexType*> &FindComponent(_MyMeshType& m, float dim, vector<_MyVertexType*> &borderVect, vector<_MyVertexType*> &notReachableVect, bool fitting = false, float planeDim = 0.0, float distanceFromPlane = 0.0, Plane3<typename _MyMeshType::ScalarType> *fittingPlane = NULL);
static void DeletePerVertexAttribute(_MyMeshType& m);
static void Dijkstra(_MyMeshType& m, _MyVertexType& v, int numOfNeighbours, float maxHopDist, vector<_MyVertexType*> &notReachableVect);
};
/** This function returns a vector which stores pointers to the vertices of the connected component with
/** This function returns a vector which stores pointers to the vertices of the connected component with
* max distance 'dim' from the center. It assumes that the vertices have the DistParam attribute, so
* we don't have to know where is the center.
* The border is also computed, using the notReachableVect parameter, which stores the vertices we
@ -38,21 +33,25 @@ public:
* We can specify to fit some points: in this case first we compute the fitting plane (vcg library method),
* then we calculate the connected component and the border.
**/
template <typename _MyMeshType, typename _MyVertexType>
std::vector<_MyVertexType*> &ComponentFinder<_MyMeshType, _MyVertexType>::FindComponent(_MyMeshType& m, float dim, vector<_MyVertexType*> &borderVect, vector<_MyVertexType*> &notReachableVect, bool fitting, float planeDim, float distanceFromPlane, Plane3<typename _MyMeshType::ScalarType> *fittingPlane) {
vector<_MyVertexType*> *resultVect = new vector<_MyVertexType*>();
vector<typename _MyMeshType::CoordType> pointToFit = vector<typename _MyMeshType::CoordType>();
static std::vector<VertexType*> &FindComponent(_MyMeshType& m, float dim,
std::vector<VertexType*> &borderVect,
std::vector<VertexType*> &notReachableVect,
bool fitting=false, float planeDim=0, float distanceFromPlane=0,
Plane3<typename _MyMeshType::ScalarType> *fittingPlane=NULL)
{
std::vector<VertexType*> *resultVect = new std::vector<VertexType*>();
std::vector<CoordType> pointToFit = std::vector<CoordType>();
tri::UpdateFlags<_MyMeshType>::VertexClearV(m);
bool hasDistParam = vcg::tri::HasPerVertexAttribute(m, "DistParam");
bool hasDistParam = tri::HasPerVertexAttribute(m, "DistParam");
typename _MyMeshType::template PerVertexAttributeHandle<float> distFromCenter;
if (hasDistParam) distFromCenter = vcg::tri::Allocator<_MyMeshType>::template GetPerVertexAttribute<float>(m, std::string("DistParam"));
if (hasDistParam) distFromCenter = tri::Allocator<_MyMeshType>::template GetPerVertexAttribute<float>(m, std::string("DistParam"));
else return *resultVect;
for (typename _MyMeshType::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++) {
for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++) {
if (fitting) {
if (distFromCenter[vi] < planeDim) {
pointToFit.push_back(vi->cP());
@ -61,11 +60,11 @@ std::vector<_MyVertexType*> &ComponentFinder<_MyMeshType, _MyVertexType>::FindCo
else if (distFromCenter[vi] < dim) resultVect->push_back(&*vi);
}
typename vector<_MyVertexType*>::iterator it;
typename std::vector<VertexType*>::iterator it;
if (fitting) {
vcg::PlaneFittingPoints(pointToFit, *fittingPlane);
for (typename _MyMeshType::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++) {
for (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++) {
@ -85,7 +84,6 @@ std::vector<_MyVertexType*> &ComponentFinder<_MyMeshType, _MyVertexType>::FindCo
/* This class is used in the priority queue to order the nodes */
template <typename _MyMeshType, typename _MyVertexType>
class Compare {
private:
typename _MyMeshType::template PerVertexAttributeHandle<float> *distFromCenter;
@ -95,7 +93,7 @@ public:
this->distFromCenter = distFromCenter;
}
bool operator() (const _MyVertexType* lhs, const _MyVertexType* rhs) const
bool operator() (const VertexType* lhs, const VertexType* rhs) const
{
return (*distFromCenter)[*lhs] > (*distFromCenter)[*rhs];
}
@ -109,34 +107,35 @@ public:
* attributes and we construct the KNNGraph.
* The notReachableVect is returned in order to calculate the border in other methods.
**/
template <typename _MyMeshType, typename _MyVertexType>
void ComponentFinder<_MyMeshType, _MyVertexType>::Dijkstra(_MyMeshType& m, _MyVertexType& v, int numOfNeighbours, float maxHopDist, vector<_MyVertexType*> &notReachableVect) {
bool hasKNNGraph = vcg::tri::HasPerVertexAttribute(m, "KNNGraph");
bool hasDistParam = vcg::tri::HasPerVertexAttribute(m, "DistParam");
static void Dijkstra(_MyMeshType& m, VertexType& v, int numOfNeighbours, float maxHopDist, std::vector<VertexType*> &notReachableVect)
{
bool hasKNNGraph = tri::HasPerVertexAttribute(m, "KNNGraph");
bool hasDistParam = tri::HasPerVertexAttribute(m, "DistParam");
notReachableVect.clear();
typename _MyMeshType::template PerVertexAttributeHandle<float> distFromCenter;
if (!hasDistParam) {
distFromCenter = vcg::tri::Allocator<_MyMeshType>::template AddPerVertexAttribute<float>(m, std::string("DistParam"));
distFromCenter = tri::Allocator<_MyMeshType>::template AddPerVertexAttribute<float>(m, std::string("DistParam"));
}
else distFromCenter = vcg::tri::Allocator<_MyMeshType>::template GetPerVertexAttribute<float>(m, std::string("DistParam"));
else distFromCenter = tri::Allocator<_MyMeshType>::template GetPerVertexAttribute<float>(m, std::string("DistParam"));
if (!hasKNNGraph) {
KNNTree<_MyMeshType, _MyVertexType>::MakeKNNTree(m, numOfNeighbours);
KNNGraph<_MyMeshType>::MakeKNNTree(m, numOfNeighbours);
}
typename _MyMeshType::template PerVertexAttributeHandle<vector<_MyVertexType*>* > neighboursVect = vcg::tri::Allocator<_MyMeshType>::template GetPerVertexAttribute<vector<_MyVertexType*>* >(m,"KNNGraph");
typename _MyMeshType::template PerVertexAttributeHandle<std::vector<VertexType*>* > neighboursVect = tri::Allocator<_MyMeshType>::template GetPerVertexAttribute<std::vector<VertexType*>* >(m,"KNNGraph");
typename vector<_MyVertexType*>::iterator it;
typename std::vector<VertexType*>::iterator it;
// For Dijkstra algorithm we use a Priority Queue
typedef priority_queue<_MyVertexType*, vector<_MyVertexType*>, Compare<_MyMeshType, _MyVertexType> > VertPriorityQueue;
Compare<_MyMeshType, _MyVertexType> Comparator(&distFromCenter);
typedef std::priority_queue<VertexType*, std::vector<VertexType*>, Compare > VertPriorityQueue;
Compare Comparator(&distFromCenter);
VertPriorityQueue prQueue (Comparator);
for (typename _MyMeshType::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++)
distFromCenter[vi] = numeric_limits<float>::max();
distFromCenter[vi] = std::numeric_limits<float>::max();
distFromCenter[v] = 0.f;
@ -145,11 +144,8 @@ void ComponentFinder<_MyMeshType, _MyVertexType>::Dijkstra(_MyMeshType& m, _MyVe
prQueue.push(&v);
v.SetV();
float distance;
_MyVertexType* element;
while (!prQueue.empty()) {
element = prQueue.top();
VertexType* element = prQueue.top();
prQueue.pop();
for (it = neighboursVect[element]->begin(); it != neighboursVect[element]->end(); it++)
@ -157,15 +153,14 @@ void ComponentFinder<_MyMeshType, _MyVertexType>::Dijkstra(_MyMeshType& m, _MyVe
//I have not to compute the arches connecting vertices already visited.
if (!(*it)->IsV())
{
distance = vcg::Distance((*it)->P(), element->P());
float distance = vcg::Distance((*it)->P(), element->P());
// we take into account only the arcs with a distance less or equal to maxHopDist
if (distance <= maxHopDist)
{
if ((distFromCenter[*element] + distance) < distFromCenter[*it])
{
distFromCenter[*it] = distFromCenter[*element] + distance;
if (!(*it)->IsV()) {
prQueue.push(*it);
(*it)->SetV();
}
@ -181,18 +176,20 @@ void ComponentFinder<_MyMeshType, _MyVertexType>::Dijkstra(_MyMeshType& m, _MyVe
/**
* Used to free memory
**/
template <typename _MyMeshType, typename _MyVertexType>
void ComponentFinder<_MyMeshType, _MyVertexType>::DeletePerVertexAttribute(_MyMeshType& m) {
KNNTree<_MyMeshType, _MyVertexType>::DeleteKNNTree(m);
bool hasDistParam = vcg::tri::HasPerVertexAttribute(m, "DistParam");
static void DeletePerVertexAttribute(_MyMeshType& m)
{
KNNGraph<_MyMeshType>::DeleteKNNTree(m);
bool hasDistParam = tri::HasPerVertexAttribute(m, "DistParam");
if (hasDistParam) {
vcg::tri::Allocator<_MyMeshType>::DeletePerVertexAttribute(m, "DistParam");
Allocator<_MyMeshType>::DeletePerVertexAttribute(m, "DistParam");
}
return;
}
}; // end ComponentFinder Class
} //end namespace tri
} // end namespace vcg;
#endif // CONNECTEDCOMPONENT_H

View File

@ -50,6 +50,9 @@ const QString EditPointPlugin::Info() {
void EditPointPlugin::Decorate(MeshModel &m, GLArea * gla, QPainter *p)
{
this->RealTimeLog("EditPointHop","Hop Thr: %8.3f (Wheel to change it)",this->maxHop);
this->RealTimeLog("EditPointRad"," Radius: %8.3f (Drag or Alt+Wheel to change it)",this->dist);
/* 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
to find the distance between the selected point and the others. */
@ -62,7 +65,7 @@ void EditPointPlugin::Decorate(MeshModel &m, GLArea * gla, QPainter *p)
if(NewSel.size() > 0) {
startingVertex = NewSel.front();
ComponentFinder<CMeshO, CVertexO>::Dijkstra(m.cm, *startingVertex, K, this->maxHop, this->NotReachableVector);
tri::ComponentFinder<CMeshO>::Dijkstra(m.cm, *startingVertex, K, this->maxHop, this->NotReachableVector);
ComponentVector.push_back(startingVertex);
}
@ -181,6 +184,7 @@ bool EditPointPlugin::StartEdit(MeshModel &m, GLArea *gla) {
this->maxHop = m.cm.bbox.Diag() / 100.0;
this->planeDist = m.cm.bbox.Diag() / 100.0;
this->fittingRadiusPerc = 0.1;
this->dist = 0;
composingSelMode = SMClear;
@ -190,19 +194,22 @@ bool EditPointPlugin::StartEdit(MeshModel &m, GLArea *gla) {
void EditPointPlugin::EndEdit(MeshModel &m, GLArea *gla) {
//delete the circle if present.
fittingCircle.Clear();
ComponentFinder<CMeshO, CVertexO>::DeletePerVertexAttribute(m.cm);
tri::ComponentFinder<CMeshO>::DeletePerVertexAttribute(m.cm);
}
void EditPointPlugin::mousePressEvent(QMouseEvent *ev, MeshModel &m, GLArea *gla) {
startingVertex = NULL;
cur = ev->pos();
haveToPick = true;
this->isMousePressed = true;
this->dist = 0.0;
this->startingClick = vcg::Point2f(ev->x(), ev->y());
if(!(ev->modifiers() & Qt::AltModifier) || startingVertex == NULL)
{
this->startingClick = vcg::Point2f(ev->x(), ev->y());
startingVertex = NULL;
this->dist = 0.0;
haveToPick = true;
}
this->fittingRadius = 0.0;
OldComponentVector.clear();
@ -236,10 +243,10 @@ void EditPointPlugin::mouseMoveEvent(QMouseEvent *ev, MeshModel &m, GLArea *gla
BorderVector.clear();
if (editType == SELECT_DEFAULT_MODE)
ComponentVector = ComponentFinder<CMeshO, CVertexO>::FindComponent(m.cm, this->dist, BorderVector, NotReachableVector);
ComponentVector = tri::ComponentFinder<CMeshO>::FindComponent(m.cm, this->dist, BorderVector, NotReachableVector);
else if (editType == SELECT_FITTING_PLANE_MODE) {
this->fittingRadius = dist * fittingRadiusPerc;
ComponentVector = ComponentFinder<CMeshO, CVertexO>::FindComponent(m.cm, this->dist, BorderVector, NotReachableVector, true, fittingRadius, planeDist, &fittingPlane);
ComponentVector = tri::ComponentFinder<CMeshO>::FindComponent(m.cm, this->dist, BorderVector, NotReachableVector, true, fittingRadius, planeDist, &fittingPlane);
}
gla->update();
@ -326,47 +333,53 @@ void EditPointPlugin::keyPressEvent(QKeyEvent *ev, MeshModel &m, GLArea *gla) {
new arcs to consider in the Dijkstra algorithm.
If we modified other parameters we need only to find the new selected component. */
if (hopDistModified) {
ComponentFinder<CMeshO, CVertexO>::Dijkstra(m.cm, *startingVertex, 6, this->maxHop, this->NotReachableVector);
tri::ComponentFinder<CMeshO>::Dijkstra(m.cm, *startingVertex, 6, this->maxHop, this->NotReachableVector);
}
if (parameterModified) {
BorderVector.clear();
if (editType == SELECT_DEFAULT_MODE)
ComponentVector = ComponentFinder<CMeshO, CVertexO>::FindComponent(m.cm, this->dist, BorderVector, NotReachableVector);
ComponentVector = tri::ComponentFinder<CMeshO>::FindComponent(m.cm, this->dist, BorderVector, NotReachableVector);
else if (editType == SELECT_FITTING_PLANE_MODE)
ComponentVector = ComponentFinder<CMeshO, CVertexO>::FindComponent(m.cm, this->dist, BorderVector, NotReachableVector, true, fittingRadius, planeDist, &fittingPlane);
ComponentVector = tri::ComponentFinder<CMeshO>::FindComponent(m.cm, this->dist, BorderVector, NotReachableVector, true, fittingRadius, planeDist, &fittingPlane);
}
gla->update();
return;
}
void EditPointPlugin::wheelEvent(QWheelEvent* ev, MeshModel &m, GLArea *gla) {
bool hopDistModified = false;
int wheelDirection = ev->delta();
void EditPointPlugin::wheelEvent(QWheelEvent* ev, MeshModel &m, GLArea *gla)
{
bool hopDistModified = false;
bool distModified = false;
if (startingVertex != NULL) {
if (wheelDirection > 0) {
this->maxHop *= pow(1.2f, wheelDirection / 120.f);
hopDistModified = true;
}
else if (wheelDirection < 0) {
this->maxHop /= pow(1.2f, (-1*wheelDirection) / 120.f);
hopDistModified = true;
}
}
int wheelDirection = ev->delta();
if (startingVertex != NULL && (ev->modifiers() & Qt::AltModifier))
{
this->dist *= pow(1.1f, wheelDirection / 120.f);
distModified = true;
}
if (hopDistModified) {
ComponentFinder<CMeshO, CVertexO>::Dijkstra(m.cm, *startingVertex, K, this->maxHop, this->NotReachableVector);
if (!(ev->modifiers() & Qt::AltModifier))
{
this->maxHop *= pow(1.1f, wheelDirection / 120.f);
hopDistModified = true;
}
BorderVector.clear();
if (hopDistModified && (startingVertex != NULL)) {
tri::ComponentFinder<CMeshO>::Dijkstra(m.cm, *startingVertex, K, this->maxHop, this->NotReachableVector);
}
if (editType == SELECT_DEFAULT_MODE)
ComponentVector = ComponentFinder<CMeshO, CVertexO>::FindComponent(m.cm, this->dist, BorderVector, NotReachableVector);
else if (editType == SELECT_FITTING_PLANE_MODE)
ComponentVector = ComponentFinder<CMeshO, CVertexO>::FindComponent(m.cm, this->dist, BorderVector, NotReachableVector, true, fittingRadius, planeDist, &fittingPlane);
}
if(startingVertex != NULL)
{
BorderVector.clear();
gla->update();
return;
if (editType == SELECT_DEFAULT_MODE)
ComponentVector = tri::ComponentFinder<CMeshO>::FindComponent(m.cm, this->dist, BorderVector, NotReachableVector);
else if (editType == SELECT_FITTING_PLANE_MODE)
ComponentVector = tri::ComponentFinder<CMeshO>::FindComponent(m.cm, this->dist, BorderVector, NotReachableVector, true, fittingRadius, planeDist, &fittingPlane);
}
gla->update();
return;
}

View File

@ -10,22 +10,21 @@
#include <vcg/space/index/kdtree/kdtree.h>
using namespace std;
using namespace vcg;
namespace vcg {
namespace tri {
template <typename _MyMeshType, typename _MyVertexType>
class KNNTree {
template <typename _MyMeshType>
class KNNGraph {
public:
static void MakeKNNTree(_MyMeshType& m, int numOfNeighbours);
static void DeleteKNNTree(_MyMeshType& m);
};
/**
typedef typename _MyMeshType::VertexType _MyVertexType;
/**
* Static function to create and fill the PerVertexAttribute KNNGraph, which stores the k-nearest
* neighbours via vertex pointers
*/
template <typename _MyMeshType, typename _MyVertexType>
void KNNTree<_MyMeshType, _MyVertexType>::MakeKNNTree(_MyMeshType& m, int numOfNeighbours) {
static void MakeKNNTree(_MyMeshType& m, int numOfNeighbours)
{
//we search k+1 neighbours in order to exclude the queryPoint from the returned heap
int neighboursVectSize = numOfNeighbours + 1;
@ -35,15 +34,15 @@ void KNNTree<_MyMeshType, _MyVertexType>::MakeKNNTree(_MyMeshType& m, int numOfN
tri::Allocator<_MyMeshType>::CompactVertexVector(m);
//the PerVertexAttribute handles is create and each of the vector capacity set to the maximum possible
typename _MyMeshType::template PerVertexAttributeHandle<vector<_MyVertexType*>* > kNeighboursVect;
kNeighboursVect = vcg::tri::Allocator<_MyMeshType>::template AddPerVertexAttribute<vector<_MyVertexType*>* >(m, std::string("KNNGraph"));
typename _MyMeshType::template PerVertexAttributeHandle<std::vector<_MyVertexType*>* > kNeighboursVect;
kNeighboursVect = tri::Allocator<_MyMeshType>::template AddPerVertexAttribute<std::vector<_MyVertexType*>* >(m, std::string("KNNGraph"));
for (typename _MyMeshType::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++) {
kNeighboursVect[vi] = new vector<_MyVertexType*>();
kNeighboursVect[vi] = new std::vector<_MyVertexType*>();
kNeighboursVect[vi]->reserve(neighboursVectSize);
}
//we create and fill the DataWrapper we need to pass the points to the KdTree
vector<typename _MyMeshType::CoordType> input(m.vn);
std::vector<typename _MyMeshType::CoordType> input(m.vn);
int i = 0;
for (typename _MyMeshType::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++, ++i) {
input[i] = vi->cP();
@ -77,15 +76,19 @@ void KNNTree<_MyMeshType, _MyVertexType>::MakeKNNTree(_MyMeshType& m, int numOfN
/**
* Static function which removes the KNNGraph PerVertex attribute
*/
template <typename _MyMeshType, typename _MyVertexType>
void KNNTree<_MyMeshType, _MyVertexType>::DeleteKNNTree(_MyMeshType& m) {
static void DeleteKNNTree(_MyMeshType& m)
{
bool hasKNNGraph = tri::HasPerVertexAttribute(m, "KNNGraph");
if (hasKNNGraph) {
vcg::tri::Allocator<_MyMeshType>::DeletePerVertexAttribute(m, "KNNGraph");
tri::Allocator<_MyMeshType>::DeletePerVertexAttribute(m, "KNNGraph");
}
return;
}
}; // end knnGraph Class
} //end namespace tri
} // end namespace vcg;
#endif // KNNGRAPH_H