+ support of export of points to pcd and ply format

This commit is contained in:
wmayer 2016-03-04 14:48:26 +01:00
parent 74a43f23b3
commit a5e6edff87
5 changed files with 495 additions and 5 deletions

View File

@ -67,9 +67,6 @@ public:
add_varargs_method("insert",&Module::importer, add_varargs_method("insert",&Module::importer,
"insert(string|mesh,[string]) -- Load or insert a mesh into the given or active document." "insert(string|mesh,[string]) -- Load or insert a mesh into the given or active document."
); );
add_varargs_method("insert",&Module::importer,
"insert(string|mesh,[string]) -- Load or insert a mesh into the given or active document."
);
add_varargs_method("export",&Module::exporter, add_varargs_method("export",&Module::exporter,
"export(list,string,[tolerance]) -- Export a list of objects into a single file. tolerance is in mm\n" "export(list,string,[tolerance]) -- Export a list of objects into a single file. tolerance is in mm\n"
"and specifies the maximum acceptable deviation between the specified objects and the exported mesh." "and specifies the maximum acceptable deviation between the specified objects and the exported mesh."

View File

@ -43,6 +43,7 @@
#include <App/Application.h> #include <App/Application.h>
#include <App/Document.h> #include <App/Document.h>
#include <App/DocumentObject.h> #include <App/DocumentObject.h>
#include <App/DocumentObjectPy.h>
#include <App/Property.h> #include <App/Property.h>
#include "Points.h" #include "Points.h"
@ -59,7 +60,9 @@ public:
{ {
add_varargs_method("open",&Module::open add_varargs_method("open",&Module::open
); );
add_varargs_method("insert",&Module::insert add_varargs_method("insert",&Module::importer
);
add_varargs_method("export",&Module::exporter
); );
add_varargs_method("show",&Module::show add_varargs_method("show",&Module::show
); );
@ -172,7 +175,7 @@ private:
return Py::None(); return Py::None();
} }
Py::Object insert(const Py::Tuple& args) Py::Object importer(const Py::Tuple& args)
{ {
char* Name; char* Name;
const char* DocName; const char* DocName;
@ -279,6 +282,92 @@ private:
return Py::None(); return Py::None();
} }
Py::Object exporter(const Py::Tuple& args)
{
PyObject *object;
char *Name;
if (!PyArg_ParseTuple(args.ptr(), "Oet", &object, "utf-8", &Name))
throw Py::Exception();
std::string encodedName = std::string(Name);
PyMem_Free(Name);
Base::FileInfo file(encodedName);
// extract ending
if (file.extension().empty())
throw Py::RuntimeError("No file extension");
Py::Sequence list(object);
Base::Type pointsId = Base::Type::fromName("Points::Feature");
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
PyObject* item = (*it).ptr();
if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) {
App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr();
if (obj->getTypeId().isDerivedFrom(pointsId)) {
Points::Feature* fea = static_cast<Points::Feature*>(obj);
const PointKernel& kernel = fea->Points.getValue();
std::auto_ptr<Writer> writer;
if (file.hasExtension("asc")) {
writer.reset(new AscWriter(kernel));
}
#ifdef HAVE_PCL_IO
else if (file.hasExtension("ply")) {
writer.reset(new PlyWriter(kernel));
}
else if (file.hasExtension("pcd")) {
writer.reset(new PcdWriter(kernel));
}
#endif
else {
throw Py::RuntimeError("Unsupported file extension");
}
// get additional properties if there
App::PropertyInteger* width = dynamic_cast<App::PropertyInteger*>
(fea->getPropertyByName("Width"));
if (width) {
writer->setWidth(width->getValue());
}
App::PropertyInteger* height = dynamic_cast<App::PropertyInteger*>
(fea->getPropertyByName("Height"));
if (height) {
writer->setHeight(height->getValue());
}
// get gray values
Points::PropertyGreyValueList* grey = dynamic_cast<Points::PropertyGreyValueList*>
(fea->getPropertyByName("Intensity"));
if (grey) {
writer->setIntensities(grey->getValues());
}
// get colors
App::PropertyColorList* col = dynamic_cast<App::PropertyColorList*>
(fea->getPropertyByName("Color"));
if (col) {
writer->setColors(col->getValues());
}
// get normals
Points::PropertyNormalList* nor = dynamic_cast<Points::PropertyNormalList*>
(fea->getPropertyByName("Normal"));
if (nor) {
writer->setNormals(nor->getValues());
}
writer->write(encodedName);
break;
}
else {
Base::Console().Message("'%s' is not a point object, export will be ignored.\n", obj->Label.getValue());
}
}
}
return Py::None();
}
Py::Object show(const Py::Tuple& args) Py::Object show(const Py::Tuple& args)
{ {
PyObject *pcObj; PyObject *pcObj;

View File

@ -46,6 +46,7 @@
#include <Base/Stream.h> #include <Base/Stream.h>
#include <boost/regex.hpp> #include <boost/regex.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
using namespace Points; using namespace Points;
@ -436,3 +437,355 @@ void PcdReader::read(const std::string& filename)
} }
#endif #endif
// ----------------------------------------------------------------------------
Writer::Writer(const PointKernel& p) : points(p)
{
width = p.size();
height = 1;
}
Writer::~Writer()
{
}
void Writer::setIntensities(const std::vector<float>& i)
{
intensity = i;
}
void Writer::setColors(const std::vector<App::Color>& c)
{
colors = c;
}
void Writer::setNormals(const std::vector<Base::Vector3f>& n)
{
normals = n;
}
void Writer::setWidth(int w)
{
width = w;
}
void Writer::setHeight(int h)
{
height = h;
}
// ----------------------------------------------------------------------------
AscWriter::AscWriter(const PointKernel& p) : Writer(p)
{
}
AscWriter::~AscWriter()
{
}
void AscWriter::write(const std::string& filename)
{
points.save(filename.c_str());
}
// ----------------------------------------------------------------------------
#ifdef HAVE_PCL_IO
PlyWriter::PlyWriter(const PointKernel& p) : Writer(p)
{
}
PlyWriter::~PlyWriter()
{
}
void PlyWriter::write(const std::string& filename)
{
bool hasIntensity = (intensity.size() == points.size());
bool hasColors = (colors.size() == points.size());
bool hasNormals = (normals.size() == points.size());
if (hasNormals && hasColors) {
pcl::PointCloud<pcl::PointXYZRGBNormal> cloud_out;
cloud_out.reserve(points.size());
const std::vector<Base::Vector3f>& pts = points.getBasicPoints();
std::size_t num_points = pts.size();
for (std::size_t index=0; index<num_points; index++) {
const Base::Vector3f& p = pts[index];
const Base::Vector3f& n = normals[index];
const App::Color& c = colors[index];
if (!boost::math::isnan(p.x) && !boost::math::isnan(p.y) && !boost::math::isnan(p.z)) {
pcl::PointXYZRGBNormal pn;
pn.x = p.x;
pn.y = p.y;
pn.z = p.z;
pn.normal_x = n.x;
pn.normal_y = n.y;
pn.normal_z = n.z;
pn.r = c.r * 255.0f;
pn.g = c.g * 255.0f;
pn.b = c.b * 255.0f;
cloud_out.push_back(pn);
}
}
pcl::io::savePLYFile<pcl::PointXYZRGBNormal>(filename, cloud_out);
}
else if (hasNormals && hasIntensity) {
pcl::PointCloud<pcl::PointXYZINormal> cloud_out;
cloud_out.reserve(points.size());
const std::vector<Base::Vector3f>& pts = points.getBasicPoints();
std::size_t num_points = pts.size();
for (std::size_t index=0; index<num_points; index++) {
const Base::Vector3f& p = pts[index];
const Base::Vector3f& n = normals[index];
if (!boost::math::isnan(p.x) && !boost::math::isnan(p.y) && !boost::math::isnan(p.z)) {
pcl::PointXYZINormal pn;
pn.x = p.x;
pn.y = p.y;
pn.z = p.z;
pn.normal_x = n.x;
pn.normal_y = n.y;
pn.normal_z = n.z;
pn.intensity = intensity[index];
cloud_out.push_back(pn);
}
}
pcl::io::savePLYFile<pcl::PointXYZINormal>(filename, cloud_out);
}
else if (hasColors) {
pcl::PointCloud<pcl::PointXYZRGBA> cloud_out;
cloud_out.reserve(points.size());
const std::vector<Base::Vector3f>& pts = points.getBasicPoints();
std::size_t num_points = pts.size();
for (std::size_t index=0; index<num_points; index++) {
const Base::Vector3f& p = pts[index];
const App::Color& c = colors[index];
if (!boost::math::isnan(p.x) && !boost::math::isnan(p.y) && !boost::math::isnan(p.z)) {
pcl::PointXYZRGBA pc;
pc.x = p.x;
pc.y = p.y;
pc.z = p.z;
pc.r = c.r * 255.0f;
pc.g = c.g * 255.0f;
pc.b = c.b * 255.0f;
cloud_out.push_back(pc);
}
}
pcl::io::savePLYFile<pcl::PointXYZRGBA>(filename, cloud_out);
}
else if (hasIntensity) {
pcl::PointCloud<pcl::PointXYZI> cloud_out;
cloud_out.reserve(points.size());
const std::vector<Base::Vector3f>& pts = points.getBasicPoints();
std::size_t num_points = pts.size();
for (std::size_t index=0; index<num_points; index++) {
const Base::Vector3f& p = pts[index];
if (!boost::math::isnan(p.x) && !boost::math::isnan(p.y) && !boost::math::isnan(p.z)) {
pcl::PointXYZI pi;
pi.x = p.x;
pi.y = p.y;
pi.z = p.z;
pi.intensity = intensity[index];
cloud_out.push_back(pi);
}
}
pcl::io::savePLYFile<pcl::PointXYZI>(filename, cloud_out);
}
else if (hasNormals) {
pcl::PointCloud<pcl::PointNormal> cloud_out;
cloud_out.reserve(points.size());
const std::vector<Base::Vector3f>& pts = points.getBasicPoints();
std::size_t num_points = pts.size();
for (std::size_t index=0; index<num_points; index++) {
const Base::Vector3f& p = pts[index];
const Base::Vector3f& n = normals[index];
if (!boost::math::isnan(p.x) && !boost::math::isnan(p.y) && !boost::math::isnan(p.z)) {
pcl::PointNormal pn;
pn.x = p.x;
pn.y = p.y;
pn.z = p.z;
pn.normal_x = n.x;
pn.normal_y = n.y;
pn.normal_z = n.z;
cloud_out.push_back(pn);
}
}
pcl::io::savePLYFile<pcl::PointNormal>(filename, cloud_out);
}
else {
pcl::PointCloud<pcl::PointXYZ> cloud_out;
cloud_out.reserve(points.size());
for (Points::PointKernel::const_iterator it = points.begin(); it != points.end(); ++it) {
if (!boost::math::isnan(it->x) && !boost::math::isnan(it->y) && !boost::math::isnan(it->z)) {
cloud_out.push_back(pcl::PointXYZ(it->x, it->y, it->z));
}
}
pcl::io::savePLYFile<pcl::PointXYZ>(filename, cloud_out);
}
}
// ----------------------------------------------------------------------------
PcdWriter::PcdWriter(const PointKernel& p) : Writer(p)
{
}
PcdWriter::~PcdWriter()
{
}
void PcdWriter::write(const std::string& filename)
{
bool hasIntensity = (intensity.size() == points.size());
bool hasColors = (colors.size() == points.size());
bool hasNormals = (normals.size() == points.size());
if (hasNormals && hasColors) {
pcl::PointCloud<pcl::PointXYZRGBNormal> cloud_out;
cloud_out.reserve(points.size());
const std::vector<Base::Vector3f>& pts = points.getBasicPoints();
std::size_t num_points = pts.size();
for (std::size_t index=0; index<num_points; index++) {
const Base::Vector3f& p = pts[index];
const Base::Vector3f& n = normals[index];
const App::Color& c = colors[index];
pcl::PointXYZRGBNormal pn;
pn.x = p.x;
pn.y = p.y;
pn.z = p.z;
pn.normal_x = n.x;
pn.normal_y = n.y;
pn.normal_z = n.z;
pn.r = c.r * 255.0f;
pn.g = c.g * 255.0f;
pn.b = c.b * 255.0f;
cloud_out.push_back(pn);
}
cloud_out.width = width;
cloud_out.height = height;
pcl::io::savePCDFile<pcl::PointXYZRGBNormal>(filename, cloud_out);
}
else if (hasNormals && hasIntensity) {
pcl::PointCloud<pcl::PointXYZINormal> cloud_out;
cloud_out.reserve(points.size());
const std::vector<Base::Vector3f>& pts = points.getBasicPoints();
std::size_t num_points = pts.size();
for (std::size_t index=0; index<num_points; index++) {
const Base::Vector3f& p = pts[index];
const Base::Vector3f& n = normals[index];
pcl::PointXYZINormal pn;
pn.x = p.x;
pn.y = p.y;
pn.z = p.z;
pn.normal_x = n.x;
pn.normal_y = n.y;
pn.normal_z = n.z;
pn.intensity = intensity[index];
cloud_out.push_back(pn);
}
cloud_out.width = width;
cloud_out.height = height;
pcl::io::savePCDFile<pcl::PointXYZINormal>(filename, cloud_out);
}
else if (hasColors) {
pcl::PointCloud<pcl::PointXYZRGBA> cloud_out;
cloud_out.reserve(points.size());
const std::vector<Base::Vector3f>& pts = points.getBasicPoints();
std::size_t num_points = pts.size();
for (std::size_t index=0; index<num_points; index++) {
const Base::Vector3f& p = pts[index];
const App::Color& c = colors[index];
pcl::PointXYZRGBA pc;
pc.x = p.x;
pc.y = p.y;
pc.z = p.z;
pc.r = c.r * 255.0f;
pc.g = c.g * 255.0f;
pc.b = c.b * 255.0f;
cloud_out.push_back(pc);
}
cloud_out.width = width;
cloud_out.height = height;
pcl::io::savePCDFile<pcl::PointXYZRGBA>(filename, cloud_out);
}
else if (hasIntensity) {
pcl::PointCloud<pcl::PointXYZI> cloud_out;
cloud_out.reserve(points.size());
const std::vector<Base::Vector3f>& pts = points.getBasicPoints();
std::size_t num_points = pts.size();
for (std::size_t index=0; index<num_points; index++) {
const Base::Vector3f& p = pts[index];
pcl::PointXYZI pi;
pi.x = p.x;
pi.y = p.y;
pi.z = p.z;
pi.intensity = intensity[index];
cloud_out.push_back(pi);
}
cloud_out.width = width;
cloud_out.height = height;
pcl::io::savePCDFile<pcl::PointXYZI>(filename, cloud_out);
}
else if (hasNormals) {
pcl::PointCloud<pcl::PointNormal> cloud_out;
cloud_out.reserve(points.size());
const std::vector<Base::Vector3f>& pts = points.getBasicPoints();
std::size_t num_points = pts.size();
for (std::size_t index=0; index<num_points; index++) {
const Base::Vector3f& p = pts[index];
const Base::Vector3f& n = normals[index];
pcl::PointNormal pn;
pn.x = p.x;
pn.y = p.y;
pn.z = p.z;
pn.normal_x = n.x;
pn.normal_y = n.y;
pn.normal_z = n.z;
cloud_out.push_back(pn);
}
cloud_out.width = width;
cloud_out.height = height;
pcl::io::savePCDFile<pcl::PointNormal>(filename, cloud_out);
}
else {
pcl::PointCloud<pcl::PointXYZ> cloud_out;
cloud_out.reserve(points.size());
for (Points::PointKernel::const_iterator it = points.begin(); it != points.end(); ++it) {
cloud_out.push_back(pcl::PointXYZ(it->x, it->y, it->z));
}
cloud_out.width = width;
cloud_out.height = height;
pcl::io::savePCDFile<pcl::PointXYZ>(filename, cloud_out);
}
}
#endif

