Building igl statically and moving to the dep scripts

Fixing dep build script on Windows and removing some warnings.

Use bundled igl by default.

Not building with the dependency scripts if not explicitly stated. This way, it will stay in
Fix the libigl patch to include C source files in header only mode.
This commit is contained in:
tamasmeszaros 2019-06-19 14:52:55 +02:00
parent 89e39e3895
commit 2ae2672ee9
1095 changed files with 181 additions and 5 deletions

View file

@ -0,0 +1,269 @@
// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
#ifndef IGL_XML_REANTTWEAKBAR_XML_SERIALIZATION_H
#define IGL_XML_REANTTWEAKBAR_XML_SERIALIZATION_H
#include "../igl_inline.h"
#include "serialize_xml.h"
#undef IGL_HEADER_ONLY
#include "../anttweakbar/ReAntTweakBar.h"
// Forward declarations
namespace igl
{
namespace anttweakbar
{
class ReTwBar;
}
};
namespace tinyxml2
{
class XMLDocument;
};
namespace igl
{
namespace xml
{
// namespace
// {
// IGL_INLINE bool save_ReAntTweakBar(::igl::anttweakbar::ReTwBar* bar, const char* file_name);
// IGL_INLINE bool save_ReAntTweakBar(::igl::anttweakbar::ReTwBar* bar, tinyxml2::XMLDocument* doc);
// IGL_INLINE bool load_ReAntTweakBar(::igl::anttweakbar::ReTwBar* bar, const char *file_name);
// IGL_INLINE bool load_ReAntTweakBar(::igl::anttweakbar::ReTwBar* bar, tinyxml2::XMLDocument* doc);
IGL_INLINE bool save_ReAntTweakBar(::igl::anttweakbar::ReTwBar* bar, const char* file_name)
{
const char * name_chars = TwGetBarName(bar->bar);
std::string name = std::string(name_chars) + "_AntTweakBar";
const std::vector< ::igl::anttweakbar::ReTwRWItem>& rw_items = bar->get_rw_items();
for(std::vector< ::igl::anttweakbar::ReTwRWItem>::const_iterator it = rw_items.begin(); it != rw_items.end(); it++)
{
std::string val = bar->get_value_as_string(it->var,it->type);
//::igl::XMLSerializer::SaveObject(val,it->name,name,file_name,false);
::igl::serialize_xml(val,it->name,file_name,false,false);
}
char var[REANTTWEAKBAR_MAX_CB_VAR_SIZE];
// Print all CB variables
const std::vector< ::igl::anttweakbar::ReTwCBItem>& cb_items = bar->get_cb_items();
for(std::vector< ::igl::anttweakbar::ReTwCBItem>::const_iterator it = cb_items.begin(); it != cb_items.end(); it++)
{
TwType type = it->type;
//TwSetVarCallback setCallback = it->setCallback;
TwGetVarCallback getCallback = it->getCallback;
void * clientData = it->clientData;
// I'm not sure how to do what I want to do. getCallback needs to be sure
// that it can write to var. So var needs to point to a valid and big
// enough chunk of memory
getCallback(var,clientData);
std::string val = bar->get_value_as_string(var,type);
//::igl::XMLSerializer::SaveObject(val,it->name,name,file_name,false);
::igl::serialize_xml(val,it->name,file_name,false,false);
}
return true;
}
/*IGL_INLINE bool save_ReAntTweakBar(::igl::anttweakbar::ReTwBar* bar, tinyxml2::XMLDocument* doc)
{
std::vector<char**> buffer;
const char * name_chars = TwGetBarName(bar->bar);
std::string name = std::string(name_chars) + "_AntTweakBar";
::igl::XMLSerializer* s = new ::igl::XMLSerializer(name);
const std::vector< ::igl::anttweakbar::ReTwRWItem>& rw_items = bar->get_rw_items();
for(std::vector< ::igl::anttweakbar::ReTwRWItem>::const_iterator it = rw_items.begin(); it != rw_items.end(); it++)
{
std::string val = bar->get_value_as_string(it->var,it->type);
char** cval = new char*; // create char* on heap
*cval = new char[val.size()+1];
buffer.push_back(cval);
strcpy(*cval,val.c_str());
s->Add(*cval,it->name);
}
char var[REANTTWEAKBAR_MAX_CB_VAR_SIZE];
// Print all CB variables
const std::vector< ::igl::anttweakbar::ReTwCBItem>& cb_items = bar->get_cb_items();
for(std::vector< ::igl::anttweakbar::ReTwCBItem>::const_iterator it = cb_items.begin(); it != cb_items.end(); it++)
{
TwType type = it->type;
//TwSetVarCallback setCallback = it->setCallback;
TwGetVarCallback getCallback = it->getCallback;
void * clientData = it->clientData;
// I'm not sure how to do what I want to do. getCallback needs to be sure
// that it can write to var. So var needs to point to a valid and big
// enough chunk of memory
getCallback(var,clientData);
std::string val = bar->get_value_as_string(var,type);
char** cval = new char*; // create char* on heap
*cval = new char[val.size()+1];
buffer.push_back(cval);
strcpy(*cval,val.c_str());
s->Add(*cval,it->name);
}
s->SaveToXMLDoc(name,doc);
// delete pointer buffers
for(unsigned int i=0;i<buffer.size();i++)
{
delete[] *buffer[i];
delete buffer[i];
}
delete s;
return true;
}*/
IGL_INLINE bool load_ReAntTweakBar(::igl::anttweakbar::ReTwBar* bar, const char *file_name)
{
char type_str[REANTTWEAKBAR_MAX_WORD];
char value_str[REANTTWEAKBAR_MAX_WORD];
TwType type;
const char * name_chars = TwGetBarName(bar->bar);
std::string name = std::string(name_chars) + "_AntTweakBar";
const std::vector< ::igl::anttweakbar::ReTwRWItem>& rw_items = bar->get_rw_items();
for(std::vector< ::igl::anttweakbar::ReTwRWItem>::const_iterator it = rw_items.begin(); it != rw_items.end(); it++)
{
char* val;
//::igl::XMLSerializer::LoadObject(val,it->name,name,file_name);
::igl::deserialize_xml(val,it->name,file_name);
sscanf(val,"%s %[^\n]",type_str,value_str);
if(!bar->type_from_string(type_str,type))
{
printf("ERROR: %s type not found... Skipping...\n",type_str);
continue;
}
bar->set_value_from_string(it->name.c_str(),type,value_str);
delete[] val;
}
const std::vector< ::igl::anttweakbar::ReTwCBItem>& cb_items = bar->get_cb_items();
for(std::vector< ::igl::anttweakbar::ReTwCBItem>::const_iterator it = cb_items.begin(); it != cb_items.end(); it++)
{
char* val;
//::igl::XMLSerializer::LoadObject(val,it->name,name,file_name);
::igl::deserialize_xml(val,it->name,file_name);
sscanf(val,"%s %[^\n]",type_str,value_str);
if(!bar->type_from_string(type_str,type))
{
printf("ERROR: %s type not found... Skipping...\n",type_str);
continue;
}
bar->set_value_from_string(it->name.c_str(),type,value_str);
delete[] val;
}
return true;
}
/*IGL_INLINE bool load_ReAntTweakBar(::igl::anttweakbar::ReTwBar* bar, tinyxml2::XMLDocument* doc)
{
std::map<std::string,char*> variables;
std::map<std::string,char*> cbVariables;
const char * name_chars = TwGetBarName(bar->bar);
std::string name = std::string(name_chars) + "_AntTweakBar";
::igl::XMLSerializer* s = new ::igl::XMLSerializer(name);
std::map<std::string,char*>::iterator iter;
const std::vector< ::igl::anttweakbar::ReTwRWItem>& rw_items = bar->get_rw_items();
for(std::vector< ::igl::anttweakbar::ReTwRWItem>::const_iterator it = rw_items.begin(); it != rw_items.end(); it++)
{
variables[it->name] = NULL;
iter = variables.find(it->name);
s->Add(iter->second,iter->first);
}
// Add all CB variables
const std::vector< ::igl::anttweakbar::ReTwCBItem>& cb_items = bar->get_cb_items();
for(std::vector< ::igl::anttweakbar::ReTwCBItem>::const_iterator it = cb_items.begin(); it != cb_items.end(); it++)
{
cbVariables[it->name] = NULL;
iter = cbVariables.find(it->name);
s->Add(iter->second,iter->first);
}
s->LoadFromXMLDoc(doc);
// Set loaded values
char type_str[REANTTWEAKBAR_MAX_WORD];
char value_str[REANTTWEAKBAR_MAX_WORD];
TwType type;
for(iter = variables.begin(); iter != variables.end(); iter++)
{
if(iter->second == NULL)
{
printf("ERROR: '%s' entry not found... Skipping...\n",iter->first.c_str());
continue;
}
sscanf(iter->second,"%s %[^\n]",type_str,value_str);
if(!bar->type_from_string(type_str,type))
{
printf("ERROR: Type '%s' of '%s' not found... Skipping...\n",type_str,iter->first.c_str());
continue;
}
bar->set_value_from_string(iter->first.c_str(),type,value_str);
}
for(iter = cbVariables.begin(); iter != cbVariables.end(); iter++)
{
if(iter->second == NULL)
{
printf("ERROR: '%s' entry not found... Skipping...\n",iter->first.c_str());
continue;
}
sscanf(iter->second,"%s %[^\n]",type_str,value_str);
if(!bar->type_from_string(type_str,type))
{
printf("ERROR: Type '%s' of '%s' not found... Skipping...\n",type_str,iter->first.c_str());
continue;
}
bar->set_value_from_string(iter->first.c_str(),type,value_str);
}
// delete buffers
for(iter = variables.begin(); iter != variables.end(); iter++)
delete[] iter->second;
for(iter = cbVariables.begin(); iter != cbVariables.end(); iter++)
delete[] iter->second;
delete s;
return true;
}*/
// }
}
}
#endif

