Skip to content

Commit

Permalink
Added some metadata to exported AMF
Browse files Browse the repository at this point in the history
  • Loading branch information
ianrrees authored and wwmayer committed Mar 2, 2017
1 parent 0bd3e5d commit e178d93
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 18 deletions.
11 changes: 9 additions & 2 deletions src/Mod/Mesh/App/AppMeshPy.cpp
Expand Up @@ -24,6 +24,7 @@
#ifndef _PreComp_
# include <algorithm>
# include <memory>
# include <map>
#endif

#include <CXX/Extensions.hxx>
Expand Down Expand Up @@ -305,7 +306,13 @@ class Module : public Py::ExtensionModule<Module>

std::unique_ptr<Exporter> exporter;
if (exportFormat == MeshIO::AMF) {
exporter.reset( new AmfExporter(EncodedName) );
std::map<std::string, std::string> meta;
meta["cad"] = App::Application::Config()["ExeName"] + " " +
App::Application::Config()["ExeVersion"];
meta[App::Application::Config()["ExeName"] + "-buildRevisionHash"] =
App::Application::Config()["BuildRevisionHash"];

exporter.reset( new AmfExporter(EncodedName, meta) );
} else {
// TODO: How do we handle unknown exportFormats?
exporter.reset( new MergeExporter(EncodedName, exportFormat) );
Expand All @@ -323,7 +330,7 @@ class Module : public Py::ExtensionModule<Module>
if (obj->getTypeId().isDerivedFrom(meshId)) {
exporter->addMesh( static_cast<Mesh::Feature*>(obj) );
} else if (obj->getTypeId().isDerivedFrom(partId)) {
exporter->addShape( obj->getPropertyByName("Shape"), fTolerance );
exporter->addPart( obj, fTolerance );
} else {
Base::Console().Message("'%s' is not a mesh or shape, export will be ignored.\n", obj->Label.getValue());
}
Expand Down
51 changes: 41 additions & 10 deletions src/Mod/Mesh/App/Exporter.cpp
Expand Up @@ -23,8 +23,8 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <algorithm>
#include <map>
#include <vector>
#include <boost/algorithm/string/replace.hpp>
#endif // #ifndef _PreComp_

#include "Exporter.h"
Expand All @@ -42,6 +42,17 @@
using namespace Mesh;
using namespace MeshCore;

//static
std::string Exporter::xmlEscape(const std::string &input)
{
std::string out(input);
boost::replace_all(out, "&", "&amp;");
boost::replace_all(out, "\"", "&quot;");
boost::replace_all(out, "'", "&apos;");
boost::replace_all(out, "<", "&lt;");
boost::replace_all(out, ">", "&gt;");
return out;
}

MergeExporter::MergeExporter(std::string fileName, MeshIO::Format fmt)
:fName(fileName)
Expand Down Expand Up @@ -110,8 +121,9 @@ bool MergeExporter::addMesh(Mesh::Feature *meshFeat)
return true;
}

bool MergeExporter::addShape(App::Property *shape, float tol)
bool MergeExporter::addPart(App::DocumentObject *obj, float tol)
{
auto *shape(obj->getPropertyByName("Shape"));
if (shape && shape->getTypeId().isDerivedFrom(App::PropertyComplexGeoData::getClassTypeId())) {
Base::Reference<MeshObject> mesh(new MeshObject());

Expand Down Expand Up @@ -145,7 +157,9 @@ bool MergeExporter::addShape(App::Property *shape, float tol)
return false;
}

AmfExporter::AmfExporter(std::string fileName, bool compress) :
AmfExporter::AmfExporter( std::string fileName,
const std::map<std::string, std::string> &meta,
bool compress ) :
outputStreamPtr(nullptr), nextObjectIndex(0)
{
// ask for write permission
Expand Down Expand Up @@ -173,6 +187,10 @@ AmfExporter::AmfExporter(std::string fileName, bool compress) :
if (outputStreamPtr) {
*outputStreamPtr << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
<< "<amf unit=\"millimeter\">\n";
for (auto const &metaEntry : meta) {
*outputStreamPtr << "\t<metadata type=\"" << metaEntry.first
<< "\">" << metaEntry.second << "</metadata>\n";
}
}
}

Expand All @@ -193,9 +211,10 @@ AmfExporter::~AmfExporter()
}
}