View File

@ -97,6 +97,53 @@ public:
}; };
#endif #endif
class Writer
{
public:
Writer(const PointKernel&);
virtual ~Writer();
virtual void write(const std::string& filename) = 0;
void setIntensities(const std::vector<float>&);
void setColors(const std::vector<App::Color>&);
void setNormals(const std::vector<Base::Vector3f>&);
void setWidth(int);
void setHeight(int);
protected:
const PointKernel& points;
std::vector<float> intensity;
std::vector<App::Color> colors;
std::vector<Base::Vector3f> normals;
int width, height;
};
class AscWriter : public Writer
{
public:
AscWriter(const PointKernel&);
~AscWriter();
void write(const std::string& filename);
};
#ifdef HAVE_PCL_IO
class PlyWriter : public Writer
{
public:
PlyWriter(const PointKernel&);
~PlyWriter();
void write(const std::string& filename);
};
class PcdWriter : public Writer
{
public:
PcdWriter(const PointKernel&);
~PcdWriter();
void write(const std::string& filename);
};
#endif
} // namespace Points } // namespace Points

View File

@ -31,3 +31,7 @@
FreeCAD.addImportType("Point formats (*.asc)","Points") FreeCAD.addImportType("Point formats (*.asc)","Points")
FreeCAD.addImportType("PLY points (*.ply)","Points") FreeCAD.addImportType("PLY points (*.ply)","Points")
FreeCAD.addImportType("PCD points (*.pcd)","Points") FreeCAD.addImportType("PCD points (*.pcd)","Points")
FreeCAD.addExportType("Point formats (*.asc)","Points")
FreeCAD.addExportType("PLY points (*.ply)","Points")
FreeCAD.addExportType("PCD points (*.pcd)","Points")