View file

@ -0,0 +1,225 @@
#ifndef IGL_XML_XMLSERIALIZABLE_H
#define IGL_XML_XMLSERIALIZABLE_H
#include "serialize_xml.h"
#include "../igl_inline.h"
#include "../serialize.h"
#include <tinyxml2.h>
// Interface for xml-serializable class see serialize_xml.h
// Pretty sure all of these IGL_INLINE should be inline
namespace igl
{
namespace xml
{
// interface for user defined types
struct XMLSerializableBase : public SerializableBase
{
virtual void Serialize(std::vector<char>& buffer) const = 0;
virtual void Deserialize(const std::vector<char>& buffer) = 0;
virtual void Serialize(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element) const = 0;
virtual void Deserialize(const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element) = 0;
};
// Convenient interface for user defined types
class XMLSerializable: public XMLSerializableBase
{
private:
template <typename T>
struct XMLSerializationObject: public XMLSerializableBase
{
bool Binary;
std::string Name;
T* Object;
void Serialize(std::vector<char>& buffer) const {
serialize(*Object,Name,buffer);
}
void Deserialize(const std::vector<char>& buffer) {
deserialize(*Object,Name,buffer);
}
void Serialize(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element) const {
serialize_xml(*Object,Name,doc,element,Binary);
}
void Deserialize(const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element) {
deserialize_xml(*Object,Name,doc,element);
}
};
mutable bool initialized;
mutable std::vector<XMLSerializableBase*> objects;
public:
// Override this function to add your member variables which should be serialized
IGL_INLINE virtual void InitSerialization() = 0;
// Following functions can be overridden to handle the specific events.
// Return false to prevent the de-/serialization of an object.
IGL_INLINE virtual bool PreSerialization() const;
IGL_INLINE virtual void PostSerialization() const;
IGL_INLINE virtual bool PreDeserialization();
IGL_INLINE virtual void PostDeserialization();
// Default implementation of XMLSerializableBase interface
IGL_INLINE void Serialize(std::vector<char>& buffer) const;
IGL_INLINE void Deserialize(const std::vector<char>& buffer);
IGL_INLINE void Serialize(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element) const;
IGL_INLINE void Deserialize(const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element);
// Default constructor, destructor, assignment and copy constructor
IGL_INLINE XMLSerializable();
IGL_INLINE XMLSerializable(const XMLSerializable& obj);
IGL_INLINE ~XMLSerializable();
IGL_INLINE XMLSerializable& operator=(const XMLSerializable& obj);
// Use this function to add your variables which should be serialized
template <typename T>
IGL_INLINE void Add(T& obj,std::string name,bool binary = false);
};
// IMPLEMENTATION
IGL_INLINE bool XMLSerializable::PreSerialization() const
{
return true;
}
IGL_INLINE void XMLSerializable::PostSerialization() const
{
}
IGL_INLINE bool XMLSerializable::PreDeserialization()
{
return true;
}
IGL_INLINE void XMLSerializable::PostDeserialization()
{
}
IGL_INLINE void XMLSerializable::Serialize(std::vector<char>& buffer) const
{
if(this->PreSerialization())
{
if(initialized == false)
{
objects.clear();
(const_cast<XMLSerializable*>(this))->InitSerialization();
initialized = true;
}
for(unsigned int i=0;i<objects.size();i++)
objects[i]->Serialize(buffer);
this->PostSerialization();
}
}
IGL_INLINE void XMLSerializable::Deserialize(const std::vector<char>& buffer)
{
if(this->PreDeserialization())
{
if(initialized == false)
{
objects.clear();
(const_cast<XMLSerializable*>(this))->InitSerialization();
initialized = true;
}
for(unsigned int i=0;i<objects.size();i++)
objects[i]->Deserialize(buffer);
this->PostDeserialization();
}
}
IGL_INLINE void XMLSerializable::Serialize(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element) const
{
if(this->PreSerialization())
{
if(initialized == false)
{
objects.clear();
(const_cast<XMLSerializable*>(this))->InitSerialization();
initialized = true;
}
for(unsigned int i=0;i<objects.size();i++)
objects[i]->Serialize(doc,element);
this->PostSerialization();
}
}
IGL_INLINE void XMLSerializable::Deserialize(const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element)
{
if(this->PreDeserialization())
{
if(initialized == false)
{
objects.clear();
(const_cast<XMLSerializable*>(this))->InitSerialization();
initialized = true;
}
for(unsigned int i=0;i<objects.size();i++)
objects[i]->Deserialize(doc,element);
this->PostDeserialization();
}
}
IGL_INLINE XMLSerializable::XMLSerializable()
{
initialized = false;
}
IGL_INLINE XMLSerializable::XMLSerializable(const XMLSerializable& obj)
{
initialized = false;
objects.clear();
}
IGL_INLINE XMLSerializable::~XMLSerializable()
{
initialized = false;
objects.clear();
}
IGL_INLINE XMLSerializable& XMLSerializable::operator=(const XMLSerializable& obj)
{
if(this != &obj)
{
if(initialized)
{
initialized = false;
objects.clear();
}
}
return *this;
}
template <typename T>
IGL_INLINE void XMLSerializable::Add(T& obj,std::string name,bool binary)
{
XMLSerializationObject<T>* object = new XMLSerializationObject<T>();
object->Binary = binary;
object->Name = name;
object->Object = &obj;
objects.push_back(object);
}
}
}
#endif

View file

