Revamp the 'IfcGeomServer' idea to have an executable rather than a library to interface with. This way IFC processing runs in a separate process from the client application, so that crashes or out of memory issues do not bring down the client application.

This commit is contained in:
Thomas Krijnen
2014-04-06 11:16:20 +00:00
parent 24279776ab
commit a0d74bdf83
3 changed files with 327 additions and 111 deletions
+6
View File
@@ -165,6 +165,12 @@ ADD_EXECUTABLE(IfcConvert
TARGET_LINK_LIBRARIES (IfcConvert IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet TKSTEP TKSTEPBase TKSTEPAttr TKXSBase TKSTEP209 TKIGES TKOffset ${Boost_LIBRARIES} ${OPENCOLLADA_LIBRARIES})
ADD_EXECUTABLE(IfcGeomServer
../src/ifcgeomserver/IfcGeomServer.cpp
)
TARGET_LINK_LIBRARIES (IfcGeomServer IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet TKSTEP TKSTEPBase TKSTEPAttr TKXSBase TKSTEP209 TKIGES TKOffset)
# Build python wrapper using separate CMakeLists.txt
ADD_SUBDIRECTORY(../src/ifcwrap ifcwrap)
+321
View File
@@ -0,0 +1,321 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* This examples exposes the IfcOpenShell API through a command-based stdin *
* interface *
* *
********************************************************************************/
#include <iostream>
#include <boost/cstdint.hpp>
#if defined(_WIN32) && !defined(__CYGWIN__)
#define SET_BINARY_STREAMS
#endif
#ifdef SET_BINARY_STREAMS
#include <io.h>
#include <fcntl.h>
#endif
#include "../ifcgeom/IfcGeomObjects.h"
using namespace boost;
template <typename T>
T sread(std::istream& s) {
char buf[sizeof(T)];
s.read(buf, sizeof(T));
return *((T*)buf);
}
template <>
std::string sread(std::istream& s) {
int32_t len = sread<int32_t>(s);
char* buf = new char[len + 1];
s.read(buf, len);
buf[len] = 0;
while (len++ % 4) s.get();
std::string str(buf);
delete buf;
return str;
}
static std::streambuf *stdout_orig, *stdout_redir;
template <typename T>
void swrite(std::ostream& s, T t) {
char buf[sizeof(T)];
memcpy(buf, &t, sizeof(T));
s.write(buf, sizeof(T));
}
template <>
void swrite(std::ostream& s, std::string t) {
int32_t len = t.size();
swrite(s, len);
s.write(t.c_str(), len);
while (len++ % 4) s.put(0);
}
class Command {
protected:
virtual void read_content(std::istream& s) = 0;
virtual void write_content(std::ostream& s) = 0;
int32_t iden;
int32_t len;
public:
void read(std::istream& s) {
len = sread<int32_t>(s);
read_content(s);
}
void write(std::ostream& s) {
std::cout.rdbuf(stdout_orig);
swrite(s, iden);
std::ostringstream oss;
write_content(oss);
swrite(s, oss.str());
s.flush();
std::cout.rdbuf(stdout_redir);
}
Command(int32_t iden) : iden(iden) {}
};
const int32_t HELLO = 0xff00;
const int32_t IFC_MODEL = HELLO + 1;
const int32_t GET = IFC_MODEL + 1;
const int32_t ENTITY = GET + 1;
const int32_t MORE = ENTITY + 1;
const int32_t NEXT = MORE + 1;
const int32_t BYE = NEXT + 1;
const int32_t GET_LOG = BYE + 1;
const int32_t LOG = GET_LOG + 1;
class Hello : public Command {
private:
std::string str;
protected:
void read_content(std::istream& s) {
str = sread<std::string>(s);
}
void write_content(std::ostream& s) {
swrite(s, str);
}
public:
const std::string& string() { return str; }
Hello() : Command(HELLO), str("IfcOpenShell-" IFCOPENSHELL_VERSION) {}
};
class More : public Command {
private:
bool more;
protected:
void read_content(std::istream& s) {
more = sread<int32_t>(s) == 1;
}
void write_content(std::ostream& s) {
swrite<int32_t>(s, more ? 1 : 0);
}
public:
More(bool more) : Command(MORE), more(more) {}
};
class IfcModel : public Command {
private:
std::string str;
protected:
void read_content(std::istream& s) {
str = sread<std::string>(s);
}
void write_content(std::ostream& s) {
swrite(s, str);
}
public:
const std::string& string() { return str; }
IfcModel() : Command(IFC_MODEL) {};
};
class Get : public Command {
protected:
void read_content(std::istream& s) {}
void write_content(std::ostream& s) {}
public:
Get() : Command(GET) {};
};
class GetLog : public Command {
protected:
void read_content(std::istream& s) {}
void write_content(std::ostream& s) {}
public:
GetLog() : Command(GET_LOG) {};
};
class WriteLog : public Command {
private:
std::string str;
protected:
void read_content(std::istream& s) {
str = sread<std::string>(s);
}
void write_content(std::ostream& s) {
swrite(s, str);
}
public:
WriteLog(const std::string& str) : Command(LOG), str(str) {};
};
class Entity : public Command {
private:
const IfcGeomObjects::IfcGeomObject* geom;
protected:
void read_content(std::istream& s) {}
void write_content(std::ostream& s) {
swrite<int32_t>(s, geom->id());
swrite(s, geom->guid());
swrite(s, geom->name());
swrite(s, geom->type());
swrite<int32_t>(s, geom->parent_id());
swrite(s, std::string((char*)geom->matrix().data(), 16 * sizeof(float)));
swrite<int32_t>(s, geom->mesh().id());
swrite(s, std::string((char*)geom->mesh().verts().data(), geom->mesh().verts().size() * sizeof(float)));
swrite(s, std::string((char*)geom->mesh().normals().data(), geom->mesh().normals().size() * sizeof(float)));
{ std::vector<int32_t> indices;
for (std::vector<int>::const_iterator it = geom->mesh().faces().begin(); it != geom->mesh().faces().end(); ++it) {
indices.push_back(*it);
}
swrite(s, std::string((char*) indices.data(), indices.size() * sizeof(int32_t))); }
{ std::vector<float> diffuse_color_array;
for (std::vector<IfcGeomObjects::Material>::const_iterator it = geom->mesh().materials().begin(); it != geom->mesh().materials().end(); ++it) {
const auto& m = *it;
if (m.hasDiffuse()) {
const double* color = m.diffuse();
diffuse_color_array.push_back(static_cast<float>(color[0]));
diffuse_color_array.push_back(static_cast<float>(color[1]));
diffuse_color_array.push_back(static_cast<float>(color[2]));
} else {
diffuse_color_array.push_back(0.f);
diffuse_color_array.push_back(0.f);
diffuse_color_array.push_back(0.f);
}
if (m.hasTransparency()) {
diffuse_color_array.push_back(static_cast<float>(1. - m.transparency()));
} else {
diffuse_color_array.push_back(1.f);
}
}
swrite(s, std::string((char*) diffuse_color_array.data(), diffuse_color_array.size() * sizeof(float))); }
{ std::vector<int32_t> material_indices;
for (std::vector<int>::const_iterator it = geom->mesh().material_ids().begin(); it != geom->mesh().material_ids().end(); ++it) {
material_indices.push_back(*it);
}
swrite(s, std::string((char*) material_indices.data(), material_indices.size() * sizeof(int32_t))); }
}
public:
Entity(const IfcGeomObjects::IfcGeomObject* geom) : Command(ENTITY), geom(geom) {};
};
class Next : public Command {
protected:
void read_content(std::istream& s) {}
void write_content(std::ostream& s) {}
public:
Next() : Command(NEXT) {};
};
class Bye : public Command {
protected:
void read_content(std::istream& s) {}
void write_content(std::ostream& s) {}
public:
Bye() : Command(BYE) {};
};
int main (int argc, char** argv) {
if (sizeof(float) != 4 || sizeof(int32_t) != 4) {
return 1;
}
// Redirect stdout to this stream, so that involuntary
// writes to stdout do not interfere with our protocol.
std::ostringstream oss;
stdout_redir = oss.rdbuf();
stdout_orig = std::cout.rdbuf();
std::cout.rdbuf(stdout_redir);
#ifdef SET_BINARY_STREAMS
_setmode(_fileno(stdout), _O_BINARY);
std::cout.setf(std::ios_base::binary);
_setmode(_fileno(stdin), _O_BINARY);
std::cin.setf(std::ios_base::binary);
#endif
bool has_more = false;
Hello().write(std::cout);
while (1) {
const int32_t msg_type = sread<int32_t>(std::cin);
switch (msg_type) {
case IFC_MODEL: {
IfcModel m; m.read(std::cin);
std::string::size_type len = m.string().size();
char* data = new char[len];
memcpy(data, m.string().c_str(), len);
IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS, false);
IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES, false);
IfcGeomObjects::Settings(IfcGeomObjects::CONVERT_BACK_UNITS, true);
IfcGeomObjects::Settings(IfcGeomObjects::FORCE_CCW_FACE_ORIENTATION, true);
has_more = IfcGeomObjects::Init(data, len);
More(has_more).write(std::cout);
break;
}
case GET: {
Get g; g.read(std::cin);
if (!has_more) return 1;
const IfcGeomObjects::IfcGeomObject* geom = IfcGeomObjects::Get();
Entity(geom).write(std::cout);
break;
}
case NEXT: {
Next n; n.read(std::cin);
has_more = IfcGeomObjects::Next();
if (!has_more) {
IfcGeomObjects::CleanUp();
}
More(has_more).write(std::cout);
break;
}
case GET_LOG: {
GetLog gl; gl.read(std::cin);
WriteLog(IfcGeomObjects::GetLog()).write(std::cout);
break;
}
case BYE: {
Bye().write(std::cout);
return 0;
}
default: return 1;
}
}
}
-111
View File
@@ -1,111 +0,0 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* This examples exposes the IfcOpenShell API through a command-based stdin *
* interface *
* *
********************************************************************************/
#include <iostream>
#include "../ifcgeom/IfcGeomObjects.h"
#if defined(WIN32) && !defined(__CYGWIN__)
#include <io.h>
#include <fcntl.h>
#endif
#define PRODUCT ("IfcOpenShell-0.2.3")
#define ACK ("y")
#define NEG ("n")
#define CONFIRM ("ok")
#define CLOSED ("No opened file")
#define QUIT ("Bye :)")
#define UNKNOWN ("Unknown command")
void send_msg(const char* c) {
std::cout.write(c,strlen(c));
std::cout.flush();
}
void send_msg(const std::string& s) {
std::cout << s << std::flush;
}
int main ( int argc, char** argv ) {
#if defined(WIN32) && !defined(__CYGWIN__)
_setmode(_fileno(stdout), _O_BINARY);
std::cout.setf(std::ios_base::binary);
#endif
bool has_more = false;
send_msg(PRODUCT);
const IfcGeomObjects::IfcGeomObject* ifc_geom = 0;
while (1) {
std::string command;
std::cin >> command;
if ( command == "load" ) {
std::string fn;
std::getline(std::cin,fn);
fn = fn.erase(0,fn.find_first_not_of(" "));
has_more = IfcGeomObjects::Init(fn.c_str(),true,0,&std::cerr);
send_msg(has_more ? ACK : NEG);
} else if ( command == "loadstdin" ) {
send_msg(CONFIRM);
int len;
std::cin >> len;
send_msg(CONFIRM);
has_more = IfcGeomObjects::Init(std::cin,len,true,0,&std::cerr);
send_msg(has_more ? ACK : NEG);
} else if ( command == "get" ) {
if ( ! has_more ) send_msg(CLOSED);
else {
ifc_geom = IfcGeomObjects::Get();
const int vcount = ifc_geom->mesh->verts.size() / 3;
std::cout.write((char*)&vcount,sizeof(int));
std::cout.write((char*)&ifc_geom->mesh->verts[0],sizeof(float)*vcount*3);
const int fcount = ifc_geom->mesh->faces.size() / 3;
std::cout.write((char*)&fcount,sizeof(int));
std::cout.write((char*)&ifc_geom->mesh->faces[0],sizeof(int)*fcount*3);
std::cout.flush();
}
} else if ( command == "type" ) {
if ( ifc_geom ) send_msg(ifc_geom->type);
else send_msg(CLOSED);
} else if ( command == "guid" ) {
if ( ifc_geom ) send_msg(ifc_geom->guid);
else send_msg(CLOSED);
} else if ( command == "next" ) {
if ( !has_more ) send_msg(CLOSED);
else {
has_more = IfcGeomObjects::Next();
if ( ! has_more )
IfcGeomObjects::CleanUp();
send_msg(has_more ? ACK : NEG);
}
} else if ( command == "quit" || command == "exit" ) {
send_msg(QUIT);
break;
} else {
send_msg(UNKNOWN);
}
}
return 0;
}