TEST (PCL, MarchingCubesTest)
{
  MarchingCubesHoppe<PointNormal> hoppe;
  hoppe.setIsoLevel (0);
  hoppe.setGridResolution (30, 30, 30);
  hoppe.setPercentageExtendGrid (0.3f);
  hoppe.setInputCloud (cloud_with_normals);
  PointCloud<PointNormal> points;
  std::vector<Vertices> vertices;
  hoppe.reconstruct (points, vertices);

  EXPECT_NEAR (points.points[points.size()/2].x, -0.037143, 1e-3);
  EXPECT_NEAR (points.points[points.size()/2].y,  0.098213, 1e-3);
  EXPECT_NEAR (points.points[points.size()/2].z, -0.044911, 1e-3);
  EXPECT_EQ (vertices[vertices.size ()/2].vertices[0], 11202);
  EXPECT_EQ (vertices[vertices.size ()/2].vertices[1], 11203);
  EXPECT_EQ (vertices[vertices.size ()/2].vertices[2], 11204);


  MarchingCubesRBF<PointNormal> rbf;
  rbf.setIsoLevel (0);
  rbf.setGridResolution (20, 20, 20);
  rbf.setPercentageExtendGrid (0.1f);
  rbf.setInputCloud (cloud_with_normals);
  rbf.setOffSurfaceDisplacement (0.02f);
  rbf.reconstruct (points, vertices);

  EXPECT_NEAR (points.points[points.size()/2].x, -0.025630, 1e-3);
  EXPECT_NEAR (points.points[points.size()/2].y,  0.135228, 1e-3);
  EXPECT_NEAR (points.points[points.size()/2].z,  0.035766, 1e-3);
  EXPECT_EQ (vertices[vertices.size ()/2].vertices[0], 4275);
  EXPECT_EQ (vertices[vertices.size ()/2].vertices[1], 4276);
  EXPECT_EQ (vertices[vertices.size ()/2].vertices[2], 4277);
}
int
  main (int argc, char** argv)
{
  PointCloud<PointXYZ>::Ptr cloud (new PointCloud<PointXYZ>);

  if(io::loadPLYFile<PointXYZ> (argv[1], *cloud) == -1){
    cout << "ERROR: couldn't find file" << endl;
    return (1);
  } else {
    cout << "loaded" << endl;

    NormalEstimationOMP<PointXYZ, Normal> ne;
    search::KdTree<PointXYZ>::Ptr tree1 (new search::KdTree<PointXYZ>);
    tree1->setInputCloud (cloud);
    ne.setInputCloud (cloud);
    ne.setSearchMethod (tree1);
    ne.setKSearch (20);
    PointCloud<Normal>::Ptr normals (new PointCloud<Normal>);
    ne.compute (*normals);
         
    // Concatenate the XYZ and normal fields*
    PointCloud<PointNormal>::Ptr cloud_with_normals (new PointCloud<PointNormal>);
    concatenateFields(*cloud, *normals, *cloud_with_normals);
 
    // Create search tree*
    search::KdTree<PointNormal>::Ptr tree (new search::KdTree<PointNormal>);
    tree->setInputCloud (cloud_with_normals);
    
    cout << "begin marching cubes reconstruction" << endl;    

    MarchingCubesRBF<PointNormal> mc;
    PolygonMesh::Ptr triangles(new PolygonMesh);
    mc.setInputCloud (cloud_with_normals);
    mc.setSearchMethod (tree);
    mc.reconstruct (*triangles);

    cout << triangles->polygons.size() << " triangles created" << endl;
  }
  return (0);
}