@ -0,0 +1,489 @@
//
// Copyright (C) 2014 Christian Schüller <schuellchr@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
//#ifndef IGL_SERIALIZATION_TEST_H
//#define IGL_SERIALIZATION_TEST_H
//#include <igl/Timer.h>
#include "serialize_xml.h"
#include "XMLSerializable.h"
namespace igl
{
namespace xml
{
struct Test1111
{
};
struct Test1 : public XMLSerializable
{
std::string ts;
std::vector<Test1*> tvt;
Test1* tt;
Test1()
{
tt = NULL;
}
void InitSerialization()
{
Add(ts,"ts",false);
Add(tvt,"tvt");
Add(tt,"tt");
}
};
struct Test2: public XMLSerializableBase
{
char tc;
int* ti;
std::vector<short> tvb;
float tf;
Test2()
{
tc = '1';
ti = NULL;
tf = 1.0004;
tvb.push_back(2);
tvb.push_back(3);
}
void Serialize(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element) const
{
serialize_xml(tc,"tc",doc,element);
serialize_xml(ti,"ti",doc,element);
serialize_xml(tvb,"tvb",doc,element);
}
void Deserialize(const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element)
{
deserialize_xml(tc,"tc",doc,element);
deserialize_xml(ti,"ti",doc,element);
deserialize_xml(tvb,"tvb",doc,element);
}
void Serialize(std::vector<char>& buffer) const
{
serialize(tc,"tc",buffer);
serialize(ti,"ti",buffer);
serialize(tvb,"tvb",buffer);
serialize(tf,"tf",buffer);
}
void Deserialize(const std::vector<char>& buffer)
{
deserialize(tc,"tc",buffer);
deserialize(ti,"ti",buffer);
deserialize(tvb,"tvb",buffer);
deserialize(tf,"tf",buffer);
}
};
void serialization_test()
{
std::string file("test");
bool tbIn = true,tbOut;
char tcIn = 't',tcOut;
unsigned char tucIn = 'u',tucOut;
short tsIn = 6,tsOut;
int tiIn = -10,tiOut;
unsigned int tuiIn = 10,tuiOut;
float tfIn = 1.0005,tfOut;
double tdIn = 1.000000005,tdOut;
int* tinpIn = NULL,*tinpOut = NULL;
float* tfpIn = new float,*tfpOut = NULL;
*tfpIn = 1.11101;
std::string tstrIn("test12345"),tstrOut;
Test2 tObjIn,tObjOut;
int ti = 2;
tObjIn.ti = &ti;
Test1 test1,test2,test3;
test1.ts = "100";
test2.ts = "200";
test3.ts = "300";
Test1 testA, testC;
testA.tt = &test1;
testA.ts = "test123";
testA.tvt.push_back(&test2);
testA.tvt.push_back(&test3);
Test1 testB = testA;
testB.ts = "400";
testB.tvt.pop_back();
std::pair<int,bool> tPairIn(10,true);
std::pair<int,bool> tPairOut;
std::vector<int> tVector1In ={1,2,3,4,5};
std::vector<int> tVector1Out;
std::pair<int,bool> p1(10,1);
std::pair<int,bool> p2(1,0);
std::pair<int,bool> p3(10000,1);
std::vector<std::pair<int,bool> > tVector2In ={p1,p2,p3};
std::vector<std::pair<int,bool> > tVector2Out;
std::set<std::pair<int,bool> > tSetIn ={p1,p2,p3};
std::set<std::pair<int,bool> > tSetOut;
std::map<int,bool> tMapIn ={p1,p2,p3};
std::map<int,bool> tMapOut;
Eigen::Matrix<float,3,3> tDenseMatrixIn;
tDenseMatrixIn << Eigen::Matrix<float,3,3>::Random();
tDenseMatrixIn.coeffRef(0,0) = 1.00001;
Eigen::Matrix<float,3,3> tDenseMatrixOut;
Eigen::Matrix<float,3,3,Eigen::RowMajor> tDenseRowMatrixIn;
tDenseRowMatrixIn << Eigen::Matrix<float,3,3,Eigen::RowMajor>::Random();
Eigen::Matrix<float,3,3,Eigen::RowMajor> tDenseRowMatrixOut;
Eigen::SparseMatrix<double> tSparseMatrixIn;
tSparseMatrixIn.resize(3,3);
tSparseMatrixIn.insert(0,0) = 1.3;
tSparseMatrixIn.insert(1,1) = 10.2;
tSparseMatrixIn.insert(2,2) = 100.1;
tSparseMatrixIn.finalize();
Eigen::SparseMatrix<double> tSparseMatrixOut;
// binary serialization
serialize(tbIn,file);
deserialize(tbOut,file);
assert(tbIn == tbOut);
serialize(tcIn,file);
deserialize(tcOut,file);
assert(tcIn == tcOut);
serialize(tucIn,file);
deserialize(tucOut,file);
assert(tucIn == tucOut);
serialize(tsIn,file);
deserialize(tsOut,file);
assert(tsIn == tsOut);
serialize(tiIn,file);
deserialize(tiOut,file);
assert(tiIn == tiOut);
serialize(tuiIn,file);
deserialize(tuiOut,file);
assert(tuiIn == tuiOut);
serialize(tfIn,file);
deserialize(tfOut,file);
assert(tfIn == tfOut);
serialize(tdIn,file);
deserialize(tdOut,file);
assert(tdIn == tdOut);
serialize(tinpIn,file);
deserialize(tinpOut,file);
assert(tinpIn == tinpOut);
serialize(tfpIn,file);
deserialize(tfpOut,file);
assert(*tfpIn == *tfpOut);
tfpOut = NULL;
serialize(tstrIn,file);
deserialize(tstrOut,file);
assert(tstrIn == tstrOut);
// updating
serialize(tbIn,"tb",file,true);
serialize(tcIn,"tc",file);
serialize(tiIn,"ti",file);
tiIn++;
serialize(tiIn,"ti",file);
tiIn++;
serialize(tiIn,"ti",file);
deserialize(tbOut,"tb",file);
deserialize(tcOut,"tc",file);
deserialize(tiOut,"ti",file);
assert(tbIn == tbOut);
assert(tcIn == tcOut);
assert(tiIn == tiOut);
serialize(tsIn,"tsIn",file,true);
serialize(tVector1In,"tVector1In",file);
serialize(tVector2In,"tsIn",file);
deserialize(tVector2Out,"tsIn",file);
for(unsigned int i=0;i<tVector2In.size();i++)
{
assert(tVector2In[i].first == tVector2Out[i].first);
assert(tVector2In[i].second == tVector2Out[i].second);
}
tVector2Out.clear();
serialize(tObjIn,file);
deserialize(tObjOut,file);
assert(tObjIn.tc == tObjOut.tc);
assert(*tObjIn.ti == *tObjOut.ti);
for(unsigned int i=0;i<tObjIn.tvb.size();i++)
assert(tObjIn.tvb[i] == tObjOut.tvb[i]);
tObjOut.ti = NULL;
serialize(tPairIn,file);
deserialize(tPairOut,file);
assert(tPairIn.first == tPairOut.first);
assert(tPairIn.second == tPairOut.second);
serialize(tVector1In,file);
deserialize(tVector1Out,file);
for(unsigned int i=0;i<tVector1In.size();i++)
assert(tVector1In[i] == tVector1Out[i]);
serialize(tVector2In,file);
deserialize(tVector2Out,file);
for(unsigned int i=0;i<tVector2In.size();i++)
{
assert(tVector2In[i].first == tVector2Out[i].first);
assert(tVector2In[i].second == tVector2Out[i].second);
}
serialize(tSetIn,file);
deserialize(tSetOut,file);
assert(tSetIn.size() == tSetOut.size());
serialize(tMapIn,file);
deserialize(tMapOut,file);
assert(tMapIn.size() == tMapOut.size());
serialize(tDenseMatrixIn,file);
deserialize(tDenseMatrixOut,file);
assert((tDenseMatrixIn - tDenseMatrixOut).sum() == 0);
serialize(tDenseRowMatrixIn,file);
deserialize(tDenseRowMatrixOut,file);
assert((tDenseRowMatrixIn - tDenseRowMatrixOut).sum() == 0);
serialize(tSparseMatrixIn,file);
deserialize(tSparseMatrixOut,file);
assert((tSparseMatrixIn - tSparseMatrixOut).sum() == 0);
serialize(testB,file);
deserialize(testC,file);
assert(testB.ts == testC.ts);
assert(testB.tvt.size() == testC.tvt.size());
for(unsigned int i=0;i<testB.tvt.size();i++)
{
assert(testB.tvt[i]->ts == testC.tvt[i]->ts);
assert(testB.tvt[i]->tvt.size() == testC.tvt[i]->tvt.size());
assert(testB.tvt[i]->tt == testC.tvt[i]->tt);
}
assert(testB.tt->ts == testC.tt->ts);
assert(testB.tt->tvt.size() == testC.tt->tvt.size());
assert(testB.tt->tt == testC.tt->tt);
testC = Test1();
// big data test
/*std::vector<std::vector<float> > bigDataIn,bigDataOut;
for(unsigned int i=0;i<10000;i++)
{
std::vector<float> v;
for(unsigned int j=0;j<10000;j++)
{
v.push_back(j);
}
bigDataIn.push_back(v);
}
Timer timer;
timer.start();
serialize(bigDataIn,file);
timer.stop();
std::cout << "ser: " << timer.getElapsedTimeInMilliSec() << std::endl;
timer.start();
deserialize(bigDataOut,file);
timer.stop();
std::cout << "des: " << timer.getElapsedTimeInMilliSec() << std::endl;
char c;
std::cin >> c; */
// xml serialization
serialize_xml(tbIn,file);
deserialize_xml(tbOut,file);
assert(tbIn == tbOut);
serialize_xml(tcIn,file);
deserialize_xml(tcOut,file);
assert(tcIn == tcOut);
serialize_xml(tucIn,file);
deserialize_xml(tucOut,file);
assert(tucIn == tucOut);
serialize_xml(tsIn,file);
deserialize_xml(tsOut,file);
assert(tsIn == tsOut);
serialize_xml(tiIn,file);
deserialize_xml(tiOut,file);
assert(tiIn == tiOut);
serialize_xml(tuiIn,file);
deserialize_xml(tuiOut,file);
assert(tuiIn == tuiOut);
serialize_xml(tfIn,file);
deserialize_xml(tfOut,file);
assert(tfIn == tfOut);
serialize_xml(tdIn,file);
deserialize_xml(tdOut,file);
assert(tdIn == tdOut);
serialize_xml(tinpIn,file);
deserialize_xml(tinpOut,file);
assert(tinpIn == tinpOut);
serialize_xml(tfpIn,file);
deserialize_xml(tfpOut,file);
assert(*tfpIn == *tfpOut);
serialize_xml(tstrIn,file);
deserialize_xml(tstrOut,file);
assert(tstrIn == tstrOut);
// updating
serialize_xml(tbIn,"tb",file,false,true);
serialize_xml(tcIn,"tc",file);
serialize_xml(tiIn,"ti",file);
tiIn++;
serialize_xml(tiIn,"ti",file);
tiIn++;
serialize_xml(tiIn,"ti",file);
deserialize_xml(tbOut,"tb",file);
deserialize_xml(tcOut,"tc",file);
deserialize_xml(tiOut,"ti",file);
assert(tbIn == tbOut);
assert(tcIn == tcOut);
assert(tiIn == tiOut);
serialize_xml(tsIn,"tsIn",file,false,true);
serialize_xml(tVector1In,"tVector1In",file);
serialize_xml(tVector2In,"tsIn",file);
deserialize_xml(tVector2Out,"tsIn",file);
for(unsigned int i=0;i<tVector2In.size();i++)
{
assert(tVector2In[i].first == tVector2Out[i].first);
assert(tVector2In[i].second == tVector2Out[i].second);
}
tVector2Out.clear();
// binarization
serialize_xml(tVector2In,"tVector2In",file,true);
deserialize_xml(tVector2Out,"tVector2In",file);
for(unsigned int i=0;i<tVector2In.size();i++)
{
assert(tVector2In[i].first == tVector2Out[i].first);
assert(tVector2In[i].second == tVector2Out[i].second);
}
serialize_xml(tObjIn,file);
deserialize_xml(tObjOut,file);
assert(tObjIn.tc == tObjOut.tc);
assert(*tObjIn.ti == *tObjOut.ti);
for(unsigned int i=0;i<tObjIn.tvb.size();i++)
assert(tObjIn.tvb[i] == tObjOut.tvb[i]);
serialize_xml(tPairIn,file);
deserialize_xml(tPairOut,file);
assert(tPairIn.first == tPairOut.first);
assert(tPairIn.second == tPairOut.second);
serialize_xml(tVector1In,file);
deserialize_xml(tVector1Out,file);
for(unsigned int i=0;i<tVector1In.size();i++)
assert(tVector1In[i] == tVector1Out[i]);
serialize_xml(tVector2In,file);
deserialize_xml(tVector2Out,file);
for(unsigned int i=0;i<tVector2In.size();i++)
{
assert(tVector2In[i].first == tVector2Out[i].first);
assert(tVector2In[i].second == tVector2Out[i].second);
}
serialize_xml(tSetIn,file);
deserialize_xml(tSetOut,file);
assert(tSetIn.size() == tSetOut.size());
serialize_xml(tMapIn,file);
deserialize_xml(tMapOut,file);
assert(tMapIn.size() == tMapOut.size());
serialize_xml(tDenseMatrixIn,file);
deserialize_xml(tDenseMatrixOut,file);
assert((tDenseMatrixIn - tDenseMatrixOut).sum() == 0);
serialize_xml(tDenseRowMatrixIn,file);
deserialize_xml(tDenseRowMatrixOut,file);
assert((tDenseRowMatrixIn - tDenseRowMatrixOut).sum() == 0);
serialize_xml(tSparseMatrixIn,file);
deserialize_xml(tSparseMatrixOut,file);
assert((tSparseMatrixIn - tSparseMatrixOut).sum() == 0);
serialize_xml(testB,file);
deserialize_xml(testC,file);
assert(testB.ts == testC.ts);
assert(testB.tvt.size() == testC.tvt.size());
for(unsigned int i=0;i<testB.tvt.size();i++)
{
assert(testB.tvt[i]->ts == testC.tvt[i]->ts);
assert(testB.tvt[i]->tvt.size() == testC.tvt[i]->tvt.size());
assert(testB.tvt[i]->tt == testC.tvt[i]->tt);
}
assert(testB.tt->ts == testC.tt->ts);
assert(testB.tt->tvt.size() == testC.tt->tvt.size());
assert(testB.tt->tt == testC.tt->tt);
// big data test
/*std::vector<std::vector<float> > bigDataIn,bigDataOut;
for(unsigned int i=0;i<10000;i++)
{
std::vector<float> v;
for(unsigned int j=0;j<10000;j++)
{
v.push_back(j);
}
bigDataIn.push_back(v);
}
Timer timer;
timer.start();
serialize_xml(bigDataIn,"bigDataIn",file,seRIALIZE_BINARY);
timer.stop();
std::cout << "ser: " << timer.getElapsedTimeInMilliSec() << std::endl;
timer.start();
deserialize_xml(bigDataOut,"bigDataIn",file);
timer.stop();
std::cout << "des: " << timer.getElapsedTimeInMilliSec() << std::endl;
char c;
std::cin >> c;*/
std::cout << "All tests run successfully!\n";
}
}
}
//#endif

