This commit is contained in:
Andrej730
2024-07-02 11:40:38 +05:00
parent 5d1b2e4651
commit 8f92877fb4
6 changed files with 46 additions and 28 deletions
@@ -46,11 +46,11 @@ import blenderbim.bim.module.drawing.helper as helper
import blenderbim.bim.export_ifc
from blenderbim.bim.module.drawing.decoration import CutDecorator
from blenderbim.bim.module.drawing.data import DecoratorData, DrawingsData
from typing import NamedTuple, List, Union, Optional
from typing import NamedTuple, List, Union, Optional, Literal
from lxml import etree
from mathutils import Vector, Color, Matrix
from timeit import default_timer as timer
from blenderbim.bim.module.drawing.prop import RasterStyleProperty, Literal, RASTER_STYLE_PROPERTIES_EXCLUDE
from blenderbim.bim.module.drawing.prop import RasterStyleProperty, RASTER_STYLE_PROPERTIES_EXCLUDE
from blenderbim.bim.ifc import IfcStore
from pathlib import Path
from bpy_extras.image_utils import load_image
@@ -465,12 +465,12 @@ class CreateDrawing(bpy.types.Operator):
ifc: ifcopenshell.file,
tree: ifcopenshell.geom.tree,
contexts: LineworkContexts,
context_type: str,
context_type: Literal["body", "annotation"],
drawing_elements: set[ifcopenshell.entity_instance],
target_view: str,
) -> None:
drawing_elements = drawing_elements.copy()
contexts = getattr(contexts, context_type)
contexts: list[list[int]] = getattr(contexts, context_type)
for context in contexts:
with profile(f"Processing {context_type} context"):
if not context or not drawing_elements:
@@ -33,7 +33,9 @@ import ifcopenshell.util.selector
import ifcopenshell.util.geolocation
import ifcopenshell.util.representation
import ifcopenshell.util.element
import ifcopenshell.util.representation
import ifcopenshell.util.shape
import ifcopenshell.util.unit
import blenderbim.bim.handler
import blenderbim.bim.schema
import blenderbim.tool as tool
+28 -15
View File
@@ -17,7 +17,7 @@
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from typing import TYPE_CHECKING, Optional, Sequence
if TYPE_CHECKING:
import bpy
@@ -109,11 +109,9 @@ def switch_representation(
) -> None:
"""Function can switch to representation that wasn't yet assigned to that object. See #2766.
`should_sync_changes_first` - sync ifc representation with current state of `obj.data`;
`should_reload` - reload `obj.data` from ifc representation;
`is_global` - replace mesh data for all users of `obj.data`, not just `obj`;
:param should_sync_changes_first: sync ifc representation with current state of `obj.data`
:param should_reload: reload `obj.data` from ifc representation
:param is_global: replace mesh data for all users of `obj.data`, not just `obj`
"""
if should_sync_changes_first and geometry.is_edited(obj) and not geometry.is_box_representation(representation):
@@ -128,7 +126,7 @@ def switch_representation(
if not current_obj_data and geometry.is_text_literal(representation):
return
use_immediate_repr = apply_openings and getattr(entity, "HasOpenings", None)
use_immediate_repr = apply_openings and bool(getattr(entity, "HasOpenings", None))
use_immediate_repr = use_immediate_repr or geometry.has_material_style_override(entity)
if use_immediate_repr:
# if it has openings make sure to switch to element's mapped representation
@@ -162,15 +160,20 @@ def switch_representation(
geometry.clear_cache(entity)
def get_representation_ifc_parameters(geometry, obj=None, should_sync_changes_first=False):
def get_representation_ifc_parameters(
geometry: tool.Geometry, obj: bpy.types.Object, should_sync_changes_first: bool = False
) -> None:
geometry.import_representation_parameters(geometry.get_object_data(obj))
def remove_representation(ifc, geometry, obj=None, representation=None):
def remove_representation(
ifc: tool.Ifc, geometry: tool.Geometry, obj: bpy.types.Object, representation: ifcopenshell.entity_instance
) -> None:
"""Consider changing obj representation before using the function,
otherwise it will replace object with empty."""
element = ifc.get_entity(obj)
assert element
element_type = geometry.get_element_type(element)
data = None
if element_type and (geometry.is_mapped_representation(representation) or geometry.is_type_product(element)):
@@ -196,7 +199,11 @@ def remove_representation(ifc, geometry, obj=None, representation=None):
geometry.delete_data(data)
def purge_unused_representations(ifc, geometry):
def purge_unused_representations(ifc: tool.Ifc, geometry: tool.Geometry) -> int:
"""Purge representations without inverses.
:return: A number of purged representations.
"""
purged_representations = 0
for representation in geometry.get_model_representations():
if ifc.get().get_total_inverses(representation) == 0:
@@ -205,29 +212,35 @@ def purge_unused_representations(ifc, geometry):
return purged_representations
def select_connection(geometry, connection=None):
def select_connection(geometry: tool.Geometry, connection: ifcopenshell.entity_instance) -> None:
geometry.select_connection(connection)
def remove_connection(geometry, connection=None):
def remove_connection(geometry: tool.Geometry, connection: ifcopenshell.entity_instance) -> None:
geometry.remove_connection(connection)
def get_similar_openings(ifc, opening):
def get_similar_openings(ifc: tool.Ifc, opening: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
model = ifc.get()
all_openings = model.by_type("IfcOpeningElement")
similar_openings = [o for o in all_openings if o.ObjectPlacement == opening.ObjectPlacement and o != opening]
return similar_openings
def get_similar_openings_building_objs(ifc, similar_openings):
def get_similar_openings_building_objs(
ifc: tool.Ifc, similar_openings: list[ifcopenshell.entity_instance]
) -> list[bpy.types.Object]:
building_objs = []
for similar_opening in similar_openings:
building_objs.append(ifc.get_object(similar_opening.VoidsElements[0].RelatingBuildingElement))
return building_objs
def edit_similar_opening_placement(geometry, opening=None, similar_openings=None):
def edit_similar_opening_placement(
geometry: tool.Geometry,
opening: Optional[ifcopenshell.entity_instance] = None,
similar_openings: Sequence[ifcopenshell.entity_instance] = (),
) -> None:
if not opening or not similar_openings:
return
for similar_opening in similar_openings:
@@ -543,6 +543,7 @@ class Geometry(blenderbim.core.tool.Geometry):
logger = logging.getLogger("ImportIFC")
ifc_import_settings = blenderbim.bim.import_ifc.IfcImportSettings.factory(bpy.context, None, logger)
element = tool.Ifc.get_entity(obj)
assert element # Type checker.
settings = ifcopenshell.geom.settings()
settings.set("weld-vertices", True)
settings.set("apply-default-materials", False)
+9 -9
View File
@@ -27,6 +27,7 @@ import ifcopenshell.geom
from xml.dom.minidom import parseString
from dataclasses import dataclass, fields
from typing import Callable, Sequence
import numpy
@@ -64,7 +65,13 @@ class draw_settings:
unify_inputs: bool = True
def main(settings, files, iterators=None, merge_projection=True, progress_function=DO_NOTHING):
def main(
settings: draw_settings,
files: list[ifcopenshell.file],
iterators: Sequence[ifcopenshell.geom.iterator] = (),
merge_projection: bool = True,
progress_function: Callable = DO_NOTHING,
):
geom_settings = ifcopenshell.geom.settings(
# when not doing booleans, proper solids from shells isn't a requirement
@@ -97,13 +104,6 @@ def main(settings, files, iterators=None, merge_projection=True, progress_functi
for it in iterators:
it.set_cache(cache)
def yield_from_iterator(it):
if it.initialize():
while True:
yield it.get()
if not it.next():
break
# Initialize serializer
buffer = ifcopenshell.geom.serializers.buffer()
serialiser_settings = ifcopenshell.geom.serializer_settings()
@@ -167,7 +167,7 @@ def main(settings, files, iterators=None, merge_projection=True, progress_functi
# Loop over iterators for geometric content
for i, it in enumerate(iterators):
for elem in yield_from_iterator(it):
for elem in it:
sr.write(elem)
if elem.type != "IfcSpace":
tree.add_element(elem)
@@ -365,6 +365,8 @@ def create_shape(
Note that in Python, you must store a reference to the element returned by this function to prevent garbage
collection when you access its children. See #1124.
:raises RuntimeError: If failed to process shape. You can turn detailed logging to get more details.
:return:
- `inst` is IfcProduct and `repr` provided / None -> ShapeElementType
- `inst` is IfcRepresentation and `repr` is None -> ShapeType