Skip to content

Commit

Permalink
Playing with pcl library
Browse files Browse the repository at this point in the history
  • Loading branch information
wwmayer committed May 26, 2012
1 parent 8078b7e commit 4ca6567
Show file tree
Hide file tree
Showing 3 changed files with 248 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Expand Up @@ -247,6 +247,10 @@ MARK_AS_ADVANCED(FORCE FREECAD_LIBPACK_CHECKFILE6X FREECAD_LIBPACK_CHECKFILE7X)
#find_package(Eigen2)
find_package(Eigen3)

# -------------------------------- pcl ----------------------------------

find_package(PCL COMPONENTS common kdtree features surface)

# -------------------------------- ODE ----------------------------------

find_package(ODE)
Expand Down
235 changes: 234 additions & 1 deletion src/Mod/Points/App/AppPointsPy.cpp
Expand Up @@ -24,7 +24,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#endif


#include <Base/Console.h>
#include <Base/Interpreter.h>
#include <Base/FileInfo.h>
Expand Down Expand Up @@ -132,11 +132,244 @@ show(PyObject *self, PyObject *args)
Py_Return;
}

// http://svn.pointclouds.org/pcl/tags/pcl-1.5.1/test/
#if defined(PCL_FOUND)
#include <pcl/point_types.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/mls.h>
#include <pcl/surface/mls_omp.h>
#include <pcl/surface/gp3.h>
#include <pcl/surface/grid_projection.h>
#include <pcl/surface/convex_hull.h>
#include <pcl/surface/concave_hull.h>
#include <pcl/surface/organized_fast_mesh.h>
#include <pcl/surface/ear_clipping.h>
#include <pcl/common/common.h>
#include <boost/random.hpp>

using namespace pcl;
using namespace pcl::io;
using namespace std;


int
saveOBJFile (const std::string &file_name,
const pcl::PolygonMesh &mesh, unsigned precision=5)
{
if (mesh.cloud.data.empty ())
{
std::cerr << "[pcl::io::saveOBJFile] Input point cloud has no data!\n";
return (-1);
}
// Open file
std::ofstream fs;
fs.precision (precision);
fs.open (file_name.c_str ());

/* Write 3D information */
// number of points
int nr_points = mesh.cloud.width * mesh.cloud.height;
// point size
int point_size = mesh.cloud.data.size () / nr_points;
// number of faces for header
int nr_faces = mesh.polygons.size ();
// Do we have vertices normals?
int normal_index = getFieldIndex (mesh.cloud, "normal");

// Write the header information
fs << "####" << std::endl;
fs << "# OBJ dataFile simple version. File name: " << file_name << std::endl;
fs << "# Vertices: " << nr_points << std::endl;
if (normal_index != -1)
fs << "# Vertices normals : " << nr_points << std::endl;
fs << "# Faces: " <<nr_faces << std::endl;
fs << "####" << std::endl;

// Write vertex coordinates
fs << "# List of Vertices, with (x,y,z) coordinates, w is optional." << std::endl;
for (int i = 0; i < nr_points; ++i)
{
int xyz = 0;
for (size_t d = 0; d < mesh.cloud.fields.size (); ++d)
{
int c = 0;
// adding vertex
if ((mesh.cloud.fields[d].datatype == sensor_msgs::PointField::FLOAT32) && (
mesh.cloud.fields[d].name == "x" ||
mesh.cloud.fields[d].name == "y" ||
mesh.cloud.fields[d].name == "z"))
{
if (mesh.cloud.fields[d].name == "x")
// write vertices beginning with v
fs << "v ";

float value;
memcpy (&value, &mesh.cloud.data[i * point_size + mesh.cloud.fields[d].offset + c * sizeof (float)], sizeof (float));
fs << value;
if (++xyz == 3)
break;
fs << " ";
}
}
if (xyz != 3)
{
std::cerr << "[pcl::io::saveOBJFile] Input point cloud has no XYZ data!\n";
return (-2);
}
fs << std::endl;
}

fs << "# "<< nr_points <<" vertices" << std::endl;

if(normal_index != -1)
{
fs << "# Normals in (x,y,z) form; normals might not be unit." << std::endl;
// Write vertex normals
for (int i = 0; i < nr_points; ++i)
{
int nxyz = 0;
for (size_t d = 0; d < mesh.cloud.fields.size (); ++d)
{
int c = 0;
// adding vertex
if ((mesh.cloud.fields[d].datatype == sensor_msgs::PointField::FLOAT32) && (
mesh.cloud.fields[d].name == "normal_x" ||
mesh.cloud.fields[d].name == "normal_y" ||
mesh.cloud.fields[d].name == "normal_z"))
{
if (mesh.cloud.fields[d].name == "normal_x")
// write vertices beginning with vn
fs << "vn ";

float value;
memcpy (&value, &mesh.cloud.data[i * point_size + mesh.cloud.fields[d].offset + c * sizeof (float)], sizeof (float));
fs << value;
if (++nxyz == 3)
break;
fs << " ";
}
}
if (nxyz != 3)
{
std::cerr << "[pcl::io::saveOBJFile] Input point cloud has no normals!\n";
return (-2);
}
fs << std::endl;
}

fs << "# "<< nr_points <<" vertices normals" << std::endl;
}

fs << "# Face Definitions" << std::endl;
// Write down faces
if(normal_index == -1)
{
for(int i = 0; i < nr_faces; i++)
{
fs << "f ";
size_t j = 0;
for (; j < mesh.polygons[i].vertices.size () - 1; ++j)
fs << mesh.polygons[i].vertices[j] + 1 << " ";
fs << mesh.polygons[i].vertices[j] + 1 << std::endl;
}
}
else
{
for(int i = 0; i < nr_faces; i++)
{
fs << "f ";
size_t j = 0;
for (; j < mesh.polygons[i].vertices.size () - 1; ++j)
fs << mesh.polygons[i].vertices[j] + 1 << "//" << mesh.polygons[i].vertices[j] + 1;
fs << mesh.polygons[i].vertices[j] + 1 << "//" << mesh.polygons[i].vertices[j] + 1 << std::endl;
}
}
fs << "# End of File" << std::endl;

// Close obj file
fs.close ();
return 0;
}

