From 12c1495bb0d62c1b54d36eebab4ac082f14098f9 Mon Sep 17 00:00:00 2001 From: cignoni Date: Fri, 23 Oct 2015 23:00:12 +0000 Subject: [PATCH] Added function for computing the visibility of a point cloud and corrected a few bugs (abs instead of fabs, and missing vertex index for the vertices of the first tetrahedron) --- vcg/complex/algorithms/convex_hull.h | 100 ++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 11 deletions(-) diff --git a/vcg/complex/algorithms/convex_hull.h b/vcg/complex/algorithms/convex_hull.h index 8521e7da..e254db8f 100644 --- a/vcg/complex/algorithms/convex_hull.h +++ b/vcg/complex/algorithms/convex_hull.h @@ -42,6 +42,7 @@ class ConvexHull public: typedef typename InputMesh::ScalarType ScalarType; + typedef typename InputMesh::CoordType CoordType; typedef typename InputMesh::VertexPointer InputVertexPointer; typedef typename InputMesh::VertexIterator InputVertexIterator; typedef typename CHMesh::VertexIterator CHVertexIterator; @@ -57,8 +58,8 @@ private: // Initialize the convex hull with the biggest tetraedron created using the vertices of the input mesh static void InitConvexHull(InputMesh& mesh, CHMesh& convexHull) { - typename CHMesh:: template PerVertexAttributeHandle indexInputVertex = Allocator::template GetPerVertexAttribute(convexHull, std::string("indexInput")); - InputVertexPointer v[3]; + typename CHMesh:: template PerVertexAttributeHandle indexInputVertex = Allocator::template GetPerVertexAttribute(convexHull, std::string("indexInput")); + InputVertexPointer v[3]; //Find the 6 points with min/max coordinate values InputVertexIterator vi = mesh.vert.begin(); std::vector minMax(6, &(*vi)); @@ -109,7 +110,7 @@ private: for (int i = 0; i < 3; i++) { (*chVi).P().Import(v[i]->P()); - indexInputVertex[chVi] = 0; + indexInputVertex[chVi] = vcg::tri::Index(mesh, v[i]); chVi++; } CHFaceIterator fi = vcg::tri::Allocator::AddFace(convexHull, 0, 1, 2); @@ -122,11 +123,11 @@ private: for (vi = mesh.vert.begin(); vi != mesh.vert.end(); vi++) { float tempDist = ((*vi).P() - (*fi).P(0)).dot((*fi).N()); - if (abs(tempDist) > absDist) + if (fabs(tempDist) > absDist) { distance = tempDist; v4 = &(*vi); - absDist = abs(distance); + absDist = fabs(distance); } } @@ -150,7 +151,7 @@ private: fi = vcg::tri::Allocator::AddFace(convexHull, &convexHull.vert[3], convexHull.face[0].V2(1), convexHull.face[0].V2(0)); (*fi).N() = vcg::NormalizedTriangleNormal(*fi); vcg::tri::UpdateTopology::FaceFace(convexHull); - }; + } public: @@ -169,11 +170,11 @@ public: vcg::tri::RequireFFAdjacency(convexHull); vcg::tri::RequirePerFaceNormal(convexHull); vcg::tri::Allocator::CompactVertexVector(mesh); - typename CHMesh:: template PerVertexAttributeHandle indexInputVertex = Allocator::template GetPerVertexAttribute(convexHull, std::string("indexInput")); + typename CHMesh:: template PerVertexAttributeHandle indexInputVertex = Allocator::template GetPerVertexAttribute(convexHull, std::string("indexInput")); if (mesh.vert.size() < 4) return false; InitConvexHull(mesh, convexHull); - + //Build list of visible vertices for each convex hull face and find the furthest vertex for each face std::vector> listVertexPerFace(convexHull.face.size()); std::vector furthestVexterPerFace(convexHull.face.size(), std::make_pair((InputVertexPointer)NULL, 0.0f)); @@ -236,7 +237,7 @@ public: { CHVertexIterator vi = vcg::tri::Allocator::AddVertices(convexHull, 1); (*vi).P().Import((*vertex).P()); - indexInputVertex[vi] = vcg::tri::Index(mesh, vertex); + indexInputVertex[vi] = vcg::tri::Index(mesh, vertex); } //Add a new face for each border @@ -281,7 +282,7 @@ public: std::vector vertexToTest(listVertexPerFace[indices[0]].size() + listVertexPerFace[indices[1]].size()); typename std::vector::iterator tempIt = std::set_union(listVertexPerFace[indices[0]].begin(), listVertexPerFace[indices[0]].end(), listVertexPerFace[indices[1]].begin(), listVertexPerFace[indices[1]].end(), vertexToTest.begin()); vertexToTest.resize(tempIt - vertexToTest.begin()); - ScalarType maxDist = 0; + Pair newInfo = std::make_pair((InputVertexPointer)NULL , 0.0f); for (int ii = 0; ii < vertexToTest.size(); ii++) { @@ -323,13 +324,90 @@ public: } } - tri::UpdateTopology::ClearFaceFace(convexHull); + tri::UpdateTopology::ClearFaceFace(convexHull); vcg::tri::Allocator::CompactFaceVector(convexHull); vcg::tri::Clean::RemoveUnreferencedVertex(convexHull); return true; } + /** + * @brief ComputePointVisibility + * Select the visible points in a point cloud, as viewed from a given viewpoint. + * It uses the Qhull implementation of che convex hull in the vcglibrary + * The algorithm used (Katz, Tal and Basri 2007) determines visibility without + * reconstructing a surface or estimating normals. + * A point is considered visible if its transformed point lies on the convex hull + * of a trasformed points cloud from the original mesh points. + * + * @param m The point cloud + * @param visible The mesh that will contain the visible hull + * @param viewpoint + * @param logR Bounds the radius of the sphere used to select visible points. + * It is used to adjust the radius of the sphere (calculated as distance between + * the center and the farthest point from it) according to the following equation: + * radius = radius * pow(10,threshold); + * As the radius increases more points are marked as visible. + * Use a big threshold for dense point clouds, a small one for sparse clouds. + */ + static void ComputePointVisibility(InputMesh& m, CHMesh& visible, CoordType viewpoint, ScalarType logR=2) + { + visible.Clear(); + tri::RequireCompactness(m); + InputMesh flipM; + tri::Allocator::AddVertices(flipM,m.vn); + ScalarType maxDist=0; + InputVertexIterator ci=flipM.vert.begin(); + for(InputVertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) + { + ci->P()=vi->P()-viewpoint; + maxDist = std::max(maxDist,Norm(ci->P())); + ++ci; + } + ScalarType R = maxDist*pow(10,logR); + printf("Using R = %f logR = %f maxdist=%f \n",R,logR,maxDist); + for(InputVertexIterator vi=flipM.vert.begin();vi!=flipM.vert.end();++vi) + { + ScalarType d = Norm(vi->P()); + vi->P() = vi->P() + vi->P()*ScalarType(2.0*(R - d)/d); + } + + tri::Allocator::AddVertex(flipM,CoordType(0,0,0)); + assert(m.vn+1 == flipM.vn); + + ComputeConvexHull(flipM,visible); + assert(flipM.vert[m.vn].P()==Point3f(0,0,0)); + int vpInd=-1; // Index of the viewpoint in the ConvexHull mesh + int selCnt=0; + typename CHMesh:: template PerVertexAttributeHandle indexInputVertex = Allocator::template GetPerVertexAttribute(visible, std::string("indexInput")); + for(int i=0;i::DeleteFace(visible,visible.face[i]); + } + + tri::Allocator::CompactEveryVector(visible); + tri::Clean::FlipMesh(visible); + + } }; } // end namespace tri