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 import blenderbim.bim.export_ifc
from blenderbim.bim.module.drawing.decoration import CutDecorator from blenderbim.bim.module.drawing.decoration import CutDecorator
from blenderbim.bim.module.drawing.data import DecoratorData, DrawingsData 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 lxml import etree
from mathutils import Vector, Color, Matrix from mathutils import Vector, Color, Matrix
from timeit import default_timer as timer 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 blenderbim.bim.ifc import IfcStore
from pathlib import Path from pathlib import Path
from bpy_extras.image_utils import load_image from bpy_extras.image_utils import load_image
@@ -465,12 +465,12 @@ class CreateDrawing(bpy.types.Operator):
ifc: ifcopenshell.file, ifc: ifcopenshell.file,
tree: ifcopenshell.geom.tree, tree: ifcopenshell.geom.tree,
contexts: LineworkContexts, contexts: LineworkContexts,
context_type: str, context_type: Literal["body", "annotation"],
drawing_elements: set[ifcopenshell.entity_instance], drawing_elements: set[ifcopenshell.entity_instance],
target_view: str, target_view: str,
) -> None: ) -> None:
drawing_elements = drawing_elements.copy() drawing_elements = drawing_elements.copy()
contexts = getattr(contexts, context_type) contexts: list[list[int]] = getattr(contexts, context_type)
for context in contexts: for context in contexts:
with profile(f"Processing {context_type} context"): with profile(f"Processing {context_type} context"):
if not context or not drawing_elements: if not context or not drawing_elements:
@@ -33,7 +33,9 @@ import ifcopenshell.util.selector
import ifcopenshell.util.geolocation import ifcopenshell.util.geolocation
import ifcopenshell.util.representation import ifcopenshell.util.representation
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.representation
import ifcopenshell.util.shape import ifcopenshell.util.shape
import ifcopenshell.util.unit
import blenderbim.bim.handler import blenderbim.bim.handler
import blenderbim.bim.schema import blenderbim.bim.schema
import blenderbim.tool as tool 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/>. # along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING, Optional from typing import TYPE_CHECKING, Optional, Sequence
if TYPE_CHECKING: if TYPE_CHECKING:
import bpy import bpy
@@ -109,11 +109,9 @@ def switch_representation(
) -> None: ) -> None:
"""Function can switch to representation that wasn't yet assigned to that object. See #2766. """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`; :param should_sync_changes_first: sync ifc representation with current state of `obj.data`
:param should_reload: reload `obj.data` from ifc representation
`should_reload` - reload `obj.data` from ifc representation; :param is_global: replace mesh data for all users of `obj.data`, not just `obj`
`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): 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): if not current_obj_data and geometry.is_text_literal(representation):
return 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) use_immediate_repr = use_immediate_repr or geometry.has_material_style_override(entity)
if use_immediate_repr: if use_immediate_repr:
# if it has openings make sure to switch to element's mapped representation # if it has openings make sure to switch to element's mapped representation
@@ -162,15 +160,20 @@ def switch_representation(
geometry.clear_cache(entity) 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)) 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, """Consider changing obj representation before using the function,
otherwise it will replace object with empty.""" otherwise it will replace object with empty."""
element = ifc.get_entity(obj) element = ifc.get_entity(obj)
assert element
element_type = geometry.get_element_type(element) element_type = geometry.get_element_type(element)
data = None data = None
if element_type and (geometry.is_mapped_representation(representation) or geometry.is_type_product(element)): 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) 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 purged_representations = 0
for representation in geometry.get_model_representations(): for representation in geometry.get_model_representations():
if ifc.get().get_total_inverses(representation) == 0: if ifc.get().get_total_inverses(representation) == 0:
@@ -205,29 +212,35 @@ def purge_unused_representations(ifc, geometry):
return purged_representations return purged_representations
def select_connection(geometry, connection=None): def select_connection(geometry: tool.Geometry, connection: ifcopenshell.entity_instance) -> None:
geometry.select_connection(connection) 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) 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() model = ifc.get()
all_openings = model.by_type("IfcOpeningElement") all_openings = model.by_type("IfcOpeningElement")
similar_openings = [o for o in all_openings if o.ObjectPlacement == opening.ObjectPlacement and o != opening] similar_openings = [o for o in all_openings if o.ObjectPlacement == opening.ObjectPlacement and o != opening]
return similar_openings 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 = [] building_objs = []
for similar_opening in similar_openings: for similar_opening in similar_openings:
building_objs.append(ifc.get_object(similar_opening.VoidsElements[0].RelatingBuildingElement)) building_objs.append(ifc.get_object(similar_opening.VoidsElements[0].RelatingBuildingElement))
return building_objs 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: if not opening or not similar_openings:
return return
for similar_opening in similar_openings: for similar_opening in similar_openings:
@@ -543,6 +543,7 @@ class Geometry(blenderbim.core.tool.Geometry):
logger = logging.getLogger("ImportIFC") logger = logging.getLogger("ImportIFC")
ifc_import_settings = blenderbim.bim.import_ifc.IfcImportSettings.factory(bpy.context, None, logger) ifc_import_settings = blenderbim.bim.import_ifc.IfcImportSettings.factory(bpy.context, None, logger)
element = tool.Ifc.get_entity(obj) element = tool.Ifc.get_entity(obj)
assert element # Type checker.
settings = ifcopenshell.geom.settings() settings = ifcopenshell.geom.settings()
settings.set("weld-vertices", True) settings.set("weld-vertices", True)
settings.set("apply-default-materials", False) settings.set("apply-default-materials", False)
+9 -9
View File
@@ -27,6 +27,7 @@ import ifcopenshell.geom
from xml.dom.minidom import parseString from xml.dom.minidom import parseString
from dataclasses import dataclass, fields from dataclasses import dataclass, fields
from typing import Callable, Sequence
import numpy import numpy
@@ -64,7 +65,13 @@ class draw_settings:
unify_inputs: bool = True 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( geom_settings = ifcopenshell.geom.settings(
# when not doing booleans, proper solids from shells isn't a requirement # 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: for it in iterators:
it.set_cache(cache) it.set_cache(cache)
def yield_from_iterator(it):
if it.initialize():
while True:
yield it.get()
if not it.next():
break
# Initialize serializer # Initialize serializer
buffer = ifcopenshell.geom.serializers.buffer() buffer = ifcopenshell.geom.serializers.buffer()
serialiser_settings = ifcopenshell.geom.serializer_settings() 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 # Loop over iterators for geometric content
for i, it in enumerate(iterators): for i, it in enumerate(iterators):
for elem in yield_from_iterator(it): for elem in it:
sr.write(elem) sr.write(elem)
if elem.type != "IfcSpace": if elem.type != "IfcSpace":
tree.add_element(elem) 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 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. 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: :return:
- `inst` is IfcProduct and `repr` provided / None -> ShapeElementType - `inst` is IfcProduct and `repr` provided / None -> ShapeElementType
- `inst` is IfcRepresentation and `repr` is None -> ShapeType - `inst` is IfcRepresentation and `repr` is None -> ShapeType