Compare commits
180 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 240884e646 | |||
| 3567dc8ae5 | |||
| 54f324436f | |||
| d5b31bc4f4 | |||
| 844e6377f4 | |||
| 71076d313e | |||
| 3bc2985b6b | |||
| e28b837cd6 | |||
| e22904b41b | |||
| af1949678a | |||
| 83e483555f | |||
| 4442c2a604 | |||
| 9da91f538b | |||
| 5ad8ad836a | |||
| 2723f71bfe | |||
| d298d13713 | |||
| 7f555b9d07 | |||
| 8004a45b54 | |||
| 3fd1209906 | |||
| 65c6876a23 | |||
| 72fbfa382f | |||
| 50f3178d97 | |||
| 6546b10838 | |||
| 155badc85e | |||
| d7e2587b1f | |||
| d9bbf16e5e | |||
| 676187b6fc | |||
| 800eb67afb | |||
| 46a1b4775c | |||
| f80cc7c7f5 | |||
| a7cbc628a8 | |||
| 3ab02a3931 | |||
| 31b095ff68 | |||
| b09e19dc8a | |||
| 97327dbc13 | |||
| 9ad0fca10e | |||
| bea095afd0 | |||
| d34e45fad5 | |||
| efed95615e | |||
| 9bb4b0328a | |||
| 5f9d1a5e63 | |||
| f6ba95935a | |||
| d9d58af049 | |||
| aed3bdf72a | |||
| 968f56a189 | |||
| 90d92e70b2 | |||
| efacef1789 | |||
| a590cf8330 | |||
| 05a7c66843 | |||
| c4a4752a7e | |||
| 50f1c52d24 | |||
| a5e419cdc3 | |||
| d22557c8a0 | |||
| c6e285cef8 | |||
| f81fc4e748 | |||
| 28d9e435d1 | |||
| fe5e35bae4 | |||
| 1dc5b8cd33 | |||
| 8e04847310 | |||
| b37d8d3e7f | |||
| 7d08360808 | |||
| 5ac0e92250 | |||
| 61d42a914c | |||
| 5d516154b1 | |||
| 59f74eaf8e | |||
| 1313cb34bb | |||
| 21edf462f3 | |||
| 69c854f0f4 | |||
| 78f03c8544 | |||
| 6ba56fdf35 | |||
| 386205cde7 | |||
| ba4f8886e9 | |||
| d55dff8a77 | |||
| 57f21d1e74 | |||
| b99e048aed | |||
| 3bf1b9f489 | |||
| 28261491d0 | |||
| f10646ad35 | |||
| d571f0871c | |||
| 267bb65b5e | |||
| 0968687bc3 | |||
| 71f1236252 | |||
| b76933b95f | |||
| edee74cb31 | |||
| 2007047ae2 | |||
| 8d16ca5d88 | |||
| d10325f69d | |||
| ea56506683 | |||
| 1ed379e466 | |||
| fcb6971d4d | |||
| 10f56a7ae2 | |||
| 29bbe814a0 | |||
| b161681ffa | |||
| c71b9c1915 | |||
| 02eb846dea | |||
| 899995cb51 | |||
| 85dde1033a | |||
| fffb5ab6a3 | |||
| d6829d04cb | |||
| efaa79a841 | |||
| 201e290897 | |||
| f43e6069ec | |||
| c6fc048fc3 | |||
| 8bb940c851 | |||
| c371bf32e7 | |||
| 522d3a8367 | |||
| 37954e35e7 | |||
| 49d5264ed2 | |||
| 1d53a92f8a | |||
| 2f39490fda | |||
| f322ab6c51 | |||
| f93d4ff92f | |||
| 412e850167 | |||
| 64021720ca | |||
| 3a8df68710 | |||
| e9a4b06f2b | |||
| bf8771c586 | |||
| 4cca5a64b0 | |||
| fb2788cf7a | |||
| c129f4f7d8 | |||
| 14e954545e | |||
| f87b4a8072 | |||
| d8b0b097e9 | |||
| 6345daa708 | |||
| 341eb4dda9 | |||
| daf1cadfdb | |||
| 5f0aa27996 | |||
| 9cf946f51d | |||
| bbc79e7f21 | |||
| 112b02c8bb | |||
| 74db8db4dd | |||
| cce0ca600b | |||
| 8432553fda | |||
| 5e80db500d | |||
| 33b5b350ef | |||
| 5262a9fec5 | |||
| 20d8b665d4 | |||
| 9838309fe3 | |||
| ada8e1e923 | |||
| 57917f89e5 | |||
| be028fe075 | |||
| 6ce8ad70d6 | |||
| ca35d75b0d | |||
| fbb3f9e83d | |||
| 6bda68e834 | |||
| 07e4e0c175 | |||
| 29bb5c666d | |||
| bab281235f | |||
| 3966f0ad29 | |||
| cc69dfc136 | |||
| 7ea8c24b68 | |||
| bc548c785d | |||
| b7ff2347f1 | |||
| b7bdddf640 | |||
| cc567534f1 | |||
| fc29eec6e9 | |||
| 2b4c09dac0 | |||
| 240c98dbd7 | |||
| d88adc2333 | |||
| 9bf6cb953f | |||
| 3361895e1d | |||
| 9f855c3a83 | |||
| 13a97babd8 | |||
| c72031fa5d | |||
| a592736b22 | |||
| d460a890a7 | |||
| fb18bd4118 | |||
| 567de9a3ba | |||
| 952a0ac2a4 | |||
| cbe3fd42a7 | |||
| 548f1531f1 | |||
| 720de2ffe5 | |||
| 93b92dca9d | |||
| 310cbebba9 | |||
| 532502a4a3 | |||
| 95b4867432 | |||
| 7c2162f054 | |||
| 8b8024ba7e | |||
| dd2f4586c7 | |||
| acee90fa89 |
@@ -29,7 +29,7 @@ jobs:
|
||||
sudo apt-get install --no-install-recommends \
|
||||
git cmake gcc g++ libboost-all-dev python3-all-dev swig libpcre3-dev libxml2-dev \
|
||||
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
|
||||
libhdf5-dev libcgal-dev nlohmann-json3-dev
|
||||
libhdf5-dev libcgal-dev
|
||||
|
||||
-
|
||||
name: ccache
|
||||
@@ -61,8 +61,6 @@ jobs:
|
||||
-DGMP_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DMPFR_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DHDF5_INCLUDE_DIR=/usr/include/hdf5/serial \
|
||||
-DGLTF_SUPPORT=On \
|
||||
-DJSON_INCLUDE_DIR=/usr/include \
|
||||
../cmake
|
||||
make -j $(nproc)
|
||||
make install
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
import pathlib
|
||||
import shutil
|
||||
|
||||
import requests
|
||||
import zipfile
|
||||
import os
|
||||
|
||||
# To test this locally, set these environment variables
|
||||
REPO_OWNER = os.environ.get("REPO_OWNER", "IfcOpenShell/IfcOpenShell")
|
||||
MY_WORKFLOW = os.environ.get("MY_WORKFLOW", "ci-ifcopenshell-conda-daily")
|
||||
WORKFLOW_RUN_ID = os.environ.get("WORKFLOW_RUN_ID", None)
|
||||
TOKEN = os.environ.get("GITHUB_TOKEN", None)
|
||||
# To test this locally create a fine-grained personal access token for this repo with permissions "actions:read"
|
||||
# See https://github.com/settings/tokens?type=beta
|
||||
|
||||
# This is a list of strings that indicate that a job has stopped abruptly.
|
||||
SIGNS_OF_STOPPAGE = [
|
||||
"Error: The operation was canceled.",
|
||||
"fatal error C1060: compiler is out of heap space",
|
||||
]
|
||||
|
||||
|
||||
def start_request_session():
|
||||
s = requests.Session()
|
||||
headers = {
|
||||
"Accept": "application/vnd.github+json",
|
||||
"X-GitHub-Api-Version": "2022-11-28",
|
||||
}
|
||||
if TOKEN:
|
||||
headers["Authorization"] = f"Bearer {TOKEN}"
|
||||
|
||||
s.headers = headers
|
||||
return s
|
||||
|
||||
|
||||
def get_ci_run(repo_name, run_id):
|
||||
url = f"https://api.github.com/repos/{repo_name}/actions/runs/{run_id}"
|
||||
s = start_request_session()
|
||||
response = s.get(url)
|
||||
return response.json()
|
||||
|
||||
|
||||
def evaluate_log_file_for_abrupt_stop(log_file):
|
||||
with open(log_file) as f:
|
||||
for i, line in enumerate(f):
|
||||
for sign in SIGNS_OF_STOPPAGE:
|
||||
if sign in line:
|
||||
print(f"Found sign of abrupt stoppage in [line {i}]: '{sign}'")
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def get_ci_specific_run_specific_failure_details(repo_name, run_id):
|
||||
url = f"https://api.github.com/repos/{repo_name}/actions/runs/{run_id}/attempts/1/logs"
|
||||
s = start_request_session()
|
||||
response = s.get(url)
|
||||
|
||||
# SAVE zip file
|
||||
with open("logs.zip", "wb") as f:
|
||||
f.write(response.content)
|
||||
|
||||
# unzip file
|
||||
with zipfile.ZipFile("logs.zip", "r") as zip_ref:
|
||||
zip_ref.extractall("logs")
|
||||
|
||||
failed_logs = []
|
||||
for file in pathlib.Path("logs").iterdir():
|
||||
if file.is_dir():
|
||||
continue
|
||||
|
||||
if evaluate_log_file_for_abrupt_stop(file):
|
||||
failed_logs.append(file)
|
||||
|
||||
return failed_logs
|
||||
|
||||
|
||||
def restart_job(repo_name, job_id):
|
||||
url = f"https://api.github.com/repos/{repo_name}/actions/runs/{job_id}/rerun-failed-jobs"
|
||||
s = start_request_session()
|
||||
response = s.post(url)
|
||||
return response.json()
|
||||
|
||||
|
||||
def eval_jobs():
|
||||
run = get_ci_run(REPO_OWNER, WORKFLOW_RUN_ID)
|
||||
if run["run_attempt"] > 1:
|
||||
print("This is not the first attempt. Exiting")
|
||||
return
|
||||
failed_logs = get_ci_specific_run_specific_failure_details(REPO_OWNER, WORKFLOW_RUN_ID)
|
||||
|
||||
if len(failed_logs) == 0:
|
||||
print("No runs exhibit signs of abrupt stoppage")
|
||||
return
|
||||
|
||||
print("restarting job", WORKFLOW_RUN_ID)
|
||||
r = restart_job(REPO_OWNER, WORKFLOW_RUN_ID)
|
||||
print(r)
|
||||
|
||||
shutil.rmtree("logs")
|
||||
os.remove("logs.zip")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
eval_jobs()
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pyver: [py39, py310]
|
||||
pyver: [py37, py39, py310]
|
||||
config:
|
||||
- {
|
||||
name: "Windows Build",
|
||||
@@ -62,7 +62,6 @@ jobs:
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
with:
|
||||
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
|
||||
python-version: '3.10'
|
||||
- run: echo ${{ env.DATE }}
|
||||
- name: Get current date
|
||||
id: date
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
name: ci-ifcopenshell-conda-daily
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- .github/workflows/ci-ifcopenshell-conda-daily.yml
|
||||
- conda/**
|
||||
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 * * *" # 11min before utc midnight every day
|
||||
workflow_run:
|
||||
workflows: ["ci"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
@@ -34,16 +26,20 @@ jobs:
|
||||
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: 'true' },
|
||||
{ name: Linux, distver: ubuntu-22.04, upload: 'true' },
|
||||
{ name: macOS, distver: macos-12, upload: 'true' }
|
||||
{ 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@v3
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Download MacOSX SDK
|
||||
@@ -54,20 +50,16 @@ jobs:
|
||||
sudo mv -v MacOSX10.13.sdk /opt/ && \
|
||||
ls /opt/
|
||||
- uses: seanmiddleditch/gha-setup-ninja@master
|
||||
- uses: mamba-org/provision-with-micromamba@main # https://github.com/mamba-org/provision-with-micromamba
|
||||
- uses: conda-incubator/setup-miniconda@v2 # https://github.com/conda-incubator/setup-miniconda
|
||||
with:
|
||||
channels: conda-forge
|
||||
channel-priority: strict
|
||||
activate-environment: conda-build
|
||||
python-version: ${{ matrix.pyver.distver }}
|
||||
environment-file: conda/environment.yml
|
||||
extra-specs: |
|
||||
python=${{ matrix.pyver.distver }}
|
||||
- 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
|
||||
working-directory: ./conda
|
||||
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
|
||||
working-directory: ./conda
|
||||
conda-build . --python ${{ matrix.pyver.distver }} -c conda-forge --no-remove-work-dir
|
||||
|
||||
@@ -8,11 +8,7 @@ on:
|
||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
||||
# * * * * *
|
||||
- cron: "0 0 18 * *"
|
||||
push:
|
||||
paths:
|
||||
- '.github/workflows/ci-ifcopenshell-pypi.yml'
|
||||
|
||||
- cron: "49 23 1 * *" # 11min before utc midnight
|
||||
|
||||
env:
|
||||
major: 0
|
||||
@@ -35,7 +31,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pyver: [py36, py37, py38, py39, py310, py311]
|
||||
pyver: [py36, py37, py38, py39, py310]
|
||||
config:
|
||||
- {
|
||||
name: "Windows Build",
|
||||
@@ -57,7 +53,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
with:
|
||||
python-version: '3.10' # Version range or exact version of a Python version to use, using SemVer's version range syntax
|
||||
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
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
name: ci-ifctester-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: "0 0 18 * *"
|
||||
push:
|
||||
paths:
|
||||
- '.github/workflows/ci-ifctester-pypi.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
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
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
with:
|
||||
python-version: '3.10' # 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
|
||||
cd src/ifctester &&
|
||||
make dist
|
||||
- name: Publish a Python distribution to PyPI
|
||||
uses: ortega2247/pypi-upload-action@master
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
packages_dir: src/ifctester/dist
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
- 'test/**'
|
||||
- 'conda/**'
|
||||
- 'cmake/**'
|
||||
- '.github/workflows/ci-py-only.yml'
|
||||
- '.github/workflows/ci_py_only.yml'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
@@ -46,14 +46,13 @@ jobs:
|
||||
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: ${GITHUB_WORKFLOW}
|
||||
|
||||
- name: Build ifcopenshell
|
||||
run: |
|
||||
sudo /usr/sbin/update-ccache-symlinks
|
||||
mkdir build && cd build
|
||||
PATH="/usr/lib/ccache:$PATH" cmake \
|
||||
cmake \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_PREFIX_PATH=/usr \
|
||||
-DCMAKE_SYSTEM_PREFIX_PATH=/usr \
|
||||
@@ -63,7 +62,7 @@ jobs:
|
||||
-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_add1" \
|
||||
"-DSCHEMA_VERSIONS=2x3;4" \
|
||||
-DBUILD_CONVERT=Off \
|
||||
-DGLTF_SUPPORT=On \
|
||||
-DJSON_INCLUDE_DIR=/usr/include \
|
||||
@@ -80,14 +79,13 @@ jobs:
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
sudo /usr/bin/python -m pip install -U pip
|
||||
sudo /usr/bin/python -m pip install xmlschema xsdata numpy lxml
|
||||
sudo /usr/bin/python -m pip install src/bcf --no-deps
|
||||
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
|
||||
sudo /usr/bin/python -m pip install python-dateutil
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
name: Restart failed daily conda builds
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [ ci-ifcopenshell-conda-daily ]
|
||||
types:
|
||||
- completed
|
||||
|
||||
env:
|
||||
REPO_OWNER: IfcOpenShell/IfcOpenShell
|
||||
MY_WORKFLOW: ci-ifcopenshell-conda-daily
|
||||
|
||||
jobs:
|
||||
restart-failed-runs:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Use python 3.11
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.11
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install requests
|
||||
- name: Check for failed runs
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }}
|
||||
run: |
|
||||
python check_repo_ci_jobs.py
|
||||
working-directory: .github/workflows
|
||||
@@ -57,8 +57,6 @@ jobs:
|
||||
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: ${GITHUB_WORKFLOW}
|
||||
|
||||
- name: Build ifcopenshell
|
||||
run: |
|
||||
@@ -75,7 +73,7 @@ jobs:
|
||||
-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_add1" \
|
||||
"-DSCHEMA_VERSIONS=2x3;4;4x3" \
|
||||
-DGLTF_SUPPORT=On \
|
||||
-DJSON_INCLUDE_DIR=/usr/include \
|
||||
-DCGAL_INCLUDE_DIR=/usr/include \
|
||||
@@ -88,32 +86,16 @@ jobs:
|
||||
sudo make -j $(nproc)
|
||||
sudo make install
|
||||
|
||||
- name: Run IfcConvert on Sample files
|
||||
run: |
|
||||
(find test/input src/blenderbim/test/files -name '*.ifc' | while read i; do \
|
||||
echo $i | tee -a log; \
|
||||
timeout 1m "$(which IfcConvert)" -yv "$i" "$i.obj" --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
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
sudo /usr/bin/python -m pip install -U pip
|
||||
sudo /usr/bin/python -m pip install xmlschema xsdata numpy lxml
|
||||
sudo /usr/bin/python -m pip install src/bcf --no-deps
|
||||
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 https://github.com/Andrej730/aud/archive/refs/heads/master-reduced-size.zip
|
||||
sudo /usr/bin/python -m pip install tabulate
|
||||
sudo /usr/bin/python -m pip install python-dateutil
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
|
||||
@@ -84,17 +84,6 @@ src/ifcopenshell-python/test/build
|
||||
# blenderbim libs
|
||||
src/blenderbim/blenderbim/libs
|
||||
|
||||
# blenderbim test temp files
|
||||
src/blenderbim/test/files/temp
|
||||
src/blenderbim/drawings
|
||||
src/blenderbim/layouts
|
||||
|
||||
# ifcopenshell swig and compiled files
|
||||
src/ifcopenshell-python/ifcopenshell/_ifcopenshell_wrapper.so
|
||||
src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.py
|
||||
|
||||
# apple
|
||||
.DS_Store
|
||||
|
||||
# Brickschema
|
||||
src/blenderbim/blenderbim/bim/schema/Brick.ttl
|
||||
@@ -0,0 +1,81 @@
|
||||
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
|
||||
@@ -27,7 +27,7 @@ RUN echo "deb http://archive.ubuntu.com/ubuntu focal-proposed main restricted" |
|
||||
libboost-all-dev \
|
||||
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev \
|
||||
libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
|
||||
libhdf5-serial-dev python3-pytest ; \
|
||||
libhdf5-serial-dev ; \
|
||||
rm -rf /var/lib/apt/lists/* ;
|
||||
|
||||
COPY . /home/IfcOpenShell/
|
||||
|
||||
@@ -2,12 +2,8 @@
|
||||
IfcOpenShell
|
||||
============
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/IfcOpenShell/IfcOpenShell/assets/88302/34901387-e2dd-4a0c-8e38-9ffc32a66cde">
|
||||
</p>
|
||||
|
||||
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, IFC4x2, and IFC4x3. Extensive geometric support
|
||||
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.
|
||||
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
# Dockerfile for Running AWS Lambda Function with Python and IfcOpenShell
|
||||
|
||||
# Base image: Python 3.9 from AWS's public container registry
|
||||
FROM public.ecr.aws/docker/library/python:3.9 AS build
|
||||
|
||||
# Set the location of your Lambda function code
|
||||
ARG FUNCTION_DIR="/var/task"
|
||||
|
||||
# Install necessary packages
|
||||
RUN apt-get -y update && apt-get -y install unzip curl
|
||||
|
||||
# Install AWS Lambda runtime interface client
|
||||
RUN pip install --target ${FUNCTION_DIR} awslambdaric
|
||||
|
||||
# Set the IfcOpenShell build version (check available builds at: https://blenderbim.org/docs-python/ifcopenshell-python/installation.html)
|
||||
ARG IFC_OPENSHELL_BUILD="39-v0.7.0-476ab50"
|
||||
|
||||
# Download and extract IfcOpenShell
|
||||
RUN curl https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-${IFC_OPENSHELL_BUILD}-linux64.zip -O && \
|
||||
unzip ifcopenshell-python-${IFC_OPENSHELL_BUILD}-linux64.zip && \
|
||||
mv ifcopenshell ${FUNCTION_DIR} && \
|
||||
rm ifcopenshell-python-${IFC_OPENSHELL_BUILD}-linux64.zip
|
||||
|
||||
# Copy the requirements file and install dependencies
|
||||
COPY requirements.txt .
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
# Copy the Lambda function code
|
||||
COPY ./example_handler ${FUNCTION_DIR}/example_handler
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR ${FUNCTION_DIR}
|
||||
|
||||
# Set the entrypoint for the Lambda function
|
||||
ENTRYPOINT [ "/usr/local/bin/python", "-m", "awslambdaric" ]
|
||||
|
||||
# Set the Python import path to the Lambda function handler
|
||||
# This path is relative to the root of the Lambda function code (FUNCTION_DIR)
|
||||
# Lambda invocation will look for this path
|
||||
CMD ["example_handler.extract_wall_psets_handler"]
|
||||
@@ -1,27 +0,0 @@
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.element
|
||||
import boto3
|
||||
|
||||
s3 = boto3.client('s3')
|
||||
|
||||
def extract_wall_psets_handler(event, context):
|
||||
print("Hello from lambda")
|
||||
print("Event: {}".format(event))
|
||||
print("Context: {}".format(context))
|
||||
|
||||
filename = event['body']['filename']
|
||||
|
||||
s3.download_file('my_ifc_files_bucket', filename, f'/tmp/{filename}')
|
||||
ifc_file = ifcopenshell.open(f'/tmp/{filename}')
|
||||
walls = ifc_file.by_type('IfcWall')
|
||||
|
||||
psets = []
|
||||
for wall in walls:
|
||||
wall_data = ifcopenshell.util.element.get_psets(wall)
|
||||
wall_data['id'] = wall.GlobalId
|
||||
psets.append(wall_data)
|
||||
|
||||
return {
|
||||
'statusCode': 200,
|
||||
'body': psets
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
boto3
|
||||
@@ -13,77 +13,68 @@ def request_repo_info(url: str):
|
||||
return resp
|
||||
|
||||
|
||||
def get_choco_package_info() -> str:
|
||||
resp = request_repo_info(URL_CHOCO_PACKAGE)
|
||||
html_txt = str(resp.read())
|
||||
return html_txt
|
||||
|
||||
|
||||
def get_latest_blender_version() -> list:
|
||||
html_txt = get_choco_package_info()
|
||||
return re.findall(RE_BLENDER_VERSION_MIN_MAJ_PAT, html_txt)
|
||||
|
||||
|
||||
URL_IFCOS_RELEASES = "https://github.com/IfcOpenShell/IfcOpenShell/releases"
|
||||
URL_CHOCO_PACKAGE = "https://community.chocolatey.org/packages/blender"
|
||||
URL_BLENDER_CMAKE = "https://raw.githubusercontent.com/blender/blender/{}/build_files/cmake/Modules/FindPythonLibsUnix.cmake"
|
||||
RE_BLENDER_VERSION_MIN_MAJ = r"Latest Version.+<span>Blender (\d+\.\d+)\..+</span>"
|
||||
RE_BLENDER_VERSION_MIN_MAJ_PAT = r"Latest Version.+<span>Blender (\d+\.\d+\.\d+)</span>"
|
||||
RE_BLENDER_PYTHON_VERSION_MAJ_MIN = r"SET\(_PYTHON_VERSION_SUPPORTED (\d+\.\d+)\)"
|
||||
|
||||
|
||||
if sys.argv[1] == "--do_choco_release?":
|
||||
now = datetime.datetime.now()
|
||||
blenderbim_date = (now - datetime.timedelta(days=1)).strftime("%y%m%d")
|
||||
resp = request_repo_info(URL_IFCOS_RELEASES)
|
||||
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?":
|
||||
latest_blender_version = get_latest_blender_version()
|
||||
if latest_blender_version:
|
||||
print(latest_blender_version[0], end="")
|
||||
else:
|
||||
print("[ERROR] could not determine blender_version_min_maj_pat")
|
||||
quit(1)
|
||||
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?":
|
||||
html_txt = get_choco_package_info()
|
||||
blender_version_min_maj = re.findall(RE_BLENDER_VERSION_MIN_MAJ, html_txt)
|
||||
if blender_version_min_maj:
|
||||
print(blender_version_min_maj[0], end="")
|
||||
else:
|
||||
print("[ERROR] could not determine blender_version_min_maj")
|
||||
quit(1)
|
||||
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?":
|
||||
latest_blender_version = get_latest_blender_version()
|
||||
if latest_blender_version:
|
||||
latest_blender_version_tag = f"v{latest_blender_version[0]}"
|
||||
resp = request_repo_info(URL_BLENDER_CMAKE.format(latest_blender_version_tag))
|
||||
# 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)
|
||||
found = re.findall(re_blender_python_version_maj_min, html_txt)
|
||||
if found:
|
||||
print(found[0], end="")
|
||||
else:
|
||||
print("[ERROR] could not determine blender_python_version_maj_min")
|
||||
quit(1)
|
||||
|
||||
|
||||
elif sys.argv[1] == "--pyver?":
|
||||
latest_blender_version = get_latest_blender_version()
|
||||
if latest_blender_version:
|
||||
latest_blender_version_tag = f"v{latest_blender_version[0]}"
|
||||
resp = request_repo_info(URL_BLENDER_CMAKE.format(latest_blender_version_tag))
|
||||
# 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)
|
||||
found = re.findall(re_blender_python_version_maj_min, html_txt)
|
||||
if found:
|
||||
print(f"py{found[0].replace('.', '')}", end="")
|
||||
else:
|
||||
print("[ERROR] could not determine pyver")
|
||||
quit(1)
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ cmake_minimum_required(VERSION 3.1.3)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON) # not necessary, but encouraged
|
||||
|
||||
project(IfcOpenShell VERSION 0.7.0)
|
||||
project (IfcOpenShell VERSION 0.7.0)
|
||||
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
cmake_policy(SET CMP0074 NEW)
|
||||
@@ -54,14 +54,12 @@ OPTION(USE_VLD "Use Visual Leak Detector for debugging memory leaks, MSVC-only."
|
||||
OPTION(USE_MMAP "Adds a command line options to parse IFC files from memory mapped files using Boost.Iostreams" OFF)
|
||||
OPTION(BUILD_SHARED_LIBS "Build IfcParse and IfcGeom as shared libs (SO/DLL)." OFF)
|
||||
OPTION(MSVC_PARALLEL_BUILD "Multi-threaded compilation in Microsoft Visual Studio (/MP)" OFF)
|
||||
OPTION(NO_WARN "Disable all warnings" OFF)
|
||||
OPTION(WASM_BUILD OFF)
|
||||
if (${HAS_MAX})
|
||||
OPTION(BUILD_IFCMAX "Build IfcMax, a 3ds Max plug-in, Windows-only." OFF)
|
||||
endif()
|
||||
if (${BUILD_CONVERT})
|
||||
OPTION(GLTF_SUPPORT "Build IfcConvert with glTF support (requires json.hpp)." OFF)
|
||||
OPTION(USD_SUPPORT "Build IfcConvert with USD support (requires pixar's USD library)." OFF)
|
||||
endif()
|
||||
OPTION(USERSPACE_PYTHON_PREFIX "Installs IfcPython for the current user only instead of system-wide." OFF)
|
||||
OPTION(ADD_COMMIT_SHA "Add commit sha and branch in version number, warning results in many rebuilds, requires git" OFF)
|
||||
@@ -74,14 +72,6 @@ if(MSVC AND MSVC_PARALLEL_BUILD)
|
||||
add_definitions("/MP")
|
||||
endif()
|
||||
|
||||
if(NO_WARN)
|
||||
if(MSVC)
|
||||
add_compile_options("/w")
|
||||
else()
|
||||
add_compile_options("-w")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# QtViewer requires Qt5
|
||||
OPTION(BUILD_QTVIEWER "Build IfcOpenShell Qt GUI Viewer" OFF)
|
||||
include(GNUInstallDirs)
|
||||
@@ -147,6 +137,11 @@ UNIFY_ENVVARS_AND_CACHE(PYTHON_EXECUTABLE)
|
||||
UNIFY_ENVVARS_AND_CACHE(HDF5_INCLUDE_DIR)
|
||||
UNIFY_ENVVARS_AND_CACHE(HDF5_LIBRARY_DIR)
|
||||
UNIFY_ENVVARS_AND_CACHE(HDF5_LIBRARIES)
|
||||
endif()
|
||||
UNIFY_ENVVARS_AND_CACHE(BOOST_ROOT)
|
||||
UNIFY_ENVVARS_AND_CACHE(BOOST_LIBRARYDIR)
|
||||
|
||||
if (NOT MINIMAL_BUILD)
|
||||
UNIFY_ENVVARS_AND_CACHE(CGAL_INCLUDE_DIR)
|
||||
UNIFY_ENVVARS_AND_CACHE(CGAL_LIBRARY_DIR)
|
||||
UNIFY_ENVVARS_AND_CACHE(GMP_INCLUDE_DIR)
|
||||
@@ -154,8 +149,6 @@ UNIFY_ENVVARS_AND_CACHE(GMP_LIBRARY_DIR)
|
||||
UNIFY_ENVVARS_AND_CACHE(MPFR_INCLUDE_DIR)
|
||||
UNIFY_ENVVARS_AND_CACHE(MPFR_LIBRARY_DIR)
|
||||
endif()
|
||||
UNIFY_ENVVARS_AND_CACHE(BOOST_ROOT)
|
||||
UNIFY_ENVVARS_AND_CACHE(BOOST_LIBRARYDIR)
|
||||
|
||||
if(WASM_BUILD)
|
||||
# when using the nix/build-all.py build script we should not
|
||||
@@ -177,54 +170,6 @@ add_definitions(-DWITH_GLTF)
|
||||
set(SWIG_DEFINES ${SWIG_DEFINES} -DWITH_GLTF)
|
||||
endif()
|
||||
|
||||
# Add USD support to serializers
|
||||
if(NOT MINIMAL_BUILD AND USD_SUPPORT)
|
||||
UNIFY_ENVVARS_AND_CACHE(USD_INCLUDE_DIR)
|
||||
UNIFY_ENVVARS_AND_CACHE(USD_LIBRARY_DIR)
|
||||
|
||||
if("${USD_INCLUDE_DIR}" STREQUAL "")
|
||||
find_path(USD_INCLUDE_DIR pxr.h
|
||||
[PATHS
|
||||
/usr/include/pxr
|
||||
/usr/local/include/pxr
|
||||
]
|
||||
REQUIRED
|
||||
)
|
||||
if(USD_INCLUDE_DIR)
|
||||
message(STATUS "Found USD include files in: ${USD_INCLUDE_DIR}")
|
||||
else()
|
||||
message(FATAL_ERROR "Unable to find USD include directory, specify USD_INCLUDE_DIR manually.")
|
||||
endif()
|
||||
else()
|
||||
set(USD_INCLUDE_DIR ${USD_INCLUDE_DIR} CACHE FILEPATH "USD header files")
|
||||
message(STATUS "Looking for USD include files in: ${USD_INCLUDE_DIR}")
|
||||
endif()
|
||||
|
||||
set(USD_LIBRARIES
|
||||
usd_usd
|
||||
usd_usdGeom
|
||||
usd_usdShade
|
||||
usd_usdLux
|
||||
usd_vt
|
||||
usd_sdf
|
||||
usd_tf
|
||||
usd_gf
|
||||
)
|
||||
|
||||
find_library(USD_LIBRARY
|
||||
NAMES ${USD_LIBRARIES}
|
||||
PATHS ${USD_LIBRARY_DIR})
|
||||
if(USD_LIBRARY)
|
||||
message(STATUS "USD libraries ${USD_LIBRARIES} found in: ${USD_LIBRARY_DIR}")
|
||||
link_directories(${USD_LIBRARY_DIR})
|
||||
else()
|
||||
message(FATAL_ERROR "Unable to find USD libraries in: ${USD_LIBRARY_DIR}")
|
||||
endif()
|
||||
|
||||
add_definitions(-DWITH_USD)
|
||||
set(SWIG_DEFINES ${SWIG_DEFINES} -DWITH_USD)
|
||||
endif()
|
||||
|
||||
# Set INSTALL_RPATH for target
|
||||
MACRO(SET_INSTALL_RPATHS _target _paths)
|
||||
SET(${_target}_rpaths "")
|
||||
@@ -688,7 +633,6 @@ ENDIF()
|
||||
|
||||
INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES} ${OCC_INCLUDE_DIR} ${OPENCOLLADA_INCLUDE_DIRS}
|
||||
${Boost_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIR} ${JSON_INCLUDE_DIR} ${HDF5_INCLUDE_DIR}
|
||||
${USD_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
function(files_for_ifc_version IFC_VERSION RESULT_NAME)
|
||||
@@ -897,9 +841,9 @@ endforeach()
|
||||
add_library(Serializers ${SERIALIZERS_FILES})
|
||||
set_target_properties(Serializers PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS ${CONVERT_PRECISION}" VERSION "0.6.0" SOVERSION "0.6")
|
||||
|
||||
TARGET_LINK_LIBRARIES(Serializers ${SERIALIZER_SCHEMA_LIBRARIES} ${OPENCOLLADA_LIBRARIES} ${USD_LIBRARIES})
|
||||
TARGET_LINK_LIBRARIES(Serializers ${SERIALIZER_SCHEMA_LIBRARIES} ${OPENCOLLADA_LIBRARIES})
|
||||
|
||||
endif(BUILD_CONVERT OR BUILD_IFCPYTHON)
|
||||
endif(BUILD_CONVERT or BUILD_IFCPYTHON)
|
||||
|
||||
if (BUILD_CONVERT)
|
||||
|
||||
@@ -910,7 +854,7 @@ set(IFCCONVERT_FILES ${IFCCONVERT_CPP_FILES} ${IFCCONVERT_H_FILES})
|
||||
ADD_EXECUTABLE(IfcConvert ${IFCCONVERT_FILES})
|
||||
set_target_properties(IfcConvert PROPERTIES COMPILE_FLAGS "${CONVERT_PRECISION}")
|
||||
|
||||
TARGET_LINK_LIBRARIES(IfcConvert ${IFCOPENSHELL_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES} ${HDF5_LIBRARIES} ${USD_LIBRARIES})
|
||||
TARGET_LINK_LIBRARIES(IfcConvert ${IFCOPENSHELL_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES} ${HDF5_LIBRARIES})
|
||||
|
||||
if ((NOT WIN32) AND BUILD_SHARED_LIBS)
|
||||
# Only set RPATHs when building shared libraries (i.e. IfcParse and
|
||||
@@ -953,7 +897,7 @@ find_package (Git)
|
||||
if (GIT_FOUND)
|
||||
message("git found: ${GIT_EXECUTABLE} with version ${GIT_VERSION_STRING}")
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} branch -a --contains HEAD
|
||||
COMMAND ${GIT_EXECUTABLE} branch --contains HEAD
|
||||
OUTPUT_VARIABLE git_branches
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
@@ -962,8 +906,7 @@ if (GIT_FOUND)
|
||||
string(REPLACE "*" "" git_branch_candidate_temp "${git_branch_candidate}")
|
||||
string(STRIP "${git_branch_candidate_temp}" git_branch_candidate_2)
|
||||
if (NOT git_branch_candidate_2 MATCHES "^HEAD$")
|
||||
string(REPLACE "/" ";" git_branch_candidate_2_list "${git_branch_candidate_2}")
|
||||
list(GET git_branch_candidate_2_list -1 git_branch)
|
||||
set(git_branch ${git_branch_candidate_2})
|
||||
endif()
|
||||
endforeach()
|
||||
execute_process(
|
||||
@@ -1074,7 +1017,7 @@ endforeach(COMPONENT)
|
||||
|
||||
set(CPACK_DEBIAN_PACKAGE_NAME "${PROJECT_NAME}")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_PACKAGE_CONTACT}")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "python3, libxml2, libocct-foundation-dev, libocct-modeling-algorithms-dev, libocct-modeling-data-dev, libocct-ocaf-dev, libocct-visualization-dev, libocct-data-exchange-dev, libhdf5-serial-dev, libpython3.8, python3-pytest ${BOOST_DEPS}")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "python3, libxml2, libocct-foundation-dev, libocct-modeling-algorithms-dev, libocct-modeling-data-dev, libocct-ocaf-dev, libocct-visualization-dev, libocct-data-exchange-dev, libhdf5-serial-dev, libpython3.8 ${BOOST_DEPS}")
|
||||
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION_SUMMARY "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}")
|
||||
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION}")
|
||||
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||
|
||||
@@ -41,4 +41,4 @@ cmake -G Ninja \
|
||||
|
||||
ninja
|
||||
|
||||
ninja install -j 1
|
||||
ninja install
|
||||
|
||||
@@ -10,4 +10,5 @@ dependencies:
|
||||
- ripgrep
|
||||
- pip
|
||||
- pip:
|
||||
- lief==0.13
|
||||
- --extra-index-url https://lief.s3-website.fr-par.scw.cloud/latest
|
||||
- lief==0.13.0.dev0
|
||||
@@ -1,6 +1,8 @@
|
||||
{% 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 }}
|
||||
@@ -24,7 +26,7 @@ requirements:
|
||||
host:
|
||||
- python
|
||||
- boost-cpp
|
||||
- occt ==7.7.0
|
||||
- occt
|
||||
- libxml2
|
||||
- cgal-cpp
|
||||
- hdf5
|
||||
@@ -32,12 +34,11 @@ requirements:
|
||||
- gmp # [unix]
|
||||
- mpir # [win]
|
||||
- nlohmann_json
|
||||
- zlib
|
||||
|
||||
run:
|
||||
- python
|
||||
- boost-cpp
|
||||
- occt ==7.7.0
|
||||
- occt
|
||||
- libxml2
|
||||
- cgal-cpp
|
||||
- hdf5
|
||||
@@ -45,7 +46,6 @@ requirements:
|
||||
- gmp # [unix]
|
||||
- mpir # [win]
|
||||
- nlohmann_json
|
||||
- zlib
|
||||
|
||||
test:
|
||||
imports:
|
||||
|
||||
@@ -59,10 +59,6 @@ import multiprocessing
|
||||
import platform
|
||||
import sysconfig
|
||||
|
||||
# @todo temporary for expired mpfr.org certificate on 2023-04-08
|
||||
import ssl
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
|
||||
from urllib.request import urlretrieve
|
||||
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# This CITATION.cff file was generated with cffinit.
|
||||
# Visit https://bit.ly/cffinit to generate yours today!
|
||||
|
||||
cff-version: 1.2.0
|
||||
title: bcf
|
||||
message: >-
|
||||
If you use this software, please cite it using the
|
||||
metadata from this file.
|
||||
type: software
|
||||
authors:
|
||||
- name: "IfcOpenShell contributors"
|
||||
repository-code: >-
|
||||
https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.7.0/src/bcf
|
||||
abstract: >-
|
||||
Library to read and write BCF-XML and query OpenCDE
|
||||
BCF-API modules
|
||||
keywords:
|
||||
- BCF
|
||||
- IFC
|
||||
license: LGPL-3.0-or-later
|
||||
@@ -1,11 +1,31 @@
|
||||
.PHONY: ci
|
||||
ci:
|
||||
.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:
|
||||
|
||||
@@ -27,7 +27,7 @@ with load("/path/to/file.bcf") as bcfxml:
|
||||
# Get a dictionary of topics
|
||||
topics = bcfxml.topics
|
||||
|
||||
for topic_guid, topic_handler in bcfxml.topics.items():
|
||||
for topic_handler in bcfxml.topics:
|
||||
topic = topic_handler.topic
|
||||
print("Topic guid is", topic.guid)
|
||||
print("Topic title is", topic.title)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
name: bcf-client
|
||||
channels:
|
||||
- conda-forge
|
||||
dependencies:
|
||||
- ifcopenshell
|
||||
- xsdata
|
||||
- numpy
|
||||
@@ -11,11 +11,10 @@ name = "bcf-client"
|
||||
description = "BCF-XML file handler."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.8"
|
||||
keywords = ["IFC", "BCF", "BIM"]
|
||||
keywords = ["IFC", "BCF", "BIM", "eingineering"]
|
||||
dependencies = [
|
||||
"xsdata",
|
||||
"numpy",
|
||||
"ifcopenshell",
|
||||
]
|
||||
version = "0.0.1"
|
||||
classifiers = [
|
||||
@@ -59,34 +58,20 @@ exclude_lines = [
|
||||
[tool.tox]
|
||||
legacy_tox_ini = """
|
||||
[tox]
|
||||
env_list = lint, type, py3{10,11}
|
||||
envlist = py310
|
||||
isolated_build = true
|
||||
skip_missing_interpreters = true
|
||||
requires = tox-conda
|
||||
|
||||
[testenv]
|
||||
deps =
|
||||
conda_deps =
|
||||
pytest
|
||||
pytest-cov
|
||||
coverage
|
||||
conda_channels =
|
||||
conda-forge
|
||||
conda_env = environment.yml
|
||||
commands = pytest --cov --cov-report=term tests
|
||||
|
||||
[testenv:lint]
|
||||
description = run linters
|
||||
skip_install = true
|
||||
deps =
|
||||
black
|
||||
isort
|
||||
pylint
|
||||
commands =
|
||||
black {posargs:.}
|
||||
isort {posargs:.}
|
||||
pylint {posargs:.} --output-format=colorized
|
||||
|
||||
[testenv:type]
|
||||
description = run type checks
|
||||
deps =
|
||||
mypy>=0.991
|
||||
commands =
|
||||
- mypy {posargs:src}
|
||||
"""
|
||||
|
||||
[tool.mypy]
|
||||
|
||||
@@ -3,4 +3,5 @@ mypy
|
||||
pylint
|
||||
isort
|
||||
xsdata
|
||||
tox==3.27.1
|
||||
tox
|
||||
tox-conda
|
||||
|
||||
@@ -23,9 +23,8 @@ from pathlib import Path
|
||||
from typing import Optional, Union
|
||||
|
||||
from bcf.v2.bcfxml import BcfXml as BcfXml2
|
||||
from bcf.v2.model import Version as Version2
|
||||
from bcf.v3.bcfxml import BcfXml as BcfXml3
|
||||
from bcf.v3.model import Version as Version3
|
||||
from bcf.v3.model import Version
|
||||
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
|
||||
|
||||
|
||||
@@ -66,8 +65,5 @@ def _get_version(filepath: Union[str, Path], xml_handler: Optional[AbstractXmlPa
|
||||
"""
|
||||
xml_handler = xml_handler or XmlParserSerializer()
|
||||
with zipfile.ZipFile(filepath) as bcf_zip:
|
||||
try:
|
||||
version = xml_handler.parse(bcf_zip.read("bcf.version"), Version3)
|
||||
except:
|
||||
version = xml_handler.parse(bcf_zip.read("bcf.version"), Version2)
|
||||
version = xml_handler.parse(bcf_zip.read("bcf.version"), Version)
|
||||
return version.version_id
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
from typing import Optional
|
||||
|
||||
import numpy as np
|
||||
from numpy.typing import NDArray
|
||||
|
||||
|
||||
def camera_vectors_from_element_placement(
|
||||
def calc_camera_vectors(
|
||||
elem_placement: NDArray[np.float_],
|
||||
) -> tuple[NDArray[np.float_], NDArray[np.float_], NDArray[np.float_]]:
|
||||
"""
|
||||
@@ -17,37 +15,19 @@ def camera_vectors_from_element_placement(
|
||||
Camera position, direction and up vectors
|
||||
"""
|
||||
target_position = elem_placement[:3, 3]
|
||||
return camera_vectors_from_target_position(target_position)
|
||||
|
||||
|
||||
def camera_vectors_from_target_position(
|
||||
target_position: NDArray[np.float_], offset: Optional[NDArray[np.float_]] = None
|
||||
) -> tuple[NDArray[np.float_], NDArray[np.float_], NDArray[np.float_]]:
|
||||
"""
|
||||
Calculate the vectors of a camera pointing to a target point.
|
||||
|
||||
Args:
|
||||
target_position: point the camera is pointing to.
|
||||
camera_offset: offset of the camera from the target point.
|
||||
|
||||
Returns:
|
||||
Camera position, direction and up vectors
|
||||
"""
|
||||
camera_offset = np.array((5, 5, 5)) if offset is None else offset
|
||||
camera_position = target_position + camera_offset
|
||||
camera_direction = unit_vector(-camera_offset) # pylint: disable=invalid-unary-operand-type
|
||||
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))
|
||||
return camera_position, camera_direction, camera_up
|
||||
# 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]
|
||||
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_]:
|
||||
|
||||
@@ -3,7 +3,7 @@ import uuid
|
||||
import warnings
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from typing import Any, NoReturn, Optional, TypeVar
|
||||
from typing import Any, Optional, TypeVar
|
||||
|
||||
import bcf.v2.model as mdl
|
||||
from bcf.inmemory_zipfile import InMemoryZipFile, ZipFileInterface
|
||||
@@ -50,7 +50,7 @@ class BcfXml:
|
||||
self._version = (
|
||||
self._xml_handler.parse(self._zip_file.read("bcf.version"), mdl.Version)
|
||||
if self._zip_file
|
||||
else mdl.Version(version_id="2.1")
|
||||
else mdl.Version(version_id="3.0")
|
||||
)
|
||||
return self._version
|
||||
|
||||
@@ -210,12 +210,10 @@ class BcfXml:
|
||||
self.topics[topic_handler.guid] = topic_handler
|
||||
return topic_handler
|
||||
|
||||
def __eq__(self, other: object) -> bool | NoReturn:
|
||||
return (
|
||||
self.version == other.version and self.project_info == other.project_info
|
||||
if isinstance(other, BcfXml)
|
||||
else NotImplemented
|
||||
)
|
||||
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":
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
"""BCF XML V2 Topic handler."""
|
||||
import datetime
|
||||
import tempfile
|
||||
import uuid
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from typing import Any, NoReturn, Optional
|
||||
from typing import Any, Optional
|
||||
|
||||
import numpy as np
|
||||
from ifcopenshell import entity_instance
|
||||
from numpy.typing import NDArray
|
||||
from xsdata.models.datatype import XmlDateTime
|
||||
|
||||
import bcf.v2.model as mdl
|
||||
@@ -219,88 +216,25 @@ class TopicHandler:
|
||||
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 extract_file(self, entity, outfile: Optional[Path] = None) -> Path:
|
||||
"""Extracts an element with a file into a temporary directory
|
||||
|
||||
These include header files, bim snippets, document references, and
|
||||
viewpoint bitmaps. External reference are not downloaded. Instead, the
|
||||
URI reference is returned.
|
||||
|
||||
:param entity: The entity with a file reference to extract
|
||||
:type entity: bcf.v2.model.HeaderFile,bcf.v2.model.BimSnippet,bcf.v2.model.TopicDocumentReference
|
||||
:param outfile: If provided, save the header file to that location.
|
||||
Otherwise, a temporary directory is created and the filename is
|
||||
derived from the header's original filename.
|
||||
:type outfile: pathlib.Path,optional
|
||||
:return: The filepath of the extracted file. It may be a URL if the
|
||||
header file is external.
|
||||
:rtype: Path
|
||||
"""
|
||||
if hasattr(entity, "reference"):
|
||||
reference = entity.reference
|
||||
else:
|
||||
reference = entity.referenced_document
|
||||
|
||||
if not reference:
|
||||
return
|
||||
|
||||
if getattr(entity, "is_external", False):
|
||||
return entity.reference
|
||||
|
||||
resolved_reference = self._topic_dir
|
||||
|
||||
for part in Path(reference).parts:
|
||||
if part == "..":
|
||||
resolved_reference = resolved_reference.parent
|
||||
else:
|
||||
resolved_reference = resolved_reference.joinpath(part)
|
||||
|
||||
if not outfile:
|
||||
if getattr(entity, "filename", None):
|
||||
filename = entity.filename
|
||||
else:
|
||||
filename = resolved_reference.name
|
||||
outfile = Path(tempfile.mkdtemp()) / filename
|
||||
|
||||
with open(outfile, "wb") as f:
|
||||
f.write(resolved_reference.read_bytes())
|
||||
|
||||
return outfile
|
||||
|
||||
def add_viewpoint(self, element: entity_instance) -> None:
|
||||
"""Add a viewpoint pointed at the placement of an IFC element to the topic.
|
||||
"""
|
||||
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)
|
||||
return new_viewpoint
|
||||
|
||||
def add_viewpoint_from_point_and_guids(self, position: NDArray[np.float_], *guids: str) -> None:
|
||||
"""Add a viewpoint pointing at an XYZ point in space
|
||||
|
||||
Args:
|
||||
position: the XYZ point in space
|
||||
guids: one or more element GlobalIds.
|
||||
"""
|
||||
vi_handler = VisualizationInfoHandler.create_from_point_and_guids(
|
||||
position, *guids, xml_handler=self._xml_handler
|
||||
)
|
||||
self.add_visinfo_handler(vi_handler)
|
||||
return vi_handler
|
||||
|
||||
def add_visinfo_handler(self, new_viewpoint: VisualizationInfoHandler) -> None:
|
||||
self.viewpoints[new_viewpoint.guid + ".bcfv"] = new_viewpoint
|
||||
self.markup.viewpoints.append(mdl.ViewPoint(viewpoint=new_viewpoint.guid + ".bcfv", guid=new_viewpoint.guid))
|
||||
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 | NoReturn:
|
||||
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
|
||||
)
|
||||
if isinstance(other, TopicHandler)
|
||||
else NotImplemented
|
||||
self.markup == other.markup
|
||||
and self.viewpoints == other.viewpoints
|
||||
and self.bim_snippet == other.bim_snippet
|
||||
)
|
||||
|
||||
@@ -5,15 +5,11 @@ from typing import Any, Iterable, Optional
|
||||
|
||||
import numpy as np
|
||||
from ifcopenshell import entity_instance
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.placement
|
||||
from ifcopenshell.util import placement
|
||||
from numpy.typing import NDArray
|
||||
|
||||
import bcf.v2.model as mdl
|
||||
from bcf.geometry import (
|
||||
camera_vectors_from_element_placement,
|
||||
camera_vectors_from_target_position,
|
||||
)
|
||||
from bcf.geometry import calc_camera_vectors
|
||||
from bcf.inmemory_zipfile import ZipFileInterface
|
||||
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
|
||||
|
||||
@@ -173,29 +169,6 @@ class VisualizationInfoHandler:
|
||||
xml_handler = xml_handler or XmlParserSerializer()
|
||||
return cls(visualization_info=build_viewpoint(element), xml_handler=xml_handler)
|
||||
|
||||
@classmethod
|
||||
def create_from_point_and_guids(
|
||||
cls,
|
||||
position: NDArray[np.float_],
|
||||
*guids: str,
|
||||
xml_handler: Optional[AbstractXmlParserSerializer] = None,
|
||||
) -> "VisualizationInfoHandler":
|
||||
"""
|
||||
Create a new VisualizationInfoHandler object from an IFC element.
|
||||
|
||||
Args:
|
||||
position: target point coordinates.
|
||||
*guids: One or more IFC element GUID.
|
||||
xml_handler: The XML handler to use.
|
||||
|
||||
Returns:
|
||||
The VisualizationInfoHandler object.
|
||||
"""
|
||||
xml_handler = xml_handler or XmlParserSerializer()
|
||||
return cls(
|
||||
visualization_info=build_viewpoint_from_position_and_guids(position, *guids), xml_handler=xml_handler
|
||||
)
|
||||
|
||||
|
||||
@lru_cache(maxsize=None)
|
||||
def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
|
||||
@@ -210,12 +183,7 @@ def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
|
||||
Returns:
|
||||
The BCF viewpoint definition.
|
||||
"""
|
||||
ifc_file = element.wrapped_data.file
|
||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
|
||||
elem_placement = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement)
|
||||
elem_placement[0][3] *= unit_scale
|
||||
elem_placement[1][3] *= unit_scale
|
||||
elem_placement[2][3] *= unit_scale
|
||||
elem_placement = placement.get_local_placement(element.ObjectPlacement)
|
||||
|
||||
return mdl.VisualizationInfo(
|
||||
guid=str(uuid.uuid4()),
|
||||
@@ -224,39 +192,18 @@ def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
|
||||
)
|
||||
|
||||
|
||||
def build_viewpoint_from_position_and_guids(position: NDArray[np.float_], *guids: str) -> 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:
|
||||
position: target point coordinates.
|
||||
*guids: One or more IFC element GUID.
|
||||
|
||||
Returns:
|
||||
The BCF viewpoint definition.
|
||||
"""
|
||||
return mdl.VisualizationInfo(
|
||||
guid=str(uuid.uuid4()),
|
||||
components=build_components(*guids),
|
||||
perspective_camera=build_camera_from_vectors(*camera_vectors_from_target_position(position)),
|
||||
)
|
||||
|
||||
|
||||
def build_components(*guids: str) -> mdl.Components:
|
||||
def build_components(guid: str) -> mdl.Components:
|
||||
"""
|
||||
Return the BCF components from an IFC element GUID.
|
||||
|
||||
Args:
|
||||
*guids: One or more IFC element GUID.
|
||||
guid: The IFC element GUID.
|
||||
|
||||
Returns:
|
||||
The BCF components definition.
|
||||
"""
|
||||
components = [mdl.Component(ifc_guid=guid) for guid in guids]
|
||||
return mdl.Components(
|
||||
selection=mdl.ComponentSelection(component=components),
|
||||
selection=mdl.ComponentSelection(component=[mdl.Component(ifc_guid=guid)]),
|
||||
visibility=mdl.ComponentVisibility(default_visibility=True),
|
||||
)
|
||||
|
||||
@@ -271,7 +218,7 @@ def build_camera(elem_placement: NDArray[np.float_]) -> mdl.PerspectiveCamera:
|
||||
Returns:
|
||||
The BCF camera definition.
|
||||
"""
|
||||
return build_camera_from_vectors(*camera_vectors_from_element_placement(elem_placement))
|
||||
return build_camera_from_vectors(*calc_camera_vectors(elem_placement))
|
||||
|
||||
|
||||
def build_camera_from_vectors(
|
||||
|
||||
@@ -3,7 +3,7 @@ import uuid
|
||||
import warnings
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from typing import Any, NoReturn, Optional, TypeVar
|
||||
from typing import Any, Optional, TypeVar
|
||||
|
||||
import bcf.v3.model as mdl
|
||||
from bcf.inmemory_zipfile import InMemoryZipFile, ZipFileInterface
|
||||
@@ -224,13 +224,13 @@ class BcfXml:
|
||||
self.topics[topic_handler.guid] = topic_handler
|
||||
return topic_handler
|
||||
|
||||
def __eq__(self, other: object) -> bool | NoReturn:
|
||||
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
|
||||
if isinstance(other, BcfXml)
|
||||
else NotImplemented
|
||||
)
|
||||
|
||||
# region Deprecated methods
|
||||
|
||||
@@ -3,11 +3,9 @@ import datetime
|
||||
import uuid
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from typing import Any, NoReturn, Optional
|
||||
from typing import Any, Optional
|
||||
|
||||
import numpy as np
|
||||
from ifcopenshell import entity_instance
|
||||
from numpy.typing import NDArray
|
||||
from xsdata.models.datatype import XmlDateTime
|
||||
|
||||
import bcf.v3.model as mdl
|
||||
@@ -75,7 +73,7 @@ class TopicHandler:
|
||||
self._bim_snippet = value
|
||||
|
||||
@property
|
||||
def viewpoints(self) -> dict[str, "VisualizationInfoHandler"]:
|
||||
def viewpoints(self) -> Optional[VisualizationInfoHandler]:
|
||||
if (
|
||||
not self._viewpoints
|
||||
and self._topic_dir
|
||||
@@ -145,7 +143,7 @@ class TopicHandler:
|
||||
self._save_viewpoints(destination_zip, topic_dir)
|
||||
self._save_bim_snippet(destination_zip)
|
||||
|
||||
def _save_viewpoints(self, destination_zip: ZipFileInterface, topic_dir: str) -> None:
|
||||
def _save_viewpoints(self, destination_zip, topic_dir) -> None:
|
||||
if not self.topic.viewpoints or not (viewpoints := self.topic.viewpoints.view_point):
|
||||
return
|
||||
for vpt in viewpoints:
|
||||
@@ -174,33 +172,17 @@ class TopicHandler:
|
||||
new_viewpoint = VisualizationInfoHandler.create_new(element, self._xml_handler)
|
||||
self.add_visinfo_handler(new_viewpoint)
|
||||
|
||||
def add_viewpoint_from_point_and_guids(self, position: NDArray[np.float_], *guids: str) -> None:
|
||||
"""
|
||||
Add a viewpoint tergeting an IFC element to the topic.
|
||||
|
||||
Args:
|
||||
element: The IFC element.
|
||||
"""
|
||||
vi_handler = VisualizationInfoHandler.create_from_point_and_guids(
|
||||
position, *guids, xml_handler=self._xml_handler
|
||||
)
|
||||
self.add_visinfo_handler(vi_handler)
|
||||
|
||||
def add_visinfo_handler(self, new_viewpoint: VisualizationInfoHandler) -> None:
|
||||
self.viewpoints[new_viewpoint.guid + ".bcfv"] = new_viewpoint
|
||||
self.viewpoints[new_viewpoint.guid] = new_viewpoint
|
||||
if self.topic.viewpoints is None:
|
||||
self.topic.viewpoints = mdl.TopicViewpoints()
|
||||
self.topic.viewpoints.view_point.append(
|
||||
mdl.ViewPoint(viewpoint=new_viewpoint.guid + ".bcfv", guid=new_viewpoint.guid)
|
||||
)
|
||||
self.topic.viewpoints.view_point.append(mdl.ViewPoint(viewpoint=new_viewpoint.guid, guid=new_viewpoint.guid))
|
||||
|
||||
def __eq__(self, other: object) -> bool | NoReturn:
|
||||
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
|
||||
)
|
||||
if isinstance(other, TopicHandler)
|
||||
else NotImplemented
|
||||
self.markup == other.markup
|
||||
and self.viewpoints == other.viewpoints
|
||||
and self.bim_snippet == other.bim_snippet
|
||||
)
|
||||
|
||||
@@ -9,10 +9,7 @@ from ifcopenshell.util import placement
|
||||
from numpy.typing import NDArray
|
||||
|
||||
import bcf.v3.model as mdl
|
||||
from bcf.geometry import (
|
||||
camera_vectors_from_element_placement,
|
||||
camera_vectors_from_target_position,
|
||||
)
|
||||
from bcf.geometry import calc_camera_vectors
|
||||
from bcf.inmemory_zipfile import ZipFileInterface
|
||||
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
|
||||
|
||||
@@ -172,29 +169,6 @@ class VisualizationInfoHandler:
|
||||
xml_handler = xml_handler or XmlParserSerializer()
|
||||
return cls(visualization_info=build_viewpoint(element), xml_handler=xml_handler)
|
||||
|
||||
@classmethod
|
||||
def create_from_point_and_guids(
|
||||
cls,
|
||||
position: NDArray[np.float_],
|
||||
*guids: str,
|
||||
xml_handler: Optional[AbstractXmlParserSerializer] = None,
|
||||
) -> "VisualizationInfoHandler":
|
||||
"""
|
||||
Create a new VisualizationInfoHandler object from an IFC element.
|
||||
|
||||
Args:
|
||||
position: target point coordinates.
|
||||
*guids: One or more IFC element GUID.
|
||||
xml_handler: The XML handler to use.
|
||||
|
||||
Returns:
|
||||
The VisualizationInfoHandler object.
|
||||
"""
|
||||
xml_handler = xml_handler or XmlParserSerializer()
|
||||
return cls(
|
||||
visualization_info=build_viewpoint_from_position_and_guids(position, *guids), xml_handler=xml_handler
|
||||
)
|
||||
|
||||
|
||||
@lru_cache(maxsize=None)
|
||||
def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
|
||||
@@ -218,39 +192,18 @@ def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
|
||||
)
|
||||
|
||||
|
||||
def build_viewpoint_from_position_and_guids(position: NDArray[np.float_], *guids: str) -> 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:
|
||||
position: target point coordinates.
|
||||
*guids: One or more IFC element GUID.
|
||||
|
||||
Returns:
|
||||
The BCF viewpoint definition.
|
||||
"""
|
||||
return mdl.VisualizationInfo(
|
||||
guid=str(uuid.uuid4()),
|
||||
components=build_components(*guids),
|
||||
perspective_camera=build_camera_from_vectors(*camera_vectors_from_target_position(position)),
|
||||
)
|
||||
|
||||
|
||||
def build_components(*guids: str) -> mdl.Components:
|
||||
def build_components(guid: str) -> mdl.Components:
|
||||
"""
|
||||
Return the BCF components from an IFC element GUID.
|
||||
|
||||
Args:
|
||||
*guids: One or more IFC element GUID.
|
||||
guid: The IFC element GUID.
|
||||
|
||||
Returns:
|
||||
The BCF components definition.
|
||||
"""
|
||||
components = [mdl.Component(ifc_guid=guid) for guid in guids]
|
||||
return mdl.Components(
|
||||
selection=mdl.ComponentSelection(component=components),
|
||||
selection=mdl.ComponentSelection(component=[mdl.Component(ifc_guid=guid)]),
|
||||
visibility=mdl.ComponentVisibility(default_visibility=True),
|
||||
)
|
||||
|
||||
@@ -265,7 +218,7 @@ def build_camera(elem_placement: NDArray[np.float_]) -> mdl.PerspectiveCamera:
|
||||
Returns:
|
||||
The BCF camera definition.
|
||||
"""
|
||||
return build_camera_from_vectors(*camera_vectors_from_element_placement(elem_placement))
|
||||
return build_camera_from_vectors(*calc_camera_vectors(elem_placement))
|
||||
|
||||
|
||||
def build_camera_from_vectors(
|
||||
|
||||
@@ -47,16 +47,12 @@ def test_bcf_edit_saveas(xml_handler, build_sample) -> None:
|
||||
modified_path = Path(tmp_dir) / "edited.bcf"
|
||||
parsed.save(modified_path)
|
||||
with BcfXml.load(modified_path, xml_handler=xml_handler) as modified_parsed:
|
||||
_assert_modified_parsed(modified_parsed, bcf, orig_th, parsed)
|
||||
|
||||
|
||||
def _assert_modified_parsed(modified_parsed, bcf, orig_th, parsed):
|
||||
assert modified_parsed == bcf
|
||||
parsed_th = modified_parsed.topics[orig_th.guid]
|
||||
assert parsed_th.markup != orig_th.markup
|
||||
assert parsed_th.markup == parsed.topics[orig_th.guid].markup
|
||||
assert parsed_th.viewpoints == orig_th.viewpoints
|
||||
assert parsed_th.bim_snippet == orig_th.bim_snippet
|
||||
assert modified_parsed == bcf
|
||||
parsed_th = modified_parsed.topics[orig_th.guid]
|
||||
assert parsed_th.markup != orig_th.markup
|
||||
assert parsed_th.markup == parsed.topics[orig_th.guid].markup
|
||||
assert parsed_th.viewpoints == orig_th.viewpoints
|
||||
assert parsed_th.bim_snippet == orig_th.bim_snippet
|
||||
|
||||
|
||||
def test_bcf_edit(xml_handler, build_sample) -> None:
|
||||
@@ -70,8 +66,13 @@ def test_bcf_edit(xml_handler, build_sample) -> None:
|
||||
th.topic.title = "New Topic Title"
|
||||
parsed.save()
|
||||
with BcfXml.load(file_path, xml_handler=xml_handler) as modified_parsed:
|
||||
_assert_modified_parsed(modified_parsed, bcf, orig_th, parsed)
|
||||
assert modified_parsed == bcf
|
||||
assert len(modified_parsed.topics) == 1
|
||||
parsed_th = modified_parsed.topics[orig_th.guid]
|
||||
assert parsed_th.markup != orig_th.markup
|
||||
assert parsed_th.markup == parsed.topics[orig_th.guid].markup
|
||||
assert parsed_th.viewpoints == orig_th.viewpoints
|
||||
assert parsed_th.bim_snippet == orig_th.bim_snippet
|
||||
|
||||
|
||||
def test_save_no_filename(build_sample) -> None:
|
||||
@@ -111,16 +112,11 @@ def test_massive_bcf(xml_handler) -> None:
|
||||
bcf.save(file_path)
|
||||
|
||||
|
||||
def test_equality_with_wrong_object(build_sample) -> None:
|
||||
assert build_sample[0] != "Wrong object"
|
||||
def test_equality_with_wrong_object() -> None:
|
||||
with pytest.raises(TypeError):
|
||||
build_sample[0] == "Wrong object"
|
||||
|
||||
|
||||
def test_topic_equality_with_wrong_object(build_sample) -> None:
|
||||
assert build_sample[1] != "Wrong object"
|
||||
|
||||
|
||||
def test_bcf_get_set_version(build_sample) -> None:
|
||||
bcf = build_sample[0]
|
||||
assert bcf.version.version_id == "2.1"
|
||||
bcf.version.version_id = "2.0"
|
||||
assert bcf.version.version_id == "2.0"
|
||||
def test_topic_equality_with_wrong_object() -> None:
|
||||
with pytest.raises(TypeError):
|
||||
build_sample[1] == "Wrong object"
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from bcf.v2.bcfxml import BcfXml
|
||||
|
||||
|
||||
def test_create_clash_set_bcf() -> None:
|
||||
bcfxml = BcfXml.create_new("Clash Test")
|
||||
topic = bcfxml.add_topic("Test", "Test topic", "IfcClash")
|
||||
topic.add_viewpoint_from_point_and_guids(
|
||||
np.array([10, 10, 10]),
|
||||
"firstId",
|
||||
"secondId",
|
||||
)
|
||||
assert len(topic.viewpoints) == 1
|
||||
guid, vi_handler = next((k, v) for k, v in topic.viewpoints.items())
|
||||
v_info = vi_handler.visualization_info
|
||||
assert f"{v_info.guid}.bcfv" == guid
|
||||
components = v_info.components.selection.component
|
||||
assert {c.ifc_guid for c in components} == {"firstId", "secondId"}
|
||||
camera = v_info.perspective_camera
|
||||
viewpoint = camera.camera_view_point
|
||||
assert viewpoint.x == 15
|
||||
assert viewpoint.y == 15
|
||||
assert viewpoint.z == 15
|
||||
# default direction is the unit vector of -1, -1, -1
|
||||
direction = camera.camera_direction
|
||||
assert direction.x == pytest.approx(-1 / 3**0.5)
|
||||
assert direction.y == pytest.approx(-1 / 3**0.5)
|
||||
assert direction.z == pytest.approx(-1 / 3**0.5)
|
||||
# default
|
||||
up_vector = camera.camera_up_vector
|
||||
assert up_vector.x == pytest.approx(-1 / 6**0.5)
|
||||
assert up_vector.y == pytest.approx(-1 / 6**0.5)
|
||||
assert up_vector.z == pytest.approx(1 / 1.5**0.5)
|
||||
assert camera.field_of_view == 60
|
||||
@@ -48,16 +48,12 @@ def test_bcf_edit_saveas(xml_handler, build_sample) -> None:
|
||||
modified_path = Path(tmp_dir) / "edited.bcf"
|
||||
parsed.save(modified_path)
|
||||
with BcfXml.load(modified_path, xml_handler=xml_handler) as modified_parsed:
|
||||
_assert_modified_parsed(modified_parsed, bcf, orig_th, parsed)
|
||||
|
||||
|
||||
def _assert_modified_parsed(modified_parsed, bcf, orig_th, parsed):
|
||||
assert modified_parsed == bcf
|
||||
parsed_th = modified_parsed.topics[orig_th.guid]
|
||||
assert parsed_th.markup != orig_th.markup
|
||||
assert parsed_th.markup == parsed.topics[orig_th.guid].markup
|
||||
assert parsed_th.viewpoints == orig_th.viewpoints
|
||||
assert parsed_th.bim_snippet == orig_th.bim_snippet
|
||||
assert modified_parsed == bcf
|
||||
parsed_th = modified_parsed.topics[orig_th.guid]
|
||||
assert parsed_th.markup != orig_th.markup
|
||||
assert parsed_th.markup == parsed.topics[orig_th.guid].markup
|
||||
assert parsed_th.viewpoints == orig_th.viewpoints
|
||||
assert parsed_th.bim_snippet == orig_th.bim_snippet
|
||||
|
||||
|
||||
def test_bcf_edit(xml_handler, build_sample) -> None:
|
||||
@@ -71,8 +67,13 @@ def test_bcf_edit(xml_handler, build_sample) -> None:
|
||||
th.topic.title = "New Topic Title"
|
||||
parsed.save()
|
||||
with BcfXml.load(file_path, xml_handler=xml_handler) as modified_parsed:
|
||||
_assert_modified_parsed(modified_parsed, bcf, orig_th, parsed)
|
||||
assert modified_parsed == bcf
|
||||
assert len(modified_parsed.topics) == 1
|
||||
parsed_th = modified_parsed.topics[orig_th.guid]
|
||||
assert parsed_th.markup != orig_th.markup
|
||||
assert parsed_th.markup == parsed.topics[orig_th.guid].markup
|
||||
assert parsed_th.viewpoints == orig_th.viewpoints
|
||||
assert parsed_th.bim_snippet == orig_th.bim_snippet
|
||||
|
||||
|
||||
def test_save_no_filename(build_sample) -> None:
|
||||
@@ -87,7 +88,7 @@ def test_load_no_filename() -> None:
|
||||
|
||||
|
||||
def test_save_keep_open(build_sample) -> None:
|
||||
bcf, _ = build_sample
|
||||
bcf, orig_th = build_sample
|
||||
with TemporaryDirectory() as tmp_dir:
|
||||
file_path = Path(tmp_dir) / "test.bcf"
|
||||
bcf.save(file_path, keep_open=True)
|
||||
@@ -95,6 +96,11 @@ def test_save_keep_open(build_sample) -> None:
|
||||
bcf._zip_file.close()
|
||||
|
||||
|
||||
# image = PIL.Image.new('RGB', size=(100, 100))
|
||||
# file = BinaryIO()
|
||||
# image.save(file)
|
||||
|
||||
|
||||
def test_massive_bcf(xml_handler) -> None:
|
||||
ext = mdl.Extensions(topic_types=mdl.ExtensionsTopicTypes(topic_type=["Test type"]))
|
||||
bcf = BcfXml.create_new("Test project", extensions=ext, xml_handler=xml_handler)
|
||||
@@ -113,9 +119,11 @@ def test_massive_bcf(xml_handler) -> None:
|
||||
bcf.save(file_path)
|
||||
|
||||
|
||||
def test_equality_with_wrong_object(build_sample) -> None:
|
||||
assert build_sample[0] != "Wrong object"
|
||||
def test_equality_with_wrong_object() -> None:
|
||||
with pytest.raises(TypeError):
|
||||
build_sample[0] == "Wrong object"
|
||||
|
||||
|
||||
def test_topic_equality_with_wrong_object(build_sample) -> None:
|
||||
assert build_sample[1] != "Wrong object"
|
||||
def test_topic_equality_with_wrong_object() -> None:
|
||||
with pytest.raises(TypeError):
|
||||
build_sample[1] == "Wrong object"
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from bcf.v3.bcfxml import BcfXml
|
||||
|
||||
|
||||
def test_create_clash_set_bcf() -> None:
|
||||
bcfxml = BcfXml.create_new("Clash Test")
|
||||
topic = bcfxml.add_topic("Test", "Test topic", "IfcClash")
|
||||
topic.add_viewpoint_from_point_and_guids(
|
||||
np.array([10, 10, 10]),
|
||||
"firstId",
|
||||
"secondId",
|
||||
)
|
||||
assert len(topic.viewpoints) == 1
|
||||
guid, vi_handler = next((k, v) for k, v in topic.viewpoints.items())
|
||||
v_info = vi_handler.visualization_info
|
||||
assert f"{v_info.guid}.bcfv" == guid
|
||||
components = v_info.components.selection.component
|
||||
assert {c.ifc_guid for c in components} == {"firstId", "secondId"}
|
||||
camera = v_info.perspective_camera
|
||||
viewpoint = camera.camera_view_point
|
||||
assert viewpoint.x == 15
|
||||
assert viewpoint.y == 15
|
||||
assert viewpoint.z == 15
|
||||
# default direction is the unit vector of -1, -1, -1
|
||||
direction = camera.camera_direction
|
||||
assert direction.x == pytest.approx(-1 / 3**0.5)
|
||||
assert direction.y == pytest.approx(-1 / 3**0.5)
|
||||
assert direction.z == pytest.approx(-1 / 3**0.5)
|
||||
# default
|
||||
up_vector = camera.camera_up_vector
|
||||
assert up_vector.x == pytest.approx(-1 / 6**0.5)
|
||||
assert up_vector.y == pytest.approx(-1 / 6**0.5)
|
||||
assert up_vector.z == pytest.approx(1 / 1.5**0.5)
|
||||
assert camera.field_of_view == 60
|
||||
@@ -1,26 +0,0 @@
|
||||
# This CITATION.cff file was generated with cffinit.
|
||||
# Visit https://bit.ly/cffinit to generate yours today!
|
||||
|
||||
cff-version: 1.2.0
|
||||
title: BlenderBIM Add-on
|
||||
message: >-
|
||||
If you use this software, please cite it using the
|
||||
metadata from this file.
|
||||
type: software
|
||||
authors:
|
||||
- name: "IfcOpenShell contributors"
|
||||
repository-code: >-
|
||||
https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.7.0/src/blenderbim
|
||||
url: 'https://blenderbim.org/'
|
||||
repository-artifact: 'https://blenderbim.org/download.html'
|
||||
abstract: >-
|
||||
Add-on to Blender providing a graphical native IFC
|
||||
authoring platform
|
||||
keywords:
|
||||
- IFC
|
||||
- Blender
|
||||
- NativeIFC
|
||||
license: GPL-3.0-or-later
|
||||
commit: 1fb6dac
|
||||
version: v0.0.230506
|
||||
date-released: '2023-05-23'
|
||||
@@ -1,5 +1,5 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2020-2023 Dion Moult <dion@thinkmoult.com>
|
||||
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
@@ -16,8 +16,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
PYTHON:=python3.10
|
||||
PIP:=pip3.10
|
||||
PYTHON:=python
|
||||
PATCH:=patch
|
||||
SED:=sed -i
|
||||
ifeq ($(OS),Windows_NT)
|
||||
@@ -36,123 +35,142 @@ endif
|
||||
endif
|
||||
|
||||
VERSION:=`date '+%y%m%d'`
|
||||
LAST_COMMIT_HASH:=$(shell git rev-parse HEAD)
|
||||
PYVERSION:=py310
|
||||
PYVERSION:=py37
|
||||
|
||||
ifeq ($(PYVERSION), py37)
|
||||
PYLIBDIR:=python3.7
|
||||
PYNUMBER:=37
|
||||
endif
|
||||
ifeq ($(PYVERSION), py39)
|
||||
PYLIBDIR:=python3.9
|
||||
PYNUMBER:=39
|
||||
endif
|
||||
ifeq ($(PYVERSION), py310)
|
||||
PYLIBDIR:=python3.10
|
||||
PYNUMBER:=310
|
||||
PYNUMBER:=31
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), linux)
|
||||
ifeq ($(PYVERSION), py37)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/1.7.5/download/linux-64/hpp-fcl-1.7.5-py37h5f1835d_0.tar.bz2
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/2.6.5/download/linux-64/eigenpy-2.6.5-py37h95e2c48_0.tar.bz2
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.74.0/download/linux-64/boost-1.74.0-py37h0379df6_3.tar.bz2
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/30/c0/d0526314971fc661b083ab135747dc68446a3022686da8c16d25fcf6ef07/lxml-4.6.3-cp37-cp37m-manylinux2014_x86_64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/a2/73/07f507b539527579c026ed5f411c35e287685ce794c4dfb7edf6675cdc24/Shapely-1.8.4-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/ed/d5/c2e84e1e36ab8ebea033921d5886a056c77e18bab5ab1051fcc22de2e8a2/Pillow-9.2.0-cp37-cp37m-manylinux_2_28_x86_64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py39)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/linux-64/hpp-fcl-2.3.4-py39h40a70d0_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/linux-64/eigenpy-3.1.0-py39hdfdd6bb_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/linux-64/boost-1.78.0-py39h7c9e3ff_4.tar.bz2
|
||||
QHULL_URL:=https://anaconda.org/conda-forge/qhull/2020.2/download/linux-64/qhull-2020.2-h4bd325d_2.tar.bz2
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/1.7.5/download/linux-64/hpp-fcl-1.7.5-py39hbcdfc36_0.tar.bz2
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/2.6.5/download/linux-64/eigenpy-2.6.5-py39h5aed9d1_0.tar.bz2
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.74.0/download/linux-64/boost-1.74.0-py39h5472131_3.tar.bz2
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/19/d9/a69c6aff5673554df48120565a14a50eaa41d29ae03b02faa0b023666318/lxml-4.6.3-cp39-cp39-manylinux2014_x86_64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/2d/f2/8ec281d357e8bb7d08dc8d727f0e4c8ef3dae7d3fa75c69c8e452bb82d50/shapely-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/08/12/5af915b2bc0470f4a652ef9978557a0fa8b705b122ccaec6626029e1674c/Shapely-1.8.4-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/01/61/3ff85fb4bb596ce3d223c8fcf93c8df5c12bc8899dfb4fb3cb1c5b20dd5f/Pillow-9.2.0-cp39-cp39-manylinux_2_28_x86_64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py310)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/linux-64/hpp-fcl-2.3.4-py310h995690b_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/linux-64/eigenpy-3.1.0-py310hf02b7e0_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/linux-64/boost-1.78.0-py310hc4a4660_4.tar.bz2
|
||||
QHULL_URL:=https://anaconda.org/conda-forge/qhull/2020.2/download/linux-64/qhull-2020.2-h4bd325d_2.tar.bz2
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/1.8.0/download/linux-64/hpp-fcl-1.8.0-py310hdaf7e41_1.tar.bz2
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/2.6.11/download/linux-64/eigenpy-2.6.11-py310hf3e5c9c_0.tar.bz2
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.74.0/download/linux-64/boost-1.74.0-py310h7c3ba0c_5.tar.bz2
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/25/1e/19b46d8e8881fe0df2e20945d51919eeb1817836d62a90efa8506530e45c/lxml-4.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/a8/a5/403728b5614b28083f6424dfdefec5fcf58068495fb03bb08532671c642f/shapely-2.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/60/20/c6321e3da92a4ad9495727c9aa8c423e47295572ccd35ece82d1ac013e28/Shapely-1.8.4-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/f6/51/320986ebd6d46a0e95c2240468ced73153b691ce07617078bcdf30c609ec/Pillow-9.2.0-cp310-cp310-manylinux_2_28_x86_64.whl
|
||||
endif
|
||||
ASSIMP_URL:=https://anaconda.org/conda-forge/assimp/5.0.1/download/linux-64/assimp-5.0.1-hedfc422_6.tar.bz2
|
||||
OCTOMAP_URL:=https://anaconda.org/conda-forge/octomap/1.9.8/download/linux-64/octomap-1.9.8-h924138e_0.tar.bz2
|
||||
BOOSTCPP_URL:=https://anaconda.org/conda-forge/boost-cpp/1.78.0/download/linux-64/boost-cpp-1.78.0-h6582d0a_3.conda
|
||||
OCTOMAP_URL:=https://anaconda.org/conda-forge/octomap/1.9.7/download/linux-64/octomap-1.9.7-h4bd325d_0.tar.bz2
|
||||
ZLIB_URL:=https://anaconda.org/conda-forge/zlib/1.2.11/download/linux-64/zlib-1.2.11-h516909a_1010.tar.bz2
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), macos)
|
||||
ifeq ($(PYVERSION), py37)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/1.7.5/download/osx-64/hpp-fcl-1.7.5-py37h2d7f23a_0.tar.bz2
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/2.6.5/download/osx-64/eigenpy-2.6.5-py37h0695097_0.tar.bz2
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.74.0/download/osx-64/boost-1.74.0-py37hd79e0ac_3.tar.bz2
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/1e/3e/f0abc15d5dac50939bccc589aae336d5ead4c72e7ad1039a2e0f3630ea92/lxml-4.6.3-cp37-cp37m-macosx_10_9_x86_64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/47/a9/7c644e71638bff2bbaa87f05ee62fdf6b4552a55e74bbf731d6210b6d436/Shapely-1.8.4-cp37-cp37m-macosx_10_9_x86_64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/88/49/c26fc3b5b0e82bdc9d8751d6b939da29327b0d98f7c3b95a575cbfed2743/Pillow-9.2.0-cp37-cp37m-macosx_10_10_x86_64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py39)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/osx-64/hpp-fcl-2.3.4-py39hd85b194_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/osx-64/eigenpy-3.1.0-py39hc4d6e28_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/osx-64/boost-1.78.0-py39h953a6b8_4.tar.bz2
|
||||
QHULL_URL:=https://anaconda.org/conda-forge/qhull/2020.2/download/osx-64/qhull-2020.2-h940c156_2.tar.bz2
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/1.7.5/download/osx-64/hpp-fcl-1.7.5-py39h1e32b98_0.tar.bz2
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/2.6.5/download/osx-64/eigenpy-2.6.5-py39h5405915_0.tar.bz2
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.74.0/download/osx-64/boost-1.74.0-py39ha641261_3.tar.bz2
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/b8/74/a71f7ad72e8db54ce899efab84507b801660750cbbfa6a39e6717557d36a/lxml-4.6.3-cp39-cp39-macosx_10_9_x86_64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/36/a4/7e542a209f862f967d7cb8e939eff155f4294a27d17e16441fb8bdd51a2c/shapely-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/f5/f9/bf6cc34b02b3c7d3777c5e47fa57d2f69387613bbd8decdf3577a9d83a83/Shapely-1.8.4-cp39-cp39-macosx_10_9_x86_64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/88/7a/ddfe28b485b623361457d4783007c1f9ba83a87f93e7fec32f64793efb6c/Pillow-9.2.0-cp39-cp39-macosx_10_10_x86_64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py310)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/osx-64/hpp-fcl-2.3.4-py310h1db6f5f_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/osx-64/eigenpy-3.1.0-py310h43da829_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/osx-64/boost-1.78.0-py310h3e792ce_4.tar.bz2
|
||||
QHULL_URL:=https://anaconda.org/conda-forge/qhull/2020.2/download/osx-64/qhull-2020.2-h940c156_2.tar.bz2
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/1.8.0/download/osx-64/hpp-fcl-1.8.0-py310h651ac30_1.tar.bz2
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/2.6.11/download/osx-64/eigenpy-2.6.11-py310hc03097c_0.tar.bz2
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.74.0/download/osx-64/boost-1.74.0-py310h509978a_5.tar.bz2
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/a1/44/17b7dac7a18807d30e2fe10c3328c152808f5464565e230bfd0e77f178c6/lxml-4.8.0-cp310-cp310-macosx_10_15_x86_64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/1f/2a/dc3353c2431cf53e8d04bb8fba27e584410ca3435c9c85f76d71bf0c0e80/shapely-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/f5/a8/02347c450b5507b9a7a2c15ad6a029613149468fc55ac2100ab215666159/Shapely-1.8.4-cp310-cp310-macosx_10_9_x86_64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/d8/60/b13c00d403f34110e96c1b5c0afa73ce461efe3fe960c3a7e3e7fe190d82/Pillow-9.2.0-cp310-cp310-macosx_10_10_x86_64.whl
|
||||
endif
|
||||
ASSIMP_URL:=https://anaconda.org/conda-forge/assimp/5.0.1/download/osx-64/assimp-5.0.1-h1224e73_6.tar.bz2
|
||||
OCTOMAP_URL:=https://anaconda.org/conda-forge/octomap/1.9.8/download/osx-64/octomap-1.9.8-hb8565cd_0.tar.bz2
|
||||
BOOSTCPP_URL:=https://anaconda.org/conda-forge/boost-cpp/1.78.0/download/osx-64/boost-cpp-1.78.0-hf5ba120_3.conda
|
||||
OCTOMAP_URL:=https://anaconda.org/conda-forge/octomap/1.9.7/download/osx-64/octomap-1.9.7-h940c156_0.tar.bz2
|
||||
ZLIB_URL:=https://anaconda.org/conda-forge/zlib/1.2.11/download/osx-64/zlib-1.2.11-h7795811_1010.tar.bz2
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), macosm1)
|
||||
ifeq ($(PYVERSION), py37)
|
||||
# Warning: py37 not supported on Apple M1
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/1.7.5/download/osx-64/hpp-fcl-1.7.5-py37h2d7f23a_0.tar.bz2
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/2.6.5/download/osx-64/eigenpy-2.6.5-py37h0695097_0.tar.bz2
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.74.0/download/osx-64/boost-1.74.0-py37hd79e0ac_3.tar.bz2
|
||||
LXML_URL:=https://anaconda.org/conda-forge/lxml/4.9.1/download/osx-64/lxml-4.9.1-py37h994c40b_0.tar.bz2
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/47/a9/7c644e71638bff2bbaa87f05ee62fdf6b4552a55e74bbf731d6210b6d436/Shapely-1.8.4-cp37-cp37m-macosx_10_9_x86_64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/aa/bc/21097cd891dd2fa02f2b3d767e02e883e026482e59d29975d1bc30024aa3/Pillow-9.2.0-cp39-cp39-macosx_11_0_arm64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py39)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/osx-arm64/hpp-fcl-2.3.4-py39hc34188a_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/osx-arm64/eigenpy-3.1.0-py39h13cfc01_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/osx-arm64/boost-1.78.0-py39h99de9ae_4.tar.bz2
|
||||
QHULL_URL:=https://anaconda.org/conda-forge/qhull/2020.2/download/osx-arm64/qhull-2020.2-hc021e02_2.tar.bz2
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/1.7.5/download/osx-arm64/hpp-fcl-1.7.5-py39ha69f3c1_2.tar.bz2
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/2.6.7/download/osx-arm64/eigenpy-2.6.7-py39ha69f3c1_0.tar.bz2
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/osx-arm64/boost-1.78.0-py39h2550fe3_0.tar.bz2
|
||||
LXML_URL:=https://anaconda.org/conda-forge/lxml/4.9.1/download/osx-arm64/lxml-4.9.1-py39h9eb174b_0.tar.bz2
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/ea/aa/45fbd031edf3149cb767d8b9f9db45d5faf0324d743c6b8fb0298cc022d0/shapely-2.0.1-cp39-cp39-macosx_11_0_arm64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/8e/60/8186995a96c5a27c9b79c015bbdd89c6d9a6df9988f86f3f1027ecd4a56a/Shapely-1.8.4-cp39-cp39-macosx_11_0_arm64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/aa/bc/21097cd891dd2fa02f2b3d767e02e883e026482e59d29975d1bc30024aa3/Pillow-9.2.0-cp39-cp39-macosx_11_0_arm64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py310)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/osx-arm64/hpp-fcl-2.3.4-py310h46fc4cd_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/osx-arm64/eigenpy-3.1.0-py310ha2643af_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/osx-arm64/boost-1.78.0-py310h629746b_4.tar.bz2
|
||||
QHULL_URL:=https://anaconda.org/conda-forge/qhull/2020.2/download/osx-arm64/qhull-2020.2-hc021e02_2.tar.bz2
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/1.8.0/download/osx-arm64/hpp-fcl-1.8.0-py310h5699539_2.tar.bz2
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/2.6.9/download/osx-arm64/eigenpy-2.6.9-py310habfc766_1.tar.bz2
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/osx-arm64/boost-1.78.0-py310h4566fd1_0.tar.bz2
|
||||
LXML_URL:=https://anaconda.org/conda-forge/lxml/4.9.1/download/osx-arm64/lxml-4.9.1-py310h02f21da_0.tar.bz2
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/ec/41/d59208743e737184e1b403e95a937aebb022b8459e99efbcd5208fc8be46/shapely-2.0.1-cp310-cp310-macosx_11_0_arm64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/ba/d0/75cd36c81a1aa26dd6d37cf7ae1c79b0bc2d379e0f32c359bcb00b14e5c3/Shapely-1.8.4-cp310-cp310-macosx_11_0_arm64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/0c/5f/117b653cad585f3aedfe0de996c292e67d4b020ed77f652e5a6c8c24f908/Pillow-9.2.0-cp310-cp310-macosx_11_0_arm64.whl
|
||||
endif
|
||||
ASSIMP_URL:=https://anaconda.org/conda-forge/assimp/5.0.1/download/osx-arm64/assimp-5.0.1-h0f81e16_7.tar.bz2
|
||||
OCTOMAP_URL:=https://anaconda.org/conda-forge/octomap/1.9.8/download/osx-arm64/octomap-1.9.8-hffc8910_0.tar.bz2
|
||||
BOOSTCPP_URL:=https://anaconda.org/conda-forge/boost-cpp/1.78.0/download/osx-arm64/boost-cpp-1.78.0-h9ed8d21_3.conda
|
||||
OCTOMAP_URL:=https://anaconda.org/conda-forge/octomap/1.9.7/download/osx-arm64/octomap-1.9.7-hc021e02_0.tar.bz2
|
||||
ZLIB_URL:=https://anaconda.org/conda-forge/zlib/1.2.11/download/osx-arm64/zlib-1.2.11-h90dfc92_1014.tar.bz2
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), win)
|
||||
ifeq ($(PYVERSION), py37)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/1.7.5/download/win-64/hpp-fcl-1.7.5-py37h839d6b1_0.tar.bz2
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/2.6.5/download/win-64/eigenpy-2.6.5-py37h2c32e34_0.tar.bz2
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.74.0/download/win-64/boost-1.74.0-py37h3b38789_3.tar.bz2
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/9e/5e/171ee9d40a600f565fe691ec5bf7596247ec62cfb2edc00c91afe8ea837b/lxml-4.6.3-cp37-cp37m-win_amd64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/ca/4d/85b912d7947261e6b3218b01946bcd7c2efb2bbafaf517c6fe1dc3bb8399/Shapely-1.8.4-cp37-cp37m-win_amd64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/69/f5/9e802159d78b2eaf26bf1f8b94648605993f5ca7247ac8870f065063fc40/Pillow-9.2.0-cp37-cp37m-win_amd64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py39)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/win-64/hpp-fcl-2.3.4-py39h39b25cb_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/win-64/eigenpy-3.1.0-py39hb6c915b_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/win-64/boost-1.78.0-py39hea4d8d1_4.tar.bz2
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/1.7.5/download/win-64/hpp-fcl-1.7.5-py39h2e7c763_0.tar.bz2
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/2.6.5/download/win-64/eigenpy-2.6.5-py39h3ce40e6_0.tar.bz2
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.74.0/download/win-64/boost-1.74.0-py39hefe7e4c_3.tar.bz2
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/72/d4/426ecb8849c47c3e370c87aa0ac05d85768df917ffea27fcd6686a5e6495/lxml-4.6.3-cp39-cp39-win_amd64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/a7/ae/eab645c4075093584b7a65ab71cb8ff4563a015bd935c9b55dba14b2c1eb/shapely-2.0.1-cp39-cp39-win_amd64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/72/c3/0d52812db25ca71203f6203891277e6ee4f0244b21a36c062123ece15f36/Shapely-1.8.4-cp39-cp39-win_amd64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/19/3f/b4d4bcf05dbcbe07f2e9613a8f4180c297395e73a91d8ad22c32c6624f8c/Pillow-9.2.0-cp39-cp39-win_amd64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py310)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/win-64/hpp-fcl-2.3.4-py310heb59267_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/win-64/eigenpy-3.1.0-py310hd146abe_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/win-64/boost-1.78.0-py310h220cb41_4.tar.bz2
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/1.8.0/download/win-64/hpp-fcl-1.8.0-py310hc5a3c62_1.tar.bz2
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/2.6.11/download/win-64/eigenpy-2.6.11-py310hbd43d28_0.tar.bz2
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.74.0/download/win-64/boost-1.74.0-py310hc781a3c_5.tar.bz2
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/f6/71/65c80a4caa1617a4c6e8fe1500cebb179db96232e2f623bfe6a1f4294e39/lxml-4.8.0-cp310-cp310-win_amd64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/81/8a/7ac076a86b2632f1872284c5e60ed5f2fc26094875a85b35d9fa17b52504/shapely-2.0.1-cp310-cp310-win_amd64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/24/b5/46d13799804b5fe9ede2eca8b19023410e29b78baca0bff727671a1df8c1/Shapely-1.8.4-cp310-cp310-win_amd64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/02/55/67a3c17b9e7d972ed8c246f104da99ca4f3ea42fba566697e479011b84b6/Pillow-9.2.0-cp310-cp310-win_amd64.whl
|
||||
endif
|
||||
ASSIMP_URL:=https://anaconda.org/conda-forge/assimp/5.0.1/download/win-64/assimp-5.0.1-hc2aa0de_6.tar.bz2
|
||||
OCTOMAP_URL:=https://anaconda.org/conda-forge/octomap/1.9.8/download/win-64/octomap-1.9.8-h91493d7_0.tar.bz2
|
||||
BOOSTCPP_URL:=https://anaconda.org/conda-forge/boost-cpp/1.78.0/download/win-64/boost-cpp-1.78.0-h9f4b32c_3.conda
|
||||
OCTOMAP_URL:=https://anaconda.org/conda-forge/octomap/1.9.7/download/win-64/octomap-1.9.7-h5362a0b_0.tar.bz2
|
||||
ZLIB_URL:=https://anaconda.org/conda-forge/zlib/1.2.11/download/win-64/zlib-1.2.11-h62dcd97_1010.tar.bz2
|
||||
endif
|
||||
|
||||
.PHONY: bump
|
||||
bump:
|
||||
cd . && $(SED) "s/$(OLD)/$(NEW)/" Makefile
|
||||
cd ../ifcopenshell-python/ && $(SED) "s/$(OLD)/$(NEW)/" Makefile
|
||||
cd ../ifcopenshell-python/docs/ifcconvert/ && $(SED) "s/$(OLD)/$(NEW)/" installation.rst
|
||||
cd ../ifcopenshell-python/docs/ifcopenshell-python/ && $(SED) "s/$(OLD)/$(NEW)/" installation.rst
|
||||
|
||||
.PHONY: dist
|
||||
dist:
|
||||
ifndef PLATFORM
|
||||
@@ -164,7 +182,7 @@ endif
|
||||
cp -r blenderbim/* dist/blenderbim/
|
||||
|
||||
# Provides IfcOpenShell Python functionality
|
||||
cd dist/working && wget https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-$(PYNUMBER)-v0.7.0-fc50bdd-$(PLATFORM)64.zip
|
||||
cd dist/working && wget https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-$(PYNUMBER)-v0.7.0-cdde536-$(PLATFORM)64.zip
|
||||
cd dist/working && unzip ifcopenshell-python*
|
||||
cp -r dist/working/ifcopenshell dist/blenderbim/libs/site/packages/
|
||||
|
||||
@@ -180,16 +198,16 @@ endif
|
||||
# IfcOpenBot sometimes lags behind, so we hotfix the Python utilities
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifcopenshell-python/ifcopenshell/util/* dist/blenderbim/libs/site/packages/ifcopenshell/util/
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifcopenshell-python/ifcopenshell/api/* dist/blenderbim/libs/site/packages/ifcopenshell/api/
|
||||
cp dist/working/IfcOpenShell-0.7.0/src/ifcopenshell-python/ifcopenshell/*.py dist/blenderbim/libs/site/packages/ifcopenshell/
|
||||
cp dist/working/IfcOpenShell-0.7.0/src/ifcopenshell-python/ifcopenshell/express/rule_executor.py dist/blenderbim/libs/site/packages/ifcopenshell/express/
|
||||
cp dist/working/IfcOpenShell-0.7.0/src/ifcopenshell-python/ifcopenshell/entity_instance.py dist/blenderbim/libs/site/packages/ifcopenshell/
|
||||
cp dist/working/IfcOpenShell-0.7.0/src/ifcopenshell-python/ifcopenshell/file.py dist/blenderbim/libs/site/packages/ifcopenshell/
|
||||
# Provides bcf functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/bcf/src/bcf dist/blenderbim/libs/site/packages/
|
||||
# Provides IFCClash functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifcclash/ifcclash dist/blenderbim/libs/site/packages/
|
||||
# Provides BIMTester functionality
|
||||
cd dist/working && $(PYTHON) -m venv env
|
||||
cd dist/working && . env/bin/activate && $(PIP) install pybabel
|
||||
cd dist/working && . env/bin/activate && $(PIP) install babel
|
||||
cd dist/working && . env/bin/activate && pip install pybabel
|
||||
cd dist/working && . env/bin/activate && pip install babel
|
||||
cd dist/working && . env/bin/activate && ./env/bin/pybabel compile -d ./IfcOpenShell-0.7.0/src/ifcbimtester/bimtester/locale/
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifcbimtester/bimtester dist/blenderbim/libs/site/packages/
|
||||
# Provides IFCTester functionality
|
||||
@@ -208,15 +226,9 @@ endif
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifc5d/ifc5d dist/blenderbim/libs/site/packages/
|
||||
# Provides IFCCityJSON functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifccityjson dist/blenderbim/libs/site/packages/
|
||||
# Provides IfcGit functionality
|
||||
cd dist/working && . env/bin/activate && $(PIP) install GitPython --target=./site-packages
|
||||
cp -r dist/working/site-packages/smmap dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/site-packages/gitdb dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/site-packages/git dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Provides Mustache templating in construction documentation
|
||||
# TODO: remove this dependency, it seems overkill and we seem to get by with str replaces
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/3f/e7/8750ba6c6101d6aa5ceeb20c013adf2c6f3554a12c71d75654b468404bfa/pystache-0.6.0.tar.gz
|
||||
cd dist/working && tar -xzvf pystache*
|
||||
@@ -258,13 +270,6 @@ endif
|
||||
cp -r dist/working/decorator-5.0.9/src/decorator.py dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Provides audio playback for costing
|
||||
mkdir -p dist/working
|
||||
git clone https://github.com/Andrej730/aud.git --branch master-reduced-size --depth 1 dist/working/aud
|
||||
cd dist/working/aud && git checkout 529af208fbcb707c387bfb681d2605c0b6112de7
|
||||
cp -r dist/working/aud/aud dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Provides jsgantt-improved supports for web-based construction sequencing gantt charts
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://raw.githubusercontent.com/jsGanttImproved/jsgantt-improved/master/dist/jsgantt.js
|
||||
@@ -348,10 +353,10 @@ endif
|
||||
cd dist/working && cp *.whl shapely.zip && unzip shapely.zip
|
||||
cp -r dist/working/shapely dist/blenderbim/libs/site/packages/
|
||||
ifeq ($(PLATFORM), win)
|
||||
cp -r dist/working/shapely.libs dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/Shapely.libs dist/blenderbim/libs/site/packages/
|
||||
endif
|
||||
ifeq ($(PLATFORM), linux)
|
||||
cp -r dist/working/shapely.libs dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/Shapely.libs dist/blenderbim/libs/site/packages/
|
||||
endif
|
||||
rm -rf dist/working
|
||||
|
||||
@@ -373,23 +378,19 @@ endif
|
||||
cp -r dist/working/tqdm-4.50.0/tqdm dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by IFCCityJSON
|
||||
mkdir dist/working
|
||||
cd dist/working && $(PYTHON) -m venv env
|
||||
cd dist/working && mkdir site-packages
|
||||
# Required by IFCCityJSON
|
||||
cd dist/working && . env/bin/activate && $(PIP) install cjio --target=./site-packages
|
||||
# Provides express rule validation for ifcopenshell.validate
|
||||
cd dist/working && . env/bin/activate && $(PIP) install pytest --target=./site-packages
|
||||
# Provides Brickschema functionality
|
||||
cd dist/working && . env/bin/activate && $(PIP) install brickschema[persistence] --target=./site-packages
|
||||
cd dist/working && . env/bin/activate && pip install cjio --target=./site-packages
|
||||
cd dist/working/site-packages/ && rm -r *dist-info*
|
||||
cp -r dist/working/site-packages/* dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by IFCClash
|
||||
mkdir dist/working
|
||||
cd dist/working && wget $(HPPFCL_URL)
|
||||
cd dist/working && unzip hpp-fcl*
|
||||
cd dist/working && tar -I zstd -xvf pkg*
|
||||
cd dist/working && tar -xf hpp-fcl*
|
||||
ifeq ($(PLATFORM), linux)
|
||||
cp -r dist/working/lib/$(PYLIBDIR)/site-packages/hppfcl dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/lib/*.so* dist/blenderbim/libs/
|
||||
@@ -398,10 +399,6 @@ ifeq ($(PLATFORM), macos)
|
||||
cp -r dist/working/lib/$(PYLIBDIR)/site-packages/hppfcl dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/lib/*.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), macosm1)
|
||||
cp -r dist/working/lib/$(PYLIBDIR)/site-packages/hppfcl dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/lib/*.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), win)
|
||||
cp -r dist/working/Lib/site-packages/hppfcl dist/blenderbim/libs/site/packages/
|
||||
cp -r dist/working/Library/bin/*.dll dist/blenderbim/libs/site/packages/hppfcl/
|
||||
@@ -418,45 +415,21 @@ endif
|
||||
ifeq ($(PLATFORM), macos)
|
||||
cp -r dist/working/lib/*.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), macosm1)
|
||||
cp -r dist/working/lib/*.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), win)
|
||||
cp -r dist/working/Library/bin/*.dll dist/blenderbim/libs/site/packages/hppfcl/
|
||||
endif
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by hpp-fcl except on Windows
|
||||
ifneq ($(PLATFORM), win)
|
||||
mkdir dist/working
|
||||
cd dist/working && wget $(QHULL_URL)
|
||||
cd dist/working && tar -xf qhull*
|
||||
ifeq ($(PLATFORM), linux)
|
||||
cp -r dist/working/lib/*.so* dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), macos)
|
||||
cp -r dist/working/lib/*.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), macosm1)
|
||||
cp -r dist/working/lib/*.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
rm -rf dist/working
|
||||
endif
|
||||
|
||||
# Required by hpp-fcl
|
||||
mkdir dist/working
|
||||
cd dist/working && wget $(EIGENPY_URL)
|
||||
cd dist/working && unzip eigenpy*
|
||||
cd dist/working && tar -I zstd -xvf pkg*
|
||||
cd dist/working && tar -xf eigenpy*
|
||||
ifeq ($(PLATFORM), linux)
|
||||
cp -r dist/working/lib/*.so* dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), macos)
|
||||
cp -r dist/working/lib/*.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), macosm1)
|
||||
cp -r dist/working/lib/*.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), win)
|
||||
cp -r dist/working/Library/bin/*.dll dist/blenderbim/libs/site/packages/hppfcl/
|
||||
endif
|
||||
@@ -472,9 +445,6 @@ endif
|
||||
ifeq ($(PLATFORM), macos)
|
||||
cp -r dist/working/lib/*.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), macosm1)
|
||||
cp -r dist/working/lib/*.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), win)
|
||||
# Uh, do nothing, apparently? No DLLs are shipped.
|
||||
endif
|
||||
@@ -490,33 +460,11 @@ endif
|
||||
ifeq ($(PLATFORM), macos)
|
||||
cp -r dist/working/lib/*.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), macosm1)
|
||||
cp -r dist/working/lib/*.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), win)
|
||||
cp -r dist/working/Library/bin/*.dll dist/blenderbim/libs/site/packages/hppfcl/
|
||||
endif
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by hpp-fcl
|
||||
mkdir dist/working
|
||||
cd dist/working && wget $(BOOSTCPP_URL)
|
||||
cd dist/working && unzip boost-cpp*
|
||||
cd dist/working && tar -I zstd -xvf pkg*
|
||||
ifeq ($(PLATFORM), linux)
|
||||
cp -r dist/working/lib/libboost_serialization.so* dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), macos)
|
||||
cp -r dist/working/lib/libboost_serialization.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), macosm1)
|
||||
cp -r dist/working/lib/libboost_serialization.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), win)
|
||||
cp -r dist/working/Library/bin/boost_serialization.dll dist/blenderbim/libs/site/packages/hppfcl/
|
||||
endif
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by hpp-fcl
|
||||
mkdir dist/working
|
||||
cd dist/working && wget $(ZLIB_URL)
|
||||
@@ -527,9 +475,6 @@ endif
|
||||
ifeq ($(PLATFORM), macos)
|
||||
cp -r dist/working/lib/*.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), macosm1)
|
||||
cp -r dist/working/lib/*.dylib dist/blenderbim/libs/
|
||||
endif
|
||||
ifeq ($(PLATFORM), win)
|
||||
cp -r dist/working/Library/bin/*.dll dist/blenderbim/libs/site/packages/hppfcl/
|
||||
endif
|
||||
@@ -583,7 +528,6 @@ endif
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by IFCCOBie for XLSX support
|
||||
# TODO: see if we can replace this with openpyxl which does both read/write
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/0c/bc/82d6783f83f65f56d8b77d052773c4a2f952fa86385f0cd54e1e006658d7/XlsxWriter-1.2.9.tar.gz
|
||||
cd dist/working && tar -xzvf XlsxWriter*
|
||||
@@ -648,9 +592,35 @@ endif
|
||||
|
||||
# Provides Brickschema functionality
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/ca/37/8309da9a72407d2f5eb5489c197ac3cfe96ee3ccba1902d2a0ecc7843f92/brickschema-0.5.1.tar.gz
|
||||
cd dist/working && tar -xzvf brickschema*
|
||||
# This is an evil hack because we don't want to bundle flask
|
||||
echo "" > dist/working/brickschema-0.5.1/brickschema/web.py
|
||||
cd dist/working/brickschema-0.5.1/ && cp -r brickschema ../../blenderbim/libs/site/packages/
|
||||
# For now lets bundle the latest nightly schema
|
||||
cd dist/working && wget https://github.com/BrickSchema/Brick/releases/download/nightly/Brick.ttl
|
||||
cd dist/working && cp Brick.ttl ../blenderbim/bim/schema/Brick.ttl
|
||||
cd dist/working && cp Brick.ttl ../../blenderbim/bim/schema/Brick.ttl
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by brickschema
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/c7/22/37bb938be8e5c20d443b0c9ba0a243573b671b01739efb0a19f81bc5b470/pyshacl-0.17.2.tar.gz
|
||||
cd dist/working && tar -xzvf pyshacl*
|
||||
cd dist/working/pyshacl-0.17.2/ && cp -r pyshacl ../../blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by brickschema
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/d2/a7/be8244688bfcee37c23733ab4fe8e6afa6d4403bd2674a3ae7bd2cecc77b/rdflib-6.0.2.tar.gz
|
||||
cd dist/working && tar -xzvf rdflib*
|
||||
cd dist/working/rdflib-6.0.2/ && cp -r rdflib ../../blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by brickschema
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/7d/c7/208aece36279e4f1236e437119358786e39530ecc1719d4e1afeddba5288/owlrl-6.0.2.tar.gz
|
||||
cd dist/working && tar -xzvf owlrl*
|
||||
cd dist/working/owlrl-6.0.2/ && cp -r owlrl ../../blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by brickschema
|
||||
@@ -661,22 +631,7 @@ endif
|
||||
cd dist/working/ && cp -r pkg_resources ../blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required for hipped roof generation
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://github.com/prochitecture/bpypolyskel/archive/refs/heads/master.zip
|
||||
cd dist/working && unzip master.zip
|
||||
cp -r dist/working/bpypolyskel-master/bpypolyskel dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required for Desktop icon and file association
|
||||
cp -r blenderbim/libs/desktop dist/blenderbim/libs/
|
||||
|
||||
# Remove dependencies also bundled with Blender
|
||||
rm -rf dist/blenderbim/libs/site/packages/numpy
|
||||
rm -rf dist/blenderbim/libs/site/packages/numpy.libs
|
||||
|
||||
cd dist/blenderbim && $(SED) "s/999999/$(VERSION)/" __init__.py
|
||||
cd dist/blenderbim/bim && $(SED) "s/8888888/$(LAST_COMMIT_HASH)/" __init__.py
|
||||
cd dist && zip -r blenderbim-$(VERSION)-$(PYVERSION)-$(PLATFORM).zip ./*
|
||||
rm -rf dist/blenderbim
|
||||
|
||||
|
||||
@@ -22,21 +22,19 @@ import site
|
||||
|
||||
bl_info = {
|
||||
"name": "BlenderBIM",
|
||||
"description": "Transforms Blender into a native Building Information Model authoring platform using IFC.",
|
||||
"description": "Author, import, and export data using the Industry Foundation Classes schema",
|
||||
"author": "IfcOpenShell Contributors",
|
||||
"blender": (3, 1, 0),
|
||||
"blender": (2, 80, 0),
|
||||
"version": (0, 0, 999999),
|
||||
"location": "File Menu, Scene Properties Tab. See documentation for more.",
|
||||
"doc_url": "https://blenderbim.org/docs",
|
||||
"location": "File > Export, File > Import, Scene / Object / Material / Mesh Properties",
|
||||
"tracker_url": "https://github.com/IfcOpenShell/IfcOpenShell/issues",
|
||||
"category": "System",
|
||||
"category": "Import-Export",
|
||||
}
|
||||
|
||||
if sys.modules.get("bpy", None):
|
||||
# Process *.pth in /libs/site/packages to setup globally importable modules
|
||||
# This is 3 levels deep as required by the static RPATH of ../../ from dependencies taken from Anaconda
|
||||
# site.addsitedir(os.path.join(os.path.dirname(os.path.realpath(__file__)), "libs", "site", "packages"))
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), "libs", "site", "packages"))
|
||||
site.addsitedir(os.path.join(os.path.dirname(os.path.realpath(__file__)), "libs", "site", "packages"))
|
||||
|
||||
import blenderbim.bim
|
||||
|
||||
|
||||
@@ -16,16 +16,10 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import bpy
|
||||
import bpy.utils.previews
|
||||
import blenderbim
|
||||
import importlib
|
||||
from . import handler, ui, prop, operator, helper
|
||||
|
||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
modules = {
|
||||
"project": None,
|
||||
"search": None,
|
||||
@@ -76,7 +70,6 @@ modules = {
|
||||
"covetool": None,
|
||||
"augin": None,
|
||||
"debug": None,
|
||||
"ifcgit": None,
|
||||
# Uncomment this line to enable loading of the demo module. Happy hacking!
|
||||
# The name "demo" must correlate to a folder name in `bim/module/`.
|
||||
# "demo": None,
|
||||
@@ -91,18 +84,15 @@ classes = [
|
||||
operator.AddIfcFile,
|
||||
operator.BIM_OT_add_section_plane,
|
||||
operator.BIM_OT_remove_section_plane,
|
||||
operator.ConfigureVisibility,
|
||||
operator.OpenUpstream,
|
||||
operator.OpenUri,
|
||||
operator.SwitchTab,
|
||||
operator.SetTab,
|
||||
operator.ReloadIfcFile,
|
||||
operator.RemoveIfcFile,
|
||||
operator.SelectDataDir,
|
||||
operator.SelectIfcFile,
|
||||
operator.ReloadSelectedIfcFile,
|
||||
operator.SelectSchemaDir,
|
||||
operator.FileAssociate,
|
||||
operator.FileUnassociate,
|
||||
operator.SelectURIAttribute,
|
||||
operator.EditBlenderCollection,
|
||||
operator.BIM_OT_open_webbrowser,
|
||||
@@ -111,83 +101,58 @@ classes = [
|
||||
operator.BIM_OT_enum_property_search, # /!\ Register AFTER prop.StrProperty
|
||||
prop.ObjProperty,
|
||||
prop.Attribute,
|
||||
prop.BIMAreaProperties,
|
||||
prop.ModuleVisibility,
|
||||
prop.BIMProperties,
|
||||
prop.IfcParameter,
|
||||
prop.PsetQto,
|
||||
prop.GlobalId,
|
||||
prop.BIMObjectProperties,
|
||||
prop.BIMCollectionProperties,
|
||||
prop.BIMMaterialProperties,
|
||||
prop.BIMMeshProperties,
|
||||
ui.BIM_PT_section_plane,
|
||||
ui.BIM_UL_generic,
|
||||
ui.BIM_UL_topics,
|
||||
ui.BIM_ADDON_preferences,
|
||||
# Project overview
|
||||
# Scene panel groups
|
||||
ui.BIM_PT_project_info,
|
||||
ui.BIM_PT_project_setup,
|
||||
ui.BIM_PT_collaboration,
|
||||
ui.BIM_PT_geometry,
|
||||
ui.BIM_PT_tab_grouping_and_filtering,
|
||||
# Tabs panel
|
||||
ui.BIM_PT_tabs,
|
||||
# Object information
|
||||
ui.BIM_PT_tab_object_metadata,
|
||||
ui.BIM_PT_tab_misc,
|
||||
# Geometry and materials
|
||||
ui.BIM_PT_tab_representations,
|
||||
ui.BIM_PT_tab_geometric_relationships,
|
||||
ui.BIM_PT_tab_parametric_geometry,
|
||||
ui.BIM_PT_tab_materials,
|
||||
ui.BIM_PT_tab_styles,
|
||||
# Drawings and documents
|
||||
# Services and systems
|
||||
ui.BIM_PT_tab_services,
|
||||
ui.BIM_PT_tab_services_object,
|
||||
# Structural analysis
|
||||
ui.BIM_PT_tab_structural,
|
||||
# Facility management
|
||||
ui.BIM_PT_tab_handover,
|
||||
ui.BIM_PT_tab_operations,
|
||||
# Quality and coordination
|
||||
ui.BIM_PT_tab_quality_control,
|
||||
ui.BIM_PT_tab_collaboration,
|
||||
ui.BIM_PT_tab_sandbox,
|
||||
# TODO: move this somewhere else and clean it up
|
||||
ui.BIM_PT_section_plane,
|
||||
ui.BIM_PT_services,
|
||||
ui.BIM_PT_structural,
|
||||
ui.BIM_PT_4D5D,
|
||||
ui.BIM_PT_quality_control,
|
||||
ui.BIM_PT_integrations,
|
||||
# Object panel groups
|
||||
ui.BIM_PT_object_metadata,
|
||||
ui.BIM_PT_geometry_object,
|
||||
ui.BIM_PT_services_object,
|
||||
ui.BIM_PT_utilities_object,
|
||||
ui.BIM_PT_misc_object,
|
||||
]
|
||||
|
||||
for mod in modules.values():
|
||||
classes.extend(mod.classes)
|
||||
|
||||
addon_keymaps = []
|
||||
icons = None
|
||||
is_registering = False
|
||||
last_commit_hash = "8888888"
|
||||
|
||||
|
||||
def on_register(scene):
|
||||
global is_registering
|
||||
|
||||
if is_registering:
|
||||
return
|
||||
is_registering = True
|
||||
handler.load_post(scene)
|
||||
handler.setDefaultProperties(scene)
|
||||
if not bpy.app.background:
|
||||
bpy.app.handlers.depsgraph_update_post.remove(on_register)
|
||||
is_registering = False
|
||||
|
||||
|
||||
def register():
|
||||
for cls in classes:
|
||||
bpy.utils.register_class(cls)
|
||||
bpy.app.handlers.depsgraph_update_post.append(on_register)
|
||||
bpy.app.handlers.undo_pre.append(handler.undo_pre)
|
||||
bpy.app.handlers.undo_post.append(handler.undo_post)
|
||||
bpy.app.handlers.redo_pre.append(handler.redo_pre)
|
||||
bpy.app.handlers.redo_post.append(handler.redo_post)
|
||||
bpy.app.handlers.load_post.append(handler.load_post)
|
||||
bpy.app.handlers.load_post.append(handler.setDefaultProperties)
|
||||
bpy.app.handlers.load_post.append(handler.loadIfcStore)
|
||||
bpy.app.handlers.save_pre.append(handler.ensureIfcExported)
|
||||
bpy.types.Scene.BIMProperties = bpy.props.PointerProperty(type=prop.BIMProperties)
|
||||
bpy.types.Screen.BIMAreaProperties = bpy.props.CollectionProperty(type=prop.BIMAreaProperties)
|
||||
bpy.types.Collection.BIMCollectionProperties = bpy.props.PointerProperty(type=prop.BIMCollectionProperties)
|
||||
bpy.types.Object.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
|
||||
bpy.types.Material.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
|
||||
bpy.types.Material.BIMMaterialProperties = bpy.props.PointerProperty(type=prop.BIMMaterialProperties)
|
||||
@@ -195,55 +160,21 @@ def register():
|
||||
bpy.types.Curve.BIMMeshProperties = bpy.props.PointerProperty(type=prop.BIMMeshProperties)
|
||||
bpy.types.Camera.BIMMeshProperties = bpy.props.PointerProperty(type=prop.BIMMeshProperties)
|
||||
bpy.types.PointLight.BIMMeshProperties = bpy.props.PointerProperty(type=prop.BIMMeshProperties)
|
||||
bpy.types.SCENE_PT_unit.append(ui.ifc_units)
|
||||
if hasattr(bpy.types, "UI_MT_button_context_menu"):
|
||||
bpy.types.UI_MT_button_context_menu.append(ui.draw_custom_context_menu)
|
||||
bpy.types.STATUSBAR_HT_header.append(ui.draw_statusbar)
|
||||
|
||||
for mod in modules.values():
|
||||
mod.register()
|
||||
|
||||
wm = bpy.context.window_manager
|
||||
if wm.keyconfigs.addon:
|
||||
km = wm.keyconfigs.addon.keymaps.new(name='Window', space_type='EMPTY')
|
||||
kmi = km.keymap_items.new('bim.switch_tab', 'TAB', 'PRESS', ctrl=True)
|
||||
addon_keymaps.append((km, kmi))
|
||||
|
||||
global icons
|
||||
|
||||
icons_dir = os.path.join(cwd, "data", "icons")
|
||||
icon_preview = bpy.utils.previews.new()
|
||||
for filename in os.listdir(icons_dir):
|
||||
if filename.endswith(".png"):
|
||||
icon_name = os.path.splitext(filename)[0]
|
||||
icon_path = os.path.join(icons_dir, filename)
|
||||
icon_preview.load(icon_name, icon_path, "IMAGE")
|
||||
|
||||
icons = icon_preview
|
||||
|
||||
global last_commit_hash
|
||||
try:
|
||||
import git
|
||||
path = Path(__file__).resolve().parent
|
||||
repo = git.Repo(str(path), search_parent_directories=True)
|
||||
last_commit_hash = repo.head.object.hexsha
|
||||
except:
|
||||
pass
|
||||
|
||||
def unregister():
|
||||
global icons
|
||||
|
||||
bpy.utils.previews.remove(icons)
|
||||
|
||||
for cls in reversed(classes):
|
||||
if getattr(cls, "is_registered", None) is None:
|
||||
bpy.utils.unregister_class(cls)
|
||||
elif cls.is_registered:
|
||||
bpy.utils.unregister_class(cls)
|
||||
|
||||
bpy.app.handlers.load_post.remove(handler.load_post)
|
||||
bpy.utils.unregister_class(cls)
|
||||
bpy.app.handlers.load_post.remove(handler.setDefaultProperties)
|
||||
bpy.app.handlers.load_post.remove(handler.loadIfcStore)
|
||||
bpy.app.handlers.save_pre.remove(handler.ensureIfcExported)
|
||||
del bpy.types.Scene.BIMProperties
|
||||
del bpy.types.Collection.BIMCollectionProperties
|
||||
del bpy.types.Object.BIMObjectProperties
|
||||
del bpy.types.Material.BIMObjectProperties
|
||||
del bpy.types.Material.BIMMaterialProperties
|
||||
@@ -251,30 +182,9 @@ def unregister():
|
||||
del bpy.types.Curve.BIMMeshProperties
|
||||
del bpy.types.Camera.BIMMeshProperties
|
||||
del bpy.types.PointLight.BIMMeshProperties
|
||||
bpy.types.SCENE_PT_unit.remove(ui.ifc_units)
|
||||
if hasattr(bpy.types, "UI_MT_button_context_menu"):
|
||||
bpy.types.UI_MT_button_context_menu.remove(ui.draw_custom_context_menu)
|
||||
bpy.types.STATUSBAR_HT_header.remove(ui.draw_statusbar)
|
||||
|
||||
for mod in reversed(list(modules.values())):
|
||||
mod.unregister()
|
||||
|
||||
wm = bpy.context.window_manager
|
||||
kc = wm.keyconfigs.addon
|
||||
if kc:
|
||||
for km, kmi in addon_keymaps:
|
||||
km.keymap_items.remove(kmi)
|
||||
addon_keymaps.clear()
|
||||
|
||||
for panel in [
|
||||
"SCENE_PT_scene",
|
||||
"SCENE_PT_unit",
|
||||
"SCENE_PT_physics",
|
||||
"SCENE_PT_rigid_body_world",
|
||||
"SCENE_PT_audio",
|
||||
"SCENE_PT_keying_sets",
|
||||
"SCENE_PT_custom_props",
|
||||
]:
|
||||
try:
|
||||
bpy.utils.unregister_class(getattr(handler, f"Override_{panel}"))
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -1,755 +0,0 @@
|
||||
{
|
||||
"Technical": {
|
||||
"render_type": "VIEWPORT",
|
||||
"raster_style": {
|
||||
"bpy.data.worlds[0].color": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"scene.render.bake_bias": 0.0010000000474974513,
|
||||
"scene.render.bake_margin": 16,
|
||||
"scene.render.bake_margin_type": "ADJACENT_FACES",
|
||||
"scene.render.bake_samples": 256,
|
||||
"scene.render.bake_type": "NORMALS",
|
||||
"scene.render.bake_user_scale": 0.0,
|
||||
"scene.render.border_max_x": 1.0,
|
||||
"scene.render.border_max_y": 1.0,
|
||||
"scene.render.border_min_x": 0.0,
|
||||
"scene.render.border_min_y": 0.0,
|
||||
"scene.render.dither_intensity": 1.0,
|
||||
"scene.render.engine": "BLENDER_WORKBENCH",
|
||||
"scene.render.film_transparent": false,
|
||||
"scene.render.filter_size": 1.5,
|
||||
"scene.render.fps": 24,
|
||||
"scene.render.fps_base": 1.0,
|
||||
"scene.render.frame_map_new": 100,
|
||||
"scene.render.frame_map_old": 100,
|
||||
"scene.render.hair_subdiv": 0,
|
||||
"scene.render.hair_type": "STRAND",
|
||||
"scene.render.line_thickness": 1.0,
|
||||
"scene.render.line_thickness_mode": "ABSOLUTE",
|
||||
"scene.render.metadata_input": "SCENE",
|
||||
"scene.render.motion_blur_shutter": 0.5,
|
||||
"scene.render.pixel_aspect_x": 1.0,
|
||||
"scene.render.pixel_aspect_y": 1.0,
|
||||
"scene.render.preview_pixel_size": "AUTO",
|
||||
"scene.render.resolution_percentage": 100,
|
||||
"scene.render.resolution_x": 1000,
|
||||
"scene.render.resolution_y": 1000,
|
||||
"scene.render.sequencer_gl_preview": "SOLID",
|
||||
"scene.render.simplify_child_particles": 1.0,
|
||||
"scene.render.simplify_child_particles_render": 1.0,
|
||||
"scene.render.simplify_gpencil": false,
|
||||
"scene.render.simplify_gpencil_antialiasing": true,
|
||||
"scene.render.simplify_gpencil_modifier": true,
|
||||
"scene.render.simplify_gpencil_onplay": false,
|
||||
"scene.render.simplify_gpencil_shader_fx": true,
|
||||
"scene.render.simplify_gpencil_tint": true,
|
||||
"scene.render.simplify_gpencil_view_fill": true,
|
||||
"scene.render.simplify_shadows": 1.0,
|
||||
"scene.render.simplify_shadows_render": 1.0,
|
||||
"scene.render.simplify_subdivision": 6,
|
||||
"scene.render.simplify_subdivision_render": 6,
|
||||
"scene.render.simplify_volumes": 1.0,
|
||||
"scene.render.stamp_font_size": 12,
|
||||
"scene.render.stamp_note_text": "",
|
||||
"scene.render.threads": 20,
|
||||
"scene.render.threads_mode": "AUTO",
|
||||
"scene.render.use_bake_clear": true,
|
||||
"scene.render.use_bake_lores_mesh": false,
|
||||
"scene.render.use_bake_multires": false,
|
||||
"scene.render.use_bake_selected_to_active": false,
|
||||
"scene.render.use_bake_user_scale": false,
|
||||
"scene.render.use_border": false,
|
||||
"scene.render.use_compositing": true,
|
||||
"scene.render.use_crop_to_border": false,
|
||||
"scene.render.use_file_extension": true,
|
||||
"scene.render.use_freestyle": false,
|
||||
"scene.render.use_high_quality_normals": false,
|
||||
"scene.render.use_lock_interface": false,
|
||||
"scene.render.use_motion_blur": false,
|
||||
"scene.render.use_multiview": false,
|
||||
"scene.render.use_overwrite": true,
|
||||
"scene.render.use_persistent_data": false,
|
||||
"scene.render.use_placeholder": false,
|
||||
"scene.render.use_render_cache": false,
|
||||
"scene.render.use_sequencer": true,
|
||||
"scene.render.use_sequencer_override_scene_strip": false,
|
||||
"scene.render.use_simplify": false,
|
||||
"scene.render.use_single_layer": false,
|
||||
"scene.render.use_stamp": false,
|
||||
"scene.render.use_stamp_camera": true,
|
||||
"scene.render.use_stamp_date": true,
|
||||
"scene.render.use_stamp_filename": true,
|
||||
"scene.render.use_stamp_frame": true,
|
||||
"scene.render.use_stamp_frame_range": false,
|
||||
"scene.render.use_stamp_hostname": false,
|
||||
"scene.render.use_stamp_labels": true,
|
||||
"scene.render.use_stamp_lens": false,
|
||||
"scene.render.use_stamp_marker": false,
|
||||
"scene.render.use_stamp_memory": false,
|
||||
"scene.render.use_stamp_note": false,
|
||||
"scene.render.use_stamp_render_time": true,
|
||||
"scene.render.use_stamp_scene": true,
|
||||
"scene.render.use_stamp_sequencer_strip": false,
|
||||
"scene.render.use_stamp_time": true,
|
||||
"scene.render.views_format": "STEREO_3D",
|
||||
"scene.view_settings.exposure": 0.0,
|
||||
"scene.view_settings.gamma": 1.0,
|
||||
"scene.view_settings.look": "None",
|
||||
"scene.view_settings.use_curve_mapping": false,
|
||||
"scene.view_settings.view_transform": "Standard",
|
||||
"scene.display.shading.aov_name": "",
|
||||
"scene.display.shading.background_color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"scene.display.shading.background_type": "THEME",
|
||||
"scene.display.shading.cavity_ridge_factor": 1.0,
|
||||
"scene.display.shading.cavity_type": "BOTH",
|
||||
"scene.display.shading.cavity_valley_factor": 1.0,
|
||||
"scene.display.shading.color_type": "SINGLE",
|
||||
"scene.display.shading.curvature_ridge_factor": 1.0,
|
||||
"scene.display.shading.curvature_valley_factor": 1.0,
|
||||
"scene.display.shading.light": "FLAT",
|
||||
"scene.display.shading.object_outline_color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"scene.display.shading.render_pass": "COMBINED",
|
||||
"scene.display.shading.shadow_intensity": 0.5,
|
||||
"scene.display.shading.show_backface_culling": false,
|
||||
"scene.display.shading.show_cavity": false,
|
||||
"scene.display.shading.show_object_outline": true,
|
||||
"scene.display.shading.show_shadows": false,
|
||||
"scene.display.shading.show_specular_highlight": true,
|
||||
"scene.display.shading.show_xray": false,
|
||||
"scene.display.shading.show_xray_wireframe": false,
|
||||
"scene.display.shading.single_color": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"scene.display.shading.studio_light": "Default",
|
||||
"scene.display.shading.studiolight_background_alpha": 0.0,
|
||||
"scene.display.shading.studiolight_background_blur": 0.0,
|
||||
"scene.display.shading.studiolight_intensity": 0.0,
|
||||
"scene.display.shading.studiolight_rotate_z": 0.0,
|
||||
"scene.display.shading.type": "SOLID",
|
||||
"scene.display.shading.use_compositor": "DISABLED",
|
||||
"scene.display.shading.use_dof": false,
|
||||
"scene.display.shading.use_scene_lights": false,
|
||||
"scene.display.shading.use_scene_lights_render": false,
|
||||
"scene.display.shading.use_scene_world": false,
|
||||
"scene.display.shading.use_scene_world_render": false,
|
||||
"scene.display.shading.use_studiolight_view_rotation": true,
|
||||
"scene.display.shading.use_world_space_lighting": false,
|
||||
"scene.display.shading.wireframe_color_type": "MATERIAL",
|
||||
"scene.display.shading.xray_alpha": 0.5,
|
||||
"scene.display.shading.xray_alpha_wireframe": 0.0,
|
||||
"scene.display.light_direction": [
|
||||
0.5,
|
||||
0.5,
|
||||
0.5
|
||||
],
|
||||
"scene.display.matcap_ssao_attenuation": 1.0,
|
||||
"scene.display.matcap_ssao_distance": 0.20000000298023224,
|
||||
"scene.display.matcap_ssao_samples": 16,
|
||||
"scene.display.render_aa": "8",
|
||||
"scene.display.shadow_focus": 0.0,
|
||||
"scene.display.shadow_shift": 0.10000000149011612,
|
||||
"scene.display.viewport_aa": "FXAA",
|
||||
"space.overlay.backwire_opacity": 0.5,
|
||||
"space.overlay.bone_wire_alpha": 1.0,
|
||||
"space.overlay.display_handle": "SELECTED",
|
||||
"space.overlay.fade_inactive_alpha": 0.4000000059604645,
|
||||
"space.overlay.gpencil_fade_layer": 0.5,
|
||||
"space.overlay.gpencil_fade_objects": 0.5,
|
||||
"space.overlay.gpencil_grid_opacity": 0.5,
|
||||
"space.overlay.gpencil_vertex_paint_opacity": 1.0,
|
||||
"space.overlay.grid_lines": 16,
|
||||
"space.overlay.grid_scale": 1.0,
|
||||
"space.overlay.grid_subdivisions": 10,
|
||||
"space.overlay.normals_constant_screen_size": 7.0,
|
||||
"space.overlay.normals_length": 0.10000000149011612,
|
||||
"space.overlay.sculpt_curves_cage_opacity": 0.5,
|
||||
"space.overlay.sculpt_mode_face_sets_opacity": 1.0,
|
||||
"space.overlay.sculpt_mode_mask_opacity": 0.75,
|
||||
"space.overlay.show_annotation": true,
|
||||
"space.overlay.show_axis_x": false,
|
||||
"space.overlay.show_axis_y": false,
|
||||
"space.overlay.show_axis_z": false,
|
||||
"space.overlay.show_bones": true,
|
||||
"space.overlay.show_cursor": true,
|
||||
"space.overlay.show_curve_normals": false,
|
||||
"space.overlay.show_edge_bevel_weight": true,
|
||||
"space.overlay.show_edge_crease": true,
|
||||
"space.overlay.show_edge_seams": true,
|
||||
"space.overlay.show_edge_sharp": true,
|
||||
"space.overlay.show_edges": false,
|
||||
"space.overlay.show_extra_edge_angle": false,
|
||||
"space.overlay.show_extra_edge_length": false,
|
||||
"space.overlay.show_extra_face_angle": false,
|
||||
"space.overlay.show_extra_face_area": false,
|
||||
"space.overlay.show_extra_indices": false,
|
||||
"space.overlay.show_extras": true,
|
||||
"space.overlay.show_face_center": false,
|
||||
"space.overlay.show_face_normals": false,
|
||||
"space.overlay.show_face_orientation": false,
|
||||
"space.overlay.show_faces": true,
|
||||
"space.overlay.show_fade_inactive": false,
|
||||
"space.overlay.show_floor": false,
|
||||
"space.overlay.show_freestyle_edge_marks": true,
|
||||
"space.overlay.show_freestyle_face_marks": true,
|
||||
"space.overlay.show_look_dev": false,
|
||||
"space.overlay.show_motion_paths": true,
|
||||
"space.overlay.show_object_origins": false,
|
||||
"space.overlay.show_object_origins_all": false,
|
||||
"space.overlay.show_occlude_wire": false,
|
||||
"space.overlay.show_onion_skins": false,
|
||||
"space.overlay.show_ortho_grid": true,
|
||||
"space.overlay.show_outline_selected": true,
|
||||
"space.overlay.show_overlays": true,
|
||||
"space.overlay.show_paint_wire": false,
|
||||
"space.overlay.show_relationship_lines": false,
|
||||
"space.overlay.show_sculpt_curves_cage": true,
|
||||
"space.overlay.show_sculpt_face_sets": true,
|
||||
"space.overlay.show_sculpt_mask": true,
|
||||
"space.overlay.show_split_normals": false,
|
||||
"space.overlay.show_stats": false,
|
||||
"space.overlay.show_statvis": false,
|
||||
"space.overlay.show_text": true,
|
||||
"space.overlay.show_vertex_normals": false,
|
||||
"space.overlay.show_viewer_attribute": true,
|
||||
"space.overlay.show_weight": false,
|
||||
"space.overlay.show_wireframes": true,
|
||||
"space.overlay.show_wpaint_contours": false,
|
||||
"space.overlay.show_xray_bone": false,
|
||||
"space.overlay.texture_paint_mode_opacity": 1.0,
|
||||
"space.overlay.use_debug_freeze_view_culling": false,
|
||||
"space.overlay.use_gpencil_canvas_xray": false,
|
||||
"space.overlay.use_gpencil_edit_lines": true,
|
||||
"space.overlay.use_gpencil_fade_gp_objects": false,
|
||||
"space.overlay.use_gpencil_fade_layers": false,
|
||||
"space.overlay.use_gpencil_fade_objects": false,
|
||||
"space.overlay.use_gpencil_grid": false,
|
||||
"space.overlay.use_gpencil_multiedit_line_only": false,
|
||||
"space.overlay.use_gpencil_onion_skin": false,
|
||||
"space.overlay.use_gpencil_show_directions": false,
|
||||
"space.overlay.use_gpencil_show_material_name": false,
|
||||
"space.overlay.use_normals_constant_screen_size": false,
|
||||
"space.overlay.vertex_opacity": 1.0,
|
||||
"space.overlay.vertex_paint_mode_opacity": 1.0,
|
||||
"space.overlay.viewer_attribute_opacity": 1.0,
|
||||
"space.overlay.weight_paint_mode_opacity": 1.0,
|
||||
"space.overlay.wireframe_opacity": 1.0,
|
||||
"space.overlay.wireframe_threshold": 0.0,
|
||||
"space.overlay.xray_alpha_bone": 0.0
|
||||
}
|
||||
},
|
||||
"Shaded": {
|
||||
"render_type": "VIEWPORT",
|
||||
"raster_style": {
|
||||
"bpy.data.worlds[0].color": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"scene.render.bake_bias": 0.0010000000474974513,
|
||||
"scene.render.bake_margin": 16,
|
||||
"scene.render.bake_margin_type": "ADJACENT_FACES",
|
||||
"scene.render.bake_samples": 256,
|
||||
"scene.render.bake_type": "NORMALS",
|
||||
"scene.render.bake_user_scale": 0.0,
|
||||
"scene.render.border_max_x": 1.0,
|
||||
"scene.render.border_max_y": 1.0,
|
||||
"scene.render.border_min_x": 0.0,
|
||||
"scene.render.border_min_y": 0.0,
|
||||
"scene.render.dither_intensity": 1.0,
|
||||
"scene.render.engine": "BLENDER_WORKBENCH",
|
||||
"scene.render.film_transparent": false,
|
||||
"scene.render.filter_size": 1.5,
|
||||
"scene.render.fps": 24,
|
||||
"scene.render.fps_base": 1.0,
|
||||
"scene.render.frame_map_new": 100,
|
||||
"scene.render.frame_map_old": 100,
|
||||
"scene.render.hair_subdiv": 0,
|
||||
"scene.render.hair_type": "STRAND",
|
||||
"scene.render.line_thickness": 1.0,
|
||||
"scene.render.line_thickness_mode": "ABSOLUTE",
|
||||
"scene.render.metadata_input": "SCENE",
|
||||
"scene.render.motion_blur_shutter": 0.5,
|
||||
"scene.render.pixel_aspect_x": 1.0,
|
||||
"scene.render.pixel_aspect_y": 1.0,
|
||||
"scene.render.preview_pixel_size": "AUTO",
|
||||
"scene.render.resolution_percentage": 100,
|
||||
"scene.render.resolution_x": 1000,
|
||||
"scene.render.resolution_y": 1000,
|
||||
"scene.render.sequencer_gl_preview": "SOLID",
|
||||
"scene.render.simplify_child_particles": 1.0,
|
||||
"scene.render.simplify_child_particles_render": 1.0,
|
||||
"scene.render.simplify_gpencil": false,
|
||||
"scene.render.simplify_gpencil_antialiasing": true,
|
||||
"scene.render.simplify_gpencil_modifier": true,
|
||||
"scene.render.simplify_gpencil_onplay": false,
|
||||
"scene.render.simplify_gpencil_shader_fx": true,
|
||||
"scene.render.simplify_gpencil_tint": true,
|
||||
"scene.render.simplify_gpencil_view_fill": true,
|
||||
"scene.render.simplify_shadows": 1.0,
|
||||
"scene.render.simplify_shadows_render": 1.0,
|
||||
"scene.render.simplify_subdivision": 6,
|
||||
"scene.render.simplify_subdivision_render": 6,
|
||||
"scene.render.simplify_volumes": 1.0,
|
||||
"scene.render.stamp_font_size": 12,
|
||||
"scene.render.stamp_note_text": "",
|
||||
"scene.render.threads": 20,
|
||||
"scene.render.threads_mode": "AUTO",
|
||||
"scene.render.use_bake_clear": true,
|
||||
"scene.render.use_bake_lores_mesh": false,
|
||||
"scene.render.use_bake_multires": false,
|
||||
"scene.render.use_bake_selected_to_active": false,
|
||||
"scene.render.use_bake_user_scale": false,
|
||||
"scene.render.use_border": false,
|
||||
"scene.render.use_compositing": true,
|
||||
"scene.render.use_crop_to_border": false,
|
||||
"scene.render.use_file_extension": true,
|
||||
"scene.render.use_freestyle": false,
|
||||
"scene.render.use_high_quality_normals": false,
|
||||
"scene.render.use_lock_interface": false,
|
||||
"scene.render.use_motion_blur": false,
|
||||
"scene.render.use_multiview": false,
|
||||
"scene.render.use_overwrite": true,
|
||||
"scene.render.use_persistent_data": false,
|
||||
"scene.render.use_placeholder": false,
|
||||
"scene.render.use_render_cache": false,
|
||||
"scene.render.use_sequencer": true,
|
||||
"scene.render.use_sequencer_override_scene_strip": false,
|
||||
"scene.render.use_simplify": false,
|
||||
"scene.render.use_single_layer": false,
|
||||
"scene.render.use_stamp": false,
|
||||
"scene.render.use_stamp_camera": true,
|
||||
"scene.render.use_stamp_date": true,
|
||||
"scene.render.use_stamp_filename": true,
|
||||
"scene.render.use_stamp_frame": true,
|
||||
"scene.render.use_stamp_frame_range": false,
|
||||
"scene.render.use_stamp_hostname": false,
|
||||
"scene.render.use_stamp_labels": true,
|
||||
"scene.render.use_stamp_lens": false,
|
||||
"scene.render.use_stamp_marker": false,
|
||||
"scene.render.use_stamp_memory": false,
|
||||
"scene.render.use_stamp_note": false,
|
||||
"scene.render.use_stamp_render_time": true,
|
||||
"scene.render.use_stamp_scene": true,
|
||||
"scene.render.use_stamp_sequencer_strip": false,
|
||||
"scene.render.use_stamp_time": true,
|
||||
"scene.render.views_format": "STEREO_3D",
|
||||
"scene.view_settings.exposure": 0.0,
|
||||
"scene.view_settings.gamma": 1.0,
|
||||
"scene.view_settings.look": "None",
|
||||
"scene.view_settings.use_curve_mapping": false,
|
||||
"scene.view_settings.view_transform": "Standard",
|
||||
"scene.display.shading.aov_name": "",
|
||||
"scene.display.shading.background_color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"scene.display.shading.background_type": "THEME",
|
||||
"scene.display.shading.cavity_ridge_factor": 1.0,
|
||||
"scene.display.shading.cavity_type": "BOTH",
|
||||
"scene.display.shading.cavity_valley_factor": 1.0,
|
||||
"scene.display.shading.color_type": "MATERIAL",
|
||||
"scene.display.shading.curvature_ridge_factor": 1.0,
|
||||
"scene.display.shading.curvature_valley_factor": 1.0,
|
||||
"scene.display.shading.light": "STUDIO",
|
||||
"scene.display.shading.object_outline_color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"scene.display.shading.render_pass": "COMBINED",
|
||||
"scene.display.shading.shadow_intensity": 0.5,
|
||||
"scene.display.shading.show_backface_culling": false,
|
||||
"scene.display.shading.show_cavity": true,
|
||||
"scene.display.shading.show_object_outline": true,
|
||||
"scene.display.shading.show_shadows": true,
|
||||
"scene.display.shading.show_specular_highlight": true,
|
||||
"scene.display.shading.show_xray": false,
|
||||
"scene.display.shading.show_xray_wireframe": false,
|
||||
"scene.display.shading.single_color": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"scene.display.shading.studio_light": "Default",
|
||||
"scene.display.shading.studiolight_background_alpha": 0.0,
|
||||
"scene.display.shading.studiolight_background_blur": 0.0,
|
||||
"scene.display.shading.studiolight_intensity": 0.0,
|
||||
"scene.display.shading.studiolight_rotate_z": 0.0,
|
||||
"scene.display.shading.type": "RENDERED",
|
||||
"scene.display.shading.use_compositor": "DISABLED",
|
||||
"scene.display.shading.use_dof": false,
|
||||
"scene.display.shading.use_scene_lights": false,
|
||||
"scene.display.shading.use_scene_lights_render": false,
|
||||
"scene.display.shading.use_scene_world": false,
|
||||
"scene.display.shading.use_scene_world_render": false,
|
||||
"scene.display.shading.use_studiolight_view_rotation": true,
|
||||
"scene.display.shading.use_world_space_lighting": false,
|
||||
"scene.display.shading.wireframe_color_type": "MATERIAL",
|
||||
"scene.display.shading.xray_alpha": 0.5,
|
||||
"scene.display.shading.xray_alpha_wireframe": 0.0,
|
||||
"scene.display.light_direction": [
|
||||
0.5,
|
||||
0.5,
|
||||
0.5
|
||||
],
|
||||
"scene.display.matcap_ssao_attenuation": 1.0,
|
||||
"scene.display.matcap_ssao_distance": 0.20000000298023224,
|
||||
"scene.display.matcap_ssao_samples": 16,
|
||||
"scene.display.render_aa": "8",
|
||||
"scene.display.shadow_focus": 0.0,
|
||||
"scene.display.shadow_shift": 0.10000000149011612,
|
||||
"scene.display.viewport_aa": "FXAA",
|
||||
"space.overlay.backwire_opacity": 0.5,
|
||||
"space.overlay.bone_wire_alpha": 1.0,
|
||||
"space.overlay.display_handle": "SELECTED",
|
||||
"space.overlay.fade_inactive_alpha": 0.4000000059604645,
|
||||
"space.overlay.gpencil_fade_layer": 0.5,
|
||||
"space.overlay.gpencil_fade_objects": 0.5,
|
||||
"space.overlay.gpencil_grid_opacity": 0.5,
|
||||
"space.overlay.gpencil_vertex_paint_opacity": 1.0,
|
||||
"space.overlay.grid_lines": 16,
|
||||
"space.overlay.grid_scale": 1.0,
|
||||
"space.overlay.grid_subdivisions": 10,
|
||||
"space.overlay.normals_constant_screen_size": 7.0,
|
||||
"space.overlay.normals_length": 0.10000000149011612,
|
||||
"space.overlay.sculpt_curves_cage_opacity": 0.5,
|
||||
"space.overlay.sculpt_mode_face_sets_opacity": 1.0,
|
||||
"space.overlay.sculpt_mode_mask_opacity": 0.75,
|
||||
"space.overlay.show_annotation": true,
|
||||
"space.overlay.show_axis_x": false,
|
||||
"space.overlay.show_axis_y": false,
|
||||
"space.overlay.show_axis_z": false,
|
||||
"space.overlay.show_bones": true,
|
||||
"space.overlay.show_cursor": true,
|
||||
"space.overlay.show_curve_normals": false,
|
||||
"space.overlay.show_edge_bevel_weight": true,
|
||||
"space.overlay.show_edge_crease": true,
|
||||
"space.overlay.show_edge_seams": true,
|
||||
"space.overlay.show_edge_sharp": true,
|
||||
"space.overlay.show_edges": false,
|
||||
"space.overlay.show_extra_edge_angle": false,
|
||||
"space.overlay.show_extra_edge_length": false,
|
||||
"space.overlay.show_extra_face_angle": false,
|
||||
"space.overlay.show_extra_face_area": false,
|
||||
"space.overlay.show_extra_indices": false,
|
||||
"space.overlay.show_extras": true,
|
||||
"space.overlay.show_face_center": false,
|
||||
"space.overlay.show_face_normals": false,
|
||||
"space.overlay.show_face_orientation": false,
|
||||
"space.overlay.show_faces": true,
|
||||
"space.overlay.show_fade_inactive": false,
|
||||
"space.overlay.show_floor": false,
|
||||
"space.overlay.show_freestyle_edge_marks": true,
|
||||
"space.overlay.show_freestyle_face_marks": true,
|
||||
"space.overlay.show_look_dev": false,
|
||||
"space.overlay.show_motion_paths": true,
|
||||
"space.overlay.show_object_origins": false,
|
||||
"space.overlay.show_object_origins_all": false,
|
||||
"space.overlay.show_occlude_wire": false,
|
||||
"space.overlay.show_onion_skins": false,
|
||||
"space.overlay.show_ortho_grid": true,
|
||||
"space.overlay.show_outline_selected": true,
|
||||
"space.overlay.show_overlays": true,
|
||||
"space.overlay.show_paint_wire": false,
|
||||
"space.overlay.show_relationship_lines": false,
|
||||
"space.overlay.show_sculpt_curves_cage": true,
|
||||
"space.overlay.show_sculpt_face_sets": true,
|
||||
"space.overlay.show_sculpt_mask": true,
|
||||
"space.overlay.show_split_normals": false,
|
||||
"space.overlay.show_stats": false,
|
||||
"space.overlay.show_statvis": false,
|
||||
"space.overlay.show_text": true,
|
||||
"space.overlay.show_vertex_normals": false,
|
||||
"space.overlay.show_viewer_attribute": true,
|
||||
"space.overlay.show_weight": false,
|
||||
"space.overlay.show_wireframes": false,
|
||||
"space.overlay.show_wpaint_contours": false,
|
||||
"space.overlay.show_xray_bone": false,
|
||||
"space.overlay.texture_paint_mode_opacity": 1.0,
|
||||
"space.overlay.use_debug_freeze_view_culling": false,
|
||||
"space.overlay.use_gpencil_canvas_xray": false,
|
||||
"space.overlay.use_gpencil_edit_lines": true,
|
||||
"space.overlay.use_gpencil_fade_gp_objects": false,
|
||||
"space.overlay.use_gpencil_fade_layers": false,
|
||||
"space.overlay.use_gpencil_fade_objects": false,
|
||||
"space.overlay.use_gpencil_grid": false,
|
||||
"space.overlay.use_gpencil_multiedit_line_only": false,
|
||||
"space.overlay.use_gpencil_onion_skin": false,
|
||||
"space.overlay.use_gpencil_show_directions": false,
|
||||
"space.overlay.use_gpencil_show_material_name": false,
|
||||
"space.overlay.use_normals_constant_screen_size": false,
|
||||
"space.overlay.vertex_opacity": 1.0,
|
||||
"space.overlay.vertex_paint_mode_opacity": 1.0,
|
||||
"space.overlay.viewer_attribute_opacity": 1.0,
|
||||
"space.overlay.weight_paint_mode_opacity": 1.0,
|
||||
"space.overlay.wireframe_opacity": 1.0,
|
||||
"space.overlay.wireframe_threshold": 0.0,
|
||||
"space.overlay.xray_alpha_bone": 0.0
|
||||
}
|
||||
},
|
||||
"Blender Default": {
|
||||
"render_type": "VIEWPORT",
|
||||
"raster_style": {
|
||||
"bpy.data.worlds[0].color": [
|
||||
0.05087608844041824,
|
||||
0.05087608844041824,
|
||||
0.05087608844041824
|
||||
],
|
||||
"scene.render.bake_bias": 0.0010000000474974513,
|
||||
"scene.render.bake_margin": 16,
|
||||
"scene.render.bake_margin_type": "ADJACENT_FACES",
|
||||
"scene.render.bake_samples": 256,
|
||||
"scene.render.bake_type": "NORMALS",
|
||||
"scene.render.bake_user_scale": 0.0,
|
||||
"scene.render.border_max_x": 1.0,
|
||||
"scene.render.border_max_y": 1.0,
|
||||
"scene.render.border_min_x": 0.0,
|
||||
"scene.render.border_min_y": 0.0,
|
||||
"scene.render.dither_intensity": 1.0,
|
||||
"scene.render.engine": "BLENDER_EEVEE",
|
||||
"scene.render.film_transparent": false,
|
||||
"scene.render.filter_size": 1.5,
|
||||
"scene.render.fps": 24,
|
||||
"scene.render.fps_base": 1.0,
|
||||
"scene.render.frame_map_new": 100,
|
||||
"scene.render.frame_map_old": 100,
|
||||
"scene.render.hair_subdiv": 0,
|
||||
"scene.render.hair_type": "STRAND",
|
||||
"scene.render.line_thickness": 1.0,
|
||||
"scene.render.line_thickness_mode": "ABSOLUTE",
|
||||
"scene.render.metadata_input": "SCENE",
|
||||
"scene.render.motion_blur_shutter": 0.5,
|
||||
"scene.render.pixel_aspect_x": 1.0,
|
||||
"scene.render.pixel_aspect_y": 1.0,
|
||||
"scene.render.preview_pixel_size": "AUTO",
|
||||
"scene.render.resolution_percentage": 100,
|
||||
"scene.render.resolution_x": 1000,
|
||||
"scene.render.resolution_y": 1000,
|
||||
"scene.render.sequencer_gl_preview": "SOLID",
|
||||
"scene.render.simplify_child_particles": 1.0,
|
||||
"scene.render.simplify_child_particles_render": 1.0,
|
||||
"scene.render.simplify_gpencil": false,
|
||||
"scene.render.simplify_gpencil_antialiasing": true,
|
||||
"scene.render.simplify_gpencil_modifier": true,
|
||||
"scene.render.simplify_gpencil_onplay": false,
|
||||
"scene.render.simplify_gpencil_shader_fx": true,
|
||||
"scene.render.simplify_gpencil_tint": true,
|
||||
"scene.render.simplify_gpencil_view_fill": true,
|
||||
"scene.render.simplify_shadows": 1.0,
|
||||
"scene.render.simplify_shadows_render": 1.0,
|
||||
"scene.render.simplify_subdivision": 6,
|
||||
"scene.render.simplify_subdivision_render": 6,
|
||||
"scene.render.simplify_volumes": 1.0,
|
||||
"scene.render.stamp_font_size": 12,
|
||||
"scene.render.stamp_note_text": "",
|
||||
"scene.render.threads": 20,
|
||||
"scene.render.threads_mode": "AUTO",
|
||||
"scene.render.use_bake_clear": true,
|
||||
"scene.render.use_bake_lores_mesh": false,
|
||||
"scene.render.use_bake_multires": false,
|
||||
"scene.render.use_bake_selected_to_active": false,
|
||||
"scene.render.use_bake_user_scale": false,
|
||||
"scene.render.use_border": false,
|
||||
"scene.render.use_compositing": true,
|
||||
"scene.render.use_crop_to_border": false,
|
||||
"scene.render.use_file_extension": true,
|
||||
"scene.render.use_freestyle": false,
|
||||
"scene.render.use_high_quality_normals": false,
|
||||
"scene.render.use_lock_interface": false,
|
||||
"scene.render.use_motion_blur": false,
|
||||
"scene.render.use_multiview": false,
|
||||
"scene.render.use_overwrite": true,
|
||||
"scene.render.use_persistent_data": false,
|
||||
"scene.render.use_placeholder": false,
|
||||
"scene.render.use_render_cache": false,
|
||||
"scene.render.use_sequencer": true,
|
||||
"scene.render.use_sequencer_override_scene_strip": false,
|
||||
"scene.render.use_simplify": false,
|
||||
"scene.render.use_single_layer": false,
|
||||
"scene.render.use_stamp": false,
|
||||
"scene.render.use_stamp_camera": true,
|
||||
"scene.render.use_stamp_date": true,
|
||||
"scene.render.use_stamp_filename": true,
|
||||
"scene.render.use_stamp_frame": true,
|
||||
"scene.render.use_stamp_frame_range": false,
|
||||
"scene.render.use_stamp_hostname": false,
|
||||
"scene.render.use_stamp_labels": true,
|
||||
"scene.render.use_stamp_lens": false,
|
||||
"scene.render.use_stamp_marker": false,
|
||||
"scene.render.use_stamp_memory": false,
|
||||
"scene.render.use_stamp_note": false,
|
||||
"scene.render.use_stamp_render_time": true,
|
||||
"scene.render.use_stamp_scene": true,
|
||||
"scene.render.use_stamp_sequencer_strip": false,
|
||||
"scene.render.use_stamp_time": true,
|
||||
"scene.render.views_format": "STEREO_3D",
|
||||
"scene.view_settings.exposure": 0.0,
|
||||
"scene.view_settings.gamma": 1.0,
|
||||
"scene.view_settings.look": "None",
|
||||
"scene.view_settings.use_curve_mapping": false,
|
||||
"scene.view_settings.view_transform": "Filmic",
|
||||
"scene.display.shading.aov_name": "",
|
||||
"scene.display.shading.background_color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"scene.display.shading.background_type": "THEME",
|
||||
"scene.display.shading.cavity_ridge_factor": 1.0,
|
||||
"scene.display.shading.cavity_type": "WORLD",
|
||||
"scene.display.shading.cavity_valley_factor": 1.0,
|
||||
"scene.display.shading.color_type": "MATERIAL",
|
||||
"scene.display.shading.curvature_ridge_factor": 0.0,
|
||||
"scene.display.shading.curvature_valley_factor": 0.0,
|
||||
"scene.display.shading.light": "STUDIO",
|
||||
"scene.display.shading.object_outline_color": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"scene.display.shading.render_pass": "COMBINED",
|
||||
"scene.display.shading.shadow_intensity": 0.5,
|
||||
"scene.display.shading.show_backface_culling": false,
|
||||
"scene.display.shading.show_cavity": false,
|
||||
"scene.display.shading.show_object_outline": false,
|
||||
"scene.display.shading.show_shadows": false,
|
||||
"scene.display.shading.show_specular_highlight": true,
|
||||
"scene.display.shading.show_xray": false,
|
||||
"scene.display.shading.show_xray_wireframe": false,
|
||||
"scene.display.shading.single_color": [
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
0.800000011920929
|
||||
],
|
||||
"scene.display.shading.studio_light": "Default",
|
||||
"scene.display.shading.studiolight_background_alpha": 0.0,
|
||||
"scene.display.shading.studiolight_background_blur": 0.0,
|
||||
"scene.display.shading.studiolight_intensity": 0.0,
|
||||
"scene.display.shading.studiolight_rotate_z": 0.0,
|
||||
"scene.display.shading.type": "RENDERED",
|
||||
"scene.display.shading.use_compositor": "DISABLED",
|
||||
"scene.display.shading.use_dof": false,
|
||||
"scene.display.shading.use_scene_lights": false,
|
||||
"scene.display.shading.use_scene_lights_render": false,
|
||||
"scene.display.shading.use_scene_world": false,
|
||||
"scene.display.shading.use_scene_world_render": false,
|
||||
"scene.display.shading.use_studiolight_view_rotation": true,
|
||||
"scene.display.shading.use_world_space_lighting": false,
|
||||
"scene.display.shading.wireframe_color_type": "MATERIAL",
|
||||
"scene.display.shading.xray_alpha": 0.5,
|
||||
"scene.display.shading.xray_alpha_wireframe": 0.0,
|
||||
"scene.display.light_direction": [
|
||||
0.5773502588272095,
|
||||
0.5773502588272095,
|
||||
0.5773502588272095
|
||||
],
|
||||
"scene.display.matcap_ssao_attenuation": 1.0,
|
||||
"scene.display.matcap_ssao_distance": 0.20000000298023224,
|
||||
"scene.display.matcap_ssao_samples": 16,
|
||||
"scene.display.render_aa": "8",
|
||||
"scene.display.shadow_focus": 0.0,
|
||||
"scene.display.shadow_shift": 0.10000000149011612,
|
||||
"scene.display.viewport_aa": "FXAA",
|
||||
"space.overlay.backwire_opacity": 0.5,
|
||||
"space.overlay.bone_wire_alpha": 1.0,
|
||||
"space.overlay.display_handle": "SELECTED",
|
||||
"space.overlay.fade_inactive_alpha": 0.4000000059604645,
|
||||
"space.overlay.gpencil_fade_layer": 0.5,
|
||||
"space.overlay.gpencil_fade_objects": 0.5,
|
||||
"space.overlay.gpencil_grid_opacity": 0.5,
|
||||
"space.overlay.gpencil_vertex_paint_opacity": 1.0,
|
||||
"space.overlay.grid_lines": 16,
|
||||
"space.overlay.grid_scale": 1.0,
|
||||
"space.overlay.grid_subdivisions": 10,
|
||||
"space.overlay.normals_constant_screen_size": 7.0,
|
||||
"space.overlay.normals_length": 0.10000000149011612,
|
||||
"space.overlay.sculpt_curves_cage_opacity": 0.5,
|
||||
"space.overlay.sculpt_mode_face_sets_opacity": 1.0,
|
||||
"space.overlay.sculpt_mode_mask_opacity": 0.75,
|
||||
"space.overlay.show_annotation": true,
|
||||
"space.overlay.show_axis_x": true,
|
||||
"space.overlay.show_axis_y": true,
|
||||
"space.overlay.show_axis_z": false,
|
||||
"space.overlay.show_bones": true,
|
||||
"space.overlay.show_cursor": true,
|
||||
"space.overlay.show_curve_normals": false,
|
||||
"space.overlay.show_edge_bevel_weight": true,
|
||||
"space.overlay.show_edge_crease": true,
|
||||
"space.overlay.show_edge_seams": true,
|
||||
"space.overlay.show_edge_sharp": true,
|
||||
"space.overlay.show_edges": false,
|
||||
"space.overlay.show_extra_edge_angle": false,
|
||||
"space.overlay.show_extra_edge_length": false,
|
||||
"space.overlay.show_extra_face_angle": false,
|
||||
"space.overlay.show_extra_face_area": false,
|
||||
"space.overlay.show_extra_indices": false,
|
||||
"space.overlay.show_extras": true,
|
||||
"space.overlay.show_face_center": false,
|
||||
"space.overlay.show_face_normals": false,
|
||||
"space.overlay.show_face_orientation": false,
|
||||
"space.overlay.show_faces": true,
|
||||
"space.overlay.show_fade_inactive": false,
|
||||
"space.overlay.show_floor": true,
|
||||
"space.overlay.show_freestyle_edge_marks": true,
|
||||
"space.overlay.show_freestyle_face_marks": true,
|
||||
"space.overlay.show_look_dev": false,
|
||||
"space.overlay.show_motion_paths": true,
|
||||
"space.overlay.show_object_origins": true,
|
||||
"space.overlay.show_object_origins_all": false,
|
||||
"space.overlay.show_occlude_wire": false,
|
||||
"space.overlay.show_onion_skins": false,
|
||||
"space.overlay.show_ortho_grid": true,
|
||||
"space.overlay.show_outline_selected": true,
|
||||
"space.overlay.show_overlays": true,
|
||||
"space.overlay.show_paint_wire": false,
|
||||
"space.overlay.show_relationship_lines": true,
|
||||
"space.overlay.show_sculpt_curves_cage": true,
|
||||
"space.overlay.show_sculpt_face_sets": true,
|
||||
"space.overlay.show_sculpt_mask": true,
|
||||
"space.overlay.show_split_normals": false,
|
||||
"space.overlay.show_stats": false,
|
||||
"space.overlay.show_statvis": false,
|
||||
"space.overlay.show_text": true,
|
||||
"space.overlay.show_vertex_normals": false,
|
||||
"space.overlay.show_viewer_attribute": true,
|
||||
"space.overlay.show_weight": false,
|
||||
"space.overlay.show_wireframes": false,
|
||||
"space.overlay.show_wpaint_contours": false,
|
||||
"space.overlay.show_xray_bone": false,
|
||||
"space.overlay.texture_paint_mode_opacity": 1.0,
|
||||
"space.overlay.use_debug_freeze_view_culling": false,
|
||||
"space.overlay.use_gpencil_canvas_xray": false,
|
||||
"space.overlay.use_gpencil_edit_lines": true,
|
||||
"space.overlay.use_gpencil_fade_gp_objects": false,
|
||||
"space.overlay.use_gpencil_fade_layers": false,
|
||||
"space.overlay.use_gpencil_fade_objects": false,
|
||||
"space.overlay.use_gpencil_grid": false,
|
||||
"space.overlay.use_gpencil_multiedit_line_only": false,
|
||||
"space.overlay.use_gpencil_onion_skin": false,
|
||||
"space.overlay.use_gpencil_show_directions": false,
|
||||
"space.overlay.use_gpencil_show_material_name": false,
|
||||
"space.overlay.use_normals_constant_screen_size": false,
|
||||
"space.overlay.vertex_opacity": 1.0,
|
||||
"space.overlay.vertex_paint_mode_opacity": 1.0,
|
||||
"space.overlay.viewer_attribute_opacity": 1.0,
|
||||
"space.overlay.weight_paint_mode_opacity": 1.0,
|
||||
"space.overlay.wireframe_opacity": 1.0,
|
||||
"space.overlay.wireframe_threshold": 1.0,
|
||||
"space.overlay.xray_alpha_bone": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<svg baseProfile="full" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="rectangle-tag">
|
||||
<rect x="-6" y="-2.5" width="12" height="5" fill="white" stroke="black" style="stroke-width: 0.25;" />
|
||||
</g>
|
||||
<g id="triangle-tag">
|
||||
<path style="fill: white; stroke: black; stroke-width: 0.25;" d="M 3.1409425e-7,-7.1069207 5.7650623,2.8784603 l -11.5301246,-6e-7 z" />
|
||||
</g>
|
||||
<g id="hexagon-tag">
|
||||
<path style="fill: white; stroke: black; stroke-width: 0.25;" d="m 0.0161133,-6.0583333 5.2339915,3.8366023 -2.031433,6.1633977 c 0,0 -6.4894866,-0.027414 -6.4894866,-0.027414 l -1.97929,-6.1803395 5.2662181,-3.7922467" />
|
||||
</g>
|
||||
<g id="capsule-tag">
|
||||
<rect x="-6" y="-2.5" width="12" height="5" rx="2.5" ry="2.5" fill="white" stroke="black" style="stroke-width: 0.25;" />
|
||||
</g>
|
||||
<g id="circle-tag">
|
||||
<circle r="5" fill="white" stroke="black" style="stroke-width: 0.25;" />
|
||||
</g>
|
||||
<g id="door-tag">
|
||||
<circle r="5" fill="white" stroke="black" style="stroke-width: 0.25;" />
|
||||
<text y="-1.75" class="regular" text-anchor="middle" dominant-baseline="middle" data-type="text-template"></text>
|
||||
<line x1="-5" x2="5" style="stroke: black; stroke-width: 0.25;" />
|
||||
<text y="2.5" class="regular" text-anchor="middle" dominant-baseline="middle" data-type="text-template"></text>
|
||||
</g>
|
||||
<g id="window-tag">
|
||||
<path style="fill: white; stroke: black; stroke-width: 0.25;" d="m 0.0161133,-6.0583333 5.2339915,3.8366023 -2.031433,6.1633977 c 0,0 -6.4894866,-0.027414 -6.4894866,-0.027414 l -1.97929,-6.1803395 5.2662181,-3.7922467" />
|
||||
</g>
|
||||
<g id="space-tag">
|
||||
<text y="-5" class="large" text-anchor="middle" dominant-baseline="middle" data-type="text-template"></text>
|
||||
<rect x="-6" y="-2.5" width="12" height="5" fill="white" stroke="black" style="stroke-width: 0.25;" />
|
||||
<text class="regular" text-anchor="middle" dominant-baseline="middle" data-type="text-template"></text>
|
||||
<text y="5" class="regular" text-anchor="middle" dominant-baseline="middle" data-type="text-template"></text>
|
||||
</g>
|
||||
<g id="elevation-arrow">
|
||||
<path style="fill: black;" d="M -7.07106 0 0 -7.07106 7.07106 0" />
|
||||
</g>
|
||||
<g id="elevation-tag">
|
||||
<circle r="5" fill="white" stroke="black" style="stroke-width: 0.25;" />
|
||||
<line x1="-5" y1="0" x2="5" y2="0" style="stroke: black; stroke-width: 0.25;" />
|
||||
</g>
|
||||
<g id="section-arrow">
|
||||
<path style="fill: black;" d="M -7.07106 0 0 -7.07106 7.07106 0" />
|
||||
</g>
|
||||
<g id="section-tag">
|
||||
<circle r="5" fill="white" stroke="black" style="stroke-width: 0.25;" />
|
||||
<line x1="-5" y1="0" x2="5" y2="0" style="stroke: black; stroke-width: 0.25;" />
|
||||
</g>
|
||||
<g id="SurveyArea">
|
||||
<circle r="1" fill="black" stroke="black" style="stroke-width: 0.25;" />
|
||||
</g>
|
||||
<g id="SurveyArea-CONTROLPOINT">
|
||||
<path style="fill: white; stroke: black; stroke-width: 0.25;" d="M 2.286165,1.4798666 H -1.0000316e-7 -2.2861651 L -1.1430826,-0.5000101 -1.0000316e-7,-2.479888 1.1430827,-0.5000101 Z" />
|
||||
<circle r="0.5" fill="black" stroke="black" style="stroke-width: 0.25;" />
|
||||
</g>
|
||||
<g id="SurveyArea-TRAVERSEPOINT">
|
||||
<path style="fill: white; stroke: black; stroke-width: 0.5;" d="M -2,-2 2,2 M -2,2 2,-2" />
|
||||
</g>
|
||||
<g id="SurveyArea-SPOTELEVATION">
|
||||
<path style="fill: white; stroke: black; stroke-width: 0.5;" d="M 0,-2 0,2 M -2,0 2,0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.5 KiB |
@@ -1,55 +1,67 @@
|
||||
<link href="jsgantt.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="../../module/sequence/gantt/main.css" rel="stylesheet" type="text/css"/>
|
||||
<script src="jsgantt.js" type="text/javascript"></script>
|
||||
<script type="text/javascript" src="../../module/sequence/gantt/index.js"></script>
|
||||
<script>
|
||||
var json_data = `{{{json_data}}}`;
|
||||
</script>
|
||||
<style>
|
||||
.gtaskcellwkend,
|
||||
.gtaskcellcurrent,
|
||||
.gminorheadingwkend {
|
||||
background-color: #e1e1e1;
|
||||
}
|
||||
|
||||
<div id="options" class="no-print">
|
||||
<h4>Choose a language:
|
||||
<select id="lang" class="sweet_button" onchange="set_language(event)">
|
||||
<option value='cn'>Chinese (cn)</option>
|
||||
<option value='cs'>Czech (cs)</option>
|
||||
<option value='nl'>Dutch (Standard)</option>
|
||||
<option value='en' selected>English (en)</option>
|
||||
<option value='fr'>French (fr)</option>
|
||||
<option value='de'>German (de)</option>
|
||||
<option value='hu'>Hungarian (hu)</option>
|
||||
<option value='id'>Indonesian (id)</option>
|
||||
<option value='it'>Italian (it)</option>
|
||||
<option value='ja'>Japanese (ja)</option>
|
||||
<option value='pt'>Portuguese (pt)</option>
|
||||
<option value='ru'>Russian (ru)</option>
|
||||
<option value='es'>Spanish (es)</option>
|
||||
<option value='sv'>Swedish (sv)</option>
|
||||
<option value='tr'>Turkish (tr)</option>
|
||||
</select>
|
||||
</h4>
|
||||
.gitemhighlight td {
|
||||
background-color: #ffdaaa;
|
||||
}
|
||||
|
||||
<br>
|
||||
</div>
|
||||
<div class="top-right no-print" id="print_options">
|
||||
<select class="sweet_button" id="print_page_size">
|
||||
<option value="210,297">A4 Portrait</option>
|
||||
<option value="297,210">A4 Landscape</option>
|
||||
<option value="297,420">A3 Portrait</option>
|
||||
<option value="420,297">A3 Landscape</option>
|
||||
<option value="420,594">A2 Portrait</option>
|
||||
<option value="594,420">A2 Landscape</option>
|
||||
<option value="594,841">A1 Portrait</option>
|
||||
<option value="841,594">A1 Landscape</option>
|
||||
<option value="841,1189">A0 Portrait</option>
|
||||
<option value="1189,841">A0 Landscape</option>
|
||||
</select>
|
||||
</div>
|
||||
.gtaskblue {
|
||||
background: #4281A4;
|
||||
}
|
||||
|
||||
<div id="schedule-data" class="no-print"></div>
|
||||
<div id="schedule-header" style=""></div>
|
||||
.gtaskred {
|
||||
background: #C1666B;
|
||||
}
|
||||
|
||||
.gtaskgreen {
|
||||
background: #48A9A6;
|
||||
}
|
||||
|
||||
.gtaskyellow {
|
||||
background: #D4B483;
|
||||
}
|
||||
|
||||
.gmainleft {
|
||||
overflow: visible;
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
<a href="#print" id="print">Print Mode</a>
|
||||
<div style="position:relative" class="gantt" id="GanttChartDIV"></div>
|
||||
|
||||
<script>
|
||||
var data = `{{{data}}}`;
|
||||
setupPage(data);
|
||||
create_gantt_chart(json_data)
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var g = new JSGantt.GanttChart(document.getElementById('GanttChartDIV'), 'day');
|
||||
g.setOptions({
|
||||
vCaptionType: 'Caption', // Set to Show Caption : None,Caption,Resource,Duration,Complete,
|
||||
vQuarterColWidth: 36,
|
||||
vDateTaskDisplayFormat: 'day dd month yyyy', // Shown in tool tip box
|
||||
vDayMajorDateDisplayFormat: 'mon yyyy - Week ww',// Set format to dates in the "Major" header of the "Day" view
|
||||
vWeekMinorDateDisplayFormat: 'dd mon', // Set format to display dates in the "Minor" header of the "Week" view
|
||||
vLang: 'en',
|
||||
vShowTaskInfoLink: 1, // Show link in tool tip (0/1)
|
||||
vShowEndWeekDate: 0, // Show/Hide the date for the last day of the week in header for daily
|
||||
vUseSingleCell: 10000, // Set the threshold cell per table row (Helps performance for large data.
|
||||
vFormatArr: ['Day', 'Week', 'Month', 'Quarter'], // Even with setUseSingleCell using Hour format on such a large chart can cause issues in some browsers,
|
||||
vShowRes: false, // Disable the resource column.
|
||||
vShowComp: false, // Disable the completion column.
|
||||
vShowDur: false, // Disable the duration column, because jsgantt doesn't calculate durations the way we want.
|
||||
vAdditionalHeaders: {ifcduration: {title: 'Duration'}},
|
||||
vUseToolTip: false, // Disable tooltips.
|
||||
vTotalHeight: 900,
|
||||
});
|
||||
document.getElementById('print').addEventListener('click', function() {
|
||||
g.setTotalHeight("");
|
||||
g.Draw();
|
||||
});
|
||||
var json_data = `
|
||||
{{{json_data}}}
|
||||
`;
|
||||
JSGantt.parseJSONString(json_data, g);
|
||||
g.Draw();
|
||||
</script>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,13 @@
|
||||
ISO-10303-21;
|
||||
HEADER;
|
||||
FILE_DESCRIPTION((),'2;1');
|
||||
FILE_NAME('EPset_Annotation.ifc','2020-01-01T00:00:00',(),(),'EPset_Annotation','EPset_Annotation',$);
|
||||
FILE_SCHEMA(('IFC4'));
|
||||
ENDSEC;
|
||||
DATA;
|
||||
#1=IFCPROPERTYSETTEMPLATE('3VuPUwdCD2Qx3XDDRs0R1N',$,'EPset_Annotation','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation',(#2,#3));
|
||||
#2=IFCSIMPLEPROPERTYTEMPLATE('2P7JN79n96Q9pElZ83LKe4',$,'ZIndex','',.P_SINGLEVALUE.,'IfcInteger',$,$,$,$,$,.READWRITE.);
|
||||
#3=IFCSIMPLEPROPERTYTEMPLATE('1Wpx_r2xj1_9w5JpI0QRJy',$,'Symbol','',.P_ENUMERATEDVALUE.,'IfcLabel',$,#4,$,$,$,.READWRITE.);
|
||||
#4=IFCPROPERTYENUMERATION('Symbol',(IFCLABEL('rectangle-tag'), IFCLABEL('door-tag')),$);
|
||||
ENDSEC;
|
||||
END-ISO-10303-21;
|
||||
@@ -5,27 +5,20 @@ FILE_NAME('EPset_Drawing.ifc','2020-01-01T00:00:00',(),(),'EPset_Drawing','EPset
|
||||
FILE_SCHEMA(('IFC4'));
|
||||
ENDSEC;
|
||||
DATA;
|
||||
#1=IFCPROPERTYSETTEMPLATE('2JhNIvqZrFnAgxfhK0XVQX',$,'EPset_Drawing','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation',(#2,#3,#4,#5,#6,#7,#8,#9,#10,#11,#12,#13,#14,#15,#16,#17,#18,#19,#20,#21));
|
||||
#1=IFCPROPERTYSETTEMPLATE('2JhNIvqZrFnAgxfhK0XVQX',$,'EPset_Drawing','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation',(#2,#3,#4,#5,#6,#7,#8,#9,#10,#11,#12,#13,#14,#15));
|
||||
#2=IFCSIMPLEPROPERTYTEMPLATE('23JavTMk98ZxXhrUEnjAcf',$,'TargetView','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#3=IFCSIMPLEPROPERTYTEMPLATE('1yVWUt5H9DAOuu0OaMMLpe',$,'Scale','The scale of this drawing represented as a numerator and denominator, such as 1/100',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#4=IFCSIMPLEPROPERTYTEMPLATE('3gsuPBtU93b8f0gg1pjkq6',$,'HumanScale','The scale of this drawing in human readable format, such as 1:100',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#4=IFCSIMPLEPROPERTYTEMPLATE('2T$a4OFsv2LeD5JeBKEV4f',$,'IsNTS','Whether or not the scale is intended to be significant',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#3=IFCSIMPLEPROPERTYTEMPLATE('1yVWUt5H9DAOuu0OaMMLpe',$,'Scale','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#4=IFCSIMPLEPROPERTYTEMPLATE('3gsuPBtU93b8f0gg1pjkq6',$,'HumanScale','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#5=IFCSIMPLEPROPERTYTEMPLATE('0AK5C2UpL4$eaac2LszAx$',$,'HasUnderlay','',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#6=IFCSIMPLEPROPERTYTEMPLATE('2j2ZEZR8X5tONm7kli5hM6',$,'HasLinework','',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#7=IFCSIMPLEPROPERTYTEMPLATE('1ttChRysH9UuEX2FeMj5Hu',$,'HasAnnotation','',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#8=IFCSIMPLEPROPERTYTEMPLATE('2NPPxuABv1huDTVh32TFgw',$,'GlobalReferencing','',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#9=IFCSIMPLEPROPERTYTEMPLATE('10hT_1zrzEbRRKMXYAWvtD',$,'Metadata','',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
|
||||
#10=IFCSIMPLEPROPERTYTEMPLATE('3Z0BXPSG5CWgtI33ioV7aj',$,'Include','Selector expression to include ifc elements in the drawing',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
|
||||
#11=IFCSIMPLEPROPERTYTEMPLATE('1RVts_g3PAw98PJA2yL3bO',$,'Exclude','Selector expression to exclude ifc elements in the drawing',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
|
||||
#12=IFCSIMPLEPROPERTYTEMPLATE('0c1$8NpYDEaBiJrj16jHIo',$,'Stylesheet','',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
|
||||
#13=IFCSIMPLEPROPERTYTEMPLATE('3mRF52q81FQB$h4oTh7M45',$,'Markers','',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
|
||||
#14=IFCSIMPLEPROPERTYTEMPLATE('1rhr_0N3LDtuORcEJP0KXM',$,'Symbols','',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
|
||||
#15=IFCSIMPLEPROPERTYTEMPLATE('2sHDBuW7P4TROy$hL2w7ct',$,'Patterns','',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
|
||||
#16=IFCSIMPLEPROPERTYTEMPLATE('1$xfo9EVb26QLqmPll2_RK',$,'MetricPrecision','',.P_SINGLEVALUE.,'IfcReal',$,$,$,$,$,.READWRITE.);
|
||||
#17=IFCSIMPLEPROPERTYTEMPLATE('38uAtrp9nD_901NO42zd$7',$,'ImperialPrecision','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#18=IFCSIMPLEPROPERTYTEMPLATE('1MX0uffTL6TOvtvEJpxFmk',$,'DecimalPlaces','',.P_SINGLEVALUE.,'IfcInteger',$,$,$,$,$,.READWRITE.);
|
||||
#19=IFCSIMPLEPROPERTYTEMPLATE('0joEq0Rd10cxweEh0NeHT6',$,'JoinCriteria','Comma separated selection keys which determine what cut objects are to be joined.',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
|
||||
#20=IFCSIMPLEPROPERTYTEMPLATE('0nYMT3OSj5gArVniCWZRtv',$,'ShadingStyles','',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
|
||||
#21=IFCSIMPLEPROPERTYTEMPLATE('3VWG22eZXBdQwdKlzMeVQH',$,'CurrentShadingStyle','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#10=IFCSIMPLEPROPERTYTEMPLATE('3Z0BXPSG5CWgtI33ioV7aj',$,'Include','',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
|
||||
#11=IFCSIMPLEPROPERTYTEMPLATE('1RVts_g3PAw98PJA2yL3bO',$,'Exclude','',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
|
||||
#12=IFCSIMPLEPROPERTYTEMPLATE('0c1$8NpYDEaBiJrj16jHIo',$,'Stylesheet','',.P_SINGLEVALUE.,'IfcURIReference',$,$,$,$,$,.READWRITE.);
|
||||
#13=IFCSIMPLEPROPERTYTEMPLATE('3mRF52q81FQB$h4oTh7M45',$,'Markers','',.P_SINGLEVALUE.,'IfcURIReference',$,$,$,$,$,.READWRITE.);
|
||||
#14=IFCSIMPLEPROPERTYTEMPLATE('1rhr_0N3LDtuORcEJP0KXM',$,'Symbols','',.P_SINGLEVALUE.,'IfcURIReference',$,$,$,$,$,.READWRITE.);
|
||||
#15=IFCSIMPLEPROPERTYTEMPLATE('2sHDBuW7P4TROy$hL2w7ct',$,'Patterns','',.P_SINGLEVALUE.,'IfcURIReference',$,$,$,$,$,.READWRITE.);
|
||||
ENDSEC;
|
||||
END-ISO-10303-21;
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
ISO-10303-21;
|
||||
HEADER;
|
||||
FILE_DESCRIPTION((),'2;1');
|
||||
FILE_NAME('EQto_BodyGeometryValidation.ifc','2020-01-01T00:00:00',(),(),'EQto_BodyGeometryValidation','EQto_BodyGeometryValidation',$);
|
||||
FILE_SCHEMA(('IFC4'));
|
||||
ENDSEC;
|
||||
DATA;
|
||||
#1=IFCPROPERTYSETTEMPLATE('2KS9su6r517uLXTGKwwDdn',$,'EQto_BodyGeometryValidation','Quantities supplied for validating the correct interpretation of the body shape representation at import. In case of multiple representation items, the quantities are summed for each of the items (irrespective of any overlap). Choosing a suitable tolerance value for comparing the supplied numbers to the numbers calculated from the reconstructed geometry is at the discretion of the importing application.',.QTO_OCCURRENCEDRIVEN.,'IfcProduct',(#2,#3,#4,#5,#6,#7));
|
||||
#2=IFCSIMPLEPROPERTYTEMPLATE('3iCdOOLRjCwQ_HRTB41Xh8',$,'GrossSurfaceArea','Total gross area of the object, normally generated as perimeter * length + 2 * cross section area. It is the sum of OuterSurfaceArea + (2 x CrossSectionArea) and shall only be given, if the OuterSurfaceArea and CrossSectionArea cannot be established separately.\X2\000A000A\X0\Total gross surface area of the element before applying product-level geometric features such as openings and projections.',.Q_AREA.,$,$,$,$,$,$,.READWRITE.);
|
||||
#3=IFCSIMPLEPROPERTYTEMPLATE('0juemEqF5889vg7HwR87Fv',$,'NetSurfaceArea','Net surface area of the object, normally generated as perimeter * length + 2 * cross section area taking into account possible processing features (cut-out''s, etc.) or openings and recesses.\X2\000A000A\X0\Total net surface area of the element after applying product-level geometric features such as openings and projections.',.Q_AREA.,$,$,$,$,$,$,.READWRITE.);
|
||||
#4=IFCSIMPLEPROPERTYTEMPLATE('1LUuLSnMXFDgGLBCvte8aH',$,'GrossVolume','Total gross volume of the object. Openings, recesses, enclosed objects and projections are not taken into account.\X2\000A000A\X0\Total gross volume of the element before applying product-level geometric features such as openings and projections.',.Q_VOLUME.,$,$,$,$,$,$,.READWRITE.);
|
||||
#5=IFCSIMPLEPROPERTYTEMPLATE('0ny7TXUFz8wvnoQ2eU8czF',$,'NetVolume','Total net volume of the object, taking into account possible processing features (cut-out''s, etc.) or openings and recesses.\X2\000A000A\X0\Total net volume of the element before applying product-level geometric features such as openings and projections.',.Q_VOLUME.,$,$,$,$,$,$,.READWRITE.);
|
||||
#6=IFCSIMPLEPROPERTYTEMPLATE('31g8_gdUv8KRkOWzW48KoP',$,'SurfaceGenusBeforeFeatures','The Surface Genus of the evaluated representation items before applying product-level geometric features such as openings and projections.Surface Genus is a topological measure that represents the number of "holes" or "handles" on a surface. For example, a sphere has genus 0, and a torus has genus 1.Computed using the Euler characteristic:$$\\chi=V-E+F$$With the numbers of vertices (V), edges (E) and faces (F)$$\\chi=2\X2\2212\X0\2g\X2\2212\X0\b$$With surface genus (g) and the number of boundaries (b) the latter zero in case of an enclosed volume.',.Q_COUNT.,$,$,$,$,$,$,.READWRITE.);
|
||||
#7=IFCSIMPLEPROPERTYTEMPLATE('3kBBtGUebC09mUggGTKpjj',$,'SurfaceGenusAfterFeatures','The Surface Genus of the evaluated representation items after applying product-level geometric features such as openings and projections.Surface Genus is a topological measure that represents the number of "holes" or "handles" on a surface. For example, a sphere has genus 0, and a torus has genus 1.Computed using the Euler characteristic:$$\\chi=V-E+F$$With the numbers of vertices (V), edges (E) and faces (F)$$\\chi=2\X2\2212\X0\2g\X2\2212\X0\b$$With surface genus (g) and the number of boundaries (b) the latter zero in case of an enclosed volume.',.Q_COUNT.,$,$,$,$,$,$,.READWRITE.);
|
||||
ENDSEC;
|
||||
END-ISO-10303-21;
|
||||
@@ -1,38 +0,0 @@
|
||||
ISO-10303-21;
|
||||
HEADER;
|
||||
FILE_DESCRIPTION((),'2;1');
|
||||
FILE_NAME('Psets_BBIM_Annotation.ifc','2020-01-01T00:00:00',(),(),'Psets_BBIM_Annotation','Psets_BBIM_Annotation',$);
|
||||
FILE_SCHEMA(('IFC4'));
|
||||
ENDSEC;
|
||||
DATA;
|
||||
#1=IFCPROPERTYSETTEMPLATE('3VuPUwdCD2Qx3XDDRs0R1N',$,'EPset_Annotation','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation,IfcTypeProduct',(#2,#3,#4));
|
||||
#2=IFCSIMPLEPROPERTYTEMPLATE('2P7JN79n96Q9pElZ83LKe4',$,'ZIndex','',.P_SINGLEVALUE.,'IfcInteger',$,$,$,$,$,.READWRITE.);
|
||||
#3=IFCSIMPLEPROPERTYTEMPLATE('1Wpx_r2xj1_9w5JpI0QRJy',$,'Symbol','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#4=IFCSIMPLEPROPERTYTEMPLATE('3q0oxMUKP47vZ4jnyG$dDb',$,'Classes','Classes separarated by spaces that end up in classes for this element in svg. Can be used to specify the text font size: small - 1.8mm; regular - 2.5mm; large - 3.5mm; header - 5mm; title - 7mm. By default regular size is used.',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#5=IFCPROPERTYSETTEMPLATE('0iKwujnQL9IevVQato8f7Z',$,'BBIM_Batting','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation,IfcTypeProduct',(#6,#7));
|
||||
#6=IFCSIMPLEPROPERTYTEMPLATE('0t2LEesGT1QRQtrIZUAR8L',$,'Thickness','Batting thickness',.P_SINGLEVALUE.,'IfcPositiveLengthMeasure',$,$,$,$,$,.READWRITE.);
|
||||
#7=IFCSIMPLEPROPERTYTEMPLATE('082PndS6v2kBOiJoSboMnh',$,'Reverse pattern direction','Reverse batting pattern (swap starting and ending points)',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#8=IFCPROPERTYSETTEMPLATE('1Dx2EiZnP67xotInXpwz90',$,'BBIM_Section','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation,IfcTypeProduct',(#9,#10,#11,#12,#13));
|
||||
#9=IFCSIMPLEPROPERTYTEMPLATE('2a_9s8spHDc9dZHtgg71XL',$,'ShowStartArrow','Display start arrow.',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#10=IFCSIMPLEPROPERTYTEMPLATE('3i6SH_GbT7zhKea$wVE56A',$,'StartArrowSymbol','Custom symbol for the start of the section marker arrow. Need to make sure it''s present in "symbols.svg".',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#11=IFCSIMPLEPROPERTYTEMPLATE('1DtsPn5a9FG8$zXHDDMavY',$,'ShowEndArrow','Display end arrow.',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#12=IFCSIMPLEPROPERTYTEMPLATE('2$6U0mLI9AiPRWeBabdY3u',$,'EndArrowSymbol','Custom symbol for the end of the section marker arrow. Need to make sure it''s present in "symbols.svg".',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#13=IFCSIMPLEPROPERTYTEMPLATE('1naFqntIL7igCY7hCaE7kq',$,'HasConnectedSectionLine','Connect or disconnect section markers with line (by default = True).',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#14=IFCPROPERTYSETTEMPLATE('3V8oZ8YRD3_O7uR5vcUleS',$,'BBIM_Documentation','',.PSET_OCCURRENCEDRIVEN.,'IfcProject',(#15,#16,#17,#18,#19,#20,#21,#22,#23));
|
||||
#15=IFCSIMPLEPROPERTYTEMPLATE('0ulAhgk3v9qfGlDILauR6J',$,'SheetsDir','Default sheets directory',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#16=IFCSIMPLEPROPERTYTEMPLATE('2yvlVKiQXASucfH40deCvu',$,'LayoutsDir','Default layouts directory',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#17=IFCSIMPLEPROPERTYTEMPLATE('2kXZqXicL3jRwsOnLM_0ho',$,'TitleblocksDir','Default titleblocks directory',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#18=IFCSIMPLEPROPERTYTEMPLATE('1lmOfo9Bf9beMBJkCZKf5Y',$,'DrawingsDir','Default drawings directory',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#19=IFCSIMPLEPROPERTYTEMPLATE('30cOKpb4D9CADKM04$N9X3',$,'StylesheetPath','Default stylesheet CSS',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#20=IFCSIMPLEPROPERTYTEMPLATE('23tejOrxj859R_eCRp1AFP',$,'MarkersPath','Default markers SVG',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#21=IFCSIMPLEPROPERTYTEMPLATE('1UDakJ5_f7kBhggNSW4$h5',$,'SymbolsPath','Default symbols SVG',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#22=IFCSIMPLEPROPERTYTEMPLATE('0d53LEtgLDQxnv__NfgH7i',$,'PatternsPath','Default patterns SVG',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#23=IFCSIMPLEPROPERTYTEMPLATE('26qFNMv7nCHgU6Jd7Anga5',$,'ShadingStylesPath','Default shading styles',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#24=IFCPROPERTYSETTEMPLATE('0I9merLinF5Ap$aZwaclgm',$,'BBIM_Dimension','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation,IfcTypeProduct',(#25,#26,#27,#28));
|
||||
#25=IFCSIMPLEPROPERTYTEMPLATE('1rL2AbQsXD8RbpoWH5pYOV',$,'ShowDescriptionOnly','Hide the measurement values and show only annotation description',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#26=IFCSIMPLEPROPERTYTEMPLATE('0SVyOfB0rC2xNfdRYf3XvY',$,'SuppressZeroInches','Suppress 0 inch values in dimension annotation text (for example: 12'' - 0" -> 12'')',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.);
|
||||
#27=IFCSIMPLEPROPERTYTEMPLATE('2bUmj458PBqPAtUoI3MXsb',$,'TextPrefix','Text to add before annotation measurement value',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#28=IFCSIMPLEPROPERTYTEMPLATE('0bnzttUb9BPuN597uNTXOE',$,'TextSuffix','Text to add after annotation measurement value',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
|
||||
ENDSEC;
|
||||
END-ISO-10303-21;
|
||||
@@ -19,20 +19,12 @@
|
||||
*/
|
||||
|
||||
* { stroke-linecap: round; stroke-linejoin: round; }
|
||||
text, tspan { /* 2.5mm */ fill: black; stroke: none; font-family: 'OpenGost Type B TT', 'DejaVu Sans Condensed', 'Liberation Sans', 'Arial Narrow', 'Arial'; font-size: 4.13px; }
|
||||
text { fill: black; stroke: none; }
|
||||
.cut { fill: black; stroke: black; stroke-linecap: 'round'; stroke-width: 0.35; fill-rule: evenodd; }
|
||||
.projection { fill: white; stroke: black; stroke-linecap: 'round'; stroke-width: 0.25; }
|
||||
.surface { stroke: none; fill: #fff; fill-rule: evenodd; }
|
||||
.annotation { fill: none; stroke: black; stroke-linecap: 'round'; stroke-width: 0.25; }
|
||||
.IfcAnnotation { fill: none; stroke: black; stroke-linecap: 'round'; stroke-width: 0.25; }
|
||||
.IfcGeographicElement { fill: none; stroke: black; stroke-linecap: 'round'; stroke-width: 1; }
|
||||
.PredefinedType-LINEWORK { stroke: black; stroke-width: 0.25; }
|
||||
.PredefinedType-LINEWORK.dashed { stroke-dasharray: 3, 2; }
|
||||
.PredefinedType-LINEWORK.fine { stroke-width: 0.18; stroke: #777777; }
|
||||
.PredefinedType-LINEWORK.thin { stroke-width: 0.25; }
|
||||
.PredefinedType-LINEWORK.medium { stroke-width: 0.35; }
|
||||
.PredefinedType-LINEWORK.thick { stroke-width: 0.5; }
|
||||
.PredefinedType-LINEWORK.strong { stroke-width: 1; }
|
||||
.PredefinedType-BACKGROUND { stroke: black; stroke-width: 0.18; }
|
||||
.PredefinedType-GRID { marker-start: url(#grid-marker); marker-end: url(#grid-marker); }
|
||||
.PredefinedType-SECTION { stroke-dasharray: 12.5, 3, 3, 3; }
|
||||
@@ -40,26 +32,18 @@ text, tspan { /* 2.5mm */ fill: black; stroke: none; font-family: 'OpenGost Type
|
||||
.PredefinedType-PLANLEVEL { marker-end: url(#plan-level-marker); }
|
||||
.PredefinedType-DIMENSION { marker-start: url(#dimension-marker-start); marker-end: url(#dimension-marker-end); }
|
||||
.PredefinedType-ANGLE { marker-start: url(#angle-marker-start); marker-end: url(#angle-marker-end); }
|
||||
.PredefinedType-RADIUS { marker-end: url(#fall-marker-end); }
|
||||
.PredefinedType-FALL { marker-end: url(#radius-marker-end); }
|
||||
.PredefinedType-SLOPEANGLE { marker-end: url(#radius-marker-end); }
|
||||
.PredefinedType-SLOPEPERCENT { marker-end: url(#radius-marker-end); }
|
||||
.PredefinedType-SLOPEFRACTION { marker-end: url(#radius-marker-end); }
|
||||
.PredefinedType-RADIUS { marker-end: url(#radius-marker-end); }
|
||||
.PredefinedType-DIAMETER { marker-start: url(#diameter-marker-start); marker-end: url(#diameter-marker-end); }
|
||||
.PredefinedType-HIDDENLINE { stroke-dasharray: 3, 2; }
|
||||
.PredefinedType-STAIRARROW { marker-start: url(#stair-marker-start); marker-end: url(#stair-marker-end); }
|
||||
.PredefinedType-BOUNDARY { fill: none; stroke: red; stroke-width: 1; stroke-dasharray: 12, 4, 3, 4, 3, 4; }
|
||||
.PredefinedType-BATTING { marker-start: url(#batting); stroke: none; }
|
||||
.PredefinedType-SEALANT { fill: url(#crosshatch1); stroke-width: 0.25; }
|
||||
.PredefinedType-FILLAREA { fill: white; stroke: black; }
|
||||
.PredefinedType-FILLAREA { fill: white; stroke: none; }
|
||||
.PredefinedType-BREAKLINE { fill: none; stroke: black; stroke-width: 0.25; marker-mid: url(#breakline-marker); }
|
||||
.PredefinedType-TEXT { fill: black; stroke: none; }
|
||||
path.PredefinedType-TEXTLEADER { marker-end: url(#leader-marker); }
|
||||
text.PredefinedType-TEXTLEADER, tspan.PredefinedType-TEXTLEADER { fill: black; stroke: none; }
|
||||
text.title, tspan.title { /* 7mm */ font-size: 11.55px; }
|
||||
text.header, tspan.header { /* 5mm */ font-size: 8.25px; }
|
||||
text.large, tspan.large { /* 3.5mm */ font-size: 5.78px; }
|
||||
text.regular, tspan.regular { /* 2.5mm */ font-size: 4.13px; }
|
||||
text.small, tspan.small { /* 1.8mm */ font-size: 2.97px; }
|
||||
text.GRID, tspan.GRID { /* 5mm */ font-size: 8.25px; }
|
||||
text.PredefinedType-TEXTLEADER { fill: black; stroke: none; }
|
||||
.material-blank { fill: white; }
|
||||
.material-diagonal1 { fill: url(#diagonal1); }
|
||||
.material-diagonal2 { fill: url(#diagonal2); }
|
||||
@@ -1,7 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<svg baseProfile="full" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<marker id="batting" markerHeight="10" markerWidth="4" orient="auto" refX="0" refY="5" markerUnits="userSpaceOnUse">
|
||||
<!-- Tip: https://svg-path-visualizer.netlify.app/ -->
|
||||
<!-- Tip: https://www.svgviewer.dev/ -->
|
||||
<path style="fill: none; stroke:black; stroke-width:0.18" d="M 0 2 A 2 2 0 0 1 4 2 L 2 8 M 0 2 L 2 8 A 2 2 0 0 0 4 10 M 2 8 A 2 2 0 0 1 0 10" />
|
||||
</marker>
|
||||
<marker id="eng-dimension-marker-start" markerHeight="14" markerWidth="11" orient="auto" refX="1" refY="7">
|
||||
<g>
|
||||
<path d="M 11 3.5 L 11 10.5 L 1 7" class="annotation" style="fill:black;" />
|
||||
@@ -19,12 +21,6 @@
|
||||
<path d="M 0 3.5 L 0 10.5 L 10 7" class="annotation" style="fill:black;" />
|
||||
</g>
|
||||
</marker>
|
||||
<!-- same as for the radius -->
|
||||
<marker id="fall-marker-end" markerHeight="14" markerWidth="11" orient="auto" refX="10" refY="7">
|
||||
<g>
|
||||
<path d="M 0 3.5 L 0 10.5 L 10 7" class="annotation" style="fill:black;" />
|
||||
</g>
|
||||
</marker>
|
||||
<marker id="angle-marker-start" markerHeight="14" markerWidth="11" orient="auto" refX="1" refY="7">
|
||||
<g>
|
||||
<path d="M 11 3.5 L 11 10.5 L 1 7" class="annotation" style="fill:black;" />
|
||||
@@ -75,7 +71,7 @@
|
||||
<marker id="stair-marker-end" markerHeight="42" markerWidth="21" orient="auto" refX="21" refY="21">
|
||||
<path d="M 0 0 L 21 21 L 0 42" class="annotation stair" style="stroke-width:2; marker-start: none; marker-end: none;" />
|
||||
</marker>
|
||||
<marker id="plan-level-marker" markerHeight="30" markerWidth="30" refX="15" refY="15" orient="auto">
|
||||
<marker id="plan-level-marker" markerHeight="30" markerWidth="30" refX="15" refY="15">
|
||||
<g>
|
||||
<path d="M 15 0 L 15 30" class="annotation" style="stroke-width:1;" />
|
||||
<path d="M 0 15 L 30 15" class="annotation" style="stroke-width:1;" />
|
||||
@@ -84,7 +80,7 @@
|
||||
<path d="M 15 15 L 22.5 15 A 7.5 7.5 0 0 1 15 22.5 Z" fill="black"/>
|
||||
</g>
|
||||
</marker>
|
||||
<marker id="section-level-marker" markerHeight="11" markerWidth="90" refX="20" refY="10" orient="auto-start-reverse">
|
||||
<marker id="section-level-marker" markerHeight="11" markerWidth="90" refX="20" refY="10">
|
||||
<g>
|
||||
<path d="M 0 1 L 20 1 L 10 11 Z" fill="black" />
|
||||
<path d="M 0 1 L 90 1" class="annotation" style="stroke-width:1;" />
|
||||
@@ -96,12 +92,4 @@
|
||||
<path d="M 7.5 10 L 10 0 L 15 10" class="annotation" style="stroke-width:1; fill: white;" />
|
||||
</g>
|
||||
</marker>
|
||||
<filter x="0" y="0" width="1" height="1" id="fill-background">
|
||||
<feFlood flood-color="white" result="bg" />
|
||||
<feMerge>
|
||||
<feMergeNode in="bg"/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.4 KiB |
@@ -17,49 +17,16 @@
|
||||
<line x1="0" y1="0" x2="0" y2="3" style="stroke:black; stroke-width:0.25" />
|
||||
</pattern>
|
||||
<pattern id="square1" width="1" height="1" patternUnits="userSpaceOnUse">
|
||||
<path style="stroke: black; stroke-width: 0.25; fill: none;" d="M 0 0 1 0 1 1" />
|
||||
<line x1="0" y1="0" x2="0" y2="1" style="stroke:black; stroke-width:0.25" />
|
||||
<line x1="0" y1="0" x2="1" y2="0" style="stroke:black; stroke-width:0.25" />
|
||||
</pattern>
|
||||
<pattern id="square2" width="2" height="2" patternUnits="userSpaceOnUse">
|
||||
<path style="stroke: black; stroke-width: 0.25; fill: none;" d="M 0 0 2 0 2 2" />
|
||||
<line x1="0" y1="0" x2="0" y2="2" style="stroke:black; stroke-width:0.25" />
|
||||
<line x1="0" y1="0" x2="2" y2="0" style="stroke:black; stroke-width:0.25" />
|
||||
</pattern>
|
||||
<pattern id="square3" width="3" height="3" patternUnits="userSpaceOnUse">
|
||||
<path style="stroke: black; stroke-width: 0.25; fill: none;" d="M 0 0 3 0 3 3" />
|
||||
</pattern>
|
||||
<pattern id="recth1" width="2" height="1" patternUnits="userSpaceOnUse">
|
||||
<path style="stroke: black; stroke-width: 0.25; fill: none;" d="M 0 0 2 0 2 1" />
|
||||
</pattern>
|
||||
<pattern id="recth2" width="4" height="2" patternUnits="userSpaceOnUse">
|
||||
<path style="stroke: black; stroke-width: 0.25; fill: none;" d="M 0 0 4 0 4 2" />
|
||||
</pattern>
|
||||
<pattern id="recth3" width="6" height="3" patternUnits="userSpaceOnUse">
|
||||
<path style="stroke: black; stroke-width: 0.25; fill: none;" d="M 0 0 6 0 6 3" />
|
||||
</pattern>
|
||||
<pattern id="rectv1" width="1" height="2" patternUnits="userSpaceOnUse">
|
||||
<path style="stroke: black; stroke-width: 0.25; fill: none;" d="M 0 0 1 0 1 2" />
|
||||
</pattern>
|
||||
<pattern id="rectv2" width="2" height="4" patternUnits="userSpaceOnUse">
|
||||
<path style="stroke: black; stroke-width: 0.25; fill: none;" d="M 0 0 2 0 2 4" />
|
||||
</pattern>
|
||||
<pattern id="rectv3" width="3" height="6" patternUnits="userSpaceOnUse">
|
||||
<path style="stroke: black; stroke-width: 0.25; fill: none;" d="M 0 0 3 0 3 6" />
|
||||
</pattern>
|
||||
<pattern id="tile1" width="2" height="2" patternUnits="userSpaceOnUse">
|
||||
<path style="stroke: black; stroke-width: 0.15; fill: none;" d="M 0 0 2 0 2 1 0 1 M 1 1 1 2" />
|
||||
</pattern>
|
||||
<pattern id="tile2" width="4" height="4" patternUnits="userSpaceOnUse">
|
||||
<path style="stroke: black; stroke-width: 0.15; fill: none;" d="M 0 0 4 0 4 2 0 2 M 2 2 2 4" />
|
||||
</pattern>
|
||||
<pattern id="tile3" width="6" height="6" patternUnits="userSpaceOnUse">
|
||||
<path style="stroke: black; stroke-width: 0.15; fill: none;" d="M 0 0 6 0 6 3 0 3 M 3 3 3 6" />
|
||||
</pattern>
|
||||
<pattern id="board1" width="4" height="2" patternUnits="userSpaceOnUse">
|
||||
<path style="stroke: black; stroke-width: 0.15; fill: none;" d="M 0 0 4 0 4 1 0 1 M 2 1 2 2" />
|
||||
</pattern>
|
||||
<pattern id="board2" width="8" height="4" patternUnits="userSpaceOnUse">
|
||||
<path style="stroke: black; stroke-width: 0.15; fill: none;" d="M 0 0 8 0 8 2 0 2 M 4 2 4 4" />
|
||||
</pattern>
|
||||
<pattern id="board3" width="12" height="6" patternUnits="userSpaceOnUse">
|
||||
<path style="stroke: black; stroke-width: 0.15; fill: none;" d="M 0 0 12 0 12 3 0 3 M 6 3 6 6" />
|
||||
<line x1="0" y1="0" x2="0" y2="3" style="stroke:black; stroke-width:0.25" />
|
||||
<line x1="0" y1="0" x2="3" y2="0" style="stroke:black; stroke-width:0.25" />
|
||||
</pattern>
|
||||
<pattern id="crosshatch1" width="1" height="1" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse">
|
||||
<line x1="0" y1="0" x2="0" y2="1" style="stroke:black; stroke-width:0.25" />
|
||||
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 67 KiB |
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<svg baseProfile="full" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="rectangle-tag">
|
||||
<rect x="-6" y="-2.5" width="12" height="5" fill="white" stroke="black" style="stroke-width: 0.25;" />
|
||||
</g>
|
||||
<g id="door-tag">
|
||||
<circle cy="1.75" r="5" fill="white" stroke="black" style="stroke-width: 0.25;" />
|
||||
<line x1="-5" y1="1.75" x2="5" y2="1.75" style="stroke: black; stroke-width: 0.25;" />
|
||||
</g>
|
||||
<g id="elevation-arrow">
|
||||
<path style="fill: black;" d="M -7.07106 0 0 -7.07106 7.07106 0" />
|
||||
</g>
|
||||
<g id="elevation-tag">
|
||||
<circle r="5" fill="white" stroke="black" style="stroke-width: 0.25;" />
|
||||
<line x1="-5" y1="0" x2="5" y2="0" style="stroke: black; stroke-width: 0.25;" />
|
||||
</g>
|
||||
<g id="section-arrow">
|
||||
<path style="fill: black;" d="M -7.07106 0 0 -7.07106 7.07106 0" />
|
||||
</g>
|
||||
<g id="section-tag">
|
||||
<circle r="5" fill="white" stroke="black" style="stroke-width: 0.25;" />
|
||||
<line x1="-5" y1="0" x2="5" y2="0" style="stroke: black; stroke-width: 0.25;" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -1,15 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 841 594"
|
||||
id="root"
|
||||
version="1.1"
|
||||
height="594mm"
|
||||
width="841mm"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
width="841mm">
|
||||
<defs
|
||||
id="defs901" />
|
||||
<metadata
|
||||
@@ -20,6 +20,7 @@
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
@@ -43,10 +44,146 @@
|
||||
width="3027.1016"
|
||||
id="rect116616"
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.88976377;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<text
|
||||
id="text116526"
|
||||
y="909.15491"
|
||||
x="113.70713"
|
||||
style="font-style:normal;font-weight:normal;font-size:15.1536px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.1536px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.94488188;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="909.15491"
|
||||
x="113.70713"
|
||||
id="tspan116524">REV. NO.</tspan></text>
|
||||
<path
|
||||
id="path116530"
|
||||
d="M 75.590564,895.24802 H 3102.9921"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
id="path116532"
|
||||
d="M 151.6811,895.24802 V 1046.9291"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 454.04331,895.24802 V 1046.9291"
|
||||
id="path116534" />
|
||||
<path
|
||||
id="path116536"
|
||||
d="M 529.63386,895.24802 V 1046.4302"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 605.22441,895.24802 V 1046.9291"
|
||||
id="path116538" />
|
||||
<path
|
||||
id="path116540"
|
||||
d="M 75.590564,914.14565 H 605.22441"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 75.590564,933.04329 H 605.22441"
|
||||
id="path116542" />
|
||||
<path
|
||||
id="path116544"
|
||||
d="M 75.590564,951.94093 H 605.22441"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 75.590564,970.83857 H 605.22441"
|
||||
id="path116546" />
|
||||
<path
|
||||
id="path116548"
|
||||
d="M 75.590564,989.73621 H 605.22441"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 75.590564,1008.6338 H 605.22441"
|
||||
id="path116550" />
|
||||
<path
|
||||
id="path116552"
|
||||
d="M 75.590564,1027.5315 H 605.22441"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
id="path116576"
|
||||
d="M 2800.5,895.24802 V 1046.9291"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
id="path116578"
|
||||
d="m 2800.5,1008.6338 h 302.4921"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
id="path116598"
|
||||
d="m 3027.4027,1008.6338 v 38.2953"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:15.1536px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
x="302.86591"
|
||||
y="909.15491"
|
||||
id="text1395"><tspan
|
||||
id="tspan1393"
|
||||
x="302.86591"
|
||||
y="909.15491"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.1536px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.94488188;stroke-miterlimit:4;stroke-dasharray:none">DESCRIPTION</tspan></text>
|
||||
<text
|
||||
id="text1399"
|
||||
y="909.15491"
|
||||
x="491.97513"
|
||||
style="font-style:normal;font-weight:normal;font-size:15.1536px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.1536px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.94488188;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="909.15491"
|
||||
x="491.97513"
|
||||
id="tspan1397">AUTHOR</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:16.0591px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
x="568.05585"
|
||||
y="909.15485"
|
||||
id="text1403"><tspan
|
||||
id="tspan1401"
|
||||
x="568.05585"
|
||||
y="909.15485"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.0591px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.94488188;stroke-miterlimit:4;stroke-dasharray:none">DATE</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:11.2271px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
x="2839.5081"
|
||||
y="1020.4988"
|
||||
id="text1421"><tspan
|
||||
id="tspan1419"
|
||||
x="2839.5081"
|
||||
y="1020.4988"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.2271px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.94488188;stroke-miterlimit:4;stroke-dasharray:none">DRAWING NUMBER</tspan></text>
|
||||
<text
|
||||
id="text1429"
|
||||
y="1020.4988"
|
||||
x="3038.5586"
|
||||
style="font-style:normal;font-weight:normal;font-size:11.2271px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.94488188;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.2271px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.94488188;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="1020.4988"
|
||||
x="3038.5586"
|
||||
id="tspan1427">REV</tspan></text>
|
||||
<text
|
||||
id="text2529"
|
||||
y="1036.1166"
|
||||
x="3030.9653"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3918px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.999999px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="stroke-width:0.999999px"
|
||||
y="1036.1166"
|
||||
x="3030.9653"
|
||||
id="tspan2527">{{Revision}}</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3918px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.999999px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="2804.7021"
|
||||
y="1036.1166"
|
||||
id="text2533"><tspan
|
||||
id="tspan2531"
|
||||
x="2804.7021"
|
||||
y="1036.1166"
|
||||
style="stroke-width:0.999999px">{{Identification}} - {{Name}}</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.26458333,0,0,0.26458334,-3.180917e-5,297.00003)"
|
||||
@@ -68,260 +205,4 @@
|
||||
transform="matrix(0.26458333,0,0,0.26458334,-3.180917e-5,297.00003)"
|
||||
id="g90677"
|
||||
style="stroke-width:3.77953" />
|
||||
<g
|
||||
id="g38171"
|
||||
transform="translate(411.014,286.96036)">
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 329.96563,246.86771 V 286.75"
|
||||
id="path116576" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 329.96563,276.8677 H 410"
|
||||
id="path116578" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 390.00031,276.8677 V 287"
|
||||
id="path116598" />
|
||||
<text
|
||||
id="text1421"
|
||||
y="280.00699"
|
||||
x="340.28653"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.9705px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.9705px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="280.00699"
|
||||
x="340.28653"
|
||||
id="tspan1419">DRAWING NUMBER</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.05925px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25747;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="393.00568"
|
||||
y="280.0592"
|
||||
id="text1429"><tspan
|
||||
id="tspan1427"
|
||||
x="393.00568"
|
||||
y="280.0592"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.05925px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25747;stroke-miterlimit:4;stroke-dasharray:none">REV</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="390.94287"
|
||||
y="284.13919"
|
||||
id="text2529"><tspan
|
||||
id="tspan2527"
|
||||
x="390.94287"
|
||||
y="284.13919"
|
||||
style="stroke-width:0.264583px">{{Revision}}</tspan></text>
|
||||
<text
|
||||
id="text2533"
|
||||
y="284.13919"
|
||||
x="331.07742"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.265;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="stroke-width:0.265;stroke-dasharray:none"
|
||||
y="284.13919"
|
||||
x="331.07742"
|
||||
id="tspan2531">{{Identification}}</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 329.96563,266.868 H 410"
|
||||
id="path36736" />
|
||||
<text
|
||||
id="text36740"
|
||||
y="270.05899"
|
||||
x="339.00919"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.05925px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25747;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.05925px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25747;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="270.05899"
|
||||
x="339.00919"
|
||||
id="tspan36738">DRAWING TITLE</tspan></text>
|
||||
<text
|
||||
id="text36744"
|
||||
y="275.05634"
|
||||
x="330.99438"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.96055px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.371;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="stroke-width:0.371;stroke-dasharray:none"
|
||||
y="275.05634"
|
||||
x="330.99438"
|
||||
id="tspan36742">{{Name}}</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 390.00031,246.86771 V 266.993"
|
||||
id="path36746" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.88677px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.169851;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="397.04108"
|
||||
y="249.72177"
|
||||
id="text36677"><tspan
|
||||
id="tspan36675"
|
||||
x="397.04108"
|
||||
y="249.72177"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.88677px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.169851;stroke-miterlimit:4;stroke-dasharray:none">GRID NORTH</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.88677px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.169851;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="338.77008"
|
||||
y="249.72177"
|
||||
id="text36752"><tspan
|
||||
id="tspan36750"
|
||||
x="335.76562"
|
||||
y="249.72177"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.88677px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.169851;stroke-miterlimit:4;stroke-dasharray:none">COMPANY</tspan></text>
|
||||
<g
|
||||
id="g37148"
|
||||
transform="translate(399.87519,258.25776)">
|
||||
<g
|
||||
id="g37140"
|
||||
data-type="grid-north">
|
||||
<path
|
||||
id="path11652"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.25;stroke-linecap:round;stroke-dasharray:none"
|
||||
d="M 0,0 V 7.12566 Z" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.25;stroke-linecap:round;stroke-dasharray:none"
|
||||
d="M 7.3079,3e-5 H -7.30798"
|
||||
id="path36547" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.25;stroke-linecap:round;stroke-dasharray:none"
|
||||
id="path36601"
|
||||
cx="-3.8305665e-05"
|
||||
cy="4.15625e-05"
|
||||
r="5" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.25;stroke-linecap:round;stroke-dasharray:none"
|
||||
d="m -5.00004,4e-5 5,-5 5,5 H 3.94162 L -4e-5,-3.94162 -3.9417,4e-5 Z"
|
||||
id="path36671" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-dasharray:none"
|
||||
d="M -4e-5,-7.12545 V 3e-5"
|
||||
id="path36673" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g38492"
|
||||
transform="translate(9.7896584,287.21036)">
|
||||
<text
|
||||
id="text116526"
|
||||
y="250.54721"
|
||||
x="20.085007"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.00939px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.00939px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="250.54721"
|
||||
x="20.085007"
|
||||
id="tspan116524">REV. NO.</tspan></text>
|
||||
<path
|
||||
id="path116532"
|
||||
d="M 30.132288,246.86771 V 287"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 110.13229,246.86771 V 287"
|
||||
id="path116534" />
|
||||
<path
|
||||
id="path116536"
|
||||
d="M 130.13229,246.86771 V 286.868"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 150.13229,246.86771 V 287"
|
||||
id="path116538" />
|
||||
<path
|
||||
id="path116540"
|
||||
d="M 10,251.86771 H 170.132"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 10,256.86771 H 170.132"
|
||||
id="path116542" />
|
||||
<path
|
||||
id="path116544"
|
||||
d="M 10,261.86771 H 170.132"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 10,266.86771 H 170.132"
|
||||
id="path116546" />
|
||||
<path
|
||||
id="path116548"
|
||||
d="M 10,271.86771 H 170.132"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 10,276.8677 H 170.132"
|
||||
id="path116550" />
|
||||
<path
|
||||
id="path116552"
|
||||
d="M 10,281.86772 H 170.132"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.00939px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="70.13327"
|
||||
y="250.54721"
|
||||
id="text1395"><tspan
|
||||
id="tspan1393"
|
||||
x="70.13327"
|
||||
y="250.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.00939px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">DESCRIPTION</tspan></text>
|
||||
<text
|
||||
id="text1399"
|
||||
y="250.54721"
|
||||
x="120.16841"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.00939px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.00939px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="250.54721"
|
||||
x="120.16841"
|
||||
id="tspan1397">AUTHOR</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.24897px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="140.29811"
|
||||
y="250.54721"
|
||||
id="text1403"><tspan
|
||||
id="tspan1401"
|
||||
x="140.29811"
|
||||
y="250.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.24897px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">ISSUED</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.24897px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="180.14232"
|
||||
y="250.54721"
|
||||
id="text36130"><tspan
|
||||
id="tspan36128"
|
||||
x="175.72011"
|
||||
y="250.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.24897px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">NOTES</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.24897px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="194.37886"
|
||||
y="255.5477"
|
||||
id="text36768"><tspan
|
||||
id="tspan36766"
|
||||
x="189.95665"
|
||||
y="255.5477"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.24897px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">DO NOT SCALE DRAWINGS</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 170.132,246.86771 V 287"
|
||||
id="path36836" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.24897px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="160.29811"
|
||||
y="250.54721"
|
||||
id="text36842"><tspan
|
||||
id="tspan36840"
|
||||
x="160.29811"
|
||||
y="250.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.24897px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">DATE</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 12 KiB |
@@ -1,15 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="594mm"
|
||||
height="420mm"
|
||||
version="1.1"
|
||||
id="root"
|
||||
viewBox="0 0 594 420"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
viewBox="0 0 594 420">
|
||||
<defs
|
||||
id="defs901" />
|
||||
<metadata
|
||||
@@ -20,6 +20,7 @@
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
@@ -39,10 +40,146 @@
|
||||
width="553.5"
|
||||
id="rect116616"
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.499999;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<text
|
||||
id="text116526"
|
||||
y="363.54721"
|
||||
x="30.085009"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.00939px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.00939px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="363.54721"
|
||||
x="30.085009"
|
||||
id="tspan116524">REV. NO.</tspan></text>
|
||||
<path
|
||||
id="path116530"
|
||||
d="m 20.000001,359.86771 553.749999,0"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
id="path116532"
|
||||
d="M 40.132289,359.86771 V 400"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 120.13229,359.86771 V 400"
|
||||
id="path116534" />
|
||||
<path
|
||||
id="path116536"
|
||||
d="M 140.13229,359.86771 V 399.868"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 160.13229,359.86771 V 400"
|
||||
id="path116538" />
|
||||
<path
|
||||
id="path116540"
|
||||
d="M 20.000001,364.86771 H 160.13229"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 20.000001,369.86771 H 160.13229"
|
||||
id="path116542" />
|
||||
<path
|
||||
id="path116544"
|
||||
d="M 20.000001,374.86771 H 160.13229"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 20.000001,379.86771 H 160.13229"
|
||||
id="path116546" />
|
||||
<path
|
||||
id="path116548"
|
||||
d="M 20.000001,384.86771 H 160.13229"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 20.000001,389.8677 H 160.13229"
|
||||
id="path116550" />
|
||||
<path
|
||||
id="path116552"
|
||||
d="M 20.000001,394.86772 H 160.13229"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.00939px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="80.13327"
|
||||
y="363.54721"
|
||||
id="text1395"><tspan
|
||||
id="tspan1393"
|
||||
x="80.13327"
|
||||
y="363.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.00939px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">DESCRIPTION</tspan></text>
|
||||
<text
|
||||
id="text1399"
|
||||
y="363.54721"
|
||||
x="130.16841"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.00939px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.00939px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="363.54721"
|
||||
x="130.16841"
|
||||
id="tspan1397">AUTHOR</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.24897px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="150.29811"
|
||||
y="363.54721"
|
||||
id="text1403"><tspan
|
||||
id="tspan1401"
|
||||
x="150.29811"
|
||||
y="363.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.24897px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">DATE</tspan></text>
|
||||
<path
|
||||
id="path116576"
|
||||
d="M 493.96563,359.86771 V 400"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
id="path116578"
|
||||
d="M 493.96563,389.8677 H 574"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
id="path116598"
|
||||
d="M 554.00031,389.8677 V 400"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.9705px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="504.28653"
|
||||
y="393.00699"
|
||||
id="text1421"><tspan
|
||||
id="tspan1419"
|
||||
x="504.28653"
|
||||
y="393.00699"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.9705px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">DRAWING NUMBER</tspan></text>
|
||||
<text
|
||||
id="text1429"
|
||||
y="393.00699"
|
||||
x="556.9519"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.9705px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.9705px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="393.00699"
|
||||
x="556.9519"
|
||||
id="tspan1427">REV</tspan></text>
|
||||
<text
|
||||
id="text2529"
|
||||
y="397.13919"
|
||||
x="554.94287"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="stroke-width:0.264583px"
|
||||
y="397.13919"
|
||||
x="554.94287"
|
||||
id="tspan2527">{{Revision}}</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="495.07742"
|
||||
y="397.13919"
|
||||
id="text2533"><tspan
|
||||
id="tspan2531"
|
||||
x="495.07742"
|
||||
y="397.13919"
|
||||
style="stroke-width:0.264583px">{{Identification}} - {{Name}}</tspan></text>
|
||||
<g
|
||||
style="stroke-width:3.77953"
|
||||
id="g90669"
|
||||
@@ -63,260 +200,4 @@
|
||||
style="stroke-width:3.77953"
|
||||
id="g90677"
|
||||
transform="matrix(0.26458333,0,0,0.26458334,-3.180917e-5,297.00003)" />
|
||||
<g
|
||||
id="g38171"
|
||||
transform="translate(163.75769,113)">
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 329.96563,246.86771 V 286.75"
|
||||
id="path116576" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 329.96563,276.8677 H 410"
|
||||
id="path116578" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 390.00031,276.8677 V 287"
|
||||
id="path116598" />
|
||||
<text
|
||||
id="text1421"
|
||||
y="280.00699"
|
||||
x="340.28653"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.9705px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.9705px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="280.00699"
|
||||
x="340.28653"
|
||||
id="tspan1419">DRAWING NUMBER</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.05925px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25747;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="393.00568"
|
||||
y="280.0592"
|
||||
id="text1429"><tspan
|
||||
id="tspan1427"
|
||||
x="393.00568"
|
||||
y="280.0592"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.05925px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25747;stroke-miterlimit:4;stroke-dasharray:none">REV</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="390.94287"
|
||||
y="284.13919"
|
||||
id="text2529"><tspan
|
||||
id="tspan2527"
|
||||
x="390.94287"
|
||||
y="284.13919"
|
||||
style="stroke-width:0.264583px">{{Revision}}</tspan></text>
|
||||
<text
|
||||
id="text2533"
|
||||
y="284.13919"
|
||||
x="331.07742"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.265;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="stroke-width:0.265;stroke-dasharray:none"
|
||||
y="284.13919"
|
||||
x="331.07742"
|
||||
id="tspan2531">{{Identification}}</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 329.96563,266.868 H 410"
|
||||
id="path36736" />
|
||||
<text
|
||||
id="text36740"
|
||||
y="270.05899"
|
||||
x="339.00919"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.05925px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25747;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.05925px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25747;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="270.05899"
|
||||
x="339.00919"
|
||||
id="tspan36738">DRAWING TITLE</tspan></text>
|
||||
<text
|
||||
id="text36744"
|
||||
y="275.05634"
|
||||
x="330.99438"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.96055px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.371;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="stroke-width:0.371;stroke-dasharray:none"
|
||||
y="275.05634"
|
||||
x="330.99438"
|
||||
id="tspan36742">{{Name}}</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 390.00031,246.86771 V 266.993"
|
||||
id="path36746" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.88677px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.169851;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="397.04108"
|
||||
y="249.72177"
|
||||
id="text36677"><tspan
|
||||
id="tspan36675"
|
||||
x="397.04108"
|
||||
y="249.72177"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.88677px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.169851;stroke-miterlimit:4;stroke-dasharray:none">GRID NORTH</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.88677px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.169851;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="338.77008"
|
||||
y="249.72177"
|
||||
id="text36752"><tspan
|
||||
id="tspan36750"
|
||||
x="335.76562"
|
||||
y="249.72177"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.88677px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.169851;stroke-miterlimit:4;stroke-dasharray:none">COMPANY</tspan></text>
|
||||
<g
|
||||
id="g37148"
|
||||
transform="translate(399.87519,258.25776)">
|
||||
<g
|
||||
id="g37140"
|
||||
data-type="grid-north">
|
||||
<path
|
||||
id="path11652"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.25;stroke-linecap:round;stroke-dasharray:none"
|
||||
d="M 0,0 V 7.12566 Z" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.25;stroke-linecap:round;stroke-dasharray:none"
|
||||
d="M 7.3079,3e-5 H -7.30798"
|
||||
id="path36547" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.25;stroke-linecap:round;stroke-dasharray:none"
|
||||
id="path36601"
|
||||
cx="-3.8305665e-05"
|
||||
cy="4.15625e-05"
|
||||
r="5" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.25;stroke-linecap:round;stroke-dasharray:none"
|
||||
d="m -5.00004,4e-5 5,-5 5,5 H 3.94162 L -4e-5,-3.94162 -3.9417,4e-5 Z"
|
||||
id="path36671" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-dasharray:none"
|
||||
d="M -4e-5,-7.12545 V 3e-5"
|
||||
id="path36673" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g38492"
|
||||
transform="translate(10.000001,113)">
|
||||
<text
|
||||
id="text116526"
|
||||
y="250.54721"
|
||||
x="20.085007"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.00939px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.00939px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="250.54721"
|
||||
x="20.085007"
|
||||
id="tspan116524">REV. NO.</tspan></text>
|
||||
<path
|
||||
id="path116532"
|
||||
d="M 30.132288,246.86771 V 287"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 110.13229,246.86771 V 287"
|
||||
id="path116534" />
|
||||
<path
|
||||
id="path116536"
|
||||
d="M 130.13229,246.86771 V 286.868"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 150.13229,246.86771 V 287"
|
||||
id="path116538" />
|
||||
<path
|
||||
id="path116540"
|
||||
d="M 10,251.86771 H 170.132"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 10,256.86771 H 170.132"
|
||||
id="path116542" />
|
||||
<path
|
||||
id="path116544"
|
||||
d="M 10,261.86771 H 170.132"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 10,266.86771 H 170.132"
|
||||
id="path116546" />
|
||||
<path
|
||||
id="path116548"
|
||||
d="M 10,271.86771 H 170.132"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 10,276.8677 H 170.132"
|
||||
id="path116550" />
|
||||
<path
|
||||
id="path116552"
|
||||
d="M 10,281.86772 H 170.132"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.00939px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="70.13327"
|
||||
y="250.54721"
|
||||
id="text1395"><tspan
|
||||
id="tspan1393"
|
||||
x="70.13327"
|
||||
y="250.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.00939px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">DESCRIPTION</tspan></text>
|
||||
<text
|
||||
id="text1399"
|
||||
y="250.54721"
|
||||
x="120.16841"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.00939px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.00939px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="250.54721"
|
||||
x="120.16841"
|
||||
id="tspan1397">AUTHOR</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.24897px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="140.29811"
|
||||
y="250.54721"
|
||||
id="text1403"><tspan
|
||||
id="tspan1401"
|
||||
x="140.29811"
|
||||
y="250.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.24897px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">ISSUED</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.24897px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="180.14232"
|
||||
y="250.54721"
|
||||
id="text36130"><tspan
|
||||
id="tspan36128"
|
||||
x="175.72011"
|
||||
y="250.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.24897px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">NOTES</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.24897px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="194.37886"
|
||||
y="255.5477"
|
||||
id="text36768"><tspan
|
||||
id="tspan36766"
|
||||
x="189.95665"
|
||||
y="255.5477"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.24897px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">DO NOT SCALE DRAWINGS</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 170.132,246.86771 V 287"
|
||||
id="path36836" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.24897px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="160.29811"
|
||||
y="250.54721"
|
||||
id="text36842"><tspan
|
||||
id="tspan36840"
|
||||
x="160.29811"
|
||||
y="250.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.24897px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">DATE</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 12 KiB |
@@ -1,15 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="420mm"
|
||||
height="297mm"
|
||||
version="1.1"
|
||||
id="root"
|
||||
viewBox="0 0 420 297"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
viewBox="0 0 420 297">
|
||||
<defs
|
||||
id="defs901" />
|
||||
<metadata
|
||||
@@ -20,6 +20,7 @@
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
@@ -39,10 +40,150 @@
|
||||
width="399.5"
|
||||
id="rect116616"
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.49999897;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<text
|
||||
id="text116526"
|
||||
y="250.54721"
|
||||
x="20.085007"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.00939px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.00939px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="250.54721"
|
||||
x="20.085007"
|
||||
id="tspan116524">REV. NO.</tspan></text>
|
||||
<path
|
||||
id="path116530"
|
||||
d="m 10,246.86771 399.75,0"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
id="path116532"
|
||||
d="M 30.132288,246.86771 V 287"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 110.13229,246.86771 V 287"
|
||||
id="path116534" />
|
||||
<path
|
||||
id="path116536"
|
||||
d="M 130.13229,246.86771 V 286.868"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 150.13229,246.86771 V 287"
|
||||
id="path116538" />
|
||||
<path
|
||||
id="path116540"
|
||||
d="M 10,251.86771 H 150.13229"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 10,256.86771 H 150.13229"
|
||||
id="path116542" />
|
||||
<path
|
||||
id="path116544"
|
||||
d="M 10,261.86771 H 150.13229"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 10,266.86771 H 150.13229"
|
||||
id="path116546" />
|
||||
<path
|
||||
id="path116548"
|
||||
d="M 10,271.86771 H 150.13229"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 10,276.8677 H 150.13229"
|
||||
id="path116550" />
|
||||
<path
|
||||
id="path116552"
|
||||
d="M 10,281.86772 H 150.13229"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.00939px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="70.13327"
|
||||
y="250.54721"
|
||||
id="text1395"><tspan
|
||||
id="tspan1393"
|
||||
x="70.13327"
|
||||
y="250.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.00939px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">DESCRIPTION</tspan></text>
|
||||
<text
|
||||
id="text1399"
|
||||
y="250.54721"
|
||||
x="120.16841"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.00939px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.00939px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="250.54721"
|
||||
x="120.16841"
|
||||
id="tspan1397">AUTHOR</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.24897px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="140.29811"
|
||||
y="250.54721"
|
||||
id="text1403"><tspan
|
||||
id="tspan1401"
|
||||
x="140.29811"
|
||||
y="250.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.24897px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">DATE</tspan></text>
|
||||
<g
|
||||
transform="translate(-154)"
|
||||
id="g3735">
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 483.96563,246.86771 V 287"
|
||||
id="path116576" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 483.96563,276.8677 H 564"
|
||||
id="path116578" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 544.00031,276.8677 V 287"
|
||||
id="path116598" />
|
||||
<text
|
||||
id="text1421"
|
||||
y="280.00699"
|
||||
x="494.28653"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.9705px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.9705px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="280.00699"
|
||||
x="494.28653"
|
||||
id="tspan1419">DRAWING NUMBER</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.9705px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="546.9519"
|
||||
y="280.00699"
|
||||
id="text1429"><tspan
|
||||
id="tspan1427"
|
||||
x="546.9519"
|
||||
y="280.00699"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.9705px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">REV</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="544.94287"
|
||||
y="284.13919"
|
||||
id="text2529"><tspan
|
||||
id="tspan2527"
|
||||
x="544.94287"
|
||||
y="284.13919"
|
||||
style="stroke-width:0.264583px">{{Revision}}</tspan></text>
|
||||
<text
|
||||
id="text2533"
|
||||
y="284.13919"
|
||||
x="485.07742"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="stroke-width:0.264583px"
|
||||
y="284.13919"
|
||||
x="485.07742"
|
||||
id="tspan2531">{{Identification}} - {{Name}}</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
style="stroke-width:3.77953"
|
||||
id="g90669"
|
||||
@@ -63,271 +204,4 @@
|
||||
style="stroke-width:3.77953"
|
||||
id="g90677"
|
||||
transform="matrix(0.26458333,0,0,0.26458334,-3.180917e-5,297.00003)" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.24897px;line-height:100%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="162.3047"
|
||||
y="256.66803"
|
||||
id="text36756" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:20.4013px;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT, Normal';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:round;stroke-dasharray:none"
|
||||
x="161.2028"
|
||||
y="266.93387"
|
||||
id="text36760" />
|
||||
<g
|
||||
id="g38492">
|
||||
<text
|
||||
id="text116526"
|
||||
y="250.54721"
|
||||
x="20.085007"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.00939px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.00939px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="250.54721"
|
||||
x="20.085007"
|
||||
id="tspan116524">REV. NO.</tspan></text>
|
||||
<path
|
||||
id="path116532"
|
||||
d="M 30.132288,246.86771 V 287"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 110.13229,246.86771 V 287"
|
||||
id="path116534" />
|
||||
<path
|
||||
id="path116536"
|
||||
d="M 130.13229,246.86771 V 286.868"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 150.13229,246.86771 V 287"
|
||||
id="path116538" />
|
||||
<path
|
||||
id="path116540"
|
||||
d="m 10,251.86771 160.132,0"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 10,256.86771 160.132,0"
|
||||
id="path116542" />
|
||||
<path
|
||||
id="path116544"
|
||||
d="m 10,261.86771 160.132,0"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 10,266.86771 160.132,0"
|
||||
id="path116546" />
|
||||
<path
|
||||
id="path116548"
|
||||
d="m 10,271.86771 160.132,0"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 10,276.8677 160.132,0"
|
||||
id="path116550" />
|
||||
<path
|
||||
id="path116552"
|
||||
d="m 10,281.86772 160.132,0"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.00939px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="70.13327"
|
||||
y="250.54721"
|
||||
id="text1395"><tspan
|
||||
id="tspan1393"
|
||||
x="70.13327"
|
||||
y="250.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.00939px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">DESCRIPTION</tspan></text>
|
||||
<text
|
||||
id="text1399"
|
||||
y="250.54721"
|
||||
x="120.16841"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.00939px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.00939px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="250.54721"
|
||||
x="120.16841"
|
||||
id="tspan1397">AUTHOR</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.24897px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="140.29811"
|
||||
y="250.54721"
|
||||
id="text1403"><tspan
|
||||
id="tspan1401"
|
||||
x="140.29811"
|
||||
y="250.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.24897px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">ISSUED</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.24897px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="180.14232"
|
||||
y="250.54721"
|
||||
id="text36130"><tspan
|
||||
id="tspan36128"
|
||||
x="175.72011"
|
||||
y="250.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.24897px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">NOTES</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.24897px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="194.37886"
|
||||
y="255.5477"
|
||||
id="text36768"><tspan
|
||||
id="tspan36766"
|
||||
x="189.95665"
|
||||
y="255.5477"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.24897px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">DO NOT SCALE DRAWINGS</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 170.132,246.86771 V 287"
|
||||
id="path36836" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.24897px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="160.29811"
|
||||
y="250.54721"
|
||||
id="text36842"><tspan
|
||||
id="tspan36840"
|
||||
x="160.29811"
|
||||
y="250.54721"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.24897px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none">DATE</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g38171"
|
||||
transform="translate(-0.25000095)">
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 329.96563,246.86771 V 286.75"
|
||||
id="path116576" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 329.96563,276.8677 H 410"
|
||||
id="path116578" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 390.00031,276.8677 V 287"
|
||||
id="path116598" />
|
||||
<text
|
||||
id="text1421"
|
||||
y="280.00699"
|
||||
x="340.28653"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.9705px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.9705px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="280.00699"
|
||||
x="340.28653"
|
||||
id="tspan1419">DRAWING NUMBER</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.05925px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25747;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="393.00568"
|
||||
y="280.0592"
|
||||
id="text1429"><tspan
|
||||
id="tspan1427"
|
||||
x="393.00568"
|
||||
y="280.0592"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.05925px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25747;stroke-miterlimit:4;stroke-dasharray:none">REV</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="390.94287"
|
||||
y="284.13919"
|
||||
id="text2529"><tspan
|
||||
id="tspan2527"
|
||||
x="390.94287"
|
||||
y="284.13919"
|
||||
style="stroke-width:0.264583px">{{Revision}}</tspan></text>
|
||||
<text
|
||||
id="text2533"
|
||||
y="284.13919"
|
||||
x="331.07742"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.265;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="stroke-width:0.265;stroke-dasharray:none"
|
||||
y="284.13919"
|
||||
x="331.07742"
|
||||
id="tspan2531">{{Identification}}</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 329.96563,266.868 H 410"
|
||||
id="path36736" />
|
||||
<text
|
||||
id="text36740"
|
||||
y="270.05899"
|
||||
x="339.00919"
|
||||
style="font-style:normal;font-weight:normal;font-size:3.05925px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25747;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.05925px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.25747;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
y="270.05899"
|
||||
x="339.00919"
|
||||
id="tspan36738">DRAWING TITLE</tspan></text>
|
||||
<text
|
||||
id="text36744"
|
||||
y="275.05634"
|
||||
x="330.99438"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.96055px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.371;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="stroke-width:0.371;stroke-dasharray:none"
|
||||
y="275.05634"
|
||||
x="330.99438"
|
||||
id="tspan36742">{{Name}}</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 390.00031,246.86771 V 266.993"
|
||||
id="path36746" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.88677px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.169851;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="397.04108"
|
||||
y="249.72177"
|
||||
id="text36677"><tspan
|
||||
id="tspan36675"
|
||||
x="397.04108"
|
||||
y="249.72177"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.88677px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.169851;stroke-miterlimit:4;stroke-dasharray:none">GRID NORTH</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.88677px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.169851;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="338.77008"
|
||||
y="249.72177"
|
||||
id="text36752"><tspan
|
||||
id="tspan36750"
|
||||
x="335.76562"
|
||||
y="249.72177"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.88677px;line-height:100%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.169851;stroke-miterlimit:4;stroke-dasharray:none">COMPANY</tspan></text>
|
||||
<g
|
||||
id="g37148"
|
||||
transform="translate(399.87519,258.25776)">
|
||||
<g
|
||||
id="g37140"
|
||||
data-type="grid-north">
|
||||
<path
|
||||
id="path11652"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.25;stroke-linecap:round;stroke-dasharray:none"
|
||||
d="M 0,0 V 7.12566 Z" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.25;stroke-linecap:round;stroke-dasharray:none"
|
||||
d="M 7.3079,3e-5 H -7.30798"
|
||||
id="path36547" />
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:0.25;stroke-linecap:round;stroke-dasharray:none"
|
||||
id="path36601"
|
||||
cx="-3.8305665e-05"
|
||||
cy="4.15625e-05"
|
||||
r="5" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.25;stroke-linecap:round;stroke-dasharray:none"
|
||||
d="m -5.00004,4e-5 5,-5 5,5 H 3.94162 L -4e-5,-3.94162 -3.9417,4e-5 Z"
|
||||
id="path36671" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-dasharray:none"
|
||||
d="M -4e-5,-7.12545 V 3e-5"
|
||||
id="path36673" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
@@ -0,0 +1,214 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BlenderBIM Add-on 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
presets = {
|
||||
"Basic": ["project", "search", "bcf", "attribute", "spatial", "pset", "qto"],
|
||||
"Admin": [
|
||||
"project",
|
||||
"search",
|
||||
"bcf",
|
||||
"root",
|
||||
"unit",
|
||||
"model",
|
||||
"georeference",
|
||||
"context",
|
||||
"drawing",
|
||||
"misc",
|
||||
"attribute",
|
||||
"type",
|
||||
"spatial",
|
||||
"void",
|
||||
"aggregate",
|
||||
"geometry",
|
||||
"cobie",
|
||||
"resource",
|
||||
"cost",
|
||||
"sequence",
|
||||
"group",
|
||||
"system",
|
||||
"structural",
|
||||
"boundary",
|
||||
"profile",
|
||||
"material",
|
||||
"style",
|
||||
"layer",
|
||||
"owner",
|
||||
"pset",
|
||||
"qto",
|
||||
"classification",
|
||||
"constraint",
|
||||
"document",
|
||||
"pset_template",
|
||||
"clash",
|
||||
"lca",
|
||||
"csv",
|
||||
"bimtester",
|
||||
"diff",
|
||||
"patch",
|
||||
"covetool",
|
||||
"augin",
|
||||
"debug",
|
||||
],
|
||||
"BIM Coordination": [
|
||||
"project",
|
||||
"search",
|
||||
"bcf",
|
||||
"root",
|
||||
"unit",
|
||||
"georeference",
|
||||
"attribute",
|
||||
"type",
|
||||
"spatial",
|
||||
"void",
|
||||
"aggregate",
|
||||
"owner",
|
||||
"pset",
|
||||
"qto",
|
||||
"clash",
|
||||
"csv",
|
||||
"bimtester",
|
||||
"diff",
|
||||
"patch",
|
||||
"debug",
|
||||
],
|
||||
"Architecture": [
|
||||
"project",
|
||||
"search",
|
||||
"bcf",
|
||||
"root",
|
||||
"unit",
|
||||
"model",
|
||||
"georeference",
|
||||
"context",
|
||||
"drawing",
|
||||
"misc",
|
||||
"attribute",
|
||||
"type",
|
||||
"spatial",
|
||||
"void",
|
||||
"aggregate",
|
||||
"geometry",
|
||||
"group",
|
||||
"system",
|
||||
"boundary",
|
||||
"profile",
|
||||
"material",
|
||||
"style",
|
||||
"layer",
|
||||
"owner",
|
||||
"pset",
|
||||
"qto",
|
||||
"classification",
|
||||
"pset_template",
|
||||
"clash",
|
||||
"csv",
|
||||
],
|
||||
"Structural Engineering": [
|
||||
"project",
|
||||
"search",
|
||||
"bcf",
|
||||
"root",
|
||||
"unit",
|
||||
"model",
|
||||
"georeference",
|
||||
"context",
|
||||
"drawing",
|
||||
"misc",
|
||||
"attribute",
|
||||
"type",
|
||||
"spatial",
|
||||
"void",
|
||||
"aggregate",
|
||||
"geometry",
|
||||
"group",
|
||||
"system",
|
||||
"structural",
|
||||
"boundary",
|
||||
"profile",
|
||||
"material",
|
||||
"style",
|
||||
"layer",
|
||||
"owner",
|
||||
"pset",
|
||||
"qto",
|
||||
"classification",
|
||||
"pset_template",
|
||||
"clash",
|
||||
"csv",
|
||||
],
|
||||
"MEP": [
|
||||
"project",
|
||||
"search",
|
||||
"bcf",
|
||||
"root",
|
||||
"unit",
|
||||
"model",
|
||||
"georeference",
|
||||
"context",
|
||||
"drawing",
|
||||
"misc",
|
||||
"attribute",
|
||||
"type",
|
||||
"spatial",
|
||||
"void",
|
||||
"aggregate",
|
||||
"geometry",
|
||||
"group",
|
||||
"system",
|
||||
"boundary",
|
||||
"profile",
|
||||
"material",
|
||||
"style",
|
||||
"layer",
|
||||
"owner",
|
||||
"pset",
|
||||
"qto",
|
||||
"classification",
|
||||
"pset_template",
|
||||
"clash",
|
||||
"csv",
|
||||
],
|
||||
"Quantity Surveying": ["project", "search", "attribute", "spatial", "void", "pset", "qto", "classification", "csv"],
|
||||
"Model Enrichment": [
|
||||
"project",
|
||||
"search",
|
||||
"root",
|
||||
"attribute",
|
||||
"spatial",
|
||||
"pset",
|
||||
"qto",
|
||||
"pset_template",
|
||||
"csv",
|
||||
"patch",
|
||||
],
|
||||
"3D Visualisation": ["project", "search", "bcf", "attribute", "spatial", "pset", "qto"],
|
||||
"4D Scheduling": ["project", "search", "attribute", "spatial", "resource", "cost", "sequence", "pset", "qto"],
|
||||
"5D Cost Management": [
|
||||
"project",
|
||||
"search",
|
||||
"attribute",
|
||||
"spatial",
|
||||
"resource",
|
||||
"cost",
|
||||
"sequence",
|
||||
"pset",
|
||||
"qto",
|
||||
"lca",
|
||||
],
|
||||
"Facility Management": ["project", "search", "attribute", "spatial", "cobie", "pset", "qto", "lca"],
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
Name,foo
|
||||
TransomThickness,500
|
||||
|
@@ -44,8 +44,10 @@ class IfcExporter:
|
||||
self.file = IfcStore.get_file()
|
||||
self.set_header()
|
||||
IfcStore.update_cache()
|
||||
self.sync_all_objects()
|
||||
self.sync_edited_objects()
|
||||
if bpy.context.scene.BIMProjectProperties.is_authoring:
|
||||
self.sync_deletions()
|
||||
self.sync_all_objects()
|
||||
self.sync_edited_objects()
|
||||
extension = self.ifc_export_settings.output_file.split(".")[-1].lower()
|
||||
if extension == "ifczip":
|
||||
with tempfile.TemporaryDirectory() as unzipped_path:
|
||||
@@ -85,6 +87,19 @@ class IfcExporter:
|
||||
self.get_application_name(), self.get_application_version()
|
||||
)
|
||||
|
||||
def sync_deletions(self):
|
||||
results = []
|
||||
for ifc_definition_id in IfcStore.deleted_ids:
|
||||
try:
|
||||
product = self.file.by_id(ifc_definition_id)
|
||||
if hasattr(product, "GlobalId"):
|
||||
results.append(product.GlobalId)
|
||||
except:
|
||||
continue
|
||||
ifcopenshell.api.run("root.remove_product", self.file, **{"product": product})
|
||||
IfcStore.deleted_ids.clear()
|
||||
return results
|
||||
|
||||
def sync_all_objects(self):
|
||||
results = []
|
||||
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
|
||||
@@ -111,8 +126,7 @@ class IfcExporter:
|
||||
continue
|
||||
try:
|
||||
if isinstance(obj, bpy.types.Material):
|
||||
if tool.Ifc.has_changed_shading(obj):
|
||||
blenderbim.core.style.update_style_colours(tool.Ifc, tool.Style, obj=obj)
|
||||
blenderbim.core.style.update_style_colours(tool.Ifc, tool.Style, obj=obj)
|
||||
else:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if element:
|
||||
@@ -135,10 +149,10 @@ class IfcExporter:
|
||||
return checksum != str([s.id() for s in tool.Geometry.get_styles(obj) if s])
|
||||
|
||||
def sync_object_placement(self, obj):
|
||||
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
if not tool.Ifc.is_moved(obj):
|
||||
return
|
||||
blender_matrix = np.array(obj.matrix_world)
|
||||
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
if (obj.scale - Vector((1.0, 1.0, 1.0))).length > 1e-4:
|
||||
bpy.ops.bim.update_representation(obj=obj.name)
|
||||
return element
|
||||
|
||||
@@ -16,26 +16,27 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import bpy
|
||||
import json
|
||||
import addon_utils
|
||||
import ifcopenshell.api.owner.settings
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.core.owner as core_owner
|
||||
from blenderbim.bim.module.drawing.prop import RasterStyleProperty
|
||||
from bpy.app.handlers import persistent
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.owner.prop import get_user_person, get_user_organisation
|
||||
from blenderbim.bim.module.model.data import AuthoringData
|
||||
from mathutils import Vector
|
||||
from math import cos, degrees
|
||||
from ifcopenshell.api.material.data import Data as MaterialData
|
||||
from ifcopenshell.api.type.data import Data as TypeData
|
||||
|
||||
|
||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||
global_subscription_owner = object()
|
||||
|
||||
|
||||
def mode_callback(obj, data):
|
||||
if not bpy.context.scene.BIMProjectProperties.is_authoring:
|
||||
return
|
||||
objects = bpy.context.selected_objects
|
||||
if bpy.context.active_object:
|
||||
objects += [bpy.context.active_object]
|
||||
@@ -48,18 +49,16 @@ def mode_callback(obj, data):
|
||||
):
|
||||
continue
|
||||
if obj.data.BIMMeshProperties.ifc_definition_id:
|
||||
tool.Ifc.edit(obj)
|
||||
IfcStore.edited_objs.add(obj)
|
||||
elif IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id).is_a("IfcGridAxis"):
|
||||
tool.Ifc.edit(obj)
|
||||
IfcStore.edited_objs.add(obj)
|
||||
|
||||
|
||||
def name_callback(obj, data):
|
||||
# TODO Do we still need this, now that we are monitoring the undo redo objects?
|
||||
try:
|
||||
obj.name
|
||||
except:
|
||||
# The object is invalid but somehow still has a callback. Clear all
|
||||
# msgbus subscriptions to prevent useless further triggers.
|
||||
bpy.msgbus.clear_by_owner(obj)
|
||||
return # In case the object RNA is gone during an undo / redo operation
|
||||
# Blender names are up to 63 UTF-8 bytes
|
||||
if len(bytes(obj.name, "utf-8")) >= 63:
|
||||
@@ -68,6 +67,7 @@ def name_callback(obj, data):
|
||||
if isinstance(obj, bpy.types.Material):
|
||||
if obj.BIMObjectProperties.ifc_definition_id:
|
||||
IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id).Name = obj.name
|
||||
MaterialData.load_materials()
|
||||
if obj.BIMMaterialProperties.ifc_style_id:
|
||||
IfcStore.get_file().by_id(obj.BIMMaterialProperties.ifc_style_id).Name = obj.name
|
||||
refresh_ui_data()
|
||||
@@ -76,87 +76,46 @@ def name_callback(obj, data):
|
||||
if not obj.BIMObjectProperties.ifc_definition_id or "/" not in obj.name:
|
||||
return
|
||||
element = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
if element.is_a("IfcGridAxis"):
|
||||
element.AxisTag = obj.name.split("/")[1]
|
||||
refresh_ui_data()
|
||||
if not element.is_a("IfcRoot"):
|
||||
return
|
||||
if obj.BIMObjectProperties.collection:
|
||||
obj.BIMObjectProperties.collection.name = obj.name
|
||||
if element.is_a("IfcSpatialStructureElement") or (hasattr(element, "IsDecomposedBy") and element.IsDecomposedBy):
|
||||
collection = obj.users_collection[0]
|
||||
collection.name = obj.name
|
||||
if element.is_a("IfcGrid"):
|
||||
axis_obj = IfcStore.get_element(element.UAxes[0].id())
|
||||
axis_collection = axis_obj.users_collection[0]
|
||||
grid_collection = None
|
||||
for collection in bpy.data.collections:
|
||||
if axis_collection.name in collection.children.keys():
|
||||
grid_collection = collection
|
||||
break
|
||||
if grid_collection:
|
||||
grid_collection.name = obj.name
|
||||
if element.is_a("IfcTypeProduct"):
|
||||
TypeData.purge()
|
||||
element.Name = "/".join(obj.name.split("/")[1:])
|
||||
refresh_ui_data()
|
||||
|
||||
|
||||
def color_callback(obj, data):
|
||||
if obj.BIMMaterialProperties.ifc_style_id:
|
||||
tool.Ifc.edit(obj)
|
||||
IfcStore.edited_objs.add(obj)
|
||||
|
||||
|
||||
def active_object_callback():
|
||||
refresh_ui_data()
|
||||
update_bim_tool_props()
|
||||
|
||||
|
||||
def update_bim_tool_props():
|
||||
"""update BIM Tools props (such as extrusion_depth, length and x_angle) when active object changes"""
|
||||
obj = bpy.context.active_object
|
||||
|
||||
# bunch of checks to see if we're in a valid state
|
||||
if not obj:
|
||||
return
|
||||
mode = bpy.context.mode
|
||||
current_tool = bpy.context.workspace.tools.from_space_view3d_mode(mode)
|
||||
if not current_tool or current_tool.idname != "bim.bim_tool":
|
||||
return
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element:
|
||||
return
|
||||
representation = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW")
|
||||
if not representation:
|
||||
return
|
||||
extrusion = tool.Model.get_extrusion(representation)
|
||||
if not extrusion:
|
||||
return
|
||||
|
||||
def get_x_angle(extrusion):
|
||||
x, y, z = extrusion.ExtrudedDirection.DirectionRatios
|
||||
x_angle = Vector((0, 1)).angle_signed(Vector((y, z)))
|
||||
return x_angle
|
||||
|
||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
props = bpy.context.scene.BIMModelProperties
|
||||
if not AuthoringData.is_loaded:
|
||||
AuthoringData.load()
|
||||
|
||||
if AuthoringData.data["active_material_usage"] == "LAYER2":
|
||||
x_angle = get_x_angle(extrusion)
|
||||
axis = tool.Model.get_wall_axis(obj)["reference"]
|
||||
props.extrusion_depth = extrusion.Depth * si_conversion * cos(x_angle)
|
||||
props.length = (axis[1] - axis[0]).length
|
||||
props.x_angle = x_angle
|
||||
|
||||
elif AuthoringData.data["active_material_usage"] == "LAYER3":
|
||||
x_angle = get_x_angle(extrusion)
|
||||
props.x_angle = x_angle
|
||||
|
||||
elif AuthoringData.data["active_material_usage"] == "PROFILE":
|
||||
props.extrusion_depth = extrusion.Depth * si_conversion
|
||||
|
||||
|
||||
def active_material_index_callback(obj, data):
|
||||
refresh_ui_data()
|
||||
|
||||
|
||||
def subscribe_to(obj, data_path, callback):
|
||||
def subscribe_to(object, data_path, callback):
|
||||
try:
|
||||
subscribe_to = obj.path_resolve(data_path, False)
|
||||
subscribe_to = object.path_resolve(data_path, False)
|
||||
except:
|
||||
return
|
||||
bpy.msgbus.subscribe_rna(
|
||||
key=subscribe_to,
|
||||
owner=obj,
|
||||
owner=object,
|
||||
args=(
|
||||
obj,
|
||||
object,
|
||||
data_path,
|
||||
),
|
||||
notify=callback,
|
||||
@@ -175,9 +134,6 @@ def refresh_ui_data():
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
if isinstance(tool.Ifc.get(), ifcopenshell.sqlite):
|
||||
tool.Ifc.get().clear_cache()
|
||||
|
||||
|
||||
def purge_module_data():
|
||||
from blenderbim.bim import modules
|
||||
@@ -205,22 +161,40 @@ def loadIfcStore(scene):
|
||||
IfcStore.relink_all_objects()
|
||||
|
||||
|
||||
@persistent
|
||||
def undo_pre(scene):
|
||||
IfcStore.track_undo_redo_stack_object_map()
|
||||
|
||||
|
||||
@persistent
|
||||
def undo_post(scene):
|
||||
if IfcStore.last_transaction != bpy.context.scene.BIMProperties.last_transaction:
|
||||
IfcStore.last_transaction = bpy.context.scene.BIMProperties.last_transaction
|
||||
IfcStore.undo(until_key=bpy.context.scene.BIMProperties.last_transaction)
|
||||
IfcStore.undo()
|
||||
purge_module_data()
|
||||
tool.Ifc.rebuild_element_maps()
|
||||
IfcStore.track_undo_redo_stack_selected_objects()
|
||||
IfcStore.reload_undo_redo_stack_objects()
|
||||
|
||||
|
||||
@persistent
|
||||
def redo_pre(scene):
|
||||
IfcStore.track_undo_redo_stack_object_map()
|
||||
|
||||
|
||||
@persistent
|
||||
def redo_post(scene):
|
||||
if IfcStore.last_transaction != bpy.context.scene.BIMProperties.last_transaction:
|
||||
IfcStore.last_transaction = bpy.context.scene.BIMProperties.last_transaction
|
||||
IfcStore.redo(until_key=bpy.context.scene.BIMProperties.last_transaction)
|
||||
IfcStore.redo()
|
||||
purge_module_data()
|
||||
tool.Ifc.rebuild_element_maps()
|
||||
IfcStore.track_undo_redo_stack_selected_objects()
|
||||
IfcStore.reload_undo_redo_stack_objects()
|
||||
|
||||
|
||||
@persistent
|
||||
def ensureIfcExported(scene):
|
||||
if IfcStore.get_file() and not bpy.context.scene.BIMProperties.ifc_file:
|
||||
bpy.ops.export_ifc.bim("INVOKE_DEFAULT")
|
||||
|
||||
|
||||
def get_application(ifc):
|
||||
@@ -251,137 +225,81 @@ def get_application_version():
|
||||
)
|
||||
|
||||
|
||||
def viewport_shading_changed_callback(area):
|
||||
shading = area.spaces.active.shading.type
|
||||
if shading == "RENDERED":
|
||||
bpy.context.scene.BIMStylesProperties.active_style_type = "External"
|
||||
|
||||
|
||||
if getattr(bpy.types, "SCENE_PT_scene"):
|
||||
|
||||
class Override_SCENE_PT_scene(bpy.types.SCENE_PT_scene):
|
||||
bl_idname = "SCENE_PT_scene_override"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "BLENDER")
|
||||
|
||||
|
||||
if getattr(bpy.types, "SCENE_PT_unit"):
|
||||
|
||||
class Override_SCENE_PT_unit(bpy.types.SCENE_PT_unit):
|
||||
bl_idname = "SCENE_PT_unit_override"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "BLENDER")
|
||||
|
||||
|
||||
if getattr(bpy.types, "SCENE_PT_physics"):
|
||||
|
||||
class Override_SCENE_PT_physics(bpy.types.SCENE_PT_physics):
|
||||
bl_idname = "SCENE_PT_physics_override"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "BLENDER")
|
||||
|
||||
|
||||
if getattr(bpy.types, "SCENE_PT_rigid_body_world"):
|
||||
|
||||
class Override_SCENE_PT_rigid_body_world(bpy.types.SCENE_PT_rigid_body_world):
|
||||
bl_idname = "SCENE_PT_rigid_body_world_override"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "BLENDER")
|
||||
|
||||
|
||||
if getattr(bpy.types, "SCENE_PT_audio"):
|
||||
|
||||
class Override_SCENE_PT_audio(bpy.types.SCENE_PT_audio):
|
||||
bl_idname = "SCENE_PT_audio_override"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "BLENDER")
|
||||
|
||||
|
||||
if getattr(bpy.types, "SCENE_PT_keying_sets"):
|
||||
|
||||
class Override_SCENE_PT_keying_sets(bpy.types.SCENE_PT_keying_sets):
|
||||
bl_idname = "SCENE_PT_keying_sets_override"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "BLENDER")
|
||||
|
||||
|
||||
if getattr(bpy.types, "SCENE_PT_custom_props"):
|
||||
|
||||
class Override_SCENE_PT_custom_props(bpy.types.SCENE_PT_custom_props):
|
||||
bl_idname = "SCENE_PT_custom_props_override"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "BLENDER")
|
||||
|
||||
|
||||
@persistent
|
||||
def load_post(scene):
|
||||
def setDefaultProperties(scene):
|
||||
global global_subscription_owner
|
||||
active_object_key = bpy.types.LayerObjects, "active"
|
||||
bpy.msgbus.subscribe_rna(
|
||||
key=active_object_key, owner=global_subscription_owner, args=(), notify=active_object_callback
|
||||
)
|
||||
|
||||
# subscribe to changes in viewport shading mode
|
||||
# NOTE: couldn't find a way to make it work for new areas too
|
||||
# it starts working for them after blender restart though
|
||||
for screen in bpy.data.screens:
|
||||
for area in screen.areas:
|
||||
if area.type != "VIEW_3D":
|
||||
continue
|
||||
shading = area.spaces.active.shading
|
||||
key = shading.path_resolve("type", False)
|
||||
|
||||
bpy.msgbus.subscribe_rna(
|
||||
key=key, owner=global_subscription_owner, args=(area,), notify=viewport_shading_changed_callback
|
||||
)
|
||||
|
||||
ifcopenshell.api.owner.settings.get_user = lambda ifc: core_owner.get_user(tool.Owner)
|
||||
ifcopenshell.api.owner.settings.get_application = get_application
|
||||
AuthoringData.type_thumbnails = {}
|
||||
|
||||
if bpy.context.preferences.addons["blenderbim"].preferences.should_setup_workspace:
|
||||
if "BIM" in bpy.data.workspaces:
|
||||
bpy.context.window.workspace = bpy.data.workspaces["BIM"]
|
||||
else:
|
||||
bpy.ops.workspace.append_activate(idname="BIM", filepath=os.path.join(cwd, "data", "workspace.blend"))
|
||||
|
||||
# To improve usability for new users, we hijack the scene properties
|
||||
# tab. We override default scene properties panels with our own poll
|
||||
# to hide them unless the user has chosen to view Blender properties.
|
||||
for panel in [
|
||||
"SCENE_PT_scene",
|
||||
"SCENE_PT_unit",
|
||||
"SCENE_PT_physics",
|
||||
"SCENE_PT_rigid_body_world",
|
||||
"SCENE_PT_audio",
|
||||
"SCENE_PT_keying_sets",
|
||||
"SCENE_PT_custom_props",
|
||||
]:
|
||||
if getattr(bpy.types, panel, None):
|
||||
try:
|
||||
bpy.utils.register_class(globals()[f"Override_{panel}"])
|
||||
bpy.utils.unregister_class(getattr(bpy.types, panel))
|
||||
except:
|
||||
pass
|
||||
|
||||
# https://blender.stackexchange.com/questions/140644/how-can-make-the-state-of-a-boolean-property-relative-to-the-3d-view-area
|
||||
for screen in bpy.data.screens:
|
||||
if len(screen.BIMAreaProperties) == 20:
|
||||
continue
|
||||
screen.BIMAreaProperties.clear()
|
||||
for i in range(20): # 20 is an arbitrary value of split areas
|
||||
screen.BIMAreaProperties.add()
|
||||
# TODO: Move to drawing module
|
||||
if len(bpy.context.scene.DocProperties.drawing_styles) == 0:
|
||||
drawing_style = bpy.context.scene.DocProperties.drawing_styles.add()
|
||||
drawing_style.name = "Technical"
|
||||
drawing_style.render_type = "VIEWPORT"
|
||||
drawing_style.raster_style = json.dumps(
|
||||
{
|
||||
RasterStyleProperty.WORLD_COLOR.value: (1, 1, 1),
|
||||
RasterStyleProperty.RENDER_ENGINE.value: "BLENDER_WORKBENCH",
|
||||
RasterStyleProperty.RENDER_TRANSPARENT.value: False,
|
||||
RasterStyleProperty.SHADING_SHOW_OBJECT_OUTLINE.value: True,
|
||||
RasterStyleProperty.SHADING_SHOW_CAVITY.value: False,
|
||||
RasterStyleProperty.SHADING_CAVITY_TYPE.value: "BOTH",
|
||||
RasterStyleProperty.SHADING_CURVATURE_RIDGE_FACTOR.value: 1,
|
||||
RasterStyleProperty.SHADING_CURVATURE_VALLEY_FACTOR.value: 1,
|
||||
RasterStyleProperty.VIEW_TRANSFORM.value: "Standard",
|
||||
RasterStyleProperty.SHADING_LIGHT.value: "FLAT",
|
||||
RasterStyleProperty.SHADING_COLOR_TYPE.value: "SINGLE",
|
||||
RasterStyleProperty.SHADING_SINGLE_COLOR.value: (1, 1, 1),
|
||||
RasterStyleProperty.SHADING_SHOW_SHADOWS.value: False,
|
||||
RasterStyleProperty.SHADING_SHADOW_INTENSITY.value: 0.5,
|
||||
RasterStyleProperty.DISPLAY_LIGHT_DIRECTION.value: (0.5, 0.5, 0.5),
|
||||
RasterStyleProperty.VIEW_USE_CURVE_MAPPING.value: False,
|
||||
RasterStyleProperty.OVERLAY_SHOW_WIREFRAMES.value: True,
|
||||
RasterStyleProperty.OVERLAY_WIREFRAME_THRESHOLD.value: 0,
|
||||
RasterStyleProperty.OVERLAY_SHOW_FLOOR.value: False,
|
||||
RasterStyleProperty.OVERLAY_SHOW_AXIS_X.value: False,
|
||||
RasterStyleProperty.OVERLAY_SHOW_AXIS_Y.value: False,
|
||||
RasterStyleProperty.OVERLAY_SHOW_AXIS_Z.value: False,
|
||||
RasterStyleProperty.OVERLAY_SHOW_OBJECT_ORIGINS.value: False,
|
||||
RasterStyleProperty.OVERLAY_SHOW_RELATIONSHIP_LINES.value: False,
|
||||
}
|
||||
)
|
||||
drawing_style = bpy.context.scene.DocProperties.drawing_styles.add()
|
||||
drawing_style.name = "Shaded"
|
||||
drawing_style.render_type = "VIEWPORT"
|
||||
drawing_style.raster_style = json.dumps(
|
||||
{
|
||||
RasterStyleProperty.WORLD_COLOR.value: (1, 1, 1),
|
||||
RasterStyleProperty.RENDER_ENGINE.value: "BLENDER_WORKBENCH",
|
||||
RasterStyleProperty.RENDER_TRANSPARENT.value: False,
|
||||
RasterStyleProperty.SHADING_SHOW_OBJECT_OUTLINE.value: True,
|
||||
RasterStyleProperty.SHADING_SHOW_CAVITY.value: True,
|
||||
RasterStyleProperty.SHADING_CAVITY_TYPE.value: "BOTH",
|
||||
RasterStyleProperty.SHADING_CURVATURE_RIDGE_FACTOR.value: 1,
|
||||
RasterStyleProperty.SHADING_CURVATURE_VALLEY_FACTOR.value: 1,
|
||||
RasterStyleProperty.VIEW_TRANSFORM.value: "Standard",
|
||||
RasterStyleProperty.SHADING_LIGHT.value: "STUDIO",
|
||||
RasterStyleProperty.SHADING_COLOR_TYPE.value: "MATERIAL",
|
||||
RasterStyleProperty.SHADING_SINGLE_COLOR.value: (1, 1, 1),
|
||||
RasterStyleProperty.SHADING_SHOW_SHADOWS.value: True,
|
||||
RasterStyleProperty.SHADING_SHADOW_INTENSITY.value: 0.5,
|
||||
RasterStyleProperty.DISPLAY_LIGHT_DIRECTION.value: (0.5, 0.5, 0.5),
|
||||
RasterStyleProperty.VIEW_USE_CURVE_MAPPING.value: False,
|
||||
RasterStyleProperty.OVERLAY_SHOW_WIREFRAMES.value: False,
|
||||
RasterStyleProperty.OVERLAY_WIREFRAME_THRESHOLD.value: 0,
|
||||
RasterStyleProperty.OVERLAY_SHOW_FLOOR.value: False,
|
||||
RasterStyleProperty.OVERLAY_SHOW_AXIS_X.value: False,
|
||||
RasterStyleProperty.OVERLAY_SHOW_AXIS_Y.value: False,
|
||||
RasterStyleProperty.OVERLAY_SHOW_AXIS_Z.value: False,
|
||||
RasterStyleProperty.OVERLAY_SHOW_OBJECT_ORIGINS.value: False,
|
||||
RasterStyleProperty.OVERLAY_SHOW_RELATIONSHIP_LINES.value: False,
|
||||
}
|
||||
)
|
||||
drawing_style = bpy.context.scene.DocProperties.drawing_styles.add()
|
||||
drawing_style.name = "Blender Default"
|
||||
drawing_style.render_type = "DEFAULT"
|
||||
bpy.ops.bim.save_drawing_style(index="2")
|
||||
AuthoringData.type_thumbnails = {}
|
||||
|
||||
@@ -23,7 +23,6 @@ import math
|
||||
import zipfile
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.attribute
|
||||
import ifcopenshell.util.element
|
||||
from ifcopenshell.util.doc import get_attribute_doc, get_predefined_type_doc, get_property_doc
|
||||
from mathutils import geometry
|
||||
from mathutils import Vector
|
||||
@@ -31,15 +30,9 @@ import blenderbim.tool as tool
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
def draw_attributes(props, layout, copy_operator=None, popup_active_attribute=None):
|
||||
"""you can set attribute active in popup with `active_attribute`
|
||||
meaning you will be able to type into attribute's field without having to click
|
||||
on it first
|
||||
"""
|
||||
def draw_attributes(props, layout, copy_operator=None):
|
||||
for attribute in props:
|
||||
row = layout.row(align=True)
|
||||
if attribute == popup_active_attribute:
|
||||
row.activate_init = True
|
||||
draw_attribute(attribute, row, copy_operator)
|
||||
|
||||
|
||||
@@ -70,14 +63,14 @@ def draw_attribute(attribute, layout, copy_operator=None):
|
||||
text=attribute.name,
|
||||
)
|
||||
|
||||
if attribute.is_uri:
|
||||
op = layout.operator("bim.select_uri_attribute", text="", icon="FILE_FOLDER")
|
||||
op.data_path = attribute.path_from_id("string_value")
|
||||
if attribute.is_optional:
|
||||
layout.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
|
||||
if copy_operator:
|
||||
op = layout.operator(f"{copy_operator}", text="", icon="COPYDOWN")
|
||||
op.name = attribute.name
|
||||
if attribute.is_uri:
|
||||
op = layout.operator("bim.select_uri_attribute", text="", icon="FILE_FOLDER")
|
||||
op.data_path = attribute.path_from_id("string_value")
|
||||
|
||||
|
||||
def import_attributes(ifc_class, props, data, callback=None):
|
||||
@@ -214,12 +207,6 @@ def get_obj_ifc_definition_id(context, obj, obj_type):
|
||||
return bpy.data.objects.get(obj).BIMObjectProperties.ifc_definition_id
|
||||
elif obj_type == "Material":
|
||||
return bpy.data.materials.get(obj).BIMObjectProperties.ifc_definition_id
|
||||
elif obj_type == "MaterialSet":
|
||||
return ifcopenshell.util.element.get_material(
|
||||
tool.Ifc.get_entity(bpy.data.objects.get(obj)), should_skip_usage=True
|
||||
).id()
|
||||
elif obj_type == "MaterialSetItem":
|
||||
return bpy.data.objects.get(obj).BIMObjectMaterialProperties.active_material_set_item_id
|
||||
elif obj_type == "Task":
|
||||
return context.scene.BIMTaskTreeProperties.tasks[
|
||||
context.scene.BIMWorkScheduleProperties.active_task_index
|
||||
@@ -249,33 +236,6 @@ def close_operator_panel(event):
|
||||
bpy.app.timers.register(move_back, first_interval=0.01)
|
||||
|
||||
|
||||
def convert_property_group_from_si(property_group, skip_props=()):
|
||||
"""Method converts property group values from si to current ifc project units
|
||||
|
||||
based on default values of the properties.
|
||||
|
||||
List of properties to skip can be supplied in `skip_props`."""
|
||||
conversion_k = 1.0 / ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
skip_props = ("rna_type", "name") + skip_props
|
||||
for prop_name in property_group.bl_rna.properties.keys():
|
||||
if prop_name in skip_props:
|
||||
continue
|
||||
prop_bl_rna = property_group.bl_rna.properties[prop_name]
|
||||
if prop_bl_rna.array_length > 0:
|
||||
prop_value = prop_bl_rna.default_array
|
||||
else:
|
||||
prop_value = prop_bl_rna.default
|
||||
|
||||
if type(prop_value) is float:
|
||||
prop_value = prop_value * conversion_k
|
||||
elif type(prop_value) is bpy.types.bpy_prop_array:
|
||||
prop_value = [el * conversion_k for el in prop_value]
|
||||
setattr(property_group, prop_name, prop_value)
|
||||
|
||||
|
||||
# TODO this should move into ifcopenshell.util
|
||||
|
||||
|
||||
class IfcHeaderExtractor:
|
||||
def __init__(self, filepath: str):
|
||||
self.filepath = filepath
|
||||
@@ -287,8 +247,6 @@ class IfcHeaderExtractor:
|
||||
return self.extract_ifc_spf(ifc_file)
|
||||
elif extension.lower() == "ifczip":
|
||||
return self.extract_ifc_zip()
|
||||
elif extension.lower() == "ifcsqlite":
|
||||
return {} # TODO
|
||||
|
||||
def extract_ifc_spf(self, ifc_file):
|
||||
# https://www.steptools.com/stds/step/IS_final_p21e3.html#clause-8
|
||||
|
||||
@@ -24,9 +24,7 @@ import zipfile
|
||||
import tempfile
|
||||
import ifcopenshell
|
||||
import blenderbim.bim.handler
|
||||
import blenderbim.tool as tool
|
||||
from pathlib import Path
|
||||
from blenderbim.tool.brick import BrickStore
|
||||
|
||||
|
||||
class IfcStore:
|
||||
@@ -37,6 +35,7 @@ class IfcStore:
|
||||
cache_path = None
|
||||
id_map = {}
|
||||
guid_map = {}
|
||||
deleted_ids = set()
|
||||
edited_objs = set()
|
||||
pset_template_path = ""
|
||||
pset_template_file = None
|
||||
@@ -44,12 +43,14 @@ class IfcStore:
|
||||
classification_file = None
|
||||
library_path = ""
|
||||
library_file = None
|
||||
element_listeners = set()
|
||||
undo_redo_stack_objects = set()
|
||||
undo_redo_stack_object_names = {}
|
||||
current_transaction = ""
|
||||
last_transaction = ""
|
||||
history = []
|
||||
future = []
|
||||
schema_identifiers = ["IFC4", "IFC2X3", "IFC4X3"]
|
||||
session_files = {}
|
||||
|
||||
@staticmethod
|
||||
def purge():
|
||||
@@ -60,6 +61,7 @@ class IfcStore:
|
||||
IfcStore.cache_path = None
|
||||
IfcStore.id_map = {}
|
||||
IfcStore.guid_map = {}
|
||||
IfcStore.deleted_ids = set()
|
||||
IfcStore.edited_objs = set()
|
||||
IfcStore.pset_template_path = ""
|
||||
IfcStore.pset_template_file = None
|
||||
@@ -69,7 +71,6 @@ class IfcStore:
|
||||
IfcStore.history = []
|
||||
IfcStore.future = []
|
||||
IfcStore.schema_identifiers = ["IFC4", "IFC2X3", "IFC4X3"]
|
||||
IfcStore.session_files = {}
|
||||
|
||||
@staticmethod
|
||||
def get_file():
|
||||
@@ -95,14 +96,7 @@ class IfcStore:
|
||||
try:
|
||||
IfcStore.cache = ifcopenshell.geom.serializers.hdf5(IfcStore.cache_path, cache_settings)
|
||||
except:
|
||||
if os.path.exists(IfcStore.cache_path):
|
||||
os.remove(IfcStore.cache_path)
|
||||
try:
|
||||
IfcStore.cache = ifcopenshell.geom.serializers.hdf5(IfcStore.cache_path, cache_settings)
|
||||
except:
|
||||
return
|
||||
else:
|
||||
return
|
||||
return
|
||||
return IfcStore.cache
|
||||
|
||||
@staticmethod
|
||||
@@ -118,8 +112,6 @@ class IfcStore:
|
||||
|
||||
@staticmethod
|
||||
def load_file(path):
|
||||
if not os.path.isfile(path):
|
||||
return
|
||||
extension = path.split(".")[-1]
|
||||
if extension.lower() == "ifczip":
|
||||
with tempfile.TemporaryDirectory() as unzipped_path:
|
||||
@@ -130,9 +122,7 @@ class IfcStore:
|
||||
return
|
||||
elif extension.lower() == "ifcxml":
|
||||
IfcStore.file = ifcopenshell.file(ifcopenshell.ifcopenshell_wrapper.parse_ifcxml(path))
|
||||
elif bpy.context.scene.BIMProjectProperties.should_stream:
|
||||
IfcStore.file = ifcopenshell.open(path, should_stream=True)
|
||||
else:
|
||||
elif extension.lower() == "ifc":
|
||||
IfcStore.file = ifcopenshell.open(path)
|
||||
|
||||
@staticmethod
|
||||
@@ -158,6 +148,96 @@ class IfcStore:
|
||||
return
|
||||
return obj
|
||||
|
||||
@staticmethod
|
||||
def add_element_listener(callback):
|
||||
IfcStore.element_listeners.add(callback)
|
||||
|
||||
@staticmethod
|
||||
def track_undo_redo_stack_object_map():
|
||||
"""Keeps track of currently mapped object names, typically during undo and redo
|
||||
|
||||
When any Blender object is stored outside a Blender PointerProperty, such as
|
||||
in a regular Python list, there is the likely probability that the object
|
||||
will be invalidated when undo or redo occurs. Object invalidation seems to
|
||||
occur whenever an object is affected during an operation.
|
||||
|
||||
For example, if an operator deletes a modifier on o1, then o1 will be invalidated.
|
||||
"""
|
||||
for key, value in IfcStore.id_map.items():
|
||||
try:
|
||||
IfcStore.undo_redo_stack_object_names[key] = value.name
|
||||
except:
|
||||
continue
|
||||
|
||||
@staticmethod
|
||||
def track_undo_redo_stack_selected_objects():
|
||||
"""Keeps track of selected object names, typically during undo and redo
|
||||
|
||||
When any Blender object is stored outside a Blender PointerProperty, such as
|
||||
in a regular Python list, there is the likely probability that the object
|
||||
will be invalidated when undo or redo occurs. Object invalidation seems to
|
||||
occur for selected objects either pre/post undo/redo event, including
|
||||
selected objects for consecutive undo/redos, and all children. This is
|
||||
important because selected objects are often deleted from the scene.
|
||||
|
||||
So if I first select o1, then o2, then o3, then press undo, o3 will be
|
||||
invalidated. If instead I press undo twice, o3 and o2 will be invalidated.
|
||||
"""
|
||||
if bpy.context.active_object:
|
||||
objects = set([o.name for o in bpy.context.selected_objects + [bpy.context.active_object]])
|
||||
objects.update([o.name for o in bpy.context.active_object.children])
|
||||
else:
|
||||
objects = set([o.name for o in bpy.context.selected_objects])
|
||||
for obj in bpy.context.selected_objects:
|
||||
objects.update([o.name for o in obj.children])
|
||||
IfcStore.undo_redo_stack_objects |= objects
|
||||
|
||||
@staticmethod
|
||||
def reload_undo_redo_stack_objects():
|
||||
"""Reloads any invalidated objects after undo or redo
|
||||
|
||||
After an undo or redo operation, objects may have been invalidated in
|
||||
our id_map and guid_map. Invalidated objects are typically those that
|
||||
have been manipulated or deleted. This checks the cache of mapped and
|
||||
selected objects prior to the operation and ensures that if the object
|
||||
is invalidated, they are reloaded based on the object name that was
|
||||
tracked prior to the undo / redo.
|
||||
"""
|
||||
file = IfcStore.get_file()
|
||||
if not file:
|
||||
return
|
||||
|
||||
# First, reload objects that were selected or active
|
||||
for name in IfcStore.undo_redo_stack_objects:
|
||||
obj = bpy.data.objects.get(name)
|
||||
if not obj:
|
||||
continue
|
||||
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||
continue
|
||||
element = file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
data = {"id": element.id(), "obj": obj.name}
|
||||
if hasattr(element, "GlobalId"):
|
||||
data["guid"] = element.GlobalId
|
||||
IfcStore.commit_link_element(data)
|
||||
|
||||
# Scan for any straggling invalidated objects which were indirectly affected and reload them too.
|
||||
for key, value in IfcStore.id_map.items():
|
||||
try:
|
||||
value.name
|
||||
except:
|
||||
# TODO not so sure about this obj_name check
|
||||
obj_name = IfcStore.undo_redo_stack_object_names.get(key, None)
|
||||
if not obj_name:
|
||||
continue
|
||||
obj = bpy.data.objects.get(obj_name)
|
||||
if not obj or not obj.BIMObjectProperties.ifc_definition_id:
|
||||
continue
|
||||
element = file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
data = {"id": element.id(), "obj": obj.name}
|
||||
if hasattr(element, "GlobalId"):
|
||||
data["guid"] = element.GlobalId
|
||||
IfcStore.commit_link_element(data)
|
||||
|
||||
@staticmethod
|
||||
def relink_all_objects():
|
||||
if not IfcStore.get_file():
|
||||
@@ -189,14 +269,24 @@ class IfcStore:
|
||||
IfcStore.commit_link_element(data)
|
||||
|
||||
@staticmethod
|
||||
def link_element(element, obj):
|
||||
# Please use tool.Ifc.link() instead of this method. We want to
|
||||
# refactor this class and deprecate usage of IfcStore in favour of
|
||||
# tools.
|
||||
if not isinstance(obj, (bpy.types.Object, bpy.types.Material)):
|
||||
obj.BIMMeshProperties.ifc_definition_id = element.id()
|
||||
return
|
||||
def delete_element(element):
|
||||
IfcStore.deleted_ids.add(element.id())
|
||||
if IfcStore.history:
|
||||
data = {"id": element.id()}
|
||||
IfcStore.history[-1]["operations"].append(
|
||||
{"rollback": IfcStore.rollback_delete_element, "commit": IfcStore.commit_delete_element, "data": data}
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def rollback_delete_element(data):
|
||||
IfcStore.deleted_ids.remove(data["id"])
|
||||
|
||||
@staticmethod
|
||||
def commit_delete_element(data):
|
||||
IfcStore.deleted_ids.add(data["id"])
|
||||
|
||||
@staticmethod
|
||||
def link_element(element, obj):
|
||||
existing_obj = IfcStore.id_map.get(element.id(), None)
|
||||
if existing_obj == obj:
|
||||
return
|
||||
@@ -221,7 +311,9 @@ class IfcStore:
|
||||
blenderbim.bim.handler.subscribe_to(obj, "diffuse_color", blenderbim.bim.handler.color_callback)
|
||||
elif isinstance(obj, bpy.types.Object):
|
||||
blenderbim.bim.handler.subscribe_to(obj, "mode", blenderbim.bim.handler.mode_callback)
|
||||
blenderbim.bim.handler.subscribe_to(obj, "active_material_index", blenderbim.bim.handler.active_material_index_callback)
|
||||
|
||||
for listener in IfcStore.element_listeners:
|
||||
listener(element, obj)
|
||||
|
||||
if IfcStore.history:
|
||||
data = {"id": element.id(), "guid": getattr(element, "GlobalId", None), "obj": obj.name}
|
||||
@@ -243,12 +335,10 @@ class IfcStore:
|
||||
IfcStore.id_map[data["id"]] = obj
|
||||
if "guid" in data:
|
||||
IfcStore.guid_map[data["guid"]] = obj
|
||||
blenderbim.bim.handler.subscribe_to(obj, "mode", blenderbim.bim.handler.mode_callback)
|
||||
blenderbim.bim.handler.subscribe_to(obj, "name", blenderbim.bim.handler.name_callback)
|
||||
if isinstance(obj, bpy.types.Material):
|
||||
blenderbim.bim.handler.subscribe_to(obj, "diffuse_color", blenderbim.bim.handler.color_callback)
|
||||
elif isinstance(obj, bpy.types.Object):
|
||||
blenderbim.bim.handler.subscribe_to(obj, "mode", blenderbim.bim.handler.mode_callback)
|
||||
blenderbim.bim.handler.subscribe_to(obj, "active_material_index", blenderbim.bim.handler.active_material_index_callback)
|
||||
# TODO Listeners are not re-registered. Does this cause nasty problems to debug later on?
|
||||
# TODO We're handling id_map and guid_map, but what about edited_objs? This might cause big problems.
|
||||
|
||||
@@ -271,7 +361,7 @@ class IfcStore:
|
||||
def unlink_element(element=None, obj=None):
|
||||
if element is None:
|
||||
try:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
element = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -314,33 +404,24 @@ class IfcStore:
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def execute_ifc_operator(operator, context, is_invoke=False):
|
||||
def execute_ifc_operator(operator, context):
|
||||
is_top_level_operator = not bool(IfcStore.current_transaction)
|
||||
|
||||
if is_top_level_operator:
|
||||
IfcStore.begin_transaction(operator)
|
||||
if tool.Ifc.get():
|
||||
tool.Ifc.get().begin_transaction()
|
||||
if BrickStore.graph:
|
||||
BrickStore.begin_transaction()
|
||||
IfcStore.get_file().begin_transaction()
|
||||
# This empty transaction ensures that each operator has at least one transaction
|
||||
IfcStore.add_transaction_operation(operator, rollback=lambda data: True, commit=lambda data: True)
|
||||
else:
|
||||
operator.transaction_key = IfcStore.current_transaction
|
||||
|
||||
if is_invoke:
|
||||
result = getattr(operator, "_invoke")(context, None)
|
||||
else:
|
||||
result = getattr(operator, "_execute")(context)
|
||||
result = getattr(operator, "_execute")(context)
|
||||
|
||||
if is_top_level_operator:
|
||||
if tool.Ifc.get():
|
||||
tool.Ifc.get().end_transaction()
|
||||
IfcStore.add_transaction_operation(
|
||||
operator, rollback=lambda d: tool.Ifc.get().undo(), commit=lambda d: tool.Ifc.get().redo()
|
||||
)
|
||||
if BrickStore.graph:
|
||||
BrickStore.end_transaction()
|
||||
IfcStore.get_file().end_transaction()
|
||||
IfcStore.add_transaction_operation(
|
||||
operator, rollback=lambda d: IfcStore.get_file().undo(), commit=lambda d: IfcStore.get_file().redo()
|
||||
)
|
||||
IfcStore.end_transaction(operator)
|
||||
blenderbim.bim.handler.refresh_ui_data()
|
||||
|
||||
@@ -348,6 +429,8 @@ class IfcStore:
|
||||
|
||||
@staticmethod
|
||||
def begin_transaction(operator):
|
||||
IfcStore.undo_redo_stack_objects = set()
|
||||
IfcStore.undo_redo_stack_object_names = {}
|
||||
IfcStore.current_transaction = str(uuid.uuid4())
|
||||
operator.transaction_key = IfcStore.current_transaction
|
||||
|
||||
@@ -373,35 +456,19 @@ class IfcStore:
|
||||
IfcStore.future = []
|
||||
|
||||
@staticmethod
|
||||
def undo(until_key=None):
|
||||
BrickStore.undo()
|
||||
def undo():
|
||||
if not IfcStore.history:
|
||||
return
|
||||
|
||||
while IfcStore.history:
|
||||
if IfcStore.history[-1]["key"] == until_key:
|
||||
return
|
||||
|
||||
event = IfcStore.history.pop()
|
||||
for transaction in event["operations"][::-1]:
|
||||
transaction["rollback"](transaction["data"])
|
||||
IfcStore.future.append(event)
|
||||
event = IfcStore.history.pop()
|
||||
for transaction in event["operations"][::-1]:
|
||||
transaction["rollback"](transaction["data"])
|
||||
IfcStore.future.append(event)
|
||||
|
||||
@staticmethod
|
||||
def redo(until_key=None):
|
||||
BrickStore.redo()
|
||||
|
||||
def redo():
|
||||
if not IfcStore.future:
|
||||
return
|
||||
|
||||
has_encountered_key = False
|
||||
while IfcStore.future:
|
||||
if has_encountered_key and IfcStore.future[-1]["key"] != until_key:
|
||||
return
|
||||
elif IfcStore.future[-1]["key"] == until_key:
|
||||
has_encountered_key = True
|
||||
|
||||
event = IfcStore.future.pop()
|
||||
for transaction in event["operations"]:
|
||||
transaction["commit"](transaction["data"])
|
||||
IfcStore.history.append(event)
|
||||
event = IfcStore.future.pop()
|
||||
for transaction in event["operations"]:
|
||||
transaction["commit"](transaction["data"])
|
||||
IfcStore.history.append(event)
|
||||
|
||||
@@ -34,6 +34,7 @@ class AggregateData:
|
||||
cls.data = {
|
||||
"has_relating_object": cls.has_relating_object(),
|
||||
"relating_object_label": cls.get_relating_object_label(),
|
||||
"relating_object_id": cls.get_relating_object_id(),
|
||||
"has_related_objects": cls.has_related_objects(),
|
||||
"related_objects_amount": cls.get_related_objects_amount(),
|
||||
"ifc_class": cls.ifc_class(),
|
||||
@@ -54,6 +55,12 @@ class AggregateData:
|
||||
if aggregate:
|
||||
return f"{aggregate.is_a()}/{aggregate.Name or ''}"
|
||||
|
||||
@classmethod
|
||||
def get_relating_object_id(cls) -> int:
|
||||
aggregate = cls.get_relating_object()
|
||||
if aggregate:
|
||||
return aggregate.id()
|
||||
|
||||
@classmethod
|
||||
def get_related_objects(cls):
|
||||
return ifcopenshell.util.element.get_parts(tool.Ifc.get_entity(bpy.context.active_object))
|
||||
|
||||
@@ -40,31 +40,16 @@ class BIM_OT_assign_object(bpy.types.Operator, Operator):
|
||||
bl_label = "Assign Object"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
relating_object: bpy.props.IntProperty()
|
||||
related_object: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
relating_obj = None
|
||||
if self.relating_object:
|
||||
relating_obj = tool.Ifc.get_object(tool.Ifc.get().by_id(self.relating_object))
|
||||
elif context.active_object:
|
||||
relating_obj = context.active_object
|
||||
if not relating_obj:
|
||||
return
|
||||
|
||||
for obj in bpy.context.selected_objects:
|
||||
if obj == relating_obj:
|
||||
continue
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element:
|
||||
continue
|
||||
result = core.assign_object(
|
||||
tool.Ifc,
|
||||
tool.Aggregate,
|
||||
tool.Collector,
|
||||
relating_obj=relating_obj,
|
||||
related_obj=obj,
|
||||
)
|
||||
if not result:
|
||||
self.report({"ERROR"}, f" Cannot aggregate {obj.name} to {relating_obj.name}")
|
||||
core.assign_object(
|
||||
tool.Ifc,
|
||||
tool.Aggregate,
|
||||
tool.Collector,
|
||||
relating_obj=tool.Ifc.get_object(tool.Ifc.get().by_id(self.relating_object)),
|
||||
related_obj=tool.Ifc.get_object(tool.Ifc.get().by_id(self.related_object)),
|
||||
)
|
||||
|
||||
|
||||
class BIM_OT_unassign_object(bpy.types.Operator, Operator):
|
||||
@@ -73,22 +58,16 @@ class BIM_OT_unassign_object(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.unassign_object"
|
||||
bl_label = "Unassign Object"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
relating_object: bpy.props.IntProperty()
|
||||
related_object: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
for obj in bpy.context.selected_objects:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element:
|
||||
continue
|
||||
aggregate = ifcopenshell.util.element.get_aggregate(element)
|
||||
if not aggregate:
|
||||
continue
|
||||
core.unassign_object(
|
||||
tool.Ifc,
|
||||
tool.Aggregate,
|
||||
tool.Collector,
|
||||
relating_obj=tool.Ifc.get_object(aggregate),
|
||||
related_obj=tool.Ifc.get_object(element),
|
||||
)
|
||||
core.unassign_object(
|
||||
tool.Ifc,
|
||||
tool.Collector,
|
||||
relating_obj=tool.Ifc.get_object(tool.Ifc.get().by_id(self.relating_object)),
|
||||
related_obj=tool.Ifc.get_object(tool.Ifc.get().by_id(self.related_object)),
|
||||
)
|
||||
|
||||
|
||||
class BIM_OT_enable_editing_aggregate(bpy.types.Operator, Operator):
|
||||
@@ -113,58 +92,52 @@ class BIM_OT_disable_editing_aggregate(bpy.types.Operator, Operator):
|
||||
core.disable_editing_aggregate(tool.Aggregate, obj=context.active_object)
|
||||
|
||||
|
||||
class BIM_OT_add_aggregate(bpy.types.Operator, tool.Ifc.Operator):
|
||||
class BIM_OT_add_aggregate(bpy.types.Operator):
|
||||
"""Add aggregate to IFC element"""
|
||||
|
||||
bl_idname = "bim.add_aggregate"
|
||||
bl_label = "Add Aggregate"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
obj: bpy.props.StringProperty()
|
||||
ifc_class: bpy.props.StringProperty(name="IFC Class", default="IfcElementAssembly")
|
||||
|
||||
def invoke(self, context, event):
|
||||
return context.window_manager.invoke_props_dialog(self)
|
||||
|
||||
def draw(self, context):
|
||||
row = self.layout
|
||||
row.prop(self, "ifc_class")
|
||||
def execute(self, context):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
|
||||
def _execute(self, context):
|
||||
try:
|
||||
ifc_class = tool.Ifc.schema().declaration_by_name(self.ifc_class).name()
|
||||
except:
|
||||
return
|
||||
aggregate = self.create_aggregate(context, ifc_class)
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element:
|
||||
return {"FINISHED"}
|
||||
|
||||
for obj in context.selected_objects:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element:
|
||||
continue
|
||||
aggregate = self.create_aggregate(context)
|
||||
tool.Collector.sync(obj)
|
||||
current_aggregate = ifcopenshell.util.element.get_aggregate(element)
|
||||
current_container = ifcopenshell.util.element.get_container(element)
|
||||
if current_aggregate:
|
||||
core.assign_object(
|
||||
tool.Ifc,
|
||||
tool.Aggregate,
|
||||
tool.Collector,
|
||||
relating_obj=tool.Ifc.get_object(current_aggregate),
|
||||
related_obj=aggregate,
|
||||
)
|
||||
elif current_container:
|
||||
blenderbim.core.spatial.assign_container(
|
||||
tool.Ifc,
|
||||
tool.Collector,
|
||||
tool.Spatial,
|
||||
structure_obj=tool.Ifc.get_object(current_container),
|
||||
element_obj=aggregate,
|
||||
)
|
||||
core.assign_object(tool.Ifc, tool.Aggregate, tool.Collector, relating_obj=aggregate, related_obj=obj)
|
||||
return {"FINISHED"}
|
||||
|
||||
tool.Collector.sync(obj)
|
||||
current_aggregate = ifcopenshell.util.element.get_aggregate(element)
|
||||
current_container = ifcopenshell.util.element.get_container(element)
|
||||
if current_aggregate:
|
||||
core.assign_object(
|
||||
tool.Ifc,
|
||||
tool.Aggregate,
|
||||
tool.Collector,
|
||||
relating_obj=tool.Ifc.get_object(current_aggregate),
|
||||
related_obj=aggregate,
|
||||
)
|
||||
elif current_container:
|
||||
blenderbim.core.spatial.assign_container(
|
||||
tool.Ifc,
|
||||
tool.Collector,
|
||||
tool.Spatial,
|
||||
structure_obj=tool.Ifc.get_object(current_container),
|
||||
element_obj=aggregate,
|
||||
)
|
||||
core.assign_object(tool.Ifc, tool.Aggregate, tool.Collector, relating_obj=aggregate, related_obj=obj)
|
||||
|
||||
def create_aggregate(self, context, ifc_class):
|
||||
def create_aggregate(self, context):
|
||||
aggregate_collection = bpy.data.collections.new("IfcElementAssembly/Assembly")
|
||||
context.scene.collection.children.link(aggregate_collection)
|
||||
aggregate = bpy.data.objects.new("Assembly", None)
|
||||
bpy.ops.bim.assign_class(obj=aggregate.name, ifc_class=ifc_class)
|
||||
aggregate_collection.objects.link(aggregate)
|
||||
bpy.ops.bim.assign_class(obj=aggregate.name, ifc_class="IfcElementAssembly")
|
||||
return aggregate
|
||||
|
||||
|
||||
|
||||
@@ -22,13 +22,13 @@ from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
class BIM_PT_aggregate(Panel):
|
||||
bl_label = "Aggregates"
|
||||
bl_label = "IFC Aggregates"
|
||||
bl_idname = "BIM_PT_aggregate"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "object"
|
||||
bl_parent_id = "BIM_PT_tab_object_metadata"
|
||||
bl_parent_id = "BIM_PT_object_metadata"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -56,6 +56,7 @@ class BIM_PT_aggregate(Panel):
|
||||
if props.relating_object:
|
||||
op = row.operator("bim.assign_object", icon="CHECKMARK", text="")
|
||||
op.relating_object = props.relating_object.BIMObjectProperties.ifc_definition_id
|
||||
op.related_object = context.active_object.BIMObjectProperties.ifc_definition_id
|
||||
row.operator("bim.disable_editing_aggregate", icon="CANCEL", text="")
|
||||
else:
|
||||
row = layout.row(align=True)
|
||||
@@ -66,6 +67,8 @@ class BIM_PT_aggregate(Panel):
|
||||
row.operator("bim.enable_editing_aggregate", icon="GREASEPENCIL", text="")
|
||||
row.operator("bim.add_aggregate", icon="ADD", text="")
|
||||
op = row.operator("bim.unassign_object", icon="X", text="")
|
||||
op.relating_object = AggregateData.data["relating_object_id"]
|
||||
op.related_object = context.active_object.BIMObjectProperties.ifc_definition_id
|
||||
else:
|
||||
row.label(text="No Aggregate", icon="TRIA_UP")
|
||||
row.operator("bim.enable_editing_aggregate", icon="GREASEPENCIL", text="")
|
||||
|
||||
@@ -59,13 +59,9 @@ class MaterialAttributesData:
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
cls.data = {"ifc_definition_id": cls.ifc_definition_id(), "attributes": cls.attributes()}
|
||||
cls.data = {"attributes": cls.attributes()}
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
def ifc_definition_id(cls):
|
||||
return bpy.context.active_object.active_material.BIMObjectProperties.ifc_definition_id
|
||||
|
||||
@classmethod
|
||||
def attributes(cls):
|
||||
results = []
|
||||
|
||||
@@ -25,6 +25,7 @@ import blenderbim.bim.handler
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.core.attribute as core
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from ifcopenshell.api.attribute.data import Data
|
||||
|
||||
|
||||
class Operator:
|
||||
@@ -50,22 +51,9 @@ class EnableEditingAttributes(bpy.types.Operator):
|
||||
oprops = obj.BIMObjectProperties
|
||||
props = obj.BIMAttributeProperties
|
||||
props.attributes.clear()
|
||||
|
||||
def callback(name, prop, data):
|
||||
if name in ("RefLatitude", "RefLongitude"):
|
||||
new = props.attributes.add()
|
||||
new.name = name
|
||||
new.is_null = data[name] is None
|
||||
new.is_optional = True
|
||||
new.data_type = "string"
|
||||
new.ifc_class = data["type"]
|
||||
new.string_value = "" if new.is_null else json.dumps(data[name])
|
||||
blenderbim.bim.helper.add_attribute_description(new)
|
||||
new.description += " The degrees, minutes and seconds should follow this format : [12,34,56]"
|
||||
|
||||
blenderbim.bim.helper.import_attributes2(
|
||||
tool.Ifc.get().by_id(oprops.ifc_definition_id), props.attributes, callback=callback
|
||||
)
|
||||
if oprops.ifc_definition_id not in Data.products:
|
||||
Data.load(IfcStore.get_file(), oprops.ifc_definition_id)
|
||||
blenderbim.bim.helper.import_attributes2(tool.Ifc.get().by_id(oprops.ifc_definition_id), props.attributes)
|
||||
props.is_editing_attributes = True
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -100,22 +88,33 @@ class EditAttributes(bpy.types.Operator, Operator):
|
||||
obj = bpy.data.objects.get(self.obj)
|
||||
elif self.obj_type == "Material":
|
||||
obj = bpy.data.materials.get(self.obj)
|
||||
oprops = obj.BIMObjectProperties
|
||||
props = obj.BIMAttributeProperties
|
||||
product = tool.Ifc.get_entity(obj)
|
||||
|
||||
def callback(attributes, prop):
|
||||
if prop.name in ("RefLatitude", "RefLongitude"):
|
||||
if prop.is_null:
|
||||
attributes[prop.name] = None
|
||||
else:
|
||||
try:
|
||||
attributes[prop.name] = json.loads(prop.string_value)
|
||||
except:
|
||||
attributes[prop.name] = None
|
||||
return True
|
||||
|
||||
attributes = blenderbim.bim.helper.export_attributes(props.attributes, callback=callback)
|
||||
ifcopenshell.api.run("attribute.edit_attributes", self.file, product=product, attributes=attributes)
|
||||
attributes = {}
|
||||
for attribute in Data.products[oprops.ifc_definition_id]:
|
||||
blender_attribute = props.attributes.get(attribute["name"])
|
||||
if not blender_attribute:
|
||||
continue
|
||||
if attribute["is_optional"] and blender_attribute.is_null:
|
||||
attributes[attribute["name"]] = None
|
||||
elif attribute["type"] == "string":
|
||||
attributes[attribute["name"]] = blender_attribute.string_value
|
||||
elif attribute["type"] == "list":
|
||||
values = blender_attribute.string_value[1:-1].split(", ")
|
||||
if attribute["list_type"] == "float":
|
||||
values = [float(v) for v in values]
|
||||
elif attribute["list_type"] == "integer":
|
||||
values = [int(v) for v in values]
|
||||
attributes[attribute["name"]] = values
|
||||
elif attribute["type"] == "integer":
|
||||
attributes[attribute["name"]] = blender_attribute.int_value
|
||||
elif attribute["type"] == "float":
|
||||
attributes[attribute["name"]] = blender_attribute.float_value
|
||||
elif attribute["type"] == "enum":
|
||||
attributes[attribute["name"]] = blender_attribute.enum_value
|
||||
product = self.file.by_id(oprops.ifc_definition_id)
|
||||
ifcopenshell.api.run("attribute.edit_attributes", self.file, **{"product": product, "attributes": attributes})
|
||||
Data.load(IfcStore.get_file(), oprops.ifc_definition_id)
|
||||
bpy.ops.bim.disable_editing_attributes(obj=obj.name, obj_type=self.obj_type)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -144,5 +143,5 @@ class CopyAttributeToSelection(bpy.types.Operator, Operator):
|
||||
|
||||
def _execute(self, context):
|
||||
value = context.active_object.BIMAttributeProperties.attributes.get(self.name).get_value()
|
||||
for obj in tool.Blender.get_selected_objects():
|
||||
for obj in context.selected_objects:
|
||||
core.copy_attribute_to_selection(tool.Ifc, name=self.name, value=value, obj=obj)
|
||||
|
||||
@@ -54,12 +54,12 @@ def draw_ui(context, layout, obj_type, attributes):
|
||||
|
||||
|
||||
class BIM_PT_object_attributes(Panel):
|
||||
bl_label = "Attributes"
|
||||
bl_label = "IFC Attributes"
|
||||
bl_idname = "BIM_PT_object_attributes"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "object"
|
||||
bl_parent_id = "BIM_PT_tab_object_metadata"
|
||||
bl_parent_id = "BIM_PT_object_metadata"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -76,7 +76,7 @@ class BIM_PT_object_attributes(Panel):
|
||||
|
||||
|
||||
class BIM_PT_material_attributes(Panel):
|
||||
bl_label = "Material Attributes"
|
||||
bl_label = "IFC Material Attributes"
|
||||
bl_idname = "BIM_PT_material_attributes"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
@@ -94,10 +94,4 @@ class BIM_PT_material_attributes(Panel):
|
||||
def draw(self, context):
|
||||
if not MaterialAttributesData.is_loaded:
|
||||
MaterialAttributesData.load()
|
||||
elif (
|
||||
context.active_object.active_material.BIMObjectProperties.ifc_definition_id
|
||||
!= MaterialAttributesData.data["ifc_definition_id"]
|
||||
):
|
||||
MaterialAttributesData.load()
|
||||
|
||||
draw_ui(context, self.layout, "Material", MaterialAttributesData.data["attributes"])
|
||||
|
||||
@@ -26,7 +26,7 @@ class BIM_PT_augin(bpy.types.Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_sandbox"
|
||||
bl_parent_id = "BIM_PT_integrations"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
@@ -20,45 +20,43 @@ import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
classes = (
|
||||
operator.ActivateBcfViewpoint,
|
||||
operator.AddBcfBimSnippet,
|
||||
operator.AddBcfComment,
|
||||
operator.AddBcfDocumentReference,
|
||||
operator.AddBcfHeaderFile,
|
||||
operator.AddBcfLabel,
|
||||
operator.AddBcfReferenceLink,
|
||||
operator.AddBcfRelatedTopic,
|
||||
operator.AddBcfTopic,
|
||||
operator.AddBcfViewpoint,
|
||||
operator.EditBcfAuthor,
|
||||
operator.EditBcfComment,
|
||||
operator.EditBcfLabels,
|
||||
operator.EditBcfProjectName,
|
||||
operator.EditBcfReferenceLinks,
|
||||
operator.EditBcfTopic,
|
||||
operator.EditBcfTopicName,
|
||||
operator.ExtractBcfFile,
|
||||
operator.LoadBcfComments,
|
||||
operator.LoadBcfProject,
|
||||
operator.LoadBcfTopic,
|
||||
operator.LoadBcfTopics,
|
||||
operator.NewBcfProject,
|
||||
operator.OpenBcfReferenceLink,
|
||||
operator.RemoveBcfBimSnippet,
|
||||
operator.RemoveBcfComment,
|
||||
operator.RemoveBcfDocumentReference,
|
||||
operator.RemoveBcfFile,
|
||||
operator.RemoveBcfLabel,
|
||||
operator.RemoveBcfReferenceLink,
|
||||
operator.RemoveBcfRelatedTopic,
|
||||
operator.RemoveBcfTopic,
|
||||
operator.RemoveBcfViewpoint,
|
||||
operator.LoadBcfProject,
|
||||
operator.LoadBcfTopics,
|
||||
operator.LoadBcfTopic,
|
||||
operator.LoadBcfComments,
|
||||
operator.EditBcfProjectName,
|
||||
operator.EditBcfAuthor,
|
||||
operator.EditBcfTopicName,
|
||||
operator.EditBcfTopic,
|
||||
operator.SaveBcfProject,
|
||||
operator.AddBcfTopic,
|
||||
operator.AddBcfHeaderFile,
|
||||
operator.AddBcfBimSnippet,
|
||||
operator.AddBcfReferenceLink,
|
||||
operator.AddBcfDocumentReference,
|
||||
operator.AddBcfLabel,
|
||||
operator.AddBcfRelatedTopic,
|
||||
operator.ViewBcfTopic,
|
||||
operator.RemoveBcfTopic,
|
||||
operator.RemoveBcfComment,
|
||||
operator.RemoveBcfBimSnippet,
|
||||
operator.RemoveBcfReferenceLink,
|
||||
operator.RemoveBcfDocumentReference,
|
||||
operator.RemoveBcfRelatedTopic,
|
||||
operator.EditBcfReferenceLinks,
|
||||
operator.EditBcfLabels,
|
||||
operator.RemoveBcfLabel,
|
||||
operator.EditBcfComment,
|
||||
operator.AddBcfComment,
|
||||
operator.ActivateBcfViewpoint,
|
||||
operator.AddBcfViewpoint,
|
||||
operator.RemoveBcfViewpoint,
|
||||
operator.RemoveBcfFile,
|
||||
operator.OpenBcfReferenceLink,
|
||||
operator.SelectBcfHeaderFile,
|
||||
operator.SelectBcfBimSnippetReference,
|
||||
operator.SelectBcfDocumentReference,
|
||||
operator.SelectBcfHeaderFile,
|
||||
operator.UnloadBcfProject,
|
||||
operator.ViewBcfTopic,
|
||||
prop.BcfReferenceLink,
|
||||
prop.BcfLabel,
|
||||
prop.BcfBimSnippet,
|
||||
|
||||
@@ -20,20 +20,14 @@ import os
|
||||
import bpy
|
||||
import bcf
|
||||
import bcf.bcfxml
|
||||
import bcf.v2.model
|
||||
import uuid
|
||||
import numpy as np
|
||||
import tempfile
|
||||
import webbrowser
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.unit
|
||||
import blenderbim.bim.module.bcf.prop as bcf_prop
|
||||
from . import bcfstore
|
||||
from pathlib import Path
|
||||
import blenderbim.bim.module.bcf.prop as bcf_prop
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from math import radians, degrees, atan, tan, cos, sin
|
||||
from mathutils import Vector, Matrix, Euler, geometry
|
||||
from xsdata.models.datatype import XmlDateTime
|
||||
|
||||
|
||||
class NewBcfProject(bpy.types.Operator):
|
||||
@@ -58,9 +52,11 @@ class LoadBcfProject(bpy.types.Operator):
|
||||
filter_glob: bpy.props.StringProperty(default="*.bcf;*.bcfzip", options={"HIDDEN"})
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BCFProperties.is_loaded = False
|
||||
if self.filepath:
|
||||
bcfstore.BcfStore.bcfxml = bcf.bcfxml.load(self.filepath)
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
bcfxml.get_project()
|
||||
context.scene.BCFProperties.name = bcfxml.project.name
|
||||
bpy.ops.bim.load_bcf_topics()
|
||||
context.scene.BCFProperties.is_loaded = True
|
||||
@@ -71,17 +67,6 @@ class LoadBcfProject(bpy.types.Operator):
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
|
||||
class UnloadBcfProject(bpy.types.Operator):
|
||||
bl_idname = "bim.unload_bcf_project"
|
||||
bl_label = "Unload BCF Project"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
bcfstore.BcfStore.set(None)
|
||||
context.scene.BCFProperties.is_loaded = False
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class LoadBcfTopics(bpy.types.Operator):
|
||||
bl_idname = "bim.load_bcf_topics"
|
||||
bl_label = "Load BCF Topics"
|
||||
@@ -89,6 +74,7 @@ class LoadBcfTopics(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
bcfxml.get_topics()
|
||||
context.scene.BCFProperties.topics.clear()
|
||||
for index, topic_guid in enumerate(bcfxml.topics.keys()):
|
||||
new = context.scene.BCFProperties.topics.add()
|
||||
@@ -105,7 +91,7 @@ class LoadBcfTopic(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
topic = bcfxml.topics[self.topic_guid]
|
||||
topic = bcfxml.get_topic(self.topic_guid)
|
||||
bcfxml.get_header(self.topic_guid)
|
||||
new = context.scene.BCFProperties.topics[self.topic_index]
|
||||
data_map = {
|
||||
@@ -139,10 +125,10 @@ class LoadBcfTopic(bpy.types.Operator):
|
||||
|
||||
if topic.topic.bim_snippet:
|
||||
data_map = {
|
||||
"type": topic.topic.bim_snippet.snippet_type,
|
||||
"is_external": topic.topic.bim_snippet.is_external,
|
||||
"reference": topic.topic.bim_snippet.reference,
|
||||
"schema": topic.topic.bim_snippet.reference_schema,
|
||||
"type": topic.bim_snippet.snippet_type,
|
||||
"is_external": topic.bim_snippet.is_external,
|
||||
"reference": topic.bim_snippet.reference,
|
||||
"schema": topic.bim_snippet.reference_schema,
|
||||
}
|
||||
for key, value in data_map.items():
|
||||
if value is not None:
|
||||
@@ -178,9 +164,10 @@ class LoadBcfComments(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
bcfxml.get_comments(self.topic_guid)
|
||||
blender_topic = context.scene.BCFProperties.topics.get(self.topic_guid)
|
||||
blender_topic.comments.clear()
|
||||
for comment in bcfxml.topics[self.topic_guid].comments:
|
||||
for comment in bcfxml.topics[self.topic_guid].comments.values():
|
||||
new = blender_topic.comments.add()
|
||||
data_map = {
|
||||
"name": comment.guid,
|
||||
@@ -205,6 +192,7 @@ class EditBcfProjectName(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
bcfxml.project.name = context.scene.BCFProperties.name
|
||||
bcfxml.edit_project()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -228,8 +216,9 @@ class EditBcfTopicName(bpy.types.Operator):
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
topic = bcfxml.topics[blender_topic.name].topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
topic.title = blender_topic.title
|
||||
bcfxml.edit_topic(topic)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -243,7 +232,7 @@ class EditBcfTopic(bpy.types.Operator):
|
||||
blender_topic = props.active_topic
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
|
||||
topic = bcfxml.topics[blender_topic.name].topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
topic.title = blender_topic.title or None
|
||||
topic.priority = blender_topic.priority or None
|
||||
topic.due_date = blender_topic.due_date or None
|
||||
@@ -253,6 +242,7 @@ class EditBcfTopic(bpy.types.Operator):
|
||||
topic.topic_status = blender_topic.status or None
|
||||
topic.topic_type = blender_topic.type or None
|
||||
|
||||
bcfxml.edit_topic(topic)
|
||||
props.refresh_topic(context)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -266,7 +256,7 @@ class SaveBcfProject(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
bcfxml.save(self.filepath)
|
||||
bcfxml.save_project(self.filepath)
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
@@ -309,17 +299,15 @@ class AddBcfBimSnippet(bpy.types.Operator):
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
is_external = "://" in props.bim_snippet_reference
|
||||
bim_snippet = bcf.v2.model.BimSnippet(
|
||||
reference=props.bim_snippet_reference if is_external else Path(props.bim_snippet_reference).name,
|
||||
reference_schema=props.bim_snippet_schema,
|
||||
snippet_type=props.bim_snippet_type,
|
||||
is_external=is_external,
|
||||
)
|
||||
topic.topic.bim_snippet = bim_snippet
|
||||
with open(props.bim_snippet_reference, "r") as f:
|
||||
topic.bim_snippet = f.read()
|
||||
bim_snippet = bcf.v2.data.BimSnippet()
|
||||
bim_snippet.reference = props.bim_snippet_reference
|
||||
bim_snippet.reference_schema = props.bim_snippet_schema
|
||||
bim_snippet.snippet_type = props.bim_snippet_type
|
||||
bcfxml.add_bim_snippet(topic, bim_snippet)
|
||||
bpy.ops.bim.load_bcf_topic(topic_guid=topic.guid, topic_index=props.active_topic_index)
|
||||
bim_snippet.reference = ""
|
||||
bim_snippet.reference_schema = ""
|
||||
bim_snippet.snippet_type = ""
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -338,14 +326,15 @@ class AddBcfRelatedTopic(bpy.types.Operator):
|
||||
if props.related_topic == blender_topic.title:
|
||||
# Prevent adding self as related topic
|
||||
return False
|
||||
related_topic_guid = None
|
||||
related_topic = None
|
||||
for topic in bcfxml.topics.values():
|
||||
if topic.topic.title == props.related_topic:
|
||||
related_topic_guid = topic.guid
|
||||
if topic.title == props.related_topic:
|
||||
related_topic = bcf.v2.data.RelatedTopic()
|
||||
related_topic.guid = topic.guid
|
||||
break
|
||||
if not related_topic_guid:
|
||||
if not related_topic:
|
||||
return False
|
||||
if str(related_topic_guid) in [t.name for t in blender_topic.related_topics]:
|
||||
if str(related_topic.guid) in [t.name for t in blender_topic.related_topics]:
|
||||
# Prevent adding the same related topic more than once
|
||||
return False
|
||||
return True
|
||||
@@ -354,12 +343,11 @@ class AddBcfRelatedTopic(bpy.types.Operator):
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
related_topic = bcf.v2.data.RelatedTopic()
|
||||
related_topic.guid = next((t for t in bcfxml.topics.values() if t.title == props.related_topic)).guid
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
topic.topic.related_topic.append(
|
||||
bcf.v2.model.TopicRelatedTopic(
|
||||
guid=next((t for t in bcfxml.topics.values() if t.topic.title == props.related_topic)).guid
|
||||
)
|
||||
)
|
||||
topic.related_topics.append(related_topic)
|
||||
bcfxml.edit_topic(topic)
|
||||
bpy.ops.bim.load_bcf_topic(topic_guid=topic.guid, topic_index=props.active_topic_index)
|
||||
props.related_topic = ""
|
||||
return {"FINISHED"}
|
||||
@@ -379,24 +367,15 @@ class AddBcfHeaderFile(bpy.types.Operator):
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
|
||||
is_external = "://" in props.file_reference
|
||||
filename = Path(props.file_reference).name if os.path.exists(props.file_reference) else None
|
||||
|
||||
if filename:
|
||||
with open(props.file_reference, "r") as f:
|
||||
topic.reference_files[filename] = f.read()
|
||||
|
||||
header_file = bcf.v2.model.HeaderFile(
|
||||
filename=filename,
|
||||
date=XmlDateTime.now(),
|
||||
reference=props.file_reference if is_external else Path(props.file_reference).name,
|
||||
ifc_project=props.file_ifc_project,
|
||||
ifc_spatial_structure_element=props.file_ifc_spatial_structure_element,
|
||||
is_external=is_external,
|
||||
)
|
||||
topic.header.file.append(header_file)
|
||||
|
||||
header_file = bcf.v2.data.HeaderFile()
|
||||
header_file.reference = props.file_reference
|
||||
if not os.path.exists(header_file.reference):
|
||||
header_file.filename = header_file.reference
|
||||
if len(props.file_ifc_project) == 22:
|
||||
header_file.ifc_project = props.file_ifc_project
|
||||
if len(props.file_ifc_spatial_structure_element) == 22:
|
||||
header_file.ifc_spatial_structure_element = props.file_ifc_spatial_structure_element
|
||||
bcfxml.add_file(topic, header_file)
|
||||
props.refresh_topic(context)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -430,34 +409,27 @@ class AddBcfViewpoint(bpy.types.Operator):
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
viewpoint = bcf.v2.data.Viewpoint()
|
||||
|
||||
direction = blender_camera.matrix_world.to_quaternion() @ Vector((0.0, 0.0, -1.0))
|
||||
up = blender_camera.matrix_world.to_quaternion() @ Vector((0.0, 1.0, 0.0))
|
||||
|
||||
camera_view_point = bcf.v2.model.Point(
|
||||
x=blender_camera.location.x, y=blender_camera.location.y, z=blender_camera.location.z
|
||||
)
|
||||
camera_direction = bcf.v2.model.Direction(x=direction.x, y=direction.y, z=direction.z)
|
||||
camera_up_vector = bcf.v2.model.Direction(x=up.x, y=up.y, z=up.z)
|
||||
if blender_camera.data.type == "ORTHO":
|
||||
camera = bcf.v2.model.OrthogonalCamera(
|
||||
view_to_world_scale=blender_camera.data.ortho_scale,
|
||||
camera_view_point=camera_view_point,
|
||||
camera_direction=camera_direction,
|
||||
camera_up_vector=camera_up_vector,
|
||||
)
|
||||
visualization_info = bcf.v2.model.VisualizationInfo(orthogonal_camera=camera)
|
||||
camera = bcf.v2.data.OrthogonalCamera()
|
||||
camera.view_to_world_scale = blender_camera.data.ortho_scale
|
||||
viewpoint.orthogonal_camera = camera
|
||||
elif blender_camera.data.type == "PERSP":
|
||||
camera = bcf.v2.model.PerspectiveCamera(
|
||||
field_of_view=degrees(blender_camera.data.angle),
|
||||
camera_view_point=camera_view_point,
|
||||
camera_direction=camera_direction,
|
||||
camera_up_vector=camera_up_vector,
|
||||
)
|
||||
visualization_info = bcf.v2.model.VisualizationInfo(guid=str(uuid.uuid4()), perspective_camera=camera)
|
||||
|
||||
# TODO allow the user to enable or disable snapshotting
|
||||
snapshot = None
|
||||
camera = bcf.v2.data.PerspectiveCamera()
|
||||
camera.field_of_view = degrees(blender_camera.data.angle)
|
||||
viewpoint.perspective_camera = camera
|
||||
camera.camera_view_point.x = blender_camera.location.x
|
||||
camera.camera_view_point.y = blender_camera.location.y
|
||||
camera.camera_view_point.z = blender_camera.location.z
|
||||
direction = blender_camera.matrix_world.to_quaternion() @ Vector((0.0, 0.0, -1.0))
|
||||
camera.camera_direction.x = direction.x
|
||||
camera.camera_direction.y = direction.y
|
||||
camera.camera_direction.z = direction.z
|
||||
up = blender_camera.matrix_world.to_quaternion() @ Vector((0.0, 1.0, 0.0))
|
||||
camera.camera_up_vector.x = up.x
|
||||
camera.camera_up_vector.y = up.y
|
||||
camera.camera_up_vector.z = up.z
|
||||
|
||||
blender_render = context.scene.render
|
||||
old_file_format = blender_render.image_settings.file_format
|
||||
@@ -465,17 +437,9 @@ class AddBcfViewpoint(bpy.types.Operator):
|
||||
old_filepath = blender_render.filepath
|
||||
blender_render.filepath = os.path.join(context.scene.BIMProperties.data_dir, "snapshot.png")
|
||||
bpy.ops.render.opengl(write_still=True)
|
||||
with open(blender_render.filepath, "rb") as f:
|
||||
snapshot = f.read()
|
||||
# viewpoint.snapshot = blender_render.filepath
|
||||
|
||||
# TODO we should handle selection and visibility state
|
||||
vizinfo = bcf.v2.visinfo.VisualizationInfoHandler(visualization_info=visualization_info, snapshot=snapshot)
|
||||
topic.viewpoints[vizinfo.guid + ".bcfv"] = vizinfo
|
||||
topic.markup.viewpoints.append(
|
||||
bcf.v2.model.ViewPoint(viewpoint=vizinfo.guid + ".bcfv", guid=vizinfo.guid, snapshot=vizinfo.guid + ".png")
|
||||
)
|
||||
viewpoint.snapshot = blender_render.filepath
|
||||
|
||||
bcfxml.add_viewpoint(topic, viewpoint)
|
||||
blender_render.filepath = old_filepath
|
||||
blender_render.image_settings.file_format = old_file_format
|
||||
props.refresh_topic(context)
|
||||
@@ -495,15 +459,9 @@ class RemoveBcfViewpoint(bpy.types.Operator):
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
viewpoint_guid = blender_topic.viewpoints
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
for key, viewpoint in topic.viewpoints.items():
|
||||
if viewpoint.guid == blender_topic.viewpoints:
|
||||
break
|
||||
del topic.viewpoints[key]
|
||||
for i, viewpoint in enumerate(topic.markup.viewpoints):
|
||||
if viewpoint.guid == blender_topic.viewpoints:
|
||||
break
|
||||
del topic.markup.viewpoints[i]
|
||||
bcfxml.delete_viewpoint(viewpoint_guid, topic)
|
||||
props.refresh_topic(context)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -519,7 +477,7 @@ class RemoveBcfFile(bpy.types.Operator):
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
del topic.header.file[self.index]
|
||||
bcfxml.delete_file(topic, self.index)
|
||||
props.refresh_topic(context)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -537,7 +495,8 @@ class RemoveBcfTopic(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
props = context.scene.BCFProperties
|
||||
del bcfxml.topics[props.active_topic.name]
|
||||
topic_to_delete = props.active_topic
|
||||
bcfxml.delete_topic(topic_to_delete.name)
|
||||
bpy.ops.bim.load_bcf_topics()
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -556,7 +515,8 @@ class AddBcfReferenceLink(bpy.types.Operator):
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
topic.topic.reference_link.append(props.reference_link)
|
||||
topic.reference_links.append(props.reference_link)
|
||||
bcfxml.edit_topic(topic)
|
||||
bpy.ops.bim.load_bcf_topic(topic_guid=topic.guid, topic_index=props.active_topic_index)
|
||||
props.reference_link = ""
|
||||
return {"FINISHED"}
|
||||
@@ -576,23 +536,10 @@ class AddBcfDocumentReference(bpy.types.Operator):
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
|
||||
is_external = "://" in props.document_reference
|
||||
filename = Path(props.document_reference).name if os.path.exists(props.document_reference) else None
|
||||
|
||||
if filename:
|
||||
with open(props.document_reference, "rb") as f:
|
||||
topic.document_references[filename] = f.read()
|
||||
|
||||
document_reference = bcf.v2.model.TopicDocumentReference(
|
||||
referenced_document=props.document_reference if is_external else filename,
|
||||
description=props.document_reference_description or None,
|
||||
guid=str(uuid.uuid4()),
|
||||
is_external=is_external,
|
||||
)
|
||||
|
||||
topic.topic.document_reference.append(document_reference)
|
||||
|
||||
document_reference = bcf.v2.data.DocumentReference()
|
||||
document_reference.referenced_document = props.document_reference
|
||||
document_reference.description = props.document_reference_description or None
|
||||
bcfxml.add_document_reference(topic, document_reference)
|
||||
bpy.ops.bim.load_bcf_topic(topic_guid=topic.guid, topic_index=props.active_topic_index)
|
||||
props.document_reference = ""
|
||||
props.document_reference_description = ""
|
||||
@@ -615,7 +562,8 @@ class AddBcfLabel(bpy.types.Operator):
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
new = blender_topic.labels.add()
|
||||
new.name = props.label
|
||||
topic.topic.labels.append(props.label)
|
||||
topic.labels.append(props.label)
|
||||
bcfxml.edit_topic(topic)
|
||||
props.label = ""
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -630,10 +578,11 @@ class EditBcfReferenceLinks(bpy.types.Operator):
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
for index, reference_link in enumerate(topic.topic.reference_link):
|
||||
for index, reference_link in enumerate(topic.reference_links):
|
||||
if reference_link == blender_topic.reference_links[index].name:
|
||||
continue
|
||||
topic.topic.reference_link[index] = blender_topic.reference_links[index].name
|
||||
topic.reference_links[index] = blender_topic.reference_links[index].name
|
||||
bcfxml.edit_topic(topic)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -648,11 +597,12 @@ class EditBcfLabels(bpy.types.Operator):
|
||||
blender_topic = props.active_topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
for index, label in enumerate(blender_topic.labels):
|
||||
if index >= len(topic.topic.labels):
|
||||
if index >= len(topic.labels):
|
||||
break
|
||||
if label.name == topic.topic.labels[index]:
|
||||
if label.name == topic.labels[index]:
|
||||
continue
|
||||
topic.topic.labels[index] = blender_topic.labels[index].name
|
||||
topic.labels[index] = blender_topic.labels[index].name
|
||||
bcfxml.edit_topic(topic)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -667,7 +617,8 @@ class RemoveBcfReferenceLink(bpy.types.Operator):
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
del topic.topic.reference_link[self.index]
|
||||
del topic.reference_links[self.index]
|
||||
bcfxml.edit_topic(topic)
|
||||
blender_topic.reference_links.remove(self.index)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -683,7 +634,8 @@ class RemoveBcfLabel(bpy.types.Operator):
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
del topic.topic.labels[self.index]
|
||||
del topic.labels[self.index]
|
||||
bcfxml.edit_topic(topic)
|
||||
blender_topic.labels.remove(self.index)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -698,7 +650,7 @@ class RemoveBcfBimSnippet(bpy.types.Operator):
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
topic.topic.bim_snippet = None
|
||||
bcfxml.delete_bim_snippet(topic)
|
||||
blender_topic.bim_snippet.schema = ""
|
||||
blender_topic.bim_snippet.reference = ""
|
||||
blender_topic.bim_snippet.type = ""
|
||||
@@ -716,7 +668,7 @@ class RemoveBcfDocumentReference(bpy.types.Operator):
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
del topic.topic.document_reference[self.index]
|
||||
bcfxml.delete_document_reference(topic, self.index)
|
||||
bpy.ops.bim.load_bcf_topic(topic_guid=topic.guid, topic_index=props.active_topic_index)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -732,7 +684,8 @@ class RemoveBcfRelatedTopic(bpy.types.Operator):
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
del topic.topic.related_topic[self.index]
|
||||
del topic.related_topics[self.index]
|
||||
bcfxml.edit_topic(topic)
|
||||
bpy.ops.bim.load_bcf_topic(topic_guid=topic.guid, topic_index=props.active_topic_index)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -748,10 +701,7 @@ class RemoveBcfComment(bpy.types.Operator):
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
for i, comment in enumerate(topic.comments):
|
||||
if comment.guid == self.comment_guid:
|
||||
break
|
||||
del topic.comments[i]
|
||||
bcfxml.delete_comment(self.comment_guid, topic)
|
||||
bpy.ops.bim.load_bcf_comments(topic_guid=topic.guid)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -768,11 +718,9 @@ class EditBcfComment(bpy.types.Operator):
|
||||
blender_topic = props.active_topic
|
||||
blender_comment = blender_topic.comments.get(self.comment_guid)
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
for i, comment in enumerate(topic.comments):
|
||||
if comment.guid == self.comment_guid:
|
||||
comment.comment = blender_comment.comment
|
||||
comment.modified_date = XmlDateTime.now()
|
||||
comment.modified_author = context.scene.BCFProperties.author
|
||||
comment = topic.comments[self.comment_guid]
|
||||
comment.comment = blender_comment.comment
|
||||
bcfxml.edit_comment(comment, topic)
|
||||
bpy.ops.bim.load_bcf_comments(topic_guid=topic.guid)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -797,15 +745,12 @@ class AddBcfComment(bpy.types.Operator):
|
||||
props = context.scene.BCFProperties
|
||||
blender_topic = props.active_topic
|
||||
topic = bcfxml.topics[blender_topic.name]
|
||||
comment = bcf.v2.model.Comment(
|
||||
date=XmlDateTime.now(),
|
||||
author=context.scene.BCFProperties.author,
|
||||
comment=props.comment,
|
||||
guid=str(uuid.uuid4()),
|
||||
)
|
||||
comment = bcf.v2.data.Comment()
|
||||
comment.comment = props.comment
|
||||
if props.has_related_viewpoint:
|
||||
comment.viewpoint = bcf.v2.model.CommentViewpoint(guid=blender_topic.viewpoints)
|
||||
topic.comments.append(comment)
|
||||
comment.viewpoint = bcf.v2.data.Viewpoint()
|
||||
comment.viewpoint.guid = blender_topic.viewpoints
|
||||
bcfxml.add_comment(topic, comment)
|
||||
bpy.ops.bim.load_bcf_comments(topic_guid=topic.guid)
|
||||
props.comment = ""
|
||||
props.has_related_viewpoint = False
|
||||
@@ -846,13 +791,11 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
cam_height = context.scene.render.resolution_y
|
||||
cam_aspect = cam_width / cam_height
|
||||
|
||||
obj.data.background_images.clear()
|
||||
if viewpoint.snapshot:
|
||||
obj.data.show_background_images = True
|
||||
obj.data.background_images.clear()
|
||||
background = obj.data.background_images.new()
|
||||
with tempfile.NamedTemporaryFile(delete=False) as f:
|
||||
f.write(viewpoint.snapshot)
|
||||
background.image = bpy.data.images.load(f.name)
|
||||
background.image = bpy.data.images.load(os.path.join(bcfxml.filepath, topic.guid, viewpoint.snapshot))
|
||||
src_width = background.image.size[0]
|
||||
src_height = background.image.size[1]
|
||||
src_aspect = src_width / src_height
|
||||
@@ -862,9 +805,6 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
else:
|
||||
background.frame_method = "CROP"
|
||||
background.display_depth = "FRONT"
|
||||
else:
|
||||
obj.data.show_background_images = False
|
||||
|
||||
area = next(area for area in context.screen.areas if area.type == "VIEW_3D")
|
||||
area.spaces[0].region_3d.view_perspective = "CAMERA"
|
||||
|
||||
@@ -874,27 +814,27 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
gp = bpy.data.grease_pencils.get("BCF")
|
||||
if gp:
|
||||
bpy.data.grease_pencils.remove(gp)
|
||||
if viewpoint.visualization_info.lines:
|
||||
if viewpoint.lines:
|
||||
self.draw_lines(viewpoint, context)
|
||||
|
||||
self.delete_clipping_planes(context)
|
||||
if viewpoint.visualization_info.clipping_planes:
|
||||
if viewpoint.clipping_planes:
|
||||
self.create_clipping_planes(viewpoint)
|
||||
|
||||
self.delete_bitmaps(context)
|
||||
if viewpoint.visualization_info.bitmap:
|
||||
if viewpoint.bitmaps:
|
||||
self.create_bitmaps(bcfxml, viewpoint, topic)
|
||||
|
||||
self.setup_camera(viewpoint, obj, cam_aspect, context)
|
||||
return {"FINISHED"}
|
||||
|
||||
def setup_camera(self, viewpoint, obj, cam_aspect, context):
|
||||
if viewpoint.visualization_info.orthogonal_camera:
|
||||
camera = viewpoint.visualization_info.orthogonal_camera
|
||||
if viewpoint.orthogonal_camera:
|
||||
camera = viewpoint.orthogonal_camera
|
||||
obj.data.type = "ORTHO"
|
||||
obj.data.ortho_scale = viewpoint.visualization_info.orthogonal_camera.view_to_world_scale
|
||||
elif viewpoint.visualization_info.perspective_camera:
|
||||
camera = viewpoint.visualization_info.perspective_camera
|
||||
obj.data.ortho_scale = viewpoint.orthogonal_camera.view_to_world_scale
|
||||
elif viewpoint.perspective_camera:
|
||||
camera = viewpoint.perspective_camera
|
||||
obj.data.type = "PERSP"
|
||||
if cam_aspect >= 1:
|
||||
obj.data.angle = radians(camera.field_of_view)
|
||||
@@ -935,22 +875,22 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
obj.matrix_world = Matrix(matrix.tolist())
|
||||
|
||||
def set_viewpoint_components(self, viewpoint, context):
|
||||
if not viewpoint.visualization_info.components:
|
||||
if not viewpoint.components:
|
||||
return
|
||||
|
||||
# Operators with context overrides are used because they are
|
||||
# significantly faster than looping through all objects
|
||||
|
||||
exception_global_ids = {v.ifc_guid for v in viewpoint.visualization_info.components.visibility.exceptions or []}
|
||||
exception_global_ids = {v.ifc_guid for v in viewpoint.components.visibility.exceptions}
|
||||
|
||||
if viewpoint.visualization_info.components.visibility.default_visibility:
|
||||
if viewpoint.components.visibility.default_visibility:
|
||||
old = context.area.type
|
||||
context.area.type = "VIEW_3D"
|
||||
bpy.ops.object.hide_view_clear()
|
||||
context.area.type = old
|
||||
for global_id in exception_global_ids:
|
||||
obj = IfcStore.get_element(global_id)
|
||||
if obj and bpy.context.view_layer.objects.get(obj.name):
|
||||
if obj:
|
||||
obj.hide_set(True)
|
||||
else:
|
||||
objs = []
|
||||
@@ -967,13 +907,11 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
bpy.ops.object.hide_view_set(context_override, unselected=True)
|
||||
context.area.type = old
|
||||
|
||||
if viewpoint.visualization_info.components.view_setup_hints:
|
||||
if not viewpoint.visualization_info.components.view_setup_hints.spaces_visible:
|
||||
if viewpoint.components.view_setup_hints:
|
||||
if not viewpoint.components.view_setup_hints.spaces_visible:
|
||||
self.hide_spaces(context)
|
||||
if viewpoint.visualization_info.components.view_setup_hints.openings_visible is not None:
|
||||
self.set_openings_visibility(
|
||||
viewpoint.visualization_info.components.view_setup_hints.openings_visible, context
|
||||
)
|
||||
if viewpoint.components.view_setup_hints.openings_visible is not None:
|
||||
self.set_openings_visibility(viewpoint.components.view_setup_hints.openings_visible, context)
|
||||
else:
|
||||
self.hide_spaces(context)
|
||||
self.set_openings_visibility(False, context)
|
||||
@@ -989,12 +927,11 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
context.area.type = old
|
||||
|
||||
def set_openings_visibility(self, is_visible, context):
|
||||
pass # We no longer have an openings collection
|
||||
for collection in self.get_opening_collections(context):
|
||||
collection.hide_viewport = not is_visible
|
||||
|
||||
def set_selection(self, viewpoint):
|
||||
if not viewpoint.visualization_info.components or not viewpoint.visualization_info.components.selection:
|
||||
return
|
||||
selected_global_ids = [s.ifc_guid for s in viewpoint.visualization_info.components.selection.component or []]
|
||||
selected_global_ids = [s.ifc_guid for s in viewpoint.components.selection]
|
||||
bpy.ops.object.select_all(action="DESELECT")
|
||||
for global_id in selected_global_ids:
|
||||
obj = IfcStore.get_element(global_id)
|
||||
@@ -1003,7 +940,7 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
|
||||
def set_colours(self, viewpoint):
|
||||
global_id_colours = {}
|
||||
for coloring in viewpoint.visualization_info.components.coloring or []:
|
||||
for coloring in viewpoint.components.coloring:
|
||||
for component in coloring.components:
|
||||
global_id_colours.setdefault(component.ifc_guid, coloring.color)
|
||||
for global_id, color in global_id_colours.items():
|
||||
@@ -1011,6 +948,14 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
if obj:
|
||||
obj.color = self.hex_to_rgb(color)
|
||||
|
||||
def get_opening_collections(self, context):
|
||||
collections = []
|
||||
for collection in context.view_layer.layer_collection.children:
|
||||
opening_collection = collection.children.get("IfcOpeningElements")
|
||||
if opening_collection:
|
||||
collections.append(opening_collection)
|
||||
return collections
|
||||
|
||||
def draw_lines(self, viewpoint, context):
|
||||
gp = bpy.data.grease_pencils.new("BCF")
|
||||
scene = context.scene
|
||||
@@ -1022,9 +967,9 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
frame = layer.frames.new(1)
|
||||
stroke = frame.strokes.new()
|
||||
stroke.display_mode = "3DSPACE"
|
||||
stroke.points.add(len(viewpoint.visualization_info.lines.line) * 2)
|
||||
stroke.points.add(len(viewpoint.lines) * 2)
|
||||
coords = []
|
||||
for l in viewpoint.visualization_info.lines.line:
|
||||
for l in viewpoint.lines:
|
||||
coords.extend(
|
||||
[l.start_point.x, l.start_point.y, l.start_point.z, l.end_point.x, l.end_point.y, l.end_point.z]
|
||||
)
|
||||
@@ -1032,7 +977,7 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
|
||||
def create_clipping_planes(self, viewpoint):
|
||||
n = 0
|
||||
for plane in viewpoint.visualization_info.clipping_planes.clipping_plane:
|
||||
for plane in viewpoint.clipping_planes:
|
||||
bpy.ops.bim.add_section_plane()
|
||||
if n == 0:
|
||||
obj = bpy.data.objects["Section"]
|
||||
@@ -1065,14 +1010,10 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
collection = bpy.data.collections.get("Bitmaps")
|
||||
if not collection:
|
||||
collection = bpy.data.collections.new("Bitmaps")
|
||||
for bitmap in viewpoint.visualization_info.bitmap:
|
||||
for bitmap in viewpoint.bitmaps:
|
||||
obj = bpy.data.objects.new("Bitmap", None)
|
||||
obj.empty_display_type = "IMAGE"
|
||||
# image = bpy.data.images.load(os.path.join(bcfxml.filepath, topic.guid, bitmap.reference))
|
||||
with tempfile.NamedTemporaryFile(delete=False) as f:
|
||||
topic.extract_file(bitmap, f.name)
|
||||
# f.write(bitmap.what)
|
||||
image = bpy.data.images.load(f.name)
|
||||
image = bpy.data.images.load(os.path.join(bcfxml.filepath, topic.guid, bitmap.reference))
|
||||
src_width = image.size[0]
|
||||
src_height = image.size[1]
|
||||
if src_height > src_width:
|
||||
@@ -1111,7 +1052,6 @@ class SelectBcfHeaderFile(bpy.types.Operator):
|
||||
bl_label = "Select BCF Header File"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml;*.ifcjson", options={"HIDDEN"})
|
||||
|
||||
def execute(self, context):
|
||||
if self.filepath:
|
||||
@@ -1153,25 +1093,3 @@ class SelectBcfDocumentReference(bpy.types.Operator):
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
|
||||
class ExtractBcfFile(bpy.types.Operator):
|
||||
bl_idname = "bim.extract_bcf_file"
|
||||
bl_label = "Extract BCF Header File"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
entity_type: bpy.props.StringProperty()
|
||||
index: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
topic = bcfxml.topics[context.scene.BCFProperties.active_topic.name]
|
||||
|
||||
if self.entity_type == "HEADER_FILE":
|
||||
entity = topic.header.file[self.index]
|
||||
elif self.entity_type == "BIM_SNIPPET":
|
||||
entity = topic.markup.topic.bim_snippet
|
||||
elif self.entity_type == "DOCUMENT_REFERENCE":
|
||||
entity = topic.markup.topic.document_reference[self.index]
|
||||
|
||||
webbrowser.open(str(topic.extract_file(entity).parent))
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -95,8 +95,8 @@ def getBcfViewpoints(self, context, force_update=False):
|
||||
props = context.scene.BCFProperties
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
topic = props.active_topic
|
||||
viewpoints = bcfxml.topics[topic.name].viewpoints.keys() if topic else []
|
||||
bcfviewpoints_enum.extend([(v, f"Viewpoint {i+1}", "") for i, v in enumerate(viewpoints)])
|
||||
viewpoints = bcfxml.get_viewpoints(topic.name) if topic else {}
|
||||
bcfviewpoints_enum.extend([(v, f"Viewpoint {i+1}", "") for i, v in enumerate(viewpoints.keys())])
|
||||
return bcfviewpoints_enum
|
||||
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class BIM_PT_bcf(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_collaboration"
|
||||
bl_parent_id = "BIM_PT_collaboration"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -39,16 +39,14 @@ class BIM_PT_bcf(Panel):
|
||||
scene = context.scene
|
||||
props = scene.BCFProperties
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.operator("bim.new_bcf_project", text="New Project")
|
||||
row.operator("bim.load_bcf_project", text="Load Project")
|
||||
|
||||
if not props.is_loaded:
|
||||
row = layout.row(align=True)
|
||||
row.operator("bim.new_bcf_project", text="New Project")
|
||||
row.operator("bim.load_bcf_project", text="Load Project")
|
||||
return
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.operator("bim.save_bcf_project", icon="EXPORT", text="Save Project")
|
||||
row.operator("bim.unload_bcf_project", text="", icon="CANCEL")
|
||||
row.operator("bim.save_bcf_project", text="Save Project")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(props, "name")
|
||||
@@ -129,21 +127,20 @@ class BIM_PT_bcf_metadata(Panel):
|
||||
layout.label(text="Header Files:")
|
||||
|
||||
if bcf_topic.header:
|
||||
for index, f in enumerate(bcf_topic.header.file):
|
||||
for index, f in enumerate(bcf_topic.header.files):
|
||||
box = self.layout.box()
|
||||
row = box.row(align=True)
|
||||
row.label(text=f.filename, icon="FILE_BLANK")
|
||||
if f.is_external:
|
||||
row.operator("bim.open_uri", icon="URL", text="").uri = f.reference
|
||||
else:
|
||||
op = row.operator("bim.extract_bcf_file", icon="FILE_FOLDER", text="")
|
||||
op.index = index
|
||||
op.entity_type = "HEADER_FILE"
|
||||
op = row.operator("bim.open_uri", icon="FILE_FOLDER", text="")
|
||||
op.uri = os.path.join(bcfxml.filepath, topic.name, f.reference)
|
||||
row.operator("bim.remove_bcf_file", icon="X", text="").index = index
|
||||
|
||||
row = box.row()
|
||||
row.label(text="Date")
|
||||
row.label(text=str(f.date))
|
||||
row.label(text=f.date)
|
||||
|
||||
if f.ifc_project:
|
||||
row = box.row()
|
||||
@@ -199,8 +196,8 @@ class BIM_PT_bcf_metadata(Panel):
|
||||
if topic.bim_snippet.is_external:
|
||||
row.operator("bim.open_uri", icon="URL", text="").uri = topic.bim_snippet.reference
|
||||
else:
|
||||
op = row.operator("bim.extract_bcf_file", icon="FILE_FOLDER", text="")
|
||||
op.entity_type = "BIM_SNIPPET"
|
||||
op = row.operator("bim.open_uri", icon="FILE_FOLDER", text="")
|
||||
op.uri = os.path.join(bcfxml.filepath, topic.name, topic.bim_snippet.reference)
|
||||
row.operator("bim.remove_bcf_bim_snippet", icon="X", text="")
|
||||
else:
|
||||
row = layout.row(align=True)
|
||||
@@ -221,10 +218,8 @@ class BIM_PT_bcf_metadata(Panel):
|
||||
if doc.is_external:
|
||||
row.operator("bim.open_uri", icon="URL", text="").uri = doc.reference
|
||||
else:
|
||||
op = row.operator("bim.extract_bcf_file", icon="FILE_FOLDER", text="")
|
||||
op.entity_type = "DOCUMENT_REFERENCE"
|
||||
op.index = index
|
||||
|
||||
op = row.operator("bim.open_uri", icon="FILE_FOLDER", text="")
|
||||
op.uri = os.path.join(bcfxml.filepath, topic.name, doc.reference)
|
||||
row.operator("bim.remove_bcf_document_reference", icon="X", text="").index = index
|
||||
row = box.row(align=True)
|
||||
row.prop(doc, "description")
|
||||
@@ -241,7 +236,7 @@ class BIM_PT_bcf_metadata(Panel):
|
||||
try:
|
||||
row = layout.row(align=True)
|
||||
op = row.operator(
|
||||
"bim.view_bcf_topic", text=f"Select {bcfxml.topics[related_topic.name.lower()].topic.title}"
|
||||
"bim.view_bcf_topic", text=f"Select {bcfxml.topics[related_topic.name.lower()].title}"
|
||||
)
|
||||
op.topic_guid = related_topic.name
|
||||
row.operator("bim.remove_bcf_related_topic", icon="X", text="").index = index
|
||||
|
||||
@@ -27,7 +27,7 @@ class BIM_PT_qa(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_quality_control"
|
||||
bl_parent_id = "BIM_PT_quality_control"
|
||||
|
||||
def draw(self, context):
|
||||
self.layout.use_property_split = True
|
||||
|
||||
@@ -20,37 +20,25 @@ import bpy
|
||||
from . import ui, operator, prop
|
||||
|
||||
classes = (
|
||||
operator.AddBoundary,
|
||||
operator.ColourByRelatedBuildingElement,
|
||||
operator.DisableEditingBoundary,
|
||||
operator.DisableEditingBoundaryGeometry,
|
||||
operator.EditBoundaryAttributes,
|
||||
operator.EditBoundaryGeometry,
|
||||
operator.EnableEditingBoundary,
|
||||
operator.EnableEditingBoundaryGeometry,
|
||||
operator.HideBoundaries,
|
||||
operator.LoadBoundary,
|
||||
operator.LoadProjectSpaceBoundaries,
|
||||
operator.LoadSpaceBoundaries,
|
||||
operator.LoadBoundary,
|
||||
operator.SelectProjectBoundaries,
|
||||
operator.SelectRelatedElementBoundaries,
|
||||
operator.SelectRelatedElementTypeBoundaries,
|
||||
operator.SelectSpaceBoundaries,
|
||||
operator.ShowBoundaries,
|
||||
operator.ColourByRelatedBuildingElement,
|
||||
operator.EnableEditingBoundary,
|
||||
operator.DisableEditingBoundary,
|
||||
operator.EditBoundaryAttributes,
|
||||
operator.UpdateBoundaryGeometry,
|
||||
ui.BIM_PT_Boundary,
|
||||
ui.BIM_PT_SceneBoundaries,
|
||||
ui.BIM_PT_SpaceBoundaries,
|
||||
ui.BIM_PT_SceneBoundaries,
|
||||
prop.BIMBoundaryProperties,
|
||||
prop.BIMObjectBoundaryProperties,
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
bpy.types.Scene.BIMBoundaryProperties = bpy.props.PointerProperty(type=prop.BIMBoundaryProperties)
|
||||
bpy.types.Object.bim_boundary_properties = bpy.props.PointerProperty(type=prop.BIMObjectBoundaryProperties)
|
||||
bpy.types.Object.bim_boundary_properties = bpy.props.PointerProperty(type=prop.BIMBoundaryProperties)
|
||||
|
||||
|
||||
def unregister():
|
||||
del bpy.types.Scene.BIMBoundaryProperties
|
||||
del bpy.types.Object.bim_boundary_properties
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2023 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BlenderBIM Add-on 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import blenderbim.tool as tool
|
||||
|
||||
|
||||
def refresh():
|
||||
SpaceBoundariesData.is_loaded = False
|
||||
|
||||
|
||||
class SpaceBoundariesData:
|
||||
data = {}
|
||||
is_loaded = False
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
cls.data = {"boundaries": cls.boundaries()}
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
def boundaries(cls):
|
||||
results = []
|
||||
element = tool.Ifc.get_entity(bpy.context.active_object)
|
||||
for rel in element.BoundedBy or []:
|
||||
description = f"{rel.id()} > {rel.RelatedBuildingElement.is_a()}/{rel.RelatedBuildingElement.Name}"
|
||||
results.append({"id": rel.id(), "description": description})
|
||||
return results
|
||||
@@ -1,112 +0,0 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2023 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BlenderBIM Add-on 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import gpu
|
||||
import bmesh
|
||||
import blenderbim.tool as tool
|
||||
from bpy.types import SpaceView3D
|
||||
from mathutils import Vector
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
|
||||
|
||||
class BoundaryDecorator:
|
||||
installed = None
|
||||
|
||||
@classmethod
|
||||
def install(cls, context):
|
||||
if cls.installed:
|
||||
cls.uninstall()
|
||||
handler = cls()
|
||||
cls.installed = SpaceView3D.draw_handler_add(handler, (context,), "WINDOW", "POST_VIEW")
|
||||
|
||||
@classmethod
|
||||
def uninstall(cls):
|
||||
try:
|
||||
SpaceView3D.draw_handler_remove(cls.installed, "WINDOW")
|
||||
except ValueError:
|
||||
pass
|
||||
cls.installed = None
|
||||
|
||||
def draw_batch(self, shader_type, content_pos, color, indices=None):
|
||||
shader = self.line_shader if shader_type == "LINES" else self.shader
|
||||
batch = batch_for_shader(shader, shader_type, {"pos": content_pos}, indices=indices)
|
||||
shader.uniform_float("color", color)
|
||||
batch.draw(shader)
|
||||
|
||||
def __call__(self, context):
|
||||
self.addon_prefs = context.preferences.addons["blenderbim"].preferences
|
||||
selected_elements_color = self.addon_prefs.decorator_color_selected
|
||||
unselected_elements_color = self.addon_prefs.decorator_color_unselected
|
||||
special_elements_color = self.addon_prefs.decorator_color_special
|
||||
|
||||
def transparent_color(color, alpha=0.1):
|
||||
color = [i for i in color]
|
||||
color[3] = alpha
|
||||
return color
|
||||
|
||||
gpu.state.point_size_set(6)
|
||||
gpu.state.blend_set("ALPHA")
|
||||
|
||||
self.line_shader = gpu.shader.from_builtin("3D_POLYLINE_UNIFORM_COLOR")
|
||||
self.line_shader.bind() # required to be able to change uniforms of the shader
|
||||
# POLYLINE_UNIFORM_COLOR specific uniforms
|
||||
self.line_shader.uniform_float("viewportSize", (context.region.width, context.region.height))
|
||||
self.line_shader.uniform_float("lineWidth", 2.0)
|
||||
|
||||
# general shader
|
||||
self.shader = gpu.shader.from_builtin("3D_UNIFORM_COLOR")
|
||||
|
||||
selected_vertices = []
|
||||
selected_edges = []
|
||||
selected_tris = []
|
||||
unselected_vertices = []
|
||||
unselected_edges = []
|
||||
unselected_tris = []
|
||||
|
||||
for boundary in context.scene.BIMBoundaryProperties.boundaries:
|
||||
obj = boundary.obj
|
||||
if not obj or not obj.data: # A boundary may not have data if it has no connection geometry
|
||||
continue
|
||||
|
||||
if obj.mode == "EDIT":
|
||||
continue # A profile decorator or something else is used here.
|
||||
else:
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(obj.data)
|
||||
obj.data.calc_loop_triangles()
|
||||
|
||||
if obj.select_get():
|
||||
offset = len(selected_vertices)
|
||||
selected_vertices.extend([tuple(obj.matrix_world @ v.co) for v in bm.verts])
|
||||
selected_edges.extend([tuple([v.index + offset for v in e.verts]) for e in bm.edges])
|
||||
selected_tris.extend([tuple([i + offset for i in t.vertices]) for t in obj.data.loop_triangles])
|
||||
else:
|
||||
offset = len(unselected_vertices)
|
||||
unselected_vertices.extend([tuple(obj.matrix_world @ v.co) for v in bm.verts])
|
||||
unselected_edges.extend([tuple([v.index + offset for v in e.verts]) for e in bm.edges])
|
||||
unselected_tris.extend([tuple([i + offset for i in t.vertices]) for t in obj.data.loop_triangles])
|
||||
|
||||
if obj.mode != "EDIT":
|
||||
bm.free()
|
||||
|
||||
if unselected_edges:
|
||||
self.draw_batch("LINES", unselected_vertices, special_elements_color, unselected_edges)
|
||||
self.draw_batch("TRIS", unselected_vertices, transparent_color(special_elements_color), unselected_tris)
|
||||
if selected_edges:
|
||||
self.draw_batch("LINES", selected_vertices, selected_elements_color, selected_edges)
|
||||
self.draw_batch("TRIS", selected_vertices, transparent_color(selected_elements_color), selected_tris)
|
||||
@@ -17,29 +17,16 @@
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import bmesh
|
||||
import logging
|
||||
import shapely
|
||||
import mathutils
|
||||
import numpy as np
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.shape
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.representation
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.bim.import_ifc as import_ifc
|
||||
from math import pi, inf
|
||||
from mathutils import Vector, Matrix
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.model.decorator import ProfileDecorator
|
||||
from blenderbim.bim.module.boundary.decorator import BoundaryDecorator
|
||||
import blenderbim.core
|
||||
from ifcopenshell.api.boundary.data import Data
|
||||
import blenderbim.bim.import_ifc as import_ifc
|
||||
|
||||
|
||||
def get_boundaries_collection(blender_space):
|
||||
space_collection = blender_space.BIMObjectProperties.collection
|
||||
space_collection = bpy.data.collections.get(blender_space.name, blender_space.users_collection[0])
|
||||
collection_name = f"Boundaries/{blender_space.BIMObjectProperties.ifc_definition_id}"
|
||||
boundaries_collection = space_collection.children.get(collection_name)
|
||||
if not boundaries_collection:
|
||||
@@ -48,27 +35,13 @@ def get_boundaries_collection(blender_space):
|
||||
return boundaries_collection
|
||||
|
||||
|
||||
def disable_editing_boundary_geometry(context):
|
||||
ProfileDecorator.uninstall()
|
||||
bpy.ops.object.mode_set(mode="OBJECT")
|
||||
|
||||
obj = context.active_object
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
|
||||
old_mesh = obj.data
|
||||
loader = Loader()
|
||||
obj.data = loader.create_mesh(element)
|
||||
tool.Geometry.delete_data(old_mesh)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class Loader:
|
||||
def __init__(self):
|
||||
self.ifc_file = None
|
||||
self.logger = None
|
||||
self.ifc_importer = None
|
||||
self.settings = self.load_settings()
|
||||
self.fallback_settings = self.load_fallback_settings()
|
||||
self.settings = None
|
||||
self.load_settings()
|
||||
self.load_importer()
|
||||
|
||||
def create_mesh(self, boundary):
|
||||
@@ -76,48 +49,18 @@ class Loader:
|
||||
if not boundary.ConnectionGeometry:
|
||||
return None
|
||||
surface = boundary.ConnectionGeometry.SurfaceOnRelatingElement
|
||||
# Workaround for invalid geometry provided by Revit. See https://github.com/Autodesk/revit-ifc/issues/270
|
||||
# workaround for invalid geometry provided by Revit. See https://github.com/IfcOpenShell/IfcOpenShell/issues/635#issuecomment-770366838
|
||||
if surface.is_a("IfcCurveBoundedPlane") and not getattr(surface, "InnerBoundaries", None):
|
||||
surface.InnerBoundaries = ()
|
||||
try:
|
||||
shape = ifcopenshell.geom.create_shape(self.settings, surface)
|
||||
mesh = self.ifc_importer.create_mesh(None, shape)
|
||||
tool.Loader.link_mesh(shape, mesh)
|
||||
except RuntimeError:
|
||||
# Fallback solution for invalid geometry provided by Revit. (InnerBoundaries cuting OuterBoundary)
|
||||
print(f"Failed to create mesh from IfcRelSpaceBoundary with ID {boundary.id()}. Geometry might be invalid")
|
||||
shape = ifcopenshell.geom.create_shape(self.fallback_settings, surface.OuterBoundary)
|
||||
mesh = bpy.data.meshes.new(str(surface.id()))
|
||||
bm = bmesh.new()
|
||||
verts = [bm.verts.new(shape.verts[i : i + 3]) for i in range(0, len(shape.verts), 3)]
|
||||
bm.faces.new(verts)
|
||||
for inner_boundary in surface.InnerBoundaries:
|
||||
shape = ifcopenshell.geom.create_shape(self.fallback_settings, inner_boundary)
|
||||
verts = [bm.verts.new(shape.verts[i : i + 3]) for i in range(0, len(shape.verts), 3)]
|
||||
for i in range(len(verts) - 1):
|
||||
bm.edges.new(verts[i : i + 2])
|
||||
bm.edges.new((verts[-1], verts[0]))
|
||||
bm.to_mesh(mesh)
|
||||
bm.free()
|
||||
mesh.BIMMeshProperties.ifc_definition_id = surface.id()
|
||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
matrix = mathutils.Matrix(
|
||||
ifcopenshell.util.placement.get_axis2placement(surface.BasisSurface.Position).tolist()
|
||||
)
|
||||
matrix.translation *= unit_scale
|
||||
mesh.transform(matrix)
|
||||
shape = ifcopenshell.geom.create_shape(self.settings, surface)
|
||||
mesh = self.ifc_importer.create_mesh(None, shape)
|
||||
self.ifc_importer.link_mesh(shape, mesh)
|
||||
return mesh
|
||||
|
||||
def load_settings(self):
|
||||
settings = ifcopenshell.geom.settings()
|
||||
settings.set(settings.EXCLUDE_SOLIDS_AND_SURFACES, False)
|
||||
settings.set(settings.USE_BREP_DATA, False)
|
||||
return settings
|
||||
|
||||
def load_fallback_settings(self):
|
||||
settings = ifcopenshell.geom.settings()
|
||||
settings.set(settings.INCLUDE_CURVES, True)
|
||||
return settings
|
||||
self.settings = ifcopenshell.geom.settings()
|
||||
self.settings.set(self.settings.EXCLUDE_SOLIDS_AND_SURFACES, False)
|
||||
self.settings.set(self.settings.USE_BREP_DATA, False)
|
||||
|
||||
def load_importer(self):
|
||||
self.ifc_file = tool.Ifc.get()
|
||||
@@ -126,7 +69,8 @@ class Loader:
|
||||
self.ifc_importer = import_ifc.IfcImporter(ifc_import_settings)
|
||||
self.ifc_importer.file = self.ifc_file
|
||||
|
||||
def load_boundary(self, boundary, blender_space):
|
||||
def load_boundary(self, boundary_id, blender_space):
|
||||
boundary = self.ifc_file.by_id(boundary_id)
|
||||
obj = tool.Ifc.get_object(boundary)
|
||||
if obj:
|
||||
return obj
|
||||
@@ -141,27 +85,32 @@ class Loader:
|
||||
|
||||
class LoadProjectSpaceBoundaries(bpy.types.Operator):
|
||||
bl_idname = "bim.load_project_space_boundaries"
|
||||
bl_label = "Load All Project Space Boundaries"
|
||||
bl_label = "Load all project space boundaries"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
loader = Loader()
|
||||
for rel in tool.Ifc.get().by_type("IfcRelSpaceBoundary"):
|
||||
loader.load_boundary(rel, tool.Ifc.get_object(rel.RelatingSpace))
|
||||
if not Data.is_loaded:
|
||||
Data.load(tool.Ifc.get())
|
||||
for space_id, boundaries_id in Data.spaces.items():
|
||||
blender_space = tool.Ifc.get_object(tool.Ifc.get().by_id(space_id))
|
||||
for boundary_id in boundaries_id:
|
||||
loader.load_boundary(boundary_id, blender_space)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class LoadBoundary(bpy.types.Operator):
|
||||
bl_idname = "bim.load_boundary"
|
||||
bl_label = "Load Boundary"
|
||||
bl_label = "Load boundary"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
boundary_id: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
loader = Loader()
|
||||
blender_space = context.active_object
|
||||
for obj in context.visible_objects:
|
||||
obj.select_set(False)
|
||||
obj = loader.load_boundary(tool.Ifc.get().by_id(self.boundary_id), context.active_object)
|
||||
obj = loader.load_boundary(self.boundary_id, blender_space)
|
||||
obj.select_set(True)
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
return {"FINISHED"}
|
||||
@@ -169,91 +118,32 @@ class LoadBoundary(bpy.types.Operator):
|
||||
|
||||
class LoadSpaceBoundaries(bpy.types.Operator):
|
||||
bl_idname = "bim.load_space_boundaries"
|
||||
bl_label = "Load Selected Space Boundaries"
|
||||
bl_label = "Load selected space boundaries"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
blender_space = context.active_object
|
||||
oprops = context.active_object.BIMObjectProperties
|
||||
loader = Loader()
|
||||
element = tool.Ifc.get_entity(context.active_object)
|
||||
for rel in element.BoundedBy or []:
|
||||
loader.load_boundary(rel, context.active_object)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
def get_element_boundaries(element):
|
||||
if not element:
|
||||
return ()
|
||||
if element.is_a("IfcSpace"):
|
||||
return (b for b in element.BoundedBy or ())
|
||||
return (b for b in element.ProvidesBoundaries)
|
||||
|
||||
|
||||
class SelectRelatedElementBoundaries(bpy.types.Operator):
|
||||
bl_idname = "bim.select_related_element_boundaries"
|
||||
bl_label = "Select Related Element Space Boundaries"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
related_element: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
for obj in context.visible_objects:
|
||||
obj.select_set(False)
|
||||
element = tool.Ifc.get().by_id(self.related_element)
|
||||
for rel in get_element_boundaries(element):
|
||||
obj = tool.Ifc.get_object(rel)
|
||||
if obj:
|
||||
obj.select_set(True)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class SelectRelatedElementTypeBoundaries(bpy.types.Operator):
|
||||
bl_idname = "bim.select_related_element_type_boundaries"
|
||||
bl_label = "Select Related Element Type Space Boundaries"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
related_element: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
for obj in context.visible_objects:
|
||||
obj.select_set(False)
|
||||
element = tool.Ifc.get().by_id(self.related_element)
|
||||
if not element:
|
||||
return {"FINISHED"}
|
||||
element_type = tool.Root.get_element_type(element)
|
||||
if not element_type:
|
||||
return {"FINISHED"}
|
||||
for child in tool.Type.get_type_occurrences(element_type):
|
||||
for rel in get_element_boundaries(child):
|
||||
obj = tool.Ifc.get_object(rel)
|
||||
if obj:
|
||||
obj.select_set(True)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class SelectSpaceBoundaries(bpy.types.Operator):
|
||||
bl_idname = "bim.select_space_boundaries"
|
||||
bl_label = "Select All Space Boundaries"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
for obj in context.visible_objects:
|
||||
obj.select_set(False)
|
||||
element = tool.Ifc.get_entity(context.active_object)
|
||||
for rel in element.BoundedBy or []:
|
||||
obj = tool.Ifc.get_object(rel)
|
||||
if obj:
|
||||
obj.select_set(True)
|
||||
if not Data.is_loaded:
|
||||
Data.load(tool.Ifc.get())
|
||||
for boundary_id in Data.spaces.get(oprops.ifc_definition_id, []):
|
||||
loader.load_boundary(boundary_id, blender_space)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class SelectProjectBoundaries(bpy.types.Operator):
|
||||
bl_idname = "bim.select_project_space_boundaries"
|
||||
bl_label = "Select All Project Space Boundaries"
|
||||
bl_label = "Select all project space boundaries"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
for obj in context.visible_objects:
|
||||
obj.select_set(False)
|
||||
for rel in tool.Ifc.get().by_type("IfcRelSpaceBoundary"):
|
||||
obj = tool.Ifc.get_object(rel)
|
||||
ifc_file = tool.Ifc.get()
|
||||
for boundary_id in Data.boundaries:
|
||||
boundary = ifc_file.by_id(boundary_id)
|
||||
obj = tool.Ifc.get_object(boundary)
|
||||
if obj:
|
||||
obj.select_set(True)
|
||||
return {"FINISHED"}
|
||||
@@ -282,7 +172,7 @@ def get_colour(ifc_boundary):
|
||||
|
||||
class ColourByRelatedBuildingElement(bpy.types.Operator):
|
||||
bl_idname = "bim.colour_by_related_building_element"
|
||||
bl_label = "Apply Colour Based on Related Building Elements"
|
||||
bl_label = "Apply colour based on related building elements"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
@@ -294,10 +184,11 @@ class ColourByRelatedBuildingElement(bpy.types.Operator):
|
||||
return result
|
||||
|
||||
def _execute(self, context):
|
||||
self.file = tool.Ifc.get()
|
||||
for obj in context.visible_objects:
|
||||
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||
continue
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
if not element.is_a("IfcRelSpaceBoundary"):
|
||||
continue
|
||||
obj.color = get_colour(element)
|
||||
@@ -330,7 +221,7 @@ EDITABLE_ATTRIBUTES = {
|
||||
|
||||
class EnableEditingBoundary(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_editing_boundary"
|
||||
bl_label = "Edit Boundary Relations"
|
||||
bl_label = "Edit boundary relations"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
@@ -349,7 +240,7 @@ class EnableEditingBoundary(bpy.types.Operator):
|
||||
|
||||
class DisableEditingBoundary(bpy.types.Operator):
|
||||
bl_idname = "bim.disable_editing_boundary"
|
||||
bl_label = "Disable Editing Boundary Relations"
|
||||
bl_label = "Disable editing boundary relations"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
@@ -362,7 +253,7 @@ class DisableEditingBoundary(bpy.types.Operator):
|
||||
|
||||
class EditBoundaryAttributes(bpy.types.Operator):
|
||||
bl_idname = "bim.edit_boundary_attributes"
|
||||
bl_label = "Disable Editing Boundary Relations"
|
||||
bl_label = "Disable editing boundary relations"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
@@ -383,7 +274,7 @@ class EditBoundaryAttributes(bpy.types.Operator):
|
||||
|
||||
class UpdateBoundaryGeometry(bpy.types.Operator):
|
||||
bl_idname = "bim.update_boundary_geometry"
|
||||
bl_label = "Update Boundary Geometry"
|
||||
bl_label = "Update boundary geometry"
|
||||
bl_description = """
|
||||
Update boundary connection geometry from mesh.
|
||||
Mesh must lie on a single plane. It should look like a face or a face with holes.
|
||||
@@ -398,357 +289,3 @@ class UpdateBoundaryGeometry(bpy.types.Operator):
|
||||
settings = tool.Boundary.get_assign_connection_geometry_settings(context.active_object)
|
||||
ifcopenshell.api.run("boundary.assign_connection_geometry", tool.Ifc.get(), **settings)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EnableEditingBoundaryGeometry(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.enable_editing_boundary_geometry"
|
||||
bl_label = "Enable Editing Boundary Geometry"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.selected_objects
|
||||
|
||||
def _execute(self, context):
|
||||
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
obj = context.active_object
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
|
||||
if element.ConnectionGeometry.is_a("IfcConnectionSurfaceGeometry"):
|
||||
surface = element.ConnectionGeometry.SurfaceOnRelatingElement
|
||||
tool.Model.import_surface(surface, obj)
|
||||
|
||||
bpy.ops.object.mode_set(mode="EDIT")
|
||||
ProfileDecorator.install(context, exit_edit_mode_callback=lambda: disable_editing_boundary_geometry(context))
|
||||
if not bpy.app.background:
|
||||
bpy.ops.wm.tool_set_by_id(tool.Blender.get_viewport_context(), name="bim.cad_tool")
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EditBoundaryGeometry(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.edit_boundary_geometry"
|
||||
bl_label = "Edit Boundary Geometry"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
ProfileDecorator.uninstall()
|
||||
bpy.ops.object.mode_set(mode="OBJECT")
|
||||
|
||||
obj = context.active_object
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
|
||||
if element.ConnectionGeometry.is_a("IfcConnectionSurfaceGeometry"):
|
||||
surface = tool.Model.export_surface(obj)
|
||||
|
||||
if not surface:
|
||||
|
||||
def msg(self, context):
|
||||
self.layout.label(text="INVALID PROFILE")
|
||||
|
||||
bpy.context.window_manager.popup_menu(msg, title="Error", icon="ERROR")
|
||||
ProfileDecorator.install(
|
||||
context, exit_edit_mode_callback=lambda: disable_editing_boundary_geometry(context)
|
||||
)
|
||||
bpy.ops.object.mode_set(mode="EDIT")
|
||||
return
|
||||
|
||||
old_surface = element.ConnectionGeometry.SurfaceOnRelatingElement
|
||||
for inverse in tool.Ifc.get().get_inverse(old_surface):
|
||||
ifcopenshell.util.element.replace_attribute(inverse, old_surface, surface)
|
||||
ifcopenshell.util.element.remove_deep2(tool.Ifc.get(), old_surface)
|
||||
|
||||
old_mesh = obj.data
|
||||
loader = Loader()
|
||||
obj.data = loader.create_mesh(element)
|
||||
tool.Geometry.delete_data(old_mesh)
|
||||
|
||||
|
||||
class DisableEditingBoundaryGeometry(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.disable_editing_boundary_geometry"
|
||||
bl_label = "Disable Editing Boundary Geometry"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.selected_objects
|
||||
|
||||
def _execute(self, context):
|
||||
return disable_editing_boundary_geometry(context)
|
||||
|
||||
|
||||
class ShowBoundaries(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.show_boundaries"
|
||||
bl_label = "Show Boundaries"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = bpy.context.scene.BIMBoundaryProperties
|
||||
loader = Loader()
|
||||
for obj in context.selected_objects:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element or not getattr(element, "BoundedBy", None):
|
||||
continue
|
||||
if tool.Ifc.is_moved(obj):
|
||||
blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj)
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
for rel in element.BoundedBy or []:
|
||||
boundary_obj = loader.load_boundary(rel, obj)
|
||||
tool.Boundary.decorate_boundary(boundary_obj)
|
||||
BoundaryDecorator.install(bpy.context)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class HideBoundaries(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.hide_boundaries"
|
||||
bl_label = "Hide Boundaries"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
to_delete = set()
|
||||
spaces = set()
|
||||
for obj in context.selected_objects:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element:
|
||||
continue
|
||||
if element.is_a("IfcSpace"):
|
||||
spaces.add(element)
|
||||
elif element.is_a("IfcRelSpaceBoundary"):
|
||||
spaces.add(element.RelatingSpace)
|
||||
|
||||
for element in spaces:
|
||||
for boundary in element.BoundedBy or []:
|
||||
boundary_obj = tool.Ifc.get_object(boundary)
|
||||
if boundary_obj:
|
||||
to_delete.add(boundary_obj)
|
||||
for boundary_obj in to_delete:
|
||||
tool.Ifc.unlink(obj=boundary_obj)
|
||||
bpy.data.objects.remove(boundary_obj)
|
||||
context.scene.BIMBoundaryProperties.boundaries.clear()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_boundary"
|
||||
bl_label = "Add Boundary"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
relating_space = None
|
||||
related_building_element = None
|
||||
relating_space_obj = None
|
||||
related_building_element_obj = None
|
||||
|
||||
objs = context.selected_objects
|
||||
if len(objs) == 2:
|
||||
# The user may select two objects, a space and its related building element
|
||||
for obj in objs:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element:
|
||||
continue
|
||||
if element.is_a("IfcSpace"):
|
||||
relating_space = element
|
||||
relating_space_obj = obj
|
||||
else:
|
||||
related_building_element = element
|
||||
related_building_element_obj = obj
|
||||
elif len(objs) == 1:
|
||||
# Optionally the user may select just the space, and the building element shall be auto-detected
|
||||
|
||||
def msg(self, context):
|
||||
self.layout.label(text="NO ACTIVE STOREY")
|
||||
|
||||
element = tool.Ifc.get_entity(objs[0])
|
||||
if element.is_a("IfcSpace"):
|
||||
relating_space = element
|
||||
relating_space_obj = objs[0]
|
||||
|
||||
target = bpy.context.scene.cursor.location
|
||||
|
||||
collection = context.view_layer.active_layer_collection.collection
|
||||
collection_obj = bpy.data.objects.get(collection.name)
|
||||
if not collection_obj:
|
||||
bpy.context.window_manager.popup_menu(msg, title="Error", icon="ERROR")
|
||||
return
|
||||
spatial_element = tool.Ifc.get_entity(collection_obj)
|
||||
if not spatial_element:
|
||||
bpy.context.window_manager.popup_menu(msg, title="Error", icon="ERROR")
|
||||
return
|
||||
|
||||
for subelement in ifcopenshell.util.element.get_decomposition(spatial_element):
|
||||
if not (subelement.is_a("IfcWall") or subelement.is_a("IfcSlab")):
|
||||
continue
|
||||
obj = tool.Ifc.get_object(subelement)
|
||||
if obj:
|
||||
raycast = obj.closest_point_on_mesh(obj.matrix_world.inverted() @ target, distance=0.1)
|
||||
if raycast[0]:
|
||||
related_building_element = subelement
|
||||
related_building_element_obj = obj
|
||||
break
|
||||
|
||||
if not relating_space or not related_building_element:
|
||||
return
|
||||
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(relating_space_obj.data)
|
||||
bmesh.ops.dissolve_limit(bm, angle_limit=pi * 2 / 360, verts=bm.verts, edges=bm.edges)
|
||||
|
||||
target_distance = inf
|
||||
target_face = None
|
||||
for face in bm.faces:
|
||||
centroid = relating_space_obj.matrix_world @ face.calc_center_median()
|
||||
raycast = related_building_element_obj.closest_point_on_mesh(
|
||||
related_building_element_obj.matrix_world.inverted() @ centroid, distance=1
|
||||
)
|
||||
if raycast[0]:
|
||||
distance = (related_building_element_obj.matrix_world @ raycast[1] - centroid).length
|
||||
if distance < target_distance:
|
||||
target_face = face
|
||||
target_distance = distance
|
||||
|
||||
if not target_face:
|
||||
return
|
||||
|
||||
parent_boundary = tool.Ifc.run("root.create_entity", ifc_class=context.scene.BIMModelProperties.boundary_class)
|
||||
|
||||
# Is this right? Or should I use loop?
|
||||
target_face_verts = [v.co.copy() for v in target_face.verts]
|
||||
target_face_matrix = self.get_face_matrix(*[v.copy() for v in target_face_verts[0:3]])
|
||||
target_face_matrix_i = target_face_matrix.inverted()
|
||||
|
||||
target_face_polygon = shapely.Polygon([tuple((target_face_matrix_i @ v).xy) for v in target_face_verts])
|
||||
|
||||
related_building_element_polygon = self.get_flattened_polygon(
|
||||
related_building_element, relating_space_obj, target_face_matrix_i
|
||||
)
|
||||
|
||||
gross_boundary_polygon = target_face_polygon.intersection(related_building_element_polygon)
|
||||
|
||||
if type(gross_boundary_polygon) == shapely.GeometryCollection:
|
||||
for geom in gross_boundary_polygon.geoms:
|
||||
if type(geom) == shapely.Polygon:
|
||||
gross_boundary_polygon = geom
|
||||
break
|
||||
|
||||
# The gross boundary polygon may not be a true gross boundary since it
|
||||
# may have openings already removed, such as in IFC4 Reference View. So
|
||||
# we cheat by using the exterior boundary to mean "gross". Later, we
|
||||
# can use this to check whether or not the opening is relevant to our
|
||||
# space.
|
||||
exterior_boundary_polygon = shapely.Polygon(gross_boundary_polygon.exterior.coords)
|
||||
|
||||
net_boundary_polygon = shapely.Polygon(gross_boundary_polygon)
|
||||
|
||||
inner_boundaries = []
|
||||
|
||||
for rel in getattr(related_building_element, "HasOpenings", []):
|
||||
opening = rel.RelatedOpeningElement
|
||||
filling = None
|
||||
if opening.HasFillings:
|
||||
filling = opening.HasFillings[0].RelatedBuildingElement
|
||||
|
||||
opening_polygon = self.get_flattened_polygon(opening, relating_space_obj, target_face_matrix_i)
|
||||
|
||||
net_boundary_polygon = net_boundary_polygon.difference(opening_polygon)
|
||||
# Only openings that are projected onto our exterior boundary are relevant.
|
||||
if opening_polygon.intersection(exterior_boundary_polygon).area == 0:
|
||||
continue
|
||||
|
||||
connection_geometry = self.create_connection_geometry_from_polygon(opening_polygon, target_face_matrix)
|
||||
boundary = tool.Ifc.run("root.create_entity", ifc_class=context.scene.BIMModelProperties.boundary_class)
|
||||
boundary.RelatingSpace = relating_space
|
||||
boundary.RelatedBuildingElement = filling or related_building_element
|
||||
boundary.ConnectionGeometry = connection_geometry
|
||||
boundary.PhysicalOrVirtualBoundary = "PHYSICAL" if filling else "VIRTUAL"
|
||||
boundary.InternalOrExternalBoundary = "INTERNAL"
|
||||
|
||||
if boundary.is_a("IfcRelSpaceBoundary2ndLevel"):
|
||||
boundary.ParentBoundary = parent_boundary
|
||||
|
||||
connection_geometry = self.create_connection_geometry_from_polygon(net_boundary_polygon, target_face_matrix)
|
||||
parent_boundary.RelatingSpace = relating_space
|
||||
parent_boundary.RelatedBuildingElement = related_building_element
|
||||
parent_boundary.ConnectionGeometry = connection_geometry
|
||||
parent_boundary.PhysicalOrVirtualBoundary = "PHYSICAL"
|
||||
parent_boundary.InternalOrExternalBoundary = "INTERNAL"
|
||||
|
||||
bpy.ops.bim.show_boundaries()
|
||||
obj = tool.Ifc.get_object(parent_boundary)
|
||||
obj.select_set(True)
|
||||
|
||||
def get_face_matrix(self, p1, p2, p3):
|
||||
edge1 = p2 - p1
|
||||
edge2 = p3 - p1
|
||||
normal = edge1.cross(edge2)
|
||||
z_axis = normal.normalized()
|
||||
x_axis = p2 - p1
|
||||
x_axis.normalize()
|
||||
y_axis = z_axis.cross(x_axis)
|
||||
|
||||
mat = Matrix()
|
||||
mat.col[0][:3] = x_axis
|
||||
mat.col[1][:3] = y_axis
|
||||
mat.col[2][:3] = z_axis
|
||||
mat.translation = p1
|
||||
|
||||
return mat
|
||||
|
||||
def get_flattened_polygon(self, element, relating_space_obj, target_face_matrix_i):
|
||||
obj = tool.Ifc.get_object(element)
|
||||
if obj and tool.Ifc.is_moved(obj):
|
||||
blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj)
|
||||
|
||||
space_matrix_i = relating_space_obj.matrix_world.inverted()
|
||||
|
||||
settings = ifcopenshell.geom.settings()
|
||||
if not element.is_a("IfcOpeningElement"):
|
||||
settings.set(settings.DISABLE_OPENING_SUBTRACTIONS, True)
|
||||
settings.set(settings.STRICT_TOLERANCE, True)
|
||||
# geometry = ifcopenshell.geom.create_shape(settings, body)
|
||||
shape = ifcopenshell.geom.create_shape(settings, element)
|
||||
m = shape.transformation.matrix.data
|
||||
mat = Matrix(([m[0], m[3], m[6], m[9]], [m[1], m[4], m[7], m[10]], [m[2], m[5], m[8], m[11]], [0, 0, 0, 1]))
|
||||
verts = [space_matrix_i @ mat @ Vector(v) for v in ifcopenshell.util.shape.get_vertices(shape.geometry)]
|
||||
faces = ifcopenshell.util.shape.get_faces(shape.geometry)
|
||||
polygons = []
|
||||
for face in faces:
|
||||
polygon = shapely.Polygon([tuple((target_face_matrix_i @ verts[vi]).xy) for vi in face])
|
||||
polygons.append(polygon)
|
||||
return shapely.ops.unary_union(polygons)
|
||||
|
||||
def create_connection_geometry_from_polygon(self, polygon, target_face_matrix):
|
||||
surface = self.export_surface(polygon, target_face_matrix)
|
||||
return tool.Ifc.get().createIfcConnectionSurfaceGeometry(surface)
|
||||
|
||||
def export_surface(self, polygon, target_face_matrix):
|
||||
x_axis = target_face_matrix.col[0][:3]
|
||||
z_axis = target_face_matrix.col[2][:3]
|
||||
p1 = target_face_matrix.translation
|
||||
|
||||
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
tool.Model.unit_scale = self.unit_scale
|
||||
|
||||
surface = tool.Ifc.get().createIfcCurveBoundedPlane()
|
||||
surface.BasisSurface = tool.Ifc.get().createIfcPlane(tool.Ifc.get().createIfcAxis2Placement3D(
|
||||
tool.Ifc.get().createIfcCartesianPoint([o / self.unit_scale for o in p1]),
|
||||
tool.Ifc.get().createIfcDirection([float(o) for o in z_axis]),
|
||||
tool.Ifc.get().createIfcDirection([float(o) for o in x_axis]),
|
||||
))
|
||||
|
||||
if tool.Ifc.get().schema != "IFC2X3":
|
||||
points = [tool.Model.convert_si_to_unit(list(co)) for co in polygon.exterior.coords]
|
||||
point_list = tool.Ifc.get().createIfcCartesianPointList2D(points)
|
||||
outer_boundary = tool.Ifc.get().createIfcIndexedPolyCurve(point_list, None, False)
|
||||
|
||||
inner_boundaries = []
|
||||
for interior in polygon.interiors:
|
||||
points = [tool.Model.convert_si_to_unit(list(co)) for co in interior.coords]
|
||||
point_list = tool.Ifc.get().createIfcCartesianPointList2D(points)
|
||||
inner_boundaries.append(tool.Ifc.get().createIfcIndexedPolyCurve(point_list, None, False))
|
||||
else:
|
||||
pass # TODO
|
||||
|
||||
surface.OuterBoundary = outer_boundary
|
||||
surface.InnerBoundaries = inner_boundaries
|
||||
|
||||
return surface
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
import bpy
|
||||
from bpy.types import PropertyGroup
|
||||
from blenderbim.bim.prop import ObjProperty
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
@@ -53,13 +52,9 @@ def element_filter(self, object):
|
||||
return False
|
||||
|
||||
|
||||
class BIMObjectBoundaryProperties(PropertyGroup):
|
||||
class BIMBoundaryProperties(PropertyGroup):
|
||||
is_editing: BoolProperty(name="Is Editing")
|
||||
relating_space: PointerProperty(name="RelatingSpace", type=bpy.types.Object, poll=space_filter)
|
||||
related_building_element: PointerProperty(name="RelatedBuildingElement", type=bpy.types.Object, poll=element_filter)
|
||||
parent_boundary: PointerProperty(name="ParentBoundary", type=bpy.types.Object, poll=boundary_filter)
|
||||
corresponding_boundary: PointerProperty(name="CorrespondingBoundary", type=bpy.types.Object, poll=boundary_filter)
|
||||
|
||||
|
||||
class BIMBoundaryProperties(PropertyGroup):
|
||||
boundaries: bpy.props.CollectionProperty(type=ObjProperty)
|
||||
|
||||
@@ -21,11 +21,11 @@ import blenderbim.bim.helper
|
||||
from bpy.types import Panel, UIList
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
import blenderbim.tool as tool
|
||||
from blenderbim.bim.module.boundary.data import SpaceBoundariesData
|
||||
from ifcopenshell.api.boundary.data import Data
|
||||
|
||||
|
||||
class BIM_PT_SceneBoundaries(Panel):
|
||||
bl_label = "Space Boundaries"
|
||||
bl_label = "IFC Space Boundaries"
|
||||
bl_id_name = "BIM_PT_scene_boundaries"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
@@ -45,12 +45,12 @@ class BIM_PT_SceneBoundaries(Panel):
|
||||
|
||||
|
||||
class BIM_PT_Boundary(Panel):
|
||||
bl_label = "Space Boundary"
|
||||
bl_label = "IFC Space Boundary"
|
||||
bl_idname = "BIM_PT_Boundary"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "object"
|
||||
bl_parent_id = "BIM_PT_tab_geometric_relationships"
|
||||
bl_parent_id = "BIM_PT_geometry_object"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -102,11 +102,6 @@ class BIM_PT_Boundary(Panel):
|
||||
row.label(text=f"{entity.is_a()}/{entity.Name}")
|
||||
op = row.operator("bim.select_global_id", text="", icon="OBJECT_DATA")
|
||||
op.global_id = entity.GlobalId
|
||||
if ifc_attribute in ("RelatingSpace", "RelatedBuildingElement"):
|
||||
op = row.operator("bim.select_related_element_boundaries", text="", icon="RESTRICT_SELECT_OFF")
|
||||
op.related_element = entity.id()
|
||||
op = row.operator("bim.select_related_element_type_boundaries", text="", icon="ASSET_MANAGER")
|
||||
op.related_element = entity.id()
|
||||
else:
|
||||
row.label(text="")
|
||||
|
||||
@@ -117,14 +112,13 @@ class BIM_PT_Boundary(Panel):
|
||||
|
||||
|
||||
class BIM_PT_SpaceBoundaries(Panel):
|
||||
bl_label = "Space Boundaries"
|
||||
bl_label = "IFC Space Boundaries"
|
||||
bl_idname = "BIM_PT_SpaceBoundaries"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "object"
|
||||
bl_order = 1
|
||||
bl_parent_id = "BIM_PT_tab_geometric_relationships"
|
||||
bl_parent_id = "BIM_PT_geometry_object"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -135,23 +129,28 @@ class BIM_PT_SpaceBoundaries(Panel):
|
||||
return False
|
||||
if not IfcStore.get_element(props.ifc_definition_id):
|
||||
return False
|
||||
element = tool.Ifc.get_entity(context.active_object)
|
||||
for ifc_class in ("IfcSpace", "IfcExternalSpatialElement"):
|
||||
if element.is_a(ifc_class):
|
||||
valid_classes = ("IfcSpace", "IfcExternalSpatialElement")
|
||||
entity = IfcStore.get_file().by_id(props.ifc_definition_id)
|
||||
for ifc_class in valid_classes:
|
||||
if entity.is_a(ifc_class):
|
||||
return True
|
||||
return False
|
||||
|
||||
def draw(self, context):
|
||||
if not SpaceBoundariesData.is_loaded:
|
||||
SpaceBoundariesData.load()
|
||||
|
||||
self.props = context.active_object.BIMObjectProperties
|
||||
self.ifc_file = tool.Ifc.get()
|
||||
row = self.layout.row()
|
||||
row.operator("bim.load_space_boundaries")
|
||||
row.operator("bim.select_space_boundaries", text="", icon="RESTRICT_SELECT_OFF")
|
||||
for boundary in SpaceBoundariesData.data["boundaries"]:
|
||||
if not Data.is_loaded:
|
||||
Data.load(self.ifc_file)
|
||||
for boundary_id in Data.spaces.get(self.props.ifc_definition_id, []):
|
||||
boundary_data = Data.boundaries[boundary_id]
|
||||
building_element = self.ifc_file.by_id(boundary_data["RelatedBuildingElement"])
|
||||
row = self.layout.row()
|
||||
row.label(text=boundary["description"], icon="GHOST_ENABLED")
|
||||
if building_element:
|
||||
bld_el_description = f"{building_element.is_a()}/{building_element.Name}"
|
||||
else:
|
||||
bld_el_description = None
|
||||
row.label(text=f"{boundary_id} > {bld_el_description}", icon="GHOST_ENABLED")
|
||||
op = row.operator("bim.load_boundary", text="", icon="RESTRICT_SELECT_OFF")
|
||||
op.boundary_id = boundary["id"]
|
||||
op.boundary_id = boundary_id
|
||||
|
||||
@@ -21,7 +21,7 @@ from . import ui, prop, operator
|
||||
|
||||
classes = (
|
||||
operator.AddBrick,
|
||||
operator.AddBrickRelation,
|
||||
operator.AddBrickFeed,
|
||||
operator.AssignBrickReference,
|
||||
operator.CloseBrickProject,
|
||||
operator.ConvertBrickProject,
|
||||
@@ -33,10 +33,6 @@ classes = (
|
||||
operator.RewindBrickClass,
|
||||
operator.ViewBrickClass,
|
||||
operator.ViewBrickItem,
|
||||
operator.SerializeBrick,
|
||||
operator.AddBrickNamespace,
|
||||
operator.SetBrickListRoot,
|
||||
operator.RemoveBrickRelation,
|
||||
prop.Brick,
|
||||
prop.BIMBrickProperties,
|
||||
ui.BIM_PT_brickschema,
|
||||
|
||||
@@ -41,7 +41,9 @@ class BrickschemaData:
|
||||
cls.is_loaded = True
|
||||
cls.data = {
|
||||
"is_loaded": cls.get_is_loaded(),
|
||||
"active_relations": cls.active_relations(),
|
||||
"attributes": cls.attributes(),
|
||||
"namespaces": cls.namespaces(),
|
||||
"brick_equipment_classes": cls.brick_equipment_classes(),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
@@ -49,7 +51,7 @@ class BrickschemaData:
|
||||
return BrickStore.graph is not None
|
||||
|
||||
@classmethod
|
||||
def active_relations(cls):
|
||||
def attributes(cls):
|
||||
if BrickStore.graph is None:
|
||||
return []
|
||||
props = bpy.context.scene.BIMBrickProperties
|
||||
@@ -57,55 +59,76 @@ class BrickschemaData:
|
||||
brick = props.bricks[props.active_brick_index]
|
||||
except:
|
||||
return []
|
||||
results = []
|
||||
uri = brick.uri
|
||||
namespace = str(uri.split("#")[0])
|
||||
if namespace == "https://brickschema.org/schema/Brick":
|
||||
query = BrickStore.graph.query(
|
||||
"""
|
||||
PREFIX brick: <https://brickschema.org/schema/Brick#>
|
||||
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
||||
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
||||
SELECT DISTINCT ?name ?value ?sp ?sv WHERE {
|
||||
<{uri}> ?name ?value .
|
||||
OPTIONAL {
|
||||
{ ?name rdfs:range brick:TimeseriesReference . }
|
||||
UNION
|
||||
{ ?name a brick:EntityProperty . }
|
||||
?value ?sp ?sv }
|
||||
}
|
||||
""".replace(
|
||||
"{uri}", uri
|
||||
)
|
||||
)
|
||||
|
||||
for row in query:
|
||||
name = row.get("name").toPython().split("#")[-1]
|
||||
value = row.get("value")
|
||||
results.append(
|
||||
{
|
||||
"name": name,
|
||||
"value": value.toPython().split("#")[-1],
|
||||
"is_uri": isinstance(value, URIRef),
|
||||
"value_uri": value.toPython(),
|
||||
"is_globalid": name == "globalID",
|
||||
}
|
||||
)
|
||||
if isinstance(row.get("value"), BNode):
|
||||
for s, p, o in BrickStore.graph.triples((value, None, None)):
|
||||
results.append(
|
||||
{
|
||||
"name": name + ":" + p.toPython().split("#")[-1],
|
||||
"value": o.toPython().split("#")[-1],
|
||||
"is_uri": isinstance(o, URIRef),
|
||||
"value_uri": o.toPython(),
|
||||
"is_globalid": p.toPython().split("#")[-1] == "globalID",
|
||||
}
|
||||
)
|
||||
return results
|
||||
|
||||
@classmethod
|
||||
def namespaces(cls):
|
||||
if BrickStore.graph is None:
|
||||
return []
|
||||
results = []
|
||||
for alias, uri in BrickStore.graph.namespaces():
|
||||
results.append((uri, f"{alias}: {uri}", ""))
|
||||
return results
|
||||
|
||||
@classmethod
|
||||
def brick_equipment_classes(cls):
|
||||
if BrickStore.graph is None:
|
||||
return []
|
||||
results = []
|
||||
query = BrickStore.graph.query(
|
||||
"""
|
||||
PREFIX brick: <https://brickschema.org/schema/Brick#>
|
||||
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
||||
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
||||
SELECT DISTINCT ?predicate ?object ?sp ?sv WHERE {
|
||||
<{uri}> ?predicate ?object .
|
||||
OPTIONAL {
|
||||
{ ?predicate rdfs:range brick:TimeseriesReference . }
|
||||
UNION
|
||||
{ ?predicate a brick:EntityProperty . }
|
||||
?object ?sp ?sv }
|
||||
SELECT ?class WHERE {
|
||||
?class rdfs:subClassOf* brick:Equipment .
|
||||
}
|
||||
""".replace(
|
||||
"{uri}", uri
|
||||
)
|
||||
"""
|
||||
)
|
||||
for row in query:
|
||||
predicate = row.get("predicate")
|
||||
predicate_name = predicate.toPython().split("#")[-1]
|
||||
object = row.get("object")
|
||||
object_name = object.toPython().split("#")[-1]
|
||||
results.append(
|
||||
{
|
||||
"predicate": predicate,
|
||||
"predicate_name": predicate_name,
|
||||
"object": object,
|
||||
"object_name": object_name,
|
||||
"is_uri": isinstance(object, URIRef),
|
||||
"object_uri": object.toPython(),
|
||||
"is_globalid": predicate == "globalID",
|
||||
}
|
||||
)
|
||||
# if isinstance(row.get("object"), BNode):
|
||||
# for s, p, o in BrickStore.graph.triples((object, None, None)):
|
||||
# results.append(
|
||||
# {
|
||||
# "predicate": predicate + ":" + p.toPython().split("#")[-1],
|
||||
# "object": o.toPython().split("#")[-1],
|
||||
# "is_uri": isinstance(o, URIRef),
|
||||
# "object_uri": o.toPython(),
|
||||
# "is_globalid": p.toPython().split("#")[-1] == "globalID",
|
||||
# }
|
||||
# )
|
||||
for uri in sorted([x[0].toPython() for x in query]):
|
||||
results.append((uri, uri.split("#")[-1], ""))
|
||||
return results
|
||||
|
||||
|
||||
|
||||
@@ -16,19 +16,17 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import bpy
|
||||
import ifcopenshell.api
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.core.brick as core
|
||||
import blenderbim.bim.handler
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.tool.brick import BrickStore
|
||||
|
||||
|
||||
class Operator:
|
||||
def execute(self, context):
|
||||
IfcStore.execute_ifc_operator(self, context)
|
||||
self._execute(context)
|
||||
blenderbim.bim.handler.refresh_ui_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -41,11 +39,7 @@ class LoadBrickProject(bpy.types.Operator, Operator):
|
||||
filter_glob: bpy.props.StringProperty(default="*.ttl", options={"HIDDEN"})
|
||||
|
||||
def _execute(self, context):
|
||||
if os.path.exists(self.filepath) and "ttl" in os.path.splitext(self.filepath)[1].lower():
|
||||
root = context.scene.BIMBrickProperties.brick_list_root
|
||||
core.load_brick_project(tool.Brick, filepath=self.filepath, brick_root=root)
|
||||
else:
|
||||
self.report({'ERROR'}, f'Failed to load {self.filepath}')
|
||||
core.load_brick_project(tool.Brick, filepath=self.filepath)
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.fileselect_add(self)
|
||||
@@ -57,10 +51,9 @@ class ViewBrickClass(bpy.types.Operator, Operator):
|
||||
bl_label = "View Brick Class"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
brick_class: bpy.props.StringProperty(name="Brick Class")
|
||||
split_screen: bpy.props.BoolProperty(name="Split Screen", default=False, options={"HIDDEN"})
|
||||
|
||||
def _execute(self, context):
|
||||
core.view_brick_class(tool.Brick, brick_class=self.brick_class, split_screen=self.split_screen)
|
||||
core.view_brick_class(tool.Brick, brick_class=self.brick_class)
|
||||
|
||||
|
||||
class ViewBrickItem(bpy.types.Operator, Operator):
|
||||
@@ -68,20 +61,18 @@ class ViewBrickItem(bpy.types.Operator, Operator):
|
||||
bl_label = "View Brick Item"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
item: bpy.props.StringProperty(name="Brick Item")
|
||||
split_screen: bpy.props.BoolProperty(name="Split Screen", default=False, options={"HIDDEN"})
|
||||
|
||||
def _execute(self, context):
|
||||
core.view_brick_item(tool.Brick, item=self.item, split_screen=self.split_screen)
|
||||
core.view_brick_item(tool.Brick, item=self.item)
|
||||
|
||||
|
||||
class RewindBrickClass(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.rewind_brick_class"
|
||||
bl_label = "Rewind Brick Class"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
split_screen: bpy.props.BoolProperty(name="Split Screen", default=False, options={"HIDDEN"})
|
||||
|
||||
def _execute(self, context):
|
||||
core.rewind_brick_class(tool.Brick, split_screen=self.split_screen)
|
||||
core.rewind_brick_class(tool.Brick)
|
||||
|
||||
|
||||
class CloseBrickProject(bpy.types.Operator, Operator):
|
||||
@@ -133,31 +124,24 @@ class AddBrick(bpy.types.Operator, Operator):
|
||||
tool.Brick,
|
||||
element=tool.Ifc.get_entity(context.active_object) if context.selected_objects else None,
|
||||
namespace=props.namespace,
|
||||
brick_class=props.brick_entity_class,
|
||||
brick_class=props.brick_equipment_class,
|
||||
library=library,
|
||||
label=props.new_brick_label,
|
||||
)
|
||||
|
||||
|
||||
class AddBrickRelation(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.add_brick_relation"
|
||||
bl_label = "Add Brick Relation"
|
||||
class AddBrickFeed(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.add_brick_feed"
|
||||
bl_label = "Add Brick Feed"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMBrickProperties
|
||||
brick = props.bricks[props.active_brick_index]
|
||||
if props.new_brick_relation_type == "http://www.w3.org/2000/01/rdf-schema#label":
|
||||
object = props.new_brick_relation_object
|
||||
elif props.split_screen_toggled:
|
||||
object = props.split_screen_bricks[props.split_screen_active_brick_index].uri
|
||||
else:
|
||||
object = props.new_brick_relation_namespace + props.new_brick_relation_object
|
||||
core.add_brick_relation(
|
||||
source = tool.Ifc.get_entity([o for o in context.selected_objects if o != context.active_object][0])
|
||||
destination = tool.Ifc.get_entity(context.active_object)
|
||||
core.add_brick_feed(
|
||||
tool.Ifc,
|
||||
tool.Brick,
|
||||
brick_uri=brick.uri,
|
||||
predicate=props.new_brick_relation_type,
|
||||
object=object
|
||||
source=source,
|
||||
destination=destination,
|
||||
)
|
||||
|
||||
|
||||
@@ -174,46 +158,22 @@ class ConvertIfcToBrick(bpy.types.Operator, Operator):
|
||||
core.convert_ifc_to_brick(tool.Brick, namespace=props.namespace, library=library)
|
||||
|
||||
|
||||
class NewBrickFile(bpy.types.Operator):
|
||||
class NewBrickFile(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.new_brick_file"
|
||||
bl_label = "New Brick File"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
IfcStore.begin_transaction(self)
|
||||
IfcStore.add_transaction_operation(self, rollback=self.rollback, commit=lambda data: True)
|
||||
self._execute(context)
|
||||
self.transaction_data = {
|
||||
"schema": BrickStore.schema,
|
||||
"path": BrickStore.path,
|
||||
"graph": BrickStore.graph,
|
||||
}
|
||||
IfcStore.add_transaction_operation(self, rollback=lambda data: True, commit=self.commit)
|
||||
IfcStore.end_transaction(self)
|
||||
blenderbim.bim.handler.refresh_ui_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
def _execute(self, context):
|
||||
root = context.scene.BIMBrickProperties.brick_list_root
|
||||
core.new_brick_file(tool.Brick, brick_root=root)
|
||||
|
||||
def rollback(self, data):
|
||||
BrickStore.purge()
|
||||
|
||||
def commit(self, data):
|
||||
BrickStore.schema = data["schema"]
|
||||
BrickStore.path = data["path"]
|
||||
BrickStore.graph = data["graph"]
|
||||
core.new_brick_file(tool.Brick)
|
||||
|
||||
|
||||
class RefreshBrickViewer(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.refresh_brick_viewer"
|
||||
bl_label = "Refresh Brick Viewer"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
split_screen: bpy.props.BoolProperty(name="Split Screen", default=False, options={"HIDDEN"})
|
||||
|
||||
def _execute(self, context):
|
||||
core.refresh_brick_viewer(tool.Brick, split_screen=self.split_screen)
|
||||
core.refresh_brick_viewer(tool.Brick)
|
||||
|
||||
|
||||
class RemoveBrick(bpy.types.Operator, Operator):
|
||||
@@ -229,69 +189,3 @@ class RemoveBrick(bpy.types.Operator, Operator):
|
||||
library=tool.Ifc.get().by_id(int(props.libraries)) if props.libraries else None,
|
||||
brick_uri=props.bricks[props.active_brick_index].uri,
|
||||
)
|
||||
|
||||
|
||||
class SerializeBrick(bpy.types.Operator):
|
||||
bl_idname = "bim.serialize_brick"
|
||||
bl_label = "Serialize Brick"
|
||||
filter_glob: bpy.props.StringProperty(default="*.ttl", options={"HIDDEN"})
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
should_save_as: bpy.props.BoolProperty(name="Should Save As", default=False, options={"HIDDEN"})
|
||||
|
||||
def invoke(self, context, event):
|
||||
if self.should_save_as or not BrickStore.path:
|
||||
WindowManager = context.window_manager
|
||||
WindowManager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
else:
|
||||
return self.execute(context)
|
||||
|
||||
def execute(self, context):
|
||||
if self.should_save_as or not BrickStore.path:
|
||||
BrickStore.path = self.filepath
|
||||
core.serialize_brick(tool.Brick)
|
||||
return {"FINISHED"}
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, properties):
|
||||
if properties.should_save_as:
|
||||
return "Save Brick project to a selected file"
|
||||
return "Save the Brick project"
|
||||
|
||||
|
||||
class AddBrickNamespace(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.add_brick_namespace"
|
||||
bl_label = "Add Brick Namespace"
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMBrickProperties
|
||||
alias = props.new_brick_namespace_alias
|
||||
uri = props.new_brick_namespace_uri
|
||||
core.add_namespace(tool.Brick, alias=alias, uri=uri)
|
||||
|
||||
|
||||
class SetBrickListRoot(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.set_brick_list_root"
|
||||
bl_label = "Set Brick View Type"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
split_screen: bpy.props.BoolProperty(name="Split Screen", default=False, options={"HIDDEN"})
|
||||
|
||||
def _execute(self, context):
|
||||
if self.split_screen:
|
||||
root = context.scene.BIMBrickProperties.split_screen_brick_list_root
|
||||
else:
|
||||
root = context.scene.BIMBrickProperties.brick_list_root
|
||||
core.set_brick_list_root(tool.Brick, brick_root=root, split_screen=self.split_screen)
|
||||
|
||||
|
||||
class RemoveBrickRelation(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.remove_brick_relation"
|
||||
bl_label = "Remove Relation"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
predicate: bpy.props.StringProperty(name="Relation")
|
||||
object: bpy.props.StringProperty(name="Object")
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMBrickProperties
|
||||
brick = props.bricks[props.active_brick_index]
|
||||
core.remove_brick_relation(tool.Brick, brick_uri=brick.uri, predicate=self.predicate, object=self.object)
|
||||
@@ -30,7 +30,7 @@ from bpy.props import (
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
from blenderbim.tool.brick import BrickStore
|
||||
|
||||
|
||||
def update_active_brick_index(self, context):
|
||||
BrickschemaData.is_loaded = False
|
||||
@@ -43,26 +43,15 @@ def get_libraries(self, context):
|
||||
|
||||
|
||||
def get_namespaces(self, context):
|
||||
return BrickStore.namespaces
|
||||
if not BrickschemaData.is_loaded:
|
||||
BrickschemaData.load()
|
||||
return BrickschemaData.data["namespaces"]
|
||||
|
||||
|
||||
def get_brick_entity_classes(self, context):
|
||||
entity = self.brick_entity_create_type
|
||||
return BrickStore.entity_classes[entity]
|
||||
|
||||
|
||||
def get_brick_roots(self, context):
|
||||
return [(root, root, "") for root in BrickStore.root_classes]
|
||||
|
||||
|
||||
def get_brick_relations(self, context):
|
||||
def is_label(relation):
|
||||
return relation["predicate_name"] == "label"
|
||||
if not list(filter(is_label, BrickschemaData.data["active_relations"])):
|
||||
new_relations = BrickStore.relationships.copy()
|
||||
new_relations.append(("http://www.w3.org/2000/01/rdf-schema#label", "label", ""))
|
||||
return new_relations
|
||||
return BrickStore.relationships
|
||||
def get_brick_equipment_classes(self, context):
|
||||
if not BrickschemaData.is_loaded:
|
||||
BrickschemaData.load()
|
||||
return BrickschemaData.data["brick_equipment_classes"]
|
||||
|
||||
|
||||
class Brick(PropertyGroup):
|
||||
@@ -78,28 +67,5 @@ class BIMBrickProperties(PropertyGroup):
|
||||
bricks: CollectionProperty(name="Bricks", type=Brick)
|
||||
active_brick_index: IntProperty(name="Active Brick Index", update=update_active_brick_index)
|
||||
libraries: EnumProperty(name="Libraries", items=get_libraries)
|
||||
set_list_root_toggled: BoolProperty(name="Set List Root Toggled", default=False)
|
||||
brick_list_root: EnumProperty(name="Brick List Root", items=get_brick_roots)
|
||||
# namespace manager
|
||||
namespace: EnumProperty(name="Namespace", items=get_namespaces)
|
||||
brick_settings_toggled: BoolProperty(name="Brick Settings Toggled", default=False)
|
||||
new_brick_namespace_alias: StringProperty(name="New Brick Namespace Alias")
|
||||
new_brick_namespace_uri: StringProperty(name="New Brick Namespace URI")
|
||||
# create brick entity
|
||||
new_brick_label: StringProperty(name="New Brick Label")
|
||||
brick_entity_create_type: EnumProperty(name="Brick Entity Types", items=get_brick_roots)
|
||||
brick_entity_class: EnumProperty(name="Brick Equipment Class", items=get_brick_entity_classes)
|
||||
# create relations
|
||||
brick_create_relations_toggled: BoolProperty(name="Brick Create Relations Toggled", default=False)
|
||||
brick_edit_relations_toggled: BoolProperty(name="Brick Edit Relations Toggled", default=False)
|
||||
new_brick_relation_type: EnumProperty(name="New Brick Relation Type", items=get_brick_relations)
|
||||
new_brick_relation_namespace: EnumProperty(name="New Brick Relation Namespace", items=get_namespaces)
|
||||
new_brick_relation_object: StringProperty(name="New Brick Relation Object")
|
||||
add_relation_failed: BoolProperty(name="Add Relation Failed", default=False)
|
||||
# create relations split screen
|
||||
split_screen_toggled: BoolProperty(name="Split Screen Toggled", default=False)
|
||||
split_screen_bricks: CollectionProperty(name="Split Screen Bricks", type=Brick)
|
||||
split_screen_active_brick_index: IntProperty(name="Split Screen Active Brick Index", update=update_active_brick_index)
|
||||
split_screen_active_brick_class: StringProperty(name="Split Screen Active Brick Class")
|
||||
split_screen_brick_breadcrumbs: CollectionProperty(name="Split Screen Brick Breadcrumbs", type=StrProperty)
|
||||
split_screen_brick_list_root: EnumProperty(name="Split Screen Brick List Root", items=get_brick_roots)
|
||||
brick_equipment_class: EnumProperty(name="Brick Equipment Class", items=get_brick_equipment_classes)
|
||||
|
||||
@@ -20,16 +20,15 @@ import blenderbim.tool as tool
|
||||
from bpy.types import Panel, UIList
|
||||
from blenderbim.bim.helper import prop_with_search
|
||||
from blenderbim.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData
|
||||
from blenderbim.tool.brick import BrickStore
|
||||
|
||||
|
||||
class BIM_PT_brickschema(Panel):
|
||||
bl_label = "Brickschema Project"
|
||||
bl_idname = "BIM_PT_brickschema"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_operations"
|
||||
|
||||
def draw(self, context):
|
||||
if not BrickschemaData.is_loaded:
|
||||
@@ -42,154 +41,39 @@ class BIM_PT_brickschema(Panel):
|
||||
row.operator("bim.load_brick_project", text="Load Project")
|
||||
return
|
||||
|
||||
if BrickStore.path:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=BrickStore.path, icon="FILEBROWSER")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
op = row.operator("bim.serialize_brick", icon="EXPORT", text="Save")
|
||||
op.should_save_as = False
|
||||
op = row.operator("bim.serialize_brick", icon="FILE_TICK", text="Save As")
|
||||
op.should_save_as = True
|
||||
if len(self.props.brick_breadcrumbs):
|
||||
row.operator("bim.rewind_brick_class", text="", icon="FRAME_PREV")
|
||||
row.label(text=self.props.active_brick_class)
|
||||
row.operator("bim.refresh_brick_viewer", text="", icon="FILE_REFRESH")
|
||||
row.operator("bim.close_brick_project", text="", icon="CANCEL")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(data=self.props, property="brick_settings_toggled", text="", icon="PREFERENCES")
|
||||
|
||||
if self.props.brick_settings_toggled:
|
||||
box = self.layout.box()
|
||||
row = box.row(align=True)
|
||||
row.label(text="Active Namespace:")
|
||||
|
||||
row = box.row(align=True)
|
||||
prop_with_search(row, self.props, "namespace", text="")
|
||||
|
||||
row = box.row(align=True)
|
||||
row.label(text="Bind New Namespace:")
|
||||
|
||||
row = box.row(align=True)
|
||||
row.prop(data=self.props, property="new_brick_namespace_alias", text="")
|
||||
col = row.column()
|
||||
col.alignment = "CENTER"
|
||||
col.scale_x = 1.1
|
||||
col.label(text=":")
|
||||
row.prop(data=self.props, property="new_brick_namespace_uri", text="")
|
||||
row.operator("bim.add_brick_namespace", text="", icon="ADD")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="Create Entity:")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(data=self.props, property="brick_entity_create_type", text="")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(data=self.props, property="new_brick_label", text="")
|
||||
prop_with_search(row, self.props, "brick_entity_class", text="")
|
||||
prop_with_search(row, self.props, "namespace", text="")
|
||||
prop_with_search(row, self.props, "brick_equipment_class", text="")
|
||||
row.operator("bim.add_brick", text="", icon="ADD")
|
||||
# row.operator("bim.refresh_brick_viewer", text="", icon="FILE_REFRESH")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
col = row.column()
|
||||
col.alignment = "RIGHT"
|
||||
row.prop(data=self.props, property="split_screen_toggled", text="", icon="WINDOW")
|
||||
row.alignment = "RIGHT"
|
||||
row.operator("bim.add_brick_feed", text="", icon="PLUGIN")
|
||||
row.operator("bim.remove_brick", text="", icon="X")
|
||||
|
||||
grid = self.layout.grid_flow(even_columns=True)
|
||||
grid1 = grid.column(align=True)
|
||||
row = grid1.row(align=True)
|
||||
if len(self.props.brick_breadcrumbs):
|
||||
op = row.operator("bim.rewind_brick_class", text="", icon="FRAME_PREV")
|
||||
op.split_screen = False
|
||||
row.prop(data=self.props, property="set_list_root_toggled", text="", icon="OUTLINER")
|
||||
row.label(text=self.props.active_brick_class)
|
||||
self.layout.template_list("BIM_UL_bricks", "", self.props, "bricks", self.props, "active_brick_index")
|
||||
|
||||
if self.props.set_list_root_toggled:
|
||||
row = grid1.row(align=True)
|
||||
op = row.operator("bim.set_brick_list_root", text="Set View")
|
||||
op.split_screen = False
|
||||
row.prop(data=self.props, property="brick_list_root", text="")
|
||||
|
||||
row = grid1.row()
|
||||
BIM_UL_bricks.split_screen = False
|
||||
row.template_list("BIM_UL_bricks", "", self.props, "bricks", self.props, "active_brick_index")
|
||||
|
||||
if self.props.split_screen_toggled:
|
||||
grid2 = grid.column(align=True)
|
||||
row = grid2.row(align=True)
|
||||
if len(self.props.split_screen_brick_breadcrumbs):
|
||||
op = row.operator("bim.rewind_brick_class", text="", icon="FRAME_PREV")
|
||||
op.split_screen = True
|
||||
row.label(text=self.props.split_screen_active_brick_class)
|
||||
|
||||
if self.props.set_list_root_toggled:
|
||||
row = grid2.row(align=True)
|
||||
op = row.operator("bim.set_brick_list_root", text="Set View")
|
||||
op.split_screen = True
|
||||
row.prop(data=self.props, property="split_screen_brick_list_root", text="")
|
||||
|
||||
row = grid2.row()
|
||||
BIM_UL_bricks.split_screen = True
|
||||
row.template_list("BIM_UL_bricks", "", self.props, "split_screen_bricks", self.props, "split_screen_active_brick_index")
|
||||
|
||||
if BrickschemaData.data["active_relations"]:
|
||||
for attribute in BrickschemaData.data["attributes"]:
|
||||
row = self.layout.row(align=True)
|
||||
col = row.column()
|
||||
col.alignment = "RIGHT"
|
||||
row.prop(data=self.props, property="brick_create_relations_toggled", text="", icon="PLUGIN")
|
||||
row.prop(data=self.props, property="brick_edit_relations_toggled", text="", icon="TOOL_SETTINGS")
|
||||
row.operator("bim.remove_brick", text="", icon="X")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="Create Relation:")
|
||||
|
||||
if self.props.brick_create_relations_toggled and self.props.new_brick_relation_type == "http://www.w3.org/2000/01/rdf-schema#label":
|
||||
row = self.layout.row(align=True)
|
||||
prop_with_search(row, self.props, "new_brick_relation_type", text="")
|
||||
row.prop(data=self.props, property="new_brick_relation_object", text="")
|
||||
row.operator("bim.add_brick_relation", text="", icon="ADD")
|
||||
|
||||
elif self.props.brick_create_relations_toggled and self.props.split_screen_toggled:
|
||||
row = self.layout.row(align=True)
|
||||
split_screen_selection = self.props.split_screen_bricks[self.props.split_screen_active_brick_index]
|
||||
if split_screen_selection.total_items:
|
||||
row.label(text="No selection", icon="INFO")
|
||||
else:
|
||||
prop_with_search(row, self.props, "new_brick_relation_type", text="")
|
||||
row.label(text=split_screen_selection.label if split_screen_selection.label else split_screen_selection.name)
|
||||
row.operator("bim.add_brick_relation", text="", icon="ADD")
|
||||
|
||||
elif self.props.brick_create_relations_toggled:
|
||||
row = self.layout.row(align=True)
|
||||
prop_with_search(row, self.props, "new_brick_relation_namespace", text="")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
prop_with_search(row, self.props, "new_brick_relation_type", text="")
|
||||
row.prop(data=self.props, property="new_brick_relation_object", text="")
|
||||
row.operator("bim.add_brick_relation", text="", icon="ADD")
|
||||
|
||||
|
||||
if self.props.brick_create_relations_toggled and self.props.add_relation_failed:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="Failed to find this entity!", icon="ERROR")
|
||||
|
||||
|
||||
for relation in BrickschemaData.data["active_relations"]:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=relation["predicate_name"])
|
||||
row.label(text=relation["object_name"])
|
||||
if self.props.brick_edit_relations_toggled and relation["predicate_name"] != "type":
|
||||
op = row.operator("bim.remove_brick_relation", text="", icon="UNLINKED")
|
||||
op.predicate = relation["predicate"]
|
||||
op.object = relation["object"]
|
||||
if relation["is_uri"] and relation["predicate_name"] != "type":
|
||||
row.label(text=attribute["name"])
|
||||
row.label(text=attribute["value"])
|
||||
if attribute["is_uri"]:
|
||||
op = row.operator("bim.view_brick_item", text="", icon="DISCLOSURE_TRI_RIGHT")
|
||||
op.item = relation["object_uri"]
|
||||
if relation["is_globalid"]:
|
||||
op.item = attribute["value_uri"]
|
||||
if attribute["is_globalid"]:
|
||||
op = row.operator("bim.select_global_id", icon="RESTRICT_SELECT_OFF", text="")
|
||||
op.global_id = relation["object_name"]
|
||||
op.global_id = attribute["value"]
|
||||
|
||||
|
||||
class BIM_PT_ifc_brickschema_references(Panel):
|
||||
bl_label = "Brickschema References"
|
||||
bl_label = "IFC Brickschema References"
|
||||
bl_idname = "BIM_PT_ifc_brickschema_references"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
@@ -238,15 +122,12 @@ class BIM_PT_ifc_brickschema_references(Panel):
|
||||
|
||||
|
||||
class BIM_UL_bricks(UIList):
|
||||
split_screen = False
|
||||
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
label = item.label if item.label else item.name
|
||||
if item.total_items:
|
||||
op = row.operator("bim.view_brick_class", text="", icon="DISCLOSURE_TRI_RIGHT", emboss=False)
|
||||
op.brick_class = item.name
|
||||
op.split_screen = self.split_screen
|
||||
label = label + " (" + str(item.total_items) + ")"
|
||||
row.label(text=label)
|
||||
row.label(text=item.label if item.label else item.name)
|
||||
if item.total_items:
|
||||
row.label(text=str(item.total_items))
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
import bpy
|
||||
from blenderbim.bim.module.model.data import AuthoringData
|
||||
from blenderbim.bim.module.model.root import ConstrTypeEntityNotFound
|
||||
from bpy.types import PropertyGroup
|
||||
from math import pi
|
||||
|
||||
|
||||
class BIMCadProperties(PropertyGroup):
|
||||
@@ -28,7 +28,3 @@ class BIMCadProperties(PropertyGroup):
|
||||
distance: bpy.props.FloatProperty(name="Distance", default=0.1)
|
||||
x: bpy.props.FloatProperty(name="X", default=0.2)
|
||||
y: bpy.props.FloatProperty(name="Y", default=0.1)
|
||||
gable_roof_edge_angle: bpy.props.FloatProperty(
|
||||
name="Gable Roof Edge Angle", default=pi / 2, soft_min=0, soft_max=pi / 2, subtype="ANGLE"
|
||||
)
|
||||
gable_roof_separate_verts: bpy.props.BoolProperty(name="Separate Verts", default=True)
|
||||
|
||||
@@ -21,7 +21,7 @@ import bpy
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.bim.module.type.prop as type_prop
|
||||
from bpy.types import WorkSpaceTool
|
||||
from blenderbim.bim.module.model.data import AuthoringData, RailingData, RoofData
|
||||
from blenderbim.bim.module.model.data import AuthoringData
|
||||
|
||||
|
||||
class CadTool(WorkSpaceTool):
|
||||
@@ -33,7 +33,8 @@ class CadTool(WorkSpaceTool):
|
||||
bl_description = "Gives you CAD authoring related superpowers"
|
||||
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.cad")
|
||||
bl_widget = None
|
||||
bl_keymap = tool.Blender.get_default_selection_keypmap() + (
|
||||
# https://docs.blender.org/api/current/bpy.types.KeyMapItems.html
|
||||
bl_keymap = (
|
||||
("bim.cad_hotkey", {"type": "C", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_C")]}),
|
||||
("bim.cad_hotkey", {"type": "E", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_E")]}),
|
||||
("bim.cad_hotkey", {"type": "F", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_F")]}),
|
||||
@@ -45,27 +46,20 @@ class CadTool(WorkSpaceTool):
|
||||
("bim.cad_hotkey", {"type": "X", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_X")]}),
|
||||
)
|
||||
|
||||
def draw_settings(context, layout, workspace_tool):
|
||||
def draw_settings(context, layout, tool):
|
||||
obj = context.active_object
|
||||
if not obj or not obj.data:
|
||||
return
|
||||
if hasattr(obj.data, "BIMMeshProperties") and obj.data.BIMMeshProperties.subshape_type == "PROFILE":
|
||||
if obj and obj.data and hasattr(obj.data, "BIMMeshProperties") and obj.data.BIMMeshProperties.is_profile:
|
||||
row = layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_Q")
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if element:
|
||||
if element.is_a("IfcProfileDef"):
|
||||
row.operator("bim.edit_arbitrary_profile", text="Save Profile")
|
||||
row.operator("bim.align_view_to_profile", text="", icon="AXIS_FRONT")
|
||||
row.operator("bim.disable_editing_arbitrary_profile", text="", icon="CANCEL")
|
||||
elif element.is_a("IfcRelSpaceBoundary"):
|
||||
row.operator("bim.edit_boundary_geometry", text="Save Profile")
|
||||
row.operator("bim.disable_editing_boundary_geometry", text="", icon="CANCEL")
|
||||
else:
|
||||
row.operator("bim.edit_extrusion_profile", text="Save Profile")
|
||||
row.operator("bim.align_view_to_profile", text="", icon="AXIS_FRONT")
|
||||
row.operator("bim.disable_editing_extrusion_profile", text="", icon="CANCEL")
|
||||
if obj.BIMObjectProperties.ifc_definition_id:
|
||||
row.operator("bim.edit_extrusion_profile", text="Save Profile")
|
||||
row.operator("bim.align_view_to_profile", text="", icon="AXIS_FRONT")
|
||||
row.operator("bim.disable_editing_extrusion_profile", text="", icon="CANCEL")
|
||||
else:
|
||||
row.operator("bim.edit_arbitrary_profile", text="Save Profile")
|
||||
row.operator("bim.align_view_to_profile", text="", icon="AXIS_FRONT")
|
||||
row.operator("bim.disable_editing_arbitrary_profile", text="", icon="CANCEL")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
@@ -106,60 +100,7 @@ class CadTool(WorkSpaceTool):
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_X")
|
||||
row.operator("bim.reset_vertex", text="Reset Vertex")
|
||||
|
||||
elif hasattr(obj.data, "BIMMeshProperties") and obj.data.BIMMeshProperties.subshape_type == "AXIS":
|
||||
row = layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_Q")
|
||||
row.operator("bim.edit_extrusion_axis", text="Save Axis")
|
||||
row.operator("bim.disable_editing_extrusion_axis", text="", icon="CANCEL")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_E")
|
||||
row.operator("bim.cad_hotkey", text="Extend").hotkey = "S_E"
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_T")
|
||||
row.operator("bim.cad_hotkey", text="Mitre").hotkey = "S_T"
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_F")
|
||||
row.operator("bim.cad_hotkey", text="Fillet").hotkey = "S_F"
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_O")
|
||||
row.operator("bim.cad_hotkey", text="Offset").hotkey = "S_O"
|
||||
|
||||
else:
|
||||
if (
|
||||
(RailingData.is_loaded or not RailingData.load())
|
||||
and RailingData.data["pset_data"]
|
||||
and context.active_object.BIMRailingProperties.is_editing_path
|
||||
):
|
||||
row = layout.row(align=True)
|
||||
row.label(text="", icon=f"EVENT_TAB")
|
||||
row.operator("bim.finish_editing_railing_path")
|
||||
row.operator("bim.cancel_editing_railing_path", icon="CANCEL", text="")
|
||||
|
||||
elif (
|
||||
(RoofData.is_loaded or not RoofData.load())
|
||||
and RoofData.data["pset_data"]
|
||||
and context.active_object.BIMRoofProperties.is_editing_path
|
||||
):
|
||||
row = layout.row(align=True)
|
||||
row.label(text="", icon=f"EVENT_TAB")
|
||||
row.operator("bim.finish_editing_roof_path")
|
||||
row.operator("bim.cancel_editing_roof_path", icon="CANCEL", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_R")
|
||||
row.operator("bim.cad_hotkey", text="Set Gable Roof Angle").hotkey = "S_R"
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_E")
|
||||
@@ -207,32 +148,20 @@ class CadHotkey(bpy.types.Operator):
|
||||
if self.is_profile():
|
||||
row = self.layout.row()
|
||||
row.prop(props, "radius")
|
||||
|
||||
elif self.hotkey == "S_F":
|
||||
if not self.is_profile():
|
||||
row = self.layout.row()
|
||||
row.prop(props, "resolution")
|
||||
row = self.layout.row()
|
||||
row.prop(props, "radius")
|
||||
|
||||
elif self.hotkey == "S_O":
|
||||
row = self.layout.row()
|
||||
row.prop(props, "distance")
|
||||
|
||||
elif self.hotkey == "S_R":
|
||||
if self.is_profile():
|
||||
row = self.layout.row()
|
||||
row.prop(props, "x")
|
||||
row = self.layout.row()
|
||||
row.prop(props, "y")
|
||||
elif (
|
||||
(RoofData.is_loaded or not RoofData.load())
|
||||
and RoofData.data["pset_data"]
|
||||
and bpy.context.active_object.BIMRoofProperties.is_editing_path
|
||||
):
|
||||
self.layout.row().prop(props, "gable_roof_edge_angle")
|
||||
self.layout.row().prop(props, "gable_roof_separate_verts")
|
||||
|
||||
row = self.layout.row()
|
||||
row.prop(props, "x")
|
||||
row = self.layout.row()
|
||||
row.prop(props, "y")
|
||||
elif self.hotkey == "S_V":
|
||||
if not self.is_profile():
|
||||
row = self.layout.row()
|
||||
@@ -257,28 +186,14 @@ class CadHotkey(bpy.types.Operator):
|
||||
bpy.ops.bim.cad_offset(distance=self.props.distance)
|
||||
|
||||
def hotkey_S_Q(self):
|
||||
element = tool.Ifc.get_entity(bpy.context.active_object)
|
||||
if bpy.context.active_object.data.BIMMeshProperties.subshape_type == "PROFILE":
|
||||
if element.is_a("IfcProfileDef"):
|
||||
bpy.ops.bim.edit_arbitrary_profile()
|
||||
elif element.is_a("IfcRelSpaceBoundary"):
|
||||
bpy.ops.bim.edit_boundary_geometry()
|
||||
else:
|
||||
bpy.ops.bim.edit_extrusion_profile()
|
||||
elif bpy.context.active_object.data.BIMMeshProperties.subshape_type == "AXIS":
|
||||
bpy.ops.bim.edit_extrusion_axis()
|
||||
if tool.Ifc.get_entity(bpy.context.active_object):
|
||||
bpy.ops.bim.edit_extrusion_profile()
|
||||
else:
|
||||
bpy.ops.bim.edit_arbitrary_profile()
|
||||
|
||||
def hotkey_S_R(self):
|
||||
if self.is_profile():
|
||||
bpy.ops.bim.add_rectangle(x=self.props.x, y=self.props.y)
|
||||
elif (
|
||||
(RoofData.is_loaded or not RoofData.load())
|
||||
and RoofData.data["pset_data"]
|
||||
and bpy.context.active_object.BIMRoofProperties.is_editing_path
|
||||
):
|
||||
bpy.ops.bim.set_gable_roof_edge_angle(
|
||||
angle=self.props.gable_roof_edge_angle, separate_verts=self.props.gable_roof_separate_verts
|
||||
)
|
||||
|
||||
def hotkey_S_T(self):
|
||||
bpy.ops.bim.cad_mitre()
|
||||
@@ -295,9 +210,4 @@ class CadHotkey(bpy.types.Operator):
|
||||
|
||||
def is_profile(self):
|
||||
obj = bpy.context.active_object
|
||||
return (
|
||||
obj
|
||||
and obj.data
|
||||
and hasattr(obj.data, "BIMMeshProperties")
|
||||
and obj.data.BIMMeshProperties.subshape_type == "PROFILE"
|
||||
)
|
||||
return obj and obj.data and hasattr(obj.data, "BIMMeshProperties") and obj.data.BIMMeshProperties.is_profile
|
||||
|
||||
@@ -22,8 +22,7 @@ import json
|
||||
import bmesh
|
||||
import logging
|
||||
import numpy as np
|
||||
import ifcopenshell
|
||||
from mathutils import Matrix, Vector
|
||||
from mathutils import Matrix
|
||||
from math import radians
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
@@ -31,10 +30,8 @@ from blenderbim.bim.ifc import IfcStore
|
||||
class ExportClashSets(bpy.types.Operator):
|
||||
bl_idname = "bim.export_clash_sets"
|
||||
bl_label = "Export Clash Sets"
|
||||
bl_description = "Export clash sets to a selected file"
|
||||
filename_ext = ".json"
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
filter_glob: bpy.props.StringProperty(default="*.json", options={"HIDDEN"})
|
||||
|
||||
def invoke(self, context, event):
|
||||
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".json")
|
||||
@@ -65,10 +62,8 @@ class ImportClashSets(bpy.types.Operator):
|
||||
bl_idname = "bim.import_clash_sets"
|
||||
bl_label = "Import Clash Sets"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Import clash sets from a selected file"
|
||||
filename_ext = ".json"
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
filter_glob: bpy.props.StringProperty(default="*.json", options={"HIDDEN"})
|
||||
|
||||
def invoke(self, context, event):
|
||||
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".json")
|
||||
@@ -103,7 +98,6 @@ class AddClashSet(bpy.types.Operator):
|
||||
bl_idname = "bim.add_clash_set"
|
||||
bl_label = "Add Clash Set"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Add a clash set"
|
||||
|
||||
def execute(self, context):
|
||||
new = context.scene.BIMClashProperties.clash_sets.add()
|
||||
@@ -116,7 +110,6 @@ class RemoveClashSet(bpy.types.Operator):
|
||||
bl_idname = "bim.remove_clash_set"
|
||||
bl_label = "Remove Clash Set"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Remove the selected clash set"
|
||||
index: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
@@ -128,7 +121,6 @@ class AddClashSource(bpy.types.Operator):
|
||||
bl_idname = "bim.add_clash_source"
|
||||
bl_label = "Add Clash Source"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Add a clash source to this group"
|
||||
group: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
@@ -141,7 +133,6 @@ class RemoveClashSource(bpy.types.Operator):
|
||||
bl_idname = "bim.remove_clash_source"
|
||||
bl_label = "Remove Clash Source"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Remove this clash source"
|
||||
index: bpy.props.IntProperty()
|
||||
group: bpy.props.StringProperty()
|
||||
|
||||
@@ -155,7 +146,6 @@ class SelectClashSource(bpy.types.Operator):
|
||||
bl_idname = "bim.select_clash_source"
|
||||
bl_label = "Select Clash Source"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Select an IFC file to add as a clash source"
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
filter_glob: bpy.props.StringProperty(default="*.ifc", options={"HIDDEN"})
|
||||
index: bpy.props.IntProperty()
|
||||
@@ -204,13 +194,11 @@ class SelectSmartGroupedClashesPath(bpy.types.Operator):
|
||||
class ExecuteIfcClash(bpy.types.Operator):
|
||||
bl_idname = "bim.execute_ifc_clash"
|
||||
bl_label = "Execute IFC Clash"
|
||||
bl_description = "Execute clash detection and save the information to a .bcf or .json file"
|
||||
filter_glob: bpy.props.StringProperty(default="*.bcf;*.json", options={"HIDDEN"})
|
||||
filename_ext = ".bcf"
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
|
||||
def invoke(self, context, event):
|
||||
_, extension = os.path.splitext(self.filepath)
|
||||
if extension != ".json":
|
||||
if ".json" not in bpy.data.filepath:
|
||||
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".bcf")
|
||||
WindowManager = context.window_manager
|
||||
WindowManager.fileselect_add(self)
|
||||
@@ -219,11 +207,9 @@ class ExecuteIfcClash(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
from ifcclash import ifcclash
|
||||
|
||||
_, extension = os.path.splitext(self.filepath)
|
||||
if extension != ".json":
|
||||
self.filepath = bpy.path.ensure_ext(self.filepath, ".bcf")
|
||||
|
||||
settings = ifcclash.ClashSettings()
|
||||
if ".json" not in self.filepath:
|
||||
self.filepath = bpy.path.ensure_ext(self.filepath, ".bcf")
|
||||
settings.output = self.filepath
|
||||
settings.logger = logging.getLogger("Clash")
|
||||
settings.logger.setLevel(logging.DEBUG)
|
||||
@@ -231,28 +217,12 @@ class ExecuteIfcClash(bpy.types.Operator):
|
||||
|
||||
if context.scene.BIMClashProperties.should_create_clash_snapshots:
|
||||
|
||||
def get_viewpoint_snapshot(viewpoint):
|
||||
def get_viewpoint_snapshot(viewpoint, mat):
|
||||
camera = bpy.data.objects.get("IFC Clash Camera")
|
||||
if not camera:
|
||||
camera = bpy.data.objects.new("IFC Clash Camera", bpy.data.cameras.new("IFC Clash Camera"))
|
||||
context.scene.collection.objects.link(camera)
|
||||
|
||||
bcf_camera = viewpoint.visualization_info.perspective_camera
|
||||
p = bcf_camera.camera_view_point
|
||||
z = bcf_camera.camera_direction
|
||||
z = Vector([z.x, z.y, z.z]) * -1
|
||||
y = bcf_camera.camera_up_vector
|
||||
y = Vector([y.x, y.y, y.z])
|
||||
x = y.cross(z)
|
||||
|
||||
mat = Matrix([
|
||||
[x[0], y[0], z[0], p.x],
|
||||
[x[1], y[1], z[1], p.y],
|
||||
[x[2], y[2], z[2], p.z],
|
||||
[0, 0, 0, 0],
|
||||
])
|
||||
|
||||
camera.matrix_world = mat
|
||||
camera.matrix_world = Matrix(mat)
|
||||
context.scene.camera = camera
|
||||
camera.data.angle = radians(60)
|
||||
area = next(area for area in context.screen.areas if area.type == "VIEW_3D")
|
||||
@@ -263,8 +233,7 @@ class ExecuteIfcClash(bpy.types.Operator):
|
||||
context.scene.render.image_settings.file_format = "PNG"
|
||||
context.scene.render.filepath = os.path.join(context.scene.BIMProperties.data_dir, "snapshot.png")
|
||||
bpy.ops.render.opengl(write_still=True)
|
||||
with open(context.scene.render.filepath, "rb") as f:
|
||||
return ("snapshot.png", f.read())
|
||||
return context.scene.render.filepath
|
||||
|
||||
clasher.get_viewpoint_snapshot = get_viewpoint_snapshot
|
||||
|
||||
@@ -292,7 +261,6 @@ class SelectIfcClashResults(bpy.types.Operator):
|
||||
bl_idname = "bim.select_ifc_clash_results"
|
||||
bl_label = "Select IFC Clash Results"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Select the clashing IFC geometry stored in a file"
|
||||
filename_ext = ".json"
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
|
||||
@@ -303,7 +271,6 @@ class SelectIfcClashResults(bpy.types.Operator):
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
self.filepath = bpy.path.ensure_ext(self.filepath, ".json")
|
||||
with open(self.filepath) as f:
|
||||
clash_sets = json.load(f)
|
||||
@@ -317,26 +284,10 @@ class SelectIfcClashResults(bpy.types.Operator):
|
||||
return {"CANCELLED"}
|
||||
for clash in clash_set["clashes"].values():
|
||||
global_ids.extend([clash["a_global_id"], clash["b_global_id"]])
|
||||
|
||||
for obj in context.visible_objects:
|
||||
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||
continue
|
||||
|
||||
ifc_file = ""
|
||||
for scene in obj.users_scene:
|
||||
if scene.BIMProperties.ifc_file:
|
||||
ifc_file = scene.BIMProperties.ifc_file
|
||||
if scene.library:
|
||||
break
|
||||
|
||||
if ifc_file:
|
||||
if ifc_file not in IfcStore.session_files:
|
||||
IfcStore.session_files[ifc_file] = ifcopenshell.open(ifc_file)
|
||||
element_file = IfcStore.session_files[ifc_file]
|
||||
else:
|
||||
element_file = self.file
|
||||
|
||||
element = element_file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
if element.GlobalId in global_ids:
|
||||
obj.select_set(True)
|
||||
return {"FINISHED"}
|
||||
@@ -353,14 +304,14 @@ class SmartClashGroup(bpy.types.Operator):
|
||||
return context.scene.BIMClashProperties.clash_results_path
|
||||
|
||||
def execute(self, context):
|
||||
from ifcclash import ifcclash
|
||||
import ifcclash
|
||||
|
||||
settings = ifcclash.ClashSettings()
|
||||
settings = ifcclash.IfcClashSettings()
|
||||
self.filepath = bpy.path.ensure_ext(context.scene.BIMClashProperties.clash_results_path, ".json")
|
||||
settings.output = self.filepath
|
||||
settings.logger = logging.getLogger("Clash")
|
||||
settings.logger.setLevel(logging.DEBUG)
|
||||
ifc_clasher = ifcclash.Clasher(settings)
|
||||
ifc_clasher = ifcclash.IfcClasher(settings)
|
||||
|
||||
with open(self.filepath) as f:
|
||||
clash_sets = json.load(f)
|
||||
|
||||