Skip to content

Commit

Permalink
+ save Brep in binary format for recovery files
Browse files Browse the repository at this point in the history
  • Loading branch information
wwmayer committed Sep 16, 2015
1 parent 739e643 commit 32367b1
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 79 deletions.
11 changes: 8 additions & 3 deletions src/Base/Reader.cpp
Expand Up @@ -319,7 +319,7 @@ void Base::XMLReader::readFiles(zipios::ZipInputStream &zipstream) const
// no file name for the current entry in the zip was registered.
if (jt != FileList.end()) {
try {
Base::Reader reader(zipstream,DocumentSchema);
Base::Reader reader(zipstream, jt->FileName, DocumentSchema);
jt->Object->RestoreDocFile(reader);
}
catch(...) {
Expand Down Expand Up @@ -506,11 +506,16 @@ void Base::XMLReader::resetErrors()

// ----------------------------------------------------------

Base::Reader::Reader(std::istream& str, int version)
: std::istream(str.rdbuf()), _str(str), fileVersion(version)
Base::Reader::Reader(std::istream& str, const std::string& name, int version)
: std::istream(str.rdbuf()), _str(str), _name(name), fileVersion(version)
{
}

std::string Base::Reader::getFileName() const
{
return this->_name;
}

int Base::Reader::getFileVersion() const
{
return fileVersion;
Expand Down
6 changes: 4 additions & 2 deletions src/Base/Reader.h
Expand Up @@ -257,12 +257,14 @@ class BaseExport XMLReader : public XERCES_CPP_NAMESPACE_QUALIFIER DefaultHandle
class BaseExport Reader : public std::istream
{
public:
Reader(std::istream&, int version);
int getFileVersion() const;
Reader(std::istream&, const std::string&, int version);
std::istream& getStream();
std::string getFileName() const;
int getFileVersion() const;

private:
std::istream& _str;
std::string _name;
int fileVersion;
};

Expand Down
18 changes: 18 additions & 0 deletions src/Base/Writer.cpp
Expand Up @@ -108,6 +108,24 @@ int Writer::getFileVersion() const
return fileVersion;
}

void Writer::setMode(const std::string& mode)
{
Modes.insert(mode);
}

bool Writer::getMode(const std::string& mode) const
{
std::set<std::string>::const_iterator it = Modes.find(mode);
return (it != Modes.end());
}

void Writer::clearMode(const std::string& mode)
{
std::set<std::string>::iterator it = Modes.find(mode);
if (it != Modes.end())
Modes.erase(it);
}

std::string Writer::addFile(const char* Name,const Base::Persistence *Object)
{
// always check isForceXML() before requesting a file!
Expand Down
8 changes: 8 additions & 0 deletions src/Base/Writer.h
Expand Up @@ -24,6 +24,7 @@
#define BASE_WRITER_H


#include <set>
#include <string>
#include <sstream>
#include <vector>
Expand Down Expand Up @@ -80,6 +81,12 @@ class BaseExport Writer
virtual void writeFiles(void)=0;
/// get all registered file names
const std::vector<std::string>& getFilenames() const;
/// Set mode
void setMode(const std::string& mode);
/// Get mode
bool getMode(const std::string& mode) const;
/// Clear mode
void clearMode(const std::string& mode);
//@}

/** @name pretty formating for XML */
Expand All @@ -105,6 +112,7 @@ class BaseExport Writer
};
std::vector<FileEntry> FileList;
std::vector<std::string> FileNames;
std::set<std::string> Modes;

short indent;
char indBuf[1024];
Expand Down
2 changes: 2 additions & 0 deletions src/Gui/AutoSaver.cpp
Expand Up @@ -139,6 +139,8 @@ void AutoSaver::saveDocument(const std::string& name)
Base::ofstream file(tmp, std::ios::out | std::ios::binary);
if (file.is_open()) {
Base::ZipWriter writer(file);
if (hGrp->GetBool("SaveBinaryBrep", true))
writer.setMode("BinaryBrep");

writer.setComment("AutoRecovery file");
writer.setLevel(1); // apparently the fastest compression
Expand Down
170 changes: 96 additions & 74 deletions src/Mod/Part/App/PropertyTopoShape.cpp
Expand Up @@ -232,9 +232,16 @@ void PropertyPartShape::Save (Base::Writer &writer) const
{
if(!writer.isForceXML()) {
//See SaveDocFile(), RestoreDocFile()
writer.Stream() << writer.ind() << "<Part file=\""
<< writer.addFile("PartShape.brp", this)
<< "\"/>" << std::endl;
if (writer.getMode("BinaryBrep")) {
writer.Stream() << writer.ind() << "<Part file=\""
<< writer.addFile("PartShape.bin", this)
<< "\"/>" << std::endl;
}
else {
writer.Stream() << writer.ind() << "<Part file=\""
<< writer.addFile("PartShape.brp", this)
<< "\"/>" << std::endl;
}
}
}

Expand All @@ -261,92 +268,107 @@ void PropertyPartShape::SaveDocFile (Base::Writer &writer) const
const TopoDS_Shape& myShape = copy.Shape();
BRepTools::Clean(myShape); // remove triangulation

// create a temporary file and copy the content to the zip stream
// once the tmp. filename is known use always the same because otherwise
// we may run into some problems on the Linux platform
static Base::FileInfo fi(Base::FileInfo::getTempFileName());

if (!BRepTools::Write(myShape,(const Standard_CString)fi.filePath().c_str())) {
// Note: Do NOT throw an exception here because if the tmp. file could
// not be created we should not abort.
// We only print an error message but continue writing the next files to the
// stream...
App::PropertyContainer* father = this->getContainer();
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
Base::Console().Error("Shape of '%s' cannot be written to BRep file '%s'\n",
obj->Label.getValue(),fi.filePath().c_str());
}
else {
Base::Console().Error("Cannot save BRep file '%s'\n", fi.filePath().c_str());
}
if (writer.getMode("BinaryBrep")) {
TopoShape shape;
shape._Shape = myShape;
shape.exportBinary(writer.Stream());
}
else {
// create a temporary file and copy the content to the zip stream
// once the tmp. filename is known use always the same because otherwise
// we may run into some problems on the Linux platform
static Base::FileInfo fi(Base::FileInfo::getTempFileName());

if (!BRepTools::Write(myShape,(const Standard_CString)fi.filePath().c_str())) {
// Note: Do NOT throw an exception here because if the tmp. file could
// not be created we should not abort.
// We only print an error message but continue writing the next files to the
// stream...
App::PropertyContainer* father = this->getContainer();
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
Base::Console().Error("Shape of '%s' cannot be written to BRep file '%s'\n",
obj->Label.getValue(),fi.filePath().c_str());
}
else {
Base::Console().Error("Cannot save BRep file '%s'\n", fi.filePath().c_str());
}
}

Base::ifstream file(fi, std::ios::in | std::ios::binary);
if (file){
unsigned long ulSize = 0;
std::streambuf* buf = file.rdbuf();
if (buf) {
unsigned long ulCurr;
ulCurr = buf->pubseekoff(0, std::ios::cur, std::ios::in);
ulSize = buf->pubseekoff(0, std::ios::end, std::ios::in);
buf->pubseekoff(ulCurr, std::ios::beg, std::ios::in);
Base::ifstream file(fi, std::ios::in | std::ios::binary);
if (file){
unsigned long ulSize = 0;
std::streambuf* buf = file.rdbuf();
if (buf) {
unsigned long ulCurr;
ulCurr = buf->pubseekoff(0, std::ios::cur, std::ios::in);
ulSize = buf->pubseekoff(0, std::ios::end, std::ios::in);
buf->pubseekoff(ulCurr, std::ios::beg, std::ios::in);
}

// read in the ASCII file and write back to the stream
std::strstreambuf sbuf(ulSize);
file >> &sbuf;
writer.Stream() << &sbuf;
}

// read in the ASCII file and write back to the stream
std::strstreambuf sbuf(ulSize);
file >> &sbuf;
writer.Stream() << &sbuf;
file.close();
// remove temp file
fi.deleteFile();
}

file.close();
// remove temp file
fi.deleteFile();
}

void PropertyPartShape::RestoreDocFile(Base::Reader &reader)
{
BRep_Builder builder;
Base::FileInfo brep(reader.getFileName());
if (brep.hasExtension("bin")) {
TopoShape shape;
shape.importBinary(reader);
setValue(shape);
}
else {
BRep_Builder builder;

// create a temporary file and copy the content from the zip stream
Base::FileInfo fi(Base::FileInfo::getTempFileName());
// create a temporary file and copy the content from the zip stream
Base::FileInfo fi(Base::FileInfo::getTempFileName());

// read in the ASCII file and write back to the file stream
Base::ofstream file(fi, std::ios::out | std::ios::binary);
unsigned long ulSize = 0;
if (reader) {
std::streambuf* buf = file.rdbuf();
reader >> buf;
file.flush();
ulSize = buf->pubseekoff(0, std::ios::cur, std::ios::in);
}
file.close();

// Read the shape from the temp file, if the file is empty the stored shape was already empty.
// If it's still empty after reading the (non-empty) file there must occurred an error.
TopoDS_Shape shape;
if (ulSize > 0) {
if (!BRepTools::Read(shape, (const Standard_CString)fi.filePath().c_str(), builder)) {
// Note: Do NOT throw an exception here because if the tmp. created file could
// not be read it's NOT an indication for an invalid input stream 'reader'.
// We only print an error message but continue reading the next files from the
// stream...
App::PropertyContainer* father = this->getContainer();
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
Base::Console().Error("BRep file '%s' with shape of '%s' seems to be empty\n",
fi.filePath().c_str(),obj->Label.getValue());
}
else {
Base::Console().Warning("Loaded BRep file '%s' seems to be empty\n", fi.filePath().c_str());
// read in the ASCII file and write back to the file stream
Base::ofstream file(fi, std::ios::out | std::ios::binary);
unsigned long ulSize = 0;
if (reader) {
std::streambuf* buf = file.rdbuf();
reader >> buf;
file.flush();
ulSize = buf->pubseekoff(0, std::ios::cur, std::ios::in);
}
file.close();

// Read the shape from the temp file, if the file is empty the stored shape was already empty.
// If it's still empty after reading the (non-empty) file there must occurred an error.
TopoDS_Shape shape;
if (ulSize > 0) {
if (!BRepTools::Read(shape, (const Standard_CString)fi.filePath().c_str(), builder)) {
// Note: Do NOT throw an exception here because if the tmp. created file could
// not be read it's NOT an indication for an invalid input stream 'reader'.
// We only print an error message but continue reading the next files from the
// stream...
App::PropertyContainer* father = this->getContainer();
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
Base::Console().Error("BRep file '%s' with shape of '%s' seems to be empty\n",
fi.filePath().c_str(),obj->Label.getValue());
}
else {
Base::Console().Warning("Loaded BRep file '%s' seems to be empty\n", fi.filePath().c_str());
}
}
}
}

// delete the temp file
fi.deleteFile();
// delete the temp file
fi.deleteFile();

setValue(shape);
setValue(shape);
}
}

// -------------------------------------------------------------------------
Expand Down
13 changes: 13 additions & 0 deletions src/Mod/Sandbox/Gui/AppSandboxGui.cpp
Expand Up @@ -34,6 +34,7 @@
#include <Base/Console.h>
#include <Base/Interpreter.h>
#include <Base/GeometryPyCXX.h>
#include <Base/Reader.h>
#include <Base/VectorPy.h>
#include <CXX/Extensions.hxx>
#include <CXX/Objects.hxx>
Expand Down Expand Up @@ -194,6 +195,8 @@ class SandboxModuleGui : public Py::ExtensionModule<SandboxModuleGui>
{
add_varargs_method("interactiveFilletArc",&SandboxModuleGui::interactiveFilletArc,
"Interactive fillet arc");
add_varargs_method("xmlReader",&SandboxModuleGui::xmlReader,
"Read XML");
initialize("This module is the SandboxGui module"); // register with Python
}

Expand Down Expand Up @@ -223,6 +226,16 @@ class SandboxModuleGui : public Py::ExtensionModule<SandboxModuleGui>
}
return Py::None();
}
Py::Object xmlReader(const Py::Tuple& args)
{
std::string file = static_cast<std::string>(Py::String(args[0]));
App::Document* doc = App::GetApplication().newDocument();

std::ifstream str(file.c_str(), std::ios::in);
Base::XMLReader reader(file.c_str(), str);
doc->Restore(reader);
return Py::None();
}
};


Expand Down

0 comments on commit 32367b1

Please sign in to comment.