Commit 9e0f43d3 authored by untereiner's avatar untereiner

...

parent b4752e7e
......@@ -24,6 +24,7 @@
#include "Algo/Geometry/normal.h"
#include "Algo/Geometry/centroid.h"
#include "intersection.h"
#include <limits>
......@@ -37,17 +38,18 @@ namespace Geometry
{
template <typename PFP>
bool intersectionLineConvexFace(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& position, const typename PFP::VEC3& P, const typename PFP::VEC3& Dir, typename PFP::VEC3& Inter)
bool intersectionLineConvexFace(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& positions, const typename PFP::VEC3& P, const typename PFP::VEC3& Dir, typename PFP::VEC3& Inter)
{
typedef typename PFP::VEC3 VEC3 ;
const float SMALL_NUM = std::numeric_limits<typename PFP::REAL>::min() * 5.0f;
VEC3 p1 = position[d];
VEC3 n = faceNormal<PFP>(map, d, position);
VEC3 p1 = positions[d];
VEC3 n = faceNormal<PFP>(map,d,positions);
VEC3 w0 = P - p1;
float a = -(n * w0);
float b = n * Dir;
float a = -(n*w0);
float b = n*Dir;
if (fabs(b) < SMALL_NUM)
return false;
......@@ -56,7 +58,7 @@ bool intersectionLineConvexFace(typename PFP::MAP& map, Dart d, const typename P
Inter = P + r * Dir; // intersect point of ray and plane
// is I inside the face?
VEC3 p2 = position[map.phi1(d)];
VEC3 p2 = positions[map.phi1(d)];
VEC3 v = p2 - p1 ;
VEC3 vInter = Inter - p1;
float dirV = v * vInter;
......@@ -67,7 +69,7 @@ bool intersectionLineConvexFace(typename PFP::MAP& map, Dart d, const typename P
while(it != d)
{
p1 = p2;
p2 = position[map.phi1(it)];
p2 = positions[map.phi1(it)];
v = p2 - p1;
vInter = Inter - p1;
float dirD = v * vInter;
......@@ -83,22 +85,22 @@ bool intersectionLineConvexFace(typename PFP::MAP& map, Dart d, const typename P
}
template <typename PFP>
bool intersectionSegmentConvexFace(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& position, const typename PFP::VEC3& PA, const typename PFP::VEC3& PB, typename PFP::VEC3& Inter)
bool intersectionSegmentConvexFace(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& positions, const typename PFP::VEC3& PA, const typename PFP::VEC3& PB, typename PFP::VEC3& Inter)
{
typename PFP::VEC3 dir = PB - PA;
if (intersectionLineConvexFace(map, d, position, PA, dir, Inter))
if (intersectionLineConvexFace(map,d,positions,PA,dir,Inter))
{
typename PFP::VEC3 dirA = PA - Inter;
typename PFP::VEC3 dirB = PB - Inter;
typename PFP::VEC3 dirB = PB -Inter;
if (dirA * dirB < 0)
if ( (dirA*dirB) < 0 )
return true;
}
return false;
}
template <typename PFP>
bool areTrianglesInIntersection(typename PFP::MAP& map, Dart tri1, Dart tri2, const typename PFP::TVEC3& position)
bool areTrianglesInIntersection(typename PFP::MAP& map, Dart tri1, Dart tri2, const typename PFP::TVEC3& positions)
{
typedef typename PFP::VEC3 VEC3 ;
......@@ -107,8 +109,8 @@ bool areTrianglesInIntersection(typename PFP::MAP& map, Dart tri1, Dart tri2, co
VEC3 tris2[3];
for (unsigned int i = 0; i < 3; ++i)
{
tris1[i] = position[tri1];
tris2[i] = position[tri2];
tris1[i] = positions[tri1];
tris2[i] = positions[tri2];
tri1 = map.phi1(tri1);
tri2 = map.phi1(tri2);
}
......@@ -165,8 +167,8 @@ bool areTrianglesInIntersection(typename PFP::MAP& map, Dart tri1, Dart tri2, co
// return isSegmentInTriangle2D(inter1,inter2,tris2[0],tris2[1],triS2[2],nTri2);
//compute face normal
VEC3 normale1 = faceNormal<PFP>(map, tri1, position);
VEC3 bary1 = faceCentroid<PFP>(map, tri1, position);
VEC3 normale1 = faceNormal<PFP>(map,tri1,positions);
VEC3 bary1 = faceCentroid<PFP>(map,tri1,positions);
int pos = 0;
int neg = 0;
......@@ -186,8 +188,8 @@ bool areTrianglesInIntersection(typename PFP::MAP& map, Dart tri1, Dart tri2, co
return false;
//same for the second triangle
VEC3 normale2 = faceNormal<PFP>(map, tri2, position);
VEC3 bary2 = faceCentroid<PFP>(map, tri2, position);
VEC3 normale2 = faceNormal<PFP>(map,tri2,positions);
VEC3 bary2 = faceCentroid<PFP>(map,tri2,positions);
pos = 0;
neg = 0;
for (unsigned int i = 0; i < 3 ; ++i)
......@@ -208,7 +210,7 @@ bool areTrianglesInIntersection(typename PFP::MAP& map, Dart tri1, Dart tri2, co
for (unsigned int i = 0; i < 3 && !intersection; ++i)
{
VEC3 inter;
intersection = Geom::intersectionSegmentTriangle(tris1[i], tris1[(i+1)%3], tris2[0], tris2[1], tris2[2], inter);
intersection = Geom::intersectionSegmentTriangle(tris1[i],tris1[(i+1)%3],tris2[0],tris2[1],tris2[2],inter);
}
if (intersection)
......@@ -217,34 +219,14 @@ bool areTrianglesInIntersection(typename PFP::MAP& map, Dart tri1, Dart tri2, co
for (unsigned int i = 0; i < 3 && !intersection; ++i)
{
VEC3 inter;
intersection = Geom::intersectionSegmentTriangle(tris2[i], tris2[(i+1)%3], tris1[0], tris1[1], tris1[2], inter);
intersection = Geom::intersectionSegmentTriangle(tris2[i],tris2[(i+1)%3],tris1[0],tris1[1],tris1[2],inter);
}
return intersection;
}
template <typename PFP>
bool intersectionSphereEdge(typename PFP::MAP& map, typename PFP::VEC3& center, typename PFP::REAL radius, Dart d, const typename PFP::TVEC3& position, typename PFP::REAL& alpha)
{
typedef typename PFP::VEC3 VEC3 ;
typedef typename PFP::REAL REAL ;
const typename PFP::VEC3& p1 = position[d];
const typename PFP::VEC3& p2 = position[map.phi1(d)];
if(Geom::isPointInSphere(p1, center, radius) && !Geom::isPointInSphere(p2, center, radius))
{
VEC3 p = p1 - center;
VEC3 qminusp = p2 - center - p;
REAL s = p * qminusp;
REAL n2 = qminusp.norm2();
alpha = (- s + sqrt(s*s + n2 * (radius*radius - p.norm2()))) / n2;
return true ;
}
return false ;
}
} // namespace Geometry
} // namespace Algo
}
} // namespace CGoGN
}
#include <iostream>
#include "Geometry/bounding_box.h"
#include "Geometry/plane_3d.h"
#include "Algo/BooleanOperator/mergeVertices.h"
#include <limits>
namespace CGoGN
{
namespace Algo
{
namespace Import
{
inline bool checkXmlNode(xmlNodePtr node, const std::string& name)
{
return (strcmp((char*)(node->name),(char*)(name.c_str())) == 0);
}
template<typename T>
inline bool valueOf(const std::string &s, T &obj)
{
std::istringstream is(s);
return is >> obj;
}
template <typename VEC>
bool posSort(const std::pair<VEC, Dart>& a1, const std::pair<VEC, Dart>& a2)
{
VEC v1 = a1.first;
VEC v2 = a2.first;
return v1[0] < v2[0] || (v1[0] == v2[0] && v1[1] < v2[1]);
}
template <typename VEC3>
void getPolygonFromSVG(std::string allcoords, std::vector<VEC3>& curPoly, bool& closedPoly)
{
closedPoly=false;
std::stringstream is(allcoords);
bool relative=false;
bool push_point;
std::string coord;
int mode = -1;
while ( std::getline( is, coord, ' ' ) )
{
float x,y;
push_point=false;
if(coord[0]=='m' || coord[0]=='l' || coord[0]=='t') //start point, line or quadratic bezier curve
{
mode = 0;
// std::cout << "relative coordinates" << std::endl;
relative=true;
}
else if(coord[0]=='M' || coord[0] == 'L' || coord[0]=='T') //same in absolute coordinates
{
// std::cout << "absolute coordinates" << std::endl;
mode = 1;
relative=false;
}
else if(coord[0]=='h' || coord[0] == 'H') //horizontal line
{
mode = 2;
relative=(coord[0]=='h');
}
else if(coord[0]=='v' || coord[0] == 'V') //vertical line
{
// std::cout << "vertical line" << std::endl;
mode = 3;
relative=(coord[0]=='v');
}
else if(coord[0]=='c' || coord[0] == 'C') //bezier curve
{
// std::cout << "bezier line" << std::endl;
mode = 4;
relative=(coord[0]=='c');
}
else if(coord[0]=='s' || coord[0] == 'S' || coord[0]=='q' || coord[0] == 'Q') //bezier curve 2
{
// std::cout << "bezier line 2" << std::endl;
mode = 5;
relative= ((coord[0]=='s') || (coord[0]=='q'));
}
else if(coord[0]=='a' || coord[0] == 'A') //elliptic arc
{
// std::cout << "elliptic arc" << std::endl;
mode =6;
relative= (coord[0]=='a');
}
else if(coord[0]=='z')
{
// std::cout << "the end" << std::endl;
closedPoly = true;
}
else //coordinates
{
switch(mode)
{
case 0 : //relative
break;
case 1 : //absolute
break;
case 2 : //horizontal
{
std::stringstream streamCoord(coord);
std::string xS;
std::getline(streamCoord, xS, ',' );
valueOf(xS,x);
VEC3 previous = (curPoly)[(curPoly).size()-1];
y = previous[1];
push_point=true;
}
break;
case 3 : //vertical
{
std::stringstream streamCoord(coord);
std::string yS;
std::getline(streamCoord, yS, ',' );
valueOf(yS,y);
typename PFP::VEC3 previous = (curPoly)[(curPoly).size()-1];
x = previous[0];
push_point=true;
}
break;
case 4 : //bezier
{
std::getline( is, coord, ' ' ); //ignore first control point
std::getline( is, coord, ' ' ); //ignore second control point
}
break;
case 5 : //bezier 2
{
std::getline( is, coord, ' ' ); //ignore control point
}
break;
case 6 : //elliptic
std::getline( is, coord, ' ' ); //ignore rx
std::getline( is, coord, ' ' ); //ignore ry
std::getline( is, coord, ' ' ); //ignore x-rotation
std::getline( is, coord, ' ' ); //ignore large arc flag
std::getline( is, coord, ' ' ); //ignore sweep flag
break;
}
std::stringstream streamCoord(coord);
std::string xS,yS;
std::getline(streamCoord, xS, ',' );
std::getline(streamCoord, yS, ',' );
valueOf(xS,x);
valueOf(yS,y);
push_point = true;
}
//if there is a point to push
if(push_point)
{
VEC3 previous;
if(curPoly.size()>0)
previous = (curPoly)[(curPoly).size()-1];
if(relative)
{
x += previous[0];
y += previous[1];
}
// 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)
{
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;
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);
}
}
}
}
}
}
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;
}
CellMarker brokenMark(map,EDGE);
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)
{
if(it->size()<2)
{
it = allBrokenLines.erase(it);
itW = allBrokenLinesWidth.erase(itW);
}
else
{
unsigned int faceDegree = it->size()*2-2;
Dart d = map.newFace(faceDegree);
polygonsFaces.mark(d);
Dart d1=d;
Dart d_1=map.phi_1(d);
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);
}
Dart dd = d;
for(typename POLYGON::iterator emb = it->begin(); emb != it->end() ; emb++)
{
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++;
}
/////////////////////////////////////////////////////////////////////////////////////////////
//create polygons
typename std::vector<POLYGON >::iterator it;
for(it = allPoly.begin() ; it != allPoly.end() ; ++it)
{
if(it->size()<4)
{
it = allPoly.erase(it);
}
else
{
Dart d = map.newFace(it->size()-1);
// std::cout << "newFace1 " << it->size()-1 << std::endl;
polygonsFaces.mark(d);
Dart dd = d;
typename POLYGON::iterator emb = it->begin();
do
{
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);
for(Dart d = map.begin(); d != map.end(); map.next(d))
{
polygons.mark(d);
inside.mark(d);
}
DartMarker close(map);
map.closeMap(close);
Algo::BooleanOperator::mergeVertices<PFP>(map,position);
/////////////////////////////////////////////////////////////////////////////////////////////
//add bounding box
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);