mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 09:48:32 +00:00
Backspace everything regarding HDF5
This commit is contained in:
@@ -31,7 +31,7 @@ jobs:
|
||||
sudo apt-get install --no-install-recommends \
|
||||
git cmake gcc g++ libboost-all-dev python3-all-dev swig libpcre3-dev libxml2-dev \
|
||||
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
|
||||
libhdf5-dev libcgal-dev nlohmann-json3-dev libeigen3-dev
|
||||
libcgal-dev nlohmann-json3-dev libeigen3-dev
|
||||
|
||||
-
|
||||
name: ccache
|
||||
@@ -60,7 +60,6 @@ jobs:
|
||||
-DMPFR_INCLUDE_DIR=/usr/include \
|
||||
-DGMP_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DMPFR_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DHDF5_INCLUDE_DIR=/usr/include/hdf5/serial \
|
||||
-DGLTF_SUPPORT=On \
|
||||
-DJSON_INCLUDE_DIR=/usr/include \
|
||||
-DEIGEN_DIR=/usr/include/eigen3 \
|
||||
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
libtbb-dev nlohmann-json3-dev \
|
||||
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
|
||||
${OCCT_CMAKE_DEPS} \
|
||||
libhdf5-dev libcgal-dev libeigen3-dev
|
||||
libcgal-dev libeigen3-dev
|
||||
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2.22
|
||||
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
swig libpcre3-dev libxml2-dev \
|
||||
libtbb-dev nlohmann-json3-dev \
|
||||
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
|
||||
libhdf5-dev libcgal-dev opencollada-dev
|
||||
libcgal-dev opencollada-dev
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
@@ -64,7 +64,6 @@ jobs:
|
||||
-DMPFR_INCLUDE_DIR=/usr/include \
|
||||
-DGMP_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DMPFR_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DHDF5_INCLUDE_DIR=/usr/include/hdf5/serial \
|
||||
-DOPENCOLLADA_INCLUDE_DIR=/usr/include/opencollada \
|
||||
-DOPENCOLLADA_LIBRARY_DIR=/usr/lib/opencollada/ \
|
||||
../cmake
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ RUN echo "deb http://archive.ubuntu.com/ubuntu focal-proposed main restricted" |
|
||||
libboost-all-dev \
|
||||
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev \
|
||||
libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
|
||||
libhdf5-serial-dev python3-pytest ; \
|
||||
python3-pytest ; \
|
||||
rm -rf /var/lib/apt/lists/* ;
|
||||
|
||||
COPY . /home/IfcOpenShell/
|
||||
|
||||
@@ -16,7 +16,6 @@ cmake ../cmake \
|
||||
-DWITH_OPENCASCADE=ON \
|
||||
-DWITH_CGAL=ON \
|
||||
-DWITH_MANIFOLD=ON \
|
||||
-DHDF5_SUPPORT=OFF \
|
||||
-DGLTF_SUPPORT=ON \
|
||||
-DIFCXML_SUPPORT=OFF \
|
||||
-DCOLLADA_SUPPORT=OFF \
|
||||
|
||||
@@ -91,7 +91,6 @@ option(WITH_CGAL "Enable geometry interpretation using CGAL" ON)
|
||||
option(WITH_MANIFOLD "Enable geometry interpretation using Manifold" OFF)
|
||||
option(COLLADA_SUPPORT "Build IfcConvert with COLLADA support (requires OpenCOLLADA)." ON)
|
||||
option(GLTF_SUPPORT "Build IfcConvert with glTF support (requires json.hpp)." OFF)
|
||||
option(HDF5_SUPPORT "Enable HDF5 support (requires HDF5, zlib)" ON)
|
||||
option(WITH_PROJ "Enable output of Earth-Centered Earth-Fixed glTF output using the PROJ library" OFF)
|
||||
option(USD_SUPPORT "Build IfcConvert with USD support (requires pixar's USD library)." OFF)
|
||||
option(WITH_ROCKSDB "Support a RocksDB key-value store as a file backend in IfcOpenShell" OFF)
|
||||
@@ -128,7 +127,6 @@ if(MINIMAL_BUILD)
|
||||
set(WITH_CGAL OFF)
|
||||
set(COLLADA_SUPPORT OFF)
|
||||
set(GLTF_SUPPORT OFF)
|
||||
set(HDF5_SUPPORT OFF)
|
||||
set(USD_SUPPORT OFF)
|
||||
endif()
|
||||
|
||||
@@ -325,10 +323,6 @@ if(COLLADA_SUPPORT)
|
||||
find_package(OpenCOLLADA REQUIRED)
|
||||
endif()
|
||||
|
||||
if(HDF5_SUPPORT)
|
||||
find_package(HDF5 REQUIRED COMPONENTS C CXX)
|
||||
endif(HDF5_SUPPORT)
|
||||
|
||||
if(ENABLE_BUILD_OPTIMIZATIONS)
|
||||
if(MSVC)
|
||||
# NOTE: RelWithDebInfo and Release use O2 (= /Ox /Gl /Gy/ = Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy) by default,
|
||||
@@ -440,7 +434,7 @@ else()
|
||||
endif(MSVC)
|
||||
|
||||
include_directories(${INCLUDE_DIRECTORIES}
|
||||
${Boost_INCLUDE_DIRS} ${HDF5_INCLUDE_DIR}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${CGAL_INCLUDE_DIR} ${GMP_INCLUDE_DIR} ${MPFR_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
@@ -737,7 +731,7 @@ endforeach(COMPONENT)
|
||||
|
||||
set(CPACK_DEBIAN_PACKAGE_NAME "${PROJECT_NAME}")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_PACKAGE_CONTACT}")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "python3, libxml2, libocct-foundation-dev, libocct-modeling-algorithms-dev, libocct-modeling-data-dev, libocct-ocaf-dev, libocct-visualization-dev, libocct-data-exchange-dev, libhdf5-serial-dev, libpython3-dev, python3-pytest ${BOOST_DEPS}")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "python3, libxml2, libocct-foundation-dev, libocct-modeling-algorithms-dev, libocct-modeling-data-dev, libocct-ocaf-dev, libocct-visualization-dev, libocct-data-exchange-dev, libpython3-dev, python3-pytest ${BOOST_DEPS}")
|
||||
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION_SUMMARY "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}")
|
||||
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION}")
|
||||
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
"BUILD_CONVERT": "ON",
|
||||
"BUILD_IFCMAX": "OFF",
|
||||
"IFCXML_SUPPORT": "ON",
|
||||
"HDF5_SUPPORT": "ON",
|
||||
"SCHEMA_VERSIONS": "4x3_add2",
|
||||
"CMAKE_GENERATOR_PLATFORM": "",
|
||||
"CMAKE_GENERATOR_TOOLSET": ""
|
||||
@@ -50,8 +49,6 @@
|
||||
"MPFR_LIBRARY_DIR": "$env{LIBRARY_PREFIX}/lib",
|
||||
"Boost_LIBRARY_DIR": "$env{LIBRARY_PREFIX}/lib",
|
||||
"Boost_INCLUDE_DIR": "$env{LIBRARY_PREFIX}/include",
|
||||
"HDF5_INCLUDE_DIR": "$env{LIBRARY_PREFIX}/include",
|
||||
"HDF5_LIBRARY_DIR": "$env{LIBRARY_PREFIX}/lib",
|
||||
"ZLIB_INCLUDE_DIR": "$env{LIBRARY_PREFIX}/include"
|
||||
}
|
||||
},
|
||||
@@ -110,4 +107,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# - `GMP_LIBRARY_DIR`
|
||||
# - `MPFR_INCLUDE_DIR`
|
||||
# - `MPFR_LIBRARY_DIR`
|
||||
# If input variables are not specified, try to find HDF5 config.
|
||||
# If input variables are not specified, try to find CGAL config.
|
||||
# Input variables could also be provided as environment variables.
|
||||
#
|
||||
# Output targets:
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
#
|
||||
# Input variables:
|
||||
# - `HDF5_INCLUDE_DIR`
|
||||
# - `HDF5_LIBRARY_DIR`
|
||||
# - `HDF5_LIBRARIES`
|
||||
# If input variables are not specified, try to find HDF5 config.
|
||||
# Input variables could also be provided as environment variables.
|
||||
#
|
||||
# Output variables:
|
||||
# - `HDF5_INCLUDE_DIR`
|
||||
# - `HDF5_LIBRARY_DIR`
|
||||
# - `HDF5_LIBRARIES`
|
||||
#
|
||||
|
||||
UNIFY_ENVVARS_AND_CACHE(HDF5_INCLUDE_DIR)
|
||||
UNIFY_ENVVARS_AND_CACHE(HDF5_LIBRARY_DIR)
|
||||
UNIFY_ENVVARS_AND_CACHE(HDF5_LIBRARIES)
|
||||
|
||||
# To avoid cyclic calls to this file
|
||||
list(REMOVE_ITEM CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR})
|
||||
|
||||
if(NOT HDF5_INCLUDE_DIR)
|
||||
message(STATUS "No HDF5 include directory specified")
|
||||
else()
|
||||
set(HDF5_INCLUDE_DIR "${HDF5_INCLUDE_DIR}" CACHE FILEPATH "HDF5 header files")
|
||||
endif()
|
||||
|
||||
if(NOT HDF5_LIBRARY_DIR)
|
||||
message(STATUS "No HDF5 library directory specified")
|
||||
else()
|
||||
set(HDF5_LIBRARY_DIR "${HDF5_LIBRARY_DIR}" CACHE FILEPATH "HDF5 library files")
|
||||
endif()
|
||||
|
||||
if(HDF5_LIBRARY_DIR)
|
||||
# result of the HDF5 ctest package
|
||||
# Find zlib using cmake find_library. How should this be implemented?
|
||||
# FIND_LIBRARY(NAMES z libz libz_debug PATHS ... NO_DEFAULT_PATH)
|
||||
if(NOT DEFINED ENV{CONDA_BUILD})
|
||||
# result of the HDF5 ctest package
|
||||
if(WIN32)
|
||||
set(zlib_post lib)
|
||||
set(lib_ext lib)
|
||||
else()
|
||||
set(lib_ext a)
|
||||
endif()
|
||||
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
set(debug_postfix "_debug")
|
||||
endif()
|
||||
|
||||
set(HDF5_LIBRARIES
|
||||
"${HDF5_LIBRARY_DIR}/libhdf5_cpp${debug_postfix}.${lib_ext}"
|
||||
"${HDF5_LIBRARY_DIR}/libhdf5${debug_postfix}.${lib_ext}"
|
||||
"${HDF5_LIBRARY_DIR}/libz${zlib_post}${debug_postfix}.${lib_ext}"
|
||||
"${HDF5_LIBRARY_DIR}/libsz${debug_postfix}.${lib_ext}"
|
||||
"${HDF5_LIBRARY_DIR}/libaec${debug_postfix}.${lib_ext}"
|
||||
)
|
||||
else()
|
||||
message(STATUS "Packaging hdf5 and zlib for conda distribution")
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
# macOS
|
||||
set(zlib_post libz)
|
||||
set(lib_ext dylib)
|
||||
set(HDF5_LIBRARIES
|
||||
"${HDF5_LIBRARY_DIR}/libhdf5_cpp.${lib_ext}"
|
||||
"${HDF5_LIBRARY_DIR}/libhdf5.${lib_ext}"
|
||||
"${HDF5_LIBRARY_DIR}/${zlib_post}.${lib_ext}"
|
||||
)
|
||||
else()
|
||||
# linux and windows
|
||||
# Find HDF5 package
|
||||
find_package(HDF5 REQUIRED COMPONENTS C CXX)
|
||||
# Find ZLIB package
|
||||
find_package(ZLIB REQUIRED)
|
||||
# Include directories
|
||||
include_directories(${HDF5_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS})
|
||||
# Link libraries
|
||||
set(HDF5_LIBRARIES ${HDF5_LIBRARIES} ${ZLIB_LIBRARIES})
|
||||
message(STATUS "HDF5 libraries: ${HDF5_LIBRARIES}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT HDF5_INCLUDE_DIR OR NOT HDF5_LIBRARY_DIR)
|
||||
# First try to find it as a config.
|
||||
find_package(HDF5 CONFIG)
|
||||
mark_as_advanced(HDF5_DIR)
|
||||
if(HDF5_DIR)
|
||||
message(STATUS "HDF5: found config at '${HDF5_DIR}'.")
|
||||
set(HDF5_LIBRARIES hdf5_cpp-static)
|
||||
else()
|
||||
# If it failed, still try to find as a module.
|
||||
# E.g. on Ubuntu `libhdf5-dev` doesn't provie hdf5-config.cmake.
|
||||
# Will automatically fill HDF5_LIBRARIES and HDF5_INCLUDE_DIR.
|
||||
find_package(HDF5 COMPONENTS CXX)
|
||||
if(NOT HDF5_INCLUDE_DIR)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"HDF5_INCLUDE_DIR is not provided (current value: '${HDF5_INCLUDE_DIR}'). "
|
||||
"HDF5_LIBRARY_DIR is not provided (current value: '${HDF5_LIBRARY_DIR}'). "
|
||||
"Also could not find HDF5 package (neither module or config)."
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Restore module path.
|
||||
list(PREPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR})
|
||||
@@ -22,9 +22,6 @@ cmake -G "Ninja" ^
|
||||
-D GMP_LIBRARY_DIR:FILEPATH="%LIBRARY_PREFIX%\lib" ^
|
||||
-D MPFR_LIBRARY_DIR:FILEPATH="%LIBRARY_PREFIX%\lib" ^
|
||||
-D COLLADA_SUPPORT=OFF ^
|
||||
-D HDF5_SUPPORT=ON ^
|
||||
-D HDF5_INCLUDE_DIR="%LIBRARY_PREFIX%\include" ^
|
||||
-D HDF5_LIBRARY_DIR="%LIBRARY_PREFIX%\lib" ^
|
||||
-D JSON_INCLUDE_DIR="%LIBRARY_PREFIX%\include" ^
|
||||
-D PYTHON_INCLUDE_DIR=%PREFIX%\include ^
|
||||
-D PYTHON_EXECUTABLE:FILEPATH=%PREFIX%\python.exe ^
|
||||
|
||||
+1
-4
@@ -24,9 +24,6 @@ cmake ${CMAKE_ARGS} -G Ninja \
|
||||
-DMPFR_LIBRARY_DIR=$PREFIX/lib \
|
||||
-DOCC_INCLUDE_DIR=$PREFIX/include/opencascade \
|
||||
-DOCC_LIBRARY_DIR=$PREFIX/lib \
|
||||
-DHDF5_SUPPORT:BOOL=ON \
|
||||
-DHDF5_INCLUDE_DIR=$PREFIX/include \
|
||||
-DHDF5_LIBRARY_DIR=$PREFIX/lib \
|
||||
-DJSON_INCLUDE_DIR=$PREFIX/include \
|
||||
-DCGAL_INCLUDE_DIR=$PREFIX/include \
|
||||
-DLIBXML2_INCLUDE_DIR=$PREFIX/include/libxml2 \
|
||||
@@ -46,4 +43,4 @@ ninja
|
||||
|
||||
ninja install -j 1
|
||||
|
||||
python "${RECIPE_DIR}/update_version_init.py" "${PKG_VERSION}" "${SP_DIR}/ifcopenshell/__init__.py"
|
||||
python "${RECIPE_DIR}/update_version_init.py" "${PKG_VERSION}" "${SP_DIR}/ifcopenshell/__init__.py"
|
||||
|
||||
@@ -26,8 +26,6 @@ c_stdlib_version:
|
||||
- 2.17 # [linux]
|
||||
- 10.13 # [osx and x86_64]
|
||||
- 11.0 # [osx and arm64]
|
||||
hdf5:
|
||||
- 1.14.6
|
||||
libboost_devel:
|
||||
- '1.86'
|
||||
libxml2:
|
||||
|
||||
@@ -33,7 +33,6 @@ requirements:
|
||||
- occt
|
||||
- libxml2
|
||||
- cgal-cpp
|
||||
- hdf5
|
||||
- eigen
|
||||
- mpfr
|
||||
- nlohmann_json
|
||||
|
||||
+2
-59
@@ -107,7 +107,6 @@ import logging
|
||||
import multiprocessing
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import shutil
|
||||
|
||||
# @todo temporary for expired mpfr.org certificate on 2023-04-08
|
||||
@@ -153,7 +152,6 @@ PCRE_VERSION = "8.41"
|
||||
LIBXML2_VERSION = "2.13.8"
|
||||
SWIG_VERSION = "4.2.1"
|
||||
OPENCOLLADA_VERSION = "v1.6.68"
|
||||
HDF5_VERSION = "1.13.1"
|
||||
|
||||
GMP_VERSION = "6.3.0"
|
||||
MPFR_VERSION = "3.1.6" # latest is 4.1.0
|
||||
@@ -331,7 +329,7 @@ cecho(""" - IFC Schemas to compile. If not provided, fallback to default provide
|
||||
""")
|
||||
|
||||
dependency_tree: "dict[str, tuple[str, ...]]" = {
|
||||
"IfcParse": ("boost", "libxml2", "hdf5", "rocksdb"),
|
||||
"IfcParse": ("boost", "libxml2", "rocksdb"),
|
||||
"IfcGeom": ("IfcParse", "occ", "manifold", "json", "cgal", "eigen", "OpenCOLLADA"),
|
||||
"IfcConvert": ("IfcGeom",),
|
||||
"OpenCOLLADA": ("libxml2", "pcre"),
|
||||
@@ -344,7 +342,6 @@ dependency_tree: "dict[str, tuple[str, ...]]" = {
|
||||
"occ": (),
|
||||
"pcre": (),
|
||||
"json": (),
|
||||
"hdf5": (),
|
||||
"cgal": (),
|
||||
"eigen": (),
|
||||
"rocksdb": ("zstd",),
|
||||
@@ -405,7 +402,6 @@ else:
|
||||
targets = set(t for t in targets if "without-%s" % t.lower() not in flags)
|
||||
if WASM:
|
||||
SKIP_TARGETS_FOR_WASM = {
|
||||
"hdf5",
|
||||
"rocksdb",
|
||||
"opencollada",
|
||||
"swig",
|
||||
@@ -633,7 +629,6 @@ def build_dependency(
|
||||
mode: Literal[
|
||||
"cmake",
|
||||
"autoconf",
|
||||
"ctest",
|
||||
"bjam",
|
||||
],
|
||||
build_tool_args: "list[str]",
|
||||
@@ -740,23 +735,7 @@ def build_dependency(
|
||||
if shell is not None:
|
||||
sp.run(shell, shell=True, check=True, cwd=extract_dir)
|
||||
|
||||
if mode == "ctest":
|
||||
try:
|
||||
run(
|
||||
["ctest", "-S", "HDF5config.cmake,BUILD_GENERATOR=Unix", "-C", BUILD_CFG, "-V", "-O", "hdf5.log"],
|
||||
cwd=extract_dir,
|
||||
)
|
||||
except Exception as e:
|
||||
print("-" * 70)
|
||||
print(open(os.path.join(extract_dir, "hdf5.log")))
|
||||
print("-" * 70)
|
||||
raise e
|
||||
run([tar, "-xf", kwargs["ctest_result"] + ".tar.gz"], cwd=os.path.join(extract_dir, "build"))
|
||||
shutil.copytree(
|
||||
os.path.join(extract_dir, "build", kwargs["ctest_result"], kwargs["ctest_result_path"]),
|
||||
os.path.join(DEPS_DIR, "install", name),
|
||||
)
|
||||
elif mode != "bjam":
|
||||
if mode != "bjam":
|
||||
extract_build_dir = os.path.join(extract_dir, *([cmake_dir] if cmake_dir else []), "build")
|
||||
if os.path.exists(extract_build_dir):
|
||||
shutil.rmtree(extract_build_dir)
|
||||
@@ -852,37 +831,6 @@ os.environ["LDFLAGS"] = LDFLAGS
|
||||
# @tfk: this is no longer needed
|
||||
# build_dependency(name="cmake-%s" % (CMAKE_VERSION,), mode="autoconf", build_tool_args=[], download_url="https://cmake.org/files/v%s" % (CMAKE_VERSION_2,), download_name="cmake-%s.tar.gz" % (CMAKE_VERSION,))
|
||||
|
||||
if "hdf5" in targets:
|
||||
# not supported
|
||||
orig = [os.environ[f] for f in compiler_flags]
|
||||
for f in compiler_flags:
|
||||
os.environ[f] = re.sub(r"-flto(=\w+)?", "", os.environ[f])
|
||||
|
||||
HDF5_UNDERSCORE = "_".join(HDF5_VERSION.split("."))
|
||||
HDF5_MAJOR = ".".join(HDF5_VERSION.split(".")[:-1])
|
||||
dependency_name = f"hdf5-{HDF5_VERSION}"
|
||||
build_dependency(
|
||||
name=dependency_name,
|
||||
mode="cmake",
|
||||
build_tool_args=[
|
||||
f"-DCMAKE_INSTALL_PREFIX={DEPS_DIR}/install/{dependency_name}",
|
||||
"-DHDF5_ENABLE_Z_LIB_SUPPORT=OFF",
|
||||
"-DBUILD_TESTING=OFF",
|
||||
"-DHDF5_BUILD_TOOLS=OFF",
|
||||
"-DHDF5_BUILD_EXAMPLES=OFF",
|
||||
"-DBUILD_SHARED_LIBS=OFF",
|
||||
"-DHDF5_BUILD_UTILS=OFF",
|
||||
"-DHDF5_BUILD_CPP_LIB=ON",
|
||||
*MAC_CROSS_COMPILE_INTEL_ARGS,
|
||||
],
|
||||
download_url=f"https://github.com/HDFGroup/hdf5/archive/refs/tags/",
|
||||
download_name=f"hdf5-{HDF5_UNDERSCORE}.tar.gz",
|
||||
)
|
||||
|
||||
for f, o in zip(compiler_flags, orig):
|
||||
os.environ[f] = o
|
||||
|
||||
|
||||
if "json" in targets:
|
||||
dependency_name = f"json-{JSON_VERSION}"
|
||||
build_dependency(
|
||||
@@ -1412,11 +1360,6 @@ else:
|
||||
if "libxml2" in targets:
|
||||
cmake_args_prefix_path.append(f"{DEPS_DIR}/install/libxml2-{LIBXML2_VERSION}")
|
||||
|
||||
if "hdf5" in targets:
|
||||
cmake_args_prefix_path.append(f"{DEPS_DIR}/install/hdf5-{HDF5_VERSION}")
|
||||
else:
|
||||
cmake_args.append("-DHDF5_SUPPORT=Off")
|
||||
|
||||
if "usd" in targets:
|
||||
cmake_args.append("-DUSD_SUPPORT=ON")
|
||||
cmake_args_prefix_path.extend(
|
||||
|
||||
@@ -34,7 +34,6 @@ environments:
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-13.3.0-h9576a4e_1.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-13.3.0-hdbfa832_1.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-13.3.0-h6834431_7.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.4-nompi_h2d575fe_105.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/imath-3.1.12-h7955e40_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/jxrlib-1.1-hd590300_3.conda
|
||||
@@ -149,7 +148,6 @@ environments:
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/freeimage-3.18.0-h7cd8ba8_22.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/freetype-2.12.1-h60636b9_2.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/gmp-6.3.0-hf036a51_2.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/hdf5-1.14.4-nompi_h1607680_105.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/icu-75.1-h120a0e1_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/imath-3.1.12-h2016aa1_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/jxrlib-1.1-h10d778d_3.conda
|
||||
@@ -243,7 +241,6 @@ environments:
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/freeimage-3.18.0-h8310ca0_22.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/freetype-2.12.1-hdaf720e_2.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/gmp-6.3.0-hfeafd45_2.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/hdf5-1.14.4-nompi_hd5d9e70_105.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/imath-3.1.12-hbb528cf_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.2.1-h57928b3_1083.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/jxrlib-1.1-hcfcfb64_3.conda
|
||||
@@ -349,7 +346,6 @@ environments:
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-13.3.0-h9576a4e_1.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-13.3.0-hdbfa832_1.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-13.3.0-h6834431_7.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.4-nompi_h2d575fe_105.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/imath-3.1.12-h7955e40_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/jxrlib-1.1-hd590300_3.conda
|
||||
@@ -464,7 +460,6 @@ environments:
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/freeimage-3.18.0-h7cd8ba8_22.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/freetype-2.12.1-h60636b9_2.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/gmp-6.3.0-hf036a51_2.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/hdf5-1.14.4-nompi_h1607680_105.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/icu-75.1-h120a0e1_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/imath-3.1.12-h2016aa1_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/jxrlib-1.1-h10d778d_3.conda
|
||||
@@ -558,7 +553,6 @@ environments:
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/freeimage-3.18.0-h8310ca0_22.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/freetype-2.12.1-hdaf720e_2.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/gmp-6.3.0-hfeafd45_2.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/hdf5-1.14.4-nompi_hd5d9e70_105.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/imath-3.1.12-hbb528cf_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.2.1-h57928b3_1083.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/jxrlib-1.1-hcfcfb64_3.conda
|
||||
@@ -743,7 +737,6 @@ environments:
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-13.3.0-h9576a4e_1.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-13.3.0-hdbfa832_1.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-13.3.0-h6834431_7.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.4-nompi_h2d575fe_105.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/imath-3.1.12-h7955e40_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/jxrlib-1.1-hd590300_3.conda
|
||||
@@ -858,7 +851,6 @@ environments:
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/freeimage-3.18.0-h7cd8ba8_22.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/freetype-2.12.1-h60636b9_2.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/gmp-6.3.0-hf036a51_2.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/hdf5-1.14.4-nompi_h1607680_105.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/icu-75.1-h120a0e1_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/imath-3.1.12-h2016aa1_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/jxrlib-1.1-h10d778d_3.conda
|
||||
@@ -952,7 +944,6 @@ environments:
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/freeimage-3.18.0-h8310ca0_22.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/freetype-2.12.1-hdaf720e_2.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/gmp-6.3.0-hfeafd45_2.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/hdf5-1.14.4-nompi_hd5d9e70_105.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/imath-3.1.12-hbb528cf_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.2.1-h57928b3_1083.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/jxrlib-1.1-hcfcfb64_3.conda
|
||||
@@ -1068,7 +1059,6 @@ environments:
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-14.3.0-he663afc_4.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-14.3.0-ha7acb78_11.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.6-nompi_h6e4c0c1_103.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda
|
||||
@@ -1239,7 +1229,6 @@ environments:
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/geos-3.13.1-h502464c_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/gmp-6.3.0-hf036a51_2.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/hdf5-1.14.6-nompi_hc8237f9_103.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/icu-75.1-h120a0e1_0.conda
|
||||
@@ -1380,7 +1369,6 @@ environments:
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/geos-3.13.1-h9ea8674_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/gmp-6.3.0-hfeafd45_2.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/hdf5-1.14.6-nompi_he30205f_103.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda
|
||||
- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.10-pyhd8ed1ab_1.conda
|
||||
@@ -2990,106 +2978,6 @@ packages:
|
||||
- pkg:pypi/h2?source=compressed-mapping
|
||||
size: 95967
|
||||
timestamp: 1756364871835
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.4-nompi_h2d575fe_105.conda
|
||||
sha256: 93d2bfc672f3ee0988d277ce463330a467f3686d3f7ee37812a3d8ca11776d77
|
||||
md5: d76fff0092b6389a12134ddebc0929bd
|
||||
depends:
|
||||
- __glibc >=2.17,<3.0.a0
|
||||
- libaec >=1.1.3,<2.0a0
|
||||
- libcurl >=8.10.1,<9.0a0
|
||||
- libgcc >=13
|
||||
- libgfortran
|
||||
- libgfortran5 >=13.3.0
|
||||
- libstdcxx >=13
|
||||
- libzlib >=1.3.1,<2.0a0
|
||||
- openssl >=3.4.0,<4.0a0
|
||||
license: BSD-3-Clause
|
||||
license_family: BSD
|
||||
size: 3950601
|
||||
timestamp: 1733003331788
|
||||
- conda: https://conda.anaconda.org/conda-forge/linux-64/hdf5-1.14.6-nompi_h6e4c0c1_103.conda
|
||||
sha256: 4f173af9e2299de7eee1af3d79e851bca28ee71e7426b377e841648b51d48614
|
||||
md5: c74d83614aec66227ae5199d98852aaf
|
||||
depends:
|
||||
- __glibc >=2.17,<3.0.a0
|
||||
- libaec >=1.1.4,<2.0a0
|
||||
- libcurl >=8.14.1,<9.0a0
|
||||
- libgcc >=14
|
||||
- libgfortran
|
||||
- libgfortran5 >=14.3.0
|
||||
- libstdcxx >=14
|
||||
- libzlib >=1.3.1,<2.0a0
|
||||
- openssl >=3.5.1,<4.0a0
|
||||
license: BSD-3-Clause
|
||||
license_family: BSD
|
||||
purls: []
|
||||
size: 3710057
|
||||
timestamp: 1753357500665
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/hdf5-1.14.4-nompi_h1607680_105.conda
|
||||
sha256: 56500937894b1ca917e1ae1bea64b873a9eec57d581173579189d0b1f590db26
|
||||
md5: 12ebafc40b10d4bf519e4c2074c52aef
|
||||
depends:
|
||||
- __osx >=10.13
|
||||
- libaec >=1.1.3,<2.0a0
|
||||
- libcurl >=8.10.1,<9.0a0
|
||||
- libcxx >=18
|
||||
- libgfortran 5.*
|
||||
- libgfortran5 >=13.2.0
|
||||
- libzlib >=1.3.1,<2.0a0
|
||||
- openssl >=3.4.0,<4.0a0
|
||||
license: BSD-3-Clause
|
||||
license_family: BSD
|
||||
size: 3732340
|
||||
timestamp: 1733003702265
|
||||
- conda: https://conda.anaconda.org/conda-forge/osx-64/hdf5-1.14.6-nompi_hc8237f9_103.conda
|
||||
sha256: e41d22f672b1fbe713d22cf69630abffaee68bdb38a500a708fc70e6f639357f
|
||||
md5: 3f1df98f96e0c369d94232712c9b87d0
|
||||
depends:
|
||||
- __osx >=10.13
|
||||
- libaec >=1.1.4,<2.0a0
|
||||
- libcurl >=8.14.1,<9.0a0
|
||||
- libcxx >=19
|
||||
- libgfortran
|
||||
- libgfortran5 >=14.3.0
|
||||
- libgfortran5 >=15.1.0
|
||||
- libzlib >=1.3.1,<2.0a0
|
||||
- openssl >=3.5.1,<4.0a0
|
||||
license: BSD-3-Clause
|
||||
license_family: BSD
|
||||
purls: []
|
||||
size: 3522832
|
||||
timestamp: 1753358062940
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/hdf5-1.14.4-nompi_hd5d9e70_105.conda
|
||||
sha256: e8ced65c604a3b9e4803758a25149d71d8096f186fe876817a0d1d97190550c0
|
||||
md5: 4381be33460283890c34341ecfa42d97
|
||||
depends:
|
||||
- libaec >=1.1.3,<2.0a0
|
||||
- libcurl >=8.10.1,<9.0a0
|
||||
- libzlib >=1.3.1,<2.0a0
|
||||
- openssl >=3.4.0,<4.0a0
|
||||
- ucrt >=10.0.20348.0
|
||||
- vc >=14.2,<15
|
||||
- vc14_runtime >=14.29.30139
|
||||
license: BSD-3-Clause
|
||||
license_family: BSD
|
||||
size: 2048450
|
||||
timestamp: 1733003052575
|
||||
- conda: https://conda.anaconda.org/conda-forge/win-64/hdf5-1.14.6-nompi_he30205f_103.conda
|
||||
sha256: 0a90263b97e9860cec6c2540160ff1a1fff2a609b3d96452f8716ae63489dac5
|
||||
md5: f1f7aaf642cefd2190582550eaca4658
|
||||
depends:
|
||||
- libaec >=1.1.4,<2.0a0
|
||||
- libcurl >=8.14.1,<9.0a0
|
||||
- libzlib >=1.3.1,<2.0a0
|
||||
- openssl >=3.5.1,<4.0a0
|
||||
- ucrt >=10.0.20348.0
|
||||
- vc >=14.3,<15
|
||||
- vc14_runtime >=14.44.35208
|
||||
license: BSD-3-Clause
|
||||
license_family: BSD
|
||||
purls: []
|
||||
size: 2031491
|
||||
timestamp: 1753357255237
|
||||
- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda
|
||||
sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba
|
||||
md5: 0a802cb9888dd14eeefc611f05c40b6e
|
||||
|
||||
@@ -31,7 +31,6 @@ occt = { version = "*", build = "*novtk*" }
|
||||
cgal-cpp = "*"
|
||||
numpy = "*"
|
||||
lark = "*"
|
||||
hdf5 = "*"
|
||||
eigen = "*"
|
||||
mpfr = "*"
|
||||
gmp = "*"
|
||||
|
||||
-1
@@ -1 +0,0 @@
|
||||
This cache folder contains .h5 files. These files cache IFC geometry for performance only. You may safely clear the contents of this cache folder without losing data.
|
||||
@@ -43,7 +43,6 @@ class IfcExporter:
|
||||
def export(self):
|
||||
self.file = tool.Ifc.get()
|
||||
self.set_header()
|
||||
IfcStore.update_cache()
|
||||
self.sync_all_objects()
|
||||
extension = self.ifc_export_settings.output_file.split(".")[-1].lower()
|
||||
if extension == "ifczip":
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
import traceback
|
||||
import uuid
|
||||
@@ -31,7 +29,6 @@ from typing import Literal, NotRequired, Optional, TypedDict, Union
|
||||
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.geom
|
||||
import ifcopenshell.ifcopenshell_wrapper
|
||||
from ifcopenshell.file import UndoSystemError
|
||||
|
||||
@@ -72,8 +69,6 @@ class IfcStore:
|
||||
"""Should be set only using ``tool.Ifc.set``."""
|
||||
|
||||
schema: Optional[ifcopenshell.ifcopenshell_wrapper.schema_definition] = None
|
||||
cache: Optional[ifcopenshell.ifcopenshell_wrapper.HdfSerializer] = None
|
||||
cache_path: Optional[str] = None
|
||||
id_map: dict[int, IFC_CONNECTED_TYPE] = {}
|
||||
guid_map: dict[str, IFC_CONNECTED_TYPE] = {}
|
||||
edited_objs: set[bpy.types.Object] = set()
|
||||
@@ -95,8 +90,6 @@ class IfcStore:
|
||||
IfcStore.path = ""
|
||||
IfcStore.file = None
|
||||
IfcStore.schema = None
|
||||
IfcStore.cache = None
|
||||
IfcStore.cache_path = None
|
||||
IfcStore.id_map = {}
|
||||
IfcStore.guid_map = {}
|
||||
IfcStore.edited_objs = set()
|
||||
@@ -130,74 +123,6 @@ class IfcStore:
|
||||
if IfcStore.path and not os.path.isabs(IfcStore.path):
|
||||
IfcStore.path = os.path.abspath(os.path.join(bpy.path.abspath("//"), IfcStore.path))
|
||||
|
||||
@staticmethod
|
||||
def generate_cache_path() -> str:
|
||||
"""Generate cache path based on the active file and it's path."""
|
||||
assert IfcStore.file
|
||||
ifc_key = IfcStore.path + IfcStore.file.header.file_name.time_stamp
|
||||
ifc_hash = hashlib.md5(ifc_key.encode("utf-8")).hexdigest()
|
||||
prefs = tool.Blender.get_addon_preferences()
|
||||
cache_path = os.path.join(prefs.cache_dir, f"{ifc_hash}.h5")
|
||||
return cache_path
|
||||
|
||||
@staticmethod
|
||||
def get_cache() -> ifcopenshell.geom.serializers.hdf5 | None:
|
||||
"""Get existing cache for the current file or create a new one.
|
||||
|
||||
.h5 cache name reflects IFC filepath and it's current header's timestamp.
|
||||
"""
|
||||
if IfcStore.cache is None and IfcStore.path:
|
||||
cache_path = IfcStore.generate_cache_path()
|
||||
os.makedirs(os.path.dirname(cache_path), exist_ok=True)
|
||||
IfcStore.cache_path = cache_path
|
||||
cache_path = Path(IfcStore.cache_path)
|
||||
cache_settings = ifcopenshell.geom.settings()
|
||||
serializer_settings = ifcopenshell.geom.serializer_settings()
|
||||
cache_preexists = cache_path.exists()
|
||||
try:
|
||||
IfcStore.cache = ifcopenshell.geom.serializers.hdf5(
|
||||
IfcStore.cache_path, cache_settings, serializer_settings
|
||||
)
|
||||
if cache_preexists:
|
||||
print(f"Successfully loaded existing cache: {cache_path.name}.")
|
||||
else:
|
||||
print("New cache was created.")
|
||||
except Exception as e:
|
||||
if cache_preexists:
|
||||
print(f"Failed to create a cache from existing file '{cache_path.name}': {str(e)}.")
|
||||
else:
|
||||
print(f"Failed to create a cache: {str(e)}.")
|
||||
# No point to trying again the same operation.
|
||||
return
|
||||
|
||||
os.remove(IfcStore.cache_path)
|
||||
try:
|
||||
IfcStore.cache = ifcopenshell.geom.serializers.hdf5(
|
||||
IfcStore.cache_path, cache_settings, serializer_settings
|
||||
)
|
||||
print("New cache was created.")
|
||||
except Exception as e:
|
||||
print(f"Failed to create a cache: {str(e)}.")
|
||||
return
|
||||
return IfcStore.cache
|
||||
|
||||
@staticmethod
|
||||
def update_cache() -> None:
|
||||
"""Update cache filename after timestamp was updated."""
|
||||
if not IfcStore.cache:
|
||||
return
|
||||
assert IfcStore.cache_path
|
||||
new_cache_path = IfcStore.generate_cache_path()
|
||||
IfcStore.cache = None
|
||||
try:
|
||||
shutil.move(IfcStore.cache_path, new_cache_path)
|
||||
except PermissionError:
|
||||
try:
|
||||
shutil.copy2(IfcStore.cache_path, new_cache_path)
|
||||
except PermissionError:
|
||||
pass # Well we tried. No cache for you!
|
||||
IfcStore.get_cache()
|
||||
|
||||
@staticmethod
|
||||
def load_file(path: str) -> None:
|
||||
if not os.path.isfile(path):
|
||||
|
||||
@@ -721,10 +721,6 @@ class IfcImporter:
|
||||
iterator = ifcopenshell.geom.iterator(
|
||||
settings, self.file, include=products, geometry_library=self.ifc_import_settings.geometry_library
|
||||
)
|
||||
if self.ifc_import_settings.should_cache:
|
||||
cache = IfcStore.get_cache()
|
||||
if cache:
|
||||
iterator.set_cache(cache)
|
||||
valid_file = iterator.initialize()
|
||||
if not valid_file:
|
||||
return results
|
||||
@@ -1267,7 +1263,6 @@ class IfcImportSettings:
|
||||
self.should_merge_materials_by_colour = False
|
||||
self.should_load_geometry = True
|
||||
self.should_clean_mesh = False
|
||||
self.should_cache = True
|
||||
self.deflection_tolerance = 0.05 # Default is 0.001, but I find this to be more practical
|
||||
self.angular_tolerance = 0.5
|
||||
self.void_limit = 30
|
||||
@@ -1295,7 +1290,6 @@ class IfcImportSettings:
|
||||
context=None, input_file: Optional[str] = None, logger: Optional[logging.Logger] = None
|
||||
) -> IfcImportSettings:
|
||||
scene_diff = tool.Blender.get_diff_props()
|
||||
prefs = tool.Blender.get_addon_preferences()
|
||||
props = tool.Project.get_project_props()
|
||||
settings = IfcImportSettings()
|
||||
settings.input_file = input_file
|
||||
@@ -1308,7 +1302,6 @@ class IfcImportSettings:
|
||||
settings.should_merge_materials_by_colour = props.should_merge_materials_by_colour
|
||||
settings.should_load_geometry = props.should_load_geometry
|
||||
settings.should_clean_mesh = props.should_clean_mesh
|
||||
settings.should_cache = prefs.should_always_cache or props.should_cache
|
||||
settings.deflection_tolerance = props.deflection_tolerance
|
||||
settings.angular_tolerance = props.angular_tolerance
|
||||
settings.void_limit = props.void_limit
|
||||
|
||||
@@ -37,7 +37,6 @@ classes = (
|
||||
operator.PrintObjectPlacement,
|
||||
operator.PrintUnusedElementStats,
|
||||
operator.ProfileImportIFC,
|
||||
operator.PurgeHdf5Cache,
|
||||
operator.PurgeUnusedElementsByClass,
|
||||
operator.PurgeUnusedObjects,
|
||||
operator.RestartBlender,
|
||||
|
||||
@@ -570,17 +570,6 @@ class SelectExpressFile(bpy.types.Operator, ImportHelper):
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class PurgeHdf5Cache(bpy.types.Operator):
|
||||
bl_idname = "bim.purge_hdf5_cache"
|
||||
bl_label = "Purge HDF5 Cache"
|
||||
bl_description = "Clean up HDF5 cache files except the ones that currently loaded"
|
||||
|
||||
def execute(self, context):
|
||||
core.purge_hdf5_cache(tool.Debug)
|
||||
self.report({"INFO"}, "HDF5 cache purged.")
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class OverrideDisplayType(bpy.types.Operator):
|
||||
bl_idname = "bim.override_display_type"
|
||||
bl_label = "Override Display Type"
|
||||
|
||||
@@ -64,9 +64,6 @@ class BIM_PT_debug(Panel):
|
||||
row = layout.row()
|
||||
row.operator("bim.copy_debug_information")
|
||||
|
||||
row = layout.row()
|
||||
row.operator("bim.purge_hdf5_cache")
|
||||
|
||||
row = layout.row()
|
||||
row.operator("bim.update_representation", text="Manually Save Representation")
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
import multiprocessing
|
||||
@@ -901,10 +900,7 @@ class CreateDrawing(bpy.types.Operator):
|
||||
# All very hackish whilst prototyping
|
||||
exporter = bonsai.bim.export_ifc.IfcExporter(None)
|
||||
exporter.file = tool.Ifc.get()
|
||||
invalidated_elements = exporter.sync_all_objects()
|
||||
invalidated_guids = [e.GlobalId for e in invalidated_elements if hasattr(e, "GlobalId")]
|
||||
if cache := IfcStore.get_cache():
|
||||
[cache.remove(guid) for guid in invalidated_guids]
|
||||
exporter.sync_all_objects()
|
||||
|
||||
# If we have already calculated it in the SVG in the past, don't recalculate
|
||||
edited_guids = set()
|
||||
@@ -922,7 +918,6 @@ class CreateDrawing(bpy.types.Operator):
|
||||
cached_linework -= edited_guids
|
||||
|
||||
bim_props = tool.Blender.get_bim_props()
|
||||
prefs = tool.Blender.get_addon_preferences()
|
||||
files = {bim_props.ifc_file: tool.Ifc.get()}
|
||||
|
||||
props = tool.Project.get_project_props()
|
||||
@@ -935,12 +930,8 @@ class CreateDrawing(bpy.types.Operator):
|
||||
tree = ifcopenshell.geom.tree()
|
||||
tree.enable_face_styles(True)
|
||||
|
||||
for ifc_path, ifc in files.items():
|
||||
for ifc in files.values():
|
||||
# Don't use draw.main() just whilst we're prototyping and experimenting
|
||||
# TODO: hash paths are never used
|
||||
ifc_hash = hashlib.md5(ifc_path.encode("utf-8")).hexdigest()
|
||||
ifc_cache_path = os.path.join(prefs.cache_dir, f"{ifc_hash}.h5")
|
||||
|
||||
self.serialiser.setFile(ifc)
|
||||
drawing_elements = tool.Drawing.get_drawing_elements(self.camera_element, ifc_file=ifc)
|
||||
|
||||
|
||||
@@ -576,9 +576,6 @@ class UpdateRepresentation(bpy.types.Operator, tool.Ifc.Operator):
|
||||
self.report({"ERROR"}, f"Object '{obj.name}' has openings - representation cannot be updated.")
|
||||
return
|
||||
|
||||
if not product.is_a("IfcGridAxis"):
|
||||
tool.Geometry.clear_cache(product)
|
||||
|
||||
if product.is_a("IfcGridAxis"):
|
||||
# Grid geometry does not follow the "representation" paradigm and needs to be treated specially
|
||||
tool.Model.create_axis_curve(obj, product)
|
||||
|
||||
@@ -1488,7 +1488,6 @@ class LoadLink(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def link_ifc(self) -> Union[set[str], None]:
|
||||
blend_filepath = self.filepath_.with_suffix(".ifc.cache.blend")
|
||||
h5_filepath = self.filepath_.with_suffix(".ifc.cache.h5")
|
||||
json_filepath = self.filepath_.with_suffix(".ifc.cache.json")
|
||||
|
||||
def should_clear_cache() -> bool:
|
||||
|
||||
@@ -345,14 +345,6 @@ class BIMProjectProperties(PropertyGroup):
|
||||
),
|
||||
default=False,
|
||||
)
|
||||
should_cache: BoolProperty(
|
||||
name="Cache",
|
||||
description=(
|
||||
"Cache loaded geometry to .h5 file in your cache directory (see in preferences) "
|
||||
"for faster imports and geometry reloads."
|
||||
),
|
||||
default=False,
|
||||
)
|
||||
deflection_tolerance: FloatProperty(name="Deflection Tolerance", default=0.05)
|
||||
angular_tolerance: FloatProperty(name="Angular Tolerance", default=0.5)
|
||||
void_limit: IntProperty(
|
||||
@@ -521,7 +513,6 @@ class BIMProjectProperties(PropertyGroup):
|
||||
should_merge_materials_by_colour: bool
|
||||
should_load_geometry: bool
|
||||
should_clean_mesh: bool
|
||||
should_cache: bool
|
||||
deflection_tolerance: float
|
||||
angular_tolerance: float
|
||||
void_limit: int
|
||||
|
||||
@@ -207,8 +207,6 @@ class BIM_PT_project(Panel):
|
||||
row = self.layout.row()
|
||||
row.prop(pprops, "should_clean_mesh")
|
||||
row = self.layout.row()
|
||||
row.prop(pprops, "should_cache")
|
||||
row = self.layout.row()
|
||||
row.prop(pprops, "should_load_geometry")
|
||||
row = self.layout.row()
|
||||
row.prop(pprops, "should_merge_materials_by_colour")
|
||||
|
||||
@@ -207,7 +207,6 @@ class RemoveOpening(bpy.types.Operator, tool.Ifc.Operator):
|
||||
representation=representation,
|
||||
)
|
||||
tool.Geometry.unlock_scale_object_with_openings(obj)
|
||||
tool.Geometry.clear_cache(element)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
|
||||
@@ -665,10 +665,6 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences):
|
||||
name="Disable Undo When Saving (Faster saves, no undo for you!)", default=False
|
||||
)
|
||||
should_stream: BoolProperty(name="Stream Data From IFC-SPF (Only for advanced users)", default=False)
|
||||
should_always_cache: BoolProperty(
|
||||
name="Always Cache Geometry",
|
||||
description="Whether to always cache geometry regardless of 'Cache' setting during Advanced Project Load.",
|
||||
)
|
||||
occurrence_name_style: bpy.props.EnumProperty(
|
||||
items=[("CLASS", "By Class", ""), ("TYPE", "By Type", ""), ("CUSTOM", "Custom", "")],
|
||||
name="Occurrence Name Style",
|
||||
@@ -777,7 +773,6 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences):
|
||||
bsdd_baseurl: str
|
||||
should_disable_undo_on_save: bool
|
||||
should_stream: bool
|
||||
should_always_cache: bool
|
||||
occurrence_name_style: Literal["CLASS", "TYPE", "CUSTOM"]
|
||||
occurrence_name_function: str
|
||||
gizmos: GizmoPreferences
|
||||
@@ -976,7 +971,6 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences):
|
||||
layout.prop(self, "opening_focus_opacity")
|
||||
layout.prop(self, "should_disable_undo_on_save")
|
||||
layout.prop(self, "should_stream")
|
||||
layout.prop(self, "should_always_cache")
|
||||
layout.label(text="bSDD:")
|
||||
layout.prop(self, "bsdd_load_preview_dictionaries")
|
||||
layout.prop(self, "bsdd_load_inactive_dictionaries")
|
||||
|
||||
@@ -30,10 +30,6 @@ def parse_express(debug: type[tool.Debug], filename: str) -> None:
|
||||
debug.add_schema_identifier(debug.load_express(filename))
|
||||
|
||||
|
||||
def purge_hdf5_cache(debug: type[tool.Debug]) -> None:
|
||||
debug.purge_hdf5_cache()
|
||||
|
||||
|
||||
def purge_unused_elements(ifc: type[tool.Ifc], debug: type[tool.Debug], ifc_class: str) -> int:
|
||||
ifc_file = ifc.get()
|
||||
unused_elements = [i for i in ifc_file.by_type(ifc_class) if ifc_file.get_total_inverses(i) == 0]
|
||||
|
||||
@@ -44,7 +44,6 @@ def edit_object_placement(
|
||||
element = ifc.get_entity(obj)
|
||||
if not element:
|
||||
return
|
||||
geometry.clear_cache(element)
|
||||
if apply_scale:
|
||||
geometry.clear_scale(obj)
|
||||
geometry.get_blender_offset_type(obj)
|
||||
@@ -125,7 +124,6 @@ def switch_representation(
|
||||
|
||||
element = ifc.get_entity(obj)
|
||||
assert element
|
||||
geometry.clear_cache(element)
|
||||
geometry.reimport_element_representations(obj, representation, apply_openings=apply_openings)
|
||||
|
||||
|
||||
|
||||
@@ -283,7 +283,6 @@ class Cost:
|
||||
class Debug:
|
||||
def add_schema_identifier(cls, schema): pass
|
||||
def load_express(cls, filename): pass
|
||||
def purge_hdf5_cache(cls): pass
|
||||
|
||||
|
||||
@interface
|
||||
@@ -422,7 +421,6 @@ class Feature:
|
||||
@interface
|
||||
class Geometry:
|
||||
def change_object_data(cls, obj, data, is_global=False): pass
|
||||
def clear_cache(cls, element): pass
|
||||
def clear_modifiers(cls, obj): pass
|
||||
def clear_scale(cls, obj): pass
|
||||
def copy_data_links(cls, data, copied_entities) -> None: pass
|
||||
|
||||
@@ -59,17 +59,6 @@ class Debug(bonsai.core.tool.Debug):
|
||||
ifcopenshell.register_schema(schema)
|
||||
return schema.schema
|
||||
|
||||
@classmethod
|
||||
def purge_hdf5_cache(cls) -> None:
|
||||
prefs = tool.Blender.get_addon_preferences()
|
||||
cache_dir = prefs.cache_dir
|
||||
filelist = [f for f in os.listdir(cache_dir) if f.endswith(".h5")]
|
||||
for f in filelist:
|
||||
try:
|
||||
os.remove(os.path.join(cache_dir, f))
|
||||
except PermissionError:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def debug_bmesh(cls, bm: bmesh.types.BMesh, name: str = "Debug") -> bpy.types.Object:
|
||||
mesh = bpy.data.meshes.new("Debug")
|
||||
|
||||
@@ -73,7 +73,6 @@ import bonsai.core.style
|
||||
import bonsai.core.system
|
||||
import bonsai.core.tool
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.geometry.prop import (
|
||||
@@ -109,16 +108,6 @@ class Geometry(bonsai.core.tool.Geometry):
|
||||
raise Exception("user_remap is not supported for meshes in EDIT mode")
|
||||
old_data.user_remap(new_data)
|
||||
|
||||
@classmethod
|
||||
def get_cache(cls) -> Union[ifcopenshell.geom.serializers.hdf5, None]:
|
||||
return IfcStore.get_cache()
|
||||
|
||||
@classmethod
|
||||
def clear_cache(cls, element: ifcopenshell.entity_instance) -> None:
|
||||
cache = IfcStore.get_cache()
|
||||
if cache and hasattr(element, "GlobalId"):
|
||||
cache.remove(element.GlobalId)
|
||||
|
||||
@classmethod
|
||||
def clear_modifiers(cls, obj: bpy.types.Object) -> None:
|
||||
for modifier in obj.modifiers:
|
||||
@@ -818,7 +807,6 @@ class Geometry(bonsai.core.tool.Geometry):
|
||||
if not cls.has_data_users(old_data):
|
||||
cls.delete_data(old_data)
|
||||
cls.clear_modifiers(obj)
|
||||
cls.clear_cache(element)
|
||||
|
||||
# Import swept disk solids as Blender curves if possible.
|
||||
elements_without_openings = {e for e in elements if not getattr(e, "HasOpenings", False)}
|
||||
|
||||
@@ -22,9 +22,6 @@ props = tool.Georeference.get_georeference_props()
|
||||
|
||||
props = tool.Project.get_project_props()
|
||||
|
||||
# Generally recommended to disable caching for stability right now
|
||||
props.should_cache = False
|
||||
|
||||
# If you are not authoring, it is recommended to enable this.
|
||||
# When enabled, types, openings, and non geometric elements are not loaded.
|
||||
props.is_coordinating = True
|
||||
|
||||
@@ -9,7 +9,6 @@ class BlenderImporter:
|
||||
|
||||
def __init__(self):
|
||||
self.file = ifcopenshell.open("/home/dion/untitled.ifc")
|
||||
self.cache_path = "cache.h5"
|
||||
self.should_use_cpu_multiprocessing = True
|
||||
self.deflection_tolerance = 0.001
|
||||
self.angular_tolerance = 0.5
|
||||
@@ -82,9 +81,6 @@ class BlenderImporter:
|
||||
iterator = ifcopenshell.geom.iterator(settings, self.file, multiprocessing.cpu_count(), include=products)
|
||||
else:
|
||||
iterator = ifcopenshell.geom.iterator(settings, self.file, include=products)
|
||||
cache = self.get_cache()
|
||||
if cache:
|
||||
iterator.set_cache(cache)
|
||||
valid_file = iterator.initialize()
|
||||
if not valid_file:
|
||||
return results
|
||||
@@ -113,13 +109,4 @@ class BlenderImporter:
|
||||
print("Done creating geometry")
|
||||
return results
|
||||
|
||||
def get_cache(self):
|
||||
cache_settings = ifcopenshell.geom.settings()
|
||||
serializer_settings = ifcopenshell.geom.serializer_settings()
|
||||
try:
|
||||
return ifcopenshell.geom.serializers.hdf5(self.cache_path, cache_settings, serializer_settings)
|
||||
except:
|
||||
return
|
||||
|
||||
|
||||
BlenderImporter().execute()
|
||||
|
||||
@@ -25,9 +25,3 @@ class TestParseExpress:
|
||||
debug.load_express("filename").should_be_called().will_return("schema")
|
||||
debug.add_schema_identifier("schema").should_be_called()
|
||||
subject.parse_express(debug, "filename")
|
||||
|
||||
|
||||
class TestPurgeHdf5Cache:
|
||||
def test_run(self, debug):
|
||||
debug.purge_hdf5_cache().should_be_called()
|
||||
subject.purge_hdf5_cache(debug)
|
||||
|
||||
@@ -24,7 +24,6 @@ from test.core.bootstrap import geometry, ifc, style, surveyor
|
||||
class TestEditObjectPlacement:
|
||||
def predict(self, ifc, geometry, surveyor):
|
||||
ifc.get_entity("obj").should_be_called().will_return("element")
|
||||
geometry.clear_cache("element").should_be_called()
|
||||
geometry.clear_scale("obj").should_be_called()
|
||||
geometry.get_blender_offset_type("obj").should_be_called()
|
||||
surveyor.get_absolute_matrix("obj").should_be_called().will_return("matrix")
|
||||
@@ -197,7 +196,6 @@ class TestSwitchRepresentation:
|
||||
def test_switching_to_a_representation(self, ifc, geometry):
|
||||
geometry.get_object_data("obj").should_be_called().will_return("current_obj_data")
|
||||
ifc.get_entity("obj").should_be_called().will_return("element")
|
||||
geometry.clear_cache("element").should_be_called()
|
||||
geometry.reimport_element_representations("obj", "mapped_rep", apply_openings=True).should_be_called()
|
||||
subject.switch_representation(
|
||||
ifc,
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api.style
|
||||
@@ -55,24 +53,6 @@ class TestLoadExpress(NewFile):
|
||||
os.remove(schema_path + ".cache.dat")
|
||||
|
||||
|
||||
class TestPurgeHdf5Cache(NewFile):
|
||||
def test_run(self):
|
||||
prefs = tool.Blender.get_addon_preferences()
|
||||
cache_dir = Path(prefs.cache_dir)
|
||||
test_file = cache_dir / "test.h5"
|
||||
test_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
test_file.touch()
|
||||
|
||||
# Ensure it can skip currently loaded cache.
|
||||
loaded_file_path = test_file.with_stem("test_loaded")
|
||||
loaded_file = open(loaded_file_path, "w")
|
||||
|
||||
subject.purge_hdf5_cache()
|
||||
# On Unix loaded files are not locked.
|
||||
paths = [loaded_file_path] if os.name == "nt" else []
|
||||
assert [f for f in cache_dir.iterdir() if f.suffix == ".h5"] == paths
|
||||
|
||||
|
||||
class TestMergeIdenticalObject(NewFile):
|
||||
def test_merge_identical_styles(self):
|
||||
tool.Ifc.set(ifc := ifcopenshell.file())
|
||||
|
||||
@@ -279,16 +279,10 @@ int main(int argc, char** argv) {
|
||||
path_t filter_filename;
|
||||
path_t default_material_filename;
|
||||
path_t log_file;
|
||||
path_t cache_file;
|
||||
std::string log_format;
|
||||
std::string geometry_kernel;
|
||||
auto& document_serializer_registry = ifcopenshell::serializers::document_serializer_registry_instance();
|
||||
auto& geometry_serializer_registry = ifcopenshell::serializers::geometry_serializer_registry_instance();
|
||||
#ifdef WITH_HDF5
|
||||
const bool supports_geometry_cache = true;
|
||||
#else
|
||||
const bool supports_geometry_cache = false;
|
||||
#endif
|
||||
|
||||
po::options_description generic_options("Command line options");
|
||||
verbosity_counter vcounter;
|
||||
@@ -302,10 +296,6 @@ int main(int argc, char** argv) {
|
||||
("no-progress", "suppress possible progress bar type of prints that use carriage return")
|
||||
("log-format", po::value<std::string>(&log_format), "log format: plain or json")
|
||||
("log-file", new po::typed_value<path_t, char_t>(&log_file), "redirect log output to file");
|
||||
if (supports_geometry_cache) {
|
||||
generic_options.add_options()
|
||||
("cache", "cache geometry creation. Use --cache-file to specify cache file path.");
|
||||
}
|
||||
|
||||
po::options_description fileio_options;
|
||||
fileio_options.add_options()
|
||||
@@ -316,10 +306,6 @@ int main(int argc, char** argv) {
|
||||
("output-file", new po::typed_value<path_t, char_t>(0), "output geometry file")
|
||||
("stream", "Use streaming conversion when supported (RocksDB uses it automatically)")
|
||||
;
|
||||
if (supports_geometry_cache) {
|
||||
fileio_options.add_options()
|
||||
("cache-file", new po::typed_value<path_t, char_t>(&cache_file), "geometry cache file");
|
||||
}
|
||||
|
||||
po::options_description ifc_options("IFC options");
|
||||
ifc_options.add_options()
|
||||
@@ -907,44 +893,6 @@ int main(int argc, char** argv) {
|
||||
context_iterator.reset(new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(ifc_file, geometry_kernel, geometry_settings), geometry_settings, ifc_file, filter_funcs, num_threads));
|
||||
}
|
||||
|
||||
#ifdef WITH_HDF5
|
||||
boost::shared_ptr<GeometrySerializer> cache;
|
||||
const bool use_cache = supports_geometry_cache && context_iterator && (vmap.count("cache-file") || vmap.count("cache"));
|
||||
if (use_cache) {
|
||||
const path_t CACHE = ifcopenshell::path::from_utf8(".cache");
|
||||
const path_t HDF = ifcopenshell::path::from_utf8(".h5");
|
||||
if (!vmap.count("cache-file")) {
|
||||
cache_file = input_filename + CACHE + HDF;
|
||||
}
|
||||
|
||||
try {
|
||||
ifcopenshell::serializers::geometry_serializer_context cache_context{
|
||||
ifcopenshell::path::to_utf8(cache_file),
|
||||
ifcopenshell::path::to_utf8(cache_file),
|
||||
geometry_settings,
|
||||
serializer_settings
|
||||
};
|
||||
cache = geometry_serializer_registry.create(".h5", cache_context);
|
||||
} catch (const std::exception& e) {
|
||||
cerr_ << "[error] Unable to initialize geometry cache: " << e.what() << std::endl;
|
||||
serializer.reset();
|
||||
ifcopenshell::path::delete_file(ifcopenshell::path::to_utf8(output_temp_filename));
|
||||
write_log(!quiet);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!cache || !cache->ready()) {
|
||||
cerr_ << "[error] Unable to initialize geometry cache serializer\n";
|
||||
serializer.reset();
|
||||
ifcopenshell::path::delete_file(ifcopenshell::path::to_utf8(output_temp_filename));
|
||||
write_log(!quiet);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
context_iterator->set_cache(cache.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
logger::message(logger::LOG_PERF, "file geometry conversion");
|
||||
|
||||
if (context_iterator && !context_iterator->initialize()) {
|
||||
|
||||
@@ -28,9 +28,6 @@ endif()
|
||||
if(WITH_MANIFOLD)
|
||||
target_compile_definitions(IfcGeom PUBLIC IFOPSH_WITH_MANIFOLD)
|
||||
endif()
|
||||
if(HDF5_SUPPORT)
|
||||
target_compile_definitions(IfcGeom PUBLIC WITH_HDF5)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
find_package(Threads)
|
||||
|
||||
@@ -362,7 +362,7 @@ void IfcGeom::Iterator::create_element_(ifcopenshell::geometry::Converter* kerne
|
||||
|
||||
logger::set_product(product);
|
||||
|
||||
IfcGeom::BRepElement* brep = static_cast<IfcGeom::BRepElement*>(decorate_with_cache_(GeometrySerializer::READ_BREP, (std::string)product.as<express::Entity>().get("GlobalId"), std::to_string(rep->item->instance.id()), [kernel, settings, product, place, rep]() {
|
||||
IfcGeom::BRepElement* brep = static_cast<IfcGeom::BRepElement*>(create_processed_element_([kernel, settings, product, place, rep]() {
|
||||
return kernel->create_brep_for_representation_and_product(rep->item, product, place);
|
||||
}));
|
||||
|
||||
@@ -385,7 +385,7 @@ void IfcGeom::Iterator::create_element_(ifcopenshell::geometry::Converter* kerne
|
||||
const express::Base product2 = p.first;
|
||||
const auto& place2 = p.second;
|
||||
|
||||
IfcGeom::BRepElement* brep2 = static_cast<IfcGeom::BRepElement*>(decorate_with_cache_(GeometrySerializer::READ_BREP, (std::string)product2.as<express::Entity>().get("GlobalId"), std::to_string(rep->item->instance.id()), [kernel, settings, product2, place2, brep]() {
|
||||
IfcGeom::BRepElement* brep2 = static_cast<IfcGeom::BRepElement*>(create_processed_element_([kernel, settings, product2, place2, brep]() {
|
||||
return kernel->create_brep_for_processed_representation(product2, place2, brep);
|
||||
}));
|
||||
if (brep2) {
|
||||
@@ -410,14 +410,7 @@ IfcGeom::Element* IfcGeom::Iterator::process_based_on_settings(ifcopenshell::geo
|
||||
return nullptr;
|
||||
}
|
||||
} else if (settings.get<ifcopenshell::geometry::settings::IteratorOutput>().get() == ifcopenshell::geometry::settings::TRIANGULATED) {
|
||||
// the part before the hyphen is the representation id
|
||||
auto gid2 = elem->geometry().id();
|
||||
auto hyphen = gid2.find("-");
|
||||
if (hyphen != std::string::npos) {
|
||||
gid2 = gid2.substr(0, hyphen);
|
||||
}
|
||||
|
||||
return decorate_with_cache_(GeometrySerializer::READ_TRIANGULATION, elem->guid(), gid2, [elem, previous]() {
|
||||
return create_processed_element_([elem, previous]() {
|
||||
try {
|
||||
if (!previous) {
|
||||
return new TriangulationElement(*elem);
|
||||
|
||||
+2
-40
@@ -66,7 +66,6 @@
|
||||
#include "../ifcgeom/taxonomy.h"
|
||||
#include "../ifcgeom/Converter.h"
|
||||
#include "../ifcgeom/abstract_mapping.h"
|
||||
#include "../ifcgeom/GeometrySerializer.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
@@ -104,8 +103,6 @@ namespace IfcGeom {
|
||||
|
||||
class IFC_GEOM_API Iterator {
|
||||
private:
|
||||
GeometrySerializer* cache_ = nullptr;
|
||||
|
||||
std::atomic<bool> finished_{ false };
|
||||
std::atomic<bool> terminating_{ false };
|
||||
std::atomic<bool> had_error_processing_elements_ { false };
|
||||
@@ -153,44 +150,11 @@ namespace IfcGeom {
|
||||
|
||||
// Should not be destructed because, destructor is blocking
|
||||
std::future<void> init_future_;
|
||||
std::mutex caching_mutex_;
|
||||
|
||||
std::array<std::chrono::high_resolution_clock::time_point, 4> time_points;
|
||||
|
||||
template <typename Fn>
|
||||
Element* decorate_with_cache_(GeometrySerializer::read_type rt, const std::string& product_guid, const std::string& representation_id, Fn f) {
|
||||
|
||||
bool read_from_cache = false;
|
||||
Element* element = nullptr;
|
||||
|
||||
#ifdef WITH_HDF5
|
||||
if (cache_) {
|
||||
std::lock_guard<std::mutex> lk(caching_mutex_);
|
||||
|
||||
auto from_cache = cache_->read(*ifc_file, product_guid, representation_id, rt);
|
||||
if (from_cache) {
|
||||
read_from_cache = true;
|
||||
element = from_cache;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!read_from_cache) {
|
||||
element = f();
|
||||
}
|
||||
|
||||
#ifdef WITH_HDF5
|
||||
if (cache_ && !read_from_cache && element) {
|
||||
std::lock_guard<std::mutex> lk(caching_mutex_);
|
||||
|
||||
if (rt == GeometrySerializer::READ_TRIANGULATION) {
|
||||
cache_->write((IfcGeom::TriangulationElement*)element);
|
||||
} else {
|
||||
cache_->write((IfcGeom::BRepElement*)element);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return element;
|
||||
Element* create_processed_element_(Fn f) {
|
||||
return f();
|
||||
}
|
||||
|
||||
express::Base create_shape_model_for_next_entity();
|
||||
@@ -244,8 +208,6 @@ namespace IfcGeom {
|
||||
|
||||
~Iterator();
|
||||
|
||||
void set_cache(GeometrySerializer* cache) { cache_ = cache; }
|
||||
|
||||
std::vector<ifcopenshell::geometry::taxonomy::item::ptr> get_task_items() const {
|
||||
std::vector<ifcopenshell::geometry::taxonomy::item::ptr> items;
|
||||
items.reserve(tasks_.size());
|
||||
|
||||
@@ -64,11 +64,6 @@
|
||||
#include <IntTools_FaceFace.hxx>
|
||||
#include "clash_utils.h"
|
||||
|
||||
#ifdef WITH_HDF5
|
||||
#include "H5Cpp.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace IfcGeom {
|
||||
namespace {
|
||||
|
||||
@@ -1498,225 +1493,6 @@ namespace IfcGeom {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_HDF5
|
||||
void write_h5() {
|
||||
H5::H5File file("filename.h5", H5F_ACC_TRUNC);
|
||||
H5::Group shapes = file.createGroup("/shapes");
|
||||
|
||||
std::set<std::string> processed_geometry_ids;
|
||||
std::vector<int> element_shape_ids;
|
||||
std::unordered_map<std::string, int> geometry_id_to_shape_id;
|
||||
int geometry_index = 0;
|
||||
|
||||
std::vector<std::vector<float>> matrices;
|
||||
std::vector<std::array<float, 4>> colours;
|
||||
std::vector<std::string> names;
|
||||
std::vector<std::string> global_ids;
|
||||
|
||||
const float tolerance = 0.01f; // Tolerance value for comparison
|
||||
|
||||
for (const auto& elem : triangulation_elements_) {
|
||||
const auto geometry_id = elem->geometry().id();
|
||||
|
||||
const auto& placement = placements_[elem->product()];
|
||||
{
|
||||
decltype(matrices)::value_type m;
|
||||
for (size_t i = 0; i < 16; ++i) {
|
||||
m.push_back(static_cast<float>(placement->ccomponents().data()[i]));
|
||||
}
|
||||
matrices.push_back(m);
|
||||
}
|
||||
|
||||
names.push_back(names_[elem->product()]);
|
||||
global_ids.push_back(global_ids_[elem->product()]);
|
||||
|
||||
if (processed_geometry_ids.find(geometry_id) != processed_geometry_ids.end()) {
|
||||
element_shape_ids.push_back(geometry_id_to_shape_id[geometry_id]);
|
||||
continue;
|
||||
}
|
||||
|
||||
processed_geometry_ids.insert(geometry_id);
|
||||
H5::Group group = shapes.createGroup(std::to_string(geometry_index));
|
||||
geometry_id_to_shape_id[geometry_id] = geometry_index;
|
||||
element_shape_ids.push_back(geometry_index);
|
||||
|
||||
geometry_index++;
|
||||
|
||||
const auto& faces = local_faces_[geometry_id];
|
||||
const auto& verts = local_verts_[geometry_id];
|
||||
const auto& materials = local_materials_[geometry_id];
|
||||
const auto& material_ids = local_material_ids_[geometry_id];
|
||||
|
||||
std::vector<float> verts_float(verts.size());
|
||||
std::transform(verts.begin(), verts.end(), verts_float.begin(),
|
||||
[](double val) { return static_cast<float>(val); });
|
||||
|
||||
// Write faces
|
||||
size_t total_verts = verts.size() / 3;
|
||||
hsize_t faces_dims[1] = {faces.size()};
|
||||
H5::DataSpace faces_dataspace(1, faces_dims);
|
||||
H5::DSetCreatPropList faces_propList;
|
||||
faces_propList.setChunk(1, faces_dims);
|
||||
faces_propList.setDeflate(9);
|
||||
if (total_verts < (1 << 8)) {
|
||||
H5::DataType dtype = H5::PredType::NATIVE_UINT8;
|
||||
std::vector<uint8_t> faces_dtype(faces.begin(), faces.end());
|
||||
H5::DataSet faces_dataset = group.createDataSet("faces", dtype, faces_dataspace, faces_propList);
|
||||
faces_dataset.write(faces_dtype.data(), dtype);
|
||||
} else if (total_verts < (1 << 16)) {
|
||||
H5::DataType dtype = H5::PredType::NATIVE_UINT16;
|
||||
std::vector<uint16_t> faces_dtype(faces.begin(), faces.end());
|
||||
H5::DataSet faces_dataset = group.createDataSet("faces", dtype, faces_dataspace, faces_propList);
|
||||
faces_dataset.write(faces_dtype.data(), dtype);
|
||||
} else {
|
||||
H5::DataType dtype = H5::PredType::NATIVE_UINT32;
|
||||
H5::DataSet faces_dataset = group.createDataSet("faces", dtype, faces_dataspace, faces_propList);
|
||||
faces_dataset.write(faces.data(), dtype);
|
||||
}
|
||||
|
||||
// Write verts
|
||||
H5::DataType dtype = H5::PredType::NATIVE_FLOAT;
|
||||
hsize_t dims[1] = {verts.size()};
|
||||
H5::DataSpace dataspace(1, dims);
|
||||
H5::DSetCreatPropList propList;
|
||||
propList.setChunk(1, dims);
|
||||
propList.setDeflate(9);
|
||||
H5::DataSet dataset = group.createDataSet("verts", dtype, dataspace, propList);
|
||||
dataset.write(verts_float.data(), H5::PredType::NATIVE_FLOAT);
|
||||
|
||||
// Write materials
|
||||
std::vector<uint8_t> material_keys;
|
||||
for (const auto& material : materials) {
|
||||
float alpha = 1.0;
|
||||
if (material->has_transparency() && material->transparency > 0) {
|
||||
alpha = 1.0 - material->transparency;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
bool is_existing_colour = false;
|
||||
for (const auto& colour : colours) {
|
||||
if (std::abs(colour[0] - static_cast<float>(material->diffuse.ccomponents()[0])) < tolerance
|
||||
&& std::abs(colour[1] - static_cast<float>(material->diffuse.ccomponents()[1])) < tolerance
|
||||
&& std::abs(colour[2] - static_cast<float>(material->diffuse.ccomponents()[2])) < tolerance
|
||||
&& std::abs(colour[3] - alpha) < tolerance) {
|
||||
is_existing_colour = true;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if ( ! is_existing_colour) {
|
||||
colours.push_back({
|
||||
static_cast<float>(material->diffuse.ccomponents()[0]),
|
||||
static_cast<float>(material->diffuse.ccomponents()[1]),
|
||||
static_cast<float>(material->diffuse.ccomponents()[2]),
|
||||
alpha});
|
||||
}
|
||||
material_keys.push_back(static_cast<decltype(material_keys)::value_type>(i));
|
||||
}
|
||||
|
||||
size_t total_material_keys = material_keys.size();
|
||||
if (total_material_keys) {
|
||||
hsize_t dims[1] = {material_keys.size()};
|
||||
H5::DataSpace dataspace(1, dims);
|
||||
H5::DSetCreatPropList propList;
|
||||
propList.setChunk(1, dims);
|
||||
propList.setDeflate(9);
|
||||
H5::DataType dtype = H5::PredType::NATIVE_UINT8;
|
||||
H5::DataSet dataset = group.createDataSet("materials", dtype, dataspace, propList);
|
||||
dataset.write(material_keys.data(), dtype);
|
||||
}
|
||||
|
||||
if (total_material_keys > 1) {
|
||||
hsize_t dims[1] = {material_ids.size()};
|
||||
H5::DataSpace dataspace(1, dims);
|
||||
H5::DSetCreatPropList propList;
|
||||
propList.setChunk(1, dims);
|
||||
propList.setDeflate(9);
|
||||
H5::DataType dtype = H5::PredType::NATIVE_UINT8;
|
||||
H5::DataSet dataset = group.createDataSet("material_ids", dtype, dataspace, propList);
|
||||
std::vector<uint8_t> data_dtype(material_ids.begin(), material_ids.end());
|
||||
dataset.write(data_dtype.data(), dtype);
|
||||
}
|
||||
}
|
||||
|
||||
// Write GlobalIds
|
||||
std::vector<uint8_t> uuids_array;
|
||||
for (const auto& id_str : global_ids) {
|
||||
for (size_t i = 0; i < id_str.length(); i += 2) {
|
||||
uuids_array.push_back(std::stoi(id_str.substr(i, 2), 0, 16));
|
||||
}
|
||||
}
|
||||
|
||||
hsize_t global_ids_dims[2] = {global_ids.size(), 16}; // 16 bytes per UUID
|
||||
H5::DataSpace global_ids_dataspace(2, global_ids_dims);
|
||||
H5::DataSet global_ids_dataset = file.createDataSet("element_global_ids", H5::PredType::NATIVE_UINT8, global_ids_dataspace);
|
||||
global_ids_dataset.write(uuids_array.data(), H5::PredType::NATIVE_UINT8);
|
||||
|
||||
// Write names
|
||||
H5::StrType strType(H5::PredType::C_S1, H5T_VARIABLE);
|
||||
hsize_t names_dims[1] = {names.size()};
|
||||
H5::DataSpace names_dataspace(1, names_dims);
|
||||
H5::DataSet names_dataset = file.createDataSet("element_names", strType, names_dataspace);
|
||||
std::vector<const char*> cstr_names;
|
||||
for (const auto& name : names) {
|
||||
cstr_names.push_back(name.c_str());
|
||||
}
|
||||
names_dataset.write(&cstr_names[0], strType);
|
||||
|
||||
// Write matrices
|
||||
std::vector<float> flat_matrices;
|
||||
for (const auto& matrix : matrices) {
|
||||
flat_matrices.insert(flat_matrices.end(), matrix.begin(), matrix.end());
|
||||
}
|
||||
hsize_t dims[2] = {matrices.size(), matrices[0].size()};
|
||||
H5::DataSpace dataspace(2, dims);
|
||||
H5::DSetCreatPropList propList;
|
||||
propList.setChunk(2, dims);
|
||||
propList.setDeflate(9);
|
||||
H5::DataSet dataset = file.createDataSet("element_matrices", H5::PredType::NATIVE_FLOAT, dataspace, propList);
|
||||
dataset.write(flat_matrices.data(), H5::PredType::NATIVE_FLOAT);
|
||||
|
||||
// Write element_shape_ids
|
||||
hsize_t element_shape_ids_dims[1] = {element_shape_ids.size()};
|
||||
H5::DataSpace element_shape_ids_dataspace(1, element_shape_ids_dims);
|
||||
H5::DSetCreatPropList element_shape_ids_propList;
|
||||
element_shape_ids_propList.setChunk(1, element_shape_ids_dims);
|
||||
element_shape_ids_propList.setDeflate(9);
|
||||
if (geometry_index < (1 << 8)) {
|
||||
H5::DataType dtype = H5::PredType::NATIVE_UINT8;
|
||||
std::vector<uint8_t> element_shape_ids_dtype(element_shape_ids.begin(), element_shape_ids.end());
|
||||
H5::DataSet element_shape_ids_dataset = file.createDataSet("element_shape_ids", dtype, element_shape_ids_dataspace, element_shape_ids_propList);
|
||||
element_shape_ids_dataset.write(element_shape_ids_dtype.data(), dtype);
|
||||
} else if (geometry_index < (1 << 16)) {
|
||||
H5::DataType dtype = H5::PredType::NATIVE_UINT16;
|
||||
std::vector<uint16_t> element_shape_ids_dtype(element_shape_ids.begin(), element_shape_ids.end());
|
||||
H5::DataSet element_shape_ids_dataset = file.createDataSet("element_shape_ids", dtype, element_shape_ids_dataspace, element_shape_ids_propList);
|
||||
element_shape_ids_dataset.write(element_shape_ids_dtype.data(), dtype);
|
||||
} else if (geometry_index < (1UL << 32)) {
|
||||
H5::DataType dtype = H5::PredType::NATIVE_UINT32;
|
||||
std::vector<uint32_t> element_shape_ids_dtype(element_shape_ids.begin(), element_shape_ids.end());
|
||||
H5::DataSet element_shape_ids_dataset = file.createDataSet("element_shape_ids", dtype, element_shape_ids_dataspace, element_shape_ids_propList);
|
||||
element_shape_ids_dataset.write(element_shape_ids_dtype.data(), dtype);
|
||||
}
|
||||
|
||||
// Write colours
|
||||
if (colours.size()) {
|
||||
std::vector<float> flat_colours;
|
||||
for (const auto& colour : colours) {
|
||||
flat_colours.insert(flat_colours.end(), colour.begin(), colour.end());
|
||||
}
|
||||
hsize_t colours_dims[2] = {colours.size(), colours[0].size()};
|
||||
H5::DataSpace colours_dataspace(2, colours_dims);
|
||||
H5::DSetCreatPropList colours_propList;
|
||||
colours_propList.setChunk(2, colours_dims);
|
||||
colours_propList.setDeflate(9);
|
||||
H5::DataSet colours_dataset = file.createDataSet("materials", H5::PredType::NATIVE_FLOAT, colours_dataspace, colours_propList);
|
||||
colours_dataset.write(flat_colours.data(), H5::PredType::NATIVE_FLOAT);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
void apply_matrix_to_flat_verts(const std::vector<T>& flat_list, const ifcopenshell::geometry::taxonomy::matrix4::ptr& matrix, std::vector<T>& result) {
|
||||
Eigen::Vector3d vin;
|
||||
|
||||
@@ -164,12 +164,6 @@ namespace ifcopenshell {
|
||||
return tree_.clash_clearance_many(set_a, set_b, clearance, check_all);
|
||||
}
|
||||
|
||||
#ifdef WITH_HDF5
|
||||
void write_h5() override {
|
||||
tree_.write_h5();
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
IfcGeom::opencascade_tree tree_;
|
||||
};
|
||||
|
||||
@@ -227,12 +227,6 @@ const std::vector<ifcopenshell::geometry::taxonomy::style::ptr>& IfcGeom::tree::
|
||||
return backend ? backend->styles() : empty_style_vector();
|
||||
}
|
||||
|
||||
#ifdef WITH_HDF5
|
||||
void IfcGeom::tree::write_h5() {
|
||||
impl_->backend(default_clash_backend_id).write_h5();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string IfcGeom::tree::uint8_to_b64(const std::vector<uint8_t>& uuids_array) const {
|
||||
std::string hex_str;
|
||||
hex_str.reserve(uuids_array.size() * 2);
|
||||
|
||||
@@ -100,10 +100,6 @@ namespace IfcGeom {
|
||||
void enable_face_styles(bool enable);
|
||||
const std::vector<ifcopenshell::geometry::taxonomy::style::ptr>& styles() const;
|
||||
|
||||
#ifdef WITH_HDF5
|
||||
void write_h5();
|
||||
#endif
|
||||
|
||||
std::string uint8_to_b64(const std::vector<uint8_t>& uuids_array) const;
|
||||
static bool is_manifold(const std::vector<int>& faces);
|
||||
|
||||
|
||||
@@ -104,12 +104,6 @@ const std::vector<ifcopenshell::geometry::taxonomy::style::ptr>& ifcopenshell::g
|
||||
unsupported_tree_operation(std::string(backend_id()), "styles()");
|
||||
}
|
||||
|
||||
#ifdef WITH_HDF5
|
||||
void ifcopenshell::geometry::trees::abstract_tree::write_h5() {
|
||||
unsupported_tree_operation(std::string(backend_id()), "write_h5()");
|
||||
}
|
||||
#endif
|
||||
|
||||
void ifcopenshell::geometry::trees::tree_registry::bind(const tree_info& info, create_fn create, const plugin::module& module) {
|
||||
entry entry;
|
||||
entry.info_ = info;
|
||||
|
||||
@@ -70,9 +70,6 @@ namespace ifcopenshell {
|
||||
virtual void enable_face_styles(bool enable);
|
||||
virtual const std::vector<ifcopenshell::geometry::taxonomy::style::ptr>& styles() const;
|
||||
|
||||
#ifdef WITH_HDF5
|
||||
virtual void write_h5();
|
||||
#endif
|
||||
};
|
||||
|
||||
class IFC_GEOM_API tree_registry {
|
||||
|
||||
@@ -2,7 +2,7 @@ IfcConvert
|
||||
==========
|
||||
|
||||
IfcConvert is a command-line application for converting IFC geometry into file
|
||||
formats such as OBJ, DAE, GLB, STP, IGS, XML, SVG, H5, TTL/WKT, and IFC-SPF itself.
|
||||
formats such as OBJ, DAE, GLB, STP, IGS, XML, SVG, TTL/WKT, and IFC-SPF itself.
|
||||
|
||||
For other formats, you may use other IfcOpenShell utilities as shown in the
|
||||
table below.
|
||||
@@ -11,8 +11,8 @@ table below.
|
||||
| From Format | To Format | Tool |
|
||||
+=========================+=========================+======================+
|
||||
| .ifc | .obj, .dae, .glb, .stp, | IfcConvert |
|
||||
| | .igs, .xml, .svg, .h5, | |
|
||||
| | .ttl, .ifc, .rdb, | |
|
||||
| | .igs, .xml, .svg, .ttl, | |
|
||||
| | .ifc, .rdb, | |
|
||||
| | .json (xeokit) | |
|
||||
+-------------------------+-------------------------+----------------------+
|
||||
| .ifc | .dae, .abc, .usd, .obj, | Bonsai_ |
|
||||
|
||||
@@ -83,7 +83,6 @@ CLI Manual
|
||||
.json JSON Property definitions and decomposition tree in xeokit json format
|
||||
.rdb RocksDB RocksDB Key-Value store serialization of IFC data
|
||||
.svg SVG Scalable Vector Graphics (2D floor plan)
|
||||
.h5 HDF Hierarchical Data Format storing positions, normals and indices
|
||||
.ttl TTL/WKT RDF Turtle with Well-Known-Text geometry
|
||||
.ifc IFC-SPF Industry Foundation Classes
|
||||
|
||||
|
||||
@@ -29,8 +29,6 @@ IfcOpenShell depends on:
|
||||
- (Optional) `SWIG <http://www.swig.org/>`__ and `Python
|
||||
<https://www.python.org/>`__ - for building the IfcOpenShell Python interface
|
||||
and use in Bonsai
|
||||
- (Optional) `HDF5 <https://www.hdfgroup.org/solutions/hdf5>`__ - for caching
|
||||
geometry using the HDF5 format
|
||||
|
||||
Compiling on Linux
|
||||
------------------
|
||||
@@ -125,13 +123,7 @@ operating systems. GCC (4.7 or newer) or Clang (any version) is required.
|
||||
|
||||
sudo apt-get install python-all-dev swig
|
||||
|
||||
6. For building support for HDF5 caching (ON by default), install dependencies:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo apt-get install libhdf5-dev libaec-dev zlibc
|
||||
|
||||
7. Compile IfcOpenShell itself.
|
||||
6. Compile IfcOpenShell itself.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@@ -149,11 +141,6 @@ operating systems. GCC (4.7 or newer) or Clang (any version) is required.
|
||||
-DOPENCOLLADA_LIBRARY_DIR="/usr/local/lib/opencollada" \
|
||||
-DPCRE_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu/ \
|
||||
\
|
||||
# Optional HDF5 support
|
||||
-DHDF5_SUPPORT=On \
|
||||
-DHDF5_LIBRARIES="/usr/local/hdf5/lib/libhdf5_cpp.so;/usr/local/hdf5/lib/libhdf5.so;/usr/lib64/libz.so;/usr/lib64/libsz.so;/usr/lib64/libaec.so" \
|
||||
-DHDF5_INCLUDE_DIR="/usr/local/hdf5/include" \
|
||||
\
|
||||
-DCGAL_INCLUDE_DIR=/usr/include \
|
||||
-DGMP_INCLUDE_DIR=/usr/include \
|
||||
-DMPFR_INCLUDE_DIR=/usr/include \
|
||||
@@ -187,7 +174,7 @@ GCC (4.7 or newer) or Clang (any version) is required.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
brew install boost cmake python3 cgal ftgl gmp libaec opencascade swig hdf5 zlib eigen
|
||||
brew install boost cmake python3 cgal ftgl gmp opencascade swig zlib eigen
|
||||
# homebrew automatically links most libraries, except some keg-only ones
|
||||
brew link zlib --force
|
||||
|
||||
@@ -209,8 +196,6 @@ GCC (4.7 or newer) or Clang (any version) is required.
|
||||
-DCGAL_INCLUDE_DIR=/opt/homebrew/include/ \
|
||||
-DGMP_LIBRARY_DIR=/opt/homebrew/lib/ \
|
||||
-DMPFR_LIBRARY_DIR=/opt/homebrew/lib/ \
|
||||
-DHDF5_LIBRARY_DIR=/opt/homebrew/lib/ \
|
||||
-DHDF5_INCLUDE_DIR=/opt/homebrew/include/ \
|
||||
-DEIGEN_DIR=/opt/homebrew/Cellar/eigen/3.4.0_1/include/eigen3 \
|
||||
-DCOLLADA_SUPPORT=0
|
||||
# `sysctl -n hw.ncpu` returns the number of cpu cores on macOS
|
||||
|
||||
@@ -38,7 +38,7 @@ IfcOpenShell has a huge amount of unique features and capabilities not found in
|
||||
- All tools can be used either as a developer library, through a command line interface, or using a rich graphical interface. Whether you're deploying headless server tools for your own pipeline, writing your own apps, or an end-user, there's something for you.
|
||||
- Supports IFC2X3, IFC4, and IFC4.3. Custom schemas (such as experimental or draft schemas) may be loaded at run-time instead of having to recompile.
|
||||
- Built-in IFC validation is possible from basic syntax validation to more detailed "Where Rule" checks. This is the same validation that powers the official buildingSMART validation engine.
|
||||
- Read and write IFC-SPF, IFCJSON, IFCXML, IFCHDF5, MySQL, and SQLite.
|
||||
- Read and write IFC-SPF, IFCJSON, IFCXML, MySQL, and SQLite.
|
||||
- High level API for hundreds of tasks. Perform complex authoring like copying objects, cost calculation, or 4D simulation with one line of code. Imagine a complete native IFC authoring and editing platform where every function is available to you as a library.
|
||||
- Convert parametric geometry into explicit geometry for any CAD system from booleans to complex sweeps. Geometry has been battle-tested over many years to accommodate complex geometric edge cases with an extensive test suite.
|
||||
- Geometry may be converted into voxels and analysed through voxels to resolve complex non-manifold geometry and precision issues. This analysis may be used from things like head height calculations, formwork analysis, to egress distances.
|
||||
|
||||
@@ -56,7 +56,6 @@ class draw_settings:
|
||||
space_areas: bool = False
|
||||
door_arcs: bool = False
|
||||
subtract_before_hlr: bool = False
|
||||
cache: bool = False
|
||||
css: str = ""
|
||||
storey_heights: str = "none"
|
||||
storey_filter: str = ""
|
||||
@@ -157,12 +156,6 @@ def main(
|
||||
)
|
||||
)
|
||||
|
||||
if settings.cache:
|
||||
serializer_settings = ifcopenshell.geom.serializer_settings()
|
||||
cache = ifcopenshell.geom.serializers.hdf5("cache.h5", geom_settings, serializer_settings)
|
||||
for it in iterators:
|
||||
it.set_cache(cache)
|
||||
|
||||
# Initialize serializer
|
||||
buffer = ifcopenshell.geom.serializers.buffer()
|
||||
serialiser_settings = ifcopenshell.geom.serializer_settings()
|
||||
|
||||
@@ -555,8 +555,6 @@ def iterate(
|
||||
exclude: Optional[Union[list[entity_instance], list[str]]] = None,
|
||||
*,
|
||||
with_progress: Literal[False] = False,
|
||||
cache: Optional[str] = None,
|
||||
serializer_settings: Optional[serializer_settings] = None,
|
||||
geometry_library: GEOMETRY_LIBRARY = "opencascade",
|
||||
) -> Generator[IteratorOutput, None, None]: ...
|
||||
@overload
|
||||
@@ -568,8 +566,6 @@ def iterate(
|
||||
exclude: Optional[Union[list[entity_instance], list[str]]] = None,
|
||||
*,
|
||||
with_progress: Literal[True] = True,
|
||||
cache: Optional[str] = None,
|
||||
serializer_settings: Optional[serializer_settings] = None,
|
||||
geometry_library: GEOMETRY_LIBRARY = "opencascade",
|
||||
) -> Generator[tuple[int, IteratorOutput], None, None]: ...
|
||||
@overload
|
||||
@@ -581,8 +577,6 @@ def iterate(
|
||||
exclude: Optional[Union[list[entity_instance], list[str]]] = None,
|
||||
*,
|
||||
with_progress: bool = False,
|
||||
cache: Optional[str] = None,
|
||||
serializer_settings: Optional[serializer_settings] = None,
|
||||
geometry_library: GEOMETRY_LIBRARY = "opencascade",
|
||||
) -> Generator[Union[IteratorOutput, tuple[int, IteratorOutput]], None, None]: ...
|
||||
def iterate(
|
||||
@@ -593,20 +587,10 @@ def iterate(
|
||||
exclude: Optional[Union[list[entity_instance], list[str]]] = None,
|
||||
*,
|
||||
with_progress: bool = False,
|
||||
cache: Optional[str] = None,
|
||||
serializer_settings: Optional[serializer_settings] = None,
|
||||
geometry_library: GEOMETRY_LIBRARY = "opencascade",
|
||||
) -> Generator[Union[IteratorOutput, tuple[int, IteratorOutput]], None, None]:
|
||||
"""Get a geometry iterator for the provided file.
|
||||
|
||||
:param cache: .h5 cache filepath (might not exist, will be created).
|
||||
:param serializer_settings: Settings for cache serializer. Required if `cache` is provided.
|
||||
"""
|
||||
"""Get a geometry iterator for the provided file."""
|
||||
it = iterator(settings, file_or_filename, num_threads, include, exclude, geometry_library)
|
||||
if cache:
|
||||
assert serializer_settings, "`serializer_settings` argument is not optional if `cache` is provided."
|
||||
hdf5_cache = serializers.hdf5(cache, settings, serializer_settings)
|
||||
it.set_cache(hdf5_cache)
|
||||
yield from consume_iterator(it, with_progress=with_progress)
|
||||
|
||||
|
||||
@@ -677,9 +661,6 @@ class _serializers_meta(type):
|
||||
"ttl": "ttl",
|
||||
"gltf": "glb",
|
||||
"glb": "glb",
|
||||
"hdf": "h5",
|
||||
"hdf5": "h5",
|
||||
"h5": "h5",
|
||||
"collada": "dae",
|
||||
"dae": "dae",
|
||||
"stp": "stp",
|
||||
@@ -711,9 +692,6 @@ class serializers(metaclass=_serializers_meta):
|
||||
ext = filepath.rsplit(".", 1)[-1].lower()
|
||||
mapping = {
|
||||
"glb": "gltf",
|
||||
"hdf": "hdf5",
|
||||
"h5": "hdf5",
|
||||
"hdf5": "hdf5",
|
||||
"obj": "obj",
|
||||
"svg": "svg",
|
||||
"ttl": "ttl",
|
||||
|
||||
@@ -298,18 +298,6 @@ class GltfSerializer(WriteOnlyGeometrySerializer):
|
||||
def write(self, *args): ...
|
||||
def writeHeader(self): ...
|
||||
|
||||
class HdfSerializer(GeometrySerializer):
|
||||
def __init__(self, hdf_filename, geometry_settings, settings, read_only=False): ...
|
||||
def finalize(self): ...
|
||||
def isTesselated(self): ...
|
||||
def read(self, *args): ...
|
||||
def ready(self): ...
|
||||
def remove(self, guid: str) -> None: ...
|
||||
def setFile(self, arg2): ...
|
||||
def setUnitNameAndMagnitude(self, arg2, arg3): ...
|
||||
def write(self, *args): ...
|
||||
def writeHeader(self): ...
|
||||
|
||||
class IfcBaseEntity(entity_instance):
|
||||
def __init__(self, *args, **kwargs): ...
|
||||
def declaration(self): ...
|
||||
@@ -383,7 +371,6 @@ class Iterator:
|
||||
"""
|
||||
...
|
||||
|
||||
def set_cache(self, cache: Union[GeometrySerializer, None]) -> None: ...
|
||||
def unit_magnitude(self): ...
|
||||
def unit_name(self): ...
|
||||
|
||||
|
||||
@@ -150,8 +150,7 @@ cmake ../cmake \
|
||||
-DBUILD_DOCUMENTATION=OFF \
|
||||
-DBUILD_EXAMPLES=OFF \
|
||||
-DCOLLADA_SUPPORT=OFF \
|
||||
-DGLTF_SUPPORT=OFF \
|
||||
-DHDF5_SUPPORT=OFF
|
||||
-DGLTF_SUPPORT=OFF
|
||||
|
||||
make -j$(nproc) IfcViewer
|
||||
```
|
||||
|
||||
@@ -230,6 +230,7 @@
|
||||
#include "../ifcgeom/Iterator.h"
|
||||
#include "../ifcgeom/ConversionResult.h"
|
||||
#include "../ifcgeom/hybrid_kernel.h"
|
||||
#include "../ifcgeom/GeometrySerializer.h"
|
||||
|
||||
#include "../ifcparse/express.h"
|
||||
#include "../ifcparse/file.h"
|
||||
|
||||
@@ -88,10 +88,6 @@ if(WITH_OPENCASCADE AND NOT WASM_BUILD)
|
||||
add_geometry_serializer_plugin(geometry_serializer_stp "geometry.stp" SOURCES geometry_stp_plugin.cpp OpenCascadeBasedSerializer.cpp LIBRARIES ${opencascade_geometry_serializer_libraries})
|
||||
add_geometry_serializer_plugin(geometry_serializer_igs "geometry.igs" SOURCES geometry_igs_plugin.cpp OpenCascadeBasedSerializer.cpp LIBRARIES ${opencascade_geometry_serializer_libraries})
|
||||
add_geometry_serializer_plugin(geometry_serializer_svg "geometry.svg" SOURCES geometry_svg_plugin.cpp SvgSerializer.cpp util.cpp LIBRARIES ${opencascade_geometry_serializer_libraries})
|
||||
|
||||
if(HDF5_SUPPORT)
|
||||
add_geometry_serializer_plugin(geometry_serializer_hdf "geometry.h5" SOURCES geometry_hdf_plugin.cpp HdfSerializer.cpp LIBRARIES ${opencascade_geometry_serializer_libraries} ${HDF5_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
install(TARGETS ${document_serializer_libraries} ${geometry_serializer_libraries})
|
||||
|
||||
@@ -1,728 +0,0 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#if defined(WITH_HDF5) && defined(IFOPSH_WITH_OPENCASCADE)
|
||||
|
||||
#include "HdfSerializer.h"
|
||||
|
||||
#include "../ifcgeom/IfcGeomRenderStyles.h"
|
||||
#include "../ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h"
|
||||
|
||||
#include "../ifcparse/utils.h"
|
||||
|
||||
#include <BRepTools_ShapeSet.hxx>
|
||||
#include <BinTools_ShapeSet.hxx>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <numeric>
|
||||
#include <functional>
|
||||
#include <cmath>
|
||||
|
||||
#ifdef USE_BINARY
|
||||
#define write_shape write_binary
|
||||
#define read_shape read_binary
|
||||
#else
|
||||
#define write_shape write_text
|
||||
#define read_shape read_text
|
||||
#endif
|
||||
|
||||
herr_t print_stack(hid_t /*estack*/, void*) {
|
||||
// For debugging: when using IfcConvert on Windows with wcout,
|
||||
// it's difficult to get console output of HDF5 stack traces.
|
||||
/*
|
||||
auto f = fopen("temp.txt", "w");
|
||||
H5Eprint(estack, f);
|
||||
fclose(f);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
HdfSerializer::HdfSerializer(const std::string& hdf_filename, const ifcopenshell::geometry::Settings& geometry_settings, const ifcopenshell::geometry::SerializerSettings& settings, bool read_only)
|
||||
: GeometrySerializer(geometry_settings, settings)
|
||||
, hdf_filename(hdf_filename)
|
||||
, settings_(settings)
|
||||
{
|
||||
H5E_auto2_t fn = &print_stack;
|
||||
H5::Exception::setAutoPrint(fn, nullptr);
|
||||
|
||||
try {
|
||||
file = H5::H5File(hdf_filename, read_only
|
||||
? H5F_ACC_RDONLY
|
||||
: (H5F_ACC_RDWR | H5F_ACC_CREAT));
|
||||
} catch (H5::Exception& e) {
|
||||
throw ifcopenshell::exception(e.getDetailMsg());
|
||||
}
|
||||
|
||||
str_type = H5::StrType(H5::PredType::C_S1, H5T_VARIABLE);
|
||||
|
||||
#ifdef USE_BINARY
|
||||
auto uint_type = H5::PredType::NATIVE_UINT8;
|
||||
shape_type = H5::VarLenType(&uint_type);
|
||||
#else
|
||||
shape_type = str_type;
|
||||
#endif
|
||||
|
||||
hsize_t dims_3[1]{ 3 };
|
||||
double3 = H5::ArrayType(H5::PredType::NATIVE_DOUBLE, 1, dims_3);
|
||||
|
||||
style_compound = H5::CompType(sizeof(surface_style_serialization));
|
||||
style_compound.insertMember("name", HOFFSET(surface_style_serialization, name), str_type);
|
||||
style_compound.insertMember("original_name", HOFFSET(surface_style_serialization, original_name), str_type);
|
||||
style_compound.insertMember("id", HOFFSET(surface_style_serialization, id), H5::PredType::NATIVE_INT);
|
||||
style_compound.insertMember("diffuse", HOFFSET(surface_style_serialization, diffuse), double3);
|
||||
style_compound.insertMember("specular", HOFFSET(surface_style_serialization, specular), double3);
|
||||
style_compound.insertMember("transparency", HOFFSET(surface_style_serialization, transparency), H5::PredType::NATIVE_DOUBLE);
|
||||
style_compound.insertMember("specularity", HOFFSET(surface_style_serialization, specularity), H5::PredType::NATIVE_DOUBLE);
|
||||
|
||||
hsize_t dims_4x4[2]{ 4, 4 };
|
||||
double4x4 = H5::ArrayType(H5::PredType::NATIVE_DOUBLE, 2, dims_4x4);
|
||||
|
||||
compound = H5::CompType(sizeof(brep_element));
|
||||
compound.insertMember("id", HOFFSET(brep_element, id), H5::PredType::NATIVE_INT);
|
||||
compound.insertMember("matrix", HOFFSET(brep_element, matrix), double4x4);
|
||||
compound.insertMember("shape_serialization", HOFFSET(brep_element, shape_serialization), shape_type);
|
||||
compound.insertMember("surface_style_id", HOFFSET(brep_element, surface_style), style_compound);
|
||||
}
|
||||
|
||||
bool HdfSerializer::ready() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void HdfSerializer::writeHeader() {
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <typename T>
|
||||
H5::DataType h5_datatype_for_cpp();
|
||||
|
||||
template <>
|
||||
H5::DataType h5_datatype_for_cpp<int>() {
|
||||
return H5::PredType::NATIVE_INT;
|
||||
}
|
||||
|
||||
template <>
|
||||
H5::DataType h5_datatype_for_cpp<uint64_t>() {
|
||||
return H5::PredType::NATIVE_UINT64;
|
||||
}
|
||||
|
||||
template <>
|
||||
H5::DataType h5_datatype_for_cpp<double>() {
|
||||
return H5::PredType::NATIVE_DOUBLE;
|
||||
}
|
||||
|
||||
template <>
|
||||
H5::DataType h5_datatype_for_cpp<std::string>() {
|
||||
return H5::StrType(H5::PredType::C_S1, H5T_VARIABLE);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void do_read(H5::Attribute& attr, T& val) {
|
||||
attr.read(h5_datatype_for_cpp<T>(), &val);
|
||||
}
|
||||
|
||||
template <>
|
||||
void do_read(H5::Attribute& attr, std::string& val) {
|
||||
attr.read(h5_datatype_for_cpp<std::string>(), val);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T read_scalar_attribute(H5::H5Object& l, const std::string& name) {
|
||||
auto attr = l.openAttribute(name);
|
||||
auto space = attr.getSpace();
|
||||
int rank = space.getSimpleExtentNdims();
|
||||
// A scalar dataspace, H5S_SCALAR, has a single element, though that
|
||||
// element may be of a complex datatype, such as a compound or array
|
||||
// datatype. By convention, the rank of a scalar dataspace is always
|
||||
// 0 (zero);
|
||||
if (rank != 0) {
|
||||
throw std::runtime_error("Invalid");
|
||||
}
|
||||
T val;
|
||||
do_read<T>(attr, val);
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
#include <BinTools.hxx>
|
||||
|
||||
namespace {
|
||||
// https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/Part/App/TopoShape.cpp
|
||||
TopoDS_Shape read_binary(const hvl_t& vlen) {
|
||||
std::string s((char*)vlen.p, (size_t)vlen.len);
|
||||
std::istringstream str(s);
|
||||
BinTools_ShapeSet theShapeSet;
|
||||
theShapeSet.Read(str);
|
||||
Standard_Integer shapeId = 0, locId = 0, orient = 0;
|
||||
BinTools::GetInteger(str, shapeId);
|
||||
if (shapeId <= 0 || shapeId > theShapeSet.NbShapes()) {
|
||||
throw std::runtime_error("");
|
||||
}
|
||||
|
||||
BinTools::GetInteger(str, locId);
|
||||
BinTools::GetInteger(str, orient);
|
||||
TopAbs_Orientation anOrient = static_cast<TopAbs_Orientation>(orient);
|
||||
|
||||
TopoDS_Shape shp = theShapeSet.Shape(shapeId);
|
||||
shp.Location(theShapeSet.Locations().Location(locId));
|
||||
shp.Orientation(anOrient);
|
||||
|
||||
return shp;
|
||||
}
|
||||
|
||||
// https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/Part/App/TopoShape.cpp
|
||||
void write_binary(TopoDS_Shape shp, std::string& s) {
|
||||
std::ostringstream out;
|
||||
|
||||
BinTools_ShapeSet theShapeSet;
|
||||
|
||||
Standard_Integer shapeId = theShapeSet.Add(shp);
|
||||
Standard_Integer locId = theShapeSet.Locations().Index(shp.Location());
|
||||
Standard_Integer orient = static_cast<int>(shp.Orientation());
|
||||
|
||||
theShapeSet.Write(out);
|
||||
BinTools::PutInteger(out, shapeId);
|
||||
BinTools::PutInteger(out, locId);
|
||||
BinTools::PutInteger(out, orient);
|
||||
|
||||
s = out.str();
|
||||
}
|
||||
|
||||
TopoDS_Shape read_text(const std::string& s) {
|
||||
std::stringstream stream(s);
|
||||
BRep_Builder B;
|
||||
TopoDS_Shape shp;
|
||||
BRepTools::Read(shp, stream, B);
|
||||
return shp;
|
||||
}
|
||||
|
||||
void write_text(TopoDS_Shape shp, std::string& out) {
|
||||
std::stringstream sstream;
|
||||
BRepTools::Write(shp, sstream);
|
||||
out = sstream.str();
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <typename T>
|
||||
std::vector<T> read_dataset(const H5::Group& group, const std::string& name) {
|
||||
auto ds = group.openDataSet(name);
|
||||
auto space = ds.getSpace();
|
||||
int rank = space.getSimpleExtentNdims();
|
||||
std::vector<hsize_t> dims(rank);
|
||||
space.getSimpleExtentDims(dims.data(), NULL);
|
||||
const hsize_t total = std::accumulate(dims.begin(), dims.end(), 1U, std::multiplies<hsize_t>());
|
||||
std::vector<T> result(total);
|
||||
ds.read(result.data(), h5_datatype_for_cpp<T>());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void HdfSerializer::read_surface_style(const surface_style_serialization& s,
|
||||
ifcopenshell::geometry::taxonomy::style& gss,
|
||||
ifcopenshell::file& f) {
|
||||
if (strlen(s.name) || s.id) {
|
||||
if (!std::isnan(s.diffuse[0])) {
|
||||
gss.diffuse = ifcopenshell::geometry::taxonomy::colour(s.diffuse[0], s.diffuse[1], s.diffuse[2]);
|
||||
}
|
||||
if (!std::isnan(s.specular[0])) {
|
||||
gss.specular = ifcopenshell::geometry::taxonomy::colour(s.specular[0], s.specular[1], s.specular[2]);
|
||||
}
|
||||
if (!std::isnan(s.transparency)) {
|
||||
gss.transparency = s.transparency;
|
||||
}
|
||||
if (!std::isnan(s.specularity)) {
|
||||
gss.specularity = s.specularity;
|
||||
}
|
||||
if (s.id != 0) {
|
||||
gss.instance = f.instance_by_id(s.id).as<express::Entity>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void HdfSerializer::remove(const std::string& guid) {
|
||||
if (H5Lexists(file.getId(), guid.c_str(), H5P_DEFAULT)) {
|
||||
file.unlink(guid);
|
||||
}
|
||||
}
|
||||
|
||||
IfcGeom::Element* HdfSerializer::read(ifcopenshell::file& f, const std::string& guid, const std::string& representation_id_str, read_type rt) {
|
||||
if (!H5Lexists(file.getId(), guid.c_str(), H5P_DEFAULT)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto element_group = file.openGroup(guid);
|
||||
if (!H5Lexists(element_group.getId(), representation_id_str.c_str(), H5P_DEFAULT)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int id = read_scalar_attribute<int>(element_group, "id");
|
||||
int parent_id = read_scalar_attribute<int>(element_group, "parent_id");
|
||||
std::string type = read_scalar_attribute<std::string>(element_group, "type");
|
||||
std::string name = read_scalar_attribute<std::string>(element_group, "name");
|
||||
std::string context = read_scalar_attribute<std::string>(element_group, "context");
|
||||
std::string unique_id = read_scalar_attribute<std::string>(element_group, "unique_id");
|
||||
|
||||
auto trsf = ifcopenshell::geometry::taxonomy::make<ifcopenshell::geometry::taxonomy::matrix4>();
|
||||
auto placeds = element_group.openDataSet(DATASET_NAME_PLACEMENT);
|
||||
double m44[4][4];
|
||||
placeds.read(m44, H5::PredType::NATIVE_DOUBLE);
|
||||
// @todo check
|
||||
trsf->components() << Eigen::Map<Eigen::Matrix4d>(&m44[0][0]);
|
||||
|
||||
auto representation_group = element_group.openGroup(representation_id_str);
|
||||
std::string geom_id = read_scalar_attribute<std::string>(representation_group, "geom_id");
|
||||
|
||||
auto inst = f.instance_by_id(id).as<express::Entity>();
|
||||
|
||||
boost::shared_ptr<IfcGeom::Representation::BRep> brep_geometry;
|
||||
boost::shared_ptr<IfcGeom::Representation::Triangulation> triangulation_geometry;
|
||||
|
||||
if (rt == READ_BREP) {
|
||||
auto it = brep_cache_.find(representation_id_str);
|
||||
if (it != brep_cache_.end()) {
|
||||
brep_geometry = it->second;
|
||||
}
|
||||
} else {
|
||||
auto it = triangulation_cache_.find(representation_id_str);
|
||||
if (it != triangulation_cache_.end()) {
|
||||
triangulation_geometry = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
if (rt == READ_BREP && !brep_geometry) {
|
||||
auto brepDataset = representation_group.openDataSet(DATASET_NAME_OCCT);
|
||||
|
||||
/*
|
||||
// @todo
|
||||
|
||||
static const auto ignored_settings =
|
||||
// Settings that do not affect storage of brep data
|
||||
IfcGeom::IteratorSettings::DISABLE_TRIANGULATION | IfcGeom::IteratorSettings::USE_BREP_DATA |
|
||||
// Settings that affect which representation is considered, but cache does not need to be complete
|
||||
IfcGeom::IteratorSettings::INCLUDE_CURVES | IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES |
|
||||
// Only affects triangulation
|
||||
IfcGeom::IteratorSettings::WELD_VERTICES | IfcGeom::IteratorSettings::NO_NORMALS |
|
||||
IfcGeom::IteratorSettings::GENERATE_UVS | IfcGeom::IteratorSettings::EDGE_ARROWS |
|
||||
// Is applied in the serializer
|
||||
IfcGeom::IteratorSettings::ELEMENT_HIERARCHY;
|
||||
|
||||
auto stored_settings = read_scalar_attribute<uint64_t>(brepDataset, "settings");
|
||||
auto requested_settings = settings_.get_raw();
|
||||
stored_settings &= ~ignored_settings;
|
||||
requested_settings &= ~ignored_settings;
|
||||
|
||||
// World coordinates can be applied post hoc
|
||||
if (stored_settings != requested_settings && (stored_settings | IfcGeom::IteratorSettings::USE_WORLD_COORDS) != requested_settings) {
|
||||
throw std::runtime_error("Settings mismatch");
|
||||
}
|
||||
*/
|
||||
|
||||
std::vector<brep_element> parts;
|
||||
{
|
||||
auto space = brepDataset.getSpace();
|
||||
int rank = space.getSimpleExtentNdims();
|
||||
|
||||
if (rank != 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<hsize_t> dims(rank);
|
||||
space.getSimpleExtentDims(dims.data(), NULL);
|
||||
|
||||
parts.resize(dims[0]);
|
||||
brepDataset.read(parts.data(), compound);
|
||||
}
|
||||
|
||||
IfcGeom::ConversionResults shapes;
|
||||
|
||||
for (auto& part : parts) {
|
||||
TopoDS_Shape shp = read_shape(part.shape_serialization);
|
||||
|
||||
// @todo check
|
||||
auto matrix = ifcopenshell::geometry::taxonomy::make<ifcopenshell::geometry::taxonomy::matrix4>();
|
||||
matrix->components() << Eigen::Map<Eigen::Matrix4d>(&part.matrix[0][0]);
|
||||
|
||||
auto style_ptr = ifcopenshell::geometry::taxonomy::make<ifcopenshell::geometry::taxonomy::style>();
|
||||
read_surface_style(part.surface_style, *style_ptr, f);
|
||||
|
||||
shapes.push_back(IfcGeom::ConversionResult(part.id, matrix, new ifcopenshell::geometry::OpenCascadeShape(shp), style_ptr));
|
||||
}
|
||||
|
||||
/*
|
||||
// @todo
|
||||
|
||||
// World coordinates can be applied post-hoc
|
||||
if (settings_.get(IfcGeom::IteratorSettings::USE_WORLD_COORDS) && !(stored_settings & IfcGeom::IteratorSettings::USE_WORLD_COORDS)) {
|
||||
for (IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++it) {
|
||||
it->prepend(trsf);
|
||||
}
|
||||
trsf = ifcopenshell::geometry::taxonomy::make<ifcopenshell::geometry::taxonomy::matrix4>();
|
||||
}
|
||||
*/
|
||||
|
||||
brep_geometry = boost::shared_ptr<IfcGeom::Representation::BRep>(new IfcGeom::Representation::BRep(geometry_settings(), type, geom_id, shapes));
|
||||
|
||||
/*
|
||||
// @todo
|
||||
if (!settings_.get(IfcGeom::IteratorSettings::USE_WORLD_COORDS)) {
|
||||
brep_cache_.insert({ representation_id_str, brep_geometry });
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (rt == READ_TRIANGULATION && !triangulation_geometry) {
|
||||
H5::Group meshGroup;
|
||||
try {
|
||||
meshGroup = representation_group.openGroup(GROUP_NAME_MESH);
|
||||
} catch (H5::Exception&) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto verts = read_dataset<double>(meshGroup, DATASET_NAME_POSITIONS);
|
||||
auto faces = read_dataset<int>(meshGroup, DATASET_NAME_INDICES);
|
||||
auto edges = read_dataset<int>(meshGroup, DATASET_NAME_EDGES);
|
||||
auto normals = read_dataset<double>(meshGroup, DATASET_NAME_NORMALS);
|
||||
auto uvcoords = read_dataset<double>(meshGroup, DATASET_NAME_UVCOORDS);
|
||||
auto material_ids = read_dataset<int>(meshGroup, DATASET_NAME_MATERIAL_IDS);
|
||||
auto item_ids = read_dataset<int>(meshGroup, DATASET_NAME_ITEM_IDS);
|
||||
auto edges_item_ids = read_dataset<int>(meshGroup, DATASET_NAME_EDGES_ITEM_IDS);
|
||||
|
||||
std::vector<surface_style_serialization> surface_styles;
|
||||
|
||||
{
|
||||
auto ds = meshGroup.openDataSet(DATASET_NAME_MATERIALS);
|
||||
auto space = ds.getSpace();
|
||||
int rank = space.getSimpleExtentNdims();
|
||||
|
||||
if (rank != 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<hsize_t> dims(rank);
|
||||
space.getSimpleExtentDims(dims.data(), NULL);
|
||||
|
||||
surface_styles.resize(dims[0]);
|
||||
ds.read(surface_styles.data(), style_compound);
|
||||
}
|
||||
|
||||
std::vector<ifcopenshell::geometry::taxonomy::style::ptr> surface_style_ptrs(surface_styles.size());
|
||||
|
||||
for (size_t i = 0; i < surface_styles.size(); ++i) {
|
||||
surface_style_ptrs[i] = ifcopenshell::geometry::taxonomy::make<ifcopenshell::geometry::taxonomy::style>();
|
||||
read_surface_style(surface_styles[i], *surface_style_ptrs[i], f);
|
||||
}
|
||||
|
||||
triangulation_geometry = boost::shared_ptr<IfcGeom::Representation::Triangulation>(new IfcGeom::Representation::Triangulation(
|
||||
geometry_settings_,
|
||||
type,
|
||||
geom_id,
|
||||
verts,
|
||||
faces,
|
||||
edges,
|
||||
normals,
|
||||
uvcoords,
|
||||
material_ids,
|
||||
surface_style_ptrs,
|
||||
item_ids
|
||||
, edges_item_ids
|
||||
));
|
||||
|
||||
triangulation_cache_.insert({ representation_id_str, triangulation_geometry });
|
||||
}
|
||||
|
||||
if (rt == READ_BREP) {
|
||||
return new IfcGeom::BRepElement(id, parent_id, name, type, guid, context, trsf, brep_geometry, inst);
|
||||
} else {
|
||||
return new IfcGeom::TriangulationElement(
|
||||
IfcGeom::Element(
|
||||
geometry_settings_,
|
||||
id,
|
||||
parent_id,
|
||||
name,
|
||||
type,
|
||||
guid,
|
||||
context,
|
||||
trsf,
|
||||
inst
|
||||
),
|
||||
triangulation_geometry
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
H5::Group HdfSerializer::write(const IfcGeom::Element* o) {
|
||||
try {
|
||||
return file.openGroup(o->guid());
|
||||
} catch (H5::Exception&) {}
|
||||
|
||||
H5::Group element_group = file.createGroup(o->guid());
|
||||
|
||||
typedef std::string const & (IfcGeom::Element::*string_member_fun)(void) const;
|
||||
typedef int (IfcGeom::Element::*int_member_fun)(void) const;
|
||||
|
||||
static const std::vector<std::pair<const char* const, string_member_fun>> data_pairs_string = {
|
||||
{"type", &IfcGeom::Element::type},
|
||||
{"name", &IfcGeom::Element::name },
|
||||
{"guid", &IfcGeom::Element::guid },
|
||||
{"context", &IfcGeom::Element::context },
|
||||
{"unique_id", &IfcGeom::Element::unique_id }
|
||||
};
|
||||
|
||||
static const std::vector<std::pair<const char* const, int_member_fun>> data_pairs_int = {
|
||||
{"id", &IfcGeom::Element::id},
|
||||
{"parent_id", &IfcGeom::Element::parent_id },
|
||||
};
|
||||
|
||||
H5::DataSpace attrdspace(H5S_SCALAR);
|
||||
|
||||
for (auto& p : data_pairs_string) {
|
||||
H5::Attribute att = element_group.createAttribute(p.first, str_type, attrdspace);
|
||||
att.write(str_type, ((*o).*(p.second))());
|
||||
}
|
||||
|
||||
for (auto& p : data_pairs_int) {
|
||||
H5::Attribute att = element_group.createAttribute(p.first, H5::PredType::NATIVE_INT, attrdspace);
|
||||
int value = ((*o).*(p.second))();
|
||||
att.write(H5::PredType::NATIVE_INT, &value);
|
||||
}
|
||||
|
||||
hsize_t dims_4x4[2]{ 4, 4 };
|
||||
H5::DataSpace dataspace_4x4(2, dims_4x4);
|
||||
|
||||
auto placement_dataset = element_group.createDataSet(DATASET_NAME_PLACEMENT, H5::PredType::NATIVE_DOUBLE, dataspace_4x4);
|
||||
const auto& m = o->transformation().data()->ccomponents();
|
||||
// @todo check, is this needed, can we use the storage of Eigen?
|
||||
double m44[4][4] = {
|
||||
{ m(0,0), m(1,0), m(2,0), m(3,0) },
|
||||
{ m(0,1), m(1,1), m(2,1), m(3,1) },
|
||||
{ m(0,2), m(1,2), m(2,2), m(3,2) },
|
||||
{ m(0,3), m(1,3), m(2,3), m(3,3) }
|
||||
};
|
||||
placement_dataset.write(m44, H5::PredType::NATIVE_DOUBLE);
|
||||
|
||||
return element_group;
|
||||
}
|
||||
|
||||
H5::Group HdfSerializer::createRepresentationGroup(const H5::Group& element_group, const std::string& gid) {
|
||||
// the part before the hyphen is the representation id
|
||||
auto gid2 = gid;
|
||||
auto hyphen = gid2.find("-");
|
||||
if (hyphen != std::string::npos) {
|
||||
gid2 = gid2.substr(0, hyphen);
|
||||
}
|
||||
|
||||
H5::Group representation_group;
|
||||
try {
|
||||
representation_group = element_group.openGroup(gid2);
|
||||
} catch (H5::Exception&) {
|
||||
representation_group = element_group.createGroup(gid2);
|
||||
|
||||
H5::DataSpace attrdspace(H5S_SCALAR);
|
||||
{
|
||||
H5::Attribute att = representation_group.createAttribute("geom_id", str_type, attrdspace);
|
||||
std::string value = gid;
|
||||
att.write(str_type, value);
|
||||
}
|
||||
}
|
||||
return representation_group;
|
||||
}
|
||||
|
||||
void HdfSerializer::write_style(surface_style_serialization& data, const ifcopenshell::geometry::taxonomy::style::ptr& sptr) {
|
||||
auto& s = *sptr;
|
||||
data.name = s.name.c_str();
|
||||
// @todo
|
||||
data.original_name = s.name.c_str();
|
||||
auto& instance = s.instance;
|
||||
data.id = instance ? instance.id() : 0;
|
||||
if (s.diffuse) {
|
||||
data.diffuse[0] = s.diffuse.ccomponents()(0);
|
||||
data.diffuse[1] = s.diffuse.ccomponents()(1);
|
||||
data.diffuse[2] = s.diffuse.ccomponents()(2);
|
||||
}
|
||||
if (s.specular) {
|
||||
data.specular[0] = s.specular.ccomponents()(0);
|
||||
data.specular[1] = s.specular.ccomponents()(1);
|
||||
data.specular[2] = s.specular.ccomponents()(2);
|
||||
}
|
||||
if (s.transparency == s.transparency) {
|
||||
data.transparency = s.transparency;
|
||||
}
|
||||
if (s.specularity == s.specularity) {
|
||||
data.specularity = s.specularity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HdfSerializer::write(const IfcGeom::BRepElement* o) {
|
||||
// Currenly we only support OpenCascade shapes.
|
||||
for (auto it = o->geometry().begin(); it != o->geometry().end(); ++it) {
|
||||
auto shape_ptr = std::dynamic_pointer_cast<ifcopenshell::geometry::OpenCascadeShape>(it->Shape());
|
||||
if (shape_ptr == nullptr) {
|
||||
std::cerr << "WARNING. Only OpenCascade shapes support caching. "
|
||||
<< "Skipping caching for item #" << it->ItemId() << "." << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static auto nan = std::numeric_limits<double>::quiet_NaN();
|
||||
|
||||
auto element_group = write((const IfcGeom::Element*)o);
|
||||
|
||||
/*
|
||||
// For now we disable softlinks, as it can't be safely used with delete()
|
||||
// @todo we can still cache the serialization or read it from the file probably for a comparible speedup.
|
||||
|
||||
auto it = group_cache_.find(o->geometry().id());
|
||||
if (it != group_cache_.end()) {
|
||||
H5Lcreate_soft(it->second.c_str(), element_group.getLocId(), o->geometry().id().c_str(), H5P_DEFAULT, H5P_DEFAULT);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
H5::Group representation_group = createRepresentationGroup(element_group, o->geometry().id());
|
||||
|
||||
/*
|
||||
const size_t len = H5Iget_name(representation_group.getId(), NULL, 0);
|
||||
char* name_buffer = new char[len];
|
||||
H5Iget_name(representation_group.getId(), name_buffer, len + 1);
|
||||
group_cache_.insert(it, { o->geometry().id(), name_buffer });
|
||||
delete[] name_buffer;
|
||||
*/
|
||||
|
||||
std::list<std::string> brep_strings;
|
||||
size_t num_parts = std::distance(o->geometry().begin(), o->geometry().end());
|
||||
brep_element* parts = new brep_element[num_parts];
|
||||
size_t i = 0;
|
||||
for (auto it = o->geometry().begin(); it != o->geometry().end(); ++it, ++i) {
|
||||
parts[i].id = it->ItemId();
|
||||
const auto& m = o->transformation().data()->ccomponents();
|
||||
// @todo check, is this needed, can we use the storage of Eigen?
|
||||
std::array<std::array<double, 4>, 4> arr = { {
|
||||
{ { m(0,0), m(1,0), m(2,0), m(3,0) } },
|
||||
{ { m(0,1), m(1,1), m(2,1), m(3,1) } },
|
||||
{ { m(0,2), m(1,2), m(2,2), m(3,2) } },
|
||||
{ { m(0,3), m(1,3), m(2,3), m(3,3) } }
|
||||
} };
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
std::copy(arr[j].begin(), arr[j].end(), parts[i].matrix[j]);
|
||||
}
|
||||
|
||||
brep_strings.emplace_back();
|
||||
// OpenCascadeShape type ensured by the check at the method start.
|
||||
write_shape(std::static_pointer_cast<ifcopenshell::geometry::OpenCascadeShape>(it->Shape())->shape(), brep_strings.back());
|
||||
|
||||
parts[i].surface_style = { "", "", 0, {nan,nan,nan}, {nan,nan,nan}, nan, nan };
|
||||
if (it->hasStyle()) {
|
||||
auto s = it->StylePtr();
|
||||
write_style(parts[i].surface_style, s);
|
||||
}
|
||||
|
||||
#ifdef USE_BINARY
|
||||
const auto& s = brep_strings.back();
|
||||
parts[i].shape_serialization.p = new char[s.size()];
|
||||
memcpy(parts[i].shape_serialization.p, s.c_str(), s.size());
|
||||
parts[i].shape_serialization.len = s.size();
|
||||
#else
|
||||
parts[i].shape_serialization = brep_strings.back().c_str();
|
||||
#endif
|
||||
}
|
||||
|
||||
hsize_t dimsp[1]{ num_parts };
|
||||
H5::DataSpace dataspace_parts(1, dimsp);
|
||||
|
||||
auto brepDataset = representation_group.createDataSet(DATASET_NAME_OCCT, compound, dataspace_parts);
|
||||
brepDataset.write(parts, compound);
|
||||
|
||||
H5::DataSpace attrdspace(H5S_SCALAR);
|
||||
H5::Attribute att = brepDataset.createAttribute("settings", H5::PredType::NATIVE_UINT64, attrdspace);
|
||||
/*
|
||||
// @todo
|
||||
uint64_t value = o->geometry().settings().get_raw();
|
||||
*/
|
||||
uint64_t value = 0;
|
||||
att.write(H5::PredType::NATIVE_UINT64, &value);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
void write_dataset(const H5::Group& group, const std::string& name, const std::vector<T>& ts, size_t stride) {
|
||||
hsize_t d[2]{ ts.size() / stride, stride };
|
||||
H5::DataSpace dataspace(stride == 1 ? 1 : 2, d);
|
||||
auto dt = h5_datatype_for_cpp<T>();
|
||||
|
||||
auto ds = group.createDataSet(name, dt, dataspace);
|
||||
ds.write(ts.data(), dt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void HdfSerializer::write(const IfcGeom::TriangulationElement* o) {
|
||||
auto element_group = write((const IfcGeom::Element*)o);
|
||||
|
||||
const auto& mesh = o->geometry();
|
||||
H5::Group representation_group = createRepresentationGroup(element_group, o->geometry().id());
|
||||
H5::Group meshGroup = representation_group.createGroup(GROUP_NAME_MESH);
|
||||
|
||||
write_dataset(meshGroup, DATASET_NAME_POSITIONS, mesh.verts(), 3);
|
||||
write_dataset(meshGroup, DATASET_NAME_INDICES, mesh.faces(), 3);
|
||||
write_dataset(meshGroup, DATASET_NAME_EDGES, mesh.edges(), 2);
|
||||
write_dataset(meshGroup, DATASET_NAME_NORMALS, mesh.normals(), 2);
|
||||
write_dataset(meshGroup, DATASET_NAME_UVCOORDS, mesh.uvs(), 2);
|
||||
write_dataset(meshGroup, DATASET_NAME_MATERIAL_IDS, mesh.material_ids(), 1);
|
||||
write_dataset(meshGroup, DATASET_NAME_ITEM_IDS, mesh.item_ids(), 1);
|
||||
write_dataset(meshGroup, DATASET_NAME_EDGES_ITEM_IDS, mesh.edges_item_ids(), 1);
|
||||
|
||||
{
|
||||
auto& ts = mesh.materials();
|
||||
hsize_t d[2] { ts.size() };
|
||||
H5::DataSpace dataspace(1, d);
|
||||
const auto& dt = style_compound;
|
||||
|
||||
std::vector<surface_style_serialization> data;
|
||||
data.reserve(ts.size());
|
||||
for (auto& m : ts) {
|
||||
data.emplace_back();
|
||||
write_style(data.back(), m);
|
||||
}
|
||||
|
||||
auto ds = meshGroup.createDataSet(DATASET_NAME_MATERIALS, dt, dataspace);
|
||||
ds.write(data.data(), dt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const H5std_string HdfSerializer::DATASET_NAME_POSITIONS = "positions";
|
||||
const H5std_string HdfSerializer::DATASET_NAME_UVCOORDS = "uvcoords";
|
||||
const H5std_string HdfSerializer::DATASET_NAME_NORMALS = "normals";
|
||||
const H5std_string HdfSerializer::DATASET_NAME_INDICES = "indices";
|
||||
const H5std_string HdfSerializer::DATASET_NAME_EDGES = "edges";
|
||||
const H5std_string HdfSerializer::DATASET_NAME_MATERIAL_IDS = "material_ids";
|
||||
const H5std_string HdfSerializer::DATASET_NAME_ITEM_IDS = "item_ids";
|
||||
const H5std_string HdfSerializer::DATASET_NAME_EDGES_ITEM_IDS = "edges_item_ids";
|
||||
const H5std_string HdfSerializer::DATASET_NAME_MATERIALS = "materials";
|
||||
const H5std_string HdfSerializer::DATASET_NAME_OCCT = "brep";
|
||||
const H5std_string HdfSerializer::DATASET_NAME_PLACEMENT = "placement";
|
||||
|
||||
const H5std_string HdfSerializer::GROUP_NAME_MESH = "mesh";
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,119 +0,0 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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 HDFSERIALIZER_H
|
||||
#define HDFSERIALIZER_H
|
||||
|
||||
#if defined(WITH_HDF5) && defined(IFOPSH_WITH_OPENCASCADE)
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
#include "H5Cpp.h"
|
||||
|
||||
#include "../serializers/serializers_api.h"
|
||||
#include "../ifcgeom/GeometrySerializer.h"
|
||||
|
||||
#define USE_BINARY
|
||||
|
||||
class SERIALIZERS_API HdfSerializer : public GeometrySerializer {
|
||||
private:
|
||||
const std::string hdf_filename;
|
||||
unsigned int vcount_total;
|
||||
H5::H5File file;
|
||||
ifcopenshell::geometry::SerializerSettings settings_;
|
||||
|
||||
static const H5std_string DATASET_NAME_POSITIONS;
|
||||
static const H5std_string DATASET_NAME_UVCOORDS;
|
||||
static const H5std_string DATASET_NAME_NORMALS;
|
||||
static const H5std_string DATASET_NAME_INDICES;
|
||||
static const H5std_string DATASET_NAME_EDGES;
|
||||
static const H5std_string DATASET_NAME_MATERIAL_IDS;
|
||||
static const H5std_string DATASET_NAME_ITEM_IDS;
|
||||
static const H5std_string DATASET_NAME_EDGES_ITEM_IDS;
|
||||
static const H5std_string DATASET_NAME_MATERIALS;
|
||||
static const H5std_string DATASET_NAME_OCCT;
|
||||
static const H5std_string DATASET_NAME_PLACEMENT;
|
||||
|
||||
static const H5std_string GROUP_NAME_MESH;
|
||||
|
||||
struct surface_style_serialization {
|
||||
const char* name;
|
||||
const char* original_name;
|
||||
// 0 if unset
|
||||
unsigned int id;
|
||||
// nan if unset
|
||||
double diffuse[3];
|
||||
double specular[3];
|
||||
double transparency;
|
||||
double specularity;
|
||||
};
|
||||
|
||||
struct brep_element {
|
||||
int id;
|
||||
double matrix[4][4];
|
||||
#ifdef USE_BINARY
|
||||
hvl_t shape_serialization;
|
||||
#else
|
||||
const char* shape_serialization;
|
||||
#endif
|
||||
surface_style_serialization surface_style;
|
||||
};
|
||||
|
||||
H5::CompType compound;
|
||||
H5::CompType style_compound;
|
||||
H5::StrType str_type;
|
||||
H5::ArrayType double4x4, double3;
|
||||
H5::DataType shape_type;
|
||||
|
||||
private:
|
||||
|
||||
std::map<std::string, boost::shared_ptr<IfcGeom::Representation::BRep>> brep_cache_;
|
||||
std::map<std::string, boost::shared_ptr<IfcGeom::Representation::Triangulation>> triangulation_cache_;
|
||||
std::map<std::string, std::string> group_cache_;
|
||||
|
||||
H5::Group createRepresentationGroup(const H5::Group& element_group, const std::string& gid);
|
||||
void read_surface_style(const surface_style_serialization& s,
|
||||
ifcopenshell::geometry::taxonomy::style& gss,
|
||||
ifcopenshell::file& f);
|
||||
void write_style(surface_style_serialization& data, const ifcopenshell::geometry::taxonomy::style::ptr& s);
|
||||
|
||||
public:
|
||||
HdfSerializer(const std::string& hdf_filename, const ifcopenshell::geometry::Settings& geometry_settings, const ifcopenshell::geometry::SerializerSettings& settings, bool read_only=false);
|
||||
virtual ~HdfSerializer() {}
|
||||
bool ready();
|
||||
void writeHeader();
|
||||
|
||||
H5::Group write(const IfcGeom::Element* o);
|
||||
void write(const IfcGeom::BRepElement* o);
|
||||
void write(const IfcGeom::TriangulationElement* o);
|
||||
void remove(const std::string& guid);
|
||||
|
||||
IfcGeom::Element* read(ifcopenshell::file& f, const std::string& guid, const std::string&, read_type rt = READ_BREP);
|
||||
|
||||
void finalize() {}
|
||||
bool isTesselated() const { return false; }
|
||||
void setUnitNameAndMagnitude(const std::string& /*name*/, float /*magnitude*/) {}
|
||||
void setFile(ifcopenshell::file*) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,68 +0,0 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* 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/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#if defined(WITH_HDF5) && defined(IFOPSH_WITH_OPENCASCADE)
|
||||
|
||||
#include "geometry_serializer_plugin.h"
|
||||
#include "HdfSerializer.h"
|
||||
|
||||
#include <boost/dll/alias.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
namespace ifcopenshell {
|
||||
namespace serializers {
|
||||
namespace geometry_hdf_plugin {
|
||||
|
||||
plugin::abi_info plugin_abi() {
|
||||
return plugin::host_abi();
|
||||
}
|
||||
|
||||
plugin::metadata plugin_metadata() {
|
||||
return geometry_serializer_plugin_metadata("h5");
|
||||
}
|
||||
|
||||
boost::shared_ptr<GeometrySerializer> create_serializer(const geometry_serializer_context& context) {
|
||||
return boost::make_shared<HdfSerializer>(context.output_temp_filename, context.geometry_settings, context.serializer_settings);
|
||||
}
|
||||
|
||||
void configure_serializer(geometry_serializer_context& context) {
|
||||
context.geometry_settings.get<ifcopenshell::geometry::settings::IteratorOutput>().value = ifcopenshell::geometry::settings::NATIVE;
|
||||
}
|
||||
|
||||
void register_plugin(geometry_serializer_registry& registry, const plugin::module& module) {
|
||||
geometry_serializer_info info;
|
||||
info.format = "hdf";
|
||||
info.name = "HDF";
|
||||
info.description = "Hierarchical Data Format storing positions, normals and indices.";
|
||||
info.extensions = { ".h5" };
|
||||
info.kernel_ids = { "opencascade" };
|
||||
info.supports_triangulation = true;
|
||||
info.supports_brep = true;
|
||||
registry.bind(info, create_serializer, configure_serializer, module);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_hdf_plugin::plugin_abi, ifcopenshell_plugin_abi_v1)
|
||||
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_hdf_plugin::plugin_metadata, ifcopenshell_plugin_metadata_v1)
|
||||
BOOST_DLL_ALIAS(ifcopenshell::serializers::geometry_hdf_plugin::register_plugin, ifcopenshell_register_geometry_serializer_plugin_v1)
|
||||
|
||||
#endif
|
||||
+11
-47
@@ -181,10 +181,8 @@ echo.
|
||||
|
||||
cd "%DEPS_DIR%"
|
||||
|
||||
:: VERSIONS
|
||||
:: Don't use HDF5 1.13.0, because it has a broken cmake package path.
|
||||
set HDF5_VERSION=1_13_1
|
||||
set OCCT_VERSION=7.8.1
|
||||
:: VERSIONS
|
||||
set OCCT_VERSION=7.8.1
|
||||
IF DEFINED QT6_VERSION (
|
||||
echo Using overridden QT6_VERSION: '%QT6_VERSION%'
|
||||
) else (
|
||||
@@ -211,9 +209,8 @@ IF "%IFCOS_INSTALL_PYTHON%"=="TRUE" (
|
||||
:: Cache last used CMake generator and configurable dependency dirs for other scripts to use
|
||||
:: This is consolidated at the beginning of the script so that the script can be partially
|
||||
:: executed by jumping (using goto) to different labels.
|
||||
if defined GEN_SHORTHAND echo GEN_SHORTHAND=%GEN_SHORTHAND%>"%~dp0\%BUILD_DEPS_CACHE_PATH%"
|
||||
echo HDF5_VERSION=%HDF5_VERSION%>>"%~dp0\%BUILD_DEPS_CACHE_PATH%"
|
||||
echo QT6_VERSION=%QT6_VERSION%>>"%~dp0\%BUILD_DEPS_CACHE_PATH%"
|
||||
if defined GEN_SHORTHAND echo GEN_SHORTHAND=%GEN_SHORTHAND%>"%~dp0\%BUILD_DEPS_CACHE_PATH%"
|
||||
echo QT6_VERSION=%QT6_VERSION%>>"%~dp0\%BUILD_DEPS_CACHE_PATH%"
|
||||
IF "%IFCOS_INSTALL_PYTHON%"=="TRUE" (
|
||||
echo PYTHONHOME=%PYTHONHOME%>>"%~dp0\%BUILD_DEPS_CACHE_PATH%"
|
||||
)
|
||||
@@ -345,10 +342,10 @@ popd
|
||||
|
||||
:mpfr
|
||||
|
||||
IF EXIST "%INSTALL_DIR%\mpfr" (
|
||||
echo Found existing "%INSTALL_DIR%\mpfr", skipping
|
||||
goto :HDF5
|
||||
)
|
||||
IF EXIST "%INSTALL_DIR%\mpfr" (
|
||||
echo Found existing "%INSTALL_DIR%\mpfr", skipping
|
||||
goto :Boost
|
||||
)
|
||||
|
||||
set DEPENDENCY_NAME=mpfr
|
||||
set DEPENDENCY_DIR=%DEPS_DIR%\mpfr
|
||||
@@ -381,42 +378,9 @@ copy lib\%VS_PLATFORM%\%DEBUG_OR_RELEASE%\* "%INSTALL_DIR%\mpfr"
|
||||
IF NOT %ERRORLEVEL%==0 GOTO :Error
|
||||
popd
|
||||
|
||||
:HDF5
|
||||
|
||||
set DEPENDENCY_NAME=hdf5
|
||||
set DEPENDENCY_DIR=%DEPS_DIR%\hdf5-%HDF5_VERSION%
|
||||
set HDF5_CMAKE_ZIP=hdf5-%HDF5_VERSION%.zip
|
||||
set DEPENDENCY_INSTALL_NAME=HDF5-%HDF5_VERSION%-win%ARCH_BITS%
|
||||
set HDF5_INSTALL_NAME=%DEPENDENCY_INSTALL_NAME%
|
||||
set NEXT_DEPENDENCY_LABEL=Boost
|
||||
|
||||
call :CheckInstallation
|
||||
if %ERRORLEVEL%==200 GOTO %NEXT_DEPENDENCY_LABEL%
|
||||
|
||||
if "%ARCH_BITS%"=="64" set ARCH_BITS_64=64
|
||||
call :DownloadFile ^
|
||||
https://github.com/HDFGroup/hdf5/archive/refs/tags/hdf5-%HDF5_VERSION%.zip ^
|
||||
"%DEPS_DIR%" %HDF5_CMAKE_ZIP%
|
||||
IF NOT %ERRORLEVEL%==0 GOTO :Error
|
||||
call :ExtractArchive %HDF5_CMAKE_ZIP% "%DEPS_DIR%" "%DEPS_DIR%\hdf5-%HDF5_VERSION%"
|
||||
IF NOT %ERRORLEVEL%==0 GOTO :Error
|
||||
if exist "%DEPS_DIR%\hdf5-hdf5-%HDF5_VERSION%" ren "%DEPS_DIR%\hdf5-hdf5-%HDF5_VERSION%" "hdf5-%HDF5_VERSION%"
|
||||
pushd "%DEPENDENCY_DIR%"
|
||||
call :RunCMake -DCMAKE_INSTALL_PREFIX="%INSTALL_DIR%\%HDF5_INSTALL_NAME%" ^
|
||||
-DHDF5_ENABLE_Z_LIB_SUPPORT=OFF -DBUILD_TESTING=OFF ^
|
||||
-DHDF5_BUILD_TOOLS=OFF -DHDF5_BUILD_EXAMPLES=OFF -DBUILD_SHARED_LIBS=OFF -DHDF5_BUILD_UTILS=OFF ^
|
||||
-DHDF5_BUILD_CPP_LIB=ON
|
||||
IF NOT %ERRORLEVEL%==0 GOTO :Error
|
||||
call :BuildCMakeProject "%DEPENDENCY_DIR%\%BUILD_DIR%" %DEBUG_OR_RELEASE%
|
||||
IF NOT %ERRORLEVEL%==0 GOTO :Error
|
||||
call :InstallCMakeProject "%DEPENDENCY_DIR%\%BUILD_DIR%" %DEBUG_OR_RELEASE%
|
||||
IF NOT %ERRORLEVEL%==0 GOTO :Error
|
||||
call :MarkInstallation
|
||||
popd
|
||||
|
||||
:: Note all of the dependencies have appropriate label so that user can easily skip something if wanted
|
||||
:: by modifying this file and using goto.
|
||||
:Boost
|
||||
:: Note all of the dependencies have appropriate label so that user can easily skip something if wanted
|
||||
:: by modifying this file and using goto.
|
||||
:Boost
|
||||
:: DEPENDENCY_NAME is used for logging and DEPENDENCY_DIR for saving from some redundant typing
|
||||
set DEPENDENCY_NAME=Boost %BOOST_VERSION%
|
||||
set DEPENDENCY_DIR=%DEPS_DIR%\boost_%BOOST_VER%
|
||||
|
||||
+11
-13
@@ -17,9 +17,9 @@
|
||||
:: ::
|
||||
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::
|
||||
:: Example usage:
|
||||
:: run-cmake.bat vs2022-x64
|
||||
:: run-cmake.bat vs2022-x64 -DGLTF_SUPPORT=ON -DHDF5_SUPPORT=OFF
|
||||
:: Example usage:
|
||||
:: run-cmake.bat vs2022-x64
|
||||
:: run-cmake.bat vs2022-x64 -DGLTF_SUPPORT=ON
|
||||
::
|
||||
:: Used environment variables:
|
||||
:: - `ADD_COMMIT_SHA` - if defined then `ADD_COMMIT_SHA` and `VERSION_OVERRIDE` cmake args will be set to `ON`.
|
||||
@@ -93,10 +93,9 @@ if not defined BOOST_INSTALL_DIR (
|
||||
set BOOST_INSTALL_DIR=%DEPS_DIR%\boost_1_86_0\stage\%GEN_SHORTHAND%
|
||||
)
|
||||
|
||||
set OPENCOLLADA_INSTALL_DIR=%INSTALL_DIR%\OpenCOLLADA
|
||||
set LIBXML2_INCLUDE_DIR=%DEPS_DIR%\OpenCOLLADA\Externals\LibXML\include
|
||||
set LIBXML2_LIBRARIES=%INSTALL_DIR%\OpenCOLLADA\lib\opencollada\xml.lib
|
||||
set HDF5_INSTALL_DIR=%INSTALL_DIR%\HDF5-%HDF5_VERSION%-win%ARCH_BITS%
|
||||
set OPENCOLLADA_INSTALL_DIR=%INSTALL_DIR%\OpenCOLLADA
|
||||
set LIBXML2_INCLUDE_DIR=%DEPS_DIR%\OpenCOLLADA\Externals\LibXML\include
|
||||
set LIBXML2_LIBRARIES=%INSTALL_DIR%\OpenCOLLADA\lib\opencollada\xml.lib
|
||||
|
||||
set PYTHON_EXECUTABLE=%PYTHONHOME%\python.exe
|
||||
for /f "usebackq delims=" %%v in (`
|
||||
@@ -142,11 +141,10 @@ echo BOOST_INSTALL_DIR = %BOOST_INSTALL_DIR%
|
||||
echo OCC_INCLUDE_DIR = %OCC_INCLUDE_DIR%
|
||||
echo OCC_LIBRARY_DIR = %OCC_LIBRARY_DIR%
|
||||
echo OCC_INSTALL_DIR = %OCC_INSTALL_DIR%
|
||||
echo OPENCOLLADA_INSTALL_DIR = %OPENCOLLADA_INSTALL_DIR%
|
||||
echo LIBXML2_INCLUDE_DIR = %LIBXML2_INCLUDE_DIR%
|
||||
echo LIBXML2_LIBRARIES = %LIBXML2_LIBRARIES%
|
||||
echo HDF5_INSTALL_DIR = %HDF5_INSTALL_DIR%
|
||||
echo PYTHONHOME = %PYTHONHOME%
|
||||
echo OPENCOLLADA_INSTALL_DIR = %OPENCOLLADA_INSTALL_DIR%
|
||||
echo LIBXML2_INCLUDE_DIR = %LIBXML2_INCLUDE_DIR%
|
||||
echo LIBXML2_LIBRARIES = %LIBXML2_LIBRARIES%
|
||||
echo PYTHONHOME = %PYTHONHOME%
|
||||
echo PYTHON_INCLUDE_DIR = %PYTHON_INCLUDE_DIR%
|
||||
echo PYTHON_LIBRARY = %PYTHON_LIBRARY%
|
||||
echo PYTHON_EXECUTABLE = %PYTHON_EXECUTABLE%
|
||||
@@ -173,7 +171,7 @@ set CMAKELISTS_DIR=..\cmake
|
||||
if not (%1)==() if exist CMakeCache.txt. del /Q CMakeCache.txt
|
||||
echo "Running CMake for %PROJECT_NAME%."
|
||||
|
||||
set CMAKE_PREFIX_PATH=%HDF5_INSTALL_DIR%;%OPENCOLLADA_INSTALL_DIR%;%SWIG_INSTALL_DIR%
|
||||
set CMAKE_PREFIX_PATH=%OPENCOLLADA_INSTALL_DIR%;%SWIG_INSTALL_DIR%
|
||||
set CMAKE_PREFIX_PATH=%CMAKE_PREFIX_PATH%;%ROCKSDB_INSTALL_DIR%;%ZSTD_INSTALL_DIR%
|
||||
set CMAKE_PREFIX_PATH=%CMAKE_PREFIX_PATH%;%BOOST_INSTALL_DIR%;%CCACHE_INSTALL_DIR%
|
||||
set CMake_PREFIX_PATH=%CMAKE_PREFIX_PATH%;%USD_INSTALL_DIR%;%TBB_INSTALL_DIR%
|
||||
|
||||
+1
-10
@@ -35,15 +35,7 @@ function mark_based_on_artifacts {
|
||||
[string]$installation_dir
|
||||
)
|
||||
|
||||
if ($dependency_name -eq "hdf5") {
|
||||
if ($env:BUILD_CFG -eq "Debug") {
|
||||
$artifact = "lib\libhdf5_D.lib"
|
||||
}
|
||||
else {
|
||||
$artifact = "lib\libhdf5.lib"
|
||||
}
|
||||
}
|
||||
elseif ($dependency_name -eq "opencollada") {
|
||||
if ($dependency_name -eq "opencollada") {
|
||||
if ($env:BUILD_CFG -eq "Debug") {
|
||||
$artifact = "lib\opencollada\OpenCOLLADAFrameworkd.lib"
|
||||
}
|
||||
@@ -109,7 +101,6 @@ function check_installation {
|
||||
|
||||
|
||||
# Dependencies Release/Debug configs compatibility:
|
||||
# - hdf5: incompatible
|
||||
# - OpenCASCADE: incompatible
|
||||
# - rocksdb: incompatible
|
||||
# - opencollada: incompatible
|
||||
|
||||
Reference in New Issue
Block a user