diff --git a/apps/test/segmentation3d/collision_detection.h b/apps/test/segmentation3d/collision_detection.h new file mode 100644 index 00000000..0fe55e03 --- /dev/null +++ b/apps/test/segmentation3d/collision_detection.h @@ -0,0 +1,131 @@ +#ifndef COLLISION_DETECTION +#define COLLISION_DETECTION + +#include +#include +#include + +template +class Collision_Detector{ + +public: + + typedef typename ContSimplex::value_type SimplexType; + typedef typename ContSimplex::value_type* SimplexPointer; + typedef typename ContSimplex::iterator SimplexIterator; + typedef typename SimplexType::CoordType Point3x; + typedef typename Point3x::ScalarType ScalarType; + + typedef SpatialHashTable HashingTable; + + Collision_Detector(ContSimplex & r_):_simplex(r_){}; + ~Collision_Detector(){}; + + ContSimplex & _simplex; + + HashingTable *HTable; + + std::set vactive; + + int active; + + //control if two faces share an edge + bool ShareEdge(SimplexType *f0,SimplexType *f1) + { + for (int i=0;i<3;i++) + if (f0->FFp(i)==f1) + return (true); + + return(false); + } + + ///initialize the box for collision detection and the dimension of a cell + void Init(Point3x _min,Point3x _max,ScalarType _l) + { + HTable=new HashingTable(); + HTable->Init(_min,_max,_l); + } + + //control if two faces share a vertex + bool ShareVertex(SimplexType *f0,SimplexType *f1) + { + for (int i=0;i<3;i++) + for (int j=0;j<3;j++) + if (f0->V(i)==f1->V(j)) + return (true); + + return(false); + } + + //test real intersection between faces + bool TestRealIntersection(SimplexType *f0,SimplexType *f1) + { + + if ((!f0->IsActive())&&(!f1->IsActive())) + return false; + //no adiacent faces + if ((f0!=f1)&& (!ShareEdge(f0,f1)) + && (!ShareVertex(f0,f1))) + return (vcg::Intersection((*f0),(*f1))); + return false; + } + + ///refresh the elemnt of spatial hashing table + void RefreshElements() + { + HTable->Clear(); + + for (SimplexIterator si=_simplex.begin();si<_simplex.end();++si) + { + if ((!(*si).IsD())&&(!(*si).IsActive())) + HTable->addSimplex(&*si); + } + + UpdateStep(); + } + + ///put active cells on apposite structure + void UpdateStep() + { + vactive.clear(); + for (SimplexIterator si=_simplex.begin();si<_simplex.end();++si) + { + if ((((!(*si).IsD()))&&(*si).IsActive())) + { + std::vector cells=HTable->addSimplex(&*si); + for(std::vector::iterator it=cells.begin();it computeSelfIntersection() + { + std::vector ret; + std::set::iterator act; + for (act=vactive.begin();act!=vactive.end();act++) + { + Point3i p=*act; + if (HTable->numElemCell(p)>=2) + { + std::vector inCell=HTable->getAtCell(p); + int nelem=inCell.size(); + if (nelem>=2) + { + //test combinations of elements + for (int i=0;iIsD())&&(!inCell[j]->IsD())&&(TestRealIntersection(inCell[i],inCell[j]))) + { + ret.push_back(inCell[i]); + ret.push_back(inCell[j]); + } + } + } + } + return ret; + } + +}; +#endif \ No newline at end of file diff --git a/apps/test/segmentation3d/main.cpp b/apps/test/segmentation3d/main.cpp new file mode 100644 index 00000000..d89370b0 --- /dev/null +++ b/apps/test/segmentation3d/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +Segmentator *s; +QTimer *timer; + +int main( int argc, char ** argv ) +{ + //s=new Segmentator(); + + //s->LoadFromDir("./venacava/","prova.txt");//to chANGE + + ////s->InitSegmentation(0.5,0.2,20,10.f); + // + QApplication a( argc, argv ); + + SegmentForm w; + w.show(); + + //assign pointer to pricipal form + w.simpleGLWidget1->w=&w; + + s=new Segmentator(); + + //s->LoadFromDir("./venacava/","prova.txt");//to chANGE + + //s->InitSegmentation(0.5,0.2,20,10.f); + + + timer = new QTimer(w.simpleGLWidget1 ); + QTimer::connect( timer, SIGNAL(timeout()), w.simpleGLWidget1, SLOT(Update()) ); + timer->start(0); // 2 seconds single-shot timer + + + a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) ); + return a.exec(); +} diff --git a/apps/test/segmentation3d/moc_simpleglwidget.cpp b/apps/test/segmentation3d/moc_simpleglwidget.cpp new file mode 100644 index 00000000..a7369cca --- /dev/null +++ b/apps/test/segmentation3d/moc_simpleglwidget.cpp @@ -0,0 +1,137 @@ +/**************************************************************************** +** SimpleGLWidget meta object code from reading C++ file 'simpleglwidget.h' +** +** Created: Fri Dec 17 12:16:05 2004 +** by: The Qt MOC ($Id: moc_simpleglwidget.cpp,v 1.1 2004-12-17 11:17:36 pietroni Exp $) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#undef QT_NO_COMPAT +#include "simpleglwidget.h" +#include +#include + +#include +#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != 26) +#error "This file was generated using the moc from 3.3.2. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +const char *SimpleGLWidget::className() const +{ + return "SimpleGLWidget"; +} + +QMetaObject *SimpleGLWidget::metaObj = 0; +static QMetaObjectCleanUp cleanUp_SimpleGLWidget( "SimpleGLWidget", &SimpleGLWidget::staticMetaObject ); + +#ifndef QT_NO_TRANSLATION +QString SimpleGLWidget::tr( const char *s, const char *c ) +{ + if ( qApp ) + return qApp->translate( "SimpleGLWidget", s, c, QApplication::DefaultCodec ); + else + return QString::fromLatin1( s ); +} +#ifndef QT_NO_TRANSLATION_UTF8 +QString SimpleGLWidget::trUtf8( const char *s, const char *c ) +{ + if ( qApp ) + return qApp->translate( "SimpleGLWidget", s, c, QApplication::UnicodeUTF8 ); + else + return QString::fromUtf8( s ); +} +#endif // QT_NO_TRANSLATION_UTF8 + +#endif // QT_NO_TRANSLATION + +QMetaObject* SimpleGLWidget::staticMetaObject() +{ + if ( metaObj ) + return metaObj; + QMetaObject* parentObject = QGLWidget::staticMetaObject(); + static const QUMethod slot_0 = {"Open", 0, 0 }; + static const QUMethod slot_1 = {"ShowSlides", 0, 0 }; + static const QUMethod slot_2 = {"SetWire", 0, 0 }; + static const QUMethod slot_3 = {"SetShowBlocked", 0, 0 }; + static const QUMethod slot_4 = {"ShowExternalForces", 0, 0 }; + static const QUMethod slot_5 = {"ShowInternalForces", 0, 0 }; + static const QUMethod slot_6 = {"ShowResultForces", 0, 0 }; + static const QUMethod slot_7 = {"Smooth", 0, 0 }; + static const QUMethod slot_8 = {"SavePly", 0, 0 }; + static const QUMethod slot_9 = {"Apply", 0, 0 }; + static const QUMethod slot_10 = {"Extract", 0, 0 }; + static const QUMethod slot_11 = {"Update", 0, 0 }; + static const QUMethod slot_12 = {"Clear", 0, 0 }; + static const QMetaData slot_tbl[] = { + { "Open()", &slot_0, QMetaData::Public }, + { "ShowSlides()", &slot_1, QMetaData::Public }, + { "SetWire()", &slot_2, QMetaData::Public }, + { "SetShowBlocked()", &slot_3, QMetaData::Public }, + { "ShowExternalForces()", &slot_4, QMetaData::Public }, + { "ShowInternalForces()", &slot_5, QMetaData::Public }, + { "ShowResultForces()", &slot_6, QMetaData::Public }, + { "Smooth()", &slot_7, QMetaData::Public }, + { "SavePly()", &slot_8, QMetaData::Public }, + { "Apply()", &slot_9, QMetaData::Public }, + { "Extract()", &slot_10, QMetaData::Public }, + { "Update()", &slot_11, QMetaData::Public }, + { "Clear()", &slot_12, QMetaData::Public } + }; + metaObj = QMetaObject::new_metaobject( + "SimpleGLWidget", parentObject, + slot_tbl, 13, + 0, 0, +#ifndef QT_NO_PROPERTIES + 0, 0, + 0, 0, +#endif // QT_NO_PROPERTIES + 0, 0 ); + cleanUp_SimpleGLWidget.setMetaObject( metaObj ); + return metaObj; +} + +void* SimpleGLWidget::qt_cast( const char* clname ) +{ + if ( !qstrcmp( clname, "SimpleGLWidget" ) ) + return this; + return QGLWidget::qt_cast( clname ); +} + +bool SimpleGLWidget::qt_invoke( int _id, QUObject* _o ) +{ + switch ( _id - staticMetaObject()->slotOffset() ) { + case 0: Open(); break; + case 1: ShowSlides(); break; + case 2: SetWire(); break; + case 3: SetShowBlocked(); break; + case 4: ShowExternalForces(); break; + case 5: ShowInternalForces(); break; + case 6: ShowResultForces(); break; + case 7: Smooth(); break; + case 8: SavePly(); break; + case 9: Apply(); break; + case 10: Extract(); break; + case 11: Update(); break; + case 12: Clear(); break; + default: + return QGLWidget::qt_invoke( _id, _o ); + } + return TRUE; +} + +bool SimpleGLWidget::qt_emit( int _id, QUObject* _o ) +{ + return QGLWidget::qt_emit(_id,_o); +} +#ifndef QT_NO_PROPERTIES + +bool SimpleGLWidget::qt_property( int id, int f, QVariant* v) +{ + return QGLWidget::qt_property( id, f, v); +} + +bool SimpleGLWidget::qt_static_property( QObject* , int , int , QVariant* ){ return FALSE; } +#endif // QT_NO_PROPERTIES diff --git a/apps/test/segmentation3d/partial_container.h b/apps/test/segmentation3d/partial_container.h new file mode 100644 index 00000000..93fd0651 --- /dev/null +++ b/apps/test/segmentation3d/partial_container.h @@ -0,0 +1,53 @@ +#ifndef __PARTIALCONT__ +#define __PARTIALCONT__ + +#include + +template +struct Partial_Container : STL_CONT +{ + + + typedef typename STL_CONT::iterator ite_father; + + typedef ELEM value_type; + +public: +struct iterator{ + + ite_father i; + iterator (){} + iterator (ite_father i_):i(i_){} + + ELEM &operator *(){return *(*i);} + + void operator ++() + { + ///((i!=(STL_CONT::end()))&& da controllare la fine + //while ((*i)->IsInvalid())++i; + ++i; + } + + iterator operator =(const iterator & oth){ + i=oth.i; + return *this; + } + + bool operator ==(const iterator & oth){ + return (i==oth.i); + } + bool operator !=(const iterator & oth){ + return (i!=oth.i); + } + + bool operator <(const iterator & oth){ + return (i +//#include + +#include +#include + +#include +#include + + +#include +#include +#include +#include + +#include +#include +#include + +//#include + + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +class Segmentator{ + +public: + +struct DummyEdge; +struct DummyTetra; +struct MyFace; + +struct MyVertex: public ParticleBasic > +{ +public: + + bool blocked;//optimize after with vertex flags + bool stopped; + + MyVertex() + { + blocked=false; + stopped=false; + Acc()=Point3f(0,0,0); + Vel()=Point3f(0,0,0); + //neeed call of the super class + } + + void UpdateAcceleration() + { + //if ((!IsBlocked(this))&&(!IsStopped(this))) + if ((!blocked)&&(!stopped)) + { + Acc()=(IntForce()+ExtForce())/Mass(); + } + else + { + Acc()=Point3f(0,0,0); + Vel()=Point3f(0,0,0); + } + } + + void Reset() + { + IntForce()=Point3f(0.f,0.f,0.f); + } + + + +}; + +///this class implements the deformable triangle in a mass spring system +struct MyFace : public TriangleMassSpring< vcg::FaceAF > +{ +public: + bool intersected; + float kdihedral; + + MyFace() + { + intersected=false; + } + + void Init ( double k, double mass,float k_dihedral ) + { + __super::Init(k,mass); + kdihedral=k_dihedral; + } + + bool IsActive() + { + return(!(((V(0)->blocked)||(V(0)->stopped))&& + ((V(1)->blocked)||(V(1)->stopped))&& + ((V(2)->blocked)||(V(2)->stopped)))); + } + + bool IsBlocked() + { + return((V(0)->blocked)&&(V(1)->blocked)&&(V(2)->blocked)); + } + + + double DiedralAngle(int edge) + { + MyFace *fopp=FFp(edge); + CoordType norm1=NormalizedNormal(); + CoordType norm2=fopp->NormalizedNormal(); + return (NormalizedNormal()*fopp->NormalizedNormal()); + } + + ///update of the internal forces using the dihedral angle + bool Update ( void ) + { + for (int i=0;i<3;i++) + { + MyFace *fopp=FFp(i); + MyFace *myAddr=fopp->FFp(FFi(i)); + if ((fopp!=0)||(foppP()-V((i+1)%3)->P()).Normalize(); + fopp=FFp(i); + CoordType Ver=(NormalizedNormal()^fopp->NormalizedNormal()).Normalize(); + ScalarType diaedral=DiedralAngle(i); + + if ((Ver*DirEdge)<=0)///convex + { + ScalarType Force=(((-diaedral)+1.f)*kdihedral); + V((i+2)%3)->IntForce()+=NormalizedNormal()*(Force); + V(i)->IntForce()-=NormalizedNormal()*(Force)/2.f; + V((i+1)%3)->IntForce()-=NormalizedNormal()*(Force)/2.f; + } + else ///non-convex + { + ScalarType Force=(((-diaedral)+1.f)*kdihedral); + V((i+2)%3)->IntForce()-=NormalizedNormal()*(Force); + V(i)->IntForce()+=NormalizedNormal()*(Force)/2.f; + V((i+1)%3)->IntForce()+=NormalizedNormal()*(Force)/2.f; + } + } + } + return(__super::Update()); + } +}; + +struct MyTriMesh: public vcg::tri::TriMesh,std::vector >{}; + +typedef Partial_Container,MyVertex> Part_VertexContainer; +typedef Partial_Container,MyFace> Part_FaceContainer; +typedef PDEIntegrator myIntegrator; +typedef Collision_Detector > Collision; + + +public: + Point3f scale; + + //VolumetricDataset d; + MyTriMesh m; + Part_FaceContainer P_Faces; + Part_VertexContainer P_Vertex; + Part_VertexContainer V_Stopped; + myIntegrator *TrINT; + + MyTriMesh::CoordType InitialBarycenter; + + float mass; + float k_elanst; + float k_dihedral; + float edge_size; + int tolerance; + int gray_init; + float time_stamp; + float edge_precision; + + bool end_loop; + bool refined; + + clock_t interval_reinit; + clock_t interval_selfcollision; + + Collision *CollDet; + + //Volume_Dataset_Optimized V; + Volume_Dataset V; + + vcg::Box3 bbox; + + char *inDir; + char *outDir; + + //attention static members + /*int BlockFlag; + int StoppedFlag;*/ + + Segmentator() + { + CollDet=new Collision(m.face); + } + + ~Segmentator() + { + } + +private: + + /////return integer coordinete in volumetric dataset + //Point3i MapToDataset(MyTriMesh::CoordType p) + //{ + // MyTriMesh::ScalarType x=((MyTriMesh::ScalarType)p.V(0)); + // MyTriMesh::ScalarType y=((MyTriMesh::ScalarType)p.V(1)); + // MyTriMesh::ScalarType z=((MyTriMesh::ScalarType)p.V(2)); + // return Point3i((int)p.V(0),(int)p.V(1),(int)p.V(2)); + //} + // + + ///map to space coordinate from dataset coordinates + MyTriMesh::CoordType MapToSpace(Point3i p) + { + MyTriMesh::ScalarType x=((MyTriMesh::ScalarType)p.V(0)); + MyTriMesh::ScalarType y=((MyTriMesh::ScalarType)p.V(1)); + MyTriMesh::ScalarType z=((MyTriMesh::ScalarType)p.V(2)); + return (MyTriMesh::CoordType(x,y,z)); + } + + ///return integer coordinete in volumetric dataset + float getColor(MyTriMesh::CoordType p) + { + + float lx=p.V(0)-(int)p.V(0);//da rivedere bene per lo scale + float ly=p.V(1)-(int)p.V(1);//da rivedere bene per lo scale + float lz=p.V(2)-(int)p.V(2);//da rivedere bene per lo scale + + Point3i base=Point3i((int)p.V(0),(int)p.V(1),(int)p.V(2)); + + float v[8]; + Point3i px; + for (int i=0;i<8;i++) + { + px=base+Point3i((i%2),(i/4),((i/2)%2)); + v[i]=(float)V.getAt(px); + } + + float color=lx*v[1]+v[0]+lz*v[0]*lx-v[0]*lx-ly*v[0]+ly*v[2]-lz*v[0]+ly*v[0]*lx-ly*lx*v[1]-ly*v[2]*lx + -lz*ly*v[0]*lx+lz*ly*lx*v[1]+lz*ly*v[2]*lx-lz*ly*lx*v[3]+lz*ly*lx*v[4]-lz*ly*lx*v[5]-lz*ly* + v[6]*lx+lz*ly*lx*v[7]+ly*lx*v[3]-lz*lx*v[1]+lz*ly*v[0]-lz*ly*v[2]-lz*lx*v[4]+lz*lx*v[5]-lz*ly* + v[4]+lz*ly*v[6]+lz*v[4]; + + return color; + } + + ///maximixe the gradient of the movement + MyTriMesh::CoordType Gradient(MyTriMesh::CoordType p,float h=0.01f) + { + float value=getColor(p); + MyTriMesh::CoordType h0=MyTriMesh::CoordType(h,0,0); + MyTriMesh::CoordType h1=MyTriMesh::CoordType(0,h,0); + MyTriMesh::CoordType h2=MyTriMesh::CoordType(0,0,h); + float dx=(getColor(p+h0)-value)/h; + + /*dx=v[1]+lz*v[0]-v[0]*lx+ly*v[0]-ly*v[1]-ly*v[2] + -lz*ly*v[0]+lz*ly*v[1]+lz*ly*v[2]-lz*ly*v[3]+lz*ly*v[4]-lz*ly*v[5]-lz*ly* + v[6]+lz*ly*v[7]+ly*v[3]-lz*v[1]-lz*v[4]+lz*v[5]-lz*ly*v[4]+lz*ly*v[6]+lz*v[4]; + + dy=-v[0]+v[2]+v[0]*lx-lx*v[1]-v[2]*lx + -lz*v[0]*lx+lz*lx*v[1]+lz*v[2]*lx-lz*lx*v[3]+lz*lx*v[4]-lz*lx*v[5]-lz*v[6]*lx+lz*ly*lx*v[7]+ly*lx*v[3]-lz*lx*v[1]+lz*ly*v[0]-lz*ly*v[2]-lz*lx*v[4]+lz*lx*v[5]-lz*ly* + v[4]+lz*ly*v[6]+lz*v[4];*/ + + float dy=(getColor(p+h1)-value)/h; + float dz=(getColor(p+h2)-value)/h; + MyTriMesh::CoordType ret=MyTriMesh::CoordType(dx,dy,dz); + return (ret); + } + + ///scale the coordinates of a point + MyTriMesh::CoordType Scale(MyTriMesh::CoordType p) + { + MyTriMesh::ScalarType x=(p.V(0))/scale.V(0); + MyTriMesh::ScalarType y=(p.V(1))/scale.V(1); + MyTriMesh::ScalarType z=(p.V(2))/scale.V(2); + return (MyTriMesh::CoordType(x,y,z)); + } + + ///return true if a coordinate is out of limits + bool OutOfLimits(MyTriMesh::CoordType p) + { + Point3f max=Scale(MapToSpace(V.Max())); + Point3f min=Scale(MapToSpace(V.Min())); + Point3f test=(Scale(p)); + + for (int i=0;i<3;i++) + { + if(((test.V(i)>=max.V(i))||(test.V(i)<=min.V(i)))) + return true; + } + return false; + } + + + bool IsBlocked(MyVertex *v) + { + //return ((v->Flags()& BlockFlag!=0)); + return (v->blocked); + } + + void SetBlocked(MyVertex *v) + { + //v->Flags()|= BlockFlag; + v->blocked=true; + //v->SetS();//for refine + } + + void SetBlockedFace(MyFace *f) + { + SetBlocked(f->V(0)); + SetBlocked(f->V(1)); + SetBlocked(f->V(2)); + } + + void SetIntersectedFace(MyFace *f) + { + f->intersected=true; + } + + bool IsStopped(MyVertex *v) + { + //return ((v->Flags()& StoppedFlag!=0)); + return (v->stopped); + } + + void SetStopped(MyVertex *v) + { + //v->Flags()|= StoppedFlag; + v->stopped=true; + V_Stopped.push_back(v); + } + + void ClearStopped(MyVertex *v) + { + //v->Flags()&= ~StoppedFlag; + v->stopped=false; + } + +///re-set physical pararmeters on the mesh +void InitPhysParam(float k_elanst,float mass,float k_dihedral) +{ + for (unsigned int i=0;i(m); + + vcg::tri::UpdateTopology::FaceFace(m); + + /* P_Vertex.clear(); + P_Faces.clear();*/ + + for (unsigned int i=0;i::PerVertexNormalized(m); + } + + +///return true if the gray level of the vertex v differ from graylevel less than tolerance +bool InTolerance(MyTriMesh::VertexType *v) +{ + return (abs(getColor(v->P())-gray_init)P()))-(float)gray_init); + assert(dinstance<=tolerance); + MyTriMesh::CoordType ret=(-v->N()*((dinstance)/(float)tolerance)); + return (ret); +} + +///find the gradient factor +MyTriMesh::CoordType GradientFactor(MyTriMesh::VertexType *v) +{ + MyTriMesh::CoordType value=Gradient(v->P()); + /*float d0=getColor(v->P()+value); + float d1=getColor(v->P()-value); + if ((fabs(d0-(float)gray_init))>(fabs(d1-(float)gray_init))) + return (-value); + else */ + return (value*(gray_init-getColor(v->P()))); +} + +///add the external forces to the deformable mesh +void AddExtForces() +{ + Part_VertexContainer::iterator vi; + + end_loop=true; + for (vi=P_Vertex.begin();viblocked=true; + SetBlocked(&*vi); + if ((!IsBlocked(&*vi))&&(!IsStopped(&*vi))) + { + end_loop=false; + if (!InTolerance(&*vi)) + { + SetBlocked(&*vi); + (*vi).ExtForce()=MyTriMesh::CoordType(0,0,0); + } + else + { + MyTriMesh::CoordType Inflating=(*vi).N(); + MyTriMesh::CoordType Containing0=ContainingForce(&*vi); + //MyTriMesh::CoordType Containing1=GradientFactor(&*vi); + (*vi).ExtForce()=Inflating+Containing0*0.75;/*+Containing1+Containing0*/; + } + } + else + (*vi).ExtForce()=MyTriMesh::CoordType(0,0,0); + } + } +} + +///reinit the partial integration vectors that describe active vertices +void Reinit_PVectors() +{ + V_Stopped.clear(); + P_Vertex.clear(); + MyTriMesh::VertexIterator vi; + + for (vi=m.vert.begin();viIsD())&&(!vi->blocked)) + P_Vertex.push_back(&(*vi)); + if ((!vi->IsD())&&((*vi).stopped)&&(!vi->blocked)) + V_Stopped.push_back(&(*vi)); + } + + P_Faces.clear(); + MyTriMesh::FaceIterator fi; + for (fi=m.face.begin();fiIsBlocked())) + if ((!fi->IsD())&&(!fi->IsBlocked())) + P_Faces.push_back(&(*fi)); + } +} + +///erase the stopped entities from the partial containers +void Refresh_PVectors() +{ + Part_FaceContainer P_FacesAux; + Part_VertexContainer P_VertexAux; + P_FacesAux.clear(); + P_VertexAux.clear(); + + int i=0; + for (i=0;iblocked) + P_VertexAux.push_back(P_Vertex[i]); + } + + for (i=0;iIsBlocked()) + P_FacesAux.push_back(P_Faces[i]); + } + + P_Faces.clear(); + P_Vertex.clear(); + + P_Faces=P_FacesAux; + P_Vertex=P_VertexAux; +} + +///add the new elements on partial vectors when allocate space for new vertices +void AddNewElements(MyTriMesh::VertexIterator vi,MyTriMesh::FaceIterator fi) +{ + while (vi!=m.vert.end()) + { + if (!(*vi).IsD()) + P_Vertex.push_back(&(*vi)); + vi++; + } + while (fi!=m.face.end()) + { + if (!(*fi).IsD()) + P_Faces.push_back(&(*fi)); + fi++; + } +} + +///verify and eventually stop the vertices of the mesh +void VerifyForces() +{ + float proj; + Part_VertexContainer::iterator vi; + for (vi=P_Vertex.begin();viinterval_reinit) + { + time=clock(); + return true; + } + return false; +} + +bool TimeSelfIntersection() +{ + static clock_t time=0; + clock_t elapsedsecs=abs(time-clock()); + if (elapsedsecs>interval_selfcollision) + { + time=clock(); + return true; + } + return false; +} + +///refine the mesh and re-update eventually +void RefineStep(float _edge_size) +{ + MyTriMesh::VertexIterator vinit=m.vert.begin(); + MyTriMesh::FaceIterator finit=m.face.begin(); + MyTriMesh::VertexIterator vend=m.vert.end(); + MyTriMesh::FaceIterator fend=m.face.end(); + + refined=vcg::Refine(m,MidPoint(),_edge_size); + + if (refined) + { + MyTriMesh::VertexIterator vinit2=m.vert.begin(); + MyTriMesh::FaceIterator finit2=m.face.begin(); + + if ((vinit2!=vinit)||(finit2!=finit)) + Reinit_PVectors(); + else + AddNewElements(vend,fend); + + vcg::tri::UpdateNormals::PerVertexNormalized(m); + CollDet->RefreshElements(); + } +} + +///reset vertex position and unblock them +void ReinitPhysicMesh() +{ + Part_FaceContainer::iterator pfi; + + for (pfi=P_Faces.begin();pfiUpdateStep(); + std::vector coll=CollDet->computeSelfIntersection(); + for (std::vector::iterator it=coll.begin();it(MapToSpace(V.Min()),MapToSpace(V.Max())); +} + + +///init the segmentation of the mesh +void InitSegmentation(int color,int tol,float Mass=0.5f,float K_elanst=0.2f,float Dihedral=0.2f,float Time_stamp=0.2f, + float Edge_precision=4.f,clock_t _interval=1000,clock_t _interval2=250, + MyTriMesh::CoordType ScaleFactor=MyTriMesh::CoordType(1.f,1.f,1.f) ) +{ + mass=Mass; + k_elanst=K_elanst; + tolerance=tol; + + interval_reinit=_interval; + interval_selfcollision=_interval2; + + edge_size=16.f; + edge_precision=Edge_precision; + time_stamp=Time_stamp; + k_dihedral=Dihedral; + scale=ScaleFactor; + + + + TrINT= new myIntegrator(P_Faces,P_Vertex); + + TrINT->SetPDESolver(PDESolvers::EULER_METHOD); + + ////caso optimized + ///*V.Resample(inDir,outDir); + + //V.Init(1000,outDir);*/ + //V.Load(inDir); + // + /*bbox=vcg::Box3(MapToSpace(V.Min()),MapToSpace(V.Max()));*/ + + //init the mesh with new + Reinit_PVectors(); + ReinitPhysicMesh(); + + CollDet->Init(bbox.min,bbox.max,5.f); + + +} + +///return the bounding box of the mesh +vcg::Box3 BBox() +{ + return (bbox); +} + +///one step of moving for the deformable object +void Step(float t,float _edge_size) +{ + if (m.face.size()!=0) + { + AddExtForces(); + TrINT->Step(t); + VerifyForces(); + Refresh_PVectors(); + if (end_loop) + { + RefineStep(_edge_size); + ReinitPhysicMesh(); + ClearStopped(); + } + if (TimeSelfIntersection()) + CollisionDetection(); + } +} + +void Smooth() +{ + ScaleLaplacianSmooth(m,2,0.5); +} + +void AutoStep() +{ + refined=false; + Step(time_stamp,edge_size); + //test on 80% of the vertex blocked + if ((((float)P_Vertex.size()/(float)m.vn)<0.2)&&(end_loop)&&(!refined)&&(edge_size>edge_precision)) + { + edge_size/=2.f; + if (edge_size +SegmentForm + + + SegmentForm + + + + 0 + 0 + 1232 + 981 + + + + Segmentation + + + + buttonGroup1 + + + + 10 + 0 + 1030 + 50 + + + + + + + + SlidesButton + + + + 10 + 10 + 80 + 31 + + + + + 10 + + + + Slides + + + true + + + + + ResultButton + + + + 740 + 10 + 110 + 31 + + + + + 10 + + + + ResultForces + + + true + + + + + InternalButton + + + + 590 + 10 + 110 + 31 + + + + + 10 + + + + InternalForces + + + true + + + + + ExternalButton + + + + 420 + 10 + 120 + 31 + + + + + 10 + + + + ExternalForces + + + true + + + + + BlockedButton + + + + 270 + 10 + 110 + 31 + + + + + 10 + + + + BlockedFaces + + + true + + + + + WireButton + + + + 130 + 10 + 100 + 31 + + + + + 10 + + + + Wire + + + true + + + true + + + true + + + + + + buttonGroup2 + + + + 1040 + 0 + 191 + 930 + + + + + + + + SaveButton + + + + 30 + 560 + 140 + 31 + + + + + 10 + + + + SavePly + + + + + SmoothButton + + + + 30 + 520 + 140 + 30 + + + + + 10 + + + + 1 + + + Smooth + + + + + SegmentButton + + + + 30 + 480 + 141 + 31 + + + + + 10 + + + + Extract + + + true + + + + + Color + + + false + + + + 30 + 390 + 70 + 30 + + + + + 10 + + + + LineEditPanel + + + Sunken + + + + + + 0 + + + + + textLabel1_2_2_2_2 + + + + 30 + 370 + 116 + 21 + + + + + 10 + + + + color + + + + + Tolerance + + + + 30 + 330 + 70 + 31 + + + + + 10 + + + + 10 + + + 2 + + + + + textLabel1_2_2_2 + + + + 30 + 310 + 116 + 21 + + + + + 10 + + + + tolerance + + + + + E_size + + + + 30 + 270 + 70 + 31 + + + + + 10 + + + + 4 + + + 1 + + + + + textLabel1_2_2 + + + + 30 + 250 + 116 + 21 + + + + + 10 + + + + minimum edge size + + + + + T_step + + + + 30 + 210 + 70 + 31 + + + + + 10 + + + + 0.2 + + + 3 + + + + + textLabel1_2 + + + + 30 + 190 + 90 + 21 + + + + + 10 + + + + initial time step + + + + + D_angle + + + + 30 + 150 + 70 + 31 + + + + + 10 + + + + 0.2 + + + 3 + + + + + textLabel1_4 + + + + 30 + 130 + 150 + 21 + + + + + 10 + + + + dihedral angle constant + + + + + K_elanst + + + + 30 + 90 + 70 + 31 + + + + + 10 + + + + LineEditPanel + + + Sunken + + + 0.2 + + + 3 + + + + + textLabel1 + + + + 30 + 70 + 131 + 21 + + + + + 10 + + + + spring constant + + + + + M_particles + + + + 30 + 30 + 70 + 31 + + + + + 10 + + + + 2 + + + 0.5 + + + 3 + + + + + textLabel1_3 + + + + 30 + 10 + 131 + 21 + + + + + 10 + + + + mass of particles + + + + + ApplyButton + + + + 30 + 440 + 141 + 31 + + + + + 10 + + + + Apply + + + + + ClearButton + + + + 30 + 600 + 141 + 31 + + + + + 10 + + + + Clear + + + + + + simpleGLWidget1 + + + + 10 + 70 + 1030 + 880 + + + + + + + MenuBar + + + + + + + + + + + + + + SimpleGLWidget +
D:/sf/apps/test/segmentation3d/simpleglwidget.h
+ + -1 + -1 + + 0 + + 5 + 5 + 0 + 0 + + image0 + ShowSlides() + SetWire() + SetShowBlocked() + ShowExternalForces() + ShowInternalForces() + ShowResultForces() + Smooth() + SavePly() + Extract() + Apply() + Clear() + slot() + Open() +
+
+ + + + fileOpenAction + + + false + + + + + + &Open... + + + &Open... + + + Ctrl+O + + + + + fileSaveAction + + + + + + Save + + + &Save + + + Ctrl+S + + + + + Segmentation + + + Save As + + + Save &As... + + + + + + + + fileExitAction + + + Exit + + + E&xit + + + + + + + + fileOpennew_itemAction + + + new item + + + new item + + + + + + 89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154789cad94514c5b5518c77fe7dc4b7b4b6150bb96324418ca32358bee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d6a78d0b027b3cd07d9e68c81c625a6c139408a4384f416100aed6d4b7bdb7b8e0fc0921a70c6ed7b3ae7e43bbff3fffedfc927e2f138bbd1dbdbab7902118fc785d8058f8d8de9aeae2e72b91cb66de338ce7f82e47239666767492412b8aefbf0dcdc553a323242f4501d918e2d3a8f15a9784584100809a609526eafd1a0f54e6142e029c5c21f3ef41583bb77a805efbe1ce9d86279e32619678eaab7853fa0f02a16abb64166ad0cdac75307eb3874b84cb0a14aa5a24108cc0688c48c9a4a1e826ddbe6f0b12219678e8ace610502ccdfafe3f68d3c33bf6c01c59dcc209d472c4e0d35d2f3ba81d205d06005e4de60c77170bd2255af80150870f70e8c0eaf009260a349577714e913a4175d16925b5cbe50607931cc3b677c68ca28a5f7066f5b26f00760febec9e8f032a0e81b68a17fc0201415989647a9d8c4c498cbe8f05f5cff3a4d4bac8bfe210b290b35e01afd428257b1b875cd01aaf4bd1de5dd0fea688e1530ad1c1bab16b7af17393558cf997311c0e49bafd670d6258621f6576c9ab09a3248fe5ae6c08103f49f36517213d33070369bf8e2529ee9c90ceb2b2eef7f14617c2c48722a4b7226845143fa87622905ebeb6514253a9eb5084504a66950c88618bee0303d99217cb09e9ed71a09369538fa523d00e9a50a42eed3bc6d8f41281fa0903e8561796cac86f8f2b33c33930ea0f0fb4d5adbeb30ad22866ffbbad226d2a805d7ee0484220208925aaa50deaa67e27b97e9c90ccdcdf5c462cdd8a94d2e7e62f3603244ea410989a4ed191f52a8fd156b056d9d553a9e0bf0e7ef45c6bf7339fd5e90ec7a88575e6d20d6e6e7e2a755ec854dce7fb8885b2cd014f6f3c2714d3a550bae55ac35c1068fb7061b00b87a7995899b25ce9e0b73e24d8fae97b37c7cbe9370b499fce6066eb54adf6098f6ee2a9a7ff9c70841a5023d270deca510d746537c7e29cdf8ad20475fb4307c82d4fc324ec6859d66fdfc6381e44014b36e9fe6e572393ca54068aa22cfd0598b686b3737aeae90bc9725796f0350802414b6e81b7c9a9f7e70708a2e6e5991cfeee3f1ecec2c0b0b3e8c068142a2a8d23728397132c6dc6f2e2b8b0a8da4b5ddc7f3c735ed47146f0cb4502983693a4c25ca7b83138904fa8a412466e00f48b4271086c2901263676c4a6990b615b6ade15b85694af239984a94585bf6f606bbae5b334f1f37e4a3531e031c8fc7c5a312ff17f849c3e3f1b8f81b8be6900aca9b61c90000000049454e44ae426082 + + + + + SlidesButton + pressed() + simpleGLWidget1 + ShowSlides() + + + WireButton + pressed() + simpleGLWidget1 + SetWire() + + + BlockedButton + pressed() + simpleGLWidget1 + SetShowBlocked() + + + ExternalButton + pressed() + simpleGLWidget1 + ShowExternalForces() + + + InternalButton + pressed() + simpleGLWidget1 + ShowInternalForces() + + + ResultButton + pressed() + simpleGLWidget1 + ShowResultForces() + + + SaveButton + clicked() + simpleGLWidget1 + SavePly() + + + SmoothButton + pressed() + simpleGLWidget1 + Smooth() + + + SegmentButton + pressed() + simpleGLWidget1 + Extract() + + + ApplyButton + pressed() + simpleGLWidget1 + Apply() + + + ClearButton + pressed() + simpleGLWidget1 + Clear() + + + fileOpenAction + activated() + simpleGLWidget1 + Open() + + + fileSaveAction + activated() + simpleGLWidget1 + SavePly() + + + + + + simpleglwidget.h + +
diff --git a/apps/test/segmentation3d/simpleglwidget.cpp b/apps/test/segmentation3d/simpleglwidget.cpp new file mode 100644 index 00000000..4a2983fd --- /dev/null +++ b/apps/test/segmentation3d/simpleglwidget.cpp @@ -0,0 +1,418 @@ +#include +#include +#include +#include +#include + +extern Segmentator *s; + +SimpleGLWidget::SimpleGLWidget( QWidget * parent, const char * name, const QGLWidget * shareWidget, WFlags f ): +QGLWidget(parent, name) +{ + + ///grabKeyboard(); + _showslides=false; + blocked=false; + wire=true; + extForces=false; + intForces=false; + resultForces=false; + continue_int=false; + _numslide=0; + Track.center=Point3f(0,0,0); + Track.Reset(); + Track.radius= 100; + zoom=1; +} + +void SimpleGLWidget::SaveMatrix() +{ + glGetDoublev(GL_PROJECTION_MATRIX ,projection); + glGetDoublev(GL_MODELVIEW_MATRIX ,modelMatrix); + glGetIntegerv(GL_VIEWPORT,viewport); +} + +void SimpleGLWidget::LoadMatrix() +{ + glMatrixMode(GL_PROJECTION); + glLoadMatrixd(projection); + glMatrixMode(GL_MODELVIEW); + glLoadMatrixd(modelMatrix); +} + + +void SimpleGLWidget::drawSlide() +{ +glBegin(GL_QUADS); +for (int x=0;x<((s->V.dimX())-1);x++) + for (int y=0;y<((s->V.dimY())-1);y++) + { + glNormal(Point3d(0,0,1)); + Point3 p0=Point3(x,y,_numslide); + double color=((double)s->V.getAt(p0))/256.f; + glColor3d(color,color,color); + glVertex(p0); + + Point3 p1=Point3(x+1,y,_numslide); + color=((double)s->V.getAt(p1))/256.f; + glColor3d(color,color,color); + glVertex(p1); + + Point3 p2=Point3(x+1,y+1,_numslide); + color=((double)s->V.getAt(p2))/256.f; + glColor3d(color,color,color); + glVertex(p2); + + Point3 p3=Point3(x,y+1,_numslide); + color=((double)s->V.getAt(p3))/256.f; + glColor3d(color,color,color); + glVertex(p3); + } +glEnd(); +} + +void drawForces(Segmentator::Part_VertexContainer *pv,int typeForce) +{ +Segmentator::Part_VertexContainer::iterator vi; +glPushAttrib(GL_ALL_ATTRIB_BITS); +glLineWidth(0.3); +glDisable(GL_NORMALIZE); +glDisable(GL_LIGHTING); +glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); + +if (typeForce==0) + glColor3d(1,0,0); +else +if (typeForce==1) + glColor3d(0,0,1); +else +if (typeForce==2) + glColor3d(0,1,0); + +for (vi=pv->begin();viend();vi++) +{ + glBegin(GL_LINE_LOOP); + vcg::glVertex((*vi).P()); + if (typeForce==0) + vcg::glVertex((*vi).P()+((*vi).IntForce()*4.f)); + else + if (typeForce==1) + vcg::glVertex((*vi).P()+((*vi).ExtForce()*4.f)); + else + if (typeForce==2) + vcg::glVertex((*vi).P()+(((*vi).ExtForce()+(*vi).IntForce())*4.f)); + glEnd(); +} +glPopAttrib(); +} + +void SimpleGLWidget::Save() +{ + QString filename = QFileDialog::getSaveFileName("prova.ply", + "Ply files (*.ply)", + this, + "save file dialog", + "Choose a filename to save under" ); + if (filename!=NULL) + { + const char *path=filename.ascii(); + vcg::tri::io::ExporterPLY::Save(s->m,path); + } + +} + +bool TimeSelfIntersection() +{ + static clock_t time=0; + clock_t elapsedsecs=abs(time-clock()); + if (elapsedsecs>500) + { + time=clock(); + return true; + } + return false; +} + +//void SimpleGLWidget::WriteInfo() +//{ +// +// if (s!=0) +// { +// +// glPushAttrib(0xffffffff); +// +// glEnable(GL_BLEND); +// glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA); +// glEnable(GL_LIGHTING); +// glEnable(GL_NORMALIZE); +// glEnable(GL_COLOR_MATERIAL); +// glDisable(GL_CLIP_PLANE0); +// glColor4d(0.7,0,0.7,0.6); +// +// glDepthRange(0.0,0.1); +// +// glBegin(GL_QUADS); +// glVertex3d(-0.5,-0.5,0); +// glVertex3d(-0.5,-0.3,0); +// glVertex3d(0.5,-0.3,0); +// glVertex3d(0.5,-0.5,0); +// glEnd(); +// +// renderText( (width() - 10) / 2, 15, "a" ); +// +// QFont f( "arial", 12 ); +// QFontMetrics fmc( f ); +// glColor3d(1,1,1); +// +// QString str=""; +// int level=0; +// +// glDisable( GL_LIGHTING ); +// glDisable( GL_TEXTURE_2D ); +// +// level++; +// str.sprintf( "Triangles : %i Vertex: %i ",s->m.fn,s->m.vn); +// renderText( 20, height() - level*20, str, f ); +// } +//} + +void SimpleGLWidget::SmoothMesh() +{ + s->Smooth(); +} + +void SimpleGLWidget::glDraw(){ + + glClearColor(0.2,0.2,0.2,1); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45,1,0.01,20); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(0,0,1,0,0,0,0,10,0); + + if (s!=0){ + + glPushMatrix(); + if (_showslides) + { + vcg::Point3f p=Point3f((float)s->BBox().Center().V(0),(float)s->BBox().Center().V(1),(float)s->BBox().Center().V(2)); + Track.radius=s->BBox().Diag(); + Track.GetView(); + Track.Apply(); + Track.Draw(); + glScalef(1/s->BBox().Diag(),1/s->BBox().Diag(),1/s->BBox().Diag()); + glScalef(GLfloat(zoom),GLfloat(zoom),GLfloat(zoom)); + glTranslate(-p); + //save transformation matrixes + SaveMatrix(); + } + else + { + vcg::tri::UpdateBounding::Box(s->m); + vcg::Point3f p=s->m.bbox.Center(); + Track.radius=s->m.bbox.Diag(); + Track.GetView(); + Track.Apply(); + Track.Draw(); + glScalef(1/s->m.bbox.Diag(),1/s->m.bbox.Diag(),1/s->m.bbox.Diag()); + glScalef(GLfloat(zoom),GLfloat(zoom),GLfloat(zoom)); + glTranslate(-p); + } + + glEnable(GL_NORMALIZE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_COLOR_MATERIAL); + if (_showslides) + drawSlide(); + + if (intForces) + drawForces(&s->P_Vertex,0); + if (extForces) + drawForces(&s->P_Vertex,1); + if (resultForces) + drawForces(&s->P_Vertex,2); + + //draw faces + glEnable(GL_NORMALIZE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_COLOR_MATERIAL); + + Segmentator::MyTriMesh::FaceIterator fi; + + + if (wire) + { + glDisable(GL_NORMALIZE); + glDisable(GL_LIGHTING); + glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); + } + else + glPolygonMode(GL_FRONT,GL_FILL); + + int i=0; + glBegin(GL_TRIANGLES); + for (fi=s->m.face.begin();fim.face.end();fi++) + { + glColor3d(0.4,0.8,0.8); + if (fi->intersected) + glColor3d(1.f,0,0); + + if (((blocked)&&(!fi->IsBlocked()))||(!blocked)) + { + + if (!wire) + vcg::glNormal(fi->Normal()); + + vcg::glVertex(fi->V(0)->P()); + vcg::glVertex(fi->V(1)->P()); + vcg::glVertex(fi->V(2)->P()); + } + } + glEnd(); + + glPopMatrix(); + //WriteInfo(); + + } + QGLWidget::glDraw(); +} + +///open the directiry and initialize dataset +void SimpleGLWidget::OpenDirectory() +{ + QString filename = QFileDialog::getExistingDirectory( + ".", + this, + "open file dialog" + "Choose a Directory" ); + if (filename!=NULL) + { + const char *path=filename.ascii(); + char *p=(char*)path; + s->LoadFromDir(p,"prova.txt"); + } +} + +void SimpleGLWidget::resizeGL( int w, int h ) + { + // setup viewport, projection etc.: + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + float ratio=(float)w/(float)h; + gluPerspective(45,ratio,1,20); + _W=w; + _H=h; + glViewport (0, 0, (GLsizei) w, (GLsizei) h); + glMatrixMode (GL_MODELVIEW); + repaint(); + + } + +void SimpleGLWidget::ClearMesh() +{ + s->m.Clear(); + repaint(); +} + + +void SimpleGLWidget::mousePressEvent ( QMouseEvent * e ) +{ + if (e->button()==Qt::LeftButton ) + Track.MouseDown(e->x(),_H-e->y(),vcg::Trackball::BUTTON_LEFT); + else + //test mass spring model + if ((e->button()==Qt::RightButton)&&(_showslides)) + { + float winz; + double x; + double y; + double z; + //LoadMatrix(); + glReadPixels(e->x(),_H-e->y(),1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&winz); + gluUnProject(e->x(),_H-e->y(),winz,modelMatrix,projection,viewport,&x,&y,&z); + s->SetInitialBarycenter(Point3f(x,y,_numslide)); + QString color=""; + color.sprintf("%i",s->gray_init); + //w->Color->text()=color; + SetExtractionParameters(); + repaint(); + } + //vcg::tri::UpdateBounding::Box(s->m); +} + +void SimpleGLWidget::wheelEvent(QWheelEvent *e) +{ + if (!_showslides) + { + zoom+=e->delta()/120.f; + repaint(); + } + else + { + int oldnum=_numslide; + _numslide+=e->delta()/120.f; + if ((_numslide<0)||(_numslide>=s->V.dimZ())) + _numslide=oldnum; + } + + repaint(); +} + +void SimpleGLWidget::mouseReleaseEvent(QMouseEvent * e ) + { + Track.MouseUp(e->x(),_H-e->y(),vcg::Trackball::BUTTON_LEFT); + repaint(); + } + +void SimpleGLWidget::Step() + { + if ((s!=0)&&(continue_int)) + { + s->AutoStep(); + repaint(); + } + } + +void SimpleGLWidget::SetExtractionParameters() + { + float mass=atof(w->M_particles->text()); + float k_elanst=atof(w->K_elanst->text()); + float dihedral=atof(w->D_angle->text()); + float timestep=atof(w->T_step->text()); + float edge=atof(w->E_size->text()); + float tolerance=atof(w->Tolerance->text()); + //int color =atoi(w->Color->text()); + ///to modify + s->InitSegmentation(s->gray_init,tolerance,mass,k_elanst,dihedral,timestep,edge); + } + +void SimpleGLWidget::mouseMoveEvent ( QMouseEvent * e ) + { + Track.MouseMove(e->x(),_H-e->y()); + repaint(); + } + + +void SimpleGLWidget::initializeGL(){ + + GLfloat f[4]={0.2,0.2,0.2,1.f}; + GLfloat p[4]={3,3,5,0}; + glLightfv(GL_LIGHT0, GL_AMBIENT,f); + glLightfv(GL_LIGHT1, GL_POSITION,p); + glLightfv(GL_LIGHT1, GL_DIFFUSE,f); + glLightfv(GL_LIGHT1, GL_SPECULAR,f); + + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_LIGHTING); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glPolygonMode(GL_FRONT,GL_FILL); + glEnable(GL_BACK); + glCullFace(GL_BACK); + + } diff --git a/apps/test/segmentation3d/simpleglwidget.h b/apps/test/segmentation3d/simpleglwidget.h new file mode 100644 index 00000000..59603e8e --- /dev/null +++ b/apps/test/segmentation3d/simpleglwidget.h @@ -0,0 +1,135 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class SimpleGLWidget: public QGLWidget{ + +Q_OBJECT + +private : + int _H; + int _W; + vcg::Trackball Track; + double zoom; + GLdouble projection[16]; + GLdouble modelMatrix[16]; + GLint viewport[4]; + bool _showslides; + int _numslide; + bool wire; + bool blocked; + bool extForces; + bool intForces; + bool resultForces; + bool continue_int; + + //vcg::GlTrimesh *Wrap; + +public: + SegmentForm *w; + SimpleGLWidget( QWidget * parent = 0, const char * name = 0, const QGLWidget * shareWidget = 0, WFlags f = 0 ); + + virtual void glDraw(); + //virtual void paintEvent ( QPaintEvent * ) ; + void resizeGL( int w, int h ); + virtual void mousePressEvent ( QMouseEvent * e ); + virtual void mouseReleaseEvent(QMouseEvent * e ); + virtual void mouseMoveEvent ( QMouseEvent * e ); + virtual void wheelEvent ( QWheelEvent * e ); + //virtual void keyPressEvent(QKeyEvent *k); + virtual void initializeGL(); + virtual void SaveMatrix(); + virtual void Save(); + void LoadMatrix(); + void drawSlide(); + void SmoothMesh(); + void Step(); + void SetExtractionParameters(); + void WriteInfo(); + void ClearMesh(); + void OpenDirectory(); + + + //virtual void keyPressEvent(QKeyEvent *qk); + + public slots: + + void Open() + { + OpenDirectory(); + } + + void ShowSlides() + { + _showslides=!_showslides; + repaint(); + } + + void SetWire() + { + wire=!wire; + repaint(); + } + + void SetShowBlocked() + { + blocked=!blocked; + repaint(); + } + + void ShowExternalForces() + { + extForces=!extForces; + repaint(); + } + + void ShowInternalForces() + { + intForces=!intForces; + repaint(); + } + + void ShowResultForces() + { + resultForces=!resultForces; + repaint(); + } + + void Smooth() + { + SmoothMesh(); + repaint(); + } + + void SavePly() + { + Save(); + } + + void Apply() + { + SetExtractionParameters(); + } + + void Extract() + { + continue_int=!continue_int; + } + + void Update() + { + Step(); + } + + void Clear() + { + ClearMesh(); + } +}; \ No newline at end of file diff --git a/apps/test/segmentation3d/volume_dataset.h b/apps/test/segmentation3d/volume_dataset.h new file mode 100644 index 00000000..76f219d7 --- /dev/null +++ b/apps/test/segmentation3d/volume_dataset.h @@ -0,0 +1,489 @@ + +#include +#include +#include +#include +#include +#include + +#define LimX 512 +#define LimY 512 +#define LimZ 240 + +#define dimXCell 20 +#define dimYCell 20 +#define dimZCell 20 + +#define TLBx 30 +#define TLBy 30 +#define TLBz 30 + + +template +class Volume_Dataset_Optimized{ + +public: + + Volume_Dataset_Optimized(){pFile=0;}; + ~Volume_Dataset_Optimized(){}; + +private: + class Cell + { + public: + + void Clear() + { + for (int i=0;itimestamp); + } + + ///operatorn to perform sorting + inline bool operator ==(const Cell &c) + { + return (c.timestamp==timestamp); + } + Point3i index; + int timestamp; + }; + + + + typedef typename std::list StackType; + typedef typename StackType::iterator IteStack; + + ///the class of grid of iterator to stack structure (corrispondence grid - stack) + struct TLBelem + { + private: + IteStack StackPoint; + + public: + + inline IteStack & I() + { + return StackPoint; + } + + bool inMem; + }; + + FILE * pFile; + StackType CurrStack; + + TLBelem TLB[TLBx][TLBy][TLBz]; + Cell buffer[TLBx][TLBy] ; + + int n_element; + int max_element; + int timestamp; + + int lx; + int ly; + int lz; + int TLBdx; + int TLBdy; + int TLBdz; + + int timesort; + + void SortStack() + { + /*std::sort(CurrStack.begin(),CurrStack.end()); + timestamp=0; + for (IteStack i=CurrStack.begin();i!=CurrStack.end();i++) + (*i).timestamp=0;*/ + } + + ///allocate momory for the buffer + void InitBuffer(Cell _buffer[TLBx][TLBy]) + { + for (int j=0;j GetCoordinate(int x,int y, int z) + { + int xd=(int) x/dimXCell; + int yd=(int) y/dimYCell; + int zd=(int) z/dimZCell; + + int xx= x%dimXCell; + int yy= y%dimYCell; + int zz= z%dimZCell; + + return (std::pair (Point3i(xd,yd,zd),Point3i(xx,yy,zz))); + } + + ///add an element to the structure + void Add(Cell _buffer[TLBx][TLBy],int x, int y, int z, ScalarType value) + { + assert(value<256); + std::pair coords=GetCoordinate(x,y,z); + Point3i cell=coords.first; + Point3i inter=coords.second; + _buffer[cell.V(0)][cell.V(1)].Data[inter.V(0)][inter.V(1)][inter.V(2)]=value; + } + + ///store a cell in the file + void SaveCell(Cell &cell) + { + int size_unit=sizeof( ScalarType ); + int dim=dimXCell*dimYCell*dimZCell; + int numwritten = fwrite(cell.Data, size_unit,dim,pFile ); + } + + ///save to file the current buffer + void SwapBuffer(Cell _buffer[TLBx][TLBy]) + { + for (int x=0;x=256) + return true; + return false; + } + +public: + + ///build and save the strucure made fo blocks + void Resample(char *path,char *_newFile) + { + pFile=fopen (_newFile,"w+b"); + + //std::vector buffer; + /*Cell buffer[TLBx][TLBy] ;*/ + + //load first one image to see dimensions + QImage qI=QImage(); + QDir Qd=QDir(path); + QString qformat; + QString Path=QString(path); + Qd.setNameFilter("*.jpg"); + int levels=Qd.count(); + + Qd.setSorting(QDir::Name); + QString PathFile=Path; + + if (PathFile.right(1)!="/") + PathFile.append("/"); + + PathFile.append(Qd[0]); + bool b=qI.load(PathFile,qformat); + + Resize(qI.width(),qI.height(),levels); + + InitBuffer(buffer); + + for (int z=0;ztimesort) + { + time=clock(); + return true; + } + return false; + } + + inline Point3i Min()//to change in case of difefrent space between sections + {return Point3i(0,0,0);} + + inline Point3i Max()//to change in case of difefrent space between sections + {return Point3i(lx,ly,lz);} + + ///return the x dimension of the dataset + inline int dimX() + {return lx;} + + ///return the y dimension of the dataset + inline int dimY() + {return ly;} + + ///return the z dimension of the dataset + inline int dimZ() + {return lz;} + + + ///return the lenght of the diagonal + inline float Diag() + { + Point3f diag=Point3f((float) _X,(float) _Y,(float) _Z); + return (diag.Norm()); + } + + /////erase the element not used for long time + //void EraseLastUsed() + //{ + // if (TimeSort()) + // SortStack(); + + // int mint=TLB[0][0][0].timestamp; + // Point3i minElem=Point3i(0,0,0); + + // for(int z=0;z=0)&&(p.V(1)>=0)&&(p.V(2)>=0)); + + std::pair co=GetCoordinate(p.V(0),p.V(1),p.V(2)); + Point3i cell=co.first; + Point3i inter=co.second; + TLBelem e=TLB[cell.V(0)][cell.V(1)][cell.V(2)]; + if (e.inMem)///the element is in the buffer + { + IteStack i=e.I(); + ScalarType ret=(*i).Data[inter.V(1)][inter.V(0)][inter.V(2)]; + timestamp++; + (*i).timestamp=timestamp; + return (ret); + } + else///element fault, must load from file /// + { + //insert new element in the TLB table + Cell c=loadFromFile(cell); + CurrStack.push_front(c); + TLB[cell.V(0)][cell.V(1)][cell.V(2)].I()=CurrStack.begin(); + TLB[cell.V(0)][cell.V(1)][cell.V(2)].inMem=true; + (*CurrStack.begin()).timestamp=timestamp; + n_element++; + ///if the number of element is the meximum , then erase one with second chanche algorithm + if (n_element>=max_element) + { + if (TimeSort()) + SortStack(); + CurrStack.pop_back(); + n_element--; + } + ScalarType ret=(*CurrStack.begin()).Data[inter.V(1)][inter.V(0)][inter.V(2)]; + return ret; + } + } + + + + +}; + + +template +class Volume_Dataset{ + +public: + + Volume_Dataset(){}; + ~Volume_Dataset(){}; + + ScalarType Data[LimX][LimY][LimZ] ; + + int lx; + int ly; + int lz; + + + ///set total size of the dataset + void Resize(int _lx,int _ly,int _lz) + { + lx=_lx; + ly=_ly; + lz=_lz; + } + +public: + + ///build and save the strucure made fo blocks + void Load(char *path) + { + //load first one image to see dimensions + QImage qI=QImage(); + QDir Qd=QDir(path); + QString qformat; + QString Path=QString(path); + Qd.setNameFilter("*.jpg"); + int levels=Qd.count(); + + Qd.setSorting(QDir::Name); + QString PathFile=Path; + + if (PathFile.right(1)!="/") + PathFile.append("/"); + + PathFile.append(Qd[0]); + bool b=qI.load(PathFile,qformat); + + Resize(qI.width(),qI.height(),levels); + + + for (int z=0;z=0)&&(p.V(1)>=0)&&(p.V(2)>=0)); + return (Data[p.V(0)][p.V(1)][p.V(2)]); + } + +};