Commit 544ff8ec authored by untereiner's avatar untereiner

Adding Catmull-clark and Loop equivalent regular subdivision for volumetric meshes

parent e4ade02b
......@@ -92,7 +92,6 @@ void MyQT::operation(int x)
if (m_selected != NIL)
{
dm.markAll();
PFP::VEC3 Q = position[myMap.phi1(m_selected)];
myMap.uncutEdge(m_selected);
updateMap();
}
......@@ -104,7 +103,6 @@ void MyQT::operation(int x)
if (myMap.deleteEdgePreCond(m_selected))
{
dm.markAll();
PFP::VEC3 Q = position[myMap.phi1(m_selected)];
myMap.deleteEdge(m_selected);
m_selected = NIL;
updateMap();
......@@ -155,7 +153,30 @@ void MyQT::operation(int x)
updateMap();
}
break;
case 8:
CGoGNout <<"collapse face"<<CGoGNendl;
if (m_selected != NIL)
{
PFP::VEC3 Q = Algo::Geometry::faceCentroid<PFP>(myMap,m_selected,position);
Dart x = myMap.collapseFace(m_selected);
dm.markAll();
position[x]= Q;
m_selected = NIL;
updateMap();
}
break;
case 9:
CGoGNout <<"collapse volume"<<CGoGNendl;
if (m_selected != NIL)
{
PFP::VEC3 Q = Algo::Geometry::volumeCentroid<PFP>(myMap,m_selected,position);
Dart x = myMap.collapseVolume(m_selected);
dm.markAll();
position[x]= Q;
m_selected = NIL;
updateMap();
}
break;
default:
break;
}
......@@ -284,8 +305,9 @@ void MyQT::cb_keyPress(int keycode)
updateMap();
updateGL();
break;
case 'c':
myMap.check();
break;
case 'a':
m_selected = myMap.phi1(m_selected);
updateGL();
......@@ -409,7 +431,7 @@ void MyQT::svg()
void MyQT::cb_Open()
{
std::string filters("all (*.*);; trian (*.trian);; off (*.off);; ply (*.ply);; map (*.map)") ;
std::string filters("all (*.*);; map (*.map)") ;
std::string filename = selectFile("Open Mesh", "", filters) ;
if (!filename.empty())
importMesh(filename);
......@@ -434,16 +456,40 @@ void MyQT::importMesh(std::string& filename)
myMap.loadMapBin(filename);
position = myMap.getAttribute<PFP::VEC3>(VERTEX, "position") ;
}
else
else if (extension == std::string(".node"))
{
std::vector<std::string> attrNames ;
if(!Algo::Import::importMeshV<PFP>(myMap, filename, attrNames, Algo::Import::ImportVolumique::NODE))
{
std::cerr << "could not import " << filename << std::endl ;
return ;
}
position = myMap.getAttribute<PFP::VEC3>(VERTEX, attrNames[0]) ;
}
else if(extension == std::string(".tet"))
{
std::vector<std::string> attrNames ;
if(!Algo::Import::importMesh<PFP>(myMap, filename.c_str(), attrNames))
if(!Algo::Import::importMeshV<PFP>(myMap, filename, attrNames, Algo::Import::ImportVolumique::TET))
{
CGoGNerr << "could not import " << filename << CGoGNendl ;
return;
std::cerr << "could not import " << filename << std::endl ;
return ;
}
position = myMap.getAttribute<PFP::VEC3>(VERTEX, attrNames[0]) ;
}
else if(extension == std::string(".off"))
{
std::vector<std::string> attrNames ;
if(!Algo::Import::importMeshV<PFP>(myMap, filename, attrNames, Algo::Import::ImportVolumique::OFF))
{
std::cerr << "could not import " << filename << std::endl ;
return ;
}
position = myMap.getAttribute<PFP::VEC3>(VERTEX, attrNames[0]) ;
}
else
{
std::cerr << "could not import " << filename << std::endl ;
}
m_selected = NIL;
m_selected2 = NIL;
......
......@@ -89,6 +89,16 @@
<string>splitVolume</string>
</property>
</item>
<item>
<property name="text">
<string>collapseFace</string>
</property>
</item>
<item>
<property name="text">
<string>collapseVolume</string>
</property>
</item>
</widget>
</item>
<item>
......
......@@ -83,6 +83,9 @@ bool importMeshToExtrude(typename PFP::MAP& map, const std::string& filename, st
template <typename PFP>
bool importOFFWithELERegions(typename PFP::MAP& the_map, const std::string& filenameOFF, const std::string& filenameELE, std::vector<std::string>& attrNames);
template <typename PFP>
bool importNodeWithELERegions(typename PFP::MAP& map, const std::string& filenameNode, const std::string& filenameELE, std::vector<std::string>& attrNames);
template <typename PFP>
bool importTet(typename PFP::MAP& the_map, const std::string& filename, std::vector<std::string>& attrNames, float scaleFactor = 1.0f);
......@@ -105,5 +108,6 @@ bool importTs(typename PFP::MAP& the_map, const std::string& filename, std::vect
#include "Algo/Import/importObjEle.hpp"
#include "Algo/Import/importTet.hpp"
#include "Algo/Import/importTs.hpp"
#include "Algo/Import/importNodeEle.hpp"
#endif
......@@ -57,7 +57,7 @@ namespace Import
namespace ImportVolumique
{
enum ImportType { UNKNOWNVOLUME , TET, ELE, TS };
enum ImportType { UNKNOWNVOLUME , TET, OFF, TS, NODE};
}
......
......@@ -37,8 +37,8 @@ ImportVolumique::ImportType MeshTablesVolume<PFP>::getFileType(const std::string
if ((filename.rfind(".tet")!=std::string::npos) || (filename.rfind(".TET")!=std::string::npos))
return ImportVolumique::TET;
if ((filename.rfind(".ele")!=std::string::npos) || (filename.rfind(".ELE")!=std::string::npos))
return ImportVolumique::ELE;
if ((filename.rfind(".node")!=std::string::npos) || (filename.rfind(".NODE")!=std::string::npos))
return ImportVolumique::NODE;
if ((filename.rfind(".ts")!=std::string::npos) || (filename.rfind(".TS")!=std::string::npos))
return ImportVolumique::TS;
......@@ -57,7 +57,7 @@ bool MeshTablesVolume<PFP>::importMesh(const std::string& filename, std::vector<
case ImportVolumique::TET:
return importTet(filename, attrNames, scaleFactor);
break;
case ImportVolumique::ELE:
case ImportVolumique::NODE:
break;
case ImportVolumique::TS:
break;
......
......@@ -269,13 +269,22 @@ bool importMeshV(typename PFP::MAP& map, const std::string& filename, std::vecto
case ImportVolumique::TET:
return Algo::Import::importTet<PFP>(map, filename, attrNames, 1.0f);
break;
case ImportVolumique::ELE:
case ImportVolumique::OFF:
{
size_t pos = filename.rfind(".");
std::string fileOFF = filename;
fileOFF.erase(pos);
fileOFF.append(".off");
return Algo::Import::importOFFWithELERegions<PFP>(map, fileOFF, filename, attrNames);
std::string fileEle = filename;
fileEle.erase(pos);
fileEle.append(".ele");
return Algo::Import::importOFFWithELERegions<PFP>(map, filename, fileEle, attrNames);
break;
}
case ImportVolumique::NODE:
{
size_t pos = filename.rfind(".");
std::string fileEle = filename;
fileEle.erase(pos);
fileEle.append(".ele");
return Algo::Import::importNodeWithELERegions<PFP>(map, filename, fileEle, attrNames);
break;
}
case ImportVolumique::TS:
......
......@@ -78,6 +78,12 @@ public:
*/
virtual void splitFace(Dart d, Dart e);
//!
/*!
*
*/
virtual Dart collapseFace(Dart d, bool delDegenerateVolumes = true);
//!
/*!
*/
......@@ -98,6 +104,11 @@ public:
*/
virtual void splitVolume(std::vector<Dart>& vd);
//!
/*!
*/
virtual Dart collapseVolume(Dart d, bool delDegenerateVolumes = true);
//!
/*! No attribute is attached to the new volume
*/
......
......@@ -198,6 +198,13 @@ public:
*/
virtual void splitFace(Dart d, Dart e);
//! Collapse a face (that is deleted) possibly merging its vertices
/*! \warning
* @param d a dart in the deleted face
* @return a dart of the resulting vertex
*/
virtual Dart collapseFace(Dart d, bool delDegenerateVolumes = true);
//! Delete a volume if and only if it has a face with degree < 3 or only 3 vertices
/*! If the volume is sewed to two distinct adjacent volumes and if the face degree
* of the two adjacent volumes is equal then those two volumes are sewed
......@@ -235,6 +242,13 @@ public:
/*! @param vd a vector of darts
*/
virtual void splitVolume(std::vector<Dart>& vd);
//! Collapse a volume (that is deleted) possibly merging its vertices
/*! \warning
* @param d a dart in the deleted volume
* @return a dart of the resulting vertex
*/
virtual Dart collapseVolume(Dart d, bool delDegenerateVolumes = true);
//@}
/*! @name Topological Queries
......
......@@ -309,11 +309,13 @@ public:
typename PFP::VEC3 p = Algo::Geometry::faceCentroid<PFP>(m_map, d, m_position);
m_map.incCurrentLevel() ;
Dart midF = m_map.phi2(m_map.phi1(d));
m_position[midF] = p ;
if(m_map.faceDegree(d) != 3)
{
Dart midF = m_map.phi2(m_map.phi1(d));
m_position[midF] = p ;
}
m_map.decCurrentLevel() ;
}
}
} ;
......@@ -338,15 +340,19 @@ public:
m_map.incCurrentLevel() ;
Dart midV = m_map.phi_1(m_map.phi2(m_map.phi1(d)));
m_position[midV] = p ;
if(!m_map.isTetrahedron(d))
{
Dart midV = m_map.phi_1(m_map.phi2(m_map.phi1(d)));
m_position[midV] = p ;
}
m_map.decCurrentLevel() ;
}
}
} ;
/* Loop on Boundary Vertices
/* Loop on Boundary Vertices and SHW04 on Insides Vertices
*********************************************************************************/
template <typename PFP>
class LoopEvenSynthesisFilter : public MRFilter
......@@ -516,233 +522,6 @@ public:
}
} ;
/*********************************************************************************
* FUNCTORS
*********************************************************************************/
/* Linear Interpolation
*********************************************************************************/
template <typename PFP>
class LerpVertexVertexFunctor : public FunctorType
{
protected:
typename PFP::MAP& m_map ;
typename PFP::TVEC3& m_position ;
public:
LerpVertexVertexFunctor(typename PFP::MAP& m, typename PFP::TVEC3& p) : m_map(m), m_position(p)
{}
bool operator() (Dart d)
{
m_map.decCurrentLevel() ;
typename PFP::VEC3 p = m_position[d] ;
m_map.incCurrentLevel() ;
m_position[d] = p ;
return false ;
}
};
template <typename PFP>
class LerpEdgeVertexFunctor : public FunctorType
{
protected:
typename PFP::MAP& m_map ;
typename PFP::TVEC3& m_position ;
public:
LerpEdgeVertexFunctor(typename PFP::MAP& m, typename PFP::TVEC3& p) : m_map(m), m_position(p)
{}
bool operator() (Dart d)
{
Dart d1 = m_map.phi2(d);
m_map.decCurrentLevel();
Dart d2 = m_map.phi2(d1);
typename PFP::VEC3 p = (m_position[d1] + m_position[d2]) * typename PFP::REAL(0.5);
m_map.incCurrentLevel();
m_position[d] = p;
return false;
}
} ;
template <typename PFP>
class LerpFaceVertexFunctor : public FunctorType
{
protected:
typename PFP::MAP& m_map ;
typename PFP::TVEC3& m_position ;
public:
LerpFaceVertexFunctor(typename PFP::MAP& m, typename PFP::TVEC3& p) : m_map(m), m_position(p)
{}
bool operator() (Dart d)
{
Dart df = m_map.phi1(m_map.phi1(d)) ;
m_map.decCurrentLevel() ;
typename PFP::VEC3 p = Algo::Geometry::faceCentroid<PFP>(m_map, df, m_position);
m_map.incCurrentLevel() ;
m_position[d] = p ;
return false ;
}
} ;
template <typename PFP>
class LerpVolumeVertexFunctor : public FunctorType
{
protected:
typename PFP::MAP& m_map ;
typename PFP::TVEC3& m_position ;
public:
LerpVolumeVertexFunctor(typename PFP::MAP& m, typename PFP::TVEC3& p) : m_map(m), m_position(p)
{}
bool operator() (Dart d)
{
Dart df = m_map.phi_1(m_map.phi2(m_map.phi1(d))) ;
m_map.decCurrentLevel() ;
typename PFP::VEC3 p = Algo::Geometry::volumeCentroid<PFP>(m_map, df, m_position);
m_map.incCurrentLevel() ;
m_position[d] = p ;
return false ;
}
} ;
/* SHW04 basic functions : tetrahedral/octahedral meshes
*********************************************************************************/
template <typename PFP>
class SHW04VertexVertexFunctor : public FunctorType
{
protected:
typename PFP::MAP& m_map ;
typename PFP::TVEC3& m_position ;
public:
SHW04VertexVertexFunctor(typename PFP::MAP& m, typename PFP::TVEC3& p) : m_map(m), m_position(p)
{}
bool operator() (Dart d)
{
if(m_map.isBoundaryVertex(d))
{
Dart db = m_map.findBoundaryFaceOfVertex(d);
m_map.decCurrentLevel() ;
typename PFP::VEC3 np(0) ;
unsigned int degree = 0 ;
Traversor2VVaE<typename PFP::MAP> trav(m_map, db) ;
for(Dart it = trav.begin(); it != trav.end(); it = trav.next())
{
++degree ;
np += m_position[it] ;
}
float tmp = 3.0 + 2.0 * cos(2.0 * M_PI / degree) ;
float beta = (5.0 / 8.0) - ( tmp * tmp / 64.0 ) ;
np *= beta / degree ;
typename PFP::VEC3 vp = m_position[db] ;
vp *= 1.0 - beta ;
m_map.incCurrentLevel() ;
m_position[d] = np + vp ;
}
else
{
std::cout << "not a boundary vertex vertex" << std::endl;
// typename PFP::VEC3 p = typename PFP::VEC3(0);
// unsigned int degree = 0;
//
// Traversor3VW<typename PFP::MAP> travVW(m_map, d);
// for(Dart dit = travVW.begin() ; dit != travVW.end() ; dit = travVW.next())
// {
// p += SHW04Vertex<PFP>(m_map, m_position, dit);
// ++degree;
// }
//
// p /= degree;
//
// m_position[d] = p ;
}
return false ;
}
} ;
template <typename PFP>
class SHW04EdgeVertexFunctor : public FunctorType
{
protected:
typename PFP::MAP& m_map ;
typename PFP::TVEC3& m_position ;
public:
SHW04EdgeVertexFunctor(typename PFP::MAP& m, typename PFP::TVEC3& p) : m_map(m), m_position(p)
{}
bool operator() (Dart d)
{
if(m_map.isBoundaryVertex(d))
{
Dart dd = m_map.phi2(d) ;
m_map.decCurrentLevel() ;
Dart d1 = m_map.findBoundaryFaceOfEdge(dd);
Dart d2 = m_map.phi2(d1) ;
Dart d3 = m_map.phi_1(d1) ;
Dart d4 = m_map.phi_1(d2) ;
typename PFP::VEC3 p1 = m_position[d1] ;
typename PFP::VEC3 p2 = m_position[d2] ;
typename PFP::VEC3 p3 = m_position[d3] ;
typename PFP::VEC3 p4 = m_position[d4] ;
p1 *= 3.0 / 8.0 ;
p2 *= 3.0 / 8.0 ;
p3 *= 1.0 / 8.0 ;
p4 *= 1.0 / 8.0 ;
m_map.incCurrentLevel() ;
m_position[d] = p1 + p2 + p3 + p4 ;
}
else
{
std::cout << "not a boundary edge vertex" << std::endl;
// typename PFP::VEC3 p = typename PFP::VEC3(0);
// unsigned int degree = 0;
//
// Traversor3VW<typename PFP::MAP> travVW(m_map, d);
// for(Dart dit = travVW.begin() ; dit != travVW.end() ; dit = travVW.next())
// {
// p += SHW04Vertex<PFP>(m_map, m_position, dit);
// ++degree;
// }
//
// p /= degree;
//
// m_position[d] = p ;
}
return false ;
}
} ;
} // namespace Multiresolution
......
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your *
* option) any later version. *
* *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this library; if not, write to the Free Software Foundation, *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
* Web site: http://cgogn.unistra.fr/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
#ifndef __3MR_FUNCTORS_PRIMAL__
#define __3MR_FUNCTORS_PRIMAL__
#include <cmath>
#include "Algo/Geometry/centroid.h"
namespace CGoGN
{
namespace Multiresolution
{
/*********************************************************************************
* LOOP BASIC FUNCTIONS
*********************************************************************************/
template <typename PFP>
typename PFP::VEC3 loopOddVertex(typename PFP::MAP& map, const typename PFP::TVEC3& position, Dart d1)
{
Dart d2 = map.phi2(d1) ;
Dart d3 = map.phi_1(d1) ;
Dart d4 = map.phi_1(d2) ;
typename PFP::VEC3 p1 = position[d1] ;
typename PFP::VEC3 p2 = position[d2] ;
typename PFP::VEC3 p3 = position[d3] ;
typename PFP::VEC3 p4 = position[d4] ;
p1 *= 3.0 / 8.0 ;
p2 *= 3.0 / 8.0 ;
p3 *= 1.0 / 8.0 ;
p4 *= 1.0 / 8.0 ;
return p1 + p2 + p3 + p4 ;
}
template <typename PFP>
typename PFP::VEC3 loopEvenVertex(typename PFP::MAP& map, const typename PFP::TVEC3& position, Dart d)
{
map.incCurrentLevel() ;
typename PFP::VEC3 np(0) ;
unsigned int degree = 0 ;
Traversor2VVaE<typename PFP::MAP> trav(map, d) ;
for(Dart it = trav.begin(); it != trav.end(); it = trav.next())
{
++degree ;
np += position[it] ;
}
map.decCurrentLevel() ;
float mu = 3.0/8.0 + 1.0/4.0 * cos(2.0 * M_PI / degree) ;
mu = (5.0/8.0 - (mu * mu)) / degree ;
np *= 8.0/5.0 * mu ;
return np ;
}
/*********************************************************************************
* SHW04 BASIC FUNCTIONS : tetrahedral/octahedral meshes
*********************************************************************************/
template <typename PFP>
typename PFP::VEC3 SHW04Vertex(typename PFP::MAP& map, const typename PFP::TVEC3& position, Dart d)
{
typename PFP::VEC3 res(0);
if(map.isTetrahedron(d))