Skip to content

Commit 3e80d36

Browse files
committed
Work on ifcxml parsere
1 parent 45be794 commit 3e80d36

7 files changed

Lines changed: 86 additions & 35 deletions

File tree

cmake/CMakeLists.txt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ project (IfcOpenShell)
2323

2424
OPTION(UNICODE_SUPPORT "Build IfcOpenShell with Unicode support (requires ICU)." ON)
2525
OPTION(COLLADA_SUPPORT "Build IfcConvert with COLLADA support (requires OpenCOLLADA)." ON)
26+
OPTION(IFCXML_SUPPORT "Build IfcParse with ifcXML support (requires libxml2)." ON)
2627
OPTION(ENABLE_BUILD_OPTIMIZATIONS "Enable certain compiler and linker optimizations on RelWithDebInfo and Release builds." OFF)
2728
OPTION(IFCCONVERT_DOUBLE_PRECISION "IfcConvert: Use double precision floating-point numbers." ON)
2829
OPTION(BUILD_IFCPYTHON "Build IfcPython." ON)
@@ -88,6 +89,8 @@ UNIFY_ENVVARS_AND_CACHE(ICU_INCLUDE_DIR)
8889
UNIFY_ENVVARS_AND_CACHE(ICU_LIBRARY_DIR)
8990
UNIFY_ENVVARS_AND_CACHE(OPENCOLLADA_INCLUDE_DIR)
9091
UNIFY_ENVVARS_AND_CACHE(OPENCOLLADA_LIBRARY_DIR)
92+
UNIFY_ENVVARS_AND_CACHE(LIBXML2_INCLUDE_DIR)
93+
UNIFY_ENVVARS_AND_CACHE(LIBXML2_LIBRARIES)
9194
UNIFY_ENVVARS_AND_CACHE(PCRE_LIBRARY_DIR)
9295
UNIFY_ENVVARS_AND_CACHE(PYTHON_EXECUTABLE)
9396
IF(WIN32)
@@ -136,6 +139,10 @@ if(USE_MMAP)
136139
add_definitions(-DUSE_MMAP)
137140
endif()
138141

142+
if (IFCXML_SUPPORT)
143+
add_definitions(-DWITH_IFCXML)
144+
endif()
145+
139146
FIND_PACKAGE(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
140147
MESSAGE(STATUS "Boost include files found in ${Boost_INCLUDE_DIRS}")
141148
MESSAGE(STATUS "Boost libraries found in ${Boost_LIBRARY_DIRS}")
@@ -437,7 +444,7 @@ if (IFCCONVERT_DOUBLE_PRECISION)
437444
endif()
438445

439446
INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES} ${OCC_INCLUDE_DIR} ${OPENCOLLADA_INCLUDE_DIRS}
440-
${ICU_INCLUDE_DIR} ${Boost_INCLUDE_DIRS}
447+
${ICU_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIR}
441448
)
442449

443450
function(files_for_ifc_version IFC_VERSION RESULT_NAME)
@@ -571,7 +578,7 @@ set(IFCPARSE_FILES ${IFCPARSE_CPP_FILES} ${IFCPARSE_H_FILES})
571578
add_library(IfcParse ${IFCPARSE_FILES})
572579
set_target_properties(IfcParse PROPERTIES COMPILE_FLAGS -DIFC_PARSE_EXPORTS)
573580

574-
TARGET_LINK_LIBRARIES(IfcParse ${Boost_LIBRARIES} ${BCRYPT_LIBRARIES})
581+
TARGET_LINK_LIBRARIES(IfcParse ${Boost_LIBRARIES} ${BCRYPT_LIBRARIES} ${LIBXML2_LIBRARIES})
575582

576583
IF(UNICODE_SUPPORT)
577584
TARGET_LINK_LIBRARIES(IfcParse ${ICU_LIBRARIES})

