mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
You can now store arbitrary IFC data in the SVG, depending on the drawing style
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user