mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-07 16:31:37 +00:00
Compare commits
76 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ba00526e1b | |||
| e744ba404e | |||
| eb39eeb30b | |||
| 286e9d183a | |||
| d4e4ca3a2a | |||
| f7adeb9cc1 | |||
| 607f7bd015 | |||
| bd00d3287e | |||
| f674493843 | |||
| dbc60bedd6 | |||
| f7f949b37b | |||
| 31ca1ac1b5 | |||
| 99d83fce42 | |||
| 4158424c25 | |||
| 1d8616883c | |||
| 8851641d94 | |||
| 0a7b1dd7f4 | |||
| bb2a983a00 | |||
| 604358b48e | |||
| 68e60f0586 | |||
| e4f141b107 | |||
| fe172672e9 | |||
| 69a27e3591 | |||
| d91e5d31f6 | |||
| a4c3fdfd18 | |||
| b235320d8c | |||
| e9a3464c26 | |||
| e08db74706 | |||
| 3a971d63f8 | |||
| 9a75a1f12d | |||
| 64f88cbf25 | |||
| ca66aac1c1 | |||
| 9262ea1890 | |||
| 81537bee95 | |||
| f9e94f5e01 | |||
| 691e5766c4 | |||
| 0770d91a3c | |||
| f3531276c8 | |||
| ffe1eddb00 | |||
| ba0ba1973a | |||
| b4e1b15da5 | |||
| a2b2add58f | |||
| c70517f3ba | |||
| d79e28157f | |||
| 4a36816f8f | |||
| 83ac741b59 | |||
| 2fb4be2edc | |||
| 868bd6efc8 | |||
| 27e18386d2 | |||
| 562210b862 | |||
| 39b3e03fc5 | |||
| ba7eec2c0b | |||
| 357357ad78 | |||
| b3bf86e697 | |||
| 6b65402611 | |||
| c7355f03e7 | |||
| 5274d73fd0 | |||
| 88f6242804 | |||
| e936ba8391 | |||
| 9136b83223 | |||
| 4987753a47 | |||
| 871ee13e05 | |||
| 9c4040345a | |||
| aa4f6c0a7b | |||
| 5471f345d8 | |||
| 9679d450fc | |||
| d8d221dce3 | |||
| ed5f879b9f | |||
| 3bc3331983 | |||
| 10657416ea | |||
| e5abdb7de8 | |||
| 7b57c8b5b3 | |||
| 22563f7283 | |||
| d35e775407 | |||
| a5684f0996 | |||
| 509c34d66a |
@@ -1,8 +0,0 @@
|
||||
c14f5eeca042232025797990396232e4feab53e7
|
||||
d6881e833da0b6278313870d37d42ca6ece8686a
|
||||
892be5444c5bd01a601c99243ac8d3e7b2f0e779
|
||||
d169a964dd7e9ab5c98b35a82bcbc76dc6229a7a
|
||||
4a6ec11f6f84a3d1fed2ee9b2f85d783ac3daa9d
|
||||
2c9d6a47f4d24a923069775206bf734feeb14830
|
||||
8f1743ed64a2a52c201a1ef5e312b4d3a7a922cf
|
||||
ad7f030344c405e10cfa7d5cf06d82c121eeb825
|
||||
@@ -1,4 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [aothms]
|
||||
open_collective: opensourcebim
|
||||
@@ -1,116 +0,0 @@
|
||||
name: CD
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
|
||||
jobs:
|
||||
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell' &&
|
||||
!startsWith(github.event.head_commit.message, 'Release ') &&
|
||||
!contains(github.event.head_commit.message, 'ci skip')
|
||||
steps:
|
||||
- run: echo ok go
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: activate
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt-get install --no-install-recommends \
|
||||
git cmake gcc g++ libboost-all-dev python3-all-dev swig libpcre3-dev libxml2-dev \
|
||||
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
|
||||
libhdf5-dev libcgal-dev
|
||||
|
||||
-
|
||||
name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
|
||||
-
|
||||
name: Build ifcopenshell
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_INSTALL_PREFIX=$PWD/install/ \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_PREFIX_PATH=/usr \
|
||||
-DCMAKE_SYSTEM_PREFIX_PATH=/usr \
|
||||
-DBUILD_PACKAGE=On \
|
||||
-DOCC_INCLUDE_DIR=/usr/include/opencascade \
|
||||
-DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 \
|
||||
-DPYTHON_INCLUDE_DIR:PATH=/usr/include/python3.8 \
|
||||
-DPYTHON_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpython3.8.so \
|
||||
-DCOLLADA_SUPPORT=Off \
|
||||
-DLIBXML2_INCLUDE_DIR=/usr/include/libxml2 \
|
||||
-DLIBXML2_LIBRARIES=/usr/lib/x86_64-linux-gnu/libxml2.so \
|
||||
-DCGAL_INCLUDE_DIR=/usr/include \
|
||||
-DGMP_INCLUDE_DIR=/usr/include \
|
||||
-DMPFR_INCLUDE_DIR=/usr/include \
|
||||
-DGMP_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DMPFR_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DHDF5_INCLUDE_DIR=/usr/include/hdf5/serial \
|
||||
../cmake
|
||||
make -j $(nproc)
|
||||
make install
|
||||
-
|
||||
name: Package
|
||||
run: |
|
||||
make package
|
||||
working-directory: build
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
# Artifact name
|
||||
name: ifcos-artifacts
|
||||
# Directory containing files to upload
|
||||
path: build/assets/Ifc*
|
||||
|
||||
deliver:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: build
|
||||
name: Docker Build, Tag, Push
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
lfs: true
|
||||
|
||||
- name: Download
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
# Artifact name
|
||||
name: ifcos-artifacts
|
||||
path: artifacts/
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
-
|
||||
name: Login to Dockerhub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: aecgeeks
|
||||
password: ${{ secrets.DOCKER_HUB_TOKEN }}
|
||||
-
|
||||
name: Build container image
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: artifacts
|
||||
repository: aecgeeks/ifcopenshell
|
||||
tags: aecgeeks/ifcopenshell:latest
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
@@ -1,37 +0,0 @@
|
||||
name: ci-bcf
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell' &&
|
||||
contains(github.event.head_commit.message, '[bcf release]')
|
||||
steps:
|
||||
- run: echo ok go
|
||||
upload:
|
||||
needs: activate
|
||||
name: Upload BCF package to Pypi
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.10'
|
||||
- name: Build package
|
||||
run: |
|
||||
cd src/bcf
|
||||
pip install build
|
||||
python -m build
|
||||
- name: Test
|
||||
run: |
|
||||
cd src/bcf
|
||||
make test
|
||||
- name: Publish package
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_TOKEN }}
|
||||
packages_dir: src/bcf/dist
|
||||
@@ -1,92 +0,0 @@
|
||||
name: Publish-blenderbim-chocolatey package
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# ┌───────────── minute (0 - 59)
|
||||
# │ ┌───────────── hour (0 - 23)
|
||||
# │ │ ┌───────────── day of the month (1 - 31)
|
||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
||||
# * * * * *
|
||||
- cron: "30 0 * * *" # 30min past utc midnight
|
||||
|
||||
env:
|
||||
major: 0
|
||||
minor: 0
|
||||
name: blenderbim
|
||||
choco_version: 1.1.0
|
||||
CHOCO_TOKEN: ${{ secrets.CHOCO_TOKEN }}
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
steps:
|
||||
- name: Set env
|
||||
run: echo ok go
|
||||
|
||||
build:
|
||||
needs: activate
|
||||
name: ${{ matrix.config.name }}-${{ matrix.pyver }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pyver: [py310]
|
||||
config:
|
||||
- {
|
||||
name: "Windows Build",
|
||||
short_name: win,
|
||||
}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
with:
|
||||
python-version: '3.10.9' # Version range or exact version of a Python version to use, using SemVer's version range syntax
|
||||
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
|
||||
- run: echo ${{ env.DATE }}
|
||||
|
||||
- name: Check in published releases if we should do a choco release
|
||||
id: do_choco
|
||||
run: |
|
||||
echo "::set-output name=choco_release::$(python3 /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/check_repo_infos.py --do_choco_release?)"
|
||||
|
||||
- name: Fill chocolatey scripts on win with latest blender python
|
||||
if: ${{steps.do_choco.outputs.choco_release}} == 'do_choco_release'
|
||||
run: |
|
||||
yesterday_non_iso="$(date --date='yesterday' +'%y%m%d' | tr -d '\n')" &&
|
||||
target_os=${{ matrix.config.short_name }} &&
|
||||
latest_blender_python_version_maj_min=$(python3 /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/check_repo_infos.py --latest_blender_python_version_maj_min?) &&
|
||||
echo "latest_blender_python_version_maj_min?: $latest_blender_python_version_maj_min" &&
|
||||
pyver=$(python3 /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/check_repo_infos.py --pyver?) &&
|
||||
export latest_blender_version_maj_min=$(python3 /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/check_repo_infos.py --latest_blender_release_maj_min?) &&
|
||||
export latest_blender_version_maj_min_pat=$(python3 /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/check_repo_infos.py --latest_blender_release_maj_min_pat?) &&
|
||||
echo latest_blender_version_maj_min_pat?: $latest_blender_version_maj_min_pat &&
|
||||
export blenderbim_build_version="${{ env.major }}.${{ env.minor }}.$yesterday_non_iso" &&
|
||||
export url_blenderbim_py310_win_zip="https://github.com/IfcOpenShell/IfcOpenShell/releases/download/blenderbim-$yesterday_non_iso/blenderbim-$yesterday_non_iso-$pyver-$target_os.zip" &&
|
||||
wget $url_blenderbim_py310_win_zip --no-verbose &&
|
||||
export sha256sum_blenderbim_py310_win_zip=$( sha256sum blenderbim-$yesterday_non_iso-$pyver-$target_os.zip --tag | cut -d ' ' -f 4 | tr -d '\n') &&
|
||||
echo sha256sum_blenderbim_py310_win_zip: $sha256sum_blenderbim_py310_win_zip &&
|
||||
python3 choco/blenderbim/fill_dynamic_parameters.py &&
|
||||
echo __build choco with mono &&
|
||||
wget "https://github.com/chocolatey/choco/archive/refs/tags/$choco_version.tar.gz" --quiet &&
|
||||
tar -xzf "$choco_version.tar.gz" &&
|
||||
cd choco-$choco_version &&
|
||||
chmod +x build.sh zip.sh &&
|
||||
./build.sh &&
|
||||
cp -r build_output/chocolatey /opt/chocolatey &&
|
||||
cd /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/ &&
|
||||
echo __choco pack &&
|
||||
mono /opt/chocolatey/choco.exe --version &&
|
||||
mono /opt/chocolatey/choco.exe pack --allow-unofficial &&
|
||||
echo __choco set apiKey &&
|
||||
mono /opt/chocolatey/choco.exe setapikey --key="$CHOCO_TOKEN" --source="https://push.chocolatey.org/" --allow-unofficial # &&
|
||||
echo __choco push &&
|
||||
mono /opt/chocolatey/choco.exe push --source="https://push.chocolatey.org/" --key="$CHOCO_TOKEN" --allow-unofficial --verbose
|
||||
|
||||
- name: Inform user about not packaging
|
||||
if: ${{steps.do_choco.outputs.choco_release}} != 'do_choco_release'
|
||||
run: |
|
||||
echo "no releases found today ${{ env.DATE }}, therefore choco packaging is skipped."
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
name: Publish-blenderbim-multiplatform
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '.github/workflows/ci-blenderbim-matrix.yml'
|
||||
- 'src/blenderbim/**'
|
||||
- 'src/ifcopenshell-python/ifcopenshell/**'
|
||||
- 'src/bcf/src/bcf/**'
|
||||
- 'src/ifcclash/ifcclash/**'
|
||||
- 'src/ifccobie/**'
|
||||
- 'src/ifcdiff/**'
|
||||
- 'src/ifccsv/**'
|
||||
- 'src/ifcpatch/ifcpatch/**'
|
||||
- 'src/ifc4d/ifc4d/**'
|
||||
- 'src/ifc5d/ifc5d/**'
|
||||
- 'src/ifccityjson/**'
|
||||
branches:
|
||||
- v0.7.0
|
||||
|
||||
env:
|
||||
major: 0
|
||||
minor: 0
|
||||
name: blenderbim
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
steps:
|
||||
- name: Set env
|
||||
run: echo ok go
|
||||
|
||||
build:
|
||||
needs: activate
|
||||
name: ${{ matrix.config.name }}-${{ matrix.pyver }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pyver: [py37, py39, py310]
|
||||
config:
|
||||
- {
|
||||
name: "Windows Build",
|
||||
short_name: win,
|
||||
}
|
||||
- {
|
||||
name: "Linux Build",
|
||||
short_name: linux
|
||||
}
|
||||
- {
|
||||
name: "MacOS Build",
|
||||
short_name: macos
|
||||
}
|
||||
- {
|
||||
name: "MacOS ARM Build",
|
||||
short_name: macosm1
|
||||
}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
with:
|
||||
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
|
||||
- run: echo ${{ env.DATE }}
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "::set-output name=date::$(date +'%y%m%d')"
|
||||
- name: Compile
|
||||
run: |
|
||||
cp -r src/blenderbim src/blenderbim_${{ matrix.config.short_name }}_${{ matrix.pyver }} &&
|
||||
cd src/blenderbim_${{ matrix.config.short_name }}_${{ matrix.pyver }} &&
|
||||
make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }}
|
||||
- name: Upload Zip file to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: src/blenderbim_${{ matrix.config.short_name }}_${{ matrix.pyver }}/dist/blenderbim-${{steps.date.outputs.date}}-${{ matrix.pyver }}-${{ matrix.config.short_name }}.zip
|
||||
asset_name: blenderbim-${{steps.date.outputs.date}}-${{ matrix.pyver }}-${{ matrix.config.short_name }}.zip
|
||||
tag: "blenderbim-${{steps.date.outputs.date}}"
|
||||
overwrite: true
|
||||
body: "Daily developer testing build blenderbim-${{steps.date.outputs.date}}"
|
||||
@@ -1,65 +0,0 @@
|
||||
name: ci-ifcopenshell-conda-daily
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["ci"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
steps:
|
||||
- name: Set env
|
||||
run: echo ok go
|
||||
|
||||
test:
|
||||
name: ${{ matrix.platform.distver }}-${{ matrix.pyver.name }}
|
||||
needs: activate
|
||||
runs-on: ${{ matrix.platform.distver }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash -l {0}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pyver: [
|
||||
# { name: py39, distver: '3.9' },
|
||||
{ name: py310, distver: '3.10'},
|
||||
{ name: py311, distver: '3.11'}
|
||||
]
|
||||
platform: [
|
||||
{ name: Windows, distver: windows-2022, upload: 'false' },
|
||||
{ name: Windows, distver: windows-2019, upload: 'true' },
|
||||
{ name: Linux, distver: ubuntu-20.04, upload: 'true' },
|
||||
{ name: Linux, distver: ubuntu-22.04, upload: 'false' },
|
||||
{ name: macOS, distver: macos-11, upload: 'true' },
|
||||
{ name: macOS, distver: macos-12, upload: 'false' }
|
||||
]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Download MacOSX SDK
|
||||
if: ${{ matrix.platform.name == 'macOS' }}
|
||||
run: |
|
||||
curl -o MacOSX10.13.sdk.tar.xz -L https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX10.13.sdk.tar.xz && \
|
||||
tar xf MacOSX10.13.sdk.tar.xz && \
|
||||
sudo mv -v MacOSX10.13.sdk /opt/ && \
|
||||
ls /opt/
|
||||
- uses: seanmiddleditch/gha-setup-ninja@master
|
||||
- uses: conda-incubator/setup-miniconda@v2 # https://github.com/conda-incubator/setup-miniconda
|
||||
with:
|
||||
activate-environment: conda-build
|
||||
python-version: ${{ matrix.pyver.distver }}
|
||||
environment-file: conda/environment.yml
|
||||
- name: build, test and upload ifcopenshell
|
||||
if: ${{ matrix.platform.upload == 'true' }}
|
||||
run: |
|
||||
conda-build . --python ${{ matrix.pyver.distver }} -c conda-forge --token ${{ secrets.ANACONDA_TOKEN }} --user ifcopenshell --no-remove-work-dir
|
||||
- name: build & test ifcopenshell
|
||||
if: ${{ matrix.platform.upload == 'false' }}
|
||||
run: |
|
||||
conda-build . --python ${{ matrix.pyver.distver }} -c conda-forge --no-remove-work-dir
|
||||
@@ -1,73 +0,0 @@
|
||||
name: ci-ifcopenshell-pypi
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# ┌───────────── minute (0 - 59)
|
||||
# │ ┌───────────── hour (0 - 23)
|
||||
# │ │ ┌───────────── day of the month (1 - 31)
|
||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
||||
# * * * * *
|
||||
- cron: "49 23 1 * *" # 11min before utc midnight
|
||||
|
||||
env:
|
||||
major: 0
|
||||
minor: 0
|
||||
name: ifcopenshell
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
steps:
|
||||
- name: Set env
|
||||
run: echo ok go
|
||||
|
||||
build:
|
||||
needs: activate
|
||||
name: ${{ matrix.config.name }}-${{ matrix.pyver }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pyver: [py36, py37, py38, py39, py310]
|
||||
config:
|
||||
- {
|
||||
name: "Windows Build",
|
||||
short_name: win,
|
||||
}
|
||||
- {
|
||||
name: "Linux Build",
|
||||
short_name: linux
|
||||
}
|
||||
- {
|
||||
name: "MacOS Build",
|
||||
short_name: macos
|
||||
}
|
||||
- {
|
||||
name: "MacOS ARM Build",
|
||||
short_name: macosm1
|
||||
}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
with:
|
||||
python-version: '3.7.7' # Version range or exact version of a Python version to use, using SemVer's version range syntax
|
||||
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
|
||||
- run: echo ${{ env.DATE }}
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "::set-output name=date::$(date +'%y%m%d')"
|
||||
- name: Compile
|
||||
run: |
|
||||
pip install build
|
||||
cp -r src/ifcopenshell-python src/ifcopenshell_${{ matrix.config.short_name }}_${{ matrix.pyver }} &&
|
||||
cd src/ifcopenshell_${{ matrix.config.short_name }}_${{ matrix.pyver }} &&
|
||||
make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }}
|
||||
- name: Publish a Python distribution to PyPI
|
||||
uses: ortega2247/pypi-upload-action@master
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
packages_dir: src/ifcopenshell_${{ matrix.config.short_name }}_${{ matrix.pyver }}/dist
|
||||
@@ -1,96 +0,0 @@
|
||||
name: ci_py_only
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'test/**'
|
||||
- 'conda/**'
|
||||
- 'cmake/**'
|
||||
- '.github/workflows/ci_py_only.yml'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell' &&
|
||||
!contains(github.event.head_commit.message, 'skip ci')
|
||||
steps:
|
||||
- run: echo ok go
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: activate
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install C++ dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt-get install --no-install-recommends \
|
||||
git cmake gcc g++ \
|
||||
libboost-date-time-dev \
|
||||
libboost-filesystem-dev \
|
||||
libboost-iostreams-dev \
|
||||
libboost-program-options-dev \
|
||||
libboost-regex-dev \
|
||||
libboost-system-dev \
|
||||
libboost-thread-dev \
|
||||
python3-all-dev python3-pip \
|
||||
swig libpcre3-dev libxml2-dev \
|
||||
libtbb-dev nlohmann-json3-dev \
|
||||
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
|
||||
libhdf5-dev libcgal-dev
|
||||
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
|
||||
- name: Build ifcopenshell
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_PREFIX_PATH=/usr \
|
||||
-DCMAKE_SYSTEM_PREFIX_PATH=/usr \
|
||||
-DOCC_INCLUDE_DIR=/usr/include/opencascade \
|
||||
-DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 \
|
||||
-DPYTHON_INCLUDE_DIR:PATH=/usr/include/python3.8 \
|
||||
-DPYTHON_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpython3.8.so \
|
||||
-DCOLLADA_SUPPORT=Off \
|
||||
"-DSCHEMA_VERSIONS=2x3;4" \
|
||||
-DBUILD_CONVERT=Off \
|
||||
-DGLTF_SUPPORT=On \
|
||||
-DJSON_INCLUDE_DIR=/usr/include \
|
||||
-DCGAL_INCLUDE_DIR=/usr/include \
|
||||
-DGMP_INCLUDE_DIR=/usr/include \
|
||||
-DMPFR_INCLUDE_DIR=/usr/include \
|
||||
-DGMP_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DMPFR_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DHDF5_INCLUDE_DIR=/usr/include/hdf5/serial \
|
||||
../cmake
|
||||
sudo make -j $(nproc)
|
||||
sudo make install
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
sudo /usr/bin/python -m pip install -U pip
|
||||
sudo /usr/bin/python -m pip install xmlschema numpy lxml
|
||||
sudo /usr/bin/python -m pip install src/bcf
|
||||
sudo /usr/bin/python -m pip install pytest
|
||||
sudo /usr/bin/python -m pip install isodate
|
||||
sudo /usr/bin/python -m pip install lark
|
||||
sudo /usr/bin/python -m pip install networkx
|
||||
sudo /usr/bin/python -m pip install tabulate
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
cd test
|
||||
sudo /usr/bin/python tests.py
|
||||
cd ../src/ifcopenshell-python
|
||||
mv ifcopenshell ifcopenshell-local # Force testing on installed module
|
||||
make test
|
||||
@@ -1,106 +0,0 @@
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'src/ifcblender/**'
|
||||
- 'src/ifcconvert/**'
|
||||
- 'src/ifcgeom/**'
|
||||
- 'src/ifcgeom_schema_agnostic/**'
|
||||
- 'src/ifcgeomserver/**'
|
||||
- 'src/ifcjni/**'
|
||||
- 'src/ifcmax/**'
|
||||
- 'src/ifcopenshell-python/**'
|
||||
- '!src/ifcopenshell-python/docs/**'
|
||||
- 'src/ifcparse/**'
|
||||
- 'src/ifcwrap/**'
|
||||
- 'src/qtviewer/**'
|
||||
- 'src/serializers/**'
|
||||
- 'conda/**'
|
||||
- 'cmake/**'
|
||||
- '.github/workflows/ci.yml'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell' &&
|
||||
!contains(github.event.head_commit.message, 'skip ci')
|
||||
steps:
|
||||
- run: echo ok go
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: activate
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install C++ dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt-get install --no-install-recommends \
|
||||
git cmake gcc g++ \
|
||||
libboost-date-time-dev \
|
||||
libboost-filesystem-dev \
|
||||
libboost-iostreams-dev \
|
||||
libboost-program-options-dev \
|
||||
libboost-regex-dev \
|
||||
libboost-system-dev \
|
||||
libboost-thread-dev \
|
||||
python3-all-dev python3-pip \
|
||||
swig libpcre3-dev libxml2-dev \
|
||||
libtbb-dev nlohmann-json3-dev \
|
||||
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
|
||||
libhdf5-dev libcgal-dev
|
||||
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
|
||||
- name: Build ifcopenshell
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_PREFIX_PATH=/usr \
|
||||
-DCMAKE_SYSTEM_PREFIX_PATH=/usr \
|
||||
-DOCC_INCLUDE_DIR=/usr/include/opencascade \
|
||||
-DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 \
|
||||
-DPYTHON_INCLUDE_DIR:PATH=/usr/include/python3.8 \
|
||||
-DPYTHON_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpython3.8.so \
|
||||
-DCOLLADA_SUPPORT=Off \
|
||||
"-DSCHEMA_VERSIONS=2x3;4;4x3" \
|
||||
-DGLTF_SUPPORT=On \
|
||||
-DJSON_INCLUDE_DIR=/usr/include \
|
||||
-DCGAL_INCLUDE_DIR=/usr/include \
|
||||
-DGMP_INCLUDE_DIR=/usr/include \
|
||||
-DMPFR_INCLUDE_DIR=/usr/include \
|
||||
-DGMP_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DMPFR_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DHDF5_INCLUDE_DIR=/usr/include/hdf5/serial \
|
||||
../cmake
|
||||
sudo make -j $(nproc)
|
||||
sudo make install
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
sudo /usr/bin/python -m pip install -U pip
|
||||
sudo /usr/bin/python -m pip install xmlschema numpy lxml
|
||||
sudo /usr/bin/python -m pip install src/bcf
|
||||
sudo /usr/bin/python -m pip install pytest
|
||||
sudo /usr/bin/python -m pip install isodate
|
||||
sudo /usr/bin/python -m pip install lark
|
||||
sudo /usr/bin/python -m pip install networkx
|
||||
sudo /usr/bin/python -m pip install tabulate
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
cd test
|
||||
sudo /usr/bin/python tests.py
|
||||
cd ../src/ifcopenshell-python
|
||||
mv ifcopenshell ifcopenshell-local # Force testing on installed module
|
||||
make test
|
||||
@@ -1,117 +0,0 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v[0-9].[0-9].[0-9]*'
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
if: github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo ok go
|
||||
build:
|
||||
needs: activate
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install C++ dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt-get install --no-install-recommends \
|
||||
git cmake gcc g++ \
|
||||
libboost-date-time-dev \
|
||||
libboost-filesystem-dev \
|
||||
libboost-iostreams-dev \
|
||||
libboost-program-options-dev \
|
||||
libboost-regex-dev \
|
||||
libboost-system-dev \
|
||||
libboost-thread-dev \
|
||||
python3-all-dev python3-pip \
|
||||
swig libpcre3-dev libxml2-dev \
|
||||
libtbb-dev nlohmann-json3-dev \
|
||||
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
|
||||
libhdf5-dev libcgal-dev opencollada-dev
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CHANGELOG_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=$PWD/install/ \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_PREFIX_PATH=/usr \
|
||||
-DCMAKE_SYSTEM_PREFIX_PATH=/usr \
|
||||
-DBUILD_PACKAGE=On \
|
||||
-DOCC_INCLUDE_DIR=/usr/include/opencascade \
|
||||
-DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 \
|
||||
-DPYTHON_INCLUDE_DIR:PATH=/usr/include/python3.8 \
|
||||
-DPYTHON_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpython3.8.so \
|
||||
-DLIBXML2_INCLUDE_DIR=/usr/include/libxml2 \
|
||||
-DLIBXML2_LIBRARIES=/usr/lib/x86_64-linux-gnu/libxml2.so \
|
||||
-DGLTF_SUPPORT=On \
|
||||
-DJSON_INCLUDE_DIR=/usr/include \
|
||||
-DCGAL_INCLUDE_DIR=/usr/include \
|
||||
-DGMP_INCLUDE_DIR=/usr/include \
|
||||
-DMPFR_INCLUDE_DIR=/usr/include \
|
||||
-DGMP_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DMPFR_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DHDF5_INCLUDE_DIR=/usr/include/hdf5/serial \
|
||||
-DOPENCOLLADA_INCLUDE_DIR=/usr/include/opencollada \
|
||||
-DOPENCOLLADA_LIBRARY_DIR=/usr/lib/opencollada/ \
|
||||
../cmake
|
||||
make -j $(nproc)
|
||||
make install
|
||||
- name: Package
|
||||
id: package
|
||||
run: |
|
||||
make package
|
||||
echo ::set-output name=tgz::$( ls assets/*.tar.gz | head -n 1 | xargs basename )
|
||||
echo ::set-output name=deb::$( ls assets/*.deb | head -n 1 | xargs basename )
|
||||
working-directory: build
|
||||
env:
|
||||
CHANGELOG_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Release
|
||||
id: release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: Release ${{ github.ref }}
|
||||
draft: false
|
||||
prerelease: true
|
||||
body: |
|
||||
Changes to this release
|
||||
- add github actions support #1306
|
||||
- add boost depends to ifcopenshell deb packaging
|
||||
- <add more changes here>
|
||||
See more details in the documentation
|
||||
# body_path: build/CHANGELOG.md
|
||||
- name: Upload TGZ
|
||||
id: upload-tgz
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: build/assets/${{ steps.package.outputs.tgz }}
|
||||
asset_name: ${{ steps.package.outputs.tgz }}
|
||||
asset_content_type: application/x-gzip
|
||||
- name: Upload DEB
|
||||
id: upload-deb
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: build/assets/${{ steps.package.outputs.deb }}
|
||||
asset_name: ${{ steps.package.outputs.deb }}
|
||||
asset_content_type: application/vnd.debian.binary-package
|
||||
-89
@@ -1,89 +0,0 @@
|
||||
# Dependency and build folders created by the build scripts
|
||||
/_deps/
|
||||
/_build-vs*-x*/
|
||||
/_deps-vs*-x*-installed/
|
||||
/_installed-vs*-x*/
|
||||
/build/
|
||||
|
||||
# output directories
|
||||
/cmake/out/
|
||||
/docs/out/
|
||||
/src/examples/out/
|
||||
/src/ifcmax/out/
|
||||
/src/ifcwrap/out/
|
||||
/src/qtviewer/out/
|
||||
|
||||
|
||||
/win/BuildDepsCache*.txt
|
||||
# IfcExpressParser residue
|
||||
/src/ifcexpressparser/express_parser.py
|
||||
# General Python residue
|
||||
__pycache__
|
||||
*.py.bak
|
||||
# Visual Studio Code files
|
||||
.vscode
|
||||
.vs
|
||||
# PyCharm files
|
||||
.idea
|
||||
|
||||
#Virtual Env Files
|
||||
Pipfile
|
||||
Pipfile.lock
|
||||
|
||||
# Docs
|
||||
/docs/output
|
||||
/docs/rst_files
|
||||
/docs/doxygen
|
||||
/src/ifcblenderexport/docs/_build
|
||||
|
||||
# gettext binary translation files
|
||||
*.mo
|
||||
|
||||
# Vim
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Flask
|
||||
instance/*
|
||||
!instance/.gitignore
|
||||
.webassets-cache
|
||||
.env
|
||||
*.db
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# pipenv
|
||||
Pipfile
|
||||
Pipfile.lock
|
||||
|
||||
# Database
|
||||
*.db
|
||||
|
||||
# PyTest
|
||||
htmlcov
|
||||
.coverage
|
||||
|
||||
# Blender
|
||||
*.blend1
|
||||
|
||||
# Sphinx
|
||||
_build/
|
||||
|
||||
# IDS Docs
|
||||
src/ifcopenshell-python/test/build
|
||||
|
||||
# tox cache
|
||||
.tox/
|
||||
*.egg-info/
|
||||
|
||||
# mypy cache
|
||||
.mypy_cache
|
||||
|
||||
# blenderbim libs
|
||||
src/blenderbim/blenderbim/libs
|
||||
|
||||
# ifcopenshell swig and compiled files
|
||||
src/ifcopenshell-python/ifcopenshell/_ifcopenshell_wrapper.so
|
||||
src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.py
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
[submodule "test/input"]
|
||||
path = test/input
|
||||
url = https://github.com/IfcOpenShell/files
|
||||
ignore = dirty
|
||||
[submodule "src/ifcopenshell-python/ifcopenshell/mvd"]
|
||||
path = src/ifcopenshell-python/ifcopenshell/mvd
|
||||
url = https://github.com/opensourceBIM/python-mvdxml/
|
||||
[submodule "src/svgfill"]
|
||||
path = src/svgfill
|
||||
url = https://github.com/IfcOpenShell/svgfill
|
||||
[submodule "src/ifcopenshell-python/test/Sample-BIM-Files"]
|
||||
path = src/ifcopenshell-python/test/Sample-BIM-Files
|
||||
url = https://github.com/IfcOpenShell/ids-test-files
|
||||
-81
@@ -1,81 +0,0 @@
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
cache: ccache
|
||||
os: linux
|
||||
dist: focal
|
||||
addons:
|
||||
apt:
|
||||
update: true
|
||||
packages:
|
||||
- libboost-date-time-dev
|
||||
- libboost-filesystem-dev
|
||||
- libboost-iostreams-dev
|
||||
- libboost-program-options-dev
|
||||
- libboost-regex-dev
|
||||
- libboost-system-dev
|
||||
- libboost-thread-dev
|
||||
- libocct-data-exchange-dev
|
||||
- libocct-foundation-dev
|
||||
- libocct-modeling-algorithms-dev
|
||||
- libocct-modeling-data-dev
|
||||
- libxml2-dev
|
||||
- nlohmann-json3-dev
|
||||
- opencollada-dev
|
||||
- python3-all-dev
|
||||
- python3-pip
|
||||
- swig
|
||||
- libhdf5-dev
|
||||
|
||||
before_script:
|
||||
- if [ $TRAVIS_OS_NAME == "linux" ]; then ccache -z; fi
|
||||
|
||||
install:
|
||||
# for IDS
|
||||
- python3 -m pip install xmlschema
|
||||
|
||||
script:
|
||||
- pwd
|
||||
- mkdir build && cd build
|
||||
- |
|
||||
cmake \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DOCC_INCLUDE_DIR=/usr/include/opencascade \
|
||||
-DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 \
|
||||
-DPYTHON_INCLUDE_DIR:PATH=/usr/include/python3.8 \
|
||||
-DPYTHON_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpython3.8.so \
|
||||
"-DSCHEMA_VERSIONS=2x3;4" \
|
||||
-DGLTF_SUPPORT=On \
|
||||
-DJSON_INCLUDE_DIR=/usr/include \
|
||||
-DHDF5_INCLUDE_DIR=/usr/include/hdf5/serial \
|
||||
../cmake
|
||||
|
||||
# TODO: Drop sudo
|
||||
- sudo make -j $(nproc) install
|
||||
|
||||
- cd ../test
|
||||
- /usr/bin/python tests.py
|
||||
- /usr/bin/python ../src/ifcopenshell-python/ifcopenshell/test_ids.py
|
||||
|
||||
- cd input
|
||||
|
||||
- /usr/local/bin/IfcConvert -yv acad2010_walls.ifc acad2010_walls.glb
|
||||
|
||||
- /usr/bin/python -c "from io import open; import ifcopenshell; f = ifcopenshell.open('encoding.ifc'); assert list(map(ord, f[1][0])) == [39, 97, 39, 32, 49, 109, 179, 32, 8804, 32, 53, 109, 179, 32, 8805, 32, 49, 48, 109, 179]"
|
||||
|
||||
- |
|
||||
(for i in *.ifc; do \
|
||||
echo $i | tee -a log; \
|
||||
timeout 1m /usr/local/bin/IfcConvert -yv "$i" "$i.dae" --validate >> log 2>&1; \
|
||||
echo $i $? >> statuses; \
|
||||
done) || true
|
||||
- echo Failed
|
||||
- grep -v 0$ statuses
|
||||
- grep -v 0$ statuses | wc -l
|
||||
- echo Succeeded
|
||||
- grep 0$ statuses
|
||||
- grep 0$ statuses | wc -l
|
||||
|
||||
after_script:
|
||||
- if [ $TRAVIS_OS_NAME == "linux" ]; then ccache -s; fi
|
||||
@@ -1,7 +1,7 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@@ -618,4 +618,4 @@ an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
END OF TERMS AND CONDITIONS
|
||||
-165
@@ -1,165 +0,0 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
# -*- mode: Dockerfile -*-
|
||||
|
||||
FROM ubuntu:focal
|
||||
|
||||
ARG CHANNEL
|
||||
ENV CHANNEL=${CHANNEL:-latest}
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y \
|
||||
vim \
|
||||
ssh \
|
||||
sudo \
|
||||
wget \
|
||||
software-properties-common ;\
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN useradd --user-group --create-home --shell /bin/bash IfcOpenShell ;\
|
||||
echo "IfcOpenShell ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
|
||||
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN echo "deb http://archive.ubuntu.com/ubuntu focal-proposed main restricted" | tee -a /etc/apt/sources.list; \
|
||||
echo "deb http://archive.ubuntu.com/ubuntu focal-proposed universe" | tee -a /etc/apt/sources.list; \
|
||||
echo "deb http://archive.ubuntu.com/ubuntu focal-proposed multiverse" | tee -a /etc/apt/sources.list; \
|
||||
apt-get -qq update; \
|
||||
apt-get -y install tzdata dos2unix rsync; \
|
||||
apt-get -y install python3 libxml2 libpython3.8 \
|
||||
libboost-all-dev \
|
||||
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev \
|
||||
libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
|
||||
libhdf5-serial-dev ; \
|
||||
rm -rf /var/lib/apt/lists/* ;
|
||||
|
||||
COPY . /home/IfcOpenShell/
|
||||
RUN ls -lrtR /home/IfcOpenShell
|
||||
|
||||
RUN dpkg -i /home/IfcOpenShell/*.deb
|
||||
|
||||
USER IfcOpenShell
|
||||
|
||||
@@ -1,81 +1,132 @@
|
||||
|
||||
IfcOpenShell
|
||||
============
|
||||
open source (LGPL) software library for working with the IFC file format
|
||||
|
||||
IfcOpenShell is an open source ([LGPL]) software library for working with Industry Foundation Classes ([IFC]). Complete
|
||||
parsing support is provided for [IFC2x3 TC1], [IFC4 Add2 TC1], IFC4x1, IFC4x3, and IFC4x3. Extensive geometric support
|
||||
is implemented for the IFC releases [IFC2x3 TC1] and [IFC4 Add2 TC1]. Extending with support for arbitrary IFC schemas
|
||||
is possible at compile-time when using C++ and at run-time when using Python.
|
||||
|
||||
In addition to a C++ and Python API, IfcOpenShell comes with an ecosystem of tools, notably including IfcConvert (an application to convert IFC models to
|
||||
other formats), the BlenderBIM Add-on (an add-on to Blender providing a graphical IFC authoring platform), and many
|
||||
other libraries, CLI apps, and more. Support is also provided for auxiliary standards such as BCF and IDS.
|
||||
http://IfcOpenShell.org
|
||||
|
||||
For more information, see:
|
||||
About this repository
|
||||
=====================
|
||||
|
||||
* [IfcOpenShell Website](http://ifcopenshell.org)
|
||||
* [IfcOpenShell Documentation](http://blenderbim.org/docs-python)
|
||||
* [IfcOpenShell C++ Installation](https://blenderbim.org/docs-python/ifcopenshell/installation.html)
|
||||
* [IfcOpenShell Python Installation](https://blenderbim.org/docs-python/ifcopenshell-python/installation.html)
|
||||
* [IfcOpenShell Python Hello World Tutorial](https://blenderbim.org/docs-python/ifcopenshell-python/hello_world.html)
|
||||
* [BlenderBIM Add-on Website](https://blenderbim.org)
|
||||
* [BlenderBIM Add-on Documentation](http://blenderbim.org/docs)
|
||||
* [Add-on Installation](https://blenderbim.org/docs/users/installation.html)
|
||||
* [Exploring an IFC model](https://blenderbim.org/docs/users/exploring_an_ifc_model.html)
|
||||
This is an initiative to expose the functionality of IfcOpenShell for parsing and writing IFC files to a Python interface. The creation of a topological representation for building elements using Open Cascade is also wrapped by returning a string serialization of the Open Cascade TopoDS_Shape. Using SWIG, a wrapper is obtained for a C++ Class which evaluates its Express attribute names at runtime. The functions created by the SWIG wrapper closely resemble the C++ structure. An additional Python wrapper around these functions is created that is more idiomatic to Python.
|
||||
|
||||
| Service | Status |
|
||||
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Anaconda Daily Build | [](https://anaconda.org/ifcopenshell/ifcopenshell) |
|
||||
| Anaconda v0.7.0 Stable | [](https://anaconda.org/conda-forge/ifcopenshell) |
|
||||
| PyPi Daily Build | [](https://pypi.org/project/ifcopenshell/) |
|
||||
| ArchLinux AUR Package Stable | [](https://aur.archlinux.org/packages/ifcopenshell) |
|
||||
| ArchLinux AUR Package git | [](https://aur.archlinux.org/packages/ifcopenshell-git) |
|
||||
| BlenderBIM Add-on Chocolatey (under moderation) | [](https://community.chocolatey.org/packages/blenderbim-nightly/) |
|
||||
| Sponsor development on OpenCollective | [](https://opencollective.com/opensourcebim/) |
|
||||
| Docker hub | [](https://hub.docker.com/r/aecgeeks/ifcopenshell) |
|
||||
The following interactive session illustrates its use:
|
||||
|
||||
Contents
|
||||
--------
|
||||
>>> import ifcopenshell
|
||||
>>> f = ifcopenshell.open("Duplex_A_20110907_optimized.ifc")
|
||||
>>> f.by_type("ifcwall")[:2]
|
||||
[#91=IfcWallStandardCase('2O2Fr$t4X7Zf8NOew3FL9r',#1,'Basic Wall:Interior - Partition (92mm Stud):144586',$,'Basic Wall:Interior - Partition (92mm Stud):128360',#5198,#18806,'144586'), #92=IfcWallStandardCase('2O2Fr$t4X7Zf8NOew3FLIE',#1,'Basic Wall:Interior - Partition (92mm Stud):143921',$,'Basic Wall:Interior - Partition (92mm Stud):128360',#5206,#18805,'143921')]
|
||||
>>> wall = _[0]
|
||||
>>> brep_data = ifcopenshell.create_shape(wall, ifcopenshell.SEW_SHELLS)
|
||||
>>> len(wall) # number of EXPRESS attributes
|
||||
8
|
||||
>>> wall.GlobalId
|
||||
'2O2Fr$t4X7Zf8NOew3FL9r'
|
||||
>>> wall.Name = "My wall"
|
||||
>>> wall.NonExistingAttr
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
File ".\ifcopenshell.py", line 14, in __getattr__
|
||||
except: raise AttributeError("entity instance of type '%s' has no attribute'%s'"%(self.wrapped_data.is_a(), name)) from None
|
||||
AttributeError: entity instance of type 'IfcWallStandardCase' has no attribute 'NonExistingAttr'
|
||||
>>> wall.GlobalId = 3
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
File ".\ifcopenshell.py", line 26, in __setattr__
|
||||
self[self.wrapped_data.get_argument_index(key)] = value
|
||||
File ".\ifcopenshell.py", line 30, in __setitem__
|
||||
self.wrapped_data.set_argument(idx, entity_instance.map_value(value))
|
||||
File ".\ifc_wrapper.py", line 118, in <lambda>
|
||||
set_argument = lambda self,x,y: self._set_argument(x) if y is None else self
|
||||
._set_argument(x,y)
|
||||
File ".\ifc_wrapper.py", line 114, in _set_argument
|
||||
def _set_argument(self, *args): return _ifc_wrapper.entity_instance__set_argument(self, *args)
|
||||
RuntimeError: INT is not a valid type for 'GlobalId'
|
||||
>>> f.createIfcCartesianPoint(Coordinates=(1.0,1.5,2.0))
|
||||
#27530=IfcCartesianPoint((1.,1.5,2.))
|
||||
>>> import uuid
|
||||
>>> ifcopenshell.guid.compress(uuid.uuid1().hex)
|
||||
'3x4C8Q_6qHuv$P$FYkANRX'
|
||||
>>> new_guid = _
|
||||
>>> owner_hist = f.by_type("IfcOwnerHistory")[0]
|
||||
>>> new_wall = f.createIfcWallStandardCase(new_guid, owner_hist, None, None, Tag='my_tag')
|
||||
>>> new_wall.ObjectType = ''
|
||||
>>> new_wall.ObjectPlacement = new_wall.Representation = None
|
||||
>>> f[92]
|
||||
#92=IfcWallStandardCase('2O2Fr$t4X7Zf8NOew3FLIE',#1,'Basic Wall:Interior - Partition (92mm Stud):143921',$,'Basic Wall:Interior - Partition (92mm Stud):128360',#5206,#18805,'143921')
|
||||
>>> f['2O2Fr$t4X7Zf8NOew3FLIE']
|
||||
#92=IfcWallStandardCase('2O2Fr$t4X7Zf8NOew3FLIE',#1,'Basic Wall:Interior - Partition (92mm Stud):143921',$,'Basic Wall:Interior - Partition (92mm Stud):128360',#5206,#18805,'143921')
|
||||
>>> f.write("out.ifc")
|
||||
|
||||
Those marked with an asterisk are part of IfcOpenShell.
|
||||
|
||||
| Name | Description | License |
|
||||
| ------------------------- | ----------------------------------------------------------------------| ------------------- |
|
||||
| bcf | Library to read and write BCF-XML and query OpenCDE BCF-API modules | LGPL-3.0-or-later |
|
||||
| blenderbim | Add-on to Blender providing a graphical native IFC authoring platform | GPL-3.0-or-later |
|
||||
| bsdd | Library to query the bSDD API | LGPL-3.0-or-later |
|
||||
| ifc2ca | Utility to convert IFC structural analysis models to Code_Aster | LGPL-3.0-or-later |
|
||||
| ifc4d | Convert to and from IFC and project management software | LGPL-3.0-or-later |
|
||||
| ifc5d | Report and optimise cost information from IFC | LGPL-3.0-or-later |
|
||||
| ifcbimtester | Wrapper for Gherkin based unit testing for IFC models | LGPL-3.0-or-later |
|
||||
| ifcblender | Historic Blender IFC import add-on | LGPL-3.0-or-later\* |
|
||||
| ifccityjson | Convert CityJSON to IFC | LGPL-3.0-or-later |
|
||||
| ifcclash | Clash detection library and CLI app | LGPL-3.0-or-later |
|
||||
| ifccobie | Extract IFC data for COBie handover requirements | LGPL-3.0-or-later |
|
||||
| ifcconvert | CLI app to convert IFC to many other formats | LGPL-3.0-or-later\* |
|
||||
| ifccsv | Library and CLI app to export and import schedules from IFC | LGPL-3.0-or-later |
|
||||
| ifcdiff | Compare changes between IFC models | LGPL-3.0-or-later |
|
||||
| ifcfm | Extract IFC data for FM handover requirements | LGPL-3.0-or-later |
|
||||
| ifcgeom | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| ifcgeom\_schema\_agnostic | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| ifcgeomserver | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| ifcjni | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| ifcmax | Historic extension for IFC support in 3DS Max | LGPL-3.0-or-later\* |
|
||||
| ifcopenshell-python | Python library for IFC manipulation | LGPL-3.0-or-later\* |
|
||||
| ifcparse | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| ifcpatch | Utility to run pre-packaged scripts to manipulate IFCs | LGPL-3.0-or-later |
|
||||
| ifcsverchok | Blender Add-on for visual node programming with IFC | GPL-3.0-or-later |
|
||||
| ifctester | Library, CLI and webapp for IDS model auditing | LGPL-3.0-or-later |
|
||||
| ifcwrap | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| qtviewer | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| serializers | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
Compiling on Windows
|
||||
====================
|
||||
Users are advised to use the Visual Studio .sln file in the win/ folder.
|
||||
For Windows users a prebuilt Open CASCADE version is available from the
|
||||
http://opencascade.org website. Download and install this version and
|
||||
provide the paths to the Open CASCADE header and library files to MS
|
||||
Visual Studio C++.
|
||||
|
||||
[LGPL]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/COPYING.LESSER "LGPL-3.0-or-later"
|
||||
[IFC]: https://technical.buildingsmart.org/standards/ifc/ "IFC"
|
||||
[IFC2x3 TC1]: https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ "IFC2x3 TC1"
|
||||
[IFC4 Add2 TC1]: https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/ "IFC4 Add2 TC1"
|
||||
[Visual Studio]: https://www.visualstudio.com/ "Visual Studio"
|
||||
[Visual C++ Build Tools]: http://landinghub.visualstudio.com/visual-cpp-build-tools "Visual C++ Build Tools"
|
||||
[MSYS2]: https://msys2.github.io/ "MSYS2"
|
||||
[win/readme.md]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/win/readme.md "win/readme.md"
|
||||
[nix/build-all.py]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/nix/build-all.py "nix/build-all.py"
|
||||
For building the Autodesk 3ds Max plugin, the 3ds Max SDK needs to be
|
||||
installed as well as 3ds Max itself. Please provide the include and
|
||||
library paths to Visual Studio.
|
||||
|
||||
For building the IfcPython wrapper, SWIG needs to be installed. Please
|
||||
download the latest swigwin version from http://www.swig.org/download.html.
|
||||
After extracting the .zip file, please add the extracted folder to the PATH
|
||||
environment variable. Python needs to be installed, please provide the
|
||||
include and library paths to Visual Studio.
|
||||
|
||||
|
||||
|
||||
Compiling on *nix
|
||||
====================
|
||||
Users are advised to build IfcOpenShell using the cmake file provided in
|
||||
the cmake/ folder. There might be an Open CASCADE package in your operating
|
||||
system's software repository. If not, you will need to compile Open
|
||||
CASCADE yourself. See http://opencascade.org.
|
||||
|
||||
For building the IfcPython wrapper, SWIG and Python development are
|
||||
required.
|
||||
|
||||
To build IfcOpenShell please take the following steps:
|
||||
$ cd /path/to/IfcOpenShell/cmake
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
Optionally:
|
||||
$ OCC_INCLUDE_PATH="/path/to/OpenCASCADE/include"
|
||||
$ OCC_LIBRARY_PATH="/path/to/OpenCASCADE/lib"
|
||||
$ export OCC_INCLUDE_PATH
|
||||
$ export OCC_LIBRARY_PATH
|
||||
$ cmake ../
|
||||
$ make
|
||||
|
||||
|
||||
Ubuntu Notes
|
||||
============
|
||||
|
||||
The following sequence of commands has been tested successfully on Ubuntu 14.04.
|
||||
|
||||
OCE installation. This step worked OK with cmake 2.8.12.2, gcc 4.8.2, g++ 4.8.2. Also, it might take up to an hour to complete.
|
||||
|
||||
apt-get install git cmake gcc g++ libftgl-dev libtbb2 libtbb-dev libboost-all-dev
|
||||
cd /
|
||||
mkdir git && cd git
|
||||
git clone https://github.com/tpaviot/oce.git
|
||||
mkdir oceBuild && cd oceBuild
|
||||
cmake ../oce
|
||||
make -j4
|
||||
sudo make install
|
||||
|
||||
IfcOpenShell installation. This step worked OK with cmake 2.8.12.2, gcc 4.8.2, g++ 4.8.2.
|
||||
|
||||
apt-get install swig
|
||||
cd /git/
|
||||
git clone https://github.com/aothms/IfcOpenShell.git
|
||||
cd IfcOpenShell/cmake
|
||||
mkdir build && cd build
|
||||
cmake ../
|
||||
make -j4
|
||||
|
||||
Once done, IfcConvert is to be found in the build folder.
|
||||
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Do not remove this test for UTF-8: if “Ω” doesn’t appear as greek uppercase omega letter enclosed in quotation marks, you should use an editor that supports UTF-8, not this one. -->
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>blenderbim-nightly</id>
|
||||
<version>blenderbim_build_version-alpha</version>
|
||||
<packageSourceUrl>https://github.com/IfcOpenShell/IfcOpenShell</packageSourceUrl>
|
||||
<owners>fbpyr</owners>
|
||||
<!-- == SOFTWARE SPECIFIC SECTION == -->
|
||||
<title>BlenderBIM install nightly</title>
|
||||
<authors>Dion Moult and many more, see: https://github.com/IfcOpenShell/IfcOpenShell/graphs/contributors</authors>
|
||||
<projectUrl>https://github.com/IfcOpenShell/IfcOpenShell</projectUrl>
|
||||
<iconUrl>https://rawcdn.githack.com/IfcOpenShell/IfcOpenShell/c6ee1d1679d1298de0d7447ff108c22709c68e54/choco/blenderbim/blenderbim.png</iconUrl>
|
||||
<!-- <copyright>Year Software Vendor</copyright> -->
|
||||
<licenseUrl>https://github.com/IfcOpenShell/IfcOpenShell/blob/v0.7.0/COPYING</licenseUrl>
|
||||
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||
<projectSourceUrl>https://github.com/IfcOpenShell/IfcOpenShell</projectSourceUrl>
|
||||
<docsUrl>https://blenderbim.org/docs/</docsUrl>
|
||||
<!--<mailingListUrl></mailingListUrl>-->
|
||||
<bugTrackerUrl>https://github.com/IfcOpenShell/IfcOpenShell/issues</bugTrackerUrl>
|
||||
<tags>blender bim blenderbim ifc python opensource foss</tags>
|
||||
<summary>opensource bim</summary>
|
||||
<description>opensource bim addon for blender - source code at: https://github.com/IfcOpenShell/IfcOpenShell</description>
|
||||
<!-- <releaseNotes>__REPLACE_OR_REMOVE__MarkDown_Okay</releaseNotes> -->
|
||||
|
||||
<dependencies>
|
||||
<dependency id="blender" version="latest_blender_version_maj_min_pat" />
|
||||
<dependency id="7zip" version="22.1"/>
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="tools\**" target="tools" />
|
||||
</files>
|
||||
</package>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.9 KiB |
@@ -1,80 +0,0 @@
|
||||
import datetime
|
||||
import re
|
||||
import sys
|
||||
from urllib import request
|
||||
|
||||
|
||||
def request_repo_info(url: str):
|
||||
req = request.Request(url)
|
||||
resp = request.urlopen(req)
|
||||
if not resp.status == 200:
|
||||
print(f"[ERROR] could not contact server: {url}")
|
||||
quit(1)
|
||||
return resp
|
||||
|
||||
|
||||
if sys.argv[1] == "--do_choco_release?":
|
||||
now = datetime.datetime.now()
|
||||
blenderbim_date = (now - datetime.timedelta(days=1)).strftime("%y%m%d")
|
||||
url = "https://github.com/IfcOpenShell/IfcOpenShell/releases"
|
||||
resp = request_repo_info(url)
|
||||
text = str(resp.read())
|
||||
if blenderbim_date in text:
|
||||
print("do_choco_release", end="")
|
||||
|
||||
|
||||
elif sys.argv[1] == "--latest_blender_release_maj_min_pat?":
|
||||
re_blender_version_min_maj_pat = r"Latest Version.+<span>Blender (\d+\.\d+\.\d+)</span>"
|
||||
url = "https://community.chocolatey.org/packages/blender"
|
||||
resp = request_repo_info(url)
|
||||
html_txt = str(resp.read())
|
||||
found = re.findall(re_blender_version_min_maj_pat, html_txt)
|
||||
if found:
|
||||
print(found[0], end="")
|
||||
|
||||
|
||||
elif sys.argv[1] == "--latest_blender_release_maj_min?":
|
||||
re_blender_version_min_maj = r"Latest Version.+<span>Blender (\d+\.\d+)\..+</span>"
|
||||
url = "https://community.chocolatey.org/packages/blender"
|
||||
resp = request_repo_info(url)
|
||||
html_txt = str(resp.read())
|
||||
found = re.findall(re_blender_version_min_maj, html_txt)
|
||||
if found:
|
||||
print(found[0], end="")
|
||||
|
||||
|
||||
elif sys.argv[1] == "--latest_blender_python_version_maj_min?":
|
||||
# get latest blender version first
|
||||
re_blender_version_min_maj_pat = r"Latest Version.+<span>Blender (\d+\.\d+\.\d+)</span>"
|
||||
url = "https://community.chocolatey.org/packages/blender"
|
||||
resp = request_repo_info(url)
|
||||
html_txt = str(resp.read())
|
||||
found = re.findall(re_blender_version_min_maj_pat, html_txt)
|
||||
if found:
|
||||
latest_blender_version_tag = f"v{found[0]}"
|
||||
re_blender_python_version_maj_min = r"SET\(PYTHON_VERSION (\d+.\d+) "
|
||||
url = f"https://raw.githubusercontent.com/blender/blender/{latest_blender_version_tag}/build_files/cmake/Modules/FindPythonLibsUnix.cmake"
|
||||
resp = request_repo_info(url)
|
||||
html_txt = str(resp.read())
|
||||
found = re.findall(re_blender_python_version_maj_min, html_txt)
|
||||
if found:
|
||||
print(found[0], end="")
|
||||
|
||||
|
||||
elif sys.argv[1] == "--pyver?":
|
||||
# get latest blender version first
|
||||
re_blender_version_min_maj_pat = r"Latest Version.+<span>Blender (\d+\.\d+\.\d+)</span>"
|
||||
url = "https://community.chocolatey.org/packages/blender"
|
||||
resp = request_repo_info(url)
|
||||
html_txt = str(resp.read())
|
||||
found = re.findall(re_blender_version_min_maj_pat, html_txt)
|
||||
if found:
|
||||
latest_blender_version_tag = f"v{found[0]}"
|
||||
re_blender_python_version_maj_min = r"SET\(PYTHON_VERSION (\d+.\d+) "
|
||||
url = f"https://raw.githubusercontent.com/blender/blender/{latest_blender_version_tag}/build_files/cmake/Modules/FindPythonLibsUnix.cmake"
|
||||
resp = request_repo_info(url)
|
||||
html_txt = str(resp.read())
|
||||
found = re.findall(re_blender_python_version_maj_min, html_txt)
|
||||
if found:
|
||||
print(f"py{found[0].replace('.', '')}", end="")
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
print("[INFO] inserting dynamic chocolatey package parameters")
|
||||
HERE_DIR = Path(__file__).parent.absolute()
|
||||
# print(f"[INFO] HERE_DIR: {HERE_DIR}")
|
||||
|
||||
topics = {
|
||||
"spec": {
|
||||
"path": HERE_DIR / "blenderbim.nuspec",
|
||||
"env_vars": {
|
||||
"latest_blender_version_maj_min_pat",
|
||||
"blenderbim_build_version",
|
||||
},
|
||||
},
|
||||
"install": {
|
||||
"path": HERE_DIR / "tools" / "chocolateyinstall.ps1",
|
||||
"env_vars": {
|
||||
"url_blenderbim_py310_win_zip",
|
||||
"sha256sum_blenderbim_py310_win_zip",
|
||||
"latest_blender_version_maj_min",
|
||||
},
|
||||
},
|
||||
"uninstall": {
|
||||
"path": HERE_DIR / "tools" / "chocolateyuninstall.ps1",
|
||||
"env_vars": {
|
||||
"latest_blender_version_maj_min",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for topic, info in topics.items():
|
||||
print(f"[INFO] {topic}:")
|
||||
for env_var_name in info["env_vars"]:
|
||||
print(f"[INFO] {env_var_name} exists?: {os.environ[env_var_name]}")
|
||||
|
||||
with open(info["path"], encoding="utf-8") as txt:
|
||||
content = txt.read()
|
||||
|
||||
for env_var_name in info["env_vars"]:
|
||||
# print(f"[INFO] replace: {env_var_name}")
|
||||
content = content.replace(env_var_name, os.environ[env_var_name])
|
||||
|
||||
with open(info["path"], "w", encoding="utf-8") as txt:
|
||||
txt.write(content)
|
||||
print(f"[INFO] written: {info['path']}")
|
||||
|
||||
print("[INFO] inserting dynamic chocolatey package parameters successful")
|
||||
@@ -1,11 +0,0 @@
|
||||
$processName = "blender"
|
||||
$blenderIsRunning = Get-Process -Name $processName -ErrorAction SilentlyContinue
|
||||
|
||||
if($blenderIsRunning -eq $null) {
|
||||
echo "Blender is not running ready for next action."
|
||||
}
|
||||
else {
|
||||
Write-Warning "$processName is still running - installer cannot safely proceed to next action."
|
||||
Write-Warning "Please retry after closing all running blender applications."
|
||||
exit 1
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$url64 = 'url_blenderbim_py310_win_zip'
|
||||
$checksum64 = 'sha256sum_blenderbim_py310_win_zip'
|
||||
$checksumType64 = 'sha256'
|
||||
|
||||
$appDataUserDir = [System.Environment]::GetEnvironmentVariable('appdata')
|
||||
$unzipTargetDir = "$appDataUserDir\Blender Foundation\Blender\latest_blender_version_maj_min\scripts\addons"
|
||||
|
||||
$chocoBaseDir = [System.Environment]::GetEnvironmentVariable('ChocolateyInstall')
|
||||
$addonEnable = "$chocoBaseDir\lib\blenderbim-nightly\tools\enable_blenderbim_addon.py"
|
||||
|
||||
$programFilesDir = [System.Environment]::GetEnvironmentVariable('ProgramFiles')
|
||||
$blenderExePath = "$env:ProgramFiles\Blender Foundation\Blender latest_blender_version_maj_min\blender.exe"
|
||||
|
||||
$processName = "blender"
|
||||
$blenderIsRunning = Get-Process -Name $processName -ErrorAction SilentlyContinue
|
||||
|
||||
|
||||
if($blenderIsRunning -eq $null) {
|
||||
echo "attempting to install blenderbim."
|
||||
Install-ChocolateyZipPackage -PackageName $env:ChocolateyPackageName -Url64 $url64 -Checksum64 $checksum64 -checksumType $checksumType64 -UnzipLocation $unzipTargetDir
|
||||
Start-Process -FilePath $blenderExePath -ArgumentList "-b", "-y", "--python", "$addonEnable"
|
||||
}
|
||||
else {
|
||||
Write-Warning "$processName is still running - blenderbim cannot be safely installed."
|
||||
Write-Warning "Please retry after closing all running blender applications."
|
||||
exit 1
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
$appDataUserDir = [System.Environment]::GetEnvironmentVariable('appdata')
|
||||
$unzippedDir = "$appDataUserDir\Blender Foundation\Blender\latest_blender_version_maj_min\scripts\addons\blenderbim"
|
||||
|
||||
$chocoBaseDir = [System.Environment]::GetEnvironmentVariable('ChocolateyInstall')
|
||||
$addonDisable = "$chocoBaseDir\lib\blenderbim-nightly\tools\disable_blenderbim_addon.py"
|
||||
|
||||
$programFilesDir = [System.Environment]::GetEnvironmentVariable('ProgramFiles')
|
||||
$blenderExePath = "$env:ProgramFiles\Blender Foundation\Blender latest_blender_version_maj_min\blender.exe"
|
||||
|
||||
$processName = "blender"
|
||||
$blenderIsRunning = Get-Process -Name $processName -ErrorAction SilentlyContinue
|
||||
|
||||
if($blenderIsRunning -eq $null) {
|
||||
echo "attempting to uninstall blenderbim."
|
||||
Start-Process -FilePath $blenderExePath -ArgumentList "-b", "-y", "--python", "$addonDisable"
|
||||
Remove-Item -LiteralPath $unzippedDir -Force -Recurse
|
||||
}
|
||||
else {
|
||||
Write-Warning "$processName is still running - blenderbim cannot be safely uninstalled."
|
||||
Write-Warning "Please retry after closing all running blender applications."
|
||||
exit 1
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import bpy
|
||||
|
||||
|
||||
bpy.ops.preferences.addon_disable(module='blenderbim')
|
||||
bpy.ops.wm.save_userpref()
|
||||
|
||||
print("disabled blenderbim addon successfully.")
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import bpy
|
||||
|
||||
|
||||
bpy.ops.preferences.addon_enable(module='blenderbim')
|
||||
bpy.ops.wm.save_userpref()
|
||||
|
||||
print("enabled blenderbim addon successfully.")
|
||||
|
||||
+181
-980
File diff suppressed because it is too large
Load Diff
@@ -1,8 +0,0 @@
|
||||
compile:
|
||||
conda activate conda-build && conda-build -c conda-forge . --keep-old-work --python 3.10.5
|
||||
|
||||
debug:
|
||||
conda activate conda-build && conda-debug -c conda-forge . --python 3.10.4
|
||||
|
||||
env:
|
||||
conda env update --f environment.yml --prune
|
||||
@@ -1,44 +0,0 @@
|
||||
mkdir build && cd build
|
||||
|
||||
set MY_PY_VER=%PY_VER:.=%
|
||||
set LIBXML2="%LIBRARY_PREFIX%/lib/libxml2.lib"
|
||||
|
||||
cmake -G "Ninja" ^
|
||||
-D CMAKE_BUILD_TYPE:STRING=Release ^
|
||||
-D CMAKE_INSTALL_PREFIX:FILEPATH="%LIBRARY_PREFIX%" ^
|
||||
-D CMAKE_PREFIX_PATH:FILEPATH="%LIBRARY_PREFIX%" ^
|
||||
-D CMAKE_SYSTEM_PREFIX_PATH:FILEPATH="%LIBRARY_PREFIX%" ^
|
||||
-D OCC_INCLUDE_DIR:FILEPATH="%LIBRARY_PREFIX%\include\opencascade" ^
|
||||
-D OCC_LIBRARY_DIR:FILEPATH="%LIBRARY_PREFIX%\lib" ^
|
||||
-D CGAL_INCLUDE_DIR:FILEPATH="%LIBRARY_PREFIX%\include" ^
|
||||
-D GMP_INCLUDE_DIR:FILEPATH="%LIBRARY_PREFIX%\include" ^
|
||||
-D GMP_LIBRARY_DIR:FILEPATH="%LIBRARY_PREFIX%\lib" ^
|
||||
-D MPFR_LIBRARY_DIR:FILEPATH="%LIBRARY_PREFIX%\lib" ^
|
||||
-D COLLADA_SUPPORT=OFF ^
|
||||
-D HDF5_SUPPORT=ON ^
|
||||
-D HDF5_INCLUDE_DIR="%LIBRARY_PREFIX%\include" ^
|
||||
-D HDF5_LIBRARY_DIR="%LIBRARY_PREFIX%\lib" ^
|
||||
-D JSON_INCLUDE_DIR="%LIBRARY_PREFIX%\include" ^
|
||||
-D PYTHON_INCLUDE_DIR=%PREFIX%\include ^
|
||||
-D PYTHON_EXECUTABLE:FILEPATH=%PREFIX%\python.exe ^
|
||||
-D PYTHON_LIBRARY:FILEPATH="%PREFIX%"\libs/python%MY_PY_VER%.lib ^
|
||||
-D BUILD_IFCPYTHON=ON ^
|
||||
-D BUILD_IFCGEOM=ON ^
|
||||
-D COLLADA_SUPPORT:BOOL=OFF ^
|
||||
-D BUILD_EXAMPLES:BOOL=OFF ^
|
||||
-D BUILD_GEOMSERVER:BOOL=OFF ^
|
||||
-D GLTF_SUPPORT:BOOL=ON ^
|
||||
-D BUILD_CONVERT:BOOL=ON ^
|
||||
-D BUILD_IFCMAX:BOOL=OFF ^
|
||||
-D IFCXML_SUPPORT:BOOL=ON ^
|
||||
-D Boost_LIBRARYDIR:FILEPATH="%LIBRARY_PREFIX%\lib" ^
|
||||
-D Boost_INCLUDEDIR:FILEPATH="%LIBRARY_PREFIX%\include" ^
|
||||
-D Boost_USE_STATIC_LIBS:BOOL=OFF ^
|
||||
%SRC_DIR%/cmake
|
||||
|
||||
if errorlevel 1 exit 1
|
||||
|
||||
:: Build and install
|
||||
cmake --build . -- install
|
||||
|
||||
if errorlevel 1 exit 1
|
||||
@@ -1,44 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
declare -a CMAKE_PLATFORM_FLAGS
|
||||
|
||||
if [[ ${HOST} =~ .*linux.* ]]; then
|
||||
CMAKE_PLATFORM_FLAGS+=(-DCMAKE_TOOLCHAIN_FILE=$RECIPE_DIR/cross-linux.cmake)
|
||||
fi
|
||||
|
||||
if [ `uname` == Darwin ]; then
|
||||
export CFLAGS="$CFLAGS -Wl,-flat_namespace,-undefined,suppress"
|
||||
export CXXFLAGS="$CXXFLAGS -Wl,-flat_namespace,-undefined,suppress"
|
||||
export LDFLAGS="$LDFLAGS -Wl,-flat_namespace,-undefined,suppress"
|
||||
fi
|
||||
|
||||
cmake -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=$PREFIX \
|
||||
${CMAKE_PLATFORM_FLAGS[@]} \
|
||||
-DCMAKE_PREFIX_PATH=$PREFIX \
|
||||
-DCMAKE_SYSTEM_PREFIX_PATH=$PREFIX \
|
||||
-DPYTHON_EXECUTABLE:FILEPATH=$PYTHON \
|
||||
-DGMP_LIBRARY_DIR=$PREFIX/lib \
|
||||
-DMPFR_LIBRARY_DIR=$PREFIX/lib \
|
||||
-DOCC_INCLUDE_DIR=$PREFIX/include/opencascade \
|
||||
-DOCC_LIBRARY_DIR=$PREFIX/lib \
|
||||
-DHDF5_SUPPORT:BOOL=ON \
|
||||
-DHDF5_INCLUDE_DIR=$PREFIX/include \
|
||||
-DHDF5_LIBRARY_DIR=$PREFIX/lib \
|
||||
-DJSON_INCLUDE_DIR=$PREFIX/include \
|
||||
-DCGAL_INCLUDE_DIR=$PREFIX/include \
|
||||
-DCOLLADA_SUPPORT=0 \
|
||||
-DBUILD_EXAMPLES:BOOL=OFF \
|
||||
-DIFCXML_SUPPORT:BOOL=ON \
|
||||
-DGLTF_SUPPORT:BOOL=ON \
|
||||
-DBUILD_CONVERT:BOOL=ON \
|
||||
-DBUILD_IFCPYTHON:BOOL=ON \
|
||||
-DBUILD_IFCGEOM:BOOL=ON \
|
||||
-DBUILD_GEOMSERVER:BOOL=OFF \
|
||||
-DBOOST_USE_STATIC_LIBS:BOOL=OFF \
|
||||
./cmake
|
||||
|
||||
ninja
|
||||
|
||||
ninja install
|
||||
@@ -1,2 +0,0 @@
|
||||
CONDA_BUILD_SYSROOT:
|
||||
- /opt/MacOSX10.13.sdk # [osx]
|
||||
@@ -1,16 +0,0 @@
|
||||
# this one is important
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_PLATFORM Linux)
|
||||
|
||||
# specify the cross compiler
|
||||
set(CMAKE_C_COMPILER $ENV{CC})
|
||||
set(CMAKE_CXX_COMPILER $ENV{CXX})
|
||||
|
||||
# where is the target environment
|
||||
set(CMAKE_FIND_ROOT_PATH $ENV{PREFIX} $ENV{BUILD_PREFIX}/$ENV{HOST}/sysroot)
|
||||
|
||||
# search for programs in the build host directories
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
# for libraries and headers in the target directories
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
@@ -1,14 +0,0 @@
|
||||
name: conda-build
|
||||
channels:
|
||||
- conda-forge
|
||||
dependencies:
|
||||
- conda-build
|
||||
- conda-verify
|
||||
- anaconda-client
|
||||
- ninja
|
||||
- doxygen
|
||||
- ripgrep
|
||||
- pip
|
||||
- pip:
|
||||
- --extra-index-url https://lief.s3-website.fr-par.scw.cloud/latest
|
||||
- lief==0.13.0.dev0
|
||||
@@ -1,63 +0,0 @@
|
||||
{% set name = "ifcopenshell" %}
|
||||
{% set version = "0.7.0" %}
|
||||
{% set occt_version = "7.6.2" %}
|
||||
{% set cgal_cpp_version = "5.3" %}
|
||||
{% set hdf5_version = "1.12.1" %}
|
||||
|
||||
package:
|
||||
name: {{ name }}
|
||||
version: {{ version }}
|
||||
|
||||
source:
|
||||
path: ..
|
||||
|
||||
build:
|
||||
binary_relocation: false [osx]
|
||||
number: 1
|
||||
|
||||
requirements:
|
||||
build:
|
||||
- {{ compiler('c') }}
|
||||
- {{ compiler('cxx') }}
|
||||
- ninja >=1.10.2
|
||||
- cmake
|
||||
- swig >=4.0.2
|
||||
|
||||
host:
|
||||
- python
|
||||
- boost-cpp
|
||||
- occt
|
||||
- libxml2
|
||||
- cgal-cpp
|
||||
- hdf5
|
||||
- mpfr
|
||||
- gmp # [unix]
|
||||
- mpir # [win]
|
||||
- nlohmann_json
|
||||
|
||||
run:
|
||||
- python
|
||||
- boost-cpp
|
||||
- occt
|
||||
- libxml2
|
||||
- cgal-cpp
|
||||
- hdf5
|
||||
- mpfr
|
||||
- gmp # [unix]
|
||||
- mpir # [win]
|
||||
- nlohmann_json
|
||||
|
||||
test:
|
||||
imports:
|
||||
- ifcopenshell
|
||||
|
||||
about:
|
||||
home: http://ifcopenshell.org
|
||||
license: LGPL-3.0-or-later
|
||||
license_file: COPYING
|
||||
summary: 'IfcOpenShell is a library to support the IFC file format'
|
||||
description: |
|
||||
IfcOpenShell is an open source (LGPL) software library for
|
||||
working with the Industry Foundation Classes (IFC) file format.
|
||||
doc_url: http://ifcopenshell.org/
|
||||
dev_url: https://github.com/IfcOpenShell/IfcOpenShell
|
||||
@@ -1,40 +0,0 @@
|
||||
#Look for an executable called sphinx-build
|
||||
find_program(SPHINX_EXECUTABLE
|
||||
NAMES sphinx-build
|
||||
DOC "Path to sphinx-build executable")
|
||||
|
||||
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)
|
||||
-2531
File diff suppressed because it is too large
Load Diff
@@ -1,11 +0,0 @@
|
||||
#Look for an executable called sphinx-build
|
||||
find_program(SPHINX_EXECUTABLE
|
||||
NAMES sphinx-build
|
||||
DOC "Path to sphinx-build executable")
|
||||
|
||||
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)
|
||||
@@ -1,11 +0,0 @@
|
||||
#Look for an executable called sphinx-build
|
||||
find_program(SPHINX_EXECUTABLE
|
||||
NAMES sphinx-build
|
||||
DOC "Path to sphinx-build executable")
|
||||
|
||||
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)
|
||||
@@ -1,37 +0,0 @@
|
||||
import textwrap
|
||||
# The `extensions` list should already be in here from `sphinx-quickstart`
|
||||
extensions = [
|
||||
# there may be others here already, e.g. 'sphinx.ext.mathjax'
|
||||
'breathe',
|
||||
'exhale',
|
||||
'sphinx.ext.intersphinx'
|
||||
]
|
||||
|
||||
project = 'IfcOpenShell'
|
||||
copyright = '2020, IfcOpenShell'
|
||||
author = ''
|
||||
|
||||
# Setup the breathe extension
|
||||
breathe_projects = {
|
||||
"My Project": "./output/doxygen/xml"
|
||||
}
|
||||
breathe_default_project = "My Project"
|
||||
|
||||
# Setup the exhale extension
|
||||
exhale_args = {
|
||||
# These arguments are required
|
||||
"containmentFolder": "./rst_files",
|
||||
"rootFileName": "library_root.rst",
|
||||
"rootFileTitle": "IfcOpenShell C++",
|
||||
"doxygenStripFromPath": "..",
|
||||
# Suggested optional arguments
|
||||
"createTreeView": True,
|
||||
# TIP: if using the sphinx-bootstrap-theme, you need
|
||||
# "treeViewIsBootstrap": True,
|
||||
"exhaleExecutesDoxygen": True,
|
||||
# "exhaleDoxygenStdin": "INPUT = ../src/serializers/ ../src/ifcgeom",
|
||||
"exhaleUseDoxyfile": True
|
||||
|
||||
}
|
||||
|
||||
cpp_id_attributes = ['IFC_PARSE_API', 'IFC_GEOM_API']
|
||||
@@ -1,10 +0,0 @@
|
||||
IfcOpenShell
|
||||
============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
rst_files/library_root
|
||||
|
||||
|
||||
* `ifcopenshell-python documentation <python/html/index.html>`_
|
||||
@@ -1,39 +0,0 @@
|
||||
# This program requires doxygen, sphinx, breathe and exhale.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import subprocess
|
||||
import multiprocessing
|
||||
|
||||
# some extra check to see if we can find sphinx in pypy bin dir
|
||||
sphinx_build = os.path.join(os.path.dirname(sys.executable), 'sphinx-build')
|
||||
if not os.path.exists(sphinx_build):
|
||||
sphinx_build = "sphinx-build"
|
||||
# else:
|
||||
# os.environ['PATH'] = os.pathsep + os.path.dirname(sys.executable)
|
||||
|
||||
# not used, -j caused issues in my sphinx install
|
||||
j = str(multiprocessing.cpu_count())
|
||||
|
||||
if not os.path.isdir("./output/doxygen/xml"):
|
||||
os.makedirs("output/doxygen/xml")
|
||||
|
||||
subprocess.check_call([sphinx_build, "-b", "html", ".", "output"])
|
||||
|
||||
if sys.platform == "linux" or sys.platform == "linux2":
|
||||
if os.path.isdir("output/python"):
|
||||
shutil.rmtree("output/python")
|
||||
|
||||
if not os.path.exists(os.path.join("../src/ifcblenderexport/docs", "contents.rst")):
|
||||
subprocess.check_call(["ln", "index.rst", "contents.rst"], cwd="../src/ifcblenderexport/docs")
|
||||
|
||||
subprocess.check_call(["sed", "-i", "s/html_theme/# html_theme/g", "conf.py"], cwd="../src/ifcblenderexport/docs")
|
||||
subprocess.check_call(["make", "html"], cwd="../src/ifcblenderexport/docs")
|
||||
subprocess.check_call(["git", "checkout", "conf.py"], cwd="../src/ifcblenderexport/docs")
|
||||
|
||||
shutil.move("../src/ifcblenderexport/docs/_build", "./output")
|
||||
os.rename("./output/_build", "./output/python")
|
||||
|
||||
elif sys.platform == "win32" or sys.platform == "win64":
|
||||
subprocess.check_call(["make.bat", "html"])
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 120 KiB |
@@ -1,240 +0,0 @@
|
||||
APPLY_DEFAULT_MATERIALS
|
||||
-----------------------
|
||||
|
||||
Given the command invocation:
|
||||
|
||||
Duplex_A_20110907_optimized.ifc d.dae -yv --include attribute GlobalId 3bXiCStxP6Fgxdej$yc50U
|
||||
|
||||
You will find log messages along the lines of
|
||||
|
||||
[Warning] {3bXiCStxP6Fgxdej$yc50U} No material and surface styles for:
|
||||
#333=IfcCovering('3bXiCStxP6Fgxdej$yc50U',#1,'Compound Ceiling:Gypsum Board:187483',$,'Compound Ceiling:Gypsum Board',#17840,#17052,'187483',.CEILING.)
|
||||
|
||||
This means that there is no IfcStyledItem associated to the representation items and that the element does not have an IfcMaterial association with IfcMaterialRepresentation from which we can derive a style (colour) for the element.
|
||||
|
||||
The interactive session below shows how with this setting enabled you will get a default generated material from the IFC element entity type and material indices of 0 pointing to that. With this setting disabled the material index would be -1 to indicate a missing style. Note that there is one material index for every triangle in the list of `shp.geometry.faces`.
|
||||
|
||||
>>> import ifcopenshell, ifcopenshell.geom
|
||||
>>> f = ifcopenshell.open("Duplex_A_20110907_optimized.ifc")
|
||||
>>> s = ifcopenshell.geom.settings()
|
||||
>>> c = f["3bXiCStxP6Fgxdej$yc50U"]
|
||||
>>>
|
||||
>>> shp = ifcopenshell.geom.create_shape(s, c)
|
||||
>>> shp.geometry.material_ids
|
||||
(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
|
||||
>>> [(m.name, m.diffuse) for m in shp.geometry.materials]
|
||||
[]
|
||||
>>>
|
||||
>>> s.set(s.APPLY_DEFAULT_MATERIALS, True)
|
||||
>>> shp = ifcopenshell.geom.create_shape(s, c)
|
||||
>>> shp.geometry.material_ids
|
||||
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||
>>> [(m.name, m.diffuse) for m in shp.geometry.materials]
|
||||
[('IfcCovering', (0.7, 0.7, 0.7))]
|
||||
|
||||
This is enabled by default for the IfcConvert serializers as they will not gracefully handle -1 material indices and allows users to quickly assign colours based on entity types in their modelling applications.
|
||||
|
||||
APPLY_LAYERSETS
|
||||
---------------
|
||||
|
||||
This setting is available in IfcConvert as `--enable-layerset-slicing`.
|
||||
|
||||
For IfcWall and IfcSlab elements, takes the associated IfcMaterialLayerSet and builds a set of surfaces to segment the building element geometry.
|
||||
|
||||
Note that enabling this settings is computationally intensive as it involves 3D Boolean operations.
|
||||
|
||||
Duplex_A_20110907_optimized.ifc d1.dae -yv --include attribute GlobalId 2O2Fr$t4X7Zf8NOew3FNr2
|
||||
|
||||

|
||||
|
||||
Duplex_A_20110907_optimized.ifc d2.dae --enable-layerset-slicing -yv --include attribute GlobalId 2O2Fr$t4X7Zf8NOew3FNr2
|
||||
|
||||

|
||||
|
||||
BUILDING_LOCAL_PLACEMENT
|
||||
------------------------
|
||||
|
||||
This setting is available in IfcConvert using `--building-local-placement`.
|
||||
|
||||
In the typical IfcSite > IfcBuilding > IfcBuildingStorey > ... hierarchy of elements, don't incorporate the ObjectPlacement of the IfcBuilding and above in the placement of elements in the output. This is useful when there is a large offset in this placement that reduces precision in further processing.
|
||||
|
||||
CONVERT_BACK_UNITS
|
||||
------------------
|
||||
|
||||
This setting is available in IfcConvert using `--convert-back-units`.
|
||||
|
||||
Internally IfcOpenShell uses meters as the global length unit to do calculations. This setting restores the coordinate positions after conversion by multiplying the factor of the IfcUnit with UnitType=LENGTHUNIT into the output geometry coordinate values.
|
||||
|
||||
DISABLE_OPENING_SUBTRACTIONS
|
||||
----------------------------
|
||||
|
||||
This setting is available in IfcConvert using `--disable-opening-subtraction`.
|
||||
|
||||
As in most viewer applications, IfcOpeningElement geometry is subtracted from their host elements. This setting disables this behavior.
|
||||
|
||||
Duplex_A_20110907_optimized.ifc d1.dae -yv --include attribute GlobalId 2O2Fr$t4X7Zf8NOew3FNr2
|
||||
|
||||

|
||||
|
||||
Duplex_A_20110907_optimized.ifc d3.dae --disable-opening-subtraction -yv --include attribute GlobalId 2O2Fr$t4X7Zf8NOew3FNr2
|
||||
|
||||

|
||||
|
||||
Note that disabling this settings will reduce processing time and improve robustness as it involves 3D Boolean operations.
|
||||
|
||||
DISABLE_TRIANGULATION
|
||||
---------------------
|
||||
|
||||
To be used in conjunction with `USE_BREP_DATA`. Do not apply the triangulation and - when `USE_BREP_DATA` is set - return a OpenCASCADE serialized TopoDS_Shape from `create_shape()` and `iterator`.
|
||||
|
||||
>>> import ifcopenshell, ifcopenshell.geom
|
||||
>>> s = ifcopenshell.geom.settings()
|
||||
>>> s.set(s.DISABLE_TRIANGULATION, True)
|
||||
>>> s.set(s.USE_BREP_DATA, True)
|
||||
>>> f = ifcopenshell.open("Duplex_A_20110907_optimized.ifc")
|
||||
>>> c = f["3bXiCStxP6Fgxdej$yc50U"]
|
||||
>>> shp = ifcopenshell.geom.create_shape(s, c)
|
||||
>>> print(shp.geometry.brep_data)
|
||||
|
||||
CASCADE Topology V1, (c) Matra-Datavision
|
||||
Locations 0
|
||||
Curve2ds 0
|
||||
Curves 12
|
||||
1 4.6750000000000034 -8.0749999999999904 2.657 -2.0455514041918775e-15 -1 0
|
||||
1 4.6750000000000034 -8.0749999999999904 2.657 1 -3.435893306383461e-15 0
|
||||
1 6.2260000000000044 -8.0749999999999957 2.657 -2.0455514041918724e-15 -1 0
|
||||
1 6.226 -10.246000000000031 2.657 -1 6.8717866127669219e-15 0
|
||||
...
|
||||
|
||||
EDGE_ARROWS
|
||||
-----------
|
||||
|
||||
When `INCLUDE_CURVES` is true and geometric elements include curves (such as the wall axis), add arrow heads to the edges to indicate direction of the curve.
|
||||
|
||||
Duplex_A_20110907_optimized.ifc d4.dae --model --plan --edge-arrows -yv --include attribute GlobalId 2O2Fr$t4X7Zf8NOew3FNr2
|
||||
|
||||

|
||||
|
||||
EXCLUDE_SOLIDS_AND_SURFACES
|
||||
---------------------------
|
||||
|
||||
Exclude faces, shells and solids from geometrical output. Implied when using `--plan` without `--model` in IfcConvert.
|
||||
|
||||
FASTER_BOOLEANS
|
||||
---------------
|
||||
|
||||
NOTE: Only applicable when using OCCT 6.9 and earlier.
|
||||
|
||||
This setting is available in IfcConvert using `--merge-boolean-operands`.
|
||||
|
||||
Fuse the collection of all boolean operands into a single union before applying the boolean subtraction, as opposed to doing individual subtractions. This likely improves performance. From OCCT 7.0 onwards the boolean operations with multiple arguments is used.
|
||||
|
||||
GENERATE_UVS
|
||||
------------
|
||||
|
||||
This setting is available in IfcConvert using `--generate-uvs`.
|
||||
|
||||
Applies a box projection on the generated geometry for the element to obtain UV coordinates. This is purely generated, it does not involve texture coordinates stored in the IFC model.
|
||||
|
||||
Duplex_A_20110907_optimized.ifc d5.dae --generate-uvs -yv --include attribute GlobalId 2O2Fr$t4X7Zf8NOew3FNr2
|
||||
|
||||

|
||||
|
||||
INCLUDE_CURVES
|
||||
--------------
|
||||
|
||||
This setting is available in IfcConvert using `--plan`.
|
||||
|
||||
Include edge and wire geometries in the geometric output.
|
||||
|
||||
LAYERSET_FIRST
|
||||
--------------
|
||||
|
||||
This setting is available in IfcConvert using `--layerset-first`.
|
||||
|
||||
When not using APPLY_LAYERSETS, take the first material layer from the set to use as the material for the overall element.
|
||||
|
||||
NO_NORMALS
|
||||
----------
|
||||
|
||||
This setting is available in IfcConvert using `--no-normals`.
|
||||
|
||||
Do not emit normals on geometric output
|
||||
|
||||
SEARCH_FLOOR
|
||||
------------
|
||||
|
||||
Note: Only applicable to Collada .DAE output when used from IfcConvert.
|
||||
|
||||
This setting is available in IfcConvert using `--use-element-hierarchy`.
|
||||
|
||||
Include the spatial hierarchy in the elements.
|
||||
|
||||
SEW_SHELLS
|
||||
----------
|
||||
|
||||
This setting is available in IfcConvert using `--orient-shells`.
|
||||
|
||||
Re-orient or sew connected face sets to have a consistent outwards orientation.
|
||||
|
||||
SITE_LOCAL_PLACEMENT
|
||||
--------------------
|
||||
|
||||
This setting is available in IfcConvert using `--site-local-placement`.
|
||||
|
||||
See `BUILDING_LOCAL_PLACEMENT`, but exclude also the ObjectPlacement of the IfcSite.
|
||||
|
||||
USE_BREP_DATA
|
||||
-------------
|
||||
|
||||
See `DISABLE_TRIANGULATION`.
|
||||
|
||||
USE_PYTHON_OPENCASCADE
|
||||
----------------------
|
||||
|
||||
Note: Only available when an import of `OCC.Core.BRepTools` or `OCC.BRepTools` succeeds.
|
||||
|
||||
This implies `USE_WORLD_COORDS` `USE_BREP_DATA` and `DISABLE_TRIANGULATION`. The serialized TopoDS_Shape of `USE_BREP_DATA` is deserialized by Python OpenCASCADE.
|
||||
|
||||
USE_WORLD_COORDS
|
||||
----------------
|
||||
|
||||
Apply the ObjectPlacement of the building elements to the geometric output. This is implied when using the Wavefront .OBJ output in IfcConvert. Note that this also eliminates the possibility for geometric elements to point to the same interpreted geometry result.
|
||||
|
||||
VALIDATE_QUANTITIES
|
||||
-------------------
|
||||
|
||||
This setting is available in IfcConvert using `--validate`.
|
||||
|
||||
Running IfcConvert with `--validate` will set a non-zero exit code when ever a log message with severity equal or greater than ERROR has been emitted.
|
||||
|
||||
Currently for internal use only. For every building element geometry converted, looks for an associated quantity set where the OwnerHistory's organization name is IfcOpenShell. And looks for the quantities "Total Surface Area", "Volume", "Shape Validation Properties.Surface Genus" and validates these according to the interpreted geometry definition. Emit Logger::Error when calculated values are outside of the tolerance range for the value stored in the model.
|
||||
|
||||
WELD_VERTICES
|
||||
-------------
|
||||
|
||||
Note: In Python, this setting is *on* by default.
|
||||
|
||||
Note: This setting only affects triangulated output.
|
||||
|
||||
This setting is available in IfcConvert using `--weld-vertices`.
|
||||
|
||||
Discards normals and joins vertices solely based on position. This is useful when output is to be modified in a modeling application.
|
||||
|
||||
>>> import ifcopenshell, ifcopenshell.geom
|
||||
>>> s = ifcopenshell.geom.settings()
|
||||
>>> s.set(s.WELD_VERTICES, False)
|
||||
>>> f = ifcopenshell.open("Duplex_A_20110907_optimized.ifc")
|
||||
>>> c = f["3bXiCStxP6Fgxdej$yc50U"]
|
||||
>>> shp = ifcopenshell.geom.create_shape(s, c)
|
||||
>>> shp.geometry.verts
|
||||
(4.675000000000003, -8.07499999999999, 2.657, 4.674999999999999, -10.24600000000002, 2.657, 6.226000000000004, -8.074999999999996, 2.657, 6.226, -10.24600000000003, 2.657, 4.675000000000003, -8.07499999999999, 2.6, 4.674999999999999, -10.24600000000002, 2.6, 6.226000000000004, -8.074999999999996, 2.6, 6.226, -10.24600000000003, 2.6, 4.674999999999999, -10.24600000000002, 2.657, 4.674999999999999, -10.24600000000002, 2.6, 4.675000000000003, -8.07499999999999, 2.657, 4.675000000000003, -8.07499999999999, 2.6, 6.226, -10.24600000000003, 2.657, 4.674999999999999, -10.24600000000002, 2.657, 6.226, -10.24600000000003, 2.6, 4.674999999999999, -10.24600000000002, 2.6, 6.226000000000004, -8.074999999999996, 2.657, 6.226, -10.24600000000003, 2.657, 6.226000000000004, -8.074999999999996, 2.6, 6.226, -10.24600000000003, 2.6, 4.675000000000003, -8.07499999999999, 2.657, 4.675000000000003, -8.07499999999999, 2.6, 6.226000000000004, -8.074999999999996, 2.657, 6.226000000000004, -8.074999999999996, 2.6)
|
||||
>>> shp.geometry.normals
|
||||
(3.059754518198021e-17, 0.0, -1.0, 3.059754518198021e-17, 0.0, -1.0, 3.059754518198021e-17, 0.0, -1.0, 3.059754518198021e-17, 0.0, -1.0, 2.110175529791737e-16, 0.0, -1.0, 2.110175529791737e-16, 0.0, -1.0, 2.110175529791737e-16, 0.0, -1.0, 2.110175529791737e-16, 0.0, -1.0, -1.0, 1.79434333701042e-15, 0.0, -1.0, 1.79434333701042e-15, 0.0, -1.0, 1.79434333701042e-15, 0.0, -1.0, 1.79434333701042e-15, 0.0, 6.8717866127669046e-15, 1.0, 0.0, 6.8717866127669046e-15, 1.0, 0.0, 6.8717866127669046e-15, 1.0, 0.0, 6.8717866127669046e-15, 1.0, 0.0, -1.0, 1.79434333701042e-15, 0.0, -1.0, 1.79434333701042e-15, 0.0, -1.0, 1.79434333701042e-15, 0.0, -1.0, 1.79434333701042e-15, 0.0, 3.4358933063834523e-15, 1.0, 0.0, 3.4358933063834523e-15, 1.0, 0.0, 3.4358933063834523e-15, 1.0, 0.0, 3.4358933063834523e-15, 1.0, 0.0)
|
||||
>>>
|
||||
>>> s.set(s.WELD_VERTICES, True)
|
||||
>>> shp = ifcopenshell.geom.create_shape(s, c)
|
||||
>>> shp.geometry.verts
|
||||
(4.675000000000003, -8.07499999999999, 2.657, 4.674999999999999, -10.24600000000002, 2.657, 6.226000000000004, -8.074999999999996, 2.657, 6.226, -10.24600000000003, 2.657, 4.675000000000003, -8.07499999999999, 2.6, 4.674999999999999, -10.24600000000002, 2.6, 6.226000000000004, -8.074999999999996, 2.6, 6.226, -10.24600000000003, 2.6)
|
||||
>>> shp.geometry.normals
|
||||
()
|
||||
@@ -1,10 +0,0 @@
|
||||
IfcOpenShell
|
||||
============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
rst_files/library_root
|
||||
|
||||
|
||||
* `ifcopenshell-python documentation <python/html/index.html>`_
|
||||
@@ -1,918 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
###############################################################################
|
||||
# #
|
||||
# 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/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# #
|
||||
# This script builds IfcOpenShell and its dependencies #
|
||||
# #
|
||||
# Prerequisites for this script to function correctly: #
|
||||
# * cmake * git * bzip2 * tar * c(++) compilers * autoconf #
|
||||
# #
|
||||
# if building with USE_OCCT additionally: #
|
||||
# * glx.h #
|
||||
# #
|
||||
# if building with OCCT 7.4.0 additionally: #
|
||||
# * libfontconfig1-dev #
|
||||
# #
|
||||
# if building with -shared #
|
||||
# * libgl1-mesa-dev libxext-dev libxmu-dev libxmu-headers libxi-dev #
|
||||
# #
|
||||
# for python37 to install correctly additionally: #
|
||||
# * libffi(-dev[el]) #
|
||||
# #
|
||||
# on debian 7.8 these can be obtained with: #
|
||||
# $ apt-get install git gcc g++ autoconf bison bzip2 cmake #
|
||||
# mesa-common-dev libffi-dev libfontconfig1-dev #
|
||||
# #
|
||||
# on ubuntu 14.04: #
|
||||
# $ apt-get install git gcc g++ autoconf bison make cmake #
|
||||
# mesa-common-dev libffi-dev libfontconfig1-dev #
|
||||
# #
|
||||
# on OS X El Capitan with homebrew: #
|
||||
# $ brew install git bison autoconf automake libffi cmake #
|
||||
# #
|
||||
###############################################################################
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import subprocess as sp
|
||||
import shutil
|
||||
import tarfile
|
||||
import multiprocessing
|
||||
import platform
|
||||
import sysconfig
|
||||
|
||||
from urllib.request import urlretrieve
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.INFO)
|
||||
ch = logging.StreamHandler()
|
||||
ch.setLevel(logging.INFO)
|
||||
logger.addHandler(ch)
|
||||
|
||||
PROJECT_NAME = "IfcOpenShell"
|
||||
USE_CURRENT_PYTHON_VERSION = os.getenv("USE_CURRENT_PYTHON_VERSION")
|
||||
ADD_COMMIT_SHA = os.getenv("ADD_COMMIT_SHA")
|
||||
|
||||
PYTHON_VERSIONS = ["3.6.14", "3.7.13", "3.8.13", "3.9.11", "3.10.3", "3.11.0"]
|
||||
JSON_VERSION = "v3.6.1"
|
||||
OCE_VERSION = "0.18.3"
|
||||
OCCT_VERSION = "7.5.3"
|
||||
BOOST_VERSION = "1.80.0"
|
||||
PCRE_VERSION = "8.41"
|
||||
LIBXML2_VERSION = "2.9.11"
|
||||
SWIG_VERSION = "4.0.2"
|
||||
OPENCOLLADA_VERSION = "v1.6.68"
|
||||
HDF5_VERSION = "1.12.1"
|
||||
|
||||
GMP_VERSION = "6.2.1"
|
||||
MPFR_VERSION = "3.1.6" # latest is 4.1.0
|
||||
CGAL_VERSION = "5.3"
|
||||
|
||||
# binaries
|
||||
cp = "cp"
|
||||
bash = "bash"
|
||||
git = "git"
|
||||
bunzip2 = "bunzip2"
|
||||
tar = "tar"
|
||||
cc = "cc"
|
||||
cplusplus = "c++"
|
||||
autoconf = "autoconf"
|
||||
automake = "automake"
|
||||
make = "make"
|
||||
date = "date"
|
||||
curl = "curl"
|
||||
wget = "wget"
|
||||
strip = "strip"
|
||||
|
||||
explicit_targets = [s for s in sys.argv[1:] if not s.startswith("-")]
|
||||
flags = set(s.lstrip('-') for s in sys.argv[1:] if s.startswith("-"))
|
||||
|
||||
# Helper function for coloured printing
|
||||
|
||||
NO_COLOR = "\033[0m" # <ref>http://stackoverflow.com/questions/5947742/how-to-change-the-output-color-of-echo-in-linux</ref>
|
||||
BLACK_ON_WHITE = "\033[0;30;107m"
|
||||
RED = "\033[31m"
|
||||
GREEN = "\033[32m"
|
||||
YELLOW = "\033[33m"
|
||||
MAGENTA = "\033[35m"
|
||||
|
||||
def cecho(message, color=NO_COLOR):
|
||||
"""Logs message `message` in color `color`."""
|
||||
logger.info(f"{color}{message}\033[0m")
|
||||
|
||||
def which(cmd):
|
||||
for path in os.getenv("PATH").split(":"):
|
||||
if os.path.exists(path) and cmd in os.listdir(path):
|
||||
return cmd
|
||||
return None
|
||||
|
||||
|
||||
# Set defaults for missing empty environment variables
|
||||
|
||||
USE_OCCT = os.environ.get("USE_OCCT", "true").lower() == "true"
|
||||
|
||||
TOOLSET = None
|
||||
if platform.system() == "Darwin":
|
||||
# C++11 features used in OCCT 7+ need a more recent stdlib
|
||||
TOOLSET = "10.9" if USE_OCCT else "10.6"
|
||||
|
||||
|
||||
IFCOS_NUM_BUILD_PROCS = os.getenv("IFCOS_NUM_BUILD_PROCS", multiprocessing.cpu_count() + 1)
|
||||
|
||||
CMAKE_DIR = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "cmake"))
|
||||
|
||||
build_dir = os.environ.get("BUILD_DIR", os.path.join(os.path.dirname(__file__), "..", "build"))
|
||||
|
||||
path = [build_dir, platform.system(), "wasm" if "wasm" in flags else platform.machine()]
|
||||
if TOOLSET:
|
||||
path.append(TOOLSET)
|
||||
DEFAULT_DEPS_DIR = os.path.realpath(os.path.join(*path))
|
||||
|
||||
DEPS_DIR = os.getenv("DEPS_DIR", DEFAULT_DEPS_DIR)
|
||||
|
||||
if not os.path.exists(DEPS_DIR):
|
||||
os.makedirs(DEPS_DIR)
|
||||
|
||||
BUILD_CFG = os.getenv("BUILD_CFG", "RelWithDebInfo")
|
||||
|
||||
|
||||
# Print build configuration information
|
||||
|
||||
cecho (f"""This script fetches and builds {PROJECT_NAME} and its dependencies
|
||||
""", BLACK_ON_WHITE)
|
||||
cecho("""Script configuration:
|
||||
|
||||
""", GREEN)
|
||||
cecho(f"""* USE_OCCT = {USE_OCCT}""", MAGENTA)
|
||||
if USE_OCCT:
|
||||
cecho(" - Compiling against official Open Cascade")
|
||||
else:
|
||||
cecho(" - Compiling against Open Cascade Community Edition")
|
||||
cecho(f"* Dependency Directory = {DEPS_DIR}", MAGENTA)
|
||||
cecho(f" - The directory where {PROJECT_NAME} dependencies are installed.")
|
||||
cecho(f"* Build Config Type = {BUILD_CFG}", MAGENTA)
|
||||
cecho(""" - The used build configuration type for the dependencies.
|
||||
Defaults to RelWithDebInfo if not specified.""")
|
||||
|
||||
if BUILD_CFG == "MinSizeRel":
|
||||
cecho(" WARNING: MinSizeRel build can suffer from a significant performance loss.", RED)
|
||||
|
||||
cecho(f"* IFCOS_NUM_BUILD_PROCS = {IFCOS_NUM_BUILD_PROCS}", MAGENTA)
|
||||
cecho(""" - How many compiler processes may be run in parallel.
|
||||
""")
|
||||
|
||||
dependency_tree = {
|
||||
'IfcParse': ('boost', 'libxml2', 'hdf5'),
|
||||
'IfcGeom': ('IfcParse', 'occ', 'json', 'cgal'),
|
||||
'IfcConvert': ('IfcGeom',),
|
||||
'OpenCOLLADA': ('libxml2', 'pcre'),
|
||||
'IfcGeomServer': ('IfcGeom',),
|
||||
'IfcOpenShell-Python': ('python', 'swig', 'IfcGeom'),
|
||||
'swig': ('pcre',),
|
||||
'boost': (),
|
||||
'libxml2': (),
|
||||
'python': (),
|
||||
'occ': ('freetype',),
|
||||
'pcre': (),
|
||||
'json': (),
|
||||
'hdf5': (),
|
||||
'cgal': (),
|
||||
'freetype': (),
|
||||
}
|
||||
|
||||
def v(dep):
|
||||
yield dep
|
||||
for d in dependency_tree[dep]:
|
||||
for x in v(d):
|
||||
yield x
|
||||
|
||||
if "v" in flags:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
else:
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
BUILD_STATIC = "shared" not in flags
|
||||
ENABLE_FLAG = "--enable-static" if BUILD_STATIC else "--enable-shared"
|
||||
DISABLE_FLAG = "--disable-shared" if BUILD_STATIC else "--disable-static"
|
||||
LINK_TYPE = "static" if BUILD_STATIC else "shared"
|
||||
LINK_TYPE_UCFIRST = LINK_TYPE[0].upper() + LINK_TYPE[1:]
|
||||
LIBRARY_EXT = "a" if BUILD_STATIC else "so"
|
||||
PIC = "-fPIC" if BUILD_STATIC else ""
|
||||
|
||||
if any(f.startswith("py-") for f in flags):
|
||||
PYTHON_VERSIONS = [pyv for pyv in PYTHON_VERSIONS if "py-%s" % "".join(pyv.split('.')[0:2]) in flags]
|
||||
|
||||
if len(explicit_targets):
|
||||
targets = set(sum((list(v(target)) for target in explicit_targets), []))
|
||||
else:
|
||||
targets = set(dependency_tree.keys())
|
||||
|
||||
targets = set(t for t in targets if 'without-%s' % t.lower() not in flags)
|
||||
|
||||
print("Building:", *sorted(targets, key=lambda t: len(list(v(t)))))
|
||||
|
||||
# Check that required tools are in PATH
|
||||
|
||||
for cmd in [git, bunzip2, tar, cc, cplusplus, autoconf, automake, make, "patch", "cmake"]:
|
||||
if which(cmd) is None:
|
||||
raise ValueError(f"Required tool '{cmd}' not installed or not added to PATH")
|
||||
|
||||
# identifiers for the download tool (could be less memory consuming as ints, but are more verbose as strings)
|
||||
download_tool_default = download_tool_py = "py"
|
||||
download_tool_git = "git"
|
||||
|
||||
# Create log directory and file
|
||||
|
||||
log_dir = os.path.join(DEPS_DIR, "logs")
|
||||
if not os.path.exists(log_dir):
|
||||
os.makedirs(log_dir)
|
||||
LOG_FILE = os.path.join(log_dir, sp.check_output([date, "+%Y%m%d"], encoding="utf-8").strip()) + ".log"
|
||||
if not os.path.exists(LOG_FILE):
|
||||
open(LOG_FILE, "w").close()
|
||||
logger.info(f"using command log file '{LOG_FILE}'")
|
||||
|
||||
def run(cmds, cwd=None, can_fail=False):
|
||||
|
||||
"""
|
||||
Wraps `subprocess.Popen.communicate()` and logs the command being executed,
|
||||
sets up logging `stderr` to `LOG_FILE` (in append mode) and returns stdout
|
||||
with leading and trailing whitespace removed.
|
||||
"""
|
||||
|
||||
logger.debug(f"running command {' '.join(cmds)} in directory {cwd}")
|
||||
log_file_handle = open(LOG_FILE, "a")
|
||||
proc = sp.Popen(cmds, cwd=cwd, stdout=sp.PIPE, stderr=sp.PIPE, encoding="utf-8")
|
||||
stdout, stderr = proc.communicate()
|
||||
log_file_handle.write(stdout)
|
||||
log_file_handle.write(stderr)
|
||||
log_file_handle.close()
|
||||
logger.debug(f"command returned {proc.returncode}")
|
||||
|
||||
if proc.returncode != 0 and not can_fail:
|
||||
print("-" * 70)
|
||||
print(stderr)
|
||||
print("-" * 70)
|
||||
raise RuntimeError(f"Command `{' '.join(cmds)}` returned exit code {proc.returncode}")
|
||||
|
||||
return stdout.strip()
|
||||
|
||||
if platform.system() == "Darwin":
|
||||
if run(["sw_vers", "-productVersion"]) >= "11.":
|
||||
# Apparently not supported
|
||||
PYTHON_VERSIONS = [pv for pv in PYTHON_VERSIONS if tuple(map(int, pv.split("."))) >= (3, 7)]
|
||||
if run(["sw_vers", "-productVersion"]) < "10.16":
|
||||
# Apparently not supported
|
||||
PYTHON_VERSIONS = [pv for pv in PYTHON_VERSIONS if tuple(map(int, pv.split("."))) < (3, 11)]
|
||||
|
||||
BOOST_VERSION_UNDERSCORE = BOOST_VERSION.replace(".", "_")
|
||||
|
||||
OCE_LOCATION = f"https://github.com/tpaviot/oce/archive/OCE-{OCE_VERSION}.tar.gz"
|
||||
BOOST_LOCATION = f"https://boostorg.jfrog.io/artifactory/main/release/{BOOST_VERSION}/source/"
|
||||
|
||||
# Helper functions
|
||||
|
||||
|
||||
def run_autoconf(arg1, configure_args, cwd):
|
||||
configure_path = os.path.realpath(os.path.join(cwd, "..", "configure"))
|
||||
if not os.path.exists(configure_path):
|
||||
run([bash, "./autogen.sh"], cwd=os.path.realpath(os.path.join(cwd, ".."))) # only run autogen.sh in the directory it is located and use cwd to achieve that in order to not mess up things
|
||||
# Using `sh` over `bash` fixes issues with building swig
|
||||
prefix = os.path.realpath(f"{DEPS_DIR}/install/{arg1}")
|
||||
|
||||
wasm = []
|
||||
if "wasm" in flags:
|
||||
wasm.append("emconfigure")
|
||||
|
||||
run([*wasm, "/bin/sh", "../configure"] + configure_args + [f"--prefix={prefix}"], cwd=cwd)
|
||||
|
||||
|
||||
def run_cmake(arg1, cmake_args, cmake_dir=None, cwd=None):
|
||||
if cmake_dir is None:
|
||||
P = ".."
|
||||
else:
|
||||
P = cmake_dir
|
||||
|
||||
wasm = []
|
||||
if "wasm" in flags:
|
||||
wasm.append("emcmake")
|
||||
|
||||
run([*wasm, "cmake", P, *cmake_args, f"-DCMAKE_BUILD_TYPE={BUILD_CFG}"], cwd=cwd)
|
||||
|
||||
|
||||
def git_clone_or_pull_repository(clone_url, target_dir, revision=None):
|
||||
"""Lazily clones the `git` repository denoted by `clone_url` into
|
||||
the `target_dir` or pulls latest changes if the `target_dir` exists (naively assumes
|
||||
that a working clone exists there) and optionally checks out a revision
|
||||
`revision` after cloning or in the existing clone if `revision` is not
|
||||
`None`."""
|
||||
if not os.path.exists(target_dir):
|
||||
logger.info(f"cloning '{clone_url}' into '{target_dir}'")
|
||||
run([git, "clone", "--recursive", clone_url, target_dir])
|
||||
else:
|
||||
logger.info(f"directory '{target_dir}' already cloned. Pulling latest changes.")
|
||||
|
||||
# detect whether we are on a branch and pull
|
||||
if run([git, "rev-parse", "--abbrev-ref", "HEAD"], cwd=target_dir) != "HEAD":
|
||||
run([git, "pull", clone_url], cwd=target_dir)
|
||||
|
||||
if revision != None:
|
||||
run([git, "checkout", revision], cwd=target_dir)
|
||||
|
||||
|
||||
def build_dependency(name, mode, build_tool_args, download_url, download_name, download_tool=download_tool_default, revision=None, patch=None, additional_files={}, no_append_name=False, **kwargs):
|
||||
"""Handles building of dependencies with different tools (which are
|
||||
distinguished with the `mode` argument. `build_tool_args` is expected to be
|
||||
a list which is necessary in order to not mess up quoting of compiler and
|
||||
linker flags."""
|
||||
check_dir = os.path.join(DEPS_DIR, "install", name)
|
||||
if os.path.exists(check_dir):
|
||||
logger.info(f"Found existing {name}, skipping")
|
||||
return
|
||||
build_dir = os.path.join(DEPS_DIR, "build")
|
||||
if not os.path.exists(build_dir):
|
||||
os.makedirs(build_dir)
|
||||
|
||||
logger.info(f"\rFetching {name}... ")
|
||||
|
||||
if download_tool == download_tool_py:
|
||||
if no_append_name:
|
||||
url = download_url
|
||||
else:
|
||||
url = os.path.join(download_url, download_name)
|
||||
|
||||
download_path = os.path.join(build_dir, download_name)
|
||||
if not os.path.exists(download_path):
|
||||
urlretrieve(url, os.path.join(build_dir, download_path))
|
||||
else:
|
||||
logger.info(f"Download '{download_path}' already exists, assuming it's an undamaged download and that it has been extracted if possible, skipping")
|
||||
elif download_tool == download_tool_git:
|
||||
logger.info(f"\rChecking {name}... ")
|
||||
git_clone_or_pull_repository(download_url, target_dir=os.path.join(build_dir, download_name), revision=revision)
|
||||
else:
|
||||
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):
|
||||
extract_dir_name = download_name
|
||||
extract_dir = os.path.join(build_dir, extract_dir_name)
|
||||
else:
|
||||
download_tarfile_path = os.path.join(build_dir, download_name)
|
||||
if download_name.endswith(".tar.gz") or download_name.endswith(".tgz"):
|
||||
compr = "gz"
|
||||
elif download_name.endswith(".tar.bz2"):
|
||||
compr = "bz2"
|
||||
else:
|
||||
raise RuntimeError("fix source for new download type")
|
||||
download_tarfile = tarfile.open(name=download_tarfile_path, mode=f"r:{compr}")
|
||||
# tarfile seriously doesn't have a function to retrieve the root directory more easily
|
||||
extract_dir_name = os.path.commonprefix([x for x in download_tarfile.getnames() if x != "."])
|
||||
#run([tar, "--exclude=\"*/*\"", "-tf", download_name], cwd=build_dir).strip() no longer works
|
||||
if extract_dir_name is None:
|
||||
extract_dir_name = run([bash, "-c", f"tar -tf {download_name} 2> /dev/null | head -n 1 | cut -f1 -d /"], cwd=build_dir)
|
||||
extract_dir = os.path.join(build_dir, extract_dir_name)
|
||||
if not os.path.exists(extract_dir):
|
||||
run([tar, "-xf", download_name], cwd=build_dir)
|
||||
|
||||
for path, url in additional_files.items():
|
||||
if not os.path.exists(path):
|
||||
urlretrieve(url, os.path.join(extract_dir, path))
|
||||
|
||||
if patch is not None:
|
||||
if isinstance(patch, str):
|
||||
patch = [patch]
|
||||
for p in patch:
|
||||
patch_abs = os.path.abspath(os.path.join(os.path.dirname(__file__), p))
|
||||
if os.path.exists(patch_abs):
|
||||
try: run(["patch", "-p1", "--batch", "--forward", "-i", patch_abs], cwd=extract_dir)
|
||||
except Exception as e:
|
||||
# Assert that the patch has already been applied
|
||||
run(["patch", "-p1", "--batch", "--reverse", "--dry-run", "-i", patch_abs], cwd=extract_dir)
|
||||
|
||||
if mode == "ctest":
|
||||
run(["ctest", "-S", "HDF5config.cmake,BUILD_GENERATOR=Unix", "-C", BUILD_CFG, "-V", "-O", "hdf5.log"], cwd=extract_dir)
|
||||
run([tar, "-xf", kwargs["ctest_result"] + ".tar.gz"], cwd=os.path.join(extract_dir, 'build'))
|
||||
shutil.copytree(
|
||||
os.path.join(extract_dir, "build", kwargs["ctest_result"], kwargs["ctest_result_path"]),
|
||||
os.path.join(DEPS_DIR, "install", name)
|
||||
)
|
||||
elif mode != "bjam":
|
||||
extract_build_dir = os.path.join(extract_dir, "build")
|
||||
if os.path.exists(extract_build_dir):
|
||||
shutil.rmtree(extract_build_dir)
|
||||
os.makedirs(extract_build_dir)
|
||||
|
||||
logger.info(f"\rConfiguring {name}...")
|
||||
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)
|
||||
else:
|
||||
raise ValueError()
|
||||
logger.info(f"\rBuilding {name}... ")
|
||||
run([make, f"-j{IFCOS_NUM_BUILD_PROCS}", "VERBOSE=1"], cwd=extract_build_dir)
|
||||
logger.info(f"\rInstalling {name}... ")
|
||||
run([make, "install"], cwd=extract_build_dir)
|
||||
logger.info(f"\rInstalled {name} \n")
|
||||
else:
|
||||
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" 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")
|
||||
|
||||
cecho("Collecting dependencies:", GREEN)
|
||||
|
||||
# Set compiler flags for 32bit builds on 64bit system
|
||||
# TODO: This is untested
|
||||
|
||||
ADDITIONAL_ARGS = []
|
||||
|
||||
if platform.system() == "Darwin":
|
||||
ADDITIONAL_ARGS = [f"-mmacosx-version-min={TOOLSET}"] + ADDITIONAL_ARGS
|
||||
|
||||
if "wasm" in flags:
|
||||
ADDITIONAL_ARGS.extend(("-sWASM_BIGINT", "-fexceptions"))
|
||||
|
||||
# If the linker supports GC sections, set it up to reduce binary file size
|
||||
# -fPIC is required for the shared libraries to work
|
||||
|
||||
CXXFLAGS = os.environ.get("CXXFLAGS", "")
|
||||
CFLAGS = os.environ.get("CFLAGS", "")
|
||||
LDFLAGS = os.environ.get("LDFLAGS", "")
|
||||
|
||||
ADDITIONAL_ARGS_STR = " ".join(ADDITIONAL_ARGS)
|
||||
if "wasm" not in flags and sp.call([bash, "-c", "ld --gc-sections 2>&1 | grep -- --gc-sections &> /dev/null"]) != 0:
|
||||
CXXFLAGS_MINIMAL = f"{CXXFLAGS} {PIC} {ADDITIONAL_ARGS_STR}"
|
||||
CFLAGS_MINIMAL = f"{CFLAGS} {PIC} {ADDITIONAL_ARGS_STR}"
|
||||
if BUILD_STATIC:
|
||||
CXXFLAGS = f"{CXXFLAGS} {PIC} -fdata-sections -ffunction-sections -fvisibility=hidden -fvisibility-inlines-hidden {ADDITIONAL_ARGS_STR}"
|
||||
CFLAGS = f"{CFLAGS} {PIC} -fdata-sections -ffunction-sections -fvisibility=hidden {ADDITIONAL_ARGS_STR}"
|
||||
else:
|
||||
CXXFLAGS = CXXFLAGS_MINIMAL
|
||||
CFLAGS = CFLAGS_MINIMAL
|
||||
LDFLAGS = f"{LDFLAGS} -Wl,--gc-sections {ADDITIONAL_ARGS_STR}"
|
||||
else:
|
||||
CXXFLAGS_MINIMAL = f"{CXXFLAGS} {PIC} {ADDITIONAL_ARGS_STR}"
|
||||
CFLAGS_MINIMAL = f"{CFLAGS} {PIC} {ADDITIONAL_ARGS_STR}"
|
||||
if BUILD_STATIC:
|
||||
CXXFLAGS = f"{CXXFLAGS} {PIC} -fvisibility=hidden -fvisibility-inlines-hidden {ADDITIONAL_ARGS_STR}"
|
||||
CFLAGS = f"{CFLAGS} {PIC} -fvisibility=hidden -fvisibility-inlines-hidden {ADDITIONAL_ARGS_STR}"
|
||||
else:
|
||||
CXXFLAGS=CXXFLAGS_MINIMAL
|
||||
CFLAGS=CFLAGS_MINIMAL
|
||||
LDFLAGS = f"{LDFLAGS} {ADDITIONAL_ARGS_STR}"
|
||||
|
||||
os.environ["CXXFLAGS"] = CXXFLAGS
|
||||
os.environ["CFLAGS"] = CFLAGS
|
||||
os.environ["LDFLAGS"] = LDFLAGS
|
||||
|
||||
# Some dependencies need a more recent CMake version than most distros provide
|
||||
# @tfk: this is no longer needed
|
||||
# build_dependency(name="cmake-%s" % (CMAKE_VERSION,), mode="autoconf", build_tool_args=[], download_url="https://cmake.org/files/v%s" % (CMAKE_VERSION_2,), download_name="cmake-%s.tar.gz" % (CMAKE_VERSION,))
|
||||
|
||||
if 'hdf5' in targets:
|
||||
HDF5_MAJOR = ".".join(HDF5_VERSION.split(".")[:-1])
|
||||
build_dependency(
|
||||
name=f"hdf5-{HDF5_VERSION}",
|
||||
mode="ctest",
|
||||
build_tool_args=[],
|
||||
download_url=f"https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-{HDF5_MAJOR}/hdf5-{HDF5_VERSION}/src/",
|
||||
download_name=f"CMake-hdf5-{HDF5_VERSION}.tar.gz",
|
||||
ctest_result=f"HDF5-{HDF5_VERSION}-{platform.system()}",
|
||||
ctest_result_path=f"HDF_Group/HDF5/{HDF5_VERSION}"
|
||||
)
|
||||
|
||||
if "json" in targets:
|
||||
json_url = f"https://github.com/nlohmann/json/releases/download/{JSON_VERSION}/json.hpp"
|
||||
json_install_path = f"{DEPS_DIR}/install/json/nlohmann/json.hpp"
|
||||
if not os.path.exists(os.path.dirname(json_install_path)):
|
||||
os.makedirs(os.path.dirname(json_install_path))
|
||||
if not os.path.exists(json_install_path):
|
||||
urlretrieve(json_url, json_install_path)
|
||||
|
||||
if "pcre" in targets:
|
||||
build_dependency(
|
||||
name=f"pcre-{PCRE_VERSION}",
|
||||
mode="autoconf",
|
||||
build_tool_args=[DISABLE_FLAG],
|
||||
download_url=f"https://downloads.sourceforge.net/project/pcre/pcre/{PCRE_VERSION}/",
|
||||
download_name=f"pcre-{PCRE_VERSION}.tar.bz2"
|
||||
)
|
||||
|
||||
# An issue exists with swig-1.3 and python >= 3.2
|
||||
# Therefore, build a recent copy from source
|
||||
if "swig" in targets:
|
||||
build_dependency(
|
||||
name="swig",
|
||||
mode="autoconf",
|
||||
build_tool_args=["--disable-ccache", f"--with-pcre-prefix={DEPS_DIR}/install/pcre-{PCRE_VERSION}"],
|
||||
download_url="https://github.com/swig/swig.git",
|
||||
download_name="swig",
|
||||
download_tool=download_tool_git,
|
||||
revision=f"rel-{SWIG_VERSION}"
|
||||
)
|
||||
|
||||
if "freetype" in targets:
|
||||
build_dependency(
|
||||
name=f"freetype",
|
||||
mode="cmake",
|
||||
build_tool_args=[
|
||||
f"-DCMAKE_INSTALL_PREFIX={DEPS_DIR}/install/freetype"
|
||||
],
|
||||
download_url = "https://github.com/freetype/freetype",
|
||||
download_name = "freetype2",
|
||||
download_tool=download_tool_git,
|
||||
)
|
||||
|
||||
if USE_OCCT and "occ" in targets:
|
||||
patches = []
|
||||
if OCCT_VERSION < "7.4":
|
||||
patches.append("./patches/occt/enable-exception-handling.patch")
|
||||
|
||||
if "wasm" in flags:
|
||||
patches.append("./patches/occt/no_em_js.patch")
|
||||
|
||||
build_dependency(
|
||||
name=f"occt-{OCCT_VERSION}",
|
||||
mode="cmake",
|
||||
build_tool_args=[
|
||||
f"-DINSTALL_DIR={DEPS_DIR}/install/occt-{OCCT_VERSION}",
|
||||
f"-DBUILD_LIBRARY_TYPE={LINK_TYPE_UCFIRST}",
|
||||
"-DBUILD_MODULE_Draw=0",
|
||||
"-DBUILD_RELEASE_DISABLE_EXCEPTIONS=Off",
|
||||
f"-D3RDPARTY_FREETYPE_DIR={DEPS_DIR}/install/freetype"
|
||||
],
|
||||
download_url = "https://github.com/Open-Cascade-SAS/OCCT",
|
||||
download_name = "occt",
|
||||
download_tool=download_tool_git,
|
||||
patch=patches,
|
||||
revision="V" + OCCT_VERSION.replace('.', '_')
|
||||
)
|
||||
elif "occ" in targets:
|
||||
build_dependency(
|
||||
name=f"oce-{OCE_VERSION}",
|
||||
mode="cmake",
|
||||
build_tool_args=[
|
||||
"-DOCE_DISABLE_TKSERVICE_FONT=ON",
|
||||
"-DOCE_TESTING=OFF",
|
||||
"-DOCE_BUILD_SHARED_LIB=OFF",
|
||||
"-DOCE_DISABLE_X11=ON",
|
||||
"-DOCE_VISUALISATION=OFF",
|
||||
"-DOCE_OCAF=OFF",
|
||||
f"-DOCE_INSTALL_PREFIX={DEPS_DIR}/install/oce-{OCE_VERSION}"
|
||||
],
|
||||
download_url="https://github.com/tpaviot/oce/archive/",
|
||||
download_name=f"OCE-{OCE_VERSION}.tar.gz"
|
||||
)
|
||||
|
||||
if "libxml2" in targets:
|
||||
build_dependency(
|
||||
f"libxml2-{LIBXML2_VERSION}",
|
||||
"autoconf",
|
||||
build_tool_args=[
|
||||
"--without-python",
|
||||
ENABLE_FLAG,
|
||||
DISABLE_FLAG,
|
||||
"--without-zlib",
|
||||
"--without-iconv",
|
||||
"--without-lzma"
|
||||
],
|
||||
download_url="ftp://xmlsoft.org/libxml2/",
|
||||
download_name=f"libxml2-{LIBXML2_VERSION}.tar.gz"
|
||||
)
|
||||
|
||||
if "OpenCOLLADA" in targets:
|
||||
build_dependency(
|
||||
"OpenCOLLADA",
|
||||
"cmake",
|
||||
build_tool_args=[
|
||||
f"-DLIBXML2_INCLUDE_DIR={DEPS_DIR}/install/libxml2-{LIBXML2_VERSION}/include/libxml2",
|
||||
f"-DLIBXML2_LIBRARIES={DEPS_DIR}/install/libxml2-{LIBXML2_VERSION}/lib/libxml2.{LIBRARY_EXT}",
|
||||
f"-DPCRE_INCLUDE_DIR={DEPS_DIR}/install/pcre-{PCRE_VERSION}/include",
|
||||
f"-DPCRE_PCREPOSIX_LIBRARY={DEPS_DIR}/install/pcre-{PCRE_VERSION}/lib/libpcreposix.{LIBRARY_EXT}",
|
||||
f"-DPCRE_PCRE_LIBRARY={DEPS_DIR}/install/pcre-{PCRE_VERSION}/lib/libpcre.{LIBRARY_EXT}",
|
||||
f"-DCMAKE_INSTALL_PREFIX={DEPS_DIR}/install/OpenCOLLADA/"
|
||||
],
|
||||
download_url="https://github.com/KhronosGroup/OpenCOLLADA.git",
|
||||
download_name="OpenCOLLADA",
|
||||
download_tool=download_tool_git,
|
||||
patch=("./patches/opencollada/pr622_and_disable_subdirs.patch", "./patches/opencollada/remove_tr1.patch"),
|
||||
revision=OPENCOLLADA_VERSION
|
||||
)
|
||||
|
||||
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_CXX_FLAGS = os.environ["CXXFLAGS"]
|
||||
OLD_C_FLAGS = os.environ["CFLAGS"]
|
||||
os.environ["CXXFLAGS"] = CXXFLAGS_MINIMAL
|
||||
os.environ["CFLAGS"] = CFLAGS_MINIMAL
|
||||
|
||||
# On OSX a dynamic python library is built or it would not be compatible
|
||||
# with the system python because of some threading initialization
|
||||
PYTHON_CONFIGURE_ARGS = []
|
||||
if platform.system() == "Darwin":
|
||||
PYTHON_CONFIGURE_ARGS = ["--enable-shared"]
|
||||
|
||||
for PYTHON_VERSION in PYTHON_VERSIONS:
|
||||
try:
|
||||
build_dependency(
|
||||
f"python-{PYTHON_VERSION}",
|
||||
"autoconf",
|
||||
PYTHON_CONFIGURE_ARGS,
|
||||
f"http://www.python.org/ftp/python/{PYTHON_VERSION}/",
|
||||
f"Python-{PYTHON_VERSION}.tgz"
|
||||
)
|
||||
except RuntimeError as e:
|
||||
# Sometimes setting up modules such as pip/lzma can cause
|
||||
# the python installer script to return a non zero exit
|
||||
# code where actually the headers and dynamic libraries
|
||||
# are installed correctly. This is all we need so we catch
|
||||
# the exception and only reraise if a partially successful
|
||||
# install is not detected.
|
||||
if not os.path.exists(
|
||||
os.path.join(DEPS_DIR, "install", f"python-{PYTHON_VERSION}")
|
||||
):
|
||||
raise e
|
||||
|
||||
os.environ["CXXFLAGS"] = OLD_CXX_FLAGS
|
||||
os.environ["CFLAGS"] = OLD_C_FLAGS
|
||||
|
||||
if "boost" in targets:
|
||||
str_concat = lambda prefix: lambda postfix: "" if postfix.strip() == "" else "=".join((prefix, postfix.strip()))
|
||||
toolset = []
|
||||
if "wasm" in flags:
|
||||
toolset.append("toolset=emscripten")
|
||||
build_dependency(
|
||||
f"boost-{BOOST_VERSION}",
|
||||
mode="bjam",
|
||||
build_tool_args=[
|
||||
f"--stagedir={DEPS_DIR}/install/boost-{BOOST_VERSION}",
|
||||
"--with-system",
|
||||
"--with-program_options",
|
||||
"--with-regex",
|
||||
"--with-thread",
|
||||
"--with-date_time",
|
||||
"--with-iostreams",
|
||||
f"link={LINK_TYPE}",
|
||||
*toolset,
|
||||
*map(str_concat("cxxflags"), CXXFLAGS.strip().split(' ')),
|
||||
*map(str_concat("linkflags"), LDFLAGS.strip().split(' ')),
|
||||
"stage", "-s", "NO_BZIP2=1"],
|
||||
download_url=BOOST_LOCATION,
|
||||
patch="./patches/boost/boostorg_regex_62.patch",
|
||||
download_name=f"boost_{BOOST_VERSION_UNDERSCORE}.tar.bz2"
|
||||
)
|
||||
if "wasm" in flags:
|
||||
# only supported on nix for now
|
||||
run(("find", ".", "-name", "*.bc", "-exec", "bash", "-c", "emar q ${1%.bc}.a $1", "bash", "{}", ";"), cwd=f"{DEPS_DIR}/install/boost-{BOOST_VERSION}/lib")
|
||||
|
||||
if "cgal" in targets:
|
||||
gmp_args = []
|
||||
mpfr_args = []
|
||||
if "wasm" in flags:
|
||||
gmp_args.extend(("--disable-assembly", "--host", "none", "--enable-cxx"))
|
||||
mpfr_args.extend(("--host", "none"))
|
||||
|
||||
build_dependency(
|
||||
name=f"gmp-{GMP_VERSION}",
|
||||
mode="autoconf",
|
||||
build_tool_args=[ENABLE_FLAG, DISABLE_FLAG, "--with-pic", *gmp_args],
|
||||
download_url="https://ftp.gnu.org/gnu/gmp/",
|
||||
download_name=f"gmp-{GMP_VERSION}.tar.bz2"
|
||||
)
|
||||
|
||||
build_dependency(
|
||||
name=f"mpfr-{MPFR_VERSION}",
|
||||
mode="autoconf",
|
||||
build_tool_args=[ENABLE_FLAG, DISABLE_FLAG, *mpfr_args, f"--with-gmp={DEPS_DIR}/install/gmp-{GMP_VERSION}"],
|
||||
download_url=f"http://www.mpfr.org/mpfr-{MPFR_VERSION}/",
|
||||
download_name=f"mpfr-{MPFR_VERSION}.tar.bz2"
|
||||
)
|
||||
|
||||
build_dependency(
|
||||
name=f"cgal-{CGAL_VERSION}",
|
||||
mode="cmake",
|
||||
build_tool_args=[
|
||||
f"-DGMP_LIBRARIES={DEPS_DIR}/install/gmp-{GMP_VERSION}/lib/libgmp.{LIBRARY_EXT}",
|
||||
f"-DGMP_INCLUDE_DIR={DEPS_DIR}/install/gmp-{GMP_VERSION}/include",
|
||||
f"-DMPFR_LIBRARIES={DEPS_DIR}/install/mpfr-{MPFR_VERSION}/lib/libmpfr.{LIBRARY_EXT}" ,
|
||||
f"-DMPFR_INCLUDE_DIR={DEPS_DIR}/install/mpfr-{MPFR_VERSION}/include",
|
||||
f"-DBoost_INCLUDE_DIR={DEPS_DIR}/install/boost-{BOOST_VERSION}",
|
||||
f"-DCMAKE_INSTALL_PREFIX={DEPS_DIR}/install/cgal-{CGAL_VERSION}/",
|
||||
"-DCGAL_HEADER_ONLY=On",
|
||||
"-DBUILD_SHARED_LIBS=Off"
|
||||
],
|
||||
download_url="https://github.com/CGAL/cgal.git",
|
||||
download_name="cgal",
|
||||
download_tool=download_tool_git,
|
||||
revision=f"v{CGAL_VERSION}"
|
||||
)
|
||||
|
||||
cecho("Building IfcOpenShell:", GREEN)
|
||||
|
||||
IFCOS_DIR = os.path.join(DEPS_DIR, "build", "ifcopenshell")
|
||||
if os.environ.get("NO_CLEAN", "").lower() not in {"1", "on", "true"}:
|
||||
if os.path.exists(IFCOS_DIR):
|
||||
shutil.rmtree(IFCOS_DIR)
|
||||
os.makedirs(IFCOS_DIR, exist_ok=True)
|
||||
executables_dir = os.path.join(IFCOS_DIR, "executables")
|
||||
os.makedirs(executables_dir, exist_ok=True)
|
||||
|
||||
OFF_ON = ["OFF", "ON"]
|
||||
|
||||
cmake_args = [
|
||||
"-DUSE_MMAP=" "OFF",
|
||||
"-DBUILD_EXAMPLES=" "OFF",
|
||||
"-DBUILD_SHARED_LIBS=" +OFF_ON[not BUILD_STATIC],
|
||||
"-DBOOST_ROOT=" f"{DEPS_DIR}/install/boost-{BOOST_VERSION}",
|
||||
"-DGLTF_SUPPORT=" "ON",
|
||||
"-DJSON_INCLUDE_DIR=" f"{DEPS_DIR}/install/json",
|
||||
"-DBoost_NO_BOOST_CMAKE=" "On",
|
||||
"-DADD_COMMIT_SHA=" +("On" if ADD_COMMIT_SHA else "Off")
|
||||
]
|
||||
|
||||
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")
|
||||
|
||||
if "cgal" in targets:
|
||||
cmake_args.extend([
|
||||
"-DCGAL_INCLUDE_DIR=" f"{DEPS_DIR}/install/cgal-{CGAL_VERSION}/include",
|
||||
"-DGMP_INCLUDE_DIR=" f"{DEPS_DIR}/install/gmp-{GMP_VERSION}/include",
|
||||
"-DGMP_LIBRARY_DIR=" f"{DEPS_DIR}/install/gmp-{GMP_VERSION}/lib",
|
||||
"-DMPFR_INCLUDE_DIR=" f"{DEPS_DIR}/install/mpfr-{MPFR_VERSION}/include",
|
||||
"-DMPFR_LIBRARY_DIR=" f"{DEPS_DIR}/install/mpfr-{MPFR_VERSION}/lib",
|
||||
])
|
||||
|
||||
if "occ" in targets and USE_OCCT:
|
||||
occ_include_dir = f"{DEPS_DIR}/install/occt-{OCCT_VERSION}/include/opencascade"
|
||||
occ_library_dir = f"{DEPS_DIR}/install/occt-{OCCT_VERSION}/lib"
|
||||
cmake_args.extend([
|
||||
"-DOCC_INCLUDE_DIR=" +occ_include_dir,
|
||||
"-DOCC_LIBRARY_DIR=" +occ_library_dir
|
||||
])
|
||||
|
||||
elif "occ" in targets:
|
||||
occ_include_dir = f"{DEPS_DIR}/install/oce-{OCE_VERSION}/include/oce"
|
||||
occ_library_dir = f"{DEPS_DIR}/install/oce-{OCE_VERSION}/lib"
|
||||
cmake_args.extend([
|
||||
"-DOCC_INCLUDE_DIR=" +occ_include_dir,
|
||||
"-DOCC_LIBRARY_DIR=" +occ_library_dir
|
||||
])
|
||||
|
||||
if "OpenCOLLADA" in targets:
|
||||
cmake_args.extend([
|
||||
"-DOPENCOLLADA_INCLUDE_DIR=" f"{DEPS_DIR}/install/OpenCOLLADA/include/opencollada",
|
||||
"-DOPENCOLLADA_LIBRARY_DIR=" f"{DEPS_DIR}/install/OpenCOLLADA/lib/opencollada"
|
||||
])
|
||||
else:
|
||||
cmake_args.extend([
|
||||
"-DCOLLADA_SUPPORT=" "Off",
|
||||
])
|
||||
|
||||
if "pcre" in targets:
|
||||
cmake_args.append(
|
||||
"-DPCRE_LIBRARY_DIR=" f"{DEPS_DIR}/install/pcre-{PCRE_VERSION}/lib"
|
||||
)
|
||||
|
||||
if "libxml2" in targets:
|
||||
cmake_args.extend([
|
||||
"-DLIBXML2_INCLUDE_DIR=" f"{DEPS_DIR}/install/libxml2-{LIBXML2_VERSION}/include/libxml2",
|
||||
"-DLIBXML2_LIBRARIES=" f"{DEPS_DIR}/install/libxml2-{LIBXML2_VERSION}/lib/libxml2.{LIBRARY_EXT}"
|
||||
])
|
||||
|
||||
if "hdf5" in targets:
|
||||
cmake_args.extend([
|
||||
"-DHDF5_INCLUDE_DIR=" f"{DEPS_DIR}/install/hdf5-{HDF5_VERSION}/include",
|
||||
"-DHDF5_LIBRARY_DIR=" f"{DEPS_DIR}/install/hdf5-{HDF5_VERSION}/lib"
|
||||
])
|
||||
else:
|
||||
cmake_args.append("-DHDF5_SUPPORT=Off")
|
||||
|
||||
if not explicit_targets or {"IfcGeom", "IfcConvert", "IfcGeomServer"} & set(explicit_targets):
|
||||
logger.info("\rConfiguring executables...")
|
||||
|
||||
exec_args = [
|
||||
"-DBUILD_IFCGEOM=" +OFF_ON["IfcGeom" in targets],
|
||||
"-DBUILD_GEOMSERVER=" +OFF_ON["IfcGeomServer" in targets],
|
||||
"-DBUILD_CONVERT=" +OFF_ON["IfcConvert" in targets],
|
||||
"-DBUILD_IFCPYTHON=" "OFF",
|
||||
"-DCMAKE_INSTALL_PREFIX=" f"{DEPS_DIR}/install/ifcopenshell",
|
||||
]
|
||||
|
||||
run_cmake("", exec_args + cmake_args, cmake_dir=CMAKE_DIR, cwd=executables_dir)
|
||||
|
||||
logger.info("\rBuilding executables... ")
|
||||
|
||||
run([make, f"-j{IFCOS_NUM_BUILD_PROCS}"], cwd=executables_dir)
|
||||
run([make, "install/strip" if BUILD_CFG == "Release" else "install"], cwd=executables_dir)
|
||||
|
||||
if "IfcOpenShell-Python" in targets:
|
||||
# On OSX the actual Python library is not linked against.
|
||||
ADDITIONAL_ARGS = ""
|
||||
if platform.system() == "Darwin":
|
||||
ADDITIONAL_ARGS = "-Wl,-flat_namespace,-undefined,suppress"
|
||||
|
||||
if "wasm" in flags:
|
||||
ADDITIONAL_ARGS = f"-Wl,-undefined,suppress -sSIDE_MODULE=2 -sEXPORTED_FUNCTIONS=_PyInit__ifcopenshell_wrapper"
|
||||
|
||||
os.environ["CXXFLAGS"] = f"{CXXFLAGS_MINIMAL} {ADDITIONAL_ARGS}"
|
||||
os.environ["CFLAGS"] = f"{CFLAGS_MINIMAL} {ADDITIONAL_ARGS}"
|
||||
os.environ["LDFLAGS"] = f"{LDFLAGS} {ADDITIONAL_ARGS}"
|
||||
|
||||
python_dir = os.path.join(IFCOS_DIR, "pythonwrapper")
|
||||
os.makedirs(python_dir, exist_ok=True)
|
||||
|
||||
def compile_python_wrapper(python_version, python_library, python_include, python_executable):
|
||||
logger.info(f"\rConfiguring python {python_version} wrapper...")
|
||||
|
||||
cache_path = os.path.join(python_dir, "CMakeCache.txt")
|
||||
if os.path.exists(cache_path):
|
||||
os.remove(cache_path)
|
||||
|
||||
os.environ["PYTHON_LIBRARY_BASENAME"] = os.path.basename(python_library)
|
||||
|
||||
swig_when_built = []
|
||||
if "swig" in targets:
|
||||
swig_when_built.append(f"-DSWIG_EXECUTABLE={DEPS_DIR}/install/swig/bin/swig")
|
||||
|
||||
run_cmake("",
|
||||
cmake_args + [
|
||||
"-DPYTHON_LIBRARY=" +python_library,
|
||||
*([f"-DPYTHON_EXECUTABLE={python_executable}"] if python_executable else []),
|
||||
# *([f"-DPYTHON_MODULE_INSTALL_DIR={os.environ['PYTHONPATH']}/ifcopenshell"] if "wasm" in flags else []),
|
||||
*(["-DPYTHON_MODULE_INSTALL_DIR="+os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "package"))] if "wasm" in flags else []),
|
||||
"-DPYTHON_INCLUDE_DIR=" +python_include,
|
||||
"-DCMAKE_INSTALL_PREFIX=" f"{DEPS_DIR}/install/ifcopenshell/tmp",
|
||||
"-DUSERSPACE_PYTHON_PREFIX=" +["Off", "On"][os.environ.get("PYTHON_USER_SITE", "").lower() in {"1", "on", "true"}],
|
||||
*swig_when_built],
|
||||
cmake_dir=CMAKE_DIR, cwd=python_dir)
|
||||
|
||||
logger.info(f"\rBuilding python {python_version} wrapper... ")
|
||||
|
||||
run([make, f"-j{IFCOS_NUM_BUILD_PROCS}", "_ifcopenshell_wrapper"], cwd=python_dir)
|
||||
run([make, "install/local"], cwd=os.path.join(python_dir, "ifcwrap"))
|
||||
|
||||
if python_executable:
|
||||
module_dir = os.path.dirname(run([python_executable, "-c", "import inspect, ifcopenshell; print(inspect.getfile(ifcopenshell))"]))
|
||||
|
||||
if platform.system() != "Darwin":
|
||||
# TODO: This symbol name depends on the Python version?
|
||||
run([strip, "-s", "-K", "PyInit__ifcopenshell_wrapper", "_ifcopenshell_wrapper.so"], cwd=module_dir)
|
||||
|
||||
return module_dir
|
||||
|
||||
if "wasm" in flags:
|
||||
compile_python_wrapper(
|
||||
f"{os.environ['PYMAJOR']}.{os.environ['PYMINOR']}.{os.environ['PYMICRO']}",
|
||||
f"{os.environ['TARGETINSTALLDIR']}/lib/libpython{os.environ['PYMAJOR']}.{os.environ['PYMINOR']}.a",
|
||||
os.environ['PYTHONINCLUDE'],
|
||||
None
|
||||
)
|
||||
|
||||
elif USE_CURRENT_PYTHON_VERSION:
|
||||
python_info = sysconfig.get_paths()
|
||||
|
||||
py_path_components = [
|
||||
sysconfig.get_config_var('LIBDIR'),
|
||||
sysconfig.get_config_var("INSTSONAME")
|
||||
]
|
||||
|
||||
if sysconfig.get_config_var('multiarchsubdir'):
|
||||
py_path_components.insert(1, sysconfig.get_config_var('multiarchsubdir').replace("/", ""))
|
||||
|
||||
python_lib = os.path.join(*py_path_components)
|
||||
|
||||
compile_python_wrapper(platform.python_version(), python_lib, python_info["include"], sys.executable)
|
||||
else:
|
||||
for python_version in PYTHON_VERSIONS:
|
||||
python_library = run([bash, "-c", f"ls {DEPS_DIR}/install/python-{python_version}/lib/libpython*.*"])
|
||||
python_include = run([bash, "-c", f"ls -d {DEPS_DIR}/install/python-{python_version}/include/python*"])
|
||||
python_executable = os.path.join(DEPS_DIR, "install", f"python-{python_version}", "bin", f"python{python_version[0]}")
|
||||
|
||||
module_dir = compile_python_wrapper(python_version, python_library, python_include, python_executable)
|
||||
run([cp, "-R", module_dir, os.path.join(DEPS_DIR, "install", "ifcopenshell", f"python-{python_version}")])
|
||||
|
||||
logger.info("\rBuilt IfcOpenShell...\n\n")
|
||||
@@ -1,20 +0,0 @@
|
||||
--- a/tools/build/src/tools/emscripten.jam
|
||||
+++ b/tools/build/src/tools/emscripten.jam
|
||||
@@ -6,6 +6,7 @@
|
||||
import feature ;
|
||||
import os ;
|
||||
import toolset ;
|
||||
+import generators ;
|
||||
import common ;
|
||||
import gcc ;
|
||||
import type ;
|
||||
@@ -52,6 +53,8 @@
|
||||
<debug-symbols>off <debug-symbols>on
|
||||
<rtti>off <rtti>on
|
||||
;
|
||||
+generators.override builtin.lib-generator : emscripten.prebuilt ;
|
||||
+generators.override emscripten.searched-lib-generator : searched-lib-generator ;
|
||||
|
||||
type.set-generated-target-suffix EXE : <toolset>emscripten : "js" ;
|
||||
type.set-generated-target-suffix OBJ : <toolset>emscripten : "bc" ;
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff;h=0ab4e621833f4eae945a3762c9a29ee12e2eec53#patch1
|
||||
diff --git a/src/HLRBRep/HLRBRep_InternalAlgo.cxx b/src/HLRBRep/HLRBRep_InternalAlgo.cxx
|
||||
index ca885ca..c13cb06 100644 (file)
|
||||
--- a/src/HLRBRep/HLRBRep_InternalAlgo.cxx
|
||||
+++ b/src/HLRBRep/HLRBRep_InternalAlgo.cxx
|
||||
@@ -165,7 +165,7 @@ void HLRBRep_InternalAlgo::Update ()
|
||||
SB.Bounds(v1,v2,e1,e2,f1,f2);
|
||||
|
||||
for (Standard_Integer e = e1; e <= e2; e++) {
|
||||
- HLRBRep_EdgeData ed = aEDataArray.ChangeValue(e);
|
||||
+ HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(e);
|
||||
HLRAlgo::DecodeMinMax(ed.MinMax(), TheMin, TheMax);
|
||||
if (FirstTime) {
|
||||
FirstTime = Standard_False;
|
||||
@@ -307,7 +307,7 @@ void HLRBRep_InternalAlgo::InitEdgeStatus ()
|
||||
Standard_Integer nf = myDS->NbFaces();
|
||||
|
||||
for (Standard_Integer e = 1; e <= ne; e++) {
|
||||
- HLRBRep_EdgeData ed = aEDataArray.ChangeValue(e);
|
||||
+ HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(e);
|
||||
if (ed.Selected()) ed.Status().ShowAll();
|
||||
}
|
||||
// for (Standard_Integer f = 1; f <= nf; f++) {
|
||||
@@ -368,7 +368,7 @@ void HLRBRep_InternalAlgo::Select ()
|
||||
Standard_Integer nf = myDS->NbFaces();
|
||||
|
||||
for (Standard_Integer e = 1; e <= ne; e++) {
|
||||
- HLRBRep_EdgeData ed = aEDataArray.ChangeValue(e);
|
||||
+ HLRBRep_EdgeData& ed = aEDataArray.ChangeValue(e);
|
||||
ed.Selected(Standard_True);
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
Description: Enable exception handling
|
||||
Upstream defaults to no exception handling for performance reasons,
|
||||
but in OCCT's role as a shared library it's better for Debian to
|
||||
enable it.
|
||||
Author: Kurt Kremitzki <kkremitzki@gmail.com>
|
||||
Last-Update: 2018-06-10
|
||||
|
||||
--- a/adm/cmake/occt_defs_flags.cmake
|
||||
+++ b/adm/cmake/occt_defs_flags.cmake
|
||||
@@ -138,5 +138,5 @@
|
||||
set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s")
|
||||
endif()
|
||||
|
||||
-set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNo_Exception")
|
||||
-set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNo_Exception")
|
||||
+#set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNo_Exception")
|
||||
+#set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNo_Exception")
|
||||
@@ -1,99 +0,0 @@
|
||||
diff --git a/src/Message/Message_PrinterSystemLog.cxx b/src/Message/Message_PrinterSystemLog.cxx
|
||||
index 0c82c2167..a2e9e6d68 100644
|
||||
--- a/src/Message/Message_PrinterSystemLog.cxx
|
||||
+++ b/src/Message/Message_PrinterSystemLog.cxx
|
||||
@@ -55,27 +55,6 @@
|
||||
return ANDROID_LOG_DEBUG;
|
||||
}
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
- #include <emscripten/emscripten.h>
|
||||
-
|
||||
- //! Print message to console.debug().
|
||||
- EM_JS(void, occJSConsoleDebug, (const char* theStr), {
|
||||
- console.debug(UTF8ToString(theStr));
|
||||
- });
|
||||
-
|
||||
- //! Print message to console.info().
|
||||
- EM_JS(void, occJSConsoleInfo, (const char* theStr), {
|
||||
- console.info(UTF8ToString(theStr));
|
||||
- });
|
||||
-
|
||||
- //! Print message to console.warn().
|
||||
- EM_JS(void, occJSConsoleWarn, (const char* theStr), {
|
||||
- console.warn(UTF8ToString(theStr));
|
||||
- });
|
||||
-
|
||||
- //! Print message to console.error().
|
||||
- EM_JS(void, occJSConsoleError, (const char* theStr), {
|
||||
- console.error(UTF8ToString(theStr));
|
||||
- });
|
||||
#else
|
||||
#include <syslog.h>
|
||||
|
||||
@@ -169,16 +148,6 @@ void Message_PrinterSystemLog::send (const TCollection_AsciiString& theString,
|
||||
#elif defined(__ANDROID__)
|
||||
__android_log_write (getAndroidLogPriority (theGravity), myEventSourceName.ToCString(), theString.ToCString());
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
- // don't use bogus emscripten_log() corrupting UNICODE strings
|
||||
- switch (theGravity)
|
||||
- {
|
||||
- case Message_Trace: occJSConsoleDebug(theString.ToCString()); return;
|
||||
- case Message_Info: occJSConsoleInfo (theString.ToCString()); return;
|
||||
- case Message_Warning: occJSConsoleWarn (theString.ToCString()); return;
|
||||
- case Message_Alarm: occJSConsoleError(theString.ToCString()); return;
|
||||
- case Message_Fail: occJSConsoleError(theString.ToCString()); return;
|
||||
- }
|
||||
- occJSConsoleWarn (theString.ToCString());
|
||||
#else
|
||||
syslog (getSysLogPriority (theGravity), "%s", theString.ToCString());
|
||||
#endif
|
||||
diff --git a/src/OSD/OSD_MemInfo.cxx b/src/OSD/OSD_MemInfo.cxx
|
||||
index 08a939beb..7c1fc79b3 100644
|
||||
--- a/src/OSD/OSD_MemInfo.cxx
|
||||
+++ b/src/OSD/OSD_MemInfo.cxx
|
||||
@@ -37,15 +37,6 @@
|
||||
|
||||
#include <OSD_MemInfo.hxx>
|
||||
|
||||
-#if defined(__EMSCRIPTEN__)
|
||||
- #include <emscripten.h>
|
||||
-
|
||||
- //! Return WebAssembly heap size in bytes.
|
||||
- EM_JS(size_t, OSD_MemInfo_getModuleHeapLength, (), {
|
||||
- return Module.HEAP8.length;
|
||||
- });
|
||||
-#endif
|
||||
-
|
||||
// =======================================================================
|
||||
// function : OSD_MemInfo
|
||||
// purpose :
|
||||
@@ -156,29 +147,6 @@ void OSD_MemInfo::Update()
|
||||
}
|
||||
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
- if (IsActive (MemHeapUsage)
|
||||
- || IsActive (MemWorkingSet)
|
||||
- || IsActive (MemWorkingSetPeak))
|
||||
- {
|
||||
- // /proc/%d/status is not emulated - get more info from mallinfo()
|
||||
- const struct mallinfo aMI = mallinfo();
|
||||
- if (IsActive (MemHeapUsage))
|
||||
- {
|
||||
- myCounters[MemHeapUsage] = aMI.uordblks;
|
||||
- }
|
||||
- if (IsActive (MemWorkingSet))
|
||||
- {
|
||||
- myCounters[MemWorkingSet] = aMI.uordblks;
|
||||
- }
|
||||
- if (IsActive (MemWorkingSetPeak))
|
||||
- {
|
||||
- myCounters[MemWorkingSetPeak] = aMI.usmblks;
|
||||
- }
|
||||
- }
|
||||
- if (IsActive (MemVirtual))
|
||||
- {
|
||||
- myCounters[MemVirtual] = OSD_MemInfo_getModuleHeapLength();
|
||||
- }
|
||||
#elif (defined(__linux__) || defined(__linux))
|
||||
if (IsActive (MemHeapUsage))
|
||||
{
|
||||
@@ -1,29 +0,0 @@
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 95abbe21..293c951c 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -284,10 +284,10 @@ add_subdirectory(COLLADASaxFrameworkLoader)
|
||||
add_subdirectory(COLLADAStreamWriter)
|
||||
|
||||
# building COLLADAValidator app
|
||||
-add_subdirectory(COLLADAValidator)
|
||||
+# add_subdirectory(COLLADAValidator)
|
||||
|
||||
# DAE validator app
|
||||
-add_subdirectory(DAEValidator)
|
||||
+# add_subdirectory(DAEValidator)
|
||||
|
||||
# Library export
|
||||
install(EXPORT LibraryExport DESTINATION ${OPENCOLLADA_INST_CMAKECONFIG} FILE OpenCOLLADATargets.cmake)
|
||||
diff --git a/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp b/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp
|
||||
index 1f9a3eef..dd6f5c59 100644
|
||||
--- a/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp
|
||||
+++ b/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "GeneratedSaxParserUtils.h"
|
||||
#include <math.h>
|
||||
+#include <cmath>
|
||||
#include <memory>
|
||||
#include <string.h>
|
||||
#include <limits>
|
||||
@@ -1,81 +0,0 @@
|
||||
diff --git a/COLLADABaseUtils/include/COLLADABUhash_map.h b/COLLADABaseUtils/include/COLLADABUhash_map.h
|
||||
index 8ab0fb9b..12503bfb 100644
|
||||
--- a/COLLADABaseUtils/include/COLLADABUhash_map.h
|
||||
+++ b/COLLADABaseUtils/include/COLLADABUhash_map.h
|
||||
@@ -32,9 +32,9 @@
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
- #define COLLADABU_HASH_MAP std::tr1::unordered_map
|
||||
- #define COLLADABU_HASH_MULTIMAP std::tr1::unordered_multimap
|
||||
- #define COLLADABU_HASH_SET std::tr1::unordered_set
|
||||
+ #define COLLADABU_HASH_MAP std::unordered_map
|
||||
+ #define COLLADABU_HASH_MULTIMAP std::unordered_multimap
|
||||
+ #define COLLADABU_HASH_SET std::unordered_set
|
||||
#define COLLADABU_HASH_NAMESPACE_OPEN std { namespace tr1
|
||||
#define COLLADABU_HASH_NAMESPACE_CLOSE }
|
||||
#define COLLADABU_HASH_FUN hash
|
||||
@@ -50,12 +50,12 @@
|
||||
#define COLLADABU_HASH_FUN hash
|
||||
#endif
|
||||
#elif defined(__MINGW32__) || defined(__MINGW64__)
|
||||
- #include <tr1/unordered_map>
|
||||
- #include <tr1/unordered_set>
|
||||
+ #include <unordered_map>
|
||||
+ #include <unordered_set>
|
||||
|
||||
- #define COLLADABU_HASH_MAP std::tr1::unordered_map
|
||||
- #define COLLADABU_HASH_MULTIMAP std::tr1::unordered_multimap
|
||||
- #define COLLADABU_HASH_SET std::tr1::unordered_set
|
||||
+ #define COLLADABU_HASH_MAP std::unordered_map
|
||||
+ #define COLLADABU_HASH_MULTIMAP std::unordered_multimap
|
||||
+ #define COLLADABU_HASH_SET std::unordered_set
|
||||
#define COLLADABU_HASH_NAMESPACE_OPEN std { namespace tr1
|
||||
#define COLLADABU_HASH_NAMESPACE_CLOSE }
|
||||
#define COLLADABU_HASH_FUN hash
|
||||
@@ -107,12 +107,12 @@
|
||||
#define COLLADABU_HASH_NAMESPACE_CLOSE
|
||||
#define COLLADABU_HASH_FUN hash
|
||||
#else
|
||||
- #include <tr1/unordered_map>
|
||||
- #include <tr1/unordered_set>
|
||||
+ #include <unordered_map>
|
||||
+ #include <unordered_set>
|
||||
|
||||
- #define COLLADABU_HASH_MAP std::tr1::unordered_map
|
||||
- #define COLLADABU_HASH_MULTIMAP std::tr1::unordered_multimap
|
||||
- #define COLLADABU_HASH_SET std::tr1::unordered_set
|
||||
+ #define COLLADABU_HASH_MAP std::unordered_map
|
||||
+ #define COLLADABU_HASH_MULTIMAP std::unordered_multimap
|
||||
+ #define COLLADABU_HASH_SET std::unordered_set
|
||||
#define COLLADABU_HASH_NAMESPACE_OPEN std { namespace tr1
|
||||
#define COLLADABU_HASH_NAMESPACE_CLOSE }
|
||||
#define COLLADABU_HASH_FUN hash
|
||||
diff --git a/common/libBuffer/include/CommonFWriteBufferFlusher.h b/common/libBuffer/include/CommonFWriteBufferFlusher.h
|
||||
index c7af45b2..fac4f133 100644
|
||||
--- a/common/libBuffer/include/CommonFWriteBufferFlusher.h
|
||||
+++ b/common/libBuffer/include/CommonFWriteBufferFlusher.h
|
||||
@@ -15,12 +15,12 @@
|
||||
|
||||
#if (defined(WIN64) || defined(_WIN64) || defined(__WIN64__)) || (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__APPLE__))
|
||||
#if defined(__GNUC__) && !defined(_LIBCPP_VERSION)
|
||||
-# include <tr1/unordered_map>
|
||||
+# include <unordered_map>
|
||||
#else
|
||||
# include <unordered_map>
|
||||
#endif
|
||||
#else
|
||||
-# include <tr1/unordered_map>
|
||||
+# include <unordered_map>
|
||||
#endif
|
||||
|
||||
#ifdef _LIBCPP_VERSION
|
||||
@@ -58,7 +58,7 @@ namespace Common
|
||||
#else
|
||||
typedef __int64 FilePosType;
|
||||
#endif
|
||||
- typedef std::tr1::unordered_map<MarkId, FilePosType > MarkIdToFilePos;
|
||||
+ typedef std::unordered_map<MarkId, FilePosType > MarkIdToFilePos;
|
||||
|
||||
public:
|
||||
static const size_t DEFAUL_BUFFER_SIZE = 64*1024;
|
||||
@@ -1,22 +0,0 @@
|
||||
From a0deb4ce8b43cf3c8b8c0a4225c6be5296446dbd Mon Sep 17 00:00:00 2001
|
||||
From: Adam Eri <adam.eri@blackmirror.media>
|
||||
Date: Tue, 3 Sep 2019 23:30:20 +0200
|
||||
Subject: [PATCH] Resolves compile error on macOS
|
||||
|
||||
Resolves "no member named 'isnan' in namespace 'std'" on macOS
|
||||
---
|
||||
GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp b/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp
|
||||
index 1f9a3eef..dd6f5c59 100644
|
||||
--- a/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp
|
||||
+++ b/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "GeneratedSaxParserUtils.h"
|
||||
#include <math.h>
|
||||
+#include <cmath>
|
||||
#include <memory>
|
||||
#include <string.h>
|
||||
#include <limits>
|
||||
@@ -1,18 +0,0 @@
|
||||
package:
|
||||
name: ifcopenshell
|
||||
version: 0.7.0
|
||||
|
||||
source:
|
||||
path: IfcOpenShell
|
||||
|
||||
build:
|
||||
script: |
|
||||
python nix/build-all.py --without-hdf5 --without-opencollada --without-swig --without-pcre -v --wasm --py310 IfcOpenShell-Python
|
||||
cp pyodide/setup.py .
|
||||
|
||||
about:
|
||||
home: http://ifcopenshell.org
|
||||
license: LGPL-3.0-or-later
|
||||
summary: |
|
||||
IfcOpenShell is an open source (LGPL) software library for
|
||||
working with the Industry Foundation Classes (IFC) file format.
|
||||
@@ -1,11 +0,0 @@
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(name='IfcOpenShell',
|
||||
version='0.7.0',
|
||||
description='IfcOpenShell is an open source (LGPL) software library for working with the Industry Foundation Classes (IFC) file format.',
|
||||
author='Thomas Krijnen',
|
||||
author_email='thomas@aecgeeks.com',
|
||||
url='http://ifcopenshell.org',
|
||||
packages=find_packages(),
|
||||
package_data={'': ['*.so']},
|
||||
)
|
||||
@@ -1,2 +0,0 @@
|
||||
[tool.black]
|
||||
line-length = 120
|
||||
@@ -1,64 +0,0 @@
|
||||
# ****************************************************************************
|
||||
# line endings
|
||||
|
||||
# to suppress line ending changes in github, add ?w=1 at link end of a diff
|
||||
|
||||
# for more information see
|
||||
# FreeCAD source code src/Mod/.gitattributes
|
||||
# FreeCAD forum topic https://forum.freecadweb.org/viewtopic.php?f=17&t=41117
|
||||
# FreeCAD pull request https://github.com/FreeCAD/FreeCAD/pull/2752
|
||||
|
||||
|
||||
# get all used file types
|
||||
|
||||
# in a directory in a bash use
|
||||
# find . -type f -name '*.*' | sed 's|.*\.||' | sort -u
|
||||
|
||||
# search for a specific file ending
|
||||
# find . -type f -name '*.ico'
|
||||
|
||||
|
||||
# normalize the line endings of the following files
|
||||
*.cpp text
|
||||
*.css text
|
||||
*.csv text
|
||||
*.feature text
|
||||
*.gitattributes text
|
||||
*.gitignore text
|
||||
*.gitkeep
|
||||
*.h text
|
||||
*.html text
|
||||
*.ifc text
|
||||
*.json text
|
||||
*.md text
|
||||
*.po text
|
||||
*.pot text
|
||||
*.py text
|
||||
*.txt text
|
||||
|
||||
|
||||
# files not normalized ATM
|
||||
# bat
|
||||
# bnf
|
||||
# blend
|
||||
# i
|
||||
# ico
|
||||
# mo
|
||||
# mpass
|
||||
# png
|
||||
# pth
|
||||
# pyc
|
||||
# rst
|
||||
# svg
|
||||
# ttf
|
||||
# xsd
|
||||
|
||||
|
||||
# line endings of all directories will be normalized
|
||||
# to exclude a directory from being normalized add it here
|
||||
# example: to exclude dirctory ifcbimtester use the following line without #
|
||||
# ifcbimtester/** -text
|
||||
|
||||
|
||||
# use git to manually correct the file endings
|
||||
# git add --renormalize .
|
||||
@@ -1 +0,0 @@
|
||||
.tox
|
||||
-621
@@ -1,621 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
@@ -1,165 +0,0 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
@@ -1,2 +0,0 @@
|
||||
include src/bcf/v2/xsd/*.xsd
|
||||
include src/bcf/v3/xsd/*.xsd
|
||||
@@ -1,37 +0,0 @@
|
||||
.PHONY: test
|
||||
test:
|
||||
tox
|
||||
|
||||
.PHONY: qa
|
||||
qa:
|
||||
black .
|
||||
isort .
|
||||
pylint ./src --output-format=colorized
|
||||
|
||||
.PHONY: typecheck
|
||||
typecheck:
|
||||
mypy src/bcf
|
||||
|
||||
.PHONY: license
|
||||
license:
|
||||
copyright-header --license LGPL3 --copyright-holder "Andrea Ghensi <andrea.ghensi@gmail.com>" --copyright-year "2022" --copyright-software "IfcOpenShell" --copyright-software-description "BCF XML file handling" -a ./ -o ./
|
||||
|
||||
.PHONY: coverage
|
||||
coverage:
|
||||
coverage run --source bcf -m pytest tests
|
||||
coverage html
|
||||
xdg-open htmlcov/index.html
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf htmlcov
|
||||
|
||||
# TODO: make this based on xsd file presence
|
||||
.PHONY: models
|
||||
models:
|
||||
cd src && xsdata generate -p bcf.v2.model --unnest-classes --kw-only --slots -ds Google bcf/v2/xsd
|
||||
cd src && xsdata generate -p bcf.v3.model --unnest-classes --kw-only --slots -ds Google bcf/v3/xsd
|
||||
|
||||
# .PHONY
|
||||
# api:
|
||||
# openapi-python-client generate --url https://api.swaggerhub.com/apis/buildingSMART/BCF/3.0
|
||||
@@ -1,84 +0,0 @@
|
||||
# bcf
|
||||
|
||||
A simple Python implementation of BCF.
|
||||
Manipulation of BCF-XML is available via `bcfxml.py` and manipulation of BCF-API
|
||||
is available via `bcfapi.py`.
|
||||
|
||||
It tries to support BCF-XML version 2.1 and 3.0, and BCF-API 3.0.
|
||||
|
||||
## bcfxml
|
||||
|
||||
The `bcfxml.load` function lets you read a BCF-XML file.
|
||||
It takes care of using the right version based on the "bcf.version" file contained in the BCF package.
|
||||
|
||||
The BCF files are extracted and parsed on-demand, and edits are stored in memory until you call the `save` method.
|
||||
|
||||
```python
|
||||
from bcf.bcfxml import load
|
||||
|
||||
# Load a project
|
||||
with load("/path/to/file.bcf") as bcfxml:
|
||||
project = bcfxml.project
|
||||
print(project.name)
|
||||
|
||||
# To edit a project, just modify the object directly
|
||||
bcfxml.project.name = "New name"
|
||||
|
||||
# Get a dictionary of topics
|
||||
topics = bcfxml.topics
|
||||
|
||||
for topic_handler in bcfxml.topics:
|
||||
topic = topic_handler.topic
|
||||
print("Topic guid is", topic.guid)
|
||||
print("Topic title is", topic.title)
|
||||
|
||||
# Fetch extra data about a topic
|
||||
header = topic_handler.header
|
||||
comments = topic_handler.comments
|
||||
viewpoints = topic_handler.viewpoints
|
||||
|
||||
for comment in comments:
|
||||
print(comment.guid)
|
||||
print(comment.comment)
|
||||
print(comment.author)
|
||||
|
||||
# Get a particular topic
|
||||
topic = bcfxml.get_topic(guid)
|
||||
|
||||
# Modify a topic
|
||||
topic.title = "New title"
|
||||
|
||||
bcfxml.save()
|
||||
```
|
||||
|
||||
## bcfapi
|
||||
|
||||
The `bcfapi` module lets you interact with the BCF-API standard.
|
||||
|
||||
```python
|
||||
from bcf.v3.bcfapi import FoundationClient, BcfClient
|
||||
|
||||
foundation_client = FoundationClient("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET", "OPENCDE_BASEURL")
|
||||
auth_methods = foundation_client.get_auth_methods()
|
||||
|
||||
# Our library currently only implements the authorization_code flow
|
||||
if "authorization_code" in auth_methods:
|
||||
foundation_client.login()
|
||||
|
||||
bcf_client = BcfClient(foundation_client)
|
||||
|
||||
versions = foundation_client.get_versions()
|
||||
for version in versions:
|
||||
if "3.0" in versions:
|
||||
if version["api_id"] == "bcf" and version["version_id"] == "3.0":
|
||||
bcf_client.set_version(version)
|
||||
|
||||
data = bcf_client.get_projects()
|
||||
print(data)
|
||||
project_id = data[0]["project_id"]
|
||||
print(project_id)
|
||||
data = bcf_client.get_project(project_id)
|
||||
print(data)
|
||||
data = bcf_client.get_extensions(project_id)
|
||||
print(data)
|
||||
```
|
||||
@@ -1,7 +0,0 @@
|
||||
name: bcf-client
|
||||
channels:
|
||||
- conda-forge
|
||||
dependencies:
|
||||
- ifcopenshell
|
||||
- xsdata
|
||||
- numpy
|
||||
@@ -1,126 +0,0 @@
|
||||
[build-system]
|
||||
requires = [
|
||||
"setuptools>=61",
|
||||
"wheel"
|
||||
]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "bcf-client"
|
||||
# author = "IfcOpenShell"
|
||||
description = "BCF-XML file handler."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.8"
|
||||
keywords = ["IFC", "BCF", "BIM", "eingineering"]
|
||||
dependencies = [
|
||||
"xsdata",
|
||||
"numpy",
|
||||
]
|
||||
version = "0.0.1"
|
||||
classifiers = [
|
||||
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Topic :: Scientific/Engineering",
|
||||
"Topic :: Utilities",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Source = "https://github.com/IfcOpenShell/IfcOpenShell"
|
||||
Issues = "https://github.com/IfcOpenShell/IfcOpenShell/issues"
|
||||
|
||||
[tool.black]
|
||||
line-length = 120
|
||||
extend-exclude = "model"
|
||||
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
extend_skip_glob = ["src/bcf/*/model/*"]
|
||||
|
||||
[tool.coverage.paths]
|
||||
source = ["src"]
|
||||
|
||||
[tool.coverage.run]
|
||||
branch = true
|
||||
source = ["bcf"]
|
||||
omit = ["*/model/*"]
|
||||
|
||||
[tool.coverage.report]
|
||||
show_missing = true
|
||||
fail_under = 65
|
||||
exclude_lines = [
|
||||
"pragma: no cover",
|
||||
"if TYPE_CHECKING",
|
||||
"if __name__ == .__main__.:",
|
||||
"Protocol",
|
||||
]
|
||||
|
||||
[tool.tox]
|
||||
legacy_tox_ini = """
|
||||
[tox]
|
||||
envlist = py310
|
||||
isolated_build = true
|
||||
skip_missing_interpreters = true
|
||||
requires = tox-conda
|
||||
|
||||
[testenv]
|
||||
conda_deps =
|
||||
pytest
|
||||
pytest-cov
|
||||
coverage
|
||||
conda_channels =
|
||||
conda-forge
|
||||
conda_env = environment.yml
|
||||
commands = pytest --cov --cov-report=term tests
|
||||
"""
|
||||
|
||||
[tool.mypy]
|
||||
check_untyped_defs = true
|
||||
disallow_any_generics = true
|
||||
disallow_incomplete_defs = true
|
||||
disallow_subclassing_any = true
|
||||
disallow_untyped_calls = true
|
||||
disallow_untyped_defs = true
|
||||
no_implicit_optional = true
|
||||
#no_implicit_reexport = true
|
||||
show_column_numbers = true
|
||||
show_error_codes = true
|
||||
show_error_context = true
|
||||
strict_equality = true
|
||||
strict_optional = true
|
||||
warn_redundant_casts = true
|
||||
#warn_return_any = true
|
||||
warn_unreachable = true
|
||||
warn_unused_configs = true
|
||||
warn_unused_ignores = true
|
||||
exclude= "src/bcf/v(2|3)/model"
|
||||
plugins = "numpy.typing.mypy_plugin"
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = "tests"
|
||||
disallow_untyped_decorators = false
|
||||
disallow_untyped_defs = false
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = [
|
||||
"pytest",
|
||||
"pytest_mock",
|
||||
"ifcopenshell",
|
||||
"ifcopenshell.*",
|
||||
]
|
||||
ignore_missing_imports = true
|
||||
|
||||
[tool.pylint.main]
|
||||
ignore = ["model"]
|
||||
ignored-modules = ["bcf.v2.model", "bcf.v3.model", "xsdata"]
|
||||
jobs = 0
|
||||
disable="all"
|
||||
enable="E" # B,B9,BLK,C,D,E,F,I,N,S,W
|
||||
|
||||
[tool.pylint.design]
|
||||
max-args = 10
|
||||
max-attributes = 10
|
||||
|
||||
[tool.pylint.format]
|
||||
expected-line-ending-format = "LF"
|
||||
max-line-length = 120
|
||||
@@ -1,7 +0,0 @@
|
||||
black
|
||||
mypy
|
||||
pylint
|
||||
isort
|
||||
xsdata
|
||||
tox
|
||||
tox-conda
|
||||
@@ -1,3 +0,0 @@
|
||||
from setuptools import setup
|
||||
|
||||
setup()
|
||||
@@ -1,17 +0,0 @@
|
||||
# BCF - BCF Python library
|
||||
# Copyright (C) 2021 Prabhat Singh <singh01prabhat@gmail.com>
|
||||
#
|
||||
# This file is part of BCF.
|
||||
#
|
||||
# BCF is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BCF 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
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with BCF. If not, see <http://www.gnu.org/licenses/>.
|
||||
@@ -1,69 +0,0 @@
|
||||
"""
|
||||
BCF - BCF Python library
|
||||
Copyright (C) 2021 Prabhat Singh <singh01prabhat@gmail.com>
|
||||
Copyright (C) 2022 Andrea Ghensi <andrea.ghensi@gmail.com>
|
||||
|
||||
This file is part of BCF.
|
||||
|
||||
BCF is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
BCF 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
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with BCF. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from typing import Optional, Union
|
||||
|
||||
from bcf.v2.bcfxml import BcfXml as BcfXml2
|
||||
from bcf.v3.bcfxml import BcfXml as BcfXml3
|
||||
from bcf.v3.model import Version
|
||||
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
|
||||
|
||||
|
||||
def load(
|
||||
filepath: Path, xml_handler: Optional[AbstractXmlParserSerializer] = None
|
||||
) -> Optional[Union[BcfXml2, BcfXml3]]:
|
||||
"""
|
||||
Load a BCF file.
|
||||
|
||||
Args:
|
||||
filepath: The path to the BCF file.
|
||||
|
||||
Returns:
|
||||
The loaded BCF file.
|
||||
|
||||
Raises:
|
||||
ValueError: If the BCF version is not supported.
|
||||
"""
|
||||
xml_handler = xml_handler or XmlParserSerializer()
|
||||
version_id = _get_version(filepath, xml_handler)
|
||||
if version_id in {"2.1", "2.0"}:
|
||||
return BcfXml2.load(filepath, xml_handler)
|
||||
if version_id == "3.0":
|
||||
return BcfXml3.load(filepath, xml_handler)
|
||||
raise ValueError(f"Version {version_id} not supported.")
|
||||
|
||||
|
||||
def _get_version(filepath: Union[str, Path], xml_handler: Optional[AbstractXmlParserSerializer] = None) -> str:
|
||||
"""
|
||||
Returns the version of the BCF file.
|
||||
|
||||
Args:
|
||||
filepath: The path to the BCF file.
|
||||
xml_handler: The XML handler. If none is given, XmlParserSerializer is used.
|
||||
|
||||
Returns:
|
||||
The version of the BCF file.
|
||||
"""
|
||||
xml_handler = xml_handler or XmlParserSerializer()
|
||||
with zipfile.ZipFile(filepath) as bcf_zip:
|
||||
version = xml_handler.parse(bcf_zip.read("bcf.version"), Version)
|
||||
return version.version_id
|
||||
@@ -1,44 +0,0 @@
|
||||
import numpy as np
|
||||
from numpy.typing import NDArray
|
||||
|
||||
|
||||
def calc_camera_vectors(
|
||||
elem_placement: NDArray[np.float_],
|
||||
) -> tuple[NDArray[np.float_], NDArray[np.float_], NDArray[np.float_]]:
|
||||
"""
|
||||
Calculate the vectors of a camera pointing to an element.
|
||||
|
||||
Args:
|
||||
elem_placement: Placement matrix of an element.
|
||||
|
||||
Returns:
|
||||
Camera position, direction and up vectors
|
||||
"""
|
||||
target_position = elem_placement[:3, 3]
|
||||
camera_position = target_position + np.array((5, 5, 5))
|
||||
camera_direction = unit_vector(camera_position - target_position)
|
||||
camera_right = unit_vector(np.cross(np.array([0.0, 0.0, 1.0]), camera_direction))
|
||||
camera_up = unit_vector(np.cross(camera_direction, camera_right))
|
||||
rotation_transform = np.eye(4)
|
||||
rotation_transform[0, :3] = camera_right
|
||||
rotation_transform[1, :3] = camera_up
|
||||
rotation_transform[2, :3] = camera_direction
|
||||
translation_transform = np.eye(4)
|
||||
translation_transform[:3, -1] = -camera_position
|
||||
look_at_transform = np.matmul(rotation_transform, translation_transform)
|
||||
mat = np.linalg.inv(look_at_transform)
|
||||
return camera_position, -mat[:3, 2], mat[:3, 1]
|
||||
|
||||
|
||||
def unit_vector(v: NDArray[np.float_]) -> NDArray[np.float_]:
|
||||
"""
|
||||
Return the unit vector of a vector.
|
||||
|
||||
Args:
|
||||
v: vector
|
||||
|
||||
Returns:
|
||||
unit vector.
|
||||
"""
|
||||
norm = np.linalg.norm(v)
|
||||
return v if norm == 0 else v / norm
|
||||
@@ -1,55 +0,0 @@
|
||||
"""
|
||||
In Memory Zip File management, taken from ruamel.std.zipfile
|
||||
|
||||
Copyright (c) 2017-2020 Anthon van der Neut, Ruamel bvba
|
||||
|
||||
original idea from https://stackoverflow.com/a/19722365/1307905
|
||||
"""
|
||||
import zipfile
|
||||
from io import BytesIO
|
||||
from os import PathLike
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional, Protocol
|
||||
|
||||
|
||||
class ZipFileInterface(Protocol):
|
||||
def writestr(self, filename_in_zip: str | zipfile.ZipInfo, file_contents: bytes | str) -> None:
|
||||
...
|
||||
|
||||
|
||||
class InMemoryZipFile:
|
||||
def __init__(
|
||||
self, file_name: Optional[str | Path] = None, compression: int = zipfile.ZIP_DEFLATED, debug: int = 0
|
||||
) -> None:
|
||||
# Create the in-memory file-like object
|
||||
self._file_name: Optional[str | Path] = str(file_name) if hasattr(file_name, "_from_parts") else file_name
|
||||
self.in_memory_data = BytesIO()
|
||||
# Create the in-memory zipfile
|
||||
self.in_memory_zip = zipfile.ZipFile(self.in_memory_data, "w", compression, False)
|
||||
self.in_memory_zip.debug = debug
|
||||
|
||||
def writestr(self, filename_in_zip: str | zipfile.ZipInfo, file_contents: bytes | str) -> None:
|
||||
"""Appends a file with name filename_in_zip and contents of
|
||||
file_contents to the in-memory zip."""
|
||||
self.in_memory_zip.writestr(filename_in_zip, file_contents)
|
||||
|
||||
def write_to_file(self, filename: str | bytes | PathLike[str] | PathLike[bytes] | int) -> None:
|
||||
"""Writes the in-memory zip to a file."""
|
||||
# Mark the files as having been created on Windows so that
|
||||
# Unix permissions are not inferred as 0000
|
||||
for zfile in self.in_memory_zip.filelist:
|
||||
zfile.create_system = 0
|
||||
self.in_memory_zip.close()
|
||||
with open(filename, "wb") as f:
|
||||
f.write(self.data)
|
||||
|
||||
@property
|
||||
def data(self) -> bytes:
|
||||
return self.in_memory_data.getvalue()
|
||||
|
||||
def __enter__(self) -> "InMemoryZipFile":
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
|
||||
if self._file_name:
|
||||
self.write_to_file(self._file_name)
|
||||
@@ -1,17 +0,0 @@
|
||||
# BCF - BCF Python library
|
||||
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BCF.
|
||||
#
|
||||
# BCF is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BCF 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
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with BCF. If not, see <http://www.gnu.org/licenses/>.
|
||||
@@ -1,273 +0,0 @@
|
||||
"""BCF XML V2 handler."""
|
||||
import uuid
|
||||
import warnings
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional, TypeVar
|
||||
|
||||
import bcf.v2.model as mdl
|
||||
from bcf.inmemory_zipfile import InMemoryZipFile, ZipFileInterface
|
||||
from bcf.v2.topic import TopicHandler
|
||||
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class BcfXml:
|
||||
"""BCF XML handler."""
|
||||
|
||||
def __init__(
|
||||
self, filename: Optional[Path] = None, xml_handler: Optional[AbstractXmlParserSerializer] = None
|
||||
) -> None:
|
||||
self._filename = filename
|
||||
self._xml_handler = xml_handler or XmlParserSerializer()
|
||||
self._version: Optional[mdl.Version] = None
|
||||
self._project_info: Optional[mdl.ProjectExtension] = None
|
||||
self._topics: dict[str, TopicHandler] = {}
|
||||
self._extension_schema: Optional[bytes] = None
|
||||
self._zip_file = self._load_zip_file()
|
||||
|
||||
def __enter__(self) -> "BcfXml":
|
||||
return self
|
||||
|
||||
def __exit__(self, *args: Any) -> None:
|
||||
self.close()
|
||||
|
||||
def __del__(self) -> None:
|
||||
self.close()
|
||||
|
||||
def close(self) -> None:
|
||||
if self._zip_file:
|
||||
self._zip_file.close()
|
||||
|
||||
def _load_zip_file(self) -> Optional[zipfile.ZipFile]:
|
||||
return zipfile.ZipFile(self._filename) if self._filename else None
|
||||
|
||||
@property
|
||||
def version(self) -> mdl.Version:
|
||||
"""Bcf Version."""
|
||||
if not self._version:
|
||||
self._version = (
|
||||
self._xml_handler.parse(self._zip_file.read("bcf.version"), mdl.Version)
|
||||
if self._zip_file
|
||||
else mdl.Version(version_id="3.0")
|
||||
)
|
||||
return self._version
|
||||
|
||||
@version.setter
|
||||
def version(self, value: mdl.Version) -> None:
|
||||
self._version = value
|
||||
|
||||
@property
|
||||
def project_info(self) -> Optional[mdl.ProjectExtension]:
|
||||
"""BCF project information."""
|
||||
if not self._project_info and self._zip_file and zipfile.Path(self._zip_file, "project.bcfp").exists():
|
||||
self._project_info = self._xml_handler.parse(self._zip_file.read("project.bcfp"), mdl.ProjectExtension)
|
||||
return self._project_info
|
||||
|
||||
@project_info.setter
|
||||
def project_info(self, value: Optional[mdl.ProjectExtension]) -> None:
|
||||
self._project_info = value
|
||||
|
||||
@property
|
||||
def project(self) -> Optional[mdl.Project]:
|
||||
"""BCF project."""
|
||||
return self.project_info.project if self.project_info else None
|
||||
|
||||
@property
|
||||
def extension_schema(self) -> Optional[bytes]:
|
||||
if not self._extension_schema and self._zip_file and self.project_info and self.project_info.extension_schema:
|
||||
self._extension_schema = self._zip_file.read(self.project_info.extension_schema)
|
||||
return self._extension_schema
|
||||
|
||||
@extension_schema.setter
|
||||
def extension_schema(self, value: bytes) -> None:
|
||||
self._extension_schema = value
|
||||
|
||||
@property
|
||||
def topics(self) -> dict[str, TopicHandler]:
|
||||
"""BCF topics."""
|
||||
if not self._topics and self._zip_file:
|
||||
self._topics = self._load_topics(self._zip_file, self._xml_handler)
|
||||
return self._topics
|
||||
|
||||
def _load_topics(
|
||||
self, zip_file: zipfile.ZipFile, xml_handler: AbstractXmlParserSerializer
|
||||
) -> dict[str, TopicHandler]:
|
||||
topics = {}
|
||||
for topic_dir in zipfile.Path(zip_file).iterdir():
|
||||
if not topic_dir.is_dir():
|
||||
continue
|
||||
markup_path = topic_dir.joinpath("markup.bcf")
|
||||
if not markup_path.exists():
|
||||
continue
|
||||
topics[topic_dir.name] = TopicHandler(topic_dir, xml_handler)
|
||||
return topics
|
||||
|
||||
@classmethod
|
||||
def load(cls, filename: Path, xml_handler: Optional[AbstractXmlParserSerializer] = None) -> Optional["BcfXml"]:
|
||||
"""
|
||||
Create a BcfXml object from a file.
|
||||
|
||||
Args:
|
||||
filename: Path to the file.
|
||||
xml_handler: XML parser and serializer.
|
||||
|
||||
Returns:
|
||||
A BcfXml object with the file contents.
|
||||
|
||||
Raises:
|
||||
ValueError: If the file name is null or empty
|
||||
"""
|
||||
if not filename:
|
||||
raise ValueError("filename is required")
|
||||
xml_handler = xml_handler or XmlParserSerializer()
|
||||
return cls(xml_handler=xml_handler, filename=filename)
|
||||
|
||||
@classmethod
|
||||
def create_new(
|
||||
cls,
|
||||
project_name: Optional[str] = None,
|
||||
xml_handler: Optional[AbstractXmlParserSerializer] = None,
|
||||
) -> "BcfXml":
|
||||
"""
|
||||
Create a new BcfXml object.
|
||||
|
||||
Args:
|
||||
project_name: The name of the project.
|
||||
xml_handler: XML parser and serializer.
|
||||
|
||||
Returns:
|
||||
A new BcfXml object.
|
||||
"""
|
||||
instance = cls(xml_handler=xml_handler or XmlParserSerializer())
|
||||
instance.project_info = mdl.ProjectExtension(
|
||||
project=mdl.Project(name=project_name, project_id=str(uuid.uuid4())), extension_schema=""
|
||||
)
|
||||
return instance
|
||||
|
||||
def save(self, filename: Optional[Path] = None, keep_open: bool = False) -> None:
|
||||
"""Save the BCF file to the given filename."""
|
||||
if not filename and not self._filename:
|
||||
raise ValueError("No file name specified, cannot save BCF file.")
|
||||
if filename:
|
||||
self._filename = filename
|
||||
with InMemoryZipFile(self._filename) as bcf_zip:
|
||||
self._save_project(bcf_zip)
|
||||
self._save_version(bcf_zip)
|
||||
self._save_topics(bcf_zip)
|
||||
if keep_open:
|
||||
self._zip_file = self._load_zip_file()
|
||||
|
||||
def _save_project(self, destination_zip: ZipFileInterface) -> None:
|
||||
self._smart_save_xml(destination_zip, self._project_info, "project.bcfp")
|
||||
if self.extension_schema and self.project_info:
|
||||
destination_zip.writestr(self.project_info.extension_schema, self.extension_schema)
|
||||
|
||||
def _save_version(self, destination_zip: ZipFileInterface) -> None:
|
||||
if not self._version and self._zip_file:
|
||||
destination_zip.writestr("bcf.version", self._zip_file.read("bcf.version"))
|
||||
else:
|
||||
self._save_xml(destination_zip, "bcf.version", self.version)
|
||||
|
||||
def _smart_save_xml(self, destination_zip: ZipFileInterface, item: Any, target: str) -> None:
|
||||
if item:
|
||||
self._save_xml(destination_zip, target, item)
|
||||
elif self._zip_file and zipfile.Path(self._zip_file, target).exists():
|
||||
destination_zip.writestr(target, self._zip_file.read(target))
|
||||
|
||||
def _save_xml(self, destination_zip: ZipFileInterface, inner_file: str, xml_obj: Any) -> None:
|
||||
destination_zip.writestr(inner_file, self._xml_handler.serialize(xml_obj))
|
||||
|
||||
def _save_topics(self, destination_zip: ZipFileInterface) -> None:
|
||||
for topic_handler in self.topics.values():
|
||||
topic_handler.save(destination_zip)
|
||||
|
||||
def add_topic(
|
||||
self, title: str, description: str, author: str, topic_type: str = "", topic_status: str = ""
|
||||
) -> TopicHandler:
|
||||
"""
|
||||
Add a new topic to the BCF.
|
||||
|
||||
Args:
|
||||
title: The title of the topic.
|
||||
description: The description of the topic.
|
||||
author: The author of the topic.
|
||||
topic_type: The type of the topic.
|
||||
topic_status: The status of the topic.
|
||||
|
||||
Returns:
|
||||
The newly created topic wrapped inside a TopicHandler object.
|
||||
"""
|
||||
topic_handler = TopicHandler.create_new(
|
||||
title,
|
||||
description,
|
||||
author,
|
||||
topic_type=topic_type,
|
||||
topic_status=topic_status,
|
||||
xml_handler=self._xml_handler,
|
||||
)
|
||||
self.topics[topic_handler.guid] = topic_handler
|
||||
return topic_handler
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if not isinstance(other, BcfXml):
|
||||
raise TypeError("Equality needs a BcfXml object.")
|
||||
return self.version == other.version and self.project_info == other.project_info
|
||||
|
||||
# region Deprecated methods
|
||||
def new_project(self) -> "BcfXml":
|
||||
"""Deprecated method."""
|
||||
warnings.warn("new_project is deprecated, use create_new instead.", DeprecationWarning)
|
||||
return self.create_new()
|
||||
|
||||
def get_project(self, _filepath: Optional[str] = None) -> Optional[mdl.Project]:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("get_project is deprecated, use project_info.project instead.", DeprecationWarning)
|
||||
return self.project
|
||||
|
||||
def edit_project(self) -> None:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("edit_project is deprecated, there's no need to use it.", DeprecationWarning)
|
||||
|
||||
def save_project(self, filepath: Path) -> None:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("save_project is deprecated, use save instead.", DeprecationWarning)
|
||||
self.save(filepath)
|
||||
|
||||
def get_version(self) -> Optional[str]:
|
||||
warnings.warn("get_version is deprecated, use version.version_id instead.", DeprecationWarning)
|
||||
return self.version.version_id
|
||||
|
||||
def edit_version(self) -> None:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("edit_version is deprecated, there's no need to use it.", DeprecationWarning)
|
||||
|
||||
def get_topics(self) -> dict[str, TopicHandler]:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("get_topics is deprecated, use topics instead.", DeprecationWarning)
|
||||
return self.topics
|
||||
|
||||
def get_topic(self, guid: str) -> TopicHandler:
|
||||
"""Return a topic by its GUID."""
|
||||
warnings.warn("get_topic is deprecated, use topics[guid] instead", DeprecationWarning)
|
||||
return self.topics[guid]
|
||||
|
||||
def get_header(self, guid: str) -> Optional[mdl.Header]:
|
||||
"""Return the header of a Topic by its GUID."""
|
||||
return self.topics[guid].header
|
||||
|
||||
def edit_topic(self) -> None:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("edit_topic is deprecated, there's no need to use it.", DeprecationWarning)
|
||||
|
||||
def add_comment(self, _topic: mdl.Topic, _comment: Optional[mdl.Comment] = None) -> None:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("add_comment is deprecated, use topics methods instead.", DeprecationWarning)
|
||||
|
||||
def edit_comment(self) -> None:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("edit_comment is deprecated, there's no need to use it.", DeprecationWarning)
|
||||
|
||||
# TODO: deprecate other methods
|
||||
# endregion
|
||||
@@ -1,70 +0,0 @@
|
||||
from bcf.v2.model.markup import (
|
||||
BimSnippet,
|
||||
Comment,
|
||||
CommentViewpoint,
|
||||
Header,
|
||||
HeaderFile,
|
||||
Markup,
|
||||
Topic,
|
||||
TopicDocumentReference,
|
||||
TopicRelatedTopic,
|
||||
ViewPoint,
|
||||
)
|
||||
from bcf.v2.model.project import Project, ProjectExtension
|
||||
from bcf.v2.model.version import Version
|
||||
from bcf.v2.model.visinfo import (
|
||||
BitmapFormat,
|
||||
ClippingPlane,
|
||||
Component,
|
||||
ComponentColoring,
|
||||
ComponentColoringColor,
|
||||
Components,
|
||||
ComponentSelection,
|
||||
ComponentVisibility,
|
||||
ComponentVisibilityExceptions,
|
||||
Direction,
|
||||
Line,
|
||||
OrthogonalCamera,
|
||||
PerspectiveCamera,
|
||||
Point,
|
||||
ViewSetupHints,
|
||||
VisualizationInfo,
|
||||
VisualizationInfoBitmap,
|
||||
VisualizationInfoClippingPlanes,
|
||||
VisualizationInfoLines,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"BimSnippet",
|
||||
"Comment",
|
||||
"CommentViewpoint",
|
||||
"Header",
|
||||
"HeaderFile",
|
||||
"Markup",
|
||||
"Topic",
|
||||
"TopicDocumentReference",
|
||||
"TopicRelatedTopic",
|
||||
"ViewPoint",
|
||||
"Project",
|
||||
"ProjectExtension",
|
||||
"Version",
|
||||
"BitmapFormat",
|
||||
"ClippingPlane",
|
||||
"Component",
|
||||
"ComponentColoring",
|
||||
"ComponentColoringColor",
|
||||
"ComponentSelection",
|
||||
"ComponentVisibility",
|
||||
"ComponentVisibilityExceptions",
|
||||
"Components",
|
||||
"Direction",
|
||||
"Line",
|
||||
"OrthogonalCamera",
|
||||
"PerspectiveCamera",
|
||||
"Point",
|
||||
"ViewSetupHints",
|
||||
"VisualizationInfo",
|
||||
"VisualizationInfoBitmap",
|
||||
"VisualizationInfoClippingPlanes",
|
||||
"VisualizationInfoLines",
|
||||
]
|
||||
@@ -1,461 +0,0 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Optional
|
||||
|
||||
from xsdata.models.datatype import XmlDateTime
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class BimSnippet:
|
||||
reference: str = field(
|
||||
metadata={
|
||||
"name": "Reference",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
reference_schema: str = field(
|
||||
metadata={
|
||||
"name": "ReferenceSchema",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
snippet_type: str = field(
|
||||
metadata={
|
||||
"name": "SnippetType",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
is_external: bool = field(
|
||||
default=False,
|
||||
metadata={
|
||||
"name": "isExternal",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class CommentViewpoint:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
guid: str = field(
|
||||
metadata={
|
||||
"name": "Guid",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"pattern": r"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class HeaderFile:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
filename: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Filename",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
date: Optional[XmlDateTime] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Date",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
reference: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Reference",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
ifc_project: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "IfcProject",
|
||||
"type": "Attribute",
|
||||
"length": 22,
|
||||
"pattern": r"[0-9,A-Z,a-z,_$]*",
|
||||
}
|
||||
)
|
||||
ifc_spatial_structure_element: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "IfcSpatialStructureElement",
|
||||
"type": "Attribute",
|
||||
"length": 22,
|
||||
"pattern": r"[0-9,A-Z,a-z,_$]*",
|
||||
}
|
||||
)
|
||||
is_external: bool = field(
|
||||
default=True,
|
||||
metadata={
|
||||
"name": "isExternal",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class TopicDocumentReference:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
referenced_document: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "ReferencedDocument",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
description: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Description",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
guid: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Guid",
|
||||
"type": "Attribute",
|
||||
"pattern": r"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}",
|
||||
}
|
||||
)
|
||||
is_external: bool = field(
|
||||
default=False,
|
||||
metadata={
|
||||
"name": "isExternal",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class TopicRelatedTopic:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
guid: str = field(
|
||||
metadata={
|
||||
"name": "Guid",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"pattern": r"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ViewPoint:
|
||||
viewpoint: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Viewpoint",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
snapshot: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Snapshot",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
index: Optional[int] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Index",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
guid: str = field(
|
||||
metadata={
|
||||
"name": "Guid",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"pattern": r"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Comment:
|
||||
date: XmlDateTime = field(
|
||||
metadata={
|
||||
"name": "Date",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
author: str = field(
|
||||
metadata={
|
||||
"name": "Author",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
comment: str = field(
|
||||
metadata={
|
||||
"name": "Comment",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
viewpoint: Optional[CommentViewpoint] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Viewpoint",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
modified_date: Optional[XmlDateTime] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "ModifiedDate",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
modified_author: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "ModifiedAuthor",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
guid: str = field(
|
||||
metadata={
|
||||
"name": "Guid",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"pattern": r"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Header:
|
||||
file: List[HeaderFile] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "File",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_occurs": 1,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Topic:
|
||||
reference_link: List[str] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "ReferenceLink",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
title: str = field(
|
||||
metadata={
|
||||
"name": "Title",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
priority: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Priority",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
index: Optional[int] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Index",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
labels: List[str] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Labels",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
creation_date: XmlDateTime = field(
|
||||
metadata={
|
||||
"name": "CreationDate",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
creation_author: str = field(
|
||||
metadata={
|
||||
"name": "CreationAuthor",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
modified_date: Optional[XmlDateTime] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "ModifiedDate",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
modified_author: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "ModifiedAuthor",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
due_date: Optional[XmlDateTime] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "DueDate",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
assigned_to: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "AssignedTo",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
stage: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Stage",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
description: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Description",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
bim_snippet: Optional[BimSnippet] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "BimSnippet",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
document_reference: List[TopicDocumentReference] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "DocumentReference",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
related_topic: List[TopicRelatedTopic] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "RelatedTopic",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
guid: str = field(
|
||||
metadata={
|
||||
"name": "Guid",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"pattern": r"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}",
|
||||
}
|
||||
)
|
||||
topic_type: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "TopicType",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
topic_status: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "TopicStatus",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Markup:
|
||||
header: Optional[Header] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Header",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
topic: Topic = field(
|
||||
metadata={
|
||||
"name": "Topic",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
comment: List[Comment] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Comment",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
viewpoints: List[ViewPoint] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Viewpoints",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
@@ -1,41 +0,0 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Project:
|
||||
name: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Name",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
project_id: str = field(
|
||||
metadata={
|
||||
"name": "ProjectId",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ProjectExtension:
|
||||
project: Optional[Project] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Project",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
extension_schema: str = field(
|
||||
metadata={
|
||||
"name": "ExtensionSchema",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
@@ -1,21 +0,0 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Version:
|
||||
detailed_version: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "DetailedVersion",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
version_id: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "VersionId",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
@@ -1,476 +0,0 @@
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from typing import List, Optional
|
||||
|
||||
|
||||
class BitmapFormat(Enum):
|
||||
PNG = "PNG"
|
||||
JPG = "JPG"
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Component:
|
||||
originating_system: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "OriginatingSystem",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
authoring_tool_id: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "AuthoringToolId",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
ifc_guid: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "IfcGuid",
|
||||
"type": "Attribute",
|
||||
"length": 22,
|
||||
"pattern": r"[0-9,A-Z,a-z,_$]*",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Direction:
|
||||
x: float = field(
|
||||
metadata={
|
||||
"name": "X",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
y: float = field(
|
||||
metadata={
|
||||
"name": "Y",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
z: float = field(
|
||||
metadata={
|
||||
"name": "Z",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Point:
|
||||
x: float = field(
|
||||
metadata={
|
||||
"name": "X",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
y: float = field(
|
||||
metadata={
|
||||
"name": "Y",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
z: float = field(
|
||||
metadata={
|
||||
"name": "Z",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ViewSetupHints:
|
||||
spaces_visible: Optional[bool] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "SpacesVisible",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
space_boundaries_visible: Optional[bool] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "SpaceBoundariesVisible",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
openings_visible: Optional[bool] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "OpeningsVisible",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ClippingPlane:
|
||||
location: Point = field(
|
||||
metadata={
|
||||
"name": "Location",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
direction: Direction = field(
|
||||
metadata={
|
||||
"name": "Direction",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ComponentColoringColor:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
component: List[Component] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Component",
|
||||
"type": "Element",
|
||||
"min_occurs": 1,
|
||||
}
|
||||
)
|
||||
color: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Color",
|
||||
"type": "Attribute",
|
||||
"pattern": r"[0-9,a-f,A-F]{6}([0-9,a-f,A-F]{2})?",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ComponentSelection:
|
||||
component: List[Component] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Component",
|
||||
"type": "Element",
|
||||
"min_occurs": 1,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ComponentVisibilityExceptions:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
component: List[Component] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Component",
|
||||
"type": "Element",
|
||||
"min_occurs": 1,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Line:
|
||||
start_point: Point = field(
|
||||
metadata={
|
||||
"name": "StartPoint",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
end_point: Point = field(
|
||||
metadata={
|
||||
"name": "EndPoint",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class OrthogonalCamera:
|
||||
"""
|
||||
Attributes
|
||||
camera_view_point:
|
||||
camera_direction:
|
||||
camera_up_vector:
|
||||
view_to_world_scale: view's visible size in meters
|
||||
"""
|
||||
camera_view_point: Point = field(
|
||||
metadata={
|
||||
"name": "CameraViewPoint",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
camera_direction: Direction = field(
|
||||
metadata={
|
||||
"name": "CameraDirection",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
camera_up_vector: Direction = field(
|
||||
metadata={
|
||||
"name": "CameraUpVector",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
view_to_world_scale: float = field(
|
||||
metadata={
|
||||
"name": "ViewToWorldScale",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class PerspectiveCamera:
|
||||
"""
|
||||
Attributes
|
||||
camera_view_point:
|
||||
camera_direction:
|
||||
camera_up_vector:
|
||||
field_of_view: It is currently limited to a value between 45 and
|
||||
60 degrees. This limitation will be dropped in the next
|
||||
release and viewers should be expect values outside this
|
||||
range in current implementations.
|
||||
"""
|
||||
camera_view_point: Point = field(
|
||||
metadata={
|
||||
"name": "CameraViewPoint",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
camera_direction: Direction = field(
|
||||
metadata={
|
||||
"name": "CameraDirection",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
camera_up_vector: Direction = field(
|
||||
metadata={
|
||||
"name": "CameraUpVector",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
field_of_view: float = field(
|
||||
metadata={
|
||||
"name": "FieldOfView",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
"min_inclusive": 1.0,
|
||||
"max_inclusive": 170.0,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class VisualizationInfoBitmap:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
bitmap: BitmapFormat = field(
|
||||
metadata={
|
||||
"name": "Bitmap",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
reference: str = field(
|
||||
metadata={
|
||||
"name": "Reference",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
location: Point = field(
|
||||
metadata={
|
||||
"name": "Location",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
normal: Direction = field(
|
||||
metadata={
|
||||
"name": "Normal",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
up: Direction = field(
|
||||
metadata={
|
||||
"name": "Up",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
height: float = field(
|
||||
metadata={
|
||||
"name": "Height",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ComponentColoring:
|
||||
color: List[ComponentColoringColor] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Color",
|
||||
"type": "Element",
|
||||
"min_occurs": 1,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ComponentVisibility:
|
||||
exceptions: Optional[ComponentVisibilityExceptions] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Exceptions",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
default_visibility: Optional[bool] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "DefaultVisibility",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class VisualizationInfoClippingPlanes:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
clipping_plane: List[ClippingPlane] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "ClippingPlane",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class VisualizationInfoLines:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
line: List[Line] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Line",
|
||||
"type": "Element",
|
||||
"min_occurs": 1,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Components:
|
||||
view_setup_hints: Optional[ViewSetupHints] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "ViewSetupHints",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
selection: Optional[ComponentSelection] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Selection",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
visibility: ComponentVisibility = field(
|
||||
metadata={
|
||||
"name": "Visibility",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
coloring: Optional[ComponentColoring] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Coloring",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class VisualizationInfo:
|
||||
"""
|
||||
VisualizationInfo documentation.
|
||||
"""
|
||||
components: Optional[Components] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Components",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
orthogonal_camera: Optional[OrthogonalCamera] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "OrthogonalCamera",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
perspective_camera: Optional[PerspectiveCamera] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "PerspectiveCamera",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
lines: Optional[VisualizationInfoLines] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Lines",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
clipping_planes: Optional[VisualizationInfoClippingPlanes] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "ClippingPlanes",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
bitmap: List[VisualizationInfoBitmap] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Bitmap",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
guid: str = field(
|
||||
metadata={
|
||||
"name": "Guid",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"pattern": r"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}",
|
||||
}
|
||||
)
|
||||
@@ -1,240 +0,0 @@
|
||||
"""BCF XML V2 Topic handler."""
|
||||
import datetime
|
||||
import uuid
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional
|
||||
|
||||
from ifcopenshell import entity_instance
|
||||
from xsdata.models.datatype import XmlDateTime
|
||||
|
||||
import bcf.v2.model as mdl
|
||||
from bcf.inmemory_zipfile import ZipFileInterface
|
||||
from bcf.v2.visinfo import VisualizationInfoHandler
|
||||
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
|
||||
|
||||
|
||||
class TopicHandler:
|
||||
"""BCF Topic and related objects handler."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
topic_dir: Optional[zipfile.Path] = None,
|
||||
xml_handler: Optional[AbstractXmlParserSerializer] = None,
|
||||
) -> None:
|
||||
self._markup: Optional[mdl.Markup] = None
|
||||
self._viewpoints: dict[str, VisualizationInfoHandler] = {}
|
||||
self._reference_files: dict[str, bytes] = {}
|
||||
self._document_references: dict[str, bytes] = {}
|
||||
self._bim_snippet: Optional[bytes] = None
|
||||
self._xml_handler = xml_handler or XmlParserSerializer()
|
||||
self._topic_dir = topic_dir
|
||||
|
||||
@property
|
||||
def markup(self) -> Optional[mdl.Markup]:
|
||||
if not self._markup:
|
||||
markup_path = self._topic_dir.joinpath("markup.bcf")
|
||||
if markup_path.exists():
|
||||
self._markup = self._xml_handler.parse(markup_path.read_bytes(), mdl.Markup)
|
||||
return self._markup
|
||||
|
||||
@markup.setter
|
||||
def markup(self, value: mdl.Markup) -> None:
|
||||
self._markup = value
|
||||
|
||||
@property
|
||||
def topic(self) -> mdl.Topic:
|
||||
"""Return the Topic object."""
|
||||
return self.markup.topic
|
||||
|
||||
@property
|
||||
def guid(self) -> str:
|
||||
"""Return the GUID of the topic."""
|
||||
if self._markup:
|
||||
return self.topic.guid
|
||||
return self._topic_dir.name if self._topic_dir else ""
|
||||
|
||||
@property
|
||||
def header(self) -> Optional[mdl.Header]:
|
||||
"""Return the header of the topic."""
|
||||
return self.markup.header if self.markup else None
|
||||
|
||||
@property
|
||||
def comments(self) -> list[mdl.Comment]:
|
||||
"""Return the comments of the topic."""
|
||||
return self.markup.comment if self.markup else []
|
||||
|
||||
@property
|
||||
def bim_snippet(self) -> Optional[bytes]:
|
||||
if not self._bim_snippet and self._topic_dir:
|
||||
self._bim_snippet = self._load_bim_snippet()
|
||||
return self._bim_snippet
|
||||
|
||||
@bim_snippet.setter
|
||||
def bim_snippet(self, value: bytes) -> None:
|
||||
self._bim_snippet = value
|
||||
|
||||
@property
|
||||
def viewpoints(self) -> dict[str, VisualizationInfoHandler]:
|
||||
if not self._viewpoints and self._topic_dir:
|
||||
self._viewpoints = self._load_viewpoints()
|
||||
return self._viewpoints
|
||||
|
||||
@property
|
||||
def reference_files(self) -> dict[str, bytes]:
|
||||
if self._reference_files or not self.header:
|
||||
return self._reference_files
|
||||
for ref in self.header.file:
|
||||
if ref.is_external:
|
||||
continue
|
||||
real_path = self._topic_dir
|
||||
for path_part in ref.reference.split("/"):
|
||||
real_path = real_path.parent if path_part == ".." else real_path.joinpath(path_part)
|
||||
self._reference_files[ref.reference] = real_path.read_bytes()
|
||||
return self._reference_files
|
||||
|
||||
@property
|
||||
def document_references(self) -> dict[str, bytes]:
|
||||
if self._document_references or not self.topic:
|
||||
return self._document_references
|
||||
for doc in self.topic.document_reference:
|
||||
if doc.is_external or not doc.referenced_document:
|
||||
continue
|
||||
real_path = self._topic_dir
|
||||
for path_part in doc.referenced_document.split("/"):
|
||||
real_path = real_path.parent if path_part == ".." else real_path.joinpath(path_part)
|
||||
self._document_references[doc.referenced_document] = real_path.read_bytes()
|
||||
return self._document_references
|
||||
|
||||
def _load_bim_snippet(self) -> Optional[bytes]:
|
||||
bim_snippet_obj = self.topic.bim_snippet
|
||||
if bim_snippet_obj and not bim_snippet_obj.is_external:
|
||||
bim_snippet_path = self._topic_dir.joinpath(bim_snippet_obj.reference)
|
||||
if bim_snippet_path.exists():
|
||||
return bim_snippet_path.read_bytes()
|
||||
return None
|
||||
|
||||
def _load_viewpoints(self) -> dict[str, VisualizationInfoHandler]:
|
||||
if self.markup and (viewpoints := self.markup.viewpoints):
|
||||
return VisualizationInfoHandler.from_topic_viewpoints(self._topic_dir, viewpoints)
|
||||
return {}
|
||||
|
||||
@classmethod
|
||||
def create_new(
|
||||
cls,
|
||||
title: str,
|
||||
description: str,
|
||||
author: str,
|
||||
topic_type: str = "",
|
||||
topic_status: str = "",
|
||||
xml_handler: Optional[AbstractXmlParserSerializer] = None,
|
||||
) -> "TopicHandler":
|
||||
"""
|
||||
Create a new BCF topic.
|
||||
|
||||
Args:
|
||||
title: The title of the topic.
|
||||
description: The description of the topic.
|
||||
author: The author of the topic.
|
||||
topic_type: The type of the topic.
|
||||
topic_status: The status of the topic.
|
||||
xml_handler: The XML parser/serializer to use.
|
||||
|
||||
Returns:
|
||||
The BCF topic definition.
|
||||
"""
|
||||
creation_date = XmlDateTime.from_datetime(datetime.datetime.now())
|
||||
guid = str(uuid.uuid4())
|
||||
topic = mdl.Topic(
|
||||
title=title,
|
||||
description=description,
|
||||
creation_author=author,
|
||||
creation_date=creation_date,
|
||||
guid=guid,
|
||||
topic_type=topic_type,
|
||||
topic_status=topic_status,
|
||||
)
|
||||
markup = mdl.Markup(topic=topic)
|
||||
obj = cls(topic_dir=Path(guid), xml_handler=xml_handler or XmlParserSerializer())
|
||||
obj.markup = markup
|
||||
return obj
|
||||
|
||||
def save(self, destination_zip: ZipFileInterface) -> None:
|
||||
"""
|
||||
Save the topic to a BCF zip file.
|
||||
|
||||
Args:
|
||||
bcf_zip: The BCF zip file to save to.
|
||||
"""
|
||||
topic_dir = self.guid
|
||||
self._save_xml(destination_zip, self._markup, "markup.bcf")
|
||||
self._save_viewpoints(destination_zip, topic_dir)
|
||||
self._save_bim_snippet(destination_zip)
|
||||
self._save_reference_files(destination_zip)
|
||||
self._save_document_references(destination_zip)
|
||||
|
||||
def _save_viewpoints(self, destination_zip: ZipFileInterface, topic_dir: str) -> None:
|
||||
if not self.markup or not (viewpoints := self.markup.viewpoints):
|
||||
return
|
||||
for vpt in viewpoints:
|
||||
if vpt.viewpoint:
|
||||
self.viewpoints[vpt.viewpoint].save(destination_zip, topic_dir, vpt)
|
||||
|
||||
def _save_xml(self, destination_zip: ZipFileInterface, item: Any, target: str) -> None:
|
||||
if self._topic_dir is None:
|
||||
return
|
||||
to_write = self._xml_handler.serialize(item) if item else self._topic_dir.joinpath(target).read_bytes()
|
||||
destination_zip.writestr(f"{self._topic_dir.name}/{target}", to_write)
|
||||
|
||||
def _save_bim_snippet(self, destination_zip: ZipFileInterface) -> None:
|
||||
snippet = self.topic.bim_snippet
|
||||
if not snippet or snippet.is_external:
|
||||
return
|
||||
ref_filename = Path(snippet.reference).name
|
||||
if self.bim_snippet:
|
||||
destination_zip.writestr(f"{self.topic.guid}/{ref_filename}", self.bim_snippet)
|
||||
|
||||
def _save_reference_files(self, destination_zip: ZipFileInterface) -> None:
|
||||
if not self.header:
|
||||
return
|
||||
for ref in self.header.file:
|
||||
if ref.is_external or not ref.reference:
|
||||
continue
|
||||
real_path = self._topic_dir
|
||||
for path_part in ref.reference.split("/"):
|
||||
real_path = real_path.parent if path_part == ".." else real_path.joinpath(path_part)
|
||||
destination_zip.writestr(real_path.at, self.reference_files[ref.reference])
|
||||
|
||||
def _save_document_references(self, destination_zip: ZipFileInterface) -> None:
|
||||
if not self.topic:
|
||||
return
|
||||
for doc in self.topic.document_reference:
|
||||
if doc.is_external or not doc.referenced_document:
|
||||
continue
|
||||
real_path = self._topic_dir
|
||||
for path_part in doc.referenced_document.split("/"):
|
||||
real_path = real_path.parent if path_part == ".." else real_path.joinpath(path_part)
|
||||
destination_zip.writestr(real_path.at, self.document_references[doc.referenced_document])
|
||||
|
||||
def add_viewpoint(self, element: entity_instance) -> None:
|
||||
"""
|
||||
Add a viewpoint tergeting an IFC element to the topic.
|
||||
|
||||
Args:
|
||||
element: The IFC element.
|
||||
"""
|
||||
new_viewpoint = VisualizationInfoHandler.create_new(element, self._xml_handler)
|
||||
self.add_visinfo_handler(new_viewpoint)
|
||||
|
||||
def add_visinfo_handler(self, new_viewpoint: VisualizationInfoHandler) -> None:
|
||||
self.viewpoints[new_viewpoint.guid] = new_viewpoint
|
||||
self.markup.viewpoints.append(mdl.ViewPoint(viewpoint=new_viewpoint.guid, guid=new_viewpoint.guid))
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if not isinstance(other, TopicHandler):
|
||||
raise TypeError("Equality needs a BcfXml object.")
|
||||
return (
|
||||
self.markup == other.markup
|
||||
and self.viewpoints == other.viewpoints
|
||||
and self.bim_snippet == other.bim_snippet
|
||||
)
|
||||
@@ -1,246 +0,0 @@
|
||||
import uuid
|
||||
import zipfile
|
||||
from functools import lru_cache
|
||||
from typing import Any, Iterable, Optional
|
||||
|
||||
import numpy as np
|
||||
from ifcopenshell import entity_instance
|
||||
from ifcopenshell.util import placement
|
||||
from numpy.typing import NDArray
|
||||
|
||||
import bcf.v2.model as mdl
|
||||
from bcf.geometry import calc_camera_vectors
|
||||
from bcf.inmemory_zipfile import ZipFileInterface
|
||||
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
|
||||
|
||||
|
||||
class VisualizationInfoHandler:
|
||||
"""Handle the VisualizationInfo and related objects."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
visualization_info: mdl.VisualizationInfo,
|
||||
snapshot: Optional[bytes] = None,
|
||||
bitmaps: Optional[dict[str, bytes]] = None,
|
||||
xml_handler: Optional[AbstractXmlParserSerializer] = None,
|
||||
) -> None:
|
||||
self.visualization_info = visualization_info
|
||||
self.snapshot = snapshot
|
||||
self.bitmaps = bitmaps or {}
|
||||
self._xml_handler = xml_handler or XmlParserSerializer()
|
||||
|
||||
@property
|
||||
def guid(self) -> str:
|
||||
"""Return the GUID of the visualization info."""
|
||||
return self.visualization_info.guid
|
||||
|
||||
@classmethod
|
||||
def from_topic_viewpoints(
|
||||
cls,
|
||||
topic_dir: zipfile.Path,
|
||||
vps: Iterable[mdl.ViewPoint],
|
||||
xml_handler: Optional[AbstractXmlParserSerializer] = None,
|
||||
) -> dict[str, "VisualizationInfoHandler"]:
|
||||
"""Create VisualizationInfoHandler objects of a Topic's ViewPoints."""
|
||||
viewpoints = {}
|
||||
for vpt in vps:
|
||||
visinfo = cls.load(topic_dir, vpt, xml_handler)
|
||||
if visinfo and vpt.viewpoint:
|
||||
viewpoints[vpt.viewpoint] = visinfo
|
||||
return viewpoints
|
||||
|
||||
@classmethod
|
||||
def load(
|
||||
cls,
|
||||
topic_dir: zipfile.Path,
|
||||
vpt: mdl.ViewPoint,
|
||||
xml_handler: Optional[AbstractXmlParserSerializer] = None,
|
||||
) -> Optional["VisualizationInfoHandler"]:
|
||||
"""
|
||||
Load the VisualizationInfo and related objects from a BCF zip file.
|
||||
|
||||
Args:
|
||||
topic_dir: The directory in the BCF zip file to load from.
|
||||
vpt: The ViewPoint to load.
|
||||
xml_handler: The XML handler to use to parse the VisualizationInfo.
|
||||
|
||||
Returns:
|
||||
The VisualizationInfoHandler object.
|
||||
"""
|
||||
visinfo = cls._load_visinfo(topic_dir, vpt.viewpoint, xml_handler)
|
||||
if not visinfo:
|
||||
return None
|
||||
snapshot = cls._load_snapshot(topic_dir, vpt.snapshot)
|
||||
bitmaps = cls._load_bitmaps(topic_dir, visinfo)
|
||||
return cls(visinfo, snapshot, bitmaps, xml_handler)
|
||||
|
||||
@staticmethod
|
||||
def _load_visinfo(
|
||||
topic_dir: zipfile.Path,
|
||||
vp_name: Optional[str],
|
||||
xml_handler: Optional[AbstractXmlParserSerializer] = None,
|
||||
) -> Optional[mdl.VisualizationInfo]:
|
||||
if not vp_name:
|
||||
return None
|
||||
vp_path = topic_dir.joinpath(vp_name)
|
||||
if vp_path.exists():
|
||||
xml_handler = xml_handler or XmlParserSerializer()
|
||||
return xml_handler.parse(vp_path.read_bytes(), mdl.VisualizationInfo)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _load_snapshot(topic_dir: zipfile.Path, vp_snapshot: Optional[str]) -> Optional[bytes]:
|
||||
if vp_snapshot:
|
||||
snapshot_path = topic_dir.joinpath(vp_snapshot)
|
||||
if snapshot_path.exists():
|
||||
return snapshot_path.read_bytes()
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _load_bitmaps(topic_dir: zipfile.Path, visinfo: Optional[mdl.VisualizationInfo]) -> dict[str, bytes]:
|
||||
if not visinfo or not (bitmaps := visinfo.bitmap):
|
||||
return {}
|
||||
bitmaps_dict = {}
|
||||
for bitmap in bitmaps:
|
||||
if not bitmap.reference:
|
||||
continue
|
||||
bitmap_path = topic_dir.joinpath(bitmap.reference)
|
||||
if bitmap_path.exists():
|
||||
bitmaps_dict[bitmap.reference] = bitmap_path.read_bytes()
|
||||
return bitmaps_dict
|
||||
|
||||
def save(
|
||||
self,
|
||||
bcf_zip: ZipFileInterface,
|
||||
topic_dir: str,
|
||||
vpt: mdl.ViewPoint,
|
||||
) -> None:
|
||||
"""
|
||||
Save the VisualizationInfo and related objects to a BCF zip file.
|
||||
|
||||
Args:
|
||||
bcf_zip: The BCF zip file to save to.
|
||||
topic_dir: The directory in the BCF zip file to save to.
|
||||
vpt: The ViewPoint to save.
|
||||
"""
|
||||
if not (vp_name := vpt.viewpoint):
|
||||
return
|
||||
self._save_visinfo(bcf_zip, topic_dir, vp_name)
|
||||
self._save_snapshot(bcf_zip, topic_dir, vpt.snapshot)
|
||||
self._save_bitmaps(bcf_zip, topic_dir)
|
||||
|
||||
def _save_snapshot(self, bcf_zip: ZipFileInterface, topic_dir: str, filename: Optional[str]) -> None:
|
||||
if self.snapshot and filename:
|
||||
bcf_zip.writestr(f"{topic_dir}/{filename}", self.snapshot)
|
||||
|
||||
def _save_visinfo(self, bcf_zip: ZipFileInterface, topic_dir: str, vp_name: str) -> None:
|
||||
bcf_zip.writestr(
|
||||
f"{topic_dir}/{vp_name}",
|
||||
self._xml_handler.serialize(self.visualization_info),
|
||||
)
|
||||
|
||||
def _save_bitmaps(self, bcf_zip: ZipFileInterface, topic_dir: str) -> None:
|
||||
if not self.bitmaps:
|
||||
return
|
||||
if not (bitmaps_defs := self.visualization_info.bitmap):
|
||||
return
|
||||
for bitmap_def in bitmaps_defs:
|
||||
if not (bitmap_name := bitmap_def.reference):
|
||||
continue
|
||||
if bitmap_name in self.bitmaps:
|
||||
bcf_zip.writestr(f"{topic_dir}/{bitmap_name}", self.bitmaps[bitmap_name])
|
||||
|
||||
@classmethod
|
||||
def create_new(
|
||||
cls,
|
||||
element: entity_instance,
|
||||
xml_handler: Optional[AbstractXmlParserSerializer] = None,
|
||||
) -> "VisualizationInfoHandler":
|
||||
"""
|
||||
Create a new VisualizationInfoHandler object from an IFC element.
|
||||
|
||||
Args:
|
||||
element: The IFC element to point at.
|
||||
xml_handler: The XML handler to use.
|
||||
|
||||
Returns:
|
||||
The VisualizationInfoHandler object.
|
||||
"""
|
||||
xml_handler = xml_handler or XmlParserSerializer()
|
||||
return cls(visualization_info=build_viewpoint(element), xml_handler=xml_handler)
|
||||
|
||||
|
||||
@lru_cache(maxsize=None)
|
||||
def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
|
||||
"""
|
||||
Return a BCF viewpoint of an IFC element.
|
||||
|
||||
This function is cached to speedudp the creation of multiple BCF topics regarding the same element.
|
||||
|
||||
Args:
|
||||
element: The IFC element to point at.
|
||||
|
||||
Returns:
|
||||
The BCF viewpoint definition.
|
||||
"""
|
||||
elem_placement = placement.get_local_placement(element.ObjectPlacement)
|
||||
|
||||
return mdl.VisualizationInfo(
|
||||
guid=str(uuid.uuid4()),
|
||||
components=build_components(element.GlobalId),
|
||||
perspective_camera=build_camera(elem_placement),
|
||||
)
|
||||
|
||||
|
||||
def build_components(guid: str) -> mdl.Components:
|
||||
"""
|
||||
Return the BCF components from an IFC element GUID.
|
||||
|
||||
Args:
|
||||
guid: The IFC element GUID.
|
||||
|
||||
Returns:
|
||||
The BCF components definition.
|
||||
"""
|
||||
return mdl.Components(
|
||||
selection=mdl.ComponentSelection(component=[mdl.Component(ifc_guid=guid)]),
|
||||
visibility=mdl.ComponentVisibility(default_visibility=True),
|
||||
)
|
||||
|
||||
|
||||
def build_camera(elem_placement: NDArray[np.float_]) -> mdl.PerspectiveCamera:
|
||||
"""
|
||||
Return a BCF camera for an IFC element placement matrix.
|
||||
|
||||
Args:
|
||||
elem_placement: The IFC element placement as a rototranslation matrix.
|
||||
|
||||
Returns:
|
||||
The BCF camera definition.
|
||||
"""
|
||||
return build_camera_from_vectors(*calc_camera_vectors(elem_placement))
|
||||
|
||||
|
||||
def build_camera_from_vectors(
|
||||
camera_position: NDArray[np.float_], camera_dir: NDArray[np.float_], camera_up: NDArray[np.float_]
|
||||
) -> mdl.PerspectiveCamera:
|
||||
"""
|
||||
Return a BCF camera for an IFC element placement matrix.
|
||||
|
||||
Args:
|
||||
camera_position: camera position array
|
||||
camera_dir: camera direction versor
|
||||
camera_up_vector: camera up versor
|
||||
|
||||
Returns:
|
||||
The BCF camera definition.
|
||||
"""
|
||||
camera_viewpoint = mdl.Point(x=camera_position[0], y=camera_position[1], z=camera_position[2])
|
||||
camera_direction = mdl.Direction(x=camera_dir[0], y=camera_dir[1], z=camera_dir[2])
|
||||
camera_up_vector = mdl.Direction(x=camera_up[0], y=camera_up[1], z=camera_up[2])
|
||||
return mdl.PerspectiveCamera(
|
||||
camera_view_point=camera_viewpoint,
|
||||
camera_direction=camera_direction,
|
||||
camera_up_vector=camera_up_vector,
|
||||
field_of_view=60.0,
|
||||
)
|
||||
@@ -1,154 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Mit XMLSpy v2011 rel. 2 sp1 (http://www.altova.com) von Klaus Linhard (IABI e.V.) bearbeitet -->
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="Markup">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Header" type="Header" minOccurs="0"/>
|
||||
<xs:element name="Topic" type="Topic"/>
|
||||
<xs:element name="Comment" type="Comment" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<!-- ISG Jira issue BCF-9. Add support for several viewpoints and snapshots per issue -->
|
||||
<xs:element name="Viewpoints" type="ViewPoint" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:complexType name="Header">
|
||||
<xs:sequence>
|
||||
<xs:element name="File" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Filename" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="Date" type="xs:dateTime" minOccurs="0"/>
|
||||
<!-- Reference (URL) of the file -->
|
||||
<xs:element name="Reference" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
<xs:attributeGroup ref="FileAttributes"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<!-- ISG Jira issue BCF-9. Add support for several viewpoints and snapshots per issue -->
|
||||
<xs:complexType name="ViewPoint">
|
||||
<xs:sequence>
|
||||
<!-- viewpoint file (xml) -->
|
||||
<xs:element name="Viewpoint" type="xs:string" minOccurs="0"/>
|
||||
<!-- the snapshot png -->
|
||||
<xs:element name="Snapshot" type="xs:string" minOccurs="0"/>
|
||||
<!-- the viewpoint index (sort order) -->
|
||||
<xs:element name="Index" type="xs:int" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="Guid" type="Guid" use="required"/>
|
||||
<!-- Guid of the viewpoint -->
|
||||
</xs:complexType>
|
||||
<!-- BimSnippet -->
|
||||
<xs:complexType name="BimSnippet">
|
||||
<xs:sequence>
|
||||
<!--
|
||||
Name of the file in the topic folder containing the snippet or a URL.
|
||||
E.G.- Expresscode containing p.e Issue, Request
|
||||
// Maybe some header infos ?? // IfcEntites // Geometry
|
||||
-->
|
||||
<!-- Reference (name) to the snippet file -->
|
||||
<xs:element name="Reference" type="xs:string"/>
|
||||
<xs:element name="ReferenceSchema" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="SnippetType" type="xs:string" use="required"/>
|
||||
<xs:attribute name="isExternal" type="xs:boolean" default="false"/>
|
||||
<!-- This flag is true when the reference is a URL pointing outside of the BCF file-->
|
||||
</xs:complexType>
|
||||
<xs:complexType name="Topic">
|
||||
<xs:sequence>
|
||||
<xs:element name="ReferenceLink" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="Title" type="xs:string"/>
|
||||
<xs:element name="Priority" type="Priority" minOccurs="0"/>
|
||||
<!-- ISG Jira issue BCF-8 Add a way save order the topics -->
|
||||
<xs:element name="Index" type="xs:int" minOccurs="0"/>
|
||||
<xs:element name="Labels" type="TopicLabel" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="CreationDate" type="xs:dateTime" minOccurs="1"/>
|
||||
<xs:element name="CreationAuthor" type="UserIdType" minOccurs="1"/>
|
||||
<xs:element name="ModifiedDate" type="xs:dateTime" minOccurs="0"/>
|
||||
<xs:element name="ModifiedAuthor" type="UserIdType" minOccurs="0"/>
|
||||
<xs:element name="DueDate" type="xs:dateTime" minOccurs="0"/>
|
||||
<xs:element name="AssignedTo" type="UserIdType" minOccurs="0"/>
|
||||
<xs:element name="Stage" type="Stage" minOccurs="0"/>
|
||||
<xs:element name="Description" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="BimSnippet" type="BimSnippet" minOccurs="0"/>
|
||||
<!-- Name of the file in the topic folder or url -->
|
||||
<xs:element name="DocumentReference" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<!-- Name of the file in the topic folder or url -->
|
||||
<xs:element name="ReferencedDocument" type="xs:string" minOccurs="0"/>
|
||||
<!-- Human readable name of the document -->
|
||||
<xs:element name="Description" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
<xs:attributeGroup ref="DocumentReference"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="RelatedTopic" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="Guid" type="Guid" use="required"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="Guid" type="Guid" use="required"/>
|
||||
<xs:attribute name="TopicType" type="TopicType"/>
|
||||
<xs:attribute name="TopicStatus" type="TopicStatus"/>
|
||||
</xs:complexType>
|
||||
<!-- Reference to a document inside of the topic folder or a url pointing to the web -->
|
||||
<xs:attributeGroup name="DocumentReference">
|
||||
<!-- Guid of the DocumentReference -->
|
||||
<xs:attribute name="Guid" type="Guid"/>
|
||||
<!-- A flag that is true when the ReferencedDocument points outside of the BCF file (a URL) -->
|
||||
<xs:attribute name="isExternal" type="xs:boolean" default="false"/>
|
||||
</xs:attributeGroup>
|
||||
<xs:complexType name="Comment">
|
||||
<xs:sequence>
|
||||
<xs:element name="Date" type="xs:dateTime"/>
|
||||
<xs:element name="Author" type="UserIdType"/>
|
||||
<xs:element name="Comment" type="xs:string"/>
|
||||
<xs:element name="Viewpoint" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="Guid" type="Guid" use="required"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="ModifiedDate" type="xs:dateTime" minOccurs="0"/>
|
||||
<xs:element name="ModifiedAuthor" type="UserIdType" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="Guid" type="Guid" use="required"/>
|
||||
</xs:complexType>
|
||||
<xs:simpleType name="TopicStatus">
|
||||
<xs:restriction base="xs:string"/>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="TopicType">
|
||||
<xs:restriction base="xs:string"/>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="TopicLabel">
|
||||
<xs:restriction base="xs:string"/>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="Priority">
|
||||
<xs:restriction base="xs:string"/>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="UserIdType">
|
||||
<xs:restriction base="xs:string"/>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="Stage">
|
||||
<xs:restriction base="xs:string"/>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="Guid">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="IfcGuid">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:length value="22"/>
|
||||
<xs:pattern value="[0-9,A-Z,a-z,_$]*"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:attributeGroup name="FileAttributes">
|
||||
<xs:attribute name="IfcProject" type="IfcGuid"/>
|
||||
<xs:attribute name="IfcSpatialStructureElement" type="IfcGuid"/>
|
||||
<xs:attribute name="isExternal" type="xs:boolean" default="true"/>
|
||||
</xs:attributeGroup>
|
||||
</xs:schema>
|
||||
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Mit XMLSpy v2011 rel. 2 sp1 (http://www.altova.com) von Klaus Linhard (IABI e.V.) bearbeitet -->
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="ProjectExtension">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Project" type="Project" minOccurs="0"/>
|
||||
<xs:element name="ExtensionSchema" type="xs:anyURI"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:complexType name="Project">
|
||||
<xs:sequence>
|
||||
<xs:element name="Name" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="ProjectId" type="xs:string" use="required"/>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Mit XMLSpy v2011 rel. 3 (http://www.altova.com) von Klaus Linhard (IABI e.V.) bearbeitet -->
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="Version">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="DetailedVersion" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="VersionId" type="xs:string"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@@ -1,191 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Mit XMLSpy v2011 rel. 2 sp1 (http://www.altova.com) von Klaus Linhard (IABI e.V.) bearbeitet -->
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
<xs:element name="VisualizationInfo">
|
||||
<xs:annotation>
|
||||
<xs:documentation>VisualizationInfo documentation</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Components" type="Components" minOccurs="0"/>
|
||||
<xs:element name="OrthogonalCamera" type="OrthogonalCamera" minOccurs="0"/>
|
||||
<xs:element name="PerspectiveCamera" type="PerspectiveCamera" minOccurs="0"/>
|
||||
<xs:element name="Lines" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Line" type="Line" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="ClippingPlanes" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ClippingPlane" type="ClippingPlane" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<!-- ISG Jira issue BCF-17: Add support for text in the viewpoints -->
|
||||
<xs:element name="Bitmap" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Bitmap" type="BitmapFormat"/>
|
||||
<!-- Name of the bitmap file in the topic folder -->
|
||||
<xs:element name="Reference" type="xs:string"/>
|
||||
<!-- Location of the center of the bitmap -->
|
||||
<xs:element name="Location" type="Point"/>
|
||||
<!-- Normal of the bitmap -->
|
||||
<xs:element name="Normal" type="Direction"/>
|
||||
<!-- Upvector of the bitmap -->
|
||||
<xs:element name="Up" type="Direction"/>
|
||||
<!-- Height of the bitmap -->
|
||||
<xs:element name="Height" type="xs:double"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<!-- Guid of the viewpoint -->
|
||||
<xs:attribute name="Guid" type="Guid" use="required"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:complexType name="OrthogonalCamera">
|
||||
<xs:sequence>
|
||||
<xs:element name="CameraViewPoint" type="Point"/>
|
||||
<xs:element name="CameraDirection" type="Direction"/>
|
||||
<xs:element name="CameraUpVector" type="Direction"/>
|
||||
<xs:element name="ViewToWorldScale" type="xs:double">
|
||||
<xs:annotation>
|
||||
<xs:documentation>view's visible size in meters</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="PerspectiveCamera">
|
||||
<xs:sequence>
|
||||
<xs:element name="CameraViewPoint" type="Point"/>
|
||||
<xs:element name="CameraDirection" type="Direction"/>
|
||||
<xs:element name="CameraUpVector" type="Direction"/>
|
||||
<xs:element name="FieldOfView" type="FieldOfView">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
It is currently limited to a value between 45 and 60 degrees.
|
||||
This limitation will be dropped in the next release and viewers
|
||||
should be expect values outside this range in current implementations.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="Point">
|
||||
<xs:sequence>
|
||||
<xs:element name="X" type="xs:double"/>
|
||||
<xs:element name="Y" type="xs:double"/>
|
||||
<xs:element name="Z" type="xs:double"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="Direction">
|
||||
<xs:sequence>
|
||||
<xs:element name="X" type="xs:double"/>
|
||||
<xs:element name="Y" type="xs:double"/>
|
||||
<xs:element name="Z" type="xs:double"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:simpleType name="FieldOfView">
|
||||
<xs:restriction base="xs:double">
|
||||
<xs:minInclusive value="1"/>
|
||||
<xs:maxInclusive value="170"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:complexType name="Components">
|
||||
<xs:sequence>
|
||||
<xs:element name="ViewSetupHints" type="ViewSetupHints" minOccurs="0" />
|
||||
<!-- Components with relevance to the viewpoint. They should be displayed highlighted or selected in a viewer -->
|
||||
<xs:element name="Selection" type="ComponentSelection" minOccurs="0" />
|
||||
<xs:element name="Visibility" type="ComponentVisibility" minOccurs="1" />
|
||||
<xs:element name="Coloring" type="ComponentColoring" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="ViewSetupHints">
|
||||
<xs:attribute name="SpacesVisible" type="xs:boolean"/>
|
||||
<xs:attribute name="SpaceBoundariesVisible" type="xs:boolean"/>
|
||||
<xs:attribute name="OpeningsVisible" type="xs:boolean"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="ComponentSelection">
|
||||
<xs:sequence>
|
||||
<xs:element name="Component" type="Component" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="ComponentVisibility">
|
||||
<xs:sequence>
|
||||
<xs:element name="Exceptions" minOccurs="0">
|
||||
<!-- List Components that are different than the DefaultVisibility. E.g. if DefaultVisibility = false then list
|
||||
Components that should be visible -->
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Component" type="Component" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="DefaultVisibility" type="xs:boolean"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="ComponentColoring">
|
||||
<xs:sequence>
|
||||
<xs:element name="Color" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Component" type="Component" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute ref="Color"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="Component">
|
||||
<xs:sequence>
|
||||
<xs:element name="OriginatingSystem" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="AuthoringToolId" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute ref="IfcGuid"/>
|
||||
<!-- ISG Jira Issue BCF-14 -->
|
||||
</xs:complexType>
|
||||
<xs:attribute name="Color">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:normalizedString">
|
||||
<!-- Should either match 3 or 4 hex bytes , e.g. "FF00FF" or "FF00FF99" -->
|
||||
<xs:pattern value="[0-9,a-f,A-F]{6}([0-9,a-f,A-F]{2})?"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IfcGuid">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:normalizedString">
|
||||
<xs:length value="22"/>
|
||||
<xs:pattern value="[0-9,A-Z,a-z,_$]*"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:complexType name="Line">
|
||||
<xs:sequence>
|
||||
<xs:element name="StartPoint" type="Point"/>
|
||||
<xs:element name="EndPoint" type="Point"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="ClippingPlane">
|
||||
<xs:sequence>
|
||||
<xs:element name="Location" type="Point"/>
|
||||
<xs:element name="Direction" type="Direction"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<!-- ISG Jira issue BCF-17: Add support for text in the viewpoints -->
|
||||
<xs:simpleType name="BitmapFormat">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="PNG"/>
|
||||
<xs:enumeration value="JPG"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="Guid">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:schema>
|
||||
@@ -1 +0,0 @@
|
||||
"""BCF XML v3 handler."""
|
||||
@@ -1,591 +0,0 @@
|
||||
# BCF - BCF Python library
|
||||
# Copyright (C) 2021 Prabhat Singh <singh01prabhat@gmail.com>
|
||||
#
|
||||
# This file is part of BCF.
|
||||
#
|
||||
# BCF is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BCF 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
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with BCF. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import base64
|
||||
import http.server
|
||||
import os
|
||||
import tempfile
|
||||
import time
|
||||
import urllib
|
||||
import uuid
|
||||
import webbrowser
|
||||
from re import A
|
||||
from typing import Any, Optional, Tuple
|
||||
|
||||
import requests
|
||||
|
||||
client_id, client_secret = "", ""
|
||||
|
||||
|
||||
class OAuthReceiver(http.server.BaseHTTPRequestHandler):
|
||||
def do_GET(self) -> None:
|
||||
query = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query)
|
||||
self.server.auth_code = query.get("code", [""])[0] # type:ignore
|
||||
self.server.auth_state = query.get("state", [""])[0] # type:ignore
|
||||
self.send_response(200)
|
||||
self.send_header("Content-type", "text/plain")
|
||||
self.end_headers()
|
||||
self.wfile.write("You have now authenticated :) You may now close this browser window.".encode("utf-8"))
|
||||
|
||||
|
||||
class FoundationClient:
|
||||
def __init__(
|
||||
self, client_id: str, client_secret: str, base_url: Optional[str] = None, redirect_subdir: Optional[str] = None
|
||||
) -> None:
|
||||
self.baseurl = base_url
|
||||
self.access_token = ""
|
||||
self.refresh_token = ""
|
||||
self.access_token_expires_on = time.time()
|
||||
self.refresh_token_expires_on = float("inf")
|
||||
self.token_endpoint = ""
|
||||
self.client_id = client_id
|
||||
self.client_secret = client_secret
|
||||
self.auth_method: Optional[str] = None
|
||||
self.redirect_subdir = redirect_subdir
|
||||
|
||||
def get_access_token(self) -> str:
|
||||
if self.access_token and self.access_token_expires_on > time.time():
|
||||
return self.access_token
|
||||
elif self.refresh_token and self.refresh_token_expires_on > time.time():
|
||||
self.get_refresh_token()
|
||||
else:
|
||||
self.login()
|
||||
return self.access_token
|
||||
|
||||
def get_auth_methods(self) -> list[Any]:
|
||||
resp = requests.get(f"{self.baseurl}foundation/1.0/auth")
|
||||
return resp.json()["supported_oauth2_flows"]
|
||||
|
||||
def get_versions(self) -> list[Any]:
|
||||
resp = requests.get(f"{self.baseurl}foundation/versions")
|
||||
return resp.json()["versions"]
|
||||
|
||||
def login(self) -> None:
|
||||
resp = requests.get(f"{self.baseurl}foundation/1.0/auth")
|
||||
values = resp.json()
|
||||
auth_endpoint = values["oauth2_auth_url"]
|
||||
self.token_endpoint = values["oauth2_token_url"]
|
||||
|
||||
with http.server.HTTPServer(("", 8080), OAuthReceiver) as server:
|
||||
state = str(uuid.uuid4())
|
||||
query = urllib.parse.urlencode(
|
||||
{
|
||||
"client_id": self.client_id,
|
||||
"response_type": "code",
|
||||
"state": state,
|
||||
"redirect_uri": f"http://localhost:{server.server_address[1]}/{self.redirect_subdir}",
|
||||
}
|
||||
)
|
||||
if "?" in auth_endpoint:
|
||||
webbrowser.open(f"{auth_endpoint}&{query}")
|
||||
else:
|
||||
webbrowser.open(f"{auth_endpoint}?{query}")
|
||||
server.timeout = 100
|
||||
server.handle_request()
|
||||
if server.auth_code and server.auth_state == state: # pylint: disable=E1101
|
||||
data = {
|
||||
"grant_type": "authorization_code",
|
||||
"code": server.auth_code, # pylint: disable=E1101 type:ignore
|
||||
"redirect_uri": f"http://localhost:{server.server_address[1]}/{self.redirect_subdir}",
|
||||
}
|
||||
headers = self._get_access_token_headers()
|
||||
self.set_tokens_from_response(requests.post(self.token_endpoint, data=data, headers=headers))
|
||||
|
||||
def get_refresh_token(self) -> None:
|
||||
self.set_tokens_from_response(
|
||||
requests.post(
|
||||
self.token_endpoint,
|
||||
params={
|
||||
"grant_type": "refresh_token",
|
||||
"refresh_token": self.refresh_token,
|
||||
},
|
||||
).json()
|
||||
)
|
||||
|
||||
def get_new_access_token(self) -> None:
|
||||
headers = self._get_access_token_headers()
|
||||
self.set_tokens_from_response(
|
||||
requests.post(
|
||||
self.token_endpoint,
|
||||
data={
|
||||
"grant_type": "refresh_token",
|
||||
"refresh_token": self.refresh_token,
|
||||
},
|
||||
headers=headers,
|
||||
).json()
|
||||
)
|
||||
|
||||
def _get_access_token_headers(self) -> dict[str, str]:
|
||||
auth_string = f"{self.client_id}:{self.client_secret}"
|
||||
header_string = base64.b64encode(auth_string.encode("utf-8")).decode("utf-8")
|
||||
return {"Authorization": f"Basic {header_string}"}
|
||||
|
||||
def set_auth_method(self, method: str = "authorization_code_grant") -> None:
|
||||
if method != "authorization_code_grant":
|
||||
raise NotImplementedError(f"{method} not supported")
|
||||
else:
|
||||
self.auth_method = method
|
||||
|
||||
def set_tokens_from_response(self, response: requests.Response) -> None:
|
||||
response_dict = response.json()
|
||||
self.access_token = response_dict["access_token"]
|
||||
self.refresh_token = response_dict["refresh_token"]
|
||||
self.access_token_expires_on = time.time() + response_dict["expires_in"]
|
||||
if "refresh_token_expires_in" in response_dict:
|
||||
self.refresh_token_expires_on = time.time() + response_dict["refresh_token_expires_in"]
|
||||
|
||||
|
||||
class BcfClient:
|
||||
def __init__(self, foundation_client: FoundationClient) -> None:
|
||||
self.foundation_client = foundation_client
|
||||
self.version_id: Optional[str] = None
|
||||
self.baseurl: Optional[str] = None
|
||||
self.filepath = tempfile.mkdtemp()
|
||||
|
||||
def set_version(self, version: dict[str, str]) -> None:
|
||||
self.version_id = version["version_id"]
|
||||
self.baseurl = version["api_base_url"]
|
||||
|
||||
def get(self, endpoint: str, params: Any = None, is_auth_required: bool = False) -> Any:
|
||||
# TODO: handle error http status codes and raise exception. Follow error.json standard.
|
||||
headers = {"Authorization": f"Bearer {self.foundation_client.get_access_token()}"}
|
||||
|
||||
response = requests.get(f"{self.baseurl}{endpoint}", headers=headers, params=params or None)
|
||||
try:
|
||||
response = requests.get(f"{self.baseurl}{endpoint}", headers=headers, params=params or None)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
response.raise_for_status()
|
||||
except requests.exceptions.HTTPError as e:
|
||||
print(f"message: {response.reason}' '{response.status_code}' '{ e }")
|
||||
|
||||
def post(self, endpoint: str, data: Any = None, params: Any = None) -> Tuple[int, str]:
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self.foundation_client.get_access_token()}",
|
||||
"Content-type": "application/json",
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
f"{self.baseurl}{endpoint}", headers=headers, params=params or None, data=data or None
|
||||
)
|
||||
|
||||
if response.status_code != 201:
|
||||
response.raise_for_status()
|
||||
return response.status_code, response.text
|
||||
except requests.exceptions.HTTPError as errh:
|
||||
print(f"message: {response.reason}' '{response.status_code}, {errh}")
|
||||
return response.status_code, response.reason
|
||||
|
||||
def put(self, endpoint: str, data: Any = None, params: Any = None) -> Tuple[int, str]:
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self.foundation_client.get_access_token()}",
|
||||
"Content-type": "application/json",
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.put(
|
||||
f"{self.baseurl}{endpoint}", headers=headers, params=params or None, data=data or None
|
||||
)
|
||||
|
||||
if response.status_code != 200:
|
||||
response.raise_for_status()
|
||||
return response.status_code, response.text
|
||||
except requests.exceptions.HTTPError as errh:
|
||||
print(f"message: {response.reason}' '{response.status_code}, {errh}")
|
||||
return response.status_code, response.reason
|
||||
|
||||
def delete(self, endpoint: str, params: Any = None) -> Tuple[int, str]:
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self.foundation_client.get_access_token()}",
|
||||
"Content-type": "application/json",
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.delete(f"{self.baseurl}{endpoint}", headers=headers, params=params or None)
|
||||
|
||||
if response.status_code != 200:
|
||||
response.raise_for_status()
|
||||
return response.status_code, response.text
|
||||
except requests.exceptions.HTTPError as errh:
|
||||
print(f"message: {response.reason}' '{response.status_code}, {errh}")
|
||||
return response.status_code, response.reason
|
||||
|
||||
def get_projects(self) -> list[Any]:
|
||||
return self.get("/projects")
|
||||
|
||||
def get_project(self, project_id: str = "") -> dict[str, Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}",
|
||||
{
|
||||
"project_id": project_id,
|
||||
},
|
||||
)
|
||||
|
||||
def update_project(self, project_id: str = "", data: Any = None) -> Tuple[int, str]:
|
||||
url = f"{self.baseurl}/projects/{project_id}"
|
||||
headers = {"Authorization": f"Bearer {self.foundation_client.get_access_token()}"}
|
||||
resp = requests.put(url, headers=headers, data=data)
|
||||
return resp.status_code, resp.text
|
||||
|
||||
def get_extensions(self, project_id: str = "") -> dict[str, Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/extensions",
|
||||
{
|
||||
"project_id": project_id,
|
||||
},
|
||||
)
|
||||
|
||||
def get_topics(
|
||||
self,
|
||||
project_id: str = "",
|
||||
topics: str = "",
|
||||
query_string: Optional[str] = None,
|
||||
) -> list[Any]:
|
||||
# return self.get(
|
||||
# f"/projects/{project_id}/topics",
|
||||
# {
|
||||
# "project_id": project_id,
|
||||
# "topics": topics,
|
||||
# "query_string": query_string,
|
||||
# },
|
||||
# )
|
||||
pass
|
||||
|
||||
def get_topic(self, project_id: str = "", topic_id: str = "") -> dict[str, Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/{topic_id}",
|
||||
{
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
},
|
||||
)
|
||||
|
||||
def create_topic(self, project_id: str = "", data: Any = None) -> Tuple[int, str]:
|
||||
return self.post(f"/projects/{project_id}/topics", data=data)
|
||||
|
||||
def update_topic(self, project_id: str = "", topic_id: str = "", data: Any = None) -> Tuple[int, str]:
|
||||
return self.put(f"/projects/{project_id}/topics/{topic_id}", data=data)
|
||||
|
||||
def delete_topic(self, project_id: str = "", topic_id: str = "") -> Tuple[int, str]:
|
||||
return self.delete(f"/projects/{project_id}/topics/{topic_id}")
|
||||
|
||||
def get_snippet(self, project_id: str = "", topic_id: str = "") -> Tuple[int, str]:
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self.foundation_client.get_access_token()}",
|
||||
"Content-type": "application/octet-stream",
|
||||
}
|
||||
|
||||
response = requests.get(f"{self.baseurl}/projects/{project_id}/topics/{topic_id}/snippet", headers=headers)
|
||||
content = response.content.decode("utf-8")
|
||||
with open(os.path.join(self.filepath, f"{project_id}_{topic_id}_snippet.txt"), "w") as f:
|
||||
f.write(content)
|
||||
return response.status_code, content
|
||||
|
||||
def update_snippet(self, project_id: str = "", topic_id: str = "", files: Any = None, data: Any = None) -> int:
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self.foundation_client.get_access_token()}",
|
||||
"Content-type": "application/octet-stream",
|
||||
}
|
||||
|
||||
response = requests.put(
|
||||
f"{self.baseurl}/projects/{project_id}/topics/{topic_id}/snippet", headers=headers, files=files
|
||||
)
|
||||
|
||||
return response.status_code
|
||||
|
||||
def get_files_information(self, project_id: str = "") -> list[Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/files_information",
|
||||
{
|
||||
"project_id": project_id,
|
||||
},
|
||||
)
|
||||
|
||||
def get_files(self, project_id: str = "", topic_id: str = "") -> list[Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/{topic_id}/files",
|
||||
{
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
},
|
||||
)
|
||||
|
||||
def update_files(
|
||||
self,
|
||||
project_id: str = "",
|
||||
topic_id: str = "",
|
||||
data: Any = None,
|
||||
params: Any = None,
|
||||
) -> Tuple[int, str]:
|
||||
return self.put(
|
||||
f"/projects/{project_id}/topics/{topic_id}/files",
|
||||
data=data,
|
||||
)
|
||||
|
||||
def get_comments(self, project_id: str = "", topic_id: str = "") -> None:
|
||||
pass
|
||||
|
||||
def create_comments(
|
||||
self,
|
||||
project_id: str = "",
|
||||
topic_id: str = "",
|
||||
data: Any = None,
|
||||
params: Any = None,
|
||||
) -> Tuple[int, str]:
|
||||
return self.post(
|
||||
f"/projects/{project_id}/topics/{topic_id}/comments",
|
||||
data=data,
|
||||
)
|
||||
|
||||
def get_comment(self, project_id: str = "", topic_id: str = "", comment_id: str = "") -> dict[str, Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/{topic_id}/comments/{comment_id}",
|
||||
{
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
"comment_id": comment_id,
|
||||
},
|
||||
)
|
||||
|
||||
def delete_comment(self, project_id: str = "", topic_id: str = "", comment_id: str = "") -> Tuple[int, str]:
|
||||
return self.delete(f"/projects/{project_id}/topics/{topic_id}/comments/{comment_id}")
|
||||
|
||||
def update_comment(
|
||||
self,
|
||||
project_id: str = "",
|
||||
topic_id: str = "",
|
||||
comment_id: str = "",
|
||||
data: Any = None,
|
||||
) -> Tuple[int, str]:
|
||||
return self.put(
|
||||
f"/projects/{project_id}/topics/{topic_id}/comments/{comment_id}",
|
||||
data=data,
|
||||
)
|
||||
|
||||
def get_viewpoints(self, project_id: str = "", topic_id: str = "") -> list[Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/{topic_id}/viewpoints",
|
||||
{
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
},
|
||||
)
|
||||
|
||||
def create_viewpoints(self, project_id: str = "", topic_id: str = "", data: Any = None) -> Tuple[int, str]:
|
||||
return self.post(
|
||||
f"/projects/{project_id}/topics/{topic_id}/viewpoints",
|
||||
data=data,
|
||||
)
|
||||
|
||||
def get_viewpoint(self, project_id: str = "", topic_id: str = "", viewpoint_id: str = "") -> dict[str, Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}",
|
||||
{
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
"viewpoint_id": viewpoint_id,
|
||||
},
|
||||
)
|
||||
|
||||
def delete_viewpoint(
|
||||
self,
|
||||
project_id: str = "",
|
||||
topic_id: str = "",
|
||||
viewpoint_id: str = "",
|
||||
) -> Tuple[int, str]:
|
||||
return self.delete(
|
||||
f"/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}",
|
||||
)
|
||||
|
||||
def get_snapshot(self, project_id: str = "", topic_id: str = "", viewpoint_id: str = "") -> str:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/snapshot",
|
||||
{
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
"viewpoint_id": viewpoint_id,
|
||||
},
|
||||
)
|
||||
|
||||
def get_bitmap(self, project_id: str = "", topic_id: str = "", viewpoint_id: str = "", bitmap_id: str = "") -> str:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/bitmaps/{bitmap_id}",
|
||||
{
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
"viewpoint_id": viewpoint_id,
|
||||
"bitmap_id": bitmap_id,
|
||||
},
|
||||
)
|
||||
|
||||
def get_selection(self, project_id: str = "", topic_id: str = "", viewpoint_id: str = "") -> dict[str, Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/selection",
|
||||
{
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
"viewpoint_id": viewpoint_id,
|
||||
},
|
||||
)
|
||||
|
||||
def get_coloring(self, project_id: str = "", topic_id: str = "", viewpoint_id: str = "") -> dict[str, Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/coloring",
|
||||
{
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
"viewpoint_id": viewpoint_id,
|
||||
},
|
||||
)
|
||||
|
||||
def get_visibility(self, project_id: str = "", topic_id: str = "", viewpoint_id: str = "") -> dict[str, Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/visibility",
|
||||
{
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
"viewpoint_id": viewpoint_id,
|
||||
},
|
||||
)
|
||||
|
||||
def get_related_topics(self, project_id: str = "", topic_id: str = "") -> list[Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/{topic_id}/related_topics",
|
||||
{
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
},
|
||||
)
|
||||
|
||||
def update_related_topics(
|
||||
self,
|
||||
project_id: str = "",
|
||||
topic_id: str = "",
|
||||
data: Any = None,
|
||||
) -> Tuple[int, str]:
|
||||
return self.put(
|
||||
f"/projects/{project_id}/topics/{topic_id}/related_topics",
|
||||
data=data,
|
||||
)
|
||||
|
||||
def get_document_references(self, project_id: str = "", topic_id: str = "") -> list[Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/{topic_id}/document_references",
|
||||
{
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
},
|
||||
)
|
||||
|
||||
def create_document_reference(
|
||||
self,
|
||||
project_id: str = "",
|
||||
topic_id: str = "",
|
||||
data: Any = None,
|
||||
) -> Tuple[int, str]:
|
||||
return self.post(
|
||||
f"/projects/{project_id}/topics/{topic_id}/document_references",
|
||||
data=data,
|
||||
)
|
||||
|
||||
def update_document_references(
|
||||
self,
|
||||
project_id: str = "",
|
||||
topic_id: str = "",
|
||||
document_reference_id: str = "",
|
||||
data: Any = None,
|
||||
) -> Tuple[int, str]:
|
||||
return self.put(
|
||||
f"/projects/{project_id}/topics/{topic_id}/document_references/{document_reference_id}",
|
||||
data=data,
|
||||
)
|
||||
|
||||
def get_documents(self, project_id: str = "", topic_id: str = "") -> list[Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/{topic_id}/documents",
|
||||
{
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
},
|
||||
)
|
||||
|
||||
def create_document(
|
||||
self, project_id: str = "", topic_id: str = "", guid: Optional[str] = None, files: Any = None, data: Any = None
|
||||
) -> int:
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self.foundation_client.get_access_token()}",
|
||||
"Content-type": "application/octet-stream",
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
f"/projects/{project_id}/topics/{topic_id}/documents",
|
||||
data=data,
|
||||
params={"guid": guid},
|
||||
files=files,
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
return response.status_code
|
||||
|
||||
def get_document(self, project_id: str = "", topic_id: str = "", document_id: str = "") -> Tuple[int, str]:
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self.foundation_client.get_access_token()}",
|
||||
"Content-type": "application/octet-stream",
|
||||
}
|
||||
|
||||
response = requests.get(f"{self.baseurl}/projects/{project_id}/topics/documents/{document_id}", headers=headers)
|
||||
content = response.content.decode("utf-8")
|
||||
with open(os.path.join(self.filepath, f"{project_id}_{topic_id}_{document_id}_document.txt"), "w") as f:
|
||||
f.write(content)
|
||||
return response.status_code, content
|
||||
|
||||
def get_topics_events(self, project_id: str = "") -> list[Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/events",
|
||||
{
|
||||
"project_id": project_id,
|
||||
},
|
||||
)
|
||||
|
||||
def get_topic_events(self, project_id: str = "", topic_id: str = "") -> list[Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/{topic_id}/events",
|
||||
{
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
},
|
||||
)
|
||||
|
||||
def get_comments_events(self, project_id: str = "") -> list[Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/comments/events",
|
||||
{
|
||||
"project_id": project_id,
|
||||
},
|
||||
)
|
||||
|
||||
def get_comment_events(self, project_id: str = "", topic_id: str = "", comment_id: str = "") -> list[Any]:
|
||||
return self.get(
|
||||
f"/projects/{project_id}/topics/{topic_id}/comments/{comment_id}/events",
|
||||
{
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
"comment_id": comment_id,
|
||||
},
|
||||
)
|
||||
@@ -1,291 +0,0 @@
|
||||
"""BCF XML V3 handlers."""
|
||||
import uuid
|
||||
import warnings
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional, TypeVar
|
||||
|
||||
import bcf.v3.model as mdl
|
||||
from bcf.inmemory_zipfile import InMemoryZipFile, ZipFileInterface
|
||||
from bcf.v3.document import DocumentsHandler
|
||||
from bcf.v3.topic import TopicHandler
|
||||
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class BcfXml:
|
||||
"""BCF XML handler."""
|
||||
|
||||
def __init__(
|
||||
self, filename: Optional[Path] = None, xml_handler: Optional[AbstractXmlParserSerializer] = None
|
||||
) -> None:
|
||||
self._filename = filename
|
||||
self._xml_handler = xml_handler or XmlParserSerializer()
|
||||
self._version: Optional[mdl.Version] = None
|
||||
self._project_info: Optional[mdl.ProjectInfo] = None
|
||||
self._extensions: Optional[mdl.Extensions] = None
|
||||
self._topics: dict[str, TopicHandler] = {}
|
||||
self._documents: Optional[DocumentsHandler] = None
|
||||
self._zip_file = self._load_zip_file()
|
||||
|
||||
def __enter__(self) -> "BcfXml":
|
||||
return self
|
||||
|
||||
def __exit__(self, *args: Any) -> None:
|
||||
self.close()
|
||||
|
||||
def __del__(self) -> None:
|
||||
self.close()
|
||||
|
||||
def close(self) -> None:
|
||||
if self._zip_file:
|
||||
self._zip_file.close()
|
||||
|
||||
def _load_zip_file(self) -> Optional[zipfile.ZipFile]:
|
||||
return zipfile.ZipFile(self._filename) if self._filename else None
|
||||
|
||||
@property
|
||||
def version(self) -> mdl.Version:
|
||||
"""Bcf Version."""
|
||||
if not self._version:
|
||||
self._version = (
|
||||
self._xml_handler.parse(self._zip_file.read("bcf.version"), mdl.Version)
|
||||
if self._zip_file
|
||||
else mdl.Version(version_id="3.0")
|
||||
)
|
||||
return self._version
|
||||
|
||||
@version.setter
|
||||
def version(self, value: mdl.Version) -> None:
|
||||
self._version = value
|
||||
|
||||
@property
|
||||
def project_info(self) -> Optional[mdl.ProjectInfo]:
|
||||
"""BCF project information."""
|
||||
if not self._project_info and self._zip_file and zipfile.Path(self._zip_file, "project.bcfp").exists():
|
||||
self._project_info = self._xml_handler.parse(self._zip_file.read("project.bcfp"), mdl.ProjectInfo)
|
||||
return self._project_info
|
||||
|
||||
@project_info.setter
|
||||
def project_info(self, value: Optional[mdl.ProjectInfo]) -> None:
|
||||
self._project_info = value
|
||||
|
||||
@property
|
||||
def project(self) -> Optional[mdl.Project]:
|
||||
"""BCF project."""
|
||||
return self.project_info.project if self.project_info else None
|
||||
|
||||
@property
|
||||
def extensions(self) -> Optional[mdl.Extensions]:
|
||||
"""BCF extensions."""
|
||||
if not self._extensions and self._zip_file:
|
||||
self._extensions = self._xml_handler.parse(self._zip_file.read("extensions.xml"), mdl.Extensions)
|
||||
return self._extensions
|
||||
|
||||
@extensions.setter
|
||||
def extensions(self, value: Optional[mdl.Extensions]) -> None:
|
||||
self._extensions = value
|
||||
|
||||
@property
|
||||
def topics(self) -> dict[str, TopicHandler]:
|
||||
"""BCF topics."""
|
||||
if not self._topics and self._zip_file:
|
||||
self._load_topics()
|
||||
return self._topics
|
||||
|
||||
def _load_topics(self) -> None:
|
||||
for topic_dir in zipfile.Path(self._zip_file).iterdir():
|
||||
if not topic_dir.is_dir():
|
||||
continue
|
||||
markup_path = topic_dir.joinpath("markup.bcf")
|
||||
if not markup_path.exists():
|
||||
continue
|
||||
self._topics[topic_dir.name] = TopicHandler(topic_dir, self._xml_handler)
|
||||
|
||||
@property
|
||||
def documents(self) -> Optional[DocumentsHandler]:
|
||||
"""Documents stored in the BCF file."""
|
||||
if not self._documents and self._zip_file:
|
||||
self._documents = DocumentsHandler.load(self._zip_file, self._xml_handler)
|
||||
return self._documents
|
||||
|
||||
@classmethod
|
||||
def load(cls, filename: Path, xml_handler: Optional[AbstractXmlParserSerializer] = None) -> Optional["BcfXml"]:
|
||||
"""
|
||||
Create a BcfXml object from a file.
|
||||
|
||||
Args:
|
||||
filename: Path to the file.
|
||||
xml_handler: XML parser and serializer.
|
||||
|
||||
Returns:
|
||||
A BcfXml object with the file contents.
|
||||
|
||||
Raises:
|
||||
ValueError: If the file name is null or empty
|
||||
"""
|
||||
if not filename:
|
||||
raise ValueError("filename is required")
|
||||
xml_handler = xml_handler or XmlParserSerializer()
|
||||
return cls(xml_handler=xml_handler, filename=filename)
|
||||
|
||||
@classmethod
|
||||
def create_new(
|
||||
cls,
|
||||
project_name: Optional[str] = None,
|
||||
extensions: Optional[mdl.Extensions] = None,
|
||||
xml_handler: Optional[AbstractXmlParserSerializer] = None,
|
||||
) -> "BcfXml":
|
||||
"""
|
||||
Create a new BcfXml object.
|
||||
|
||||
Args:
|
||||
project_name: The name of the project.
|
||||
extensions: The Extension XML object. Defaults to an empty one.
|
||||
xml_handler: XML parser and serializer.
|
||||
|
||||
Returns:
|
||||
A new BcfXml object.
|
||||
"""
|
||||
instance = cls(xml_handler=xml_handler or XmlParserSerializer())
|
||||
instance.project_info = mdl.ProjectInfo(project=mdl.Project(name=project_name, project_id=str(uuid.uuid4())))
|
||||
instance.extensions = extensions or mdl.Extensions()
|
||||
return instance
|
||||
|
||||
def save(self, filename: Optional[Path] = None, keep_open: bool = False) -> None:
|
||||
"""Save the BCF file to the given filename."""
|
||||
if not filename and not self._filename:
|
||||
raise ValueError("No file name specified, cannot save BCF file.")
|
||||
if filename:
|
||||
self._filename = filename
|
||||
with InMemoryZipFile(self._filename) as bcf_zip:
|
||||
self._save_project(bcf_zip)
|
||||
self._save_version(bcf_zip)
|
||||
self._save_extensions(bcf_zip)
|
||||
self._save_documents(bcf_zip)
|
||||
self._save_topics(bcf_zip)
|
||||
if keep_open:
|
||||
self._zip_file = self._load_zip_file()
|
||||
|
||||
def _save_project(self, destination_zip: ZipFileInterface) -> None:
|
||||
self._smart_save_xml(destination_zip, self._project_info, "project.bcfp")
|
||||
|
||||
def _save_version(self, destination_zip: ZipFileInterface) -> None:
|
||||
if not self._version and self._zip_file:
|
||||
destination_zip.writestr("bcf.version", self._zip_file.read("bcf.version"))
|
||||
else:
|
||||
self._save_xml(destination_zip, "bcf.version", self.version)
|
||||
|
||||
def _save_extensions(self, destination_zip: ZipFileInterface) -> None:
|
||||
self._smart_save_xml(destination_zip, self._extensions, "extensions.xml")
|
||||
|
||||
def _smart_save_xml(self, destination_zip: ZipFileInterface, item: Any, target: str) -> None:
|
||||
if item:
|
||||
self._save_xml(destination_zip, target, item)
|
||||
elif self._zip_file and zipfile.Path(self._zip_file, target).exists():
|
||||
destination_zip.writestr(target, self._zip_file.read(target))
|
||||
|
||||
def _save_xml(self, destination_zip: ZipFileInterface, inner_file: str, xml_obj: Any) -> None:
|
||||
destination_zip.writestr(inner_file, self._xml_handler.serialize(xml_obj))
|
||||
|
||||
def _save_documents(self, bcf_zip: ZipFileInterface) -> None:
|
||||
if self.documents:
|
||||
self.documents.save(bcf_zip)
|
||||
|
||||
def _save_topics(self, destination_zip: ZipFileInterface) -> None:
|
||||
for topic_handler in self.topics.values():
|
||||
topic_handler.save(destination_zip)
|
||||
|
||||
def add_topic(
|
||||
self, title: str, description: str, author: str, topic_type: str = "", topic_status: str = ""
|
||||
) -> TopicHandler:
|
||||
"""
|
||||
Add a new topic to the BCF.
|
||||
|
||||
Args:
|
||||
title: The title of the topic.
|
||||
description: The description of the topic.
|
||||
author: The author of the topic.
|
||||
topic_type: The type of the topic.
|
||||
topic_status: The status of the topic.
|
||||
|
||||
Returns:
|
||||
The newly created topic wrapped inside a TopicHandler object.
|
||||
"""
|
||||
topic_handler = TopicHandler.create_new(
|
||||
title,
|
||||
description,
|
||||
author,
|
||||
topic_type=topic_type,
|
||||
topic_status=topic_status,
|
||||
xml_handler=self._xml_handler,
|
||||
)
|
||||
self.topics[topic_handler.guid] = topic_handler
|
||||
return topic_handler
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if not isinstance(other, BcfXml):
|
||||
raise TypeError("Equality needs a BcfXml object.")
|
||||
return (
|
||||
self.version == other.version
|
||||
and self.project_info == other.project_info
|
||||
and self.extensions == other.extensions
|
||||
)
|
||||
|
||||
# region Deprecated methods
|
||||
def new_project(self) -> "BcfXml":
|
||||
"""Deprecated method."""
|
||||
warnings.warn("new_project is deprecated, use create_new instead.", DeprecationWarning)
|
||||
return self.create_new()
|
||||
|
||||
def get_project(self, _filepath: Optional[str] = None) -> Optional[mdl.Project]:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("get_project is deprecated, use project_info.project instead.", DeprecationWarning)
|
||||
return self.project
|
||||
|
||||
def edit_project(self) -> None:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("edit_project is deprecated, there's no need to use it.", DeprecationWarning)
|
||||
|
||||
def save_project(self, filepath: Path) -> None:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("save_project is deprecated, use save instead.", DeprecationWarning)
|
||||
self.save(filepath)
|
||||
|
||||
def get_version(self) -> str:
|
||||
warnings.warn("get_version is deprecated, use version.version_id instead.", DeprecationWarning)
|
||||
return self.version.version_id
|
||||
|
||||
def edit_version(self) -> None:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("edit_version is deprecated, there's no need to use it.", DeprecationWarning)
|
||||
|
||||
def get_topics(self) -> dict[str, TopicHandler]:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("get_topics is deprecated, use topics instead.", DeprecationWarning)
|
||||
return self.topics
|
||||
|
||||
def get_topic(self, guid: str) -> TopicHandler:
|
||||
"""Return a topic by its GUID."""
|
||||
warnings.warn("get_topic is deprecated, use topics[guid] instead", DeprecationWarning)
|
||||
return self.topics[guid]
|
||||
|
||||
def get_header(self, guid: str) -> Optional[mdl.Header]:
|
||||
"""Return the header of a Topic by its GUID."""
|
||||
return self.topics[guid].header
|
||||
|
||||
def edit_topic(self) -> None:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("edit_topic is deprecated, there's no need to use it.", DeprecationWarning)
|
||||
|
||||
def add_comment(self, _topic: mdl.Topic, _comment: Optional[mdl.Comment] = None) -> None:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("add_comment is deprecated, use topics methods instead.", DeprecationWarning)
|
||||
|
||||
def edit_comment(self) -> None:
|
||||
"""Deprecated method."""
|
||||
warnings.warn("edit_comment is deprecated, there's no need to use it.", DeprecationWarning)
|
||||
|
||||
# TODO: deprecate other methods
|
||||
# endregion
|
||||
@@ -1,61 +0,0 @@
|
||||
"""BCF XML V3 Documents handler."""
|
||||
import zipfile
|
||||
from typing import Any, Optional
|
||||
|
||||
import bcf.v3.model as mdl
|
||||
from bcf.inmemory_zipfile import ZipFileInterface
|
||||
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
|
||||
|
||||
|
||||
class DocumentsHandler:
|
||||
"""BCF documents handler."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
definition: mdl.DocumentInfo,
|
||||
documents: Optional[dict[str, bytes]] = None,
|
||||
xml_handler: Optional[AbstractXmlParserSerializer] = None,
|
||||
) -> None:
|
||||
self.definition = definition
|
||||
self.documents = documents or {}
|
||||
self._xml_handler = xml_handler or XmlParserSerializer()
|
||||
|
||||
@classmethod
|
||||
def load(
|
||||
cls,
|
||||
zip_file: zipfile.ZipFile,
|
||||
xml_handler: Optional[AbstractXmlParserSerializer] = None,
|
||||
) -> Optional["DocumentsHandler"]:
|
||||
"""
|
||||
Loads the documents from the given zip file directory.
|
||||
|
||||
Args:
|
||||
zip_path: The directory path inside the zip file.
|
||||
xml_handler: The xml parser/serializer to use.
|
||||
|
||||
Returns:
|
||||
The documents handler.
|
||||
"""
|
||||
xml_handler = xml_handler or XmlParserSerializer()
|
||||
file_to_open = zipfile.Path(zip_file, "documents.xml")
|
||||
if not file_to_open.exists():
|
||||
return None
|
||||
definition = xml_handler.parse(file_to_open.read_bytes(), mdl.DocumentInfo)
|
||||
documents = {}
|
||||
if def_docs := definition.documents:
|
||||
for document in def_docs.document:
|
||||
document_path = zipfile.Path(zip_file, f"documents/{document.guid}")
|
||||
if document_path.exists():
|
||||
documents[document.filename] = document_path.read_bytes()
|
||||
return cls(definition, documents=documents)
|
||||
|
||||
def save(self, bcf_zip: ZipFileInterface) -> None:
|
||||
"""Save the documents to the zip file."""
|
||||
bcf_zip.writestr("documents.xml", self._xml_handler.serialize(self.definition))
|
||||
if documents := self.definition.documents:
|
||||
for doc in documents.document:
|
||||
if doc.filename in self.documents:
|
||||
bcf_zip.writestr(
|
||||
f"documents/{doc.guid}",
|
||||
self.documents[doc.filename],
|
||||
)
|
||||
@@ -1,110 +0,0 @@
|
||||
from bcf.v3.model.documents import Document, DocumentInfo, DocumentInfoDocuments
|
||||
from bcf.v3.model.extensions import (
|
||||
Extensions,
|
||||
ExtensionsPriorities,
|
||||
ExtensionsSnippetTypes,
|
||||
ExtensionsStages,
|
||||
ExtensionsTopicLabels,
|
||||
ExtensionsTopicStatuses,
|
||||
ExtensionsTopicTypes,
|
||||
ExtensionsUsers,
|
||||
)
|
||||
from bcf.v3.model.markup import (
|
||||
BimSnippet,
|
||||
Comment,
|
||||
CommentViewpoint,
|
||||
DocumentReference,
|
||||
File,
|
||||
Header,
|
||||
HeaderFiles,
|
||||
Markup,
|
||||
Topic,
|
||||
TopicComments,
|
||||
TopicDocumentReferences,
|
||||
TopicLabels,
|
||||
TopicReferenceLinks,
|
||||
TopicRelatedTopics,
|
||||
TopicRelatedTopicsRelatedTopic,
|
||||
TopicViewpoints,
|
||||
ViewPoint,
|
||||
)
|
||||
from bcf.v3.model.project import Project, ProjectInfo
|
||||
from bcf.v3.model.version import Version
|
||||
from bcf.v3.model.visinfo import (
|
||||
Bitmap,
|
||||
BitmapFormat,
|
||||
ClippingPlane,
|
||||
Component,
|
||||
ComponentColoring,
|
||||
ComponentColoringColor,
|
||||
ComponentColoringColorComponents,
|
||||
Components,
|
||||
ComponentSelection,
|
||||
ComponentVisibility,
|
||||
ComponentVisibilityExceptions,
|
||||
Direction,
|
||||
Line,
|
||||
OrthogonalCamera,
|
||||
PerspectiveCamera,
|
||||
Point,
|
||||
ViewSetupHints,
|
||||
VisualizationInfo,
|
||||
VisualizationInfoBitmaps,
|
||||
VisualizationInfoClippingPlanes,
|
||||
VisualizationInfoLines,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"Document",
|
||||
"DocumentInfo",
|
||||
"DocumentInfoDocuments",
|
||||
"Extensions",
|
||||
"ExtensionsPriorities",
|
||||
"ExtensionsSnippetTypes",
|
||||
"ExtensionsStages",
|
||||
"ExtensionsTopicLabels",
|
||||
"ExtensionsTopicStatuses",
|
||||
"ExtensionsTopicTypes",
|
||||
"ExtensionsUsers",
|
||||
"BimSnippet",
|
||||
"Comment",
|
||||
"CommentViewpoint",
|
||||
"DocumentReference",
|
||||
"File",
|
||||
"Header",
|
||||
"HeaderFiles",
|
||||
"Markup",
|
||||
"Topic",
|
||||
"TopicComments",
|
||||
"TopicDocumentReferences",
|
||||
"TopicLabels",
|
||||
"TopicReferenceLinks",
|
||||
"TopicRelatedTopics",
|
||||
"TopicRelatedTopicsRelatedTopic",
|
||||
"TopicViewpoints",
|
||||
"ViewPoint",
|
||||
"Project",
|
||||
"ProjectInfo",
|
||||
"Version",
|
||||
"Bitmap",
|
||||
"BitmapFormat",
|
||||
"ClippingPlane",
|
||||
"Component",
|
||||
"ComponentColoring",
|
||||
"ComponentColoringColor",
|
||||
"ComponentColoringColorComponents",
|
||||
"ComponentSelection",
|
||||
"ComponentVisibility",
|
||||
"ComponentVisibilityExceptions",
|
||||
"Components",
|
||||
"Direction",
|
||||
"Line",
|
||||
"OrthogonalCamera",
|
||||
"PerspectiveCamera",
|
||||
"Point",
|
||||
"ViewSetupHints",
|
||||
"VisualizationInfo",
|
||||
"VisualizationInfoBitmaps",
|
||||
"VisualizationInfoClippingPlanes",
|
||||
"VisualizationInfoLines",
|
||||
]
|
||||
@@ -1,61 +0,0 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Optional
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Document:
|
||||
filename: str = field(
|
||||
metadata={
|
||||
"name": "Filename",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
description: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Description",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
guid: str = field(
|
||||
metadata={
|
||||
"name": "Guid",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class DocumentInfoDocuments:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
document: List[Document] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Document",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class DocumentInfo:
|
||||
documents: Optional[DocumentInfoDocuments] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Documents",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
@@ -1,181 +0,0 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Optional
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ExtensionsPriorities:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
priority: List[str] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Priority",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ExtensionsSnippetTypes:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
snippet_type: List[str] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "SnippetType",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ExtensionsStages:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
stage: List[str] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Stage",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ExtensionsTopicLabels:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
topic_label: List[str] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "TopicLabel",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ExtensionsTopicStatuses:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
topic_status: List[str] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "TopicStatus",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ExtensionsTopicTypes:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
topic_type: List[str] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "TopicType",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ExtensionsUsers:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
user: List[str] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "User",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Extensions:
|
||||
topic_types: Optional[ExtensionsTopicTypes] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "TopicTypes",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
topic_statuses: Optional[ExtensionsTopicStatuses] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "TopicStatuses",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
priorities: Optional[ExtensionsPriorities] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Priorities",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
topic_labels: Optional[ExtensionsTopicLabels] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "TopicLabels",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
users: Optional[ExtensionsUsers] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Users",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
snippet_types: Optional[ExtensionsSnippetTypes] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "SnippetTypes",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
stages: Optional[ExtensionsStages] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Stages",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
@@ -1,616 +0,0 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Optional
|
||||
|
||||
from xsdata.models.datatype import XmlDateTime
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class BimSnippet:
|
||||
reference: str = field(
|
||||
metadata={
|
||||
"name": "Reference",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
reference_schema: str = field(
|
||||
metadata={
|
||||
"name": "ReferenceSchema",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
snippet_type: str = field(
|
||||
metadata={
|
||||
"name": "SnippetType",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
is_external: bool = field(
|
||||
default=False,
|
||||
metadata={
|
||||
"name": "IsExternal",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class CommentViewpoint:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
guid: str = field(
|
||||
metadata={
|
||||
"name": "Guid",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class DocumentReference:
|
||||
document_guid: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "DocumentGuid",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
|
||||
}
|
||||
)
|
||||
url: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Url",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
description: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Description",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
guid: str = field(
|
||||
metadata={
|
||||
"name": "Guid",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class File:
|
||||
filename: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Filename",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
date: Optional[XmlDateTime] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Date",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
reference: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Reference",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
ifc_project: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "IfcProject",
|
||||
"type": "Attribute",
|
||||
"length": 22,
|
||||
"pattern": r"[0-9A-Za-z_$]*",
|
||||
}
|
||||
)
|
||||
ifc_spatial_structure_element: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "IfcSpatialStructureElement",
|
||||
"type": "Attribute",
|
||||
"length": 22,
|
||||
"pattern": r"[0-9A-Za-z_$]*",
|
||||
}
|
||||
)
|
||||
is_external: bool = field(
|
||||
default=True,
|
||||
metadata={
|
||||
"name": "IsExternal",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class TopicLabels:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
label: List[str] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Label",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class TopicReferenceLinks:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
reference_link: List[str] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "ReferenceLink",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class TopicRelatedTopicsRelatedTopic:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
guid: str = field(
|
||||
metadata={
|
||||
"name": "Guid",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ViewPoint:
|
||||
viewpoint: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Viewpoint",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
snapshot: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Snapshot",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
index: Optional[int] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Index",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
guid: str = field(
|
||||
metadata={
|
||||
"name": "Guid",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Comment:
|
||||
date: XmlDateTime = field(
|
||||
metadata={
|
||||
"name": "Date",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
author: str = field(
|
||||
metadata={
|
||||
"name": "Author",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
comment: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Comment",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
viewpoint: Optional[CommentViewpoint] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Viewpoint",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
modified_date: Optional[XmlDateTime] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "ModifiedDate",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
modified_author: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "ModifiedAuthor",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
guid: str = field(
|
||||
metadata={
|
||||
"name": "Guid",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class HeaderFiles:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
file: List[File] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "File",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class TopicDocumentReferences:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
document_reference: List[DocumentReference] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "DocumentReference",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class TopicRelatedTopics:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
related_topic: List[TopicRelatedTopicsRelatedTopic] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "RelatedTopic",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class TopicViewpoints:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
view_point: List[ViewPoint] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "ViewPoint",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Header:
|
||||
files: Optional[HeaderFiles] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Files",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class TopicComments:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
comment: List[Comment] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Comment",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Topic:
|
||||
reference_links: Optional[TopicReferenceLinks] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "ReferenceLinks",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
title: str = field(
|
||||
metadata={
|
||||
"name": "Title",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
priority: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Priority",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
index: Optional[int] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Index",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
labels: Optional[TopicLabels] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Labels",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
creation_date: XmlDateTime = field(
|
||||
metadata={
|
||||
"name": "CreationDate",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
creation_author: str = field(
|
||||
metadata={
|
||||
"name": "CreationAuthor",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
modified_date: Optional[XmlDateTime] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "ModifiedDate",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
modified_author: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "ModifiedAuthor",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
due_date: Optional[XmlDateTime] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "DueDate",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
assigned_to: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "AssignedTo",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
stage: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Stage",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
description: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Description",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
bim_snippet: Optional[BimSnippet] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "BimSnippet",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
document_references: Optional[TopicDocumentReferences] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "DocumentReferences",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
related_topics: Optional[TopicRelatedTopics] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "RelatedTopics",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
comments: Optional[TopicComments] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Comments",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
viewpoints: Optional[TopicViewpoints] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Viewpoints",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
guid: str = field(
|
||||
metadata={
|
||||
"name": "Guid",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
|
||||
}
|
||||
)
|
||||
server_assigned_id: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "ServerAssignedId",
|
||||
"type": "Attribute",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
topic_type: str = field(
|
||||
metadata={
|
||||
"name": "TopicType",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
topic_status: str = field(
|
||||
metadata={
|
||||
"name": "TopicStatus",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Markup:
|
||||
header: Optional[Header] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Header",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
}
|
||||
)
|
||||
topic: Topic = field(
|
||||
metadata={
|
||||
"name": "Topic",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
@@ -1,37 +0,0 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Project:
|
||||
name: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Name",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
project_id: str = field(
|
||||
metadata={
|
||||
"name": "ProjectId",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ProjectInfo:
|
||||
project: Project = field(
|
||||
metadata={
|
||||
"name": "Project",
|
||||
"type": "Element",
|
||||
"namespace": "",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
@@ -1,12 +0,0 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Version:
|
||||
version_id: str = field(
|
||||
metadata={
|
||||
"name": "VersionId",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
@@ -1,524 +0,0 @@
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from typing import List, Optional
|
||||
|
||||
|
||||
class BitmapFormat(Enum):
|
||||
PNG = "png"
|
||||
JPG = "jpg"
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Component:
|
||||
originating_system: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "OriginatingSystem",
|
||||
"type": "Element",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
authoring_tool_id: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "AuthoringToolId",
|
||||
"type": "Element",
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
ifc_guid: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "IfcGuid",
|
||||
"type": "Attribute",
|
||||
"length": 22,
|
||||
"pattern": r"[0-9A-Za-z_$]*",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Direction:
|
||||
x: float = field(
|
||||
metadata={
|
||||
"name": "X",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
y: float = field(
|
||||
metadata={
|
||||
"name": "Y",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
z: float = field(
|
||||
metadata={
|
||||
"name": "Z",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Point:
|
||||
x: float = field(
|
||||
metadata={
|
||||
"name": "X",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
y: float = field(
|
||||
metadata={
|
||||
"name": "Y",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
z: float = field(
|
||||
metadata={
|
||||
"name": "Z",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ViewSetupHints:
|
||||
spaces_visible: bool = field(
|
||||
default=False,
|
||||
metadata={
|
||||
"name": "SpacesVisible",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
space_boundaries_visible: bool = field(
|
||||
default=False,
|
||||
metadata={
|
||||
"name": "SpaceBoundariesVisible",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
openings_visible: bool = field(
|
||||
default=False,
|
||||
metadata={
|
||||
"name": "OpeningsVisible",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Bitmap:
|
||||
format: BitmapFormat = field(
|
||||
metadata={
|
||||
"name": "Format",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
reference: str = field(
|
||||
metadata={
|
||||
"name": "Reference",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
"min_length": 1,
|
||||
"white_space": "collapse",
|
||||
}
|
||||
)
|
||||
location: Point = field(
|
||||
metadata={
|
||||
"name": "Location",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
normal: Direction = field(
|
||||
metadata={
|
||||
"name": "Normal",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
up: Direction = field(
|
||||
metadata={
|
||||
"name": "Up",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
height: float = field(
|
||||
metadata={
|
||||
"name": "Height",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ClippingPlane:
|
||||
location: Point = field(
|
||||
metadata={
|
||||
"name": "Location",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
direction: Direction = field(
|
||||
metadata={
|
||||
"name": "Direction",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ComponentColoringColorComponents:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
component: List[Component] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Component",
|
||||
"type": "Element",
|
||||
"min_occurs": 1,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ComponentSelection:
|
||||
component: List[Component] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Component",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ComponentVisibilityExceptions:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
component: List[Component] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Component",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Line:
|
||||
start_point: Point = field(
|
||||
metadata={
|
||||
"name": "StartPoint",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
end_point: Point = field(
|
||||
metadata={
|
||||
"name": "EndPoint",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class OrthogonalCamera:
|
||||
"""
|
||||
Attributes
|
||||
camera_view_point:
|
||||
camera_direction:
|
||||
camera_up_vector:
|
||||
view_to_world_scale: view's visible vertical size in meters
|
||||
aspect_ratio: Proportional relationship between the width and
|
||||
the height of the view (w/h).
|
||||
"""
|
||||
camera_view_point: Point = field(
|
||||
metadata={
|
||||
"name": "CameraViewPoint",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
camera_direction: Direction = field(
|
||||
metadata={
|
||||
"name": "CameraDirection",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
camera_up_vector: Direction = field(
|
||||
metadata={
|
||||
"name": "CameraUpVector",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
view_to_world_scale: float = field(
|
||||
metadata={
|
||||
"name": "ViewToWorldScale",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
aspect_ratio: float = field(
|
||||
metadata={
|
||||
"name": "AspectRatio",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
"min_exclusive": 0.0,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class PerspectiveCamera:
|
||||
"""
|
||||
Attributes
|
||||
camera_view_point:
|
||||
camera_direction:
|
||||
camera_up_vector:
|
||||
field_of_view: Vertical field of view, in degrees. It is
|
||||
currently limited to a value between 45 and 60 degrees. This
|
||||
limitation will be dropped in the next release and viewers
|
||||
should be expect values outside this range in current
|
||||
implementations.
|
||||
aspect_ratio: Proportional relationship between the width and
|
||||
the height of the view (w/h).
|
||||
"""
|
||||
camera_view_point: Point = field(
|
||||
metadata={
|
||||
"name": "CameraViewPoint",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
camera_direction: Direction = field(
|
||||
metadata={
|
||||
"name": "CameraDirection",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
camera_up_vector: Direction = field(
|
||||
metadata={
|
||||
"name": "CameraUpVector",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
field_of_view: float = field(
|
||||
metadata={
|
||||
"name": "FieldOfView",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
"min_exclusive": 0.0,
|
||||
"max_exclusive": 180.0,
|
||||
}
|
||||
)
|
||||
aspect_ratio: float = field(
|
||||
metadata={
|
||||
"name": "AspectRatio",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
"min_exclusive": 0.0,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ComponentColoringColor:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
components: ComponentColoringColorComponents = field(
|
||||
metadata={
|
||||
"name": "Components",
|
||||
"type": "Element",
|
||||
"required": True,
|
||||
}
|
||||
)
|
||||
color: str = field(
|
||||
metadata={
|
||||
"name": "Color",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"pattern": r"[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ComponentVisibility:
|
||||
view_setup_hints: Optional[ViewSetupHints] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "ViewSetupHints",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
exceptions: Optional[ComponentVisibilityExceptions] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Exceptions",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
default_visibility: bool = field(
|
||||
default=False,
|
||||
metadata={
|
||||
"name": "DefaultVisibility",
|
||||
"type": "Attribute",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class VisualizationInfoBitmaps:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
bitmap: List[Bitmap] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Bitmap",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class VisualizationInfoClippingPlanes:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
clipping_plane: List[ClippingPlane] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "ClippingPlane",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class VisualizationInfoLines:
|
||||
class Meta:
|
||||
global_type = False
|
||||
|
||||
line: List[Line] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Line",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ComponentColoring:
|
||||
color: List[ComponentColoringColor] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "Color",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class Components:
|
||||
selection: Optional[ComponentSelection] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Selection",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
visibility: Optional[ComponentVisibility] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Visibility",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
coloring: Optional[ComponentColoring] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Coloring",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class VisualizationInfo:
|
||||
"""
|
||||
VisualizationInfo documentation.
|
||||
"""
|
||||
components: Optional[Components] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Components",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
orthogonal_camera: Optional[OrthogonalCamera] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "OrthogonalCamera",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
perspective_camera: Optional[PerspectiveCamera] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "PerspectiveCamera",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
lines: Optional[VisualizationInfoLines] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Lines",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
clipping_planes: Optional[VisualizationInfoClippingPlanes] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "ClippingPlanes",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
bitmaps: Optional[VisualizationInfoBitmaps] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"name": "Bitmaps",
|
||||
"type": "Element",
|
||||
}
|
||||
)
|
||||
guid: str = field(
|
||||
metadata={
|
||||
"name": "Guid",
|
||||
"type": "Attribute",
|
||||
"required": True,
|
||||
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
|
||||
}
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user