Commit e32aeaa7 authored by David Cazier's avatar David Cazier

Merge Vertex version 1997 ajouté :)

parent cc8261af
...@@ -15,7 +15,6 @@ IF (FORCE_MR EQUAL 1) ...@@ -15,7 +15,6 @@ IF (FORCE_MR EQUAL 1)
add_definitions(-DCGoGN_FORCE_MR=1) add_definitions(-DCGoGN_FORCE_MR=1)
ENDIF (FORCE_MR EQUAL 1) ENDIF (FORCE_MR EQUAL 1)
# for CGoGN in one lib on not # for CGoGN in one lib on not
file(STRINGS ${CGoGN_ROOT_DIR}/include/cgogn_onelib.h ONELIB_STR) file(STRINGS ${CGoGN_ROOT_DIR}/include/cgogn_onelib.h ONELIB_STR)
IF (ONELIB_STR EQUAL 1) IF (ONELIB_STR EQUAL 1)
...@@ -26,28 +25,22 @@ ELSE (ONELIB_STR EQUAL 1) ...@@ -26,28 +25,22 @@ ELSE (ONELIB_STR EQUAL 1)
SET(CGoGN_LIBS_R topology algo container utils) SET(CGoGN_LIBS_R topology algo container utils)
ENDIF (ONELIB_STR EQUAL 1) ENDIF (ONELIB_STR EQUAL 1)
IF(WIN32) IF(WIN32)
set(CMAKE_PREFIX_PATH ${CGoGN_ROOT_DIR}/windows_dependencies CACHE STRING "path to dependencies") set(CMAKE_PREFIX_PATH ${CGoGN_ROOT_DIR}/windows_dependencies CACHE STRING "path to dependencies")
ENDIF(WIN32) ENDIF(WIN32)
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
find_package(Boost COMPONENTS regex thread REQUIRED) find_package(Boost COMPONENTS regex thread REQUIRED)
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
find_package(LibXml2 REQUIRED) find_package(LibXml2 REQUIRED)
find_package(GLEW REQUIRED) find_package(GLEW REQUIRED)
IF (DEFINED ASSERTON) IF (DEFINED ASSERTON)
add_definitions(-DCGOGN_ASSERT_BOOL=${ASSERTON}) add_definitions(-DCGOGN_ASSERT_BOOL=${ASSERTON})
ELSE (DEFINED ASSERTON) ELSE (DEFINED ASSERTON)
add_definitions(-DCGOGN_ASSERT_BOOL=false) add_definitions(-DCGOGN_ASSERT_BOOL=false)
ENDIF (DEFINED ASSERTON) ENDIF (DEFINED ASSERTON)
add_definitions(-DSHADERPATH="${CGoGN_ROOT_DIR}/lib/Shaders/") add_definitions(-DSHADERPATH="${CGoGN_ROOT_DIR}/lib/Shaders/")
# define includes of external libs # define includes of external libs
...@@ -97,7 +90,6 @@ IF (WITH_NUMERICAL) ...@@ -97,7 +90,6 @@ IF (WITH_NUMERICAL)
SET (COMMON_LIBS ${COMMON_LIBS} numerical lapack blas f2c) SET (COMMON_LIBS ${COMMON_LIBS} numerical lapack blas f2c)
ENDIF (WITH_NUMERICAL) ENDIF (WITH_NUMERICAL)
# qq definition specifiques pour mac # qq definition specifiques pour mac
IF(APPLE) IF(APPLE)
# attention a changer pour chercher la bonne version automatiquement # attention a changer pour chercher la bonne version automatiquement
...@@ -123,6 +115,3 @@ IF(WIN32) ...@@ -123,6 +115,3 @@ IF(WIN32)
ELSE (WIN32) ELSE (WIN32)
link_directories( ${CGoGN_ROOT_DIR}/lib/Debug ${CGoGN_ROOT_DIR}/lib/Release) link_directories( ${CGoGN_ROOT_DIR}/lib/Debug ${CGoGN_ROOT_DIR}/lib/Release)
ENDIF (WIN32) ENDIF (WIN32)
...@@ -38,6 +38,9 @@ namespace Algo ...@@ -38,6 +38,9 @@ namespace Algo
namespace BooleanOperator namespace BooleanOperator
{ {
template <typename PFP>
bool isBetween(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions, Dart d, Dart e, Dart f) ;
template <typename PFP> template <typename PFP>
void mergeVertex(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions, Dart d, Dart e); void mergeVertex(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions, Dart d, Dart e);
......
...@@ -31,42 +31,57 @@ namespace Algo ...@@ -31,42 +31,57 @@ namespace Algo
namespace BooleanOperator namespace BooleanOperator
{ {
template <typename PFP>
bool isBetween(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions, Dart d, Dart e, Dart f)
{
return CGoGN::Geom::isBetween(positions[map.phi1(d)]-positions[d],
positions[map.phi1(e)]-positions[e],
positions[map.phi1(f)]-positions[f]);
}
template <typename PFP> template <typename PFP>
void mergeVertex(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions, Dart d, Dart e) void mergeVertex(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions, Dart d, Dart e)
{ {
assert(Geom::arePointsEquals(positions[d],positions[e]) && !map.sameVertex(d,e)); assert(Geom::arePointsEquals(positions[d],positions[e]) && !map.sameVertex(d,e));
Dart dd; // d1 traverses the vertex of d (following the alpha1 permutation)
do // y is a temporay buffer to stop the loop
{ Dart d1=d;
dd = map.phi2_1(d); // e1 traverses the vertex of e (following the alpha1 permutation)
map.removeEdgeFromVertex(dd); Dart e1=e;
Dart ee = e; bool notempty = true;
do do {
{ if (map.phi2_1(e1) == e1) notempty = false;
if(Geom::testOrientation2D(positions[map.phi1(dd)],positions[ee],positions[map.phi1(ee)])!=Geom::RIGHT // detach z from its vertex
&& Geom::testOrientation2D(positions[map.phi1(dd)],positions[ee],positions[map.phi1(map.phi2_1(ee))])==Geom::RIGHT) map.removeEdgeFromVertex(e1);
{ // Searchs the dart of the vertex of x where tz may be inserted
break; Dart nd1 = d1;
} do {
ee = map.phi2_1(ee); if (CGoGN::Algo::BooleanOperator::isBetween<PFP>(map,positions,e1,d1,map.phi2_1(d1))) break;
} while(ee != e); d1 = map.phi2_1(d1);
map.insertEdgeInVertex(ee,dd); } while (d1 != nd1);
map.insertEdgeInVertex(d1,e1);
d1 = e1;
} while (notempty);
} while(dd!=d); // 0-embed z on the vertex of x without copy of the vertex
// positions[d] = ;
} }
template <typename PFP> template <typename PFP>
void mergeVertices(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions) void mergeVertices(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions)
{ {
// TODO optimiser en triant les sommets
for(Dart d = map.begin() ; d != map.end() ; map.next(d)) for(Dart d = map.begin() ; d != map.end() ; map.next(d))
{ {
CellMarker<VERTEX> vM(map); CellMarker<VERTEX> vM(map);
vM.mark(d); vM.mark(d);
std::cout << "." ; std::cout.flush() ;
for(Dart dd = map.begin() ; dd != map.end() ; map.next(dd)) for(Dart dd = map.begin() ; dd != map.end() ; map.next(dd))
{ {
if(!vM.isMarked(dd)) if(!vM.isMarked(dd))
{ {
vM.mark(dd);
if(Geom::arePointsEquals(positions[d],positions[dd])) if(Geom::arePointsEquals(positions[d],positions[dd]))
{ {
mergeVertex<PFP>(map,positions,d,dd); mergeVertex<PFP>(map,positions,d,dd);
......
...@@ -303,13 +303,14 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib ...@@ -303,13 +303,14 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
CellMarker<EDGE> brokenMark(map); CellMarker<EDGE> brokenMark(map);
EdgeAttribute<float> edgeWidth = map.template addAttribute<float, EDGE>("width"); EdgeAttribute<float> edgeWidth = map.template addAttribute<float, EDGE>("width");
EdgeAttribute<Dart> edgeOpp = map.template addAttribute<Dart, EDGE>("opp");
EdgeAttribute<NoMathAttribute<Geom::Plane3D<typename PFP::REAL> > > edgePlanes = map.template addAttribute<NoMathAttribute<Geom::Plane3D<typename PFP::REAL> >, EDGE>("planes"); EdgeAttribute<NoMathAttribute<Geom::Plane3D<typename PFP::REAL> > > edgePlanes = map.template addAttribute<NoMathAttribute<Geom::Plane3D<typename PFP::REAL> >, EDGE>("planes");
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
//create broken lines //create broken lines
DartMarker brokenL(map); DartMarker brokenL(map);
unsigned int nbVertices = 0 ;
std::vector<float >::iterator itW = allBrokenLinesWidth.begin(); std::vector<float >::iterator itW = allBrokenLinesWidth.begin();
for(typename std::vector<POLYGON >::iterator it = allBrokenLines.begin() ; it != allBrokenLines.end() ; ++it) for(typename std::vector<POLYGON >::iterator it = allBrokenLines.begin() ; it != allBrokenLines.end() ; ++it)
{ {
...@@ -320,46 +321,42 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib ...@@ -320,46 +321,42 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
} }
else else
{ {
unsigned int faceDegree = it->size()*2-2; nbVertices += it->size() ;
Dart d = map.newFace(faceDegree);
polygonsFaces.mark(d); Dart d = map.newFace(it->size()*2-2,false);
Dart d1=d; Dart d1=d;
Dart d_1=map.phi_1(d); Dart d_1=map.phi_1(d);
//build a degenerated "line" face //build a degenerated "line" face
for(unsigned int i = 0; i<faceDegree/2 ; ++i) for(unsigned int i = 0; i<it->size() ; ++i)
{ {
edgeOpp[d1] = d_1;
edgeOpp[d_1] = d_1;
edgeWidth[d1] = *itW;
edgeWidth[d_1] = *itW;
brokenL.mark(d1); brokenL.mark(d1);
brokenL.mark(d_1); brokenL.mark(d_1);
map.sewFaces(d1,d_1,false) ;
edgeWidth[d1] = *itW;
d1 = map.phi1(d1); d1 = map.phi1(d1);
d_1 = map.phi_1(d_1); d_1 = map.phi_1(d_1);
} }
polygonsFaces.mark(d);
//embed the line //embed the line
Dart dd = d; d1 = d;
Dart dOp = d;
for(typename POLYGON::iterator emb = it->begin(); emb != it->end() ; emb++) for(typename POLYGON::iterator emb = it->begin(); emb != it->end() ; emb++)
{ {
bb->addPoint(*emb); bb->addPoint(*emb);
position[dd] = *emb; position[d1] = *emb;
position[dOp] = *emb; d1 = map.phi1(d1);
dd = map.phi1(dd);
dOp = map.phi_1(dOp);
} }
} }
itW++; itW++;
} }
std::cout << "importSVG : broken lines created." << std::endl; std::cout << "importSVG : broken lines created : " << nbVertices << " vertices"<< std::endl;
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
//create polygons //create polygons
...@@ -411,6 +408,7 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib ...@@ -411,6 +408,7 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
// map.closeMap(close); // map.closeMap(close);
// map.closeMap(); // map.closeMap();
std::cout << "importSVG : Vertices merging..." << std::endl;
Algo::BooleanOperator::mergeVertices<PFP>(map,position); Algo::BooleanOperator::mergeVertices<PFP>(map,position);
std::cout << "importSVG : Vertices merged." << std::endl; std::cout << "importSVG : Vertices merged." << std::endl;
...@@ -455,12 +453,12 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib ...@@ -455,12 +453,12 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
CellMarker<EDGE> eMTreated(map); CellMarker<EDGE> eMTreated(map);
for(Dart d = map.begin();d != map.end(); map.next(d)) for(Dart d = map.begin();d != map.end(); map.next(d))
{ {
if(brokenL.isMarked(d) && !eMTreated.isMarked(d) && edgeOpp[d]!=d) if(brokenL.isMarked(d) && !eMTreated.isMarked(d))
{ {
// -> we convert broken lines to faces to represent their width // -> we convert broken lines to faces to represent their width
Dart d1 = d; Dart d1 = d;
Dart d2 = edgeOpp[d]; Dart d2 = map.phi2(d);
VEC3 p1 = position[d1]; VEC3 p1 = position[d1];
VEC3 p2 = position[d2]; VEC3 p2 = position[d2];
...@@ -487,7 +485,6 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib ...@@ -487,7 +485,6 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
Dart dC = map.phi1(d2); Dart dC = map.phi1(d2);
eMTreated.mark(dC); eMTreated.mark(dC);
edgeOpp[dC] = dC;
position[map.phi_1(d1)]=p1; position[map.phi_1(d1)]=p1;
edgePlanes[map.phi_1(d1)] = Geom::Plane3D<typename PFP::REAL>(v,p1); edgePlanes[map.phi_1(d1)] = Geom::Plane3D<typename PFP::REAL>(v,p1);
...@@ -507,7 +504,6 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib ...@@ -507,7 +504,6 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
Dart dC = map.phi1(d1); Dart dC = map.phi1(d1);
eMTreated.mark(dC); eMTreated.mark(dC);
edgeOpp[dC] = dC;
position[map.phi_1(d2)]=p2; position[map.phi_1(d2)]=p2;
edgePlanes[map.phi_1(d2)] = Geom::Plane3D<typename PFP::REAL>(-1.0f*v, p2); edgePlanes[map.phi_1(d2)] = Geom::Plane3D<typename PFP::REAL>(-1.0f*v, p2);
...@@ -548,9 +544,9 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib ...@@ -548,9 +544,9 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
VEC3 pos = position[d]; VEC3 pos = position[d];
pl.project(pos); pl.project(pos);
// pl = edgePlanes[map.phi_1(d)]; pl = edgePlanes[map.phi_1(d)];
//
// pl.project(pos); pl.project(pos);
position[d] = pos; position[d] = pos;
} }
} }
......
...@@ -35,16 +35,12 @@ namespace Geom ...@@ -35,16 +35,12 @@ namespace Geom
enum OrientationLine enum OrientationLine
{ {
CW, CW, CCW, INTERSECT
CCW,
INTERSECT
} ; } ;
enum Orientation2D enum Orientation2D
{ {
ALIGNED, ALIGNED, RIGHT, LEFT
RIGHT,
LEFT
} ; } ;
/** /**
...@@ -53,21 +49,21 @@ enum Orientation2D ...@@ -53,21 +49,21 @@ enum Orientation2D
* return INTERSECT if (a,b) and (c,d) intersect each other * return INTERSECT if (a,b) and (c,d) intersect each other
*/ */
template <typename VEC3> template <typename VEC3>
OrientationLine testOrientationLines(const VEC3& a, const VEC3& b, const VEC3& c, const VEC3& d) OrientationLine testOrientationLines(const VEC3& a, const VEC3& b, const VEC3& c, const VEC3& d)
{ {
typedef typename VEC3::DATA_TYPE T ; typedef typename VEC3::DATA_TYPE T ;
T vol = tetraSignedVolume(a,b,c,d) ; T vol = tetraSignedVolume(a, b, c, d) ;
return vol > T(0) ? CCW : vol < T(0) ? CW : INTERSECT ; return vol > T(0) ? CCW : vol < T(0) ? CW : INTERSECT ;
} }
/** /**
* return the orientation of point P w.r.t. the plane defined by 3 points * return the orientation of point P w.r.t. the plane defined by 3 points
* @param P the point * @param P the point
* @param A plane point 1 * @param A plane point 1
* @param B plane point 2 * @param B plane point 2
* @param C plane point 3 * @param C plane point 3
* @return the orientation * @return the orientation
*/ */
template <typename VEC3> template <typename VEC3>
Orientation3D testOrientation3D(const VEC3& P, const VEC3& A, const VEC3& B, const VEC3& C) Orientation3D testOrientation3D(const VEC3& P, const VEC3& A, const VEC3& B, const VEC3& C)
{ {
...@@ -77,12 +73,12 @@ Orientation3D testOrientation3D(const VEC3& P, const VEC3& A, const VEC3& B, con ...@@ -77,12 +73,12 @@ Orientation3D testOrientation3D(const VEC3& P, const VEC3& A, const VEC3& B, con
} }
/** /**
* return the orientation of point P w.r.t. the plane defined by its normal and 1 point * return the orientation of point P w.r.t. the plane defined by its normal and 1 point
* @param P the point * @param P the point
* @param N plane normal * @param N plane normal
* @param PP plane point * @param PP plane point
* @return the orientation * @return the orientation
*/ */
template <typename VEC3> template <typename VEC3>
Orientation3D testOrientation3D(const VEC3& P, const VEC3& N, const VEC3& PP) Orientation3D testOrientation3D(const VEC3& P, const VEC3& N, const VEC3& PP)
{ {
...@@ -92,15 +88,54 @@ Orientation3D testOrientation3D(const VEC3& P, const VEC3& N, const VEC3& PP) ...@@ -92,15 +88,54 @@ Orientation3D testOrientation3D(const VEC3& P, const VEC3& N, const VEC3& PP)
} }
/** /**
* return the orientation of point P w.r.t. the vector (Pb-Pa) * return the orientation of point P w.r.t. the vector (Pb-Pa)
* --> tells if P is on/right/left of the line (Pa,Pb) * --> tells if P is on/right/left of the line (Pa,Pb)
* @param P the point * @param P the point
* @param Pa origin point * @param Pa origin point
* @param Pb end point * @param Pb end point
* @return the orientation * @return the orientation
*/ */
template <typename VEC3>
Orientation2D testOrientation2D(const VEC3& P, const VEC3& Pa, const VEC3& Pb) ;
/**
* return the relative orientation of two vectors in the plane (u,v)
* the return value is
* +1 if u^v > 0
* 0 if u^v = 0
* -1 if u^v < 0
* @param u first vector
* @param v second vector
* @return the orientation
*/
template <typename VEC3>
int orientation2D(const VEC3& u, const VEC3& v) ;
/**
* test if two vectors are aligned or orthogonal, the return value is
* +1 if u and v are ALIGNED and u*v > 0
* 0 if u and v are ORTHOGONAL or u*v = 0
* -1 if u and v are ALIGNED and u*v < 0
* @param u first vector
* @param v second vector
* @return the alignment
*/
template <typename VEC3>
int aligned2D(const VEC3& u, const VEC3& v) ;
/**
* test if vector u is between vectors v and w in the plane (v,w)
* in other words if u is inside the angular sector [v,w[
* (v being included and w being is excluded)
* if u,v,w are aligned the result is true
*
* @param u first vector of the angular sector
* @param v second vector of the angular sector
* @param w the vector to test
* @return the result of the test
*/
template <typename VEC3> template <typename VEC3>
Orientation2D testOrientation2D(const VEC3& P, const VEC3& Pa, const VEC3& Pb); bool isBetween(const VEC3& u, const VEC3& v, const VEC3& w) ;
/** /**
* test if the tetrahedron is well oriented depending on the orientation of the faces we want * test if the tetrahedron is well oriented depending on the orientation of the faces we want
......
...@@ -35,29 +35,76 @@ Orientation2D testOrientation2D(const VEC3& P, const VEC3& Pa, const VEC3& Pb) ...@@ -35,29 +35,76 @@ Orientation2D testOrientation2D(const VEC3& P, const VEC3& Pa, const VEC3& Pb)
{ {
typedef typename VEC3::DATA_TYPE T ; typedef typename VEC3::DATA_TYPE T ;
// const T min = std::numeric_limits<T>::min()*T(100); const T zero = 0.0001 ;
const T min = 0.0001;
T p = (P[0] - Pa[0]) * (Pb[1] - Pa[1]) - (Pb[0] - Pa[0]) * (P[1] - Pa[1]) ;
// T wsof = (Pa[0]-P[0])*(P[1]-Pb[1])-(P[0]-Pb[0])*(Pa[1]-P[1]); if (p > zero)
T wsof = (P[0]-Pa[0])*(Pb[1]-Pa[1])-(Pb[0]-Pa[0])*(P[1]-Pa[1]);
if(wsof>min)
return RIGHT ; return RIGHT ;
else if(fabs(wsof)>min) else if (-p > zero)
return LEFT; return LEFT ;
else
return ALIGNED; return ALIGNED ;
}
// VEC3 dir = Pb - Pa ;
// VEC3 Np = dir ^ N ; // TODO use triple product with a normal to the plane that contains u and v
// int o3d = testOrientation3D(P, Np, Pa) ; template <typename VEC3>
// switch(o3d) int orientation2D(const VEC3& u, const VEC3& v)
// { {
// case ON : return ALIGNED ; typedef typename VEC3::DATA_TYPE T ;
// case OVER : return RIGHT ;
// case UNDER : return LEFT ; T p = u[0] * v[1] - u[1] * v[0] ;
// } const T zero = 0.0001 ;
if (p > zero)
return 1 ;
else if (-p > zero)
return -1 ;
else
return 0 ;
}
// TODO use dot product => include epsilon in vector_gen to test sign
template <typename VEC3>
int aligned2D(const VEC3& u, const VEC3& v)
{
typedef typename VEC3::DATA_TYPE T ;
T p = u[0] * v[0] + u[1] * v[1] ;
const T zero = 0.0001 ;
if (p > zero)
return 1 ;
else if (-p > zero)
return -1 ;
else
return 0 ;
}
template <typename VEC3>
bool isBetween(const VEC3& u, const VEC3& v, const VEC3& w)
{
int orientWV = orientation2D(w,v) ;
if (orientWV > 0)
{
if (orientation2D(v,u) >= 0) return true ;
int orientWU = orientation2D(w,u) ;
if (orientWU < 0) return true ;
return (orientWU == 0) && (aligned2D(w,u) <= 0) ;
}
else if (orientWV < 0 || (orientWV == 0 && aligned2D(w,v) < 0))
{
if (orientation2D(v,u) < 0) return false ;
int orientWU = orientation2D(w,u) ;
if (orientWU < 0) return true ;
return (orientWU == 0) && (aligned2D(w,u) <= 0) ;
}
else // orientWV == 0 && v*u >= 0
// ==> v et u ont même direction ou sont nuls
{
return (orientation2D(v,u) == 0 && aligned2D(v,u) >= 0) ;
}
} }
template <typename VEC3> template <typename VEC3>
...@@ -72,7 +119,7 @@ bool isTetrahedronWellOriented(const VEC3 points[4], bool CCW) ...@@ -72,7 +119,7 @@ bool isTetrahedronWellOriented(const VEC3 points[4], bool CCW)
VEC3 N = AB ^ AC ; VEC3 N = AB ^ AC ;
T dot = N * AD ; T dot = N * AD ;
if(CCW) if (CCW)
return dot <= 0