Commit 200b462f authored by Thomas's avatar Thomas
Browse files

ajout fusion sommet, import chemin svg et debug fction geom

parent 3806dbad
......@@ -49,6 +49,8 @@
#include "Algo/Render/GL2/topo3Render.h"
#include "Utils/Shaders/shaderSimpleColor.h"
#include "Utils/cgognStream.h"
#include "Utils/drawer.h"
......
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009-2011, 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.u-strasbg.fr/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
#ifndef __ALGO_BOOLEANOPERATOR_VERTICES_H__
#define __ALGO_BOOLEANOPERATOR_VERTICES_H__
#include "Geometry/basic.h"
#include "Geometry/inclusion.h"
#include "Geometry/orientation.h"
namespace CGoGN
{
namespace Algo
{
namespace BooleanOperator
{
template <typename PFP>
void mergeVertex(typename PFP::MAP& map, const typename PFP::TVEC3& positions, Dart d, Dart e);
template <typename PFP>
void mergeVertices(typename PFP::MAP& map, const typename PFP::TVEC3& positions);
}
}
}
#include "mergeVertices.hpp"
#endif
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009-2011, 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.u-strasbg.fr/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
namespace CGoGN
{
namespace Algo
{
namespace BooleanOperator
{
template <typename PFP>
void mergeVertex(typename PFP::MAP& map, const typename PFP::TVEC3& positions, Dart d, Dart e)
{
assert(Geom::arePointsEquals(positions[d],positions[e]) && !map.sameVertex(d,e));
Dart dd;
do
{
dd = map.alpha1(d);
map.removeEdgeFromVertex(dd);
Dart ee = e;
do
{
if(Geom::testOrientation2D(positions[map.phi1(dd)],positions[ee],positions[map.phi1(ee)])!=Geom::RIGHT
&& Geom::testOrientation2D(positions[map.phi1(dd)],positions[ee],positions[map.phi1(map.alpha1(ee))])==Geom::RIGHT)
{
break;
}
ee = map.alpha1(ee);
} while(ee != e);
map.insertEdgeInVertex(ee,dd);
} while(dd!=d);
}
template <typename PFP>
void mergeVertices(typename PFP::MAP& map, const typename PFP::TVEC3& positions)
{
for(Dart d = map.begin() ; d != map.end() ; map.next(d))
{
CellMarker vM(map,VERTEX);
vM.mark(d);
for(Dart dd = map.begin() ; dd != map.end() ; map.next(dd))
{
if(!vM.isMarked(dd))
{
vM.mark(dd);
if(Geom::arePointsEquals(positions[d],positions[dd]))
{
mergeVertex<PFP>(map,positions,d,dd);
}
}
}
}
}
}
}
}
......@@ -95,7 +95,7 @@ void exportMeshWire(std::ofstream& out, typename PFP::MAP& map, typename PFP::TV
if(position[dd][0]!=position[map.phi1(dd)][0] || position[dd][1]!=position[map.phi1(dd)][1] || position[dd][2]!=position[map.phi1(dd)][2]) {
out << "cylinder{ " << std::endl;
out << "<" << position[dd][0] << "," << position[dd][2] << "," << position[dd][1] << ">," << std::endl;
out << "<" << position[map.phi1(dd)][0] << "," << position[map.phi1(dd)][2] << "," << position[map.phi1(dd)][1] << ">, 0.5" << std::endl;
out << "<" << position[map.phi1(dd)][0] << "," << position[map.phi1(dd)][2] << "," << position[map.phi1(dd)][1] << ">, 1.5" << std::endl;
out << "}" << std::endl;
}
dd = map.phi1(dd);
......
......@@ -16,7 +16,7 @@ namespace Import
* @param name the name
* @ return true if node has the good name
*/
bool chechXmlNode(xmlNodePtr node, const std::string& name);
bool checkXmlNode(xmlNodePtr node, const std::string& name);
template <typename PFP>
bool importSVG(typename PFP::MAP& map, const std::string& filename, typename PFP::TVEC3& position, CellMarker& polygons);
......
#include <iostream>
#include "Geometry/bounding_box.h"
#include "Geometry/plane_3d.h"
#include "Algo/BooleanOperator/mergeVertices.h"
#include <limits>
namespace CGoGN
......@@ -11,7 +13,7 @@ namespace Algo
namespace Import
{
inline bool chechXmlNode(xmlNodePtr node, const std::string& name)
inline bool checkXmlNode(xmlNodePtr node, const std::string& name)
{
return (strcmp((char*)(node->name),(char*)(name.c_str())) == 0);
}
......@@ -31,43 +33,10 @@ bool posSort(const std::pair<VEC, Dart>& a1, const std::pair<VEC, Dart>& a2)
return v1[0] < v2[0] || (v1[0] == v2[0] && v1[1] < v2[1]);
}
template <typename PFP>
bool importSVG(typename PFP::MAP& map, const std::string& filename, typename PFP::TVEC3& position, CellMarker& polygons, CellMarker& polygonsFaces)
template <typename VEC3>
void getPolygonFromSVG(std::string allcoords, std::vector<VEC3>& curPoly, bool& closedPoly)
{
typedef typename PFP::VEC3 VEC3;
typedef std::vector<VEC3 > POLYGON;
xmlDocPtr doc = xmlReadFile(filename.c_str(), NULL, 0);
xmlNodePtr map_node = xmlDocGetRootElement(doc);
if (!chechXmlNode(map_node,"svg"))
{
CGoGNerr << "Wrong xml format: Root node != svg"<< CGoGNendl;
return false;
}
std::vector<POLYGON> allPoly;
std::vector<POLYGON> allBrokenLines;
std::vector<float> allBrokenLinesWidth;
for (xmlNode* cur_node = map_node->children; cur_node; cur_node = cur_node->next)
{
// for each layer
if (chechXmlNode(cur_node, "g"))
{
CGoGNout << "----load layer----"<< CGoGNendl;
for (xmlNode* cur_path = cur_node->children; cur_path; cur_path = cur_path->next)
{
if (chechXmlNode(cur_path, "path"))
{
bool closedPoly=false;
POLYGON curPoly;
CGoGNout << "--load a path--"<< CGoGNendl;
xmlChar* prop = xmlGetProp(cur_path, BAD_CAST "d");
// CGoGNout << "path "<< prop << CGoGNendl;
std::string allcoords((reinterpret_cast<const char*>(prop)));
closedPoly=false;
std::stringstream is(allcoords);
bool relative=false;
bool push_point;
......@@ -197,33 +166,77 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, typename PFP
if(push_point)
{
if(relative && curPoly.size()>0)
VEC3 previous;
if(curPoly.size()>0)
previous = (curPoly)[(curPoly).size()-1];
if(relative)
{
VEC3 previous = (curPoly)[(curPoly).size()-1];
x += previous[0];
y += previous[1];
}
std::cout << "coord " << x << " " << y << std::endl;
// std::cout << "coord " << x << " " << y << std::endl;
if(curPoly.size()==0 || (curPoly.size()>0 && (x!=previous[0] || y!= previous[1])))
curPoly.push_back(VEC3(x,y,0));
}
}
}
template <typename PFP>
bool importSVG(typename PFP::MAP& map, const std::string& filename, typename PFP::TVEC3& position, CellMarker& polygons, CellMarker& polygonsFaces)
{
typedef typename PFP::VEC3 VEC3;
typedef std::vector<VEC3 > POLYGON;
xmlDocPtr doc = xmlReadFile(filename.c_str(), NULL, 0);
xmlNodePtr map_node = xmlDocGetRootElement(doc);
if (!checkXmlNode(map_node,"svg"))
{
CGoGNerr << "Wrong xml format: Root node != svg"<< CGoGNendl;
return false;
}
std::vector<POLYGON> allPoly;
std::vector<POLYGON> allBrokenLines;
std::vector<float> allBrokenLinesWidth;
bool closedPoly;
for (xmlNode* cur_node = map_node->children; cur_node; cur_node = cur_node->next)
{
// for each layer
if (checkXmlNode(cur_node, "g"))
{
// CGoGNout << "----load layer----"<< CGoGNendl;
for (xmlNode* cur_path = cur_node->children ; cur_path; cur_path = cur_path->next)
{
if (checkXmlNode(cur_path, "path"))
{
POLYGON curPoly;
// CGoGNout << "--load a path--"<< CGoGNendl;
xmlChar* prop = xmlGetProp(cur_path, BAD_CAST "d");
std::string allcoords((reinterpret_cast<const char*>(prop)));
getPolygonFromSVG(allcoords,curPoly,closedPoly);
//check orientation : set in CCW
if(curPoly.size()>2)
{
VEC3 v1(curPoly[1]-curPoly[0]);
VEC3 v2(curPoly[2]-curPoly[1]);
if((v1^v2)[2]<0)
if((v1^v2)[2]>0)
{
std::cout << "reverse !" << std::endl;
std::reverse(curPoly.begin(), curPoly.end());
}
}
if(closedPoly)
allPoly.push_back(curPoly);
else {
else
{
allBrokenLines.push_back(curPoly);
xmlChar* prop = xmlGetProp(cur_path, BAD_CAST "style");
std::string allstyle((reinterpret_cast<const char*>(prop)));
......@@ -237,13 +250,56 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, typename PFP
std::getline( isSize, style, ':' );
float sizeOfLine;
isSize >> sizeOfLine;
std::cout << "sizeOfLine : " << sizeOfLine << std::endl;
allBrokenLinesWidth.push_back(sizeOfLine);
}
}
}
}
}
}
else
{
xmlNode* cur_path = cur_node;
if (checkXmlNode(cur_path, "path"))
{
POLYGON curPoly;
// CGoGNout << "--load a path--"<< CGoGNendl;
xmlChar* prop = xmlGetProp(cur_path, BAD_CAST "d");
std::string allcoords((reinterpret_cast<const char*>(prop)));
getPolygonFromSVG(allcoords,curPoly,closedPoly);
//check orientation : set in CCW
if(curPoly.size()>2)
{
VEC3 v1(curPoly[1]-curPoly[0]);
VEC3 v2(curPoly[2]-curPoly[1]);
if((v1^v2)[2]>0)
{
std::reverse(curPoly.begin(), curPoly.end());
}
}
if(closedPoly)
allPoly.push_back(curPoly);
else
{
allBrokenLines.push_back(curPoly);
xmlChar* prop = xmlGetProp(cur_path, BAD_CAST "style");
std::string allstyle((reinterpret_cast<const char*>(prop)));
std::stringstream is(allstyle);
std::string style;
while ( std::getline( is, style, ';' ) )
{
if(style.find("stroke-width:")!=std::string::npos)
{
std::stringstream isSize(style);
std::getline( isSize, style, ':' );
float sizeOfLine;
isSize >> sizeOfLine;
std::cout << "sizeOfLine : " << sizeOfLine << std::endl;
allBrokenLinesWidth.push_back(sizeOfLine);
}
}
}
}
}
......@@ -251,13 +307,25 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, typename PFP
xmlFreeDoc(doc);
Geom::BoundingBox<typename PFP::VEC3> bb(*(allBrokenLines.begin()->begin()));
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;
}
CellMarker brokenMark(map,EDGE);
AttributeHandler<float> edgeWidth = map.template addAttribute<float>(FACE, "width");
AttributeHandler<float> edgeWidth = map.template addAttribute<float>(EDGE, "width");
AttributeHandler<NoMathAttribute<Geom::Plane3D<typename PFP::REAL> > > edgePlanes = map.template addAttribute<NoMathAttribute<Geom::Plane3D<typename PFP::REAL> > >(EDGE, "planes");
/////////////////////////////////////////////////////////////////////////////////////////////
//create broken lines
DartMarker brokenL(map);
std::vector<float >::iterator itW = allBrokenLinesWidth.begin();
for(typename std::vector<POLYGON >::iterator it = allBrokenLines.begin() ; it != allBrokenLines.end() ; ++it)
{
......@@ -270,8 +338,6 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, typename PFP
{
unsigned int faceDegree = it->size()*2-2;
Dart d = map.newFace(faceDegree);
edgeWidth[d] = *itW;
std::cout << "newFace " << faceDegree << std::endl;
polygonsFaces.mark(d);
......@@ -280,17 +346,33 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, typename PFP
for(unsigned int i = 0; i<faceDegree/2 ; ++i)
{
map.sewFaces(d1,d_1);
edgeWidth[d1] = *itW;
brokenL.mark(d1);
brokenL.mark(d_1);
d1 = map.phi1(d1);
d_1 = map.phi_1(d_1);
}
for(typename POLYGON::iterator emb = it->begin() ; emb != it->end() ; emb++)
Dart dd = d;
for(typename POLYGON::iterator emb = it->begin(); emb != it->end() ; emb++)
{
position[d] = *emb;
bb.addPoint(*emb);
d = map.phi1(d);
bb->addPoint(*emb);
position[dd] = *emb;
dd = map.phi1(dd);
}
// do
// {
// bb->addPoint(*emb);
// position[dd] = *emb;
// std::cout << "emb " << *emb << std::endl;
// emb++;
// dd = map.phi1(dd);
// } while(dd!=map.phi_1(d));
}
itW++;
......@@ -309,41 +391,63 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, typename PFP
else
{
Dart d = map.newFace(it->size()-1);
std::cout << "newFace " << it->size()-1 << std::endl;
// std::cout << "newFace1 " << it->size()-1 << std::endl;
polygonsFaces.mark(d);
for(typename POLYGON::iterator emb = it->begin() ; emb != it->end() ; emb++)
Dart dd = d;
typename POLYGON::iterator emb = it->begin();
do
{
position[d] = *emb;
bb.addPoint(*emb);
d = map.phi1(d);
bb->addPoint(*emb);
position[dd] = *emb;
emb++;
dd = map.phi1(dd);
} while(dd!=d);
}
}
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);
/////////////////////////////////////////////////////////////////////////////////////////////
//add bounding box
for(Dart d = map.begin(); d != map.end(); map.next(d))
{
polygons.mark(d);
inside.mark(d);
}
CellMarker boundingBox(map,VERTEX);
Dart dBorder = map.newFace(4);
DartMarker close(map);
map.closeMap(close);
VEC3 bbCenter = bb.center();
VEC3 bmin = bb.min();
bmin += 0.3f*(bmin-bbCenter);
VEC3 bmax = bb.max();
bmax -= 0.3f*(bmin-bbCenter);
Algo::BooleanOperator::mergeVertices<PFP>(map,position);
position[dBorder] = bmin;
position[map.phi1(dBorder)] = VEC3(bmax[0],bmin[1],0);
position[map.phi1(map.phi1(dBorder))] = VEC3(bmax[0],bmax[1],0);
position[map.phi_1(dBorder)] = VEC3(bmin[0],bmax[1],0);
/////////////////////////////////////////////////////////////////////////////////////////////
//add bounding box
Dart d = dBorder;
do
{
boundingBox.mark(d);
d = map.phi1(d);
} while(d!=dBorder);
CellMarker boundingBox(map,VERTEX);
// Dart dBorder = map.newFace(4);
//
// VEC3 bbCenter = bb->center();
// VEC3 bmin = bb->min();
// bmin += 0.3f*(bmin-bbCenter);
// VEC3 bmax = bb->max();
// bmax -= 0.3f*(bmin-bbCenter);
//
// position[dBorder] = bmin;
// position[map.phi1(dBorder)] = VEC3(bmax[0],bmin[1],0);
// position[map.phi1(map.phi1(dBorder))] = VEC3(bmax[0],bmax[1],0);
// position[map.phi_1(dBorder)] = VEC3(bmin[0],bmax[1],0);
//
// Dart d = dBorder;
// do
// {
// boundingBox.mark(d);
// d = map.phi1(d);
// } while(d!=dBorder);
/////////////////////////////////////////////////////////////////////////////////////////////
//cut the edges to have a more regular sampling
......@@ -381,91 +485,93 @@ bool importSVG(typename PFP::MAP& map, const std::string& filename, typename PFP
// }
// }
DartMarker inside(map);
for(Dart d = map.begin(); d != map.end(); map.next(d))
{
polygons.mark(d);
inside.mark(d);
}
DartMarker close(map);
map.closeMap(close);
/////////////////////////////////////////////////////////////////////////////////////////////
//process broken lines
CellMarker eMTreated(map,EDGE);
for(Dart d = map.begin();d != map.end(); map.next(d))
{
if(map.phi2(d) != d && map.sameFace(map.phi2(d),d) && !boundingBox.isMarked(d) && inside.isMarked(d))
if(brokenL.isMarked(d) && !eMTreated.isMarked(d))
{
std::cout << "add face" << std::endl;
eMTreated.mark(d);
//insert a quadrangular face in the broken line
// -> we convert broken lines to faces to represent their width
// -> the intersection are then closed
Dart d1 = d;
Dart d2 = map.phi2(d);
Dart d2 = map.phi2(d1);
VEC3 p1 = position[d1];
VEC3 p2 = position[d2];
float width = edgeWidth[d1];
float width = edgeWidth[d1]/2.0f;
if(width==0)
std::cout << "importSVG : error width of path is equal to zero" << std::endl;
VEC3 v = p2-p1;
map.unsewFaces(d);
map.unsewFaces(d1);
Dart dN = map.newFace(4);
//take the orthogonal direction to the path to apply width afterward
VEC3 ortho = v^VEC3(0,0,1);
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.alpha1(d1)==d1)
{
std::cout << "cut1 " << std::endl;
map.cutEdge(map.phi_1(d1));
map.cutEdge(d2);
position[map.phi_1(d1)]=p1-width*ortho;
position[d1]=p1+width*ortho;