From 457eaae5f4873ed9be37b034276f6a1f4a48ec22 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni cignoni Date: Mon, 20 Aug 2007 09:22:47 +0000 Subject: [PATCH] Several Improvements --- .../editsegment/curvaturetensor.h | 149 +++-------------- src/meshlabplugins/editsegment/cutting.h | 157 +++++++++++++----- .../editsegment/editsegment.cpp | 21 ++- src/meshlabplugins/editsegment/editsegment.h | 1 + 4 files changed, 153 insertions(+), 175 deletions(-) diff --git a/src/meshlabplugins/editsegment/curvaturetensor.h b/src/meshlabplugins/editsegment/curvaturetensor.h index 449317fc4..7d4cd9981 100644 --- a/src/meshlabplugins/editsegment/curvaturetensor.h +++ b/src/meshlabplugins/editsegment/curvaturetensor.h @@ -1,3 +1,6 @@ +#ifndef MESHCUTCURVATURE_H +#define MESHCUTCURVATURE_H + #include #include #include @@ -9,7 +12,7 @@ #include #include #include -#include + namespace vcg { class CurvData { @@ -57,7 +60,7 @@ namespace vcg { for (vi = mesh->vert.begin(); vi != mesh->vert.end(); ++vi) { - if ( ! (*vi).IsD()) { + if ( ! (*vi).IsD() && (*vi).VFp() != NULL) { VertexType * central_vertex = &(*vi); @@ -71,13 +74,13 @@ namespace vcg { VertexType* tempV; float totalDoubleAreaSize = 0.0f; - /* if (((firstV->P()-central_vertex->P())^(pos.VFlip()->P()-central_vertex->P()))*central_vertex->N()<=0.0f) + if (((firstV->P()-central_vertex->P())^(pos.VFlip()->P()-central_vertex->P()))*central_vertex->N()<=0.0f) { pos.Set(central_vertex->VFp(), central_vertex); pos.FlipE(); firstV = pos.VFlip(); } - else pos.Set(central_vertex->VFp(), central_vertex);*/ + else pos.Set(central_vertex->VFp(), central_vertex); do { @@ -95,7 +98,7 @@ namespace vcg { } while(tempV != firstV); - for (int i = 0; i::PerVertex(*mesh); - - VertexIterator vi; - for (vi = mesh->vert.begin(); vi != mesh->vert.end(); ++vi) { - if (!vi->IsD() ) { - - Matrix33 Mvi; - Mvi.SetZero(); - Matrix33 I; - I.SetIdentity(); - - Matrix33 n_nM; - //Point3 normal_d = Point3((double)vi->N()[0], (double)vi->N()[1],(double)vi->N()[2]); - Point3 normal = vi->N(); - normal = normal.Normalize(); - n_nM.ExternalProduct(normal, normal); - n_nM = I - n_nM; - - //Inizio Calcolo dei wij per tutti i vertici adiacenti - FaceType* first_face = vi->VFp(); - vcg::face::Pos pos2(first_face, vi->VFi(), &(*vi)); - vector wij_container; - float totalDoubleAreaSize = 0; - do { - - float doubleArea = vcg::DoubleArea(*pos2.F()); - totalDoubleAreaSize += doubleArea; - wij_container.push_back(doubleArea); - - pos2.NextE(); - } while (first_face != pos2.F()); - - totalDoubleAreaSize *= 2; - - int last_wij = wij_container[wij_container.size()-1]; - for (int i = (wij_container.size()-1); i > 0; --i) { - wij_container[i] += wij_container[i-1]; - wij_container[i] /= totalDoubleAreaSize; - } - wij_container[0] += last_wij; - wij_container[0] /= totalDoubleAreaSize; - - //calcola la matrice Mvi per ogni vertice - vcg::face::Pos pos(first_face, vi->VFi(), &(*vi)); - pos.FlipV(); - pos.FlipE(); - int i = 0; - ComputePerVertexMatrix(*vi, *(pos.V()), Mvi, n_nM, wij_container[i]); - pos.FlipV(); - pos.FlipE(); - pos.FlipF(); - pos.FlipE(); - while (first_face != pos.F()) { - ++i; - ComputePerVertexMatrix(*vi, *(pos.V()), Mvi, n_nM, wij_container[i]); - pos.FlipV(); - pos.FlipE(); - pos.FlipF(); - pos.FlipE(); - } - - - //Mvi matrix ready for the vertex vi - //calculate principal directions and curvature - Point3f Wvi; - Matrix33f Qvi; - Matrix33f QviT; - Matrix33f tempMatrix; - - Matrix33f A; - Point3f E1(1.0,0.0,0.0); - Point3f Nvi = (*vi).N(); - Nvi.Normalize(); - Point3f E1nNvi = E1 - Nvi; - Point3f E1pNvi = E1 + Nvi; - - if (E1nNvi.Norm() > E1pNvi.Norm() ) Wvi = E1nNvi / E1nNvi.Norm(); - else Wvi = E1pNvi / E1pNvi.Norm(); - - tempMatrix.ExternalProduct(Wvi, Wvi); - - Qvi.SetIdentity(); - Qvi -= tempMatrix * 2; - QviT = Qvi; - QviT.Transpose(); - - A = QviT * Mvi * Qvi; - - float c; - float s; - - givens(A[1][1], A[2][1], &c, &s); - - Point3 T1 = (A.GetColumn(1) * c) - (A.GetColumn(2) * s); - Point3 T2 = (A.GetColumn(1) * s) + (A.GetColumn(2) * c); - - float k1 = 3*T1[1] - T2[2]; - float k2 = 3*T2[2] - T1[1]; - - (*TDCurvPtr)[*vi].T1 = T1; - (*TDCurvPtr)[*vi].T2 = T2; - (*TDCurvPtr)[*vi].k1 = k1; - (*TDCurvPtr)[*vi].k2 = k2; - } - } - } - */ - }; } +#endif \ No newline at end of file diff --git a/src/meshlabplugins/editsegment/cutting.h b/src/meshlabplugins/editsegment/cutting.h index 99174831e..e8628dda3 100644 --- a/src/meshlabplugins/editsegment/cutting.h +++ b/src/meshlabplugins/editsegment/cutting.h @@ -4,11 +4,13 @@ #ifdef max #undef max #endif -#ifdef minor -#undef minor -#endif + +#include +#include +#include #include +#include #include #include #include @@ -24,12 +26,10 @@ #include #include - - - namespace vcg { - enum MarkType {U, //unmarked + enum MarkType { + U, //unmarked F, //foreground B, //background iF, //inputForeground @@ -51,7 +51,7 @@ namespace vcg { template class MinTriplet { public: bool operator() (const CuttingTriplet & a, const CuttingTriplet & b) const { - return (a.d > b.d); + return (a.d < b.d); } }; @@ -73,42 +73,44 @@ namespace vcg { SimpleTempData *TDCurvPtr; TripletQueue Q; + set, MinTriplet > setQ; //usato come coda principale, serve a garantire l'ordinamento e allo stesso tempo a permettere la cancellazione di elementi in ordine sparso + multimap VertToV; //ogni vertice inserito nella coda principale ha una coppia qui che punta al vertice che ne ha provocato l'inserimento + map > VToTriplet; //ogni vertice ha una referenza alle triplette da esso inserite + + float ImprovedIsophoticDist(VertexType * p, VertexType * q) { float dist; - double kpq = 0.0; + float kpq = 0.0f; const float e = 2.71828182845904523536; - const float W1 = 0.1f; - const float W2 = 0.9f; - + const float W1 = 5.0f; + const float W2 = 5.0f; Matrix33 n_nMatrix; Point3 ViVj = p->P() - q->P(); Point3 Tij; - + Point3 n = p->N(); n = n.Normalize(); n_nMatrix.ExternalProduct(n, n); - - Tij = (n_nMatrix * ViVj) / Norm(n_nMatrix * ViVj); - float cos = (Tij * (*TDCurvPtr)[*p].T1) / (Tij.Norm() * ((*TDCurvPtr)[*p].T1).Norm()); + Tij = (n_nMatrix * ViVj).Normalize(); + + float cos = (Tij * (*TDCurvPtr)[*p].T1.Normalize()); cos *= cos; //k = k1 * cos^2(@) + k2 * sin^2(@); @ = angle between T1 and direction P->Q projected onto the plane N kpq = ((*TDCurvPtr)[*p].k1 * cos) + ((*TDCurvPtr)[*p].k2 * (1 - cos)); - if (kpq < 0) { - //kpq = pow(e,fabs(kpq)) - 1; //if kpq < 0 -> kpq = (e^|kpq|) - 1 + if (kpq < 0) kpq = powf(e,fabs(kpq)) -1; - } - dist = (p->P() - q->P()).Norm() + W1 * (p->N() - q->N()).Norm() + W2 * kpq; + dist = (p->P() - q->P()).Norm() + (W1 * (p->N() - q->N()).Norm()) + (W2 * kpq); return dist; } - void AddNearestToQ(VertexType * v) { + void AddNearestToQ(VertexType * v, std::ofstream & file) { float dist = 0.0f; float min_dist = std::numeric_limits::max(); @@ -123,7 +125,6 @@ namespace vcg { for (int i = 0; i < 3; ++i) { tempV = pos.F()->V(i); if (tempV->P() != v->P() && (*TDMarkPtr)[tempV].Mark == U) { - //dist = vcg::SquaredDistance(v->P(), tempV->P()); dist = ImprovedIsophoticDist(v, tempV); if (dist < min_dist) { min_dist = dist; @@ -136,13 +137,17 @@ namespace vcg { if (nearestV) { CuttingTriplet tempTriplet; tempTriplet.v = nearestV; - tempTriplet.d = ImprovedIsophoticDist(v, nearestV); + tempTriplet.d = min_dist; switch((*TDMarkPtr)[v].Mark) { case iF: tempTriplet.m = F; break; case iB: tempTriplet.m = B; break; default : tempTriplet.m = (*TDMarkPtr)[v].Mark; break; } - Q.push(tempTriplet); + + setQ.insert(tempTriplet); + VertToV.insert(make_pair(tempTriplet.v, v)); + VToTriplet.insert(make_pair(v,tempTriplet)); + if (file) file << "inserita tripletta con distanza: " << tempTriplet.d << std::endl; } } @@ -169,13 +174,13 @@ namespace vcg { void MeshCut() { VertexIterator vi; - int counter = 0; + int vertex_to_go = 0; int inputCounter = 0; for (vi=(*mesh).vert.begin(); vi!=(*mesh).vert.end(); ++vi) { if ( !vi->IsD() && (*TDMarkPtr)[*vi].Mark != iF && (*TDMarkPtr)[*vi].Mark != iB) { (*TDMarkPtr)[*vi].Mark = U; - ++counter; + ++vertex_to_go; } else { ++inputCounter; } @@ -184,31 +189,82 @@ namespace vcg { //check if no input is given to prevent infinite loop. if (!inputCounter) return; + std::ofstream file; + file.open("editsegment.log"); + //Computing principal curvatures and directions for all vertices vcg::CurvatureTensorct(mesh, TDCurvPtr); ct.ComputeCurvatureTensor(); //now each vertex has principals curvatures and directions in its temp data + if (file) file << "Inizializzazione da input." << std::endl; - while (counter != 0) { - //second iteration on the marked vertex - for (vi=(*mesh).vert.begin(); vi!=(*mesh).vert.end(); ++vi) { - if ( !vi->IsD() && ((*TDMarkPtr)[*vi].Mark != U)) - AddNearestToQ(&(*vi)); - } + //second iteration on the marked vertex + for (vi=(*mesh).vert.begin(); vi!=(*mesh).vert.end(); ++vi) { + if ( !vi->IsD() && ((*TDMarkPtr)[*vi].Mark != U)) + AddNearestToQ(&(*vi),file); + } + if (file) file << "Fine inizializzazione da input. Elementi aggiunti: " << setQ.size() << std::endl; + + while (vertex_to_go != 0) { //algorithm main loop - CuttingTriplet tempTriplet; - while(!Q.empty()) { - tempTriplet = Q.top(); - Q.pop(); - if ( (*TDMarkPtr)[tempTriplet.v].Mark == U) { - (*TDMarkPtr)[tempTriplet.v].Mark = tempTriplet.m; - AddNearestToQ(tempTriplet.v); - --counter; - } + + if (setQ.empty()) { + if (file) file << "Coda vuota. Re-Inizializzazione." << std::endl; + for (vi=(*mesh).vert.begin(); vi!=(*mesh).vert.end(); ++vi) { + if ( !vi->IsD() && ((*TDMarkPtr)[*vi].Mark != U)) + AddNearestToQ(&(*vi),file); + } + if (setQ.empty()) break; + } else { + + CuttingTriplet tempTriplet; + + //prendo la tripletta con distanza minima + + tempTriplet = *(setQ.begin()); + assert((*TDMarkPtr)[tempTriplet.v].Mark == U); + (*TDMarkPtr)[tempTriplet.v].Mark = tempTriplet.m; + --vertex_to_go; + + + if (file) file << "Estratta tripletta con distanza: " << tempTriplet.d << std::endl; + + //prendo tutti i vertici che avevano inserito il vertice estratto + vector tempVertex; + + typedef multimap::iterator MMI; + pair mm_range = VertToV.equal_range(tempTriplet.v); + for (MMI mm_iter = mm_range.first; mm_iter != mm_range.second; ++mm_iter) { + tempVertex.push_back(mm_iter->second); + } + + VertToV.erase(tempTriplet.v); + + //rimuovo dalla coda tutte le triplette che sono state inserite dai vertici presi prima + vector::iterator tempV_iter; + for (tempV_iter = tempVertex.begin(); tempV_iter != tempVertex.end(); tempV_iter++) { + if (setQ.find(VToTriplet[*tempV_iter]) != setQ.end()) + setQ.erase(setQ.find(VToTriplet[*tempV_iter])); + + if (VToTriplet.find(*tempV_iter) != VToTriplet.end() ) + VToTriplet.erase(VToTriplet.find(*tempV_iter)); + } + + for (tempV_iter = tempVertex.begin(); tempV_iter != tempVertex.end(); tempV_iter++) { + AddNearestToQ((*tempV_iter), file); + } + + AddNearestToQ(tempTriplet.v, file); + tempVertex.clear(); } } + + VToTriplet.clear(); + setQ.clear(); + VertToV.clear(); + if (file) file.close(); } void Colorize(bool selectForeground) { @@ -244,7 +300,7 @@ namespace vcg { void ColorizeCurvature(bool gaussian) { vcg::CurvatureTensorct(mesh, TDCurvPtr); ct.ComputeCurvatureTensor(); - + VertexIterator vi; if (gaussian) { //gaussian @@ -261,7 +317,22 @@ namespace vcg { Histogramf H; tri::Stat::ComputePerVertexQualityHistogram(*mesh,H); - tri::UpdateColor::VertexQuality(*mesh,H.Percentile(0.1),H.Percentile(0.9)); + tri::UpdateColor::VertexQuality(*mesh,H.Percentile(0.1f),H.Percentile(0.9f)); + } + + void Reset() { + VertexIterator vi; + + for (vi = mesh->vert.begin(); vi != mesh->vert.end(); ++vi) { + (*TDMarkPtr)[*vi].Mark = U; + vi->C() = Color4b::White; + vi->Q() = 0.0f; + } + + FaceIterator fi; + for (fi = mesh->face.begin(); fi != mesh->face.end(); ++fi) { + (*fi).ClearS(); + } } }; diff --git a/src/meshlabplugins/editsegment/editsegment.cpp b/src/meshlabplugins/editsegment/editsegment.cpp index 150745196..1ffb6c94d 100644 --- a/src/meshlabplugins/editsegment/editsegment.cpp +++ b/src/meshlabplugins/editsegment/editsegment.cpp @@ -229,7 +229,7 @@ Color4b toVcgColor(QColor c) { EditSegment::EditSegment() { actionList << new QAction(QIcon(":/images/editsegment.png"),"Mesh Segmentation", this); pixels = 0; - pen.radius = 5; + pen.radius = 3; pen.backface = false; pen.invisible = false; pressed = false; @@ -247,7 +247,7 @@ QList EditSegment::actions() const { const QString EditSegment::Info(QAction *action) { if( action->text() != tr("Mesh Segmentation") ) assert (0); - return tr("blablabla"); + return tr("Segment the mesh by selecting the foreground and background"); } const PluginInfo &EditSegment::Info() { @@ -261,7 +261,8 @@ const PluginInfo &EditSegment::Info() { void EditSegment::StartEdit(QAction * mode, MeshModel & m, GLArea * parent) { parent->setCursor(QCursor(QPixmap(":/images/editsegment_cursor.png","PNG"),1,1)); - if (!meshCut) meshCut = new MeshCutting(&m.cm); + if (!meshCut) + meshCut = new MeshCutting(&m.cm); if (!meshCutDialog) { meshCutDialog = new MeshCutDialog(parent->window()); @@ -275,6 +276,7 @@ void EditSegment::StartEdit(QAction * mode, MeshModel & m, GLArea * parent) { QObject::connect(meshCutDialog, SIGNAL(meshCutSignal()),this, SLOT(MeshCutSlot())); QObject::connect(meshCutDialog, SIGNAL(selectForegroundSignal(bool)),this, SLOT(SelectForegroundSlot(bool))); + QObject::connect(meshCutDialog, SIGNAL(resetSignal()),this,SLOT(ResetSlot())); QObject::connect(meshCutDialog, SIGNAL(colorizeGaussianSignal()),this, SLOT(ColorizeGaussianSlot())); QObject::connect(meshCutDialog, SIGNAL(colorizeMeanSignal()),this, SLOT(ColorizeMeanSlot())); @@ -317,15 +319,13 @@ void EditSegment::Decorate (QAction * ac, MeshModel & m, GLArea * gla) { getInternFaces(m,¤tSelection,&newSel,&faceSel,gla,pen,current_point,previous_point,pixels,mvmatrix,projmatrix,viewport); vector::iterator fpo; - bool sel_or_not=(mouse_button_pressed==Qt::LeftButton); + for(fpo=faceSel.begin();fpo!=faceSel.end();++fpo) { for (int i=0; i<3; ++i) { - if (sel_or_not) { + if (mouse_button_pressed==Qt::LeftButton) { meshCut->Mark((*fpo)->V(i), iF); (*fpo)->V(i)->C() = toVcgColor(meshCutDialog->getForegroundColor()); - //(*fpo)->SetS(); } else { - //(*fpo)->ClearS(); meshCut->Mark((*fpo)->V(i), iB); (*fpo)->V(i)->C() = toVcgColor(meshCutDialog->getBackgroundColor()); } @@ -429,4 +429,11 @@ void EditSegment::ColorizeMeanSlot() { } } +void EditSegment::ResetSlot() { + if (meshCut) { + meshCut->Reset(); + glarea->update(); + } +} + Q_EXPORT_PLUGIN(EditSegment) diff --git a/src/meshlabplugins/editsegment/editsegment.h b/src/meshlabplugins/editsegment/editsegment.h index 1922fa634..58ab79e8c 100644 --- a/src/meshlabplugins/editsegment/editsegment.h +++ b/src/meshlabplugins/editsegment/editsegment.h @@ -84,6 +84,7 @@ public slots: void ColorizeGaussianSlot(); void ColorizeMeanSlot(); + void ResetSlot(); };