mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 09:48:32 +00:00
Convert ODS schedules into SVG schedules for inclusion in drawings
This commit is contained in:
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user