assign_representation_styles to reuse existing styled item + tests

This commit is contained in:
Andrej730
2024-02-21 10:55:54 +05:00
parent bdc991856c
commit 863a8248af
2 changed files with 122 additions and 3 deletions
@@ -47,8 +47,8 @@ class Usecase:
showing up in Revit. In that case, set it to True, but keep in mind showing up in Revit. In that case, set it to True, but keep in mind
that this is no longer a valid IFC. Blame Autodesk. that this is no longer a valid IFC. Blame Autodesk.
:type should_use_presentation_style_assignment: bool :type should_use_presentation_style_assignment: bool
:return: None :return: List of created IfcStyledItems
:rtype: None :rtype: ifcopenshell.entity_instance.entity_instance
Example: Example:
@@ -101,7 +101,10 @@ class Usecase:
def execute(self): def execute(self):
if not self.settings["styles"]: if not self.settings["styles"]:
return [] return []
self.settings["styles"] = self.settings["styles"].copy()
self.results = [] self.results = []
use_style_assignment = self.file.schema == "IFC2X3" or self.settings["should_use_presentation_style_assignment"]
for element in self.file.traverse(self.settings["shape_representation"]): for element in self.file.traverse(self.settings["shape_representation"]):
if not element.is_a("IfcShapeRepresentation"): if not element.is_a("IfcShapeRepresentation"):
continue continue
@@ -112,7 +115,34 @@ class Usecase:
# If there are more items than styles, fallback to using the last style # If there are more items than styles, fallback to using the last style
style = self.settings["styles"].pop(0) style = self.settings["styles"].pop(0)
name = style.Name name = style.Name
if self.file.schema == "IFC2X3" or self.settings["should_use_presentation_style_assignment"]:
# item may had previous styled item
prev_styled_item = next((i for i in item.StyledByItem), None)
if prev_styled_item is not None:
# collect previously assigned styles
assigned_styles = []
style_assignment = None # try to find some style assignment to reuse
for style_ in prev_styled_item.Styles:
if style_.is_a("IfcPresentationStyleAssignment"):
if style_assignment is None:
style_assignment = style_
assigned_styles.extend(style_.Styles)
else: # IfcPresentationStyle
assigned_styles.append(style_)
if style not in assigned_styles:
if use_style_assignment:
if style_assignment is not None:
style_assignment.Styles = style_assignment.Styles + (style,)
else:
style_assignment = self.file.createIfcPresentationStyleAssignment([style])
prev_styled_item.Styles = prev_styled_item.Styles + (style_assignment,)
else:
prev_styled_item.Styles = prev_styled_item.Styles + (style,)
# if style is in previous styles we also continue
continue
if use_style_assignment:
style_assignment = self.file.createIfcPresentationStyleAssignment([style]) style_assignment = self.file.createIfcPresentationStyleAssignment([style])
self.results.append(self.file.createIfcStyledItem(item, [style_assignment], name)) self.results.append(self.file.createIfcStyledItem(item, [style_assignment], name))
else: else:
@@ -0,0 +1,89 @@
# IfcOpenShell - IFC toolkit and geometry engine
# Copyright (C) 2022 Dion Moult <dion@thinkmoult.com>
#
# This file is part of IfcOpenShell.
#
# IfcOpenShell is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# IfcOpenShell is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
import pytest
import test.bootstrap
import ifcopenshell
import ifcopenshell.api
class TestAssignRepresentationStyles(test.bootstrap.IFC4):
def test_run(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
product_shape = self.file.createIfcProductDefinitionShape()
element.Representation = product_shape
representation = self.file.createIfcShapeRepresentation()
item = self.file.createIfcExtrudedAreaSolid()
representation.Items = [item]
style = self.file.createIfcSurfaceStyle()
ifcopenshell.api.run(
"style.assign_representation_styles", self.file, styles=[style], shape_representation=representation
)
assert item.StyledByItem[0].Styles == (style,)
# reusing existing styled item
style2 = self.file.createIfcSurfaceStyle()
ifcopenshell.api.run(
"style.assign_representation_styles", self.file, styles=[style2], shape_representation=representation
)
assert item.StyledByItem[0].Styles == (style, style2)
assert len(self.file.by_type("IfcStyledItem")) == 1
def test_assign_using_style_assignment(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
product_shape = self.file.createIfcProductDefinitionShape()
element.Representation = product_shape
representation = self.file.createIfcShapeRepresentation()
item = self.file.createIfcExtrudedAreaSolid()
representation.Items = [item]
style = self.file.createIfcSurfaceStyle()
ifcopenshell.api.run(
"style.assign_representation_styles",
self.file,
styles=[style],
shape_representation=representation,
should_use_presentation_style_assignment=True,
)
assert len(self.file.by_type("IfcPresentationStyleAssignment")) == 1
style_assignment = self.file.by_type("IfcPresentationStyleAssignment")[0]
assert style_assignment.Styles == (style,)
assert item.StyledByItem[0].Styles == (style_assignment,)
# reusing existing styled item and style assignment
style2 = self.file.createIfcSurfaceStyle()
ifcopenshell.api.run(
"style.assign_representation_styles",
self.file,
styles=[style2],
shape_representation=representation,
should_use_presentation_style_assignment=True,
)
assert len(self.file.by_type("IfcPresentationStyleAssignment")) == 1
assert item.StyledByItem[0].Styles == (style_assignment,)
assert item.StyledByItem[0].Styles[0].Styles == (style, style2)
assert len(self.file.by_type("IfcStyledItem")) == 1
class TestAssignRepresentationStylesIFC2X3(test.bootstrap.IFC2X3):
def test_run(self):
TestAssignRepresentationStyles.test_assign_using_style_assignment(self)