Fix bug where editing styles didn't work if factors were stored instead of RGB colours

This commit is contained in:
Dion Moult
2021-09-10 17:43:26 +10:00
parent 9b94c3ceca
commit d350a17ce5
7 changed files with 170 additions and 99 deletions
+1 -1
View File
@@ -172,6 +172,7 @@ class IfcExporter:
try:
# This will throw an exception if the Blender object no longer exists
foo = obj.name
foo
return False
except:
return True
@@ -199,7 +200,6 @@ class IfcExportSettings:
@staticmethod
def factory(context, output_file, logger):
scene_bim = context.scene.BIMProperties
settings = IfcExportSettings()
settings.output_file = output_file
settings.logger = logger
+17 -28
View File
@@ -16,31 +16,24 @@
# 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 ifcopenshell
import ifcopenshell.geom
import ifcopenshell.util.geolocation
import ifcopenshell.util.selector
import ifcopenshell.util.element
import ifcopenshell.util.unit
import bpy
import bmesh
import os
import re
import shutil
import threading
import bpy
import json
import time
import bmesh
import shutil
import threading
import mathutils
import math
import multiprocessing
import zipfile
import tempfile
import numpy as np
from blenderbim.bim.module.drawing.prop import getDiagramScales
from pathlib import Path
from itertools import cycle
from datetime import datetime
import multiprocessing
import ifcopenshell
import ifcopenshell.geom
import ifcopenshell.util.unit
import ifcopenshell.util.element
import ifcopenshell.util.selector
import ifcopenshell.util.geolocation
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.module.drawing.prop import getDiagramScales
class FileCopy(threading.Thread):
@@ -407,7 +400,6 @@ class IfcImporter:
props.has_blender_offset = True
def get_offset_point(self):
offset_point = None
elements_checked = 0
# If more than these points aren't far away, the file probably isn't absolutely positioned
element_checking_threshold = 100
@@ -462,16 +454,14 @@ class IfcImporter:
return mathutils.Matrix(matrix.tolist())
def find_decomposed_ifc_class(self, element, ifc_class):
results = []
if element.is_a(ifc_class):
return element
rel_aggregates = element.IsDecomposedBy
if not rel_aggregates:
return results
for rel_aggregate in rel_aggregates:
for part in rel_aggregate.RelatedObjects:
if part.is_a(ifc_class):
results.append(part)
results.extend(self.find_decomposed_ifc_class(part, ifc_class))
return results
result = self.find_decomposed_ifc_class(part, ifc_class)
if result:
return result
def create_grids(self):
grids = self.file.by_type("IfcGrid")
@@ -1485,7 +1475,6 @@ class IfcImportSettings:
@staticmethod
def factory(context, input_file, logger):
scene_bim = context.scene.BIMProperties
scene_diff = context.scene.DiffProperties
settings = IfcImportSettings()
settings.input_file = input_file
@@ -52,8 +52,25 @@ class UpdateStyleColours(bpy.types.Operator):
self.file = IfcStore.get_file()
material = bpy.data.materials.get(self.material) if self.material else context.active_object.active_material
settings = get_colour_settings(material)
settings["style"] = self.file.by_id(material.BIMMaterialProperties.ifc_style_id)
ifcopenshell.api.run("style.edit_style_colours", self.file, **settings)
for style in self.file.by_id(material.BIMMaterialProperties.ifc_style_id).Styles:
if style.is_a("IfcSurfaceStyleRendering"):
ifcopenshell.api.run(
"style.edit_surface_style",
self.file,
style=style,
attributes={
"SurfaceColour": settings["surface_colour"],
"Transparency": settings["transparency"],
"DiffuseColour": settings["diffuse_colour"],
},
)
elif style.is_a("IfcSurfaceStyleShading"):
ifcopenshell.api.run(
"style.edit_surface_style",
self.file,
style=style,
attributes={"SurfaceColour": settings["surface_colour"], "Transparency": settings["transparency"]},
)
return {"FINISHED"}
@@ -167,7 +184,7 @@ class EditStyle(bpy.types.Operator):
attributes = blenderbim.bim.helper.export_attributes(props.attributes)
self.file = IfcStore.get_file()
style = self.file.by_id(material.BIMMaterialProperties.ifc_style_id)
ifcopenshell.api.run("style.edit_style", self.file, **{"style": style, "attributes": attributes})
ifcopenshell.api.run("style.edit_presentation_style", self.file, **{"style": style, "attributes": attributes})
Data.load(IfcStore.get_file(), material.BIMMaterialProperties.ifc_style_id)
bpy.ops.bim.disable_editing_style()
return {"FINISHED"}
@@ -1,67 +0,0 @@
class Usecase:
def __init__(self, file, **settings):
self.file = file
self.settings = {
"style": None,
"surface_colour": [], # RGB
"diffuse_colour": [], # RGB
"transparency": 0,
"external_definition": {"location": None, "identification": None, "name": "Name"},
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
# has_external_definition = None
for element in self.file.traverse(self.settings["style"]):
if element.is_a("IfcSurfaceStyleShading"):
if element.SurfaceColour:
self.update_colour_rgb(element.SurfaceColour, self.settings["surface_colour"])
else:
element.SurfaceColour = self.create_colour_rgb(self.settings["surface_colour"])
element.Transparency = self.settings["transparency"]
if element.is_a("IfcSurfaceStyleRendering"):
if element.DiffuseColour:
self.update_colour_rgb(element.DiffuseColour, self.settings["diffuse_colour"])
else:
element.DiffuseColour = self.create_colour_rgb(self.settings["diffuse_colour"])
# TODO: Move to separate usecase
# if element.is_a("IfcExternallyDefinedSurfaceStyle"):
# element.Location = self.settings["location"]
# element.Identification = self.settings["identification"]
# element.Name = self.settings["name"]
# has_external_definition = True
# if not has_external_definition:
# styles = list(self.settings["style"].Styles)
# styles.append(self.create_externally_defined_surface_style())
# self.settings["style"].Styles = styles
return self.settings["style"]
def create_surface_style_rendering(self):
return self.file.create_entity(
"IfcSurfaceStyleRendering",
**{
"SurfaceColour": self.create_colour_rgb(self.settings["surface_colour"]),
"Transparency": self.settings["transparency"],
"ReflectanceMethod": "NOTDEFINED",
"DiffuseColour": self.create_colour_rgb(self.settings["diffuse_colour"]),
}
)
def create_externally_defined_surface_style(self):
self.file.create_entity(
"IfcExternallyDefinedSurfaceStyle",
**{
"Location": self.settings["location"],
"Identification": self.settings["identification"],
"Name": self.settings["name"],
}
)
def create_colour_rgb(self, colour):
return self.file.createIfcColourRgb(None, colour[0], colour[1], colour[2])
def update_colour_rgb(self, element, colour):
element[1] = colour[0]
element[2] = colour[1]
element[3] = colour[2]
@@ -0,0 +1,45 @@
class Usecase:
def __init__(self, file, **settings):
self.file = file
self.settings = {"style": None, "attributes": {}}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
for key, value in self.settings["attributes"].items():
if key == "SurfaceColour":
self.edit_surface_colour(value)
elif self.is_colour_or_factor(key):
self.edit_colour_or_factor(key, value)
else:
setattr(self.settings["style"], key, value)
def edit_surface_colour(self, value):
self.settings["style"].SurfaceColour[1] = value[0]
self.settings["style"].SurfaceColour[2] = value[1]
self.settings["style"].SurfaceColour[3] = value[2]
def is_colour_or_factor(self, name):
return name in [
"DiffuseColour",
"TransmissionColour",
"DiffuseTransmissionColour",
"ReflectionColour",
"SpecularColour",
]
def edit_colour_or_factor(self, name, value):
if isinstance(value, (list, tuple)):
attribute = getattr(self.settings["style"], name)
if not attribute or not attribute.is_a("IfcColourRgb"):
colour = self.file.createIfcColourRgb(None, 0, 0, 0)
setattr(self.settings["style"], name, colour)
attribute = getattr(self.settings["style"], name)
attribute[1] = value[0]
attribute[2] = value[1]
attribute[3] = value[2]
else:
existing_value = getattr(self.settings["style"], name)
if existing_value and existing_value.id():
self.file.remove(existing_value)
setattr(self.settings["style"], name, self.file.createIfcNormalisedRatioMeasure(value))
@@ -0,0 +1,87 @@
import pytest
import test.bootstrap
import ifcopenshell.api
class TestEditStyleColours(test.bootstrap.IFC4):
def test_editing_a_shading_style(self):
colour = self.file.createIfcColourRgb(None, 0, 0, 0)
style = self.file.createIfcSurfaceStyleShading(colour)
ifcopenshell.api.run(
"style.edit_surface_style",
self.file,
style=style,
attributes={"SurfaceColour": [1, 1, 1], "Transparency": 0.5},
)
assert style.SurfaceColour == colour
assert list(colour) == [None, 1, 1, 1]
assert style.Transparency == 0.5
def test_editing_an_empty_colour_or_factor(self):
for attribute in [
"DiffuseColour",
"TransmissionColour",
"DiffuseTransmissionColour",
"ReflectionColour",
"SpecularColour",
]:
style = self.file.createIfcSurfaceStyleRendering(self.file.createIfcColourRgb(None, 0, 0, 0))
ifcopenshell.api.run("style.edit_surface_style", self.file, style=style, attributes={attribute: [1, 1, 1]})
assert list(getattr(style, attribute)) == [None, 1, 1, 1]
def test_editing_an_existing_colour_to_another_colour(self):
for attribute in [
"DiffuseColour",
"TransmissionColour",
"DiffuseTransmissionColour",
"ReflectionColour",
"SpecularColour",
]:
colour = self.file.createIfcColourRgb(None, 0, 0, 0)
style = self.file.createIfcSurfaceStyleRendering(self.file.createIfcColourRgb(None, 0, 0, 0))
setattr(style, attribute, colour)
ifcopenshell.api.run("style.edit_surface_style", self.file, style=style, attributes={attribute: [1, 1, 1]})
assert list(colour) == [None, 1, 1, 1]
def test_editing_an_existing_colour_to_a_factor(self):
for attribute in [
"DiffuseColour",
"TransmissionColour",
"DiffuseTransmissionColour",
"ReflectionColour",
"SpecularColour",
]:
colour = self.file.createIfcColourRgb(None, 0, 0, 0)
colour_id = colour.id()
style = self.file.createIfcSurfaceStyleRendering(self.file.createIfcColourRgb(None, 0, 0, 0))
setattr(style, attribute, colour)
ifcopenshell.api.run("style.edit_surface_style", self.file, style=style, attributes={attribute: 0.5})
with pytest.raises(RuntimeError):
self.file.by_id(colour_id)
assert getattr(style, attribute).wrappedValue == 0.5
def test_editing_an_existing_factor_to_another_factor(self):
for attribute in [
"DiffuseColour",
"TransmissionColour",
"DiffuseTransmissionColour",
"ReflectionColour",
"SpecularColour",
]:
style = self.file.createIfcSurfaceStyleRendering(self.file.createIfcColourRgb(None, 0, 0, 0))
setattr(style, attribute, self.file.createIfcNormalisedRatioMeasure(0.5))
ifcopenshell.api.run("style.edit_surface_style", self.file, style=style, attributes={attribute: 0.4})
assert getattr(style, attribute).wrappedValue == 0.4
def test_editing_an_existing_factor_to_a_colour(self):
for attribute in [
"DiffuseColour",
"TransmissionColour",
"DiffuseTransmissionColour",
"ReflectionColour",
"SpecularColour",
]:
style = self.file.createIfcSurfaceStyleRendering(self.file.createIfcColourRgb(None, 0, 0, 0))
setattr(style, attribute, self.file.createIfcNormalisedRatioMeasure(0.5))
ifcopenshell.api.run("style.edit_surface_style", self.file, style=style, attributes={attribute: [1, 1, 1]})
assert list(getattr(style, attribute)) == [None, 1, 1, 1]