nix/build-all.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,8 @@ def PYTHON_VERSION_CONFS():
559559
"-DICU_INCLUDE_DIR=" "%s/install/icu-%s/include" % (DEPS_DIR, ICU_VERSION),
560560
"-DICU_LIBRARY_DIR=" "%s/install/icu-%s/lib" % (DEPS_DIR, ICU_VERSION),
561561
"-DPCRE_LIBRARY_DIR=" "%s/install/pcre-%s/lib" % (DEPS_DIR, PCRE_VERSION),
562+
"-DLIBXML2_INCLUDE_DIR=" "%s/install/libxml2-%s/include/libxml2" % (DEPS_DIR, LIBXML_VERSION),
563+
"-DLIBXML2_LIBRARIES=" "%s/install/libxml2-%s/lib/libxml2.a" % (DEPS_DIR, LIBXML_VERSION),
562564
"-DBUILD_IFCPYTHON=" "OFF",
563565
"-DUSE_MMAP=" "OFF",
564566
"-DCMAKE_INSTALL_PREFIX=" "%s/install/ifcopenshell" % (DEPS_DIR,)], cmake_dir=CMAKE_DIR, cwd=executables_dir)
@@ -596,6 +598,8 @@ def PYTHON_VERSION_CONFS():
596598
"-DOPENCOLLADA_LIBRARY_DIR=%s/install/OpenCOLLADA/lib/opencollada" % (DEPS_DIR,),
597599
"-DICU_INCLUDE_DIR=%s/install/icu-%s/include" % (DEPS_DIR, ICU_VERSION),
598600
"-DICU_LIBRARY_DIR=%s/install/icu-%s/lib" % (DEPS_DIR, ICU_VERSION),
601+
"-DLIBXML2_INCLUDE_DIR=%s/install/libxml2-%s/include/libxml2" % (DEPS_DIR, LIBXML_VERSION),
602+
"-DLIBXML2_LIBRARIES=%s/install/libxml2-%s/lib/libxml2.a" % (DEPS_DIR, LIBXML_VERSION),
599603
"-DPYTHON_LIBRARY=%s" % (PYTHON_LIBRARY,),
600604
"-DPYTHON_EXECUTABLE=%s" % (PYTHON_EXECUTABLE,),
601605
"-DPYTHON_INCLUDE_DIR=%s" % (PYTHON_INCLUDE,),

src/ifcconvert/IfcConvert.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,8 @@ void write_log(bool header) {
779779
}
780780
}
781781

782+
#include <boost/algorithm/string/predicate.hpp>
783+
782784
bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file, bool no_progress, bool mmap) {
783785

784786
// Prevent IfcFile::Init() prints by setting output to null temporarily
@@ -788,6 +790,12 @@ bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file,
788790
ifc_file = new IfcParse::IfcFile(filename, mmap);
789791
#else
790792
(void)mmap;
793+
794+
#ifdef WITH_IFCXML
795+
if (boost::ends_with(boost::to_lower_copy(filename), ".ifcxml")) {
796+
ifc_file = IfcParse::parse_ifcxml(filename);
797+
} else
798+
#endif
791799
ifc_file = new IfcParse::IfcFile(filename);
792800
if (!ifc_file->good()) {
793801
#endif

src/ifcparse/IfcFile.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class IFC_PARSE_API IfcFile {
8686

8787
void initialize_(IfcParse::IfcSpfStream* f);
8888

89+
void build_inverses_(IfcUtil::IfcBaseClass*);
8990
public:
9091
IfcParse::IfcSpfLexer* tokens;
9192
IfcParse::IfcSpfStream* stream;
@@ -191,6 +192,11 @@ class IFC_PARSE_API IfcFile {
191192
const IfcParse::schema_definition* schema() const { return schema_; }
192193

193194
std::pair<IfcUtil::IfcBaseClass*, double> getUnit(const std::string& unit_type);
195+
196+
bool parsing_complete() const { return parsing_complete_; }
197+
bool& parsing_complete() { return parsing_complete_; }
198+
199+
void build_inverses();
194200
};
195201

196202
template <typename Schema>
@@ -207,6 +213,10 @@ class IFC_PARSE_API IfcFileWithSchema : public IfcFile {
207213
}
208214
};
209215

216+
#ifdef WITH_IFCXML
217+
IFC_PARSE_API IfcFile* parse_ifcxml(const std::string& filename);
218+
#endif
219+
210220
}
211221

212222
#endif

src/ifcparse/IfcParse.cpp

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,13 +1016,18 @@ IfcEntityInstanceData::IfcEntityInstanceData(const IfcEntityInstanceData& e) {
10161016
}
10171017
}
10181018

