diff --git a/src/ifcblenderexport/blenderbim/__init__.py b/src/ifcblenderexport/blenderbim/__init__.py
index f8f62e8c2f..3a73ee0ce6 100644
--- a/src/ifcblenderexport/blenderbim/__init__.py
+++ b/src/ifcblenderexport/blenderbim/__init__.py
@@ -101,6 +101,8 @@ if bpy is not None:
operator.AddSubcontext,
operator.RemoveSubcontext,
operator.CutSection,
+ operator.CreateSheet,
+ operator.AddViewToSheet,
operator.CreateSheets,
operator.GenerateDigitalTwin,
operator.CreateView,
diff --git a/src/ifcblenderexport/blenderbim/cut_ifc.py b/src/ifcblenderexport/blenderbim/cut_ifc.py
index 41cf411207..9b4d2da1be 100644
--- a/src/ifcblenderexport/blenderbim/cut_ifc.py
+++ b/src/ifcblenderexport/blenderbim/cut_ifc.py
@@ -723,7 +723,7 @@ class SvgWriter():
def draw_background_image(self):
self.svg.add(self.svg.image(
- os.path.basename(self.ifc_cutter.background_image), **{
+ os.path.join('..', 'diagrams', os.path.basename(self.ifc_cutter.background_image)), **{
'width': self.width,
'height': self.height
}
diff --git a/src/ifcblenderexport/blenderbim/data/sheets/SHEET.svg b/src/ifcblenderexport/blenderbim/data/sheets/SHEET.svg
new file mode 100644
index 0000000000..1650be34e7
--- /dev/null
+++ b/src/ifcblenderexport/blenderbim/data/sheets/SHEET.svg
@@ -0,0 +1,4 @@
+
+
diff --git a/src/ifcblenderexport/blenderbim/data/sheets/sheet1.svg b/src/ifcblenderexport/blenderbim/data/sheets/sheet1.svg
deleted file mode 100644
index 8381f3616c..0000000000
--- a/src/ifcblenderexport/blenderbim/data/sheets/sheet1.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
diff --git a/src/ifcblenderexport/blenderbim/operator.py b/src/ifcblenderexport/blenderbim/operator.py
index e4fc636db2..8b705e0c3a 100644
--- a/src/ifcblenderexport/blenderbim/operator.py
+++ b/src/ifcblenderexport/blenderbim/operator.py
@@ -1346,6 +1346,31 @@ class CutSection(bpy.types.Operator):
def is_landscape(self):
return bpy.context.scene.render.resolution_x > bpy.context.scene.render.resolution_y
+
+class CreateSheet(bpy.types.Operator):
+ bl_idname = 'bim.create_sheet'
+ bl_label = 'Create Sheet'
+
+ def execute(self, context):
+ sheet_builder = sheeter.SheetBuilder()
+ sheet_builder.data_dir = bpy.context.scene.BIMProperties.data_dir
+ sheet_builder.create(bpy.context.scene.DocProperties.sheet_name)
+ bpy.context.scene.DocProperties.sheet_name = ''
+ return {'FINISHED'}
+
+
+class AddViewToSheet(bpy.types.Operator):
+ bl_idname = 'bim.add_view_to_sheet'
+ bl_label = 'Add View To Sheet'
+
+ def execute(self, context):
+ props = bpy.context.scene.DocProperties
+ sheet_builder = sheeter.SheetBuilder()
+ sheet_builder.data_dir = bpy.context.scene.BIMProperties.data_dir
+ sheet_builder.add_view(props.available_views, props.available_sheets)
+ return {'FINISHED'}
+
+
class CreateSheets(bpy.types.Operator):
bl_idname = 'bim.create_sheets'
bl_label = 'Create Sheets'
@@ -1356,6 +1381,7 @@ class CreateSheets(bpy.types.Operator):
sheet_builder.build()
return {'FINISHED'}
+
class GenerateDigitalTwin(bpy.types.Operator):
bl_idname = 'bim.generate_digital_twin'
bl_label = 'Generate Digital Twin'
diff --git a/src/ifcblenderexport/blenderbim/prop.py b/src/ifcblenderexport/blenderbim/prop.py
index a05e9239d5..4daa150cf4 100644
--- a/src/ifcblenderexport/blenderbim/prop.py
+++ b/src/ifcblenderexport/blenderbim/prop.py
@@ -42,6 +42,7 @@ target_views_enum = []
persons_enum = []
organisations_enum = []
views_enum = []
+sheets_enum = []
bcfviewpoints_enum = []
@persistent
@@ -344,6 +345,21 @@ def getViews(self, context):
return views_enum
+def refreshSheets(self, context):
+ global sheets_enum
+ sheets_enum.clear()
+ getSheets(self, context)
+
+def getSheets(self, context):
+ global sheets_enum
+ if len(sheets_enum) < 1:
+ sheets_enum.clear()
+ for filename in Path(os.path.join(context.scene.BIMProperties.data_dir, 'sheets')).glob('*.svg'):
+ f = str(filename.stem)
+ sheets_enum.append((f, f, ''))
+ return sheets_enum
+
+
class Subcontext(PropertyGroup):
name: StringProperty(name='Name')
target_view: StringProperty(name='Target View')
@@ -353,6 +369,8 @@ class DocProperties(PropertyGroup):
should_recut: BoolProperty(name="Should Recut", default=True)
view_name: StringProperty(name="View Name")
available_views: EnumProperty(items=getViews, name="Available Views")
+ sheet_name: StringProperty(name="Sheet Name", update=refreshSheets)
+ available_sheets: EnumProperty(items=getSheets, name="Available Sheets")
class BIMCameraProperties(PropertyGroup):
diff --git a/src/ifcblenderexport/blenderbim/sheeter.py b/src/ifcblenderexport/blenderbim/sheeter.py
index 1440bdc92a..ca9491f424 100644
--- a/src/ifcblenderexport/blenderbim/sheeter.py
+++ b/src/ifcblenderexport/blenderbim/sheeter.py
@@ -3,11 +3,66 @@ import pystache
import ntpath
import os
from shutil import copy
+from xml.dom import minidom
class SheetBuilder:
def __init__(self):
self.data_dir = None
+ def create(self, name):
+ sheet_path = '{}sheets/{}.svg'.format(self.data_dir, name)
+ root = ET.Element('svg')
+ root.attrib['xmlns'] = 'http://www.w3.org/2000/svg'
+ root.attrib['xmlns:xlink'] = 'http://www.w3.org/1999/xlink'
+ root.attrib['id'] = 'root'
+ root.attrib['version'] = '1.1'
+ root.attrib['width'] = '841mm'
+ root.attrib['height'] = '594mm'
+
+ titleblock = ET.SubElement(root, 'image')
+ titleblock.attrib['xlink:href'] = '../templates/titleblock.svg'
+ titleblock.attrib['x'] = '0'
+ titleblock.attrib['y'] = '0'
+ titleblock.attrib['width'] = '841mm'
+ titleblock.attrib['height'] = '594mm'
+
+ with open(sheet_path, 'w') as f:
+ f.write(minidom.parseString(ET.tostring(root)).toprettyxml(indent=' '))
+
+ def add_view(self, view_name, sheet_name):
+ sheet_path = '{}sheets/{}.svg'.format(self.data_dir, sheet_name)
+ view_path = '{}diagrams/{}.svg'.format(self.data_dir, view_name)
+
+ ET.register_namespace('', 'http://www.w3.org/2000/svg')
+ ET.register_namespace('xlink', 'http://www.w3.org/1999/xlink')
+
+ sheet_tree = ET.parse(sheet_path)
+ sheet_root = sheet_tree.getroot()
+
+ view_tree = ET.parse(view_path)
+ view_root = view_tree.getroot()
+
+ # The view is placed into a group with a background image element.
+ # Although the foreground SVG already has a background, it is duplicated
+ # here to accommodate browsers which do not nest images.
+ view = ET.SubElement(sheet_root, 'g')
+
+ background = ET.SubElement(view, 'image')
+ background.attrib['xlink:href'] = '../diagrams/{}.png'.format(view_name)
+ background.attrib['x'] = '0'
+ background.attrib['y'] = '0'
+ background.attrib['width'] = view_root.attrib.get('width')
+ background.attrib['height'] = view_root.attrib.get('height')
+
+ foreground = ET.SubElement(view, 'image')
+ foreground.attrib['xlink:href'] = '../diagrams/{}.svg'.format(view_name)
+ foreground.attrib['x'] = '0'
+ foreground.attrib['y'] = '0'
+ foreground.attrib['width'] = view_root.attrib.get('width')
+ foreground.attrib['height'] = view_root.attrib.get('height')
+
+ sheet_tree.write(sheet_path)
+
def build(self):
sheet_path = '{}sheets/sheet1.svg'.format(self.data_dir)
sheet_filename = ntpath.basename(sheet_path)
diff --git a/src/ifcblenderexport/blenderbim/ui.py b/src/ifcblenderexport/blenderbim/ui.py
index 5653770516..e56b2ff281 100644
--- a/src/ifcblenderexport/blenderbim/ui.py
+++ b/src/ifcblenderexport/blenderbim/ui.py
@@ -309,6 +309,14 @@ class BIM_PT_documentation(Panel):
row = layout.row()
row.operator('bim.set_view_preset_1')
+ row = layout.row()
+ row.prop(props, 'sheet_name')
+ row.operator('bim.create_sheet', icon='ADD', text='')
+
+ row = layout.row()
+ row.prop(props, 'available_sheets')
+ row.operator('bim.add_view_to_sheet', icon='ADD', text='')
+
row = layout.row()
row.operator('bim.create_sheets')