From 0b4506673615ec9c11c798a8f3755a52531304a3 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sat, 20 Aug 2011 09:08:56 +0000 Subject: [PATCH] IfcParse: allow reading of IFC file from stdin IfcServer: first commit of a stdin/stdout interface to IfcGeomObjects [undocumented for now] BIMserver_plugin: first commit of IfcEngine plugin implementation for use with http://BIMserver.org [undocumented for now] --- cmake/CMakeLists.txt | 4 +- src/ifcparse/IfcGeomObjects.cpp | 18 ++++++ src/ifcparse/IfcGeomObjects.h | 1 + src/ifcparse/IfcParse.cpp | 47 ++++++++++++--- src/ifcparse/IfcParse.h | 11 +++- src/ifcserver/IfcServer.cpp | 103 ++++++++++++++++++++++++++++++++ 6 files changed, 173 insertions(+), 11 deletions(-) create mode 100644 src/ifcserver/IfcServer.cpp diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index d974864528..43344388ce 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -58,7 +58,9 @@ CHECK_ADD_OCE_OCC_DEF(iomanip.h) CHECK_ADD_OCE_OCC_DEF(iostream) CHECK_ADD_OCE_OCC_DEF(iostream.h) -ADD_DEFINITIONS(-O2) +IF(NOT CMAKE_BUILD_TYPE) + SET(CMAKE_BUILD_TYPE "Release") +ENDIF(NOT CMAKE_BUILD_TYPE) ADD_DEFINITIONS(-fPIC) INCLUDE_DIRECTORIES(${OCC_INCLUDE_DIR}) diff --git a/src/ifcparse/IfcGeomObjects.cpp b/src/ifcparse/IfcGeomObjects.cpp index 1082a5e471..6a03a94859 100644 --- a/src/ifcparse/IfcGeomObjects.cpp +++ b/src/ifcparse/IfcGeomObjects.cpp @@ -275,6 +275,24 @@ extern bool IfcGeomObjects::Init(const char* fn, bool world_coords, std::ostream total = shapereps->Size(); return true; } +extern bool IfcGeomObjects::Init(std::istream& f, int len, bool world_coords, std::ostream* log1, std::ostream* log2) { + if ( log1 || log2 ) Ifc::SetOutput(log1,log2); + use_world_coords = world_coords; + if ( !Ifc::Init(f, len) ) return false; + + shapereps = Ifc::EntitiesByType(); + if ( ! shapereps ) return false; + + outer = shapereps->begin(); + entities.reset(); + currentGeomObj = _get(); + + if ( ! currentGeomObj ) return false; + + done = 0; + total = shapereps->Size(); + return true; +} extern int IfcGeomObjects::Progress() { return 100 * done / total; } diff --git a/src/ifcparse/IfcGeomObjects.h b/src/ifcparse/IfcGeomObjects.h index 1b986de5ca..e0acc6409f 100644 --- a/src/ifcparse/IfcGeomObjects.h +++ b/src/ifcparse/IfcGeomObjects.h @@ -98,6 +98,7 @@ namespace IfcGeomObjects { }; extern bool Init(const char* fn, bool world_coords = false, std::ostream* log1= 0, std::ostream* log2= 0); + extern bool Init(std::istream& f, int len, bool world_coords = false, std::ostream* log1= 0, std::ostream* log2= 0); extern const IfcGeomObject* Get(); extern bool Next(); extern int Progress(); diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index a25115753e..166599f9a7 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -39,6 +39,7 @@ File::File(const std::string& fn) { stream.seekg(0,std::ios_base::end); size = (unsigned int) stream.tellg(); stream.seekg(0,std::ios_base::beg); + paging = size > BUF_SIZE; buffer = new char[size < BUF_SIZE ? size : BUF_SIZE]; ptr = 0; len = 0; @@ -46,6 +47,18 @@ File::File(const std::string& fn) { ReadBuffer(false); } +File::File(std::istream& f, int l) { + eof = false; + size = l; + paging = false; + buffer = new char[size]; + f.read(buffer,size); + valid = f.gcount() == size; + ptr = 0; + len = l; + offset = 0; +} + void File::Close() { stream.close(); delete[] buffer; @@ -71,7 +84,10 @@ void File::ReadBuffer(bool inc) { // Seeks an arbitrary position in the file // void File::Seek(unsigned int o) { - if ( o >= offset && (o < (offset+len)) ) { + if ( !paging ) { + ptr = o; + eof = false; + } else if ( o >= offset && (o < (offset+len)) ) { ptr = o - offset; } else { offset = o; @@ -92,7 +108,9 @@ char File::Peek() { // Returns the character at specified offset // char File::Read(unsigned int o) { - if ( o >= offset && (o < (offset+len)) ) { + if ( ! paging ) { + return buffer[o]; + } else if ( o >= offset && (o < (offset+len)) ) { return buffer[o-offset]; } else { stream.clear(); @@ -112,7 +130,10 @@ unsigned int File::Tell() { // Increments cursor and reads new chunk if necessary // void File::Inc() { - if ( ++ptr == len ) { ReadBuffer(); } + if ( ++ptr == len ) { + if ( paging ) ReadBuffer(); + else eof = true; + } } Tokens::Tokens(IfcParse::File *f) { @@ -433,6 +454,7 @@ void Entity::Load(std::vector& ids, bool seek) { if ( seek ) { Ifc::file->Seek(offset); Token datatype = Ifc::tokens->Next(); + std::string dt = TokenFunc::toString(datatype); if ( ! TokenFunc::isDatatype(datatype)) throw IfcException("Unexpected token while parsing entity"); _type = Ifc2x3::Type::FromString(TokenFunc::asString(datatype)); } @@ -502,7 +524,13 @@ unsigned int Entity::id() { return _id; } // Gets the unit definitins from the file // bool Ifc::Init(const std::string& fn) { - file = new File (fn); + return Ifc::Init(new File(fn)); +} +bool Ifc::Init(std::istream& f, int len) { + return Ifc::Init(new File(f,len)); +} +bool Ifc::Init(IfcParse::File* f) { + file = f; if ( ! file->valid ) return false; tokens = new Tokens (file); Token token = 0; @@ -545,9 +573,14 @@ bool Ifc::Init(const std::string& fn) { } if ( log1 ) std::cout << "\rDone scanning file " << std::endl; - - Ifc2x3::IfcUnitAssignment::ptr unit_assignment = *EntitiesByType()->begin(); - IfcUtil::IfcAbstractSelect::list units = unit_assignment->Units(); + + Ifc2x3::IfcUnitAssignment::list unit_assignments = EntitiesByType(); + IfcUtil::IfcAbstractSelect::list units = IfcUtil::IfcAbstractSelect::list(); + if ( unit_assignments->Size() ) { + Ifc2x3::IfcUnitAssignment::ptr unit_assignment = *unit_assignments->begin(); + IfcUtil::IfcAbstractSelect::list units = unit_assignment->Units(); + } + if ( units ) for ( IfcUtil::IfcAbstractSelect::it it = units->begin(); it != units->end(); ++ it ) { const IfcUtil::IfcAbstractSelect::ptr base = *it; Ifc2x3::IfcSIUnit::ptr unit = Ifc2x3::IfcSIUnit::ptr(); diff --git a/src/ifcparse/IfcParse.h b/src/ifcparse/IfcParse.h index 4f0cdb8d39..9e02eba26c 100644 --- a/src/ifcparse/IfcParse.h +++ b/src/ifcparse/IfcParse.h @@ -61,11 +61,13 @@ namespace IfcParse { unsigned int len; unsigned int offset; void ReadBuffer(bool inc=true); + bool paging; public: bool valid; bool eof; unsigned int size; File(const std::string& fn); + File(std::istream& f, int len); char Peek(); char Read(unsigned int offset); void Inc(); @@ -258,9 +260,10 @@ public: template static typename T::list EntitiesByType() { IfcEntities e = EntitiesByType(T::Class()); - typename T::list l ( new IfcTemplatedEntityList() ); \ - for ( IfcEntityList::it it = e->begin(); it != e->end(); ++ it ) { \ - l->push(reinterpret_pointer_cast(*it));\ + typename T::list l ( new IfcTemplatedEntityList() ); + if ( e && e->Size() ) + for ( IfcEntityList::it it = e->begin(); it != e->end(); ++ it ) { + l->push(reinterpret_pointer_cast(*it)); } return l; } @@ -268,6 +271,8 @@ public: static IfcEntities EntitiesByReference(int id); static IfcEntity EntityById(int id); static bool Init(const std::string& fn); + static bool Init(std::istream& fn, int len); + static bool Init(IfcParse::File* f); static void Dispose(); static float LengthUnit; static float PlaneAngleUnit; diff --git a/src/ifcserver/IfcServer.cpp b/src/ifcserver/IfcServer.cpp new file mode 100644 index 0000000000..7151f05933 --- /dev/null +++ b/src/ifcserver/IfcServer.cpp @@ -0,0 +1,103 @@ +/******************************************************************************** + * * + * 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 "../ifcparse/IfcGeomObjects.h" + +#if defined(WIN32) && !defined(__CYGWIN__) +#include +#include +#endif + +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; + std::cout.write("IfcOpenShell-0.2.0",18); + std::cout.flush(); + 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); + std::cout.write(has_more ? "y" : "n",1); + std::cout.flush(); + } else if ( command == "loadstdin" ) { + std::cout << "ok" << std::flush; + int len; + std::cin >> len; + std::cout << "ok" << std::flush; + has_more = IfcGeomObjects::Init(std::cin,len,true,0,&std::cerr); + std::cout.write(has_more ? "y" : "n",1); + std::cout.flush(); + } else if ( command == "get" ) { + if ( !has_more ) { + std::cout << "Not loaded" << std::flush; + } 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 ) { + std::cout << "Not loaded" << std::flush; + } else { + std::cout << ifc_geom->type << std::flush; + } + } else if ( command == "guid" ) { + if ( ! ifc_geom ) { + std::cout << "Not loaded" << std::flush; + } else { + std::cout << ifc_geom->name << std::flush; + } + } else if ( command == "next" ) { + if ( !has_more ) { + std::cout << "Not loaded" << std::flush; + } else { + has_more = IfcGeomObjects::Next(); + std::cout.write(has_more ? "y" : "n",1); + std::cout.flush(); + } + } else if ( command == "quit" || command == "exit" ) { + std::cout << "Bye" << std::flush; + break; + } else { + std::cout << "Unknown command " << command << std::flush; + } + } +}