From 4002b9a706d1c46e762f022d7b87993eafa18d4d Mon Sep 17 00:00:00 2001 From: ganovelli Date: Mon, 27 Oct 2008 16:50:45 +0000 Subject: [PATCH] created as a first working draft. Tessellates a simple polygon with the earcut algorithm assuming the polygon is almost planar --- vcg/space/planar_polygon_tessellation.h | 142 ++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 vcg/space/planar_polygon_tessellation.h diff --git a/vcg/space/planar_polygon_tessellation.h b/vcg/space/planar_polygon_tessellation.h new file mode 100644 index 00000000..7c59abd4 --- /dev/null +++ b/vcg/space/planar_polygon_tessellation.h @@ -0,0 +1,142 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef __VCGLIB_PLANAR_POLYGON_TESSELLATOR +#define __VCGLIB_PLANAR_POLYGON_TESSELLATOR + +#include +#include +#include + +namespace vcg { + +/** \addtogroup space */ +/*@{*/ + /** + A very simple earcut tessellation of planar 2D polygon. + Input: a vector or Point2<> + Output: a vector of faces as a triple of indices to the input vector + */ + template + bool Cross( const Point2 & p00, + const Point2 & p01, + const Point2 & p10, + const Point2 & p11) + { + Point2 vec0 = p01-p00; + Point2 vec1 = p11-p10; + if ( ( vec0^ (p11-p00)) * ( vec0^ (p10 - p00)) >=0) return false; + if ( ( vec1^ (p01-p10)) * ( vec1^ (p00 - p10)) >=0) return false; + return true; + } + + template + bool Intersect(int cur , int v2, std::vector & next, std::vector > & points2){ + for(int i = 0; i < points2.size();++i) + if( (next[i]!=-1) && (i!=cur)) + if( Cross(points2[cur], points2[v2],points2[i],points2[next[i]])) + return true; + return false; + } + + + template + void TessellatePlanarPolygon2( POINT_CONTAINER & points2, std::vector & output){ + typedef typename POINT_CONTAINER::value_type Point2x; + typedef typename Point2x::ScalarType S; + // tessellate + // first very inefficient implementation + std::vector next,prev; + for(int i = 0; i < points2.size(); ++i) next.push_back((i+1)%points2.size()); + for(int i = 0; i < points2.size(); ++i) prev.push_back((i+points2.size()-1)%points2.size()); + int v1,v2; + // check orientation + S orient = 0.0; + for(int i = 0 ; i < points2.size(); ++i){ + v1 = next[i]; + v2 = next[v1]; + orient+= (points2[v1] - points2[0]) ^ (points2[v2] - points2[0]); + } + orient = (orient>0)? 1.0:-1.0; + + int cur = 0; + int n_faces = 0; + while(output.size()<3*(points2.size()-2)){ + v1 = next[cur]; + v2 = next[v1]; + if( ( (orient*((points2[v1] - points2[cur]) ^ (points2[v2] - points2[cur]))) >= 0.0) && + !Intersect(cur, v2,next,points2)) + { + // output the face + output.push_back(cur); + output.push_back(v1); + output.push_back(v2); + + // readjust the topology + next[cur] = v2; + prev[v2] = cur; + prev[v1] = -1;//unnecessary + next[v1] = -1;//unnecessary + } + else + do{cur = (cur+1)%points2.size();} while(next[cur]==-1); + } + } + + /** + A very simple earcut tessellation of planar 2D polygon. + Input: a vector or Point3<> + Output: a vector of faces as a triple of indices to the input vector + + */ + + template + void TessellatePlanarPolygon3( POINT_CONTAINER & points, std::vector & output){ + typedef typename POINT_CONTAINER::value_type Point3x; + typedef typename Point3x::ScalarType S; + Point3x n; + + math::RandomGenerator rg; + int i12[2]; + S bestsn = -1.0; + Point3x bestn,u,v; + for(int i =0; i < points.size();++i){ + for(int j = 0; j < 2; ++j){ i12[j] = i; while(i12[j]==i) i12[j] = rg(points.size()-1);} + n = (points[i12[0]]-points[i])^(points[i12[1]]-points[i]); + S sn = n.SquaredNorm(); + if(sn > bestsn){ bestsn = sn; bestn = n;} + } + + GetUV(n,u,v); + // project the coordinates + std::vector > points2; + for(int i = 0; i < points.size(); ++i){ + Point3x & p = points[i]; + points2.push_back(Point2(p*u,p*v)); + } + TessellatePlanarPolygon2( points2,output); + } + +/*@}*/ +} // end namespace +#endif