View file

@ -0,0 +1,912 @@
// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2014 Christian Schüller <schuellchr@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
#include "serialize_xml.h"
#include "../STR.h"
#include "../serialize.h"
#include "XMLSerializable.h"
#include <iterator>
#include <limits>
#include <iomanip>
namespace igl
{
namespace xml
{
template <typename T>
IGL_INLINE void serialize_xml(
const T& obj,
const std::string& filename)
{
serialize_xml(obj,"object",filename,false,true);
}
template <typename T>
IGL_INLINE void serialize_xml(
const T& obj,
const std::string& objectName,
const std::string& filename,
bool binary,
bool overwrite)
{
tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
if(overwrite == false)
{
// Check if file exists
tinyxml2::XMLError error = doc->LoadFile(filename.c_str());
if(error != tinyxml2::XML_SUCCESS)
{
doc->Clear();
}
}
tinyxml2::XMLElement* element = doc->FirstChildElement("serialization");
if(element == NULL)
{
element = doc->NewElement("serialization");
doc->InsertEndChild(element);
}
serialize_xml(obj,objectName,doc,element,binary);
// Save
tinyxml2::XMLError error = doc->SaveFile(filename.c_str());
if(error != tinyxml2::XML_SUCCESS)
{
doc->PrintError();
}
delete doc;
}
template <typename T>
IGL_INLINE void serialize_xml(
const T& obj,
const std::string& objectName,
tinyxml2::XMLDocument* doc,
tinyxml2::XMLElement* element,
bool binary)
{
static_assert(
serialization_xml::is_serializable<T>::value,
"'igl::xml::serialize_xml': type is not serializable");
std::string name(objectName);
serialization_xml::encodeXMLElementName(name);
tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
if(child != NULL)
element->DeleteChild(child);
child = doc->NewElement(name.c_str());
element->InsertEndChild(child);
if(binary)
{
std::vector<char> buffer;
serialize(obj,name,buffer);
std::string data =
serialization_xml::base64_encode(
reinterpret_cast<const unsigned char*>(
buffer.data()),buffer.size());
child->SetAttribute("binary",true);
serialization_xml::serialize(data,doc,element,name);
}
else
{
serialization_xml::serialize(obj,doc,element,name);
}
}
template <typename T>
IGL_INLINE void deserialize_xml(T& obj,const std::string& filename)
{
deserialize_xml(obj,"object",filename);
}
template <typename T>
IGL_INLINE void deserialize_xml(T& obj,const std::string& objectName,const std::string& filename)
{
tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
tinyxml2::XMLError error = doc->LoadFile(filename.c_str());
if(error != tinyxml2::XML_SUCCESS)
{
std::cerr << "File not found!" << std::endl;
doc->PrintError();
doc = NULL;
}
else
{
tinyxml2::XMLElement* element = doc->FirstChildElement("serialization");
if(element == NULL)
{
std::cerr << "Name of object not found! Initialized with default value." << std::endl;
obj = T();
}
else
{
deserialize_xml(obj,objectName,doc,element);
}
delete doc;
}
}
template <typename T>
IGL_INLINE void deserialize_xml(T& obj,const std::string& objectName,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element)
{
static_assert(serialization::is_serializable<T>::value,"'igl::xml::deserialize_xml': type is not deserializable");
std::string name(objectName);
serialization_xml::encodeXMLElementName(name);
const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
if(child != NULL)
{
bool isBinary = false;
const tinyxml2::XMLAttribute* attr = child->FindAttribute("binary");
if(attr != NULL)
{
std::string code;
serialization_xml::deserialize(code,doc,element,name);
std::string decoded = serialization_xml::base64_decode(code);
std::vector<char> buffer;
std::copy(decoded.c_str(),decoded.c_str()+decoded.length(),std::back_inserter(buffer));
deserialize(obj,name,buffer);
}
else
{
serialization_xml::deserialize(obj,doc,element,name);
}
}
}
namespace serialization_xml
{
// fundamental types
template <typename T>
IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value>::type serialize(const T& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
{
tinyxml2::XMLElement* child = getElement(doc,element,name.c_str());
child->SetAttribute("val",obj);
}
template <typename T>
IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value>::type deserialize(T& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
{
const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
if(child != NULL)
{
getAttribute(child->Attribute("val"),obj);
}
else
{
obj = T();
}
}
// std::string
IGL_INLINE void serialize(const std::string& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
{
tinyxml2::XMLElement* child = getElement(doc,element,name.c_str());
child->SetAttribute("val",obj.c_str());
}
IGL_INLINE void deserialize(std::string& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
{
const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
if(child != NULL)
{
getAttribute(child->Attribute("val"),obj);
}
else
{
obj = std::string("");
}
}
// Serializable
template <typename T>
IGL_INLINE typename std::enable_if<std::is_base_of<XMLSerializableBase,T>::value>::type serialize(const T& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
{
// Serialize object implementing Serializable interface
const XMLSerializableBase& object = dynamic_cast<const XMLSerializableBase&>(obj);
tinyxml2::XMLElement* child = getElement(doc,element,name.c_str());
object.Serialize(doc,child);
}
template <typename T>
IGL_INLINE typename std::enable_if<std::is_base_of<XMLSerializableBase,T>::value>::type deserialize(T& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
{
const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
if(child != NULL)
{
obj.Deserialize(doc,child);
}
else
{
obj = T();
}
}
// STL containers
template <typename T1,typename T2>
IGL_INLINE void serialize(const std::pair<T1,T2>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
{
tinyxml2::XMLElement* pair = getElement(doc,element,name.c_str());
serialize(obj.first,doc,pair,"first");
serialize(obj.second,doc,pair,"second");
}
template <typename T1,typename T2>
IGL_INLINE void deserialize(std::pair<T1,T2>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
{
const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
if(child != NULL)
{
deserialize(obj.first,doc,child,"first");
deserialize(obj.second,doc,child,"second");
}
else
{
obj.first = T1();
obj.second = T2();
}
}
template <typename T1,typename T2>
IGL_INLINE void serialize(const std::vector<T1,T2>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
{
tinyxml2::XMLElement* vector = getElement(doc,element,name.c_str());
vector->SetAttribute("size",(unsigned int)obj.size());
std::stringstream num;
for(unsigned int i=0;i<obj.size();i++)
{
num.str("");
num << "value" << i;
serialize(obj[i],doc,vector,num.str());
}
}
template <typename T1,typename T2>
IGL_INLINE void deserialize(std::vector<T1,T2>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
{
obj.clear();
const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
if(child != NULL)
{
unsigned int size = child->UnsignedAttribute("size");
obj.resize(size);
std::stringstream num;
for(unsigned int i=0;i<size;i++)
{
num.str("");
num << "value" << i;
deserialize(obj[i],doc,child,num.str());
}
}
else
{
obj.clear();
}
}
template <typename T>
IGL_INLINE void serialize(const std::set<T>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
{
tinyxml2::XMLElement* set = getElement(doc,element,name.c_str());
set->SetAttribute("size",(unsigned int)obj.size());
std::stringstream num;
typename std::set<T>::iterator iter = obj.begin();
for(int i=0;iter!=obj.end();iter++,i++)
{
num.str("");
num << "value" << i;
serialize((T)*iter,doc,set,num.str());
}
}
template <typename T>
IGL_INLINE void deserialize(std::set<T>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
{
obj.clear();
const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
if(child != NULL)
{
unsigned int size = child->UnsignedAttribute("size");
std::stringstream num;
typename std::set<T>::iterator iter = obj.begin();
for(int i=0;i<size;i++)
{
num.str("");
num << "value" << i;
T val;
deserialize(val,doc,child,num.str());
obj.insert(val);
}
}
else
{
obj.clear();
}
}
template <typename T1,typename T2>
IGL_INLINE void serialize(const std::map<T1,T2>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
{
tinyxml2::XMLElement* map = getElement(doc,element,name.c_str());
map->SetAttribute("size",(unsigned int)obj.size());
std::stringstream num;
typename std::map<T1,T2>::const_iterator iter = obj.cbegin();
for(int i=0;iter!=obj.end();iter++,i++)
{
num.str("");
num << "value" << i;
serialize((std::pair<T1,T2>)*iter,doc,map,num.str());
}
}
template <typename T1,typename T2>
IGL_INLINE void deserialize(std::map<T1,T2>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
{
obj.clear();
const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
if(child != NULL)
{
unsigned int size = child->UnsignedAttribute("size");
std::stringstream num;
typename std::map<T1,T2>::iterator iter = obj.begin();
for(int i=0;i<size;i++)
{
num.str("");
num << "value" << i;
std::pair<T1,T2> pair;
deserialize(pair,doc,child,num.str());
obj.insert(pair);
}
}
else
{
obj.clear();
}
}
template<typename T,int R,int C,int P,int MR,int MC>
IGL_INLINE void serialize(
const Eigen::Matrix<T,R,C,P,MR,MC>& obj,
const std::string& name,
const std::function<std::string(const T &) >& to_string,
tinyxml2::XMLDocument* doc,
tinyxml2::XMLElement* element)
{
tinyxml2::XMLElement* matrix = getElement(doc,element,name.c_str());
const unsigned int rows = obj.rows();
const unsigned int cols = obj.cols();
matrix->SetAttribute("rows",rows);
matrix->SetAttribute("cols",cols);
std::stringstream ms;
ms << "\n";
for(unsigned int r=0;r<rows;r++)
{
for(unsigned int c=0;c<cols;c++)
{
ms << to_string(obj(r,c)) << ",";
}
ms << "\n";
}
std::string mString = ms.str();
if(mString.size() > 1)
mString[mString.size()-2] = '\0';
matrix->SetAttribute("matrix",mString.c_str());
}
// Eigen types
template<typename T,int R,int C,int P,int MR,int MC>
IGL_INLINE void serialize(
const Eigen::Matrix<T,R,C,P,MR,MC>& obj,
tinyxml2::XMLDocument* doc,
tinyxml2::XMLElement* element,
const std::string& name)
{
const std::function<std::string(const T &) > to_string =
[](const T & v)->std::string
{
return
STR(std::setprecision(std::numeric_limits<double>::digits10+2)<<v);
};
serialize(obj,name,to_string,doc,element);
}
template<typename T,int R,int C,int P,int MR,int MC>
IGL_INLINE void deserialize(
const tinyxml2::XMLDocument* doc,
const tinyxml2::XMLElement* element,
const std::string& name,
const std::function<void(const std::string &,T &)> & from_string,
Eigen::Matrix<T,R,C,P,MR,MC>& obj)
{
const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
bool initialized = false;
if(child != NULL)
{
const unsigned int rows = child->UnsignedAttribute("rows");
const unsigned int cols = child->UnsignedAttribute("cols");
if(rows > 0 && cols > 0)
{
obj.resize(rows,cols);
const tinyxml2::XMLAttribute* attribute = child->FindAttribute("matrix");
if(attribute != NULL)
{
std::string matTemp;
getAttribute(attribute->Value(),matTemp);
std::string line,srows,scols;
std::stringstream mats;
mats << matTemp;
int r=0;
std::string val;
// for each line
getline(mats,line);
while(getline(mats,line))
{
// get current line
std::stringstream liness(line);
for(unsigned int c=0;c<cols-1;c++)
{
// split line
getline(liness,val,',');
// push pack the data if any
if(!val.empty())
{
from_string(val,obj.coeffRef(r,c));
}
}
getline(liness,val);
from_string(val,obj.coeffRef(r,cols-1));
r++;
}
initialized = true;
}
}
}
if(!initialized)
{
obj = Eigen::Matrix<T,R,C,P,MR,MC>();
}
}
template<typename T,int R,int C,int P,int MR,int MC>
IGL_INLINE void deserialize(
Eigen::Matrix<T,R,C,P,MR,MC>& obj,
const tinyxml2::XMLDocument* doc,
const tinyxml2::XMLElement* element,
const std::string& name)
{
const std::function<void(const std::string &,T &)> & from_string =
[](const std::string & s,T & v)
{
getAttribute(s.c_str(),v);
};
deserialize(doc,element,name,from_string,obj);
}
template<typename T,int P,typename I>
IGL_INLINE void serialize(const Eigen::SparseMatrix<T,P,I>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
{
tinyxml2::XMLElement* matrix = getElement(doc,element,name.c_str());
const unsigned int rows = obj.rows();
const unsigned int cols = obj.cols();
matrix->SetAttribute("rows",rows);
matrix->SetAttribute("cols",cols);
char buffer[200];
std::stringstream ms;
ms << "\n";
for(int k=0;k<obj.outerSize();++k)
{
for(typename Eigen::SparseMatrix<T,P,I>::InnerIterator it(obj,k);it;++it)
{
tinyxml2::XMLUtil::ToStr(it.value(),buffer,200);
ms << it.row() << "," << it.col() << "," << buffer << "\n";
}
}
std::string mString = ms.str();
if(mString.size() > 0)
mString[mString.size()-1] = '\0';
matrix->SetAttribute("matrix",mString.c_str());
}
template<typename T,int P,typename I>
IGL_INLINE void deserialize(Eigen::SparseMatrix<T,P,I>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
{
const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
bool initialized = false;
if(child != NULL)
{
const unsigned int rows = child->UnsignedAttribute("rows");
const unsigned int cols = child->UnsignedAttribute("cols");
if(rows > 0 && cols > 0)
{
obj.resize(rows,cols);
obj.setZero();
const tinyxml2::XMLAttribute* attribute = child->FindAttribute("matrix");
if(attribute != NULL)
{
std::string matTemp;
getAttribute(attribute->Value(),matTemp);
std::string line,srows,scols;
std::stringstream mats;
mats << matTemp;
std::vector<Eigen::Triplet<T,I> > triplets;
int r=0;
std::string val;
// for each line
getline(mats,line);
while(getline(mats,line))
{
// get current line
std::stringstream liness(line);
// row
getline(liness,val,',');
int row = atoi(val.c_str());
// col
getline(liness,val,',');
int col = atoi(val.c_str());
// val
getline(liness,val);
T value;
getAttribute(val.c_str(),value);
triplets.push_back(Eigen::Triplet<T,I>(row,col,value));
r++;
}
obj.setFromTriplets(triplets.begin(),triplets.end());
initialized = true;
}
}
}
if(!initialized)
{
obj = Eigen::SparseMatrix<T,P,I>();
}
}
// pointers
template <typename T>
IGL_INLINE typename std::enable_if<std::is_pointer<T>::value>::type serialize(const T& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
{
tinyxml2::XMLElement* pointer = getElement(doc,element,name.c_str());
bool isNullPtr = (obj == NULL);
pointer->SetAttribute("isNullPtr",isNullPtr);
if(isNullPtr == false)
serialization_xml::serialize(*obj,doc,element,name);
}
template <typename T>
IGL_INLINE typename std::enable_if<std::is_pointer<T>::value>::type deserialize(T& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
{
const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
if(child != NULL)
{
bool isNullPtr = child->BoolAttribute("isNullPtr");
if(isNullPtr)
{
if(obj != NULL)
{
std::cout << "deserialization: possible memory leak for '" << typeid(obj).name() << "'" << std::endl;
obj = NULL;
}
}
else
{
if(obj != NULL)
std::cout << "deserialization: possible memory leak for '" << typeid(obj).name() << "'" << std::endl;
obj = new typename std::remove_pointer<T>::type();
serialization_xml::deserialize(*obj,doc,element,name);
}
}
}
// helper functions
IGL_INLINE tinyxml2::XMLElement* getElement(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
{
tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
if(child == NULL)
{
child = doc->NewElement(name.c_str());
element->InsertEndChild(child);
}
return child;
}
IGL_INLINE void getAttribute(const char* src,bool& dest)
{
tinyxml2::XMLUtil::ToBool(src,&dest);
}
IGL_INLINE void getAttribute(const char* src,char& dest)
{
dest = (char)atoi(src);
}
IGL_INLINE void getAttribute(const char* src,std::string& dest)
{
dest = src;
}
IGL_INLINE void getAttribute(const char* src,float& dest)
{
tinyxml2::XMLUtil::ToFloat(src,&dest);
}
IGL_INLINE void getAttribute(const char* src,double& dest)
{
tinyxml2::XMLUtil::ToDouble(src,&dest);
}
template<typename T>
IGL_INLINE typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value>::type getAttribute(const char* src,T& dest)
{
unsigned int val;
tinyxml2::XMLUtil::ToUnsigned(src,&val);
dest = (T)val;
}
template<typename T>
IGL_INLINE typename std::enable_if<std::is_integral<T>::value && !std::is_unsigned<T>::value>::type getAttribute(const char* src,T& dest)
{
int val;
tinyxml2::XMLUtil::ToInt(src,&val);
dest = (T)val;
}
// tinyXML2 related stuff
static const int numForbiddenChars = 8;
static const char forbiddenChars[] ={' ','/','~','#','&','>','<','='};
IGL_INLINE void replaceSubString(std::string& str,const std::string& search,const std::string& replace)
{
size_t pos = 0;
while((pos = str.find(search,pos)) != std::string::npos)
{
str.replace(pos,search.length(),replace);
pos += replace.length();
}
}
IGL_INLINE void encodeXMLElementName(std::string& name)
{
// must not start with a digit
if(isdigit(*name.begin()))
{
name = ":::" + name;
}
std::stringstream stream;
for(int i=0;i<numForbiddenChars;i++)
{
std::string search;
search = forbiddenChars[i];
std::stringstream replaces;
replaces << ":" << (int)forbiddenChars[i];
std::string replace = replaces.str();
replaceSubString(name,search,replace);
}
}
IGL_INLINE void decodeXMLElementName(std::string& name)
{
if(name.find("::",0) == 0)
name.replace(0,3,"");
for(auto chr : forbiddenChars)
{
std::stringstream searchs;
searchs << ":" << (int)chr;
std::string search = searchs.str();
std::string replace;
replace = chr;
replaceSubString(name,search,replace);
}
}
/* Copyright(C) 2004-2008 Ren<65> Nyffenegger
This source code is provided 'as-is',without any express or implied
warranty.In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications,and to alter it and redistribute it
freely,subject to the following restrictions:
1. The origin of this source code must not be misrepresented; you must not
claim that you wrote the original source code.If you use this source code
in a product,an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such,and must not be
misrepresented as being the original source code.
3. This notice may not be removed or altered from any source distribution.
Ren<EFBFBD> Nyffenegger rene.nyffenegger@adp-gmbh.ch
*/
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static inline bool is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
std::string base64_encode(unsigned char const* bytes_to_encode,unsigned int in_len)
{
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while(in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if(i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for(i = 0; (i <4) ; i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if(i)
{
for(j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for(j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while((i++ < 3))
ret += '=';
}
return ret;
}
std::string base64_decode(std::string const& encoded_string)
{
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4],char_array_3[3];
std::string ret;
// construct fast lookup table
// added by Christian Sch<63>ller (schuellc@inf.ethz.ch)
int charLookup[200];
for(int i=0;i<(int)(base64_chars.length());i++)
charLookup[(int)base64_chars[i]] = i;
while(in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if(i ==4) {
for(i = 0; i <4; i++)
char_array_4[i] = charLookup[char_array_4[i]]; // new fast lookup
//char_array_4[i] = base64_chars.find(char_array_4[i]); // original version
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for(i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}
if(i) {
for(j = i; j <4; j++)
char_array_4[j] = 0;
for(j = 0; j <4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for(j = 0; (j < i - 1);
j++) ret += char_array_3[j];
}
return ret;
}
}
}
}
#ifdef IGL_STATIC_LIBRARY
// Explicit template instantiation
template void igl::xml::serialize_xml<std::vector<float, std::allocator<float> > >(std::vector<float, std::allocator<float> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool, bool);
template void igl::xml::deserialize_xml<std::vector<float, std::allocator<float> > >(std::vector<float, std::allocator<float> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&);
#endif

View file

@ -0,0 +1,247 @@
//
// Copyright (C) 2014 Christian Sch<63>ller <schuellchr@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
#ifndef IGL_XML_SERIALIZABLE_XML_H
#define IGL_XML_SERIALIZABLE_XML_H
// -----------------------------------------------------------------------------
// Functions to save and load a serialization of fundamental c++ data types to
// and from a xml file. STL containers, Eigen matrix types and nested data
// structures are also supported. To serialize a user defined class implement
// the interface XMLSerializable or XMLSerializableBase.
//
// See also: serialize.h
// -----------------------------------------------------------------------------
#include "../igl_inline.h"
#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <tinyxml2.h>
#include <type_traits>
#include <functional>
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <memory>
//#define SERIALIZE_XML(x) igl::xml::serialize_xml(x,#x,doc,element);
//#define DESERIALIZE_XML(x) igl::xml::deserialize_xml(x,#x,,doc,element);
namespace igl
{
namespace xml
{
struct XMLSerializableBase;
// serializes the given object either to a xml file or to the provided doc data
//
// Templates:
// T type of the object to serialize
// Inputs:
// obj object to serialize
// objectName unique object name,used for the identification
// filename name of the file containing the serialization
// binary set to true to serialize the object in binary format (faster for big data)
// overwrite set to true to overwrite an existing xml file
// element tinyxml2 virtual representation of the current xml node
// Outputs:
// doc contains current tinyxml2 virtual representation of the xml data
//
template <typename T>
IGL_INLINE void serialize_xml(const T& obj,const std::string& filename);
template <typename T>
IGL_INLINE void serialize_xml(
const T& obj,
const std::string& objectName,
const std::string& filename,
bool binary = false,
bool overwrite = false);
template <typename T>
IGL_INLINE void serialize_xml(
const T& obj,
const std::string& objectName,
tinyxml2::XMLDocument* doc,
tinyxml2::XMLElement* element,
bool binary = false);
// deserializes the given data from a xml file or doc data back to the provided object
//
// Templates:
// T type of the object to serialize
// Inputs:
//
// objectName unique object name,used for the identification
// filename name of the file containing the serialization
// binary set to true to serialize the object in binary format (faster for big data)
// overwrite set to true to overwrite an existing xml file
// doc contains current tinyxml2 virtual representation of the xml data
// element tinyxml2 virtual representation of the current xml node
// Outputs:
// obj object to load back serialization to
//
template <typename T>
IGL_INLINE void deserialize_xml(T& obj,const std::string& filename);
template <typename T>
IGL_INLINE void deserialize_xml(T& obj,const std::string& objectName,const std::string& filename);
template <typename T>
IGL_INLINE void deserialize_xml(T& obj,const std::string& objectName,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element);
// internal functions
namespace serialization_xml
{
// fundamental types
template <typename T>
IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value>::type serialize(const T& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name);
template <typename T>
IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value>::type deserialize(T& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name);
// std::string
IGL_INLINE void serialize(const std::string& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name);
IGL_INLINE void deserialize(std::string& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name);
// XMLSerializableBase
template <typename T>
IGL_INLINE typename std::enable_if<std::is_base_of<XMLSerializableBase,T>::value>::type serialize(const T& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name);
template <typename T>
IGL_INLINE typename std::enable_if<std::is_base_of<XMLSerializableBase,T>::value>::type deserialize(T& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name);
// STL containers
template <typename T1, typename T2>
IGL_INLINE void serialize(const std::pair<T1,T2>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name);
template <typename T1,typename T2>
IGL_INLINE void deserialize(std::pair<T1,T2>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name);
template <typename T1,typename T2>
IGL_INLINE void serialize(const std::vector<T1,T2>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name);
template <typename T1,typename T2>
IGL_INLINE void deserialize(std::vector<T1,T2>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name);
template <typename T>
IGL_INLINE void serialize(const std::set<T>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name);
template <typename T>
IGL_INLINE void deserialize(std::set<T>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name);
template <typename T1,typename T2>
IGL_INLINE void serialize(const std::map<T1,T2>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name);
template <typename T1,typename T2>
IGL_INLINE void deserialize(std::map<T1,T2>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name);
// Eigen types
// Serialize a Dense Eigen Matrix to xml (in the matrix= attribute,
// awkward...)
//
// Inputs:
// obj MR by MC matrix of T types
// name name of matrix
// to_string function converting T to string
// Outputs:
// doc pointer to xml document
// element pointer to xml element
//
template<typename T,int R,int C,int P,int MR,int MC>
IGL_INLINE void serialize(
const Eigen::Matrix<T,R,C,P,MR,MC>& obj,
const std::string& name,
const std::function<std::string(const T &) >& to_string,
tinyxml2::XMLDocument* doc,
tinyxml2::XMLElement* element);
// De-Serialize a Dense Eigen Matrix from xml (in the matrix= attribute,
// awkward...)
//
// Inputs:
// doc pointer to xml document
// element pointer to xml element
// name name of matrix
// from_string function string to T
// Outputs:
// obj MR by MC matrix of T types
template<typename T,int R,int C,int P,int MR,int MC>
IGL_INLINE void deserialize(
const tinyxml2::XMLDocument* doc,
const tinyxml2::XMLElement* element,
const std::string& name,
const std::function<void(const std::string &,T &)> & from_string,
Eigen::Matrix<T,R,C,P,MR,MC>& obj);
// Legacy APIs
template<typename T,int R,int C,int P,int MR,int MC>
IGL_INLINE void serialize(
const Eigen::Matrix<T,R,C,P,MR,MC>& obj,
tinyxml2::XMLDocument* doc,
tinyxml2::XMLElement* element,
const std::string& name);
template<typename T,int R,int C,int P,int MR,int MC>
IGL_INLINE void deserialize(
Eigen::Matrix<T,R,C,P,MR,MC>& obj,
const tinyxml2::XMLDocument* doc,
const tinyxml2::XMLElement* element,
const std::string& name);
template<typename T,int P,typename I>
IGL_INLINE void serialize(const Eigen::SparseMatrix<T,P,I>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name);
template<typename T,int P,typename I>
IGL_INLINE void deserialize(Eigen::SparseMatrix<T,P,I>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name);
// raw pointers
template <typename T>
IGL_INLINE typename std::enable_if<std::is_pointer<T>::value>::type serialize(const T& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name);
template <typename T>
IGL_INLINE typename std::enable_if<std::is_pointer<T>::value>::type deserialize(T& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name);
// helper functions
tinyxml2::XMLElement* getElement(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name);
IGL_INLINE void getAttribute(const char* src,bool& dest);
IGL_INLINE void getAttribute(const char* scr,char& dest);
IGL_INLINE void getAttribute(const char* src,std::string& dest);
IGL_INLINE void getAttribute(const char* src,float& dest);
IGL_INLINE void getAttribute(const char* src,double& dest);
template<typename T>
IGL_INLINE typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value>::type getAttribute(const char* src,T& dest);
template<typename T>
IGL_INLINE typename std::enable_if<std::is_integral<T>::value && !std::is_unsigned<T>::value>::type getAttribute(const char* src,T& dest);
IGL_INLINE void replaceSubString(std::string& str,const std::string& search,const std::string& replace);
IGL_INLINE void encodeXMLElementName(std::string& name);
IGL_INLINE void decodeXMLElementName(std::string& name);
IGL_INLINE std::string base64_encode(unsigned char const* bytes_to_encode,unsigned int in_len);
IGL_INLINE std::string base64_decode(std::string const& encoded_string);
// compile time type serializable check
template <typename T>
struct is_stl_container { static const bool value = false; };
template <typename T1,typename T2>
struct is_stl_container<std::pair<T1,T2> > { static const bool value = true; };
template <typename T1,typename T2>
struct is_stl_container<std::vector<T1,T2> > { static const bool value = true; };
template <typename T>
struct is_stl_container<std::set<T> > { static const bool value = true; };
template <typename T1,typename T2>
struct is_stl_container<std::map<T1,T2> > { static const bool value = true; };
template <typename T>
struct is_eigen_type { static const bool value = false; };
template <typename T,int R,int C,int P,int MR,int MC>
struct is_eigen_type<Eigen::Matrix<T,R,C,P,MR,MC> > { static const bool value = true; };
template <typename T,int P,typename I>
struct is_eigen_type<Eigen::SparseMatrix<T,P,I> > { static const bool value = true; };
template <typename T>
struct is_serializable {
using T0 = typename std::remove_pointer<T>::type;
static const bool value = std::is_fundamental<T0>::value || std::is_same<std::string,T0>::value || std::is_base_of<XMLSerializableBase,T0>::value
|| is_stl_container<T0>::value || is_eigen_type<T0>::value;
};
}
}
}
#ifndef IGL_STATIC_LIBRARY
#include "serialize_xml.cpp"
#endif
#endif

View file

@ -0,0 +1,138 @@
// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
#include "writeDAE.h"
#include "../STR.h"
#include <tinyxml2.h>
#include <map>
#include <list>
template <typename DerivedV, typename DerivedF>
IGL_INLINE bool igl::xml::writeDAE(
const std::string & filename,
const Eigen::PlainObjectBase<DerivedV> & V,
const Eigen::PlainObjectBase<DerivedF> & F)
{
using namespace std;
using namespace Eigen;
using namespace tinyxml2;
XMLDocument* doc = new XMLDocument();
const auto & ele = [&doc](
const std::string tag,
// Can't just use `{}` as the default argument because of a clang-bug
// http://stackoverflow.com/questions/17264067/
const std::map<std::string,std::string> attribs =
std::map<std::string,std::string>(),
const std::string text="",
const std::list<XMLElement *> children =
std::list<XMLElement *>()
)->XMLElement *
{
XMLElement * element = doc->NewElement(tag.c_str());
for(const auto & key_value : attribs)
{
element->SetAttribute(key_value.first.c_str(),key_value.second.c_str());
}
if(!text.empty())
{
element->InsertEndChild(doc->NewText(text.c_str()));
}
for(auto & child : children)
{
element->InsertEndChild(child);
}
return element;
};
Eigen::IOFormat row_format(Eigen::FullPrecision,0," "," ","","","");
doc->InsertEndChild(
ele("COLLADA",
{
{"xmlns","http://www.collada.org/2005/11/COLLADASchema"},
{"version","1.4.1"}
},
"",
{
ele("asset",{},"",
{
ele("unit",{{"meter","0.0254000"},{"name","inch"}}),
ele("up_axis",{},"Y_UP")
}),
ele("library_visual_scenes",{},"",
{
ele("visual_scene",{{"id","ID2"}},"",
{
ele("node",{{"name","SketchUp"}},"",
{
ele("node",{{"id","ID3"},{"name","group_0"}},"",
{
ele("matrix",{},"1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1"),
ele("instance_geometry",{{"url","#ID4"}},"",
{
ele("bind_material",{},"",{ele("technique_common")}),
}),
}),
}),
}),
}),
ele("library_geometries",{},"",
{
ele("geometry",{{"id","ID4"}},"",
{
ele("mesh",{},"",
{
ele("source",{{"id","ID7"}},"",
{
ele(
"float_array",
{{"count",STR(V.size())},{"id","ID10"}},
STR(V.format(row_format))),
ele("technique_common",{},"",
{
ele(
"accessor",
{{"count",STR(V.rows())},{"source","#ID8"},{"stride","3"}},
"",
{
ele("param",{{"name","X"},{"type","float"}}),
ele("param",{{"name","Y"},{"type","float"}}),
ele("param",{{"name","Z"},{"type","float"}}),
})
})
}),
ele(
"vertices",
{{"id","ID9"}},
"",
{ele("input",{{"semantic","POSITION"},{"source","#ID7"}})}),
ele(
"triangles",
{{"count",STR(F.rows())}},
"",
{
ele("input",{{"semantic","VERTEX"},{"source","#ID9"}}),
ele("p",{},STR(F.format(row_format))),
})
})
})
}),
ele("scene",{},"",{ele("instance_visual_scene",{{"url","#ID2"}})}),
}));
// tinyxml2 seems **not** to print the <?xml ...?> header by default, but it
// also seems that that's OK
XMLError error = doc->SaveFile(filename.c_str());
bool ret = true;
if(error != XML_NO_ERROR)
{
doc->PrintError();
ret = false;
}
delete doc;
return ret;
}

View file

@ -0,0 +1,38 @@
// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
#ifndef IGL_XML_WRITEDAE_H
#define IGL_XML_WRITEDAE_H
#include "../igl_inline.h"
#include <string>
#include <Eigen/Core>
namespace igl
{
namespace xml
{
// Write a mesh to a Collada .dae scene file. The resulting scene contains
// a single "geometry" suitable for solid operaions (boolean union,
// intersection, etc.) in SketchUp.
//
// Inputs:
// filename path to .dae file
// V #V by 3 list of vertex positions
// F #F by 3 list of face indices
// Returns true iff success
//
template <typename DerivedV, typename DerivedF>
IGL_INLINE bool writeDAE(
const std::string & filename,
const Eigen::PlainObjectBase<DerivedV> & V,
const Eigen::PlainObjectBase<DerivedF> & F);
}
}
#ifndef IGL_STATIC_LIBRARY
#include "writeDAE.cpp"
#endif
#endif

View file

@ -0,0 +1,33 @@
// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
#include "write_triangle_mesh.h"
#include "../write_triangle_mesh.h"
#include "../pathinfo.h"
#include "writeDAE.h"
template <typename DerivedV, typename DerivedF>
IGL_INLINE bool igl::xml::write_triangle_mesh(
const std::string str,
const Eigen::PlainObjectBase<DerivedV>& V,
const Eigen::PlainObjectBase<DerivedF>& F,
const bool ascii)
{
using namespace std;
// dirname, basename, extension and filename
string d,b,e,f;
pathinfo(str,d,b,e,f);
// Convert extension to lower case
std::transform(e.begin(), e.end(), e.begin(), ::tolower);
if(e == "dae")
{
return writeDAE(str,V,F);
}else
{
return igl::write_triangle_mesh(str,V,F,ascii);
}
}

View file

@ -0,0 +1,45 @@
// This file is part of libigl, a simple c++ geometry processing library.
//
// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.
#ifndef IGL_XML_WRITE_TRIANGLE_MESH_H
#define IGL_XML_WRITE_TRIANGLE_MESH_H
#include "../igl_inline.h"
#include <Eigen/Core>
#include <string>
namespace igl
{
namespace xml
{
// write mesh to a file with automatic detection of file format. supported:
// dae, or any of the formats supported by igl::write_triangle_mesh
//
// Templates:
// Scalar type for positions and vectors (will be read as double and cast
// to Scalar)
// Index type for indices (will be read as int and cast to Index)
// Inputs:
// str path to file
// V eigen double matrix #V by 3
// F eigen int matrix #F by 3
// Returns true iff success
template <typename DerivedV, typename DerivedF>
IGL_INLINE bool write_triangle_mesh(
const std::string str,
const Eigen::PlainObjectBase<DerivedV>& V,
const Eigen::PlainObjectBase<DerivedF>& F,
const bool ascii = true);
}
}
#ifndef IGL_STATIC_LIBRARY
# include "write_triangle_mesh.cpp"
#endif
#endif