diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 2b04eebd39..129f350419 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -396,6 +396,10 @@ IF(UNICODE_SUPPORT) TARGET_LINK_LIBRARIES(IfcParse ${ICU_LIBRARIES}) ENDIF() +if(HDF5_SUPPORT) + TARGET_LINK_LIBRARIES(IfcParse ${HDF5_LIBRARIES}) +endif() + # IfcGeom file(GLOB IFCGEOM_H_FILES ../src/ifcgeom/*.h) file(GLOB IFCGEOM_CPP_FILES ../src/ifcgeom/*.cpp) @@ -425,7 +429,7 @@ if("${libTKernelExt}" STREQUAL ".a") set(OPENCASCADE_LIBRARIES ${OPENCASCADE_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} rt dl) endif() -TARGET_LINK_LIBRARIES(IfcConvert IfcParse IfcGeom ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES} ${OPENCOLLADA_LIBRARIES} ${ICU_LIBRARIES} ${HDF5_LIBRARIES}) +TARGET_LINK_LIBRARIES(IfcConvert IfcParse IfcGeom ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES} ${OPENCOLLADA_LIBRARIES} ${ICU_LIBRARIES}) # IfcGeomServer file(GLOB CPP_FILES ../src/ifcgeomserver/*.cpp) @@ -443,6 +447,10 @@ IF(BUILD_EXAMPLES) ADD_SUBDIRECTORY(../src/examples examples) ENDIF() +IF(HDF5_SUPPORT) + ADD_SUBDIRECTORY(../src/hdf5_usecases hdf5_usecases) +ENDIF() + # CMake installation targets INSTALL(FILES ${IFCPARSE_H_FILES} DESTINATION include/ifcparse) INSTALL(FILES ${IFCGEOM_H_FILES} DESTINATION include/ifcgeom) diff --git a/src/hdf5_usecases/CMakeLists.txt b/src/hdf5_usecases/CMakeLists.txt new file mode 100644 index 0000000000..507ec68be5 --- /dev/null +++ b/src/hdf5_usecases/CMakeLists.txt @@ -0,0 +1,21 @@ +################################################################################ +# # +# 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 . # +# # +################################################################################ + +ADD_EXECUTABLE(hdf5_mount mount.cpp) +TARGET_LINK_LIBRARIES(hdf5_mount IfcParse) diff --git a/src/hdf5_usecases/mount.cpp b/src/hdf5_usecases/mount.cpp new file mode 100644 index 0000000000..6bdd51608c --- /dev/null +++ b/src/hdf5_usecases/mount.cpp @@ -0,0 +1,185 @@ +/******************************************************************************** + * * + * 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 . * + * * + ********************************************************************************/ + +#include "../../../src/ifcparse/IfcHdf5File.h" + +#include + +#pragma warning(disable:4100) + +class ifc_inst_cmp { +public: + + // For these we simply assume that only a single instance exists + bool operator()(IfcSchema::IfcSite* a, IfcSchema::IfcSite* b) { return false; } + bool operator()(IfcSchema::IfcProject* a, IfcSchema::IfcProject* b) { return false; } + bool operator()(IfcSchema::IfcBuilding* a, IfcSchema::IfcBuilding* b) { return false; } + bool operator()(IfcSchema::IfcPostalAddress* a, IfcSchema::IfcPostalAddress* b) { return false; } + bool operator()(IfcSchema::IfcUnitAssignment* a, IfcSchema::IfcUnitAssignment* b) { return false; } + + bool operator()(IfcSchema::IfcConversionBasedUnit* a, IfcSchema::IfcConversionBasedUnit* b) { + return a->Name() < b->Name(); + } + + bool operator()(IfcSchema::IfcDimensionalExponents* a, IfcSchema::IfcDimensionalExponents* b) { + // For every attribute (which are all integers) check equality + + unsigned num_attrs = a->data().getArgumentCount(); + for (unsigned i = 0; i < num_attrs; ++i) { + const int v1 = *a->data().getArgument(i); + const int v2 = *b->data().getArgument(i); + if (v1 != v2) { + return v1 < v2; + } + } + + return false; + } + + bool operator()(IfcSchema::IfcMeasureWithUnit* a, IfcSchema::IfcMeasureWithUnit* b) { + // Assume the value component is enough to differentiate + + double v1 = *a->ValueComponent()->data().getArgument(0); + double v2 = *b->ValueComponent()->data().getArgument(0); + return v1 < v2; + } + + bool operator()(IfcSchema::IfcGeometricRepresentationSubContext* a, IfcSchema::IfcGeometricRepresentationSubContext* b) { + return a->ContextType() < b->ContextType(); + } + + bool operator()(IfcSchema::IfcGeometricRepresentationContext* a, IfcSchema::IfcGeometricRepresentationContext* b) { + return a->ContextType() < b->ContextType(); + } + + bool operator()(IfcSchema::IfcSIUnit* a, IfcSchema::IfcSIUnit* b) { + // Assume same units accross files + + return a->UnitType() < b->UnitType(); + } + + bool operator()(IfcSchema::IfcBuildingStorey* a, IfcSchema::IfcBuildingStorey* b) { + return a->Name() < b->Name(); + } + + bool operator()(IfcUtil::IfcBaseClass* a, IfcUtil::IfcBaseClass* b) { + if (a->declaration().type() != b->declaration().type()) { + throw std::runtime_error("Types not matching"); + } + + std::cerr << IfcSchema::Type::ToString(a->declaration().type()) << std::endl; + + if (a->declaration().type() == IfcSchema::Type::IfcSite) { return (*this)((IfcSchema::IfcSite*) a, (IfcSchema::IfcSite*) b); } + if (a->declaration().type() == IfcSchema::Type::IfcConversionBasedUnit) { return (*this)((IfcSchema::IfcConversionBasedUnit*) a, (IfcSchema::IfcConversionBasedUnit*) b); } + if (a->declaration().type() == IfcSchema::Type::IfcDimensionalExponents) { return (*this)((IfcSchema::IfcDimensionalExponents*) a, (IfcSchema::IfcDimensionalExponents*) b); } + if (a->declaration().type() == IfcSchema::Type::IfcMeasureWithUnit) { return (*this)((IfcSchema::IfcMeasureWithUnit*) a, (IfcSchema::IfcMeasureWithUnit*) b); } + if (a->declaration().type() == IfcSchema::Type::IfcProject) { return (*this)((IfcSchema::IfcProject*) a, (IfcSchema::IfcProject*) b); } + if (a->declaration().type() == IfcSchema::Type::IfcBuilding) { return (*this)((IfcSchema::IfcBuilding*) a, (IfcSchema::IfcBuilding*) b); } + if (a->declaration().type() == IfcSchema::Type::IfcPostalAddress) { return (*this)((IfcSchema::IfcPostalAddress*) a, (IfcSchema::IfcPostalAddress*) b); } + if (a->declaration().type() == IfcSchema::Type::IfcUnitAssignment) { return (*this)((IfcSchema::IfcUnitAssignment*) a, (IfcSchema::IfcUnitAssignment*) b); } + if (a->declaration().type() == IfcSchema::Type::IfcGeometricRepresentationSubContext) { return (*this)((IfcSchema::IfcGeometricRepresentationSubContext*) a, (IfcSchema::IfcGeometricRepresentationSubContext*) b); } + if (a->declaration().type() == IfcSchema::Type::IfcGeometricRepresentationContext) { return (*this)((IfcSchema::IfcGeometricRepresentationContext*) a, (IfcSchema::IfcGeometricRepresentationContext*) b); } + if (a->declaration().type() == IfcSchema::Type::IfcSIUnit) { return (*this)((IfcSchema::IfcSIUnit*) a, (IfcSchema::IfcSIUnit*) b); } + if (a->declaration().type() == IfcSchema::Type::IfcBuildingStorey) { return (*this)((IfcSchema::IfcBuildingStorey*) a, (IfcSchema::IfcBuildingStorey*) b); } + + throw std::runtime_error("Unexpected type"); + } +}; + +int main(int argc, char** argv) { + + std::set shared { + IfcSchema::Type::IfcSite, + IfcSchema::Type::IfcConversionBasedUnit, + IfcSchema::Type::IfcDimensionalExponents, + IfcSchema::Type::IfcMeasureWithUnit, + IfcSchema::Type::IfcProject, + IfcSchema::Type::IfcBuilding, + IfcSchema::Type::IfcPostalAddress, + IfcSchema::Type::IfcUnitAssignment, + IfcSchema::Type::IfcGeometricRepresentationSubContext, + IfcSchema::Type::IfcGeometricRepresentationContext, + IfcSchema::Type::IfcSIUnit, + IfcSchema::Type::IfcBuildingStorey + }; + + std::vector files; + + for (int i = 1; i < argc; ++i) { + files.push_back(new IfcParse::IfcFile()); + files.back()->Init(argv[i]); + } + + std::set shared_instances; + + for (auto& ty : shared) { + std::cout << IfcSchema::Type::ToString(ty) << std::endl; + + for (auto& file : files) { + IfcEntityList::ptr insts = file->entitiesByType(ty); + std::vector no_subtypes; + std::copy_if(insts->begin(), insts->end(), std::back_inserter(no_subtypes), [ty](IfcUtil::IfcBaseClass* inst) { + return inst->declaration().type() == ty; + }); + + std::set insts_unique(no_subtypes.begin(), no_subtypes.end()); + + if (insts_unique.size() != no_subtypes.size()) { + throw std::runtime_error("Non-unique instances encountered within file"); + } + + shared_instances.insert(insts_unique.begin(), insts_unique.end()); + } + } + + std::set shared_instances_and_refs; + + for (auto& inst : shared_instances) { + IfcEntityList::ptr insts = inst->data().file->traverse(inst); + + // Filter out simple types + std::vector insts_without_types; + std::copy_if(insts->begin(), insts->end(), std::back_inserter(insts_without_types), [](IfcUtil::IfcBaseClass* inst) { + return inst->declaration().as_entity() != nullptr; + }); + + shared_instances_and_refs.insert(insts_without_types.begin(), insts_without_types.end()); + } + + for (auto& i : shared_instances_and_refs) { + if (shared_instances.find(i) == shared_instances.end()) { + std::cerr << i->data().toString() << std::endl; + } + } + + IfcParse::Hdf5Settings settings; + settings.profile() = IfcParse::Hdf5Settings::standard_referenced; + + H5::H5File file("merged.hdf", H5F_ACC_TRUNC); + H5::Group group1 = file.createGroup("shared"); + + IfcParse::IfcHdf5File ifc_hdf5(file, get_schema(), settings); + IfcParse::IfcSpfHeader header; + header.set_default(); + + IfcParse::instance_enumerator shared_insts_enum(&header, shared_instances_and_refs.begin(), shared_instances_and_refs.end()); + + ifc_hdf5.write_schema(); + ifc_hdf5.write_population(group1, shared_insts_enum); +}