Commit a0bae45e authored by Pierre Kraemer's avatar Pierre Kraemer

Merge cgogn:~cgogn/CGoGN

parents 9f23310e 69653d4f
......@@ -31,6 +31,8 @@
#include "Algo/Import/import.h"
#include "Algo/Geometry/volume.h"
#include "Utils/chrono.h"
PFP::MAP myMap;
VertexAttribute<PFP::VEC3> position ;
......@@ -128,6 +130,82 @@ void MyQT::slider_released()
}
void MyQT::cb_Open()
{
std::string filters("all (*.*);; trian (*.trian);; ctm (*.ctm);; off (*.off);; ply (*.ply)") ;
std::string filename = selectFile("Open Mesh", "", filters) ;
if (filename.empty())
return ;
myMap.clear(true);
std::vector<std::string> attrNames ;
size_t pos = filename.rfind("."); // position of "." in filename
std::string extension = filename.substr(pos);
if(extension == std::string(".tet"))
{
if(!Algo::Import::importTet<PFP>(myMap,filename,attrNames))
{
CGoGNerr << "could not import " << filename << CGoGNendl ;
return;
}
else
position = myMap.getAttribute<PFP::VEC3, VERTEX>(attrNames[0]) ;
}
if(extension == std::string(".node"))
{
if(!Algo::Import::importMeshV<PFP>(myMap, filename, attrNames, Algo::Import::ImportVolumique::NODE))
{
std::cerr << "could not import " << filename << std::endl ;
return ;
}
else
position = myMap.getAttribute<PFP::VEC3,VERTEX>(attrNames[0]) ;
}
if(extension == std::string(".off"))
{
if(!Algo::Import::importMeshToExtrude<PFP>(myMap, filename, attrNames))
{
std::cerr << "could not import " << filename << std::endl ;
return ;
}
else
{
position = myMap.getAttribute<PFP::VEC3, VERTEX>(attrNames[0]) ;
myMap.closeMap();
}
}
color = myMap.addAttribute<PFP::VEC3, VOLUME>("color");
TraversorCell<PFP::MAP, VOLUME> tra(myMap);
float maxV = 0.0f;
for (Dart d = tra.begin(); d != tra.end(); d = tra.next())
{
float v = Algo::Geometry::tetrahedronVolume<PFP>(myMap, d, position);
color[d] = PFP::VEC3(v,0,0);
if (v>maxV)
maxV=v;
}
for (unsigned int i = color.begin(); i != color.end(); color.next(i))
{
color[i][0] /= maxV;
color[i][2] = 1.0f - color[i][0];
}
SelectorDartNoBoundary<PFP::MAP> nb(myMap);
m_topo_render->updateData<PFP>(myMap, position, 0.8f, 0.8f, 0.8f, nb);
m_explode_render->updateData<PFP>(myMap, position, color);
updateGL() ;
}
void MyQT::cb_initGL()
{
// choose to use GL version 2
......@@ -415,6 +493,24 @@ int main(int argc, char **argv)
dock.slider_explode_face->setValue(80);
sqt.clipping_onoff(true);
Utils::Chrono ch;
std::cout << "Compute Volume ->"<< std::endl;
ch.start();
float vol = Algo::Geometry::totalVolume<PFP>(myMap, position);
vol += Algo::Geometry::totalVolume<PFP>(myMap, position);
vol += Algo::Geometry::totalVolume<PFP>(myMap, position);
vol += Algo::Geometry::totalVolume<PFP>(myMap, position);
std::cout << ch.elapsed()<< " ms val="<<vol<< std::endl;
ch.start();
vol = Algo::Geometry::Parallel::totalVolume<PFP>(myMap, position);
vol += Algo::Geometry::Parallel::totalVolume<PFP>(myMap, position);
vol += Algo::Geometry::Parallel::totalVolume<PFP>(myMap, position);
vol += Algo::Geometry::Parallel::totalVolume<PFP>(myMap, position);
std::cout << ch.elapsed()<< " ms // val="<<vol<< std::endl;
// et on attend la fin.
return app.exec();
}
......@@ -118,9 +118,10 @@ public:
protected:
void cb_redraw();
void cb_initGL();
void cb_mouseMove(int buttons, int x, int y);
void cb_mousePress(int button, int x, int y);
void cb_mouseRelease(int button, int x, int y);
void cb_mouseMove(int buttons, int x, int y);
void cb_mousePress(int button, int x, int y);
void cb_mouseRelease(int button, int x, int y);
void cb_Open();
// slots locaux
......
......@@ -98,8 +98,8 @@ target_link_libraries( tuto_histo
# exemple: BOOST_LIBS(boost_lib_lists "boost_thread-mt;boost_iostreams-mt")
#BOOST_LIBS(boost_lib_lists "boost_thread-mt")
#QT4_WRAP_CPP(tuto_mt_moc tuto_mt.h)
#add_executable( tuto_mt tuto_mt.cpp ${tuto_mt_moc})
#target_link_libraries( tuto_mt
# ${CGoGN_LIBS_D} ${CGoGN_EXT_LIBS} ${Boost_THREAD_LIBRARY})
QT4_WRAP_CPP(tuto_mt_moc tuto_mt.h)
add_executable( tuto_mt tuto_mt.cpp ${tuto_mt_moc})
target_link_libraries( tuto_mt
${CGoGN_LIBS_D} ${CGoGN_EXT_LIBS} ${Boost_THREAD_LIBRARY})
......@@ -32,9 +32,7 @@
#include "Algo/Render/GL2/topo3Render.h"
#include "Algo/Render/SVG/mapSVGRender.h"
//#include "Topology/generic/traversor3.h"
//#include "Topology/generic/traversor3.h"
#include "Topology/generic/traversorGen.h"
#include "Topology/generic/traversorFactory.h"
#include "Algo/Render/GL2/drawerCells.h"
......@@ -214,7 +212,7 @@ void MyQT::traverse2()
{
Algo::Render::drawerCell<PFP>(VERTEX+m_second2, m_drawer, myMap, m_selected, position, m_expl);
m_drawer.color3f(1.0f,0.0f,0.0f);
Traversor<PFP::MAP>* tra = Traversor<PFP::MAP>::createIncident(myMap, m_selected, 2, VERTEX+m_second2, VERTEX+m_first2);
Traversor<PFP::MAP>* tra = TraversorFactory<PFP::MAP>::createIncident(myMap, m_selected, 2, VERTEX+m_second2, VERTEX+m_first2);
for (Dart d=tra->begin(); d != tra->end(); d= tra->next())
m_affDarts.push_back(d);
Algo::Render::drawerCells<PFP>(VERTEX+m_first2, m_drawer, myMap, m_affDarts, position, m_expl);
......@@ -223,7 +221,7 @@ void MyQT::traverse2()
{
Algo::Render::drawerCell<PFP>(VERTEX+m_first2, m_drawer, myMap, m_selected, position, m_expl);
m_drawer.color3f(1.0f,0.0f,0.0f);
Traversor<PFP::MAP>* tra = Traversor<PFP::MAP>::createAdjacent(myMap, m_selected, 2, VERTEX+m_first2, VERTEX+m_second2);
Traversor<PFP::MAP>* tra = TraversorFactory<PFP::MAP>::createAdjacent(myMap, m_selected, 2, VERTEX+m_first2, VERTEX+m_second2);
for (Dart d = tra->begin(); d != tra->end(); d = tra->next())
m_affDarts.push_back(d);
Algo::Render::drawerCells<PFP>(VERTEX+m_first2, m_drawer, myMap, m_affDarts, position, m_expl);
......@@ -286,7 +284,7 @@ void MyQT::traverse3()
dynamicMarkOrbit(VERTEX+m_second3);
m_drawer.color3f(1.0f,0.0f,0.0f);
Traversor<PFP::MAP>* tra = Traversor<PFP::MAP>::createIncident(myMap,m_selected, 3, VERTEX+m_second3, VERTEX+m_first3);
Traversor<PFP::MAP>* tra = TraversorFactory<PFP::MAP>::createIncident(myMap,m_selected, 3, VERTEX+m_second3, VERTEX+m_first3);
for (Dart d = tra->begin(); d != tra->end(); d = tra->next())
{
m_affDarts.push_back(d);
......@@ -306,7 +304,7 @@ void MyQT::traverse3()
dynamicMarkOrbit(VERTEX+m_first3);
m_drawer.color3f(1.0f,0.0f,0.0f);
Traversor<PFP::MAP>* tra = Traversor<PFP::MAP>::createAdjacent(myMap,m_selected, 3, VERTEX+m_first3, VERTEX+m_second3);
Traversor<PFP::MAP>* tra = TraversorFactory<PFP::MAP>::createAdjacent(myMap,m_selected, 3, VERTEX+m_first3, VERTEX+m_second3);
for (Dart d = tra->begin(); d != tra->end(); d = tra->next())
{
m_affDarts.push_back(d);
......
......@@ -33,16 +33,15 @@
#include "Algo/Import/import.h"
#include "Algo/Geometry/boundingbox.h"
#include "Algo/Render/GL1/map_glRender.h"
#include "Utils/GLSLShader.h"
#include "Algo/Geometry/area.h"
//#include "Algo/Geometry/area.h"
#include "Algo/Geometry/normal.h"
#include "Algo/Modelisation/polyhedron.h"
#include "Algo/Parallel/parallel_foreach.h"
// for file input
#include "Utils/qtInputs.h"
#include "Algo/Parallel/cgogn_thread.h"
#include "Utils/cgognStream.h"
#include "Utils/chrono.h"
using namespace CGoGN ;
......@@ -56,312 +55,249 @@ struct PFP: public PFP_STANDARD
typedef EmbeddedMap2 MAP;
};
// declaration of the map
PFP::MAP myMap;
// attribute handlers
PFP::MAP myMap;
VertexAttribute<PFP::VEC3> position;
VertexAttribute<PFP::VEC3> position2;
VertexAttribute<PFP::VEC3> normal;
// open file
void MyQT::cb_Open()
{
// set some filters
// std::string filters("all (*.*);; trian (*.trian);; ctm (*.ctm);; off (*.off);; ply (*.ply)");
//
// std::string filename = selectFile("OpenMesh","",filters);
//
// std::vector<std::string> attrNames ;
// if(!Algo::Import::importMesh<PFP>(myMap, filename.c_str(), attrNames))
// {
// CGoGNerr << "could not import " << filename << CGoGNendl ;
// return;
// }
std::vector<std::string> attrNames ;
if(!Algo::Import::importMesh<PFP>(myMap, "/home/thery/Data/liver.trian", attrNames))
{
CGoGNerr << "could not import xxx" << CGoGNendl ;
return;
}
// recuper l'attribut pour la position des points (créé lors de l'import)
position = myMap.getAttribute<PFP::VEC3, VERTEX>(attrNames[0]) ;
if (!normal.isValid())
normal = myMap.addAttribute<PFP::VEC3, VERTEX>("normal");
Algo::Geometry::computeNormalVertices<PFP>(myMap, position, normal) ;
template <typename XXX>
class ThreadNormals: public Algo::Parallel::CGoGNThread<typename XXX::MAP>
{
protected:
VertexAttribute<typename XXX::VEC3>& m_positions;
VertexAttribute<typename XXX::VEC3>& m_normals;
public:
ThreadNormals(typename XXX::MAP& map, VertexAttribute<typename XXX::VEC3>& pos, VertexAttribute<typename XXX::VEC3>& norm, unsigned int th):
Algo::Parallel::CGoGNThread<typename XXX::MAP>(map,th),
m_positions(pos),
m_normals(norm)
{}
void operator()()
{
Algo::Geometry::computeNormalVertices<XXX>(this->m_map, m_positions, m_normals, SelectorTrue(), this->tid());
}
};
// bounding box
Geom::BoundingBox<PFP::VEC3> bb = Algo::Geometry::computeBoundingBox<PFP>(myMap, position);
float lWidthObj = std::max<PFP::REAL>(std::max<PFP::REAL>(bb.size(0), bb.size(1)), bb.size(2));
Geom::Vec3f lPosObj = (bb.min() + bb.max()) / PFP::REAL(2);
// envoit info BB a l'interface
setParamObject(lWidthObj,lPosObj.data());
updateGLMatrices();
}
// new
void MyQT::cb_New()
void MyQT::cb_initGL()
{
if (!position.isValid())
position = myMap.addAttribute<PFP::VEC3, VERTEX>("position");
Utils::GLSLShader::setCurrentOGLVersion(2);
// create a sphere
Algo::Modelisation::Polyhedron<PFP> prim(myMap, position);
prim.cylinder_topo(16,16, true, true); // topo of sphere is a closed cylinder
prim.embedSphere(10.0f);
// create the render
m_render = new Algo::Render::GL2::MapRender();
if (!normal.isValid())
normal = myMap.addAttribute<PFP::VEC3, VERTEX>("normal");
// create VBO for position
m_positionVBO = new Utils::VBO();
m_positionVBO->updateData(position);
Algo::Geometry::computeNormalVertices<PFP>(myMap, position, normal) ;
m_normalVBO = new Utils::VBO();
// bounding box
Geom::BoundingBox<PFP::VEC3> bb = Algo::Geometry::computeBoundingBox<PFP>(myMap, position);
float lWidthObj = std::max<PFP::REAL>(std::max<PFP::REAL>(bb.size(0), bb.size(1)), bb.size(2));
Geom::Vec3f lPosObj = (bb.min() + bb.max()) / PFP::REAL(2);
m_shader = new Utils::ShaderSimpleColor();
m_shader->setAttributePosition(m_positionVBO);
m_shader->setColor(Geom::Vec4f(1.,1.,0.,0.));
setParamObject(lWidthObj,lPosObj.data());
updateGLMatrices();
}
m_lines = new Utils::ShaderVectorPerVertex();
m_lines->setAttributePosition(m_positionVBO);
m_lines->setAttributeVector(m_normalVBO);
m_lines->setScale(2.0f);
m_lines->setColor(Geom::Vec4f(0.0f, 1.0f, 0.2f, 0.0f));
CGoGNout << "Je calcule les normales en meme temps que les primitives" << CGoGNendl;
boost::thread thread1( ThreadNormals<PFP>(myMap,position,normal,1));
void MyQT::cb_initGL()
{
// Old school openGL ;)
Utils::GLSLShader::setCurrentOGLVersion(1);
glewInit();
m_render->initPrimitives<PFP>(myMap, allDarts, Algo::Render::GL2::LINES);
m_render->initPrimitives<PFP>(myMap, allDarts, Algo::Render::GL2::POINTS);
// init lighting parameters
float lightPosition[4]= {10.0f,10.0f,10000.0f,1.0f};
float lightColor[4]= {0.9f,0.9f,0.9f,1.0f};
registerShader(m_shader);
registerShader(m_lines);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glEnable(GL_NORMALIZE);
// glDisable(GL_CULL_FACE);
// glFrontFace(GL_CCW);
// on attend la fin du thread pour etre sur que normal est a jour
thread1.join();
m_normalVBO->updateData(normal);
}
void MyQT::cb_redraw()
{
GLfloat diff[4]= {0.0f,1.0f,0.1f,1.0f};
GLfloat amb[4]= {0.1f,0.0f,0.1f,1.0f};
GLfloat spec[4]= {1.0f,1.0f,1.0f,1.0f};
float shininess=125.0f;
// draw the lines
// glDisable(GL_LIGHTING);
// glColor3f(0.0f, 0.0f, 0.3f);
// glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
// glDisable(GL_LIGHTING);
//
// Algo::Render::GL1::renderTriQuadPoly<PFP>(myMap,Algo::Render::GL1::LINE, 1.0f,position, normal);
// draw the faces
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0f, 1.0f);
glEnable(GL_LIGHTING);
glEnable(GL_SMOOTH);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diff);
glMaterialfv(GL_FRONT, GL_AMBIENT, amb);
glMaterialfv(GL_FRONT,GL_SPECULAR,spec);
glMaterialf( GL_FRONT, GL_SHININESS, shininess);
Algo::Render::GL1::renderTriQuadPoly<PFP>(myMap,Algo::Render::GL1::SMOOTH, 1.0f,position, normal);
glDisable(GL_POLYGON_OFFSET_FILL);
m_render->draw(m_shader, Algo::Render::GL2::LINES);
m_render->draw(m_lines, Algo::Render::GL2::POINTS);
}
template <typename XXX>
class ThreadArea: public Algo::Parallel::CGoGNThread<typename XXX::MAP>
void MyQT::cb_keyPress(int code)
{
protected:
const typename XXX::TVEC3& m_positions;
float area;
public:
ThreadArea(typename XXX::MAP& map, const typename XXX::TVEC3& pos, unsigned int th) :
Algo::Parallel::CGoGNThread<typename XXX::MAP>(map,th),
m_positions(pos),
area(0.0f)
{}
Utils::Chrono ch;
ch.start();
void operator()()
switch(code)
{
// 3 times just for fun !!!
area += Algo::Geometry::totalArea<XXX>(this->m_map, m_positions, SelectorTrue(), this->m_threadId);
area += Algo::Geometry::totalArea<XXX>(this->m_map, m_positions, SelectorTrue(), this->m_threadId);
area += Algo::Geometry::totalArea<XXX>(this->m_map, m_positions, SelectorTrue(), this->m_threadId);
case 'a':
threadSimple();
break;
case 'z':
threadStorage();
break;
case 'q':
threadAttrib();
break;
default:
break;
}
CGoGNout << "time = "<< ch.elapsed() << CGoGNendl;
updateGL();
}
float getTripleValue() { return area; }
};
//
// Simple attribute parallel functor and traversor
//
template <typename XXX>
class ThreadNormals: public Algo::Parallel::CGoGNThread<typename XXX::MAP>
class UnshrinkFunctor : public FunctorAttribThreaded
{
protected:
const typename XXX::TVEC3& m_positions;
typename XXX::TVEC3& m_normals;
VertexAttribute<typename XXX::VEC3>& m_positions;
VertexAttribute<typename XXX::VEC3>& m_positions2;
public:
ThreadNormals(typename XXX::MAP& map, const typename XXX::TVEC3& pos, typename XXX::TVEC3& norm, unsigned int th):
Algo::Parallel::CGoGNThread<typename XXX::MAP>(map,th),
m_positions(pos),
m_normals(norm)
UnshrinkFunctor( VertexAttribute<typename XXX::VEC3>& pos, VertexAttribute<typename XXX::VEC3>& pos2):
FunctorAttribThreaded(),m_positions(pos),m_positions2(pos2)
{}
void operator()()
void run(unsigned int i, unsigned int threadID)
{
Algo::Geometry::computeNormalVertices<XXX>(this->m_map, m_positions, m_normals, SelectorTrue(), this->m_threadId);
m_positions2[i] = 1.1f * m_positions[i];
}
};
//template<typename XXX>
//class Thread0
//{
//protected:
// typename XXX::MAP& m_map;
// MyGlutWin& m_mgw;
// unsigned int m_th;
// SelectorTrue m_selt;
//public:
// Thread0(typename XXX::MAP& map,MyGlutWin& mgw, unsigned int th):
// m_map(map), m_mgw(mgw), m_th(th) {}
//
// void operator()()
// {
// CGoGNout << "Begin render init"<<CGoGNendl;
// m_mgw.useContext();
//
// // instanciation of the renderer (here using VBOs)
// m_mgw.m_render = new Algo::Render::VBO::MapRender_VBO();
//
// // update the renderer (geometry and primitives)
// m_mgw.m_render->updateData(Algo::Render::VBO::POSITIONS, position);
//
// m_mgw.m_render->initPrimitives<PFP>(m_map, m_selt, Algo::Render::VBO::TRIANGLES,m_th);
// m_mgw.m_render->initPrimitives<PFP>(m_map, m_selt, Algo::Render::VBO::LINES,m_th);
//
// m_mgw.releaseContext();
// CGoGNout<< "Render OK "<< CGoGNendl;
//
// }
//};
void MyQT::threadAttrib()
{
UnshrinkFunctor<PFP> funct(position,position2);
Algo::Parallel::foreach_attrib(myMap.getAttributeContainer<VERTEX>(), funct);
myMap.swapAttributes(position,position2);
m_positionVBO->updateData(position);
m_lines->setAttributePosition(m_positionVBO);
updateGL();
}
//
// Simple thread that traverse a map
//
template <typename XXX>
class calculFunctor1 : public Algo::Parallel::FunctorMapThreaded<typename XXX::MAP>
class ShrinkFunctor : public FunctorMapThreaded<typename XXX::MAP >
{
protected:
typename XXX::TVEC3& m_positions;
typename XXX::TVEC3& m_normals;
VertexAttribute<typename XXX::VEC3>& m_positions;
VertexAttribute<typename XXX::VEC3>& m_positions2;
public:
calculFunctor1( typename XXX::MAP& map, typename XXX::TVEC3& pos, typename XXX::TVEC3& norm, unsigned int id=0):
Algo::Parallel::FunctorMapThreaded<typename XXX::MAP>(map,id), m_positions(pos), m_normals(norm) {}
bool operator()(Dart d)
{
typename XXX::VEC3 n1 = Algo::Geometry::vertexNormal<XXX>(this->m_map, d, m_positions);
typename XXX::VEC3 n2 = Algo::Geometry::vertexNormal<XXX>(this->m_map, this->m_map.phi1(d), m_positions);
typename XXX::VEC3 n3 = Algo::Geometry::vertexNormal<XXX>(this->m_map, this->m_map.phi_1(d), m_positions);
typename XXX::VEC3 n = n1+n2+n3;
n1 = Algo::Geometry::vertexNormal<XXX>(this->m_map, d, m_positions);
n2 = Algo::Geometry::vertexNormal<XXX>(this->m_map, this->m_map.phi1(d), m_positions);
n3 = Algo::Geometry::vertexNormal<XXX>(this->m_map, this->m_map.phi_1(d), m_positions);
n += n1+n2+n3;
n.normalize();
m_normals[d] = n;
// m_normals[d] = Algo::Geometry::vertexNormal<XXX>(this->m_map, d, m_positions);
return false;
}
ShrinkFunctor( typename XXX::MAP& map, VertexAttribute<typename XXX::VEC3>& pos, VertexAttribute<typename XXX::VEC3>& pos2):
FunctorMapThreaded< typename XXX::MAP>(map),
m_positions(pos),m_positions2(pos2)
{}
Algo::Parallel::FunctorMapThreaded<typename XXX::MAP>* duplicate(unsigned int id)
void run(Dart d, unsigned int threadID)
{
calculFunctor1<XXX>* copy = new calculFunctor1<XXX>(this->m_map,m_positions,m_normals,id);
return reinterpret_cast<Algo::Parallel::FunctorMapThreaded<typename XXX::MAP>*>(copy);
typename XXX::VEC3 Q(0,0,0);
int nb=0;
Traversor2VVaE<typename XXX::MAP> trav(this->m_map,d);
for (Dart e=trav.begin(); e!=trav.end(); e = trav.next())
{
Q += m_positions[e];
nb++;
}
m_positions2[d] = Q/nb;
}
// no need to duplicate here functor can be shared (no data), call foreach with true parameter
};
void MyQT::threadSimple()
{
ShrinkFunctor<PFP> funct(myMap,position,position2);
Algo::Parallel::foreach_cell<PFP::MAP,VERTEX>(myMap, funct);
myMap.swapAttributes(position,position2);
m_positionVBO->updateData(position);
m_lines->setAttributePosition(m_positionVBO);
updateGL();
}
// Thread foreach with storage (computing average length of edges)
template <typename XXX>
class LengthEdgeFunctor : public Algo::Parallel::FunctorMapThreadedResult<typename XXX::MAP, std::pair<double,unsigned int> >
class LengthEdgeFunctor : public FunctorMapThreaded<typename XXX::MAP >
{
protected:
typename XXX::TVEC3& m_positions;
VertexAttribute<typename XXX::VEC3>& m_positions;
double m_length;
unsigned int m_nb;
public:
LengthEdgeFunctor( typename XXX::MAP& map, typename XXX::TVEC3& pos, unsigned int id=0):
Algo::Parallel::FunctorMapThreadedResult< typename XXX::MAP, std::pair<double,unsigned int> >(map,id),
m_positions(pos),
m_length(0.0),
m_nb(0) {}
LengthEdgeFunctor( typename XXX::MAP& map, VertexAttribute<typename XXX::VEC3>& pos):
FunctorMapThreaded< typename XXX::MAP>(map),
m_positions(pos), m_length(0.0), m_nb(0)
{}
bool operator()(Dart d)
double getLength() { return m_length;}
unsigned int getNb() { return m_nb;}
void run(Dart d, unsigned int threadID)
{
Dart dd = this->m_map.phi2(d);
typename XXX::VEC3 V = m_positions[dd] - m_positions[d];
m_length += V.norm();
m_nb++;
return false;
}
Algo::Parallel::FunctorMapThreaded<typename XXX::MAP>* duplicate(unsigned int id)
{
LengthEdgeFunctor<XXX>* copy = new LengthEdgeFunctor<XXX>(this->m_map,m_positions,id);
return reinterpret_cast<Algo::Parallel::FunctorMapThreaded<typename XXX::MAP>*>(copy);
}
std::pair<double,unsigned int> getResult() { return std::pair<double,unsigned int>(m_length,m_nb);}
// no need to duplicate here, we create 1 functor by thread (see bellow)
};
void MyQT::menu_slot1()
void MyQT::threadStorage()
{
// cree un handler pour les normales aux sommets
VertexAttribute<PFP::VEC3> normal2 = myMap.addAttribute<PFP::VEC3, VERTEX>("normal2");
// functor need storage so we need one per thread
std::vector<FunctorMapThreaded<PFP::MAP>*> functs;
unsigned int nbthreads = Algo::Parallel::optimalNbThreads();
// ajout de 4 threads pour les markers
myMap.addThreadMarker(4);
for (unsigned int i=0; i<nbthreads; ++i)
{
LengthEdgeFunctor<PFP>* lef = new LengthEdgeFunctor<PFP>(myMap,position);
functs.push_back(lef);
}
//Algorithmes en //
CGoGNout << "using "<< nbthreads << " threads"<< CGoGNendl;
Algo::Parallel::foreach_cell<PFP::MAP,EDGE>(myMap, functs);
//compute average length from each thread result and delete functors
double average = 0;
unsigned int all = 0;
for (unsigned int i=0; i<nbthreads; ++i)
{
LengthEdgeFunctor<PFP>* lef = dynamic_cast<LengthEdgeFunctor<PFP>*>(functs[i]);
average += lef->getLength();
all += lef->getNb();
delete lef;
}