trimesh_indexing.cpp
Go to the documentation of this file.
00001 #include <iostream>
00002 #include <QTime>
00003 #include <omp.h>
00004 
00005 #include "nanoflann.hpp"
00006 
00007 #include <vcg/complex/complex.h>
00008 
00009 #include <wrap/io_trimesh/import.h>
00010 #include <wrap/io_trimesh/export.h>
00011 
00012 
00013 #include <vcg/space/index/kdtree/kdtree.h>
00014 #include <vcg/space/index/grid_static_ptr.h>
00015 #include <vcg/space/index/perfect_spatial_hashing.h>
00016 #include <vcg/space/index/spatial_hashing.h>
00017 #include <vcg/space/index/octree.h>
00018 
00019 int num_test = 1000;
00020 int kNearest = 256;
00021 float queryDist = 0.0037;
00022 float ratio = 1000.0f;
00023 
00024 
00025 class CVertex;
00026 class CFace;
00027 class CEdge;
00028 
00029 class CUsedTypes        : public vcg::UsedTypes < vcg::Use< CVertex >::AsVertexType, vcg::Use< CFace >::AsFaceType>{};
00030 class CVertex           : public vcg::Vertex < CUsedTypes, vcg::vertex::Coord3f, vcg::vertex::Normal3f, vcg::vertex::Radiusf, vcg::vertex::BitFlags, vcg::vertex::Qualityf, vcg::vertex::Color4b>{};
00031 class CFace                     : public vcg::Face < CUsedTypes, vcg::face::VertexRef>{};
00032 
00033 class CMesh                     : public vcg::tri::TriMesh < std::vector< CVertex >, std::vector< CFace > > {};
00034 
00035 
00036 template <typename T>
00037 struct PointCloud
00038 {
00039         struct Point
00040         {
00041                 T  x,y,z;
00042         };
00043 
00044         std::vector<Point>  pts;
00045 
00046         inline size_t kdtree_get_point_count() const { return pts.size(); }
00047 
00048         inline T kdtree_distance(const T *p1, const size_t idx_p2,size_t size) const
00049         {
00050                 const T d0=p1[0]-pts[idx_p2].x;
00051                 const T d1=p1[1]-pts[idx_p2].y;
00052                 const T d2=p1[2]-pts[idx_p2].z;
00053                 return d0*d0+d1*d1+d2*d2;
00054         }
00055 
00056         inline T kdtree_get_pt(const size_t idx, int dim) const
00057         {
00058                 if (dim==0) return pts[idx].x;
00059                 else if (dim==1) return pts[idx].y;
00060                 else return pts[idx].z;
00061         }
00062 
00063         template <class BBOX>
00064         bool kdtree_get_bbox(BBOX &bb) const { return false; }
00065 
00066 };
00067 
00068 
00069 void testKDTree(CMesh& mesh, std::vector<unsigned int>& test_indeces, std::vector<vcg::Point3f>& randomSamples)
00070 {
00071         std::cout << "==================================================="<< std::endl;
00072         std::cout << "KDTree" << std::endl;
00073         QTime time;
00074         time.start();
00075 
00076         // Construction of the kdTree
00077         vcg::ConstDataWrapper<CMesh::VertexType::CoordType> wrapperVcg(&mesh.vert[0].P(), mesh.vert.size(), size_t(mesh.vert[1].P().V()) - size_t(mesh.vert[0].P().V()));
00078         vcg::KdTree<CMesh::ScalarType> kdTreeVcg(wrapperVcg);
00079         std::cout << "Build: " << time.elapsed() <<  " ms" << std::endl;
00080 
00081         // Computation of the point radius
00082         float mAveragePointSpacing = 0;
00083         time.restart();
00084         #pragma omp parallel for reduction(+: mAveragePointSpacing) schedule(dynamic, 10)
00085         for (int i = 0; i < mesh.vert.size(); i++)
00086         {
00087                 vcg::KdTree<CMesh::ScalarType>::PriorityQueue queue; 
00088                 kdTreeVcg.doQueryK(mesh.vert[i].cP(), 16, queue);
00089                 float newRadius = 2.0f * sqrt(queue.getWeight(0)/ queue.getNofElements());
00090                 mesh.vert[i].R() -= newRadius;
00091                 mAveragePointSpacing += newRadius;
00092         }
00093         mAveragePointSpacing /= mesh.vert.size();
00094         std::cout << "Average point radius (OpenMP) " << mAveragePointSpacing << std::endl;
00095         std::cout << "Time (OpenMP): " << time.elapsed() << " ms" << std::endl;
00096         
00097         queryDist = mAveragePointSpacing * 150;
00098 
00099         // Test with the radius search
00100         std::cout << "Radius search (" << num_test << " tests)"<< std::endl; 
00101         float avgTime = 0.0f;
00102         for (int ii = 0; ii < num_test; ii++)
00103         {
00104                 time.restart();
00105                 std::vector<unsigned int> indeces;
00106                 std::vector<float> dists;
00107                 kdTreeVcg.doQueryDist(mesh.vert[test_indeces[ii]].cP(), queryDist, indeces, dists);
00108                 avgTime += time.elapsed();
00109         }
00110         std::cout << "Time (radius = " << queryDist << "): " << avgTime << " ms (mean " << avgTime / num_test << "ms)"  << std::endl;
00111 
00112         // Test with the k-nearest search
00113         std::cout << "k-Nearest search (" << num_test*10 << " tests)"<< std::endl;
00114         avgTime = 0.0f;
00115         for (int ii = 0; ii < num_test * 10; ii++)
00116         {
00117                 time.restart();
00118                 vcg::KdTree<CMesh::ScalarType>::PriorityQueue queue; 
00119                 kdTreeVcg.doQueryK(mesh.vert[test_indeces[ii]].cP(), kNearest, queue);
00120                 avgTime += time.elapsed();
00121         }
00122         std::cout << "Time (k = " << kNearest << "): " << avgTime << " ms (mean " << avgTime / (num_test * 10) << "ms)"  << std::endl;
00123         
00124         // Test with the closest search
00125         std::cout << "Closest search (" << num_test*10 << " tests)"<< std::endl;
00126         avgTime = 0.0f;
00127         for (int ii = 0; ii < num_test * 10; ii++)
00128         {
00129                 time.restart();
00130                 unsigned int index;
00131                 float minDist;
00132                 kdTreeVcg.doQueryClosest(randomSamples[ii], index, minDist);
00133                 avgTime += time.elapsed();
00134         }
00135         std::cout << "Time : " << avgTime << " ms (mean " << avgTime / (num_test * 10) << "ms)"  << std::endl << std::endl;
00136 }
00137 
00138 
00139 void testNanoFLANN(CMesh& mesh, std::vector<unsigned int>& test_indeces, std::vector<vcg::Point3f> randomSamples)
00140 {
00141         std::cout << "==================================================="<< std::endl;
00142         std::cout << "nanoFLANN" << std::endl;
00143         
00144         PointCloud<float> cloud;
00145         cloud.pts.resize(mesh.vert.size());
00146         for (size_t i=0; i < mesh.vert.size(); i++)
00147         {
00148                 cloud.pts[i].x = mesh.vert[i].P().X();
00149                 cloud.pts[i].y = mesh.vert[i].P().Y();
00150                 cloud.pts[i].z = mesh.vert[i].P().Z();
00151         }
00152 
00153         typedef nanoflann::KDTreeSingleIndexAdaptor<
00154                 nanoflann::L2_Simple_Adaptor<float, PointCloud<float> > ,
00155                 PointCloud<float>,
00156                 3 /* dim */
00157                 > my_kd_tree_t;
00158 
00159         // Construction of the nanoFLANN KDtree
00160         QTime time;
00161         time.start();
00162         my_kd_tree_t   index(3, cloud, nanoflann::KDTreeSingleIndexAdaptorParams(16) );
00163         index.buildIndex();
00164         std::cout << "Build nanoFlann: " << time.elapsed() <<  " ms" << std::endl;
00165 
00166         // Test with the radius search
00167         std::cout << "Radius search (" << num_test << " tests)"<< std::endl; 
00168         float avgTime = 0.0f;
00169         std::vector<std::pair<size_t,float> >   ret_matches;
00170         nanoflann::SearchParams params;
00171         for (int ii = 0; ii < num_test; ii++)
00172         {
00173                 time.restart();
00174                 const size_t nMatches = index.radiusSearch(mesh.vert[test_indeces[ii]].P().V(), queryDist, ret_matches, params);
00175                 avgTime += time.elapsed();
00176         }
00177         std::cout << "Time (radius = " << queryDist << "): " << avgTime << " ms (mean " << avgTime / num_test << "ms)"  << std::endl;
00178 
00179         // Test with the k-nearest search
00180         std::cout << "k-Nearest search (" << num_test*10 << " tests)"<< std::endl;
00181         avgTime = 0.0f;
00182         std::vector<size_t>   ret_index(kNearest);
00183         std::vector<float> out_dist_sqr(kNearest);
00184         for (int ii = 0; ii < num_test * 10; ii++)
00185         {
00186                 time.restart();
00187                 index.knnSearch(mesh.vert[test_indeces[ii]].P().V(), kNearest, &ret_index[0], &out_dist_sqr[0]);
00188                 avgTime += time.elapsed();
00189         }
00190         std::cout << "Time (k = " << kNearest << "): " << avgTime << " ms (mean " << avgTime / (num_test * 10) << "ms)"  << std::endl;
00191 
00192         // Test with the closest search
00193         std::cout << "Closest search (" << num_test*10 << " tests)"<< std::endl;
00194         avgTime = 0.0f;
00195         std::vector<size_t>   ret_index_clos(1);
00196         std::vector<float> out_dist_sqr_clos(1);
00197         for (int ii = 0; ii < num_test * 10; ii++)
00198         {
00199                 time.restart();
00200                 index.knnSearch(randomSamples[ii].V(), 1, &ret_index_clos[0], &out_dist_sqr_clos[0]);
00201                 avgTime += time.elapsed();
00202         }
00203         std::cout << "Time : " << avgTime << " ms (mean " << avgTime / (num_test * 10) << "ms)"  << std::endl << std::endl;
00204 }
00205 
00206 
00207 void testUniformGrid(CMesh& mesh, std::vector<unsigned int>& test_indeces, std::vector<vcg::Point3f>& randomSamples)
00208 {
00209         std::cout << "==================================================="<< std::endl;
00210         std::cout << "Uniform Grid" << std::endl;
00211         QTime time;
00212         time.start();
00213 
00214         // Construction of the uniform grid
00215         typedef vcg::GridStaticPtr<CMesh::VertexType, CMesh::VertexType::ScalarType> MeshGrid; 
00216         MeshGrid uniformGrid;
00217         uniformGrid.Set(mesh.vert.begin(), mesh.vert.end());
00218         std::cout << "Build: " << time.elapsed() <<  " ms" << std::endl;
00219 
00220         // Test with the radius search
00221         std::cout << "Radius search (" << num_test << " tests)"<< std::endl; 
00222         float  avgTime = 0.0f;
00223         for (int ii = 0; ii < num_test; ii++)
00224         {
00225                 time.restart();
00226                 std::vector<CMesh::VertexPointer> vertexPtr;
00227                 std::vector<CMesh::VertexType::CoordType> points;
00228                 std::vector<float> dists;
00229                 vcg::tri::GetInSphereVertex(mesh, uniformGrid, mesh.vert[test_indeces[ii]].cP(), queryDist, vertexPtr, dists, points);
00230                 avgTime += time.elapsed();
00231         }
00232         std::cout << "Time (radius = " << queryDist << "): " << avgTime << " ms (mean " << avgTime / num_test << "ms)"  << std::endl;
00233 
00234         // Test with the k-nearest search
00235         std::cout << "k-Nearest search (" << num_test*10 << " tests)"<< std::endl;
00236         avgTime = 0.0f;
00237         for (int ii = 0; ii < num_test * 10; ii++)
00238         {
00239                 time.restart();
00240                 std::vector<CMesh::VertexPointer> vertexPtr;
00241                 std::vector<CMesh::VertexType::CoordType> points;
00242                 std::vector<float> dists;
00243                 vcg::tri::GetKClosestVertex(mesh, uniformGrid, kNearest, mesh.vert[test_indeces[ii]].cP(), mesh.bbox.Diag(), vertexPtr, dists, points);
00244                 avgTime += time.elapsed();
00245         }
00246         std::cout << "Time (k = " << kNearest << "): " << avgTime << " ms (mean " << avgTime / (num_test * 10) << "ms)"  << std::endl;
00247 
00248         // Test with the Closest search
00249         std::cout << "Closest search (" << num_test*10 << " tests)"<< std::endl;
00250         avgTime = 0.0f;
00251         for (int ii = 0; ii < num_test * 10; ii++)
00252         {
00253                 time.restart();
00254                 float minDist;
00255                 vcg::tri::GetClosestVertex(mesh, uniformGrid, randomSamples[ii], mesh.bbox.Diag(), minDist);
00256                 avgTime += time.elapsed();
00257         }
00258         std::cout << "Time : " << avgTime << " ms (mean " << avgTime / (num_test * 10) << "ms)"  << std::endl << std::endl;
00259 }
00260 
00261 
00262 
00263 void testSpatialHashing(CMesh& mesh, std::vector<unsigned int>& test_indeces, std::vector<vcg::Point3f>& randomSamples)
00264 {
00265         std::cout << "==================================================="<< std::endl;
00266         std::cout << "Spatial Hashing" << std::endl;
00267         QTime time;
00268         time.start();
00269 
00270         // Construction of the uniform grid
00271         typedef vcg::SpatialHashTable<CMesh::VertexType, CMesh::VertexType::ScalarType> MeshGrid; 
00272         MeshGrid uniformGrid;
00273         uniformGrid.Set(mesh.vert.begin(), mesh.vert.end());
00274         std::cout << "Build: " << time.elapsed() <<  " ms" << std::endl;
00275 
00276         // Test with the radius search
00277         std::cout << "Radius search (" << num_test << " tests)"<< std::endl; 
00278         float  avgTime = 0.0f;
00279         for (int ii = 0; ii < num_test; ii++)
00280         {
00281                 time.restart();
00282                 std::vector<CMesh::VertexPointer> vertexPtr;
00283                 std::vector<CMesh::VertexType::CoordType> points;
00284                 std::vector<float> dists;
00285                 vcg::tri::GetInSphereVertex(mesh, uniformGrid, mesh.vert[test_indeces[ii]].cP(), queryDist, vertexPtr, dists, points);
00286                 avgTime += time.elapsed();
00287         }
00288         std::cout << "Time (radius = " << queryDist << "): " << avgTime << " ms (mean " << avgTime / num_test << "ms)"  << std::endl;
00289 
00290         // Test with the k-nearest search
00291         std::cout << "k-Nearest search (" << num_test*10 << " tests)"<< std::endl;
00292         avgTime = 0.0f;
00293         for (int ii = 0; ii < num_test * 10; ii++)
00294         {
00295                 time.restart();
00296                 std::vector<CMesh::VertexPointer> vertexPtr;
00297                 std::vector<CMesh::VertexType::CoordType> points;
00298                 std::vector<float> dists;
00299                 vcg::tri::GetKClosestVertex(mesh, uniformGrid, kNearest, mesh.vert[test_indeces[ii]].cP(), mesh.bbox.Diag(), vertexPtr, dists, points);
00300                 avgTime += time.elapsed();
00301         }
00302         std::cout << "Time (k = " << kNearest << "): " << avgTime << " ms (mean " << avgTime / (num_test * 10) << "ms)"  << std::endl;
00303 
00304         // Test with the Closest search
00305         std::cout << "Closest search (" << num_test*10 << " tests)"<< std::endl;
00306         avgTime = 0.0f;
00307         for (int ii = 0; ii < num_test * 10; ii++)
00308         {
00309                 time.restart();
00310                 float minDist;
00311                 vcg::tri::GetClosestVertex(mesh, uniformGrid, randomSamples[ii], mesh.bbox.Diag(), minDist);
00312                 avgTime += time.elapsed();
00313         }
00314         std::cout << "Time : " << avgTime << " ms (mean " << avgTime / (num_test * 10) << "ms)"  << std::endl << std::endl;
00315 }
00316 
00317 
00318 
00319 void testPerfectSpatialHashing(CMesh& mesh, std::vector<unsigned int>& test_indeces)
00320 {
00321         std::cout << "==================================================="<< std::endl;
00322         std::cout << "Perfect Spatial Hashing" << std::endl;
00323         QTime time;
00324         time.start();
00325 
00326         // Construction of the uniform grid
00327         typedef vcg::SpatialHashTable<CMesh::VertexType, CMesh::VertexType::ScalarType> MeshGrid; 
00328         MeshGrid uniformGrid;
00329         uniformGrid.Set(mesh.vert.begin(), mesh.vert.end());
00330         std::cout << "Build: " << time.elapsed() <<  " ms" << std::endl;
00331 
00332         // Test with the radius search
00333         std::cout << "Radius search (" << num_test << " tests)"<< std::endl; 
00334         float  avgTime = 0.0f;
00335         for (int ii = 0; ii < num_test; ii++)
00336         {
00337                 time.restart();
00338                 std::vector<CMesh::VertexPointer> vertexPtr;
00339                 std::vector<CMesh::VertexType::CoordType> points;
00340                 std::vector<float> dists;
00341                 vcg::tri::GetInSphereVertex(mesh, uniformGrid, mesh.vert[test_indeces[ii]].cP(), queryDist, vertexPtr, dists, points);
00342                 avgTime += time.elapsed();
00343         }
00344         std::cout << "Time (radius = " << queryDist << "): " << avgTime << " ms (mean " << avgTime / num_test << "ms)"  << std::endl << std::endl;
00345 }
00346 
00347 
00348 void testOctree(CMesh& mesh, std::vector<unsigned int>& test_indeces, std::vector<vcg::Point3f>& randomSamples)
00349 {
00350         std::cout << "==================================================="<< std::endl;
00351         std::cout << "Octree" << std::endl;
00352         QTime time;
00353         time.start();
00354 
00355         // Construction of the uniform grid
00356         typedef vcg::Octree<CMesh::VertexType, CMesh::VertexType::ScalarType> MeshGrid; 
00357         MeshGrid uniformGrid;
00358         uniformGrid.Set(mesh.vert.begin(), mesh.vert.end());
00359         std::cout << "Build: " << time.elapsed() <<  " ms" << std::endl;
00360 
00361         // Test with the radius search
00362         std::cout << "Radius search (" << num_test << " tests)"<< std::endl; 
00363         float  avgTime = 0.0f;
00364         for (int ii = 0; ii < num_test; ii++)
00365         {
00366                 time.restart();
00367                 std::vector<CMesh::VertexPointer> vertexPtr;
00368                 std::vector<CMesh::VertexType::CoordType> points;
00369                 std::vector<float> dists;
00370                 vcg::tri::GetInSphereVertex(mesh, uniformGrid, mesh.vert[test_indeces[ii]].cP(), queryDist, vertexPtr, dists, points);
00371                 avgTime += time.elapsed();
00372         }
00373         std::cout << "Time (radius = " << queryDist << "): " << avgTime << " ms (mean " << avgTime / num_test << "ms)"  << std::endl;
00374 
00375         // Test with the k-nearest search
00376         std::cout << "k-Nearest search (" << num_test*10 << " tests)"<< std::endl;
00377         avgTime = 0.0f;
00378         for (int ii = 0; ii < num_test * 10; ii++)
00379         {
00380                 time.restart();
00381                 std::vector<CMesh::VertexPointer> vertexPtr;
00382                 std::vector<CMesh::VertexType::CoordType> points;
00383                 std::vector<float> dists;
00384                 vcg::tri::GetKClosestVertex(mesh, uniformGrid, kNearest, mesh.vert[test_indeces[ii]].cP(), mesh.bbox.Diag(), vertexPtr, dists, points);
00385                 avgTime += time.elapsed();
00386         }
00387         std::cout << "Time (k = " << kNearest << "): " << avgTime << " ms (mean " << avgTime / (num_test * 10) << "ms)"  << std::endl;
00388 
00389         // Test with the Closest search
00390         std::cout << "Closest search (" << num_test*10 << " tests)"<< std::endl;
00391         avgTime = 0.0f;
00392         for (int ii = 0; ii < num_test * 10; ii++)
00393         {
00394                 time.restart();
00395                 float minDist;
00396                 vcg::tri::GetClosestVertex(mesh, uniformGrid, randomSamples[ii], mesh.bbox.Diag(), minDist);
00397                 avgTime += time.elapsed();
00398         }
00399         std::cout << "Time : " << avgTime << " ms (mean " << avgTime / (num_test * 10) << "ms)"  << std::endl << std::endl;
00400 }
00401 
00402 
00403 
00404 int main( int argc, char * argv[] )
00405 {
00406         if (argc < 2)
00407                 std::cout << "Invalid arguments" << std::endl;
00408 
00409         CMesh mesh;
00410         if (vcg::tri::io::Importer<CMesh>::Open(mesh, argv[1])  != 0)
00411                 std::cout << "Invalid filename" << std::endl;
00412 
00413         std::cout << "Mesh BBox diagonal: " << mesh.bbox.Diag() << std::endl; 
00414         std::cout << "Max point random offset: " << mesh.bbox.Diag() / 1000.0f << std::endl << std::endl; 
00415 
00416         vcg::math::MarsenneTwisterRNG randGen;
00417         randGen.initialize(0);
00418         std::vector<vcg::Point3f> randomSamples;
00419         for (int i = 0; i < num_test * 10; i++)
00420                 randomSamples.push_back(vcg::math::GeneratePointOnUnitSphereUniform<float>(randGen) * randGen.generate01() * mesh.bbox.Diag() / ratio);
00421 
00422         std::vector<unsigned int> test_indeces;
00423         for (int i = 0; i < num_test * 10; i++)
00424         {
00425                 int index = randGen.generate01() * (mesh.vert.size() - 1);
00426                 test_indeces.push_back(index);
00427                 randomSamples[i] += mesh.vert[i].P();
00428         }
00429 
00430         testKDTree(mesh, test_indeces, randomSamples);
00431         testNanoFLANN(mesh, test_indeces, randomSamples);
00432         testUniformGrid(mesh, test_indeces, randomSamples);
00433         testSpatialHashing(mesh, test_indeces, randomSamples);
00434         testPerfectSpatialHashing(mesh, test_indeces);
00435         testOctree(mesh, test_indeces, randomSamples);
00436 }


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:38:20