I have a small script that adds a custom Formwork Qto to the file. What it calculates:
-
for IfcSlab / BASESLAB: perimeter * height
-
for IfcSlab / FLOOR | LANDING | ROOF: horizontal area - perimeter * height
-
for IfcColumn / COLUMN: surface area - area * 2
-
for IfcWall / SOLIDWALL | PARAPET | SHEAR: side area
-
for IfcBeam / BEAM: (width + height 2) length - (width height) 2
I assume that every beam is connected to a column or a wall on either end, and every slab is surrounded by beams, columns or walls. So if you have beams and slabs that don't conform to these rules you will have deviations. The code is below, I hope this helps.
from blenderbim.bim.ifc import IfcStore
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.geom
import ifcopenshell.util.unit
import ifcopenshell.util.shape
file = IfcStore.file
elements = file.by_type("IfcElement")
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(file)
net_settings = ifcopenshell.geom.settings()
net_settings.set(net_settings.DISABLE_OPENING_SUBTRACTIONS, False)
qtos = ifcopenshell.util.element.get_psets(elements[0], qtos_only = True)
net_shape = ifcopenshell.geom.create_shape(net_settings, elements[0])
sub_formwork = 0
super_formwork = 0
for element in elements:
qtos = ifcopenshell.util.element.get_psets(element, qtos_only = True)
net_shape = ifcopenshell.geom.create_shape(net_settings, element)
try:
predefined_type = ifcopenshell.util.element.get_type(element).PredefinedType
except:
pass
if element.is_a() == "IfcSlab" or element.is_a() == "IfcRamp":
if predefined_type == "BASESLAB":
surface_area = ifcopenshell.util.shape.get_outer_surface_area(net_shape.geometry) / unit_scale
sub_formwork = sub_formwork + surface_area
qto = ifcopenshell.api.run("pset.add_qto", file, product = element, name = "Qto_ReinforcedConcreteQuantities")
ifcopenshell.api.run("pset.edit_qto", file, qto = qto, properties = {"Formwork": file.createIfcAreaMeasure(round(surface_area, 2))})
elif element.is_a() == "IfcRamp" or predefined_type == "FLOOR" or predefined_type == "LANDING" or predefined_type == "ROOF":
area = ifcopenshell.util.shape.get_footprint_area(net_shape.geometry) / unit_scale
surface_area = ifcopenshell.util.shape.get_outer_surface_area(net_shape.geometry) / unit_scale
super_formwork = super_formwork + area - surface_area
qto = ifcopenshell.api.run("pset.add_qto", file, product = element, name = "Qto_ReinforcedConcreteQuantities")
ifcopenshell.api.run("pset.edit_qto", file, qto = qto, properties = {"Formwork": file.createIfcAreaMeasure(round(area - surface_area, 2))})
elif element.is_a() == "IfcColumn":
if predefined_type == "COLUMN":
surface_area = ifcopenshell.util.shape.get_outer_surface_area(net_shape.geometry) / unit_scale
area = ifcopenshell.util.shape.get_footprint_area(net_shape.geometry) / unit_scale
super_formwork = super_formwork + surface_area - area * 2
qto = ifcopenshell.api.run("pset.add_qto", file, product = element, name = "Qto_ReinforcedConcreteQuantities")
ifcopenshell.api.run("pset.edit_qto", file, qto = qto, properties = {"Formwork": file.createIfcAreaMeasure(round(surface_area - area * 2, 2))})
elif element.is_a() == "IfcWall":
if predefined_type == "SOLIDWALL" or predefined_type == "PARAPET" or predefined_type == "SHEAR":
side_area = ifcopenshell.util.shape.get_side_area(net_shape.geometry) / unit_scale
super_formwork = super_formwork + side_area
qto = ifcopenshell.api.run("pset.add_qto", file, product = element, name = "Qto_ReinforcedConcreteQuantities")
ifcopenshell.api.run("pset.edit_qto", file, qto = qto, properties = {"Formwork": file.createIfcAreaMeasure(round(side_area, 2))})
elif element.is_a() == "IfcBeam":
if predefined_type == "BEAM":
length = ifcopenshell.util.shape.get_z(net_shape.geometry) / unit_scale
width = ifcopenshell.util.shape.get_x(net_shape.geometry) / unit_scale
height = ifcopenshell.util.shape.get_y(net_shape.geometry) / unit_scale
super_formwork = super_formwork + (width + height * 2) * length - (width * height) * 2
qto = ifcopenshell.api.run("pset.add_qto", file, product = element, name = "Qto_ReinforcedConcreteQuantities")
ifcopenshell.api.run("pset.edit_qto", file, qto = qto, properties = {"Formwork": file.createIfcAreaMeasure(round((width + height * 2) * length - (width * height) * 2, 2))})