static PyObject *
testPCL(PyObject *self, PyObject *args)
{
PyObject *pcObj;
if (!PyArg_ParseTuple(args, "O!", &(PointsPy::Type), &pcObj)) // convert args: Python->C
return NULL; // NULL triggers exception

PointsPy* pPoints = static_cast<PointsPy*>(pcObj);
PointKernel* kernel = pPoints->getPointKernelPtr();

PointCloud<PointXYZ>::Ptr cloud (new PointCloud<PointXYZ>);
PointCloud<PointNormal>::Ptr cloud_with_normals (new PointCloud<PointNormal>);
search::KdTree<PointXYZ>::Ptr tree;
search::KdTree<PointNormal>::Ptr tree2;

for (PointKernel::const_iterator it = kernel->begin(); it != kernel->end(); ++it) {
cloud->push_back(PointXYZ(it->x, it->y, it->z));
}

// Create search tree
tree.reset (new search::KdTree<PointXYZ> (false));
tree->setInputCloud (cloud);

// Normal estimation
NormalEstimation<PointXYZ, Normal> n;
PointCloud<Normal>::Ptr normals (new PointCloud<Normal> ());
n.setInputCloud (cloud);
//n.setIndices (indices[B);
n.setSearchMethod (tree);
n.setKSearch (20);
n.compute (*normals);

// Concatenate XYZ and normal information
pcl::concatenateFields (*cloud, *normals, *cloud_with_normals);

// Create search tree
tree2.reset (new search::KdTree<PointNormal>);
tree2->setInputCloud (cloud_with_normals);

// Init objects
PolygonMesh triangles;
GreedyProjectionTriangulation<PointNormal> gp3;

// Set parameters
gp3.setInputCloud (cloud_with_normals);
gp3.setSearchMethod (tree2);
gp3.setSearchRadius (2.025);
gp3.setMu (2.5);
gp3.setMaximumNearestNeighbors (100);
gp3.setMaximumSurfaceAngle(M_PI/4); // 45 degrees
gp3.setMinimumAngle(M_PI/18); // 10 degrees
gp3.setMaximumAngle(2*M_PI/3); // 120 degrees
gp3.setNormalConsistency(false);

// Reconstruct
gp3.reconstruct (triangles);

// Additional vertex information
std::vector<int> parts = gp3.getPartIDs();
std::vector<int> states = gp3.getPointStates();
int nr_points = cloud_with_normals->width * cloud_with_normals->height;

std::cerr << "Number of triangles: " << triangles.polygons.size() << std::endl;
saveOBJFile("/tmp/pcl.obj", triangles);


Py_Return;
}
#endif // PCL_FOUND

// registration table
struct PyMethodDef Points_Import_methods[] = {
{"open", open, 1}, /* method name, C func ptr, always-tuple */
{"insert",insert, 1},
{"show",show, 1},
#if defined(PCL_FOUND)
{"testPCL",testPCL, 1},
#endif

{NULL, NULL} /* end of table marker */
};

10 changes: 10 additions & 0 deletions src/Mod/Points/App/CMakeLists.txt
Expand Up @@ -2,17 +2,27 @@ if(WIN32)
add_definitions(-DFCAppPoints)
endif(WIN32)

if (PCL_FOUND)
add_definitions(-DPCL_FOUND)
endif(PCL_FOUND)

include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${Boost_INCLUDE_DIRS}
${PYTHON_INCLUDE_PATH}
${XERCESC_INCLUDE_DIR}
${ZLIB_INCLUDE_DIR}
${EIGEN3_INCLUDE_DIR}
${PCL_INCLUDE_DIRS}
)

set(Points_LIBS
FreeCADApp
${PCL_COMMON_LIBRARIES}
${PCL_KDTREE_LIBRARIES}
${PCL_FEATURES_LIBRARIES}
${PCL_SURFACE_LIBRARIES}
)

generate_from_xml(PointsPy)
Expand Down

0 comments on commit 4ca6567

Please sign in to comment.