Commit 271c50a6 authored by Sylvain Thery's avatar Sylvain Thery

Merge branch 'master' of cgogn:~jund/CGoGN

Conflicts:
	include/Algo/Import/importSvg.hpp
parents a07476af 0f35dc93
......@@ -45,10 +45,10 @@ template <typename PFP>
bool isBetween(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions, Dart d, Dart e, Dart f) ;
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, VertexAttribute<typename PFP::VEC3>& positions, Dart d, Dart e);
template <typename PFP>
void mergeVertices(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions);
void mergeVertices(typename PFP::MAP& map, VertexAttribute<typename PFP::VEC3>& positions);
}
......
......@@ -43,55 +43,61 @@ bool isBetween(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>
}
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, VertexAttribute<typename PFP::VEC3>& positions, Dart d, Dart e, int precision)
{
assert(Geom::arePointsEquals(positions[d],positions[e]) && !map.sameVertex(d,e));
// d1 traverses the vertex of d (following the alpha1 permutation)
// y is a temporay buffer to stop the loop
Dart d1=d;
// e1 traverses the vertex of e (following the alpha1 permutation)
Dart e1=e;
bool notempty = true;
do {
if (map.phi2_1(e1) == e1) notempty = false;
// detach z from its vertex
map.removeEdgeFromVertex(e1);
// Searchs the dart of the vertex of x where tz may be inserted
Dart nd1 = d1;
do {
if (CGoGN::Algo::BooleanOperator::isBetween<PFP>(map,positions,e1,d1,map.phi2_1(d1))) break;
d1 = map.phi2_1(d1);
} while (d1 != nd1);
map.insertEdgeInVertex(d1,e1);
d1 = e1;
} while (notempty);
assert(positions[d].isNear(positions[e], precision) && !map.sameVertex(d, e)) ;
// 0-embed z on the vertex of x without copy of the vertex
// positions[d] = ;
}
bool notempty = true ;
do // While vertex of e contains more than one dart
{
Dart e1 = map.alpha1(e) ; // e1 stores next dart of vertex of e
if (e1 == e)
notempty = false ; // last dart of vertex of e
else {
map.removeEdgeFromVertex(e) ; // detach e from its vertex
}
// Searchs where e may be inserted in the vertex of d
Dart d1 = d ;
do
{
if (CGoGN::Algo::BooleanOperator::isBetween<PFP>(map, positions, e, d,
map.alpha1(d))) break ;
d = map.alpha1(d) ;
} while (d != d1) ;
// Inserted e in the correct place (after d)
map.insertEdgeInVertex(d, e) ;
// Go on with next darts
d = e ;
e = e1 ;
} while (notempty) ;
}
template <typename PFP>
void mergeVertices(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions)
void mergeVertices(typename PFP::MAP& map, VertexAttribute<typename PFP::VEC3>& positions, int precision)
{
// TODO optimiser en triant les sommets
for(Dart d = map.begin() ; d != map.end() ; map.next(d))
// map.template enableQuickTraversal<VERTEX>();
TraversorV<typename PFP::MAP> travV1(map) ;
CellMarker<VERTEX> vM(map);
for(Dart d1 = travV1.begin() ; d1 != travV1.end() ; d1 = travV1.next())
{
CellMarker<VERTEX> vM(map);
vM.mark(d);
std::cout << "." ; std::cout.flush() ;
for(Dart dd = map.begin() ; dd != map.end() ; map.next(dd))
vM.mark(d1);
TraversorV<typename PFP::MAP> travV2(map) ;
for(Dart d2 = travV2.begin() ; d2 != travV2.end() ; d2 = travV2.next())
{
if(!vM.isMarked(dd))
if(!vM.isMarked(d2))
{
if(Geom::arePointsEquals(positions[d],positions[dd]))
if(positions[d1].isNear(positions[d2], precision))
{
mergeVertex<PFP>(map,positions,d,dd);
if (map.sameVertex(d1,d2)) std::cout << "fusion: sameVertex" << std::endl ;
if (!map.sameVertex(d1,d2)) mergeVertex<PFP>(map,positions,d1,d2,precision);
}
}
}
}
// map.template disableQuickTraversal<VERTEX>();
}
}
......
This diff is collapsed.
......@@ -176,9 +176,6 @@ Dart revolution(typename PFP::MAP& the_map, VertexAttribute<typename PFP::VEC3>&
* @param the_map the map in which include created surface
* @param d a dart of the face to extrude
* @param N the vector use to extrude face center (point) of axis revolution
* @param axis direction of axis revolution
* @param profile_closed profile is a closed polygon or not ?
* @param nbSide number of steps around the revolution
*/
template<typename PFP>
Dart extrudeFace(typename PFP::MAP& the_map, VertexAttribute<typename PFP::VEC3>& positions,
......@@ -188,10 +185,7 @@ Dart extrudeFace(typename PFP::MAP& the_map, VertexAttribute<typename PFP::VEC3>
* Face extrusion
* @param the_map the map in which include created surface
* @param d a dart of the face to extrude
* @param N the vector use to extrude face center (point) of axis revolution
* @param axis direction of axis revolution
* @param profile_closed profile is a closed polygon or not ?
* @param nbSide number of steps around the revolution
* @param dist the height to extrude face
*/
template<typename PFP>
Dart extrudeFace(typename PFP::MAP& the_map, VertexAttribute<typename PFP::VEC3>& positions,
......
......@@ -453,36 +453,42 @@ void LoopSubdivision(typename PFP::MAP& map, VertexAttribute<typename PFP::VEC3>
template <typename PFP, typename EMBV, typename EMB>
void TwoNPlusOneSubdivision(typename PFP::MAP& map, EMBV& attributs, const FunctorSelect& selected)
{
EdgeAutoAttribute<Dart> tablePred(map);
CellMarker<EDGE> m0(map);
CellMarker<FACE> m1(map);
std::vector<Dart> dOrig;
std::vector<EMB> cOrig;
m0.unmarkAll();
m1.unmarkAll();
//first pass cut edge
for (Dart d = map.begin(); d != map.end(); map.next(d))
{
if(selected(d))
{
if(!m0.isMarked(d)) {
dOrig.push_back(d);
Dart dd = d;
do {
if(!m0.isMarked(dd)) {
EMB e1 = attributs[dd];
EMB e2 = attributs[map.phi1(dd)];
map.cutEdge(dd);
attributs[map.phi1(dd)] = e1*2.0f/3.0f+e2/3.0f;
map.cutEdge(map.phi1(dd));
attributs[map.phi1(map.phi1(dd))] = e2*2.0f/3.0f+e1/3.0f;
m0.mark(dd);
m0.mark(map.phi1(dd));
m0.mark(map.template phi<11>(dd));
}
dd = map.template phi<111>(dd);
} while(dd!=d);
if(!m0.isMarked(d))
{
if(!m1.isMarked(d))
{
m1.mark(d);
dOrig.push_back(d);
}
if(selected(map.phi2(d)) && !m1.isMarked(map.phi2(d)))
{
m1.mark(map.phi2(d));
dOrig.push_back(map.phi2(d));
}
EMB e1 = attributs[d];
EMB e2 = attributs[map.phi1(d)];
map.cutEdge(d);
attributs[map.phi1(d)] = e1*2.0f/3.0f+e2/3.0f;
map.cutEdge(map.phi1(d));
attributs[map.phi1(map.phi1(d))] = e2*2.0f/3.0f+e1/3.0f;
m0.mark(d);
m0.mark(map.phi1(d));
m0.mark(map.template phi<11>(d));
}
}
}
......
......@@ -70,14 +70,14 @@ public:
Geom::Orientation2D getOrientationFace(VEC3 sourcePoint, Dart d) ;
void vertexState(const VEC3& current) ;
virtual void vertexState(const VEC3& current) ;
void edgeState(const VEC3& current, Geom::Orientation2D sideOfEdge = Geom::ALIGNED) ;
virtual void edgeState(const VEC3& current, Geom::Orientation2D sideOfEdge = Geom::ALIGNED) ;
//just an orientation test : check which dart is aimed to leave the current face to reach an other position
Dart faceOrientationState(const VEC3& toward) ;
void faceState(const VEC3& current) ;
virtual void faceState(const VEC3& current) ;
void move(const VEC3& goal)
{
......
......@@ -42,11 +42,11 @@ public:
}
void vertexState(const VEC3& current, CellMarkerMemo<FACE>& memo_cross) ;
virtual void vertexState(const VEC3& current, CellMarkerMemo<FACE>& memo_cross) ;
void edgeState(const VEC3& current, CellMarkerMemo<FACE>& memo_cross, Geom::Orientation2D sideOfEdge = Geom::ALIGNED) ;
virtual void edgeState(const VEC3& current, CellMarkerMemo<FACE>& memo_cross, Geom::Orientation2D sideOfEdge = Geom::ALIGNED) ;
void faceState(const VEC3& current, CellMarkerMemo<FACE>& memo_cross) ;
virtual void faceState(const VEC3& current, CellMarkerMemo<FACE>& memo_cross) ;
std::vector<Dart> move(const VEC3& goal) ;
std::vector<Dart> move(const VEC3& goal, CellMarkerMemo<FACE>& memo_cross) ;
......
#ifndef PARTCELL2DMEMOSECURED_H
#define PARTCELL2DMEMOSECURED_H
//#define DEBUG
#include "particle_cell_2D_memo.h"
#include "Algo/Geometry/inclusion.h"
#include "Geometry/intersection.h"
#include "Geometry/orientation.h"
#include <iostream>
/* A particle cell secured : version of particle cell-memo where particles might go outside the navigation map
* this class should be used for debug mode only */
namespace CGoGN
{
namespace Algo
{
namespace MovingObjects
{
template <typename PFP>
class ParticleCell2DSecured : public ParticleCell2DMemo<PFP>
{
typedef typename PFP::MAP MAP ;
typedef typename PFP::VEC3 VEC3;
typedef VertexAttribute<typename PFP::VEC3> TAB_POS ;
private:
ParticleCell2DSecured(){
std::cout << "Particle Secured : for debugging (unoptimized)" << std::endl;
}
public:
ParticleCell2DSecured(MAP& map, Dart belonging_cell, VEC3 pos, const TAB_POS& tabPos) :
ParticleCell2DMemo<PFP>(map, belonging_cell, pos, tabPos)
{
std::cout << "Particle Memo : for debugging (unoptimized)" << std::endl;
}
virtual void vertexState(const VEC3& current, CellMarkerMemo<FACE>& memo_cross) ;
virtual void edgeState(const VEC3& current, CellMarkerMemo<FACE>& memo_cross, Geom::Orientation2D sideOfEdge = Geom::ALIGNED) ;
virtual void faceState(const VEC3& current, CellMarkerMemo<FACE>& memo_cross) ;
std::vector<Dart> move(const VEC3& goal) ;
std::vector<Dart> move(const VEC3& goal, CellMarkerMemo<FACE>& memo_cross) ;
} ;
#include "particle_cell_2D_secured.hpp"
} //MovingObject
} //Algo
} //CGoGN
#endif
template <typename PFP>
std::vector<Dart> ParticleCell2DSecured<PFP>::move(const VEC3& goal)
{
this->crossCell = NO_CROSS ;
if (!Geom::arePointsEquals(goal, this->getPosition()))
{
CellMarkerMemo<FACE> memo_cross(this->m);
// memo_cross.mark(this->d);
switch (this->getState())
{
case VERTEX :
vertexState(goal,memo_cross) ;
break ;
case EDGE :
edgeState(goal,memo_cross) ;
break ;
case FACE :
faceState(goal,memo_cross) ;
break ;
}
return memo_cross.get_markedCells();
}
else
this->ParticleBase<PFP>::move(goal) ;
std::vector<Dart> res;
res.push_back(this->d);
return res;
}
template <typename PFP>
void ParticleCell2DSecured<PFP>::vertexState(const VEC3& current, CellMarkerMemo<FACE>& memo_cross)
{
#ifdef DEBUG
CGoGNout << "vertexState" << this->d << CGoGNendl ;
#endif
// std::vector<Dart> mc = memo_cross.get_markedCells();
// if(std::find(mc.begin(),mc.end(),this->d)!=mc.end())
// {
// std::cout << "Error : particle outside map (vertex) " << std::endl;
// return;
// }
// else
{
assert(std::isfinite(current[0]) && std::isfinite(current[1]) && std::isfinite(current[2])) ;
this->crossCell = CROSS_OTHER ;
if (Algo::Geometry::isPointOnVertex < PFP > (this->m, this->d, this->positionAttribut, current))
{
this->setState(VERTEX) ;
this->ParticleBase<PFP>::move(current) ;
return ;
}
else
{
//orientation step
if (this->positionAttribut[this->d][0] == this->positionAttribut[this->m.phi1(this->d)][0] && this->positionAttribut[this->d][1] == this->positionAttribut[this->m.phi1(this->d)][1])
this->d = this->m.phi2_1(this->d) ;
if (this->getOrientationEdge(current, this->m.phi2_1(this->d)) != Geom::RIGHT)
{
Dart dd_vert = this->d ;
do
{
this->d = this->m.phi2_1(this->d) ;
if (this->positionAttribut[this->d][0] == this->positionAttribut[this->m.phi1(this->d)][0]
&& this->positionAttribut[this->d][1]== this->positionAttribut[this->m.phi1(this->d)][1])
this->d = this->m.phi2_1(this->d) ;
} while (this->getOrientationEdge(current, this->m.phi2_1(this->d)) != Geom::RIGHT && dd_vert != this->d) ;
if (dd_vert == this->d)
{
//orbit with 2 edges : point on one edge
if (this->m.phi2_1(this->m.phi2_1(this->d)) == this->d)
{
if (!Algo::Geometry::isPointOnHalfEdge<PFP>(this->m, this->d, this->positionAttribut, current))
this->d = this->m.phi2_1(this->d) ;
}
else
{
//checking : case with 3 orthogonal darts and point on an edge
do
{
if(Algo::Geometry::isPointOnHalfEdge<PFP>(this->m,this->d,this->positionAttribut,current)
&& Algo::Geometry::isPointOnHalfEdge<PFP>(this->m,this->m.phi2(this->d),this->positionAttribut,current)
&& this->getOrientationEdge(current, this->d) == Geom::ALIGNED)
{
this->edgeState(current,memo_cross) ;
return;
}
this->d = this->m.phi2_1(this->d) ;
} while (this->getOrientationEdge(current, this->m.phi2_1(this->d)) != Geom::RIGHT && dd_vert != this->d) ;
this->ParticleBase<PFP>::move(current) ;
this->setState(VERTEX) ;
return ;
}
}
}
else
{
Dart dd_vert = this->m.phi2_1(this->d) ;
while (this->getOrientationEdge(current, this->d) == Geom::RIGHT && dd_vert != this->d)
{
this->d = this->m.phi12(this->d) ;
if (this->positionAttribut[this->d][0] == this->positionAttribut[this->m.phi1(this->d)][0]
&& this->positionAttribut[this->d][1] == this->positionAttribut[this->m.phi1(this->d)][1])
this->d = this->m.phi12(this->d) ;
}
}
//displacement step
if (this->getOrientationEdge(current, this->d) == Geom::ALIGNED
&& Algo::Geometry::isPointOnHalfEdge<PFP>(this->m, this->d, this->positionAttribut, current))
edgeState(current,memo_cross) ;
else
{
this->d = this->m.phi1(this->d) ;
faceState(current,memo_cross) ;
}
}
}
}
template <typename PFP>
void ParticleCell2DSecured<PFP>::edgeState(const VEC3& current, CellMarkerMemo<FACE>& memo_cross, Geom::Orientation2D sideOfEdge)
{
#ifdef DEBUG
CGoGNout << "edgeState" << this->d << CGoGNendl ;
#endif
// std::vector<Dart> mc = memo_cross.get_markedCells();
// if(std::find(mc.begin(),mc.end(),this->d)!=mc.end())
// {
// std::cout << "Error : particle outside map (edge)" << std::endl;
// return;
// }
// else
{
assert(std::isfinite(current[0]) && std::isfinite(current[1]) && std::isfinite(current[2])) ;
// assert(Algo::Geometry::isPointOnEdge<PFP>(m,d,m_positions,m_position));
if (this->crossCell == NO_CROSS)
{
this->crossCell = CROSS_EDGE ;
this->lastCrossed = this->d ;
}
else
this->crossCell = CROSS_OTHER ;
if (sideOfEdge == Geom::ALIGNED) sideOfEdge = this->getOrientationEdge(current, this->d) ;
switch (sideOfEdge)
{
case Geom::LEFT :
this->d = this->m.phi1(this->d) ;
faceState(current,memo_cross) ;
return ;
case Geom::RIGHT :
this->d = this->m.phi1(this->m.phi2(this->d)) ;
faceState(current,memo_cross) ;
return ;
default :
this->setState(EDGE) ;
break ;
}
if (!Algo::Geometry::isPointOnHalfEdge < PFP
> (this->m, this->d, this->positionAttribut, current))
{
this->ParticleBase<PFP>::move(this->positionAttribut[this->d]) ;
vertexState(current,memo_cross) ;
return ;
}
else if (!Algo::Geometry::isPointOnHalfEdge < PFP
> (this->m, this->m.phi2(this->d), this->positionAttribut, current))
{
this->d = this->m.phi2(this->d) ;
this->ParticleBase<PFP>::move(this->positionAttribut[this->d]) ;
vertexState(current,memo_cross) ;
return ;
}
this->ParticleBase<PFP>::move(current) ;
}
}
template <typename PFP>
void ParticleCell2DSecured<PFP>::faceState(const VEC3& current, CellMarkerMemo<FACE>& memo_cross)
{
#ifdef DEBUG
CGoGNout << "faceState" << this->d << CGoGNendl ;
#endif
std::vector<Dart> mc = memo_cross.get_markedCells();
if(std::find(mc.begin(),mc.end(),this->d)!=mc.end())
{
std::cout << "Error : particle outside map (face)" << std::endl;
return;
}
else
{
ParticleCell2DMemo<PFP>::faceState(current,memo_cross);
}
}
......@@ -35,7 +35,7 @@ Orientation2D testOrientation2D(const VEC3& P, const VEC3& Pa, const VEC3& Pb)
{
typedef typename VEC3::DATA_TYPE T ;
const T zero = 0.0001 ;
const T zero = 0.00001 ;
T p = (P[0] - Pa[0]) * (Pb[1] - Pa[1]) - (Pb[0] - Pa[0]) * (P[1] - Pa[1]) ;
......
......@@ -117,7 +117,7 @@ void Plane3D<T>::project(Vector<3,T>& p) const
{
#define PRECISION 1e-10
T d = -distance(p) ;
if(abs(d) > PRECISION)
if(std::abs(d) > PRECISION)
{
Vector<3,T> v = m_normal * d ;
p += v ;
......
......@@ -127,8 +127,16 @@ public:
double norm() const ;
/*
* normalize the vector and returns its norm
*/
double normalize() ;
/*
* Return a normalized copy
*/
Vector<DIM, T> normalized() const;
// dot product
T operator*(const Vector<DIM, T> v) const ;
......@@ -152,13 +160,21 @@ public:
*/
bool isNormalized(const T& epsilon) const ;
/**
* Tests if current and given vectors are near within 1/precision (equal if precision is zero)
* @param V a vector
* @param epsilon tolerated error
* @return true if orthogonal
*/
bool isNear(const Vector<DIM, T>& v, int precision) const ;
/**
* Tests if current and given vectors are orthogonal
* @param V a vector
* @param epsilon tolerated error
* @return true if orthogonal
*/
bool isOrthogonal(const Vector<DIM, T>& V, const T& epsilon = 1e-5) const ;
bool isOrthogonal(const Vector<DIM, T>& v, const T& epsilon = 1e-5) const ;
/**********************************************/
/* STREAM OPERATORS */
......@@ -174,6 +190,22 @@ private:
T m_data[DIM] ;
} ;
/***
* Test if x is null within precision.
* Two cases are possible :
* - precision == 0 : x is null if (x == 0)
* - precision > 0 : x is null if (|x| < 1/precision) or (precision * |x| < 1)
*/
template <typename T>
bool isNull(T x, int precision = 0) ;
/***
* Test if the square root of x is null within precision.
* In other words, test if x is null within precision*precision
*/
template <typename T>
bool isNull2(T x, int precision = 0) ;
template <unsigned int DIM, typename T>
Vector<DIM, T> operator*(T a, const Vector<DIM, T>& v) ;
......
......@@ -256,6 +256,14 @@ inline double Vector<DIM, T>::normalize()
return n ;
}
template <unsigned int DIM, typename T>
inline Vector<DIM, T> Vector<DIM, T>::normalized() const
{
Vector<DIM, T> v(*this);
v.normalize();
return v;
}
template <unsigned int DIM, typename T>
inline T Vector<DIM, T>::operator*(const Vector<DIM, T> v) const
{
......@@ -315,9 +323,23 @@ inline bool Vector<DIM, T>::isNormalized(const T& epsilon) const
}
template <unsigned int DIM, typename T>
inline bool Vector<DIM, T>::isOrthogonal(const Vector<DIM, T>& V, const T& epsilon) const
inline bool Vector<DIM, T>::isOrthogonal(const Vector<DIM, T>& v, const T& epsilon) const
{
return (fabs(v * (*this)) < epsilon) ;
}
template <unsigned int DIM, typename T>
inline bool Vector<DIM, T>::isNear(const Vector<DIM, T>& v, int precision) const
{
return (fabs(V * (*this)) < epsilon) ;
T diff ;
T norm2(0) ;
for (unsigned int i = 0 ; i < DIM ; ++i)
{
diff = m_data[i] - v[i] ;
if (!isNull(diff, precision)) return false ;
norm2 += diff * diff ;
}
return isNull2(norm2, precision) ;
}
/**********************************************/
......@@ -340,6 +362,39 @@ std::istream& operator>>(std::istream& in, Vector<DIM, T>& v)
return in ;
}
/***
* Test if x is null within precision.
* 3 cases are possible :
* - precision = 0 : x is null <=> (x == 0)
* - precision > 0 : x is null <=> (|x| < precision)
* - precision < 0 : x is null <=> (|x| < 1/precision) <=> (precision * |x| < 1)
*/
template <typename T>
inline bool isNull(T x, int precision)
{
if (precision == 0)
return (x == 0) ;
else if (precision > 0)
return (fabs(x) < precision) ;
else
return (precision * fabs(x) < 1) ;
}
/***
* Test if the square root of x is null within precision.
* In other words, test if x is null within precision*precision
*/
template <typename T>
inline bool isNull2(T x, int precision)
{
if (precision == 0)
return (x == 0) ;
else if (precision > 0)
return (isNull(x, precision * precision)) ;
else
return (isNull(x, - (precision * precision))) ;
}
template <unsigned int DIM, typename T>
inline Vector<DIM, T> operator*(T a, const Vector<DIM, T>& v)
{
......
......@@ -42,7 +42,10 @@ public:
static const unsigned int DIMENSION = 2 ;
/*