Files
2026-05-31 10:17:09 +07:00

144 lines
6.5 KiB
Python

# IfcOpenShell - IFC toolkit and geometry engine
# Copyright (C) 2021 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/>.
from typing import Any, Literal, Optional
import ifcopenshell
import ifcopenshell.api.style
SURFACE_STYLE_TYPES = Literal[
"IfcSurfaceStyleShading",
"IfcSurfaceStyleRendering",
"IfcSurfaceStyleWithTextures",
"IfcSurfaceStyleLighting",
"IfcSurfaceStyleRefraction",
"IfcExternallyDefinedSurfaceStyle",
]
def add_surface_style(
file: ifcopenshell.file,
style: ifcopenshell.entity_instance,
ifc_class: SURFACE_STYLE_TYPES = "IfcSurfaceStyleShading",
attributes: Optional[dict[str, Any]] = None,
) -> ifcopenshell.entity_instance:
"""Adds a new presentation item to a surface style
A surface style can have multiple different types of presentation items
assigned to it:
- Shading, this is the simplest item, which defines a single basic
colour and transparency that can be used to display the object on a
screen. It is an indicative colour of what the object would be in real
life. It is commonly incorrectly abused to colour code systems for MEP
equipment or object types for structural steel. If you just want to
give something a colour, this is what you need.
- Rendering, this is an advanced extension of shading, which includes
the definition of a shader for a rendering engine. You may select the
reflectance / lighting model such as PHYSICAL, for PBR style
rendering, or FLAT, for flat shading, or PHONG for older biased
rendering workflows. Based on the chosen lighting model, you may then
specify the appropriate colour maps, such as diffuse colours,
specularity, emissive component, etc. These lighting models are fully
compatible with glTF and X3D. This should be used if your model is
prepared to be rendered by a rendering engine which is compatible with
glTF / X3D shader descriptions. If you are doing archviz or 3D
rendering, this is what you need.
- Textures, this is a special type of Rendering presentation item that
uses image textures instead of single colours. Textures may be either
mapped using a bounding box stretch mapping, or with UV coordinates
for mesh-like geometry.
- Lighting, this is used to define photometrically accurate colour
parameters used in lighting simulation. If you are a simulationist,
this is what you need.
- Reflectance, this is a special type of Lighting presentation item
which includes some lesser used photometric properties, typically
required for advanced materials like glazing.
- External, this is for any other surface style defined using an
external URI. This is relevant if you are using a third-party non-glTF
compatible shader definition such as for Cycles, Renderman, V-Ray,
etc, or a complex lighting simulation definition, such as for
Radiance.
Shading is sufficient for the majority of basic models.
The attributes you specify will depend on the type of presentation item
you are adding. An example is shown below, but for full details please
refer to the IFC documentation.
:param style: The IfcSurfaceStyle you want to add to presentation item
to. See ifcopenshell.api.style.add_style.
:param ifc_class: Choose from IfcSurfaceStyleShading,
IfcSurfaceStyleRendering, IfcSurfaceStyleWithTextures,
IfcSurfaceStyleLighting, IfcSurfaceStyleReflectance, or
IfcExternallyDefinedSurfaceStyle.
:param attributes: a dictionary of attribute names and values.
:return: The newly created presentation item based on the provided
ifc_class.
Example:
.. code:: python
# Create a new surface style
style = ifcopenshell.api.style.add_style(model)
# Create a simple shading colour and transparency.
ifcopenshell.api.style.add_surface_style(model,
style=style, ifc_class="IfcSurfaceStyleShading", attributes={
"SurfaceColour": { "Name": None, "Red": 1.0, "Green": 0.8, "Blue": 0.8 },
"Transparency": 0., # 0 is opaque, 1 is transparent
})
# Alternatively, create a rendering style.
ifcopenshell.api.style.add_surface_style(model,
style=style, ifc_class="IfcSurfaceStyleRendering", attributes={
# A surface colour and transparency is still supplied for
# viewport display only. This will supersede the shading
# presentation item.
"SurfaceColour": { "Name": None, "Red": 1.0, "Green": 0.8, "Blue": 0.8 },
"Transparency": 0., # 0 is opaque, 1 is transparent
# NOTDEFINED is assumed to be a PHYSICAL (PBR) lighting
# model. In IFC4X3, you may choose PHYSICAL directly.
"ReflectanceMethod": "NOTDEFINED",
# For PBR shading, you may specify these parameters:
"DiffuseColour": { "Name": None, "Red": 0.9, "Green": 0.8, "Blue": 0.8 },
"SpecularColour": 0.1, # Metallic factor
"SpecularHighlight": {"SpecularRoughness": 0.5}, # Roughness factor
})
"""
attributes = attributes or {}
style_item = file.create_entity(ifc_class)
ifcopenshell.api.style.edit_surface_style(file, style=style_item, attributes=attributes)
styles: list[ifcopenshell.entity_instance]
styles = list(style.Styles or [])
select_class = ifc_class
if select_class == "IfcSurfaceStyleRendering":
select_class = "IfcSurfaceStyleShading"
duplicate_items = [s for s in styles if s.is_a(select_class)]
for duplicate_item in duplicate_items:
ifcopenshell.api.style.remove_surface_style(file, style=duplicate_item)
styles = list(style.Styles or [])
styles.append(style_item)
style.Styles = styles
return style_item