mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-10 06:00:51 +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.SetViewportShadowFromSun,
|
||||||
operator.SetNorthOffset,
|
operator.SetNorthOffset,
|
||||||
operator.GetNorthOffset,
|
operator.GetNorthOffset,
|
||||||
|
operator.AddDrawingStyleAttribute,
|
||||||
|
operator.RemoveDrawingStyleAttribute,
|
||||||
prop.StrProperty,
|
prop.StrProperty,
|
||||||
prop.Variable,
|
prop.Variable,
|
||||||
prop.Role,
|
prop.Role,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import math
|
import math
|
||||||
import time
|
import time
|
||||||
import numpy
|
import numpy
|
||||||
@@ -807,8 +808,17 @@ class IfcCutter:
|
|||||||
classes = [position, element.is_a()]
|
classes = [position, element.is_a()]
|
||||||
for association in element.HasAssociations:
|
for association in element.HasAssociations:
|
||||||
if association.is_a('IfcRelAssociatesMaterial'):
|
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))
|
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
|
return classes
|
||||||
|
|
||||||
def get_material_name(self, element):
|
def get_material_name(self, element):
|
||||||
|
|||||||
@@ -2134,7 +2134,8 @@ class CutSection(bpy.types.Operator):
|
|||||||
import ifccsv
|
import ifccsv
|
||||||
ifc_cutter.ifc_filenames = [i.name for i in bpy.context.scene.DocProperties.ifc_files]
|
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.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.diagram_name = self.diagram_name
|
||||||
ifc_cutter.background_image = bpy.context.scene.render.filepath
|
ifc_cutter.background_image = bpy.context.scene.render.filepath
|
||||||
if camera.data.BIMCameraProperties.cut_objects == 'CUSTOM':
|
if camera.data.BIMCameraProperties.cut_objects == 'CUSTOM':
|
||||||
@@ -2153,6 +2154,7 @@ class CutSection(bpy.types.Operator):
|
|||||||
ifc_cutter.grid_objs = []
|
ifc_cutter.grid_objs = []
|
||||||
ifc_cutter.text_objs = []
|
ifc_cutter.text_objs = []
|
||||||
ifc_cutter.misc_objs = []
|
ifc_cutter.misc_objs = []
|
||||||
|
ifc_cutter.attributes = [a.name for a in drawing_style.attributes]
|
||||||
for obj in camera.users_collection[0].objects:
|
for obj in camera.users_collection[0].objects:
|
||||||
if 'IfcGrid' in obj.name:
|
if 'IfcGrid' in obj.name:
|
||||||
ifc_cutter.grid_objs.append(obj)
|
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_abscissa = str(cos(x_angle))
|
||||||
bpy.context.scene.MapConversion.x_axis_ordinate = str(sin(x_angle))
|
bpy.context.scene.MapConversion.x_axis_ordinate = str(sin(x_angle))
|
||||||
return {'FINISHED'}
|
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')
|
vector_style: EnumProperty(items=getVectorStyles, name='Vector Style')
|
||||||
include_query: StringProperty(name='Include Query')
|
include_query: StringProperty(name='Include Query')
|
||||||
exclude_query: StringProperty(name='Exclude Query')
|
exclude_query: StringProperty(name='Exclude Query')
|
||||||
|
attributes: CollectionProperty(name='Attributes', type=StrProperty)
|
||||||
|
|
||||||
|
|
||||||
class DocProperties(PropertyGroup):
|
class DocProperties(PropertyGroup):
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import bpy
|
import bpy
|
||||||
import math
|
import math
|
||||||
import pystache
|
import pystache
|
||||||
@@ -286,6 +287,44 @@ class SvgWriter():
|
|||||||
for p in projected_points])
|
for p in projected_points])
|
||||||
d = 'M{}'.format(d[1:])
|
d = 'M{}'.format(d[1:])
|
||||||
path = self.svg.add(self.svg.path(d=d, class_=' '.join(classes)))
|
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):
|
def draw_line_annotation(self, obj_data, classes):
|
||||||
# TODO: properly scope these offsets
|
# TODO: properly scope these offsets
|
||||||
x_offset = self.raw_width / 2
|
x_offset = self.raw_width / 2
|
||||||
@@ -306,16 +345,22 @@ class SvgWriter():
|
|||||||
d = 'M{}'.format(d[1:])
|
d = 'M{}'.format(d[1:])
|
||||||
path = self.svg.add(self.svg.path(d=d, class_=' '.join(classes)))
|
path = self.svg.add(self.svg.path(d=d, class_=' '.join(classes)))
|
||||||
elif isinstance(data, bpy.types.Mesh):
|
elif isinstance(data, bpy.types.Mesh):
|
||||||
for edge in data.edges:
|
self.draw_edge_annotation(obj, classes)
|
||||||
v0_global = matrix_world @ data.vertices[edge.vertices[0]].co.xyz
|
|
||||||
v1_global = matrix_world @ data.vertices[edge.vertices[1]].co.xyz
|
def draw_edge_annotation(self, obj, classes):
|
||||||
v0 = self.project_point_onto_camera(v0_global)
|
x_offset = self.raw_width / 2
|
||||||
v1 = self.project_point_onto_camera(v1_global)
|
y_offset = self.raw_height / 2
|
||||||
start = Vector(((x_offset + v0.x), (y_offset - v0.y)))
|
matrix_world = obj.matrix_world
|
||||||
end = Vector(((x_offset + v1.x), (y_offset - v1.y)))
|
for edge in obj.data.edges:
|
||||||
vector = end - start
|
v0_global = matrix_world @ obj.data.vertices[edge.vertices[0]].co.xyz
|
||||||
line = self.svg.add(self.svg.line(start=tuple(start * self.scale),
|
v1_global = matrix_world @ obj.data.vertices[edge.vertices[1]].co.xyz
|
||||||
end=tuple(end * self.scale), class_=' '.join(classes)))
|
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):
|
def draw_text_annotations(self):
|
||||||
x_offset = self.raw_width / 2
|
x_offset = self.raw_width / 2
|
||||||
|
|||||||
@@ -918,6 +918,14 @@ class BIM_PT_camera(Panel):
|
|||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
row.prop(drawing_style, 'exclude_query')
|
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 = layout.row(align=True)
|
||||||
row.operator('bim.save_drawing_style')
|
row.operator('bim.save_drawing_style')
|
||||||
row.operator('bim.activate_drawing_style')
|
row.operator('bim.activate_drawing_style')
|
||||||
|
|||||||
Reference in New Issue
Block a user