diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 89635cfafc..0039132826 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -169,6 +169,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; + } + } +}