Convert ODS schedules into SVG schedules for inclusion in drawings

This commit is contained in:
Dion Moult
2020-08-17 22:10:06 +10:00
parent d3da378ba3
commit eac72dc852
5 changed files with 92 additions and 0 deletions
@@ -189,6 +189,7 @@ if bpy is not None:
operator.AddSchedule,
operator.RemoveSchedule,
operator.SelectScheduleFile,
operator.BuildSchedule,
prop.StrProperty,
prop.Variable,
prop.Role,
@@ -8,12 +8,14 @@ import webbrowser
import ifcopenshell
import ifcopenshell.util.selector
import tempfile
import ntpath
from . import export_ifc
from . import import_ifc
from . import qto
from . import cut_ifc
from . import svgwriter
from . import sheeter
from . import scheduler
from . import schema
from . import bcf
from . import ifc
@@ -3664,3 +3666,19 @@ class SelectScheduleFile(bpy.types.Operator):
def invoke(self, context, event):
context.window_manager.fileselect_add(self)
return {'RUNNING_MODAL'}
class BuildSchedule(bpy.types.Operator):
bl_idname = 'bim.build_schedule'
bl_label = 'Build Schedule'
def execute(self, context):
props = bpy.context.scene.DocProperties
schedule = props.schedules[props.active_schedule_index]
schedule_creator = scheduler.Scheduler()
outfile = os.path.join(
bpy.context.scene.BIMProperties.data_dir, 'schedules',
ntpath.basename(schedule.file).replace('.ods', '.svg'))
schedule_creator.schedule(schedule.file, outfile)
webbrowser.open('file://' + outfile)
return {'FINISHED'}
@@ -0,0 +1,72 @@
import svgwrite
import xml.etree.ElementTree as ET
from odf.opendocument import load
from odf.table import Table, TableRow, TableColumn, TableCell
from odf.text import P
from odf.style import Style
class Scheduler():
def schedule(self, infile, outfile):
self.svg = svgwrite.Drawing(
outfile,
debug=False,
id='root',
)
self.padding = 1
self.margin = 5
doc = load(infile)
styles = {}
for style in doc.getElementsByType(Style):
name = style.getAttribute('name')
if not style.firstChild:
continue
styles[name] = {key[1]: value for key, value in style.firstChild.attributes.items()}
table = doc.getElementsByType(Table)[0]
column_widths = []
for col in table.getElementsByType(TableColumn):
style_name = col.getAttribute('stylename')
repeat = col.getAttribute('numbercolumnsrepeated')
repeat = int(repeat) if repeat else 1
for i in range(0, repeat):
if not style_name or 'column-width' not in styles[style_name]:
column_widths.append(50)
else:
column_widths.append(self.convert_to_si(styles[style_name]['column-width']))
y = self.margin
for tri, tr in enumerate(table.getElementsByType(TableRow)):
x = self.margin
height = 6
tdi = 0
for td in tr.getElementsByType(TableCell):
repeat = td.getAttribute('numbercolumnsrepeated')
repeat = int(repeat) if repeat else 1
for i in range(0, repeat):
width = column_widths[tdi]
self.svg.add(self.svg.rect(insert=(x, y), size=(width, height), style='fill:rgba(255,255,255,1); stroke-width:.125; stroke:rgb(0,0,0)'))
value = td.getElementsByType(P)
if value:
self.add_text(value[0], x+self.padding, y+self.padding)
x += width
tdi += 1
y += height
total_width = sum(column_widths) + (self.margin * 2)
self.svg['width'] = '{}mm'.format(total_width)
self.svg['height'] = '{}mm'.format(y)
self.svg['viewBox'] = '0 0 {} {}'.format(total_width, y)
self.svg.save(pretty=True)
def add_text(self, text, x, y):
self.svg.add(self.svg.text(str(text).upper(), insert=tuple((x, y)), **{
'font-size': 4.13,
'font-family': 'OpenGost Type B TT',
'text-anchor': 'start',
'alignment-baseline': 'baseline',
'dominant-baseline': 'hanging'
}))
def convert_to_si(self, value):
if 'in' in value:
return float(value[0:-2]) * 25.4
@@ -766,6 +766,7 @@ class BIM_PT_schedules(Panel):
row.operator('bim.add_schedule')
if props.schedules:
row.operator('bim.build_schedule', icon='LINENUMBERS_ON', text='')
row.operator('bim.remove_schedule', icon='X', text='').index = props.active_schedule_index
layout.template_list('BIM_UL_generic', '', props, 'schedules', props, 'active_schedule_index')