Commit 72faa2ea authored by Jund Thomas's avatar Jund Thomas
Browse files

Merge cgogn.unistra.fr:~cazier/CGoGN

parents 974379f0 f2cdf37d
......@@ -40,15 +40,12 @@ bool isBetween(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>
}
template <typename PFP>
void mergeVertex(typename PFP::MAP& map, 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)) ;
typedef typename PFP::VEC3 VEC3;
VEC3 p = positions[d] ;
assert(positions[d].isNear(positions[e], precision) && !map.sameVertex(d, e)) ;
bool notempty = true ;
do // while vertex of e contains more than one dart
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)
......@@ -72,32 +69,32 @@ void mergeVertex(typename PFP::MAP& map, VertexAttribute<typename PFP::VEC3>& po
d = e ;
e = e1 ;
} while (notempty) ;
// 0-embed z on the merged vertex
positions[d] = p ;
}
template <typename PFP>
void mergeVertices(typename PFP::MAP& map, 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);
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))
{
if (map.sameVertex(d,dd)) std::cout << "fusion: sameVertex" << std::endl ;
if (!map.sameVertex(d,dd)) mergeVertex<PFP>(map,positions,d,dd);
// vM.mark(d);
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>();
}
}
......
......@@ -256,10 +256,10 @@ void readCoordAndStyle(xmlNode* cur_path,
}
template <typename PFP>
bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttribute<typename PFP::VEC3>& position, CellMarker<EDGE>& polygons, CellMarker<FACE>& polygonsFaces)
bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttribute<typename PFP::VEC3>& position, CellMarker<EDGE>& obstacleMark, CellMarker<FACE>& buildingMark)
{
typedef typename PFP::VEC3 VEC3;
typedef std::vector<VEC3 > POLYGON;
typedef std::vector<VEC3> POLYGON;
xmlDocPtr doc = xmlReadFile(filename.c_str(), NULL, 0);
xmlNodePtr map_node = xmlDocGetRootElement(doc);
......@@ -289,17 +289,6 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
xmlFreeDoc(doc);
Geom::BoundingBox<typename PFP::VEC3> * bb;
if(allBrokenLines.size()>0)
bb = new Geom::BoundingBox<typename PFP::VEC3>(*(allBrokenLines.begin()->begin()));
else if(allPoly.size()>0)
bb = new Geom::BoundingBox<typename PFP::VEC3>(*(allPoly.begin()->begin()));
else
{
std::cerr << " no usable data in svg file " << std::endl;
return false;
}
std::cout << "importSVG : XML read." << std::endl;
CellMarker<EDGE> brokenMark(map);
......@@ -310,10 +299,9 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
//create broken lines
DartMarker brokenL(map);
unsigned int nbVertices = 0 ;
typename std::vector<POLYGON >::iterator it;
std::vector<float >::iterator itW = allBrokenLinesWidth.begin();
for(typename std::vector<POLYGON >::iterator it = allBrokenLines.begin() ; it != allBrokenLines.end() ; ++it)
for(it = allBrokenLines.begin() ; it != allBrokenLines.end() ; ++it, ++itW)
{
if(it->size()<2)
{
......@@ -322,130 +310,85 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
}
else
{
nbVertices += it->size() ;
Dart d = map.newPolyLine(it->size()-1);
Dart d = map.newFace(it->size()*2-2,false);
Dart d1=d;
Dart d_1=map.phi_1(d);
//build a degenerated "line" face
for(unsigned int i = 0; i<it->size() ; ++i)
for(typename POLYGON::iterator emb = it->begin(); emb != it->end() ; emb++)
{
brokenL.mark(d1);
brokenL.mark(d_1);
map.sewFaces(d1,d_1,false) ;
brokenL.mark(d);
brokenL.mark(map.phi2(d));
edgeWidth[d1] = *itW;
edgeWidth[d] = *itW;
if (*itW == 0)
std::cout << "importSVG : null path width" << std::endl ;
d1 = map.phi1(d1);
d_1 = map.phi_1(d_1);
}
// polygonsFaces.mark(d);
//embed the line
d1 = d;
for(typename POLYGON::iterator emb = it->begin(); emb != it->end() ; emb++)
{
bb->addPoint(*emb);
position[d1] = *emb;
d1 = map.phi1(d1);
position[d] = *emb;
d = map.phi1(d);
}
}
itW++;
}
std::cout << "importSVG : broken lines created : " << nbVertices << " vertices"<< std::endl;
std::cout << "importSVG : broken lines created : " << std::endl;
/////////////////////////////////////////////////////////////////////////////////////////////
Algo::BooleanOperator::mergeVertices<PFP>(map,position);
// Merge near vertices
Algo::BooleanOperator::mergeVertices<PFP>(map,position,1);
std::cout << "importSVG : Merging of vertices." << std::endl;
/////////////////////////////////////////////////////////////////////////////////////////////
//create polygons
typename std::vector<POLYGON >::iterator it;
for(it = allPoly.begin() ; it != allPoly.end() ; ++it)
{
if(it->size()<4)
if(it->size()<3)
{
it = allPoly.erase(it);
}
else
{
Dart d = map.newFace(it->size());
// std::cout << "newFace1 " << it->size()-1 << std::endl;
polygonsFaces.mark(d);
buildingMark.mark(d);
buildingMark.mark(map.phi2(d));
Dart dd = d;
typename POLYGON::iterator emb = it->begin();
do
for(typename POLYGON::iterator emb = it->begin(); emb != it->end() ; emb++)
{
bb->addPoint(*emb);
position[dd] = *emb;
emb++;
dd = map.phi1(dd);
} while(dd!=d);
position[d] = *emb;
obstacleMark.mark(d);
d = map.phi1(d);
}
}
}
Geom::BoundingBox<typename PFP::VEC3> bb ;
bb = Algo::Geometry::computeBoundingBox<PFP>(map, position) ;
float tailleX = bb.size(0) ;
float tailleY = bb.size(1) ;
float tailleM = std::max<float>(tailleX, tailleY) / 20 ;
std::cout << "bounding box = " << tailleX << " X " << tailleY << std::endl;
for(Dart d = map.begin();d != map.end(); map.next(d))
{
if(position[d][0] == position[map.phi1(d)][0] && position[d][1] == position[map.phi1(d)][1])
std::cout << "prob d " << d << std::endl;
}
DartMarker inside(map);
for(Dart d = map.begin(); d != map.end(); map.next(d))
{
polygons.mark(d);
inside.mark(d);
}
std::cout << "importSVG : Polygons generated." << std::endl;
/////////////////////////////////////////////////////////////////////////////////////////////
//simplify the edges to have a more regular sampling
float minDist = 20.0f ;
for (Dart d = map.begin() ; d != map.end() ; map.next(d))
{
if(!polygons.isMarked(d))
{
bool canSimplify = true ;
while ( canSimplify && ((position[map.phi1(d)] - position[d]).norm() < minDist) )
{
if (map.vertexDegree(map.phi1(d)) == 2) {
map.uncutEdge(d) ;
}
else canSimplify = false ;
}
}
}
std::cout << "importSVG : Downsampling of vertices." << std::endl;
/////////////////////////////////////////////////////////////////////////////////////////////
//cut the edges to have a more regular sampling
float maxDist = 40.0f ;
CellMarker<EDGE> treated(map) ;
for (Dart d = map.begin() ; d != map.end() ; map.next(d))
TraversorE<typename PFP::MAP> edges(map) ;
unsigned int count = 0 ;
for (Dart d = edges.begin() ; d != edges.end() ; d = edges.next())
{
if (!polygons.isMarked(d) && !treated.isMarked(d))
if (!buildingMark.isMarked(d))
{
treated.mark(d) ;
VEC3 p1 = position[d] ;
VEC3 p2 = position[map.phi1(d)] ;
VEC3 v = p2 - p1 ;
float length = v.norm() ;
if (v.norm() > maxDist)
if (length > tailleM)
{
unsigned int nbSeg = (unsigned int)(v.norm() / maxDist) ;
unsigned int nbSeg = (unsigned int)(length / tailleM) ;
v /= nbSeg ;
count += nbSeg ;
for (unsigned int i = 0 ; i < nbSeg - 1 ; ++i)
map.cutEdge(d) ;
......@@ -464,7 +407,27 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
}
}
}
std::cout << "importSVG : Refinement of long edges." << std::endl;
std::cout << "importSVG : Subdivision of long edges : " << count << " morceaux."<< std::endl;
/////////////////////////////////////////////////////////////////////////////////////////////
//simplify the edges to have a more regular sampling
count = 0 ;
for (Dart d = map.begin() ; d != map.end() ; map.next(d))
{
if(!buildingMark.isMarked(d))
{
bool canSimplify = true ;
while ( canSimplify && ((position[map.phi1(d)] - position[d]).norm() < edgeWidth[d]) )
{
if (map.vertexDegree(map.phi1(d)) == 2) {
map.uncutEdge(d) ;
count++;
}
else canSimplify = false ;
}
}
}
std::cout << "importSVG : Downsampling of vertices : " << count << " sommets supprimés." << std::endl;
/////////////////////////////////////////////////////////////////////////////////////////////
//process broken lines
......@@ -492,8 +455,6 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
ortho.normalize() ;
v.normalize() ;
//if the valence of one of the vertex is equal to one
//cut the edge to insert the quadrangular face
if(map.vertexDegree(d1)==2)
......@@ -502,7 +463,7 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
brokenL.mark(map.phi1(d2)) ;
eMTreated.mark(map.phi1(d2)) ;
map.sewFaces(map.phi_1(d1), map.phi1(dN)) ;
obstacleMark.mark(map.phi_1(d1)) ;
position[map.phi_1(d1)] = p1 ;
edgePlanes[map.phi_1(d1)] = Geom::Plane3D<typename PFP::REAL>(v, p1) ;
}
......@@ -512,26 +473,24 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
map.cutEdge(d1) ;
brokenL.mark(map.phi1(d1)) ;
eMTreated.mark(map.phi1(d1)) ;
map.sewFaces(map.phi_1(d2), map.phi_1(dN)) ;
obstacleMark.mark(map.phi_1(d2)) ;
position[map.phi_1(d2)] = p2 ;
edgePlanes[map.phi_1(d2)] = Geom::Plane3D<typename PFP::REAL>(-1.0f * v, p2) ;
}
map.sewFaces(d1, dN) ;
map.sewFaces(d2, map.phi1(map.phi1(dN))) ;
obstacleMark.mark(d1) ;
edgePlanes[d1] = Geom::Plane3D<typename PFP::REAL>(ortho, p1 - (width * ortho)) ;
map.sewFaces(d2, map.phi1(map.phi1(dN))) ;
obstacleMark.mark(d2) ;
edgePlanes[d2] = Geom::Plane3D<typename PFP::REAL>(-1.0f * ortho, p2 + (width * ortho)) ;
}
}
//close the intersections
for (Dart d = map.begin() ; d != map.end() ; map.next(d))
{
if (d == map.phi2(d)) map.closeHole(d) ;
}
map.closeMap() ;
//embed the path
for (Dart d = map.begin() ; d != map.end() ; map.next(d))
......@@ -545,9 +504,6 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
pl = edgePlanes[d] ;
pl.project(pos) ;
// pl = edgePlanes[map.phi_1(d)] ;
// pl.project(pos) ;
position[d] = pos ;
pos = position[map.phi1(d)] ;
......@@ -555,122 +511,6 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, VertexAttrib
position[map.phi1(d)] = pos ;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
//process polygons
// std::vector<std::pair<VEC3,Dart> > toConnect;
// CellMarker connected(map,VERTEX);
// for(Dart d = map.begin(); d != map.end(); map.next(d))
// {
// if( ((!boundingBox.isMarked(d) && !inside.isMarked(d)) || (boundingBox.isMarked(d) && inside.isMarked(d)))
// && !connected.isMarked(d)
// )
// {
// connected.mark(d);
// toConnect.push_back(std::make_pair(position[d],d));
// }
// }
//
// std::sort(toConnect.begin(), toConnect.end(),posSort<VEC3>);
//
// for(typename std::vector<std::pair<VEC3 ,Dart > >::iterator it = toConnect.begin(); it != toConnect.end() ; ++it)
// {
// Dart d = it->second;
// typename std::vector<std::pair<VEC3,Dart> >::iterator it2 = it+1;
// if(it2!= toConnect.end())
// {
// Dart dd = it2->second;
// if(!map.sameFace(map.phi2(d),map.phi2(dd)))
// {
// if(!map.sameFace(dd,d)) {
// std::cout << "link" << std::endl;
// map.linkVertices(dd,d);
// }
// else
// {
// map.splitFace(dd,d);
// std::cout << "split" << std::endl;
// }
// }
// }
//
// }
//
// CellMarker connected(map,VERTEX);
// unsigned int i=0;
// for(Dart d = map.begin();d != map.end(); map.next(d))
// {
// if(!connected.isMarked(d) && !boundingBox.isMarked(d) && !inside.isMarked(d))
// {
// i++;
// Dart dMin=map.end();
// float distMin = std::numeric_limits<float>::max();
// for(Dart dd = map.begin(); dd != map.end(); map.next(dd))
// {
// if( (
// (boundingBox.isMarked(dd) && inside.isMarked(dd))
// || (!boundingBox.isMarked(dd) && !inside.isMarked(dd))
// )
// && !map.sameFace(map.phi2(d),map.phi2(dd)))
// {
// if(Geom::testOrientation2D(position[dd], position[d], position[map.phi1(d)]) == Geom::LEFT
// && Geom::testOrientation2D(position[dd], position[d], position[map.phi_1(d)]) == Geom::RIGHT)
// {
// float dist = (position[dd]-position[d]).norm();
// if(dist<distMin)
// {
// distMin = dist;
// dMin = dd;
// }
// }
// }
// }
//
// if(dMin!=map.end())
// {
// bool noIntersect=true;
// CellMarker edgeM(map,EDGE);
// edgeM.mark(d);
// edgeM.mark(dMin);
//// edgeM.mark(map.phi1(d));
//// edgeM.mark(map.phi_1(d));
//// edgeM.mark(map.phi1(dMin));
//// edgeM.mark(map.phi_1(dMin));
// for(Dart dd = map.begin();noIntersect && dd != map.end(); map.next(dd))
// {
// if(!edgeM.isMarked(dd))
// {
// edgeM.mark(dd);
// VEC3 inter;
// Geom::Intersection eeI = Geom::intersection2DSegmentSegment(position[dd],position[map.phi1(dd)],position[dMin],position[d],inter);
// if(eeI ==Geom::EDGE_INTERSECTION)
// {
// noIntersect=false;
//// std::cout << "dd " << dd << " d " << d << " dMin " << dMin << std::endl;
// std::cout << " pos " << position[dd] << " ; " << position[map.phi1(dd)] << std::endl;
// }
// }
// }
//
// if(noIntersect)
// {
// if(!map.sameFace(dMin,d)) {
// connected.mark(d);
// connected.mark(dMin);
// map.linkVertices(dMin,d);
// }
// else
// {
// map.splitFace(dMin,d);
// connected.mark(d);
// connected.mark(dMin);
// }
// }
// }
// }
// }
return true ;
}
......
......@@ -152,13 +152,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 +182,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) ;
......
......@@ -315,9 +315,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) ;
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
{
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 +354,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)
{
......
......@@ -40,7 +40,10 @@ public:
typedef Map2 TOPO_MAP;