mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-27 18:57:17 +00:00
Support placing a view / section / diagram on a sheet
This commit is contained in:
@@ -62,6 +62,7 @@ classes = (
|
|||||||
operator.AddSubcontext,
|
operator.AddSubcontext,
|
||||||
operator.RemoveSubcontext,
|
operator.RemoveSubcontext,
|
||||||
operator.CutSection,
|
operator.CutSection,
|
||||||
|
operator.CreateSheets,
|
||||||
prop.Subcontext,
|
prop.Subcontext,
|
||||||
prop.BIMProperties,
|
prop.BIMProperties,
|
||||||
prop.DocProperties,
|
prop.DocProperties,
|
||||||
|
|||||||
@@ -598,7 +598,9 @@ class SvgWriter():
|
|||||||
self.output,
|
self.output,
|
||||||
debug=False,
|
debug=False,
|
||||||
size=('{}mm'.format(self.width), '{}mm'.format(self.height)),
|
size=('{}mm'.format(self.width), '{}mm'.format(self.height)),
|
||||||
viewBox=('0 0 {} {}'.format(self.width, self.height)))
|
viewBox=('0 0 {} {}'.format(self.width, self.height)),
|
||||||
|
id='root'
|
||||||
|
)
|
||||||
|
|
||||||
self.add_stylesheet()
|
self.add_stylesheet()
|
||||||
self.add_defs()
|
self.add_defs()
|
||||||
@@ -622,7 +624,7 @@ class SvgWriter():
|
|||||||
self.svg.defs.add(self.svg.style(stylesheet.read()))
|
self.svg.defs.add(self.svg.style(stylesheet.read()))
|
||||||
|
|
||||||
def add_defs(self):
|
def add_defs(self):
|
||||||
tree = ET.parse('{}styles/defs.svg'.format(self.ifc_cutter.data_dir))
|
tree = ET.parse('{}templates/defs.svg'.format(self.ifc_cutter.data_dir))
|
||||||
root = tree.getroot()
|
root = tree.getroot()
|
||||||
for child in root.getchildren():
|
for child in root.getchildren():
|
||||||
self.svg.defs.add(External(child))
|
self.svg.defs.add(External(child))
|
||||||
@@ -651,11 +653,18 @@ class SvgWriter():
|
|||||||
classes = ['annotation', 'dimension']
|
classes = ['annotation', 'dimension']
|
||||||
v0 = self.ifc_cutter.annotation_obj.data.vertices[edge.vertices[0]].co
|
v0 = self.ifc_cutter.annotation_obj.data.vertices[edge.vertices[0]].co
|
||||||
v1 = self.ifc_cutter.annotation_obj.data.vertices[edge.vertices[1]].co
|
v1 = self.ifc_cutter.annotation_obj.data.vertices[edge.vertices[1]].co
|
||||||
start = ((x_offset + v0.x) * self.scale, (y_offset - v0.y) * self.scale)
|
start = Vector(((x_offset + v0.x), (y_offset - v0.y)))
|
||||||
end = ((x_offset + v1.x) * self.scale, (y_offset - v1.y) * self.scale)
|
end = Vector(((x_offset + v1.x), (y_offset - v1.y)))
|
||||||
line = self.svg.add(self.svg.line(start=start, end=end, class_=' '.join(classes)))
|
mid = ((end - start) / 2) + start
|
||||||
|
# TODO: hardcoded meters to mm conversion, until I properly do units
|
||||||
|
dimension = (end - start).length * 1000
|
||||||
|
line = self.svg.add(self.svg.line(start=tuple(start * self.scale),
|
||||||
|
end=tuple(end * self.scale), class_=' '.join(classes)))
|
||||||
line['marker-start'] = 'url(#dimension-marker)'
|
line['marker-start'] = 'url(#dimension-marker)'
|
||||||
line['marker-end'] = 'url(#dimension-marker)'
|
line['marker-end'] = 'url(#dimension-marker)'
|
||||||
|
self.svg.add(self.svg.text(str(round(dimension)), insert=tuple(mid * self.scale), **{
|
||||||
|
'font-size': '0.2mm'
|
||||||
|
}))
|
||||||
|
|
||||||
def draw_cut_polygons(self):
|
def draw_cut_polygons(self):
|
||||||
for polygon in self.ifc_cutter.cut_polygons:
|
for polygon in self.ifc_cutter.cut_polygons:
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" height="594mm" width="841mm">
|
||||||
|
<defs />
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<use xlink:href="../templates/titleblock.svg#root" />
|
||||||
|
</svg>
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="150mm" y="50mm">
|
||||||
|
<use xlink:href="../diagrams/Camera.svg#root" />
|
||||||
|
</svg>
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="150mm" y="50mm">
|
||||||
|
<use xlink:href="../templates/view-title.svg#root" />
|
||||||
|
</svg>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 714 B |
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<svg baseProfile="full" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<marker id="dimension-marker" markerHeight="20" markerWidth="20" refX="7.5" refY="10" orient="auto">
|
||||||
|
<path d="M 7.5 0 L 7.5 20" class="annotation" style="stroke-width:2px;" />
|
||||||
|
<path d="M 0 0 L 15 20" class="annotation" style="stroke-width:3px;" />
|
||||||
|
</marker>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 498 B |
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 111 KiB |
@@ -0,0 +1,71 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
id="root"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 50.222462 10"
|
||||||
|
height="10mm"
|
||||||
|
width="50.222462mm">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
transform="translate(-27.82024,-96.649986)"
|
||||||
|
id="layer1">
|
||||||
|
<circle
|
||||||
|
r="4.8499999"
|
||||||
|
cy="101.64999"
|
||||||
|
cx="32.82024"
|
||||||
|
id="path853"
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.30000001;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
id="path855"
|
||||||
|
d="m 37.67024,101.64999 40.37246,-1e-5"
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<text
|
||||||
|
id="text859"
|
||||||
|
y="102.19775"
|
||||||
|
x="32.820755"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:125%;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
xml:space="preserve"><tspan
|
||||||
|
style="font-size:2.11666656px;text-align:center;text-anchor:middle;stroke-width:0.26458332px"
|
||||||
|
y="102.19775"
|
||||||
|
x="32.820755"
|
||||||
|
id="tspan857">{{no}}</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:125%;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
x="39.368858"
|
||||||
|
y="99.525047"
|
||||||
|
id="text863"><tspan
|
||||||
|
id="tspan861"
|
||||||
|
x="39.368858"
|
||||||
|
y="99.525047"
|
||||||
|
style="font-size:2.11666656px;text-align:start;text-anchor:start;stroke-width:0.26458332px">{{name}}</tspan></text>
|
||||||
|
<text
|
||||||
|
id="text867"
|
||||||
|
y="104.66998"
|
||||||
|
x="39.368858"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:125%;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
xml:space="preserve"><tspan
|
||||||
|
style="font-size:2.11666656px;text-align:start;text-anchor:start;stroke-width:0.26458332px"
|
||||||
|
y="104.66998"
|
||||||
|
x="39.368858"
|
||||||
|
id="tspan865">{{scale}}</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.2 KiB |
@@ -7,6 +7,7 @@ import ifcopenshell
|
|||||||
from . import export_ifc
|
from . import export_ifc
|
||||||
from . import import_ifc
|
from . import import_ifc
|
||||||
from . import cut_ifc
|
from . import cut_ifc
|
||||||
|
from . import sheeter
|
||||||
from bpy_extras.io_utils import ImportHelper
|
from bpy_extras.io_utils import ImportHelper
|
||||||
from itertools import cycle
|
from itertools import cycle
|
||||||
from mathutils import Vector
|
from mathutils import Vector
|
||||||
@@ -809,3 +810,13 @@ class CutSection(bpy.types.Operator):
|
|||||||
|
|
||||||
def is_landscape(self):
|
def is_landscape(self):
|
||||||
return bpy.context.scene.render.resolution_x > bpy.context.scene.render.resolution_y
|
return bpy.context.scene.render.resolution_x > bpy.context.scene.render.resolution_y
|
||||||
|
|
||||||
|
class CreateSheets(bpy.types.Operator):
|
||||||
|
bl_idname = 'bim.create_sheets'
|
||||||
|
bl_label = 'Create Sheets'
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
sheet_builder = sheeter.SheetBuilder()
|
||||||
|
sheet_builder.data_dir = bpy.context.scene.BIMProperties.data_dir
|
||||||
|
sheet_builder.build()
|
||||||
|
return {'FINISHED'}
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
import pystache
|
||||||
|
import ntpath
|
||||||
|
import os
|
||||||
|
from shutil import copy
|
||||||
|
|
||||||
|
class SheetBuilder:
|
||||||
|
def __init__(self):
|
||||||
|
self.data_dir = None
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
sheet_path = '{}sheets/sheet1.svg'.format(self.data_dir)
|
||||||
|
sheet_filename = ntpath.basename(sheet_path)
|
||||||
|
sheet_name = sheet_filename[0:-4]
|
||||||
|
|
||||||
|
data = [
|
||||||
|
{'number': 'ASDF', 'revision': 'A'},
|
||||||
|
{},
|
||||||
|
{'no': '01', 'name': 'HOUSE', 'scale': '1:100'},
|
||||||
|
{},
|
||||||
|
{'no': '02', 'name': 'ELEVATION', 'scale': '1:100'},
|
||||||
|
{},
|
||||||
|
{'no': '03', 'name': 'PLAN', 'scale': '1:100'},
|
||||||
|
{},
|
||||||
|
{'no': '04', 'name': 'SECTION', 'scale': '1:100'},
|
||||||
|
]
|
||||||
|
tree = ET.parse(sheet_path)
|
||||||
|
root = tree.getroot()
|
||||||
|
embedded_svgs = root.findall('{http://www.w3.org/2000/svg}svg')
|
||||||
|
n = 0
|
||||||
|
for svg in embedded_svgs:
|
||||||
|
use = svg.findall('{http://www.w3.org/2000/svg}use')[0]
|
||||||
|
source = use.attrib.get('{http://www.w3.org/1999/xlink}href')
|
||||||
|
source_path = source.split('#')[0]
|
||||||
|
source_filename = ntpath.basename(source_path)
|
||||||
|
source_background = '{}diagrams/{}.png'.format(self.data_dir, source_filename[0:-4])
|
||||||
|
source_anchor = source.split('#')[1]
|
||||||
|
dest_filename = '{}-{}.svg'.format(source_filename[0:-4], n)
|
||||||
|
os.makedirs('{}build/{}/'.format(self.data_dir, sheet_name), exist_ok=True)
|
||||||
|
with open('{}build/{}/{}'.format(self.data_dir, sheet_name, dest_filename), 'w') as out:
|
||||||
|
with open('{}sheets/{}'.format(self.data_dir, source_path), 'r') as template:
|
||||||
|
out.write(pystache.render(template.read(), data[n]))
|
||||||
|
use.set('{http://www.w3.org/1999/xlink}href',
|
||||||
|
'{}#{}'.format(dest_filename, source_anchor))
|
||||||
|
# TODO: hardcoded that all diagrams have a raster background
|
||||||
|
if 'diagrams/' in source_path:
|
||||||
|
copy(source_background, '{}build/{}/'.format(self.data_dir, sheet_name))
|
||||||
|
n += 1
|
||||||
|
|
||||||
|
with open('{}build/{}/{}'.format(self.data_dir, sheet_name, sheet_filename), 'wb') as output:
|
||||||
|
tree.write(output)
|
||||||
@@ -196,6 +196,9 @@ class BIM_PT_documentation(Panel):
|
|||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.operator('bim.cut_section')
|
row.operator('bim.cut_section')
|
||||||
|
|
||||||
|
row = layout.row()
|
||||||
|
row.operator('bim.create_sheets')
|
||||||
|
|
||||||
class BIM_PT_context(Panel):
|
class BIM_PT_context(Panel):
|
||||||
bl_label = "Geometric Representation Contexts"
|
bl_label = "Geometric Representation Contexts"
|
||||||
bl_idname = "BIM_PT_context"
|
bl_idname = "BIM_PT_context"
|
||||||
|
|||||||
Reference in New Issue
Block a user