bool AmfExporter::addShape(App::Property *shape, float tol)
bool AmfExporter::addPart(App::DocumentObject *obj, float tol)
{
// TODO: Add meta info, look into a different way to extract mesh with vertex normals
auto *shape(obj->getPropertyByName("Shape"));
// TODO: Look into a different way to extract mesh with vertex normals
if (shape && shape->getTypeId().isDerivedFrom(App::PropertyComplexGeoData::getClassTypeId())) {
Base::Reference<MeshObject> mesh(new MeshObject());

Expand All @@ -213,7 +232,10 @@ bool AmfExporter::addShape(App::Property *shape, float tol)
MeshCore::MeshKernel kernel = mesh->getKernel();
kernel.Transform(mesh->getTransform());

return addMesh(kernel);
std::map<std::string, std::string> meta;
meta["name"] = xmlEscape(obj->Label.getStrValue());

return addMesh(kernel, meta);
}
return false;
}
Expand All @@ -225,10 +247,14 @@ bool AmfExporter::addMesh(Mesh::Feature *meshFeat)
MeshCore::MeshKernel kernel( mesh.getKernel() );
kernel.Transform(mesh.getTransform());

return addMesh(kernel);
std::map<std::string, std::string> meta;
meta["name"] = xmlEscape(meshFeat->Label.getStrValue());

return addMesh(kernel, meta);
}

bool AmfExporter::addMesh(const MeshCore::MeshKernel &kernel)
bool AmfExporter::addMesh(const MeshCore::MeshKernel &kernel,
const std::map<std::string, std::string> &meta)
{
if (!outputStreamPtr || outputStreamPtr->bad()) {
return false;
Expand All @@ -244,8 +270,13 @@ bool AmfExporter::addMesh(const MeshCore::MeshKernel &kernel)

Base::SequencerLauncher seq("Saving...", 2 * numFacets + 1);

*outputStreamPtr << "\t<object id=\"" << nextObjectIndex << "\">\n"
<< "\t\t<mesh>\n"
*outputStreamPtr << "\t<object id=\"" << nextObjectIndex << "\">\n";

for (auto const &metaEntry : meta) {
*outputStreamPtr << "\t\t<metadata type=\"" << metaEntry.first
<< "\">" << metaEntry.second << "</metadata>\n";
}
*outputStreamPtr << "\t\t<mesh>\n"
<< "\t\t\t<vertices>\n";

const MeshCore::MeshGeomFacet *facet;
Expand Down
28 changes: 22 additions & 6 deletions src/Mod/Mesh/App/Exporter.h
Expand Up @@ -25,6 +25,7 @@

#include "PreCompiled.h"
#ifndef _PreComp_
#include <map>
#include <ostream>
#endif // #ifndef _PreComp_

Expand All @@ -42,7 +43,7 @@ namespace Mesh
* Constructors of derived classes are expected to be required, for passing
* in the name of output file.
*
* Objects are added using the addMesh(), addShape(), etc.
* Objects are added using the addMesh(), addPart(), etc.
*
* If objects are meant to be combined into a single file, then the file should
* be saved from the derived class' destructor.
Expand All @@ -51,8 +52,13 @@ class Exporter
{
public:
virtual bool addMesh(Mesh::Feature *meshFeat) = 0;
virtual bool addShape(App::Property *shape, float tol) = 0;
virtual bool addPart(App::DocumentObject *obj, float tol) = 0;
virtual ~Exporter() {};

protected:
/// Does some simple escaping of characters for XML-type exports
//TODO: Use xerces or something instead?
static std::string xmlEscape(const std::string &input);
};

/// Creates a single mesh, in a file, from one or more objects
Expand All @@ -65,7 +71,7 @@ class MergeExporter : public Exporter
/// Directly adds a mesh
bool addMesh(Mesh::Feature *meshFeat);
/// Converts the a Part::Feature to a mesh, adds that mesh
bool addShape(App::Property *shape, float tol);
bool addPart(App::DocumentObject *obj, float tol);
protected:
MeshObject mergingMesh;
std::string fName;
Expand All @@ -80,14 +86,24 @@ class AmfExporter : public Exporter
{
public:
/// Writes AMF header
AmfExporter(std::string fileName, bool compress = true);
/*!
* meta information passed in is applied at the <amf> tag level
*/
AmfExporter(std::string fileName,
const std::map<std::string, std::string> &meta,
bool compress = false);

/// Writes AMF footer
~AmfExporter();

bool addMesh(Mesh::Feature *meshFeat);
bool addMesh(const MeshCore::MeshKernel &kernel);
bool addShape(App::Property *shape, float tol);

/*!
* meta is included for the AMF object created
*/
bool addMesh(const MeshCore::MeshKernel &kernel,
const std::map<std::string, std::string> &meta);
bool addPart(App::DocumentObject *obj, float tol);

private:
std::ostream *outputStreamPtr;
Expand Down

0 comments on commit e178d93

Please sign in to comment.