mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-28 19:27:10 +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.SelectSchemaDir,
|
||||||
operator.ExportIFC,
|
operator.ExportIFC,
|
||||||
operator.ImportIFC,
|
operator.ImportIFC,
|
||||||
|
operator.ColourByClass,
|
||||||
|
operator.ResetObjectColours,
|
||||||
|
operator.ApproveClass,
|
||||||
|
operator.RejectClass,
|
||||||
|
operator.SelectAudited,
|
||||||
|
operator.RejectElement,
|
||||||
ui.BIMProperties,
|
ui.BIMProperties,
|
||||||
ui.BIMPanel,
|
ui.BIMPanel,
|
||||||
ui.MVDPanel,
|
ui.MVDPanel,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import logging
|
|||||||
from . import export_ifc
|
from . import export_ifc
|
||||||
from . import import_ifc
|
from . import import_ifc
|
||||||
from bpy_extras.io_utils import ImportHelper
|
from bpy_extras.io_utils import ImportHelper
|
||||||
|
from itertools import cycle
|
||||||
|
|
||||||
class ExportIFC(bpy.types.Operator):
|
class ExportIFC(bpy.types.Operator):
|
||||||
bl_idname = "export.ifc"
|
bl_idname = "export.ifc"
|
||||||
@@ -116,6 +117,90 @@ class SelectType(bpy.types.Operator):
|
|||||||
object.select_set(True)
|
object.select_set(True)
|
||||||
return {'FINISHED'}
|
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):
|
class SelectDataDir(bpy.types.Operator):
|
||||||
bl_idname = "bim.select_data_dir"
|
bl_idname = "bim.select_data_dir"
|
||||||
bl_label = "Select Data Directory"
|
bl_label = "Select Data Directory"
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class BIMProperties(bpy.types.PropertyGroup):
|
|||||||
name="Predefined Type", default=None)
|
name="Predefined Type", default=None)
|
||||||
ifc_userdefined_type: bpy.props.StringProperty(name="Userdefined Type")
|
ifc_userdefined_type: bpy.props.StringProperty(name="Userdefined Type")
|
||||||
export_has_representations: bpy.props.BoolProperty(name="Export Representations", default=True)
|
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):
|
class BIMPanel(bpy.types.Panel):
|
||||||
bl_label = "Building Information Modeling"
|
bl_label = "Building Information Modeling"
|
||||||
@@ -74,6 +75,24 @@ class BIMPanel(bpy.types.Panel):
|
|||||||
row.operator("bim.select_class")
|
row.operator("bim.select_class")
|
||||||
row.operator("bim.select_type")
|
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):
|
class MVDPanel(bpy.types.Panel):
|
||||||
bl_label = "Model View Definitions"
|
bl_label = "Model View Definitions"
|
||||||
bl_idname = "mvd.panel"
|
bl_idname = "mvd.panel"
|
||||||
|
|||||||
Reference in New Issue
Block a user