2011-05-08 11:04:32 +00:00
|
|
|
/********************************************************************************
|
2011-07-11 09:33:18 +00:00
|
|
|
* *
|
|
|
|
|
* 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/>. *
|
|
|
|
|
* *
|
|
|
|
|
********************************************************************************/
|
2011-05-08 11:04:32 +00:00
|
|
|
|
2012-03-13 11:56:52 +00:00
|
|
|
#include <algorithm>
|
|
|
|
|
#include <string>
|
2011-07-25 14:56:40 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
2011-09-25 09:53:22 +00:00
|
|
|
#include "../ifcparse/IfcCharacterDecoder.h"
|
2011-05-08 11:04:32 +00:00
|
|
|
#include "../ifcparse/IfcParse.h"
|
2011-09-25 09:53:22 +00:00
|
|
|
#include "../ifcparse/IfcException.h"
|
2011-07-25 14:56:40 +00:00
|
|
|
#include "../ifcparse/IfcUtil.h"
|
2011-09-25 09:53:22 +00:00
|
|
|
#include "../ifcparse/IfcFile.h"
|
2011-05-08 11:04:32 +00:00
|
|
|
|
|
|
|
|
using namespace IfcParse;
|
|
|
|
|
|
2011-07-11 09:33:18 +00:00
|
|
|
//
|
|
|
|
|
// Opens the file, gets the filesize and reads a chunk in memory
|
|
|
|
|
//
|
|
|
|
|
File::File(const std::string& fn) {
|
|
|
|
|
eof = false;
|
|
|
|
|
stream.open(fn.c_str(),std::ios_base::binary);
|
2011-08-07 10:21:22 +00:00
|
|
|
if ( ! stream.good() ) {
|
|
|
|
|
valid = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
valid = true;
|
2011-07-11 09:33:18 +00:00
|
|
|
stream.seekg(0,std::ios_base::end);
|
2011-07-25 14:56:40 +00:00
|
|
|
size = (unsigned int) stream.tellg();
|
2011-07-11 09:33:18 +00:00
|
|
|
stream.seekg(0,std::ios_base::beg);
|
2012-05-26 09:00:30 +00:00
|
|
|
#ifdef BUF_SIZE
|
|
|
|
|
offset = 0;
|
2011-08-20 09:08:56 +00:00
|
|
|
paging = size > BUF_SIZE;
|
2011-07-11 09:33:18 +00:00
|
|
|
buffer = new char[size < BUF_SIZE ? size : BUF_SIZE];
|
2012-05-26 09:00:30 +00:00
|
|
|
#else
|
|
|
|
|
buffer = new char[size];
|
|
|
|
|
#endif
|
2011-07-11 09:33:18 +00:00
|
|
|
ptr = 0;
|
2012-05-26 09:00:30 +00:00
|
|
|
len = 0;
|
2011-07-11 09:33:18 +00:00
|
|
|
ReadBuffer(false);
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-20 09:08:56 +00:00
|
|
|
File::File(std::istream& f, int l) {
|
|
|
|
|
eof = false;
|
|
|
|
|
size = l;
|
2012-05-26 09:00:30 +00:00
|
|
|
#ifdef BUF_SIZE
|
2011-08-20 09:08:56 +00:00
|
|
|
paging = false;
|
2012-05-26 09:00:30 +00:00
|
|
|
offset = 0;
|
|
|
|
|
#endif
|
2011-08-20 09:08:56 +00:00
|
|
|
buffer = new char[size];
|
|
|
|
|
f.read(buffer,size);
|
|
|
|
|
valid = f.gcount() == size;
|
|
|
|
|
ptr = 0;
|
2012-05-26 09:00:30 +00:00
|
|
|
len = l;
|
2011-08-20 09:08:56 +00:00
|
|
|
}
|
|
|
|
|
|
2011-10-27 16:13:29 +00:00
|
|
|
File::File(void* data, int l) {
|
|
|
|
|
eof = false;
|
|
|
|
|
size = l;
|
2012-05-26 09:00:30 +00:00
|
|
|
#ifdef BUF_SIZE
|
2011-10-27 16:13:29 +00:00
|
|
|
paging = false;
|
2012-05-26 09:00:30 +00:00
|
|
|
offset = 0;
|
|
|
|
|
#endif
|
2011-10-27 16:13:29 +00:00
|
|
|
buffer = (char*) data;
|
|
|
|
|
valid = true;
|
|
|
|
|
ptr = 0;
|
2012-05-26 09:00:30 +00:00
|
|
|
len = l;
|
2011-10-27 16:13:29 +00:00
|
|
|
}
|
|
|
|
|
|
2011-07-11 09:33:18 +00:00
|
|
|
void File::Close() {
|
|
|
|
|
stream.close();
|
|
|
|
|
delete[] buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Reads a chunk of BUF_SIZE in memory and increments cursor if requested
|
|
|
|
|
//
|
|
|
|
|
void File::ReadBuffer(bool inc) {
|
2012-05-26 09:00:30 +00:00
|
|
|
#ifdef BUF_SIZE
|
2011-07-11 09:33:18 +00:00
|
|
|
if ( inc ) {
|
|
|
|
|
offset += len;
|
|
|
|
|
stream.seekg(offset,std::ios_base::beg);
|
|
|
|
|
}
|
2012-05-26 09:00:30 +00:00
|
|
|
#endif
|
2011-07-11 09:33:18 +00:00
|
|
|
eof = stream.eof();
|
|
|
|
|
if ( eof ) return;
|
2012-05-26 09:00:30 +00:00
|
|
|
#ifdef BUF_SIZE
|
2011-07-11 09:33:18 +00:00
|
|
|
stream.read(buffer,size < BUF_SIZE ? size : BUF_SIZE);
|
2012-05-26 09:00:30 +00:00
|
|
|
#else
|
|
|
|
|
stream.read(buffer,size);
|
|
|
|
|
#endif
|
2011-07-25 14:56:40 +00:00
|
|
|
len = (unsigned int) stream.gcount();
|
2011-07-11 09:33:18 +00:00
|
|
|
eof = len == 0;
|
|
|
|
|
ptr = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Seeks an arbitrary position in the file
|
|
|
|
|
//
|
|
|
|
|
void File::Seek(unsigned int o) {
|
2012-05-26 09:00:30 +00:00
|
|
|
#ifdef BUF_SIZE
|
2011-08-20 09:08:56 +00:00
|
|
|
if ( !paging ) {
|
2012-05-26 09:00:30 +00:00
|
|
|
#endif
|
2011-08-20 09:08:56 +00:00
|
|
|
ptr = o;
|
2012-02-04 15:10:17 +00:00
|
|
|
if (ptr >= len) throw IfcException("Reading outside of file limits");
|
2011-08-20 09:08:56 +00:00
|
|
|
eof = false;
|
2012-05-26 09:00:30 +00:00
|
|
|
#ifdef BUF_SIZE
|
2011-08-20 09:08:56 +00:00
|
|
|
} else if ( o >= offset && (o < (offset+len)) ) {
|
2011-07-11 09:33:18 +00:00
|
|
|
ptr = o - offset;
|
|
|
|
|
} else {
|
|
|
|
|
offset = o;
|
|
|
|
|
stream.clear();
|
|
|
|
|
stream.seekg(o,std::ios_base::beg);
|
|
|
|
|
ReadBuffer(false);
|
|
|
|
|
}
|
2012-05-26 09:00:30 +00:00
|
|
|
#endif
|
2011-07-11 09:33:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Returns the character at the cursor
|
|
|
|
|
//
|
|
|
|
|
char File::Peek() {
|
|
|
|
|
return buffer[ptr];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Returns the character at specified offset
|
|
|
|
|
//
|
|
|
|
|
char File::Read(unsigned int o) {
|
2012-05-26 09:00:30 +00:00
|
|
|
#ifdef BUF_SIZE
|
2011-08-20 09:08:56 +00:00
|
|
|
if ( ! paging ) {
|
2012-05-26 09:00:30 +00:00
|
|
|
#endif
|
2012-02-04 15:10:17 +00:00
|
|
|
return buffer[o];
|
2012-05-26 09:00:30 +00:00
|
|
|
#ifdef BUF_SIZE
|
2011-08-20 09:08:56 +00:00
|
|
|
} else if ( o >= offset && (o < (offset+len)) ) {
|
2011-07-11 09:33:18 +00:00
|
|
|
return buffer[o-offset];
|
2011-05-08 11:04:32 +00:00
|
|
|
} else {
|
2011-07-11 09:33:18 +00:00
|
|
|
stream.clear();
|
|
|
|
|
stream.seekg(o,std::ios_base::beg);
|
|
|
|
|
return stream.peek();
|
|
|
|
|
}
|
2012-05-26 09:00:30 +00:00
|
|
|
#endif
|
2011-07-11 09:33:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Returns the cursor position
|
|
|
|
|
//
|
|
|
|
|
unsigned int File::Tell() {
|
2012-05-26 09:00:30 +00:00
|
|
|
#ifdef BUF_SIZE
|
2011-07-11 09:33:18 +00:00
|
|
|
return offset + ptr;
|
2012-05-26 09:00:30 +00:00
|
|
|
#else
|
|
|
|
|
return ptr;
|
|
|
|
|
#endif
|
2011-07-11 09:33:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Increments cursor and reads new chunk if necessary
|
|
|
|
|
//
|
|
|
|
|
void File::Inc() {
|
2011-08-20 09:08:56 +00:00
|
|
|
if ( ++ptr == len ) {
|
2012-05-26 09:00:30 +00:00
|
|
|
#ifdef BUF_SIZE
|
2011-08-20 09:08:56 +00:00
|
|
|
if ( paging ) ReadBuffer();
|
2012-02-04 15:10:17 +00:00
|
|
|
else {
|
2012-05-26 09:00:30 +00:00
|
|
|
#endif
|
2012-02-04 15:10:17 +00:00
|
|
|
eof = true;
|
|
|
|
|
return;
|
2012-05-26 09:00:30 +00:00
|
|
|
#ifdef BUF_SIZE
|
2012-02-04 15:10:17 +00:00
|
|
|
}
|
2012-05-26 09:00:30 +00:00
|
|
|
#endif
|
2011-08-20 09:08:56 +00:00
|
|
|
}
|
2011-09-25 09:53:22 +00:00
|
|
|
const char current = File::Peek();
|
|
|
|
|
if ( current == '\n' || current == '\r' ) File::Inc();
|
2011-07-11 09:33:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Tokens::Tokens(IfcParse::File *f) {
|
|
|
|
|
file = f;
|
2011-09-25 09:53:22 +00:00
|
|
|
decoder = new IfcCharacterDecoder(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Tokens::~Tokens() {
|
|
|
|
|
delete decoder;
|
2011-07-11 09:33:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Returns the offset of the current Token and moves cursor to next
|
|
|
|
|
//
|
|
|
|
|
Token Tokens::Next() {
|
|
|
|
|
|
|
|
|
|
if ( file->eof ) return TokenPtr();
|
|
|
|
|
|
|
|
|
|
char c;
|
|
|
|
|
|
|
|
|
|
// Trim whitespace
|
|
|
|
|
while ( !file->eof ) {
|
|
|
|
|
c = file->Peek();
|
|
|
|
|
if ( (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) file->Inc();
|
|
|
|
|
else break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( file->eof ) return TokenPtr();
|
|
|
|
|
unsigned int pos = file->Tell();
|
|
|
|
|
|
|
|
|
|
bool inString = false;
|
|
|
|
|
bool inComment = false;
|
|
|
|
|
|
|
|
|
|
// If the cursor is at [()=,;$*] we know token consists of single char
|
|
|
|
|
if ( c == '(' || c == ')' || c == '=' || c == ',' || c == ';' || c == '$' || c == '*' ) {
|
|
|
|
|
file->Inc();
|
|
|
|
|
return TokenPtr(c);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
|
|
char p = 0;
|
|
|
|
|
while ( ! file->eof ) {
|
|
|
|
|
|
|
|
|
|
// Read character and increment pointer if not starting a new token
|
|
|
|
|
char c = file->Peek();
|
|
|
|
|
if ( len && (!inString || inComment) && (c == '(' || c == ')' || c == '=' || c == ',' || c == ';' ) ) break;
|
|
|
|
|
file->Inc();
|
|
|
|
|
|
|
|
|
|
// Skip whitespace if not in comment or string
|
|
|
|
|
if ( !inComment && !inString && (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) continue;
|
|
|
|
|
|
|
|
|
|
len ++;
|
|
|
|
|
|
|
|
|
|
// Keep track of whether cursor is inside a string or comment
|
|
|
|
|
if ( inComment && p == '*' && c == '/' ) inComment = false;
|
|
|
|
|
else if ( !inString && !inComment && p == '/' && c == '*' ) inComment = true;
|
2011-09-25 09:53:22 +00:00
|
|
|
else if ( !inComment && c == '\'' ) decoder->dryRun();
|
2011-07-11 09:33:18 +00:00
|
|
|
|
|
|
|
|
p = c;
|
|
|
|
|
}
|
|
|
|
|
if ( len ) return TokenPtr(pos);
|
|
|
|
|
else return TokenPtr();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Reads a std::string from the file at specified offset
|
|
|
|
|
// Omits whitespace and comments
|
|
|
|
|
//
|
|
|
|
|
std::string Tokens::TokenString(unsigned int offset) {
|
2012-02-04 15:10:17 +00:00
|
|
|
const bool was_eof = file->eof;
|
2011-07-11 09:33:18 +00:00
|
|
|
unsigned int old_offset = file->Tell();
|
|
|
|
|
file->Seek(offset);
|
|
|
|
|
bool inString = false;
|
|
|
|
|
bool inComment = false;
|
|
|
|
|
std::string buffer;
|
|
|
|
|
buffer.reserve(128);
|
|
|
|
|
char p = 0;
|
|
|
|
|
while ( ! file->eof ) {
|
|
|
|
|
char c = file->Peek();
|
|
|
|
|
if ( buffer.size() && (!inString || inComment) && (c == '(' || c == ')' || c == '=' || c == ',' || c == ';' ) ) break;
|
|
|
|
|
file->Inc();
|
|
|
|
|
if ( !inComment && !inString && (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) continue;
|
|
|
|
|
if ( !inComment ) buffer.push_back(c);
|
|
|
|
|
if ( inComment && p == '*' && c == '/' ) inComment = false;
|
|
|
|
|
else if ( !inString && !inComment && p == '/' && c == '*' ) inComment = true;
|
2011-09-25 09:53:22 +00:00
|
|
|
else if ( !inComment && c == '\'' ) return *decoder;
|
2011-07-11 09:33:18 +00:00
|
|
|
p = c;
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2012-02-04 15:10:17 +00:00
|
|
|
if ( was_eof ) file->eof = true;
|
|
|
|
|
else file->Seek(old_offset);
|
2011-07-11 09:33:18 +00:00
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Functions for creating Tokens from an arbitary file offset.
|
|
|
|
|
// The first 4 bits are reserved for Tokens of type ()=,;$*
|
|
|
|
|
//
|
|
|
|
|
Token IfcParse::TokenPtr(unsigned int offset) { return offset + 128; }
|
|
|
|
|
Token IfcParse::TokenPtr(char c) { return c; }
|
|
|
|
|
Token IfcParse::TokenPtr() { return 0; }
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Functions to convert Tokens to binary data
|
|
|
|
|
//
|
|
|
|
|
unsigned int TokenFunc::Offset(Token t) { return t - 128; }
|
|
|
|
|
bool TokenFunc::startsWith(Token t, char c) {
|
|
|
|
|
return Ifc::file->Read(Offset(t)) == c;
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
bool TokenFunc::isOperator(Token t, char op) {
|
|
|
|
|
return (t < 128) && (!op || op == t);
|
2011-06-13 07:23:09 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
bool TokenFunc::isIdentifier(Token t) {
|
|
|
|
|
return ! isOperator(t) && startsWith(t, '#');
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
bool TokenFunc::isString(Token t) {
|
|
|
|
|
return ! isOperator(t) && startsWith(t, '\'');
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
bool TokenFunc::isEnumeration(Token t) {
|
|
|
|
|
return ! isOperator(t) && startsWith(t, '.');
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
bool TokenFunc::isDatatype(Token t) {
|
|
|
|
|
return ! isOperator(t) && startsWith(t, 'I');
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
int TokenFunc::asInt(Token t) {
|
|
|
|
|
const std::string str = asString(t);
|
2012-06-07 11:56:20 +00:00
|
|
|
// In case of an ENTITY_INSTANCE_NAME skip the leading #
|
|
|
|
|
const char* start = str.c_str() + (isIdentifier(t) ? 1 : 0);
|
|
|
|
|
char* end;
|
|
|
|
|
long result = strtol(start,&end,10);
|
|
|
|
|
if ( start == end ) throw IfcException("Token is not an integer or identifier");
|
|
|
|
|
return (int) result;
|
2011-06-13 07:23:09 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
bool TokenFunc::asBool(Token t) {
|
|
|
|
|
const std::string str = asString(t);
|
|
|
|
|
return str == "T";
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2012-03-13 11:56:52 +00:00
|
|
|
double TokenFunc::asFloat(Token t) {
|
2011-07-11 09:33:18 +00:00
|
|
|
const std::string str = asString(t);
|
2012-03-13 11:56:52 +00:00
|
|
|
return (double) atof(str.c_str());
|
2011-07-11 09:33:18 +00:00
|
|
|
}
|
|
|
|
|
std::string TokenFunc::asString(Token t) {
|
|
|
|
|
if ( isOperator(t,'$') ) return "";
|
|
|
|
|
else if ( isOperator(t) ) throw IfcException("Token is not a string");
|
|
|
|
|
std::string str = Ifc::tokens->TokenString(t - 128);
|
|
|
|
|
return isString(t) || isEnumeration(t) ? str.substr(1,str.size()-2) : str;
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
std::string TokenFunc::toString(Token t) {
|
|
|
|
|
if ( isOperator(t) ) return std::string ( (char*) &t, 1 );
|
2011-08-24 12:21:07 +00:00
|
|
|
else return Ifc::tokens->TokenString(t - 128);
|
2011-07-11 09:33:18 +00:00
|
|
|
}
|
|
|
|
|
|
2011-05-08 11:04:32 +00:00
|
|
|
|
2011-07-11 09:33:18 +00:00
|
|
|
TokenArgument::TokenArgument(Token t) {
|
|
|
|
|
token = t;
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
|
2011-09-03 13:58:59 +00:00
|
|
|
EntityArgument::EntityArgument(Ifc2x3::Type::Enum ty, Token t) {
|
|
|
|
|
entity = new IfcUtil::IfcArgumentSelect(ty,new TokenArgument(t));
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Reads the arguments from a list of token
|
|
|
|
|
// Aditionally, stores the ids (i.e. #[\d]+) in a vector
|
|
|
|
|
//
|
|
|
|
|
ArgumentList::ArgumentList(Tokens* t, std::vector<unsigned int>& ids) {
|
|
|
|
|
while( Token next = t->Next() ) {
|
|
|
|
|
if ( TokenFunc::isOperator(next,',') ) continue;
|
|
|
|
|
if ( TokenFunc::isOperator(next,')') ) break;
|
2011-09-03 13:58:59 +00:00
|
|
|
if ( TokenFunc::isOperator(next,'(') ) Push( new ArgumentList(t,ids) );
|
2011-07-11 09:33:18 +00:00
|
|
|
else {
|
|
|
|
|
if ( TokenFunc::isIdentifier(next) ) ids.push_back(TokenFunc::asInt(next));
|
|
|
|
|
if ( TokenFunc::isDatatype(next) ) {
|
2011-09-03 13:58:59 +00:00
|
|
|
t->Next();
|
2012-03-31 09:54:15 +00:00
|
|
|
try {
|
|
|
|
|
Push ( new EntityArgument(Ifc2x3::Type::FromString(TokenFunc::asString(next)),t->Next()) );
|
|
|
|
|
} catch ( IfcException& e ) {
|
|
|
|
|
Ifc::LogMessage("Error",e.what());
|
|
|
|
|
}
|
2011-09-03 13:58:59 +00:00
|
|
|
t->Next();
|
2011-07-11 09:33:18 +00:00
|
|
|
} else {
|
2011-09-03 13:58:59 +00:00
|
|
|
Push ( new TokenArgument(next) );
|
2011-07-11 09:33:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
|
|
|
|
|
void ArgumentList::Push(ArgumentPtr l) {
|
|
|
|
|
list.push_back(l);
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
|
|
|
|
|
2011-07-11 09:33:18 +00:00
|
|
|
//
|
|
|
|
|
// Functions for casting the ArgumentList to other types
|
|
|
|
|
//
|
|
|
|
|
ArgumentList::operator int() const { throw IfcException("Argument is not an integer"); }
|
|
|
|
|
ArgumentList::operator bool() const { throw IfcException("Argument is not a boolean"); }
|
2012-03-13 11:56:52 +00:00
|
|
|
ArgumentList::operator double() const { throw IfcException("Argument is not a number"); }
|
2011-07-11 09:33:18 +00:00
|
|
|
ArgumentList::operator std::string() const { throw IfcException("Argument is not a string"); }
|
2012-03-13 11:56:52 +00:00
|
|
|
ArgumentList::operator std::vector<double>() const {
|
|
|
|
|
std::vector<double> r;
|
2011-07-25 14:56:40 +00:00
|
|
|
std::vector<ArgumentPtr>::const_iterator it;
|
|
|
|
|
for ( it = list.begin(); it != list.end(); ++ it ) {
|
|
|
|
|
r.push_back(**it);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
ArgumentList::operator std::vector<int>() const {
|
|
|
|
|
std::vector<int> r;
|
|
|
|
|
std::vector<ArgumentPtr>::const_iterator it;
|
|
|
|
|
for ( it = list.begin(); it != list.end(); ++ it ) {
|
|
|
|
|
r.push_back(**it);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
ArgumentList::operator std::vector<std::string>() const {
|
|
|
|
|
std::vector<std::string> r;
|
|
|
|
|
std::vector<ArgumentPtr>::const_iterator it;
|
|
|
|
|
for ( it = list.begin(); it != list.end(); ++ it ) {
|
|
|
|
|
r.push_back(**it);
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
ArgumentList::operator IfcUtil::IfcSchemaEntity() const { throw IfcException("Argument is not an IFC type"); }
|
2011-09-03 13:58:59 +00:00
|
|
|
//ArgumentList::operator IfcUtil::IfcAbstractSelect::ptr() const { throw IfcException("Argument is not an IFC type"); }
|
2011-07-25 14:56:40 +00:00
|
|
|
ArgumentList::operator IfcEntities() const {
|
|
|
|
|
IfcEntities l ( new IfcEntityList() );
|
2011-07-11 09:33:18 +00:00
|
|
|
std::vector<ArgumentPtr>::const_iterator it;
|
|
|
|
|
for ( it = list.begin(); it != list.end(); ++ it ) {
|
|
|
|
|
// FIXME: account for $
|
2011-07-25 14:56:40 +00:00
|
|
|
const IfcUtil::IfcSchemaEntity entity = **it;
|
2011-07-11 09:33:18 +00:00
|
|
|
l->push(entity);
|
|
|
|
|
}
|
|
|
|
|
return l;
|
|
|
|
|
}
|
2011-07-25 14:56:40 +00:00
|
|
|
unsigned int ArgumentList::Size() const { return (unsigned int) list.size(); }
|
2011-07-11 09:33:18 +00:00
|
|
|
ArgumentPtr ArgumentList::operator [] (unsigned int i) const {
|
|
|
|
|
if ( i >= list.size() )
|
|
|
|
|
throw IfcException("Argument index out of range");
|
|
|
|
|
return list[i];
|
|
|
|
|
}
|
2012-03-13 11:56:52 +00:00
|
|
|
std::string ArgumentList::toString(bool upper) const {
|
2011-07-11 09:33:18 +00:00
|
|
|
std::stringstream ss;
|
|
|
|
|
ss << "(";
|
|
|
|
|
for( std::vector<ArgumentPtr>::const_iterator it = list.begin(); it != list.end(); it ++ ) {
|
|
|
|
|
if ( it != list.begin() ) ss << ",";
|
2012-03-13 11:56:52 +00:00
|
|
|
ss << (*it)->toString(upper);
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
|
|
|
|
ss << ")";
|
|
|
|
|
return ss.str();
|
|
|
|
|
}
|
2011-07-25 14:56:40 +00:00
|
|
|
bool ArgumentList::isNull() const { return false; }
|
2011-09-03 13:58:59 +00:00
|
|
|
ArgumentList::~ArgumentList() {
|
|
|
|
|
for( std::vector<ArgumentPtr>::iterator it = list.begin(); it != list.end(); it ++ ) {
|
|
|
|
|
delete (*it);
|
|
|
|
|
}
|
|
|
|
|
list.clear();
|
|
|
|
|
}
|
2011-05-08 11:04:32 +00:00
|
|
|
|
2011-07-11 09:33:18 +00:00
|
|
|
//
|
|
|
|
|
// Functions for casting the TokenArgument to other types
|
|
|
|
|
//
|
|
|
|
|
TokenArgument::operator int() const { return TokenFunc::asInt(token); }
|
|
|
|
|
TokenArgument::operator bool() const { return TokenFunc::asBool(token); }
|
2012-03-13 11:56:52 +00:00
|
|
|
TokenArgument::operator double() const { return TokenFunc::asFloat(token); }
|
2011-07-11 09:33:18 +00:00
|
|
|
TokenArgument::operator std::string() const { return TokenFunc::asString(token); }
|
2012-03-13 11:56:52 +00:00
|
|
|
TokenArgument::operator std::vector<double>() const { throw IfcException("Argument is not a list of floats"); }
|
2011-07-25 14:56:40 +00:00
|
|
|
TokenArgument::operator std::vector<int>() const { throw IfcException("Argument is not a list of ints"); }
|
|
|
|
|
TokenArgument::operator std::vector<std::string>() const { throw IfcException("Argument is not a list of strings"); }
|
|
|
|
|
TokenArgument::operator IfcUtil::IfcSchemaEntity() const { return Ifc::EntityById(TokenFunc::asInt(token)); }
|
2011-09-03 13:58:59 +00:00
|
|
|
/*TokenArgument::operator IfcUtil::IfcAbstractSelect::ptr() const {
|
2012-03-13 11:56:52 +00:00
|
|
|
//TODO Fix memory leak
|
|
|
|
|
return new IfcUtil::IfcEntitySelect(*this);
|
2011-09-03 13:58:59 +00:00
|
|
|
}*/
|
2011-07-25 14:56:40 +00:00
|
|
|
TokenArgument::operator IfcEntities() const { throw IfcException("Argument is not a list of entities"); }
|
2011-07-11 09:33:18 +00:00
|
|
|
unsigned int TokenArgument::Size() const { return 1; }
|
|
|
|
|
ArgumentPtr TokenArgument::operator [] (unsigned int i) const { throw IfcException("Argument is not a list of arguments"); }
|
2012-03-13 11:56:52 +00:00
|
|
|
std::string TokenArgument::toString(bool upper) const { return TokenFunc::toString(token); }
|
2011-07-25 14:56:40 +00:00
|
|
|
bool TokenArgument::isNull() const { return TokenFunc::isOperator(token,'$'); }
|
2011-07-11 09:33:18 +00:00
|
|
|
//
|
|
|
|
|
// Functions for casting the EntityArgument to other types
|
|
|
|
|
//
|
|
|
|
|
EntityArgument::operator int() const { throw IfcException("Argument is not an integer"); }
|
|
|
|
|
EntityArgument::operator bool() const { throw IfcException("Argument is not a boolean"); }
|
2012-03-13 11:56:52 +00:00
|
|
|
EntityArgument::operator double() const { throw IfcException("Argument is not a number"); }
|
2011-07-11 09:33:18 +00:00
|
|
|
EntityArgument::operator std::string() const { throw IfcException("Argument is not a string"); }
|
2012-03-13 11:56:52 +00:00
|
|
|
EntityArgument::operator std::vector<double>() const { throw IfcException("Argument is not a list of floats"); }
|
2011-07-25 14:56:40 +00:00
|
|
|
EntityArgument::operator std::vector<int>() const { throw IfcException("Argument is not a list of ints"); }
|
|
|
|
|
EntityArgument::operator std::vector<std::string>() const { throw IfcException("Argument is not a list of strings"); }
|
2011-09-03 13:58:59 +00:00
|
|
|
EntityArgument::operator IfcUtil::IfcSchemaEntity() const { return entity; }
|
|
|
|
|
//EntityArgument::operator IfcUtil::IfcAbstractSelect::ptr() const { return entity; }
|
2011-07-25 14:56:40 +00:00
|
|
|
EntityArgument::operator IfcEntities() const { throw IfcException("Argument is not a list of entities"); }
|
2011-09-03 13:58:59 +00:00
|
|
|
unsigned int EntityArgument::Size() const { return 1; }
|
2011-07-11 09:33:18 +00:00
|
|
|
ArgumentPtr EntityArgument::operator [] (unsigned int i) const { throw IfcException("Argument is not a list of arguments"); }
|
2012-03-13 11:56:52 +00:00
|
|
|
std::string EntityArgument::toString(bool upper) const {
|
|
|
|
|
ArgumentPtr arg = entity->wrappedValue();
|
|
|
|
|
IfcParse::TokenArgument* token_arg = dynamic_cast<IfcParse::TokenArgument*>(arg);
|
2012-03-16 15:21:52 +00:00
|
|
|
std::string token_string = ( token_arg ) ? TokenFunc::toString(token_arg->token) : "";
|
2012-03-13 11:56:52 +00:00
|
|
|
std::string dt = Ifc2x3::Type::ToString(entity->type());
|
|
|
|
|
if ( upper ) {
|
|
|
|
|
for (std::string::iterator p = dt.begin(); p != dt.end(); ++p ) *p = toupper(*p);
|
|
|
|
|
}
|
|
|
|
|
return dt + "(" + token_string + ")";
|
|
|
|
|
}
|
2011-09-03 13:58:59 +00:00
|
|
|
//return entity->entity->toString(); }
|
2011-07-25 14:56:40 +00:00
|
|
|
bool EntityArgument::isNull() const { return false; }
|
2011-09-03 13:58:59 +00:00
|
|
|
EntityArgument::~EntityArgument() { delete entity; }
|
2011-07-11 09:33:18 +00:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Reads an Entity from the list of Tokens
|
|
|
|
|
//
|
2011-07-25 14:56:40 +00:00
|
|
|
Entity::Entity(unsigned int i, Tokens* t) {
|
2011-07-11 09:33:18 +00:00
|
|
|
Token datatype = t->Next();
|
|
|
|
|
if ( ! TokenFunc::isDatatype(datatype)) throw IfcException("Unexpected token while parsing entity");
|
2011-07-25 14:56:40 +00:00
|
|
|
_type = Ifc2x3::Type::FromString(TokenFunc::asString(datatype));
|
|
|
|
|
_id = i;
|
2011-07-11 09:33:18 +00:00
|
|
|
args = ArgumentPtr();
|
|
|
|
|
offset = TokenFunc::Offset(datatype);
|
2011-06-17 13:07:06 +00:00
|
|
|
}
|
2011-05-08 11:04:32 +00:00
|
|
|
|
2011-07-11 09:33:18 +00:00
|
|
|
//
|
|
|
|
|
// Reads an Entity from the list of Tokens at the specified offset in the file
|
|
|
|
|
//
|
|
|
|
|
Entity::Entity(unsigned int i, Tokens* t, unsigned int o) {
|
|
|
|
|
std::vector<unsigned int> ids;
|
2011-07-25 14:56:40 +00:00
|
|
|
_id = i;
|
2011-07-11 09:33:18 +00:00
|
|
|
offset = o;
|
|
|
|
|
Load(ids, true);
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Access the Nth argument from the ArgumentList
|
|
|
|
|
//
|
2011-07-25 14:56:40 +00:00
|
|
|
ArgumentPtr Entity::getArgument(unsigned int i) {
|
2011-07-11 09:33:18 +00:00
|
|
|
if ( ! args ) {
|
|
|
|
|
std::vector<unsigned int> ids;
|
|
|
|
|
Load(ids, true);
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
return (*args)[i];
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
|
2011-09-25 09:53:22 +00:00
|
|
|
unsigned int Entity::getArgumentCount() {
|
|
|
|
|
if ( ! args ) {
|
|
|
|
|
std::vector<unsigned int> ids;
|
|
|
|
|
Load(ids, true);
|
|
|
|
|
}
|
|
|
|
|
return args->Size();
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-11 09:33:18 +00:00
|
|
|
//
|
|
|
|
|
// Load the ArgumentList
|
|
|
|
|
//
|
|
|
|
|
void Entity::Load(std::vector<unsigned int>& ids, bool seek) {
|
|
|
|
|
if ( seek ) {
|
|
|
|
|
Ifc::file->Seek(offset);
|
|
|
|
|
Token datatype = Ifc::tokens->Next();
|
2011-07-25 14:56:40 +00:00
|
|
|
if ( ! TokenFunc::isDatatype(datatype)) throw IfcException("Unexpected token while parsing entity");
|
|
|
|
|
_type = Ifc2x3::Type::FromString(TokenFunc::asString(datatype));
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
Token open = Ifc::tokens->Next();
|
2011-09-03 13:58:59 +00:00
|
|
|
args = new ArgumentList(Ifc::tokens, ids);
|
2011-07-11 09:33:18 +00:00
|
|
|
unsigned int old_offset = Ifc::file->Tell();
|
|
|
|
|
Token semilocon = Ifc::tokens->Next();
|
|
|
|
|
if ( ! TokenFunc::isOperator(semilocon,';') ) Ifc::file->Seek(old_offset);
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
|
2011-09-03 13:58:59 +00:00
|
|
|
Ifc2x3::Type::Enum Entity::type() const {
|
2011-07-25 14:56:40 +00:00
|
|
|
return _type;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-11 09:33:18 +00:00
|
|
|
//
|
2011-07-25 14:56:40 +00:00
|
|
|
// Returns the CamelCase string representation of the datatype as it is defined in the schema
|
2011-07-11 09:33:18 +00:00
|
|
|
//
|
2011-07-25 14:56:40 +00:00
|
|
|
std::string Entity::datatype() {
|
|
|
|
|
return Ifc2x3::Type::ToString(_type);
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Returns a string representation of the entity
|
|
|
|
|
// Note that this initializes the entity if it is not initialized
|
|
|
|
|
//
|
2012-03-13 11:56:52 +00:00
|
|
|
std::string Entity::toString(bool upper) {
|
2011-07-11 09:33:18 +00:00
|
|
|
if ( ! args ) {
|
|
|
|
|
std::vector<unsigned int> ids;
|
|
|
|
|
Load(ids, true);
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
std::stringstream ss;
|
2012-03-13 11:56:52 +00:00
|
|
|
std::string dt = datatype();
|
|
|
|
|
if ( upper ) {
|
|
|
|
|
for (std::string::iterator p = dt.begin(); p != dt.end(); ++p ) *p = toupper(*p);
|
|
|
|
|
}
|
|
|
|
|
ss << "#" << _id << "=" << dt << args->toString(upper);
|
2011-05-08 11:04:32 +00:00
|
|
|
return ss.str();
|
|
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
|
2011-09-03 13:58:59 +00:00
|
|
|
Entity::~Entity() {
|
|
|
|
|
delete args;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-11 09:33:18 +00:00
|
|
|
//
|
|
|
|
|
// Returns the entities of type c that have this entity in their ArgumentList
|
|
|
|
|
//
|
2011-07-25 14:56:40 +00:00
|
|
|
IfcEntities Entity::getInverse(Ifc2x3::Type::Enum c) {
|
|
|
|
|
IfcEntities l = IfcEntities(new IfcEntityList());
|
|
|
|
|
IfcEntities all = Ifc::EntitiesByReference(_id);
|
2011-05-08 11:04:32 +00:00
|
|
|
if ( ! all ) return l;
|
2011-07-25 14:56:40 +00:00
|
|
|
for( IfcEntityList::it it = all->begin(); it != all->end();++ it ) {
|
|
|
|
|
if ( c == Ifc2x3::Type::ALL || (*it)->is(c) ) {
|
2011-05-08 11:04:32 +00:00
|
|
|
l->push(*it);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return l;
|
|
|
|
|
}
|
2011-07-25 14:56:40 +00:00
|
|
|
IfcEntities Entity::getInverse(Ifc2x3::Type::Enum c, int i, const std::string& a) {
|
|
|
|
|
IfcEntities l = IfcEntities(new IfcEntityList());
|
|
|
|
|
IfcEntities all = getInverse(c);
|
|
|
|
|
for( IfcEntityList::it it = all->begin(); it != all->end();++ it ) {
|
|
|
|
|
const std::string s = *(*it)->entity->getArgument(i);
|
2011-07-11 09:33:18 +00:00
|
|
|
if ( s == a ) {
|
2011-05-08 11:04:32 +00:00
|
|
|
l->push(*it);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return l;
|
|
|
|
|
}
|
2011-09-03 13:58:59 +00:00
|
|
|
bool Entity::is(Ifc2x3::Type::Enum v) const { return _type == v; }
|
2011-07-25 14:56:40 +00:00
|
|
|
unsigned int Entity::id() { return _id; }
|
2011-07-11 09:33:18 +00:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Parses the IFC file in fn
|
|
|
|
|
// Creates the maps
|
|
|
|
|
// Gets the unit definitins from the file
|
|
|
|
|
//
|
|
|
|
|
bool Ifc::Init(const std::string& fn) {
|
2012-03-13 11:56:52 +00:00
|
|
|
return Ifc::Init(new File(fn));
|
2011-08-20 09:08:56 +00:00
|
|
|
}
|
|
|
|
|
bool Ifc::Init(std::istream& f, int len) {
|
2012-03-13 11:56:52 +00:00
|
|
|
return Ifc::Init(new File(f,len));
|
2011-08-20 09:08:56 +00:00
|
|
|
}
|
2011-10-27 16:13:29 +00:00
|
|
|
bool Ifc::Init(void* data, int len) {
|
2012-03-13 11:56:52 +00:00
|
|
|
return Ifc::Init(new File(data,len));
|
2011-10-27 16:13:29 +00:00
|
|
|
}
|
2011-08-20 09:08:56 +00:00
|
|
|
bool Ifc::Init(IfcParse::File* f) {
|
2011-09-03 13:58:59 +00:00
|
|
|
Ifc2x3::InitStringMap();
|
2011-08-20 09:08:56 +00:00
|
|
|
file = f;
|
2011-08-07 10:21:22 +00:00
|
|
|
if ( ! file->valid ) return false;
|
2011-07-11 09:33:18 +00:00
|
|
|
tokens = new Tokens (file);
|
|
|
|
|
Token token = 0;
|
|
|
|
|
Token previous = 0;
|
|
|
|
|
unsigned int currentId = 0;
|
|
|
|
|
lastId = 0;
|
|
|
|
|
int x = 0;
|
2011-07-25 14:56:40 +00:00
|
|
|
EntityPtr e;
|
2012-03-13 11:56:52 +00:00
|
|
|
IfcUtil::IfcSchemaEntity entity = 0;
|
2011-08-07 10:21:22 +00:00
|
|
|
if ( log1 ) std::cout << "Scanning file..." << std::endl;
|
2012-02-04 15:10:17 +00:00
|
|
|
while ( ! file->eof ) {
|
2011-07-11 09:33:18 +00:00
|
|
|
if ( currentId ) {
|
2011-10-13 11:25:59 +00:00
|
|
|
try {
|
|
|
|
|
e = new Entity(currentId,tokens);
|
|
|
|
|
entity = Ifc2x3::SchemaEntity(e);
|
|
|
|
|
} catch (IfcException ex) {
|
|
|
|
|
currentId = 0;
|
|
|
|
|
Ifc::LogMessage("Error",ex.what());
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2011-08-07 10:21:22 +00:00
|
|
|
if ( log1 && !((++x)%1000) ) std::cout << "\r#" << currentId << " " << std::flush;
|
2012-03-13 11:56:52 +00:00
|
|
|
if ( entity->is(Ifc2x3::Type::IfcRoot) ) {
|
|
|
|
|
Ifc2x3::IfcRoot::ptr ifc_root = (Ifc2x3::IfcRoot::ptr) entity;
|
|
|
|
|
try {
|
|
|
|
|
const std::string guid = ifc_root->GlobalId();
|
|
|
|
|
if ( byguid.find(guid) != byguid.end() ) {
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
ss << "Overwriting entity with guid " << guid;
|
|
|
|
|
Ifc::LogMessage("Warning",ss.str());
|
|
|
|
|
}
|
|
|
|
|
byguid[guid] = ifc_root;
|
|
|
|
|
} catch (IfcException ex) {
|
|
|
|
|
Ifc::LogMessage("Error",ex.what());
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-08-24 12:21:07 +00:00
|
|
|
Ifc2x3::Type::Enum ty = entity->type();
|
|
|
|
|
do {
|
|
|
|
|
IfcEntities L = EntitiesByType(ty);
|
|
|
|
|
if ( L == 0 ) {
|
|
|
|
|
L = IfcEntities(new IfcEntityList());
|
|
|
|
|
bytype[ty] = L;
|
|
|
|
|
}
|
|
|
|
|
L->push(entity);
|
|
|
|
|
ty = Ifc2x3::Type::Parent(ty);
|
|
|
|
|
} while ( ty > -1 );
|
2012-02-04 15:10:17 +00:00
|
|
|
if ( byid.find(currentId) != byid.end() ) {
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
ss << "Overwriting entity with id " << currentId;
|
|
|
|
|
Ifc::LogMessage("Warning",ss.str());
|
|
|
|
|
}
|
2011-07-25 14:56:40 +00:00
|
|
|
byid[currentId] = entity;
|
2011-07-11 09:33:18 +00:00
|
|
|
currentId = 0;
|
2012-03-13 11:56:52 +00:00
|
|
|
} else {
|
|
|
|
|
try { token = tokens->Next(); }
|
|
|
|
|
catch (... ) { token = 0; }
|
|
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
if ( ! token ) break;
|
|
|
|
|
if ( previous && TokenFunc::isIdentifier(previous) ) {
|
|
|
|
|
int id = TokenFunc::asInt(previous);
|
|
|
|
|
if ( TokenFunc::isOperator(token,'=') ) {
|
|
|
|
|
currentId = id;
|
2012-03-13 11:56:52 +00:00
|
|
|
} else if (entity) {
|
2011-07-25 14:56:40 +00:00
|
|
|
IfcEntities L = EntitiesByReference(id);
|
2011-05-08 11:04:32 +00:00
|
|
|
if ( L == 0 ) {
|
2011-07-25 14:56:40 +00:00
|
|
|
L = IfcEntities(new IfcEntityList());
|
2011-07-11 09:33:18 +00:00
|
|
|
byref[id] = L;
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
L->push(entity);
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
previous = token;
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
|
|
|
|
|
2011-08-07 10:21:22 +00:00
|
|
|
if ( log1 ) std::cout << "\rDone scanning file " << std::endl;
|
2012-03-13 11:56:52 +00:00
|
|
|
|
2011-08-20 09:08:56 +00:00
|
|
|
Ifc2x3::IfcUnitAssignment::list unit_assignments = EntitiesByType<Ifc2x3::IfcUnitAssignment>();
|
|
|
|
|
IfcUtil::IfcAbstractSelect::list units = IfcUtil::IfcAbstractSelect::list();
|
|
|
|
|
if ( unit_assignments->Size() ) {
|
2011-08-24 12:21:07 +00:00
|
|
|
Ifc2x3::IfcUnitAssignment::ptr unit_assignment = *unit_assignments->begin();
|
|
|
|
|
units = unit_assignment->Units();
|
2011-11-02 12:52:35 +00:00
|
|
|
}
|
|
|
|
|
if ( ! units ) {
|
|
|
|
|
// No units eh... Since tolerances and deflection are specified internally in meters
|
|
|
|
|
// we will try to find another indication of the model size.
|
|
|
|
|
Ifc2x3::IfcExtrudedAreaSolid::list extrusions = EntitiesByType<Ifc2x3::IfcExtrudedAreaSolid>();
|
|
|
|
|
if ( ! extrusions->Size() ) return true;
|
2012-03-13 11:56:52 +00:00
|
|
|
double max_height = -1.0f;
|
2011-11-02 12:52:35 +00:00
|
|
|
for ( Ifc2x3::IfcExtrudedAreaSolid::it it = extrusions->begin(); it != extrusions->end(); ++ it ) {
|
2012-03-13 11:56:52 +00:00
|
|
|
const double depth = (*it)->Depth();
|
2011-11-02 12:52:35 +00:00
|
|
|
if ( depth > max_height ) max_height = depth;
|
|
|
|
|
}
|
|
|
|
|
if ( max_height > 100.0f ) Ifc::LengthUnit = 0.001f;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2011-10-18 08:12:39 +00:00
|
|
|
try {
|
2012-03-13 11:56:52 +00:00
|
|
|
for ( IfcUtil::IfcAbstractSelect::it it = units->begin(); it != units->end(); ++ it ) {
|
|
|
|
|
const IfcUtil::IfcAbstractSelect::ptr base = *it;
|
|
|
|
|
Ifc2x3::IfcSIUnit::ptr unit = Ifc2x3::IfcSIUnit::ptr();
|
|
|
|
|
double value = 1.0f;
|
|
|
|
|
if ( base->is(Ifc2x3::Type::IfcConversionBasedUnit) ) {
|
|
|
|
|
const Ifc2x3::IfcConversionBasedUnit::ptr u = reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcConversionBasedUnit>(base);
|
|
|
|
|
const Ifc2x3::IfcMeasureWithUnit::ptr u2 = u->ConversionFactor();
|
|
|
|
|
Ifc2x3::IfcUnit u3 = u2->UnitComponent();
|
|
|
|
|
if ( u3->is(Ifc2x3::Type::IfcSIUnit) ) {
|
|
|
|
|
unit = (Ifc2x3::IfcSIUnit*) u3;
|
|
|
|
|
}
|
|
|
|
|
Ifc2x3::IfcValue v = u2->ValueComponent();
|
|
|
|
|
IfcUtil::IfcArgumentSelect* v2 = (IfcUtil::IfcArgumentSelect*) v;
|
|
|
|
|
const double f = *v2->wrappedValue();
|
|
|
|
|
value *= f;
|
|
|
|
|
} else if ( base->is(Ifc2x3::Type::IfcSIUnit) ) {
|
|
|
|
|
unit = reinterpret_pointer_cast<IfcUtil::IfcAbstractSelect,Ifc2x3::IfcSIUnit>(base);
|
2011-07-11 09:33:18 +00:00
|
|
|
}
|
2012-03-13 11:56:52 +00:00
|
|
|
if ( unit ) {
|
|
|
|
|
if ( unit->hasPrefix() ) {
|
|
|
|
|
value *= UnitPrefixToValue(unit->Prefix());
|
|
|
|
|
}
|
|
|
|
|
Ifc2x3::IfcUnitEnum::IfcUnitEnum type = unit->UnitType();
|
|
|
|
|
if ( type == Ifc2x3::IfcUnitEnum::IfcUnit_LENGTHUNIT ) {
|
|
|
|
|
Ifc::LengthUnit = value;
|
|
|
|
|
} else if ( type == Ifc2x3::IfcUnitEnum::IfcUnit_PLANEANGLEUNIT ) {
|
|
|
|
|
Ifc::PlaneAngleUnit = value;
|
|
|
|
|
Ifc::hasPlaneAngleUnit = true;
|
|
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-10-18 08:12:39 +00:00
|
|
|
} catch ( IfcException ex ) {
|
|
|
|
|
Ifc::LogMessage("Error",ex.what());
|
|
|
|
|
}
|
2011-07-25 14:56:40 +00:00
|
|
|
return true;
|
2011-07-11 09:33:18 +00:00
|
|
|
}
|
2011-05-08 11:04:32 +00:00
|
|
|
|
2011-07-25 14:56:40 +00:00
|
|
|
IfcEntities Ifc::EntitiesByType(Ifc2x3::Type::Enum t) {
|
2011-07-11 09:33:18 +00:00
|
|
|
MapEntitiesByType::const_iterator it = bytype.find(t);
|
2011-07-25 14:56:40 +00:00
|
|
|
return (it == bytype.end()) ? IfcEntities() : it->second;
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-25 14:56:40 +00:00
|
|
|
IfcEntities Ifc::EntitiesByReference(int t) {
|
2011-07-11 09:33:18 +00:00
|
|
|
MapEntitiesByRef::const_iterator it = byref.find(t);
|
2011-07-25 14:56:40 +00:00
|
|
|
return (it == byref.end()) ? IfcEntities() : it->second;
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-25 14:56:40 +00:00
|
|
|
IfcUtil::IfcSchemaEntity Ifc::EntityById(int id) {
|
2011-07-11 09:33:18 +00:00
|
|
|
MapEntityById::const_iterator it = byid.find(id);
|
|
|
|
|
if ( it == byid.end() ) {
|
|
|
|
|
MapOffsetById::const_iterator it2 = offsets.find(id);
|
|
|
|
|
if ( it2 == offsets.end() ) throw IfcException("Entity not found");
|
|
|
|
|
const unsigned int offset = (*it2).second;
|
2011-07-25 14:56:40 +00:00
|
|
|
EntityPtr e = EntityPtr(new Entity(id,Ifc::tokens,offset));
|
|
|
|
|
IfcUtil::IfcSchemaEntity entity = Ifc2x3::SchemaEntity(e);
|
2011-07-11 09:33:18 +00:00
|
|
|
byid[id] = entity;
|
|
|
|
|
return entity;
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
return it->second;
|
2011-05-08 11:04:32 +00:00
|
|
|
}
|
2012-03-13 11:56:52 +00:00
|
|
|
Ifc2x3::IfcRoot::ptr Ifc::EntityByGuid(const std::string& guid) {
|
|
|
|
|
MapEntityByGuid::const_iterator it = byguid.find(guid);
|
|
|
|
|
if ( it == byguid.end() ) {
|
|
|
|
|
throw IfcException("Entity not found");
|
|
|
|
|
} else {
|
|
|
|
|
return it->second;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-07-25 14:56:40 +00:00
|
|
|
|
2011-07-11 09:33:18 +00:00
|
|
|
IfcException::IfcException(std::string e) { error = e; }
|
2011-07-22 08:24:00 +00:00
|
|
|
IfcException::~IfcException() throw () {}
|
|
|
|
|
const char* IfcException::what() const throw() { return error.c_str(); }
|
2011-07-25 14:56:40 +00:00
|
|
|
|
2011-05-08 11:04:32 +00:00
|
|
|
void Ifc::Dispose() {
|
2011-09-03 13:58:59 +00:00
|
|
|
for( MapEntityById::const_iterator it = byid.begin(); it != byid.end(); ++ it ) {
|
|
|
|
|
delete it->second->entity;
|
|
|
|
|
delete it->second;
|
|
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
bytype.clear();
|
|
|
|
|
byid.clear();
|
|
|
|
|
byref.clear();
|
2011-10-12 16:43:29 +00:00
|
|
|
file->Close();
|
2011-09-03 13:58:59 +00:00
|
|
|
delete file;
|
|
|
|
|
delete tokens;
|
|
|
|
|
offsets.clear();
|
2011-10-24 19:26:55 +00:00
|
|
|
log_stream.str("");
|
2011-07-25 14:56:40 +00:00
|
|
|
}
|
|
|
|
|
|
2012-03-13 11:56:52 +00:00
|
|
|
double UnitPrefixToValue( Ifc2x3::IfcSIPrefix::IfcSIPrefix v ) {
|
|
|
|
|
if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_EXA ) return (double) 1e18;
|
|
|
|
|
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_PETA ) return (double) 1e15;
|
|
|
|
|
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_TERA ) return (double) 1e12;
|
|
|
|
|
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_GIGA ) return (double) 1e9;
|
|
|
|
|
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_MEGA ) return (double) 1e6;
|
|
|
|
|
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_KILO ) return (double) 1e3;
|
|
|
|
|
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_HECTO ) return (double) 1e2;
|
|
|
|
|
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_DECA ) return (double) 1;
|
|
|
|
|
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_DECI ) return (double) 1e-1;
|
|
|
|
|
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_CENTI ) return (double) 1e-2;
|
|
|
|
|
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_MILLI ) return (double) 1e-3;
|
|
|
|
|
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_MICRO ) return (double) 1e-6;
|
|
|
|
|
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_NANO ) return (double) 1e-9;
|
|
|
|
|
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_PICO ) return (double) 1e-12;
|
|
|
|
|
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_FEMTO ) return (double) 1e-15;
|
|
|
|
|
else if ( v == Ifc2x3::IfcSIPrefix::IfcSIPrefix_ATTO ) return (double) 1e-18;
|
2011-06-13 07:23:09 +00:00
|
|
|
else return 1.0f;
|
|
|
|
|
}
|
2011-10-12 16:43:29 +00:00
|
|
|
void Ifc::SetOutput(std::ostream* l1, std::ostream* l2) {
|
|
|
|
|
log1 = l1;
|
|
|
|
|
log2 = l2;
|
|
|
|
|
if ( ! log2 ) {
|
|
|
|
|
log2 = &log_stream;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-09-03 13:58:59 +00:00
|
|
|
void Ifc::LogMessage(const std::string& type, const std::string& message, const IfcAbstractEntityPtr entity) {
|
2011-08-07 10:21:22 +00:00
|
|
|
if ( log2 ) {
|
|
|
|
|
(*log2) << "[" << type << "] " << message << std::endl;
|
|
|
|
|
if ( entity ) (*log2) << entity->toString() << std::endl;
|
2011-07-25 14:56:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-10-12 16:43:29 +00:00
|
|
|
std::string Ifc::GetLog() {
|
|
|
|
|
return log_stream.str();
|
|
|
|
|
}
|
2012-03-16 15:21:52 +00:00
|
|
|
MapEntityById::const_iterator Ifc::First() {
|
|
|
|
|
return byid.begin();
|
|
|
|
|
}
|
|
|
|
|
MapEntityById::const_iterator Ifc::Last() {
|
|
|
|
|
return byid.end();
|
|
|
|
|
}
|
2011-07-11 09:33:18 +00:00
|
|
|
|
|
|
|
|
File* Ifc::file = 0;
|
2011-08-07 10:21:22 +00:00
|
|
|
std::ostream* Ifc::log1 = 0;
|
|
|
|
|
std::ostream* Ifc::log2 = 0;
|
2011-07-11 09:33:18 +00:00
|
|
|
unsigned int Ifc::lastId = 0;
|
|
|
|
|
Tokens* Ifc::tokens = 0;
|
2012-03-13 11:56:52 +00:00
|
|
|
double Ifc::LengthUnit = 1.0f;
|
|
|
|
|
double Ifc::PlaneAngleUnit = 1.0f;
|
2011-12-07 14:07:22 +00:00
|
|
|
bool Ifc::hasPlaneAngleUnit = false;
|
2012-03-23 17:38:44 +00:00
|
|
|
bool Ifc::SewShells = false;
|
2011-07-11 09:33:18 +00:00
|
|
|
int Ifc::CircleSegments = 32;
|
|
|
|
|
MapEntitiesByType Ifc::bytype;
|
|
|
|
|
MapEntityById Ifc::byid;
|
2012-03-13 11:56:52 +00:00
|
|
|
MapEntityByGuid Ifc::byguid;
|
2011-07-11 09:33:18 +00:00
|
|
|
MapEntitiesByRef Ifc::byref;
|
|
|
|
|
MapOffsetById Ifc::offsets;
|
2011-10-12 16:43:29 +00:00
|
|
|
std::stringstream Ifc::log_stream;
|
2012-06-07 14:38:21 +00:00
|
|
|
int Ifc::Verbosity = 2;
|