mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-21 12:36:00 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 54df93c001 |
@@ -1,4 +1,5 @@
|
||||
Checks: 'bugprone-*,cert-*,clang-analyzer-*,readability-*'
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: ''
|
||||
AnalyzeTemporaryDtors: false
|
||||
FormatStyle: none
|
||||
@@ -35,9 +35,6 @@ jobs:
|
||||
lfs: true
|
||||
token: ${{ secrets.BUILD_REPO_TOKEN }}
|
||||
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
brew update
|
||||
@@ -64,7 +61,7 @@ jobs:
|
||||
- name: Unpack Dependencies
|
||||
run: |
|
||||
cd build
|
||||
uv run ../nix/cache_dependencies.py unpack
|
||||
python ../nix/cache_dependencies.py unpack
|
||||
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2.23
|
||||
@@ -105,7 +102,7 @@ jobs:
|
||||
# INSTALL_RPATH to "@loader_path" on Apple.
|
||||
CXXFLAGS="-O3" CFLAGS="-O3 ${DARWIN_C_SOURCE}" ADD_COMMIT_SHA=1 BUILD_CFG=Release \
|
||||
BUILD_BONSAIVIEWER=ON QT_DIR="${QT_DIR}" \
|
||||
uv run ./nix/build-all.py -v --diskcleanup --ifcopenshell-shared ${MAC_INTEL} \
|
||||
python3 ./nix/build-all.py -v --diskcleanup --ifcopenshell-shared ${MAC_INTEL} \
|
||||
| tee build.log
|
||||
|
||||
- name: Upload Build Logs
|
||||
@@ -122,7 +119,7 @@ jobs:
|
||||
- name: Pack Dependencies
|
||||
run: |
|
||||
cd build
|
||||
uv run ../nix/cache_dependencies.py pack
|
||||
python ../nix/cache_dependencies.py pack
|
||||
|
||||
- name: Commit and Push Changes to Build Repository
|
||||
run: |
|
||||
@@ -139,7 +136,7 @@ jobs:
|
||||
# packaging/build.py stages the connector binary + connector.json
|
||||
# into dist/autodesk/; the .app loop below copies that folder into
|
||||
# the bundle. Same on-disk shape as the Linux and Windows builds.
|
||||
uv run src/bonsaiviewer-autodesk/packaging/build.py
|
||||
python3 src/bonsaiviewer-autodesk/packaging/build.py
|
||||
autodesk_connector_dir="$PWD/src/bonsaiviewer-autodesk/dist/autodesk"
|
||||
test -d "$autodesk_connector_dir"
|
||||
|
||||
|
||||
@@ -92,6 +92,10 @@ jobs:
|
||||
./run_pytest.py setup
|
||||
./run_pytest.py run
|
||||
|
||||
- name: Setup tmate session
|
||||
if: failure()
|
||||
uses: mxschmitt/action-tmate@v3
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v6
|
||||
with:
|
||||
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
python-version: '3.11'
|
||||
- name: Get current version
|
||||
id: version
|
||||
run: echo "version=$(sed -E 's/[[:alpha:]]+[0-9]+$//' VERSION)" >> $GITHUB_OUTPUT
|
||||
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
|
||||
- name: Compile
|
||||
run: |
|
||||
cd src/bonsai && make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }}
|
||||
|
||||
@@ -27,9 +27,7 @@ jobs:
|
||||
|
||||
- name: Get current version
|
||||
id: version
|
||||
# Strip any trailing prerelease label and number; the dated alpha
|
||||
# suffix is added below.
|
||||
run: echo "version=$(sed -E 's/[[:alpha:]]+[0-9]+$//' VERSION)" >> $GITHUB_OUTPUT
|
||||
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get current date
|
||||
id: date
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
python-version: '3.11'
|
||||
- name: Get current version
|
||||
id: version
|
||||
run: echo "version=$(sed -E 's/[[:alpha:]]+[0-9]+$//' VERSION)" >> $GITHUB_OUTPUT
|
||||
run: echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "date=$(date +'%y%m%d')" >> $GITHUB_OUTPUT
|
||||
|
||||
@@ -43,7 +43,6 @@ jobs:
|
||||
sudo apt update
|
||||
sudo apt-get install --no-install-recommends -y \
|
||||
cmake \
|
||||
bison \
|
||||
gcc \
|
||||
g++ \
|
||||
libboost-date-time-dev \
|
||||
@@ -62,23 +61,13 @@ jobs:
|
||||
libocct-ocaf-dev \
|
||||
libocct-visualization-dev \
|
||||
libpcre3-dev \
|
||||
libpcre2-dev \
|
||||
libtbb-dev \
|
||||
libxml2-dev \
|
||||
libxi-dev \
|
||||
occt-misc \
|
||||
tcl-dev \
|
||||
tk-dev
|
||||
|
||||
- name: Build SWIG
|
||||
# IfcOpenShell requires SWIG 4.1+, ubuntu-22.04 ships 4.0.2.
|
||||
run: |
|
||||
sudo apt-get remove --purge -y swig swig4.0
|
||||
git clone https://github.com/swig/swig --branch v4.2.1 --depth 1
|
||||
cmake -S swig -B swig/build -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build swig/build -j "$(nproc)"
|
||||
sudo cmake --install swig/build
|
||||
swig -version
|
||||
tk-dev \
|
||||
swig
|
||||
|
||||
- name: Configure minimal IfcOpenShell
|
||||
run: |
|
||||
|
||||
@@ -121,7 +121,7 @@ jobs:
|
||||
cd OpenCOLLADA
|
||||
git checkout v1.6.68
|
||||
patch -p1 --batch --forward -i ../nix/patches/opencollada/pr622_and_disable_subdirs.patch
|
||||
patch -p1 --batch --forward -i ../nix/patches/opencollada/config_select_libs_by_use_shared.patch
|
||||
patch -p1 --batch --forward -i ../nix/patches/opencollada/allow_static_libraries_config_on_unix.patch
|
||||
mkdir build && cd build
|
||||
cmake .. \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
# This file was generated with the assistance of an AI coding tool.
|
||||
|
||||
name: Publish C++ API documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- v0.9.0
|
||||
paths:
|
||||
- '.github/workflows/publish-cpp-api-docs.yml'
|
||||
- 'docs/cpp-api/**'
|
||||
- 'src/ifcgeom/**'
|
||||
- 'src/ifcparse/**'
|
||||
- 'src/serializers/**'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: publish-cpp-api-docs
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
if: github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: Checkout IfcOpenShell
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v7
|
||||
with:
|
||||
python-version: '3.10'
|
||||
|
||||
- name: Install documentation dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes doxygen graphviz
|
||||
python -m pip install --requirement docs/cpp-api/requirements.txt
|
||||
|
||||
- name: Build C++ API documentation
|
||||
working-directory: docs/cpp-api
|
||||
run: |
|
||||
export PROJECT_NUMBER="$(git rev-parse --short HEAD)"
|
||||
python -m sphinx -M html . output -W --keep-going
|
||||
|
||||
- name: Checkout documentation repository
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
repository: IfcOpenShell/cpp_docs
|
||||
ref: master
|
||||
path: published-docs
|
||||
token: ${{ secrets.BUILD_REPO_TOKEN }}
|
||||
|
||||
- name: Replace published documentation
|
||||
run: |
|
||||
publish_tree="${RUNNER_TEMP}/published-docs-tree"
|
||||
mkdir -p "${publish_tree}/v0.9.0-latest"
|
||||
|
||||
rsync --archive docs/cpp-api/output/html/ "${publish_tree}/v0.9.0-latest/"
|
||||
touch "${publish_tree}/.nojekyll"
|
||||
|
||||
if [[ -f published-docs/CNAME ]]; then
|
||||
cp published-docs/CNAME "${publish_tree}/CNAME"
|
||||
fi
|
||||
|
||||
rsync --archive --delete --exclude='.git/' "${publish_tree}/" published-docs/
|
||||
|
||||
- name: Commit and push if changed
|
||||
working-directory: published-docs
|
||||
env:
|
||||
SOURCE_SHA: ${{ github.sha }}
|
||||
run: |
|
||||
git config user.name 'IfcOpenBot'
|
||||
git config user.email 'IfcOpenBot@users.noreply.github.com'
|
||||
|
||||
git add --all
|
||||
if git diff --cached --quiet; then
|
||||
echo "No changes to commit"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git commit -m "Update C++ API docs from ${SOURCE_SHA:0:7}"
|
||||
git push origin master
|
||||
+3
-7
@@ -111,11 +111,10 @@ src/ifcopenshell-python/ifcopenshell/_ifcopenshell_wrapper*.so
|
||||
src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.py
|
||||
|
||||
# plugins
|
||||
src/ifcopenshell-python/ifcopenshell/ifcopenshell_document_*.so
|
||||
src/ifcopenshell-python/ifcopenshell/ifcopenshell_geometry_*.so
|
||||
src/ifcopenshell-python/ifcopenshell/ifcopenshell_parse_schema*.so
|
||||
src/ifcopenshell-python/ifcopenshell/ifcopenshell.document.*.so
|
||||
src/ifcopenshell-python/ifcopenshell/ifcopenshell.geometry.*.so
|
||||
src/ifcopenshell-python/ifcopenshell/ifcopenshell.parse.schema*.so
|
||||
src/ifcopenshell-python/ifcopenshell/libifcopenshell.geometry.so
|
||||
src/ifcopenshell-python/ifcopenshell/libifcopenshell.geometry.writer.so
|
||||
src/ifcopenshell-python/ifcopenshell/libifcopenshell.parse.so
|
||||
src/ifcopenshell-python/ifcopenshell/libifcopenshell.plugin.so
|
||||
|
||||
@@ -126,9 +125,6 @@ src/ifcopenshell-python/ifcopenshell/libifcopenshell.plugin.so
|
||||
.clangd
|
||||
# clangd cache
|
||||
.cache
|
||||
# Useful for symlinking json compilation database from cmake,
|
||||
# allowing clang commands without `-p path/to/build`.
|
||||
/compile_commands.json
|
||||
|
||||
# Brickschema
|
||||
src/bonsai/bonsai/bim/schema/Brick.ttl
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
[submodule "src/ifcopenshell-python/test/Sample-BIM-Files"]
|
||||
path = src/ifcopenshell-python/test/Sample-BIM-Files
|
||||
url = https://github.com/IfcOpenShell/ids-test-files
|
||||
[submodule "docs/cpp-api/assets/doxygen-awesome-css"]
|
||||
path = docs/cpp-api/assets/doxygen-awesome-css
|
||||
url = https://github.com/jothepro/doxygen-awesome-css.git
|
||||
[submodule "src/ifcopenshell-python/ifcopenshell/simple_spf"]
|
||||
path = src/ifcopenshell-python/ifcopenshell/simple_spf
|
||||
url = https://github.com/IfcOpenShell/step-file-parser
|
||||
|
||||
+14
-19
@@ -36,14 +36,6 @@ file(READ "../VERSION" "RELEASE_VERSION_")
|
||||
string(STRIP "${RELEASE_VERSION_}" RELEASE_VERSION)
|
||||
message(STATUS "Detected version '${RELEASE_VERSION}'")
|
||||
|
||||
# CMake's project(VERSION) only accepts numeric components. Keep the complete
|
||||
# release identifier for build information, but use its numeric release part
|
||||
# for PROJECT_VERSION, SOVERSION, and generated CMake package metadata.
|
||||
string(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" PROJECT_VERSION_NUMERIC "${RELEASE_VERSION}")
|
||||
if(NOT PROJECT_VERSION_NUMERIC)
|
||||
message(FATAL_ERROR "VERSION must start with a numeric major.minor.patch version: '${RELEASE_VERSION}'")
|
||||
endif()
|
||||
|
||||
add_definitions(-D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR)
|
||||
|
||||
if(POLICY CMP0141) # 3.25+
|
||||
@@ -63,15 +55,9 @@ endif()
|
||||
# Include utility macros and functions
|
||||
include(utilities.cmake)
|
||||
|
||||
# Use a SemVer-compatible spelling for CPack artifact names. A trailing
|
||||
# alphabetic label and number is separated from the numeric version by a
|
||||
# hyphen: for example, 0.9.0alpha0 becomes 0.9.0-alpha0.
|
||||
# use extra version to make pre-release using eg semver
|
||||
if(NOT DEFINED EXTRA_VERSION)
|
||||
if(RELEASE_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+([A-Za-z]+)([0-9]+)$")
|
||||
set(EXTRA_VERSION "-${CMAKE_MATCH_1}${CMAKE_MATCH_2}")
|
||||
else()
|
||||
set(EXTRA_VERSION "")
|
||||
endif()
|
||||
set(EXTRA_VERSION "-alpha.3")
|
||||
endif()
|
||||
|
||||
option(MINIMAL_BUILD "The build is to make a minimal version of IFC converter from OCCT into IFC." OFF)
|
||||
@@ -133,7 +119,7 @@ option(WITH_ZSTD "Use Zstd compression in RocksDB writes" OFF)
|
||||
option(USERSPACE_PYTHON_PREFIX "Installs IfcPython for the current user only instead of system-wide." OFF)
|
||||
option(USE_DEBUG_PYTHON "Use debug binaries when building Debug IfcPython on Windows." OFF)
|
||||
option(ADD_COMMIT_SHA "Add commit sha and branch in version number, requires git" OFF)
|
||||
option(VERSION_OVERRIDE "Use VERSION as the branch label when commit information is embedded" OFF)
|
||||
option(VERSION_OVERRIDE "Override the version defined in buildinfo.cpp with the file VERSION in the repository root" OFF)
|
||||
|
||||
set(
|
||||
PYTHON_MODULE_INSTALL_DIR
|
||||
@@ -141,7 +127,15 @@ set(
|
||||
"Directory to install IfcPython package to. By default package is installed in found Python's site-packages."
|
||||
)
|
||||
|
||||
project(IfcOpenShell VERSION ${PROJECT_VERSION_NUMERIC})
|
||||
if (VERSION_OVERRIDE)
|
||||
file(READ "../VERSION" "RELEASE_VERSION_")
|
||||
string(STRIP "${RELEASE_VERSION_}" RELEASE_VERSION)
|
||||
message(STATUS "Detected version '${RELEASE_VERSION}'")
|
||||
else()
|
||||
set(RELEASE_VERSION "0.8.0")
|
||||
endif()
|
||||
|
||||
project(IfcOpenShell VERSION ${RELEASE_VERSION})
|
||||
|
||||
# Make sure CMake modules in this project are found first
|
||||
list(PREPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR})
|
||||
@@ -699,7 +693,8 @@ endif()
|
||||
|
||||
# Documentation
|
||||
if(BUILD_DOCUMENTATION)
|
||||
add_subdirectory(../docs/cpp-api docs/cpp-api)
|
||||
set(CMAKE_MODULE_PATH "../docs/cmake")
|
||||
add_subdirectory(../docs docs)
|
||||
endif()
|
||||
|
||||
if(BUILD_EXAMPLES)
|
||||
|
||||
@@ -52,7 +52,6 @@ macro(SET_INSTALL_SELF_RPATH _target)
|
||||
endmacro()
|
||||
|
||||
function(ifcopenshell_plugin_target TARGET)
|
||||
# Plug-ins are loaded by exact filename and should not receive a platform library prefix.
|
||||
set_target_properties(${TARGET} PROPERTIES PREFIX "")
|
||||
if((NOT WIN32) AND BUILD_SHARED_LIBS AND NOT WASM_BUILD AND NOT CREATE_BUNDLE AND NOT CMAKE_INSTALL_RPATH AND COMMAND SET_INSTALL_SELF_RPATH)
|
||||
SET_INSTALL_SELF_RPATH(${TARGET})
|
||||
|
||||
+34
-14
@@ -1,15 +1,35 @@
|
||||
find_package(Doxygen REQUIRED)
|
||||
find_program(
|
||||
SPHINX_EXECUTABLE
|
||||
NAMES sphinx-build
|
||||
REQUIRED
|
||||
DOC "Path to the sphinx-build executable"
|
||||
)
|
||||
#Look for an executable called sphinx-build
|
||||
find_program(SPHINX_EXECUTABLE NAMES sphinx-build DOC "Path to sphinx-build executable")
|
||||
|
||||
add_custom_target(
|
||||
cpp_api_docs
|
||||
COMMAND ${SPHINX_EXECUTABLE} -M html . output -W --keep-going
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Generating the IfcOpenShell C++ API documentation"
|
||||
VERBATIM
|
||||
)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
#Handle standard arguments to find_package like REQUIRED and QUIET
|
||||
find_package_handle_standard_args(Sphinx "Failed to find sphinx-build executable" SPHINX_EXECUTABLE)
|
||||
|
||||
find_package(Doxygen REQUIRED)
|
||||
#find_package(Sphinx REQUIRED)
|
||||
|
||||
set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/docs/sphinx)
|
||||
|
||||
message(STATUS "SPHINX BUILD ${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
file(MAKE_DIRECTORY ./output/doxygen)
|
||||
|
||||
if(DOXYGEN_FOUND)
|
||||
add_custom_target(
|
||||
Sphinx
|
||||
ALL
|
||||
COMMAND ${SPHINX_EXECUTABLE} -v -T -b html ${SPHINX_SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/output
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/output
|
||||
COMMENT "Generating documentation with Sphinx"
|
||||
)
|
||||
|
||||
# add_custom_target(ifcopenshell_python_docs ALL
|
||||
# COMMAND make html
|
||||
# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
|
||||
# OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
|
||||
# COMMENT "Generating documentation with Sphinx")
|
||||
else(DOXYGEN_FOUND)
|
||||
message("Doxygen need to be installed to generate the doxygen documentation")
|
||||
endif(DOXYGEN_FOUND)
|
||||
|
||||
+22
-63
@@ -68,7 +68,7 @@ PROJECT_LOGO =
|
||||
# entered, it will be relative to the location where doxygen was started. If
|
||||
# left blank the current directory will be used.
|
||||
|
||||
OUTPUT_DIRECTORY = ./output/doxygen
|
||||
OUTPUT_DIRECTORY = ./output
|
||||
|
||||
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
|
||||
# sub-directories (in 2 levels) under the output directory of each output format
|
||||
@@ -852,7 +852,7 @@ WARNINGS = YES
|
||||
# will automatically be disabled.
|
||||
# The default value is: YES.
|
||||
|
||||
WARN_IF_UNDOCUMENTED = NO
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
|
||||
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
|
||||
# potential errors in the documentation, such as documenting some parameters in
|
||||
@@ -901,7 +901,7 @@ WARN_IF_UNDOC_ENUM_VAL = NO
|
||||
# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT.
|
||||
# The default value is: NO.
|
||||
|
||||
WARN_AS_ERROR = FAIL_ON_WARNINGS
|
||||
WARN_AS_ERROR = NO
|
||||
|
||||
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
|
||||
# can produce. The string should contain the $file, $line, and $text tags, which
|
||||
@@ -944,6 +944,7 @@ WARN_LOGFILE =
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = ../../src/ifcgeom \
|
||||
../../src/ifcgeom_schema_agnostic \
|
||||
../../src/ifcparse \
|
||||
../../src/serializers \
|
||||
|
||||
@@ -1000,7 +1001,7 @@ RECURSIVE = YES
|
||||
# Note that relative paths are relative to the directory from which doxygen is
|
||||
# run.
|
||||
|
||||
EXCLUDE = ../../src/ifcparse/schemas
|
||||
EXCLUDE =
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||
@@ -1024,33 +1025,7 @@ EXCLUDE_PATTERNS =
|
||||
# wildcard * is used, a substring. Examples: ANamespace, AClass,
|
||||
# ANamespace::AClass, ANamespace::*Test
|
||||
|
||||
EXCLUDE_SYMBOLS = "ifcopenshell::geom::opaque_number::*" \
|
||||
ifcopenshell::entity::attribute_by_name_cmp \
|
||||
ifcopenshell::impl::rocks_db_file_storage::rocksdb_types_iterator \
|
||||
ifcopenshell::impl::in_memory_file_storage::type_iterator \
|
||||
"util::string_buffer::*_item" \
|
||||
util::string_buffer::item \
|
||||
ifcopenshell::geom::layer_filter::wildcards_match \
|
||||
ifcopenshell::paged_file_impl::entry \
|
||||
ifcopenshell::token \
|
||||
attribute_value::pointer_type \
|
||||
INCLUDE_PARENT_PARENT_DIR \
|
||||
POSTFIX_SCHEMA_ \
|
||||
POSTFIX_SCHEMA__ \
|
||||
STRINGIFY_ \
|
||||
MAKE_INIT_FN_ \
|
||||
MAKE_INIT_FN__ \
|
||||
key_from_string \
|
||||
add_ \
|
||||
subtract_ \
|
||||
multiply_ \
|
||||
divide_ \
|
||||
equals_ \
|
||||
less_than_ \
|
||||
negate_ \
|
||||
ifcopenshell::geom::utils::create_cube \
|
||||
ifcopenshell::geom::utils::create_polyhedron \
|
||||
ifcopenshell::geom::utils::create_nef_polyhedron
|
||||
EXCLUDE_SYMBOLS =
|
||||
|
||||
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
|
||||
# that contain example code fragments that are included (see the \include
|
||||
@@ -1261,7 +1236,7 @@ IGNORE_PREFIX =
|
||||
# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
|
||||
# The default value is: YES.
|
||||
|
||||
GENERATE_HTML = NO
|
||||
GENERATE_HTML = YES
|
||||
|
||||
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
|
||||
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
|
||||
@@ -1336,7 +1311,7 @@ HTML_STYLESHEET =
|
||||
# documentation.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
HTML_EXTRA_STYLESHEET = assets/doxygen-awesome-css/doxygen-awesome.css
|
||||
|
||||
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
|
||||
# other source files which should be copied to the HTML output directory. Note
|
||||
@@ -2191,7 +2166,7 @@ MAN_LINKS = NO
|
||||
# captures the structure of the code including all documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
GENERATE_XML = YES
|
||||
GENERATE_XML = NO
|
||||
|
||||
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
|
||||
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
|
||||
@@ -2328,7 +2303,7 @@ ENABLE_PREPROCESSING = YES
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
MACRO_EXPANSION = YES
|
||||
MACRO_EXPANSION = NO
|
||||
|
||||
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
|
||||
# the macro expansion is limited to the macros specified with the PREDEFINED and
|
||||
@@ -2336,7 +2311,7 @@ MACRO_EXPANSION = YES
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
|
||||
# If the SEARCH_INCLUDES tag is set to YES, the include files in the
|
||||
# INCLUDE_PATH will be searched if a #include is found.
|
||||
@@ -2369,17 +2344,7 @@ INCLUDE_FILE_PATTERNS =
|
||||
# recursively expanded use the := operator instead of the = operator.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
PREDEFINED = IFC_PARSE_API= \
|
||||
IFC_SCHEMA_API= \
|
||||
IFC_GEOM_API= \
|
||||
IFC_GEOMLIBRARY_API= \
|
||||
IFC_GEOMSERIALIZATION_API= \
|
||||
SERIALIZERS_API= \
|
||||
"POSTFIX_SCHEMA(name)=name##_Schema" \
|
||||
"Handle(name):=opencascade::handle<name>" \
|
||||
kernel_=kernel \
|
||||
Simplekernel_=Simplekernel \
|
||||
inline=
|
||||
PREDEFINED =
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||
# tag can be used to specify a list of macro names that should be expanded. The
|
||||
@@ -2388,22 +2353,7 @@ PREDEFINED = IFC_PARSE_API= \
|
||||
# definition found in the source code.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
EXPAND_AS_DEFINED = kernel_ \
|
||||
cgal_shape \
|
||||
cgal_kernel \
|
||||
cgal_placement \
|
||||
cgal_point \
|
||||
cgal_direction \
|
||||
cgal_vector \
|
||||
cgal_plane \
|
||||
cgal_curve \
|
||||
cgal_wire \
|
||||
cgal_face \
|
||||
cgal_polyhedron \
|
||||
cgal_vertex_descriptor \
|
||||
cgal_face_descriptor \
|
||||
create_cube \
|
||||
create_polyhedron
|
||||
EXPAND_AS_DEFINED =
|
||||
|
||||
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
|
||||
# remove all references to function-like macros that are alone on a line, have
|
||||
@@ -2781,6 +2731,15 @@ DOT_GRAPH_MAX_NODES = 50
|
||||
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
|
||||
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
|
||||
# files in one run (i.e. multiple -o and -T options on the command line). This
|
||||
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
|
||||
# this, this feature is disabled by default.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_MULTI_TARGETS = NO
|
||||
|
||||
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
|
||||
# explaining the meaning of the various boxes and arrows in the dot generated
|
||||
# graphs.
|
||||
|
||||
+18
-41
@@ -1,56 +1,33 @@
|
||||
# IfcOpenShell C++ API documentation
|
||||
|
||||
This directory contains the Sphinx, Doxygen, Breathe, and Exhale configuration
|
||||
for the IfcOpenShell C++ API reference. During a Sphinx build, Exhale runs
|
||||
Doxygen, Breathe consumes the generated XML, and Exhale creates the API pages.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Python 3.10 or newer
|
||||
- [Doxygen](https://www.doxygen.nl/)
|
||||
- [Graphviz](https://graphviz.org/)
|
||||
|
||||
Install the Python dependencies from this directory:
|
||||
|
||||
```shell
|
||||
python -m pip install -r requirements.txt
|
||||
```
|
||||
|
||||
Both `doxygen` and `dot` must be available on `PATH`. For the standard Windows
|
||||
install locations, this can be done for the current PowerShell session with:
|
||||
|
||||
```powershell
|
||||
$env:Path = "C:\Program Files\doxygen\bin;C:\Program Files\Graphviz\bin;$env:Path"
|
||||
```
|
||||
This folder contains the setup to build the IfcOpenShell C++ API documentation from the source code.
|
||||
|
||||
## Generating the documentation
|
||||
|
||||
From this directory, run:
|
||||
> Prerequisites:
|
||||
>
|
||||
> Make sure to have [Doxygen](https://www.doxygen.nl) and [Graphviz](https://graphviz.org) installed into your `$PATH` variable.
|
||||
>
|
||||
> The documentation also use the [doxygen-awesome](https://jothepro.github.io/doxygen-awesome-css) theme as a git submodule.
|
||||
|
||||
Build with the command (from within the `/docs/cpp-api` folder):
|
||||
|
||||
```shell
|
||||
python -m sphinx -M html . output -W --keep-going
|
||||
$ doxygen
|
||||
```
|
||||
|
||||
To include the current Git commit in Doxygen's project metadata, set
|
||||
`PROJECT_NUMBER` before building. For example, in PowerShell:
|
||||
|
||||
```powershell
|
||||
$env:PROJECT_NUMBER = git rev-parse --short HEAD
|
||||
python -m sphinx -M html . output -W --keep-going
|
||||
```
|
||||
|
||||
Or in a POSIX shell:
|
||||
To include the current git commit hash into the build documentation, use the following command:
|
||||
|
||||
```shell
|
||||
PROJECT_NUMBER=$(git rev-parse --short HEAD) python -m sphinx -M html . output -W --keep-going
|
||||
$ PROJECT_NUMBER=$(git rev-parse --short HEAD) doxygen
|
||||
```
|
||||
|
||||
Alternatively, configure the main CMake project with
|
||||
`-DBUILD_DOCUMENTATION=ON` and build the `cpp_api_docs` target.
|
||||
This will extract the current commit hash in short version and sets the propper ENV variable used by doxygen.
|
||||
|
||||
The generated documentation is written to `output/html/index.html`. The
|
||||
generated Doxygen XML and Exhale sources are kept under `output/` as build
|
||||
artifacts.
|
||||
The generation of the documentation might take a while depending on your systems hardware, as it is configured to generate the Class graphs using .
|
||||
|
||||
The generated headers under `src/ifcparse/schemas` are intentionally excluded
|
||||
from this documentation build.
|
||||
The resulting documentation is located unter `/cpp-api/output/html` and can be directly accessed with your browser:
|
||||
|
||||
```shell
|
||||
$ open ./output/html/index.html
|
||||
```
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
# This file was generated with the assistance of an AI coding tool.
|
||||
|
||||
import warnings
|
||||
from pathlib import Path
|
||||
from shutil import rmtree
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx90Warning
|
||||
|
||||
warnings.filterwarnings("ignore", category=RemovedInSphinx90Warning, module=r"exhale\.configs")
|
||||
|
||||
generated_directories = (
|
||||
Path(__file__).parent / "output" / "api",
|
||||
Path(__file__).parent / "output" / "doxygen",
|
||||
)
|
||||
for generated_directory in generated_directories:
|
||||
if generated_directory.is_dir():
|
||||
rmtree(generated_directory)
|
||||
|
||||
project = "IfcOpenShell"
|
||||
copyright = "2020, IfcOpenShell"
|
||||
|
||||
extensions = [
|
||||
"breathe",
|
||||
"exhale",
|
||||
]
|
||||
|
||||
primary_domain = "cpp"
|
||||
highlight_language = "cpp"
|
||||
html_theme = "alabaster"
|
||||
|
||||
breathe_projects = {
|
||||
"IfcOpenShell": "./output/doxygen/xml",
|
||||
}
|
||||
breathe_default_project = "IfcOpenShell"
|
||||
|
||||
exhale_args = {
|
||||
"containmentFolder": "./output/api",
|
||||
"rootFileName": "library_root.rst",
|
||||
"rootFileTitle": "IfcOpenShell C++ API",
|
||||
"doxygenStripFromPath": "../..",
|
||||
"createTreeView": False,
|
||||
"exhaleExecutesDoxygen": True,
|
||||
"exhaleUseDoxyfile": True,
|
||||
}
|
||||
|
||||
cpp_id_attributes = [
|
||||
"IFC_PARSE_API",
|
||||
"IFC_SCHEMA_API",
|
||||
"IFC_GEOM_API",
|
||||
"IFC_GEOMLIBRARY_API",
|
||||
"IFC_GEOMSERIALIZATION_API",
|
||||
"SERIALIZERS_API",
|
||||
]
|
||||
|
||||
exclude_patterns = [
|
||||
"output/doctrees",
|
||||
"output/doxygen",
|
||||
"output/html",
|
||||
]
|
||||
@@ -1,9 +0,0 @@
|
||||
.. This file was generated with the assistance of an AI coding tool.
|
||||
|
||||
IfcOpenShell C++ API
|
||||
====================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
output/api/library_root
|
||||
@@ -1,5 +0,0 @@
|
||||
# This file was generated with the assistance of an AI coding tool.
|
||||
|
||||
Sphinx==8.1.3
|
||||
breathe==4.36.0
|
||||
exhale==0.3.7
|
||||
+37
-54
@@ -1,8 +1,5 @@
|
||||
#!/usr/bin/python
|
||||
# /// script
|
||||
# dependencies = [
|
||||
# "typing_extensions",
|
||||
# ]
|
||||
# ///
|
||||
###############################################################################
|
||||
# #
|
||||
@@ -35,7 +32,6 @@ Example usage:
|
||||
Available arguments:
|
||||
``-py-313`` - build for specific Python version
|
||||
(building for all supported Python version by default).
|
||||
``-occt-xxx`` - use a specific OCCT version (e.g. ``-occt-7.8.1``) instead of the default
|
||||
``-wasm`` - compile for wasm
|
||||
``-without-xxx`` - do not build dependency ``xxx`` (e.g. ``--without-swig``)
|
||||
``-mac-cross-compile-intel`` - cross compile for Intel Mac on Apple Silicon host
|
||||
@@ -43,8 +39,6 @@ Available arguments:
|
||||
``-ifcopenshell-shared`` - build only IfcOpenShell's own libraries as shared
|
||||
(dependencies stay static). Redundant if ``-shared`` is also passed.
|
||||
``-diskcleanup`` - clean up build directories after finishing building dependencies
|
||||
``-build-examples`` - build IfcOpenShell examples
|
||||
``-lto`` - enable link-time optimization (adds ``-flto`` to compiler flags)
|
||||
``-v`` - enable verbose logs
|
||||
|
||||
|
||||
@@ -137,8 +131,6 @@ from pathlib import Path
|
||||
from typing import Literal
|
||||
from urllib.request import urlretrieve
|
||||
|
||||
from typing_extensions import assert_never
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.INFO)
|
||||
ch = logging.StreamHandler()
|
||||
@@ -225,11 +217,6 @@ def cecho(message, color=NO_COLOR):
|
||||
|
||||
|
||||
# Flags.
|
||||
BUILD_EXAMPLES = "build-examples" in flags
|
||||
DISK_CLEANUP = "diskcleanup" in flags
|
||||
LTO = "lto" in flags
|
||||
VERBOSE = "v" in flags
|
||||
|
||||
APPLE = platform.system() == "Darwin"
|
||||
MAC_CROSS_COMPILE_INTEL = "mac-cross-compile-intel" in flags
|
||||
assert platform.system() == "Darwin" or not MAC_CROSS_COMPILE_INTEL
|
||||
@@ -385,7 +372,7 @@ def gather_dependencies(dep: str) -> Generator[str]:
|
||||
yield x
|
||||
|
||||
|
||||
if VERBOSE:
|
||||
if "v" in flags:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
|
||||
ch.setFormatter(formatter)
|
||||
@@ -445,6 +432,7 @@ if WASM:
|
||||
SKIP_TARGETS_FOR_WASM = {
|
||||
"rocksdb",
|
||||
"opencollada",
|
||||
"swig",
|
||||
"pcre",
|
||||
"IfcGeom",
|
||||
"IfcConvert",
|
||||
@@ -466,8 +454,12 @@ bison = "bison"
|
||||
|
||||
missing_commands: list[str] = []
|
||||
required_commands = [git, bunzip2, tar, cc, cplusplus, autoconf, automake, make, "patch", "cmake", yacc, xz, bison]
|
||||
if WASM:
|
||||
if "wasm" in flags:
|
||||
# Skip swig build for WASM.
|
||||
required_commands.append("swig")
|
||||
required_commands.append("pyodide")
|
||||
required_commands.remove(yacc)
|
||||
required_commands.remove(bison)
|
||||
if platform.system() == "Linux" and "BonsaiViewer" in targets:
|
||||
required_commands.append("patchelf")
|
||||
|
||||
@@ -584,7 +576,7 @@ def run_autoconf(dependency_name: str, configure_args: list[str], cwd: str) -> N
|
||||
prefix = os.path.realpath(f"{DEPS_DIR}/install/{dependency_name}")
|
||||
|
||||
wasm = []
|
||||
if WASM:
|
||||
if "wasm" in flags:
|
||||
wasm.append("emconfigure")
|
||||
|
||||
run(
|
||||
@@ -592,7 +584,7 @@ def run_autoconf(dependency_name: str, configure_args: list[str], cwd: str) -> N
|
||||
*wasm,
|
||||
"/bin/sh",
|
||||
"../configure",
|
||||
*(["--host=wasm32"] if WASM and not any(s.startswith("--host") for s in configure_args) else []),
|
||||
*(["--host=wasm32"] if "wasm" in flags and not any(s.startswith("--host") for s in configure_args) else []),
|
||||
*configure_args,
|
||||
f"--prefix={prefix}",
|
||||
],
|
||||
@@ -600,20 +592,18 @@ def run_autoconf(dependency_name: str, configure_args: list[str], cwd: str) -> N
|
||||
)
|
||||
|
||||
|
||||
def run_cmake(
|
||||
name, cmake_args: list[str], cmake_dir: str | None = None, cwd: str | None = None, native: bool = False
|
||||
) -> None:
|
||||
def run_cmake(arg1, cmake_args: list[str], cmake_dir: str | None = None, cwd: str | None = None):
|
||||
if cmake_dir is None:
|
||||
P = ".."
|
||||
else:
|
||||
P = cmake_dir
|
||||
|
||||
wasm = []
|
||||
if WASM and not native:
|
||||
if "wasm" in flags:
|
||||
wasm.append("emcmake")
|
||||
|
||||
cmake_flags: list[str] = []
|
||||
if not native and (not WASM or not WASM_CMAKE_IS_USING_INIT_VARS):
|
||||
if not WASM or not WASM_CMAKE_IS_USING_INIT_VARS:
|
||||
# For WASM we provide flags using just environment variables.
|
||||
# If we provide them using cmake vars, it will override emscripten toolchain flags.
|
||||
# Unsure if we need this in general even for non-WASM builds.
|
||||
@@ -629,10 +619,6 @@ def run_cmake(
|
||||
f"-DBUILD_SHARED_LIBS={OFF_ON[not BUILD_STATIC]}",
|
||||
)
|
||||
|
||||
if WASM and native:
|
||||
# Override emscripten cmake toolchain coming from environment variable.
|
||||
cmake_flags.append("-DCMAKE_TOOLCHAIN_FILE=")
|
||||
|
||||
run(
|
||||
[
|
||||
*wasm,
|
||||
@@ -641,7 +627,7 @@ def run_cmake(
|
||||
*cmake_flags,
|
||||
*cmake_args,
|
||||
f"-DCMAKE_BUILD_TYPE={BUILD_CFG}",
|
||||
*([] if native else [f"-DCMAKE_SHARED_LINKER_FLAGS={os.environ['LDFLAGS']}"]),
|
||||
f"-DCMAKE_SHARED_LINKER_FLAGS={os.environ['LDFLAGS']}",
|
||||
],
|
||||
cwd=cwd,
|
||||
)
|
||||
@@ -689,7 +675,7 @@ def build_dependency(
|
||||
additional_files: dict[str, str] | None = None,
|
||||
no_append_name=False,
|
||||
cmake_dir=None,
|
||||
cmake_native: bool = False,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
"""Handles building of dependencies with different tools (which are
|
||||
distinguished with the `mode` argument. `build_tool_args` is expected to be
|
||||
@@ -698,8 +684,7 @@ def build_dependency(
|
||||
|
||||
:param pre_compile_subs: A sequence of ``(fn, before, after)``
|
||||
:param additional_files: Mapping path->url.
|
||||
:param cmake_native: For ``mode="cmake"``, force a native (host) build
|
||||
even when building for WASM. Needed for build-time tools like swig.
|
||||
:param kwargs: Additional ``mode`` related kwargs.
|
||||
"""
|
||||
check_dir = os.path.join(DEPS_DIR, "install", name)
|
||||
if os.path.exists(check_dir):
|
||||
@@ -735,7 +720,7 @@ def build_dependency(
|
||||
logger.info(f"\rChecking {name}... ")
|
||||
git_clone_or_pull_repository(download_url, target_dir=os.path.join(build_dir, download_name), revision=revision)
|
||||
else:
|
||||
assert_never(download_tool)
|
||||
raise ValueError(f"download tool '{download_tool}' is not supported")
|
||||
download_dir = os.path.join(build_dir, download_name)
|
||||
|
||||
if os.path.isdir(download_dir):
|
||||
@@ -796,9 +781,9 @@ def build_dependency(
|
||||
if mode == "autoconf":
|
||||
run_autoconf(name, build_tool_args, cwd=extract_build_dir)
|
||||
elif mode == "cmake":
|
||||
run_cmake(name, build_tool_args, cwd=extract_build_dir, native=cmake_native)
|
||||
run_cmake(name, build_tool_args, cwd=extract_build_dir)
|
||||
else:
|
||||
assert_never(mode)
|
||||
raise ValueError()
|
||||
for fn, before, after in pre_compile_subs:
|
||||
with open(os.path.join(extract_dir, fn), "r") as f:
|
||||
s = f.read()
|
||||
@@ -814,14 +799,14 @@ def build_dependency(
|
||||
logger.info(f"\rConfiguring {name}...")
|
||||
run([bash, "./bootstrap.sh"], cwd=extract_dir)
|
||||
logger.info(f"\rBuilding {name}... ")
|
||||
run(["./b2", f"-j{IFCOS_NUM_BUILD_PROCS}"] + build_tool_args, cwd=extract_dir, can_fail=WASM)
|
||||
run(["./b2", f"-j{IFCOS_NUM_BUILD_PROCS}"] + build_tool_args, cwd=extract_dir, can_fail="wasm" in flags)
|
||||
logger.info(f"\rInstalling {name}... ")
|
||||
shutil.copytree(
|
||||
os.path.join(extract_dir, "boost"), os.path.join(DEPS_DIR, "install", f"boost-{BOOST_VERSION}", "boost")
|
||||
)
|
||||
logger.info(f"\rInstalled {name} \n")
|
||||
|
||||
if DISK_CLEANUP:
|
||||
if "diskcleanup" in flags:
|
||||
shutil.rmtree(build_dir, ignore_errors=True)
|
||||
|
||||
|
||||
@@ -927,7 +912,7 @@ ADDITIONAL_ARGS_STR = " ".join(ADDITIONAL_ARGS)
|
||||
|
||||
CXXFLAGS_MINIMAL = f"{CXXFLAGS} {PIC} {ADDITIONAL_ARGS_STR}"
|
||||
CFLAGS_MINIMAL = f"{CFLAGS} {PIC} {ADDITIONAL_ARGS_STR}"
|
||||
if WASM:
|
||||
if "wasm" in flags:
|
||||
# WASM `SIDE_MODULE_` are absorbed by `emcmake` automatically.
|
||||
CXXFLAGS = CXXFLAGS_MINIMAL
|
||||
CFLAGS = CFLAGS_MINIMAL
|
||||
@@ -948,7 +933,7 @@ else:
|
||||
CFLAGS = CFLAGS_MINIMAL
|
||||
LDFLAGS = f"{LDFLAGS} {ADDITIONAL_ARGS_STR}"
|
||||
|
||||
if LTO:
|
||||
if "lto" in flags:
|
||||
for f in compiler_flags:
|
||||
locals()[f] += f" -flto={IFCOS_NUM_BUILD_PROCS}"
|
||||
|
||||
@@ -1025,7 +1010,6 @@ if "swig" in targets:
|
||||
download_name="swig",
|
||||
download_tool=download_tool_git,
|
||||
revision=f"v{SWIG_VERSION}",
|
||||
cmake_native=WASM,
|
||||
)
|
||||
|
||||
if USE_OCCT and "occ" in targets:
|
||||
@@ -1036,13 +1020,13 @@ if USE_OCCT and "occ" in targets:
|
||||
|
||||
# Skip ExpToCasExe as we don't need it and it requires additional dependencies.
|
||||
# Before 7.7.2 ExpToCasExe is part of DataExchange, DETools doesn't exist yet.
|
||||
# Since we do need DataExchange (used for iges_serializer), we use a patch to skip only ExpToCasExe.
|
||||
# Since we do need DataExchange (used for IgesSerializer), we use a patch to skip only ExpToCasExe.
|
||||
if "7.7.2" > OCCT_VERSION >= "7.7":
|
||||
patches.append("./patches/occt/no_ExpToCasExe.patch")
|
||||
elif OCCT_VERSION >= "7.7.2":
|
||||
occt_args.append("-DBUILD_MODULE_DETools=OFF")
|
||||
|
||||
if WASM:
|
||||
if "wasm" in flags:
|
||||
patches.append("./patches/occt/no_em_js.patch")
|
||||
|
||||
build_dependency(
|
||||
@@ -1126,7 +1110,7 @@ if "libxml2" in targets:
|
||||
"--without-iconv",
|
||||
"--without-lzma",
|
||||
]
|
||||
if WASM:
|
||||
if "wasm" in flags:
|
||||
build_tool_args.append("--without-threads")
|
||||
build_dependency(
|
||||
f"libxml2-{LIBXML2_VERSION}",
|
||||
@@ -1148,7 +1132,7 @@ if "OpenCOLLADA" in targets:
|
||||
# whether shared libs were actually built. We make it follow `USE_SHARED` instead.
|
||||
patches.append("./patches/opencollada/config_select_libs_by_use_shared.patch")
|
||||
|
||||
if WASM:
|
||||
if "wasm" in flags:
|
||||
# This is necessary for the WASM build, because recent versions of
|
||||
# clang don't have the tr1:: namespace anymore. However, it breaks
|
||||
# some versions of gcc (9.4.0 at least) due to specializing std::hash
|
||||
@@ -1178,7 +1162,7 @@ if "OpenCOLLADA" in targets:
|
||||
revision=OPENCOLLADA_VERSION,
|
||||
)
|
||||
|
||||
if "python" in targets and not USE_CURRENT_PYTHON_VERSION and not WASM:
|
||||
if "python" in targets and not USE_CURRENT_PYTHON_VERSION and "wasm" not in flags:
|
||||
# Python should not be built with -fvisibility=hidden, from experience that introduces segfaults
|
||||
OLD_CPP_FLAGS = os.environ["CPPFLAGS"]
|
||||
OLD_CXX_FLAGS = os.environ["CXXFLAGS"]
|
||||
@@ -1239,7 +1223,7 @@ if "python" in targets and not USE_CURRENT_PYTHON_VERSION and not WASM:
|
||||
if "boost" in targets:
|
||||
str_concat = lambda prefix: lambda postfix: "" if postfix.strip() == "" else "=".join((prefix, postfix.strip()))
|
||||
toolset = []
|
||||
if WASM:
|
||||
if "wasm" in flags:
|
||||
toolset.append("toolset=emscripten")
|
||||
build_dependency(
|
||||
f"boost-{BOOST_VERSION}",
|
||||
@@ -1267,7 +1251,7 @@ if "boost" in targets:
|
||||
# patch="./patches/boost/boostorg_regex_62.patch",
|
||||
download_name=f"boost-{BOOST_VERSION}-b2-nodocs.tar.gz",
|
||||
)
|
||||
if WASM:
|
||||
if "wasm" in flags:
|
||||
# only supported on nix for now
|
||||
run(
|
||||
("find", ".", "-name", "*.bc", "-exec", "bash", "-c", "emar q ${1%.bc}.a $1", "bash", "{}", ";"),
|
||||
@@ -1309,7 +1293,9 @@ if "cgal" in targets:
|
||||
name=f"gmp-{GMP_VERSION}",
|
||||
mode="autoconf",
|
||||
build_tool_args=[ENABLE_FLAG, DISABLE_FLAG, "--with-pic", *gmp_args],
|
||||
pre_compile_subs=([("build/config.h", "HAVE_OBSTACK_VPRINTF 1", "HAVE_OBSTACK_VPRINTF 0")] if WASM else []),
|
||||
pre_compile_subs=(
|
||||
[("build/config.h", "HAVE_OBSTACK_VPRINTF 1", "HAVE_OBSTACK_VPRINTF 0")] if "wasm" in flags else []
|
||||
),
|
||||
patch=gmp_patches,
|
||||
# Sometimes ftp.gnu.org is very slow, use ftpmirror.gnu.org as a workaround.
|
||||
download_url="https://ftpmirror.gnu.org/gnu/gmp/",
|
||||
@@ -1441,7 +1427,7 @@ os.makedirs(ifcos_build_dir, exist_ok=True)
|
||||
|
||||
cmake_args = [
|
||||
"-DUSE_MMAP=OFF",
|
||||
f"-DBUILD_EXAMPLES={OFF_ON[BUILD_EXAMPLES]}",
|
||||
"-DBUILD_EXAMPLES=OFF",
|
||||
"-DBUILD_SHARED_LIBS=" + OFF_ON[not IFCOPENSHELL_STATIC],
|
||||
"-DGLTF_SUPPORT=ON",
|
||||
"-DBoost_NO_BOOST_CMAKE=On",
|
||||
@@ -1471,7 +1457,7 @@ def get_cmake_args_prefix_path(additional_paths: Sequence[str] = ()) -> list[str
|
||||
return [f"-DCMAKE_PREFIX_PATH={prefix_path}"]
|
||||
|
||||
|
||||
if WASM:
|
||||
if "wasm" in flags:
|
||||
# Boost is built by the build script so should not be found
|
||||
# inside of the sysroot set by the emscriptem toolchain
|
||||
cmake_args.append("-DWASM_BUILD=On")
|
||||
@@ -1537,10 +1523,7 @@ if "rocksdb" in targets:
|
||||
)
|
||||
|
||||
if "swig" in targets:
|
||||
# `cmake_args_prefix_path` won't work on wasm
|
||||
# because `find_program` in emscripten toolchain don't use `find_root_path`.
|
||||
# As a workaround we provide executable path directly on all platforms.
|
||||
cmake_args.append(f"-DSWIG_EXECUTABLE={DEPS_DIR}/install/swig-{SWIG_VERSION}/bin/swig")
|
||||
cmake_args_prefix_path.append(f"{DEPS_DIR}/install/swig-{SWIG_VERSION}")
|
||||
|
||||
if os.environ.get("QT_DIR"):
|
||||
cmake_args_prefix_path.append(os.environ["QT_DIR"])
|
||||
@@ -1652,7 +1635,7 @@ if "IfcOpenShell-Python" in targets:
|
||||
if platform.system() != "Darwin":
|
||||
if BUILD_CFG == "Release":
|
||||
for so in glob.glob(os.path.join(module_dir, "*.so")):
|
||||
if WASM:
|
||||
if "wasm" in flags:
|
||||
run(["wasm-strip", so, "-k", "dylink.0"])
|
||||
elif os.path.basename(so).startswith("_ifcopenshell_wrapper"):
|
||||
# TODO: This symbol name depends on the Python version?
|
||||
@@ -1662,7 +1645,7 @@ if "IfcOpenShell-Python" in targets:
|
||||
|
||||
return module_dir
|
||||
|
||||
if WASM:
|
||||
if "wasm" in flags:
|
||||
compile_python_wrapper(
|
||||
run(["pyodide", "config", "get", "python_version"]),
|
||||
run(["pyodide", "config", "get", "python_include_dir"]),
|
||||
|
||||
+2
-5
@@ -28,11 +28,8 @@ since it's pure cmake without any additional moving parts.
|
||||
- clone IfcOpenShell repo next to it to `IfcOpenShell` folder
|
||||
- run `python nix/build-all.py -wasm -py-313` in `IfcOpenShell`
|
||||
- it will produce Python package in `IfcOpenShell/ifcopenshell`
|
||||
- run `python pyodide/build-all-pack-wheel-local.py`, it will
|
||||
- clean up previous wheels
|
||||
- run `pyodide build`
|
||||
- prepare standalone and modular wheels
|
||||
- produce final wheels in `IfcOpenShell/dist` and `IfcOpenshell/dist-modular`
|
||||
- run `pyodide build`
|
||||
- it will produce a wheel in `IfcOpenShell/dist`
|
||||
- testing:
|
||||
- ensure you're in pyodide environment
|
||||
- `cd IfcOpenshell/pyodide`
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Intended to be run after nix/build-all.py has finished the wasm build."""
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def get_repo_root() -> Path:
|
||||
output = subprocess.check_output(["git", "rev-parse", "--show-toplevel"], text=True)
|
||||
return Path(output.strip())
|
||||
|
||||
|
||||
def run(cmd: list[str], **kwargs) -> None:
|
||||
print("$", " ".join(cmd))
|
||||
subprocess.check_call(cmd, **kwargs)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
repo_root = get_repo_root()
|
||||
|
||||
shutil.rmtree(repo_root / "dist", ignore_errors=True)
|
||||
shutil.rmtree(repo_root / "dist_modular", ignore_errors=True)
|
||||
run(["pyodide", "build"], cwd=repo_root)
|
||||
shutil.rmtree(repo_root / "ifcopenshell", ignore_errors=True)
|
||||
(repo_root / "setup.py").unlink(missing_ok=True)
|
||||
run(["git", "restore", "pyproject.toml"], cwd=repo_root)
|
||||
|
||||
wheel = next((repo_root / "dist").glob("ifcopenshell-*.whl"))
|
||||
|
||||
run(["uv", "run", "pyodide/order_pyodide_wheel_shared_objects.py", str(wheel)], cwd=repo_root)
|
||||
run(
|
||||
["uv", "run", "pyodide/split_pyodide_ifcopenshell_wheel.py", str(wheel), "dist-modular/"],
|
||||
cwd=repo_root,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,8 +1,10 @@
|
||||
#!/usr/bin/bash
|
||||
set -ex
|
||||
|
||||
PYODIDE_VERSION=0.29.4
|
||||
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
PYODIDE_VERSION=0.29.3
|
||||
PYODIDE_BUILD_VERSION=0.33.0
|
||||
PYODIDE_XBUILDENV_ROOT="${HOME}/.cache/.pyodide-xbuildenv-${PYODIDE_BUILD_VERSION}"
|
||||
PYODIDE_XBUILDENV="${PYODIDE_XBUILDENV_ROOT}/${PYODIDE_VERSION}"
|
||||
|
||||
# Script is assuming that it will be possible to execute it multiple times
|
||||
# therefore we're clearing venv each time and ignoring existing 'emsdk' folder.
|
||||
@@ -14,14 +16,12 @@ source .venv/bin/activate
|
||||
|
||||
# Install pyodide cross build environment.
|
||||
# Instructions: https://pyodide.org/en/stable/development/building-packages.html
|
||||
uv pip install -r "${SCRIPT_DIR}/requirements.txt"
|
||||
uv pip install "pyodide-build==${PYODIDE_BUILD_VERSION}"
|
||||
# `uv run` is required, so xbuildenv would skip using `pip`.
|
||||
uv run pyodide xbuildenv install "${PYODIDE_VERSION}"
|
||||
uv run pyodide xbuildenv install-emscripten
|
||||
|
||||
# Cache path includes a hash segment that varies by pyodide-build version,
|
||||
# so query it instead of constructing it manually.
|
||||
EMSDK_ROOT=$(uv run pyodide config get emsdk_dir)
|
||||
EMSDK_ROOT="${PYODIDE_XBUILDENV}/emsdk"
|
||||
[ -f "${EMSDK_ROOT}/emsdk_env.sh" ] && source "${EMSDK_ROOT}/emsdk_env.sh"
|
||||
[ -f "${EMSDK_ROOT}/../../emsdk_env.sh" ] && source "${EMSDK_ROOT}/../../emsdk_env.sh"
|
||||
which emcc
|
||||
@@ -29,10 +29,8 @@ emcc --version
|
||||
|
||||
mkdir -p packages/ifcopenshell
|
||||
VERSION=`cat IfcOpenShell/VERSION`
|
||||
# Normalize to the canonical PEP 440 form (e.g. 0.9.0alpha0 -> 0.9.0a0).
|
||||
VERSION=`python3 -c "from packaging.version import Version; print(Version('$VERSION'))"`
|
||||
cp IfcOpenShell/pyodide/meta.yaml packages/ifcopenshell
|
||||
sed -i s/9.9.9/$VERSION/g packages/ifcopenshell/meta.yaml
|
||||
sed -i s/0.8.0/$VERSION/g packages/ifcopenshell/meta.yaml
|
||||
|
||||
# Use custom build ifcopenshell directory in build-all to make caching simpler
|
||||
# Otherwise pyodide build path typically includes package version, so cached cmake configs might break.
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
package:
|
||||
name: ifcopenshell
|
||||
# Placeholder, replaced by build_pyodide.sh with the actual version from VERSION file.
|
||||
version: 9.9.9
|
||||
version: 0.8.0
|
||||
|
||||
source:
|
||||
# meta.yaml is placed as `packages/ifcopenshell/meta.yaml`.
|
||||
|
||||
@@ -34,10 +34,10 @@ SCHEMA_ORDER = {
|
||||
}
|
||||
|
||||
MAIN_SHARED_OBJECT_RE = re.compile(r"^_ifcopenshell_wrapper(?:\.|$)")
|
||||
SCHEMA_PLUGIN_RE = re.compile(r"^ifcopenshell_parse_schema_(.+)\.so$")
|
||||
MAPPING_PLUGIN_RE = re.compile(r"^ifcopenshell_geometry_mapping_(.+)\.so$")
|
||||
DOCUMENT_PLUGIN_RE = re.compile(r"^ifcopenshell_document_[a-z0-9]+(?:_(.+))?\.so$")
|
||||
GEOMETRY_SERIALIZATION_PLUGIN_RE = re.compile(r"^ifcopenshell_geometry_writer_(.+)\.so$")
|
||||
SCHEMA_PLUGIN_RE = re.compile(r"^ifcopenshell\.parse\.schema\.([^.]+)\.so$")
|
||||
MAPPING_PLUGIN_RE = re.compile(r"^ifcopenshell\.geometry\.mapping\.([^.]+)\.so$")
|
||||
DOCUMENT_PLUGIN_RE = re.compile(r"^ifcopenshell\.document\.[^.]+\.([^.]+)\.so$")
|
||||
GEOMETRY_SERIALIZATION_PLUGIN_RE = re.compile(r"^ifcopenshell\.geometry\.serialization\.([^.]+)\.so$")
|
||||
|
||||
|
||||
def schema_key(schema: str) -> tuple[int, str]:
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
pyodide-build==0.39.0
|
||||
+10
-20
@@ -63,30 +63,20 @@ select = [
|
||||
#
|
||||
"FA", # future annotations
|
||||
"UP", # pyupgrade
|
||||
"unnecessary-iterable-allocation-for-first-element",
|
||||
"unsorted-dunder-all",
|
||||
"RUF015", # next() > list_comprehension[0]
|
||||
"RUF022", # sort __all__
|
||||
"I", # import sorting
|
||||
"unused-noqa",
|
||||
"rule-codes-in-selectors",
|
||||
"noqa-comments",
|
||||
"rule-codes-in-suppression-comments",
|
||||
# General util rules.
|
||||
"invalid-rule-code",
|
||||
"redirected-noqa",
|
||||
"invalid-pyproject-toml",
|
||||
"invalid-suppression-comment",
|
||||
]
|
||||
ignore = [
|
||||
# Conflicts with Blender using annotations for props definitions.
|
||||
"future-rewritable-type-annotation",
|
||||
"FA100", # Conflicts with Blender using annotations for props definitions.
|
||||
# Maybe will enable later:
|
||||
"non-pep604-annotation-union", # Union[X,Y] to X | Y
|
||||
"non-pep604-annotation-optional", # Optional to X | None
|
||||
"redundant-open-modes", # Unnecessary mode argument
|
||||
"yield-in-for-loop", # yield for -> yield from
|
||||
"format-literals", # implicit references for positional format fields
|
||||
"printf-string-formatting", # Replace % with .format
|
||||
"f-string", # Replace .format with f-string
|
||||
"UP007", # Union[X,Y] to X | Y
|
||||
"UP045", # Optional to X | None
|
||||
"UP015", # Unnecessary mode argument
|
||||
"UP028", # yield for -> yield from
|
||||
"UP030", # implicit references for positional format fields
|
||||
"UP031", # Replace % with .format
|
||||
"UP032", # Replace .format with f-string
|
||||
]
|
||||
|
||||
[tool.ty.rules]
|
||||
|
||||
@@ -10,7 +10,7 @@ name = "bcf-client"
|
||||
# author = "IfcOpenShell"
|
||||
description = "BCF-XML file handler."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
requires-python = ">=3.8"
|
||||
keywords = ["IFC", "BCF", "BIM"]
|
||||
dependencies = [
|
||||
"xsdata>=24.4",
|
||||
@@ -65,6 +65,6 @@ commands = pytest --cov --cov-report=term tests
|
||||
|
||||
[tool.ruff]
|
||||
extend = "../../pyproject.toml"
|
||||
lint.extend-select = [
|
||||
"unused-import", # unused imports
|
||||
lint.select = [
|
||||
"F401", # unused imports
|
||||
]
|
||||
|
||||
+11
-13
@@ -42,12 +42,10 @@ endif
|
||||
|
||||
IS_STABLE:=FALSE
|
||||
VERSION:=$(shell cat ../../VERSION)
|
||||
VERSION_BASE:=$(shell sed -E 's/[[:alpha:]]+[0-9]+$$//' ../../VERSION)
|
||||
VERSION_PYTHON:=$(shell sed 's/alpha/a/' ../../VERSION)
|
||||
VERSION_SEMVER:=$(shell sed -E 's/([[:alpha:]]+)([0-9]+)$$/-\\1\\2/' ../../VERSION)
|
||||
VERSION_MAJOR:=$(shell cat '../../VERSION' | cut -d '.' -f 1)
|
||||
VERSION_MINOR:=$(shell cat '../../VERSION' | cut -d '.' -f 2)
|
||||
VERSION_PATCH:=$(shell cat '../../VERSION' | cut -d '.' -f 3)
|
||||
VERSION_DATE:=$(shell date '+%y%m%d')
|
||||
VERSION_DAILY:=$(VERSION_BASE)a$(VERSION_DATE)
|
||||
VERSION_SEMVER_DAILY:=$(VERSION_BASE)-alpha$(VERSION_DATE)
|
||||
LAST_COMMIT_HASH:=$(shell git rev-parse HEAD)
|
||||
LAST_COMMIT_DATE:=$(shell git show -s --format=%cI)
|
||||
LAST_GIT_BRANCH:=$(shell git rev-parse --abbrev-ref HEAD)
|
||||
@@ -262,14 +260,14 @@ endif
|
||||
|
||||
cp pyproject.toml build/
|
||||
ifeq ($(IS_STABLE), TRUE)
|
||||
$(SED) "s/0.0.0/$(VERSION_SEMVER)/" build/bonsai/blender_manifest.toml
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION_PYTHON)"/' build/pyproject.toml
|
||||
$(SED) "s/0.0.0/$(VERSION)/" build/bonsai/blender_manifest.toml
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION)"/' build/pyproject.toml
|
||||
else
|
||||
$(SED) "s/0.0.0/$(VERSION_SEMVER_DAILY)/" build/bonsai/blender_manifest.toml
|
||||
$(SED) "s/0.0.0/$(VERSION)-alpha$(VERSION_DATE)/" build/bonsai/blender_manifest.toml
|
||||
$(SED) "s/8888888/$(LAST_COMMIT_HASH)/" build/bonsai/__init__.py
|
||||
$(SED) "s/9999999/$(LAST_COMMIT_DATE)/" build/bonsai/__init__.py
|
||||
$(SED) "s/7777777/$(LAST_GIT_BRANCH)/" build/bonsai/__init__.py
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION_DAILY)"/' build/pyproject.toml
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION)-alpha$(VERSION_DATE)"/' build/pyproject.toml
|
||||
endif
|
||||
|
||||
# Blender 5.1+ requires Python 3.13.
|
||||
@@ -281,9 +279,9 @@ endif
|
||||
|
||||
# Provides bonsai Add-on functionality
|
||||
ifeq ($(IS_STABLE), TRUE)
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION_PYTHON)"/' build/pyproject.toml
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION)"/' build/pyproject.toml
|
||||
else
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION_DAILY)"/' build/pyproject.toml
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION)a$(VERSION_DATE)"/' build/pyproject.toml
|
||||
endif
|
||||
cd build && . env/$(VENV_ACTIVATE) && $(PYTHON) -m build
|
||||
cp build/dist/*.whl build/wheels/
|
||||
@@ -317,9 +315,9 @@ endif
|
||||
rm -rf build/bonsai/libs/
|
||||
|
||||
ifeq ($(IS_STABLE), TRUE)
|
||||
cd build && zip -r bonsai_$(PYVERSION)-$(VERSION_SEMVER)-$(BLENDER_PLATFORM).zip ./bonsai
|
||||
cd build && zip -r bonsai_$(PYVERSION)-$(VERSION)-$(BLENDER_PLATFORM).zip ./bonsai
|
||||
else
|
||||
cd build && zip -r bonsai_$(PYVERSION)-$(VERSION_SEMVER_DAILY)-$(BLENDER_PLATFORM).zip ./bonsai
|
||||
cd build && zip -r bonsai_$(PYVERSION)-$(VERSION)-alpha$(VERSION_DATE)-$(BLENDER_PLATFORM).zip ./bonsai
|
||||
endif
|
||||
|
||||
mv build/bonsai*.zip dist/
|
||||
|
||||
@@ -185,10 +185,13 @@ class IfcStore:
|
||||
os.makedirs(os.path.dirname(cache_path), exist_ok=True)
|
||||
IfcStore.cache_path = cache_path
|
||||
cache_path = Path(IfcStore.cache_path)
|
||||
settings = ifcopenshell.geom.settings()
|
||||
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, settings)
|
||||
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:
|
||||
@@ -203,7 +206,9 @@ class IfcStore:
|
||||
|
||||
os.remove(IfcStore.cache_path)
|
||||
try:
|
||||
IfcStore.cache = ifcopenshell.geom.serializers.hdf5(IfcStore.cache_path, settings)
|
||||
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)}.")
|
||||
|
||||
@@ -740,7 +740,7 @@ class IfcImporter:
|
||||
self.update_progress((percent_average / 100 * progress_range) + start_progress)
|
||||
shape = iterator.get()
|
||||
if shape:
|
||||
assert isinstance(shape, W.triangulation_element)
|
||||
assert isinstance(shape, W.TriangulationElement)
|
||||
product = self.file.by_id(shape.id)
|
||||
self.create_product(product, shape)
|
||||
results.add(product)
|
||||
@@ -1079,9 +1079,9 @@ class IfcImporter:
|
||||
def create_curve(
|
||||
self,
|
||||
element: ifcopenshell.entity_instance,
|
||||
shape: Union[W.triangulation, W.triangulation_element],
|
||||
shape: Union[W.Triangulation, W.TriangulationElement],
|
||||
) -> bpy.types.Curve:
|
||||
if isinstance(shape, W.triangulation_element):
|
||||
if isinstance(shape, W.TriangulationElement):
|
||||
geometry = shape.geometry
|
||||
else:
|
||||
geometry = shape
|
||||
@@ -1112,11 +1112,11 @@ class IfcImporter:
|
||||
def create_mesh(
|
||||
self,
|
||||
element: ifcopenshell.entity_instance,
|
||||
shape: Union[W.triangulation, W.triangulation_element],
|
||||
shape: Union[W.Triangulation, W.TriangulationElement],
|
||||
cartesian_point_offset: Union[npt.NDArray[np.float64], Literal[False]] = None,
|
||||
) -> Union[bpy.types.Mesh, None]:
|
||||
try:
|
||||
if isinstance(shape, W.triangulation_element):
|
||||
if isinstance(shape, W.TriangulationElement):
|
||||
# shape is ShapeElementType
|
||||
geometry = shape.geometry
|
||||
else:
|
||||
|
||||
@@ -678,7 +678,7 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
# Identify all potential building elements
|
||||
# TODO: don't select everything, use AABB culling in Blender
|
||||
building_elements = list(
|
||||
building_elements = (
|
||||
tool.Ifc.get().by_type("IfcWall")
|
||||
+ tool.Ifc.get().by_type("IfcSlab")
|
||||
+ tool.Ifc.get().by_type("IfcVirtualElement")
|
||||
@@ -708,7 +708,7 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
while True:
|
||||
tree.add_element(iterator.get_native())
|
||||
shape = iterator.get()
|
||||
assert isinstance(shape, W.triangulation_element)
|
||||
assert isinstance(shape, W.TriangulationElement)
|
||||
shapes[shape.id] = {
|
||||
"verts": ifcopenshell.util.shape.get_vertices(shape.geometry),
|
||||
"faces": ifcopenshell.util.shape.get_faces(shape.geometry),
|
||||
|
||||
@@ -348,7 +348,10 @@ class AddClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def _execute(self, context):
|
||||
if self.obj_type == "Object":
|
||||
objects = [o.name for o in tool.Blender.get_selected_objects()]
|
||||
if context.selected_objects:
|
||||
objects = [o.name for o in context.selected_objects]
|
||||
else:
|
||||
objects = [context.active_object.name]
|
||||
else:
|
||||
objects = [self.obj]
|
||||
props = tool.Classification.get_classification_props()
|
||||
|
||||
@@ -516,7 +516,7 @@ def _world_segment_to_screen_pixels(
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class BIM_GT_box_face_quad(bpy.types.Gizmo):
|
||||
class BIM_GT_box_face_quad(bpy.types.Gizmo): # noqa: N801 — Blender bl_idname convention
|
||||
"""Near-invisible face-quad click target with drag-to-resize modal.
|
||||
|
||||
Geometry: a unit quad in the local XY plane at z=0. The adapter
|
||||
@@ -620,7 +620,7 @@ class BIM_GT_box_face_quad(bpy.types.Gizmo):
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
|
||||
class BIM_GT_box_face_outline(bpy.types.Gizmo):
|
||||
class BIM_GT_box_face_outline(bpy.types.Gizmo): # noqa: N801 — Blender bl_idname convention
|
||||
"""Thin non-interactive colored edge outline for one face.
|
||||
|
||||
Drawn as 4 line segments in the face plane. The layout helper
|
||||
|
||||
@@ -160,7 +160,7 @@ def _make_face_set_cb(gz: Any, group: Any, axis: int, is_max: bool):
|
||||
return setter
|
||||
|
||||
|
||||
class OBJECT_GGT_bim_clip_box(bpy.types.GizmoGroup):
|
||||
class OBJECT_GGT_bim_clip_box(bpy.types.GizmoGroup): # noqa: N801 — Blender bl_idname convention
|
||||
"""Face-quad resize handles on the active clip box.
|
||||
|
||||
Renders six near-invisible click-target quads and six colored edge
|
||||
|
||||
@@ -987,7 +987,7 @@ class ExportCostSchedulesToPDF(bpy.types.Operator, ExportHelper):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
try:
|
||||
import typst # ruff: ignore[unused-import]
|
||||
import typst # noqa: F401
|
||||
|
||||
return True
|
||||
except ModuleNotFoundError:
|
||||
|
||||
@@ -313,7 +313,7 @@ class CreateAllShapes(bpy.types.Operator):
|
||||
failures.append(element)
|
||||
print("***** FAILURE *****")
|
||||
if shape:
|
||||
assert isinstance(shape, W.triangulation_element)
|
||||
assert isinstance(shape, W.TriangulationElement)
|
||||
geom = shape.geometry
|
||||
print(
|
||||
f"Success {time.time() - start:.3f}s "
|
||||
|
||||
@@ -28,7 +28,7 @@ operators via ``target_set_operator``; drag handles inherit modal state
|
||||
from ``GizmoMovable``.
|
||||
"""
|
||||
|
||||
__all__ = [ # ruff: ignore[unsorted-dunder-all]
|
||||
__all__ = [ # noqa: RUF022 (unsorted `__all__`)
|
||||
"GizmoColor",
|
||||
"GizmoAxis",
|
||||
"TextAlignment",
|
||||
@@ -5660,7 +5660,7 @@ class BaseParametricGizmoGroup:
|
||||
"""
|
||||
return 0.0
|
||||
|
||||
def _update_view_dependent_dimensions(self, context: bpy.types.Context, mw: Matrix, props) -> None:
|
||||
def _update_view_dependent_dimensions(self, context: bpy.types.Context, mw: Matrix, props) -> None: # noqa: ARG002
|
||||
"""Update overall_width, overall_height, and lining_offset based on view direction.
|
||||
|
||||
This base implementation handles the common pattern for door/window gizmos.
|
||||
@@ -5837,7 +5837,7 @@ class BaseParametricGizmoGroup:
|
||||
self.update_dimension_gizmos(mw, props)
|
||||
self._refresh_element_specific(context, mw, props)
|
||||
|
||||
def _refresh_element_specific(self, context: bpy.types.Context, mw: "Matrix", props) -> None:
|
||||
def _refresh_element_specific(self, context: bpy.types.Context, mw: "Matrix", props) -> None: # noqa: ARG002
|
||||
"""Override for element-specific refresh logic.
|
||||
|
||||
Called from both refresh() (on state change) and draw_prepare() (per frame),
|
||||
@@ -6344,7 +6344,7 @@ class BaseParametricGizmoGroup:
|
||||
"""
|
||||
return (0.0, 0.0)
|
||||
|
||||
def get_icon_y_offset(self, context: bpy.types.Context, mw: Matrix) -> float:
|
||||
def get_icon_y_offset(self, context: bpy.types.Context, mw: Matrix) -> float: # noqa: ARG002
|
||||
"""Get Y offset for icons based on view direction.
|
||||
|
||||
Uses get_icon_y_extent() to determine how far to offset icons based on
|
||||
@@ -6546,7 +6546,9 @@ class BaseParametricGizmoGroup:
|
||||
|
||||
self._refresh_element_specific(context, mw, props)
|
||||
|
||||
def _update_dimension_gizmo_positions(self, context: bpy.types.Context, mw: "Matrix", props) -> None:
|
||||
def _update_dimension_gizmo_positions(
|
||||
self, context: bpy.types.Context, mw: "Matrix", props # noqa: ARG002
|
||||
) -> None:
|
||||
"""Update dimension gizmo positions based on view direction.
|
||||
|
||||
Override this method in subclasses to implement view-dependent
|
||||
|
||||
@@ -1406,28 +1406,31 @@ class CreateDrawing(bpy.types.Operator):
|
||||
# Backwards compatibility with older ifcopenshell builds that don't expose these keys.
|
||||
pass
|
||||
self.svg_buffer = ifcopenshell.geom.serializers.buffer()
|
||||
self.svg_settings.set("svg-without-storeys", True)
|
||||
self.svg_settings.set("svg-write-poly", True)
|
||||
self.svg_settings.set("svg-poly", True)
|
||||
self.serialiser_settings = ifcopenshell.geom.serializer_settings()
|
||||
self.serialiser_settings.set("svg-without-storeys", True)
|
||||
self.serialiser_settings.set("svg-write-poly", True)
|
||||
self.serialiser_settings.set("svg-poly", True)
|
||||
# Objects with more than these edges are rendered as wireframe instead of HLR for optimisation
|
||||
self.svg_settings.set("profile-threshold", 10000)
|
||||
self.svg_settings.set("svg-xmlns", True)
|
||||
self.svg_settings.set("svg-project", True)
|
||||
self.svg_settings.set("auto-elevation", False)
|
||||
self.svg_settings.set("auto-section", False)
|
||||
self.svg_settings.set("print-space-names", False)
|
||||
self.svg_settings.set("print-space-areas", False)
|
||||
self.svg_settings.set("door-arcs", False)
|
||||
self.svg_settings.set("svg-no-css", True)
|
||||
self.svg_settings.set("elevation-ref-guid", self.camera_element.GlobalId)
|
||||
self.svg_settings.set("scale", str(self.scale))
|
||||
self.svg_settings.set("svg-subtract-before", "always")
|
||||
self.svg_settings.set("svg-prefilter", True) # See #3359
|
||||
self.svg_settings.set("svg-unify-inputs", True)
|
||||
self.svg_settings.set("svg-segment-projection", True)
|
||||
self.serialiser_settings.set("profile-threshold", 10000)
|
||||
self.serialiser_settings.set("svg-xmlns", True)
|
||||
self.serialiser_settings.set("svg-project", True)
|
||||
self.serialiser_settings.set("auto-elevation", False)
|
||||
self.serialiser_settings.set("auto-section", False)
|
||||
self.serialiser_settings.set("print-space-names", False)
|
||||
self.serialiser_settings.set("print-space-areas", False)
|
||||
self.serialiser_settings.set("door-arcs", False)
|
||||
self.serialiser_settings.set("svg-no-css", True)
|
||||
self.serialiser_settings.set("elevation-ref-guid", self.camera_element.GlobalId)
|
||||
self.serialiser_settings.set("scale", str(self.scale))
|
||||
self.serialiser_settings.set("svg-subtract-before", "always")
|
||||
self.serialiser_settings.set("svg-prefilter", True) # See #3359
|
||||
self.serialiser_settings.set("svg-unify-inputs", True)
|
||||
self.serialiser_settings.set("svg-segment-projection", True)
|
||||
if target_view == "REFLECTED_PLAN_VIEW":
|
||||
self.svg_settings.set("svg-mirror-y", True)
|
||||
self.serialiser = ifcopenshell.geom.serializers.svg(self.svg_buffer, self.svg_settings)
|
||||
self.serialiser_settings.set("svg-mirror-y", True)
|
||||
self.serialiser = ifcopenshell.geom.serializers.svg(
|
||||
self.svg_buffer, self.svg_settings, self.serialiser_settings
|
||||
)
|
||||
# tree = ifcopenshell.geom.tree()
|
||||
# This instructs the tree to explode BReps into faces and return
|
||||
# the style of the face when running tree.select_ray()
|
||||
|
||||
@@ -72,10 +72,11 @@ class ExportOBJ(bpy.types.Operator):
|
||||
# Conversion from IFC to OBJ
|
||||
# Settings for obj
|
||||
settings = ifcopenshell.geom.settings()
|
||||
serializer_settings = ifcopenshell.geom.serializer_settings()
|
||||
|
||||
settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.SURFACES_AND_SOLIDS)
|
||||
settings.set("apply-default-materials", True)
|
||||
settings.set("use-element-guids", True)
|
||||
serializer_settings.set("use-element-guids", True)
|
||||
settings.set("use-world-coords", True)
|
||||
|
||||
ifc_file: ifcopenshell.file
|
||||
@@ -89,7 +90,7 @@ class ExportOBJ(bpy.types.Operator):
|
||||
obj_file_path = os.path.join(output_dir, "model.obj")
|
||||
mtl_file_path = os.path.join(output_dir, "model.mtl")
|
||||
|
||||
serialiser = ifcopenshell.geom.serializers.obj(obj_file_path, mtl_file_path, settings)
|
||||
serialiser = ifcopenshell.geom.serializers.obj(obj_file_path, mtl_file_path, settings, serializer_settings)
|
||||
serialiser.setFile(ifc_file)
|
||||
serialiser.setUnitNameAndMagnitude("METER", 1.0)
|
||||
serialiser.writeHeader()
|
||||
@@ -106,7 +107,7 @@ class ExportOBJ(bpy.types.Operator):
|
||||
if iterator.initialize():
|
||||
while True:
|
||||
shape = iterator.get()
|
||||
assert isinstance(shape, W.triangulation_element)
|
||||
assert isinstance(shape, W.TriangulationElement)
|
||||
materials = shape.geometry.materials
|
||||
|
||||
for material in materials:
|
||||
|
||||
@@ -430,7 +430,7 @@ class SverchokData:
|
||||
@classmethod
|
||||
def has_sverchok(cls) -> bool:
|
||||
try:
|
||||
import sverchok # ruff: ignore[unused-import]
|
||||
import sverchok # noqa: F401
|
||||
|
||||
return True
|
||||
except ModuleNotFoundError:
|
||||
|
||||
@@ -560,7 +560,7 @@ class AddDoor(bpy.types.Operator, tool.Ifc.Operator):
|
||||
)
|
||||
update_door_modifier_representation(obj)
|
||||
|
||||
def _execute(self, context: bpy.types.Context) -> set[str]:
|
||||
def _execute(self, context: bpy.types.Context) -> set[str]: # noqa: ARG002
|
||||
for obj in tool.Blender.get_selected_objects():
|
||||
if not tool.Blender.Modifier.is_eligible_for_door_modifier(obj):
|
||||
continue
|
||||
@@ -638,7 +638,7 @@ class RemoveDoor(bpy.types.Operator, tool.Ifc.Operator):
|
||||
pset = tool.Pset.get_element_pset(element, "BBIM_Door")
|
||||
ifcopenshell.api.pset.remove_pset(tool.Ifc.get(), product=element, pset=pset)
|
||||
|
||||
def _execute(self, context: bpy.types.Context) -> set[str]:
|
||||
def _execute(self, context: bpy.types.Context) -> set[str]: # noqa: ARG002
|
||||
for obj in tool.Blender.get_selected_objects():
|
||||
self.remove_door_on_object(obj)
|
||||
return {"FINISHED"}
|
||||
@@ -683,7 +683,7 @@ class ToggleDoorSwing(bpy.types.Operator, tool.Ifc.Operator):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _execute(self, context: bpy.types.Context) -> set[str]:
|
||||
def _execute(self, context: bpy.types.Context) -> set[str]: # noqa: ARG002
|
||||
obj = tool.Blender.get_active_object()
|
||||
if not obj:
|
||||
return {"CANCELLED"}
|
||||
@@ -909,7 +909,9 @@ class GizmoDoorEdition(bpy.types.GizmoGroup, gizmo.BaseParametricGizmoGroup):
|
||||
setattr(self, f"gizmo_swing_arc_{cfg.name}", main)
|
||||
setattr(self, f"gizmo_swing_arc_{cfg.name}_flip", flip)
|
||||
|
||||
def _refresh_element_specific(self, context: bpy.types.Context, mw: Matrix, props: "BIMDoorProperties") -> None:
|
||||
def _refresh_element_specific(
|
||||
self, context: bpy.types.Context, mw: Matrix, props: "BIMDoorProperties" # noqa: ARG002
|
||||
) -> None:
|
||||
"""Update door-specific swing arc gizmos."""
|
||||
self.update_swing_gizmos(mw, props)
|
||||
|
||||
|
||||
@@ -765,7 +765,7 @@ class GizmoRoofEdition(bpy.types.GizmoGroup, gizmo.BaseParametricGizmoGroup):
|
||||
def is_element_type(cls, element: ifcopenshell.entity_instance) -> bool:
|
||||
return tool.Parametric.is_roof(element)
|
||||
|
||||
def _update_dimension_gizmo_positions(self, context: bpy.types.Context, mw, props) -> None:
|
||||
def _update_dimension_gizmo_positions(self, context: bpy.types.Context, mw, props) -> None: # noqa: ARG002
|
||||
"""Anchor every dimension gizmo at the object origin. Each gizmo's
|
||||
declared axis (height/slope along +Z, thickness along -Z) separates
|
||||
them in 3D so they don't visually collide despite sharing a
|
||||
@@ -776,7 +776,7 @@ class GizmoRoofEdition(bpy.types.GizmoGroup, gizmo.BaseParametricGizmoGroup):
|
||||
self.set_dimension_gizmo_position("angle", mw, origin, (0, 0, 1))
|
||||
self.set_dimension_gizmo_position("roof_thickness", mw, origin, (0, 0, -1))
|
||||
|
||||
def get_element_height(self, props) -> float:
|
||||
def get_element_height(self, props) -> float: # noqa: ARG002
|
||||
"""Object-local Z of the mesh's topmost vertex, so the pen / validate /
|
||||
cancel / cycle row anchors visibly above sloped or stepped roof
|
||||
bodies rather than at the parametric ``props.height`` which may not
|
||||
|
||||
@@ -405,7 +405,7 @@ class SetStairTreads(bpy.types.Operator):
|
||||
bl_label = "Set Number of Treads"
|
||||
bl_options = {"REGISTER", "UNDO", "INTERNAL"}
|
||||
|
||||
def invoke(self, context: bpy.types.Context, event: bpy.types.Event) -> set[str]:
|
||||
def invoke(self, context: bpy.types.Context, event: bpy.types.Event) -> set[str]: # noqa: ARG002
|
||||
obj = context.active_object
|
||||
if not obj:
|
||||
return {"CANCELLED"}
|
||||
@@ -658,7 +658,9 @@ class GizmoStairEdition(bpy.types.GizmoGroup, gizmo.BaseParametricGizmoGroup):
|
||||
self.tread_count_label_gizmo.alpha = 0.8
|
||||
self.tread_count_label_gizmo.target_set_operator("bim.input_stair_treads")
|
||||
|
||||
def _refresh_element_specific(self, context: bpy.types.Context, mw: Matrix, props: "BIMStairProperties") -> None:
|
||||
def _refresh_element_specific(
|
||||
self, context: bpy.types.Context, mw: Matrix, props: "BIMStairProperties" # noqa: ARG002
|
||||
) -> None:
|
||||
"""Update stair-specific lock and tread count gizmos. Lock positioning is
|
||||
handled per-frame in the dimension-positioning hook."""
|
||||
self.update_lock_gizmo(props)
|
||||
@@ -705,7 +707,7 @@ class GizmoStairEdition(bpy.types.GizmoGroup, gizmo.BaseParametricGizmoGroup):
|
||||
self.update_gizmo_visibility(self.tread_count_label_gizmo, props.is_editing)
|
||||
|
||||
def _update_dimension_gizmo_positions(
|
||||
self, context: bpy.types.Context, mw: Matrix, props: "BIMStairProperties"
|
||||
self, context: bpy.types.Context, mw: Matrix, props: "BIMStairProperties" # noqa: ARG002
|
||||
) -> None:
|
||||
"""Update dimension gizmo positions based on camera view direction."""
|
||||
viewing_from_negative_y, viewing_from_negative_x = self._frame_view_dir
|
||||
|
||||
@@ -2174,7 +2174,7 @@ class GizmoWallEdition(bpy.types.GizmoGroup, gizmo.BaseParametricGizmoGroup):
|
||||
return (far, near)
|
||||
|
||||
def _update_dimension_gizmo_positions(
|
||||
self, context: bpy.types.Context, mw: Matrix, props: "BIMWallProperties"
|
||||
self, context: bpy.types.Context, mw: Matrix, props: "BIMWallProperties" # noqa: ARG002
|
||||
) -> None:
|
||||
"""Re-position length / height / height_end dimensions to the camera-facing
|
||||
Y-side of the wall every frame. Mirrors the door & stair pattern: when the
|
||||
@@ -2530,7 +2530,7 @@ def _perpendicular_wall_params(
|
||||
return clamped_x, abs(cursor_local_y), side_sign
|
||||
|
||||
|
||||
def _commit_pending_wall_edits_for_selection(context: bpy.types.Context) -> None:
|
||||
def _commit_pending_wall_edits_for_selection(context: bpy.types.Context) -> None: # noqa: ARG001
|
||||
"""Thin wall-scoped alias for ``tool.Parametric.commit_pending_edits_for_selection``.
|
||||
|
||||
Encapsulates the ``names=("wall",)`` filter so the registry name is
|
||||
|
||||
@@ -538,7 +538,7 @@ class RemoveWindow(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_label = "Remove Window"
|
||||
bl_options = {"REGISTER"}
|
||||
|
||||
def _execute(self, context: bpy.types.Context) -> set[str]:
|
||||
def _execute(self, context: bpy.types.Context) -> set[str]: # noqa: ARG002
|
||||
obj = context.active_object
|
||||
assert obj
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
|
||||
@@ -2442,7 +2442,7 @@ class LoadLinkedProject(bpy.types.Operator, ImportHelper):
|
||||
if iterator.initialize():
|
||||
while True: # Main loop.
|
||||
shape = iterator.get()
|
||||
assert isinstance(shape, W.triangulation_element)
|
||||
assert isinstance(shape, W.TriangulationElement)
|
||||
results.add(self.file.by_id(shape.id))
|
||||
geometry = shape.geometry
|
||||
|
||||
@@ -2518,7 +2518,7 @@ class LoadLinkedProject(bpy.types.Operator, ImportHelper):
|
||||
print("Finished", time.time() - start)
|
||||
return {"FINISHED"}
|
||||
|
||||
def process_occurrence(self, shape: W.triangulation_element) -> None:
|
||||
def process_occurrence(self, shape: W.TriangulationElement) -> None:
|
||||
element = self.file.by_id(shape.id)
|
||||
|
||||
mat = ifcopenshell.util.shape.get_shape_matrix(shape)
|
||||
|
||||
@@ -558,7 +558,7 @@ class IntegerInputDialogMixin:
|
||||
return None
|
||||
return props
|
||||
|
||||
def invoke(self, context: bpy.types.Context, event: bpy.types.Event) -> set[str]:
|
||||
def invoke(self, context: bpy.types.Context, event: bpy.types.Event) -> set[str]: # noqa: ARG002
|
||||
props = self._resolve_props(context)
|
||||
if props is None:
|
||||
return {"CANCELLED"}
|
||||
|
||||
@@ -142,35 +142,8 @@ def assign_material(
|
||||
else:
|
||||
element_material_type = material_type
|
||||
|
||||
# TODO: this whole dance is a stopgap and wants rewriting.
|
||||
#
|
||||
# material.assign_material creates material sets with no items in them,
|
||||
# ignoring the material it was handed -- an IfcMaterialLayerSet with no
|
||||
# MaterialLayers is not valid IFC, since the list is mandatory and
|
||||
# [1:?]. So we repair it below, after the fact. Worse, the API rejects a
|
||||
# plain IfcMaterial outright when asked for a usage, which is exactly
|
||||
# what the Object Materials dropdown gives us, so we cannot even pass it
|
||||
# on and have to let the API invent an empty set and then fill it in.
|
||||
#
|
||||
# The fix is for assign_material to build the set around the material it
|
||||
# is given, rather than leaving an invalid one behind for its callers to
|
||||
# patch up. That is a wider change than it looks: add_material_set has
|
||||
# the same behaviour, and the create-empty-then-add-items idiom is
|
||||
# spread through the API's own docstrings, examples and tests. Until
|
||||
# that is untangled, keep the repair here where it is at least visible.
|
||||
|
||||
# Only a usage refuses a plain IfcMaterial; every other type still wants
|
||||
# it, and IfcMaterial and IfcMaterialList cannot be created without it.
|
||||
pass_material = material_tool.is_a_material_set(material) or not element_material_type.endswith("Usage")
|
||||
ifc.run(
|
||||
"material.assign_material",
|
||||
products=[element],
|
||||
type=element_material_type,
|
||||
material=material if pass_material else None,
|
||||
)
|
||||
# A usage points at the set rather than being one, and it is the set
|
||||
# that needs an item adding to it below.
|
||||
assigned_material = material_tool.get_material(element, should_skip_usage=True)
|
||||
ifc.run("material.assign_material", products=[element], type=element_material_type, material=material)
|
||||
assigned_material = material_tool.get_material(element)
|
||||
assert assigned_material # Type checker.
|
||||
|
||||
if material_tool.is_a_material_set(material):
|
||||
|
||||
@@ -651,7 +651,7 @@ class Material:
|
||||
def get_default_material(cls): pass
|
||||
def get_elements_by_material(cls, material): pass
|
||||
def get_material_attributes(cls): pass
|
||||
def get_material(cls, element, should_inherit: bool = False, should_skip_usage: bool = False): pass
|
||||
def get_material(cls, element, should_inherit: bool = False): pass
|
||||
def get_object_ui_active_material(cls): pass
|
||||
def get_object_ui_material_type(cls): pass
|
||||
def get_style(cls, material): pass
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Ignore unused imports.
|
||||
# ruff: file-ignore[unused-import]
|
||||
# ruff: noqa: F401
|
||||
|
||||
from bonsai.tool.aggregate import Aggregate
|
||||
from bonsai.tool.array import Array
|
||||
|
||||
@@ -25,7 +25,6 @@ import importlib
|
||||
import math
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
@@ -1757,7 +1756,6 @@ class Blender(bonsai.core.tool.Blender):
|
||||
repo_path = repo.working_tree_dir
|
||||
assert repo_path
|
||||
version_ = (Path(repo_path) / "VERSION").read_text().strip()
|
||||
version_ = re.sub(r"[A-Za-z]+\d+$", "", version_)
|
||||
commit_date = bonsai.get_last_commit_date()
|
||||
assert commit_date
|
||||
commit_date = datetime.fromisoformat(commit_date)
|
||||
|
||||
@@ -1187,7 +1187,7 @@ class Geometry(bonsai.core.tool.Geometry):
|
||||
if iterator and iterator.initialize():
|
||||
while True:
|
||||
shape = iterator.get()
|
||||
assert isinstance(shape, W.triangulation_element)
|
||||
assert isinstance(shape, W.TriangulationElement)
|
||||
element = tool.Ifc.get().by_id(shape.id)
|
||||
if obj := tool.Ifc.get_object(element):
|
||||
# It's possible that there will be multiple shapes for the same context,
|
||||
@@ -2179,7 +2179,7 @@ class Geometry(bonsai.core.tool.Geometry):
|
||||
item = tool.Ifc.get().by_id(props.ifc_definition_id)
|
||||
allowed_attributes = [
|
||||
a.name()
|
||||
for a in item.declaration.as_entity().all_attributes()
|
||||
for a in item.declaration().as_entity.all_attributes()
|
||||
if a.type_of_attribute()._is("IfcLengthMeasure")
|
||||
]
|
||||
|
||||
|
||||
@@ -872,7 +872,7 @@ class Loader(bonsai.core.tool.Loader):
|
||||
cls,
|
||||
element: ifcopenshell.entity_instance,
|
||||
representation: ifcopenshell.entity_instance,
|
||||
shape: W.triangulation_element,
|
||||
shape: W.TriangulationElement,
|
||||
) -> bpy.types.Camera:
|
||||
"""Create camera data.
|
||||
|
||||
@@ -1026,7 +1026,7 @@ class Loader(bonsai.core.tool.Loader):
|
||||
@classmethod
|
||||
def convert_geometry_to_mesh(
|
||||
cls,
|
||||
geometry: W.triangulation,
|
||||
geometry: W.Triangulation,
|
||||
mesh: bpy.types.Mesh,
|
||||
verts: Optional[npt.NDArray[np.float64]] = None,
|
||||
*,
|
||||
|
||||
@@ -220,14 +220,9 @@ class Material(bonsai.core.tool.Material):
|
||||
|
||||
@classmethod
|
||||
def get_material(
|
||||
cls,
|
||||
element: ifcopenshell.entity_instance,
|
||||
should_inherit: bool = False,
|
||||
should_skip_usage: bool = False,
|
||||
cls, element: ifcopenshell.entity_instance, should_inherit: bool = False
|
||||
) -> Union[ifcopenshell.entity_instance, None]:
|
||||
return ifcopenshell.util.element.get_material(
|
||||
element, should_inherit=should_inherit, should_skip_usage=should_skip_usage
|
||||
)
|
||||
return ifcopenshell.util.element.get_material(element, should_inherit=should_inherit)
|
||||
|
||||
@classmethod
|
||||
def is_a_material_set(cls, material: ifcopenshell.entity_instance) -> bool:
|
||||
|
||||
@@ -2459,7 +2459,7 @@ class Model(bonsai.core.tool.Model):
|
||||
polygons = {}
|
||||
for curve in curves:
|
||||
geometry = ifcopenshell.geom.create_shape(settings, curve)
|
||||
assert isinstance(geometry, W.triangulation)
|
||||
assert isinstance(geometry, W.Triangulation)
|
||||
v = ifcopenshell.util.shape.get_vertices(geometry, is_2d=True)
|
||||
v = np.round(v, 4) # Round to nearest 0.1mm, otherwise things like circles don't polygonise reliably
|
||||
edges = ifcopenshell.util.shape.get_edges(geometry)
|
||||
|
||||
@@ -53,7 +53,7 @@ class Profile(bonsai.core.tool.Profile):
|
||||
settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.CURVES_SURFACES_AND_SOLIDS)
|
||||
shape = ifcopenshell.geom.create_shape(settings, profile)
|
||||
|
||||
assert isinstance(shape, W.triangulation)
|
||||
assert isinstance(shape, W.Triangulation)
|
||||
verts = ifcopenshell.util.shape.get_vertices(shape)
|
||||
if verts.size == 0:
|
||||
raise RuntimeError(f"Profile shape has no vertices, it probably is invalid: '{profile}'.")
|
||||
|
||||
@@ -76,10 +76,6 @@ Release
|
||||
Notes:
|
||||
|
||||
- Typically all packages are released at once using the same version schema
|
||||
- ``VERSION`` uses Python/PEP 440-compatible spelling. For example, an alpha
|
||||
release may be ``0.9.0alpha0`` (canonicalized to ``0.9.0a0``); build scripts
|
||||
derive numeric-only and SemVer forms such as ``0.9.0`` and
|
||||
``0.9.0-alpha0`` where required.
|
||||
- The ``README.md`` badges can serve as a visual reference for what versions have been released
|
||||
- Corrective Release (if needed after a standard release):
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ exclude = ["test*"]
|
||||
[tool.ruff]
|
||||
extend = "../../pyproject.toml"
|
||||
lint.extend-select = [
|
||||
"unused-import", # unused imports
|
||||
"F401", # unused imports
|
||||
]
|
||||
|
||||
[tool.ruff.lint.isort]
|
||||
|
||||
@@ -42,7 +42,6 @@ markers =
|
||||
type
|
||||
unit
|
||||
void
|
||||
wall
|
||||
web
|
||||
|
||||
# Provide plugins explicitly, so it will be possible run tests with PYTEST_DISABLE_PLUGIN_AUTOLOAD.
|
||||
|
||||
@@ -45,10 +45,10 @@ for dep in dependencies:
|
||||
subprocess.check_call(command + [dep])
|
||||
|
||||
try:
|
||||
import pygments # ruff: ignore[unused-import]
|
||||
import pytest # ruff: ignore[unused-import]
|
||||
import pytest_bdd # ruff: ignore[unused-import]
|
||||
import pytest_blender # ruff: ignore[unused-import]
|
||||
import pygments # noqa: F401
|
||||
import pytest # noqa: F401
|
||||
import pytest_bdd # noqa: F401
|
||||
import pytest_blender # noqa: F401
|
||||
|
||||
print("Test dependency installation was successful!")
|
||||
except Exception as e:
|
||||
|
||||
@@ -163,29 +163,32 @@ class Drawer:
|
||||
|
||||
# self.svg_settings.set_deflection_tolerance(0.0001)
|
||||
self.svg_buffer = ifcopenshell.geom.serializers.buffer()
|
||||
self.svg_settings.set("svg-without-storeys", True)
|
||||
self.svg_settings.set("svg-write-poly", True)
|
||||
self.svg_settings.set("svg-poly", True)
|
||||
self.serialiser_settings = ifcopenshell.geom.serializer_settings()
|
||||
self.serialiser_settings.set("svg-without-storeys", True)
|
||||
self.serialiser_settings.set("svg-write-poly", True)
|
||||
self.serialiser_settings.set("svg-poly", True)
|
||||
# Objects with more than these edges are rendered as wireframe instead of HLR for optimisation
|
||||
self.svg_settings.set("profile-threshold", 10000)
|
||||
self.svg_settings.set("svg-xmlns", True)
|
||||
self.svg_settings.set("svg-project", True)
|
||||
self.svg_settings.set("auto-elevation", False)
|
||||
self.svg_settings.set("auto-section", False)
|
||||
self.svg_settings.set("print-space-names", False)
|
||||
self.svg_settings.set("print-space-areas", False)
|
||||
self.svg_settings.set("door-arcs", False)
|
||||
self.svg_settings.set("svg-no-css", True)
|
||||
self.svg_settings.set("elevation-ref-guid", self.camera_element.GlobalId)
|
||||
self.svg_settings.set("scale", "1/50")
|
||||
self.svg_settings.set("svg-subtract-before", "always")
|
||||
self.svg_settings.set("svg-prefilter", True) # See #3359
|
||||
# self.svg_settings.set("svg-prefilter", False) # See #3359
|
||||
self.svg_settings.set("svg-unify-inputs", True)
|
||||
self.svg_settings.set("svg-segment-projection", True)
|
||||
self.serialiser_settings.set("profile-threshold", 10000)
|
||||
self.serialiser_settings.set("svg-xmlns", True)
|
||||
self.serialiser_settings.set("svg-project", True)
|
||||
self.serialiser_settings.set("auto-elevation", False)
|
||||
self.serialiser_settings.set("auto-section", False)
|
||||
self.serialiser_settings.set("print-space-names", False)
|
||||
self.serialiser_settings.set("print-space-areas", False)
|
||||
self.serialiser_settings.set("door-arcs", False)
|
||||
self.serialiser_settings.set("svg-no-css", True)
|
||||
self.serialiser_settings.set("elevation-ref-guid", self.camera_element.GlobalId)
|
||||
self.serialiser_settings.set("scale", "1/50")
|
||||
self.serialiser_settings.set("svg-subtract-before", "always")
|
||||
self.serialiser_settings.set("svg-prefilter", True) # See #3359
|
||||
# self.serialiser_settings.set("svg-prefilter", False) # See #3359
|
||||
self.serialiser_settings.set("svg-unify-inputs", True)
|
||||
self.serialiser_settings.set("svg-segment-projection", True)
|
||||
if target_view == "REFLECTED_PLAN_VIEW":
|
||||
self.svg_settings.set("svg-mirror-y", True)
|
||||
self.serialiser = ifcopenshell.geom.serializers.svg(self.svg_buffer, self.svg_settings)
|
||||
self.serialiser_settings.set("svg-mirror-y", True)
|
||||
self.serialiser = ifcopenshell.geom.serializers.svg(
|
||||
self.svg_buffer, self.svg_settings, self.serialiser_settings
|
||||
)
|
||||
self.serialiser.setFile(ifc)
|
||||
|
||||
|
||||
|
||||
@@ -72,12 +72,12 @@ Scenario: Add classification reference - object
|
||||
And I press "bim.add_classification"
|
||||
And I add a cube
|
||||
And the object "Cube" is selected
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElement"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.change_classification_level(parent_id={classification})"
|
||||
And the variable "reference" is "{classification_ifc}.by_type('IfcClassificationReference')[0].id()"
|
||||
When I press "bim.add_classification_reference(reference={reference}, obj='IfcWall/Cube', obj_type='Object')"
|
||||
When I press "bim.add_classification_reference(reference={reference}, obj='IfcWallType/Cube', obj_type='Object')"
|
||||
Then nothing happens
|
||||
|
||||
Scenario: Change classification level
|
||||
@@ -88,8 +88,8 @@ Scenario: Change classification level
|
||||
And I press "bim.add_classification"
|
||||
And I add a cube
|
||||
And the object "Cube" is selected
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElement"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.change_classification_level(parent_id={classification})"
|
||||
And the variable "reference" is "{classification_ifc}.by_type('IfcClassificationReference')[0].id()"
|
||||
@@ -104,8 +104,8 @@ Scenario: Disable editing classification references
|
||||
And I press "bim.add_classification"
|
||||
And I add a cube
|
||||
And the object "Cube" is selected
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElement"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.change_classification_level(parent_id={classification})"
|
||||
When I press "bim.disable_editing_classification_references"
|
||||
@@ -119,12 +119,12 @@ Scenario: Enable editing classification reference
|
||||
And I press "bim.add_classification"
|
||||
And I add a cube
|
||||
And the object "Cube" is selected
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElement"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.change_classification_level(parent_id={classification})"
|
||||
And the variable "reference" is "{classification_ifc}.by_type('IfcClassificationReference')[0].id()"
|
||||
And I press "bim.add_classification_reference(reference={reference}, obj='IfcWall/Cube', obj_type='Object')"
|
||||
And I press "bim.add_classification_reference(reference={reference}, obj='IfcWallType/Cube', obj_type='Object')"
|
||||
And the variable "reference" is "{ifc}.by_type('IfcClassificationReference')[0].id()"
|
||||
When I press "bim.enable_editing_classification_reference(reference={reference})"
|
||||
Then nothing happens
|
||||
@@ -137,12 +137,12 @@ Scenario: Disable editing classification reference
|
||||
And I press "bim.add_classification"
|
||||
And I add a cube
|
||||
And the object "Cube" is selected
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElement"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.change_classification_level(parent_id={classification})"
|
||||
And the variable "reference" is "{classification_ifc}.by_type('IfcClassificationReference')[0].id()"
|
||||
And I press "bim.add_classification_reference(reference={reference}, obj='IfcWall/Cube', obj_type='Object')"
|
||||
And I press "bim.add_classification_reference(reference={reference}, obj='IfcWallType/Cube', obj_type='Object')"
|
||||
And the variable "reference" is "{ifc}.by_type('IfcClassificationReference')[0].id()"
|
||||
And I press "bim.enable_editing_classification_reference(reference={reference})"
|
||||
When I press "bim.disable_editing_classification_reference"
|
||||
@@ -156,15 +156,15 @@ Scenario: Remove classification reference - object
|
||||
And I press "bim.add_classification"
|
||||
And I add a cube
|
||||
And the object "Cube" is selected
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElement"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.change_classification_level(parent_id={classification})"
|
||||
And the variable "reference" is "{classification_ifc}.by_type('IfcClassificationReference')[0].id()"
|
||||
And I press "bim.add_classification_reference(reference={reference}, obj='IfcWall/Cube', obj_type='Object')"
|
||||
And I press "bim.add_classification_reference(reference={reference}, obj='IfcWallType/Cube', obj_type='Object')"
|
||||
And the variable "reference" is "{ifc}.by_type('IfcClassificationReference')[0].id()"
|
||||
And I press "bim.enable_editing_classification_reference(reference={reference})"
|
||||
When I press "bim.remove_classification_reference(reference={reference}, obj='IfcWall/Cube', obj_type='Object')"
|
||||
When I press "bim.remove_classification_reference(reference={reference}, obj='IfcWallType/Cube', obj_type='Object')"
|
||||
Then nothing happens
|
||||
|
||||
Scenario: Edit classification reference
|
||||
@@ -175,12 +175,12 @@ Scenario: Edit classification reference
|
||||
And I press "bim.add_classification"
|
||||
And I add a cube
|
||||
And the object "Cube" is selected
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElement"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.change_classification_level(parent_id={classification})"
|
||||
And the variable "reference" is "{classification_ifc}.by_type('IfcClassificationReference')[0].id()"
|
||||
And I press "bim.add_classification_reference(reference={reference}, obj='IfcWall/Cube', obj_type='Object')"
|
||||
And I press "bim.add_classification_reference(reference={reference}, obj='IfcWallType/Cube', obj_type='Object')"
|
||||
And the variable "reference" is "{ifc}.by_type('IfcClassificationReference')[0].id()"
|
||||
And I press "bim.enable_editing_classification_reference(reference={reference})"
|
||||
When I press "bim.edit_classification_reference"
|
||||
|
||||
@@ -185,7 +185,6 @@ Scenario: Update representation - updating a layered extrusion
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
And I press "bim.enable_editing_assigned_material"
|
||||
@@ -214,7 +213,6 @@ Scenario: Update representation - updating a profiled extrusion
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialProfileSet"
|
||||
And I press "bim.assign_material"
|
||||
And I press "bim.enable_editing_assigned_material"
|
||||
@@ -418,7 +416,6 @@ Scenario: Override duplicate move - copying a layered extrusion
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
And I press "bim.enable_editing_assigned_material"
|
||||
@@ -450,7 +447,6 @@ Scenario: Override duplicate move - copying a profiled extrusion
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialProfileSet"
|
||||
And I press "bim.assign_material"
|
||||
And I press "bim.enable_editing_assigned_material"
|
||||
|
||||
@@ -121,7 +121,6 @@ Scenario: Assign material - material layer set
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
When I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
Then the object "IfcWallType/Empty" does not have the material "Default"
|
||||
@@ -135,7 +134,6 @@ Scenario: Unassign material - material layer set
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
When I press "bim.unassign_material"
|
||||
@@ -157,7 +155,6 @@ Scenario: Unassign material - removing inherited material
|
||||
And I press "bim.assign_class"
|
||||
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
|
||||
@@ -184,7 +181,6 @@ Scenario: Enable editing assigned material - material layer set
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
When I press "bim.enable_editing_assigned_material"
|
||||
@@ -204,7 +200,6 @@ Scenario: Disable editing assigned material - material layer set
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
And I press "bim.enable_editing_assigned_material"
|
||||
@@ -225,7 +220,6 @@ Scenario: Edit assigned material - material layer set
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
And I press "bim.enable_editing_assigned_material"
|
||||
@@ -241,7 +235,6 @@ Scenario: Assign material - material profile set
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
When I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialProfileSet"
|
||||
And I press "bim.assign_material"
|
||||
Then the object "IfcWallType/Empty" does not have the material "Default"
|
||||
@@ -255,7 +248,6 @@ Scenario: Unassign material - material profile set
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialProfileSet"
|
||||
And I press "bim.assign_material"
|
||||
When I press "bim.unassign_material"
|
||||
@@ -275,7 +267,6 @@ Scenario: Enable editing assigned material - material profile set
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialProfileSet"
|
||||
And I press "bim.assign_material"
|
||||
When I press "bim.enable_editing_assigned_material"
|
||||
@@ -295,7 +286,6 @@ Scenario: Disable editing assigned material - material profile set
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialProfileSet"
|
||||
And I press "bim.assign_material"
|
||||
And I press "bim.enable_editing_assigned_material"
|
||||
@@ -316,7 +306,6 @@ Scenario: Edit assigned material - material profile set
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialProfileSet"
|
||||
And I press "bim.assign_material"
|
||||
And I press "bim.enable_editing_assigned_material"
|
||||
@@ -465,7 +454,6 @@ Scenario: Add material set layer
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
And I press "bim.enable_editing_assigned_material"
|
||||
@@ -489,7 +477,6 @@ Scenario: Remove material set layer
|
||||
And I press "bim.assign_class"
|
||||
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
|
||||
|
||||
@@ -314,12 +314,6 @@ Scenario: Load project elements - auto offset of cartesian points
|
||||
Then the object "IfcBuildingElementProxy/NAME" is at "0,0,0"
|
||||
|
||||
Scenario: Load project elements - all georeferencing coordinate situations - disabled false origin mode
|
||||
# D, G and J have their geometry far from their placement, so each is
|
||||
# shifted onto one of its own verts to keep its precision. Which vert that
|
||||
# is comes from the geometry kernel and has changed before, so these assert
|
||||
# that the origin is on a vert rather than which one, and name verts rather
|
||||
# than origins. In automatic mode the model origin is picked the same way
|
||||
# and everything moves with it, so there they are relative to it.
|
||||
Given an empty Blender session
|
||||
And I press "bim.load_project(filepath='{cwd}/test/files/geolocation.ifc', is_advanced=True)"
|
||||
When I set "scene.BIMProjectProperties.false_origin_mode" to "DISABLED"
|
||||
@@ -332,19 +326,13 @@ Scenario: Load project elements - all georeferencing coordinate situations - dis
|
||||
And the object "IfcActuator/A" is at "7,3,0"
|
||||
And the object "IfcActuator/B" is at "6,1,0"
|
||||
And the object "IfcActuator/C" is at "0,0,0"
|
||||
And the object "IfcActuator/D" has its origin on a vertex
|
||||
And the object "IfcActuator/D" has a vert at "13,4,-1" at map coordinates "13000,4000,-1000"
|
||||
And the object "IfcActuator/D" has a vert at "15,2,1" at map coordinates "15000,2000,1000"
|
||||
And the object "IfcActuator/D" is at "13,4,-1"
|
||||
And the object "IfcActuator/E" is at "6,3,0"
|
||||
And the object "IfcActuator/F" is at "3,3,0"
|
||||
And the object "IfcActuator/G" has its origin on a vertex
|
||||
And the object "IfcActuator/G" has a vert at "15,6,-1" at map coordinates "15000,6000,-1000"
|
||||
And the object "IfcActuator/G" has a vert at "17,4,1" at map coordinates "17000,4000,1000"
|
||||
And the object "IfcActuator/G" is at "15,6,-1"
|
||||
And the object "IfcActuator/H" is at "9,2,0"
|
||||
And the object "IfcActuator/I" is at "3,3,0"
|
||||
And the object "IfcActuator/J" has its origin on a vertex
|
||||
And the object "IfcActuator/J" has a vert at "11,3,-1" at map coordinates "11000,3000,-1000"
|
||||
And the object "IfcActuator/J" has a vert at "13,1,1" at map coordinates "13000,1000,1000"
|
||||
And the object "IfcActuator/J" is at "11,3,-1"
|
||||
And the object "IfcActuator/K" is at "10,0,0"
|
||||
|
||||
Scenario: Load project elements - all georeferencing coordinate situations - automatic false origin mode
|
||||
@@ -354,27 +342,24 @@ Scenario: Load project elements - all georeferencing coordinate situations - aut
|
||||
When I set "scene.BIMProjectProperties.distance_limit" to "5"
|
||||
And I press "bim.load_project_elements"
|
||||
Then "scene.BIMGeoreferenceProperties.has_blender_offset" is "True"
|
||||
And the model origin is on an object vertex
|
||||
And "scene.BIMGeoreferenceProperties.model_origin" is "13000.0,4000.0,-1000.0"
|
||||
And "scene.BIMGeoreferenceProperties.blender_offset_x" is "13000.0"
|
||||
And "scene.BIMGeoreferenceProperties.blender_offset_y" is "4000.0"
|
||||
And "scene.BIMGeoreferenceProperties.blender_offset_z" is "-1000.0"
|
||||
And the object "IfcSite/My Site" is at "0,0,0"
|
||||
And the object "IfcBuilding/My Building" is at "0,0,0"
|
||||
And the object "IfcBuildingStorey/My Storey" is at "0,0,0"
|
||||
And the object "IfcActuator/A" is at "7,3,0" relative to the model origin at map coordinates "7000,3000,0"
|
||||
And the object "IfcActuator/B" is at "6,1,0" relative to the model origin at map coordinates "6000,1000,0"
|
||||
And the object "IfcActuator/A" is at "-6,-1,1"
|
||||
And the object "IfcActuator/B" is at "-7,-3,1"
|
||||
And the object "IfcActuator/C" is at "0,0,0"
|
||||
And the object "IfcActuator/D" has its origin on a vertex
|
||||
And the object "IfcActuator/D" has a vert at "13,4,-1" relative to the model origin at map coordinates "13000,4000,-1000"
|
||||
And the object "IfcActuator/D" has a vert at "15,2,1" relative to the model origin at map coordinates "15000,2000,1000"
|
||||
And the object "IfcActuator/E" is at "6,3,0" relative to the model origin at map coordinates "6000,3000,0"
|
||||
And the object "IfcActuator/F" is at "3,3,0" relative to the model origin at map coordinates "3000,3000,0"
|
||||
And the object "IfcActuator/G" has its origin on a vertex
|
||||
And the object "IfcActuator/G" has a vert at "15,6,-1" relative to the model origin at map coordinates "15000,6000,-1000"
|
||||
And the object "IfcActuator/G" has a vert at "17,4,1" relative to the model origin at map coordinates "17000,4000,1000"
|
||||
And the object "IfcActuator/H" is at "9,2,0" relative to the model origin at map coordinates "9000,2000,0"
|
||||
And the object "IfcActuator/I" is at "3,3,0" relative to the model origin at map coordinates "3000,3000,0"
|
||||
And the object "IfcActuator/J" has its origin on a vertex
|
||||
And the object "IfcActuator/J" has a vert at "11,3,-1" relative to the model origin at map coordinates "11000,3000,-1000"
|
||||
And the object "IfcActuator/J" has a vert at "13,1,1" relative to the model origin at map coordinates "13000,1000,1000"
|
||||
And the object "IfcActuator/K" is at "10,0,0" relative to the model origin at map coordinates "10000,0,0"
|
||||
And the object "IfcActuator/D" is at "0,0,0"
|
||||
And the object "IfcActuator/E" is at "-7,-1,1"
|
||||
And the object "IfcActuator/F" is at "-10,-1,1"
|
||||
And the object "IfcActuator/G" is at "2,2,0"
|
||||
And the object "IfcActuator/H" is at "-4,-2,1"
|
||||
And the object "IfcActuator/I" is at "-10,-1,1"
|
||||
And the object "IfcActuator/J" is at "-2,-1,0"
|
||||
And the object "IfcActuator/K" is at "-3,-4,1"
|
||||
|
||||
Scenario: Load project elements - all georeferencing coordinate situations - manual false origin mode
|
||||
Given an empty Blender session
|
||||
@@ -394,20 +379,23 @@ Scenario: Load project elements - all georeferencing coordinate situations - man
|
||||
And the object "IfcActuator/A" is at "-3,3,0"
|
||||
And the object "IfcActuator/B" is at "-4,1,0"
|
||||
And the object "IfcActuator/C" is at "0,0,0"
|
||||
And the object "IfcActuator/D" has its origin on a vertex
|
||||
And the object "IfcActuator/D" has a vert at "3,4,-1" at map coordinates "13000,4000,-1000"
|
||||
And the object "IfcActuator/D" has a vert at "5,2,1" at map coordinates "15000,2000,1000"
|
||||
And the object "IfcActuator/D" is at "3,4,-1"
|
||||
And the object "IfcActuator/E" is at "-4,3,0"
|
||||
And the object "IfcActuator/F" is at "-7,3,0"
|
||||
And the object "IfcActuator/G" has its origin on a vertex
|
||||
And the object "IfcActuator/G" has a vert at "5,6,-1" at map coordinates "15000,6000,-1000"
|
||||
And the object "IfcActuator/G" has a vert at "7,4,1" at map coordinates "17000,4000,1000"
|
||||
And the object "IfcActuator/G" is at "5,6,-1"
|
||||
And the object "IfcActuator/H" is at "-1,2,0"
|
||||
And the object "IfcActuator/I" is at "-7,3,0"
|
||||
And the object "IfcActuator/J" has its origin on a vertex
|
||||
And the object "IfcActuator/J" has a vert at "1,3,-1" at map coordinates "11000,3000,-1000"
|
||||
And the object "IfcActuator/J" has a vert at "3,1,1" at map coordinates "13000,1000,1000"
|
||||
And the object "IfcActuator/J" is at "1,3,-1"
|
||||
And the object "IfcActuator/K" is at "0,0,0"
|
||||
And the object "IfcActuator/D" has a cartesian point offset of "31,4,-1"
|
||||
And the object "IfcActuator/G" has a cartesian point offset of "-25,6,-1"
|
||||
And the object "IfcActuator/J" has a cartesian point offset of "11,3,-1"
|
||||
And the object "IfcActuator/D" has a vertex at "3,2,-1"
|
||||
And the object "IfcActuator/D" has a vertex at "5,2,-1"
|
||||
And the object "IfcActuator/G" has a vertex at "5,4,-1"
|
||||
And the object "IfcActuator/G" has a vertex at "7,4,-1"
|
||||
And the object "IfcActuator/J" has a vertex at "1,1,-1"
|
||||
And the object "IfcActuator/J" has a vertex at "3,1,-1"
|
||||
|
||||
Scenario: Load project elements - all georeferencing coordinate situations with an offset site - disabled false origin mode
|
||||
Given an empty Blender session
|
||||
@@ -422,19 +410,13 @@ Scenario: Load project elements - all georeferencing coordinate situations with
|
||||
And the object "IfcActuator/A" is at "5.985,14.71,0"
|
||||
And the object "IfcActuator/B" is at "5.5367,12.519,0"
|
||||
And the object "IfcActuator/C" is at "0,10,0"
|
||||
And the object "IfcActuator/D" has its origin on a vertex
|
||||
And the object "IfcActuator/D" has a vert at "11.5218,17.2284,-1" at map coordinates "11521.758,17228.35,-1000"
|
||||
And the object "IfcActuator/D" has a vert at "13.9712,15.8141,1" at map coordinates "13971.246,15814.136,1000"
|
||||
And the object "IfcActuator/D" is at "11.522,17.228,-1"
|
||||
And the object "IfcActuator/E" is at "5.0191,14.451,0"
|
||||
And the object "IfcActuator/F" is at "2.1213,13.674,0"
|
||||
And the object "IfcActuator/G" has its origin on a vertex
|
||||
And the object "IfcActuator/G" has a vert at "12.936,19.6778,-1" at map coordinates "12935.975,19677.841,-1000"
|
||||
And the object "IfcActuator/G" has a vert at "15.3855,18.2636,1" at map coordinates "15385.465,18263.627,1000"
|
||||
And the object "IfcActuator/G" is at "12.936,19.678,-1"
|
||||
And the object "IfcActuator/H" is at "8.1757,14.261,0"
|
||||
And the object "IfcActuator/I" is at "2.1213,13.674,0"
|
||||
And the object "IfcActuator/J" has its origin on a vertex
|
||||
And the object "IfcActuator/J" has a vert at "9.8487,15.7448,-1" at map coordinates "9848.726,15744.786,-1000"
|
||||
And the object "IfcActuator/J" has a vert at "12.2982,14.3306,1" at map coordinates "12298.216,14330.573,1000"
|
||||
And the object "IfcActuator/J" is at "9.8487,15.745,-1"
|
||||
And the object "IfcActuator/K" is at "9.6593,12.588,0"
|
||||
|
||||
Scenario: Load project elements - all georeferencing coordinate situations with an offset site - automatic false origin mode
|
||||
@@ -454,19 +436,13 @@ Scenario: Load project elements - all georeferencing coordinate situations with
|
||||
And the object "IfcActuator/A" is at "7,3,0"
|
||||
And the object "IfcActuator/B" is at "6,1,0"
|
||||
And the object "IfcActuator/C" is at "0,0,0"
|
||||
And the object "IfcActuator/D" has its origin on a vertex
|
||||
And the object "IfcActuator/D" has a vert at "13,4,-1" at map coordinates "11521.758,17228.35,-1000"
|
||||
And the object "IfcActuator/D" has a vert at "15,2,1" at map coordinates "13971.246,15814.136,1000"
|
||||
And the object "IfcActuator/D" is at "13,4,-1"
|
||||
And the object "IfcActuator/E" is at "6,3,0"
|
||||
And the object "IfcActuator/F" is at "3,3,0"
|
||||
And the object "IfcActuator/G" has its origin on a vertex
|
||||
And the object "IfcActuator/G" has a vert at "15,6,-1" at map coordinates "12935.975,19677.841,-1000"
|
||||
And the object "IfcActuator/G" has a vert at "17,4,1" at map coordinates "15385.465,18263.627,1000"
|
||||
And the object "IfcActuator/G" is at "15,6,-1"
|
||||
And the object "IfcActuator/H" is at "9,2,0"
|
||||
And the object "IfcActuator/I" is at "3,3,0"
|
||||
And the object "IfcActuator/J" has its origin on a vertex
|
||||
And the object "IfcActuator/J" has a vert at "11,3,-1" at map coordinates "9848.726,15744.786,-1000"
|
||||
And the object "IfcActuator/J" has a vert at "13,1,1" at map coordinates "12298.216,14330.573,1000"
|
||||
And the object "IfcActuator/J" is at "11,3,-1"
|
||||
And the object "IfcActuator/K" is at "10,0,0"
|
||||
|
||||
Scenario: Load project elements - all georeferencing coordinate situations with an offset site - manual false origin mode
|
||||
@@ -487,20 +463,23 @@ Scenario: Load project elements - all georeferencing coordinate situations with
|
||||
And the object "IfcActuator/A" is at "5.985,4.71,0"
|
||||
And the object "IfcActuator/B" is at "5.5367,2.519,0"
|
||||
And the object "IfcActuator/C" is at "0,0,0"
|
||||
And the object "IfcActuator/D" has its origin on a vertex
|
||||
And the object "IfcActuator/D" has a vert at "11.5218,7.2284,-1" at map coordinates "11521.758,17228.35,-1000"
|
||||
And the object "IfcActuator/D" has a vert at "13.9712,5.8141,1" at map coordinates "13971.246,15814.136,1000"
|
||||
And the object "IfcActuator/D" is at "11.522,7.228,-1"
|
||||
And the object "IfcActuator/E" is at "5.0191,4.451,0"
|
||||
And the object "IfcActuator/F" is at "2.1213,3.674,0"
|
||||
And the object "IfcActuator/G" has its origin on a vertex
|
||||
And the object "IfcActuator/G" has a vert at "12.936,9.6778,-1" at map coordinates "12935.975,19677.841,-1000"
|
||||
And the object "IfcActuator/G" has a vert at "15.3855,8.2636,1" at map coordinates "15385.465,18263.627,1000"
|
||||
And the object "IfcActuator/G" is at "12.936,9.678,-1"
|
||||
And the object "IfcActuator/H" is at "8.1757,4.261,0"
|
||||
And the object "IfcActuator/I" is at "2.1213,3.674,0"
|
||||
And the object "IfcActuator/J" has its origin on a vertex
|
||||
And the object "IfcActuator/J" has a vert at "9.8487,5.7448,-1" at map coordinates "9848.726,15744.786,-1000"
|
||||
And the object "IfcActuator/J" has a vert at "12.2982,4.3306,1" at map coordinates "12298.216,14330.573,1000"
|
||||
And the object "IfcActuator/J" is at "9.8487,5.745,-1"
|
||||
And the object "IfcActuator/K" is at "9.6593,2.588,0"
|
||||
And the object "IfcActuator/D" has a cartesian point offset of "31,4,-1"
|
||||
And the object "IfcActuator/G" has a cartesian point offset of "-25,6,-1"
|
||||
And the object "IfcActuator/J" has a cartesian point offset of "11,3,-1"
|
||||
And the object "IfcActuator/D" has a vertex at "12.039,5.296,-1"
|
||||
And the object "IfcActuator/D" has a vertex at "13.971,5.814,-1"
|
||||
And the object "IfcActuator/G" has a vertex at "13.454,7.746,-1"
|
||||
And the object "IfcActuator/G" has a vertex at "15.385,8.264,-1"
|
||||
And the object "IfcActuator/J" has a vertex at "10.366,3.813,-1"
|
||||
And the object "IfcActuator/J" has a vertex at "12.298,4.331,-1"
|
||||
|
||||
Scenario: Load project elements - all georeferencing coordinate situations with an offset site - manual false origin mode - with custom project north
|
||||
Given an empty Blender session
|
||||
@@ -521,19 +500,13 @@ Scenario: Load project elements - all georeferencing coordinate situations with
|
||||
And the object "IfcActuator/A" is at "7,3,0"
|
||||
And the object "IfcActuator/B" is at "6,1,0"
|
||||
And the object "IfcActuator/C" is at "0,0,0"
|
||||
And the object "IfcActuator/D" has its origin on a vertex
|
||||
And the object "IfcActuator/D" has a vert at "13,4,-1" at map coordinates "11521.758,17228.35,-1000"
|
||||
And the object "IfcActuator/D" has a vert at "15,2,1" at map coordinates "13971.246,15814.136,1000"
|
||||
And the object "IfcActuator/D" is at "13,4,-1"
|
||||
And the object "IfcActuator/E" is at "6,3,0"
|
||||
And the object "IfcActuator/F" is at "3,3,0"
|
||||
And the object "IfcActuator/G" has its origin on a vertex
|
||||
And the object "IfcActuator/G" has a vert at "15,6,-1" at map coordinates "12935.975,19677.841,-1000"
|
||||
And the object "IfcActuator/G" has a vert at "17,4,1" at map coordinates "15385.465,18263.627,1000"
|
||||
And the object "IfcActuator/G" is at "15,6,-1"
|
||||
And the object "IfcActuator/H" is at "9,2,0"
|
||||
And the object "IfcActuator/I" is at "3,3,0"
|
||||
And the object "IfcActuator/J" has its origin on a vertex
|
||||
And the object "IfcActuator/J" has a vert at "11,3,-1" at map coordinates "9848.726,15744.786,-1000"
|
||||
And the object "IfcActuator/J" has a vert at "13,1,1" at map coordinates "12298.216,14330.573,1000"
|
||||
And the object "IfcActuator/J" is at "11,3,-1"
|
||||
And the object "IfcActuator/K" is at "10,0,0"
|
||||
|
||||
Scenario: Load project elements - all georeferencing coordinate situations with a map conversion - disabled false origin mode (this should be identical to the situation with no map conversion)
|
||||
@@ -549,19 +522,13 @@ Scenario: Load project elements - all georeferencing coordinate situations with
|
||||
And the object "IfcActuator/A" is at "7,3,0"
|
||||
And the object "IfcActuator/B" is at "6,1,0"
|
||||
And the object "IfcActuator/C" is at "0,0,0"
|
||||
And the object "IfcActuator/D" has its origin on a vertex
|
||||
And the object "IfcActuator/D" has a vert at "13,4,-1" at map coordinates "28000,4000,-1000"
|
||||
And the object "IfcActuator/D" has a vert at "15,2,1" at map coordinates "30000,2000,1000"
|
||||
And the object "IfcActuator/D" is at "13,4,-1"
|
||||
And the object "IfcActuator/E" is at "6,3,0"
|
||||
And the object "IfcActuator/F" is at "3,3,0"
|
||||
And the object "IfcActuator/G" has its origin on a vertex
|
||||
And the object "IfcActuator/G" has a vert at "15,6,-1" at map coordinates "30000,6000,-1000"
|
||||
And the object "IfcActuator/G" has a vert at "17,4,1" at map coordinates "32000,4000,1000"
|
||||
And the object "IfcActuator/G" is at "15,6,-1"
|
||||
And the object "IfcActuator/H" is at "9,2,0"
|
||||
And the object "IfcActuator/I" is at "3,3,0"
|
||||
And the object "IfcActuator/J" has its origin on a vertex
|
||||
And the object "IfcActuator/J" has a vert at "11,3,-1" at map coordinates "26000,3000,-1000"
|
||||
And the object "IfcActuator/J" has a vert at "13,1,1" at map coordinates "28000,1000,1000"
|
||||
And the object "IfcActuator/J" is at "11,3,-1"
|
||||
And the object "IfcActuator/K" is at "10,0,0"
|
||||
|
||||
Scenario: Load project elements - all georeferencing coordinate situations with a map conversion - automatic false origin mode (this should affect the Blender eastings and northings, which is now different to the Blender offset XYZ, but is otherwise identical to the non-map conversion variant)
|
||||
@@ -571,27 +538,24 @@ Scenario: Load project elements - all georeferencing coordinate situations with
|
||||
When I set "scene.BIMProjectProperties.distance_limit" to "5"
|
||||
And I press "bim.load_project_elements"
|
||||
Then "scene.BIMGeoreferenceProperties.has_blender_offset" is "True"
|
||||
And the model origin is on an object vertex
|
||||
And "scene.BIMGeoreferenceProperties.model_origin" is "28000.0,4000.0,-1000.0"
|
||||
And "scene.BIMGeoreferenceProperties.blender_offset_x" is "13000.0"
|
||||
And "scene.BIMGeoreferenceProperties.blender_offset_y" is "4000.0"
|
||||
And "scene.BIMGeoreferenceProperties.blender_offset_z" is "-1000.0"
|
||||
And the object "IfcSite/My Site" is at "0,0,0"
|
||||
And the object "IfcBuilding/My Building" is at "0,0,0"
|
||||
And the object "IfcBuildingStorey/My Storey" is at "0,0,0"
|
||||
And the object "IfcActuator/A" is at "22,3,0" relative to the model origin at map coordinates "22000,3000,0"
|
||||
And the object "IfcActuator/B" is at "21,1,0" relative to the model origin at map coordinates "21000,1000,0"
|
||||
And the object "IfcActuator/A" is at "-6,-1,1"
|
||||
And the object "IfcActuator/B" is at "-7,-3,1"
|
||||
And the object "IfcActuator/C" is at "0,0,0"
|
||||
And the object "IfcActuator/D" has its origin on a vertex
|
||||
And the object "IfcActuator/D" has a vert at "28,4,-1" relative to the model origin at map coordinates "28000,4000,-1000"
|
||||
And the object "IfcActuator/D" has a vert at "30,2,1" relative to the model origin at map coordinates "30000,2000,1000"
|
||||
And the object "IfcActuator/E" is at "21,3,0" relative to the model origin at map coordinates "21000,3000,0"
|
||||
And the object "IfcActuator/F" is at "18,3,0" relative to the model origin at map coordinates "18000,3000,0"
|
||||
And the object "IfcActuator/G" has its origin on a vertex
|
||||
And the object "IfcActuator/G" has a vert at "30,6,-1" relative to the model origin at map coordinates "30000,6000,-1000"
|
||||
And the object "IfcActuator/G" has a vert at "32,4,1" relative to the model origin at map coordinates "32000,4000,1000"
|
||||
And the object "IfcActuator/H" is at "24,2,0" relative to the model origin at map coordinates "24000,2000,0"
|
||||
And the object "IfcActuator/I" is at "18,3,0" relative to the model origin at map coordinates "18000,3000,0"
|
||||
And the object "IfcActuator/J" has its origin on a vertex
|
||||
And the object "IfcActuator/J" has a vert at "26,3,-1" relative to the model origin at map coordinates "26000,3000,-1000"
|
||||
And the object "IfcActuator/J" has a vert at "28,1,1" relative to the model origin at map coordinates "28000,1000,1000"
|
||||
And the object "IfcActuator/K" is at "25,0,0" relative to the model origin at map coordinates "25000,0,0"
|
||||
And the object "IfcActuator/D" is at "0,0,0"
|
||||
And the object "IfcActuator/E" is at "-7,-1,1"
|
||||
And the object "IfcActuator/F" is at "-10,-1,1"
|
||||
And the object "IfcActuator/G" is at "2,2,0"
|
||||
And the object "IfcActuator/H" is at "-4,-2,1"
|
||||
And the object "IfcActuator/I" is at "-10,-1,1"
|
||||
And the object "IfcActuator/J" is at "-2,-1,0"
|
||||
And the object "IfcActuator/K" is at "-3,-4,1"
|
||||
|
||||
Scenario: Load project elements - all georeferencing coordinate situations with a map conversion - manual false origin mode (this should affect the Blender eastings and northings, which is now different to the Blender offset XYZ, but is otherwise identical to the non-map conversion variant)
|
||||
Given an empty Blender session
|
||||
@@ -611,20 +575,23 @@ Scenario: Load project elements - all georeferencing coordinate situations with
|
||||
And the object "IfcActuator/A" is at "-3,3,0"
|
||||
And the object "IfcActuator/B" is at "-4,1,0"
|
||||
And the object "IfcActuator/C" is at "0,0,0"
|
||||
And the object "IfcActuator/D" has its origin on a vertex
|
||||
And the object "IfcActuator/D" has a vert at "3,4,-1" at map coordinates "28000,4000,-1000"
|
||||
And the object "IfcActuator/D" has a vert at "5,2,1" at map coordinates "30000,2000,1000"
|
||||
And the object "IfcActuator/D" is at "3,4,-1"
|
||||
And the object "IfcActuator/E" is at "-4,3,0"
|
||||
And the object "IfcActuator/F" is at "-7,3,0"
|
||||
And the object "IfcActuator/G" has its origin on a vertex
|
||||
And the object "IfcActuator/G" has a vert at "5,6,-1" at map coordinates "30000,6000,-1000"
|
||||
And the object "IfcActuator/G" has a vert at "7,4,1" at map coordinates "32000,4000,1000"
|
||||
And the object "IfcActuator/G" is at "5,6,-1"
|
||||
And the object "IfcActuator/H" is at "-1,2,0"
|
||||
And the object "IfcActuator/I" is at "-7,3,0"
|
||||
And the object "IfcActuator/J" has its origin on a vertex
|
||||
And the object "IfcActuator/J" has a vert at "1,3,-1" at map coordinates "26000,3000,-1000"
|
||||
And the object "IfcActuator/J" has a vert at "3,1,1" at map coordinates "28000,1000,1000"
|
||||
And the object "IfcActuator/J" is at "1,3,-1"
|
||||
And the object "IfcActuator/K" is at "0,0,0"
|
||||
And the object "IfcActuator/D" has a cartesian point offset of "31,4,-1"
|
||||
And the object "IfcActuator/G" has a cartesian point offset of "-25,6,-1"
|
||||
And the object "IfcActuator/J" has a cartesian point offset of "11,3,-1"
|
||||
And the object "IfcActuator/D" has a vertex at "3,2,-1"
|
||||
And the object "IfcActuator/D" has a vertex at "5,2,-1"
|
||||
And the object "IfcActuator/G" has a vertex at "5,4,-1"
|
||||
And the object "IfcActuator/G" has a vertex at "7,4,-1"
|
||||
And the object "IfcActuator/J" has a vertex at "1,1,-1"
|
||||
And the object "IfcActuator/J" has a vertex at "3,1,-1"
|
||||
|
||||
Scenario: Load project elements - all georeferencing coordinate situations with map conversion and an offset site - disabled false origin mode
|
||||
Given an empty Blender session
|
||||
@@ -639,19 +606,13 @@ Scenario: Load project elements - all georeferencing coordinate situations with
|
||||
And the object "IfcActuator/A" is at "5.985,14.71,0"
|
||||
And the object "IfcActuator/B" is at "5.5367,12.519,0"
|
||||
And the object "IfcActuator/C" is at "0,10,0"
|
||||
And the object "IfcActuator/D" has its origin on a vertex
|
||||
And the object "IfcActuator/D" has a vert at "11.5218,17.2284,-1" at map coordinates "26521.758,17228.35,-1000"
|
||||
And the object "IfcActuator/D" has a vert at "13.9712,15.8141,1" at map coordinates "28971.246,15814.136,1000"
|
||||
And the object "IfcActuator/D" is at "11.522,17.228,-1"
|
||||
And the object "IfcActuator/E" is at "5.0191,14.451,0"
|
||||
And the object "IfcActuator/F" is at "2.1213,13.674,0"
|
||||
And the object "IfcActuator/G" has its origin on a vertex
|
||||
And the object "IfcActuator/G" has a vert at "12.936,19.6778,-1" at map coordinates "27935.975,19677.841,-1000"
|
||||
And the object "IfcActuator/G" has a vert at "15.3855,18.2636,1" at map coordinates "30385.465,18263.627,1000"
|
||||
And the object "IfcActuator/G" is at "12.936,19.678,-1"
|
||||
And the object "IfcActuator/H" is at "8.1757,14.261,0"
|
||||
And the object "IfcActuator/I" is at "2.1213,13.674,0"
|
||||
And the object "IfcActuator/J" has its origin on a vertex
|
||||
And the object "IfcActuator/J" has a vert at "9.8487,15.7448,-1" at map coordinates "24848.726,15744.786,-1000"
|
||||
And the object "IfcActuator/J" has a vert at "12.2982,14.3306,1" at map coordinates "27298.216,14330.573,1000"
|
||||
And the object "IfcActuator/J" is at "9.8487,15.745,-1"
|
||||
And the object "IfcActuator/K" is at "9.6593,12.588,0"
|
||||
|
||||
Scenario: Load project elements - all georeferencing coordinate situations with map conversion and an offset site - automatic false origin mode
|
||||
@@ -671,19 +632,13 @@ Scenario: Load project elements - all georeferencing coordinate situations with
|
||||
And the object "IfcActuator/A" is at "7,3,0"
|
||||
And the object "IfcActuator/B" is at "6,1,0"
|
||||
And the object "IfcActuator/C" is at "0,0,0"
|
||||
And the object "IfcActuator/D" has its origin on a vertex
|
||||
And the object "IfcActuator/D" has a vert at "13,4,-1" at map coordinates "26521.758,17228.35,-1000"
|
||||
And the object "IfcActuator/D" has a vert at "15,2,1" at map coordinates "28971.246,15814.136,1000"
|
||||
And the object "IfcActuator/D" is at "13,4,-1"
|
||||
And the object "IfcActuator/E" is at "6,3,0"
|
||||
And the object "IfcActuator/F" is at "3,3,0"
|
||||
And the object "IfcActuator/G" has its origin on a vertex
|
||||
And the object "IfcActuator/G" has a vert at "15,6,-1" at map coordinates "27935.975,19677.841,-1000"
|
||||
And the object "IfcActuator/G" has a vert at "17,4,1" at map coordinates "30385.465,18263.627,1000"
|
||||
And the object "IfcActuator/G" is at "15,6,-1"
|
||||
And the object "IfcActuator/H" is at "9,2,0"
|
||||
And the object "IfcActuator/I" is at "3,3,0"
|
||||
And the object "IfcActuator/J" has its origin on a vertex
|
||||
And the object "IfcActuator/J" has a vert at "11,3,-1" at map coordinates "24848.726,15744.786,-1000"
|
||||
And the object "IfcActuator/J" has a vert at "13,1,1" at map coordinates "27298.216,14330.573,1000"
|
||||
And the object "IfcActuator/J" is at "11,3,-1"
|
||||
And the object "IfcActuator/K" is at "10,0,0"
|
||||
|
||||
Scenario: Load project elements - all georeferencing coordinate situations with map conversion and an offset site - manual false origin mode
|
||||
@@ -704,20 +659,23 @@ Scenario: Load project elements - all georeferencing coordinate situations with
|
||||
And the object "IfcActuator/A" is at "5.985,4.71,0"
|
||||
And the object "IfcActuator/B" is at "5.5367,2.519,0"
|
||||
And the object "IfcActuator/C" is at "0,0,0"
|
||||
And the object "IfcActuator/D" has its origin on a vertex
|
||||
And the object "IfcActuator/D" has a vert at "11.5218,7.2284,-1" at map coordinates "26521.758,17228.35,-1000"
|
||||
And the object "IfcActuator/D" has a vert at "13.9712,5.8141,1" at map coordinates "28971.246,15814.136,1000"
|
||||
And the object "IfcActuator/D" is at "11.522,7.228,-1"
|
||||
And the object "IfcActuator/E" is at "5.0191,4.451,0"
|
||||
And the object "IfcActuator/F" is at "2.1213,3.674,0"
|
||||
And the object "IfcActuator/G" has its origin on a vertex
|
||||
And the object "IfcActuator/G" has a vert at "12.936,9.6778,-1" at map coordinates "27935.975,19677.841,-1000"
|
||||
And the object "IfcActuator/G" has a vert at "15.3855,8.2636,1" at map coordinates "30385.465,18263.627,1000"
|
||||
And the object "IfcActuator/G" is at "12.936,9.678,-1"
|
||||
And the object "IfcActuator/H" is at "8.1757,4.261,0"
|
||||
And the object "IfcActuator/I" is at "2.1213,3.674,0"
|
||||
And the object "IfcActuator/J" has its origin on a vertex
|
||||
And the object "IfcActuator/J" has a vert at "9.8487,5.7448,-1" at map coordinates "24848.726,15744.786,-1000"
|
||||
And the object "IfcActuator/J" has a vert at "12.2982,4.3306,1" at map coordinates "27298.216,14330.573,1000"
|
||||
And the object "IfcActuator/J" is at "9.8487,5.745,-1"
|
||||
And the object "IfcActuator/K" is at "9.6593,2.588,0"
|
||||
And the object "IfcActuator/D" has a cartesian point offset of "31,4,-1"
|
||||
And the object "IfcActuator/G" has a cartesian point offset of "-25,6,-1"
|
||||
And the object "IfcActuator/J" has a cartesian point offset of "11,3,-1"
|
||||
And the object "IfcActuator/D" has a vertex at "12.039,5.296,-1"
|
||||
And the object "IfcActuator/D" has a vertex at "13.971,5.814,-1"
|
||||
And the object "IfcActuator/G" has a vertex at "13.454,7.746,-1"
|
||||
And the object "IfcActuator/G" has a vertex at "15.385,8.264,-1"
|
||||
And the object "IfcActuator/J" has a vertex at "10.366,3.813,-1"
|
||||
And the object "IfcActuator/J" has a vertex at "12.298,4.331,-1"
|
||||
|
||||
Scenario: Link IFC - from an empty IFC project
|
||||
Given an empty IFC project
|
||||
|
||||
@@ -81,7 +81,6 @@ Scenario: Assign type - assign to a type with a material layer set, which automa
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
When the variable "type" is "{ifc}.by_type('IfcWallType')[0].id()"
|
||||
@@ -103,7 +102,6 @@ Scenario: Assign type - assign to a type with a material layer set, which automa
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
When the variable "type" is "{ifc}.by_type('IfcWallType')[0].id()"
|
||||
@@ -127,7 +125,6 @@ Scenario: Assign type - assign to a different type with a LAYER2 material layer
|
||||
And I press "bim.assign_class"
|
||||
And the variable "type" is "{ifc}.by_type('IfcWallType')[-1].id()"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
And I add an empty
|
||||
@@ -183,7 +180,6 @@ Scenario: Assign type - assign to a type with a material profile set
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material()"
|
||||
And the object "IfcWallType/Empty" is selected
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialProfileSet"
|
||||
And I press "bim.assign_material"
|
||||
And I press "bim.enable_editing_assigned_material"
|
||||
|
||||
@@ -45,14 +45,14 @@ def test_text_formatter_defaults_to_none():
|
||||
|
||||
|
||||
def test_text_formatter_field_stores_callable():
|
||||
formatter = lambda props, value: f"{value:.2f}m"
|
||||
formatter = lambda props, value: f"{value:.2f}m" # noqa: E731
|
||||
config = DimensionGizmoConfig(attr_name="length", axis=(1, 0, 0), text_formatter=formatter)
|
||||
assert config.text_formatter is not None
|
||||
assert callable(config.text_formatter)
|
||||
|
||||
|
||||
def test_text_formatter_receives_props_and_value():
|
||||
formatter = lambda props, value: f"{props.label}={value}"
|
||||
formatter = lambda props, value: f"{props.label}={value}" # noqa: E731
|
||||
config = DimensionGizmoConfig(attr_name="length", axis=(1, 0, 0), text_formatter=formatter)
|
||||
props = SimpleNamespace(label="L")
|
||||
assert config.text_formatter(props, 3.14) == "L=3.14"
|
||||
|
||||
@@ -104,7 +104,7 @@ class TestParametricGizmoPollsHideDuringTransformModal:
|
||||
continue
|
||||
try:
|
||||
result = poll(bpy.context)
|
||||
except Exception as exc:
|
||||
except Exception as exc: # noqa: BLE001
|
||||
offenders.append((name, f"poll raised: {type(exc).__name__}: {exc}"))
|
||||
continue
|
||||
if result:
|
||||
|
||||
@@ -98,7 +98,7 @@ class TestWallGizmoGroupsHideDuringPreview:
|
||||
continue
|
||||
try:
|
||||
result = poll(bpy.context)
|
||||
except Exception as exc:
|
||||
except Exception as exc: # noqa: BLE001
|
||||
offenders.append((name, f"poll raised: {type(exc).__name__}: {exc}"))
|
||||
continue
|
||||
if result:
|
||||
|
||||
@@ -119,7 +119,7 @@ class TestWallGizmoGroupsHideOnArrayChildSelection:
|
||||
for name, cls in groups:
|
||||
try:
|
||||
result = cls.poll(bpy.context)
|
||||
except Exception as exc:
|
||||
except Exception as exc: # noqa: BLE001
|
||||
offenders.append((name, f"poll raised: {type(exc).__name__}: {exc}"))
|
||||
continue
|
||||
if result:
|
||||
@@ -159,7 +159,7 @@ class TestWallOperatorsRejectArrayChildSelection:
|
||||
for name, cls in ops:
|
||||
try:
|
||||
result = cls.poll(bpy.context)
|
||||
except Exception as exc:
|
||||
except Exception as exc: # noqa: BLE001
|
||||
offenders.append((name, f"poll raised: {type(exc).__name__}: {exc}"))
|
||||
continue
|
||||
if result:
|
||||
|
||||
@@ -36,7 +36,6 @@ import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.representation
|
||||
import ifcopenshell.util.unit
|
||||
import numpy as np
|
||||
import pytest
|
||||
from mathutils import Vector
|
||||
@@ -1001,7 +1000,6 @@ def i_click_button_and_expect_error_error_msg(button, error_msg):
|
||||
|
||||
@given(parsers.parse('I evaluate expression "{expression}"'))
|
||||
@when(parsers.parse('I evaluate expression "{expression}"'))
|
||||
@then(parsers.parse('I evaluate expression "{expression}"'))
|
||||
def i_evaluate_expression(expression):
|
||||
expression = replace_variables(expression)
|
||||
exec(expression)
|
||||
@@ -1682,111 +1680,6 @@ def the_object_name_has_a_vertex_at_location(name, location):
|
||||
assert is_pass, f"No verts found at {location}: {verts}"
|
||||
|
||||
|
||||
def get_model_origin() -> Vector:
|
||||
"""Where the model was shifted to, in Blender units.
|
||||
|
||||
Geometry far from the origin is moved next to it so it keeps its precision,
|
||||
and the shift is recorded as the model origin. Which vert of which object it
|
||||
lands on is not something to depend on, so anything measured from it stays
|
||||
put even when that choice changes.
|
||||
"""
|
||||
props = bpy.context.scene.BIMGeoreferenceProperties
|
||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(an_ifc_file_exists())
|
||||
return Vector([float(co) for co in props.model_origin.split(",")]) * unit_scale
|
||||
|
||||
|
||||
def get_world_verts(obj: bpy.types.Object) -> list[Vector]:
|
||||
mesh = obj.data
|
||||
assert isinstance(mesh, bpy.types.Mesh) and len(mesh.vertices), f"Object {obj.name} has no mesh"
|
||||
return [obj.matrix_world @ v.co for v in mesh.vertices]
|
||||
|
||||
|
||||
def assert_vert_at_map_coordinates(obj: bpy.types.Object, vert: Vector, coordinates: str) -> None:
|
||||
# Same conversion as the georeferencing calculator, which works in project
|
||||
# units rather than Blender ones.
|
||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(an_ifc_file_exists())
|
||||
enh = Vector(tool.Georeference.xyz2enh(tuple(co / unit_scale for co in vert)))
|
||||
expected = Vector([float(co) for co in coordinates.split(",")])
|
||||
assert (enh - expected).length < 0.05, f"Vert {vert} is at map coordinates {enh[:]} instead of {coordinates}"
|
||||
|
||||
|
||||
@then(
|
||||
parsers.parse(
|
||||
'the object "{name}" is at "{location}" relative to the model origin at map coordinates "{coordinates}"'
|
||||
)
|
||||
)
|
||||
def the_object_name_is_at_location_relative_to_the_model_origin_at_map_coordinates(name, location, coordinates):
|
||||
"""For objects with no geometry to name a vert on.
|
||||
|
||||
The Blender location is only meaningful next to the origin everything was
|
||||
shifted by, since the two move together, but the map coordinates hold still
|
||||
either way.
|
||||
"""
|
||||
obj = the_object_name_exists(name)
|
||||
obj_location = obj.location + get_model_origin()
|
||||
assert (
|
||||
obj_location - Vector([float(co) for co in location.split(",")])
|
||||
).length < 0.05, f"Object is at {obj_location} relative to the model origin instead of {location}"
|
||||
assert_vert_at_map_coordinates(obj, obj.matrix_world.translation, coordinates)
|
||||
|
||||
|
||||
@then(parsers.parse('the object "{name}" has a vert at "{location}" at map coordinates "{coordinates}"'))
|
||||
def the_object_name_has_a_vert_at_location_at_map_coordinates(name, location, coordinates):
|
||||
"""Check where a vert sits in Blender and where it is in the world.
|
||||
|
||||
Both matter: the Blender location is what the user sees, and checking only
|
||||
the map coordinates would pass just as happily if the georeferencing maths
|
||||
or the offsets it reads were wrong, since the same maths produces both.
|
||||
"""
|
||||
obj = the_object_name_exists(name)
|
||||
target = Vector([float(co) for co in location.split(",")])
|
||||
verts = get_world_verts(obj)
|
||||
vert = next((v for v in verts if (v - target).length < 0.001), None)
|
||||
assert vert is not None, f"No vert found at {location}: {verts}"
|
||||
assert_vert_at_map_coordinates(obj, vert, coordinates)
|
||||
|
||||
|
||||
@then(
|
||||
parsers.parse(
|
||||
'the object "{name}" has a vert at "{location}" relative to the model origin at map coordinates "{coordinates}"'
|
||||
)
|
||||
)
|
||||
def the_object_name_has_a_vert_at_location_relative_to_the_model_origin_at_map_coordinates(name, location, coordinates):
|
||||
"""As above, for when the whole model has been shifted onto the origin.
|
||||
|
||||
Blender locations are then only meaningful relative to that origin, since
|
||||
everything moves together with it.
|
||||
"""
|
||||
obj = the_object_name_exists(name)
|
||||
target = Vector([float(co) for co in location.split(",")]) - get_model_origin()
|
||||
verts = get_world_verts(obj)
|
||||
vert = next((v for v in verts if (v - target).length < 0.001), None)
|
||||
assert vert is not None, f"No vert found at {location} relative to the model origin: {verts}"
|
||||
assert_vert_at_map_coordinates(obj, vert, coordinates)
|
||||
|
||||
|
||||
@then(parsers.parse('the object "{name}" has its origin on a vertex'))
|
||||
def the_object_name_has_its_origin_on_a_vertex(name):
|
||||
"""Far away geometry is shifted onto one of its own verts, which keeps the
|
||||
origin on the geometry and the local coordinates small enough to keep their
|
||||
precision. Which vert that is does not matter."""
|
||||
obj = the_object_name_exists(name)
|
||||
mesh = obj.data
|
||||
assert isinstance(mesh, bpy.types.Mesh) and len(mesh.vertices), f"Object {obj.name} has no mesh"
|
||||
nearest = min(v.co.length for v in mesh.vertices)
|
||||
assert nearest < 0.001, f"Object origin is {nearest} away from its nearest vert"
|
||||
|
||||
|
||||
@then("the model origin is on an object vertex")
|
||||
def the_model_origin_is_on_an_object_vertex():
|
||||
for obj in bpy.data.objects:
|
||||
if not isinstance(obj.data, bpy.types.Mesh):
|
||||
continue
|
||||
if any(v.length < 0.001 for v in get_world_verts(obj)):
|
||||
return
|
||||
assert False, "No object has a vert at the model origin"
|
||||
|
||||
|
||||
@then(parsers.parse('the object "{name}" has no scale'))
|
||||
def the_object_name_has_no_scale(name):
|
||||
assert the_object_name_exists(name).scale == Vector(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[tool.ruff]
|
||||
extend = "../pyproject.toml"
|
||||
lint.ignore = [
|
||||
"unused-import", # unused imports
|
||||
"F401", # unused imports
|
||||
]
|
||||
|
||||
@@ -168,7 +168,7 @@ ifcopenshell_deploy_qt_runtime(BonsaiViewer)
|
||||
# them explicitly. (In a static build these are absent from lib/
|
||||
# and the glob just no-ops, so this rule is safe in both modes.)
|
||||
#
|
||||
# 2. Plug-ins (ifcopenshell_*.dylib, no `lib` prefix) — dlopen-only
|
||||
# 2. Plug-ins (ifcopenshell.*.dylib, no `lib` prefix) — dlopen-only
|
||||
# deps the plug-in loader resolves at runtime. macdeployqt has
|
||||
# no way to know about these.
|
||||
#
|
||||
@@ -177,7 +177,7 @@ ifcopenshell_deploy_qt_runtime(BonsaiViewer)
|
||||
# inside the bundle), so plug-ins and core libs both find each other
|
||||
# on the first probe.
|
||||
#
|
||||
# The geometry-writer filter drops ifcopenshell_geometry_writer_*.dylib
|
||||
# The geometry-writer filter drops ifcopenshell.geometry.writer.*.dylib
|
||||
# (the per-schema OBJ / glTF / DAE / STP / IGS / SVG / TTL export
|
||||
# converters — heavy, viewer-irrelevant). Mirrors the Rocky workflow's
|
||||
# filter in `stage_runtime_payload` (see 27249770e).
|
||||
@@ -195,7 +195,7 @@ if(APPLE)
|
||||
install(CODE [[
|
||||
set(_fw "${CMAKE_INSTALL_PREFIX}/BonsaiViewer.app/Contents/Frameworks")
|
||||
file(GLOB _ifc_dylibs "${CMAKE_INSTALL_PREFIX}/lib/*.dylib")
|
||||
list(FILTER _ifc_dylibs EXCLUDE REGEX "ifcopenshell_geometry_writer_")
|
||||
list(FILTER _ifc_dylibs EXCLUDE REGEX "ifcopenshell\\.geometry\\.writer\\.")
|
||||
if(_ifc_dylibs)
|
||||
message(STATUS "Staging IfcOpenShell dylibs (linked core + plug-ins) into BonsaiViewer.app/Contents/Frameworks")
|
||||
file(COPY ${_ifc_dylibs} DESTINATION "${_fw}")
|
||||
|
||||
@@ -70,7 +70,7 @@ std::optional<BasicElementInfo> ElementRegistry::findBasicElementInfo(uint32_t o
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::optional<express::base> ElementRegistry::findEntity(uint32_t object_id) const {
|
||||
std::optional<express::Base> ElementRegistry::findEntity(uint32_t object_id) const {
|
||||
if (!loader_) return std::nullopt;
|
||||
|
||||
auto info = findBasicElementInfo(object_id);
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
void removeModel(uint32_t session_model_id);
|
||||
std::vector<BasicElementInfo> basicElementInfoForModel(uint32_t session_model_id) const;
|
||||
std::optional<BasicElementInfo> findBasicElementInfo(uint32_t object_id) const;
|
||||
std::optional<express::base> findEntity(uint32_t object_id) const;
|
||||
std::optional<express::Base> findEntity(uint32_t object_id) const;
|
||||
|
||||
private:
|
||||
void onSidecarElementsReady(uint32_t session_model_id,
|
||||
|
||||
@@ -44,7 +44,7 @@ Main components
|
||||
code.
|
||||
|
||||
``GeometryStreamer``
|
||||
Runs ``ifcopenshell::geom::iterator`` on a worker thread for raw IFC loads. It emits a
|
||||
Runs ``IfcGeom::Iterator`` on a worker thread for raw IFC loads. It emits a
|
||||
``StreamedMesh`` once for each unique representation mesh and a
|
||||
``StreamedInstance`` for each placed occurrence.
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "../../../ifcviewer/SceneLoader.h"
|
||||
#include "../../../ifcviewer/SidecarBuilder.h"
|
||||
#include "../../../ifcviewer/ViewportWindow.h"
|
||||
#include "../../../ifcgeom/serializer.h"
|
||||
#include "../../../ifcgeom/Serializer.h"
|
||||
#include "../../../serializers/document_serializer_plugin.h"
|
||||
|
||||
#include <QDebug>
|
||||
@@ -685,7 +685,7 @@ void convertIfcToDatabase(SessionState& session, QWidget& host) {
|
||||
throw ifcopenshell::exception("RDB serializer does not support streaming from an input filename");
|
||||
}
|
||||
|
||||
std::shared_ptr<ifcopenshell::geom::serializer> serializer = registry.create("rdb", context);
|
||||
boost::shared_ptr<Serializer> serializer = registry.create("rdb", context);
|
||||
serializer->finalize();
|
||||
} catch (const std::exception& e) {
|
||||
*error_message = QString::fromUtf8(e.what());
|
||||
@@ -791,7 +791,7 @@ void exportGeometryDatabase(SessionState& session, QWidget& host) {
|
||||
throw ifcopenshell::exception("RDB serializer does not support streaming from an input filename");
|
||||
}
|
||||
|
||||
std::shared_ptr<ifcopenshell::geom::serializer> serializer = registry.create("rdb", context);
|
||||
boost::shared_ptr<Serializer> serializer = registry.create("rdb", context);
|
||||
serializer->finalize();
|
||||
serializer.reset();
|
||||
|
||||
|
||||
@@ -75,16 +75,16 @@ QString formatCachedUnitScale(double meters_per_unit) {
|
||||
return QString("Cached scale: 1 unit = %1 m").arg(formatNumber(meters_per_unit));
|
||||
}
|
||||
|
||||
std::string enumString(const ifcopenshell::attribute_value& av) {
|
||||
std::string enumString(const attribute_value& av) {
|
||||
if (av.isNull()) return {};
|
||||
if (av.type() != ifcopenshell::Argument_ENUMERATION) return {};
|
||||
ifcopenshell::enumeration_reference enumeration = av;
|
||||
enumeration_reference enumeration = av;
|
||||
return std::string(enumeration.value() ? enumeration.value() : "");
|
||||
}
|
||||
|
||||
QString formatNamedUnit(const express::base& unit) {
|
||||
QString formatNamedUnit(const express::Base& unit) {
|
||||
if (!unit) return "—";
|
||||
auto entity = unit.as<express::entity>();
|
||||
auto entity = unit.as<express::Entity>();
|
||||
if (unit.declaration().is("IfcSIUnit")) {
|
||||
const std::string prefix = enumString(entity.get("Prefix"));
|
||||
const std::string name = enumString(entity.get("Name"));
|
||||
|
||||
@@ -109,7 +109,7 @@ void PropertiesPanelView::refresh(uint32_t object_id) {
|
||||
state.entity = {"No item selected", ""};
|
||||
|
||||
auto entity = registry ? registry->findEntity(object_id)
|
||||
: std::optional<express::base>{};
|
||||
: std::optional<express::Base>{};
|
||||
if (entity) {
|
||||
state.entity.entity_class = QString::fromStdString(entity->declaration().name());
|
||||
if (auto predefined_type = get_predefined_type(*entity)) {
|
||||
@@ -121,16 +121,16 @@ void PropertiesPanelView::refresh(uint32_t object_id) {
|
||||
}
|
||||
// Relationships: the construction type and the spatial container, shown
|
||||
// by name (falling back to the entity class when unnamed).
|
||||
auto display_name = [](const express::base& related) -> QString {
|
||||
auto display_name = [](const express::Base& related) -> QString {
|
||||
if (auto name = get_string_attribute(related, "Name"); name && !name->empty()) {
|
||||
return QString::fromStdString(*name);
|
||||
}
|
||||
return QString::fromStdString(related.declaration().name());
|
||||
};
|
||||
if (express::base type = get_type(*entity)) {
|
||||
if (express::Base type = get_type(*entity)) {
|
||||
state.relationships.append({"Type", display_name(type)});
|
||||
}
|
||||
if (express::base container = get_container(*entity)) {
|
||||
if (express::Base container = get_container(*entity)) {
|
||||
state.relationships.append({"Container", display_name(container)});
|
||||
}
|
||||
// Property sets (Pset_*) and quantity sets (Qto_* / BaseQuantities),
|
||||
|
||||
@@ -60,7 +60,7 @@ TreeNode* findNodeRecursive(QList<TreeNode>& nodes, const NodePath& path, int de
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ItemKind kindOf(const express::base& element) {
|
||||
ItemKind kindOf(const express::Base& element) {
|
||||
const auto& declaration = element.declaration();
|
||||
if (declaration.is("IfcSite")) return ItemKind::Site;
|
||||
if (declaration.is("IfcBuilding")) return ItemKind::Building;
|
||||
@@ -68,14 +68,14 @@ ItemKind kindOf(const express::base& element) {
|
||||
return ItemKind::Space; // IfcSpace, IfcSpatialZone, …
|
||||
}
|
||||
|
||||
QString displayName(const express::base& element) {
|
||||
QString displayName(const express::Base& element) {
|
||||
if (auto name = get_string_attribute(element, "Name"); name && !name->empty()) {
|
||||
return QString::fromStdString(*name);
|
||||
}
|
||||
return QString::fromStdString(element.declaration().name());
|
||||
}
|
||||
|
||||
TreeNode buildNode(const express::base& element) {
|
||||
TreeNode buildNode(const express::Base& element) {
|
||||
TreeNode node;
|
||||
node.name = displayName(element);
|
||||
node.kind = kindOf(element);
|
||||
|
||||
@@ -46,6 +46,6 @@ py-modules = ["bsdd","bsdd_json","type_hints"]
|
||||
|
||||
[tool.ruff]
|
||||
extend = "../../pyproject.toml"
|
||||
lint.extend-select = [
|
||||
"unused-import", # unused imports
|
||||
lint.select = [
|
||||
"F401", # unused imports
|
||||
]
|
||||
|
||||
+6
-9
@@ -3,10 +3,7 @@ IS_STABLE:=FALSE
|
||||
PYTHON:=python3
|
||||
PIP:=pip3
|
||||
VERSION:=$(shell cat ../../VERSION)
|
||||
VERSION_BASE:=$(shell sed -E 's/[[:alpha:]]+[0-9]+$$//' ../../VERSION)
|
||||
VERSION_PYTHON:=$(shell sed 's/alpha/a/' ../../VERSION)
|
||||
VERSION_DATE:=$(shell date '+%y%m%d')
|
||||
VERSION_DAILY:=$(VERSION_BASE)a$(VERSION_DATE)
|
||||
SED:=sed -i
|
||||
VENV_BIN:=bin
|
||||
|
||||
@@ -33,18 +30,18 @@ dist:
|
||||
cp pyproject.toml build/
|
||||
if [ -f README.md ]; then cp README.md build/; fi
|
||||
ifeq ($(IS_STABLE), TRUE)
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION_PYTHON)"/' build/pyproject.toml
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION)"/' build/pyproject.toml
|
||||
ifdef IS_MODULE
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION_PYTHON)"/' build/$(PACKAGE_NAME)
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION)"/' build/$(PACKAGE_NAME)
|
||||
else
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION_PYTHON)"/' build/$(PACKAGE_NAME)/__init__.py
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION)"/' build/$(PACKAGE_NAME)/__init__.py
|
||||
endif
|
||||
else
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION_DAILY)"/' build/pyproject.toml
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION)a$(VERSION_DATE)"/' build/pyproject.toml
|
||||
ifdef IS_MODULE
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION_DAILY)"/' build/$(PACKAGE_NAME)
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION)-alpha$(VERSION_DATE)"/' build/$(PACKAGE_NAME)
|
||||
else
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION_DAILY)"/' build/$(PACKAGE_NAME)/__init__.py
|
||||
$(SED) 's/version = "0.0.0"/version = "$(VERSION)-alpha$(VERSION_DATE)"/' build/$(PACKAGE_NAME)/__init__.py
|
||||
endif
|
||||
endif
|
||||
cd build && $(PYTHON) -m venv env && . env/$(VENV_ACTIVATE) && $(PIP) install build
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
#include "ifcparse/hierarchy_helper.h"
|
||||
#include "plugin/plugin.h"
|
||||
|
||||
#include "../ifcgeom/serialization/serialization.h"
|
||||
#include "../ifcgeom/Serialization/Serialization.h"
|
||||
|
||||
#if USE_VLD
|
||||
#include <vld.h>
|
||||
@@ -101,7 +101,7 @@ int main() {
|
||||
// IfcFacetedBRep. If it would not be a polyhedron, serialise() can only be successful when linked
|
||||
// to the IFC4 model and with `advanced` set to `true` which introduces IfcAdvancedFace. It would
|
||||
// return `0` otherwise.
|
||||
auto building_shape = ifcopenshell::geom::serialise(file, building_shell, false).as<IfcSchema::IfcProductDefinitionShape>();
|
||||
auto building_shape = IfcGeom::serialise(file, building_shell, false).as<IfcSchema::IfcProductDefinitionShape>();
|
||||
|
||||
file.add_entity(building_shape);
|
||||
auto building_representations = building_shape.Representations();
|
||||
@@ -117,9 +117,9 @@ int main() {
|
||||
TopoDS_Shape shape;
|
||||
createGroundShape(shape);
|
||||
|
||||
auto ground_representation = ifcopenshell::geom::serialise(file, shape, true);
|
||||
auto ground_representation = IfcGeom::serialise(file, shape, true);
|
||||
if (!ground_representation) {
|
||||
ground_representation = ifcopenshell::geom::tesselate(file, shape, 100.);
|
||||
ground_representation = IfcGeom::tesselate(file, shape, 100.);
|
||||
}
|
||||
file.getSingle<IfcSchema::IfcSite>().setRepresentation(ground_representation.as<IfcSchema::IfcProductDefinitionShape>());
|
||||
|
||||
@@ -131,13 +131,13 @@ int main() {
|
||||
setSurfaceColour(file, ground_representation.as<IfcSchema::IfcProductDefinitionShape>(), 0.15, 0.25, 0.05);
|
||||
|
||||
/*
|
||||
// Note that IFC lacks elementary surfaces that STEP does have, such as spherical_surface.
|
||||
// BRepBuilderAPI_NurbsConvert can be used to serialize such surfaces as nurbs surfaces.
|
||||
// Note that IFC lacks elementary surfaces that STEP does have, such as spherical_surface.
|
||||
// BRepBuilderAPI_NurbsConvert can be used to serialize such surfaces as nurbs surfaces.
|
||||
TopoDS_Shape sphere = BRepPrimAPI_MakeSphere(gp_Pnt(), 1000.).Shape();
|
||||
auto sphere_representation = ifcopenshell::geom::serialise(file, sphere, true);
|
||||
IfcSchema::IfcProductDefinitionShape* sphere_representation = IfcGeom::serialise(sphere, true);
|
||||
if (S(IfcSchema::Identifier) == "IFC4") {
|
||||
sphere = BRepBuilderAPI_NurbsConvert(sphere, true).Shape();
|
||||
sphere_representation = ifcopenshell::geom::serialise(file, sphere, true);
|
||||
sphere_representation = IfcGeom::serialise(sphere, true);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
#include "ifcparse/hierarchy_helper.h"
|
||||
#include "plugin/plugin.h"
|
||||
|
||||
#include "../ifcgeom/serialization/serialization.h"
|
||||
#include "../ifcgeom/Serialization/Serialization.h"
|
||||
|
||||
#if USE_VLD
|
||||
#include <vld.h>
|
||||
@@ -301,7 +301,7 @@ int main() {
|
||||
// will be tessellated using the deflection specified.
|
||||
TopoDS_Shape shape;
|
||||
createGroundShape(shape);
|
||||
auto ground_representation = ifcopenshell::geom::tesselate(file, shape, 100.).as<IfcSchema::IfcProductDefinitionShape>();
|
||||
auto ground_representation = IfcGeom::tesselate(file, shape, 100.).as<IfcSchema::IfcProductDefinitionShape>();
|
||||
file.getSingle<IfcSchema::IfcSite>().setRepresentation(ground_representation);
|
||||
|
||||
GProp_GProps prop;
|
||||
|
||||
@@ -70,10 +70,10 @@ typedef IfcSchema::IfcBuildingElement element_t;
|
||||
typedef IfcSchema::IfcBuiltElement element_t;
|
||||
#endif
|
||||
|
||||
std::string format_string(const ifcopenshell::attribute_value& argument) {
|
||||
std::string format_string(const attribute_value& argument) {
|
||||
// Argument is a runtime tagged variant for the various data types in a IFC model,
|
||||
// in this particular case we only care about flattening it to a string.
|
||||
// @todo mostly duplicated from xml_serializer.cpp
|
||||
// @todo mostly duplicated from XmlSerializer.cpp
|
||||
if (argument.isNull()) {
|
||||
return "-";
|
||||
}
|
||||
@@ -194,7 +194,7 @@ void get_psets_s(element_properties& props, const typename Schema::IfcObjectDefi
|
||||
}
|
||||
}
|
||||
|
||||
element_properties get_psets(const express::base& inst) {
|
||||
element_properties get_psets(const express::Base& inst) {
|
||||
element_properties props;
|
||||
if (auto object_definition = inst.as<IfcSchema::IfcObjectDefinition>()) {
|
||||
get_psets_s<IfcSchema>(props, object_definition);
|
||||
@@ -213,7 +213,7 @@ int main(int argc, char** argv) {
|
||||
#endif
|
||||
|
||||
// Redirect the output (both progress and log) to stdout
|
||||
ifcopenshell::logger::root().set_output(&std::cout, &std::cout);
|
||||
::logger::root().set_output(&std::cout, &std::cout);
|
||||
|
||||
// Parse the IFC file provided in argv[1]
|
||||
ifcopenshell::file file(argv[1]);
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
ISO-10303-21;
|
||||
HEADER;
|
||||
FILE_DESCRIPTION(('ViewDefinition[DesignTransferView]'),'2;1');
|
||||
FILE_NAME('IfcParseExamples_test.ifc','2025-12-12T13:49:19+05:00',(''),(''),'IfcOpenShell 0.0.0','Bonsai 0.8.5-alpha251212-a47cbc3','Nobody');
|
||||
FILE_SCHEMA(('IFC2X3'));
|
||||
ENDSEC;
|
||||
DATA;
|
||||
#1=IFCPERSON('HSeldon','Seldon','Hari',$,$,$,$,$);
|
||||
#2=IFCORGANIZATION('APTR','Aperture Science',$,$,$);
|
||||
#3=IFCPERSONANDORGANIZATION(#1,#2,$);
|
||||
#4=IFCACTORROLE(.USERDEFINED.,'CONTRIBUTOR',$);
|
||||
#5=IFCORGANIZATION('IfcOpenShell','IfcOpenShell','IfcOpenShell is an open source software library that helps users and software developers to work with IFC data.',(#4),(#6));
|
||||
#6=IFCTELECOMADDRESS(.USERDEFINED.,$,'WEBPAGE',$,$,$,$,'https://ifcopenshell.org');
|
||||
#7=IFCAPPLICATION(#5,'0.8.5','Bonsai','Bonsai-0.8.5');
|
||||
#8=IFCOWNERHISTORY(#3,#7,.READWRITE.,.ADDED.,1765520605,#3,#7,1765520605);
|
||||
#9=IFCPROJECT('3GSSvm5SP5U96O5iar8uYb',#8,'My Project',$,$,$,$,(#22,#34),#17);
|
||||
#10=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
|
||||
#11=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
|
||||
#12=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);
|
||||
#13=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);
|
||||
#14=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);
|
||||
#15=IFCMEASUREWITHUNIT(IFCREAL(0.0174532925199433),#14);
|
||||
#16=IFCCONVERSIONBASEDUNIT(#13,.PLANEANGLEUNIT.,'degree',#15);
|
||||
#17=IFCUNITASSIGNMENT((#12,#10,#16,#11));
|
||||
#18=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#19=IFCDIRECTION((0.,0.,1.));
|
||||
#20=IFCDIRECTION((1.,0.,0.));
|
||||
#21=IFCAXIS2PLACEMENT3D(#18,#19,#20);
|
||||
#22=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#21,$);
|
||||
#23=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,#22,$,.MODEL_VIEW.,$);
|
||||
#24=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Axis','Model',*,*,*,*,#22,$,.GRAPH_VIEW.,$);
|
||||
#25=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Box','Model',*,*,*,*,#22,$,.MODEL_VIEW.,$);
|
||||
#26=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Annotation','Model',*,*,*,*,#22,$,.SECTION_VIEW.,$);
|
||||
#27=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Annotation','Model',*,*,*,*,#22,$,.ELEVATION_VIEW.,$);
|
||||
#28=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Annotation','Model',*,*,*,*,#22,$,.MODEL_VIEW.,$);
|
||||
#29=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Annotation','Model',*,*,*,*,#22,$,.PLAN_VIEW.,$);
|
||||
#30=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Profile','Model',*,*,*,*,#22,$,.ELEVATION_VIEW.,$);
|
||||
#31=IFCCARTESIANPOINT((0.,0.));
|
||||
#32=IFCDIRECTION((1.,0.));
|
||||
#33=IFCAXIS2PLACEMENT2D(#31,#32);
|
||||
#34=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Plan',2,1.E-05,#33,$);
|
||||
#35=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Axis','Plan',*,*,*,*,#34,$,.GRAPH_VIEW.,$);
|
||||
#36=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Plan',*,*,*,*,#34,$,.PLAN_VIEW.,$);
|
||||
#37=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Annotation','Plan',*,*,*,*,#34,$,.PLAN_VIEW.,$);
|
||||
#38=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Annotation','Plan',*,*,*,*,#34,$,.REFLECTED_PLAN_VIEW.,$);
|
||||
#39=IFCOWNERHISTORY(#3,#7,.READWRITE.,.MODIFIED.,1765520605,#3,#7,1765520605);
|
||||
#40=IFCSITE('2Ys4j4OOf3x9UYeALDJ_g3',#39,'My Site',$,$,#66,$,$,.ELEMENT.,$,$,$,$,$);
|
||||
#46=IFCOWNERHISTORY(#3,#7,.READWRITE.,.MODIFIED.,1765520605,#3,#7,1765520605);
|
||||
#47=IFCBUILDING('3e580MQFTCD9tCSaZWRPi9',#46,'My Building',$,$,#73,$,$,.ELEMENT.,$,$,$);
|
||||
#53=IFCOWNERHISTORY(#3,#7,.READWRITE.,.MODIFIED.,1765520605,#3,#7,1765520605);
|
||||
#54=IFCBUILDINGSTOREY('3XFkAr6KbAsP5wR3gxi3my',#53,'My Storey',$,$,#80,$,$,.ELEMENT.,$);
|
||||
#60=IFCOWNERHISTORY(#3,#7,.READWRITE.,.ADDED.,1765520605,#3,#7,1765520605);
|
||||
#61=IFCRELAGGREGATES('2OWfFyDQn0qP0Vd6NWGX7k',#60,$,$,#9,(#40));
|
||||
#62=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#63=IFCDIRECTION((0.,0.,1.));
|
||||
#64=IFCDIRECTION((1.,0.,0.));
|
||||
#65=IFCAXIS2PLACEMENT3D(#62,#63,#64);
|
||||
#66=IFCLOCALPLACEMENT($,#65);
|
||||
#67=IFCOWNERHISTORY(#3,#7,.READWRITE.,.ADDED.,1765520605,#3,#7,1765520605);
|
||||
#68=IFCRELAGGREGATES('3_X_vfPpXDaO3NODBJgmSp',#67,$,$,#40,(#47));
|
||||
#69=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#70=IFCDIRECTION((0.,0.,1.));
|
||||
#71=IFCDIRECTION((1.,0.,0.));
|
||||
#72=IFCAXIS2PLACEMENT3D(#69,#70,#71);
|
||||
#73=IFCLOCALPLACEMENT(#66,#72);
|
||||
#74=IFCOWNERHISTORY(#3,#7,.READWRITE.,.ADDED.,1765520605,#3,#7,1765520605);
|
||||
#75=IFCRELAGGREGATES('3ScF98CZD3pAa0SW$mhBHF',#74,$,$,#47,(#54));
|
||||
#76=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#77=IFCDIRECTION((0.,0.,1.));
|
||||
#78=IFCDIRECTION((1.,0.,0.));
|
||||
#79=IFCAXIS2PLACEMENT3D(#76,#77,#78);
|
||||
#80=IFCLOCALPLACEMENT(#73,#79);
|
||||
#110=IFCOWNERHISTORY(#3,#7,.READWRITE.,.MODIFIED.,1765529359,#3,#7,1765520632);
|
||||
#111=IFCWALL('1lfiJzSCH1a8vjDuSLL4Ii',#110,'Cube',$,$,#203,$,$);
|
||||
#112=IFCOWNERHISTORY(#3,#7,.READWRITE.,.MODIFIED.,1765520818,#3,#7,1765520632);
|
||||
#113=IFCRELCONTAINEDINSPATIALSTRUCTURE('2Gqx6vP7jB4x_h65Tawn0f',#112,$,$,(#111,#182,#150),#54);
|
||||
#149=IFCOWNERHISTORY(#3,#7,.READWRITE.,.MODIFIED.,1765529359,#3,#7,1765520810);
|
||||
#150=IFCWINDOW('1eE0btB_54tBL59wLXKO1B',#149,'Cube',$,$,#208,$,$,$,$);
|
||||
#181=IFCOWNERHISTORY(#3,#7,.READWRITE.,.MODIFIED.,1765529359,#3,#7,1765520818);
|
||||
#182=IFCBUILDINGELEMENTPART('0fmaoBJgz0kPBavO$EJkPn',#181,'Cube',$,$,#198,$,$);
|
||||
#194=IFCCARTESIANPOINT((-3.82147288322449,-0.987768530845642,1.78445267677307));
|
||||
#195=IFCDIRECTION((0.,0.,1.));
|
||||
#196=IFCDIRECTION((1.,0.,0.));
|
||||
#197=IFCAXIS2PLACEMENT3D(#194,#195,#196);
|
||||
#198=IFCLOCALPLACEMENT(#80,#197);
|
||||
#199=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#200=IFCDIRECTION((0.,0.,1.));
|
||||
#201=IFCDIRECTION((1.,0.,0.));
|
||||
#202=IFCAXIS2PLACEMENT3D(#199,#200,#201);
|
||||
#203=IFCLOCALPLACEMENT(#80,#202);
|
||||
#204=IFCCARTESIANPOINT((0.,4.25822639465332,0.));
|
||||
#205=IFCDIRECTION((0.,0.,1.));
|
||||
#206=IFCDIRECTION((1.,0.,0.));
|
||||
#207=IFCAXIS2PLACEMENT3D(#204,#205,#206);
|
||||
#208=IFCLOCALPLACEMENT(#80,#207);
|
||||
ENDSEC;
|
||||
END-ISO-10303-21;
|
||||
@@ -0,0 +1,147 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* Example that generates various representations from *
|
||||
* IfcArbitraryOpenProfileDefs and its subclass IfcCenterLineProfileDef *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "ifcparse/macros.h"
|
||||
|
||||
#ifndef IfcSchema
|
||||
#define IfcSchema Ifc4
|
||||
#endif
|
||||
|
||||
#include INCLUDE_SCHEMA(ifcparse/schemas, IfcSchema)
|
||||
#include INCLUDE_SCHEMA_DEFINITIONS(ifcparse/schemas, IfcSchema)
|
||||
|
||||
#include "ifcparse/hierarchy_helper.h"
|
||||
|
||||
typedef std::string S;
|
||||
typedef ifcopenshell::global_id guid;
|
||||
boost::none_t const null = boost::none;
|
||||
static int i = 0;
|
||||
|
||||
void create_product_from_item(hierarchy_helper& file, IfcSchema::IfcRepresentationItem* item, const std::string& s) {
|
||||
IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
|
||||
guid(), 0, S("product"), null, null, 0, 0, null, null);
|
||||
file.addBuildingProduct(product);
|
||||
product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
|
||||
|
||||
product->setObjectPlacement(file.addLocalPlacement(0, 120 * i++));
|
||||
|
||||
IfcSchema::IfcRepresentation::list::ptr reps (new IfcSchema::IfcRepresentation::list());
|
||||
IfcSchema::IfcRepresentationItem::list::ptr items (new IfcSchema::IfcRepresentationItem::list());
|
||||
items->push(item);
|
||||
|
||||
if (s == "GeometricSet") {
|
||||
IfcSchema::IfcGeometricSet* set = new IfcSchema::IfcGeometricSet(items->generalize());
|
||||
file.add_entity(set);
|
||||
items = IfcSchema::IfcRepresentationItem::list::ptr(new IfcSchema::IfcRepresentationItem::list());
|
||||
items->push(set);
|
||||
}
|
||||
|
||||
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
|
||||
file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), s, items);
|
||||
reps->push(rep);
|
||||
|
||||
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(boost::none, boost::none, reps);
|
||||
file.add_entity(rep);
|
||||
file.add_entity(shape);
|
||||
|
||||
product->setRepresentation(shape);
|
||||
}
|
||||
|
||||
void create_surfaces_from_profile(hierarchy_helper& file, IfcSchema::IfcProfileDef* profile) {
|
||||
IfcSchema::IfcSurfaceOfLinearExtrusion* extrusion = new IfcSchema::IfcSurfaceOfLinearExtrusion(profile, file.addPlacement3d(), file.addTriplet<IfcSchema::IfcDirection>(0, 0, 1), 100.);
|
||||
file.add_entity(extrusion);
|
||||
|
||||
IfcSchema::IfcAxis1Placement* ax1 = new IfcSchema::IfcAxis1Placement(file.addTriplet<IfcSchema::IfcCartesianPoint>(0,100,0), file.addTriplet<IfcSchema::IfcDirection>(1,0,0));
|
||||
IfcSchema::IfcSurfaceOfRevolution* revolution = new IfcSchema::IfcSurfaceOfRevolution(profile, file.addPlacement3d(), ax1);
|
||||
file.add_entity(ax1);
|
||||
file.add_entity(revolution);
|
||||
|
||||
create_product_from_item(file, extrusion, "GeometricSet");
|
||||
create_product_from_item(file, revolution, "GeometricSet");
|
||||
}
|
||||
|
||||
void create_solids_from_profile(hierarchy_helper& file, IfcSchema::IfcProfileDef* profile) {
|
||||
IfcSchema::IfcExtrudedAreaSolid* extrusion = new IfcSchema::IfcExtrudedAreaSolid(profile, file.addPlacement3d(), file.addTriplet<IfcSchema::IfcDirection>(0, 0, 1), 100.);
|
||||
file.add_entity(extrusion);
|
||||
|
||||
IfcSchema::IfcAxis1Placement* ax1 = new IfcSchema::IfcAxis1Placement(file.addTriplet<IfcSchema::IfcCartesianPoint>(0,100,0), file.addTriplet<IfcSchema::IfcDirection>(1,0,0));
|
||||
IfcSchema::IfcRevolvedAreaSolid* revolution1 = new IfcSchema::IfcRevolvedAreaSolid(profile, file.addPlacement3d(), ax1, 360.);
|
||||
IfcSchema::IfcRevolvedAreaSolid* revolution2 = new IfcSchema::IfcRevolvedAreaSolid(profile, file.addPlacement3d(), ax1, 90.);
|
||||
file.add_entity(ax1);
|
||||
file.add_entity(revolution1);
|
||||
file.add_entity(revolution2);
|
||||
|
||||
create_product_from_item(file, extrusion, "SweptSolid");
|
||||
create_product_from_item(file, revolution1, "SweptSolid");
|
||||
create_product_from_item(file, revolution2, "SweptSolid");
|
||||
}
|
||||
|
||||
void create_products_from_curve(hierarchy_helper& file, IfcSchema::IfcBoundedCurve* curve) {
|
||||
IfcSchema::IfcArbitraryOpenProfileDef* open = new IfcSchema::IfcArbitraryOpenProfileDef(IfcSchema::IfcProfileTypeEnum::IfcProfileType_CURVE, null, curve);
|
||||
IfcSchema::IfcCenterLineProfileDef* center_line = new IfcSchema::IfcCenterLineProfileDef(IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, null, curve, 10.);
|
||||
file.add_entity(open);
|
||||
file.add_entity(center_line);
|
||||
|
||||
create_surfaces_from_profile(file, open);
|
||||
create_solids_from_profile(file, center_line);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
const char filename[] = "IfcArbitraryOpenProfileDef.ifc";
|
||||
hierarchy_helper file;
|
||||
file.header().file_name().name(filename);
|
||||
|
||||
double coords1[] = {-50.0, 0.0};
|
||||
double coords2[] = { 50.0, 0.0};
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points (new IfcSchema::IfcCartesianPoint::list());
|
||||
points->push(new IfcSchema::IfcCartesianPoint(std::vector<double>(coords1, coords1+2)));
|
||||
points->push(new IfcSchema::IfcCartesianPoint(std::vector<double>(coords2, coords2+2)));
|
||||
file.addEntities(points->generalize());
|
||||
IfcSchema::IfcPolyline* poly = new IfcSchema::IfcPolyline(points);
|
||||
file.add_entity(poly);
|
||||
|
||||
create_products_from_curve(file, poly);
|
||||
|
||||
IfcSchema::IfcEllipse* ellipse = new IfcSchema::IfcEllipse(file.addPlacement2d(), 50., 25.);
|
||||
file.add_entity(ellipse);
|
||||
IfcEntityList::ptr trim1(new IfcEntityList);
|
||||
IfcEntityList::ptr trim2(new IfcEntityList);
|
||||
trim1->push(new IfcSchema::IfcParameterValue( 0.));
|
||||
trim2->push(new IfcSchema::IfcParameterValue(180.));
|
||||
IfcSchema::IfcTrimmedCurve* trim = new IfcSchema::IfcTrimmedCurve(ellipse, trim1, trim2, true, IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
|
||||
file.add_entity(trim);
|
||||
|
||||
create_products_from_curve(file, trim);
|
||||
|
||||
file.getSingle<Ifc2x3::IfcProject>()->setName("IfcArbitraryOpenProfileDef");
|
||||
|
||||
std::ofstream f(filename);
|
||||
f << file;
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* Example that generates extrusions of parameterized profiles. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "ifcparse/macros.h"
|
||||
|
||||
#ifndef IfcSchema
|
||||
#define IfcSchema Ifc2x3
|
||||
#endif
|
||||
|
||||
#include INCLUDE_SCHEMA(ifcparse/schemas, IfcSchema)
|
||||
#include INCLUDE_SCHEMA_DEFINITIONS(ifcparse/schemas, IfcSchema)
|
||||
|
||||
#include "ifcparse/hierarchy_helper.h"
|
||||
|
||||
typedef std::string S;
|
||||
typedef ifcopenshell::global_id guid;
|
||||
boost::none_t const null = boost::none;
|
||||
|
||||
#ifdef SCHEMA_IfcIShapeProfileDef_HAS_FlangeEdgeRadius
|
||||
#define IFC_I_SHAPE_PROFILE_DEF_EXTRA_ARGS , null, null
|
||||
#else
|
||||
#define IFC_I_SHAPE_PROFILE_DEF_EXTRA_ARGS
|
||||
#endif
|
||||
|
||||
#ifdef SCHEMA_IfcLShapeProfileDef_HAS_CentreOfGravityInX
|
||||
#define IFC_L_SHAPE_PROFILE_DEF_EXTRA_ARGS , null, null
|
||||
#else
|
||||
#define IFC_L_SHAPE_PROFILE_DEF_EXTRA_ARGS
|
||||
#endif
|
||||
|
||||
#ifdef SCHEMA_IfcTShapeProfileDef_HAS_CentreOfGravityInY
|
||||
#define IFC_T_SHAPE_PROFILE_DEF_EXTRA_ARGS , null
|
||||
#else
|
||||
#define IFC_T_SHAPE_PROFILE_DEF_EXTRA_ARGS
|
||||
#endif
|
||||
|
||||
#ifdef SCHEMA_IfcCShapeProfileDef_HAS_CentreOfGravityInX
|
||||
#define IFC_C_SHAPE_PROFILE_DEF_EXTRA_ARGS , null
|
||||
#else
|
||||
#define IFC_C_SHAPE_PROFILE_DEF_EXTRA_ARGS
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
const char filename[] = "IfcCompositeProfileDef.ifc";
|
||||
hierarchy_helper file;
|
||||
file.header().file_name().name(filename);
|
||||
|
||||
double coords1[] = {100.0, 0.0};
|
||||
double coords2[] = {200.0, 0.0};
|
||||
double coords3[] = {300.0, 0.0};
|
||||
|
||||
IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list());
|
||||
|
||||
IfcSchema::IfcCartesianTransformationOperator2D* transform1 = new IfcSchema::IfcCartesianTransformationOperator2D(file.addDoublet<IfcSchema::IfcDirection>(1, 0), file.addDoublet<IfcSchema::IfcDirection>(0, -1), file.addDoublet<IfcSchema::IfcCartesianPoint>(40, 0), null);
|
||||
IfcSchema::IfcCartesianTransformationOperator2D* transform2 = new IfcSchema::IfcCartesianTransformationOperator2D(file.addDoublet<IfcSchema::IfcDirection>(0, -1), file.addDoublet<IfcSchema::IfcDirection>(1, 0), file.addDoublet<IfcSchema::IfcCartesianPoint>(40, 0), 0.3);
|
||||
|
||||
IfcSchema::IfcProfileDef* p1 = new IfcSchema::IfcIShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, file.addPlacement2d(), 25.0, 50.0, 5.0, 5.0, 2.0 IFC_I_SHAPE_PROFILE_DEF_EXTRA_ARGS);
|
||||
|
||||
IfcSchema::IfcProfileDef* p2 = new IfcSchema::IfcLShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, file.addPlacement2d(), 50.0, 25.0, 5.0, 1.0, 2.0, 2.0 IFC_L_SHAPE_PROFILE_DEF_EXTRA_ARGS);
|
||||
|
||||
IfcSchema::IfcProfileDef* p3 = new IfcSchema::IfcTShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, file.addPlacement2d(), 50.0, 40.0, 10.0, 10.0, 3.0, 2.0, 1.0, 2.0, 2.0 IFC_T_SHAPE_PROFILE_DEF_EXTRA_ARGS);
|
||||
|
||||
IfcSchema::IfcProfileDef* p4 = new IfcSchema::IfcCShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, file.addPlacement2d(80.), 50.0, 25.0, 5.0, 10.0, 2.0 IFC_C_SHAPE_PROFILE_DEF_EXTRA_ARGS);
|
||||
|
||||
file.add_entity(p2);
|
||||
file.add_entity(p3);
|
||||
|
||||
file.add_entity(transform1);
|
||||
file.add_entity(transform2);
|
||||
|
||||
IfcSchema::IfcDerivedProfileDef* p5 = new IfcSchema::IfcDerivedProfileDef(IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, null, p2, transform1, null);
|
||||
IfcSchema::IfcDerivedProfileDef* p6 = new IfcSchema::IfcDerivedProfileDef(IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, null, p3, transform2, null);
|
||||
|
||||
profiles->push(p1);
|
||||
profiles->push(p5);
|
||||
profiles->push(p6);
|
||||
profiles->push(p4);
|
||||
|
||||
file.addEntities(profiles->generalize());
|
||||
|
||||
IfcSchema::IfcCompositeProfileDef* composite = new IfcSchema::IfcCompositeProfileDef(IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, S("IFC"), profiles, null);
|
||||
|
||||
IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
|
||||
guid(), 0, S("profile"), null, null, 0, 0, null, null);
|
||||
|
||||
file.addBuildingProduct(product);
|
||||
|
||||
product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
|
||||
|
||||
product->setObjectPlacement(file.addLocalPlacement());
|
||||
|
||||
IfcSchema::IfcExtrudedAreaSolid* solid = new IfcSchema::IfcExtrudedAreaSolid(composite,
|
||||
file.addPlacement3d(), file.addTriplet<IfcSchema::IfcDirection>(0, 0, 1), 20.0);
|
||||
|
||||
file.add_entity(composite);
|
||||
file.add_entity(solid);
|
||||
|
||||
IfcSchema::IfcRepresentation::list::ptr reps (new IfcSchema::IfcRepresentation::list());
|
||||
IfcSchema::IfcRepresentationItem::list::ptr items (new IfcSchema::IfcRepresentationItem::list());
|
||||
|
||||
items->push(solid);
|
||||
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
|
||||
file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), S("SweptSolid"), items);
|
||||
reps->push(rep);
|
||||
|
||||
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(boost::none, boost::none, reps);
|
||||
file.add_entity(rep);
|
||||
file.add_entity(shape);
|
||||
|
||||
product->setRepresentation(shape);
|
||||
|
||||
file.getSingle<IfcSchema::IfcProject>()->setName("IfcCompositeProfileDef");
|
||||
|
||||
std::ofstream f(filename);
|
||||
f << file;
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* Example that generates a Constructive Solid Geometry example *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "ifcparse/macros.h"
|
||||
|
||||
#ifndef IfcSchema
|
||||
#define IfcSchema Ifc2x3
|
||||
#endif
|
||||
|
||||
#include INCLUDE_SCHEMA(ifcparse/schemas, IfcSchema)
|
||||
#include INCLUDE_SCHEMA_DEFINITIONS(ifcparse/schemas, IfcSchema)
|
||||
|
||||
#include "ifcparse/hierarchy_helper.h"
|
||||
|
||||
typedef std::string S;
|
||||
typedef ifcopenshell::global_id guid;
|
||||
boost::none_t const null = boost::none;
|
||||
|
||||
class Node {
|
||||
private:
|
||||
typedef enum {
|
||||
OP_ADD, OP_SUBTRACT, OP_INTERSECT, OP_TERMINAL
|
||||
} Op;
|
||||
typedef enum {
|
||||
PRIM_BOX, PRIM_CONE, PRIM_CYLINDER, PRIM_PYRAMID, PRIM_SPHERE
|
||||
} Prim;
|
||||
|
||||
double x,y,z, zx,zy,zz, xx,xy,xz, a,b,c;
|
||||
const Node *left, *right;
|
||||
|
||||
Op op;
|
||||
Prim prim;
|
||||
|
||||
Node& operate(Op op, const Node& p) {
|
||||
left = new Node(*this);
|
||||
right = new Node(p);
|
||||
this->op = op;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Node(Prim p, double la, double lb=0., double lc=0.)
|
||||
: prim(p), op(OP_TERMINAL),
|
||||
x(0.), y(0.), z(0.),
|
||||
zx(0.), zy(0.), zz(1.),
|
||||
xx(1.), xy(0.), xz(0.),
|
||||
a(la), b(lb), c(lc) {}
|
||||
public:
|
||||
static Node Sphere(double r) {
|
||||
return Node(PRIM_SPHERE, r);
|
||||
}
|
||||
static Node Box(double dx, double dy, double dz) {
|
||||
return Node(PRIM_BOX, dx, dy, dz);
|
||||
}
|
||||
static Node Pyramid(double dx, double dy, double dz) {
|
||||
return Node(PRIM_PYRAMID, dx, dy, dz);
|
||||
}
|
||||
static Node Cylinder(double r, double h) {
|
||||
return Node(PRIM_CYLINDER, r, h);
|
||||
}
|
||||
static Node Cone(double r, double h) {
|
||||
return Node(PRIM_CONE, r, h);
|
||||
}
|
||||
|
||||
Node& move(
|
||||
double px = 0., double py = 0., double pz = 0.,
|
||||
double zx = 0., double zy = 0., double zz = 1.,
|
||||
double xx = 1., double xy = 0., double xz = 0.)
|
||||
{
|
||||
this->x = px; this->y = py; this->z = pz;
|
||||
this->zx = zx; this->zy = zy; this->zz = zz;
|
||||
this->xx = xx; this->xy = xy; this->xz = xz;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Node& add(const Node& p) {
|
||||
return operate(OP_ADD, p);
|
||||
}
|
||||
Node& subtract(const Node& p) {
|
||||
return operate(OP_SUBTRACT, p);
|
||||
}
|
||||
Node& intersect(const Node& p) {
|
||||
return operate(OP_INTERSECT, p);
|
||||
}
|
||||
|
||||
IfcSchema::IfcRepresentationItem* serialize(hierarchy_helper& file) const {
|
||||
IfcSchema::IfcRepresentationItem* my;
|
||||
if (op == OP_TERMINAL) {
|
||||
IfcSchema::IfcAxis2Placement3D* place = file.addPlacement3d(x,y,z,zx,zy,zz,xx,xy,xz);
|
||||
if (prim == PRIM_SPHERE) {
|
||||
my = new IfcSchema::IfcSphere(place, a);
|
||||
} else if (prim == PRIM_BOX) {
|
||||
my = new IfcSchema::IfcBlock(place, a, b, c);
|
||||
} else if (prim == PRIM_PYRAMID) {
|
||||
my = new IfcSchema::IfcRectangularPyramid(place, a, b, c);
|
||||
} else if (prim == PRIM_CYLINDER) {
|
||||
my = new IfcSchema::IfcRightCircularCylinder(place, b, a);
|
||||
} else if (prim == PRIM_CONE) {
|
||||
my = new IfcSchema::IfcRightCircularCone(place, b, a);
|
||||
}
|
||||
} else {
|
||||
IfcSchema::IfcBooleanOperator::IfcBooleanOperator o;
|
||||
if (op == OP_ADD) {
|
||||
o = IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION;
|
||||
} else if (op == OP_SUBTRACT) {
|
||||
o = IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE;
|
||||
} else if (op == OP_INTERSECT) {
|
||||
o = IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION;
|
||||
}
|
||||
my = new IfcSchema::IfcBooleanResult(o, left->serialize(file), right->serialize(file));
|
||||
}
|
||||
file.add_entity(my);
|
||||
return my;
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
const char filename[] = "IfcCsgPrimitive.ifc";
|
||||
hierarchy_helper file;
|
||||
file.header().file_name().name(filename);
|
||||
|
||||
IfcSchema::IfcRepresentationItem* csg1 = Node::Box(8000.,6000.,3000.).subtract(
|
||||
Node::Box(7600.,5600.,2800.).move(200.,200.,200.)
|
||||
).add(
|
||||
Node::Pyramid(8000.,6000.,3000.).move(0,0,3000.).add(
|
||||
Node::Cylinder(1000.,4000.).move(4000.,1000.,4000., 0.,1.,0.)
|
||||
).subtract(
|
||||
Node::Pyramid(7600.,5600.,2800.).move(200.,200.,3000.)
|
||||
).subtract(
|
||||
Node::Cylinder(900.,4000.).move(4000.,1000.,4000., 0.,1.,0.).intersect(
|
||||
Node::Box(2000.,4000.,1000.).move(3000.,1000.,4000.)
|
||||
)
|
||||
)
|
||||
).serialize(file);
|
||||
|
||||
const double x = 1000.; const double y = -4000.;
|
||||
|
||||
IfcSchema::IfcRepresentationItem* csg2 = Node::Sphere(5000.).move(x,y,-4500.).intersect(
|
||||
Node::Box(6000., 6000., 6000.).move(x-3000., y-3000., 0.)
|
||||
).add(
|
||||
Node::Cone(500., 3000.).move(x,y).add(
|
||||
Node::Cone(1500., 1000.).move(x,y, 900.).add(
|
||||
Node::Cone(1100., 1000.).move(x,y, 1800.).add(
|
||||
Node::Cone(750., 600.).move(x,y, 2700.)
|
||||
)))).serialize(file);
|
||||
|
||||
IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
|
||||
guid(), 0, S("IfcCsgPrimitive"), null, null, 0, 0, null, null);
|
||||
|
||||
file.addBuildingProduct(product);
|
||||
|
||||
product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
|
||||
|
||||
product->setObjectPlacement(file.addLocalPlacement());
|
||||
|
||||
IfcSchema::IfcRepresentation::list::ptr reps (new IfcSchema::IfcRepresentation::list());
|
||||
IfcSchema::IfcRepresentationItem::list::ptr items (new IfcSchema::IfcRepresentationItem::list());
|
||||
|
||||
items->push(csg1);
|
||||
items->push(csg2);
|
||||
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
|
||||
file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), S("CSG"), items);
|
||||
reps->push(rep);
|
||||
|
||||
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(null, null, reps);
|
||||
file.add_entity(rep);
|
||||
file.add_entity(shape);
|
||||
|
||||
product->setRepresentation(shape);
|
||||
|
||||
file.getSingle<IfcSchema::IfcProject>()->setName("IfcCompositeProfileDef");
|
||||
|
||||
std::ofstream f(filename);
|
||||
f << file;
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* Example that generates profiles of trimmed ellipses. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "ifcparse/macros.h"
|
||||
|
||||
#ifndef IfcSchema
|
||||
#define IfcSchema Ifc2x3
|
||||
#endif
|
||||
|
||||
#include INCLUDE_SCHEMA(ifcparse/schemas, IfcSchema)
|
||||
#include INCLUDE_SCHEMA_DEFINITIONS(ifcparse/schemas, IfcSchema)
|
||||
|
||||
#include "ifcparse/hierarchy_helper.h"
|
||||
|
||||
typedef std::string S;
|
||||
typedef ifcopenshell::global_id guid;
|
||||
boost::none_t const null = boost::none;
|
||||
|
||||
#ifdef SCHEMA_HAS_IfcSegment
|
||||
typedef IfcSchema::IfcSegment curve_segment_tt;
|
||||
#else
|
||||
typedef IfcSchema::IfcCompositeCurveSegment curve_segment_tt;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
double r1;
|
||||
double r2;
|
||||
double t1;
|
||||
double t2;
|
||||
} EllipsePie;
|
||||
|
||||
static int i = 0;
|
||||
|
||||
void create_testcase_for(hierarchy_helper& file, const EllipsePie& pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference pref) {
|
||||
const double deg = 1. / 180. * 3.141592653;
|
||||
double flt1[] = {0. , 0. };
|
||||
double flt2[] = {pie.r1 * cos(pie.t1*deg), pie.r2 * sin(pie.t1*deg)};
|
||||
double flt3[] = {pie.r1 * cos(pie.t2*deg), pie.r2 * sin(pie.t2*deg)};
|
||||
|
||||
std::vector<double> coords1(flt1, flt1 + 2);
|
||||
std::vector<double> coords2(flt2, flt2 + 2);
|
||||
std::vector<double> coords3(flt3, flt3 + 2);
|
||||
|
||||
IfcSchema::IfcCartesianPoint* p1 = new IfcSchema::IfcCartesianPoint(coords1);
|
||||
IfcSchema::IfcCartesianPoint* p2 = new IfcSchema::IfcCartesianPoint(coords2);
|
||||
IfcSchema::IfcCartesianPoint* p3 = new IfcSchema::IfcCartesianPoint(coords3);
|
||||
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points(new IfcSchema::IfcCartesianPoint::list());
|
||||
points->push(p3);
|
||||
points->push(p1);
|
||||
points->push(p2);
|
||||
file.addEntities(points->generalize());
|
||||
|
||||
|
||||
IfcSchema::IfcEllipse* ellipse = new IfcSchema::IfcEllipse(file.addPlacement2d(), pie.r1, pie.r2);
|
||||
file.addEntity(ellipse);
|
||||
aggregate_of_instance::ptr trim1(new aggregate_of_instance);
|
||||
aggregate_of_instance::ptr trim2(new aggregate_of_instance);
|
||||
if (pref == IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER) {
|
||||
trim1->push(new IfcSchema::IfcParameterValue(pie.t1));
|
||||
trim2->push(new IfcSchema::IfcParameterValue(pie.t2));
|
||||
} else {
|
||||
trim1->push(p2);
|
||||
trim2->push(p3);
|
||||
}
|
||||
IfcSchema::IfcTrimmedCurve* trim = new IfcSchema::IfcTrimmedCurve(ellipse, trim1->as<IfcSchema::IfcTrimmingSelect>(), trim2->as<IfcSchema::IfcTrimmingSelect>(), true, pref);
|
||||
file.addEntity(trim);
|
||||
|
||||
curve_segment_tt::list::ptr segments(new curve_segment_tt::list());
|
||||
IfcSchema::IfcCompositeCurveSegment* s2 = new IfcSchema::IfcCompositeCurveSegment(IfcSchema::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, trim);
|
||||
|
||||
IfcSchema::IfcPolyline* poly = new IfcSchema::IfcPolyline(points);
|
||||
file.addEntity(poly);
|
||||
IfcSchema::IfcCompositeCurveSegment* s1 = new IfcSchema::IfcCompositeCurveSegment(IfcSchema::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, poly);
|
||||
segments->push(s1);
|
||||
|
||||
segments->push(s2);
|
||||
file.addEntities(segments->generalize());
|
||||
|
||||
IfcSchema::IfcCompositeCurve* ccurve = new IfcSchema::IfcCompositeCurve(segments, false);
|
||||
IfcSchema::IfcArbitraryClosedProfileDef* profile = new IfcSchema::IfcArbitraryClosedProfileDef(IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, null, ccurve);
|
||||
file.addEntity(ccurve);
|
||||
file.addEntity(profile);
|
||||
|
||||
IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
|
||||
guid(), 0, S("profile"), null, null, 0, 0, null, null);
|
||||
file.addBuildingProduct(product);
|
||||
product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
|
||||
|
||||
product->setObjectPlacement(file.addLocalPlacement(0, 200 * i++));
|
||||
|
||||
IfcSchema::IfcExtrudedAreaSolid* solid = new IfcSchema::IfcExtrudedAreaSolid(profile,
|
||||
file.addPlacement3d(), file.addTriplet<IfcSchema::IfcDirection>(0, 0, 1), 20.0);
|
||||
|
||||
file.add_entity(solid);
|
||||
|
||||
IfcSchema::IfcRepresentation::list::ptr reps (new IfcSchema::IfcRepresentation::list());
|
||||
IfcSchema::IfcRepresentationItem::list::ptr items (new IfcSchema::IfcRepresentationItem::list());
|
||||
|
||||
items->push(solid);
|
||||
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
|
||||
file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), S("SweptSolid"), items);
|
||||
reps->push(rep);
|
||||
|
||||
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(boost::none, boost::none, reps);
|
||||
file.add_entity(rep);
|
||||
file.add_entity(shape);
|
||||
|
||||
product->setRepresentation(shape);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
const std::string filename = "ellipse_pies.ifc";
|
||||
hierarchy_helper file;
|
||||
{ EllipsePie pie = {80., 50., 0., 150.};
|
||||
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
|
||||
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
|
||||
{ EllipsePie pie = {80, 50., 30., 300.};
|
||||
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
|
||||
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
|
||||
{ EllipsePie pie = {80, 50., 300., 30.};
|
||||
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
|
||||
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
|
||||
{ EllipsePie pie = {50., 80., 0., 150.};
|
||||
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
|
||||
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
|
||||
{ EllipsePie pie = {50, 80., 30., 300.};
|
||||
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
|
||||
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
|
||||
{ EllipsePie pie = {50, 80., 300., 30.};
|
||||
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
|
||||
create_testcase_for(file, pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);}
|
||||
std::ofstream f(filename.c_str());
|
||||
f << file;
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* Example that generates various forms of IfcFace *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "ifcparse/macros.h"
|
||||
|
||||
#ifndef IfcSchema
|
||||
#define IfcSchema Ifc2x3
|
||||
#endif
|
||||
|
||||
#include INCLUDE_SCHEMA(ifcparse/schemas, IfcSchema)
|
||||
#include INCLUDE_SCHEMA_DEFINITIONS(ifcparse/schemas, IfcSchema)
|
||||
|
||||
#include "ifcparse/hierarchy_helper.h"
|
||||
|
||||
typedef std::string S;
|
||||
typedef ifcopenshell::global_id guid;
|
||||
boost::none_t const null = (static_cast<boost::none_t>(0));
|
||||
|
||||
static int x = 0;
|
||||
|
||||
void create_testcase(hierarchy_helper& file, IfcSchema::IfcFace* face, const std::string& name) {
|
||||
IfcSchema::IfcFace::list::ptr faces(new IfcSchema::IfcFace::list);
|
||||
faces->push(face);
|
||||
IfcSchema::IfcOpenShell* shell = new IfcSchema::IfcOpenShell(faces);
|
||||
|
||||
IfcSchema::IfcConnectedFaceSet::list::ptr shells(new IfcSchema::IfcConnectedFaceSet::list);
|
||||
shells->push(shell);
|
||||
IfcSchema::IfcFaceBasedSurfaceModel* model = new IfcSchema::IfcFaceBasedSurfaceModel(shells);
|
||||
|
||||
IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
|
||||
guid(), 0, name, null, null, 0, 0, null, null);
|
||||
file.addBuildingProduct(product);
|
||||
product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
|
||||
|
||||
product->setObjectPlacement(file.addLocalPlacement(0, 1000 * x++, 0));
|
||||
|
||||
IfcSchema::IfcRepresentation::list::ptr reps (new IfcSchema::IfcRepresentation::list);
|
||||
IfcSchema::IfcRepresentationItem::list::ptr items (new IfcSchema::IfcRepresentationItem::list);
|
||||
|
||||
items->push(model);
|
||||
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
|
||||
file.getRepresentationContext("Model"), S("Body"), S("SurfaceModel"), items);
|
||||
reps->push(rep);
|
||||
|
||||
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
|
||||
file.add_entity(shape);
|
||||
|
||||
product->setRepresentation(shape);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
hierarchy_helper file;
|
||||
{
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points (new IfcSchema::IfcCartesianPoint::list);
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, -400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, -400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, +400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, +400, 0));
|
||||
IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
|
||||
IfcSchema::IfcFaceOuterBound* bound = new IfcSchema::IfcFaceOuterBound(loop, true);
|
||||
|
||||
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
|
||||
bounds->push(bound);
|
||||
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
|
||||
create_testcase(file, face, "polyloop");
|
||||
}
|
||||
{
|
||||
IfcSchema::IfcCartesianPoint* point1 = file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, 0., 0.);
|
||||
IfcSchema::IfcCartesianPoint* point2 = file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, 0., 0.);
|
||||
IfcSchema::IfcVertexPoint* vertex1 = new IfcSchema::IfcVertexPoint(point1);
|
||||
IfcSchema::IfcVertexPoint* vertex2 = new IfcSchema::IfcVertexPoint(point2);
|
||||
IfcSchema::IfcCircle* circle = new IfcSchema::IfcCircle(file.addPlacement2d(), 400.);
|
||||
IfcSchema::IfcEdgeCurve* edge1 = new IfcSchema::IfcEdgeCurve(vertex1, vertex2, circle, true);
|
||||
IfcSchema::IfcEdgeCurve* edge2 = new IfcSchema::IfcEdgeCurve(vertex2, vertex1, circle, true);
|
||||
IfcSchema::IfcOrientedEdge* oriented_edge1 = new IfcSchema::IfcOrientedEdge(edge1, true);
|
||||
IfcSchema::IfcOrientedEdge* oriented_edge2 = new IfcSchema::IfcOrientedEdge(edge2, true);
|
||||
IfcSchema::IfcOrientedEdge::list::ptr edges(new IfcSchema::IfcOrientedEdge::list);
|
||||
edges->push(oriented_edge1);
|
||||
edges->push(oriented_edge2);
|
||||
IfcSchema::IfcEdgeLoop* loop = new IfcSchema::IfcEdgeLoop(edges);
|
||||
IfcSchema::IfcFaceOuterBound* bound = new IfcSchema::IfcFaceOuterBound(loop, true);
|
||||
|
||||
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
|
||||
bounds->push(bound);
|
||||
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
|
||||
create_testcase(file, face, "circle");
|
||||
}
|
||||
{
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points (new IfcSchema::IfcCartesianPoint::list);
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, -400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, -400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, +400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, +400, 0));
|
||||
IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
|
||||
IfcSchema::IfcFaceOuterBound* outer_bound = new IfcSchema::IfcFaceOuterBound(loop, true);
|
||||
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points2 (new IfcSchema::IfcCartesianPoint::list);
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-300, -300, 0));
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-100, -300, 0));
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-100, +300, 0));
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-300, +300, 0));
|
||||
IfcSchema::IfcPolyLoop* loop2 = new IfcSchema::IfcPolyLoop(points2);
|
||||
IfcSchema::IfcFaceBound* inner_bound1 = new IfcSchema::IfcFaceBound(loop2, false);
|
||||
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points3 (new IfcSchema::IfcCartesianPoint::list);
|
||||
points3->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+100, +300, 0));
|
||||
points3->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+300, +300, 0));
|
||||
points3->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+300, -300, 0));
|
||||
points3->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+100, -300, 0));
|
||||
IfcSchema::IfcPolyLoop* loop3 = new IfcSchema::IfcPolyLoop(points3);
|
||||
IfcSchema::IfcFaceBound* inner_bound2 = new IfcSchema::IfcFaceBound(loop3, true);
|
||||
|
||||
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
|
||||
bounds->push(inner_bound1);
|
||||
bounds->push(outer_bound);
|
||||
bounds->push(inner_bound2);
|
||||
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
|
||||
create_testcase(file, face, "polyloop with holes");
|
||||
}
|
||||
{
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points (new IfcSchema::IfcCartesianPoint::list);
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, -400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-100, -400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-100, +400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, +400, 0));
|
||||
IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
|
||||
IfcSchema::IfcFaceOuterBound* bound1 = new IfcSchema::IfcFaceOuterBound(loop, true);
|
||||
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points2 (new IfcSchema::IfcCartesianPoint::list);
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+100, +400, 0));
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, +400, 0));
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, -400, 0));
|
||||
points2->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+100, -400, 0));
|
||||
IfcSchema::IfcPolyLoop* loop2 = new IfcSchema::IfcPolyLoop(points2);
|
||||
IfcSchema::IfcFaceOuterBound* bound2 = new IfcSchema::IfcFaceOuterBound(loop2, false);
|
||||
|
||||
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
|
||||
bounds->push(bound1);
|
||||
bounds->push(bound2);
|
||||
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
|
||||
create_testcase(file, face, "multiple outer boundaries (invalid)");
|
||||
}
|
||||
{
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points (new IfcSchema::IfcCartesianPoint::list);
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, -400, 1e-6));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, -400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, +400, 0));
|
||||
points->push(file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, +400, 0));
|
||||
IfcSchema::IfcPolyLoop* loop = new IfcSchema::IfcPolyLoop(points);
|
||||
IfcSchema::IfcFaceOuterBound* bound = new IfcSchema::IfcFaceOuterBound(loop, true);
|
||||
|
||||
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
|
||||
bounds->push(bound);
|
||||
IfcSchema::IfcFace* face = new IfcSchema::IfcFace(bounds);
|
||||
create_testcase(file, face, "imprecise polyloop");
|
||||
}
|
||||
{
|
||||
IfcSchema::IfcCartesianPoint* point1 = file.addTriplet<IfcSchema::IfcCartesianPoint>(+400, 0., 0.);
|
||||
IfcSchema::IfcCartesianPoint* point2 = file.addTriplet<IfcSchema::IfcCartesianPoint>(-400, 0., 0.);
|
||||
IfcSchema::IfcVertexPoint* vertex1 = new IfcSchema::IfcVertexPoint(point1);
|
||||
IfcSchema::IfcVertexPoint* vertex2 = new IfcSchema::IfcVertexPoint(point2);
|
||||
IfcSchema::IfcCircle* circle = new IfcSchema::IfcCircle(file.addPlacement2d(), 400.);
|
||||
IfcSchema::IfcEdgeCurve* edge1 = new IfcSchema::IfcEdgeCurve(vertex1, vertex2, circle, true);
|
||||
IfcSchema::IfcEdgeCurve* edge2 = new IfcSchema::IfcEdgeCurve(vertex2, vertex1, circle, true);
|
||||
IfcSchema::IfcOrientedEdge* oriented_edge1 = new IfcSchema::IfcOrientedEdge(edge1, true);
|
||||
IfcSchema::IfcOrientedEdge* oriented_edge2 = new IfcSchema::IfcOrientedEdge(edge2, true);
|
||||
IfcSchema::IfcOrientedEdge::list::ptr edges(new IfcSchema::IfcOrientedEdge::list);
|
||||
edges->push(oriented_edge1);
|
||||
edges->push(oriented_edge2);
|
||||
IfcSchema::IfcEdgeLoop* loop = new IfcSchema::IfcEdgeLoop(edges);
|
||||
IfcSchema::IfcFaceOuterBound* bound = new IfcSchema::IfcFaceOuterBound(loop, true);
|
||||
|
||||
IfcSchema::IfcFaceBound::list::ptr bounds (new IfcSchema::IfcFaceBound::list);
|
||||
bounds->push(bound);
|
||||
|
||||
IfcSchema::IfcCartesianPoint::list::ptr trim1(new IfcSchema::IfcCartesianPoint::list);
|
||||
IfcSchema::IfcCartesianPoint::list::ptr trim2(new IfcSchema::IfcCartesianPoint::list);
|
||||
trim1->push(point1);
|
||||
trim2->push(point2);
|
||||
IfcSchema::IfcTrimmedCurve* trimmed_curve = new IfcSchema::IfcTrimmedCurve(circle, trim1->generalize(), trim2->generalize(), true, IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_CARTESIAN);
|
||||
IfcSchema::IfcArbitraryOpenProfileDef* profile = new IfcSchema::IfcArbitraryOpenProfileDef(IfcSchema::IfcProfileTypeEnum::IfcProfileType_CURVE, boost::none, trimmed_curve);
|
||||
IfcSchema::IfcAxis1Placement* place = new IfcSchema::IfcAxis1Placement(file.addTriplet<IfcSchema::IfcCartesianPoint>(0., 0., 0.), file.addTriplet<IfcSchema::IfcDirection>(1., 0., 0.));
|
||||
IfcSchema::IfcSurfaceOfRevolution* surface = new IfcSchema::IfcSurfaceOfRevolution(profile, file.addPlacement3d(), place);
|
||||
|
||||
IfcSchema::IfcFace* face = new IfcSchema::IfcFaceSurface(bounds, surface, true);
|
||||
create_testcase(file, face, "face surface");
|
||||
}
|
||||
const std::string filename = "faces.ifc";
|
||||
file.header().file_name().name(filename);
|
||||
std::ofstream f(filename.c_str());
|
||||
f << file;
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* Example of curve rebar. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
#include "ifcparse/macros.h"
|
||||
|
||||
#ifndef IfcSchema
|
||||
#define IfcSchema Ifc2x3
|
||||
#endif
|
||||
|
||||
#include INCLUDE_SCHEMA(ifcparse/schemas, IfcSchema)
|
||||
#include INCLUDE_SCHEMA_DEFINITIONS(ifcparse/schemas, IfcSchema)
|
||||
|
||||
#include "ifcparse/hierarchy_helper.h"
|
||||
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
const static double PI = boost::math::constants::pi<double>();
|
||||
|
||||
typedef std::string S;
|
||||
typedef ifcopenshell::global_id guid;
|
||||
boost::none_t const null = boost::none;
|
||||
|
||||
#ifdef SCHEMA_HAS_IfcSegment
|
||||
typedef IfcSchema::IfcSegment curve_segment_t;
|
||||
#else
|
||||
typedef IfcSchema::IfcCompositeCurveSegment curve_segment_t;
|
||||
#endif
|
||||
|
||||
#ifdef SCHEMA_IfcReinforcingBar_HAS_PredefinedType
|
||||
#define IFC_REINFORCING_BAR_TYPE IfcSchema::IfcReinforcingBarTypeEnum::IfcReinforcingBarType_LIGATURE
|
||||
#else
|
||||
#define IFC_REINFORCING_BAR_TYPE IfcSchema::IfcReinforcingBarRoleEnum::IfcReinforcingBarRole_LIGATURE
|
||||
#endif
|
||||
|
||||
void create_curve_rebar(hierarchy_helper<IfcSchema>& file)
|
||||
{
|
||||
int dia = 24;
|
||||
int R = 3 * dia;
|
||||
int length = 12 * dia;
|
||||
|
||||
double crossSectionarea = M_PI * (dia / 2) * 2;
|
||||
IfcSchema::IfcReinforcingBar* rebar = new IfcSchema::IfcReinforcingBar(
|
||||
guid(), 0, S("test"), null,
|
||||
null, 0, 0,
|
||||
null, S("SR24"), //SteelGrade
|
||||
dia, //diameter
|
||||
crossSectionarea, //crossSectionarea = math.pi*(12.0/2)**2
|
||||
0,
|
||||
IFC_REINFORCING_BAR_TYPE,
|
||||
IfcSchema::IfcReinforcingBarSurfaceEnum::IfcReinforcingBarSurfaceEnum::IfcReinforcingBarSurface_PLAIN //PLAIN or TEXTURED
|
||||
);
|
||||
|
||||
file.addBuildingProduct(rebar);
|
||||
rebar->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
|
||||
|
||||
curve_segment_t::list::ptr segments(new curve_segment_t::list());
|
||||
|
||||
IfcSchema::IfcCartesianPoint* p1 = file.addTriplet<IfcSchema::IfcCartesianPoint>(0, 0, 1000.);
|
||||
IfcSchema::IfcCartesianPoint* p2 = file.addTriplet<IfcSchema::IfcCartesianPoint>(0, 0, 0);
|
||||
IfcSchema::IfcCartesianPoint* p3 = file.addTriplet<IfcSchema::IfcCartesianPoint>(0, R, 0);
|
||||
IfcSchema::IfcCartesianPoint* p4 = file.addTriplet<IfcSchema::IfcCartesianPoint>(0, R, -R);
|
||||
IfcSchema::IfcCartesianPoint* p5 = file.addTriplet<IfcSchema::IfcCartesianPoint>(0, R + length, -R);
|
||||
|
||||
/*first segment - line */
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points1(new IfcSchema::IfcCartesianPoint::list());
|
||||
points1->push(p1);
|
||||
points1->push(p2);
|
||||
file.addEntities(points1->generalize());
|
||||
IfcSchema::IfcPolyline* poly1 = new IfcSchema::IfcPolyline(points1);
|
||||
file.add_entity(poly1);
|
||||
|
||||
IfcSchema::IfcCompositeCurveSegment* segment1 = new IfcSchema::IfcCompositeCurveSegment(IfcSchema::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, poly1);
|
||||
file.add_entity(segment1);
|
||||
segments->push(segment1);
|
||||
|
||||
/*second segment - arc */
|
||||
IfcSchema::IfcAxis2Placement3D* axis1 = new IfcSchema::IfcAxis2Placement3D(p3, file.addTriplet<IfcSchema::IfcDirection>(1, 0, 0), file.addTriplet<IfcSchema::IfcDirection>(0, 1, 0));
|
||||
file.add_entity(axis1);
|
||||
IfcSchema::IfcCircle* circle = new IfcSchema::IfcCircle(axis1, R);
|
||||
file.add_entity(circle);
|
||||
|
||||
IfcEntityList::ptr trim1(new IfcEntityList);
|
||||
IfcEntityList::ptr trim2(new IfcEntityList);
|
||||
|
||||
trim1->push(new IfcSchema::IfcParameterValue(180));
|
||||
trim1->push(p2);
|
||||
|
||||
trim2->push(new IfcSchema::IfcParameterValue(270));
|
||||
trim2->push(p4);
|
||||
IfcSchema::IfcTrimmedCurve* trimmed_curve = new IfcSchema::IfcTrimmedCurve(circle, trim1, trim2, false, IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
|
||||
file.add_entity(trimmed_curve);
|
||||
|
||||
IfcSchema::IfcCompositeCurveSegment* segment2 = new IfcSchema::IfcCompositeCurveSegment(IfcSchema::IfcTransitionCode::IfcTransitionCode_CONTSAMEGRADIENT, false, trimmed_curve);
|
||||
file.add_entity(segment2);
|
||||
segments->push(segment2);
|
||||
|
||||
/*third segment - line */
|
||||
IfcSchema::IfcCartesianPoint::list::ptr points2(new IfcSchema::IfcCartesianPoint::list());
|
||||
points2->push(p4);
|
||||
points2->push(p5);
|
||||
file.addEntities(points2->generalize());
|
||||
IfcSchema::IfcPolyline* poly2 = new IfcSchema::IfcPolyline(points2);
|
||||
file.add_entity(poly2);
|
||||
|
||||
IfcSchema::IfcCompositeCurveSegment* segment3 = new IfcSchema::IfcCompositeCurveSegment(IfcSchema::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, poly2);
|
||||
file.add_entity(segment3);
|
||||
segments->push(segment3);
|
||||
|
||||
IfcSchema::IfcCompositeCurve* curve = new IfcSchema::IfcCompositeCurve(segments, false);
|
||||
file.add_entity(curve);
|
||||
|
||||
IfcSchema::IfcSweptDiskSolid* solid = new IfcSchema::IfcSweptDiskSolid(curve, dia / 2, null, 0, 1);
|
||||
|
||||
IfcSchema::IfcRepresentation::list::ptr reps(new IfcSchema::IfcRepresentation::list());
|
||||
IfcSchema::IfcRepresentationItem::list::ptr items(new IfcSchema::IfcRepresentationItem::list());
|
||||
items->push(solid);
|
||||
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
|
||||
file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), S("AdvancedSweptSolid"), items);
|
||||
reps->push(rep);
|
||||
|
||||
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(null, null, reps);
|
||||
file.add_entity(shape);
|
||||
|
||||
rebar->setRepresentation(shape);
|
||||
|
||||
IfcSchema::IfcObjectPlacement* storey_placement = file.getSingle<IfcSchema::IfcBuildingStorey>()->ObjectPlacement();
|
||||
rebar->setObjectPlacement(file.addLocalPlacement(storey_placement, 0, 0, 0));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
hierarchy_helper file;
|
||||
file.header().file_name().name("ifc_curve_rebar.ifc");
|
||||
create_curve_rebar(file);
|
||||
std::ofstream f("ifc_curve_rebar.ifc");
|
||||
f << file;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* Example that generates extrusions of parameterized profiles. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "ifcparse/macros.h"
|
||||
|
||||
#ifndef IfcSchema
|
||||
#define IfcSchema Ifc2x3
|
||||
#endif
|
||||
|
||||
#include INCLUDE_SCHEMA(ifcparse/schemas, IfcSchema)
|
||||
#include INCLUDE_SCHEMA_DEFINITIONS(ifcparse/schemas, IfcSchema)
|
||||
|
||||
#include "ifcparse/hierarchy_helper.h"
|
||||
|
||||
typedef std::string S;
|
||||
typedef IfcWrite::IfcGuidHelper guid;
|
||||
boost::none_t const null = (static_cast<boost::none_t>(0));
|
||||
|
||||
#ifdef SCHEMA_IfcUShapeProfileDef_HAS_CentreOfGravityInX
|
||||
#define IFC_U_SHAPE_PROFILE_DEF_EXTRA_ARGS , null
|
||||
#else
|
||||
#define IFC_U_SHAPE_PROFILE_DEF_EXTRA_ARGS
|
||||
#endif
|
||||
|
||||
#ifdef SCHEMA_IfcTShapeProfileDef_HAS_CentreOfGravityInY
|
||||
#define IFC_T_SHAPE_PROFILE_DEF_EXTRA_ARGS , null
|
||||
#else
|
||||
#define IFC_T_SHAPE_PROFILE_DEF_EXTRA_ARGS
|
||||
#endif
|
||||
|
||||
#ifdef SCHEMA_IfcIShapeProfileDef_HAS_FlangeEdgeRadius
|
||||
#define IFC_I_SHAPE_PROFILE_DEF_EXTRA_ARGS , null, null
|
||||
#else
|
||||
#define IFC_I_SHAPE_PROFILE_DEF_EXTRA_ARGS
|
||||
#endif
|
||||
|
||||
#ifdef SCHEMA_IfcAsymmetricIShapeProfileDef_HAS_BottomFlangeSlope
|
||||
#define IFC_ASYMMETRIC_I_SHAPE_PROFILE_DEF_EXTRA_ARGS , null, null, null
|
||||
#else
|
||||
#define IFC_ASYMMETRIC_I_SHAPE_PROFILE_DEF_EXTRA_ARGS
|
||||
#endif
|
||||
|
||||
#ifdef SCHEMA_IfcLShapeProfileDef_HAS_CentreOfGravityInX
|
||||
#define IFC_L_SHAPE_PROFILE_DEF_EXTRA_ARGS , null, null
|
||||
#else
|
||||
#define IFC_L_SHAPE_PROFILE_DEF_EXTRA_ARGS
|
||||
#endif
|
||||
|
||||
#ifdef SCHEMA_IfcCShapeProfileDef_HAS_CentreOfGravityInX
|
||||
#define IFC_C_SHAPE_PROFILE_DEF_EXTRA_ARGS , null
|
||||
#else
|
||||
#define IFC_C_SHAPE_PROFILE_DEF_EXTRA_ARGS
|
||||
#endif
|
||||
|
||||
void create_testcase_for(IfcSchema::IfcProfileDef::list::ptr profiles) {
|
||||
IfcSchema::IfcProfileDef* profile = *profiles->begin();
|
||||
const std::string profile_type = IfcSchema::Type::ToString(profile->type());
|
||||
const std::string filename = profile_type + ".ifc";
|
||||
|
||||
hierarchy_helper file;
|
||||
file.filename(filename);
|
||||
|
||||
int i = 0;
|
||||
for (IfcSchema::IfcProfileDef::list::it it = profiles->begin(); it != profiles->end(); ++it, ++i) {
|
||||
IfcSchema::IfcProfileDef* profile = *it;
|
||||
IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
|
||||
guid(), 0, S("profile"), null, null, 0, 0, null, null);
|
||||
file.addBuildingProduct(product);
|
||||
file.getSingle<IfcSchema::IfcProject>()->setName(profile_type);
|
||||
product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
|
||||
|
||||
product->setObjectPlacement(file.addLocalPlacement(0, 100. * i));
|
||||
|
||||
if (profile->is(IfcSchema::Type::IfcParameterizedProfileDef)) {
|
||||
((IfcSchema::IfcParameterizedProfileDef*) profile)->setPosition(file.addPlacement2d());
|
||||
}
|
||||
|
||||
IfcSchema::IfcExtrudedAreaSolid* solid = new IfcSchema::IfcExtrudedAreaSolid(profile,
|
||||
file.addPlacement3d(), file.addTriplet<IfcSchema::IfcDirection>(0, 0, 1), 20.0);
|
||||
|
||||
file.add_entity(profile);
|
||||
file.add_entity(solid);
|
||||
|
||||
IfcSchema::IfcRepresentation::list::ptr reps (new IfcSchema::IfcRepresentation::list);
|
||||
IfcSchema::IfcRepresentationItem::list::ptr items (new IfcSchema::IfcRepresentationItem::list);
|
||||
|
||||
items->push(solid);
|
||||
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
|
||||
file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), S("SweptSolid"), items);
|
||||
reps->push(rep);
|
||||
|
||||
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
|
||||
file.add_entity(rep);
|
||||
file.add_entity(shape);
|
||||
|
||||
product->setRepresentation(shape);
|
||||
}
|
||||
|
||||
std::ofstream f(filename.c_str());
|
||||
f << file;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
|
||||
profiles->push(new Ifc2x3::IfcUShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, 5.0, null, null, null IFC_U_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
profiles->push(new IfcSchema::IfcUShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, 5.0, 2.0, 2.0, null IFC_U_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
profiles->push(new IfcSchema::IfcUShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, 5.0, null, null, 4.0 IFC_U_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
profiles->push(new IfcSchema::IfcUShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, 5.0, 1.0, 3.0, 6.0 IFC_U_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
create_testcase_for(profiles); }
|
||||
|
||||
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
|
||||
profiles->push(new Ifc2x3::IfcTShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, 5.0, null, null, null, null, null IFC_T_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
profiles->push(new IfcSchema::IfcTShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, 5.0, 2.0, 2.0, 2.0, null, null IFC_T_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
profiles->push(new IfcSchema::IfcTShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, 5.0, null, null, null, 2.0, 2.0 IFC_T_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
profiles->push(new IfcSchema::IfcTShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, 5.0, 3.0, 2.0, 1.0, 2.0, 2.0 IFC_T_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
create_testcase_for(profiles); }
|
||||
|
||||
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
|
||||
profiles->push(new Ifc2x3::IfcZShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, 5.0, null, null));
|
||||
profiles->push(new Ifc2x3::IfcZShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, 5.0, 2.0, 2.0));
|
||||
create_testcase_for(profiles); }
|
||||
|
||||
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
|
||||
profiles->push(new Ifc2x3::IfcEllipseProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 25.0, 15.0));
|
||||
profiles->push(new Ifc2x3::IfcEllipseProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 15.0, 25.0));
|
||||
create_testcase_for(profiles); }
|
||||
|
||||
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
|
||||
profiles->push(new IfcSchema::IfcIShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 25.0, 50.0, 5.0, 5.0, null IFC_I_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
profiles->push(new IfcSchema::IfcIShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 25.0, 50.0, 5.0, 5.0, 2.0 IFC_I_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
profiles->push(new IfcSchema::IfcAsymmetricIShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 25.0, 50.0, 5.0, 5.0, 2.0, 20.0, 10.0, 5.0, null IFC_ASYMMETRIC_I_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
create_testcase_for(profiles); }
|
||||
|
||||
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
|
||||
profiles->push(new Ifc2x3::IfcLShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, null, null, null IFC_L_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
profiles->push(new IfcSchema::IfcLShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, 2.0, 2.0, null IFC_L_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
profiles->push(new IfcSchema::IfcLShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, null, null, 2.0 IFC_L_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
profiles->push(new IfcSchema::IfcLShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, 1.0, 2.0, 2.0 IFC_L_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
create_testcase_for(profiles); }
|
||||
|
||||
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
|
||||
profiles->push(new Ifc2x3::IfcCShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, 10.0, null IFC_C_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
profiles->push(new IfcSchema::IfcCShapeProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, 10.0, 2.0 IFC_C_SHAPE_PROFILE_DEF_EXTRA_ARGS));
|
||||
create_testcase_for(profiles); }
|
||||
|
||||
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
|
||||
profiles->push(new Ifc2x3::IfcCircleProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 25.0));
|
||||
profiles->push(new Ifc2x3::IfcCircleHollowProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 25.0, 5.0));
|
||||
create_testcase_for(profiles); }
|
||||
|
||||
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
|
||||
profiles->push(new Ifc2x3::IfcRectangleProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0));
|
||||
profiles->push(new Ifc2x3::IfcRoundedRectangleProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0));
|
||||
profiles->push(new Ifc2x3::IfcRectangleHollowProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, null, null));
|
||||
profiles->push(new Ifc2x3::IfcRectangleHollowProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 25.0, 5.0, 2.0, 4.0));
|
||||
create_testcase_for(profiles); }
|
||||
|
||||
{ IfcSchema::IfcProfileDef::list::ptr profiles (new IfcSchema::IfcProfileDef::list);
|
||||
profiles->push(new Ifc2x3::IfcTrapeziumProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 30.0, 25.0, 0.0));
|
||||
profiles->push(new Ifc2x3::IfcTrapeziumProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 60.0, 25.0, -20.0));
|
||||
profiles->push(new Ifc2x3::IfcTrapeziumProfileDef(
|
||||
IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
|
||||
null, 0, 50.0, 10.0, 25.0, 30.0));
|
||||
create_testcase_for(profiles); }
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,96 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* Example that generates an IfcTriangulatedFaceSet *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
|
||||
#include "ifcparse/macros.h"
|
||||
|
||||
#ifndef IfcSchema
|
||||
#define IfcSchema Ifc4
|
||||
#endif
|
||||
|
||||
#include INCLUDE_SCHEMA(ifcparse/schemas, IfcSchema)
|
||||
#include INCLUDE_SCHEMA_DEFINITIONS(ifcparse/schemas, IfcSchema)
|
||||
|
||||
#include "ifcparse/hierarchy_helper.h"
|
||||
|
||||
#include "suzanne_geometry.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
typedef std::string S;
|
||||
typedef ifcopenshell::global_id guid;
|
||||
|
||||
template <typename T>
|
||||
std::vector< std::vector<T> > create_vector_from_array(const T* arr, unsigned size) {
|
||||
std::vector< std::vector<T> > result;
|
||||
result.reserve(size);
|
||||
|
||||
for (unsigned i = 0; i < size; ) {
|
||||
std::vector<T> ts; ts.reserve(3);
|
||||
for (unsigned j = 0; j < 3; ++i, ++j) {
|
||||
ts.push_back(arr[i]);
|
||||
}
|
||||
result.push_back(ts);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
hierarchy_helper<Ifc4> file;
|
||||
|
||||
Ifc4::IfcBuildingElementProxy product = file.create<Ifc4::IfcBuildingElementProxy>().initialize(
|
||||
guid(), std::nullopt, S("Blender's Suzanne"), std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt);
|
||||
file.addBuildingProduct(product);
|
||||
product.setOwnerHistory(file.getSingle<Ifc4::IfcOwnerHistory>());
|
||||
|
||||
product.setObjectPlacement(file.addLocalPlacement());
|
||||
|
||||
std::vector< std::vector< double > > vertices_vector = create_vector_from_array(vertices, sizeof(vertices) / sizeof(vertices[0]));
|
||||
std::vector< std::vector< int > > indices_vector = create_vector_from_array(indices, sizeof(indices) / sizeof(indices[0]));
|
||||
|
||||
IfcSchema::IfcCartesianPointList3D* coordinates = new IfcSchema::IfcCartesianPointList3D(vertices_vector
|
||||
#ifdef SCHEMA_IfcCartesianPointList3D_HAS_TagList
|
||||
, boost::none
|
||||
#endif
|
||||
);
|
||||
IfcSchema::IfcTriangulatedFaceSet* faceset = new IfcSchema::IfcTriangulatedFaceSet(coordinates, null, null, indices_vector, null);
|
||||
|
||||
Ifc4::IfcShapeRepresentation rep = file.create<Ifc4::IfcShapeRepresentation>().initialize(
|
||||
file.getRepresentationContext("Model"), "Body", "SurfaceModel", {faceset});
|
||||
|
||||
Ifc4::IfcProductDefinitionShape shape = file.create<Ifc4::IfcProductDefinitionShape>().initialize(std::nullopt, std::nullopt, {rep});
|
||||
file.add_entity(shape);
|
||||
|
||||
product.setRepresentation(shape);
|
||||
|
||||
const std::string filename = "tesselated_faceset.ifc";
|
||||
file.header().file_name().setname(filename);
|
||||
std::ofstream f(filename.c_str());
|
||||
f << file;
|
||||
}
|
||||
@@ -206,7 +206,7 @@ class context:
|
||||
|
||||
Args:
|
||||
file (ifcopenshell.file): file containing elem
|
||||
elem (triangulation_element): triangulated geometry
|
||||
elem (TriangulationElement): triangulated geometry
|
||||
min_thickness (float, optional): minimal thickness of the oriented bounding box to create around elem
|
||||
|
||||
Returns:
|
||||
@@ -889,7 +889,7 @@ class context:
|
||||
def write_obj(ofn, *, elem=None, item=None):
|
||||
s = ifcopenshell.geom.settings(USE_WORLD_COORDS=True, WELD_VERTICES=False)
|
||||
if item:
|
||||
geom = item.triangulate(s)
|
||||
geom = item.Triangulate(s)
|
||||
else:
|
||||
geom = elem.geometry
|
||||
|
||||
|
||||
@@ -36,34 +36,8 @@ message("Running CMakeLists.txt in /src/helpers")
|
||||
|
||||
find_package(Eigen3 REQUIRED)
|
||||
|
||||
# helpers_math: the schema-free subset — unit conversion tables and Helmert
|
||||
# matrix math over plain numbers. No IfcParse, no Qt, no schema dispatch, so it
|
||||
# builds under Emscripten where the rest of this directory cannot.
|
||||
#
|
||||
# It exists as its own target rather than being compiled into both `helpers` and
|
||||
# IfcViewerCore so the objects are built exactly once and both libraries agree
|
||||
# on them. IfcViewerCore links it directly (see src/ifcviewer/CMakeLists.txt);
|
||||
# `helpers` re-exports it PUBLIC below so existing consumers keep working
|
||||
# through the unchanged unit.h / geolocation.h includes.
|
||||
set(HELPER_MATH_CPP_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/unit_convert.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/geolocation_transform.cpp
|
||||
)
|
||||
add_library(helpers_math STATIC ${HELPER_MATH_CPP_FILES})
|
||||
target_include_directories(helpers_math PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(helpers_math PUBLIC Eigen3::Eigen)
|
||||
set_target_properties(helpers_math PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
install(TARGETS helpers_math EXPORT ${IFCOPENSHELL_EXPORT_TARGETS})
|
||||
|
||||
# The rest of this directory needs IfcParse and the generated schema bindings,
|
||||
# so it is desktop-only.
|
||||
if(EMSCRIPTEN)
|
||||
return()
|
||||
endif()
|
||||
|
||||
file(GLOB HELPER_CPP_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
|
||||
file(GLOB HELPER_H_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
|
||||
list(REMOVE_ITEM HELPER_CPP_FILES ${HELPER_MATH_CPP_FILES})
|
||||
|
||||
add_library(helpers STATIC ${HELPER_CPP_FILES} ${HELPER_H_FILES})
|
||||
|
||||
@@ -90,7 +64,6 @@ target_include_directories(helpers PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(helpers PUBLIC
|
||||
IfcParse
|
||||
Eigen3::Eigen
|
||||
helpers_math
|
||||
PRIVATE
|
||||
${HELPER_SCHEMA_LIBRARIES}
|
||||
)
|
||||
|
||||
+19
-19
@@ -41,7 +41,7 @@ struct is_ifc4_or_higher : std::false_type {};
|
||||
template <typename Schema>
|
||||
struct is_ifc4_or_higher<Schema, std::void_t<typename Schema::IfcMaterialDefinition>> : std::true_type {};
|
||||
|
||||
std::string schema_name(const express::base& instance) {
|
||||
std::string schema_name(const express::Base& instance) {
|
||||
return instance.declaration().schema()->name();
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ std::string schema_name(const express::base& instance) {
|
||||
// A primitive scalar attribute value formatted for display, or std::nullopt for
|
||||
// IFC null and for non-primitive values (entity references, aggregates/lists,
|
||||
// binary) — which the properties UI omits.
|
||||
std::optional<std::string> format_scalar(const ifcopenshell::attribute_value& value) {
|
||||
std::optional<std::string> format_scalar(const attribute_value& value) {
|
||||
if (value.isNull()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ std::optional<std::string> format_scalar(const ifcopenshell::attribute_value& va
|
||||
case ifcopenshell::Argument_STRING:
|
||||
return static_cast<std::string>(value);
|
||||
case ifcopenshell::Argument_ENUMERATION: {
|
||||
const ifcopenshell::enumeration_reference enumeration = value;
|
||||
const enumeration_reference enumeration = value;
|
||||
return enumeration.value() ? std::string(enumeration.value()) : std::string();
|
||||
}
|
||||
case ifcopenshell::Argument_INT:
|
||||
@@ -87,7 +87,7 @@ std::optional<std::string> format_scalar(const ifcopenshell::attribute_value& va
|
||||
// ifcopenshell.util.element.get_type: the construction type of an occurrence
|
||||
// (get_type(type_element) == type_element).
|
||||
template <typename Schema>
|
||||
express::base get_type_s(const express::base& element) {
|
||||
express::Base get_type_s(const express::Base& element) {
|
||||
if (element.template as<typename Schema::IfcTypeObject>()) {
|
||||
return element;
|
||||
}
|
||||
@@ -111,9 +111,9 @@ express::base get_type_s(const express::base& element) {
|
||||
}
|
||||
|
||||
template <typename Schema>
|
||||
std::optional<std::string> get_predefined_type_s(const express::base& element) {
|
||||
std::optional<std::string> get_predefined_type_s(const express::Base& element) {
|
||||
// Prefer the associated type element's predefined type.
|
||||
if (const express::base type = get_type_s<Schema>(element)) {
|
||||
if (const express::Base type = get_type_s<Schema>(element)) {
|
||||
std::optional<std::string> predefined_type = get_string_attribute(type, "PredefinedType");
|
||||
if (!predefined_type || *predefined_type == "USERDEFINED") {
|
||||
// ElementType (IfcElementType) or ProcessType (IfcTypeProcess) — the
|
||||
@@ -140,7 +140,7 @@ std::optional<std::string> get_predefined_type_s(const express::base& element) {
|
||||
// ifcopenshell.util.element.get_aggregate: the aggregate parent, via the
|
||||
// Decomposes inverse (IfcRelAggregates.RelatingObject).
|
||||
template <typename Schema>
|
||||
express::base get_aggregate_s(const express::base& element) {
|
||||
express::Base get_aggregate_s(const express::Base& element) {
|
||||
const auto object = element.template as<typename Schema::IfcObjectDefinition>();
|
||||
if (!object) {
|
||||
return {};
|
||||
@@ -162,8 +162,8 @@ express::base get_aggregate_s(const express::base& element) {
|
||||
// The spatial-structure children aggregated under this element (IsDecomposedBy →
|
||||
// RelatedObjects, filtered to spatial elements).
|
||||
template <typename Schema>
|
||||
std::vector<express::base> get_spatial_children_s(const express::base& element) {
|
||||
std::vector<express::base> children;
|
||||
std::vector<express::Base> get_spatial_children_s(const express::Base& element) {
|
||||
std::vector<express::Base> children;
|
||||
const auto object = element.template as<typename Schema::IfcObjectDefinition>();
|
||||
if (!object) {
|
||||
return children;
|
||||
@@ -182,14 +182,14 @@ std::vector<express::base> get_spatial_children_s(const express::base& element)
|
||||
// ifc_class): the directly containing spatial element, or the container of the
|
||||
// aggregate parent for an aggregated part.
|
||||
template <typename Schema>
|
||||
express::base get_container_s(const express::base& element) {
|
||||
express::Base get_container_s(const express::Base& element) {
|
||||
if (const auto product = element.template as<typename Schema::IfcElement>()) {
|
||||
const auto relationships = product.ContainedInStructure();
|
||||
if (!relationships.empty()) {
|
||||
return relationships.front().RelatingStructure();
|
||||
}
|
||||
}
|
||||
if (const express::base aggregate = get_aggregate_s<Schema>(element)) {
|
||||
if (const express::Base aggregate = get_aggregate_s<Schema>(element)) {
|
||||
return get_container_s<Schema>(aggregate);
|
||||
}
|
||||
return {};
|
||||
@@ -197,7 +197,7 @@ express::base get_container_s(const express::base& element) {
|
||||
|
||||
} // namespace
|
||||
|
||||
std::optional<std::string> get_predefined_type(const express::base& element) {
|
||||
std::optional<std::string> get_predefined_type(const express::Base& element) {
|
||||
if (!element) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -211,7 +211,7 @@ std::optional<std::string> get_predefined_type(const express::base& element) {
|
||||
unsupported_schema(name);
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> get_scalar_attributes(const express::base& element) {
|
||||
std::vector<std::pair<std::string, std::string>> get_scalar_attributes(const express::Base& element) {
|
||||
std::vector<std::pair<std::string, std::string>> result;
|
||||
if (!element) {
|
||||
return result;
|
||||
@@ -230,7 +230,7 @@ std::vector<std::pair<std::string, std::string>> get_scalar_attributes(const exp
|
||||
return result;
|
||||
}
|
||||
|
||||
express::base get_type(const express::base& element) {
|
||||
express::Base get_type(const express::Base& element) {
|
||||
if (!element) {
|
||||
return {};
|
||||
}
|
||||
@@ -244,7 +244,7 @@ express::base get_type(const express::base& element) {
|
||||
unsupported_schema(name);
|
||||
}
|
||||
|
||||
express::base get_container(const express::base& element) {
|
||||
express::Base get_container(const express::Base& element) {
|
||||
if (!element) {
|
||||
return {};
|
||||
}
|
||||
@@ -258,7 +258,7 @@ express::base get_container(const express::base& element) {
|
||||
unsupported_schema(name);
|
||||
}
|
||||
|
||||
std::vector<express::base> get_spatial_children(const express::base& element) {
|
||||
std::vector<express::Base> get_spatial_children(const express::Base& element) {
|
||||
if (!element) {
|
||||
return {};
|
||||
}
|
||||
@@ -275,7 +275,7 @@ std::vector<express::base> get_spatial_children(const express::base& element) {
|
||||
// getattr(element, name) for a string- or enum-valued attribute. Reads by name,
|
||||
// so it works uniformly across the various subtypes that carry a given
|
||||
// attribute (PredefinedType, Name, ...).
|
||||
std::optional<std::string> get_string_attribute(const express::base& element,
|
||||
std::optional<std::string> get_string_attribute(const express::Base& element,
|
||||
const std::string& name) {
|
||||
if (!element) {
|
||||
return std::nullopt;
|
||||
@@ -288,13 +288,13 @@ std::optional<std::string> get_string_attribute(const express::base& element,
|
||||
if (index < 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
const ifcopenshell::attribute_value value = element.get_attribute_value(static_cast<std::size_t>(index));
|
||||
const attribute_value value = element.get_attribute_value(static_cast<std::size_t>(index));
|
||||
if (value.isNull()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
switch (value.type()) {
|
||||
case ifcopenshell::Argument_ENUMERATION: {
|
||||
const ifcopenshell::enumeration_reference enumeration = value;
|
||||
const enumeration_reference enumeration = value;
|
||||
return enumeration.value() ? std::string(enumeration.value()) : std::string();
|
||||
}
|
||||
case ifcopenshell::Argument_STRING:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user