diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5ee1122b8..a53048377 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -521,6 +521,10 @@ else(FREECAD_LIBPACK_USE)
find_package(Eigen3)
+# -------------------------------- pcl ----------------------------------
+
+ find_package(PCL COMPONENTS common kdtree features surface)
+
# -------------------------------- ODE ----------------------------------
# find_package(ODE)
diff --git a/src/Mod/Points/App/AppPointsPy.cpp b/src/Mod/Points/App/AppPointsPy.cpp
index ad280d915..129b2bd4b 100644
--- a/src/Mod/Points/App/AppPointsPy.cpp
+++ b/src/Mod/Points/App/AppPointsPy.cpp
@@ -24,7 +24,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#endif
-
+
#include
#include
#include
@@ -168,3 +168,4 @@ struct PyMethodDef Points_Import_methods[] = {
{NULL, NULL} /* end of table marker */
};
+
diff --git a/src/Mod/ReverseEngineering/App/AppReverseEngineeringPy.cpp b/src/Mod/ReverseEngineering/App/AppReverseEngineeringPy.cpp
index 3d2d116d7..7768b2b4a 100644
--- a/src/Mod/ReverseEngineering/App/AppReverseEngineeringPy.cpp
+++ b/src/Mod/ReverseEngineering/App/AppReverseEngineeringPy.cpp
@@ -22,7 +22,7 @@
#include "PreCompiled.h"
-#ifndef _PreComp_
+#ifndef _PreComp_
# include
# include
#endif
@@ -32,8 +32,12 @@
#include
#include
+#include
+#include
+#include
#include "ApproxSurface.h"
+#include "SurfaceTriangulation.h"
using namespace Reen;
@@ -46,10 +50,10 @@ static PyObject * approxSurface(PyObject *self, PyObject *args)
int pointsU=6,pointsV=6;
if (!PyArg_ParseTuple(args, "O|iiii",&o,&orderU,&orderV,&pointsU,&pointsV))
return NULL;
-
+
PY_TRY {
Py::Sequence l(o);
- TColgp_Array1OfPnt clPoints(0, l.size()-1);
+ TColgp_Array1OfPnt clPoints(0, l.size()-1);
int index=0;
for (Py::Sequence::iterator it = l.begin(); it != l.end(); ++it) {
@@ -59,15 +63,15 @@ static PyObject * approxSurface(PyObject *self, PyObject *args)
(double)Py::Float(t.getItem(1)),
(double)Py::Float(t.getItem(2)));
}
-
- Reen::BSplineParameterCorrection pc(orderU,orderV,pointsU,pointsV);
- Handle_Geom_BSplineSurface hSurf;
-
- //pc.EnableSmoothing(true, 0.1f, 0.5f, 0.2f, 0.3f);
- pc.EnableSmoothing(true, 0.1f, 1.0f, 0.0f, 0.0f);
- hSurf = pc.CreateSurface(clPoints, 5, true, 1.0);
- if (!hSurf.IsNull()) {
- return new Part::BSplineSurfacePy(new Part::GeomBSplineSurface(hSurf));
+
+ Reen::BSplineParameterCorrection pc(orderU,orderV,pointsU,pointsV);
+ Handle_Geom_BSplineSurface hSurf;
+
+ //pc.EnableSmoothing(true, 0.1f, 0.5f, 0.2f, 0.3f);
+ pc.EnableSmoothing(true, 0.1f, 1.0f, 0.0f, 0.0f);
+ hSurf = pc.CreateSurface(clPoints, 5, true, 1.0);
+ if (!hSurf.IsNull()) {
+ return new Part::BSplineSurfacePy(new Part::GeomBSplineSurface(hSurf));
}
PyErr_SetString(PyExc_Exception, "Computation of B-Spline surface failed");
@@ -75,8 +79,31 @@ static PyObject * approxSurface(PyObject *self, PyObject *args)
} PY_CATCH;
}
+#if defined(PCL_FOUND)
+static PyObject *
+triangulate(PyObject *self, PyObject *args)
+{
+ PyObject *pcObj;
+ if (!PyArg_ParseTuple(args, "O!", &(Points::PointsPy::Type), &pcObj))
+ return NULL;
+
+ Points::PointsPy* pPoints = static_cast(pcObj);
+ Points::PointKernel* points = pPoints->getPointKernelPtr();
+
+ Mesh::MeshObject* mesh = new Mesh::MeshObject();
+ SurfaceTriangulation tria(*points, *mesh);
+ tria.perform();
+
+ return new Mesh::MeshPy(mesh);
+}
+#endif
+
/* registration table */
struct PyMethodDef ReverseEngineering_methods[] = {
{"approxSurface" , approxSurface, 1},
+#if defined(PCL_FOUND)
+ {"triangulate" , triangulate, 1},
+#endif
{NULL, NULL} /* end of table marker */
};
+
diff --git a/src/Mod/ReverseEngineering/App/CMakeLists.txt b/src/Mod/ReverseEngineering/App/CMakeLists.txt
index 4cbf02bc4..20a6d8575 100644
--- a/src/Mod/ReverseEngineering/App/CMakeLists.txt
+++ b/src/Mod/ReverseEngineering/App/CMakeLists.txt
@@ -4,6 +4,10 @@ else(MSVC)
add_definitions(-DHAVE_LIMITS_H -DHAVE_CONFIG_H)
endif(MSVC)
+if (PCL_FOUND)
+ add_definitions(-DPCL_FOUND)
+endif(PCL_FOUND)
+
include_directories(
${CMAKE_SOURCE_DIR}/src
${Boost_INCLUDE_DIRS}
@@ -11,6 +15,8 @@ include_directories(
${PYTHON_INCLUDE_PATH}
${XERCESC_INCLUDE_DIR}
${ZLIB_INCLUDE_DIR}
+ ${EIGEN3_INCLUDE_DIR}
+ ${PCL_INCLUDE_DIRS}
)
link_directories(${OCC_LIBRARY_DIR})
@@ -18,7 +24,12 @@ link_directories(${OCC_LIBRARY_DIR})
set(Reen_LIBS
Part
Mesh
+ Points
FreeCADApp
+ ${PCL_COMMON_LIBRARIES}
+ ${PCL_KDTREE_LIBRARIES}
+ ${PCL_FEATURES_LIBRARIES}
+ ${PCL_SURFACE_LIBRARIES}
)
SET(Reen_SRCS
@@ -26,6 +37,8 @@ SET(Reen_SRCS
AppReverseEngineeringPy.cpp
ApproxSurface.cpp
ApproxSurface.h
+ SurfaceTriangulation.cpp
+ SurfaceTriangulation.h
PreCompiled.cpp
PreCompiled.h
)
diff --git a/src/Mod/ReverseEngineering/App/PreCompiled.h b/src/Mod/ReverseEngineering/App/PreCompiled.h
index eaaea1f87..603a5afff 100644
--- a/src/Mod/ReverseEngineering/App/PreCompiled.h
+++ b/src/Mod/ReverseEngineering/App/PreCompiled.h
@@ -29,12 +29,14 @@
// Exporting of App classes
#ifdef FC_OS_WIN32
# define ReenExport __declspec(dllexport)
-# define PartExport __declspec(dllimport)
+# define PartExport __declspec(dllimport)
# define MeshExport __declspec(dllimport)
+# define PointsExport __declspec(dllimport)
#else // for Linux
# define ReenExport
-# define PartExport
-# define MeshExport
+# define PartExport
+# define MeshExport
+# define PointsExport
#endif
#ifdef _PreComp_
@@ -51,15 +53,15 @@
#include
// OpenCasCade
-#include
-#include
+#include
+#include
#include
#include
#include
#include
#include
#include
-#include
+#include
#include
#include
#include
diff --git a/src/Mod/ReverseEngineering/App/SurfaceTriangulation.cpp b/src/Mod/ReverseEngineering/App/SurfaceTriangulation.cpp
new file mode 100644
index 000000000..dfcd2a4ee
--- /dev/null
+++ b/src/Mod/ReverseEngineering/App/SurfaceTriangulation.cpp
@@ -0,0 +1,159 @@
+/***************************************************************************
+ * Copyright (c) 2012 Werner Mayer *
+ * *
+ * This file is part of the FreeCAD CAx development system. *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this library; see the file COPYING.LIB. If not, *
+ * write to the Free Software Foundation, Inc., 59 Temple Place, *
+ * Suite 330, Boston, MA 02111-1307, USA *
+ * *
+ ***************************************************************************/
+
+
+#include "PreCompiled.h"
+
+#include "SurfaceTriangulation.h"
+#include
+#include
+#include
+#include
+
+// http://svn.pointclouds.org/pcl/tags/pcl-1.5.1/test/
+#if defined(PCL_FOUND)
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace pcl;
+using namespace pcl::io;
+using namespace std;
+using namespace Reen;
+
+SurfaceTriangulation::SurfaceTriangulation(const Points::PointKernel& pts, Mesh::MeshObject& mesh)
+ : myPoints(pts), myMesh(mesh)
+{
+}
+
+void SurfaceTriangulation::perform()
+{
+ PointCloud::Ptr cloud (new PointCloud);
+ PointCloud::Ptr cloud_with_normals (new PointCloud);
+ search::KdTree::Ptr tree;
+ search::KdTree::Ptr tree2;
+
+ for (Points::PointKernel::const_iterator it = myPoints.begin(); it != myPoints.end(); ++it) {
+ cloud->push_back(PointXYZ(it->x, it->y, it->z));
+ }
+
+ // Create search tree
+ tree.reset (new search::KdTree (false));
+ tree->setInputCloud (cloud);
+
+ // Normal estimation
+ NormalEstimation n;
+ PointCloud::Ptr normals (new PointCloud ());
+ 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);
+ tree2->setInputCloud (cloud_with_normals);
+
+ // Init objects
+ GreedyProjectionTriangulation 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
+ PolygonMesh mesh;
+ gp3.reconstruct (mesh);
+
+ // number of points
+ int nr_points = mesh.cloud.width * mesh.cloud.height;
+ int point_size = mesh.cloud.data.size () / nr_points;
+ // number of faces for header
+ int nr_faces = mesh.polygons.size ();
+
+ MeshCore::MeshPointArray points;
+ points.reserve(nr_points);
+ MeshCore::MeshFacetArray facets;
+ facets.reserve(nr_faces);
+
+ // get vertices
+ MeshCore::MeshPoint vertex;
+ 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"))
+ {
+ float value;
+ memcpy (&value, &mesh.cloud.data[i * point_size + mesh.cloud.fields[d].offset + c * sizeof (float)], sizeof (float));
+ vertex[xyz] = value;
+ if (++xyz == 3) {
+ points.push_back(vertex);
+ break;
+ }
+ }
+ }
+ }
+ // get faces
+ MeshCore::MeshFacet face;
+ for(int i = 0; i < nr_faces; i++) {
+ face._aulPoints[0] = mesh.polygons[i].vertices[0];
+ face._aulPoints[1] = mesh.polygons[i].vertices[1];
+ face._aulPoints[2] = mesh.polygons[i].vertices[2];
+ facets.push_back(face);
+ }
+
+ MeshCore::MeshKernel kernel;
+ kernel.Adopt(points, facets, true);
+ myMesh.swap(kernel);
+ myMesh.harmonizeNormals();
+
+ // Additional vertex information
+ //std::vector parts = gp3.getPartIDs();
+ //std::vector states = gp3.getPointStates();
+}
+
+#endif // PCL_FOUND
+
diff --git a/src/Mod/ReverseEngineering/App/SurfaceTriangulation.h b/src/Mod/ReverseEngineering/App/SurfaceTriangulation.h
new file mode 100644
index 000000000..5310c2d35
--- /dev/null
+++ b/src/Mod/ReverseEngineering/App/SurfaceTriangulation.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * Copyright (c) 2012 Werner Mayer *
+ * *
+ * This file is part of the FreeCAD CAx development system. *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this library; see the file COPYING.LIB. If not, *
+ * write to the Free Software Foundation, Inc., 59 Temple Place, *
+ * Suite 330, Boston, MA 02111-1307, USA *
+ * *
+ ***************************************************************************/
+
+
+#ifndef REEN_SURFACETRIANGULATION_H
+#define REEN_SURFACETRIANGULATION_H
+
+namespace Points {class PointKernel;}
+namespace Mesh {class MeshObject;}
+
+namespace Reen {
+
+class SurfaceTriangulation
+{
+public:
+ SurfaceTriangulation(const Points::PointKernel&, Mesh::MeshObject&);
+ void perform();
+
+private:
+ const Points::PointKernel& myPoints;
+ Mesh::MeshObject& myMesh;
+};
+
+} // namespace Reen
+
+#endif // REEN_SURFACETRIANGULATION_H
+