1019+
static IfcParse::NullArgument static_null_attribute;
10191020

10201021
Argument* IfcEntityInstanceData::getArgument(unsigned int i) const {
10211022
if (attributes_ == 0) {
10221023
load();
10231024
}
10241025
if (i < getArgumentCount()) {
1025-
return attributes_[i];
1026+
if (attributes_[i] == nullptr) {
1027+
return &static_null_attribute;
1028+
} else {
1029+
return attributes_[i];
1030+
}
10261031
} else {
10271032
throw IfcParse::IfcException("Attribute index out of range");
10281033
}
@@ -1284,8 +1289,8 @@ IfcFile::IfcFile(IfcParse::IfcSpfStream* s) {
12841289
}
12851290

12861291
IfcFile::IfcFile(const IfcParse::schema_definition* schema)
1287-
: parsing_complete_(false)
1288-
, good_(false)
1292+
: parsing_complete_(true)
1293+
, good_(true)
12891294
, schema_(schema)
12901295
, ifcroot_type_(schema_->declaration_by_name("IfcRoot"))
12911296
, MaxId(0)
@@ -1521,18 +1526,20 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
15211526

15221527
// Obtain all forward references by a depth-first
15231528
// traversal and add them to the file.
1524-
try {
1525-
IfcEntityList::ptr entity_attributes = traverse(entity, 1);
1526-
for (IfcEntityList::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) {
1527-
if (*it != entity) {
1528-
entity_entity_map_t::iterator mit2 = entity_file_map.find(*it);
1529-
if (mit2 == entity_file_map.end()) {
1530-
entity_file_map.insert(entity_entity_map_t::value_type(*it, addEntity(*it)));
1529+
if (parsing_complete_) {
1530+
try {
1531+
IfcEntityList::ptr entity_attributes = traverse(entity, 1);
1532+
for (IfcEntityList::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) {
1533+
if (*it != entity) {
1534+
entity_entity_map_t::iterator mit2 = entity_file_map.find(*it);
1535+
if (mit2 == entity_file_map.end()) {
1536+
entity_file_map.insert(entity_entity_map_t::value_type(*it, addEntity(*it)));
1537+
}
15311538
}
15321539
}
1540+
} catch (...) {
1541+
Logger::Message(Logger::LOG_ERROR, "Failed to visit forward references of", entity);
15331542
}
1534-
} catch (...) {
1535-
Logger::Message(Logger::LOG_ERROR, "Failed to visit forward references of", entity);
15361543
}
15371544

15381545
// See whether the instance is already part of a file
@@ -1642,6 +1649,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
16421649
we->set_id(FreshId());
16431650
}
16441651

1652+
// @todo entity_file_map: use weak_ptr
16451653
entity_file_map.insert(entity_entity_map_t::value_type(entity, new_entity));
16461654
}
16471655

@@ -1709,27 +1717,8 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity) {
17091717
byid[new_id] = new_entity;
17101718
}
17111719

1712-
if (ty->as_entity()) {
1713-
// The mapping by reference is updated.
1714-
IfcEntityList::ptr entity_attributes(new IfcEntityList);
1715-
try {
1716-
entity_attributes = traverse(new_entity, 1);
1717-
} catch (const std::exception& e) {
1718-
Logger::Error(e);
1719-
}
1720-
1721-
for (IfcEntityList::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) {
1722-
IfcUtil::IfcBaseClass* entity_attribute = *it;
1723-
if (*it == new_entity) continue;
1724-
try {
1725-
if (entity_attribute->declaration().as_entity()) {
1726-
unsigned entity_attribute_id = entity_attribute->data().id();
1727-
byref[entity_attribute_id].push_back(new_entity->data().id());
1728-
}
1729-
} catch (const std::exception& e) {
1730-
Logger::Error(e);
1731-
}
1732-
}
1720+
if (parsing_complete_ && ty->as_entity()) {
1721+
build_inverses_(new_entity);
17331722
}
17341723

17351724
return new_entity;
@@ -2097,3 +2086,31 @@ std::pair<IfcUtil::IfcBaseClass*, double> IfcFile::getUnit(const std::string& un
20972086

20982087
return return_value;
20992088
}
2089+
2090+
void IfcParse::IfcFile::build_inverses_(IfcUtil::IfcBaseClass* inst) {
2091+
IfcEntityList::ptr entity_attributes(new IfcEntityList);
2092+
try {
2093+
entity_attributes = traverse(inst, 1);
2094+
} catch (const std::exception& e) {
2095+
Logger::Error(e);
2096+
}
2097+
2098+
for (IfcEntityList::it it = entity_attributes->begin(); it != entity_attributes->end(); ++it) {
2099+
IfcUtil::IfcBaseClass* entity_attribute = *it;
2100+
if (*it == inst) continue;
2101+
try {
2102+
if (entity_attribute->declaration().as_entity()) {
2103+
unsigned entity_attribute_id = entity_attribute->data().id();
2104+
byref[entity_attribute_id].push_back(inst->data().id());
2105+
}
2106+
} catch (const std::exception& e) {
2107+
Logger::Error(e);
2108+
}
2109+
}
2110+
}
2111+
2112+
void IfcParse::IfcFile::build_inverses() {
2113+
for (auto& pair : *this) {
2114+
build_inverses_(pair.second);
2115+
}
2116+
}

src/ifcparse/IfcParse.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ namespace IfcParse {
165165

166166
public:
167167
ArgumentList() : size_(0), list_(0) {}
168+
ArgumentList(size_t n) : size_(n), list_(new Argument*[size_]) {}
168169
~ArgumentList();
169170

170171
void read(IfcSpfLexer* t, std::vector<unsigned int>& ids);

win/run-cmake.bat

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ if not defined OCC_INCLUDE_DIR set OCC_INCLUDE_DIR=%INSTALL_DIR%\oce\include\oce
7070
if not defined OCC_LIBRARY_DIR set OCC_LIBRARY_DIR=%INSTALL_DIR%\oce\Win%ARCH_BITS%\lib
7171
set OPENCOLLADA_INCLUDE_DIR=%INSTALL_DIR%\OpenCOLLADA\include\opencollada
7272
set OPENCOLLADA_LIBRARY_DIR=%INSTALL_DIR%\OpenCOLLADA\lib\opencollada
73+
set LIBXML2_INCLUDE_DIR=%DEPS_DIR%\OpenCOLLADA\Externals\LibXML\include
74+
set LIBXML2_LIBRARIES=%INSTALL_DIR%\OpenCOLLADA\lib\opencollada\xml.lib
7375
if not defined PY_VER_MAJOR_MINOR set PY_VER_MAJOR_MINOR=34
7476
if not defined PYTHONHOME set PYTHONHOME=%INSTALL_DIR%\Python%PY_VER_MAJOR_MINOR%
7577
set PYTHON_INCLUDE_DIR=%PYTHONHOME%\include
@@ -93,6 +95,8 @@ echo OCC_INCLUDE_DIR = %OCC_INCLUDE_DIR%
9395
echo OCC_LIBRARY_DIR = %OCC_LIBRARY_DIR%
9496
echo OPENCOLLADA_INCLUDE_DIR = %OPENCOLLADA_INCLUDE_DIR%
9597
echo OPENCOLLADA_LIBRARY_DIR = %OPENCOLLADA_LIBRARY_DIR%
98+
echo LIBXML2_INCLUDE_DIR = %LIBXML2_INCLUDE_DIR%
99+
echo LIBXML2_LIBRARIES = %LIBXML2_LIBRARIES%
96100
echo PYTHONHOME = %PYTHONHOME%
97101
echo PYTHON_INCLUDE_DIR = %PYTHON_INCLUDE_DIR%
98102
echo PYTHON_LIBRARY = %PYTHON_LIBRARY%

0 commit comments

Comments
 (0)