Commit ab4545fa authored by Sylvain Thery's avatar Sylvain Thery

Merge cgogn:~vanhoey/CGoGN

parents bac3af1b 277688bd
......@@ -196,6 +196,12 @@ void decimate(
case S_hLightfieldKCL :
selector = new HalfEdgeSelector_LightfieldKCL<PFP>(map, position, approximators) ;
break ;
case S_hColorExperimental:
selector = new HalfEdgeSelector_ColorExperimental<PFP>(map, position, approximators, selected) ;
break ;
case S_hLFexperimental:
selector = new HalfEdgeSelector_LFexperimental<PFP>(map, position, approximators, selected) ;
break ;
}
for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = approximators.begin(); it != approximators.end(); ++it)
......@@ -213,9 +219,6 @@ void decimate(
return ;
}
if (edgeErrors != NULL)
selector->getEdgeErrors(edgeErrors) ;
unsigned int nbVertices = map.template getNbOrbits<VERTEX>() ;
bool finished = false ;
Dart d ;
......@@ -257,6 +260,9 @@ void decimate(
callback_wrapper(callback_object, &nbVertices) ;
}
if (edgeErrors != NULL)
selector->getEdgeErrors(edgeErrors) ;
delete selector ;
for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = approximators.begin(); it != approximators.end(); ++it)
......
......@@ -466,7 +466,7 @@ public:
(*errors)[d] = halfEdgeInfo[d].it->first ;
}
Dart dd = this->m_map.phi2(d) ;
if (halfEdgeInfo[dd].valid && halfEdgeInfo[dd].it->first > (*errors)[d])
if (halfEdgeInfo[dd].valid && halfEdgeInfo[dd].it->first < (*errors)[d])
{
(*errors)[dd] = halfEdgeInfo[dd].it->first ;
}
......@@ -475,10 +475,202 @@ public:
}
} ;
/*****************************************************************************************************************
* HALF-EDGE COLOR EXPERIMENTAL *
*****************************************************************************************************************/
template <typename PFP>
class HalfEdgeSelector_ColorExperimental : public EdgeSelector<PFP>
{
public:
typedef typename PFP::MAP MAP ;
typedef typename PFP::REAL REAL ;
typedef typename PFP::VEC3 VEC3 ;
private:
typedef struct
{
typename std::multimap<float,Dart>::iterator it ;
bool valid ;
static std::string CGoGNnameOfType() { return "ColorExperimentalHalfEdgeInfo" ; }
} QEMextColorHalfEdgeInfo ;
typedef NoMathIOAttribute<QEMextColorHalfEdgeInfo> HalfEdgeInfo ;
DartAttribute<HalfEdgeInfo> halfEdgeInfo ;
VertexAttribute<Utils::Quadric<REAL> > m_quadric ;
VertexAttribute<VEC3> m_pos, m_color ;
int m_approxindex_pos, m_attrindex_pos ;
int m_approxindex_color, m_attrindex_color ;
std::vector<Approximator<PFP, typename PFP::VEC3,DART>* > m_approx ;
std::multimap<float,Dart> halfEdges ;
typename std::multimap<float,Dart>::iterator cur ;
void initHalfEdgeInfo(Dart d) ;
void updateHalfEdgeInfo(Dart d) ;
void computeHalfEdgeInfo(Dart d, HalfEdgeInfo& einfo) ;
//void recomputeQuadric(const Dart d, const bool recomputeNeighbors = false) ;
void recomputeQuadric(const Dart d) ;
typename PFP::REAL computeExperimentalColorError(const Dart& v0, const Dart& v1) ;
public:
HalfEdgeSelector_ColorExperimental(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select = allDarts) :
EdgeSelector<PFP>(m, pos, approx, select),
m_approxindex_pos(-1),
m_attrindex_pos(-1),
m_approxindex_color(-1),
m_attrindex_color(-1)
{
halfEdgeInfo = m.template addAttribute<HalfEdgeInfo, DART>("halfEdgeInfo") ;
m_quadric = m.template addAttribute<Utils::Quadric<REAL>, VERTEX>("QEMquadric") ;
}
~HalfEdgeSelector_ColorExperimental()
{
this->m_map.removeAttribute(m_quadric) ;
this->m_map.removeAttribute(halfEdgeInfo) ;
}
SelectorType getType() { return S_hColorExperimental ; }
bool init() ;
bool nextEdge(Dart& d) ;
void updateBeforeCollapse(Dart d) ;
void updateAfterCollapse(Dart d2, Dart dd2) ;
void updateWithoutCollapse() { }
void getEdgeErrors(EdgeAttribute<typename PFP::REAL> *errors)
{
assert(errors != NULL || !"EdgeSelector::setColorMap requires non null vertexattribute argument") ;
if (!errors->isValid())
std::cerr << "EdgeSelector::setColorMap requires valid edgeattribute argument" << std::endl ;
assert(halfEdgeInfo.isValid()) ;
TraversorE<typename PFP::MAP> travE(this->m_map) ;
for(Dart d = travE.begin() ; d != travE.end() ; d = travE.next())
{
(*errors)[d] = -1 ;
if (halfEdgeInfo[d].valid)
{
(*errors)[d] = halfEdgeInfo[d].it->first ;
}
Dart dd = this->m_map.phi2(d) ;
if (halfEdgeInfo[dd].valid && halfEdgeInfo[dd].it->first < (*errors)[d])
{
(*errors)[d] = halfEdgeInfo[dd].it->first ;
}
}
}
} ;
/*****************************************************************************************************************
* HALF-EDGE LF EXPERIMENTAL METRIC *
*****************************************************************************************************************/
template <typename PFP>
class HalfEdgeSelector_LFexperimental : public EdgeSelector<PFP>
{
public:
typedef typename PFP::MAP MAP ;
typedef typename PFP::REAL REAL ;
typedef typename PFP::VEC3 VEC3 ;
private:
typedef struct
{
typename std::multimap<float,Dart>::iterator it ;
bool valid ;
static std::string CGoGNnameOfType() { return "LightfieldExpHalfEdgeInfo" ; }
} LightfieldHalfEdgeInfo ;
typedef NoMathIOAttribute<LightfieldHalfEdgeInfo> HalfEdgeInfo ;
DartAttribute<HalfEdgeInfo> halfEdgeInfo ;
VertexAttribute<Utils::Quadric<REAL> > m_quadric ;
VertexAttribute<REAL> m_visualImportance ;
VertexAttribute<VEC3> m_avgColor ;
int m_approxindex_pos, m_attrindex_pos ;
int m_approxindex_FT, m_attrindex_FT ;
int m_approxindex_FB, m_attrindex_FB ;
int m_approxindex_FN, m_attrindex_FN ;
std::vector<unsigned int> m_approxindex_HF, m_attrindex_HF ;
unsigned int m_K ;
std::vector<Approximator<PFP, typename PFP::VEC3,DART>* > m_approx ;
std::multimap<float,Dart> halfEdges ;
typename std::multimap<float,Dart>::iterator cur ;
void initHalfEdgeInfo(Dart d) ;
void updateHalfEdgeInfo(Dart d) ;
void computeHalfEdgeInfo(Dart d, HalfEdgeInfo& einfo) ;
void recomputeQuadric(const Dart d) ;
REAL computeLightfieldError(const Dart& v0, const Dart& v1) ;
REAL computeSquaredLightfieldDifference(const Dart& d1, const Dart& d2) ;
public:
HalfEdgeSelector_LFexperimental(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select = allDarts) :
EdgeSelector<PFP>(m, pos, approx, select),
m_approxindex_pos(-1),
m_attrindex_pos(-1),
m_approxindex_FT(-1),
m_attrindex_FT(-1),
m_approxindex_FB(-1),
m_attrindex_FB(-1),
m_approxindex_FN(-1),
m_attrindex_FN(-1),
m_K(0)
{
halfEdgeInfo = m.template addAttribute<HalfEdgeInfo, DART>("halfEdgeInfo") ;
m_quadric = m.template addAttribute<Utils::Quadric<REAL>, VERTEX>("QEMquadric") ;
m_avgColor = m.template getAttribute<typename PFP::VEC3, VERTEX>("color") ;
assert(m_avgColor.isValid()) ;
}
~HalfEdgeSelector_LFexperimental()
{
this->m_map.removeAttribute(m_quadric) ;
this->m_map.removeAttribute(halfEdgeInfo) ;
}
SelectorType getType() { return S_hLFexperimental ; }
bool init() ;
bool nextEdge(Dart& d) ;
void updateBeforeCollapse(Dart d) ;
void updateAfterCollapse(Dart d2, Dart dd2) ;
void updateWithoutCollapse() { }
void getEdgeErrors(EdgeAttribute<typename PFP::REAL> *errors)
{
assert(errors != NULL || !"EdgeSelector::setColorMap requires non null vertexattribute argument") ;
if (!errors->isValid())
std::cerr << "EdgeSelector::setColorMap requires valid edgeattribute argument" << std::endl ;
assert(halfEdgeInfo.isValid()) ;
TraversorE<typename PFP::MAP> travE(this->m_map) ;
for(Dart d = travE.begin() ; d != travE.end() ; d = travE.next())
{
(*errors)[d] = -1 ;
if (halfEdgeInfo[d].valid)
{
(*errors)[d] = halfEdgeInfo[d].it->first ;
}
Dart dd = this->m_map.phi2(d) ;
if (halfEdgeInfo[dd].valid && halfEdgeInfo[dd].it->first < (*errors)[d])
{
(*errors)[d] = halfEdgeInfo[dd].it->first ;
}
}
}
} ;
} // namespace Decimation
}
} // namespace Surface
} // namespace Algo
......
......@@ -56,7 +56,9 @@ enum SelectorType
S_hQEMml,
S_hLightfield,
S_hLightfieldExp,
S_hLightfieldKCL
S_hLightfieldKCL,
S_hColorExperimental,
S_hLFexperimental
} ;
template <typename PFP> class ApproximatorGen ;
......
......@@ -25,6 +25,8 @@
#ifndef __PLANE_3D__
#define __PLANE_3D__
#include "Geometry/vector_gen.h"
namespace CGoGN
{
......
......@@ -58,11 +58,12 @@ public: // types
*/
enum ColourEncoding
{
C_RGB = 0,
C_XYZ = 1,
C_Luv = 2,
C_Lab = 3,
C_HSV = 4
C_RGB = 0, /*!< R,G,B in [0,1] */
C_XYZ = 1, /*!< X,Y,Z in [0,1] */
C_Luv = 2, /*!< L in [0,100], u in [-83,175], v in [-134,108] */
C_Lab = 3, /*!< L in [0,100], u in [-86,98], v in [-108,95] */
C_HSV = 4, /*!< H,S,V in [0,1] */
C_HSL = 5 /*!< H,S,L in [0,1] */
} ;
typedef Geom::Vector<3,REAL> VEC3 ; /*!< Triplet for color encoding */
......@@ -109,6 +110,11 @@ public: // methods
* @return Lab value of provided colour
*/
VEC3 getHSV() ;
/**
* getR
* @return HSL value of provided colour
*/
VEC3 getHSL() ;
/**
* getR
* @return XYZ value of provided colour
......@@ -124,6 +130,7 @@ private: // private members
VEC3 *Lab ;
VEC3 *HSV ;
VEC3 *XYZ ;
VEC3 *HSL ;
bool convert(enum ColourEncoding from, enum ColourEncoding to) ;
void convertRGBtoXYZ() ;
......@@ -135,9 +142,30 @@ private: // private members
void convertXYZtoLab() ;
void convertLabToXYZ() ;
/**
* Converts RGB to HSV. All is normalized between 0 and 1.
* Conversion formula adapted from http://en.wikipedia.org/wiki/HSL_color_space.
*/
void convertRGBtoHSV() ;
/**
* Converts HSV to RGB. All is normalized between 0 and 1.
* Conversion formula adapted from http://en.wikipedia.org/wiki/HSL_color_space.
*/
void convertHSVtoRGB() ;
/**
* Converts RGB to HSL. All is normalized between 0 and 1.
* Conversion formula adapted from http://en.wikipedia.org/wiki/HSL_color_space.
*/
void convertRGBtoHSL() ;
/**
* Converts HSL to RGB. All is normalized between 0 and 1.
* Conversion formula adapted from http://en.wikipedia.org/wiki/HSL_color_space.
*/
void convertHSLtoRGB() ;
static REAL hue2rgb(const REAL& p, const REAL& q, REAL t) ;
private: // private constants
// D65 reference white
static const REAL Xn = 0.950456 ;
......
......@@ -32,7 +32,8 @@ ColourConverter<REAL>::ColourConverter(const VEC3& col, const enum ColourEncodin
Luv(NULL),
Lab(NULL),
HSV(NULL),
XYZ(NULL)
XYZ(NULL),
HSL(NULL)
{
originalEnc = enc ;
......@@ -70,12 +71,18 @@ ColourConverter<REAL>::ColourConverter(const VEC3& col, const enum ColourEncodin
break ;
case (C_HSV) :
#ifdef DEBUG
if (!(-0.001 < col[0] && col[0] < 360.001 && -0.001 < col[1] && col[1] < 1.001 && -0.001 < col[2] && col[2] < 1.001))
std::cerr << "Warning : an unvalid Lab color was entered in ColourConverter constructor" << std::endl ;
if (!(-0.001 < col[0] && col[0] < 1.001 && -0.001 < col[1] && col[1] < 1.001 && -0.001 < col[2] && col[2] < 1.001))
std::cerr << "Warning : an unvalid HSV color was entered in ColourConverter constructor" << std::endl ;
#endif
HSV = new VEC3(col) ;
break ;
case (C_HSL) :
#ifdef DEBUG
if (!(-0.001 < col[0] && col[0] < 1.001 && -0.001 < col[1] && col[1] < 1.001 && -0.001 < col[2] && col[2] < 1.001))
std::cerr << "Warning : an unvalid HSL color was entered in ColourConverter constructor" << std::endl ;
#endif
HSL = new VEC3(col) ;
break ;
}
}
......@@ -87,6 +94,7 @@ ColourConverter<REAL>::~ColourConverter()
delete XYZ ;
delete Lab ;
delete HSV ;
delete HSL ;
}
template<typename REAL>
......@@ -112,6 +120,10 @@ Geom::Vector<3,REAL> ColourConverter<REAL>::getColour(enum ColourEncoding enc) {
return getHSV() ;
break ;
case (C_HSL) :
return getHSL() ;
break ;
default :
assert(!"Should never arrive here : ColourConverter::getColour default case") ;
return getOriginal() ;
......@@ -119,12 +131,16 @@ Geom::Vector<3,REAL> ColourConverter<REAL>::getColour(enum ColourEncoding enc) {
}
template<typename REAL>
Geom::Vector<3,REAL> ColourConverter<REAL>::getOriginal() {
Geom::Vector<3,REAL>
ColourConverter<REAL>::getOriginal()
{
return getColour(this->originalEnc) ;
}
template<typename REAL>
Geom::Vector<3,REAL> ColourConverter<REAL>::getRGB() {
Geom::Vector<3,REAL>
ColourConverter<REAL>::getRGB()
{
if (RGB == NULL)
convert(originalEnc,C_RGB) ;
......@@ -132,7 +148,9 @@ Geom::Vector<3,REAL> ColourConverter<REAL>::getRGB() {
}
template<typename REAL>
Geom::Vector<3,REAL> ColourConverter<REAL>::getLuv() {
Geom::Vector<3,REAL>
ColourConverter<REAL>::getLuv()
{
if (Luv == NULL)
convert(originalEnc,C_Luv) ;
......@@ -140,7 +158,9 @@ Geom::Vector<3,REAL> ColourConverter<REAL>::getLuv() {
}
template<typename REAL>
Geom::Vector<3,REAL> ColourConverter<REAL>::getLab() {
Geom::Vector<3,REAL>
ColourConverter<REAL>::getLab()
{
if (Lab == NULL)
convert(originalEnc,C_Lab) ;
......@@ -148,7 +168,9 @@ Geom::Vector<3,REAL> ColourConverter<REAL>::getLab() {
}
template<typename REAL>
Geom::Vector<3,REAL> ColourConverter<REAL>::getXYZ() {
Geom::Vector<3,REAL>
ColourConverter<REAL>::getXYZ()
{
if (XYZ == NULL) {
convert(originalEnc,C_XYZ) ;
}
......@@ -157,7 +179,9 @@ Geom::Vector<3,REAL> ColourConverter<REAL>::getXYZ() {
}
template<typename REAL>
Geom::Vector<3,REAL> ColourConverter<REAL>::getHSV() {
Geom::Vector<3,REAL>
ColourConverter<REAL>::getHSV()
{
if (HSV == NULL)
convert(originalEnc,C_HSV) ;
......@@ -165,7 +189,20 @@ Geom::Vector<3,REAL> ColourConverter<REAL>::getHSV() {
}
template<typename REAL>
void ColourConverter<REAL>::convertRGBtoXYZ() {
Geom::Vector<3,REAL>
ColourConverter<REAL>::getHSL()
{
if (HSL == NULL)
convert(originalEnc,C_HSL) ;
return *HSL ;
}
template<typename REAL>
void
ColourConverter<REAL>::convertRGBtoXYZ()
{
Geom::Matrix<3,3,REAL> M ;
M(0,0) = 0.412453 ;
......@@ -189,7 +226,9 @@ void ColourConverter<REAL>::convertRGBtoXYZ() {
}
template<typename REAL>
void ColourConverter<REAL>::convertXYZtoRGB() {
void
ColourConverter<REAL>::convertXYZtoRGB()
{
Geom::Matrix<3,3,REAL> M ;
M(0,0) = 3.240479 ;
......@@ -213,7 +252,8 @@ void ColourConverter<REAL>::convertXYZtoRGB() {
}
template<typename REAL>
void ColourConverter<REAL>::convertRGBtoHSV()
void
ColourConverter<REAL>::convertRGBtoHSV()
{
const REAL& r = (*RGB)[0] ;
const REAL& g = (*RGB)[1] ;
......@@ -221,27 +261,38 @@ void ColourConverter<REAL>::convertRGBtoHSV()
const REAL& max = std::max(std::max(r,g),b) ;
const REAL& min = std::min(std::min(r,g),b) ;
VEC3 c ;
REAL& H = c[0] ;
REAL& S = c[1] ;
REAL& V = c[2] ;
const REAL diff = max - min ;
V = max ;
S = max == 0. ? 0 : diff / max ;
if (max == min)
{
c[0] = 0 ;
}
else if (max == r)
{
c[0] = 60 * (g - b) / (max - min) + 360 ;
c[0] = (unsigned int)(c[0]) % 360 ;
H = 0 ;
}
else if (max == g)
{
c[0] = 60 * (b - r) / (max - min) + 120 ;
}
else if (max == b)
else
{
c[0] = 60 * (r - g) / (max - min) + 240 ;
if (max == r)
{
H = (g - b) / diff + (g < b ? 6 : 0) ;
}
else if (max == g)
{
H = (b - r) / diff + 2 ;
}
else if (max == b)
{
H = (r - g) / diff + 4 ;
}
}
c[1] = (max == 0) ? 0 : 1 - min/max ;
c[2] = max ;
H /= 6. ;
if (HSV != NULL)
*HSV = c ;
......@@ -250,54 +301,134 @@ void ColourConverter<REAL>::convertRGBtoHSV()
}
template<typename REAL>
void ColourConverter<REAL>::convertHSVtoRGB()
void
ColourConverter<REAL>::convertHSVtoRGB()
{
const REAL& H = (*HSV)[0] ;
const REAL& s = (*HSV)[1] ;
const REAL& v = (*HSV)[2] ;
const REAL& S = (*HSV)[1] ;
const REAL& V = (*HSV)[2] ;
const unsigned int Hi = (unsigned int)(floor(H / 60)) % 6 ;
const REAL f = (H / 60) - Hi ;
const REAL l = v * (1 - s) ;
const REAL m = v * (1 - f * s) ;
const REAL n = v * (1 - (1 - f) * s) ;
const int i = std::floor(H * 6);
const REAL f = H * 6 - i;
const REAL p = V * (1 - S);
const REAL q = V * (1 - f * S);
const REAL t = V * (1 - (1 - f) * S);
VEC3 c ;
switch(Hi)
REAL& r = c[0] ;
REAL& g = c[1] ;
REAL& b = c[2] ;
switch(i % 6)
{
case(0) :
{
c = VEC3(v,n,l) ;
}
break ;
case(1):
{
c = VEC3(m,v,l) ;
}
break ;
case(2):
case 0: r = V, g = t, b = p; break;
case 1: r = q, g = V, b = p; break;
case 2: r = p, g = V, b = t; break;
case 3: r = p, g = q, b = V; break;
case 4: r = t, g = p, b = V; break;
case 5: r = V, g = p, b = q; break;
}
if (RGB != NULL)
*RGB = c ;
else
RGB = new VEC3(c) ;
}
template<typename REAL>
void
ColourConverter<REAL>::convertRGBtoHSL()
{
const REAL& r = (*RGB)[0] ;
const REAL& g = (*RGB)[1] ;
const REAL& b = (*RGB)[2] ;
const REAL& max = std::max(std::max(r,g),b) ;
const REAL& min = std::min(std::min(r,g),b) ;
VEC3 c ;
REAL& H = c[0] ;
REAL& S = c[1] ;
REAL& L = c[2] ;
const REAL sum = max + min ;
L = sum / 2. ;
if (max == min)
{
H = 0 ;
S = 0 ;
}
else
{