Hi all
so here i have a simple cube in an ifc file.
!
When i open it in an ifc-viewer, the cube is gray like in the image above in the spoiler tag.
So how can i change the color from this cube with ifcopenshell-python?
Thanks for the reply :)
Hi all
so here i have a simple cube in an ifc file.
!
When i open it in an ifc-viewer, the cube is gray like in the image above in the spoiler tag.
So how can i change the color from this cube with ifcopenshell-python?
Thanks for the reply :)
Hey @Martin156131, I don't know how to do it with just IfcOpenShell, but with Blenderbim that would be about changing the IfcStyle:
Here's a thread with the same request:
https://community.osarch.org/discussion/comment/8780/#Comment_8780
You change the colour in the viewport display tab and then click update IFCstyle to save it
Here is a red ifc cube for example:
Thanks for the feedback!
So it is possible to change the color, however I search the method how to do it in python.
Because i am trying to write a script to make from different obj files one ifc file, so it could be nice when the different ifc entity have a different color, instead having all uniformly gray shading.
If I look at your cube Ifc written out vs the red one you need to include these elements:
#79=IFCSURFACESTYLE('Red',.BOTH.,(#80));
#80=IFCSURFACESTYLERENDERING(#81,0.,#82,$,$,$,IFCNORMALISEDRATIOMEASURE(0.),IFCSPECULARROUGHNESS(0.4),.NOTDEFINED.);
#81=IFCCOLOURRGB($,0.800000071525574,0.0212754905223846,0.0212754905223846);
#82=IFCCOLOURRGB($,0.800000011920929,0.800000011920929,0.800000011920929);
#83=IFCSTYLEDITEM(#73,(#79),'Material');
#84=IFCMATERIAL('Red',$,$);
#85=IFCSTYLEDITEM($,(#79),'Material');
#86=IFCSTYLEDREPRESENTATION(#15,'Body',$,(#85));
#87=IFCMATERIALDEFINITIONREPRESENTATION($,$,(#86),#84);
I don't code so my usefulness ends here
@Martin156131
So it is possible to change the color, however I search the method how to do it in python. Because i am trying to write a script to make from different obj files one ifc file, so it could be nice when the different ifc entity have a different color,
You could try this code snippet, I copied it from @brunopostle
mymaterial = ifcfile.createIfcMaterial("wall material")
material_layer = ifcfile.createIfcMaterialLayer(mymaterial, 0.2, None)
material_layer_set = ifcfile.createIfcMaterialLayerSet([material_layer], None)
material_layer_set_usage = ifcfile.createIfcMaterialLayerSetUsage(material_layer_set, "AXIS2", "POSITIVE", -0.1)
style = ifcopenshell.api.run("style.add_style", ifcfile, name="brick")
ifcopenshell.api.run(
"style.add_surface_style",
ifcfile,
style=style,
attributes={
"SurfaceColour": {
"Name": None,
"Red": 2.2,
"Green": 0.8,
"Blue": 0.5,
},
"DiffuseColour": {
"Name": None,
"Red": 2.2,
"Green": 0.8,
"Blue": 0.5,
},
"Transparency": 0.0,
"ReflectanceMethod": "PLASTIC",
},
)
ifcopenshell.api.run(
"style.assign_material_style",
ifcfile,
material=mymaterial,
style=style,
context=context,
)
ifcfile.createIfcRelAssociatesMaterial(create_guid(), owner_history, RelatedObjects=[ifc_wall], RelatingMaterial=material_layer_set_usage)
There are two ways for an object to receive a colour: 1) its geometry could directly have a style, or 2) it can be associated with a material, and that material can have a style. @Coen's code snippet shows the latter. The former, however, is more appropriate for your usecase as you don't have any materials it seems.
# Create a blank style
style = ifcopenshell.api.run("style.add_style", ifc, name="My style")
# Give that style a surface shading colour
ifcopenshell.api.run("style.add_surface_style", ifc, style=style, ifc_class="IfcSurfaceStyleShading", attributes={
"SurfaceColour": { "Name": None, "Red": 1., "Green": 0., "Blue": 0. }
})
# Assign the style to your geometry's representation (IfcShapeRepresentation)
ifcopenshell.api.run("style.assign_representation_styles", ifc, shape_representation=representation, styles=[style])
Thank you all for your awesome help!
The jupyternotebook code, that i used:
!
My yellow cube ?:
!
@Coen Thanks for the snippet ! Just as a heads up AFAIK unless you're working with HDR images you should not set the color channels with values > 1.0, the result may not be physically correct or may be clamped by the software you'll open it in. For instance Blender technically supports RGB channels with values > 1 (you have to type it in the fields since the slider doesn't let you) but I'm not sure how it will be handled by other softs. Cheers :)
I am a bit confused why this happens, I've made an IfcWallType instance and added to a project with this script:
import ifcopenshell
from ifcopenshell.api import run
import numpy
import bpy
ifc_file = ifcopenshell.file()
project = run("root.create_entity", ifc_file, ifc_class="IfcProject", name="Demo")
run("unit.assign_unit", ifc_file, length={"is_metric": True, "raw": "METERS"})
context = run("context.add_context", ifc_file, context_type="Model")
body = run("context.add_context", ifc_file,context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=context)
# Create a site, building, and storey. Many hierarchies are possible.
site = run("root.create_entity", ifc_file, ifc_class="IfcSite", name="My Site")
building = run("root.create_entity", ifc_file, ifc_class="IfcBuilding", name="Building A")
storey = run("root.create_entity", ifc_file, ifc_class="IfcBuildingStorey", name="Ground Floor")
# Since the site is our top level location, assign it to the project
# Then place our building on the site, and our storey in the building
run("aggregate.assign_object", ifc_file, relating_object=project, product=site)
run("aggregate.assign_object", ifc_file, relating_object=site, product=building)
run("aggregate.assign_object", ifc_file, relating_object=building, product=storey)
def read_from_csv():
print ('read from csv')
def create_wall():
ifc_material = run("material.add_material", ifc_file, name="brick")
ifc_walltype = run("root.create_entity", ifc_file, ifc_class="IfcWallType", name="wall_demo")
relating_material = run("material.assign_material", ifc_file, product=ifc_walltype, type="IfcMaterialLayerSet")
layer_set = relating_material.RelatingMaterial
layer = run("material.add_layer", ifc_file, layer_set=layer_set, material=ifc_material)
layer.LayerThickness = 0.2
print ('hier', ifc_walltype)
ifc_walltype_instance = run("root.create_entity", ifc_file, ifc_class="IfcWall", relating_type=ifc_walltype, name='walltype_instance')
representation = run("geometry.add_wall_representation",ifc_file,context=body,length=5,height=3,thickness=layer.LayerThickness)
matrix_1 = numpy.array(
(
(1.0, 0.0, 0.0, 0.0),
(0.0, 1.0, 0.0, 0.0),
(0.0, 0.0, 1.0, 0.0),
(0.0, 0.0, 0.0, 1.0),
)
)
run("type.assign_type", ifc_file, related_object=ifc_walltype_instance, relating_type=ifc_walltype)
run("geometry.edit_object_placement",ifc_file,product=ifc_walltype_instance ,matrix=matrix_1)
run("spatial.assign_container", ifc_file, relating_structure=storey, product=ifc_walltype_instance)
run("geometry.assign_representation", ifc_file, product=ifc_walltype, representation=representation)
style = ifcopenshell.api.run("style.add_style", ifc_file, name="My style")
run("style.add_surface_style", ifc_file, style=style, ifc_class="IfcSurfaceStyleShading", attributes={
"SurfaceColour": { "Name": None, "Red": 1., "Green": 0., "Blue": 0. }
})
run("style.assign_representation_styles", ifc_file, shape_representation=representation, styles=[style])
def create_beam():
#create material
#create ifcmaterialprofileset
#assign material to profileset
#create type
#create occurence
#place occurence
#representation = run("geometry.add_profile_representation", ifc_file, context=representations["body"], profile=profile, depth=5)
print ('create beam')
create_wall()
file_name="demo_library"
folder_path = "C:\\Algemeen\\00_prive\\BlenderScripts\\BlenderBIM_create_objects\\ifc_library\\"
filename = str(file_name) + ".ifc"
file_path = (folder_path + filename)
ifc_file.write(file_path)
def load_ifc_automatically():
if (bool(ifc_file)) == True:
project = ifc_file.by_type('IfcProject')
if project is not None:
for i in project:
collection_name = 'IfcProject/' + i.Name
collection = bpy.data.collections.get(str(collection_name))
if collection is not None:
for obj in collection.objects:
bpy.data.objects.remove(obj, do_unlink=True)
bpy.data.collections.remove(collection)
#for material in bpy.data.materials:
# material.user_clear()
# bpy.data.materials.remove(material)
bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True)
bpy.ops.bim.load_project(filepath=file_path)
load_ifc_automatically()
Creates a beautiful red wall
Now when I open the BIM tool in BlenderBIM, and want to add another IfcWallType instance, this happens:
When trying to save the project Blender crashes, when I remove the colours I just get a grey colour and BlenderBIM works
When I open the project in BIM Vision I see this:
My aim is to create a library of different coloured WallType instances.
This is the line where BIMVision claims there is an error
#107=IFCCARTESIANTRANSFORMATIONOPERATOR3D(#104,#105,#103,1.,#106);
#108=IFCMAPPEDITEM(#95,#107);
#109=IFCSHAPEREPRESENTATION(#11,'Body','MappedRepresentation',(#108));
Some further experimenting, when I use this for assigning a colour:
#brunopostle gorgious snippet
style = run("style.add_style", ifc_file, name=ifc_material.Name)
run("style.add_surface_style",ifc_file,style=style,attributes={"SurfaceColour": {"Name": ifc_material.Name,"Red": 0.8,"Green": 0.5,"Blue": 0.2,},"Transparency": 0,"ReflectanceMethod": "PLASTIC",})
run("style.assign_material_style",ifc_file,material=ifc_material,style=style,context=context)
Instead of this like my previous post:
#moult snippet
style = ifcopenshell.api.run("style.add_style", ifc_file, name="My style")
run("style.add_surface_style", ifc_file, style=style, ifc_class="IfcSurfaceStyleShading", attributes={"SurfaceColour": { "Name": None, "Red": 1., "Green": 0., "Blue": 0. }})
run("style.assign_representation_styles", ifc_file, shape_representation=representation, styles=[style])
It creates also a colour, and when I try to add an IfcWallType instance it preserves the colour:
However I am unable to open it in BIMVision, BIM Vision gives this log:
#67 0YP$_BwmD0kQ48ohs7NscA Wall wall_demo
When I try to save the IFC project when adding another wall I get this weird error when I ran Blender form the command prompt:
fake_module: addon missing 'bl_info' gives bad performance!: 'C:\\Users\\cclaus\\AppData\\Roaming\\Blender Foundation\\Blender\\3.3\\scripts\\addons\\Z-Anatomy\\__init__.py'
Error : EXCEPTION_ACCESS_VIOLATION
Address : 0x00007FFF744712B9
Module : _ifcopenshell_wrapper.pyd
Thread : 00003678
Writing: C:\Users\cclaus\AppData\Local\Temp\blender.crash.txt
Don't understand why the IfcWallType instance suddenly is transparant and why it crashes :(
Even when I remove all the style lines and the load_ifc_automaticaly
method, then manullay loading it in Blender. Like so:
import ifcopenshell
from ifcopenshell.api import run
import numpy
import bpy
ifc_file = ifcopenshell.file()
project = run("root.create_entity", ifc_file, ifc_class="IfcProject", name="Demo")
run("unit.assign_unit", ifc_file, length={"is_metric": True, "raw": "METERS"})
context = run("context.add_context", ifc_file, context_type="Model")
body = run("context.add_context", ifc_file,context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=context)
# Create a site, building, and storey. Many hierarchies are possible.
site = run("root.create_entity", ifc_file, ifc_class="IfcSite", name="My Site")
building = run("root.create_entity", ifc_file, ifc_class="IfcBuilding", name="Building A")
storey = run("root.create_entity", ifc_file, ifc_class="IfcBuildingStorey", name="Ground Floor")
# Since the site is our top level location, assign it to the project
# Then place our building on the site, and our storey in the building
run("aggregate.assign_object", ifc_file, relating_object=project, product=site)
run("aggregate.assign_object", ifc_file, relating_object=site, product=building)
run("aggregate.assign_object", ifc_file, relating_object=building, product=storey)
def read_from_csv():
print ('read from csv')
def create_wall():
ifc_material = run("material.add_material", ifc_file, name="brick")
ifc_walltype = run("root.create_entity", ifc_file, ifc_class="IfcWallType", name="wall_demo")
relating_material = run("material.assign_material", ifc_file, product=ifc_walltype, type="IfcMaterialLayerSet")
layer_set = relating_material.RelatingMaterial
layer = run("material.add_layer", ifc_file, layer_set=layer_set, material=ifc_material)
layer.LayerThickness = 0.2
print ('hier', ifc_walltype)
ifc_walltype_instance = run("root.create_entity", ifc_file, ifc_class="IfcWall", relating_type=ifc_walltype, name='wall_demo')
representation = run("geometry.add_wall_representation",ifc_file,context=body,length=5,height=3,thickness=layer.LayerThickness)
matrix_1 = numpy.array(
(
(1.0, 0.0, 0.0, 0.0),
(0.0, 1.0, 0.0, 0.0),
(0.0, 0.0, 1.0, 0.0),
(0.0, 0.0, 0.0, 1.0),
)
)
#moult snippet
#style = ifcopenshell.api.run("style.add_style", ifc_file, name="My style")
#run("style.add_surface_style", ifc_file, style=style, ifc_class="IfcSurfaceStyleShading", attributes={"SurfaceColour": { "Name": 'red', "Red": 1., "Green": 0., "Blue": 0. }})
#run("style.assign_representation_styles", ifc_file, shape_representation=representation, styles=[style])
#brunopostle gorgious snippet
#style = run("style.add_style", ifc_file, name=ifc_material.Name)
#run("style.add_surface_style",ifc_file,style=style,attributes={"SurfaceColour": {"Name": ifc_material.Name,"Red": 0.8,"Green": 0.5,"Blue": 0.2,},"Transparency": 0,"ReflectanceMethod": "PLASTIC",})
#run("style.assign_material_style",ifc_file,material=ifc_material,style=style,context=context)
run("type.assign_type", ifc_file, related_object=ifc_walltype_instance, relating_type=ifc_walltype)
run("geometry.edit_object_placement",ifc_file,product=ifc_walltype_instance ,matrix=matrix_1)
run("spatial.assign_container", ifc_file, relating_structure=storey, product=ifc_walltype_instance)
run("geometry.assign_representation", ifc_file, product=ifc_walltype, representation=representation)
create_wall()
Then, I close Blender, open it in BIMVision:
Opening it in BlenderBIM
Then trying to add a wall, this works, when when trying to Miter join with Shift+Y or Shift+T
I get this crash
Error: Python: Traceback (most recent call last):
File "C:\Users\cclaus\AppData\Roaming\Blender Foundation\Blender\3.3\scripts\addons\blenderbim\bim\module\model\workspace.py", line 394, in invoke
return self.execute(context)
File "C:\Users\cclaus\AppData\Roaming\Blender Foundation\Blender\3.3\scripts\addons\blenderbim\tool\ifc.py", line 105, in execute
IfcStore.execute_ifc_operator(self, context)
File "C:\Users\cclaus\AppData\Roaming\Blender Foundation\Blender\3.3\scripts\addons\blenderbim\bim\ifc.py", line 418, in execute_ifc_operator
result = getattr(operator, "_execute")(context)
File "C:\Users\cclaus\AppData\Roaming\Blender Foundation\Blender\3.3\scripts\addons\blenderbim\bim\module\model\workspace.py", line 385, in _execute
getattr(self, f"hotkey_{self.hotkey}")()
File "C:\Users\cclaus\AppData\Roaming\Blender Foundation\Blender\3.3\scripts\addons\blenderbim\bim\module\model\workspace.py", line 500, in hotkey_S_Y
bpy.ops.bim.join_wall(join_type="V")
File "C:\Program Files\Blender Foundation\Blender 3.3\3.3\scripts\modules\bpy\ops.py", line 113, in __call__
ret = _op_call(self.idname_py(), None, kw)
RuntimeError: Error: Python: Traceback (most recent call last):
File "C:\Users\cclaus\AppData\Roaming\Blender Foundation\Blender\3.3\scripts\addons\blenderbim\tool\ifc.py", line 105, in execute
IfcStore.execute_ifc_operator(self, context)
File "C:\Users\cclaus\AppData\Roaming\Blender Foundation\Blender\3.3\scripts\addons\blenderbim\bim\ifc.py", line 418, in execute_ifc_operator
result = getattr(operator, "_execute")(context)
File "C:\Users\cclaus\AppData\Roaming\Blender Foundation\Blender\3.3\scripts\addons\blenderbim\bim\module\model\wall.py", line 106, in _execute
joiner.join_V([o for o in selected_objs if o != context.active_object][0], context.active_object)
File "C:\Users\cclaus\AppData\Roaming\Blender Foundation\Blender\3.3\scripts\addons\blenderbim\bim\module\model\wall.py", line 1072, in join_V
self.recreate_wall(element1, wall1, axis1["reference"], axis1["reference"])
File "C:\Users\cclaus\AppData\Roaming\Blender Foundation\Blender\3.3\scripts\addons\blenderbim\bim\module\model\wall.py", line 1168, in recreate_wall
if tool.Ifc.is_moved(obj):
File "C:\Users\cclaus\AppData\Roaming\Blender Foundation\Blender\3.3\scripts\addons\blenderbim\tool\ifc.py", line 59, in is_moved
if not obj.BIMObjectProperties.location_checksum:
ReferenceError: StructRNA of type Object has been removed
Location: C:\Program Files\Blender Foundation\Blender 3.3\3.3\scripts\modules\bpy\ops.py:113
I can replicate your problem.
That's all i got. ;)
@theoryshaw said:
I can replicate your problem.
That's all i got. ;)
At least it's excluded it's not some funny add-on on my end which is causing this :-)
When I use python to create an IfcProjectLibrary instead of IfProject and load them into BlenderBIM, everything works fine. Just wondering how I would use python to load IFC files from the IfcProjectLibrary automatically.
Login or Register to reply.