mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 06:21:40 +00:00
Initial attempt at a qto module in Ifc5D
This is a more flexible, non-Blender approach to doing QTO which allows: - Doing QTO without Blender - Doing QTO using query filters - Using config files for QTOs - Choosing your calculation engine, either built-in or creating your own
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "IFC4 Base Quantities",
|
||||||
|
"description": "This ruleset quantifies every single possible standardised base quantity in IFC4",
|
||||||
|
"calculators": {
|
||||||
|
"IOSTriangulation": {
|
||||||
|
"IfcWall": {
|
||||||
|
"Qto_WallBaseQuantities": {
|
||||||
|
"Length": "net_get_x",
|
||||||
|
"Width": "net_get_y",
|
||||||
|
"Height": "net_get_z",
|
||||||
|
"NetSideArea": "net_get_side_area",
|
||||||
|
"NetVolume": "net_get_volume"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
# Ifc5D - IFC costing utility
|
||||||
|
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||||
|
#
|
||||||
|
# This file is part of Ifc5D.
|
||||||
|
#
|
||||||
|
# Ifc5D 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.
|
||||||
|
#
|
||||||
|
# Ifc5D 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 Ifc5D. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import ifcopenshell
|
||||||
|
import ifcopenshell.api
|
||||||
|
import ifcopenshell.api.pset
|
||||||
|
import ifcopenshell.util.selector
|
||||||
|
import multiprocessing
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
|
def get_rules(name: str):
|
||||||
|
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
with open(os.path.join(cwd, name + ".json"), "r") as f:
|
||||||
|
return json.load(f)
|
||||||
|
|
||||||
|
|
||||||
|
def quantify(ifc_file: ifcopenshell.file, elements: set[ifcopenshell.entity_instance], rules: dict):
|
||||||
|
results = {}
|
||||||
|
for calculator, queries in rules["calculators"].items():
|
||||||
|
calculator = calculators[calculator]
|
||||||
|
for query, qtos in queries.items():
|
||||||
|
filtered_elements = ifcopenshell.util.selector.filter_elements(ifc_file, query, elements)
|
||||||
|
calculator.calculate(ifc_file, filtered_elements, qtos, results)
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
def edit_qtos(ifc_file, results):
|
||||||
|
for element, qtos in results.items():
|
||||||
|
for name, quantities in qtos.items():
|
||||||
|
qto = ifcopenshell.util.element.get_pset(element, name, should_inherit=False)
|
||||||
|
if qto:
|
||||||
|
qto = ifc_file.by_id(qto["id"])
|
||||||
|
else:
|
||||||
|
qto = ifcopenshell.api.pset.add_qto(ifc_file, element, name)
|
||||||
|
ifcopenshell.api.pset.edit_qto(ifc_file, qto=qto, properties=quantities)
|
||||||
|
|
||||||
|
|
||||||
|
class IOSTriangulation:
|
||||||
|
@staticmethod
|
||||||
|
def calculate(
|
||||||
|
ifc_file: ifcopenshell.file,
|
||||||
|
elements: set[ifcopenshell.entity_instance],
|
||||||
|
qtos: dict,
|
||||||
|
results: Optional[dict] = None,
|
||||||
|
):
|
||||||
|
import ifcopenshell
|
||||||
|
import ifcopenshell.geom
|
||||||
|
import ifcopenshell.util.shape
|
||||||
|
|
||||||
|
if results is None:
|
||||||
|
results = {}
|
||||||
|
|
||||||
|
formula_functions = {}
|
||||||
|
|
||||||
|
gross_settings = ifcopenshell.geom.settings()
|
||||||
|
gross_settings.set(gross_settings.DISABLE_OPENING_SUBTRACTIONS, True)
|
||||||
|
net_settings = ifcopenshell.geom.settings()
|
||||||
|
|
||||||
|
gross_qtos = {}
|
||||||
|
net_qtos = {}
|
||||||
|
|
||||||
|
for name, quantities in qtos.items():
|
||||||
|
for quantity, formula in quantities.items():
|
||||||
|
if formula.startswith("gross_"):
|
||||||
|
formula = formula[6:]
|
||||||
|
gross_qtos.setdefault(name, {})[quantity] = formula
|
||||||
|
formula_functions[formula] = getattr(ifcopenshell.util.shape, formula)
|
||||||
|
elif formula.startswith("net_"):
|
||||||
|
formula = formula[4:]
|
||||||
|
net_qtos.setdefault(name, {})[quantity] = formula
|
||||||
|
formula_functions[formula] = getattr(ifcopenshell.util.shape, formula)
|
||||||
|
|
||||||
|
tasks = []
|
||||||
|
|
||||||
|
if gross_qtos:
|
||||||
|
tasks.append((IOSTriangulation.create_iterator(ifc_file, gross_settings, elements), gross_qtos))
|
||||||
|
|
||||||
|
if net_qtos:
|
||||||
|
tasks.append((IOSTriangulation.create_iterator(ifc_file, net_settings, elements), net_qtos))
|
||||||
|
|
||||||
|
for iterator, qtos in tasks:
|
||||||
|
if iterator.initialize():
|
||||||
|
while True:
|
||||||
|
shape = iterator.get()
|
||||||
|
element = ifc_file.by_id(shape.id)
|
||||||
|
results.setdefault(element, {})
|
||||||
|
for name, quantities in qtos.items():
|
||||||
|
results[element].setdefault(name, {})
|
||||||
|
for quantity, formula in quantities.items():
|
||||||
|
results[element][name][quantity] = formula_functions[formula](shape.geometry)
|
||||||
|
if not iterator.next():
|
||||||
|
break
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_iterator(ifc_file, settings, elements):
|
||||||
|
return ifcopenshell.geom.iterator(settings, ifc_file, multiprocessing.cpu_count(), include=elements)
|
||||||
|
|
||||||
|
|
||||||
|
class Blender:
|
||||||
|
@staticmethod
|
||||||
|
def calculate(ifc_file, elements, qtos):
|
||||||
|
import blenderbim.tool as tool
|
||||||
|
|
||||||
|
for element in elements:
|
||||||
|
obj = tool.Ifc.get_object(element)
|
||||||
|
if not obj:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for name, quantities in qtos.items():
|
||||||
|
for quantity, formula in quantities.items():
|
||||||
|
getattr(tool.Qto, formula)
|
||||||
|
# TODO
|
||||||
|
|
||||||
|
|
||||||
|
calculators = {"Blender": Blender, "IOSTriangulation": IOSTriangulation}
|
||||||
Reference in New Issue
Block a user