Go to the documentation of this file.00001 #ifndef OUTLINE_SUPPORT_H
00002 #define OUTLINE_SUPPORT_H
00003
00004 #include <vcg/math/random_generator.h>
00005 #include <vcg/complex/complex.h>
00006 #include <vcg/complex/algorithms/update/topology.h>
00007 #include <vcg/complex/algorithms/update/bounding.h>
00008
00009 namespace vcg {
00010 namespace tri {
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 template < class ScalarType>
00021 class OutlineUtil
00022 {
00023 public:
00024
00025
00031 static ScalarType Outline2Area(const std::vector< Point2<ScalarType> > &outline2)
00032 {
00033 float area=0;
00034 for (size_t i=0,j=outline2.size()-1; i<outline2.size(); i++) {
00035 area+=(outline2[j][0]+outline2[i][0])*(outline2[j][1]-outline2[i][1]);
00036 j=i;
00037 }
00038 return -area*.5;
00039 }
00040
00046 static ScalarType Outline2Perimeter(const std::vector< Point2<ScalarType> > &outline2)
00047 {
00048 float dd=0; int sz = outline2.size();
00049
00050
00051 for(int j=0; j<sz; ++j)
00052 {
00053 dd += Distance (Point2f(outline2[j][0],outline2[j][1]),Point2f(outline2[(j+1)%sz][0],outline2[(j+1)%sz][1]));
00054 }
00055 return dd;
00056 }
00057
00064 static Box2<ScalarType> Outline2BBox(const std::vector<Point2<ScalarType> > &outline2)
00065 {
00066 Box2<ScalarType> bb;
00067 for(size_t i=0;i<outline2.size();++i)
00068 bb.Add(outline2[i]);
00069
00070 return bb;
00071 }
00072
00079 static Box2<ScalarType> Outline2VecBBox(const std::vector<std::vector<Point2<ScalarType> > > &outline2Vec)
00080 {
00081 Box2<ScalarType> bb;
00082 for(size_t j=0;j<outline2Vec.size();++j)
00083 for(size_t i=0;i<outline2Vec[j].size();++i)
00084 bb.Add(outline2Vec[j][i]);
00085
00086 return bb;
00087 }
00088
00089 static void ReverseOutline2(std::vector< Point2<ScalarType> > &outline2)
00090 {
00091 std::reverse(outline2.begin(),outline2.end());
00092 }
00093
00094
00095 static void BuildRandomOutlineVec(int outlineNum, std::vector< std::vector< Point2f > > &outline2Vec, int seed=0)
00096 {
00097 vcg::math::MarsenneTwisterRNG rnd;
00098 if(seed==0) seed=time(0);
00099 rnd.initialize(seed);
00100 for(int i=0;i<outlineNum;++i)
00101 {
00102 std::vector<Point2f> poly;
00103 for(int j=0;j<10;j++)
00104 poly.push_back(Point2f(0.5+0.5*rnd.generate01(),2.0f*M_PI*rnd.generate01()));
00105
00106 std::sort(poly.begin(),poly.end());
00107
00108 float ratio = rnd.generateRange(0.2,0.9);
00109 float rot = rnd.generateRange(-M_PI,M_PI);
00110 float scale = pow(rnd.generateRange(0.3,0.9),1);
00111
00112 for(size_t j=0;j<poly.size();j++)
00113 {
00114 poly[j].Polar2Cartesian();
00115 poly[j][1]*=ratio;
00116 poly[j] *= scale;
00117 poly[j].Cartesian2Polar();
00118 poly[j][1]+=rot;
00119 poly[j].Polar2Cartesian();
00120 }
00121
00122 Point2f randTras(rnd.generateRange(-5,5),rnd.generateRange(-5,5));
00123 for(size_t j=0;j<poly.size();j++)
00124 poly[j]+=randTras;
00125
00126 outline2Vec.push_back(poly);
00127 }
00128 }
00129
00130 static int LargestOutline2(const std::vector< std::vector< Point2f > > &outline2Vec)
00131 {
00132 float maxArea =0;
00133 int maxInd=-1;
00134 for(size_t i=0;i<outline2Vec.size();++i)
00135 {
00136 float curArea = fabs(Outline2Area(outline2Vec[i]));
00137 if(curArea > maxArea)
00138 {
00139 maxArea=curArea;
00140 maxInd=i;
00141 }
00142 }
00143 assert(maxInd>=0);
00144 return maxInd;
00145 }
00146
00147 template<class PointType>
00148 static bool ConvertOutline3VecToOutline2Vec(std::vector< std::vector< PointType> > &outline3Vec, std::vector< std::vector< Point2f> > &outline2Vec )
00149 {
00150 outline2Vec.resize(outline3Vec.size());
00151 for(size_t i=0;i<outline3Vec.size();++i)
00152 {
00153
00154 outline2Vec[i].resize(outline3Vec[i].size());
00155 for(size_t j=0;j<outline3Vec[i].size();++j)
00156 {
00157 outline2Vec[i][j][0]=outline3Vec[i][j][0];
00158 outline2Vec[i][j][1]=outline3Vec[i][j][1];
00159
00160 }
00161
00162 }
00163 return true;
00164 }
00165
00166 template<class MeshType>
00167 static int ConvertMeshBoundaryToOutline3Vec(MeshType &m, std::vector< std::vector<Point3f> > &outline3Vec)
00168 {
00169 typedef typename MeshType::FaceType FaceType;
00170 std::vector<Point3f> outline;
00171
00172 tri::Allocator<MeshType>::CompactVertexVector(m);
00173 tri::Allocator<MeshType>::CompactFaceVector(m);
00174 tri::UpdateFlags<MeshType>::FaceClearV(m);
00175 tri::UpdateFlags<MeshType>::VertexClearV(m);
00176 tri::UpdateTopology<MeshType>::FaceFace(m);
00177 int totalVn=0;
00178 for(size_t i=0;i<m.face.size();i++)
00179 {
00180 for (int j=0;j<3;j++)
00181 if (!m.face[i].IsV() && face::IsBorder(m.face[i],j))
00182 {
00183 FaceType* startB=&(m.face[i]);
00184 face::Pos<FaceType> p(startB,j);
00185 face::Pos<FaceType> startPos = p;
00186 assert(p.IsBorder());
00187 do
00188 {
00189 assert(p.IsManifold());
00190 p.F()->SetV();
00191 outline.push_back(p.V()->P());
00192 p.NextB();
00193 totalVn++;
00194 }
00195 while(p != startPos);
00196 outline3Vec.push_back(outline);
00197 outline.clear();
00198 }
00199 }
00200 return totalVn;
00201 }
00202
00203 template<class MeshType>
00204 static void ConvertMeshBoundaryToEdgeMesh(MeshType &m, MeshType &em)
00205 {
00206 typedef typename MeshType::VertexIterator VertexIterator;
00207 typedef typename MeshType::EdgeIterator EdgeIterator;
00208 typedef typename MeshType::VertexPointer VertexPointer;
00209 em.Clear();
00210 std::vector< std::vector<Point3f> > outlines;
00211 int nv = ConvertMeshBoundaryToOutlines(m,outlines);
00212 if (nv<2) return;
00213 VertexIterator vi=vcg::tri::Allocator<MeshType>::AddVertices(em,nv);
00214 EdgeIterator ei=vcg::tri::Allocator<MeshType>::AddEdges(em,nv);
00215
00216
00217
00218 for (size_t i=0;i<outlines.size();i++)
00219 {
00220 VertexPointer firstVp = &*vi;
00221 for(size_t j=0;j<outlines[i].size();++j,++vi,++ei)
00222 {
00223 (&*vi)->P()=outlines[i][j];
00224
00225 ei->V(0)=&*vi;
00226 if((j+1)<outlines[i].size()) ei->V(1)=&*(vi+1);
00227 else ei->V(1)=firstVp;
00228 }
00229
00230 }
00231 }
00232
00233 template<class MeshType>
00234 static bool ConvertOutline3VecToEdgeMesh(std::vector< std::vector< Point3f> > &outlineVec, MeshType &m)
00235 {
00236 typedef typename MeshType::VertexPointer VertexPointer;
00237 typedef typename MeshType::EdgePointer EdgePointer;
00238
00239 m.Clear();
00240 std::vector< std::vector<int> > Indexes(outlineVec.size());
00241 for(size_t i=0;i<outlineVec.size();++i)
00242 {
00243 for(size_t j=0;j<outlineVec[i].size();++j)
00244 {
00245 Indexes[i].push_back(m.vert.size());
00246 VertexPointer vp=&*tri::Allocator<MeshType>::AddVertices(m,1);
00247 Point3f pp=Point3f(outlineVec[i][j][0],outlineVec[i][j][1],outlineVec[i][j][2]);
00248 vp->P()= pp;
00249 }
00250 }
00251
00252 for(size_t i=0;i<outlineVec.size();++i)
00253 for(size_t j=0;j<outlineVec[i].size();++j)
00254 { int polyLen =outlineVec[i].size();
00255 EdgePointer ep=&*tri::Allocator<MeshType>::AddEdges(m,1);
00256 ep->V(0)=&m.vert[Indexes[i][j]];
00257 ep->V(1)=&m.vert[Indexes[i][(j+1)%polyLen]];
00258 }
00259 tri::UpdateBounding<MeshType>::Box(m);
00260 return true;
00261 }
00262
00263 template<class MeshType>
00264 static bool ConvertOutline3VecToEdgeMesh(std::vector< Point3f> &outline, MeshType &m)
00265 {
00266 std::vector< std::vector< Point3f> > outlineVec;
00267 outlineVec.push_back(outline);
00268 return Convert3DOutlinesToEdgeMesh(outlineVec,m);
00269 }
00270
00271 };
00272
00273 }
00274 }
00275
00276 #endif // OUTLINE_SUPPORT_H