You can now store arbitrary IFC data in the SVG, depending on the drawing style

This commit is contained in:
Dion Moult
2020-09-02 21:51:58 +10:00
parent 9c8f8ba56f
commit dbbc56ef0d
6 changed files with 101 additions and 12 deletions
@@ -196,6 +196,8 @@ if bpy is not None:
operator.SetViewportShadowFromSun,
operator.SetNorthOffset,
operator.GetNorthOffset,
operator.AddDrawingStyleAttribute,
operator.RemoveDrawingStyleAttribute,
prop.StrProperty,
prop.Variable,
prop.Role,
+11 -1
View File
@@ -1,4 +1,5 @@
import os
import re
import math
import time
import numpy
@@ -807,8 +808,17 @@ class IfcCutter:
classes = [position, element.is_a()]
for association in element.HasAssociations:
if association.is_a('IfcRelAssociatesMaterial'):
classes.append('material-{}'.format(self.get_material_name(association.RelatingMaterial)))
classes.append('material-{}'.format(
re.sub('[^0-9a-zA-Z]+', '', self.get_material_name(association.RelatingMaterial))
))
classes.append('globalid-{}'.format(element.GlobalId))
for attribute in self.attributes:
result = self.selector.get_element_value(element, attribute)
if result:
classes.append('{}-{}'.format(
re.sub('[^0-9a-zA-Z]+', '', attribute),
re.sub('[^0-9a-zA-Z]+', '', result)
))
return classes
def get_material_name(self, element):
@@ -2134,7 +2134,8 @@ class CutSection(bpy.types.Operator):
import ifccsv
ifc_cutter.ifc_filenames = [i.name for i in bpy.context.scene.DocProperties.ifc_files]
ifc_cutter.data_dir = bpy.context.scene.BIMProperties.data_dir
ifc_cutter.vector_style = bpy.context.scene.DocProperties.drawing_styles[camera.data.BIMCameraProperties.active_drawing_style_index].vector_style
drawing_style = bpy.context.scene.DocProperties.drawing_styles[camera.data.BIMCameraProperties.active_drawing_style_index]
ifc_cutter.vector_style = drawing_style.vector_style
ifc_cutter.diagram_name = self.diagram_name
ifc_cutter.background_image = bpy.context.scene.render.filepath
if camera.data.BIMCameraProperties.cut_objects == 'CUSTOM':
@@ -2153,6 +2154,7 @@ class CutSection(bpy.types.Operator):
ifc_cutter.grid_objs = []
ifc_cutter.text_objs = []
ifc_cutter.misc_objs = []
ifc_cutter.attributes = [a.name for a in drawing_style.attributes]
for obj in camera.users_collection[0].objects:
if 'IfcGrid' in obj.name:
ifc_cutter.grid_objs.append(obj)
@@ -3868,3 +3870,24 @@ class GetNorthOffset(bpy.types.Operator):
bpy.context.scene.MapConversion.x_axis_abscissa = str(cos(x_angle))
bpy.context.scene.MapConversion.x_axis_ordinate = str(sin(x_angle))
return {'FINISHED'}
class AddDrawingStyleAttribute(bpy.types.Operator):
bl_idname = 'bim.add_drawing_style_attribute'
bl_label = 'Add Drawing Style Attribute'
def execute(self, context):
props = bpy.context.scene.camera.data.BIMCameraProperties
context.scene.DocProperties.drawing_styles[props.active_drawing_style_index].attributes.add()
return {'FINISHED'}
class RemoveDrawingStyleAttribute(bpy.types.Operator):
bl_idname = 'bim.remove_drawing_style_attribute'
bl_label = 'Remove Drawing Style Attribute'
index: bpy.props.IntProperty()
def execute(self, context):
props = bpy.context.scene.camera.data.BIMCameraProperties
context.scene.DocProperties.drawing_styles[props.active_drawing_style_index].attributes.remove(self.index)
return {'FINISHED'}
@@ -521,6 +521,7 @@ class DrawingStyle(PropertyGroup):
vector_style: EnumProperty(items=getVectorStyles, name='Vector Style')
include_query: StringProperty(name='Include Query')
exclude_query: StringProperty(name='Exclude Query')
attributes: CollectionProperty(name='Attributes', type=StrProperty)
class DocProperties(PropertyGroup):
@@ -1,4 +1,5 @@
import os
import re
import bpy
import math
import pystache
@@ -286,6 +287,44 @@ class SvgWriter():
for p in projected_points])
d = 'M{}'.format(d[1:])
path = self.svg.add(self.svg.path(d=d, class_=' '.join(classes)))
def get_attribute_classes(self, obj):
classes = []
for attribute in self.ifc_cutter.attributes:
result = self.get_obj_value(obj, attribute)
if result:
classes.append('{}-{}'.format(
re.sub('[^0-9a-zA-Z]+', '', attribute),
re.sub('[^0-9a-zA-Z]+', '', result)
))
return classes
def get_obj_value(self, obj, key):
# This is a duplicate implementation of the IFC selector key in Blender
# In the future if all this becomes purely IFC based this can be deleted
if '.' in key \
and key.split('.')[0] == 'type':
try:
obj = obj.BIMObjectProperties.relating_type
except:
return
key = '.'.join(key.split('.')[1:])
result = obj.BIMObjectProperties.attributes.get(key)
if result:
return result.string_value
elif key == 'Name':
return obj.name.split('/')[1]
elif '.' in key:
pset_name, prop = key.split('.')
pset = obj.BIMObjectProperties.psets.get(pset_name)
if not pset:
pset = obj.BIMObjectProperties.qtos.get(pset_name)
if not pset:
return
result = pset.properties.get(prop)
if result:
return result.string_value
def draw_line_annotation(self, obj_data, classes):
# TODO: properly scope these offsets
x_offset = self.raw_width / 2
@@ -306,16 +345,22 @@ class SvgWriter():
d = 'M{}'.format(d[1:])
path = self.svg.add(self.svg.path(d=d, class_=' '.join(classes)))
elif isinstance(data, bpy.types.Mesh):
for edge in data.edges:
v0_global = matrix_world @ data.vertices[edge.vertices[0]].co.xyz
v1_global = matrix_world @ data.vertices[edge.vertices[1]].co.xyz
v0 = self.project_point_onto_camera(v0_global)
v1 = self.project_point_onto_camera(v1_global)
start = Vector(((x_offset + v0.x), (y_offset - v0.y)))
end = Vector(((x_offset + v1.x), (y_offset - v1.y)))
vector = end - start
line = self.svg.add(self.svg.line(start=tuple(start * self.scale),
end=tuple(end * self.scale), class_=' '.join(classes)))
self.draw_edge_annotation(obj, classes)
def draw_edge_annotation(self, obj, classes):
x_offset = self.raw_width / 2
y_offset = self.raw_height / 2
matrix_world = obj.matrix_world
for edge in obj.data.edges:
v0_global = matrix_world @ obj.data.vertices[edge.vertices[0]].co.xyz
v1_global = matrix_world @ obj.data.vertices[edge.vertices[1]].co.xyz
v0 = self.project_point_onto_camera(v0_global)
v1 = self.project_point_onto_camera(v1_global)
start = Vector(((x_offset + v0.x), (y_offset - v0.y)))
end = Vector(((x_offset + v1.x), (y_offset - v1.y)))
vector = end - start
line = self.svg.add(self.svg.line(start=tuple(start * self.scale),
end=tuple(end * self.scale), class_=' '.join(classes)))
def draw_text_annotations(self):
x_offset = self.raw_width / 2
@@ -918,6 +918,14 @@ class BIM_PT_camera(Panel):
row = layout.row(align=True)
row.prop(drawing_style, 'exclude_query')
row = layout.row()
row.operator('bim.add_drawing_style_attribute')
for index, attribute in enumerate(drawing_style.attributes):
row = layout.row(align=True)
row.prop(attribute, 'name', text='')
row.operator('bim.remove_drawing_style_attribute', icon='X', text='').index = index
row = layout.row(align=True)
row.operator('bim.save_drawing_style')
row.operator('bim.activate_drawing_style')