mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-13 10:57:49 +00:00
Implement basic Gherkin-based QA system
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
import ifcopenshell
|
||||
from behave import given, when, then, step
|
||||
|
||||
@given('the IFC file "{file}"')
|
||||
def step_impl(context, file):
|
||||
context.file = ifcopenshell.open(file)
|
||||
|
||||
@then('the element {id} is an {ifc_class}')
|
||||
def step_impl(context, id, ifc_class):
|
||||
assert context.file.by_id(id).is_a(ifc_class)
|
||||
|
||||
@then('the element {id} should not exist because {reason}')
|
||||
def step_impl(context, id, reason):
|
||||
assert not context.file.by_id(id)
|
||||
@@ -22,6 +22,12 @@ classes = (
|
||||
operator.SelectSchemaDir,
|
||||
operator.ExportIFC,
|
||||
operator.ImportIFC,
|
||||
operator.ColourByClass,
|
||||
operator.ResetObjectColours,
|
||||
operator.ApproveClass,
|
||||
operator.RejectClass,
|
||||
operator.SelectAudited,
|
||||
operator.RejectElement,
|
||||
ui.BIMProperties,
|
||||
ui.BIMPanel,
|
||||
ui.MVDPanel,
|
||||
|
||||
@@ -4,6 +4,7 @@ import logging
|
||||
from . import export_ifc
|
||||
from . import import_ifc
|
||||
from bpy_extras.io_utils import ImportHelper
|
||||
from itertools import cycle
|
||||
|
||||
class ExportIFC(bpy.types.Operator):
|
||||
bl_idname = "export.ifc"
|
||||
@@ -116,6 +117,90 @@ class SelectType(bpy.types.Operator):
|
||||
object.select_set(True)
|
||||
return {'FINISHED'}
|
||||
|
||||
class ColourByClass(bpy.types.Operator):
|
||||
bl_idname = 'bim.colour_by_class'
|
||||
bl_label = 'Colour by Class'
|
||||
|
||||
def execute(self, context):
|
||||
colour_list = [
|
||||
(.651, .81, .892, 1),
|
||||
(.121, .471, .706, 1),
|
||||
(.699, .876, .54, 1),
|
||||
(.199, .629, .174, 1),
|
||||
(.983, .605, .602, 1),
|
||||
(.89, .101, .112, 1),
|
||||
(.989, .751, .427, 1),
|
||||
(.986, .497, .1, 1),
|
||||
(.792, .699, .839, 1),
|
||||
(.414, .239, .603, 1),
|
||||
(.993, .999, .6, 1),
|
||||
(.693, .349, .157, 1)]
|
||||
colours = cycle(colour_list)
|
||||
ifc_classes = {}
|
||||
for object in bpy.context.selected_objects:
|
||||
if '/' not in object.name:
|
||||
continue
|
||||
ifc_class = object.name.split('/')[0]
|
||||
if ifc_class not in ifc_classes:
|
||||
ifc_classes[ifc_class] = next(colours)
|
||||
object.color = ifc_classes[ifc_class]
|
||||
return {'FINISHED'}
|
||||
|
||||
class ResetObjectColours(bpy.types.Operator):
|
||||
bl_idname = 'bim.reset_object_colours'
|
||||
bl_label = 'Reset Colours'
|
||||
|
||||
def execute(self, context):
|
||||
for object in bpy.context.selected_objects:
|
||||
object.color = (1, 1, 1, 1)
|
||||
return {'FINISHED'}
|
||||
|
||||
class ApproveClass(bpy.types.Operator):
|
||||
bl_idname = 'bim.approve_class'
|
||||
bl_label = 'Approve Class'
|
||||
|
||||
def execute(self, context):
|
||||
with open(bpy.context.scene.BIMProperties.data_dir + 'audit.txt', 'a') as file:
|
||||
for object in bpy.context.selected_objects:
|
||||
file.write('Then the element {} is an {}\n'.format(
|
||||
object['IfcGlobalId'], object.name.split('/')[0]))
|
||||
return {'FINISHED'}
|
||||
|
||||
class RejectClass(bpy.types.Operator):
|
||||
bl_idname = 'bim.reject_class'
|
||||
bl_label = 'Reject Class'
|
||||
|
||||
def execute(self, context):
|
||||
with open(bpy.context.scene.BIMProperties.data_dir + 'audit.txt', 'a') as file:
|
||||
for object in bpy.context.selected_objects:
|
||||
file.write('Then the element {} is an {}\n'.format(
|
||||
object['IfcGlobalId'], bpy.context.scene.BIMProperties.ifc_class))
|
||||
return {'FINISHED'}
|
||||
|
||||
class RejectElement(bpy.types.Operator):
|
||||
bl_idname = 'bim.reject_element'
|
||||
bl_label = 'Reject Element'
|
||||
|
||||
def execute(self, context):
|
||||
with open(bpy.context.scene.BIMProperties.data_dir + 'audit.txt', 'a') as file:
|
||||
for object in bpy.context.selected_objects:
|
||||
file.write('Then the element {} should not exist because {}\n'.format(
|
||||
object['IfcGlobalId'], bpy.context.scene.BIMProperties.qa_reject_element_reason))
|
||||
return {'FINISHED'}
|
||||
|
||||
class SelectAudited(bpy.types.Operator):
|
||||
bl_idname = 'bim.select_audited'
|
||||
bl_label = 'Select Audited'
|
||||
|
||||
def execute(self, context):
|
||||
with open(bpy.context.scene.BIMProperties.data_dir + 'audit.txt') as file:
|
||||
for line in file:
|
||||
for object in bpy.context.visible_objects:
|
||||
if 'IfcGlobalId' in object.keys() \
|
||||
and object['IfcGlobalId'] == line.split(' ')[3]:
|
||||
object.select_set(True)
|
||||
return {'FINISHED'}
|
||||
|
||||
class SelectDataDir(bpy.types.Operator):
|
||||
bl_idname = "bim.select_data_dir"
|
||||
bl_label = "Select Data Directory"
|
||||
|
||||
@@ -33,6 +33,7 @@ class BIMProperties(bpy.types.PropertyGroup):
|
||||
name="Predefined Type", default=None)
|
||||
ifc_userdefined_type: bpy.props.StringProperty(name="Userdefined Type")
|
||||
export_has_representations: bpy.props.BoolProperty(name="Export Representations", default=True)
|
||||
qa_reject_element_reason: bpy.props.StringProperty(name="Element rejection reason")
|
||||
|
||||
class BIMPanel(bpy.types.Panel):
|
||||
bl_label = "Building Information Modeling"
|
||||
@@ -74,6 +75,24 @@ class BIMPanel(bpy.types.Panel):
|
||||
row.operator("bim.select_class")
|
||||
row.operator("bim.select_type")
|
||||
|
||||
layout.label(text="Quality Auditing:")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(bim_properties, "qa_reject_element_reason")
|
||||
row = layout.row()
|
||||
row.operator("bim.reject_element")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.operator("bim.colour_by_class")
|
||||
row.operator("bim.reset_object_colours")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.operator("bim.approve_class")
|
||||
row.operator("bim.reject_class")
|
||||
|
||||
row = layout.row()
|
||||
row.operator("bim.select_audited")
|
||||
|
||||
class MVDPanel(bpy.types.Panel):
|
||||
bl_label = "Model View Definitions"
|
||||
bl_idname = "mvd.panel"
|
||||
|
||||
Reference in New Issue
Block a user