mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 14:31:39 +00:00
Merge remote-tracking branch 'origin/v0.8.0' into test-ci
This commit is contained in:
@@ -114,6 +114,7 @@ jobs:
|
|||||||
-DPYTHON_INCLUDE_DIR:PATH=${{ env.pythonLocation }}/include/python3.11 \
|
-DPYTHON_INCLUDE_DIR:PATH=${{ env.pythonLocation }}/include/python3.11 \
|
||||||
-DPYTHON_LIBRARY:FILEPATH=${{ env.pythonLocation }}/lib/libpython3.11.so \
|
-DPYTHON_LIBRARY:FILEPATH=${{ env.pythonLocation }}/lib/libpython3.11.so \
|
||||||
-DCOLLADA_SUPPORT=Off \
|
-DCOLLADA_SUPPORT=Off \
|
||||||
|
-DUSE_MMAP=On \
|
||||||
"-DSCHEMA_VERSIONS=2x3;4;4x3_add2" \
|
"-DSCHEMA_VERSIONS=2x3;4;4x3_add2" \
|
||||||
-DGLTF_SUPPORT=On \
|
-DGLTF_SUPPORT=On \
|
||||||
-DWITH_ROCKSDB=On \
|
-DWITH_ROCKSDB=On \
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
# #
|
# #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
# ruff: noqa: UP035
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Example usage:
|
Example usage:
|
||||||
# Build all targets by default.
|
# Build all targets by default.
|
||||||
|
|||||||
@@ -487,7 +487,11 @@ def sync_references(
|
|||||||
continue
|
continue
|
||||||
if (obj := ifc.get_object(element)) and ifc.is_moved(obj):
|
if (obj := ifc.get_object(element)) and ifc.is_moved(obj):
|
||||||
drawing_tool.sync_object_placement(obj)
|
drawing_tool.sync_object_placement(obj)
|
||||||
reference_element = drawing_tool.get_assigned_product(element)
|
if not (reference_element := drawing_tool.get_assigned_product(element)):
|
||||||
|
if obj := ifc.get_object(element):
|
||||||
|
drawing_tool.delete_object(obj)
|
||||||
|
ifc.run("root.remove_product", product=element)
|
||||||
|
continue
|
||||||
reference_obj = ifc.get_object(reference_element)
|
reference_obj = ifc.get_object(reference_element)
|
||||||
if reference_element not in potential_reference_elements:
|
if reference_element not in potential_reference_elements:
|
||||||
# It was auto created, so it makes sense to auto delete
|
# It was auto created, so it makes sense to auto delete
|
||||||
|
|||||||
@@ -786,17 +786,21 @@ class Model(bonsai.core.tool.Model):
|
|||||||
elif material.is_a("IfcMaterialLayerSet"):
|
elif material.is_a("IfcMaterialLayerSet"):
|
||||||
axis = ifcopenshell.util.element.get_pset(element, "EPset_Parametric", "LayerSetDirection")
|
axis = ifcopenshell.util.element.get_pset(element, "EPset_Parametric", "LayerSetDirection")
|
||||||
if axis is None:
|
if axis is None:
|
||||||
if element.is_a() in [
|
if element.is_a() in (
|
||||||
"IfcSlabType",
|
"IfcSlabType",
|
||||||
"IfcRoofType",
|
"IfcRoofType",
|
||||||
"IfcRampType",
|
"IfcRampType",
|
||||||
"IfcPlateType",
|
"IfcPlateType",
|
||||||
"IfcCovering",
|
"IfcSlab",
|
||||||
"IfcFurniture",
|
"IfcRoof",
|
||||||
]:
|
"IfcRamp",
|
||||||
|
"IfcPlate",
|
||||||
|
):
|
||||||
axis = "AXIS3"
|
axis = "AXIS3"
|
||||||
else:
|
elif element.is_a() in ("IfcWallType", "IfcWall"):
|
||||||
axis = "AXIS2"
|
axis = "AXIS2"
|
||||||
|
else:
|
||||||
|
return
|
||||||
return f"LAYER{axis[-1]}"
|
return f"LAYER{axis[-1]}"
|
||||||
elif material.is_a("IfcMaterialProfileSetUsage"):
|
elif material.is_a("IfcMaterialProfileSetUsage"):
|
||||||
# TODO: remove after we support editing profile usages with IfcRevolvedAreaSolid.
|
# TODO: remove after we support editing profile usages with IfcRevolvedAreaSolid.
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ import importlib
|
|||||||
import ifcopenshell.util.selector
|
import ifcopenshell.util.selector
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from typing import Literal, Union, Any, Callable, TYPE_CHECKING
|
from typing import Literal, Union, Any, TYPE_CHECKING
|
||||||
|
from collections.abc import Callable
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from openpyxl import Workbook
|
from openpyxl import Workbook
|
||||||
|
|||||||
@@ -367,11 +367,13 @@ void IfcGeom::Iterator::create_element_(ifcopenshell::geometry::Converter* kerne
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
if (!brep) {
|
if (!brep) {
|
||||||
|
Logger::SetProduct(boost::none);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto elem = process_based_on_settings(settings, brep);
|
auto elem = process_based_on_settings(settings, brep);
|
||||||
if (!elem) {
|
if (!elem) {
|
||||||
|
Logger::SetProduct(boost::none);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,6 +396,8 @@ void IfcGeom::Iterator::create_element_(ifcopenshell::geometry::Converter* kerne
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger::SetProduct(boost::none);
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcGeom::Element* IfcGeom::Iterator::process_based_on_settings(ifcopenshell::geometry::Settings settings, IfcGeom::BRepElement* elem, IfcGeom::TriangulationElement* previous)
|
IfcGeom::Element* IfcGeom::Iterator::process_based_on_settings(ifcopenshell::geometry::Settings settings, IfcGeom::BRepElement* elem, IfcGeom::TriangulationElement* previous)
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ Examples
|
|||||||
Learning how to use the bSDD is best done by reading the official Swagger API docs.
|
Learning how to use the bSDD is best done by reading the official Swagger API docs.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from bsdd import Client,apply_ifc_classification_properties
|
from bsdd import Client,apply_ifc_classification_properties
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
|
||||||
|
|||||||
@@ -17,4 +17,5 @@ capabilities of the C++ core are available in Python.
|
|||||||
ifcopenshell-python/geometry_creation
|
ifcopenshell-python/geometry_creation
|
||||||
ifcopenshell-python/geometry_tree
|
ifcopenshell-python/geometry_tree
|
||||||
ifcopenshell-python/selector_syntax
|
ifcopenshell-python/selector_syntax
|
||||||
ifcopenshell-python/developer_guide
|
ifcopenshell-python/schema_querying
|
||||||
|
ifcopenshell-python/validation
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
Developer Guide
|
|
||||||
===============
|
|
||||||
|
|
||||||
The core module implements low-level functionality to read and write IFC data. This includes:
|
|
||||||
|
|
||||||
- Reading IFC data from different serialisations into Python objects
|
|
||||||
- Accessing direct and indirect attributes of IFC entities
|
|
||||||
- Creating IFC entities
|
|
||||||
- Generating GlobalIds
|
|
||||||
- Removing IFC entities and all references
|
|
||||||
- Modifying IFC direct attributes
|
|
||||||
- Checking IFC class inheritance
|
|
||||||
- Validating IFC data
|
|
||||||
|
|
||||||
TODO
|
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
Schema querying
|
||||||
|
===============
|
||||||
|
|
||||||
|
Schema declarations
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
IfcOpenShell can query the IFC schema itself without instantiating or loading an IFC dataset.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import ifcopenshell
|
||||||
|
ifc4 = ifcopenshell.schema_by_name("IFC4")
|
||||||
|
|
||||||
|
A schema definition is known as a declaration. You may loop through all declarations or retrieve a declaration by name. All declarations have a name.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
for declaration in ifc4.declarations():
|
||||||
|
print(declaration.name()) # 'IfcAbsorbedDoseMeasure', 'IfcAccelerationMeasure', 'IfcActionRequest', ...
|
||||||
|
|
||||||
|
ifcwall = ifc4.declaration_by_name("IfcWall")
|
||||||
|
|
||||||
|
You can check if an entity is abstract, and retrive both the supertype and subtypes of an entity:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
print(ifcwall.is_abstract()) # False
|
||||||
|
print(ifcwall.supertype()) # <entity IfcBuildingElement>
|
||||||
|
print(ifcwall.subtypes()) # (<entity IfcWallElementedCase>, <entity IfcWallStandardCase>)
|
||||||
|
|
||||||
|
You can retrieve only the direct attributes of an entity, or all the direct attributes including inherited attributes, or inverse attributes:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
print(ifcwall.attributes())
|
||||||
|
print(ifcwall.all_attributes())
|
||||||
|
print(ifcwall.all_inverse_attributes())
|
||||||
|
|
||||||
|
buildingSMART property set templates
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
For each IFC schema version, buildingSMART publishes built in property and quantity set templates for standardised properties. These define property names, property sets, data types, and which IFC class they are applicable to. You can query these templates.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import ifcopenshell.util.pset
|
||||||
|
templates = ifcopenshell.util.pset.PsetQto("IFC4")
|
||||||
|
|
||||||
|
To get just the names of applicable templates for an entity:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# ['Pset_EnvironmentalImpactIndicators', 'Pset_EnvironmentalImpactValues', 'Pset_WallCommon', 'Qto_WallBaseQuantities', ...]
|
||||||
|
print(templates.get_applicable_names("IfcWall"))
|
||||||
|
|
||||||
|
They may also be retrieved as an ``IfcPropertySetTemplate`` entity:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
print(templates.get_applicable("IfcWall"))
|
||||||
|
|
||||||
|
A single template may be retrieved by name:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
templates.get_by_name('Pset_WallCommon')
|
||||||
|
|
||||||
|
You may add your own IFC files containing pset template definitions:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
my_pset_library = ifcopenshell.open('/path/to/library.ifc')
|
||||||
|
templates.templates.append(my_pset_library)
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
Validation
|
||||||
|
==========
|
||||||
|
|
||||||
|
SPF syntax validation
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
IfcOpenShell can validate whether or not an IFC-SPF file contains correct SPF syntax.
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
$ python -m ifcopenshell.simple_spf path/to/model.ifc
|
||||||
|
Valid
|
||||||
|
|
||||||
|
Here are some examples of failures:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
$ python -m ifcopenshell.simple_spf fixtures/fail_double_comma.ifc
|
||||||
|
On line 8 column 21:
|
||||||
|
Unexpected comma (',')
|
||||||
|
Expecting one of DBLQUOTE DOT HASH INT LPAR NONE QUOTE REAL STAR UPPER
|
||||||
|
00008 | #1=IFCPERSON($,$,'',,$,$,$,$);
|
||||||
|
^
|
||||||
|
|
||||||
|
$ python -m ifcopenshell.simple_spf fixtures/fail_double_semi.ifc
|
||||||
|
On line 27 column 66:
|
||||||
|
Unexpected semicolon (';')
|
||||||
|
Expecting one of ENDSEC HASH
|
||||||
|
00027 | #20=IFCPROJECT('2AyG2X0sb16Bjd4gQc07yZ',#5,'',$,$,$,$,(#11),#19);;
|
||||||
|
^
|
||||||
|
|
||||||
|
$ python -m ifcopenshell.simple_spf fixtures/fail_duplicate_id.ifc
|
||||||
|
On line 27:
|
||||||
|
Duplicate instance name #19
|
||||||
|
00027 | #19=IFCPROJECT('2AyG2X0sb16Bjd4gQc07yZ',#5,'',$,$,$,$,(#11),#19);
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
$ python -m ifcopenshell.simple_spf fixtures/fail_no_header.ifc
|
||||||
|
On line 2 column 1:
|
||||||
|
Unexpected hex ('F')
|
||||||
|
Expecting HEADER
|
||||||
|
00002 | FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
|
||||||
|
^
|
||||||
|
|
||||||
|
The optional ``--json`` argument may be used to instead get results in JSON.
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
$ python -m ifcopenshell.simple_spf test.ifc
|
||||||
|
{"type": "unexpected_token", "lineno": 8, "column": 48, "found_type": "semicolon", "found_value": ";", "expected": ["ENDSEC"], "line": "#1= IFCPERSON($,'Nicht definiert',$,$,$,$,$,$);;", "message": "On line 8 column 48:\nUnexpected semicolon (';')\nExpecting ENDSEC\n00008 | #1= IFCPERSON($,'Nicht definiert',$,$,$,$,$,$);;\n ^"}
|
||||||
|
|
||||||
|
IFC schema validation
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
IfcOpenShell can validate models against the IFC schema itself. It checks against attributes, entity names, data types, cardinality, and where rules.
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ python -m ifcopenshell.validate -h
|
||||||
|
|
||||||
|
usage: validate.py [-h] [--rules] [--json] [--fields] [--spf] files [files ...]
|
||||||
|
|
||||||
|
positional arguments:
|
||||||
|
files The IFC file to validate.
|
||||||
|
|
||||||
|
options:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
--rules Run express rules.
|
||||||
|
--json Output in JSON format.
|
||||||
|
--fields Output more detailed information about failed entities (only with --json).
|
||||||
|
--spf Output entities in SPF format (only with --json).
|
||||||
|
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
python -m ifcopenshell.validate /path/to/model.ifc --rules
|
||||||
@@ -54,27 +54,27 @@ IfcOpenShell is a modular ecosystem of tools that work together, where each tool
|
|||||||
.. csv-table::
|
.. csv-table::
|
||||||
:header: "Name", "Description"
|
:header: "Name", "Description"
|
||||||
|
|
||||||
"**IfcOpenShell**", "The core library for C++ developers. The library includes the ability to parse schemas, tessellate and process implicit geometry."
|
"`IfcOpenShell <https://docs.ifcopenshell.org/ifcopenshell.html>`_", "The core library for C++ developers. The library includes the ability to parse schemas, tessellate and process implicit geometry."
|
||||||
"**IfcOpenShell-Python**", "Python bindings to the core IfcOpenShell C++ system, as well as high level analysis and authoring functions."
|
"`IfcOpenShell-Python <https://docs.ifcopenshell.org/ifcopenshell-python.html>`_", "Python bindings to the core IfcOpenShell C++ system, as well as high level analysis and authoring functions."
|
||||||
"**IfcConvert**", "A command-line application for converting IFC geometry into file formats such as OBJ, DAE, GLB, STP, IGS, XML, SVG, H5, and IFC itself."
|
"`IfcConvert <https://docs.ifcopenshell.org/ifcconvert.html>`_", "A command-line application for converting IFC geometry into file formats such as OBJ, DAE, GLB, STP, IGS, XML, SVG, H5, and IFC itself."
|
||||||
"**Bonsai**", "A graphical add-on for Blender that lets you analyse, author, and modify IFC with Blender. Graphically create BIM models from scratch!"
|
"`Bonsai <https://docs.ifcopenshell.org/bonsai.html>`_", "A graphical add-on for Blender that lets you analyse, author, and modify IFC with Blender. Graphically create BIM models from scratch!"
|
||||||
"**BCF**", "BIM Collaboration Format (BCF) is a standard to manage and exchange coordination topics between disciplines collaborating on a project by changing XML files or querying an API."
|
"`BCF <https://docs.ifcopenshell.org/bcf.html>`_", "BIM Collaboration Format (BCF) is a standard to manage and exchange coordination topics between disciplines collaborating on a project by changing XML files or querying an API."
|
||||||
"**BIMServer-Plugin**", "A plugin to the open source BIMServer CDE to allow you to use IfcOpenShell to parse, view, and audit models."
|
"`BIMServer-Plugin <https://docs.ifcopenshell.org/bimserver-plugin.html>`_", "A plugin to the open source BIMServer CDE to allow you to use IfcOpenShell to parse, view, and audit models."
|
||||||
"**BIMTester**", "A utility that allows you to write Gherkin-based tests for models."
|
"`BIMTester <https://docs.ifcopenshell.org/bimtester.html>`_", "A utility that allows you to write Gherkin-based tests for models."
|
||||||
"**bSDD**", "A Python library to query the buildingSMART Data Dictionary API to search for standardised classifications and properties."
|
"`bSDD <https://docs.ifcopenshell.org/bsdd.html>`_", "A Python library to query the buildingSMART Data Dictionary API to search for standardised classifications and properties."
|
||||||
"**Ifc2CA**", "Converts IFC models to FEM structural analytical models to be used in Code_Aster."
|
"`Ifc2CA <https://docs.ifcopenshell.org/ifc2ca.html>`_", "Converts IFC models to FEM structural analytical models to be used in Code_Aster."
|
||||||
"**Ifc4D**", "A series of utilities for converting to and from various 4D software like MS Project, PowerProject, and Oracle P6."
|
"`Ifc4D <https://docs.ifcopenshell.org/ifc4d.html>`_", "A series of utilities for converting to and from various 4D software like MS Project, PowerProject, and Oracle P6."
|
||||||
"**Ifc5D**", "A collection of utilities of manipulating cost-related data to and from formats, reports, and optimisation engines."
|
"`Ifc5D <https://docs.ifcopenshell.org/ifc5d.html>`_", "A collection of utilities of manipulating cost-related data to and from formats, reports, and optimisation engines."
|
||||||
"**IfcCityJSON**", "A converter for CityJSON files and IFC. It currently only supports one-way conversion from CityJSON to IFC."
|
"`IfcCityJSON <https://docs.ifcopenshell.org/ifccityjson.html>`_", "A converter for CityJSON files and IFC. It currently only supports one-way conversion from CityJSON to IFC."
|
||||||
"**IfcClash**", "A CLI utility and library that lets you perform clash detection on one or more IFC models. Clashes are defined in terms of clash sets with filters using the IFC query syntax."
|
"`IfcClash <https://docs.ifcopenshell.org/ifcclash.html>`_", "A CLI utility and library that lets you perform clash detection on one or more IFC models. Clashes are defined in terms of clash sets with filters using the IFC query syntax."
|
||||||
"**IfcCSV**", "View and edit IFC data using spreadsheets or tabular datasets, such as CSV, ODS, XLSX, Pandas DataFrames, and regular Python lists."
|
"`IfcCSV <https://docs.ifcopenshell.org/ifccsv.html>`_", "View and edit IFC data using spreadsheets or tabular datasets, such as CSV, ODS, XLSX, Pandas DataFrames, and regular Python lists."
|
||||||
"**IfcDiff**", "A CLI utility and library that lets you compare the changes between two IFC models."
|
"`IfcDiff <https://docs.ifcopenshell.org/ifcdiff.html>`_", "A CLI utility and library that lets you compare the changes between two IFC models."
|
||||||
"**IfcFM**", "A highly standards-compliant tool (e.g. COBie 2.4, COBie 3.0, AOH-BSEM) to convert FM data in IFC databases to spreadsheets and other machine readable formats, such as ODS, XLSX, CSV, Pandas, XML, and JSON."
|
"`IfcFM <https://docs.ifcopenshell.org/ifcfm.html>`_", "A highly standards-compliant tool (e.g. COBie 2.4, COBie 3.0, AOH-BSEM) to convert FM data in IFC databases to spreadsheets and other machine readable formats, such as ODS, XLSX, CSV, Pandas, XML, and JSON."
|
||||||
"**IfcMax**", "A 3ds Max importer plugin able to import the IFC file format."
|
"`IfcMax <https://docs.ifcopenshell.org/ifcmax.html>`_", "A 3ds Max importer plugin able to import the IFC file format."
|
||||||
"**IfcPatch**", "A CLI utility and library that lets you run and distribute predetermined modifications on an IFC file, known as a patch recipe. Useful in deploying a data pipeline or batch-fixing external models."
|
"`IfcPatch <https://docs.ifcopenshell.org/ifcpatch.html>`_", "A CLI utility and library that lets you run and distribute predetermined modifications on an IFC file, known as a patch recipe. Useful in deploying a data pipeline or batch-fixing external models."
|
||||||
"**IfcSverchok**", "A node based visual programming add-on for Blender to interact with IFC and Sverchok."
|
"`IfcSverchok <https://docs.ifcopenshell.org/ifcsverchok.html>`_", "A node based visual programming add-on for Blender to interact with IFC and Sverchok."
|
||||||
"**IfcTester**", "Author and read Information Delivery Specification (IDS) files. You can validate IFC models against IDS and generate reports in multiple formats. It works from the command line, as a web app, or as a library."
|
"`IfcTester <https://docs.ifcopenshell.org/ifctester.html>`_", "Author and read Information Delivery Specification (IDS) files. You can validate IFC models against IDS and generate reports in multiple formats. It works from the command line, as a web app, or as a library."
|
||||||
"**VoxelisationToolkit**", "Converts .ifc geometry into voxels, and lets you perform voxel based geometric analysis."
|
"`VoxelisationToolkit <https://github.com/opensourceBIM/voxelization_toolkit>`_", "Converts .ifc geometry into voxels, and lets you perform voxel based geometric analysis."
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ INVALID_SYNTAX = ifcopenshell_wrapper.file_open_status.INVALID_SYNTAX
|
|||||||
try:
|
try:
|
||||||
UNKNOWN = ifcopenshell_wrapper.file_open_status.UNKNOWN
|
UNKNOWN = ifcopenshell_wrapper.file_open_status.UNKNOWN
|
||||||
except:
|
except:
|
||||||
UNKNOWN = 5 # Workaround
|
UNKNOWN = 5 # Workaround
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import operator
|
import operator
|
||||||
|
|
||||||
from .. import ifcopenshell_wrapper
|
from .. import open, ifcopenshell_wrapper
|
||||||
from ..file import file
|
from ..file import file
|
||||||
from ..entity_instance import entity_instance
|
from ..entity_instance import entity_instance
|
||||||
|
|
||||||
@@ -307,10 +307,7 @@ class iterator(ifcopenshell_wrapper.Iterator):
|
|||||||
self.file = file
|
self.file = file
|
||||||
file_or_filename = file_or_filename.wrapped_data
|
file_or_filename = file_or_filename.wrapped_data
|
||||||
else:
|
else:
|
||||||
# @todo?
|
file_or_filename = self.file = open(file_or_filename)
|
||||||
self.file = None
|
|
||||||
# Makes sure people are able to use python's platform agnostic paths
|
|
||||||
file_or_filename = os.path.abspath(file_or_filename)
|
|
||||||
|
|
||||||
if include is not None and exclude is not None:
|
if include is not None and exclude is not None:
|
||||||
raise ValueError("include and exclude cannot be specified simultaneously")
|
raise ValueError("include and exclude cannot be specified simultaneously")
|
||||||
@@ -342,7 +339,9 @@ class iterator(ifcopenshell_wrapper.Iterator):
|
|||||||
geometry_library, self.settings, file_or_filename, include_or_exclude, include is not None, num_threads
|
geometry_library, self.settings, file_or_filename, include_or_exclude, include is not None, num_threads
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
ifcopenshell_wrapper.Iterator.__init__(self, geometry_library, settings, file_or_filename, num_threads)
|
self.this = ifcopenshell_wrapper.construct_iterator(
|
||||||
|
geometry_library, self.settings, file_or_filename, num_threads
|
||||||
|
)
|
||||||
|
|
||||||
if has_occ:
|
if has_occ:
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,13 @@ FILTERED_CARTESIAN_QUOTIENT: Any
|
|||||||
EXACT_PREDICATES: Any
|
EXACT_PREDICATES: Any
|
||||||
EXACT_CONSTRUCTIONS: Any
|
EXACT_CONSTRUCTIONS: Any
|
||||||
|
|
||||||
|
FT_AUTODETECT: Any
|
||||||
|
FT_IFCSPF: Any
|
||||||
|
FT_IFCXML: Any
|
||||||
|
FT_IFCZIP: Any
|
||||||
|
FT_ROCKSDB: Any
|
||||||
|
FT_UNKNOWN: Any
|
||||||
|
|
||||||
CURVES: Any
|
CURVES: Any
|
||||||
SURFACES_AND_SOLIDS: Any
|
SURFACES_AND_SOLIDS: Any
|
||||||
CURVES_SURFACES_AND_SOLIDS: Any
|
CURVES_SURFACES_AND_SOLIDS: Any
|
||||||
@@ -96,12 +103,9 @@ class IfcSpfHeader:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def file(self, *args): ...
|
def file(self, *args): ...
|
||||||
@property
|
def file_description_py(self): ...
|
||||||
def file_description(self) -> ifcopenshell.entity_instance: ...
|
def file_name_py(self): ...
|
||||||
@property
|
def file_schema_py(self): ...
|
||||||
def file_name(self) -> ifcopenshell.entity_instance: ...
|
|
||||||
@property
|
|
||||||
def file_schema(self) -> ifcopenshell.entity_instance: ...
|
|
||||||
def read(self): ...
|
def read(self): ...
|
||||||
def tryRead(self): ...
|
def tryRead(self): ...
|
||||||
def write(self, out): ...
|
def write(self, out): ...
|
||||||
@@ -145,6 +149,7 @@ class ConversionResult:
|
|||||||
def Style(self): ...
|
def Style(self): ...
|
||||||
def StylePtr(self): ...
|
def StylePtr(self): ...
|
||||||
def append(self, trsf): ...
|
def append(self, trsf): ...
|
||||||
|
def apply_transform(self, unit_scale): ...
|
||||||
def hasStyle(self): ...
|
def hasStyle(self): ...
|
||||||
def prepend(self, trsf): ...
|
def prepend(self, trsf): ...
|
||||||
def setStyle(self, newStyle): ...
|
def setStyle(self, newStyle): ...
|
||||||
@@ -157,6 +162,7 @@ class ConversionResultShape:
|
|||||||
def axis(self): ...
|
def axis(self): ...
|
||||||
def bounding_box(self, *args): ...
|
def bounding_box(self, *args): ...
|
||||||
def box(self): ...
|
def box(self): ...
|
||||||
|
def concat(self, arg2): ...
|
||||||
def convex_decomposition(self): ...
|
def convex_decomposition(self): ...
|
||||||
def convex_tag(self, b): ...
|
def convex_tag(self, b): ...
|
||||||
def edges(self): ...
|
def edges(self): ...
|
||||||
@@ -178,9 +184,11 @@ class ConversionResultShape:
|
|||||||
def solid(self): ...
|
def solid(self): ...
|
||||||
def solid_mt(self): ...
|
def solid_mt(self): ...
|
||||||
def subtract(self, arg2): ...
|
def subtract(self, arg2): ...
|
||||||
|
def surface_area_along_direction(self, tol, arg3, along_x, along_y, along_z): ...
|
||||||
def surface_genus(self): ...
|
def surface_genus(self): ...
|
||||||
def vertices(self): ...
|
def vertices(self): ...
|
||||||
def volume(self): ...
|
def volume(self): ...
|
||||||
|
def wrap_in_compound(self): ...
|
||||||
|
|
||||||
class DoubleArray3:
|
class DoubleArray3:
|
||||||
def back(self): ...
|
def back(self): ...
|
||||||
@@ -284,11 +292,6 @@ class HdfSerializer(GeometrySerializer):
|
|||||||
def write(self, *args): ...
|
def write(self, *args): ...
|
||||||
def writeHeader(self): ...
|
def writeHeader(self): ...
|
||||||
|
|
||||||
class HeaderEntity:
|
|
||||||
def getArgument(self, index): ...
|
|
||||||
def getArgumentCount(self): ...
|
|
||||||
def toString(self, upper): ...
|
|
||||||
|
|
||||||
class IfcBaseEntity(entity_instance):
|
class IfcBaseEntity(entity_instance):
|
||||||
def declaration(self): ...
|
def declaration(self): ...
|
||||||
def get(self, name): ...
|
def get(self, name): ...
|
||||||
@@ -304,9 +307,17 @@ class IfcEntityInstanceData: ...
|
|||||||
class IfcLateBoundEntity(IfcBaseEntity):
|
class IfcLateBoundEntity(IfcBaseEntity):
|
||||||
def declaration(self): ...
|
def declaration(self): ...
|
||||||
|
|
||||||
class InstanceReference:
|
class InstanceStreamer:
|
||||||
file_offset: Any
|
def bypassTypes(self, type_names): ...
|
||||||
v: Any
|
def bypassed_instances(self): ...
|
||||||
|
coerce_attribute_count: bool
|
||||||
|
def hasSemicolon(self): ...
|
||||||
|
def inverses(self, *args): ...
|
||||||
|
def pushPage(self, page): ...
|
||||||
|
def readInstancePy(self, type_as_declaration_instance): ...
|
||||||
|
def references(self, *args): ...
|
||||||
|
def semicolonCount(self): ...
|
||||||
|
def status(self): ...
|
||||||
|
|
||||||
class Iterator:
|
class Iterator:
|
||||||
initialization_outcome_: Any
|
initialization_outcome_: Any
|
||||||
@@ -377,6 +388,18 @@ class Representation:
|
|||||||
|
|
||||||
def settings(self): ...
|
def settings(self): ...
|
||||||
|
|
||||||
|
class RocksDBPrefixIterator:
|
||||||
|
def key(self): ...
|
||||||
|
def next(self): ...
|
||||||
|
def valid(self): ...
|
||||||
|
def value(self): ...
|
||||||
|
|
||||||
|
class RocksDbSerializer:
|
||||||
|
def finalize(self): ...
|
||||||
|
def ready(self): ...
|
||||||
|
def setFile(self, arg2): ...
|
||||||
|
def writeHeader(self): ...
|
||||||
|
|
||||||
class Serialization(Representation):
|
class Serialization(Representation):
|
||||||
@property
|
@property
|
||||||
def brep_data(self): ...
|
def brep_data(self): ...
|
||||||
@@ -829,6 +852,7 @@ class entity_instance:
|
|||||||
...
|
...
|
||||||
|
|
||||||
def get_attribute_names(self): ...
|
def get_attribute_names(self): ...
|
||||||
|
def get_attribute_value(self, index): ...
|
||||||
def get_inverse(self, a): ...
|
def get_inverse(self, a): ...
|
||||||
def get_inverse_attribute_names(self): ...
|
def get_inverse_attribute_names(self): ...
|
||||||
def id(self) -> int: ...
|
def id(self) -> int: ...
|
||||||
@@ -851,6 +875,7 @@ class entity_instance:
|
|||||||
def setArgumentAsLogical(self, i, v): ...
|
def setArgumentAsLogical(self, i, v): ...
|
||||||
def setArgumentAsNull(self, i): ...
|
def setArgumentAsNull(self, i): ...
|
||||||
def setArgumentAsString(self, i, a): ...
|
def setArgumentAsString(self, i, a): ...
|
||||||
|
def set_attribute_value(self, *args): ...
|
||||||
def toString(self, arg2, upper): ...
|
def toString(self, arg2, upper): ...
|
||||||
def to_string(self, valid_spf): ...
|
def to_string(self, valid_spf): ...
|
||||||
def unset_attribute_value(self, i): ...
|
def unset_attribute_value(self, i): ...
|
||||||
@@ -888,14 +913,10 @@ class face:
|
|||||||
def print_impl(self, o, indent): ...
|
def print_impl(self, o, indent): ...
|
||||||
|
|
||||||
class file:
|
class file:
|
||||||
INSTANCE_ID: Any
|
|
||||||
INSTANCE_TYPE: Any
|
|
||||||
ATTRIBUTE_INDEX: Any
|
|
||||||
guid_map_: Any
|
|
||||||
stream: Any
|
|
||||||
def FreshId(self): ...
|
def FreshId(self): ...
|
||||||
def add(self, entity: entity_instance, id: int) -> entity_instance: ...
|
def add(self, entity: entity_instance, id: int) -> entity_instance: ...
|
||||||
def addEntities(self, entities): ...
|
def addEntities(self, entities): ...
|
||||||
|
def add_type_ref(self, new_entity): ...
|
||||||
def batch(self) -> None:
|
def batch(self) -> None:
|
||||||
"""Enable batch mode.
|
"""Enable batch mode.
|
||||||
|
|
||||||
@@ -919,10 +940,15 @@ class file:
|
|||||||
...
|
...
|
||||||
|
|
||||||
def build_inverses(self): ...
|
def build_inverses(self): ...
|
||||||
|
def build_inverses_(self, arg2): ...
|
||||||
def by_guid(self, guid: str) -> entity_instance: ...
|
def by_guid(self, guid: str) -> entity_instance: ...
|
||||||
def by_id(self, id: int) -> entity_instance: ...
|
def by_id(self, id: int) -> entity_instance: ...
|
||||||
def by_type(self, *args): ...
|
def by_type(self, *args): ...
|
||||||
def by_type_excl_subtypes(self, *args): ...
|
def by_type_excl_subtypes(self, *args): ...
|
||||||
|
def bypass_type(self, type_name): ...
|
||||||
|
calculate_unit_factors: bool
|
||||||
|
check_existance_before_adding: bool
|
||||||
|
def create(self, decl): ...
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def createTimestamp(): ...
|
def createTimestamp(): ...
|
||||||
def entity_names(self) -> tuple[int, ...]:
|
def entity_names(self) -> tuple[int, ...]:
|
||||||
@@ -961,24 +987,27 @@ class file:
|
|||||||
|
|
||||||
def get_total_inverses(self, e: entity_instance) -> int: ...
|
def get_total_inverses(self, e: entity_instance) -> int: ...
|
||||||
def good(self): ...
|
def good(self): ...
|
||||||
@staticmethod
|
def header(self, *args) -> IfcSpfHeader:
|
||||||
def guid_map(*args): ...
|
|
||||||
def header(self) -> IfcSpfHeader:
|
|
||||||
"""Internal IfcSpfHeader instance, always prefer ``ifcopenshell.file.header`` instead."""
|
"""Internal IfcSpfHeader instance, always prefer ``ifcopenshell.file.header`` instead."""
|
||||||
|
|
||||||
def ifcroot_type(self) -> entity: ...
|
def ifcroot_type(self) -> entity: ...
|
||||||
def internal_guid_map(self): ...
|
def initialize(self, *args): ...
|
||||||
def load(self, entity_instance_name, entity, arg4, attribute_index): ...
|
instantiate_typed_instances: bool
|
||||||
|
def key_value_store_iter(self, prefix): ...
|
||||||
|
def key_value_store_query(self, key): ...
|
||||||
|
def process_deletion_inverse(self, inst): ...
|
||||||
def recalculate_id_counter(self): ...
|
def recalculate_id_counter(self): ...
|
||||||
def remove(self, entity: entity_instance) -> None: ...
|
def remove(self, entity: entity_instance) -> None: ...
|
||||||
|
def remove_type_ref(self, new_entity): ...
|
||||||
|
def reset_identity_cache(self): ...
|
||||||
@property
|
@property
|
||||||
def schema(self): ...
|
def schema(self): ...
|
||||||
|
def storage_mode(self): ...
|
||||||
def to_string(self): ...
|
def to_string(self): ...
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def traverse(instance: entity_instance, max_level: int) -> tuple[entity_instance, ...]: ...
|
def traverse(instance: entity_instance, max_level: int) -> tuple[entity_instance, ...]: ...
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def traverse_breadth_first(instance: entity_instance, max_level: int) -> tuple[entity_instance, ...]: ...
|
def traverse_breadth_first(instance: entity_instance, max_level: int) -> tuple[entity_instance, ...]: ...
|
||||||
def try_read_semicolon(self): ...
|
|
||||||
def types(self) -> tuple[str, ...]:
|
def types(self) -> tuple[str, ...]:
|
||||||
"""Return a tuple of classes present in the file.
|
"""Return a tuple of classes present in the file.
|
||||||
|
|
||||||
@@ -986,16 +1015,15 @@ class file:
|
|||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def types_begin(self): ...
|
|
||||||
def types_end(self): ...
|
|
||||||
def write(self, fn): ...
|
def write(self, fn): ...
|
||||||
|
|
||||||
class file_open_status:
|
class file_open_status:
|
||||||
SUCCESS: Any
|
SUCCESS: int
|
||||||
READ_ERROR: Any
|
READ_ERROR: int
|
||||||
NO_HEADER: Any
|
NO_HEADER: int
|
||||||
UNSUPPORTED_SCHEMA: Any
|
UNSUPPORTED_SCHEMA: int
|
||||||
INVALID_SYNTAX: Any
|
INVALID_SYNTAX: int
|
||||||
|
UNKNOWN: int
|
||||||
def value(self): ...
|
def value(self): ...
|
||||||
|
|
||||||
class fn_evaluator:
|
class fn_evaluator:
|
||||||
@@ -1037,9 +1065,6 @@ class geometry_conversion_result:
|
|||||||
products_2: Any
|
products_2: Any
|
||||||
representation: Any
|
representation: Any
|
||||||
|
|
||||||
class geometry_exception:
|
|
||||||
def what(self): ...
|
|
||||||
|
|
||||||
class gradient_function(function_item):
|
class gradient_function(function_item):
|
||||||
def calc_hash(self): ...
|
def calc_hash(self): ...
|
||||||
def clone_(self): ...
|
def clone_(self): ...
|
||||||
@@ -1138,6 +1163,8 @@ class matrix4(item):
|
|||||||
def is_identity(self): ...
|
def is_identity(self): ...
|
||||||
def kind(self): ...
|
def kind(self): ...
|
||||||
def translation_part(self): ...
|
def translation_part(self): ...
|
||||||
|
def post_multiply_scale(self, s): ...
|
||||||
|
def pre_multiply_scale(self, s): ...
|
||||||
|
|
||||||
class named_type(parameter_type):
|
class named_type(parameter_type):
|
||||||
def _is(self, *args): ...
|
def _is(self, *args): ...
|
||||||
@@ -1516,13 +1543,11 @@ class sweep(geom_item):
|
|||||||
class sweep_along_curve(sweep):
|
class sweep_along_curve(sweep):
|
||||||
curve: Any
|
curve: Any
|
||||||
surface: Any
|
surface: Any
|
||||||
|
direction: Any
|
||||||
def calc_hash(self): ...
|
def calc_hash(self): ...
|
||||||
def clone_(self): ...
|
def clone_(self): ...
|
||||||
def kind(self): ...
|
def kind(self): ...
|
||||||
|
|
||||||
class too_many_faces_exception(geometry_exception): ...
|
|
||||||
class topology_error: ...
|
|
||||||
|
|
||||||
class torus(surface):
|
class torus(surface):
|
||||||
radius1: Any
|
radius1: Any
|
||||||
radius2: Any
|
radius2: Any
|
||||||
@@ -1568,6 +1593,8 @@ class type_declaration(declaration):
|
|||||||
def as_type_declaration(self) -> type_declaration: ...
|
def as_type_declaration(self) -> type_declaration: ...
|
||||||
def declared_type(self): ...
|
def declared_type(self): ...
|
||||||
|
|
||||||
|
class uninitialized_tag: ...
|
||||||
|
|
||||||
def arrange_polygons(polygons): ...
|
def arrange_polygons(polygons): ...
|
||||||
def clear_schemas(): ...
|
def clear_schemas(): ...
|
||||||
def construct_iterator_with_include_exclude(geometry_library, settings, file, elems, include, num_threads): ...
|
def construct_iterator_with_include_exclude(geometry_library, settings, file, elems, include, num_threads): ...
|
||||||
@@ -1581,6 +1608,7 @@ def flatten(deep): ...
|
|||||||
def get_feature(x): ...
|
def get_feature(x): ...
|
||||||
def get_info_cpp(v, include_identifier): ...
|
def get_info_cpp(v, include_identifier): ...
|
||||||
def get_log(): ...
|
def get_log(): ...
|
||||||
|
def guess_file_type(fn): ...
|
||||||
def helmert_curve_point(A0, A1, A2, s): ...
|
def helmert_curve_point(A0, A1, A2, s): ...
|
||||||
def kind_to_string(k): ...
|
def kind_to_string(k): ...
|
||||||
def less(arg1, arg2): ...
|
def less(arg1, arg2): ...
|
||||||
@@ -1588,7 +1616,7 @@ def line_segments_to_polygons(s, eps, segments): ...
|
|||||||
def map_shape(settings, instance): ...
|
def map_shape(settings, instance): ...
|
||||||
def nary_union(sequence): ...
|
def nary_union(sequence): ...
|
||||||
def new_IfcBaseClass(schema_identifier: str, name: str) -> entity_instance: ...
|
def new_IfcBaseClass(schema_identifier: str, name: str) -> entity_instance: ...
|
||||||
def open(fn): ...
|
def open(fn, readonly): ...
|
||||||
def parse_ifcxml(filename): ...
|
def parse_ifcxml(filename): ...
|
||||||
def polygons_to_svg(*args): ...
|
def polygons_to_svg(*args): ...
|
||||||
def read(data): ...
|
def read(data): ...
|
||||||
@@ -1599,6 +1627,7 @@ def serialise(schema_name, shape_str, advanced): ...
|
|||||||
def set_feature(x, v): ...
|
def set_feature(x, v): ...
|
||||||
def set_log_format_json(): ...
|
def set_log_format_json(): ...
|
||||||
def set_log_format_text(): ...
|
def set_log_format_text(): ...
|
||||||
|
def stream_from_string(data): ...
|
||||||
def svg_to_line_segments(data, class_name): ...
|
def svg_to_line_segments(data, class_name): ...
|
||||||
def svg_to_polygons(data, class_name): ...
|
def svg_to_polygons(data, class_name): ...
|
||||||
def taxonomy_item_repr(i): ...
|
def taxonomy_item_repr(i): ...
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ def get_brick_type(element: ifcopenshell.entity_instance) -> Union[str, None]:
|
|||||||
if not result:
|
if not result:
|
||||||
result = ifc4_to_brick_map.get(ifc_type_class, None)
|
result = ifc4_to_brick_map.get(ifc_type_class, None)
|
||||||
if result:
|
if result:
|
||||||
|
if result.startswith("http"):
|
||||||
|
return result
|
||||||
return f"https://brickschema.org/schema/Brick#{result}"
|
return f"https://brickschema.org/schema/Brick#{result}"
|
||||||
# Generic fallback
|
# Generic fallback
|
||||||
if element.is_a("IfcDistributionElement"):
|
if element.is_a("IfcDistributionElement"):
|
||||||
|
|||||||
@@ -474,7 +474,7 @@ def get_elements_by_pset(pset: ifcopenshell.entity_instance) -> set[ifcopenshell
|
|||||||
"""Retrieve the elements (or element types) that are using the provided property set."""
|
"""Retrieve the elements (or element types) that are using the provided property set."""
|
||||||
is_ifc2x3 = pset.file.schema == "IFC2X3"
|
is_ifc2x3 = pset.file.schema == "IFC2X3"
|
||||||
elements = set()
|
elements = set()
|
||||||
if pset.is_a("IfcPropertySet") or pset.is_a("IfcElementQuantity"):
|
if pset.is_a("IfcPropertySet") or pset.is_a("IfcPreDefinedPropertySet") or pset.is_a("IfcElementQuantity"):
|
||||||
rels = pset.PropertyDefinitionOf if is_ifc2x3 else pset.DefinesOccurrence
|
rels = pset.PropertyDefinitionOf if is_ifc2x3 else pset.DefinesOccurrence
|
||||||
for rel in rels:
|
for rel in rels:
|
||||||
elements.update(rel.RelatedObjects)
|
elements.update(rel.RelatedObjects)
|
||||||
|
|||||||
@@ -27,10 +27,9 @@
|
|||||||
"IfcFlowMeter.WATERMETER": "Water_Meter",
|
"IfcFlowMeter.WATERMETER": "Water_Meter",
|
||||||
"IfcElectricMotor": "Motor",
|
"IfcElectricMotor": "Motor",
|
||||||
"IfcSolarDevice.SOLARPANEL": "PV_Panel",
|
"IfcSolarDevice.SOLARPANEL": "PV_Panel",
|
||||||
"IfcBuilding": "Building",
|
"IfcBuilding": "https://w3id.org/rec#Building",
|
||||||
"IfcBuildingStorey": "Floor",
|
"IfcBuildingStorey": "https://w3id.org/rec#Level",
|
||||||
"IfcSpace": "Space",
|
"IfcSpace": "https://w3id.org/rec#Room",
|
||||||
"IfcSpatialZone": "Zone",
|
"IfcSpatialZone": "https://w3id.org/rec#Zone",
|
||||||
"IfcSpatialZone.THERMAL": "HVAC_Zone",
|
"IfcSpatialZone.THERMAL": "https://w3id.org/rec#HVACZone"
|
||||||
"IfcSpatialZone.LIGHTING": "Lighting_Zone"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -856,8 +856,10 @@ class FacetTransformer(lark.Transformer):
|
|||||||
comparison, value = args
|
comparison, value = args
|
||||||
|
|
||||||
def filter_function(element: ifcopenshell.entity_instance) -> bool:
|
def filter_function(element: ifcopenshell.entity_instance) -> bool:
|
||||||
element_value = getattr(ifcopenshell.util.element.get_type(element), "Name", None)
|
element_type = ifcopenshell.util.element.get_type(element)
|
||||||
return self.compare(element_value, comparison, value)
|
return self.compare(getattr(element_type, "Name", None), comparison, value) or self.compare(
|
||||||
|
getattr(element_type, "GlobalId", None), comparison, value
|
||||||
|
)
|
||||||
|
|
||||||
self.add_default_elements()
|
self.add_default_elements()
|
||||||
self.elements = set(filter(filter_function, self.elements))
|
self.elements = set(filter(filter_function, self.elements))
|
||||||
@@ -940,7 +942,7 @@ class FacetTransformer(lark.Transformer):
|
|||||||
containers = self.get_container_tree(container)
|
containers = self.get_container_tree(container)
|
||||||
result = False if containers else None
|
result = False if containers else None
|
||||||
for container in containers:
|
for container in containers:
|
||||||
if self.compare(container.Name, "=", value):
|
if self.compare(container.Name, "=", value) or self.compare(container.GlobalId, "=", value):
|
||||||
result = True
|
result = True
|
||||||
if result is not None:
|
if result is not None:
|
||||||
return result if comparison == "=" else not result
|
return result if comparison == "=" else not result
|
||||||
@@ -958,6 +960,8 @@ class FacetTransformer(lark.Transformer):
|
|||||||
if rel.is_a("IfcRelAssignsToGroup") and rel.RelatingGroup:
|
if rel.is_a("IfcRelAssignsToGroup") and rel.RelatingGroup:
|
||||||
if self.compare(rel.RelatingGroup.Name, "=", value):
|
if self.compare(rel.RelatingGroup.Name, "=", value):
|
||||||
result = True
|
result = True
|
||||||
|
elif self.compare(rel.RelatingGroup.GlobalId, "=", value):
|
||||||
|
result = True
|
||||||
return result if comparison == "=" else not result
|
return result if comparison == "=" else not result
|
||||||
|
|
||||||
self.add_default_elements()
|
self.add_default_elements()
|
||||||
@@ -969,32 +973,44 @@ class FacetTransformer(lark.Transformer):
|
|||||||
parents = set()
|
parents = set()
|
||||||
for rel in self.file.by_type("IfcRelAggregates"):
|
for rel in self.file.by_type("IfcRelAggregates"):
|
||||||
parent = rel.RelatingObject
|
parent = rel.RelatingObject
|
||||||
if parent and self.compare(parent.Name, comparison, value):
|
if parent and (
|
||||||
|
self.compare(parent.Name, comparison, value) or self.compare(parent.GlobalId, comparison, value)
|
||||||
|
):
|
||||||
parents.add(parent)
|
parents.add(parent)
|
||||||
|
|
||||||
for rel in self.file.by_type("IfcRelContainedInSpatialStructure"):
|
for rel in self.file.by_type("IfcRelContainedInSpatialStructure"):
|
||||||
parent = rel.RelatingStructure
|
parent = rel.RelatingStructure
|
||||||
if parent and self.compare(parent.Name, comparison, value):
|
if parent and (
|
||||||
|
self.compare(parent.Name, comparison, value) or self.compare(parent.GlobalId, comparison, value)
|
||||||
|
):
|
||||||
parents.add(parent)
|
parents.add(parent)
|
||||||
|
|
||||||
for rel in self.file.by_type("IfcRelNests"):
|
for rel in self.file.by_type("IfcRelNests"):
|
||||||
parent = rel.RelatingObject
|
parent = rel.RelatingObject
|
||||||
if parent and self.compare(parent.Name, comparison, value):
|
if parent and (
|
||||||
|
self.compare(parent.Name, comparison, value) or self.compare(parent.GlobalId, comparison, value)
|
||||||
|
):
|
||||||
parents.add(parent)
|
parents.add(parent)
|
||||||
|
|
||||||
for rel in self.file.by_type("IfcRelVoidsElement"):
|
for rel in self.file.by_type("IfcRelVoidsElement"):
|
||||||
parent = rel.RelatingBuildingElement
|
parent = rel.RelatingBuildingElement
|
||||||
if parent and self.compare(parent.Name, comparison, value):
|
if parent and (
|
||||||
|
self.compare(parent.Name, comparison, value) or self.compare(parent.GlobalId, comparison, value)
|
||||||
|
):
|
||||||
parents.add(parent)
|
parents.add(parent)
|
||||||
|
|
||||||
for rel in self.file.by_type("IfcRelVoidsElement"):
|
for rel in self.file.by_type("IfcRelVoidsElement"):
|
||||||
parent = rel.RelatingBuildingElement
|
parent = rel.RelatingBuildingElement
|
||||||
if parent and self.compare(parent.Name, comparison, value):
|
if parent and (
|
||||||
|
self.compare(parent.Name, comparison, value) or self.compare(parent.GlobalId, comparison, value)
|
||||||
|
):
|
||||||
parents.add(parent)
|
parents.add(parent)
|
||||||
|
|
||||||
for rel in self.file.by_type("IfcRelFillsElement"):
|
for rel in self.file.by_type("IfcRelFillsElement"):
|
||||||
parent = rel.RelatingOpeningElement
|
parent = rel.RelatingOpeningElement
|
||||||
if parent and self.compare(parent.Name, comparison, value):
|
if parent and (
|
||||||
|
self.compare(parent.Name, comparison, value) or self.compare(parent.GlobalId, comparison, value)
|
||||||
|
):
|
||||||
parents.add(parent)
|
parents.add(parent)
|
||||||
|
|
||||||
children: set[ifcopenshell.entity_instance] = set()
|
children: set[ifcopenshell.entity_instance] = set()
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
import functools
|
||||||
|
import itertools
|
||||||
|
import multiprocessing
|
||||||
|
import operator
|
||||||
|
import os
|
||||||
import pytest
|
import pytest
|
||||||
import test.bootstrap
|
import test.bootstrap
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
@@ -12,6 +17,8 @@ import ifcopenshell.util.shape
|
|||||||
from ifcopenshell.util.shape_builder import ShapeBuilder
|
from ifcopenshell.util.shape_builder import ShapeBuilder
|
||||||
from typing import get_args
|
from typing import get_args
|
||||||
|
|
||||||
|
fn = os.path.join(os.path.dirname(__file__), "fixtures/ColumnPSetsOfSets.ifc")
|
||||||
|
|
||||||
|
|
||||||
class TestGeomSettings:
|
class TestGeomSettings:
|
||||||
def test_settings(self):
|
def test_settings(self):
|
||||||
@@ -185,6 +192,28 @@ class TestAssignObject:
|
|||||||
assert len(set(vs)) == 12
|
assert len(set(vs)) == 12
|
||||||
|
|
||||||
|
|
||||||
|
def test_iterator():
|
||||||
|
# just test some permutations of invocation
|
||||||
|
settings = ifcopenshell.geom.settings()
|
||||||
|
file_or_filename = [fn, ifcopenshell.open(fn)]
|
||||||
|
with_or_without_threads = [[], [multiprocessing.cpu_count()]]
|
||||||
|
includes = [
|
||||||
|
{},
|
||||||
|
{"include": ["IfcColumn"]},
|
||||||
|
{"include": [file_or_filename[1].by_type("IfcColumn")[0]]},
|
||||||
|
]
|
||||||
|
for args in itertools.product(file_or_filename, with_or_without_threads, includes):
|
||||||
|
kwargs = functools.reduce(operator.or_, (a for a in args if isinstance(a, dict)))
|
||||||
|
pargs = []
|
||||||
|
for a in (_ for _ in args if not isinstance(_, dict)):
|
||||||
|
if isinstance(a, list):
|
||||||
|
pargs.extend(a)
|
||||||
|
else:
|
||||||
|
pargs.append(a)
|
||||||
|
iterator = ifcopenshell.geom.iterator(settings, *pargs, **kwargs)
|
||||||
|
assert iterator.initialize()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|||||||
@@ -196,6 +196,7 @@ class TestFilterElements(test.bootstrap.IFC4):
|
|||||||
assert subject.filter_elements(self.file, "IfcWall, type=Foo") == {element}
|
assert subject.filter_elements(self.file, "IfcWall, type=Foo") == {element}
|
||||||
assert subject.filter_elements(self.file, 'IfcWall, type="Foo"') == {element}
|
assert subject.filter_elements(self.file, 'IfcWall, type="Foo"') == {element}
|
||||||
assert subject.filter_elements(self.file, "IfcWall, type=/Fo.*/") == {element}
|
assert subject.filter_elements(self.file, "IfcWall, type=/Fo.*/") == {element}
|
||||||
|
assert subject.filter_elements(self.file, f"IfcWall, type={element_type.GlobalId}") == {element}
|
||||||
|
|
||||||
def test_selecting_by_material(self):
|
def test_selecting_by_material(self):
|
||||||
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
@@ -273,6 +274,7 @@ class TestFilterElements(test.bootstrap.IFC4):
|
|||||||
assert subject.filter_elements(self.file, "IfcWall, location=G") == {element, element2}
|
assert subject.filter_elements(self.file, "IfcWall, location=G") == {element, element2}
|
||||||
assert subject.filter_elements(self.file, "IfcWall, location=Building") == {element, element2}
|
assert subject.filter_elements(self.file, "IfcWall, location=Building") == {element, element2}
|
||||||
assert subject.filter_elements(self.file, "IfcWall, location!=Space") == {element2}
|
assert subject.filter_elements(self.file, "IfcWall, location!=Space") == {element2}
|
||||||
|
assert subject.filter_elements(self.file, f"IfcWall, location={space.GlobalId}") == {element}
|
||||||
|
|
||||||
def test_selecting_by_group(self):
|
def test_selecting_by_group(self):
|
||||||
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
@@ -281,6 +283,7 @@ class TestFilterElements(test.bootstrap.IFC4):
|
|||||||
ifcopenshell.api.group.assign_group(self.file, products=[element], group=group)
|
ifcopenshell.api.group.assign_group(self.file, products=[element], group=group)
|
||||||
assert subject.filter_elements(self.file, "IfcWall, group=Foo") == {element}
|
assert subject.filter_elements(self.file, "IfcWall, group=Foo") == {element}
|
||||||
assert subject.filter_elements(self.file, "IfcWall, group!=Foo") == {element2}
|
assert subject.filter_elements(self.file, "IfcWall, group!=Foo") == {element2}
|
||||||
|
assert subject.filter_elements(self.file, f"IfcWall, group={group.GlobalId}") == {element}
|
||||||
|
|
||||||
def test_selecting_by_parent(self):
|
def test_selecting_by_parent(self):
|
||||||
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall", name="Element1")
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall", name="Element1")
|
||||||
@@ -300,6 +303,7 @@ class TestFilterElements(test.bootstrap.IFC4):
|
|||||||
assert subject.filter_elements(self.file, "IfcWall, parent=Space") == {element}
|
assert subject.filter_elements(self.file, "IfcWall, parent=Space") == {element}
|
||||||
assert subject.filter_elements(self.file, "IfcWall, parent=G") == {element, element2, element3}
|
assert subject.filter_elements(self.file, "IfcWall, parent=G") == {element, element2, element3}
|
||||||
assert subject.filter_elements(self.file, "IfcWall, parent=Element2") == {element3}
|
assert subject.filter_elements(self.file, "IfcWall, parent=Element2") == {element3}
|
||||||
|
assert subject.filter_elements(self.file, "IfcWall, parent=Space") == {element}
|
||||||
|
|
||||||
def test_selecting_multiple_filter_groups(self):
|
def test_selecting_multiple_filter_groups(self):
|
||||||
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
|||||||
@@ -628,6 +628,7 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
|||||||
$result = boost::apply_visitor(ShapeRTTI(), (boost::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*>) $1);
|
$result = boost::apply_visitor(ShapeRTTI(), (boost::variant<IfcGeom::Element*, IfcGeom::Representation::Representation*, IfcGeom::Transformation*>) $1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%newobject construct_iterator;
|
||||||
%newobject construct_iterator_with_include_exclude;
|
%newobject construct_iterator_with_include_exclude;
|
||||||
%newobject construct_iterator_with_include_exclude_globalid;
|
%newobject construct_iterator_with_include_exclude_globalid;
|
||||||
%newobject construct_iterator_with_include_exclude_id;
|
%newobject construct_iterator_with_include_exclude_id;
|
||||||
@@ -635,6 +636,10 @@ struct ShapeRTTI : public boost::static_visitor<PyObject*>
|
|||||||
// I couldn't get the vector<string> typemap to be applied when %extending Iterator constructor.
|
// I couldn't get the vector<string> typemap to be applied when %extending Iterator constructor.
|
||||||
// anyway it does not matter as SWIG generates C code without actual constructors
|
// anyway it does not matter as SWIG generates C code without actual constructors
|
||||||
%inline %{
|
%inline %{
|
||||||
|
IfcGeom::Iterator* construct_iterator(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, IfcParse::IfcFile* file, int num_threads) {
|
||||||
|
return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings), settings, file, num_threads);
|
||||||
|
}
|
||||||
|
|
||||||
IfcGeom::Iterator* construct_iterator_with_include_exclude(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, IfcParse::IfcFile* file, std::vector<std::string> elems, bool include, int num_threads) {
|
IfcGeom::Iterator* construct_iterator_with_include_exclude(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, IfcParse::IfcFile* file, std::vector<std::string> elems, bool include, int num_threads) {
|
||||||
std::set<std::string> elems_set(elems.begin(), elems.end());
|
std::set<std::string> elems_set(elems.begin(), elems.end());
|
||||||
IfcGeom::entity_filter ef{ include, false, elems_set };
|
IfcGeom::entity_filter ef{ include, false, elems_set };
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ private:
|
|||||||
%ignore IfcParse::IfcFile::types_end;
|
%ignore IfcParse::IfcFile::types_end;
|
||||||
%ignore IfcParse::IfcFile::internal_guid_map;
|
%ignore IfcParse::IfcFile::internal_guid_map;
|
||||||
%ignore IfcParse::IfcFile::storage_;
|
%ignore IfcParse::IfcFile::storage_;
|
||||||
|
%ignore IfcParse::IfcFile::byguid_;
|
||||||
|
%ignore IfcParse::IfcFile::byid_;
|
||||||
|
%ignore IfcParse::IfcFile::byref_excl_;
|
||||||
|
%ignore IfcParse::IfcFile::types_to_bypass_loading_;
|
||||||
|
|
||||||
%ignore IfcParse::InstanceStreamer::InstanceStreamer(const IfcParse::schema_definition* schema, IfcParse::IfcSpfLexer* lexer);
|
%ignore IfcParse::InstanceStreamer::InstanceStreamer(const IfcParse::schema_definition* schema, IfcParse::IfcSpfLexer* lexer);
|
||||||
|
|
||||||
|
|||||||
@@ -93,6 +93,10 @@
|
|||||||
%ignore curve_to_face_upgrade_impl;
|
%ignore curve_to_face_upgrade_impl;
|
||||||
%ignore loop_to_function_item_upgrade_impl;
|
%ignore loop_to_function_item_upgrade_impl;
|
||||||
|
|
||||||
|
%ignore IfcGeom::geometry_exception;
|
||||||
|
%ignore IfcGeom::too_many_faces_exception;
|
||||||
|
%ignore ifcopenshell::geometry::taxonomy::topology_error;
|
||||||
|
|
||||||
// settings, can this done more generally?
|
// settings, can this done more generally?
|
||||||
// GeometrySerializer.h
|
// GeometrySerializer.h
|
||||||
%ignore UseElementNames;
|
%ignore UseElementNames;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from starlette.background import BackgroundTask
|
|||||||
from starlette.responses import StreamingResponse
|
from starlette.responses import StreamingResponse
|
||||||
from fastapi.routing import APIRoute
|
from fastapi.routing import APIRoute
|
||||||
from starlette.types import Message
|
from starlette.types import Message
|
||||||
from typing import Callable
|
from collections.abc import Callable
|
||||||
import logging
|
import logging
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user