diff --git a/.github/workflows/ci-ifcopenshell-docker.yml b/.github/workflows/ci-ifcopenshell-docker.yml index df672139b8..454955e731 100644 --- a/.github/workflows/ci-ifcopenshell-docker.yml +++ b/.github/workflows/ci-ifcopenshell-docker.yml @@ -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 \ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a49c92fcd7..0e2b15d321 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4880ed8177..d37e93d938 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -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 diff --git a/Dockerfile b/Dockerfile index 60689beb09..ff2723146e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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/ diff --git a/build.sh b/build.sh index 939c4ae443..ebf4200a4c 100755 --- a/build.sh +++ b/build.sh @@ -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 \ diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index d963355066..4d3f05fd10 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -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") diff --git a/cmake/CMakePresets.json b/cmake/CMakePresets.json index 5bd4a18635..c3c1dc5c74 100644 --- a/cmake/CMakePresets.json +++ b/cmake/CMakePresets.json @@ -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 @@ } } ] -} \ No newline at end of file +} diff --git a/cmake/FindCGAL.cmake b/cmake/FindCGAL.cmake index 0b789d5f03..afde47c49c 100644 --- a/cmake/FindCGAL.cmake +++ b/cmake/FindCGAL.cmake @@ -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: diff --git a/cmake/FindHDF5.cmake b/cmake/FindHDF5.cmake deleted file mode 100644 index 399b1c9f13..0000000000 --- a/cmake/FindHDF5.cmake +++ /dev/null @@ -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}) diff --git a/conda/build.bat b/conda/build.bat index b43448e255..3b25bcddab 100644 --- a/conda/build.bat +++ b/conda/build.bat @@ -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 ^ diff --git a/conda/build.sh b/conda/build.sh index 83fac5809c..22df31425c 100644 --- a/conda/build.sh +++ b/conda/build.sh @@ -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" \ No newline at end of file +python "${RECIPE_DIR}/update_version_init.py" "${PKG_VERSION}" "${SP_DIR}/ifcopenshell/__init__.py" diff --git a/conda/conda_build_config.yaml b/conda/conda_build_config.yaml index 47b843ee31..376770dc5d 100644 --- a/conda/conda_build_config.yaml +++ b/conda/conda_build_config.yaml @@ -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: diff --git a/conda/recipe.yaml b/conda/recipe.yaml index aeddedbe07..3d43c9539d 100644 --- a/conda/recipe.yaml +++ b/conda/recipe.yaml @@ -33,7 +33,6 @@ requirements: - occt - libxml2 - cgal-cpp - - hdf5 - eigen - mpfr - nlohmann_json diff --git a/nix/build-all.py b/nix/build-all.py index c81c3d58b1..49a205d966 100644 --- a/nix/build-all.py +++ b/nix/build-all.py @@ -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( diff --git a/pixi.lock b/pixi.lock index aff1b38b70..60628cbaeb 100644 --- a/pixi.lock +++ b/pixi.lock @@ -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 diff --git a/pixi.toml b/pixi.toml index 71bc0b887d..5eb7f4d293 100644 --- a/pixi.toml +++ b/pixi.toml @@ -31,7 +31,6 @@ occt = { version = "*", build = "*novtk*" } cgal-cpp = "*" numpy = "*" lark = "*" -hdf5 = "*" eigen = "*" mpfr = "*" gmp = "*" diff --git a/src/bonsai/bonsai/bim/data/cache/README.md b/src/bonsai/bonsai/bim/data/cache/README.md deleted file mode 100644 index 0a51fc4a12..0000000000 --- a/src/bonsai/bonsai/bim/data/cache/README.md +++ /dev/null @@ -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. diff --git a/src/bonsai/bonsai/bim/export_ifc.py b/src/bonsai/bonsai/bim/export_ifc.py index f28c106e95..0ed61017e7 100644 --- a/src/bonsai/bonsai/bim/export_ifc.py +++ b/src/bonsai/bonsai/bim/export_ifc.py @@ -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": diff --git a/src/bonsai/bonsai/bim/ifc.py b/src/bonsai/bonsai/bim/ifc.py index b07e584a71..5058b29e60 100644 --- a/src/bonsai/bonsai/bim/ifc.py +++ b/src/bonsai/bonsai/bim/ifc.py @@ -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): diff --git a/src/bonsai/bonsai/bim/import_ifc.py b/src/bonsai/bonsai/bim/import_ifc.py index 267800469a..eb7024b30e 100644 --- a/src/bonsai/bonsai/bim/import_ifc.py +++ b/src/bonsai/bonsai/bim/import_ifc.py @@ -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 diff --git a/src/bonsai/bonsai/bim/module/debug/__init__.py b/src/bonsai/bonsai/bim/module/debug/__init__.py index bd3ecac4f6..ca331251b2 100644 --- a/src/bonsai/bonsai/bim/module/debug/__init__.py +++ b/src/bonsai/bonsai/bim/module/debug/__init__.py @@ -37,7 +37,6 @@ classes = ( operator.PrintObjectPlacement, operator.PrintUnusedElementStats, operator.ProfileImportIFC, - operator.PurgeHdf5Cache, operator.PurgeUnusedElementsByClass, operator.PurgeUnusedObjects, operator.RestartBlender, diff --git a/src/bonsai/bonsai/bim/module/debug/operator.py b/src/bonsai/bonsai/bim/module/debug/operator.py index d7b99746ab..5cf9f08f56 100644 --- a/src/bonsai/bonsai/bim/module/debug/operator.py +++ b/src/bonsai/bonsai/bim/module/debug/operator.py @@ -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" diff --git a/src/bonsai/bonsai/bim/module/debug/ui.py b/src/bonsai/bonsai/bim/module/debug/ui.py index 5ffa99cf35..58ac29881b 100644 --- a/src/bonsai/bonsai/bim/module/debug/ui.py +++ b/src/bonsai/bonsai/bim/module/debug/ui.py @@ -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") diff --git a/src/bonsai/bonsai/bim/module/drawing/operator.py b/src/bonsai/bonsai/bim/module/drawing/operator.py index d6594364bf..43db20f24a 100644 --- a/src/bonsai/bonsai/bim/module/drawing/operator.py +++ b/src/bonsai/bonsai/bim/module/drawing/operator.py @@ -16,7 +16,6 @@ # You should have received a copy of the GNU General Public License # along with Bonsai. If not, see . -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) diff --git a/src/bonsai/bonsai/bim/module/geometry/operator.py b/src/bonsai/bonsai/bim/module/geometry/operator.py index 7b73280e51..d210fbfa57 100644 --- a/src/bonsai/bonsai/bim/module/geometry/operator.py +++ b/src/bonsai/bonsai/bim/module/geometry/operator.py @@ -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) diff --git a/src/bonsai/bonsai/bim/module/project/operator.py b/src/bonsai/bonsai/bim/module/project/operator.py index d38c4f3b68..e2aa06337e 100644 --- a/src/bonsai/bonsai/bim/module/project/operator.py +++ b/src/bonsai/bonsai/bim/module/project/operator.py @@ -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: diff --git a/src/bonsai/bonsai/bim/module/project/prop.py b/src/bonsai/bonsai/bim/module/project/prop.py index 1408d2f786..8f7aed8283 100644 --- a/src/bonsai/bonsai/bim/module/project/prop.py +++ b/src/bonsai/bonsai/bim/module/project/prop.py @@ -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 diff --git a/src/bonsai/bonsai/bim/module/project/ui.py b/src/bonsai/bonsai/bim/module/project/ui.py index 5e828ddd9b..b8b8e1a4e1 100644 --- a/src/bonsai/bonsai/bim/module/project/ui.py +++ b/src/bonsai/bonsai/bim/module/project/ui.py @@ -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") diff --git a/src/bonsai/bonsai/bim/module/void/operator.py b/src/bonsai/bonsai/bim/module/void/operator.py index 8c584e0b14..c27b8891f6 100644 --- a/src/bonsai/bonsai/bim/module/void/operator.py +++ b/src/bonsai/bonsai/bim/module/void/operator.py @@ -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"} diff --git a/src/bonsai/bonsai/bim/ui.py b/src/bonsai/bonsai/bim/ui.py index 97980d92dd..ee82e55331 100644 --- a/src/bonsai/bonsai/bim/ui.py +++ b/src/bonsai/bonsai/bim/ui.py @@ -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") diff --git a/src/bonsai/bonsai/core/debug.py b/src/bonsai/bonsai/core/debug.py index 3702a9cca3..ea01560341 100644 --- a/src/bonsai/bonsai/core/debug.py +++ b/src/bonsai/bonsai/core/debug.py @@ -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] diff --git a/src/bonsai/bonsai/core/geometry.py b/src/bonsai/bonsai/core/geometry.py index 83ba921d30..4237a29354 100644 --- a/src/bonsai/bonsai/core/geometry.py +++ b/src/bonsai/bonsai/core/geometry.py @@ -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) diff --git a/src/bonsai/bonsai/core/tool.py b/src/bonsai/bonsai/core/tool.py index e6a60c9deb..5b141320c6 100644 --- a/src/bonsai/bonsai/core/tool.py +++ b/src/bonsai/bonsai/core/tool.py @@ -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 diff --git a/src/bonsai/bonsai/tool/debug.py b/src/bonsai/bonsai/tool/debug.py index ccd30ddd74..686367c3ab 100644 --- a/src/bonsai/bonsai/tool/debug.py +++ b/src/bonsai/bonsai/tool/debug.py @@ -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") diff --git a/src/bonsai/bonsai/tool/geometry.py b/src/bonsai/bonsai/tool/geometry.py index 5c3e5a4435..dce6c7a419 100644 --- a/src/bonsai/bonsai/tool/geometry.py +++ b/src/bonsai/bonsai/tool/geometry.py @@ -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)} diff --git a/src/bonsai/scripts/headless_import.py b/src/bonsai/scripts/headless_import.py index 7554eacc04..edc389ee0d 100644 --- a/src/bonsai/scripts/headless_import.py +++ b/src/bonsai/scripts/headless_import.py @@ -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 diff --git a/src/bonsai/scripts/standalone_blender_import.py b/src/bonsai/scripts/standalone_blender_import.py index a2b9908afb..088722c8a2 100644 --- a/src/bonsai/scripts/standalone_blender_import.py +++ b/src/bonsai/scripts/standalone_blender_import.py @@ -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() diff --git a/src/bonsai/test/core/test_debug.py b/src/bonsai/test/core/test_debug.py index 4384c0abd1..26435ca3bc 100644 --- a/src/bonsai/test/core/test_debug.py +++ b/src/bonsai/test/core/test_debug.py @@ -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) diff --git a/src/bonsai/test/core/test_geometry.py b/src/bonsai/test/core/test_geometry.py index 21ccb09220..28202492b8 100644 --- a/src/bonsai/test/core/test_geometry.py +++ b/src/bonsai/test/core/test_geometry.py @@ -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, diff --git a/src/bonsai/test/tool/test_debug.py b/src/bonsai/test/tool/test_debug.py index 7b434c4ee6..f69ff5444c 100644 --- a/src/bonsai/test/tool/test_debug.py +++ b/src/bonsai/test/tool/test_debug.py @@ -17,8 +17,6 @@ # along with Bonsai. If not, see . 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()) diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 0578a24ea4..188278b9e1 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -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(&log_format), "log format: plain or json") ("log-file", new po::typed_value(&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(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(&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 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()) { diff --git a/src/ifcgeom/CMakeLists.txt b/src/ifcgeom/CMakeLists.txt index d00ecbee90..990fcd5ba2 100644 --- a/src/ifcgeom/CMakeLists.txt +++ b/src/ifcgeom/CMakeLists.txt @@ -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) diff --git a/src/ifcgeom/Iterator.cpp b/src/ifcgeom/Iterator.cpp index eab7744e48..6e7ab5a77f 100644 --- a/src/ifcgeom/Iterator.cpp +++ b/src/ifcgeom/Iterator.cpp @@ -362,7 +362,7 @@ void IfcGeom::Iterator::create_element_(ifcopenshell::geometry::Converter* kerne logger::set_product(product); - IfcGeom::BRepElement* brep = static_cast(decorate_with_cache_(GeometrySerializer::READ_BREP, (std::string)product.as().get("GlobalId"), std::to_string(rep->item->instance.id()), [kernel, settings, product, place, rep]() { + IfcGeom::BRepElement* brep = static_cast(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(decorate_with_cache_(GeometrySerializer::READ_BREP, (std::string)product2.as().get("GlobalId"), std::to_string(rep->item->instance.id()), [kernel, settings, product2, place2, brep]() { + IfcGeom::BRepElement* brep2 = static_cast(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().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); diff --git a/src/ifcgeom/Iterator.h b/src/ifcgeom/Iterator.h index 61c369cb0a..7aff23845a 100644 --- a/src/ifcgeom/Iterator.h +++ b/src/ifcgeom/Iterator.h @@ -66,7 +66,6 @@ #include "../ifcgeom/taxonomy.h" #include "../ifcgeom/Converter.h" #include "../ifcgeom/abstract_mapping.h" -#include "../ifcgeom/GeometrySerializer.h" #include @@ -104,8 +103,6 @@ namespace IfcGeom { class IFC_GEOM_API Iterator { private: - GeometrySerializer* cache_ = nullptr; - std::atomic finished_{ false }; std::atomic terminating_{ false }; std::atomic had_error_processing_elements_ { false }; @@ -153,44 +150,11 @@ namespace IfcGeom { // Should not be destructed because, destructor is blocking std::future init_future_; - std::mutex caching_mutex_; - std::array time_points; template - 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 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 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 get_task_items() const { std::vector items; items.reserve(tasks_.size()); diff --git a/src/ifcgeom/kernels/opencascade/IfcGeomTree.h b/src/ifcgeom/kernels/opencascade/IfcGeomTree.h index cfd6e95704..0bdb99151a 100644 --- a/src/ifcgeom/kernels/opencascade/IfcGeomTree.h +++ b/src/ifcgeom/kernels/opencascade/IfcGeomTree.h @@ -64,11 +64,6 @@ #include #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 processed_geometry_ids; - std::vector element_shape_ids; - std::unordered_map geometry_id_to_shape_id; - int geometry_index = 0; - - std::vector> matrices; - std::vector> colours; - std::vector names; - std::vector 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(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 verts_float(verts.size()); - std::transform(verts.begin(), verts.end(), verts_float.begin(), - [](double val) { return static_cast(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 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 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 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(material->diffuse.ccomponents()[0])) < tolerance - && std::abs(colour[1] - static_cast(material->diffuse.ccomponents()[1])) < tolerance - && std::abs(colour[2] - static_cast(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(material->diffuse.ccomponents()[0]), - static_cast(material->diffuse.ccomponents()[1]), - static_cast(material->diffuse.ccomponents()[2]), - alpha}); - } - material_keys.push_back(static_cast(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 data_dtype(material_ids.begin(), material_ids.end()); - dataset.write(data_dtype.data(), dtype); - } - } - - // Write GlobalIds - std::vector 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 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 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 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 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 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 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 void apply_matrix_to_flat_verts(const std::vector& flat_list, const ifcopenshell::geometry::taxonomy::matrix4::ptr& matrix, std::vector& result) { Eigen::Vector3d vin; diff --git a/src/ifcgeom/kernels/opencascade/tree_backends.h b/src/ifcgeom/kernels/opencascade/tree_backends.h index f3805f73d7..e6c669623c 100644 --- a/src/ifcgeom/kernels/opencascade/tree_backends.h +++ b/src/ifcgeom/kernels/opencascade/tree_backends.h @@ -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_; }; diff --git a/src/ifcgeom/tree.cpp b/src/ifcgeom/tree.cpp index ad99adc576..f391bf518f 100644 --- a/src/ifcgeom/tree.cpp +++ b/src/ifcgeom/tree.cpp @@ -227,12 +227,6 @@ const std::vector& 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& uuids_array) const { std::string hex_str; hex_str.reserve(uuids_array.size() * 2); diff --git a/src/ifcgeom/tree.h b/src/ifcgeom/tree.h index c113ea4a2d..43a1558969 100644 --- a/src/ifcgeom/tree.h +++ b/src/ifcgeom/tree.h @@ -100,10 +100,6 @@ namespace IfcGeom { void enable_face_styles(bool enable); const std::vector& styles() const; -#ifdef WITH_HDF5 - void write_h5(); -#endif - std::string uint8_to_b64(const std::vector& uuids_array) const; static bool is_manifold(const std::vector& faces); diff --git a/src/ifcgeom/tree_registry.cpp b/src/ifcgeom/tree_registry.cpp index 70e9fa7043..57cd05719e 100644 --- a/src/ifcgeom/tree_registry.cpp +++ b/src/ifcgeom/tree_registry.cpp @@ -104,12 +104,6 @@ const std::vector& 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; diff --git a/src/ifcgeom/tree_registry.h b/src/ifcgeom/tree_registry.h index d38d5e5949..6d116f29c9 100644 --- a/src/ifcgeom/tree_registry.h +++ b/src/ifcgeom/tree_registry.h @@ -70,9 +70,6 @@ namespace ifcopenshell { virtual void enable_face_styles(bool enable); virtual const std::vector& styles() const; -#ifdef WITH_HDF5 - virtual void write_h5(); -#endif }; class IFC_GEOM_API tree_registry { diff --git a/src/ifcopenshell-python/docs/ifcconvert.rst b/src/ifcopenshell-python/docs/ifcconvert.rst index beef450578..87c1eabb12 100644 --- a/src/ifcopenshell-python/docs/ifcconvert.rst +++ b/src/ifcopenshell-python/docs/ifcconvert.rst @@ -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_ | diff --git a/src/ifcopenshell-python/docs/ifcconvert/usage.rst b/src/ifcopenshell-python/docs/ifcconvert/usage.rst index 3c6846d25b..af5fbec7f8 100644 --- a/src/ifcopenshell-python/docs/ifcconvert/usage.rst +++ b/src/ifcopenshell-python/docs/ifcconvert/usage.rst @@ -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 diff --git a/src/ifcopenshell-python/docs/ifcopenshell/installation.rst b/src/ifcopenshell-python/docs/ifcopenshell/installation.rst index b187451671..af6665e9d6 100644 --- a/src/ifcopenshell-python/docs/ifcopenshell/installation.rst +++ b/src/ifcopenshell-python/docs/ifcopenshell/installation.rst @@ -29,8 +29,6 @@ IfcOpenShell depends on: - (Optional) `SWIG `__ and `Python `__ - for building the IfcOpenShell Python interface and use in Bonsai -- (Optional) `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 diff --git a/src/ifcopenshell-python/docs/introduction.rst b/src/ifcopenshell-python/docs/introduction.rst index 39b963e8f7..6357667c19 100644 --- a/src/ifcopenshell-python/docs/introduction.rst +++ b/src/ifcopenshell-python/docs/introduction.rst @@ -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. diff --git a/src/ifcopenshell-python/ifcopenshell/draw.py b/src/ifcopenshell-python/ifcopenshell/draw.py index 962dbbb34f..db87ba5e3c 100644 --- a/src/ifcopenshell-python/ifcopenshell/draw.py +++ b/src/ifcopenshell-python/ifcopenshell/draw.py @@ -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() diff --git a/src/ifcopenshell-python/ifcopenshell/geom/main.py b/src/ifcopenshell-python/ifcopenshell/geom/main.py index 05701d9bc7..41a58eee0b 100644 --- a/src/ifcopenshell-python/ifcopenshell/geom/main.py +++ b/src/ifcopenshell-python/ifcopenshell/geom/main.py @@ -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", diff --git a/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi b/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi index bf6e830500..777c00d106 100644 --- a/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi +++ b/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi @@ -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): ... diff --git a/src/ifcviewer/README.md b/src/ifcviewer/README.md index 4d8290d736..efc59ccb63 100644 --- a/src/ifcviewer/README.md +++ b/src/ifcviewer/README.md @@ -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 ``` diff --git a/src/ifcwrap/IfcPython.i b/src/ifcwrap/IfcPython.i index 2e2c911f1c..686e6ce743 100644 --- a/src/ifcwrap/IfcPython.i +++ b/src/ifcwrap/IfcPython.i @@ -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" diff --git a/src/serializers/CMakeLists.txt b/src/serializers/CMakeLists.txt index af00749df2..ccdeb08bf8 100644 --- a/src/serializers/CMakeLists.txt +++ b/src/serializers/CMakeLists.txt @@ -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}) diff --git a/src/serializers/HdfSerializer.cpp b/src/serializers/HdfSerializer.cpp deleted file mode 100644 index d6271bade5..0000000000 --- a/src/serializers/HdfSerializer.cpp +++ /dev/null @@ -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 . * - * * - ********************************************************************************/ - -#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 -#include -#include - -#include -#include -#include -#include - -#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 - H5::DataType h5_datatype_for_cpp(); - - template <> - H5::DataType h5_datatype_for_cpp() { - return H5::PredType::NATIVE_INT; - } - - template <> - H5::DataType h5_datatype_for_cpp() { - return H5::PredType::NATIVE_UINT64; - } - - template <> - H5::DataType h5_datatype_for_cpp() { - return H5::PredType::NATIVE_DOUBLE; - } - - template <> - H5::DataType h5_datatype_for_cpp() { - return H5::StrType(H5::PredType::C_S1, H5T_VARIABLE); - } - - template - void do_read(H5::Attribute& attr, T& val) { - attr.read(h5_datatype_for_cpp(), &val); - } - - template <> - void do_read(H5::Attribute& attr, std::string& val) { - attr.read(h5_datatype_for_cpp(), val); - } - - template - 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(attr, val); - return val; - } -} - -#include - -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(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(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 - std::vector 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 dims(rank); - space.getSimpleExtentDims(dims.data(), NULL); - const hsize_t total = std::accumulate(dims.begin(), dims.end(), 1U, std::multiplies()); - std::vector result(total); - ds.read(result.data(), h5_datatype_for_cpp()); - 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(); - } - } - -} - -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(element_group, "id"); - int parent_id = read_scalar_attribute(element_group, "parent_id"); - std::string type = read_scalar_attribute(element_group, "type"); - std::string name = read_scalar_attribute(element_group, "name"); - std::string context = read_scalar_attribute(element_group, "context"); - std::string unique_id = read_scalar_attribute(element_group, "unique_id"); - - auto trsf = ifcopenshell::geometry::taxonomy::make(); - 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(&m44[0][0]); - - auto representation_group = element_group.openGroup(representation_id_str); - std::string geom_id = read_scalar_attribute(representation_group, "geom_id"); - - auto inst = f.instance_by_id(id).as(); - - boost::shared_ptr brep_geometry; - boost::shared_ptr 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(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 parts; - { - auto space = brepDataset.getSpace(); - int rank = space.getSimpleExtentNdims(); - - if (rank != 1) { - return nullptr; - } - - std::vector 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(); - matrix->components() << Eigen::Map(&part.matrix[0][0]); - - auto style_ptr = ifcopenshell::geometry::taxonomy::make(); - 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(); - } - */ - - brep_geometry = boost::shared_ptr(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(meshGroup, DATASET_NAME_POSITIONS); - auto faces = read_dataset(meshGroup, DATASET_NAME_INDICES); - auto edges = read_dataset(meshGroup, DATASET_NAME_EDGES); - auto normals = read_dataset(meshGroup, DATASET_NAME_NORMALS); - auto uvcoords = read_dataset(meshGroup, DATASET_NAME_UVCOORDS); - auto material_ids = read_dataset(meshGroup, DATASET_NAME_MATERIAL_IDS); - auto item_ids = read_dataset(meshGroup, DATASET_NAME_ITEM_IDS); - auto edges_item_ids = read_dataset(meshGroup, DATASET_NAME_EDGES_ITEM_IDS); - - std::vector surface_styles; - - { - auto ds = meshGroup.openDataSet(DATASET_NAME_MATERIALS); - auto space = ds.getSpace(); - int rank = space.getSimpleExtentNdims(); - - if (rank != 1) { - return nullptr; - } - - std::vector dims(rank); - space.getSimpleExtentDims(dims.data(), NULL); - - surface_styles.resize(dims[0]); - ds.read(surface_styles.data(), style_compound); - } - - std::vector surface_style_ptrs(surface_styles.size()); - - for (size_t i = 0; i < surface_styles.size(); ++i) { - surface_style_ptrs[i] = ifcopenshell::geometry::taxonomy::make(); - read_surface_style(surface_styles[i], *surface_style_ptrs[i], f); - } - - triangulation_geometry = boost::shared_ptr(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> 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> 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(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::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 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, 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(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 - void write_dataset(const H5::Group& group, const std::string& name, const std::vector& 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(); - - 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 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 \ No newline at end of file diff --git a/src/serializers/HdfSerializer.h b/src/serializers/HdfSerializer.h deleted file mode 100644 index 5a12b17805..0000000000 --- a/src/serializers/HdfSerializer.h +++ /dev/null @@ -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 . * - * * - ********************************************************************************/ - -#ifndef HDFSERIALIZER_H -#define HDFSERIALIZER_H - -#if defined(WITH_HDF5) && defined(IFOPSH_WITH_OPENCASCADE) - -#include -#include -#include - -#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> brep_cache_; - std::map> triangulation_cache_; - std::map 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 diff --git a/src/serializers/geometry_hdf_plugin.cpp b/src/serializers/geometry_hdf_plugin.cpp deleted file mode 100644 index b06713bd35..0000000000 --- a/src/serializers/geometry_hdf_plugin.cpp +++ /dev/null @@ -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 . * - * * - ********************************************************************************/ - -#if defined(WITH_HDF5) && defined(IFOPSH_WITH_OPENCASCADE) - -#include "geometry_serializer_plugin.h" -#include "HdfSerializer.h" - -#include -#include - -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 create_serializer(const geometry_serializer_context& context) { - return boost::make_shared(context.output_temp_filename, context.geometry_settings, context.serializer_settings); -} - -void configure_serializer(geometry_serializer_context& context) { - context.geometry_settings.get().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 diff --git a/win/build-deps.cmd b/win/build-deps.cmd index e0ae94b9ab..96a5150bf0 100644 --- a/win/build-deps.cmd +++ b/win/build-deps.cmd @@ -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% diff --git a/win/run-cmake.bat b/win/run-cmake.bat index 84e7e1cff5..98d291f8ce 100755 --- a/win/run-cmake.bat +++ b/win/run-cmake.bat @@ -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% diff --git a/win/utils/tools.ps1 b/win/utils/tools.ps1 index 583e4cfb3b..a36186c508 100644 --- a/win/utils/tools.ps1 +++ b/win/utils/tools.ps1 @@ -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