mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-28 15:53:00 +00:00
Merge branch 'v0.6.0' into v0.7.0
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
********************************************************************************/
|
||||
|
||||
#include "../serializers/ColladaSerializer.h"
|
||||
#include "../serializers/GltfSerializer.h"
|
||||
#include "../serializers/IgesSerializer.h"
|
||||
#include "../serializers/StepSerializer.h"
|
||||
#include "../serializers/WavefrontObjSerializer.h"
|
||||
@@ -92,6 +93,9 @@ void print_usage(bool suggest_help = true)
|
||||
<< " .obj WaveFront OBJ (a .mtl file is also created)\n"
|
||||
#ifdef WITH_OPENCOLLADA
|
||||
<< " .dae Collada Digital Assets Exchange\n"
|
||||
#endif
|
||||
#ifdef WITH_GLTF
|
||||
<< " .glb glTF Binary glTF v2.0\n"
|
||||
#endif
|
||||
<< " .stp STEP Standard for the Exchange of Product Data\n"
|
||||
<< " .igs IGES Initial Graphics Exchange Specification\n"
|
||||
@@ -531,6 +535,7 @@ int main(int argc, char** argv) {
|
||||
const path_t OBJ = IfcUtil::path::from_utf8(".obj"),
|
||||
MTL = IfcUtil::path::from_utf8(".mtl"),
|
||||
DAE = IfcUtil::path::from_utf8(".dae"),
|
||||
GLB = IfcUtil::path::from_utf8(".glb"),
|
||||
STP = IfcUtil::path::from_utf8(".stp"),
|
||||
IGS = IfcUtil::path::from_utf8(".igs"),
|
||||
SVG = IfcUtil::path::from_utf8(".svg"),
|
||||
@@ -656,6 +661,10 @@ int main(int argc, char** argv) {
|
||||
#ifdef WITH_OPENCOLLADA
|
||||
} else if (output_extension == DAE) {
|
||||
serializer = boost::make_shared<ColladaSerializer>(IfcUtil::path::to_utf8(output_temp_filename), settings);
|
||||
#endif
|
||||
#ifdef WITH_GLTF
|
||||
} else if (output_extension == GLB) {
|
||||
serializer = boost::make_shared<GltfSerializer>(IfcUtil::path::to_utf8(output_temp_filename), settings);
|
||||
#endif
|
||||
} else if (output_extension == STP) {
|
||||
serializer = boost::make_shared<StepSerializer>(IfcUtil::path::to_utf8(output_temp_filename), settings);
|
||||
|
||||
@@ -2683,8 +2683,17 @@ bool IfcGeom::Kernel::triangulate_wire(const TopoDS_Wire& wire, TopTools_ListOfS
|
||||
// Validation
|
||||
|
||||
for (int i = 1; i <= mape.Extent(); ++i) {
|
||||
#if OCC_VERSION_HEX >= 0x70000
|
||||
TopTools_ListOfShape val;
|
||||
if (!mapn.FindFromKey(mape.FindKey(i), val)) {
|
||||
#else
|
||||
bool contains = false;
|
||||
try {
|
||||
TopTools_ListOfShape val = mapn.FindFromKey(mape.FindKey(i));
|
||||
contains = true;
|
||||
} catch (Standard_NoSuchObject&) {}
|
||||
if (!contains) {
|
||||
#endif
|
||||
// All existing edges need to exist in the new faces
|
||||
Logger::Error("Internal error, missing edge from triangulation");
|
||||
if (faceset_helper_ != nullptr) {
|
||||
|
||||
@@ -70,89 +70,26 @@
|
||||
using namespace IfcParse;
|
||||
using namespace IfcWrite;
|
||||
|
||||
#ifdef HAVE_ICU
|
||||
#include <unicode/unistr.h>
|
||||
#endif
|
||||
|
||||
void IfcCharacterDecoder::addChar(std::stringstream& s,const UChar32& ch) {
|
||||
#ifdef HAVE_ICU
|
||||
if ( destination ) {
|
||||
/* Note: The extraction buffer is of size 5, because in the UTF-8 encoding the
|
||||
maximum length in bytes is 4. We add 1 for the NUL character. In other encodings
|
||||
the length could be higher, but we have not taken that into account. */
|
||||
char extraction_buffer[5] = {};
|
||||
icu::UnicodeString(ch).extract(extraction_buffer,5,destination,status);
|
||||
extraction_buffer[4] = '\0';
|
||||
s << extraction_buffer;
|
||||
} else {
|
||||
std::stringstream s2;
|
||||
s2 << "\\u" << std::hex << std::setw(4) << std::setfill('0') << (int) ch;
|
||||
s << s2.str();
|
||||
}
|
||||
#else
|
||||
(void)ch;
|
||||
s.put(substitution_character);
|
||||
#endif
|
||||
}
|
||||
IfcCharacterDecoder::IfcCharacterDecoder(IfcParse::IfcSpfStream* f) {
|
||||
file = f;
|
||||
#ifdef HAVE_ICU
|
||||
if (destination) ucnv_close(destination);
|
||||
if (compatibility_converter) ucnv_close(compatibility_converter);
|
||||
destination = 0;
|
||||
compatibility_converter = 0;
|
||||
codepage_ = 0;
|
||||
}
|
||||
|
||||
if (mode == DEFAULT) {
|
||||
destination = ucnv_open(0, &status);
|
||||
} else if (mode == UTF8) {
|
||||
destination = ucnv_open("utf-8", &status);
|
||||
} else if (mode == LATIN) {
|
||||
destination = ucnv_open("iso-8859-1", &status);
|
||||
}
|
||||
if (compatibility_charset.empty()) {
|
||||
compatibility_charset = ucnv_getDefaultName();
|
||||
}
|
||||
compatibility_converter = ucnv_open(compatibility_charset.c_str(), &status);
|
||||
#endif
|
||||
}
|
||||
IfcCharacterDecoder::~IfcCharacterDecoder() {
|
||||
#ifdef HAVE_ICU
|
||||
if ( destination ) ucnv_close(destination);
|
||||
if ( converter ) ucnv_close(converter);
|
||||
if ( compatibility_converter ) ucnv_close(compatibility_converter);
|
||||
destination = 0;
|
||||
converter = 0;
|
||||
compatibility_converter = 0;
|
||||
ucnv_flushCache();
|
||||
#endif
|
||||
}
|
||||
|
||||
IfcCharacterDecoder::operator std::string() {
|
||||
unsigned int parse_state = 0;
|
||||
std::stringstream s;
|
||||
s.put('\'');
|
||||
builder_.clear();
|
||||
builder_.push_back('\'');
|
||||
char current_char;
|
||||
int codepage = 1;
|
||||
unsigned int hex = 0;
|
||||
unsigned int hex_count = 0;
|
||||
#ifdef HAVE_ICU
|
||||
unsigned int old_hex = 0; // for compatibility_mode
|
||||
#endif
|
||||
|
||||
while ( (current_char = file->Peek()) != 0 ) {
|
||||
if ( EXPECTS_CHARACTER(parse_state) ) {
|
||||
#ifdef HAVE_ICU
|
||||
if ( previous_codepage != codepage ) {
|
||||
if ( converter ) ucnv_close(converter);
|
||||
char encoder[11] = {'i','s','o','-','8','8','5','9','-', static_cast<char>(codepage + 0x30) };
|
||||
converter = ucnv_open(encoder, &status);
|
||||
}
|
||||
const char characters[2] = { static_cast<char>(current_char + 0x80) };
|
||||
const char* char_array = &characters[0];
|
||||
UChar32 ch = ucnv_getNextUChar(converter,&char_array,char_array+1,&status);
|
||||
addChar(s,ch);
|
||||
#else
|
||||
UChar32 ch = 0;
|
||||
addChar(s,ch);
|
||||
#endif
|
||||
builder_.push_back(IfcUtil::convert_codepage(codepage, current_char + 0x80));
|
||||
parse_state = 0;
|
||||
} else if ( current_char == '\'' && ! parse_state ) {
|
||||
parse_state = APOSTROPHE;
|
||||
@@ -192,31 +129,15 @@ IfcCharacterDecoder::operator std::string() {
|
||||
hex += HEX_TO_INT(current_char);
|
||||
if ( (hex_count == 2 && !(parse_state & EXTENDED2)) ||
|
||||
(hex_count == 4 && !(parse_state & EXTENDED4)) ||
|
||||
(hex_count == 8) ) {
|
||||
#ifdef HAVE_ICU
|
||||
if (compatibility_mode) {
|
||||
if (old_hex == 0) {
|
||||
old_hex = hex;
|
||||
} else {
|
||||
char characters[3] = { (char)old_hex, (char)hex };
|
||||
const char* char_array = &characters[0];
|
||||
UChar32 ch = ucnv_getNextUChar(compatibility_converter,&char_array,char_array+2,&status);
|
||||
addChar(s,ch);
|
||||
old_hex = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
addChar(s,(UChar32) hex);
|
||||
#ifdef HAVE_ICU
|
||||
}
|
||||
#endif
|
||||
if ( hex_count == 2 ) parse_state = 0;
|
||||
else {
|
||||
CLEAR_HEX(parse_state);
|
||||
parse_state |= ENCOUNTERED_HEX;
|
||||
}
|
||||
hex = hex_count = 0;
|
||||
(hex_count == 8) )
|
||||
{
|
||||
builder_.push_back(hex);
|
||||
if ( hex_count == 2 ) parse_state = 0;
|
||||
else {
|
||||
CLEAR_HEX(parse_state);
|
||||
parse_state |= ENCOUNTERED_HEX;
|
||||
}
|
||||
hex = hex_count = 0;
|
||||
}
|
||||
} else if ( parse_state && !(
|
||||
(current_char == '\\' && parse_state == FIRST_SOLIDUS) ||
|
||||
@@ -226,14 +147,40 @@ IfcCharacterDecoder::operator std::string() {
|
||||
throw IfcInvalidTokenException(file->Tell(), current_char);
|
||||
} else {
|
||||
parse_state = hex = hex_count = 0;
|
||||
// NOTE: this is in fact wrong, this ought to be the representation of the character.
|
||||
// In UTF-8 this is the same, but we should not rely on that.
|
||||
s.put(current_char);
|
||||
builder_.push_back(current_char);
|
||||
}
|
||||
file->Inc();
|
||||
}
|
||||
s.put('\'');
|
||||
return s.str();
|
||||
builder_.push_back('\'');
|
||||
|
||||
if (mode == UTF8) {
|
||||
return IfcUtil::convert_utf8(builder_);
|
||||
} else if (mode == SUBSTITUTE) {
|
||||
std::string r;
|
||||
r.reserve(builder_.size());
|
||||
const char& sub = substitution_character;
|
||||
std::transform(builder_.begin(), builder_.end(), std::back_inserter(r), [&sub](wchar_t c) {
|
||||
if (c >= 0x20 && c <= 0x7e) {
|
||||
return (char)c;
|
||||
} else {
|
||||
return sub;
|
||||
}
|
||||
});
|
||||
return r;
|
||||
} else if (mode == ESCAPE) {
|
||||
std::stringstream str;
|
||||
str << std::hex << std::setw(4) << std::setfill('0');
|
||||
std::for_each(builder_.begin(), builder_.end(), [&str](wchar_t c) {
|
||||
if (c >= 0x20 && c <= 0x7e) {
|
||||
str.put((char)c);
|
||||
} else {
|
||||
str << "\\u" << c;
|
||||
}
|
||||
});
|
||||
return str.str();
|
||||
} else {
|
||||
throw IfcParse::IfcException("Invalid conversion mode");
|
||||
}
|
||||
}
|
||||
|
||||
void IfcCharacterDecoder::dryRun() {
|
||||
@@ -298,60 +245,28 @@ void IfcCharacterDecoder::dryRun() {
|
||||
file->Inc();
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_ICU
|
||||
UConverter* IfcCharacterDecoder::destination = 0;
|
||||
UConverter* IfcCharacterDecoder::converter = 0;
|
||||
UConverter* IfcCharacterDecoder::compatibility_converter = 0;
|
||||
int IfcCharacterDecoder::previous_codepage = -1;
|
||||
UErrorCode IfcCharacterDecoder::status = U_ZERO_ERROR;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ICU
|
||||
|
||||
IfcCharacterDecoder::ConversionMode IfcCharacterDecoder::mode = IfcCharacterDecoder::UTF8;
|
||||
|
||||
// Many BIM software (eg. Revit, ArchiCAD, ...) has wrong behavior
|
||||
bool IfcCharacterDecoder::compatibility_mode = false;
|
||||
std::string IfcCharacterDecoder::compatibility_charset = "";
|
||||
|
||||
#else
|
||||
char IfcCharacterDecoder::substitution_character = '_';
|
||||
#endif
|
||||
|
||||
|
||||
IfcCharacterEncoder::IfcCharacterEncoder(const std::string& input) {
|
||||
#ifdef HAVE_ICU
|
||||
if ( !converter) converter = ucnv_open("utf-8", &status);
|
||||
#endif
|
||||
str = input;
|
||||
}
|
||||
|
||||
IfcCharacterEncoder::~IfcCharacterEncoder() {
|
||||
#ifdef HAVE_ICU
|
||||
if ( converter) ucnv_close(converter);
|
||||
converter = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
IfcCharacterEncoder::IfcCharacterEncoder(const std::string& input)
|
||||
: str(IfcUtil::convert_utf8(input)) {}
|
||||
|
||||
IfcCharacterEncoder::operator std::string() {
|
||||
std::ostringstream oss;
|
||||
oss.put('\'');
|
||||
#ifdef HAVE_ICU
|
||||
|
||||
// Either 2 or 4 to uses \X2 or \X4 respectively.
|
||||
// Currently hardcoded to 4, but \X2 might be
|
||||
// sufficient for nearly all purposes.
|
||||
const int num_bytes = 4;
|
||||
const std::string num_bytes_str = std::string(1,num_bytes + 0x30);
|
||||
|
||||
|
||||
UChar32 ch;
|
||||
|
||||
const char* source = str.c_str();
|
||||
const char* limit = source + str.size();
|
||||
|
||||
|
||||
bool in_extended = false;
|
||||
|
||||
while(source < limit) {
|
||||
ch = ucnv_getNextUChar(converter, &source, limit, &status);
|
||||
for (auto it = str.begin(); it != str.end(); ++it) {
|
||||
auto ch = *it;
|
||||
const bool within_spf_range = ch >= 0x20 && ch <= 0x7e;
|
||||
if ( in_extended && within_spf_range ) {
|
||||
oss << "\\X0\\";
|
||||
@@ -368,26 +283,61 @@ IfcCharacterEncoder::operator std::string() {
|
||||
}
|
||||
|
||||
if ( in_extended ) oss << "\\X0\\";
|
||||
#else
|
||||
for (std::string::const_iterator i = str.begin(); i != str.end(); ++i) {
|
||||
char ch = *i;
|
||||
const bool within_spf_range = ch >= 0x20 && ch <= 0x7e;
|
||||
if (within_spf_range) {
|
||||
if ( ch == '\\' || ch == '\'' ) {
|
||||
oss.put(ch);
|
||||
}
|
||||
oss.put(ch);
|
||||
} else {
|
||||
oss.put('_');
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
oss.put('\'');
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
/*
|
||||
Generate with:
|
||||
|
||||
#ifdef HAVE_ICU
|
||||
UErrorCode IfcCharacterEncoder::status = U_ZERO_ERROR;
|
||||
UConverter* IfcCharacterEncoder::converter = 0;
|
||||
#endif
|
||||
import codecs, string
|
||||
codecs.register_error('zero', lambda e: (chr(0),e.start + 1))
|
||||
def _():
|
||||
for i in range(1,17):
|
||||
try:
|
||||
chrs = bytes(range(256)).decode('iso-8859-%d' % i, errors='zero')
|
||||
except: chrs = "\x00" * 256
|
||||
yield str(list(map(ord, chrs))).translate(string.maketrans("[]", "{}"))
|
||||
|
||||
"{%s}" % ",".join(_())
|
||||
*/
|
||||
std::wstring::value_type IfcUtil::convert_codepage(int codepage, int c) {
|
||||
if (codepage < 1 || codepage > 16 || codepage == 12) {
|
||||
throw IfcParse::IfcException("Invalid codepage");
|
||||
}
|
||||
if (c < 0 || c > 255) {
|
||||
throw IfcParse::IfcException("Invalid character ordinal");
|
||||
}
|
||||
static std::array<std::array<wchar_t, 256>, 16> codepage_data = { {
|
||||
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255}},
|
||||
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 260, 728, 321, 164, 317, 346, 167, 168, 352, 350, 356, 377, 173, 381, 379, 176, 261, 731, 322, 180, 318, 347, 711, 184, 353, 351, 357, 378, 733, 382, 380, 340, 193, 194, 258, 196, 313, 262, 199, 268, 201, 280, 203, 282, 205, 206, 270, 272, 323, 327, 211, 212, 336, 214, 215, 344, 366, 218, 368, 220, 221, 354, 223, 341, 225, 226, 259, 228, 314, 263, 231, 269, 233, 281, 235, 283, 237, 238, 271, 273, 324, 328, 243, 244, 337, 246, 247, 345, 367, 250, 369, 252, 253, 355, 729}},
|
||||
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 294, 728, 163, 164, 0, 292, 167, 168, 304, 350, 286, 308, 173, 0, 379, 176, 295, 178, 179, 180, 181, 293, 183, 184, 305, 351, 287, 309, 189, 0, 380, 192, 193, 194, 0, 196, 266, 264, 199, 200, 201, 202, 203, 204, 205, 206, 207, 0, 209, 210, 211, 212, 288, 214, 215, 284, 217, 218, 219, 220, 364, 348, 223, 224, 225, 226, 0, 228, 267, 265, 231, 232, 233, 234, 235, 236, 237, 238, 239, 0, 241, 242, 243, 244, 289, 246, 247, 285, 249, 250, 251, 252, 365, 349, 729}},
|
||||
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 260, 312, 342, 164, 296, 315, 167, 168, 352, 274, 290, 358, 173, 381, 175, 176, 261, 731, 343, 180, 297, 316, 711, 184, 353, 275, 291, 359, 330, 382, 331, 256, 193, 194, 195, 196, 197, 198, 302, 268, 201, 280, 203, 278, 205, 206, 298, 272, 325, 332, 310, 212, 213, 214, 215, 216, 370, 218, 219, 220, 360, 362, 223, 257, 225, 226, 227, 228, 229, 230, 303, 269, 233, 281, 235, 279, 237, 238, 299, 273, 326, 333, 311, 244, 245, 246, 247, 248, 371, 250, 251, 252, 361, 363, 729}},
|
||||
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 173, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 8470, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 167, 1118, 1119}},
|
||||
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 0, 1548, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1563, 0, 0, 0, 1567, 0, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 0, 0, 0, 0, 0, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 8216, 8217, 163, 8364, 8367, 166, 167, 168, 169, 890, 171, 172, 173, 0, 8213, 176, 177, 178, 179, 900, 901, 902, 183, 904, 905, 906, 187, 908, 189, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 0, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 0}},
|
||||
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 0, 162, 163, 164, 165, 166, 167, 168, 169, 215, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 247, 187, 188, 189, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8215, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 0, 0, 8206, 8207, 0}},
|
||||
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 286, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 304, 350, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 287, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 305, 351, 255}},
|
||||
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 260, 274, 290, 298, 296, 310, 167, 315, 272, 352, 358, 381, 173, 362, 330, 176, 261, 275, 291, 299, 297, 311, 183, 316, 273, 353, 359, 382, 8213, 363, 331, 256, 193, 194, 195, 196, 197, 198, 302, 268, 201, 280, 203, 278, 205, 206, 207, 208, 325, 332, 211, 212, 213, 214, 360, 216, 370, 218, 219, 220, 221, 222, 223, 257, 225, 226, 227, 228, 229, 230, 303, 269, 233, 281, 235, 279, 237, 238, 239, 240, 326, 333, 243, 244, 245, 246, 361, 248, 371, 250, 251, 252, 253, 254, 312}},
|
||||
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 3585, 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593, 3594, 3595, 3596, 3597, 3598, 3599, 3600, 3601, 3602, 3603, 3604, 3605, 3606, 3607, 3608, 3609, 3610, 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, 0, 0, 0, 0, 3647, 3648, 3649, 3650, 3651, 3652, 3653, 3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, 0, 0, 0, 0}},
|
||||
{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 8221, 162, 163, 164, 8222, 166, 167, 216, 169, 342, 171, 172, 173, 174, 198, 176, 177, 178, 179, 8220, 181, 182, 183, 248, 185, 343, 187, 188, 189, 190, 230, 260, 302, 256, 262, 196, 197, 280, 274, 268, 201, 377, 278, 290, 310, 298, 315, 352, 323, 325, 211, 332, 213, 214, 215, 370, 321, 346, 362, 220, 379, 381, 223, 261, 303, 257, 263, 228, 229, 281, 275, 269, 233, 378, 279, 291, 311, 299, 316, 353, 324, 326, 243, 333, 245, 246, 247, 371, 322, 347, 363, 252, 380, 382, 8217}},
|
||||
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 7682, 7683, 163, 266, 267, 7690, 167, 7808, 169, 7810, 7691, 7922, 173, 174, 376, 7710, 7711, 288, 289, 7744, 7745, 182, 7766, 7809, 7767, 7811, 7776, 7923, 7812, 7813, 7777, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 372, 209, 210, 211, 212, 213, 214, 7786, 216, 217, 218, 219, 220, 221, 374, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 373, 241, 242, 243, 244, 245, 246, 7787, 248, 249, 250, 251, 252, 253, 375, 255}},
|
||||
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 8364, 165, 352, 167, 353, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 381, 181, 182, 183, 382, 185, 186, 187, 338, 339, 376, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255}},
|
||||
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 260, 261, 321, 8364, 8222, 352, 167, 353, 169, 536, 171, 377, 173, 378, 379, 176, 177, 268, 322, 381, 8221, 182, 183, 382, 269, 537, 187, 338, 339, 376, 380, 192, 193, 194, 258, 196, 262, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 272, 323, 210, 211, 212, 336, 214, 346, 368, 217, 218, 219, 220, 280, 538, 223, 224, 225, 226, 259, 228, 263, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 273, 324, 242, 243, 244, 337, 246, 347, 369, 249, 250, 251, 252, 281, 539, 255}}
|
||||
}};
|
||||
auto r = codepage_data[codepage - 1][c];
|
||||
if (r == 0) {
|
||||
throw IfcParse::IfcException("Character not defined");
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
std::string IfcUtil::convert_utf8(const std::wstring& s) {
|
||||
return std::wstring_convert<std::codecvt_utf8<std::wstring::value_type>>().to_bytes(s);
|
||||
}
|
||||
|
||||
std::wstring IfcUtil::convert_utf8(const std::string& s) {
|
||||
return std::wstring_convert<std::codecvt_utf8<std::wstring::value_type>>().from_bytes(s);
|
||||
}
|
||||
@@ -29,43 +29,27 @@
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef HAVE_ICU
|
||||
#include "unicode/ucnv.h"
|
||||
#include "unicode/unistr.h"
|
||||
#else
|
||||
typedef unsigned int UChar32;
|
||||
#endif
|
||||
#include <codecvt>
|
||||
|
||||
#include "../ifcparse/IfcSpfStream.h"
|
||||
|
||||
namespace IfcUtil {
|
||||
std::wstring::value_type convert_codepage(int codepage, int c);
|
||||
std::string convert_utf8(const std::wstring& s);
|
||||
std::wstring convert_utf8(const std::string& s);
|
||||
}
|
||||
|
||||
namespace IfcParse {
|
||||
|
||||
class IFC_PARSE_API IfcCharacterDecoder {
|
||||
private:
|
||||
IfcParse::IfcSpfStream* file;
|
||||
#ifdef HAVE_ICU
|
||||
static UConverter* destination;
|
||||
static UConverter* converter;
|
||||
static UConverter* compatibility_converter;
|
||||
static int previous_codepage;
|
||||
static UErrorCode status;
|
||||
#endif
|
||||
void addChar(std::stringstream& s,const UChar32& ch);
|
||||
std::wstring builder_;
|
||||
int codepage_;
|
||||
public:
|
||||
#ifdef HAVE_ICU
|
||||
enum ConversionMode {DEFAULT,UTF8,LATIN,JSON,PYTHON};
|
||||
enum ConversionMode {SUBSTITUTE, UTF8, ESCAPE};
|
||||
static ConversionMode mode;
|
||||
|
||||
// Many BIM software (eg. Revit, ArchiCAD, ...) has wrong behavior to encode characters.
|
||||
// It just translate to extended string in system default code page, not unicode.
|
||||
// If you want to process these strings, set true.
|
||||
static bool compatibility_mode;
|
||||
static std::string compatibility_charset;
|
||||
|
||||
#else
|
||||
static char substitution_character;
|
||||
#endif
|
||||
IfcCharacterDecoder(IfcParse::IfcSpfStream* file);
|
||||
~IfcCharacterDecoder();
|
||||
void dryRun();
|
||||
@@ -78,14 +62,9 @@ namespace IfcWrite {
|
||||
|
||||
class IFC_PARSE_API IfcCharacterEncoder {
|
||||
private:
|
||||
std::string str;
|
||||
#ifdef HAVE_ICU
|
||||
static UErrorCode status;
|
||||
static UConverter* converter;
|
||||
#endif
|
||||
std::wstring str;
|
||||
public:
|
||||
IfcCharacterEncoder(const std::string& input);
|
||||
~IfcCharacterEncoder();
|
||||
operator std::string();
|
||||
};
|
||||
|
||||
|
||||
@@ -56,14 +56,12 @@ SET_SOURCE_FILES_PROPERTIES(IfcPython.i PROPERTIES CPLUSPLUS ON)
|
||||
SWIG_ADD_MODULE(ifcopenshell_wrapper python IfcPython.i)
|
||||
if("$ENV{LDFLAGS}" MATCHES ".undefined.suppress")
|
||||
# On osx there is some state in the python dylib. With `-Wl,undefined,suppress` we can ignore the missing symbols at compile time.
|
||||
SWIG_LINK_LIBRARIES(ifcopenshell_wrapper ${IFCOPENSHELL_LIBRARIES} ${OPENCASCADE_LIBRARIES}
|
||||
${ICU_LIBRARIES} ${Boost_LIBRARIES})
|
||||
SWIG_LINK_LIBRARIES(ifcopenshell_wrapper ${IFCOPENSHELL_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES})
|
||||
else()
|
||||
SWIG_LINK_LIBRARIES(ifcopenshell_wrapper ${IFCOPENSHELL_LIBRARIES} ${PYTHON_LIBRARIES} ${OPENCASCADE_LIBRARIES}
|
||||
${ICU_LIBRARIES} ${Boost_LIBRARIES})
|
||||
SWIG_LINK_LIBRARIES(ifcopenshell_wrapper ${IFCOPENSHELL_LIBRARIES} ${PYTHON_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES})
|
||||
endif()
|
||||
if ((NOT WIN32) AND BUILD_SHARED_LIBS)
|
||||
SET_INSTALL_RPATHS(${SWIG_MODULE_ifcopenshell_wrapper_REAL_NAME} "${IFCDIRS};${OCC_LIBRARY_DIR};${ICU_LIBRARY_DIR}")
|
||||
SET_INSTALL_RPATHS(${SWIG_MODULE_ifcopenshell_wrapper_REAL_NAME} "${IFCDIRS};${OCC_LIBRARY_DIR}")
|
||||
endif()
|
||||
|
||||
# Try to find the Python interpreter to get the site-packages
|
||||
|
||||
@@ -0,0 +1,327 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifdef WITH_GLTF
|
||||
|
||||
#include "GltfSerializer.h"
|
||||
|
||||
#include "../ifcparse/utils.h"
|
||||
|
||||
#include <iterator>
|
||||
|
||||
static const uint32_t GLTF = 0x46546C67U;
|
||||
static const uint32_t JSON = 0x4E4F534A;
|
||||
static const uint32_t BIN = 0x004E4942;
|
||||
|
||||
static const uint32_t CT_BYTE = 5120;
|
||||
static const uint32_t CT_UNSIGNED_BYTE = 5121;
|
||||
static const uint32_t CT_SHORT = 5122;
|
||||
static const uint32_t CT_UNSIGNED_SHORT = 5123;
|
||||
static const uint32_t CT_UNSIGNED_INT = 5125;
|
||||
static const uint32_t CT_FLOAT = 5126;
|
||||
|
||||
static const uint32_t PRIM_POINTS = 0;
|
||||
static const uint32_t PRIM_LINES = 1;
|
||||
static const uint32_t PRIM_LINE_LOOP = 2;
|
||||
static const uint32_t PRIM_LINE_STRIP = 3;
|
||||
static const uint32_t PRIM_TRIANGLES = 4;
|
||||
static const uint32_t PRIM_TRIANGLE_STRIP = 5;
|
||||
static const uint32_t PRIM_TRIANGLE_FAN = 6;
|
||||
|
||||
GltfSerializer::GltfSerializer(const std::string& filename, const SerializerSettings& settings)
|
||||
: GeometrySerializer(settings)
|
||||
, filename_(filename)
|
||||
, tmp_filename1_(filename + ".indices.tmp")
|
||||
, tmp_filename2_(filename + ".vertices.tmp")
|
||||
, fstream_(IfcUtil::path::from_utf8(filename).c_str(), std::ios_base::binary)
|
||||
, tmp_fstream1_(IfcUtil::path::from_utf8(tmp_filename1_).c_str(), std::ios_base::binary)
|
||||
, tmp_fstream2_(IfcUtil::path::from_utf8(tmp_filename2_).c_str(), std::ios_base::binary)
|
||||
{}
|
||||
|
||||
bool GltfSerializer::ready() {
|
||||
return fstream_.is_open() && tmp_fstream1_.is_open() && tmp_fstream2_.is_open();
|
||||
}
|
||||
|
||||
void GltfSerializer::writeHeader() {
|
||||
json_["asset"]["generator"] = "IfcOpenShell IfcConvert " IFCOPENSHELL_VERSION;
|
||||
json_["asset"]["version"] = "2.0";
|
||||
json_["scene"] = 0;
|
||||
|
||||
node_array_ = json::array();
|
||||
json_["accessors"] = json::array();
|
||||
json_["scenes"] = json::array();
|
||||
json_["nodes"] = json::array();
|
||||
json_["meshes"] = json::array();
|
||||
json_["materials"] = json::array();
|
||||
}
|
||||
|
||||
int GltfSerializer::writeMaterial(const IfcGeom::Material& style) {
|
||||
auto it = materials_.find(style.name());
|
||||
if (it != materials_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
int idx = json_["materials"].size();
|
||||
materials_[style.name()] = idx;
|
||||
|
||||
std::array<double, 4> base;
|
||||
base.fill(1.0);
|
||||
if (style.hasDiffuse()) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
base[i] = style.diffuse()[i];
|
||||
}
|
||||
}
|
||||
if (style.hasTransparency()) {
|
||||
base[3] = 1. - style.transparency();
|
||||
}
|
||||
|
||||
json_["materials"].push_back({ {"pbrMetallicRoughness", {{"baseColorFactor", base}, {"metallicFactor", 0}}} });
|
||||
|
||||
if (style.hasTransparency() && style.transparency() > 1.e-9) {
|
||||
json_["materials"].back()["alphaMode"] = "BLEND";
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
struct stride_name { static const char* const value; };
|
||||
template <>
|
||||
const char* const stride_name<1U>::value = "SCALAR";
|
||||
template <>
|
||||
const char* const stride_name<3U>::value = "VEC3";
|
||||
|
||||
template <typename T>
|
||||
struct component_type { static const uint32_t value; };
|
||||
template <>
|
||||
const uint32_t component_type<int>::value = CT_UNSIGNED_INT;
|
||||
template <>
|
||||
const uint32_t component_type<float>::value = CT_FLOAT;
|
||||
|
||||
template <size_t N, typename It>
|
||||
size_t write_accessor(json& j, std::ofstream& ofs, It begin, It end) {
|
||||
auto num = std::distance(begin, end) / N;
|
||||
|
||||
json accessor = json::object();
|
||||
|
||||
accessor["bufferView"] = N == 1 ? 0 : 1;
|
||||
accessor["byteOffset"] = (size_t)ofs.tellp();
|
||||
accessor["componentType"] = component_type<typename It::value_type>::value;
|
||||
accessor["count"] = num;
|
||||
|
||||
std::array<typename It::value_type, N> min, max;
|
||||
min.fill(std::numeric_limits<typename It::value_type>::max());
|
||||
max.fill(std::numeric_limits<typename It::value_type>::min());
|
||||
for (auto it = begin; it != end; it += N) {
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
const float& v = *(it + i);
|
||||
if (v < min[i]) {
|
||||
min[i] = v;
|
||||
}
|
||||
if (v > max[i]) {
|
||||
max[i] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
accessor["min"] = min;
|
||||
accessor["max"] = max;
|
||||
accessor["type"] = stride_name<N>::value;
|
||||
|
||||
ofs.write((const char*)&*begin, sizeof(typename It::value_type) * num * N);
|
||||
|
||||
j["accessors"].push_back(accessor);
|
||||
|
||||
return j["accessors"].size() - 1;
|
||||
}
|
||||
|
||||
void GltfSerializer::write(const IfcGeom::TriangulationElement<real_t>* o) {
|
||||
node_array_.push_back(json_["nodes"].size());
|
||||
|
||||
const std::vector<double>& m = o->transformation().matrix().data();
|
||||
// nb: note that this contains the Y-UP transform as well.
|
||||
const std::array<double, 16> matrix_flat = {
|
||||
m[0], m[ 2], m[ 1], 0,
|
||||
m[3], m[ 5], m[ 4], 0,
|
||||
m[6], m[ 8], m[ 7], 0,
|
||||
m[9], m[11], m[10], 1
|
||||
};
|
||||
static const std::array<double, 16> identity_matrix = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
|
||||
|
||||
json node;
|
||||
if (matrix_flat != identity_matrix) {
|
||||
// glTF validator complains about identity matrices
|
||||
node["matrix"] = matrix_flat;
|
||||
}
|
||||
|
||||
int current_mesh_index;
|
||||
|
||||
// See if this mesh has already been processed
|
||||
auto it = meshes_.find(o->geometry().id());
|
||||
if (it == meshes_.end()) {
|
||||
|
||||
auto mid1 = o->geometry().material_ids().begin();
|
||||
auto mid0 = mid1;
|
||||
auto fid0 = o->geometry().faces().begin();
|
||||
|
||||
json mesh;
|
||||
mesh["name"] = o->geometry().id();
|
||||
|
||||
while (true) {
|
||||
// In glTF we need to decompose a mesh into several primitives
|
||||
// with a constant material. In the triangulations coming from
|
||||
// IfcOpenShell the materials are encoded in an additional set
|
||||
// of indices. Therefore we loop over the material indices to
|
||||
// find equal ranges of materials. Triangle indices then need
|
||||
// to be updated to reference the vertices only for the current
|
||||
// material.
|
||||
mid1++;
|
||||
|
||||
if ((mid1 == o->geometry().material_ids().end()) || (*mid1 != *mid0)) {
|
||||
auto n = std::distance(mid0, mid1);
|
||||
auto fid1 = fid0 + n * 3;
|
||||
|
||||
auto idx_range = std::minmax_element(fid0, fid1);
|
||||
const auto& idx_begin = *idx_range.first;
|
||||
const auto& idx_end = *idx_range.second + 1;
|
||||
|
||||
std::vector<int> idx_transformed;
|
||||
idx_transformed.reserve((n * 3));
|
||||
std::transform(fid0, fid1, std::back_inserter(idx_transformed), [idx_begin](int i) {
|
||||
return i - idx_begin;
|
||||
});
|
||||
|
||||
json primitive = json::object();
|
||||
|
||||
primitive["indices"] = write_accessor<1U>(json_, tmp_fstream1_, idx_transformed.begin(), idx_transformed.end());
|
||||
|
||||
auto vbegin = o->geometry().verts().begin();
|
||||
std::vector<float> vf(vbegin + idx_begin * 3, vbegin + idx_end * 3);
|
||||
primitive["attributes"]["POSITION"] = write_accessor<3U>(json_, tmp_fstream2_, vf.begin(), vf.end());
|
||||
|
||||
auto nbegin = o->geometry().normals().begin();
|
||||
std::vector<float> nf(nbegin + idx_begin * 3, nbegin + idx_end * 3);
|
||||
primitive["attributes"]["NORMAL"] = write_accessor<3U>(json_, tmp_fstream2_, nf.begin(), nf.end());
|
||||
|
||||
primitive["material"] = writeMaterial(o->geometry().materials()[*mid0]);
|
||||
primitive["mode"] = PRIM_TRIANGLES;
|
||||
|
||||
mesh["primitives"].push_back(primitive);
|
||||
|
||||
if (mid1 == o->geometry().material_ids().end()) {
|
||||
break;
|
||||
}
|
||||
|
||||
mid0 = mid1;
|
||||
fid0 = fid1;
|
||||
}
|
||||
}
|
||||
|
||||
json_["meshes"].push_back(mesh);
|
||||
|
||||
meshes_[o->geometry().id()] = current_mesh_index = json_["meshes"].size() - 1;
|
||||
} else {
|
||||
current_mesh_index = it->second;
|
||||
}
|
||||
|
||||
node["mesh"] = current_mesh_index;
|
||||
json_["nodes"].push_back(node);
|
||||
}
|
||||
|
||||
template <uint32_t>
|
||||
struct padding_char { static const char value; };
|
||||
template <>
|
||||
const char padding_char<JSON>::value = ' ';
|
||||
template <>
|
||||
const char padding_char<BIN>::value = '\x00';
|
||||
|
||||
uint32_t padding_for(uint32_t length) {
|
||||
return ((4 - (length % 4)) % 4);
|
||||
}
|
||||
|
||||
template <uint32_t iden>
|
||||
void write_padding(std::ostream& fs, uint32_t N) {
|
||||
uint32_t padding = padding_for(N);
|
||||
for (uint32_t i = 0; i < padding; ++i) {
|
||||
fs.put(padding_char<iden>::value);
|
||||
}
|
||||
}
|
||||
|
||||
template <uint32_t iden>
|
||||
void write_header(std::ostream& fs, uint32_t N) {
|
||||
uint32_t padding = padding_for(N);
|
||||
uint32_t header[] = { N + padding, iden };
|
||||
fs.write((const char*)header, sizeof(header));
|
||||
}
|
||||
|
||||
template <uint32_t iden, typename It>
|
||||
void write_block(std::ostream& fs, It begin, It end) {
|
||||
uint32_t N = std::distance(begin, end);
|
||||
write_header<iden>(fs, N);
|
||||
fs.write((const char*)&*begin, N);
|
||||
write_padding<iden>(fs, N);
|
||||
}
|
||||
|
||||
void GltfSerializer::finalize() {
|
||||
tmp_fstream1_.close();
|
||||
tmp_fstream2_.close();
|
||||
|
||||
std::vector<char> binary_contents;
|
||||
// nb: uint32_t is the max buffer size in glTF
|
||||
uint32_t indices_length, binary_length;
|
||||
{
|
||||
std::ifstream ifs(IfcUtil::path::from_utf8(tmp_filename1_).c_str(), std::ios::binary);
|
||||
ifs.ignore(std::numeric_limits<std::streamsize>::max());
|
||||
indices_length = ifs.gcount();
|
||||
}
|
||||
{
|
||||
std::ifstream ifs(IfcUtil::path::from_utf8(tmp_filename2_).c_str(), std::ios::binary);
|
||||
ifs.ignore(std::numeric_limits<std::streamsize>::max());
|
||||
binary_length = indices_length + ifs.gcount();
|
||||
}
|
||||
|
||||
json scene_0;
|
||||
scene_0["nodes"] = node_array_;
|
||||
json_["scenes"].push_back(scene_0);
|
||||
json_["bufferViews"].push_back({ {"buffer", 0}, { "byteLength", indices_length } });
|
||||
json_["bufferViews"].push_back({ {"buffer", 0}, {"byteStride", 12}, { "byteOffset", indices_length }, { "byteLength", binary_length - indices_length } });
|
||||
json_["buffers"].push_back({ {"byteLength", binary_length} });
|
||||
|
||||
std::string json_contents = json_.dump();
|
||||
uint32_t json_length = (uint32_t) json_contents.size();
|
||||
|
||||
uint32_t header[] = { GLTF, 2U, 12 + 8 + json_length + padding_for(json_length) + 8 + binary_length + padding_for(binary_length) };
|
||||
fstream_.write((const char*)header, sizeof(header));
|
||||
|
||||
write_block<JSON>(fstream_, json_contents.begin(), json_contents.end());
|
||||
write_header<BIN>(fstream_, binary_length);
|
||||
{
|
||||
std::ifstream ifs(IfcUtil::path::from_utf8(tmp_filename1_).c_str(), std::ios::binary);
|
||||
fstream_ << ifs.rdbuf();
|
||||
}
|
||||
{
|
||||
std::ifstream ifs(IfcUtil::path::from_utf8(tmp_filename2_).c_str(), std::ios::binary);
|
||||
fstream_ << ifs.rdbuf();
|
||||
}
|
||||
write_padding<BIN>(fstream_, binary_length);
|
||||
|
||||
IfcUtil::path::delete_file(tmp_filename1_);
|
||||
IfcUtil::path::delete_file(tmp_filename2_);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef GLTFSERIALIZER_H
|
||||
#define GLTFSERIALIZER_H
|
||||
|
||||
#ifdef WITH_GLTF
|
||||
|
||||
#include "../serializers/GeometrySerializer.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
using json = nlohmann::json;
|
||||
|
||||
#include <map>
|
||||
|
||||
class GltfSerializer : public GeometrySerializer {
|
||||
private:
|
||||
std::string filename_, tmp_filename1_, tmp_filename2_;
|
||||
std::ofstream fstream_, tmp_fstream1_, tmp_fstream2_;
|
||||
std::map<std::string, int> materials_, meshes_;
|
||||
json json_, node_array_;
|
||||
|
||||
int writeMaterial(const IfcGeom::Material& style);
|
||||
public:
|
||||
GltfSerializer(const std::string& filename, const SerializerSettings& settings);
|
||||
virtual ~GltfSerializer() {}
|
||||
bool ready();
|
||||
void writeHeader();
|
||||
void write(const IfcGeom::TriangulationElement<real_t>* o);
|
||||
void write(const IfcGeom::BRepElement<real_t>* /*o*/) {}
|
||||
void finalize();
|
||||
bool isTesselated() const { return true; }
|
||||
void setUnitNameAndMagnitude(const std::string& /*name*/, float /*magnitude*/) {}
|
||||
void setFile(IfcParse::IfcFile*) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user