diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 07a9ee6161..5fe6e41e22 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -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)
diff --git a/src/ifcgeomserver/IfcGeomServer.cpp b/src/ifcgeomserver/IfcGeomServer.cpp
new file mode 100644
index 0000000000..0b33299346
--- /dev/null
+++ b/src/ifcgeomserver/IfcGeomServer.cpp
@@ -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 . *
+ * *
+ ********************************************************************************/
+
+/********************************************************************************
+ * *
+ * This examples exposes the IfcOpenShell API through a command-based stdin *
+ * interface *
+ * *
+ ********************************************************************************/
+
+#include
+#include
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#define SET_BINARY_STREAMS
+#endif
+#ifdef SET_BINARY_STREAMS
+#include
+#include
+#endif
+
+#include "../ifcgeom/IfcGeomObjects.h"
+
+using namespace boost;
+
+template
+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(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
+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(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(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(s) == 1;
+ }
+ void write_content(std::ostream& s) {
+ swrite(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(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(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(s, geom->id());
+ swrite(s, geom->guid());
+ swrite(s, geom->name());
+ swrite(s, geom->type());
+ swrite(s, geom->parent_id());
+ swrite(s, std::string((char*)geom->matrix().data(), 16 * sizeof(float)));
+ swrite(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 indices;
+ for (std::vector::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 diffuse_color_array;
+ for (std::vector::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(color[0]));
+ diffuse_color_array.push_back(static_cast(color[1]));
+ diffuse_color_array.push_back(static_cast(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(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 material_indices;
+ for (std::vector::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(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;
+ }
+ }
+}
diff --git a/src/ifcserver/IfcServer.cpp b/src/ifcserver/IfcServer.cpp
deleted file mode 100644
index c0563dcb5a..0000000000
--- a/src/ifcserver/IfcServer.cpp
+++ /dev/null
@@ -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 . *
- * *
- ********************************************************************************/
-
-/********************************************************************************
- * *
- * This examples exposes the IfcOpenShell API through a command-based stdin *
- * interface *
- * *
- ********************************************************************************/
-
-#include
-
-#include "../ifcgeom/IfcGeomObjects.h"
-
-#if defined(WIN32) && !defined(__CYGWIN__)
-#include
-#include
-#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;
-}